/** * @brief Free resource and cleanup * * @param intf Pointer to usb_interface * * @return N/A */ static void woal_usb_disconnect(struct usb_interface *intf) { struct usb_card_rec *cardp = usb_get_intfdata(intf); moal_handle *phandle = NULL; ENTER(); if (!cardp || !cardp->phandle) { PRINTM(MERROR, "Card or phandle is not valid\n"); LEAVE(); return; } phandle = (moal_handle *) cardp->phandle; /* * Update Surprise removed to TRUE * Free all the URB's allocated */ phandle->surprise_removed = MTRUE; /* Unlink and free urb */ woal_usb_free(cardp); /* Card is removed and we can call wlan_remove_card */ PRINTM(MINFO, "Call remove card\n"); woal_remove_card(cardp); /* Reset device */ usb_reset_device(cardp->udev); usb_set_intfdata(intf, NULL); usb_put_dev(interface_to_usbdev(intf)); kfree(cardp); LEAVE(); return; }
/** * @brief Sets the configuration values * * @param intf Pointer to usb_interface * @param id Pointer to usb_device_id * * @return Address of variable usb_cardp */ static int woal_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *udev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; int i; struct usb_card_rec *usb_cardp = NULL; ENTER(); udev = interface_to_usbdev(intf); usb_cardp = kzalloc(sizeof(struct usb_card_rec), GFP_ATOMIC); if (!usb_cardp) { LEAVE(); return (-ENOMEM); } udev->descriptor.idVendor = woal_cpu_to_le16(udev->descriptor.idVendor); udev->descriptor.idProduct = woal_cpu_to_le16(udev->descriptor.idProduct); udev->descriptor.bcdDevice = woal_cpu_to_le16(udev->descriptor.bcdDevice); udev->descriptor.bcdUSB = woal_cpu_to_le16(udev->descriptor.bcdUSB); /* Check probe is for our device */ for (i = 0; woal_usb_table[i].idVendor; i++) { if (udev->descriptor.idVendor == woal_usb_table[i].idVendor && udev->descriptor.idProduct == woal_usb_table[i].idProduct) { PRINTM(MSG, "VID/PID = %X/%X, Boot2 version = %X\n", udev->descriptor.idVendor, udev->descriptor.idProduct, udev->descriptor.bcdDevice); break; } } if (woal_usb_table[i].idVendor) { usb_cardp->udev = udev; iface_desc = intf->cur_altsetting; PRINTM(INFO, "bcdUSB = 0x%X bDeviceClass = 0x%X" " bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n", udev->descriptor.bcdUSB, udev->descriptor.bDeviceClass, udev->descriptor.bDeviceSubClass, udev->descriptor.bDeviceProtocol); for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) && ((endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) == MLAN_USB_EP_CMD_EVENT) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) { /* We found a bulk in command/event endpoint */ PRINTM(INFO, "Bulk IN: max packet size = %d, address = %d\n", woal_le16_to_cpu(endpoint->wMaxPacketSize), endpoint->bEndpointAddress); usb_cardp->rx_cmd_ep = (endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); atomic_set(&usb_cardp->rx_cmd_urb_pending, 0); } if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) && ((endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) == MLAN_USB_EP_DATA) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) { /* We found a bulk in data endpoint */ PRINTM(INFO, "Bulk IN: max packet size = %d, address = %d\n", woal_le16_to_cpu(endpoint->wMaxPacketSize), endpoint->bEndpointAddress); usb_cardp->rx_data_ep = (endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); atomic_set(&usb_cardp->rx_data_urb_pending, 0); usb_cardp->rx_urb_recall = MFALSE; } if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) && ((endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) == MLAN_USB_EP_DATA) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) { /* We found a bulk out data endpoint */ PRINTM(INFO, "Bulk OUT: max packet size = %d, address = %d\n", woal_le16_to_cpu(endpoint->wMaxPacketSize), endpoint->bEndpointAddress); usb_cardp->tx_data_ep = endpoint->bEndpointAddress; atomic_set(&usb_cardp->tx_data_urb_pending, 0); } if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) && ((endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) == MLAN_USB_EP_CMD_EVENT) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) { /* We found a bulk out command/event endpoint */ PRINTM(INFO, "Bulk OUT: max packet size = %d, address = %d\n", woal_le16_to_cpu(endpoint->wMaxPacketSize), endpoint->bEndpointAddress); usb_cardp->tx_cmd_ep = endpoint->bEndpointAddress; atomic_set(&usb_cardp->tx_cmd_urb_pending, 0); usb_cardp->bulk_out_maxpktsize = woal_le16_to_cpu(endpoint->wMaxPacketSize); } } /* At this point wlan_add_card() will be called */ if (!(woal_add_card(usb_cardp))) { PRINTM(ERROR, "%s: woal_add_callback failed\n", __FUNCTION__); goto error; } usb_get_dev(udev); usb_set_intfdata(intf, usb_cardp); LEAVE(); return 0; } else { PRINTM(INFO, "Discard the Probe request\n"); PRINTM(INFO, "VID = 0x%X PID = 0x%X\n", udev->descriptor.idVendor, udev->descriptor.idProduct); } error: usb_reset_device(udev); woal_usb_free(usb_cardp); kfree(usb_cardp); usb_cardp = NULL; LEAVE(); return (-ENOMEM); }