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

📄 usb.c

📁 改文件可以安装无线网卡在linux下的驱动,大家可以在网站上查找一下用法
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  Copyright (C) 2004 Jan Kiszka * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *  GNU General Public License for more details. * */#include "ndis.h"#include "usb.h"#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)#define WRAP_ALLOC_URB(a, b)  usb_alloc_urb(a)#define WRAP_SUBMIT_URB(a, b) usb_submit_urb(a)#else#define WRAP_ALLOC_URB(a, b)  usb_alloc_urb(a, b)#define WRAP_SUBMIT_URB(a, b) usb_submit_urb(a, b)#endif#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,5)#define CUR_ALT_SETTING(intf) (intf)->cur_altsetting#else#define CUR_ALT_SETTING(intf) (intf)->altsetting[(intf)->act_altsetting]#endifstatic struct list_head completed_irps;static KIRQL completed_irps_lock;void usb_transfer_complete_tasklet(unsigned long dummy);DECLARE_TASKLET(completed_irps_tasklet, usb_transfer_complete_tasklet, 0);static struct list_head canceled_irps;void usb_cancel_worker(void *dummy);static struct work_struct cancel_usb_irp_work;extern KSPIN_LOCK irp_cancel_lock;#ifdef DUMPURBS#define DUMP_URB(urb) do {						\		int i;							\		char dbg[40], *t;					\		if ((urb)->pipe & USB_DIR_IN)				\			USBTRACE("URB coming back");			\		else							\			USBTRACE("URB going down");			\		printk(KERN_DEBUG "length: %x",				\		       urb->transfer_buffer_length);			\		t = dbg;						\		for (i = 0; i < urb->transfer_buffer_length &&		\			     t < &dbg[sizeof(dbg) - 2]; i++)		\			t += sprintf(t, "%02X ",			\				     *(((UCHAR *)urb->transfer_buffer)+i)); \		dbg[sizeof(dbg)-1] = 0;					\		printk(KERN_DEBUG "%s\n", dbg);				\	} while (0)#else#define DUMP_URB(urb)#endif /* DUMPURBS */static inline int wrap_submit_urb(struct urb *urb, int flags){	int ret;	struct irp *irp = urb->context;	ret = WRAP_SUBMIT_URB(urb, flags);	if (ret) {		ERROR("usb_submit_urb() = %d", ret);		usb_free_urb(urb);		if (IRP_DRIVER_CONTEXT(irp)[2])			kfree(IRP_DRIVER_CONTEXT(irp)[2]);	}	return ret;}int usb_init(void){	kspin_lock_init(&completed_irps_lock);	INIT_LIST_HEAD(&canceled_irps);	INIT_LIST_HEAD(&completed_irps);	INIT_WORK(&cancel_usb_irp_work, usb_cancel_worker, NULL);	return 0;}void usb_exit(void){	return;}#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)void usb_transfer_complete(struct urb *urb, struct pt_regs *regs)#elsevoid usb_transfer_complete(struct urb *urb)#endif{	struct irp *irp = urb->context;	int cancel;	USBTRACEENTER("urb = %p", urb);	/* canceled via usb_unlink_urb? */	if ((urb->status == -ENOENT) || (urb->status == -ECONNRESET))		USBTRACEEXIT(return);	/* canceled but not yet unlinked? */	kspin_lock(&irp_cancel_lock);	irp->cancel_routine = NULL;	cancel = irp->cancel;	kspin_unlock(&irp_cancel_lock);	if (cancel)		USBTRACEEXIT(return);	kspin_lock(&completed_irps_lock);	list_add_tail(&irp->completed_list, &completed_irps);	kspin_unlock(&completed_irps_lock);	tasklet_schedule(&completed_irps_tasklet);	USBTRACEEXIT(return);}void usb_transfer_complete_tasklet(unsigned long dummy){	struct irp *irp;	struct urb *urb;	struct io_stack_location *stack;	union nt_urb *nt_urb;	unsigned long flags;	while (1) {		kspin_lock_irqsave(&completed_irps_lock, flags);		if (list_empty(&completed_irps)) {			kspin_unlock_irqrestore(&completed_irps_lock, flags);			USBTRACEEXIT(return);		}		irp = list_entry(completed_irps.next, struct irp,				 completed_list);		list_del(&irp->completed_list);		kspin_unlock_irqrestore(&completed_irps_lock, flags);		urb = IRP_DRIVER_CONTEXT(irp)[3];		stack = IRP_CUR_STACK_LOC(irp) - 1;		nt_urb = stack->params.generic.arg1;		USBTRACE("irp = %p, urb = %p, status = %d", irp, urb,			  urb->status);		if (urb->setup_packet)			kfree(urb->setup_packet);		irp->pending_returned = 1;		if (urb->status)			irp->io_status.status = STATUS_FAILURE;		else			irp->io_status.status = STATUS_SUCCESS;		irp->io_status.status_info = urb->actual_length;		/* also applies to ctrlDescReq or venClsReq */		nt_urb->bulkIntrTrans.transferBufLen = urb->actual_length;		DUMP_URB(urb);		if (IRP_DRIVER_CONTEXT(irp)[2]) {			if (urb->pipe & USB_DIR_IN) {				/* also applies to ctrlDescReq or venClsReq */				memcpy(nt_urb->bulkIntrTrans.transferBuf,				       IRP_DRIVER_CONTEXT(irp)[2],				       nt_urb->bulkIntrTrans.transferBufLen);			}			kfree(IRP_DRIVER_CONTEXT(irp)[2]);		}		IofCompleteRequest(FASTCALL_ARGS_2(irp, 0));		USBTRACE("freeing urb %p", urb);		usb_free_urb(urb);	}}/* this is called holding irp_cancel_lock */STDCALL void usb_cancel_transfer(struct device_object *dev_obj,				 struct irp *irp){	struct urb *urb;	USBTRACEENTER("irp = %p", irp);	urb = IRP_DRIVER_CONTEXT(irp)[3];	USBTRACE("adding urb %p to cancel", urb);	/* while this function can run at DISPATCH_LEVEL,	 * usb_unlink/kill_urb will only work successfully in	 * schedulable context */	list_add_tail(&irp->cancel_list, &canceled_irps);	schedule_work(&cancel_usb_irp_work);}void usb_cancel_worker(void *dummy){	struct irp *irp;	struct urb *urb;	USBTRACEENTER("%s", "");	while (1) {		kspin_lock(&irp_cancel_lock);		if (list_empty(&canceled_irps)) {			kspin_unlock(&irp_cancel_lock);			USBTRACEEXIT(return);		}		irp = list_entry(canceled_irps.next, struct irp, cancel_list);		list_del(&irp->cancel_list);		kspin_unlock(&irp_cancel_lock);		urb = IRP_DRIVER_CONTEXT(irp)[3];		USBTRACE("freeing urb = %p", urb);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,8)		usb_kill_urb(urb);#else		if (usb_unlink_urb(urb) < 0)			USBTRACEEXIT(return);#endif		if (urb->setup_packet)			kfree(urb->setup_packet);		usb_free_urb(urb);		if (IRP_DRIVER_CONTEXT(irp)[2])			kfree(IRP_DRIVER_CONTEXT(irp)[2]);		irp->io_status.status = STATUS_CANCELLED;		irp->io_status.status_info = 0;		IofCompleteRequest(FASTCALL_ARGS_2(irp, 0));	}}unsigned long usb_bulk_or_intr_trans(struct usb_device *dev,				     union nt_urb *nt_urb, struct irp *irp){	union pipe_handle pipe_handle;	struct urb *urb;	unsigned int pipe;	int ret;	UCHAR endpoint;	ASSERT(!nt_urb->bulkIntrTrans.transferBufMdl);	ASSERT(!nt_urb->bulkIntrTrans.urbLink);	USBTRACE("flags = %lX, length = %lu, buffer = %p",		  nt_urb->bulkIntrTrans.transferFlags,		  nt_urb->bulkIntrTrans.transferBufLen,		  nt_urb->bulkIntrTrans.transferBuf);	/* FIXME: we should better check what GFP_ is required */	urb = WRAP_ALLOC_URB(0, GFP_ATOMIC);	if (!urb)		return -ENOMEM;	/* store the linux-urb in the nt-irp and set the cancel routine */	IRP_DRIVER_CONTEXT(irp)[3] = urb;	irp->cancel_routine = usb_cancel_transfer;	pipe_handle = nt_urb->bulkIntrTrans.pipeHandle;	endpoint = pipe_handle.encoded.endpointAddr;	switch(pipe_handle.encoded.pipeType) {	case USB_ENDPOINT_XFER_CONTROL:		if (nt_urb->bulkIntrTrans.transferFlags &		    USBD_TRANSFER_DIRECTION_IN)			pipe = usb_rcvctrlpipe(dev, endpoint);		else			pipe = usb_sndctrlpipe(dev, endpoint);		usb_fill_control_urb(urb, dev, pipe, urb->setup_packet,				     nt_urb->bulkIntrTrans.transferBuf,				     nt_urb->bulkIntrTrans.transferBufLen,				     usb_transfer_complete, irp);		break;	case USB_ENDPOINT_XFER_ISOC:		if (nt_urb->bulkIntrTrans.transferFlags &		    USBD_TRANSFER_DIRECTION_IN)			pipe = usb_rcvisocpipe(dev, endpoint);		else			pipe = usb_sndisocpipe(dev, endpoint);		break;	case USB_ENDPOINT_XFER_BULK:		if (nt_urb->bulkIntrTrans.transferFlags &		    USBD_TRANSFER_DIRECTION_IN)			pipe = usb_rcvbulkpipe(dev, endpoint);		else			pipe = usb_sndbulkpipe(dev, endpoint);		usb_fill_bulk_urb(urb, dev, pipe,				  nt_urb->bulkIntrTrans.transferBuf,				  nt_urb->bulkIntrTrans.transferBufLen,				  usb_transfer_complete, irp);		break;	case USB_ENDPOINT_XFER_INT:		if (nt_urb->bulkIntrTrans.transferFlags &		    USBD_TRANSFER_DIRECTION_IN)			pipe = usb_rcvintpipe(dev, endpoint);		else			pipe = usb_sndintpipe(dev, endpoint);		usb_fill_int_urb(urb, dev, pipe,				 nt_urb->bulkIntrTrans.transferBuf,				 nt_urb->bulkIntrTrans.transferBufLen,				 usb_transfer_complete, irp,				 pipe_handle.encoded.interval);		break;	default:		ERROR("unknown pipe type: %d", pipe_handle.encoded.pipeType);		return -EINVAL;	}	if ((nt_urb->venClsReq.transferFlags &	     (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK)) ==	    USBD_TRANSFER_DIRECTION_IN)		urb->transfer_flags |= URB_SHORT_NOT_OK;	DUMP_URB(urb);	/* non-DMA-capable buffers have to be mirrored */	IRP_DRIVER_CONTEXT(irp)[2] = NULL;	if (!virt_addr_valid(nt_urb->bulkIntrTrans.transferBuf)) {		IRP_DRIVER_CONTEXT(irp)[2] =			kmalloc(nt_urb->bulkIntrTrans.transferBufLen,				GFP_ATOMIC);		if (!IRP_DRIVER_CONTEXT(irp)[2]) {			ERROR("%s", "kmalloc failed!");			usb_free_urb(urb);			return -ENOMEM;		}		if (!(pipe & USB_DIR_IN))			memcpy(IRP_DRIVER_CONTEXT(irp)[2],			       nt_urb->bulkIntrTrans.transferBuf,			       nt_urb->bulkIntrTrans.transferBufLen);		urb->transfer_buffer = IRP_DRIVER_CONTEXT(irp)[2];		USBTRACE("mirroring non-DMA buffer");	}	/* mark setup_packet as unused for cleanup procedure */	urb->setup_packet = NULL;	USBTRACE("submitting urb %p on pipe %p", urb, pipe_handle.handle);	/* FIXME: we should better check what GFP_ is required */	ret = wrap_submit_urb(urb, GFP_ATOMIC);	return ret;}unsigned long usb_vendor_or_class_intf(struct usb_device *dev,				       union nt_urb *nt_urb, struct irp *irp){	struct urb *urb;	struct usb_ctrlrequest *dr;	char req_type;	unsigned int pipe;	int ret;	ASSERT(!nt_urb->venClsReq.transferBufMdl);	ASSERT(!nt_urb->venClsReq.urbLink);	USBTRACE("reservedBits = %x, request = %x, "		  "value = %d, index = %d, transferFlags = %lx, "		  "transferBuf = %p, transferBufLen = %ld",		  nt_urb->venClsReq.reservedBits,		  nt_urb->venClsReq.request, nt_urb->venClsReq.value,		  nt_urb->venClsReq.index, nt_urb->venClsReq.transferFlags,		  nt_urb->venClsReq.transferBuf,		  nt_urb->venClsReq.transferBufLen);	/* FIXME: we should better check what GFP_ is required */	urb = WRAP_ALLOC_URB(0, GFP_ATOMIC);	if (!urb) {		ERROR("%s", "usb_alloc_urb failed!");		return -ENOMEM;	}	req_type = USB_TYPE_VENDOR | USB_RECIP_DEVICE |		nt_urb->venClsReq.reservedBits;	if (nt_urb->venClsReq.transferFlags & USBD_TRANSFER_DIRECTION_IN) {		pipe = usb_rcvctrlpipe(dev, 0);		req_type |= USB_DIR_IN;	} else {		pipe = usb_sndctrlpipe(dev, 0);		req_type |= USB_DIR_OUT;	}

⌨️ 快捷键说明

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