dst_ca.c
来自「trident tm5600的linux驱动」· C语言 代码 · 共 816 行 · 第 1/2 页
C
816 行
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;}#if 0/* MMI */static int ca_get_mmi(struct dst_state *state, struct ca_msg *hw_msg, struct ca_msg *mmi_msg){ static u8 get_mmi[] = { 0x07, 0x40, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x0f }; put_checksum(&get_mmi[0], 7); if ((dst_put_ci(state, get_mmi, sizeof (get_mmi), hw_msg->msg, GET_REPLY)) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !"); return -1; } dprintk(verbose, DST_CA_NOTICE, 1, " -->dst_put_ci SUCCESS !"); memcpy(mmi_msg->msg, hw_msg->msg, hw_msg->msg[4]); return 0;}/** * Get Menu should be the first MMI function (like open !) */static int ca_get_menu(struct dst_state *state){ static u8 get_menu[] = { 0x07, 0x40, 0x00, 0x00, 0x09, 0x00, 0x00, 0xff }; put_checksum(&get_menu[0], 7); if ((dst_put_ci(state, get_menu, sizeof (get_menu), get_menu, NO_REPLY)) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !"); return -1; } dprintk(verbose, DST_CA_NOTICE, 1, " -->dst_put_ci SUCCESS !"); return 0;}/** * MMI Enq (Enquire the application to allow user input) */static int ca_answer_menu(struct dst_state *state, struct ca_msg *hw_msg, struct ca_msg *menu_answ){ u8 choice = 0; static u8 answer_menu[] = { 0x08, 0x40, 0x00, 0x00, 0x0b, 0x01, 0x00, 0x01, 0xff }; /* derive answer from menu (This comes from the user) */ answer_menu[7] = choice; put_checksum(&answer_menu[0], 7); if ((dst_put_ci(state, answer_menu, sizeof (answer_menu), hw_msg->msg, NO_REPLY)) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !"); return -1; } dprintk(verbose, DST_CA_NOTICE, 1, " -->dst_put_ci SUCCESS !"); return 0;}static int ca_answer_mmi(struct dst_state *state, struct ca_msg *hw_msg, struct ca_msg *answ_msg){ u8 answer =0, length = 0; static u8 answer_mmi[] = { 0x08, 0x40, 0x00, 0x00, 0x08, 0x01, 0x00, 0x01, 0xff }; /* derive answer from answ_msg (This comes from the user) */ if (answer == 0) /* 0x00 == Cancel */ answer_mmi[7] = 0x00; else { /* 0x01 == Answer */ length = strlen(answ_msg->msg); memcpy(&answer_mmi[8], answ_msg->msg, length); answer_mmi[0] += length; answer_mmi[5] += length; } put_checksum(&answer_mmi[0], (8 + length)); if ((dst_put_ci(state, answer_mmi, sizeof (answer_mmi), hw_msg->msg, GET_REPLY)) < 0) { dprintk(verbose, DST_CA_NOTICE, 1, " -->dst_put_ci FAILED !"); return -1; } dprintk(verbose, DST_CA_NOTICE, 1, " -->dst_put_ci SUCCESS !"); return 0;}static int ca_close_mmi(struct dst_state *state, struct ca_msg *hw_msg){ static u8 close_mmi[] = { 0x07, 0x40, 0x00, 0x00, 0x0e, 0x00, 0x00, 0xff }; put_checksum(&close_mmi[0], 7); if ((dst_put_ci(state, close_mmi, sizeof (close_mmi), hw_msg->msg, NO_REPLY)) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->dst_put_ci FAILED !"); return -1; } dprintk(verbose, DST_CA_NOTICE, 1, " -->dst_put_ci SUCCESS !"); return 0;}#endifstatic 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 = 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; case CA_INFO_ENQUIRY: dprintk(verbose, DST_CA_INFO, 1, " Getting CA Information"); if ((ca_get_ca_info(state)) < 0) { dprintk(verbose, DST_CA_ERROR, 1, " -->CA_INFO_ENQUIRY Failed !"); result = -1; goto free_mem_and_exit; } dprintk(verbose, DST_CA_INFO, 1, " -->CA_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; p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL); p_ca_slot_info = kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL); p_ca_caps = kmalloc(sizeof (struct ca_caps), GFP_KERNEL); if (!p_ca_message || !p_ca_slot_info || !p_ca_caps) { dprintk(verbose, DST_CA_ERROR, 1, " Memory allocation failure"); result = -ENOMEM; goto free_mem_and_exit; } /* 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){ ssize_t 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};struct dvb_device *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"); if (dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst, DVB_DEVICE_CA) == 0) { dst->dst_ca = dvbdev; return dst->dst_ca; } return NULL;}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 + =
减小字号Ctrl + -
显示快捷键?