⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_usb.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/**  * 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/list.h>#include <linux/usb.h>#define DRV_NAME "usb8xxx"#include "host.h"#include "decl.h"#include "defs.h"#include "dev.h"#include "if_usb.h"#define MESSAGE_HEADER_LEN	4static const char usbdriver_name[] = "usb8xxx";static u8 *default_fw_name = "usb8388.bin";static char *libertas_fw_name = NULL;module_param_named(fw_name, libertas_fw_name, charp, 0644);/* * We need to send a RESET command to all USB devices before * we tear down the USB connection. Otherwise we would not * be able to re-init device the device if the module gets * loaded again. This is a list of all initialized USB devices, * for the reset code see if_usb_reset_device()*/static LIST_HEAD(usb_devices);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(wlan_private * priv, u8 type, u8 * payload, u16 nb);static int if_usb_get_int_status(wlan_private * priv, u8 *);static int if_usb_read_event_cause(wlan_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) {		wlan_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) {			wlan_adapter *adapter = priv->adapter;			struct net_device *dev = priv->dev;			priv->dnld_sent = DNLD_RES_RECEIVED;			/* Wake main thread if commands are pending */			if (!adapter->cur_cmd)				wake_up_interruptible(&priv->waitq);			if ((adapter->connect_status == LIBERTAS_CONNECTED)) {				netif_wake_queue(dev);				netif_wake_queue(priv->mesh_dev);			}		}	} 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);}/** *  @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 *priv;	struct usb_card_rec *cardp;	int i;	udev = interface_to_usbdev(intf);	cardp = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL);	if (!cardp) {		lbs_pr_err("Out of memory allocating private data.\n");		goto error;	}	cardp->udev = udev;	iface_desc = intf->cur_altsetting;	lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X"	       " bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n",		     le16_to_cpu(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_deb_usbd(&udev->dev, "Bulk in size is %d\n",				     le16_to_cpu(endpoint->wMaxPacketSize));			if (!(cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL))) {				lbs_deb_usbd(&udev->dev,				       "Rx URB allocation failed\n");				goto dealloc;			}			cardp->rx_urb_recall = 0;			cardp->bulk_in_size =				le16_to_cpu(endpoint->wMaxPacketSize);			cardp->bulk_in_endpointAddr =			    (endpoint->			     bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);			lbs_deb_usbd(&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 (!(cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL))) {				lbs_deb_usbd(&udev->dev,				       "Tx URB allocation failed\n");				goto dealloc;			}			cardp->bulk_out_size =				le16_to_cpu(endpoint->wMaxPacketSize);			lbs_deb_usbd(&udev->dev,				     "Bulk out size is %d\n",				     le16_to_cpu(endpoint->wMaxPacketSize));			cardp->bulk_out_endpointAddr =			    endpoint->bEndpointAddress;			lbs_deb_usbd(&udev->dev, "out_endpoint = %d\n",				    endpoint->bEndpointAddress);			cardp->bulk_out_buffer =			    kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE,				    GFP_KERNEL);			if (!cardp->bulk_out_buffer) {				lbs_deb_usbd(&udev->dev,				       "Could not allocate buffer\n");				goto dealloc;			}		}	}	/* Upload firmware */	cardp->rinfo.cardp = cardp;	if (if_usb_prog_firmware(cardp)) {		lbs_deb_usbd(&udev->dev, "FW upload failed");		goto err_prog_firmware;	}	if (!(priv = libertas_add_card(cardp, &udev->dev)))		goto err_prog_firmware;	cardp->priv = priv;	if (libertas_add_mesh(priv, &udev->dev))		goto err_add_mesh;	cardp->eth_dev = priv->dev;	priv->hw_host_to_card = if_usb_host_to_card;	priv->hw_get_int_status = if_usb_get_int_status;	priv->hw_read_event_cause = if_usb_read_event_cause;	priv->boot2_version = udev->descriptor.bcdDevice;	/* Delay 200 ms to waiting for the FW ready */	if_usb_submit_rx_urb(cardp);	msleep_interruptible(200);	priv->adapter->fw_ready = 1;	if (libertas_start_card(priv))		goto err_start_card;	list_add_tail(&cardp->list, &usb_devices);	usb_get_dev(udev);	usb_set_intfdata(intf, cardp);	return 0;err_start_card:	libertas_remove_mesh(priv);err_add_mesh:	libertas_remove_card(priv);err_prog_firmware:	if_usb_reset_device(cardp);dealloc:	if_usb_free(cardp);error:	return -ENOMEM;}/** *  @brief free resource and cleanup *  @param intf		USB interface structure *  @return 	   	N/A */static void if_usb_disconnect(struct usb_interface *intf){	struct usb_card_rec *cardp = usb_get_intfdata(intf);	wlan_private *priv = (wlan_private *) cardp->priv;	lbs_deb_enter(LBS_DEB_MAIN);	/* Update Surprise removed to TRUE */	cardp->surprise_removed = 1;	list_del(&cardp->list);	if (priv) {		wlan_adapter *adapter = priv->adapter;		adapter->surpriseremoved = 1;		libertas_stop_card(priv);		libertas_remove_mesh(priv);		libertas_remove_card(priv);	}	/* Unlink and free urb */	if_usb_free(cardp);	usb_set_intfdata(intf, NULL);	usb_put_dev(interface_to_usbdev(intf));	lbs_deb_leave(LBS_DEB_MAIN);}/** *  @brief  This function download FW *  @param priv		pointer to wlan_private *  @return 	   	0 */static int if_prog_firmware(struct usb_card_rec *cardp){	struct FWData *fwdata;	struct fwheader *fwheader;	u8 *firmware = cardp->fw->data;	fwdata = kmalloc(sizeof(struct FWData), GFP_ATOMIC);	if (!fwdata)		return -1;	fwheader = &fwdata->fwheader;	if (!cardp->CRC_OK) {		cardp->totalbytes = cardp->fwlastblksent;		cardp->fwseqnum = cardp->lastseqnum - 1;	}	/*	lbs_deb_usbd(&cardp->udev->dev, "totalbytes = %d\n",		    cardp->totalbytes);	*/	memcpy(fwheader, &firmware[cardp->totalbytes],	       sizeof(struct fwheader));	cardp->fwlastblksent = cardp->totalbytes;	cardp->totalbytes += sizeof(struct fwheader);	/* lbs_deb_usbd(&cardp->udev->dev,"Copy Data\n"); */	memcpy(fwdata->data, &firmware[cardp->totalbytes],	       le32_to_cpu(fwdata->fwheader.datalength));	/*	lbs_deb_usbd(&cardp->udev->dev,		    "Data length = %d\n", le32_to_cpu(fwdata->fwheader.datalength));	*/	cardp->fwseqnum = cardp->fwseqnum + 1;	fwdata->seqnum = cpu_to_le32(cardp->fwseqnum);	cardp->lastseqnum = cardp->fwseqnum;	cardp->totalbytes += le32_to_cpu(fwdata->fwheader.datalength);	if (fwheader->dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) {		/*		lbs_deb_usbd(&cardp->udev->dev, "There are data to follow\n");		lbs_deb_usbd(&cardp->udev->dev,			    "seqnum = %d totalbytes = %d\n", cardp->fwseqnum,			    cardp->totalbytes);		*/		memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE);		usb_tx_block(cardp, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);	} else if (fwdata->fwheader.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) {		/*		lbs_deb_usbd(&cardp->udev->dev,			    "Host has finished FW downloading\n");		lbs_deb_usbd(&cardp->udev->dev,			    "Donwloading FW JUMP BLOCK\n");		*/		memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE);		usb_tx_block(cardp, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);		cardp->fwfinalblk = 1;	}	/*	lbs_deb_usbd(&cardp->udev->dev,		    "The firmware download is done size is %d\n",		    cardp->totalbytes);	*/	kfree(fwdata);	return 0;}static int if_usb_reset_device(struct usb_card_rec *cardp){	int ret;	wlan_private * priv = cardp->priv;	lbs_deb_enter(LBS_DEB_USB);	/* Try a USB port reset first, if that fails send the reset	 * command to the firmware.	 */	ret = usb_reset_device(cardp->udev);	if (!ret && priv) {		msleep(10);		ret = libertas_reset_device(priv);		msleep(10);	}	lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret);	return ret;}/** *  @brief This function transfer the data to the device. *  @param priv 	pointer to wlan_private *  @param payload	pointer to payload data *  @param nb		data length *  @return 	   	0 or -1 */static int usb_tx_block(struct usb_card_rec *cardp, u8 * payload, u16 nb){	int ret = -1;	/* check if device is removed */	if (cardp->surprise_removed) {		lbs_deb_usbd(&cardp->udev->dev, "Device removed\n");		goto tx_ret;	}	usb_fill_bulk_urb(cardp->tx_urb, cardp->udev,			  usb_sndbulkpipe(cardp->udev,					  cardp->bulk_out_endpointAddr),			  payload, nb, if_usb_write_bulk_callback, cardp);	cardp->tx_urb->transfer_flags |= URB_ZERO_PACKET;	if ((ret = usb_submit_urb(cardp->tx_urb, GFP_ATOMIC))) {		/*  transfer failed */		lbs_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed\n");		ret = -1;	} else {		/* lbs_deb_usbd(&cardp->udev->dev, "usb_submit_urb success\n"); */		ret = 0;	}tx_ret:	return ret;}static int __if_usb_submit_rx_urb(struct usb_card_rec *cardp,				  void (*callbackfn)(struct urb *urb)){	struct sk_buff *skb;	struct read_cb_info *rinfo = &cardp->rinfo;	int ret = -1;	if (!(skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE))) {		lbs_pr_err("No free skb\n");		goto rx_ret;	}	rinfo->skb = skb;	/* Fill the receive configuration URB and initialise the Rx call back */	usb_fill_bulk_urb(cardp->rx_urb, cardp->udev,			  usb_rcvbulkpipe(cardp->udev,					  cardp->bulk_in_endpointAddr),			  (void *) (skb->tail + (size_t) IPFIELD_ALIGN_OFFSET),			  MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn,			  rinfo);	cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;	/* lbs_deb_usbd(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb); */	if ((ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC))) {		/* handle failure conditions */		lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed\n");		ret = -1;	} else {		/* lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB success\n"); */		ret = 0;	}rx_ret:	return ret;}static int if_usb_submit_rx_urb_fwload(struct usb_card_rec *cardp){	return __if_usb_submit_rx_urb(cardp, &if_usb_receive_fwload);}static int if_usb_submit_rx_urb(struct usb_card_rec *cardp){	return __if_usb_submit_rx_urb(cardp, &if_usb_receive);}static void if_usb_receive_fwload(struct urb *urb){	struct read_cb_info *rinfo = (struct read_cb_info *)urb->context;	struct sk_buff *skb = rinfo->skb;	struct usb_card_rec *cardp = (struct usb_card_rec *)rinfo->cardp;	struct fwsyncheader *syncfwheader;	struct bootcmdrespStr bootcmdresp;	if (urb->status) {		lbs_deb_usbd(&cardp->udev->dev,			    "URB status is failed during fw load\n");		kfree_skb(skb);		return;	}	if (cardp->bootcmdresp == 0) {		memcpy (&bootcmdresp, skb->data + IPFIELD_ALIGN_OFFSET,			sizeof(bootcmdresp));		if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) {			kfree_skb(skb);			if_usb_submit_rx_urb_fwload(cardp);			cardp->bootcmdresp = 1;			lbs_deb_usbd(&cardp->udev->dev,				    "Received valid boot command response\n");			return;		}		if (bootcmdresp.u32magicnumber != cpu_to_le32(BOOT_CMD_MAGIC_NUMBER)) {			lbs_pr_info(				"boot cmd response wrong magic number (0x%x)\n",				le32_to_cpu(bootcmdresp.u32magicnumber));		} else if (bootcmdresp.u8cmd_tag != BOOT_CMD_FW_BY_USB) {			lbs_pr_info(				"boot cmd response cmd_tag error (%d)\n",				bootcmdresp.u8cmd_tag);		} else if (bootcmdresp.u8result != BOOT_CMD_RESP_OK) {			lbs_pr_info(				"boot cmd response result error (%d)\n",				bootcmdresp.u8result);		} else {			cardp->bootcmdresp = 1;			lbs_deb_usbd(&cardp->udev->dev,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -