/** @brief This function handles client driver probe. * * @param func A pointer to sdio_func structure. * @param id A pointer to sdio_device_id structure. * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE/error code */ int woal_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) { int ret = MLAN_STATUS_SUCCESS; struct sdio_mmc_card *card = NULL; ENTER(); PRINTM(MMSG, "vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n", func->vendor, func->device, func->class, func->num); card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL); if (!card) { PRINTM(MFATAL, "Failed to allocate memory in probe function!\n"); LEAVE(); return -ENOMEM; } card->func = func; #ifdef MMC_QUIRK_BLKSZ_FOR_BYTE_MODE /* The byte mode patch is available in kernel MMC driver which fixes one issue in MP-A transfer. bit1: use func->cur_blksize for byte mode */ func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) func->card->quirks |= MMC_QUIRK_LENIENT_FN0; #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) /* wait for chip fully wake up */ if (!func->enable_timeout) func->enable_timeout = 200; #endif sdio_claim_host(func); ret = sdio_enable_func(func); if (ret) { sdio_disable_func(func); sdio_release_host(func); kfree(card); PRINTM(MFATAL, "sdio_enable_func() failed: ret=%d\n", ret); LEAVE(); return -EIO; } sdio_release_host(func); if (NULL == woal_add_card(card)) { PRINTM(MERROR, "woal_add_card failed\n"); kfree(card); sdio_claim_host(func); sdio_disable_func(func); sdio_release_host(func); ret = MLAN_STATUS_FAILURE; } LEAVE(); return ret; }
/** * @brief Sets the configuration values * * @param intf Pointer to usb_interface * @param id Pointer to usb_device_id * * @return Address of variable usb_cardp, error code otherwise */ 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 = kmalloc(sizeof(struct usb_card_rec), GFP_KERNEL); memset((t_u8 *) usb_cardp, 0, sizeof(struct usb_card_rec)); 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(MMSG, "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; usb_cardp->intf = intf; PRINTM(MINFO, "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(MINFO, "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(MINFO, "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); } 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(MINFO, "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(MINFO, "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); } } usb_set_intfdata(intf, usb_cardp); /* At this point wlan_add_card() will be called */ if (!(woal_add_card(usb_cardp))) { PRINTM(MERROR, "%s: woal_add_callback failed\n", __FUNCTION__); goto error; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) /* Note: From 2.6.34.2 onwards, remote wakeup is NOT enabled by default. So drivers wanting remote wakeup will have to enable this using - device_set_wakeup_enable(&udev->dev, 1); It has been observed that some cards having device attr = 0xa0 do not support remote wakeup. These cards come immediately out of the suspend when power/wakeup file is set to 'enabled'. To support all types of cards i.e. with/without remote wakeup, we are NOT setting the 'power/wakeup' file from here. Also in principle, we are not supposed to change the wakeup policy, which is purely a userspace decision. */ // if (udev->actconfig->desc.bmAttributes & USB_CONFIG_ATT_WAKEUP) // intf->needs_remote_wakeup = 1; #endif usb_get_dev(udev); LEAVE(); return 0; } else { PRINTM(MINFO, "Discard the Probe request\n"); PRINTM(MINFO, "VID = 0x%X PID = 0x%X\n", udev->descriptor.idVendor, udev->descriptor.idProduct); } error: usb_reset_device(udev); kfree(usb_cardp); usb_cardp = NULL; LEAVE(); return (-ENOMEM); }
/** * @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); }