/**
* This file contains functions used in USB interface module.
*/
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/netdevice.h>
#include <linux/usb.h>
#include "host.h"
#include "sbi.h"
#include "decl.h"
#include "defs.h"
#include "dev.h"
#include "if_usb.h"
#define MESSAGE_HEADER_LEN 4
static const char usbdriver_name[] = "usb8xxx";
static struct usb_device_id if_usb_table[] = {
/* Enter the device signature inside */
{
USB_DEVICE(USB8388_VID_1, USB8388_PID_1),
},
{
USB_DEVICE(USB8388_VID_2, USB8388_PID_2),
},
{} /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, if_usb_table);
static void if_usb_receive(struct urb *urb);
static void if_usb_receive_fwload(struct urb *urb);
/**
* @brief call back function to handle the status of the URB
* @param urb pointer to urb structure
* @return N/A
*/
static void if_usb_write_bulk_callback(struct urb *urb)
{
wlan_private *priv = (wlan_private *) (urb->context);
wlan_adapter *adapter = priv->adapter;
struct net_device *dev = priv->wlan_dev.netdev;
/* handle the transmission complete validations */
if (urb->status != 0) {
/* print the failure status number for debug */
lbs_pr_info("URB in failure status\n");
} else {
lbs_dev_dbg(2, &urb->dev->dev, "URB status is successfull\n");
lbs_dev_dbg(2, &urb->dev->dev, "Actual length transmitted %d\n",
urb->actual_length);
priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED;
/* Wake main thread if commands are pending */
if (!adapter->cur_cmd)
wake_up_interruptible(&priv->mainthread.waitq);
if ((adapter->connect_status == libertas_connected))
netif_wake_queue(dev);
}
return;
}
/**
* @brief free tx/rx urb, skb and rx buffer
* @param cardp pointer usb_card_rec
* @return N/A
*/
void if_usb_free(struct usb_card_rec *cardp)
{
ENTER();
/* Unlink tx & rx urb */
usb_kill_urb(cardp->tx_urb);
usb_kill_urb(cardp->rx_urb);
usb_free_urb(cardp->tx_urb);
cardp->tx_urb = NULL;
usb_free_urb(cardp->rx_urb);
cardp->rx_urb = NULL;
kfree(cardp->bulk_out_buffer);
cardp->bulk_out_buffer = NULL;
LEAVE();
return;
}
/**
* @brief sets the configuration values
* @param ifnum interface number
* @param id pointer to usb_device_id
* @return 0 on success, error code on failure
*/
static int if_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;
wlan_private *pwlanpriv;
struct usb_card_rec *usb_cardp;
int i;
udev = interface_to_usbdev(intf);
usb_cardp = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL);
if (!usb_cardp) {
lbs_pr_err("Out of memory allocating private data.\n");
goto error;
}
usb_cardp->udev = udev;
iface_desc = intf->cur_altsetting;
lbs_dev_dbg(1, &udev->dev, "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->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_BULK)) {
/* we found a bulk in endpoint */
lbs_dev_dbg(1, &udev->dev, "Bulk in size is %d\n",
endpoint->wMaxPacketSize);
if (!
(usb_cardp->rx_urb =
usb_alloc_urb(0, GFP_KERNEL))) {
lbs_dev_dbg(1, &udev->dev,
"Rx URB allocation failed\n");
goto dealloc;
}
usb_cardp->rx_urb_recall = 0;
usb_cardp->bulk_in_size =
endpoint->wMaxPacketSize;
usb_cardp->bulk_in_endpointAddr =
(endpoint->
bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
lbs_dev_dbg(1, &udev->dev, "in_endpoint = %d\n",
endpoint->bEndpointAddress);
}
if (((endpoint->
bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
USB_DIR_OUT)
&& ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_BULK)) {
/* We found bulk out endpoint */
if (!
(usb_cardp->tx_urb =
usb_alloc_urb(0, GFP_KERNEL))) {
lbs_dev_dbg(