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

📄 af9005.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	memset(ibuf, 0, sizeof(ibuf));	obuf[0] = 14;		/* length of rest of packet low */	obuf[1] = 0;		/* length of rest of packer high */	obuf[2] = 0x2a;		/* read/write eeprom */	obuf[3] = 12;		/* size */	obuf[4] = st->sequence++;	obuf[5] = 0;		/* read */	obuf[6] = len;	obuf[7] = address;	ret = af9005_usb_generic_rw(d, obuf, 16, ibuf, 14, 0);	if (ret)		return ret;	if (ibuf[2] != 0x2b) {		err("Read eeprom, invalid reply code");		return -EIO;	}	if (ibuf[3] != 10) {		err("Read eeprom, invalid reply length");		return -EIO;	}	if (ibuf[4] != obuf[4]) {		err("Read eeprom, wrong sequence in reply ");		return -EIO;	}	if (ibuf[5] != 1) {		err("Read eeprom, wrong status in reply ");		return -EIO;	}	for (i = 0; i < len; i++) {		values[i] = ibuf[6 + i];	}	return 0;}static int af9005_boot_packet(struct usb_device *udev, int type, u8 * reply){	u8 buf[FW_BULKOUT_SIZE + 2];	u16 checksum;	int act_len, i, ret;	memset(buf, 0, sizeof(buf));	buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff);	buf[1] = (u8) ((FW_BULKOUT_SIZE >> 8) & 0xff);	switch (type) {	case FW_CONFIG:		buf[2] = 0x11;		buf[3] = 0x04;		buf[4] = 0x00;	/* sequence number, original driver doesn't increment it here */		buf[5] = 0x03;		checksum = buf[4] + buf[5];		buf[6] = (u8) ((checksum >> 8) & 0xff);		buf[7] = (u8) (checksum & 0xff);		break;	case FW_CONFIRM:		buf[2] = 0x11;		buf[3] = 0x04;		buf[4] = 0x00;	/* sequence number, original driver doesn't increment it here */		buf[5] = 0x01;		checksum = buf[4] + buf[5];		buf[6] = (u8) ((checksum >> 8) & 0xff);		buf[7] = (u8) (checksum & 0xff);		break;	case FW_BOOT:		buf[2] = 0x10;		buf[3] = 0x08;		buf[4] = 0x00;	/* sequence number, original driver doesn't increment it here */		buf[5] = 0x97;		buf[6] = 0xaa;		buf[7] = 0x55;		buf[8] = 0xa5;		buf[9] = 0x5a;		checksum = 0;		for (i = 4; i <= 9; i++)			checksum += buf[i];		buf[10] = (u8) ((checksum >> 8) & 0xff);		buf[11] = (u8) (checksum & 0xff);		break;	default:		err("boot packet invalid boot packet type");		return -EINVAL;	}	deb_fw(">>> ");	debug_dump(buf, FW_BULKOUT_SIZE + 2, deb_fw);	ret = usb_bulk_msg(udev,			   usb_sndbulkpipe(udev, 0x02),			   buf, FW_BULKOUT_SIZE + 2, &act_len, 2000);	if (ret)		err("boot packet bulk message failed: %d (%d/%d)", ret,		    FW_BULKOUT_SIZE + 2, act_len);	else		ret = act_len != FW_BULKOUT_SIZE + 2 ? -1 : 0;	if (ret)		return ret;	memset(buf, 0, 9);	ret = usb_bulk_msg(udev,			   usb_rcvbulkpipe(udev, 0x01), buf, 9, &act_len, 2000);	if (ret) {		err("boot packet recv bulk message failed: %d", ret);		return ret;	}	deb_fw("<<< ");	debug_dump(buf, act_len, deb_fw);	checksum = 0;	switch (type) {	case FW_CONFIG:		if (buf[2] != 0x11) {			err("boot bad config header.");			return -EIO;		}		if (buf[3] != 0x05) {			err("boot bad config size.");			return -EIO;		}		if (buf[4] != 0x00) {			err("boot bad config sequence.");			return -EIO;		}		if (buf[5] != 0x04) {			err("boot bad config subtype.");			return -EIO;		}		for (i = 4; i <= 6; i++)			checksum += buf[i];		if (buf[7] * 256 + buf[8] != checksum) {			err("boot bad config checksum.");			return -EIO;		}		*reply = buf[6];		break;	case FW_CONFIRM:		if (buf[2] != 0x11) {			err("boot bad confirm header.");			return -EIO;		}		if (buf[3] != 0x05) {			err("boot bad confirm size.");			return -EIO;		}		if (buf[4] != 0x00) {			err("boot bad confirm sequence.");			return -EIO;		}		if (buf[5] != 0x02) {			err("boot bad confirm subtype.");			return -EIO;		}		for (i = 4; i <= 6; i++)			checksum += buf[i];		if (buf[7] * 256 + buf[8] != checksum) {			err("boot bad confirm checksum.");			return -EIO;		}		*reply = buf[6];		break;	case FW_BOOT:		if (buf[2] != 0x10) {			err("boot bad boot header.");			return -EIO;		}		if (buf[3] != 0x05) {			err("boot bad boot size.");			return -EIO;		}		if (buf[4] != 0x00) {			err("boot bad boot sequence.");			return -EIO;		}		if (buf[5] != 0x01) {			err("boot bad boot pattern 01.");			return -EIO;		}		if (buf[6] != 0x10) {			err("boot bad boot pattern 10.");			return -EIO;		}		for (i = 4; i <= 6; i++)			checksum += buf[i];		if (buf[7] * 256 + buf[8] != checksum) {			err("boot bad boot checksum.");			return -EIO;		}		break;	}	return 0;}int af9005_download_firmware(struct usb_device *udev, const struct firmware *fw){	int i, packets, ret, act_len;	u8 buf[FW_BULKOUT_SIZE + 2];	u8 reply;	ret = af9005_boot_packet(udev, FW_CONFIG, &reply);	if (ret)		return ret;	if (reply != 0x01) {		err("before downloading firmware, FW_CONFIG expected 0x01, received 0x%x", reply);		return -EIO;	}	packets = fw->size / FW_BULKOUT_SIZE;	buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff);	buf[1] = (u8) ((FW_BULKOUT_SIZE >> 8) & 0xff);	for (i = 0; i < packets; i++) {		memcpy(&buf[2], fw->data + i * FW_BULKOUT_SIZE,		       FW_BULKOUT_SIZE);		deb_fw(">>> ");		debug_dump(buf, FW_BULKOUT_SIZE + 2, deb_fw);		ret = usb_bulk_msg(udev,				   usb_sndbulkpipe(udev, 0x02),				   buf, FW_BULKOUT_SIZE + 2, &act_len, 1000);		if (ret) {			err("firmware download failed at packet %d with code %d", i, ret);			return ret;		}	}	ret = af9005_boot_packet(udev, FW_CONFIRM, &reply);	if (ret)		return ret;	if (reply != (u8) (packets & 0xff)) {		err("after downloading firmware, FW_CONFIRM expected 0x%x, received 0x%x", packets & 0xff, reply);		return -EIO;	}	ret = af9005_boot_packet(udev, FW_BOOT, &reply);	if (ret)		return ret;	ret = af9005_boot_packet(udev, FW_CONFIG, &reply);	if (ret)		return ret;	if (reply != 0x02) {		err("after downloading firmware, FW_CONFIG expected 0x02, received 0x%x", reply);		return -EIO;	}	return 0;}int af9005_led_control(struct dvb_usb_device *d, int onoff){	struct af9005_device_state *st = d->priv;	int temp, ret;	if (onoff && dvb_usb_af9005_led)		temp = 1;	else		temp = 0;	if (st->led_state != temp) {		ret =		    af9005_write_register_bits(d, xd_p_reg_top_locken1,					       reg_top_locken1_pos,					       reg_top_locken1_len, temp);		if (ret)			return ret;		ret =		    af9005_write_register_bits(d, xd_p_reg_top_lock1,					       reg_top_lock1_pos,					       reg_top_lock1_len, temp);		if (ret)			return ret;		st->led_state = temp;	}	return 0;}static int af9005_frontend_attach(struct dvb_usb_adapter *adap){	u8 buf[8];	int i;	/* without these calls the first commands after downloading	   the firmware fail. I put these calls here to simulate	   what it is done in dvb-usb-init.c.	 */	struct usb_device *udev = adap->dev->udev;	usb_clear_halt(udev, usb_sndbulkpipe(udev, 2));	usb_clear_halt(udev, usb_rcvbulkpipe(udev, 1));	if (dvb_usb_af9005_dump_eeprom) {		printk("EEPROM DUMP\n");		for (i = 0; i < 255; i += 8) {			af9005_read_eeprom(adap->dev, i, buf, 8);			printk("ADDR %x ", i);			debug_dump(buf, 8, printk);		}	}	adap->fe = af9005_fe_attach(adap->dev);	return 0;}static int af9005_rc_query(struct dvb_usb_device *d, u32 * event, int *state){	struct af9005_device_state *st = d->priv;	int ret, len;	u8 obuf[5];	u8 ibuf[256];	*state = REMOTE_NO_KEY_PRESSED;	if (rc_decode == NULL) {		/* it shouldn't never come here */		return 0;	}	/* deb_info("rc_query\n"); */	obuf[0] = 3;		/* rest of packet length low */	obuf[1] = 0;		/* rest of packet lentgh high */	obuf[2] = 0x40;		/* read remote */	obuf[3] = 1;		/* rest of packet length */	obuf[4] = st->sequence++;	/* sequence number */	ret = af9005_usb_generic_rw(d, obuf, 5, ibuf, 256, 0);	if (ret) {		err("rc query failed");		return ret;	}	if (ibuf[2] != 0x41) {		err("rc query bad header.");		return -EIO;	}	if (ibuf[4] != obuf[4]) {		err("rc query bad sequence.");		return -EIO;	}	len = ibuf[5];	if (len > 246) {		err("rc query invalid length");		return -EIO;	}	if (len > 0) {		deb_rc("rc data (%d) ", len);		debug_dump((ibuf + 6), len, deb_rc);		ret = rc_decode(d, &ibuf[6], len, event, state);		if (ret) {			err("rc_decode failed");			return ret;		} else {			deb_rc("rc_decode state %x event %x\n", *state, *event);			if (*state == REMOTE_KEY_REPEAT)				*event = d->last_event;		}	}	return 0;}static int af9005_power_ctrl(struct dvb_usb_device *d, int onoff){	return 0;}static int af9005_pid_filter_control(struct dvb_usb_adapter *adap, int onoff){	int ret;	deb_info("pid filter control  onoff %d\n", onoff);	if (onoff) {		ret =		    af9005_write_ofdm_register(adap->dev, XD_MP2IF_DMX_CTRL, 1);		if (ret)			return ret;		ret =		    af9005_write_register_bits(adap->dev,					       XD_MP2IF_DMX_CTRL, 1, 1, 1);		if (ret)			return ret;		ret =		    af9005_write_ofdm_register(adap->dev, XD_MP2IF_DMX_CTRL, 1);	} else		ret =		    af9005_write_ofdm_register(adap->dev, XD_MP2IF_DMX_CTRL, 0);	if (ret)		return ret;	deb_info("pid filter control ok\n");	return 0;}static int af9005_pid_filter(struct dvb_usb_adapter *adap, int index,			     u16 pid, int onoff){	u8 cmd = index & 0x1f;	int ret;	deb_info("set pid filter, index %d, pid %x, onoff %d\n", index,		 pid, onoff);	if (onoff) {		/* cannot use it as pid_filter_ctrl since it has to be done		   before setting the first pid */		if (adap->feedcount == 1) {			deb_info("first pid set, enable pid table\n");			ret = af9005_pid_filter_control(adap, onoff);			if (ret)				return ret;		}		ret =		    af9005_write_ofdm_register(adap->dev,					       XD_MP2IF_PID_DATA_L,					       (u8) (pid & 0xff));		if (ret)			return ret;		ret =		    af9005_write_ofdm_register(adap->dev,					       XD_MP2IF_PID_DATA_H,					       (u8) (pid >> 8));		if (ret)			return ret;		cmd |= 0x20 | 0x40;	} else {		if (adap->feedcount == 0) {			deb_info("last pid unset, disable pid table\n");			ret = af9005_pid_filter_control(adap, onoff);			if (ret)				return ret;		}	}	ret = af9005_write_ofdm_register(adap->dev, XD_MP2IF_PID_IDX, cmd);	if (ret)		return ret;	deb_info("set pid ok\n");	return 0;}static int af9005_identify_state(struct usb_device *udev,				 struct dvb_usb_device_properties *props,				 struct dvb_usb_device_description **desc,				 int *cold){	int ret;	u8 reply;	ret = af9005_boot_packet(udev, FW_CONFIG, &reply);	if (ret)		return ret;	deb_info("result of FW_CONFIG in identify state %d\n", reply);	if (reply == 0x01)		*cold = 1;	else if (reply == 0x02)		*cold = 0;	else		return -EIO;	deb_info("Identify state cold = %d\n", *cold);	return 0;}static struct dvb_usb_device_properties af9005_properties;static int af9005_usb_probe(struct usb_interface *intf,			    const struct usb_device_id *id){	return dvb_usb_device_init(intf, &af9005_properties, THIS_MODULE, NULL);}static struct usb_device_id af9005_usb_table[] = {	{USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9005)},	{USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_USB_XE)},	{0},};MODULE_DEVICE_TABLE(usb, af9005_usb_table);static struct dvb_usb_device_properties af9005_properties = {	.caps = DVB_USB_IS_AN_I2C_ADAPTER,	.usb_ctrl = DEVICE_SPECIFIC,	.firmware = "af9005.fw",	.download_firmware = af9005_download_firmware,	.no_reconnect = 1,	.size_of_priv = sizeof(struct af9005_device_state),	.num_adapters = 1,	.adapter = {		    {		     .caps =		     DVB_USB_ADAP_HAS_PID_FILTER |		     DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,		     .pid_filter_count = 32,		     .pid_filter = af9005_pid_filter,		     /* .pid_filter_ctrl = af9005_pid_filter_control, */		     .frontend_attach = af9005_frontend_attach,		     /* .tuner_attach     = af9005_tuner_attach, */		     /* parameter for the MPEG2-data transfer */		     .stream = {				.type = USB_BULK,				.count = 10,				.endpoint = 0x04,				.u = {				      .bulk = {					       .buffersize = 4096,	/* actual size seen is 3948 */					       }				      }				},		     }		    },	.power_ctrl = af9005_power_ctrl,	.identify_state = af9005_identify_state,	.i2c_algo = &af9005_i2c_algo,	.rc_interval = 200,	.rc_key_map = NULL,	.rc_key_map_size = 0,	.rc_query = af9005_rc_query,	.num_device_descs = 2,	.devices = {		    {.name = "Afatech DVB-T USB1.1 stick",		     .cold_ids = {&af9005_usb_table[0], NULL},		     .warm_ids = {NULL},		     },		    {.name = "TerraTec Cinergy T USB XE",		     .cold_ids = {&af9005_usb_table[1], NULL},		     .warm_ids = {NULL},		     },		    {NULL},		    }};/* usb specific object needed to register this driver with the usb subsystem */static struct usb_driver af9005_usb_driver = {	.name = "dvb_usb_af9005",	.probe = af9005_usb_probe,	.disconnect = dvb_usb_device_exit,	.id_table = af9005_usb_table,};/* module stuff */static int __init af9005_usb_module_init(void){	int result;	if ((result = usb_register(&af9005_usb_driver))) {		err("usb_register failed. (%d)", result);		return result;	}	rc_decode = symbol_request(af9005_rc_decode);	rc_keys = symbol_request(af9005_rc_keys);	rc_keys_size = symbol_request(af9005_rc_keys_size);	if (rc_decode == NULL || rc_keys == NULL || rc_keys_size == NULL) {		err("af9005_rc_decode function not found, disabling remote");		af9005_properties.rc_query = NULL;	} else {		af9005_properties.rc_key_map = rc_keys;		af9005_properties.rc_key_map_size = *rc_keys_size;	}	return 0;}static void __exit af9005_usb_module_exit(void){	/* release rc decode symbols */	if (rc_decode != NULL)		symbol_put(af9005_rc_decode);	if (rc_keys != NULL)		symbol_put(af9005_rc_keys);	if (rc_keys_size != NULL)		symbol_put(af9005_rc_keys_size);	/* deregister this driver from the USB subsystem */	usb_deregister(&af9005_usb_driver);}module_init(af9005_usb_module_init);module_exit(af9005_usb_module_exit);MODULE_AUTHOR("Luca Olivetti <luca@ventoso.org>");MODULE_DESCRIPTION("Driver for Afatech 9005 DVB-T USB1.1 stick");MODULE_VERSION("1.0");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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