18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * av7110_ca.c: CA and CI stuff 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 1999-2002 Ralph Metzler 68c2ecf20Sopenharmony_ci * & Marcus Metzler for convergence integrated media GmbH 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * originally based on code by: 98c2ecf20Sopenharmony_ci * Copyright (C) 1998,1999 Christian Theiss <mistert@rz.fh-augsburg.de> 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * the project's page is at https://linuxtv.org 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/kernel.h> 158c2ecf20Sopenharmony_ci#include <linux/types.h> 168c2ecf20Sopenharmony_ci#include <linux/delay.h> 178c2ecf20Sopenharmony_ci#include <linux/fs.h> 188c2ecf20Sopenharmony_ci#include <linux/timer.h> 198c2ecf20Sopenharmony_ci#include <linux/poll.h> 208c2ecf20Sopenharmony_ci#include <linux/gfp.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include "av7110.h" 238c2ecf20Sopenharmony_ci#include "av7110_hw.h" 248c2ecf20Sopenharmony_ci#include "av7110_ca.h" 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_civoid CI_handle(struct av7110 *av7110, u8 *data, u16 len) 288c2ecf20Sopenharmony_ci{ 298c2ecf20Sopenharmony_ci dprintk(8, "av7110:%p\n",av7110); 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci if (len < 3) 328c2ecf20Sopenharmony_ci return; 338c2ecf20Sopenharmony_ci switch (data[0]) { 348c2ecf20Sopenharmony_ci case CI_MSG_CI_INFO: 358c2ecf20Sopenharmony_ci if (data[2] != 1 && data[2] != 2) 368c2ecf20Sopenharmony_ci break; 378c2ecf20Sopenharmony_ci switch (data[1]) { 388c2ecf20Sopenharmony_ci case 0: 398c2ecf20Sopenharmony_ci av7110->ci_slot[data[2] - 1].flags = 0; 408c2ecf20Sopenharmony_ci break; 418c2ecf20Sopenharmony_ci case 1: 428c2ecf20Sopenharmony_ci av7110->ci_slot[data[2] - 1].flags |= CA_CI_MODULE_PRESENT; 438c2ecf20Sopenharmony_ci break; 448c2ecf20Sopenharmony_ci case 2: 458c2ecf20Sopenharmony_ci av7110->ci_slot[data[2] - 1].flags |= CA_CI_MODULE_READY; 468c2ecf20Sopenharmony_ci break; 478c2ecf20Sopenharmony_ci } 488c2ecf20Sopenharmony_ci break; 498c2ecf20Sopenharmony_ci case CI_SWITCH_PRG_REPLY: 508c2ecf20Sopenharmony_ci //av7110->ci_stat=data[1]; 518c2ecf20Sopenharmony_ci break; 528c2ecf20Sopenharmony_ci default: 538c2ecf20Sopenharmony_ci break; 548c2ecf20Sopenharmony_ci } 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_civoid ci_get_data(struct dvb_ringbuffer *cibuf, u8 *data, int len) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci if (dvb_ringbuffer_free(cibuf) < len + 2) 618c2ecf20Sopenharmony_ci return; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci DVB_RINGBUFFER_WRITE_BYTE(cibuf, len >> 8); 648c2ecf20Sopenharmony_ci DVB_RINGBUFFER_WRITE_BYTE(cibuf, len & 0xff); 658c2ecf20Sopenharmony_ci dvb_ringbuffer_write(cibuf, data, len); 668c2ecf20Sopenharmony_ci wake_up_interruptible(&cibuf->queue); 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci/****************************************************************************** 718c2ecf20Sopenharmony_ci * CI link layer file ops 728c2ecf20Sopenharmony_ci ******************************************************************************/ 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic int ci_ll_init(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf, int size) 758c2ecf20Sopenharmony_ci{ 768c2ecf20Sopenharmony_ci struct dvb_ringbuffer *tab[] = { cirbuf, ciwbuf, NULL }, **p; 778c2ecf20Sopenharmony_ci void *data; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci for (p = tab; *p; p++) { 808c2ecf20Sopenharmony_ci data = vmalloc(size); 818c2ecf20Sopenharmony_ci if (!data) { 828c2ecf20Sopenharmony_ci while (p-- != tab) { 838c2ecf20Sopenharmony_ci vfree(p[0]->data); 848c2ecf20Sopenharmony_ci p[0]->data = NULL; 858c2ecf20Sopenharmony_ci } 868c2ecf20Sopenharmony_ci return -ENOMEM; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci dvb_ringbuffer_init(*p, data, size); 898c2ecf20Sopenharmony_ci } 908c2ecf20Sopenharmony_ci return 0; 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistatic void ci_ll_flush(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci dvb_ringbuffer_flush_spinlock_wakeup(cirbuf); 968c2ecf20Sopenharmony_ci dvb_ringbuffer_flush_spinlock_wakeup(ciwbuf); 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic void ci_ll_release(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci vfree(cirbuf->data); 1028c2ecf20Sopenharmony_ci cirbuf->data = NULL; 1038c2ecf20Sopenharmony_ci vfree(ciwbuf->data); 1048c2ecf20Sopenharmony_ci ciwbuf->data = NULL; 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cistatic int ci_ll_reset(struct dvb_ringbuffer *cibuf, struct file *file, 1088c2ecf20Sopenharmony_ci int slots, struct ca_slot_info *slot) 1098c2ecf20Sopenharmony_ci{ 1108c2ecf20Sopenharmony_ci int i; 1118c2ecf20Sopenharmony_ci int len = 0; 1128c2ecf20Sopenharmony_ci u8 msg[8] = { 0x00, 0x06, 0x00, 0x00, 0xff, 0x02, 0x00, 0x00 }; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 1158c2ecf20Sopenharmony_ci if (slots & (1 << i)) 1168c2ecf20Sopenharmony_ci len += 8; 1178c2ecf20Sopenharmony_ci } 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci if (dvb_ringbuffer_free(cibuf) < len) 1208c2ecf20Sopenharmony_ci return -EBUSY; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 1238c2ecf20Sopenharmony_ci if (slots & (1 << i)) { 1248c2ecf20Sopenharmony_ci msg[2] = i; 1258c2ecf20Sopenharmony_ci dvb_ringbuffer_write(cibuf, msg, 8); 1268c2ecf20Sopenharmony_ci slot[i].flags = 0; 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci } 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci return 0; 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistatic ssize_t ci_ll_write(struct dvb_ringbuffer *cibuf, struct file *file, 1348c2ecf20Sopenharmony_ci const char __user *buf, size_t count, loff_t *ppos) 1358c2ecf20Sopenharmony_ci{ 1368c2ecf20Sopenharmony_ci int free; 1378c2ecf20Sopenharmony_ci int non_blocking = file->f_flags & O_NONBLOCK; 1388c2ecf20Sopenharmony_ci u8 *page = (u8 *)__get_free_page(GFP_USER); 1398c2ecf20Sopenharmony_ci int res; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci if (!page) 1428c2ecf20Sopenharmony_ci return -ENOMEM; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci res = -EINVAL; 1458c2ecf20Sopenharmony_ci if (count > 2048) 1468c2ecf20Sopenharmony_ci goto out; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci res = -EFAULT; 1498c2ecf20Sopenharmony_ci if (copy_from_user(page, buf, count)) 1508c2ecf20Sopenharmony_ci goto out; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci free = dvb_ringbuffer_free(cibuf); 1538c2ecf20Sopenharmony_ci if (count + 2 > free) { 1548c2ecf20Sopenharmony_ci res = -EWOULDBLOCK; 1558c2ecf20Sopenharmony_ci if (non_blocking) 1568c2ecf20Sopenharmony_ci goto out; 1578c2ecf20Sopenharmony_ci res = -ERESTARTSYS; 1588c2ecf20Sopenharmony_ci if (wait_event_interruptible(cibuf->queue, 1598c2ecf20Sopenharmony_ci (dvb_ringbuffer_free(cibuf) >= count + 2))) 1608c2ecf20Sopenharmony_ci goto out; 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci DVB_RINGBUFFER_WRITE_BYTE(cibuf, count >> 8); 1648c2ecf20Sopenharmony_ci DVB_RINGBUFFER_WRITE_BYTE(cibuf, count & 0xff); 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci res = dvb_ringbuffer_write(cibuf, page, count); 1678c2ecf20Sopenharmony_ciout: 1688c2ecf20Sopenharmony_ci free_page((unsigned long)page); 1698c2ecf20Sopenharmony_ci return res; 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_cistatic ssize_t ci_ll_read(struct dvb_ringbuffer *cibuf, struct file *file, 1738c2ecf20Sopenharmony_ci char __user *buf, size_t count, loff_t *ppos) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci int avail; 1768c2ecf20Sopenharmony_ci int non_blocking = file->f_flags & O_NONBLOCK; 1778c2ecf20Sopenharmony_ci ssize_t len; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci if (!cibuf->data || !count) 1808c2ecf20Sopenharmony_ci return 0; 1818c2ecf20Sopenharmony_ci if (non_blocking && (dvb_ringbuffer_empty(cibuf))) 1828c2ecf20Sopenharmony_ci return -EWOULDBLOCK; 1838c2ecf20Sopenharmony_ci if (wait_event_interruptible(cibuf->queue, 1848c2ecf20Sopenharmony_ci !dvb_ringbuffer_empty(cibuf))) 1858c2ecf20Sopenharmony_ci return -ERESTARTSYS; 1868c2ecf20Sopenharmony_ci avail = dvb_ringbuffer_avail(cibuf); 1878c2ecf20Sopenharmony_ci if (avail < 4) 1888c2ecf20Sopenharmony_ci return 0; 1898c2ecf20Sopenharmony_ci len = DVB_RINGBUFFER_PEEK(cibuf, 0) << 8; 1908c2ecf20Sopenharmony_ci len |= DVB_RINGBUFFER_PEEK(cibuf, 1); 1918c2ecf20Sopenharmony_ci if (avail < len + 2 || count < len) 1928c2ecf20Sopenharmony_ci return -EINVAL; 1938c2ecf20Sopenharmony_ci DVB_RINGBUFFER_SKIP(cibuf, 2); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci return dvb_ringbuffer_read_user(cibuf, buf, len); 1968c2ecf20Sopenharmony_ci} 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_cistatic int dvb_ca_open(struct inode *inode, struct file *file) 1998c2ecf20Sopenharmony_ci{ 2008c2ecf20Sopenharmony_ci struct dvb_device *dvbdev = file->private_data; 2018c2ecf20Sopenharmony_ci struct av7110 *av7110 = dvbdev->priv; 2028c2ecf20Sopenharmony_ci int err = dvb_generic_open(inode, file); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci dprintk(8, "av7110:%p\n",av7110); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci if (err < 0) 2078c2ecf20Sopenharmony_ci return err; 2088c2ecf20Sopenharmony_ci ci_ll_flush(&av7110->ci_rbuffer, &av7110->ci_wbuffer); 2098c2ecf20Sopenharmony_ci return 0; 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cistatic __poll_t dvb_ca_poll (struct file *file, poll_table *wait) 2138c2ecf20Sopenharmony_ci{ 2148c2ecf20Sopenharmony_ci struct dvb_device *dvbdev = file->private_data; 2158c2ecf20Sopenharmony_ci struct av7110 *av7110 = dvbdev->priv; 2168c2ecf20Sopenharmony_ci struct dvb_ringbuffer *rbuf = &av7110->ci_rbuffer; 2178c2ecf20Sopenharmony_ci struct dvb_ringbuffer *wbuf = &av7110->ci_wbuffer; 2188c2ecf20Sopenharmony_ci __poll_t mask = 0; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci dprintk(8, "av7110:%p\n",av7110); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci poll_wait(file, &rbuf->queue, wait); 2238c2ecf20Sopenharmony_ci poll_wait(file, &wbuf->queue, wait); 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci if (!dvb_ringbuffer_empty(rbuf)) 2268c2ecf20Sopenharmony_ci mask |= (EPOLLIN | EPOLLRDNORM); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci if (dvb_ringbuffer_free(wbuf) > 1024) 2298c2ecf20Sopenharmony_ci mask |= (EPOLLOUT | EPOLLWRNORM); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci return mask; 2328c2ecf20Sopenharmony_ci} 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_cistatic int dvb_ca_ioctl(struct file *file, unsigned int cmd, void *parg) 2358c2ecf20Sopenharmony_ci{ 2368c2ecf20Sopenharmony_ci struct dvb_device *dvbdev = file->private_data; 2378c2ecf20Sopenharmony_ci struct av7110 *av7110 = dvbdev->priv; 2388c2ecf20Sopenharmony_ci unsigned long arg = (unsigned long) parg; 2398c2ecf20Sopenharmony_ci int ret = 0; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci dprintk(8, "av7110:%p\n",av7110); 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(&av7110->ioctl_mutex)) 2448c2ecf20Sopenharmony_ci return -ERESTARTSYS; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci switch (cmd) { 2478c2ecf20Sopenharmony_ci case CA_RESET: 2488c2ecf20Sopenharmony_ci ret = ci_ll_reset(&av7110->ci_wbuffer, file, arg, 2498c2ecf20Sopenharmony_ci &av7110->ci_slot[0]); 2508c2ecf20Sopenharmony_ci break; 2518c2ecf20Sopenharmony_ci case CA_GET_CAP: 2528c2ecf20Sopenharmony_ci { 2538c2ecf20Sopenharmony_ci struct ca_caps cap; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci cap.slot_num = 2; 2568c2ecf20Sopenharmony_ci cap.slot_type = (FW_CI_LL_SUPPORT(av7110->arm_app) ? 2578c2ecf20Sopenharmony_ci CA_CI_LINK : CA_CI) | CA_DESCR; 2588c2ecf20Sopenharmony_ci cap.descr_num = 16; 2598c2ecf20Sopenharmony_ci cap.descr_type = CA_ECD; 2608c2ecf20Sopenharmony_ci memcpy(parg, &cap, sizeof(cap)); 2618c2ecf20Sopenharmony_ci break; 2628c2ecf20Sopenharmony_ci } 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci case CA_GET_SLOT_INFO: 2658c2ecf20Sopenharmony_ci { 2668c2ecf20Sopenharmony_ci struct ca_slot_info *info=(struct ca_slot_info *)parg; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci if (info->num < 0 || info->num > 1) { 2698c2ecf20Sopenharmony_ci mutex_unlock(&av7110->ioctl_mutex); 2708c2ecf20Sopenharmony_ci return -EINVAL; 2718c2ecf20Sopenharmony_ci } 2728c2ecf20Sopenharmony_ci av7110->ci_slot[info->num].num = info->num; 2738c2ecf20Sopenharmony_ci av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ? 2748c2ecf20Sopenharmony_ci CA_CI_LINK : CA_CI; 2758c2ecf20Sopenharmony_ci memcpy(info, &av7110->ci_slot[info->num], sizeof(struct ca_slot_info)); 2768c2ecf20Sopenharmony_ci break; 2778c2ecf20Sopenharmony_ci } 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci case CA_GET_MSG: 2808c2ecf20Sopenharmony_ci break; 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci case CA_SEND_MSG: 2838c2ecf20Sopenharmony_ci break; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci case CA_GET_DESCR_INFO: 2868c2ecf20Sopenharmony_ci { 2878c2ecf20Sopenharmony_ci struct ca_descr_info info; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci info.num = 16; 2908c2ecf20Sopenharmony_ci info.type = CA_ECD; 2918c2ecf20Sopenharmony_ci memcpy(parg, &info, sizeof (info)); 2928c2ecf20Sopenharmony_ci break; 2938c2ecf20Sopenharmony_ci } 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci case CA_SET_DESCR: 2968c2ecf20Sopenharmony_ci { 2978c2ecf20Sopenharmony_ci struct ca_descr *descr = (struct ca_descr*) parg; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci if (descr->index >= 16 || descr->parity > 1) { 3008c2ecf20Sopenharmony_ci mutex_unlock(&av7110->ioctl_mutex); 3018c2ecf20Sopenharmony_ci return -EINVAL; 3028c2ecf20Sopenharmony_ci } 3038c2ecf20Sopenharmony_ci av7110_fw_cmd(av7110, COMTYPE_PIDFILTER, SetDescr, 5, 3048c2ecf20Sopenharmony_ci (descr->index<<8)|descr->parity, 3058c2ecf20Sopenharmony_ci (descr->cw[0]<<8)|descr->cw[1], 3068c2ecf20Sopenharmony_ci (descr->cw[2]<<8)|descr->cw[3], 3078c2ecf20Sopenharmony_ci (descr->cw[4]<<8)|descr->cw[5], 3088c2ecf20Sopenharmony_ci (descr->cw[6]<<8)|descr->cw[7]); 3098c2ecf20Sopenharmony_ci break; 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci default: 3138c2ecf20Sopenharmony_ci ret = -EINVAL; 3148c2ecf20Sopenharmony_ci break; 3158c2ecf20Sopenharmony_ci } 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci mutex_unlock(&av7110->ioctl_mutex); 3188c2ecf20Sopenharmony_ci return ret; 3198c2ecf20Sopenharmony_ci} 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_cistatic ssize_t dvb_ca_write(struct file *file, const char __user *buf, 3228c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 3238c2ecf20Sopenharmony_ci{ 3248c2ecf20Sopenharmony_ci struct dvb_device *dvbdev = file->private_data; 3258c2ecf20Sopenharmony_ci struct av7110 *av7110 = dvbdev->priv; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci dprintk(8, "av7110:%p\n",av7110); 3288c2ecf20Sopenharmony_ci return ci_ll_write(&av7110->ci_wbuffer, file, buf, count, ppos); 3298c2ecf20Sopenharmony_ci} 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_cistatic ssize_t dvb_ca_read(struct file *file, char __user *buf, 3328c2ecf20Sopenharmony_ci size_t count, loff_t *ppos) 3338c2ecf20Sopenharmony_ci{ 3348c2ecf20Sopenharmony_ci struct dvb_device *dvbdev = file->private_data; 3358c2ecf20Sopenharmony_ci struct av7110 *av7110 = dvbdev->priv; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci dprintk(8, "av7110:%p\n",av7110); 3388c2ecf20Sopenharmony_ci return ci_ll_read(&av7110->ci_rbuffer, file, buf, count, ppos); 3398c2ecf20Sopenharmony_ci} 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_cistatic const struct file_operations dvb_ca_fops = { 3428c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 3438c2ecf20Sopenharmony_ci .read = dvb_ca_read, 3448c2ecf20Sopenharmony_ci .write = dvb_ca_write, 3458c2ecf20Sopenharmony_ci .unlocked_ioctl = dvb_generic_ioctl, 3468c2ecf20Sopenharmony_ci .open = dvb_ca_open, 3478c2ecf20Sopenharmony_ci .release = dvb_generic_release, 3488c2ecf20Sopenharmony_ci .poll = dvb_ca_poll, 3498c2ecf20Sopenharmony_ci .llseek = default_llseek, 3508c2ecf20Sopenharmony_ci}; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_cistatic struct dvb_device dvbdev_ca = { 3538c2ecf20Sopenharmony_ci .priv = NULL, 3548c2ecf20Sopenharmony_ci .users = 1, 3558c2ecf20Sopenharmony_ci .writers = 1, 3568c2ecf20Sopenharmony_ci .fops = &dvb_ca_fops, 3578c2ecf20Sopenharmony_ci .kernel_ioctl = dvb_ca_ioctl, 3588c2ecf20Sopenharmony_ci}; 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ciint av7110_ca_register(struct av7110 *av7110) 3628c2ecf20Sopenharmony_ci{ 3638c2ecf20Sopenharmony_ci return dvb_register_device(&av7110->dvb_adapter, &av7110->ca_dev, 3648c2ecf20Sopenharmony_ci &dvbdev_ca, av7110, DVB_DEVICE_CA, 0); 3658c2ecf20Sopenharmony_ci} 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_civoid av7110_ca_unregister(struct av7110 *av7110) 3688c2ecf20Sopenharmony_ci{ 3698c2ecf20Sopenharmony_ci dvb_unregister_device(av7110->ca_dev); 3708c2ecf20Sopenharmony_ci} 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ciint av7110_ca_init(struct av7110* av7110) 3738c2ecf20Sopenharmony_ci{ 3748c2ecf20Sopenharmony_ci return ci_ll_init(&av7110->ci_rbuffer, &av7110->ci_wbuffer, 8192); 3758c2ecf20Sopenharmony_ci} 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_civoid av7110_ca_exit(struct av7110* av7110) 3788c2ecf20Sopenharmony_ci{ 3798c2ecf20Sopenharmony_ci ci_ll_release(&av7110->ci_rbuffer, &av7110->ci_wbuffer); 3808c2ecf20Sopenharmony_ci} 381