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 + -
显示快捷键?