📄 irda-usb.c
字号:
kfree(self->speed_buff); self->speed_buff = NULL; kfree(self->tx_buff); self->tx_buff = NULL;}/********************** USB CONFIG SUBROUTINES **********************//* * Various subroutines dealing with USB stuff we use to configure and * initialise each irda-usb instance. * These functions are used below in the main calls of the driver... *//*------------------------------------------------------------------*//* * Function irda_usb_parse_endpoints(dev, ifnum) * * Parse the various endpoints and find the one we need. * * The endpoint are the pipes used to communicate with the USB device. * The spec defines 2 endpoints of type bulk transfer, one in, and one out. * These are used to pass frames back and forth with the dongle. * Most dongle have also an interrupt endpoint, that will be probably * documented in the next spec... */static inline int irda_usb_parse_endpoints(struct irda_usb_cb *self, struct usb_host_endpoint *endpoint, int ennum){ int i; /* Endpoint index in table */ /* Init : no endpoints */ self->bulk_in_ep = 0; self->bulk_out_ep = 0; self->bulk_int_ep = 0; /* Let's look at all those endpoints */ for(i = 0; i < ennum; i++) { /* All those variables will get optimised by the compiler, * so let's aim for clarity... - Jean II */ __u8 ep; /* Endpoint address */ __u8 dir; /* Endpoint direction */ __u8 attr; /* Endpoint attribute */ __u16 psize; /* Endpoint max packet size in bytes */ /* Get endpoint address, direction and attribute */ ep = endpoint[i].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; dir = endpoint[i].desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK; attr = endpoint[i].desc.bmAttributes; psize = le16_to_cpu(endpoint[i].desc.wMaxPacketSize); /* Is it a bulk endpoint ??? */ if(attr == USB_ENDPOINT_XFER_BULK) { /* We need to find an IN and an OUT */ if(dir == USB_DIR_IN) { /* This is our Rx endpoint */ self->bulk_in_ep = ep; } else { /* This is our Tx endpoint */ self->bulk_out_ep = ep; self->bulk_out_mtu = psize; } } else { if((attr == USB_ENDPOINT_XFER_INT) && (dir == USB_DIR_IN)) { /* This is our interrupt endpoint */ self->bulk_int_ep = ep; } else { IRDA_ERROR("%s(), Unrecognised endpoint %02X.\n", __FUNCTION__, ep); } } } IRDA_DEBUG(0, "%s(), And our endpoints are : in=%02X, out=%02X (%d), int=%02X\n", __FUNCTION__, self->bulk_in_ep, self->bulk_out_ep, self->bulk_out_mtu, self->bulk_int_ep); return((self->bulk_in_ep != 0) && (self->bulk_out_ep != 0));}#ifdef IU_DUMP_CLASS_DESC/*------------------------------------------------------------------*//* * Function usb_irda_dump_class_desc(desc) * * Prints out the contents of the IrDA class descriptor * */static inline void irda_usb_dump_class_desc(struct irda_class_desc *desc){ /* Values are little endian */ printk("bLength=%x\n", desc->bLength); printk("bDescriptorType=%x\n", desc->bDescriptorType); printk("bcdSpecRevision=%x\n", le16_to_cpu(desc->bcdSpecRevision)); printk("bmDataSize=%x\n", desc->bmDataSize); printk("bmWindowSize=%x\n", desc->bmWindowSize); printk("bmMinTurnaroundTime=%d\n", desc->bmMinTurnaroundTime); printk("wBaudRate=%x\n", le16_to_cpu(desc->wBaudRate)); printk("bmAdditionalBOFs=%x\n", desc->bmAdditionalBOFs); printk("bIrdaRateSniff=%x\n", desc->bIrdaRateSniff); printk("bMaxUnicastList=%x\n", desc->bMaxUnicastList);}#endif /* IU_DUMP_CLASS_DESC *//*------------------------------------------------------------------*//* * Function irda_usb_find_class_desc(intf) * * Returns instance of IrDA class descriptor, or NULL if not found * * The class descriptor is some extra info that IrDA USB devices will * offer to us, describing their IrDA characteristics. We will use that in * irda_usb_init_qos() */static inline struct irda_class_desc *irda_usb_find_class_desc(struct usb_interface *intf){ struct usb_device *dev = interface_to_usbdev (intf); struct irda_class_desc *desc; int ret; desc = kmalloc(sizeof (*desc), GFP_KERNEL); if (desc == NULL) return NULL; memset(desc, 0, sizeof(*desc)); /* USB-IrDA class spec 1.0: * 6.1.3: Standard "Get Descriptor" Device Request is not * appropriate to retrieve class-specific descriptor * 6.2.5: Class Specific "Get Class Descriptor" Interface Request * is mandatory and returns the USB-IrDA class descriptor */ ret = usb_control_msg(dev, usb_rcvctrlpipe(dev,0), IU_REQ_GET_CLASS_DESC, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, intf->altsetting->desc.bInterfaceNumber, desc, sizeof(*desc), 500); IRDA_DEBUG(1, "%s(), ret=%d\n", __FUNCTION__, ret); if (ret < sizeof(*desc)) { IRDA_WARNING("usb-irda: class_descriptor read %s (%d)\n", (ret<0) ? "failed" : "too short", ret); } else if (desc->bDescriptorType != USB_DT_IRDA) { IRDA_WARNING("usb-irda: bad class_descriptor type\n"); } else {#ifdef IU_DUMP_CLASS_DESC irda_usb_dump_class_desc(desc);#endif /* IU_DUMP_CLASS_DESC */ return desc; } kfree(desc); return NULL;}/*********************** USB DEVICE CALLBACKS ***********************//* * Main calls from the USB subsystem. * Mostly registering a new irda-usb device and removing it.... *//*------------------------------------------------------------------*//* * This routine is called by the USB subsystem for each new device * in the system. We need to check if the device is ours, and in * this case start handling it. * The USB layer protect us from reentrancy (via BKL), so we don't need * to spinlock in there... Jean II */static int irda_usb_probe(struct usb_interface *intf, const struct usb_device_id *id){ struct net_device *net; struct usb_device *dev = interface_to_usbdev(intf); struct irda_usb_cb *self = NULL; struct usb_host_interface *interface; struct irda_class_desc *irda_desc; int ret = -ENOMEM; int i; /* Driver instance index / Rx URB index */ /* Note : the probe make sure to call us only for devices that * matches the list of dongle (top of the file). So, we * don't need to check if the dongle is really ours. * Jean II */ IRDA_MESSAGE("IRDA-USB found at address %d, Vendor: %x, Product: %x\n", dev->devnum, le16_to_cpu(dev->descriptor.idVendor), le16_to_cpu(dev->descriptor.idProduct)); net = alloc_irdadev(sizeof(*self)); if (!net) goto err_out; SET_MODULE_OWNER(net); SET_NETDEV_DEV(net, &intf->dev); self = net->priv; self->netdev = net; spin_lock_init(&self->lock); init_timer(&self->rx_defer_timer); self->capability = id->driver_info; self->needspatch = ((self->capability & IUC_STIR421X) != 0); /* Create all of the needed urbs */ if (self->capability & IUC_STIR421X) { self->max_rx_urb = IU_SIGMATEL_MAX_RX_URBS; self->header_length = USB_IRDA_STIR421X_HEADER; } else { self->max_rx_urb = IU_MAX_RX_URBS; self->header_length = USB_IRDA_HEADER; } self->rx_urb = kzalloc(self->max_rx_urb * sizeof(struct urb *), GFP_KERNEL); for (i = 0; i < self->max_rx_urb; i++) { self->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL); if (!self->rx_urb[i]) { goto err_out_1; } } self->tx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!self->tx_urb) { goto err_out_1; } self->speed_urb = usb_alloc_urb(0, GFP_KERNEL); if (!self->speed_urb) { goto err_out_2; } /* Is this really necessary? (no, except maybe for broken devices) */ if (usb_reset_configuration (dev) < 0) { err("reset_configuration failed"); ret = -EIO; goto err_out_3; } /* Is this really necessary? */ /* Note : some driver do hardcode the interface number, some others * specify an alternate, but very few driver do like this. * Jean II */ ret = usb_set_interface(dev, intf->altsetting->desc.bInterfaceNumber, 0); IRDA_DEBUG(1, "usb-irda: set interface %d result %d\n", intf->altsetting->desc.bInterfaceNumber, ret); switch (ret) { case 0: break; case -EPIPE: /* -EPIPE = -32 */ /* Martin Diehl says if we get a -EPIPE we should * be fine and we don't need to do a usb_clear_halt(). * - Jean II */ IRDA_DEBUG(0, "%s(), Received -EPIPE, ignoring...\n", __FUNCTION__); break; default: IRDA_DEBUG(0, "%s(), Unknown error %d\n", __FUNCTION__, ret); ret = -EIO; goto err_out_3; } /* Find our endpoints */ interface = intf->cur_altsetting; if(!irda_usb_parse_endpoints(self, interface->endpoint, interface->desc.bNumEndpoints)) { IRDA_ERROR("%s(), Bogus endpoints...\n", __FUNCTION__); ret = -EIO; goto err_out_3; } self->usbdev = dev; /* Find IrDA class descriptor */ irda_desc = irda_usb_find_class_desc(intf); ret = -ENODEV; if (irda_desc == NULL) goto err_out_3; if (self->needspatch) { ret = usb_control_msg (self->usbdev, usb_sndctrlpipe (self->usbdev, 0), 0x02, 0x40, 0, 0, NULL, 0, 500); if (ret < 0) { IRDA_DEBUG (0, "usb_control_msg failed %d\n", ret); goto err_out_3; } else { mdelay(10); } } self->irda_desc = irda_desc; self->present = 1; self->netopen = 0; self->usbintf = intf; /* Allocate the buffer for speed changes */ /* Don't change this buffer size and allocation without doing * some heavy and complete testing. Don't ask why :-( * Jean II */ self->speed_buff = kmalloc(IRDA_USB_SPEED_MTU, GFP_KERNEL); if (self->speed_buff == NULL) goto err_out_3; memset(self->speed_buff, 0, IRDA_USB_SPEED_MTU); self->tx_buff = kzalloc(IRDA_SKB_MAX_MTU + self->header_length, GFP_KERNEL); if (self->tx_buff == NULL) goto err_out_4; ret = irda_usb_open(self); if (ret) goto err_out_5; IRDA_MESSAGE("IrDA: Registered device %s\n", net->name); usb_set_intfdata(intf, self); if (self->needspatch) { /* Now we fetch and upload the firmware patch */ ret = stir421x_patch_device(self); self->needspatch = (ret < 0); if (self->needspatch) { IRDA_ERROR("STIR421X: Couldn't upload patch\n"); goto err_out_6; } /* replace IrDA class descriptor with what patched device is now reporting */ irda_desc = irda_usb_find_class_desc (self->usbintf); if (irda_desc == NULL) { ret = -ENODEV; goto err_out_6; } if (self->irda_desc) kfree (self->irda_desc); self->irda_desc = irda_desc; irda_usb_init_qos(self); } return 0;err_out_6: unregister_netdev(self->netdev);err_out_5: kfree(self->tx_buff);err_out_4: kfree(self->speed_buff);err_out_3: /* Free all urbs that we may have created */ usb_free_urb(self->speed_urb);err_out_2: usb_free_urb(self->tx_urb);err_out_1: for (i = 0; i < self->max_rx_urb; i++) usb_free_urb(self->rx_urb[i]); free_netdev(net);err_out: return ret;}/*------------------------------------------------------------------*//* * The current irda-usb device is removed, the USB layer tell us * to shut it down... * One of the constraints is that when we exit this function, * we cannot use the usb_device no more. Gone. Destroyed. kfree(). * Most other subsystem allow you to destroy the instance at a time * when it's convenient to you, to postpone it to a later date, but * not the USB subsystem. * So, we must make bloody sure that everything gets deactivated. * Jean II */static void irda_usb_disconnect(struct usb_interface *intf){ unsigned long flags; struct irda_usb_cb *self = usb_get_intfdata(intf); int i; IRDA_DEBUG(1, "%s()\n", __FUNCTION__); usb_set_intfdata(intf, NULL); if (!self) return; /* Make sure that the Tx path is not executing. - Jean II */ spin_lock_irqsave(&self->lock, flags); /* Oups ! We are not there any more. * This will stop/desactivate the Tx path. - Jean II */ self->present = 0; /* Kill defered Rx URB */ del_timer(&self->rx_defer_timer); /* We need to have irq enabled to unlink the URBs. That's OK, * at this point the Tx path is gone - Jean II */ spin_unlock_irqrestore(&self->lock, flags); /* Hum... Check if networking is still active (avoid races) */ if((self->netopen) || (self->irlap)) { /* Accept no more transmissions */ /*netif_device_detach(self->netdev);*/ netif_stop_queue(self->netdev); /* Stop all the receive URBs. Must be synchronous. */ for (i = 0; i < self->max_rx_urb; i++) usb_kill_urb(self->rx_urb[i]); /* Cancel Tx and speed URB. * Make sure it's synchronous to avoid races. */ usb_kill_urb(self->tx_urb); usb_kill_urb(self->speed_urb); } /* Cleanup the device stuff */ irda_usb_close(self); /* No longer attached to USB bus */ self->usbdev = NULL; self->usbintf = NULL; /* Clean up our urbs */ for (i = 0; i < self->max_rx_urb; i++) usb_free_urb(self->rx_urb[i]); kfree(self->rx_urb); /* Clean up Tx and speed URB */ usb_free_urb(self->tx_urb); usb_free_urb(self->speed_urb); /* Free self and network device */ free_netdev(self->netdev); IRDA_DEBUG(0, "%s(), USB IrDA Disconnected\n", __FUNCTION__);}/*------------------------------------------------------------------*//* * USB device callbacks */static struct usb_driver irda_driver = { .name = "irda-usb", .probe = irda_usb_probe, .disconnect = irda_usb_disconnect, .id_table = dongles,};/************************* MODULE CALLBACKS *************************//* * Deal with module insertion/removal * Mostly tell USB about our existence *//*------------------------------------------------------------------*//* * Module insertion */static int __init usb_irda_init(void){ int ret; ret = usb_register(&irda_driver); if (ret < 0) return ret; IRDA_MESSAGE("USB IrDA support registered\n"); return 0;}module_init(usb_irda_init);/*------------------------------------------------------------------*//* * Module removal */static void __exit usb_irda_cleanup(void){ /* Deregister the driver and remove all pending instances */ usb_deregister(&irda_driver);}module_exit(usb_irda_cleanup);/*------------------------------------------------------------------*//* * Module parameters */module_param(qos_mtt_bits, int, 0);MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time");MODULE_AUTHOR("Roman Weissgaerber <weissg@vienna.at>, Dag Brattli <dag@brattli.net>, Jean Tourrilhes <jt@hpl.hp.com> and Nick Fedchik <nick@fedchik.org.ua>");MODULE_DESCRIPTION("IrDA-USB Dongle Driver");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -