/**
* This file contains functions used in USB interface module.
*/
#include <linux/delay.h>
#include <linux/moduleparam.h>
#include <linux/firmware.h>
#include <linux/netdevice.h>
#include <linux/usb.h>
#define DRV_NAME "usb8xxx"
#include "host.h"
#include "decl.h"
#include "defs.h"
#include "dev.h"
#include "cmd.h"
#include "if_usb.h"
#define MESSAGE_HEADER_LEN 4
static char *lbs_fw_name = "usb8388.bin";
module_param_named(fw_name, lbs_fw_name, charp, 0644);
static struct usb_device_id if_usb_table[] = {
/* Enter the device signature inside */
{ USB_DEVICE(0x1286, 0x2001) },
{ USB_DEVICE(0x05a3, 0x8388) },
{} /* 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);
static int if_usb_prog_firmware(struct usb_card_rec *cardp);
static int if_usb_host_to_card(struct lbs_private *priv,
u8 type,
u8 *payload,
u16 nb);
static int if_usb_get_int_status(struct lbs_private *priv, u8 *);
static int if_usb_read_event_cause(struct lbs_private *);
static int usb_tx_block(struct usb_card_rec *cardp, u8 *payload, u16 nb);
static void if_usb_free(struct usb_card_rec *cardp);
static int if_usb_submit_rx_urb(struct usb_card_rec *cardp);
static int if_usb_reset_device(struct usb_card_rec *cardp);
/**
* @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)
{
struct usb_card_rec *cardp = (struct usb_card_rec *) urb->context;
/* handle the transmission complete validations */
if (urb->status == 0) {
struct lbs_private *priv = cardp->priv;
/*
lbs_deb_usbd(&urb->dev->dev, "URB status is successfull\n");
lbs_deb_usbd(&urb->dev->dev, "Actual length transmitted %d\n",
urb->actual_length);
*/
/* Used for both firmware TX and regular TX. priv isn't
* valid at firmware load time.
*/
if (priv)
lbs_host_to_card_done(priv);
} else {
/* print the failure status number for debug */
lbs_pr_info("URB in failure status: %d\n", urb->status);
}
return;
}
/**
* @brief free tx/rx urb, skb and rx buffer
* @param cardp pointer usb_card_rec
* @return N/A
*/
static void if_usb_free(struct usb_card_rec *cardp)
{
lbs_deb_enter(LBS_DEB_USB);
/* 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;
lbs_deb_leave(LBS_DEB_USB);
}
static void if_usb_set_boot2_ver(struct lbs_private *priv)
{
struct cmd_ds_set_boot2_ver b2_cmd;
b2_cmd.action = 0;
b2_cmd.version = priv->boot2_version;
if (lbs_cmd(priv, CMD_SET_BOOT2_VER, b2_cmd, NULL, 0))
lbs_deb_usb("Setting boot2 version failed\n");
}
static void if_usb_fw_timeo(unsigned long priv)
{
struct usb_card_rec *cardp = (void *)priv;
if (cardp->fwdnldover) {
lbs_deb_usb("Download complete, no event. Assuming success\n");
} else {
lbs_pr_err("Download timed out\n");
cardp->surprise_removed = 1;
}
wake_up(&cardp->fw_wq);
}
/**
* @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;
struct lbs_private *priv;
struct usb_card_rec *cardp;
int i;
udev = interface_to_usbdev(intf);
cardp = kzalloc(sizeof(struct usb_card_rec<