⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dvb_ca.c

📁 linux_dvb的驱动程序:linuxtv-dvb-1.1.1.rar
💻 C
📖 第 1 页 / 共 5 页
字号:
        return packet_size;}/* ******************************************************************************** *//* File IO interface functions *//** * Implementation of file open syscall. * * @param inode Inode concerned. * @param file File concerned. * * @return 0 on success, <0 on failure. */int dvb_ca_io_open(struct inode *inode, struct file *file) {        dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;        dvb_ca *ca=(dvb_ca*) dvbdev->priv;        int i;        int err=dvb_generic_open(inode, file);        if (err<0)                return err;        ca->open = 1;        return 0;}/** * Implementation of file close syscall. * * @param inode Inode concerned. * @param file File concerned. * * @return 0 on success, <0 on failure. */int dvb_ca_io_release(struct inode *inode, struct file *file) {        dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;        dvb_ca *ca=(dvb_ca*) dvbdev->priv;        int i;        /* mark the CA device as closed */        ca->open = 0;        /* flush connection buffers */        for(i=0; i< ca->slot_count; i++) {                dvb_ca_buf_flush_buffers(ca, slot);        }        int err=dvb_generic_release(inode, file);        if (err<0)                return err;        return 0;}/** * Implementation of poll() syscall. * * @param file File concerned. * @param wait poll wait table. * * @return Standard poll mask. */unsigned int dvb_ca_io_poll(struct file *file, poll_table *wait) {        dvb_device_t* dvbdev = (dvb_device_t*) file->private_data;        dvb_ca* ca = (dvb_ca*) dvbdev->priv;        unsigned int mask=0;        int slot;        struct dvb_ca_connection* cacon;        /* go through each slot looking to see if there is data available */        for(slot=0; slot < ca->slot_count; slot++) {                /* acquire the slot */                dvb_ca_slot_acquire(ca, slot);                /* go through each connection id to see if there is data available */                list_for_each_entry(cacon, &ca->slot_info[slot].connections, next) {                        /* if the RX queue is NOT empty... */                        if (dvb_ringbuffer_avail(&cacon->rx_buffer) > 3) {                                /* and if the first packet on the RX buffer is marked as complete, data is ready to be read */                                if (DVB_RINGBUFFER_PEEK(&cacon->rx_buffer, 2) == 1)                                        mask|= POLLIN;                        }                        /* is there data still to be written? */                        if (!dvb_ringbuffer_empty(&cacon->tx_buffer))                                mask|=POLLOUT;                }                /* finished with this slot now */                dvb_ca_slot_release(ca, slot);        }        /* if there is something, return now */        if (mask) return mask;        /* wait for something to happen */        poll_wait(file, &ca->read_queue, wait);        /* see if there is some data available now */        for(slot=0; slot < ca->slot_count; slot++) {                /* acquire the slot */                dvb_ca_slot_acquire(ca, slot);                /* go through each connection id to see if there is data available */                list_for_each_entry(cacon, &ca->slot_info[slot].connections, next) {                        /* if the RX queue is NOT empty... */                        if (dvb_ringbuffer_avail(&cacon->rx_buffer) > 3) {                                /* and if the first packet on the RX buffer is marked as complete, data is ready to be read */                                if (DVB_RINGBUFFER_PEEK(&cacon->rx_buffer, 2) == 1)                                        mask|= POLLIN;                        }                        /* is there data still to be written? */                        if (!dvb_ringbuffer_empty(&cacon->tx_buffer))                                mask|=POLLOUT;                }                /* finished with this slot now */                dvb_ca_slot_release(ca, slot);        }        return mask;}/** * Real ioctl implementation. * NOTE: CA_SEND_MSG/CA_GET_MSG ioctls have userspace buffers passed to them. * * @param inode Inode concerned. * @param file File concerned. * @param cmd IOCTL command. * @param arg Associated argument. * * @return 0 on success, <0 on error. */int dvb_ca_io_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) {        dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;        dvb_ca* ca=(dvb_ca*) dvbdev->priv;        int err=0;        int slot, connection_id;        ca_msg_t msg;        int msg_buf_offset = &msg.p.en50021.buf - &msg;        switch (cmd) {        case CA_RESET:                // FIXME: update                err=dvb_ci_ll_reset(&ci->wbuf, file, (int) parg, &ci->info[0]);                break;        case CA_GET_CAP:        {                if (ca->flags & DVB_CA_FLAG_EN50221) {                        ca_cap_t *cap = (ca_cap_t*) parg;                        cap->slot_num=ca->slot_count;                        cap->slot_type=CA_EN50221;                        cap->descr_num=0;                        cap->descr_type=0;                }                break;        }        case CA_GET_SLOT_INFO:        {                if (ca->flags & DVB_CA_FLAG_EN50221) {                        ca_slot_info_t *info=(ca_slot_info_t *)parg;                        if (info->num > ca->slot_count)                                return -EINVAL;                        info->type = CA_EN50221;                        info->flags = 0;                        if (ca->slot_info[info->num].cam_present)                                  info->flags = CA_CI_MODULE_PRESENT | CA_CI_MODULE_READY;                }                break;        }        case CA_GET_MSG:                if (ca->flags & DVB_CA_FLAG_EN50221) {                        if (copy_from_user(&msg, parg, msg_buf_offset)) return -EFAULT;                        err = dvb_ca_buf_copy_to_user(ca, file, parg + msg_buf_offset, msg.p.en50221.length, NULL, &slot, &connection_id);                        if (err >= 0) {                                msg.index = slot;                                msg.type = CA_EN50221;                                msg.p.en50221.connection_id = connection_id;                                msg.p.en50221.length = err;                                if (copy_to_user(&msg, parg, msg_buf_offset)) return -EFAULT;                        }                }                break;        case CA_SEND_MSG:                if ((ca->flags & DVB_CA_FLAG_EN50221) && (msg->type == CA_EN50221)) {                        if (copy_from_user(&msg, parg, msg_buf_offset)) return -EFAULT;                        err = dvb_ca_buf_copy_from_user(ca, file, parg + msg_buf_offset, msg.p.en50221.length, NULL,                                                        msg.index, msg.p.en50221.connection_id);                }                break;        case CA_GET_DESCR_INFO:        case CA_SET_DESCR:        case CA_SET_PID:                if (ca->flags & DVB_CA_FLAG_EN50221) {                        err=-EINVAL;                }                break;        default:                err=-EINVAL;                break;        }        if (ca->ioctl)                err=ca->ioctl(ca, cmd, parg);        if (err<0 && err!=-EINVAL)                return err;        return 0;}/** * Wrapper for ioctl implementation. * * @param inode Inode concerned. * @param file File concerned. * @param cmd IOCTL command. * @param arg Associated argument. * * @return 0 on success, <0 on error. */int dvb_ca_io_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) {        /* need to pass userspace buffer to these two */        if ((cmd == CA_GET_MSG) || (cmd == CA_SEND_MSG)) {                return dvb_ca_do_ioctl(inode, file, cmd, (void*) arg);        }        /* otherwise, just use the easy route */        return generic_usercopy(inode, file, cmd, arg, dvb_ca_io_do_ioctl);}/** * Implementation of write() syscall. * * @param file File structure. * @param buf Source buffer. * @param count Size of source buffer. * @param ppos Position in file (ignored). * * @return Number of bytes read, or <0 on error. */ssize_t dvb_ca_io_write(struct file *file, const char *buf, size_t count, loff_t *ppos) {        dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;        dvb_ca *ca=(dvb_ca*) dvbdev->priv;        u8 hdr[2];        u8 slot, connection_id;        /* Incoming packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */        if (count < 2) return -EINVAL;        /* extract slot and connection id */        if (copy_from_user(hdr, buf, 2)) return -EFAULT;        slot = hdr[0];        connection_id = hdr[1];        /* copy the data from the buffer */        status = dvb_ca_buf_copy_from_user(ca, file, buf+2, count-2, ppos, slot, connection_id);        if (status < 0) return status;        /* success */        return status + 2;}/** * Implementation of read() syscall. * * @param file File structure. * @param buf Destination buffer. * @param count Size of destination buffer. * @param ppos Position in file (ignored). * * @return Number of bytes read, or <0 on error. */ssize_t dvb_ca_io_read(struct file *file, char *buf, size_t count, loff_t *ppos) {        dvb_device_t *dvbdev=(dvb_device_t *) file->private_data;        dvb_ca *ca=(dvb_ca*) dvbdev->priv;        int status;        u8 hdr[2];        u8 slot, connection_id;        /* Outgoing packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */        if (count < 2) return -EINVAL;        /* copy the data into the buffer */        status = dvb_ca_buf_copy_to_user(ca, file, buf+2, count-2, ppos, &slot, &connection_id);        if (status < 0) return status;        /* set the slot and connection id */        hdr[0] = slot;        hdr[1] = connetion_id;        if (copy_to_user(buf, hdr, 2)) return -EFAULT;        /* success */        return status + 2;}static struct file_operations dvb_ca_fops = {        owner: THIS_MODULE,        read: dvb_ca_io_read,        write: dvb_ca_io_write,        ioctl: dvb_ca_io_ioctl,        open: dvb_ca_io_open,        release: dvb_ca_io_release,        poll: dvb_ca_io_poll,};static dvb_device_t dvbdev_ca = {        priv: 0,        users: 1,        writers: 1,        fops: &dvb_ca_fops,};/* ******************************************************************************** *//* Initialisation/shutdown functions *//** * Initialise a new DVB CA device. * * @param dvb_adapter DVB adapter to attach the new CA device to. * @param ca_dev The dvb_device_t to return. * @param ca The dvb_ca instance. * * @return 0 on success, non

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -