📄 dst_ca.c
字号:
dprintk(verbose, DST_CA_DEBUG, 1, " Length field=[%02x]", length_field); if (length_field < 0x80) { length = length_field & 0x7f; dprintk(verbose, DST_CA_DEBUG, 1, " Length=[%02x]\n", length); } else { word_count = length_field & 0x7f; for (count = 0; count < word_count; count++) { length = length << 8; length += asn_1_array[count + 1]; dprintk(verbose, DST_CA_DEBUG, 1, " Length=[%04x]", length); } } return length;}static int debug_string(u8 *msg, u32 length, u32 offset){ u32 i; dprintk(verbose, DST_CA_DEBUG, 0, " String=[ "); for (i = offset; i < length; i++) dprintk(verbose, DST_CA_DEBUG, 0, "%02x ", msg[i]); dprintk(verbose, DST_CA_DEBUG, 0, "]\n"); return 0;}static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query){ u32 length = 0; u8 tag_length = 8; length = asn_1_decode(&p_ca_message->msg[3]); dprintk(verbose, DST_CA_DEBUG, 1, " CA Message length=[%d]", length); debug_string(&p_ca_message->msg[4], length, 0); /* length is excluding tag & length */ memset(hw_buffer->msg, '\0', length); handle_dst_tag(state, p_ca_message, hw_buffer, length); put_checksum(hw_buffer->msg, hw_buffer->msg[0]); debug_string(hw_buffer->msg, (length + tag_length), 0); /* tags too */ write_to_8820(state, hw_buffer, (length + tag_length), reply); return 0;}/* Board supports CA PMT reply ? */static int dst_check_ca_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer){ int ca_pmt_reply_test = 0; /* Do test board */ /* Not there yet but soon */ /* CA PMT Reply capable */ if (ca_pmt_reply_test) { if ((ca_set_pmt(state, p_ca_message, hw_buffer, 1, GET_REPLY)) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " ca_set_pmt.. failed !"); return -1; } /* Process CA PMT Reply */ /* will implement soon */ dprintk(verbose, DST_CA_ERROR, 1, " Not there yet"); } /* CA PMT Reply not capable */ if (!ca_pmt_reply_test) { if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, NO_REPLY)) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " ca_set_pmt.. failed !"); return -1; } dprintk(verbose, DST_CA_NOTICE, 1, " ca_set_pmt.. success !"); /* put a dummy message */ } return 0;}static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, void __user *arg){ int i = 0; unsigned int ca_message_header_len; u32 command = 0; struct ca_msg *hw_buffer; int result = 0; if ((hw_buffer = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) { dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure"); return -ENOMEM; } dprintk(verbose, DST_CA_DEBUG, 1, " "); if (copy_from_user(p_ca_message, arg, sizeof (struct ca_msg))) { result = -EFAULT; goto free_mem_and_exit; } if (p_ca_message->msg) { ca_message_header_len = p_ca_message->length; /* Restore it back when you are done */ /* EN50221 tag */ command = 0; for (i = 0; i < 3; i++) { command = command | p_ca_message->msg[i]; if (i < 2) command = command << 8; } dprintk(verbose, DST_CA_DEBUG, 1, " Command=[0x%x]\n", command); switch (command) { case CA_PMT: dprintk(verbose, DST_CA_DEBUG, 1, "Command = SEND_CA_PMT"); if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) { // code simplification started dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT Failed !"); result = -1; goto free_mem_and_exit; } dprintk(verbose, DST_CA_INFO, 1, " -->CA_PMT Success !"); break; case CA_PMT_REPLY: dprintk(verbose, DST_CA_INFO, 1, "Command = CA_PMT_REPLY"); /* Have to handle the 2 basic types of cards here */ if ((dst_check_ca_pmt(state, p_ca_message, hw_buffer)) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->CA_PMT_REPLY Failed !"); result = -1; goto free_mem_and_exit; } dprintk(verbose, DST_CA_INFO, 1, " -->CA_PMT_REPLY Success !"); break; case CA_APP_INFO_ENQUIRY: // only for debugging dprintk(verbose, DST_CA_INFO, 1, " Getting Cam Application information"); if ((ca_get_app_info(state)) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->CA_APP_INFO_ENQUIRY Failed !"); result = -1; goto free_mem_and_exit; } dprintk(verbose, DST_CA_INFO, 1, " -->CA_APP_INFO_ENQUIRY Success !"); break; } }free_mem_and_exit: kfree (hw_buffer); return result;}static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long ioctl_arg){ struct dvb_device* dvbdev = (struct dvb_device*) file->private_data; struct dst_state* state = (struct dst_state*) dvbdev->priv; struct ca_slot_info *p_ca_slot_info; struct ca_caps *p_ca_caps; struct ca_msg *p_ca_message; void __user *arg = (void __user *)ioctl_arg; int result = 0; if ((p_ca_message = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) { dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure"); return -ENOMEM; } if ((p_ca_slot_info = (struct ca_slot_info *) kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL)) == NULL) { dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure"); return -ENOMEM; } if ((p_ca_caps = (struct ca_caps *) kmalloc(sizeof (struct ca_caps), GFP_KERNEL)) == NULL) { dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure"); return -ENOMEM; } /* We have now only the standard ioctl's, the driver is upposed to handle internals. */ switch (cmd) { case CA_SEND_MSG: dprintk(verbose, DST_CA_INFO, 1, " Sending message"); if ((ca_send_message(state, p_ca_message, arg)) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SEND_MSG Failed !"); result = -1; goto free_mem_and_exit; } break; case CA_GET_MSG: dprintk(verbose, DST_CA_INFO, 1, " Getting message"); if ((ca_get_message(state, p_ca_message, arg)) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_MSG Failed !"); result = -1; goto free_mem_and_exit; } dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_MSG Success !"); break; case CA_RESET: dprintk(verbose, DST_CA_ERROR, 1, " Resetting DST"); dst_error_bailout(state); msleep(4000); break; case CA_GET_SLOT_INFO: dprintk(verbose, DST_CA_INFO, 1, " Getting Slot info"); if ((ca_get_slot_info(state, p_ca_slot_info, arg)) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_SLOT_INFO Failed !"); result = -1; goto free_mem_and_exit; } dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_SLOT_INFO Success !"); break; case CA_GET_CAP: dprintk(verbose, DST_CA_INFO, 1, " Getting Slot capabilities"); if ((ca_get_slot_caps(state, p_ca_caps, arg)) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_CAP Failed !"); result = -1; goto free_mem_and_exit; } dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_CAP Success !"); break; case CA_GET_DESCR_INFO: dprintk(verbose, DST_CA_INFO, 1, " Getting descrambler description"); if ((ca_get_slot_descr(state, p_ca_message, arg)) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->CA_GET_DESCR_INFO Failed !"); result = -1; goto free_mem_and_exit; } dprintk(verbose, DST_CA_INFO, 1, " -->CA_GET_DESCR_INFO Success !"); break; case CA_SET_DESCR: dprintk(verbose, DST_CA_INFO, 1, " Setting descrambler"); if ((ca_set_slot_descr()) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SET_DESCR Failed !"); result = -1; goto free_mem_and_exit; } dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_DESCR Success !"); break; case CA_SET_PID: dprintk(verbose, DST_CA_INFO, 1, " Setting PID"); if ((ca_set_pid()) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->CA_SET_PID Failed !"); result = -1; goto free_mem_and_exit; } dprintk(verbose, DST_CA_INFO, 1, " -->CA_SET_PID Success !"); default: result = -EOPNOTSUPP; }; free_mem_and_exit: kfree (p_ca_message); kfree (p_ca_slot_info); kfree (p_ca_caps); return result;}static int dst_ca_open(struct inode *inode, struct file *file){ dprintk(verbose, DST_CA_DEBUG, 1, " Device opened [%p] ", file); try_module_get(THIS_MODULE); return 0;}static int dst_ca_release(struct inode *inode, struct file *file){ dprintk(verbose, DST_CA_DEBUG, 1, " Device closed."); module_put(THIS_MODULE); return 0;}static ssize_t dst_ca_read(struct file *file, char __user *buffer, size_t length, loff_t *offset){ int bytes_read = 0; dprintk(verbose, DST_CA_DEBUG, 1, " Device read."); return bytes_read;}static ssize_t dst_ca_write(struct file *file, const char __user *buffer, size_t length, loff_t *offset){ dprintk(verbose, DST_CA_DEBUG, 1, " Device write."); return 0;}static struct file_operations dst_ca_fops = { .owner = THIS_MODULE, .ioctl = dst_ca_ioctl, .open = dst_ca_open, .release = dst_ca_release, .read = dst_ca_read, .write = dst_ca_write};static struct dvb_device dvbdev_ca = { .priv = NULL, .users = 1, .readers = 1, .writers = 1, .fops = &dst_ca_fops};int dst_ca_attach(struct dst_state *dst, struct dvb_adapter *dvb_adapter){ struct dvb_device *dvbdev; dprintk(verbose, DST_CA_ERROR, 1, "registering DST-CA device"); dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst, DVB_DEVICE_CA); return 0;}EXPORT_SYMBOL(dst_ca_attach);MODULE_DESCRIPTION("DST DVB-S/T/C Combo CA driver");MODULE_AUTHOR("Manu Abraham");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -