예제 #1
0
/**  @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;
}
예제 #2
0
/**
 *  @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);
}
예제 #3
0
/**
 *  @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);
}