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

📄 usb.c

📁 ndis在linux下的无线网卡驱动源码
💻 C
📖 第 1 页 / 共 3 页
字号:
#elsestatic void wrap_urb_complete_worker(worker_param_t dummy)#endif{	struct irp *irp;	struct urb *urb;	struct usbd_bulk_or_intr_transfer *bulk_int_tx;	struct usbd_vendor_or_class_request *vc_req;	union nt_urb *nt_urb;	struct wrap_urb *wrap_urb;	struct nt_list *ent;	unsigned long flags;	USBENTER("");	while (1) {		nt_spin_lock_irqsave(&wrap_urb_complete_list_lock, flags);		ent = RemoveHeadList(&wrap_urb_complete_list);		nt_spin_unlock_irqrestore(&wrap_urb_complete_list_lock, flags);		if (!ent)			break;		wrap_urb = container_of(ent, struct wrap_urb, complete_list);		urb = wrap_urb->urb;#ifdef USB_DEBUG		if (wrap_urb->state != URB_COMPLETED &&		    wrap_urb->state != URB_INT_UNLINKED)			WARNING("urb %p in wrong state: %d",				urb, wrap_urb->state);#endif		irp = wrap_urb->irp;		DUMP_IRP(irp);		nt_urb = IRP_URB(irp);		USBTRACE("urb: %p, nt_urb: %p, status: %d",			 urb, nt_urb, urb->status);		switch (urb->status) {		case 0:			/* succesfully transferred */			irp->io_status.info = urb->actual_length;			if (nt_urb->header.function ==			    URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER) {				bulk_int_tx = &nt_urb->bulk_int_transfer;				bulk_int_tx->transfer_buffer_length =					urb->actual_length;				DUMP_URB_BUFFER(urb, USB_DIR_IN);				if ((wrap_urb->flags & WRAP_URB_COPY_BUFFER) &&				    usb_pipein(urb->pipe))					memcpy(bulk_int_tx->transfer_buffer,					       urb->transfer_buffer,					       urb->actual_length);			} else { // vendor or class request				vc_req = &nt_urb->vendor_class_request;				vc_req->transfer_buffer_length =					urb->actual_length;				DUMP_URB_BUFFER(urb, USB_DIR_IN);				if ((wrap_urb->flags & WRAP_URB_COPY_BUFFER) &&				    usb_pipein(urb->pipe))					memcpy(vc_req->transfer_buffer,					       urb->transfer_buffer,					       urb->actual_length);			}			NT_URB_STATUS(nt_urb) = USBD_STATUS_SUCCESS;			irp->io_status.status = STATUS_SUCCESS;			break;		case -ENOENT:		case -ECONNRESET:			/* urb canceled */			irp->io_status.info = 0;			TRACE1("urb %p canceled", urb);			NT_URB_STATUS(nt_urb) = USBD_STATUS_SUCCESS;			irp->io_status.status = STATUS_CANCELLED;			break;		default:			TRACE1("irp: %p, urb: %p, status: %d/%d",			       irp, urb, urb->status, wrap_urb->state);			irp->io_status.info = 0;			NT_URB_STATUS(nt_urb) = wrap_urb_status(urb->status);			irp->io_status.status =				nt_urb_irp_status(NT_URB_STATUS(nt_urb));			break;		}		wrap_free_urb(urb);		IoCompleteRequest(irp, IO_NO_INCREMENT);	}	USBEXIT(return);}static USBD_STATUS wrap_bulk_or_intr_trans(struct irp *irp){	usbd_pipe_handle pipe_handle;	struct urb *urb;	unsigned int pipe;	struct usbd_bulk_or_intr_transfer *bulk_int_tx;	USBD_STATUS status;	struct usb_device *udev;	union nt_urb *nt_urb;	nt_urb = IRP_URB(irp);	udev = IRP_WRAP_DEVICE(irp)->usb.udev;	bulk_int_tx = &nt_urb->bulk_int_transfer;	pipe_handle = bulk_int_tx->pipe_handle;	USBTRACE("flags: %X, length: %u, buffer: %p, handle: %p",		 bulk_int_tx->transfer_flags,		 bulk_int_tx->transfer_buffer_length,		 bulk_int_tx->transfer_buffer, pipe_handle);	if (USBD_IS_BULK_PIPE(pipe_handle)) {		if (bulk_int_tx->transfer_flags & USBD_TRANSFER_DIRECTION_IN)			pipe = usb_rcvbulkpipe(udev,					       pipe_handle->bEndpointAddress);		else			pipe = usb_sndbulkpipe(udev,					       pipe_handle->bEndpointAddress);	} else {		if (bulk_int_tx->transfer_flags & USBD_TRANSFER_DIRECTION_IN)			pipe = usb_rcvintpipe(udev,					      pipe_handle->bEndpointAddress);		else			pipe = usb_sndintpipe(udev,					      pipe_handle->bEndpointAddress);	}	DUMP_IRP(irp);	urb = wrap_alloc_urb(irp, pipe, bulk_int_tx->transfer_buffer,			     bulk_int_tx->transfer_buffer_length);	if (!urb) {		ERROR("couldn't allocate urb");		return USBD_STATUS_NO_MEMORY;	}	if (usb_pipein(pipe) &&	    (!(bulk_int_tx->transfer_flags & USBD_SHORT_TRANSFER_OK))) {		USBTRACE("short not ok");		urb->transfer_flags |= URB_SHORT_NOT_OK;	}	if (usb_pipebulk(pipe)) {		usb_fill_bulk_urb(urb, udev, pipe, urb->transfer_buffer,				  bulk_int_tx->transfer_buffer_length,				  wrap_urb_complete, urb->context);		USBTRACE("submitting bulk urb %p on pipe 0x%x (ep 0x%x)",			 urb, urb->pipe, pipe_handle->bEndpointAddress);	} else {		usb_fill_int_urb(urb, udev, pipe, urb->transfer_buffer,				 bulk_int_tx->transfer_buffer_length,				 wrap_urb_complete, urb->context,				 pipe_handle->bInterval);		USBTRACE("submitting interrupt urb %p on pipe 0x%x (ep 0x%x), "			 "intvl: %d", urb, urb->pipe,			 pipe_handle->bEndpointAddress, pipe_handle->bInterval);	}	status = wrap_submit_urb(irp);	USBTRACE("status: %08X", status);	USBEXIT(return status);}static USBD_STATUS wrap_vendor_or_class_req(struct irp *irp){	u8 req_type;	unsigned int pipe;	struct usbd_vendor_or_class_request *vc_req;	struct usb_device *udev;	union nt_urb *nt_urb;	USBD_STATUS status;	struct urb *urb;	struct usb_ctrlrequest *dr;	nt_urb = IRP_URB(irp);	udev = IRP_WRAP_DEVICE(irp)->usb.udev;	vc_req = &nt_urb->vendor_class_request;	USBTRACE("bits: %x, req: %x, val: %08x, index: %08x, flags: %x,"		 "buf: %p, len: %d", vc_req->reserved_bits, vc_req->request,		 vc_req->value, vc_req->index, vc_req->transfer_flags,		 vc_req->transfer_buffer, vc_req->transfer_buffer_length);	USBTRACE("%x", nt_urb->header.function);	switch (nt_urb->header.function) {	case URB_FUNCTION_VENDOR_DEVICE:		req_type = USB_TYPE_VENDOR | USB_RECIP_DEVICE;		break;	case URB_FUNCTION_VENDOR_INTERFACE:		req_type = USB_TYPE_VENDOR | USB_RECIP_INTERFACE;		break;	case URB_FUNCTION_VENDOR_ENDPOINT:		req_type = USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;		break;	case URB_FUNCTION_VENDOR_OTHER:		req_type = USB_TYPE_VENDOR | USB_RECIP_OTHER;		break;	case URB_FUNCTION_CLASS_DEVICE:		req_type = USB_TYPE_CLASS | USB_RECIP_DEVICE;		break;	case URB_FUNCTION_CLASS_INTERFACE:		req_type = USB_TYPE_CLASS | USB_RECIP_INTERFACE;		break;	case URB_FUNCTION_CLASS_ENDPOINT:		req_type = USB_TYPE_CLASS | USB_RECIP_ENDPOINT;		break;	case URB_FUNCTION_CLASS_OTHER:		req_type = USB_TYPE_CLASS | USB_RECIP_OTHER;		break;	default:		ERROR("unknown request type: %x", nt_urb->header.function);		req_type = 0;		break;	}	req_type |= vc_req->reserved_bits;	USBTRACE("req type: %08x", req_type);	if (vc_req->transfer_flags & USBD_TRANSFER_DIRECTION_IN) {		pipe = usb_rcvctrlpipe(udev, 0);		req_type |= USB_DIR_IN;		USBTRACE("pipe: %x, dir in", pipe);	} else {		pipe = usb_sndctrlpipe(udev, 0);		req_type |= USB_DIR_OUT;		USBTRACE("pipe: %x, dir out", pipe);	}	urb = wrap_alloc_urb(irp, pipe, vc_req->transfer_buffer,			     vc_req->transfer_buffer_length);	if (!urb) {		ERROR("couldn't allocate urb");		return USBD_STATUS_NO_MEMORY;	}	if (usb_pipein(pipe) &&	    (!(vc_req->transfer_flags & USBD_SHORT_TRANSFER_OK))) {		USBTRACE("short not ok");		urb->transfer_flags |= URB_SHORT_NOT_OK;	}	dr = kmalloc(sizeof(*dr), GFP_ATOMIC);	if (!dr) {		ERROR("couldn't allocate memory");		wrap_free_urb(urb);		return USBD_STATUS_NO_MEMORY;	}	memset(dr, 0, sizeof(*dr));	dr->bRequestType = req_type;	dr->bRequest = vc_req->request;	dr->wValue = cpu_to_le16(vc_req->value);	dr->wIndex = cpu_to_le16((u16)vc_req->index);	dr->wLength = cpu_to_le16((u16)urb->transfer_buffer_length);	usb_fill_control_urb(urb, udev, pipe, (unsigned char *)dr,			     urb->transfer_buffer, urb->transfer_buffer_length,			     wrap_urb_complete, urb->context);	status = wrap_submit_urb(irp);	USBTRACE("status: %08X", status);	USBEXIT(return status);}static USBD_STATUS wrap_reset_pipe(struct usb_device *udev, struct irp *irp){	int ret;	union nt_urb *nt_urb;	usbd_pipe_handle pipe_handle;	unsigned int pipe1, pipe2;	nt_urb = IRP_URB(irp);	pipe_handle = nt_urb->pipe_req.pipe_handle;	/* TODO: not clear if both directions should be cleared? */	if (USBD_IS_BULK_PIPE(pipe_handle)) {		pipe1 = usb_rcvbulkpipe(udev, pipe_handle->bEndpointAddress);		pipe2 = usb_sndbulkpipe(udev, pipe_handle->bEndpointAddress);	} else if (USBD_IS_INT_PIPE(pipe_handle)) {		pipe1 = usb_rcvintpipe(udev, pipe_handle->bEndpointAddress);		pipe2 = pipe1;	} else {		WARNING("invalid pipe %d", pipe_handle->bEndpointAddress);		return USBD_STATUS_INVALID_PIPE_HANDLE;	}	USBTRACE("ep: %d, pipe: 0x%x", pipe_handle->bEndpointAddress, pipe1);	ret = usb_clear_halt(udev, pipe1);	if (ret)		USBTRACE("resetting pipe %d failed: %d", pipe1, ret);	if (pipe2 != pipe1) {		ret = usb_clear_halt(udev, pipe2);		if (ret)			USBTRACE("resetting pipe %d failed: %d", pipe2, ret);	}//	return wrap_urb_status(ret);	return USBD_STATUS_SUCCESS;}static USBD_STATUS wrap_abort_pipe(struct usb_device *udev, struct irp *irp){	union nt_urb *nt_urb;	usbd_pipe_handle pipe_handle;	struct wrap_urb *wrap_urb;	struct wrap_device *wd;	KIRQL irql;	wd = IRP_WRAP_DEVICE(irp);	nt_urb = IRP_URB(irp);	pipe_handle = nt_urb->pipe_req.pipe_handle;	USBENTER("%p, %x", irp, pipe_handle->bEndpointAddress);	IoAcquireCancelSpinLock(&irql);	nt_list_for_each_entry(wrap_urb, &wd->usb.wrap_urb_list, list) {		USBTRACE("%p, %p, %d, %x, %x", wrap_urb, wrap_urb->urb,			 wrap_urb->state, wrap_urb->urb->pipe,			 usb_pipeendpoint(wrap_urb->urb->pipe));		/* for WG111T driver, urbs for endpoint 0 should also		 * be canceled */		if ((usb_pipeendpoint(wrap_urb->urb->pipe) ==		     pipe_handle->bEndpointAddress) ||		    (usb_pipeendpoint(wrap_urb->urb->pipe) == 0)) {			if (wrap_cancel_urb(wrap_urb) == 0)				USBTRACE("canceled wrap_urb: %p", wrap_urb);		}	}	IoReleaseCancelSpinLock(irql);	NT_URB_STATUS(nt_urb) = USBD_STATUS_CANCELED;	USBEXIT(return USBD_STATUS_SUCCESS);}static void set_intf_pipe_info(struct wrap_device *wd,			       struct usb_interface *usb_intf,			       struct usbd_interface_information *intf){	int i;	struct usb_endpoint_descriptor *ep;	struct usbd_pipe_information *pipe;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)	for (i = 0; i < CUR_ALT_SETTING(usb_intf)->desc.bNumEndpoints; i++) {		ep = &(CUR_ALT_SETTING(usb_intf)->endpoint[i]).desc;#else	for (i = 0; i < CUR_ALT_SETTING(usb_intf).bNumEndpoints; i++) {		ep = &((CUR_ALT_SETTING(usb_intf)).endpoint[i]);#endif		if (i >= intf->bNumEndpoints) {			ERROR("intf %p has only %d endpoints, "			      "ignoring endpoints above %d",			      intf, intf->bNumEndpoints, i);			break;		}		pipe = &intf->pipes[i];		if (pipe->flags & USBD_PF_CHANGE_MAX_PACKET)			USBTRACE("pkt_sz: %d: %d", pipe->wMaxPacketSize,				 pipe->max_tx_size);		USBTRACE("driver wants max_tx_size to %d",			 pipe->max_tx_size);		pipe->wMaxPacketSize = ep->wMaxPacketSize;		pipe->bEndpointAddress = ep->bEndpointAddress;		pipe->type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;		if (pipe->type == UsbdPipeTypeInterrupt) {			/* for low speed devices, Linux sets bInterval			 * as frames per second, whereas Windows			 * interprets it as milliseconds */			if (wd->usb.udev->speed == USB_SPEED_LOW)				pipe->bInterval = 1 << (ep->bInterval - 1);			else				pipe->bInterval = ep->bInterval;		}		pipe->handle = ep;		USBTRACE("%d: ep 0x%x, type %d, pkt_sz %d, intv %d (%d),"			 "type: %d, handle %p", i, ep->bEndpointAddress,			 ep->bmAttributes, ep->wMaxPacketSize, ep->bInterval,			 pipe->bInterval, pipe->type, pipe->handle);	}}static USBD_STATUS wrap_select_configuration(struct wrap_device *wd,					     union nt_urb *nt_urb,					     struct irp *irp){	int i, ret;	struct usbd_select_configuration *sel_conf;	struct usb_device *udev;	struct usbd_interface_information *intf;	struct usb_config_descriptor *config;	struct usb_interface *usb_intf;	udev = wd->usb.udev;	sel_conf = &nt_urb->select_conf;	config = sel_conf->config;	USBTRACE("%p", config);	if (config == NULL) {		kill_all_urbs(wd, 1);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)		ret = usb_reset_configuration(udev);#else		ret = 0;#endif		return wrap_urb_status(ret);	}	USBTRACE("conf: %d, type: %d, length: %d, numif: %d, attr: %08x",		 config->bConfigurationValue, config->bDescriptorType,		 config->wTotalLength, config->bNumInterfaces,		 config->bmAttributes);	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),			      USB_REQ_SET_CONFIGURATION, 0,			      config->bConfigurationValue, 0,			      NULL, 0, USB_CTRL_SET_TIMEOUT);	if (ret < 0) {		ERROR("ret: %d", ret);		return wrap_urb_status(ret);	}	sel_conf->handle = udev->actconfig;	intf = &sel_conf->intf;	for (i = 0; i < config->bNumInterfaces && intf->bLength > 0;	     i++, intf = (((void *)intf) + intf->bLength)) {		USBTRACE("intf: %d, alt setting: %d",			 intf->bInterfaceNumber, intf->bAlternateSetting);		ret = usb_set_interface(udev, intf->bInterfaceNumber,					intf->bAlternateSetting);		if (ret < 0) {			ERROR("failed with %d", ret);			return wrap_urb_status(ret);		}		usb_intf = usb_ifnum_to_if(udev, intf->bInterfaceNumber);		if (!usb_intf) {			ERROR("couldn't obtain ifnum");			return USBD_STATUS_REQUEST_FAILED;		}		USBTRACE("intf: %p, num ep: %d", intf, intf->bNumEndpoints);		set_intf_pipe_info(wd, usb_intf, intf);	}	return USBD_STATUS_SUCCESS;}static USBD_STATUS wrap_select_interface(struct wrap_device *wd,					 union nt_urb *nt_urb,					 struct irp *irp){	int ret;	struct usbd_select_interface *sel_intf;	struct usb_device *udev;	struct usbd_interface_information *intf;	struct usb_interface *usb_intf;	udev = wd->usb.udev;	sel_intf = &nt_urb->select_intf;	intf = &sel_intf->intf;	ret = usb_set_interface(udev, intf->bInterfaceNumber,				intf->bAlternateSetting);	if (ret < 0) {		ERROR("failed with %d", ret);		return wrap_urb_status(ret);	}	usb_intf = usb_ifnum_to_if(udev, intf->bInterfaceNumber);	if (!usb_intf) {		ERROR("couldn't get interface information");		return USBD_STATUS_REQUEST_FAILED;	}	USBTRACE("intf: %p, num ep: %d", usb_intf, intf->bNumEndpoints);	set_intf_pipe_info(wd, usb_intf, intf);	return USBD_STATUS_SUCCESS;}static int wrap_usb_get_string(struct usb_device *udev, unsigned short langid,			       unsigned char index, void *buf, int size){	int i, ret;	/* if langid is 0, return array of langauges supported in	 * buf */	for (i = 0; i < 3; i++) {		ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),				      USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,				      (USB_DT_STRING << 8) + index, langid,				      buf, size, USB_CTRL_GET_TIMEOUT);		if (ret > 0 || ret == -EPIPE)			break;	}	return ret;}static USBD_STATUS wrap_get_descriptor(struct wrap_device *wd,				       union nt_urb *nt_urb, struct irp *irp){	struct usbd_control_descriptor_request *control_desc;	int ret = 0;	struct usb_device *udev;	udev = wd->usb.udev;	control_desc = &nt_urb->control_desc;	USBTRACE("desctype = %d, descindex = %d, transfer_buffer = %p,"		 "transfer_buffer_length = %d", control_desc->desc_type,		 control_desc->index, control_desc->transfer_buffer,		 control_desc->transfer_buffer_length);

⌨️ 快捷键说明

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