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

📄 zd_usb.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	cmd[3] = 0x43;	/* bulk command signature */	cmd[14] = 6;	/* command length */	cmd[15] = 0x1b;	/* SCSI command: START STOP UNIT */	cmd[19] = 0x2;	/* eject disc */	dev_info(&udev->dev, "Ejecting virtual installer media...\n");	r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, bulk_out_ep),		cmd, 31, NULL, 2000);	kfree(cmd);	if (r)		return r;	/* At this point, the device disconnects and reconnects with the real	 * ID numbers. */	usb_set_intfdata(intf, NULL);	return 0;}int zd_usb_init_hw(struct zd_usb *usb){	int r;	struct zd_mac *mac = zd_usb_to_mac(usb);	dev_dbg_f(zd_usb_dev(usb), "\n");	r = upload_firmware(usb);	if (r) {		dev_err(zd_usb_dev(usb),		       "couldn't load firmware. Error number %d\n", r);		return r;	}	r = usb_reset_configuration(zd_usb_to_usbdev(usb));	if (r) {		dev_dbg_f(zd_usb_dev(usb),			"couldn't reset configuration. Error number %d\n", r);		return r;	}	r = zd_mac_init_hw(mac);	if (r) {		dev_dbg_f(zd_usb_dev(usb),		         "couldn't initialize mac. Error number %d\n", r);		return r;	}	usb->initialized = 1;	return 0;}static int probe(struct usb_interface *intf, const struct usb_device_id *id){	int r;	struct zd_usb *usb;	struct usb_device *udev = interface_to_usbdev(intf);	struct net_device *netdev = NULL;	print_id(udev);	if (id->driver_info & DEVICE_INSTALLER)		return eject_installer(intf);	switch (udev->speed) {	case USB_SPEED_LOW:	case USB_SPEED_FULL:	case USB_SPEED_HIGH:		break;	default:		dev_dbg_f(&intf->dev, "Unknown USB speed\n");		r = -ENODEV;		goto error;	}	usb_reset_device(interface_to_usbdev(intf));	netdev = zd_netdev_alloc(intf);	if (netdev == NULL) {		r = -ENOMEM;		goto error;	}	usb = &zd_netdev_mac(netdev)->chip.usb;	usb->is_zd1211b = (id->driver_info == DEVICE_ZD1211B) != 0;	r = zd_mac_preinit_hw(zd_netdev_mac(netdev));	if (r) {		dev_dbg_f(&intf->dev,		         "couldn't initialize mac. Error number %d\n", r);		goto error;	}	r = register_netdev(netdev);	if (r) {		dev_dbg_f(&intf->dev,			 "couldn't register netdev. Error number %d\n", r);		goto error;	}	dev_dbg_f(&intf->dev, "successful\n");	dev_info(&intf->dev,"%s\n", netdev->name);	return 0;error:	usb_reset_device(interface_to_usbdev(intf));	zd_netdev_free(netdev);	return r;}static void disconnect(struct usb_interface *intf){	struct net_device *netdev = zd_intf_to_netdev(intf);	struct zd_mac *mac;	struct zd_usb *usb;	/* Either something really bad happened, or we're just dealing with	 * a DEVICE_INSTALLER. */	if (netdev == NULL)		return;	mac = zd_netdev_mac(netdev);	usb = &mac->chip.usb;	dev_dbg_f(zd_usb_dev(usb), "\n");	zd_netdev_disconnect(netdev);	/* Just in case something has gone wrong! */	zd_usb_disable_rx(usb);	zd_usb_disable_int(usb);	/* If the disconnect has been caused by a removal of the	 * driver module, the reset allows reloading of the driver. If the	 * reset will not be executed here, the upload of the firmware in the	 * probe function caused by the reloading of the driver will fail.	 */	usb_reset_device(interface_to_usbdev(intf));	zd_netdev_free(netdev);	dev_dbg(&intf->dev, "disconnected\n");}static struct usb_driver driver = {	.name		= "zd1211rw",	.id_table	= usb_ids,	.probe		= probe,	.disconnect	= disconnect,};struct workqueue_struct *zd_workqueue;static int __init usb_init(void){	int r;	pr_debug("%s usb_init()\n", driver.name);	zd_workqueue = create_singlethread_workqueue(driver.name);	if (zd_workqueue == NULL) {		printk(KERN_ERR "%s couldn't create workqueue\n", driver.name);		return -ENOMEM;	}	r = usb_register(&driver);	if (r) {		destroy_workqueue(zd_workqueue);		printk(KERN_ERR "%s usb_register() failed. Error number %d\n",		       driver.name, r);		return r;	}	pr_debug("%s initialized\n", driver.name);	return 0;}static void __exit usb_exit(void){	pr_debug("%s usb_exit()\n", driver.name);	usb_deregister(&driver);	destroy_workqueue(zd_workqueue);}module_init(usb_init);module_exit(usb_exit);static int usb_int_regs_length(unsigned int count){	return sizeof(struct usb_int_regs) + count * sizeof(struct reg_data);}static void prepare_read_regs_int(struct zd_usb *usb){	struct zd_usb_interrupt *intr = &usb->intr;	spin_lock_irq(&intr->lock);	intr->read_regs_enabled = 1;	INIT_COMPLETION(intr->read_regs.completion);	spin_unlock_irq(&intr->lock);}static void disable_read_regs_int(struct zd_usb *usb){	struct zd_usb_interrupt *intr = &usb->intr;	spin_lock_irq(&intr->lock);	intr->read_regs_enabled = 0;	spin_unlock_irq(&intr->lock);}static int get_results(struct zd_usb *usb, u16 *values,	               struct usb_req_read_regs *req, unsigned int count){	int r;	int i;	struct zd_usb_interrupt *intr = &usb->intr;	struct read_regs_int *rr = &intr->read_regs;	struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer;	spin_lock_irq(&intr->lock);	r = -EIO;	/* The created block size seems to be larger than expected.	 * However results appear to be correct.	 */	if (rr->length < usb_int_regs_length(count)) {		dev_dbg_f(zd_usb_dev(usb),			 "error: actual length %d less than expected %d\n",			 rr->length, usb_int_regs_length(count));		goto error_unlock;	}	if (rr->length > sizeof(rr->buffer)) {		dev_dbg_f(zd_usb_dev(usb),			 "error: actual length %d exceeds buffer size %zu\n",			 rr->length, sizeof(rr->buffer));		goto error_unlock;	}	for (i = 0; i < count; i++) {		struct reg_data *rd = &regs->regs[i];		if (rd->addr != req->addr[i]) {			dev_dbg_f(zd_usb_dev(usb),				 "rd[%d] addr %#06hx expected %#06hx\n", i,				 le16_to_cpu(rd->addr),				 le16_to_cpu(req->addr[i]));			goto error_unlock;		}		values[i] = le16_to_cpu(rd->value);	}	r = 0;error_unlock:	spin_unlock_irq(&intr->lock);	return r;}int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,	             const zd_addr_t *addresses, unsigned int count){	int r;	int i, req_len, actual_req_len;	struct usb_device *udev;	struct usb_req_read_regs *req = NULL;	unsigned long timeout;	if (count < 1) {		dev_dbg_f(zd_usb_dev(usb), "error: count is zero\n");		return -EINVAL;	}	if (count > USB_MAX_IOREAD16_COUNT) {		dev_dbg_f(zd_usb_dev(usb),			 "error: count %u exceeds possible max %u\n",			 count, USB_MAX_IOREAD16_COUNT);		return -EINVAL;	}	if (in_atomic()) {		dev_dbg_f(zd_usb_dev(usb),			 "error: io in atomic context not supported\n");		return -EWOULDBLOCK;	}	if (!usb_int_enabled(usb)) {		 dev_dbg_f(zd_usb_dev(usb),			  "error: usb interrupt not enabled\n");		return -EWOULDBLOCK;	}	req_len = sizeof(struct usb_req_read_regs) + count * sizeof(__le16);	req = kmalloc(req_len, GFP_KERNEL);	if (!req)		return -ENOMEM;	req->id = cpu_to_le16(USB_REQ_READ_REGS);	for (i = 0; i < count; i++)		req->addr[i] = cpu_to_le16((u16)addresses[i]);	udev = zd_usb_to_usbdev(usb);	prepare_read_regs_int(usb);	r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT),		         req, req_len, &actual_req_len, 1000 /* ms */);	if (r) {		dev_dbg_f(zd_usb_dev(usb),			"error in usb_bulk_msg(). Error number %d\n", r);		goto error;	}	if (req_len != actual_req_len) {		dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg()\n"			" req_len %d != actual_req_len %d\n",			req_len, actual_req_len);		r = -EIO;		goto error;	}	timeout = wait_for_completion_timeout(&usb->intr.read_regs.completion,	                                      msecs_to_jiffies(1000));	if (!timeout) {		disable_read_regs_int(usb);		dev_dbg_f(zd_usb_dev(usb), "read timed out\n");		r = -ETIMEDOUT;		goto error;	}	r = get_results(usb, values, req, count);error:	kfree(req);	return r;}int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,	              unsigned int count){	int r;	struct usb_device *udev;	struct usb_req_write_regs *req = NULL;	int i, req_len, actual_req_len;	if (count == 0)		return 0;	if (count > USB_MAX_IOWRITE16_COUNT) {		dev_dbg_f(zd_usb_dev(usb),			"error: count %u exceeds possible max %u\n",			count, USB_MAX_IOWRITE16_COUNT);		return -EINVAL;	}	if (in_atomic()) {		dev_dbg_f(zd_usb_dev(usb),			"error: io in atomic context not supported\n");		return -EWOULDBLOCK;	}	req_len = sizeof(struct usb_req_write_regs) +		  count * sizeof(struct reg_data);	req = kmalloc(req_len, GFP_KERNEL);	if (!req)		return -ENOMEM;	req->id = cpu_to_le16(USB_REQ_WRITE_REGS);	for (i = 0; i < count; i++) {		struct reg_data *rw  = &req->reg_writes[i];		rw->addr = cpu_to_le16((u16)ioreqs[i].addr);		rw->value = cpu_to_le16(ioreqs[i].value);	}	udev = zd_usb_to_usbdev(usb);	r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT),		         req, req_len, &actual_req_len, 1000 /* ms */);	if (r) {		dev_dbg_f(zd_usb_dev(usb),			"error in usb_bulk_msg(). Error number %d\n", r);		goto error;	}	if (req_len != actual_req_len) {		dev_dbg_f(zd_usb_dev(usb),			"error in usb_bulk_msg()"			" req_len %d != actual_req_len %d\n",			req_len, actual_req_len);		r = -EIO;		goto error;	}	/* FALL-THROUGH with r == 0 */error:	kfree(req);	return r;}int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits){	int r;	struct usb_device *udev;	struct usb_req_rfwrite *req = NULL;	int i, req_len, actual_req_len;	u16 bit_value_template;	if (in_atomic()) {		dev_dbg_f(zd_usb_dev(usb),			"error: io in atomic context not supported\n");		return -EWOULDBLOCK;	}	if (bits < USB_MIN_RFWRITE_BIT_COUNT) {		dev_dbg_f(zd_usb_dev(usb),			"error: bits %d are smaller than"			" USB_MIN_RFWRITE_BIT_COUNT %d\n",			bits, USB_MIN_RFWRITE_BIT_COUNT);		return -EINVAL;	}	if (bits > USB_MAX_RFWRITE_BIT_COUNT) {		dev_dbg_f(zd_usb_dev(usb),			"error: bits %d exceed USB_MAX_RFWRITE_BIT_COUNT %d\n",			bits, USB_MAX_RFWRITE_BIT_COUNT);		return -EINVAL;	}#ifdef DEBUG	if (value & (~0UL << bits)) {		dev_dbg_f(zd_usb_dev(usb),			"error: value %#09x has bits >= %d set\n",			value, bits);		return -EINVAL;	}#endif /* DEBUG */	dev_dbg_f(zd_usb_dev(usb), "value %#09x bits %d\n", value, bits);	r = zd_usb_ioread16(usb, &bit_value_template, CR203);	if (r) {		dev_dbg_f(zd_usb_dev(usb),			"error %d: Couldn't read CR203\n", r);		goto out;	}	bit_value_template &= ~(RF_IF_LE|RF_CLK|RF_DATA);	req_len = sizeof(struct usb_req_rfwrite) + bits * sizeof(__le16);	req = kmalloc(req_len, GFP_KERNEL);	if (!req)		return -ENOMEM;	req->id = cpu_to_le16(USB_REQ_WRITE_RF);	/* 1: 3683a, but not used in ZYDAS driver */	req->value = cpu_to_le16(2);	req->bits = cpu_to_le16(bits);	for (i = 0; i < bits; i++) {		u16 bv = bit_value_template;		if (value & (1 << (bits-1-i)))			bv |= RF_DATA;		req->bit_values[i] = cpu_to_le16(bv);	}	udev = zd_usb_to_usbdev(usb);	r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT),		         req, req_len, &actual_req_len, 1000 /* ms */);	if (r) {		dev_dbg_f(zd_usb_dev(usb),			"error in usb_bulk_msg(). Error number %d\n", r);		goto out;	}	if (req_len != actual_req_len) {		dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg()"			" req_len %d != actual_req_len %d\n",			req_len, actual_req_len);		r = -EIO;		goto out;	}	/* FALL-THROUGH with r == 0 */out:	kfree(req);	return r;}

⌨️ 快捷键说明

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