📄 dvb_ca.c
字号:
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 + -