1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * av7110_ca.c: CA and CI stuff
5 * Copyright (C) 1999-2002 Ralph Metzler
6 * & Marcus Metzler for convergence integrated media GmbH
8 * originally based on code by:
9 * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de>
11 * the project's page is at https://linuxtv.org
14 #include <linux/kernel.h>
15 #include <linux/types.h>
16 #include <linux/delay.h>
18 #include <linux/timer.h>
19 #include <linux/poll.h>
20 #include <linux/gfp.h>
23 #include "av7110_hw.h"
24 #include "av7110_ca.h"
27 void CI_handle(struct av7110
*av7110
, u8
*data
, u16 len
)
29 dprintk(8, "av7110:%p\n",av7110
);
35 if (data
[2] != 1 && data
[2] != 2)
39 av7110
->ci_slot
[data
[2] - 1].flags
= 0;
42 av7110
->ci_slot
[data
[2] - 1].flags
|= CA_CI_MODULE_PRESENT
;
45 av7110
->ci_slot
[data
[2] - 1].flags
|= CA_CI_MODULE_READY
;
49 case CI_SWITCH_PRG_REPLY
:
50 //av7110->ci_stat=data[1];
58 void ci_get_data(struct dvb_ringbuffer
*cibuf
, u8
*data
, int len
)
60 if (dvb_ringbuffer_free(cibuf
) < len
+ 2)
63 DVB_RINGBUFFER_WRITE_BYTE(cibuf
, len
>> 8);
64 DVB_RINGBUFFER_WRITE_BYTE(cibuf
, len
& 0xff);
65 dvb_ringbuffer_write(cibuf
, data
, len
);
66 wake_up_interruptible(&cibuf
->queue
);
70 /******************************************************************************
71 * CI link layer file ops
72 ******************************************************************************/
74 static int ci_ll_init(struct dvb_ringbuffer
*cirbuf
, struct dvb_ringbuffer
*ciwbuf
, int size
)
76 struct dvb_ringbuffer
*tab
[] = { cirbuf
, ciwbuf
, NULL
}, **p
;
79 for (p
= tab
; *p
; p
++) {
88 dvb_ringbuffer_init(*p
, data
, size
);
93 static void ci_ll_flush(struct dvb_ringbuffer
*cirbuf
, struct dvb_ringbuffer
*ciwbuf
)
95 dvb_ringbuffer_flush_spinlock_wakeup(cirbuf
);
96 dvb_ringbuffer_flush_spinlock_wakeup(ciwbuf
);
99 static void ci_ll_release(struct dvb_ringbuffer
*cirbuf
, struct dvb_ringbuffer
*ciwbuf
)
107 static int ci_ll_reset(struct dvb_ringbuffer
*cibuf
, struct file
*file
,
108 int slots
, struct ca_slot_info
*slot
)
112 u8 msg
[8] = { 0x00, 0x06, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00 };
114 for (i
= 0; i
< 2; i
++) {
115 if (slots
& (1 << i
))
119 if (dvb_ringbuffer_free(cibuf
) < len
)
122 for (i
= 0; i
< 2; i
++) {
123 if (slots
& (1 << i
)) {
125 dvb_ringbuffer_write(cibuf
, msg
, 8);
133 static ssize_t
ci_ll_write(struct dvb_ringbuffer
*cibuf
, struct file
*file
,
134 const char __user
*buf
, size_t count
, loff_t
*ppos
)
137 int non_blocking
= file
->f_flags
& O_NONBLOCK
;
138 u8
*page
= (u8
*)__get_free_page(GFP_USER
);
149 if (copy_from_user(page
, buf
, count
))
152 free
= dvb_ringbuffer_free(cibuf
);
153 if (count
+ 2 > free
) {
158 if (wait_event_interruptible(cibuf
->queue
,
159 (dvb_ringbuffer_free(cibuf
) >= count
+ 2)))
163 DVB_RINGBUFFER_WRITE_BYTE(cibuf
, count
>> 8);
164 DVB_RINGBUFFER_WRITE_BYTE(cibuf
, count
& 0xff);
166 res
= dvb_ringbuffer_write(cibuf
, page
, count
);
168 free_page((unsigned long)page
);
172 static ssize_t
ci_ll_read(struct dvb_ringbuffer
*cibuf
, struct file
*file
,
173 char __user
*buf
, size_t count
, loff_t
*ppos
)
176 int non_blocking
= file
->f_flags
& O_NONBLOCK
;
179 if (!cibuf
->data
|| !count
)
181 if (non_blocking
&& (dvb_ringbuffer_empty(cibuf
)))
183 if (wait_event_interruptible(cibuf
->queue
,
184 !dvb_ringbuffer_empty(cibuf
)))
186 avail
= dvb_ringbuffer_avail(cibuf
);
189 len
= DVB_RINGBUFFER_PEEK(cibuf
, 0) << 8;
190 len
|= DVB_RINGBUFFER_PEEK(cibuf
, 1);
191 if (avail
< len
+ 2 || count
< len
)
193 DVB_RINGBUFFER_SKIP(cibuf
, 2);
195 return dvb_ringbuffer_read_user(cibuf
, buf
, len
);
198 static int dvb_ca_open(struct inode
*inode
, struct file
*file
)
200 struct dvb_device
*dvbdev
= file
->private_data
;
201 struct av7110
*av7110
= dvbdev
->priv
;
202 int err
= dvb_generic_open(inode
, file
);
204 dprintk(8, "av7110:%p\n",av7110
);
208 ci_ll_flush(&av7110
->ci_rbuffer
, &av7110
->ci_wbuffer
);
212 static __poll_t
dvb_ca_poll (struct file
*file
, poll_table
*wait
)
214 struct dvb_device
*dvbdev
= file
->private_data
;
215 struct av7110
*av7110
= dvbdev
->priv
;
216 struct dvb_ringbuffer
*rbuf
= &av7110
->ci_rbuffer
;
217 struct dvb_ringbuffer
*wbuf
= &av7110
->ci_wbuffer
;
220 dprintk(8, "av7110:%p\n",av7110
);
222 poll_wait(file
, &rbuf
->queue
, wait
);
223 poll_wait(file
, &wbuf
->queue
, wait
);
225 if (!dvb_ringbuffer_empty(rbuf
))
226 mask
|= (EPOLLIN
| EPOLLRDNORM
);
228 if (dvb_ringbuffer_free(wbuf
) > 1024)
229 mask
|= (EPOLLOUT
| EPOLLWRNORM
);
234 static int dvb_ca_ioctl(struct file
*file
, unsigned int cmd
, void *parg
)
236 struct dvb_device
*dvbdev
= file
->private_data
;
237 struct av7110
*av7110
= dvbdev
->priv
;
238 unsigned long arg
= (unsigned long) parg
;
241 dprintk(8, "av7110:%p\n",av7110
);
243 if (mutex_lock_interruptible(&av7110
->ioctl_mutex
))
248 ret
= ci_ll_reset(&av7110
->ci_wbuffer
, file
, arg
,
249 &av7110
->ci_slot
[0]);
256 cap
.slot_type
= (FW_CI_LL_SUPPORT(av7110
->arm_app
) ?
257 CA_CI_LINK
: CA_CI
) | CA_DESCR
;
259 cap
.descr_type
= CA_ECD
;
260 memcpy(parg
, &cap
, sizeof(cap
));
264 case CA_GET_SLOT_INFO
:
266 struct ca_slot_info
*info
=(struct ca_slot_info
*)parg
;
268 if (info
->num
< 0 || info
->num
> 1) {
269 mutex_unlock(&av7110
->ioctl_mutex
);
272 av7110
->ci_slot
[info
->num
].num
= info
->num
;
273 av7110
->ci_slot
[info
->num
].type
= FW_CI_LL_SUPPORT(av7110
->arm_app
) ?
275 memcpy(info
, &av7110
->ci_slot
[info
->num
], sizeof(struct ca_slot_info
));
285 case CA_GET_DESCR_INFO
:
287 struct ca_descr_info info
;
291 memcpy(parg
, &info
, sizeof (info
));
297 struct ca_descr
*descr
= (struct ca_descr
*) parg
;
299 if (descr
->index
>= 16 || descr
->parity
> 1) {
300 mutex_unlock(&av7110
->ioctl_mutex
);
303 av7110_fw_cmd(av7110
, COMTYPE_PIDFILTER
, SetDescr
, 5,
304 (descr
->index
<<8)|descr
->parity
,
305 (descr
->cw
[0]<<8)|descr
->cw
[1],
306 (descr
->cw
[2]<<8)|descr
->cw
[3],
307 (descr
->cw
[4]<<8)|descr
->cw
[5],
308 (descr
->cw
[6]<<8)|descr
->cw
[7]);
317 mutex_unlock(&av7110
->ioctl_mutex
);
321 static ssize_t
dvb_ca_write(struct file
*file
, const char __user
*buf
,
322 size_t count
, loff_t
*ppos
)
324 struct dvb_device
*dvbdev
= file
->private_data
;
325 struct av7110
*av7110
= dvbdev
->priv
;
327 dprintk(8, "av7110:%p\n",av7110
);
328 return ci_ll_write(&av7110
->ci_wbuffer
, file
, buf
, count
, ppos
);
331 static ssize_t
dvb_ca_read(struct file
*file
, char __user
*buf
,
332 size_t count
, loff_t
*ppos
)
334 struct dvb_device
*dvbdev
= file
->private_data
;
335 struct av7110
*av7110
= dvbdev
->priv
;
337 dprintk(8, "av7110:%p\n",av7110
);
338 return ci_ll_read(&av7110
->ci_rbuffer
, file
, buf
, count
, ppos
);
341 static const struct file_operations dvb_ca_fops
= {
342 .owner
= THIS_MODULE
,
344 .write
= dvb_ca_write
,
345 .unlocked_ioctl
= dvb_generic_ioctl
,
347 .release
= dvb_generic_release
,
349 .llseek
= default_llseek
,
352 static struct dvb_device dvbdev_ca
= {
356 .fops
= &dvb_ca_fops
,
357 .kernel_ioctl
= dvb_ca_ioctl
,
361 int av7110_ca_register(struct av7110
*av7110
)
363 return dvb_register_device(&av7110
->dvb_adapter
, &av7110
->ca_dev
,
364 &dvbdev_ca
, av7110
, DVB_DEVICE_CA
, 0);
367 void av7110_ca_unregister(struct av7110
*av7110
)
369 dvb_unregister_device(av7110
->ca_dev
);
372 int av7110_ca_init(struct av7110
* av7110
)
374 return ci_ll_init(&av7110
->ci_rbuffer
, &av7110
->ci_wbuffer
, 8192);
377 void av7110_ca_exit(struct av7110
* av7110
)
379 ci_ll_release(&av7110
->ci_rbuffer
, &av7110
->ci_wbuffer
);