📄 usb.c
字号:
dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC); if (!dr) { ERROR("%s", "kmalloc failed!"); usb_free_urb(urb); return -ENOMEM; } dr->bRequestType = req_type; dr->bRequest = nt_urb->venClsReq.request; dr->wValue = nt_urb->venClsReq.value; dr->wIndex = nt_urb->venClsReq.index; dr->wLength = nt_urb->venClsReq.transferBufLen; usb_fill_control_urb(urb, dev, pipe, (unsigned char *)dr, nt_urb->venClsReq.transferBuf, nt_urb->venClsReq.transferBufLen, usb_transfer_complete, irp); 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 ((nt_urb->venClsReq.transferBufLen > 0) && !virt_addr_valid(nt_urb->venClsReq.transferBuf)) { IRP_DRIVER_CONTEXT(irp)[2] = kmalloc(nt_urb->venClsReq.transferBufLen, GFP_KERNEL); if (!IRP_DRIVER_CONTEXT(irp)[2]) { ERROR("%s", "kmalloc failed!"); kfree(dr); usb_free_urb(urb); return -ENOMEM; } if (!(pipe & USB_DIR_IN)) memcpy(IRP_DRIVER_CONTEXT(irp)[2], nt_urb->venClsReq.transferBuf, nt_urb->venClsReq.transferBufLen); urb->transfer_buffer = IRP_DRIVER_CONTEXT(irp)[2]; USBTRACE("mirroring non-DMA buffer"); } /* 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; USBTRACE("submitting urb %p on control pipe", urb); /* FIXME: we should better check what GFP_ is required */ ret = wrap_submit_urb(urb, GFP_ATOMIC); if (ret) kfree(dr); return ret;}unsigned long usb_reset_pipe(struct usb_device *dev, union pipe_handle pipe_handle){ int pipe; UCHAR endpoint; USBTRACE("pipe = %p", pipe_handle.handle); endpoint = pipe_handle.encoded.endpointAddr; switch (pipe_handle.encoded.pipeType) { case USB_ENDPOINT_XFER_CONTROL: if (pipe_handle.encoded.endpointAddr & USB_ENDPOINT_DIR_MASK) pipe = usb_rcvctrlpipe(dev, endpoint); else pipe = usb_sndctrlpipe(dev, endpoint); break; case USB_ENDPOINT_XFER_ISOC: if (pipe_handle.encoded.endpointAddr & USB_ENDPOINT_DIR_MASK) pipe = usb_rcvisocpipe(dev, endpoint); else pipe = usb_sndisocpipe(dev, endpoint); break; case USB_ENDPOINT_XFER_BULK: if (pipe_handle.encoded.endpointAddr & USB_ENDPOINT_DIR_MASK) pipe = usb_rcvbulkpipe(dev, endpoint); else pipe = usb_sndbulkpipe(dev, endpoint); break; default: /* USB_ENDPOINT_XFER_INT */ if (pipe_handle.encoded.endpointAddr & USB_ENDPOINT_DIR_MASK) pipe = usb_rcvbulkpipe(dev, endpoint); else pipe = usb_sndbulkpipe(dev, endpoint); break; } return usb_clear_halt(dev, pipe);}unsigned long usb_select_configuration(struct usb_device *dev, union nt_urb *nt_urb, struct irp *irp){ struct usb_interface *intf; struct usbd_pipe_information *pipe_info; int i, ret; struct usb_endpoint_descriptor *desc; ASSERT(nt_urb->selConf.config->bNumInterfaces == 1); USBTRACE("intf.intfNum = %d, intf.altSet = %d", nt_urb->selConf.intf.intfNum, nt_urb->selConf.intf.altSet); ret = usb_set_interface(dev, nt_urb->selConf.intf.intfNum, nt_urb->selConf.intf.altSet); if (ret < 0) { ERROR("usb_set_interface() = %d", ret); USBTRACEEXIT(return ret); } intf = usb_ifnum_to_if(dev, nt_urb->selConf.intf.intfNum); if (!intf) { ERROR("usb_ifnum_to_if() = %d", ret); USBTRACEEXIT(return ret); }#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) for (i = 0; i < CUR_ALT_SETTING(intf)->desc.bNumEndpoints; i++) { desc = &(CUR_ALT_SETTING(intf)->endpoint + i)->desc;#else for (i = 0; i < CUR_ALT_SETTING(intf).bNumEndpoints; i++) { desc = &((CUR_ALT_SETTING(intf)).endpoint[i]);#endif pipe_info = &nt_urb->selConf.intf.pipes[i]; pipe_info->maxPacketSize = desc->wMaxPacketSize; pipe_info->endpointAddr = desc->bEndpointAddress; pipe_info->interval = desc->bInterval; pipe_info->pipeType = desc->bmAttributes; pipe_info->pipeHandle.encoded.endpointAddr = desc->bEndpointAddress; pipe_info->pipeHandle.encoded.pipeType = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; pipe_info->pipeHandle.encoded.interval = (dev->speed == USB_SPEED_HIGH) ? desc->bInterval + 3 : desc->bInterval; pipe_info->pipeHandle.encoded.fill = 0; USBTRACE("%i: Addr %X, Type %d, PkSz %d, " "Intv %d, Handle %p", i, desc->bEndpointAddress, desc->bmAttributes, desc->wMaxPacketSize, desc->bInterval, pipe_info->pipeHandle.handle); } USBTRACEEXIT(return 0);}unsigned long usb_submit_nt_urb(struct usb_device *dev, union nt_urb *nt_urb, struct irp *irp){ int ret; USBTRACEENTER("nt_urb = %p, irp = %p, length = %d, function = %x", nt_urb, irp, nt_urb->header.length, nt_urb->header.function); nt_urb->header.status = USB_STATUS_SUCCESS; switch (nt_urb->header.function) { case URB_FUNCTION_SELECT_CONFIGURATION: usb_select_configuration(dev, nt_urb, irp); USBTRACEEXIT(return STATUS_SUCCESS); case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: ret = usb_bulk_or_intr_trans(dev, nt_urb, irp); if (ret < 0) break; USBTRACEEXIT(return STATUS_PENDING); case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: ASSERT(!nt_urb->ctrlDescReq.transferBufMdl); ASSERT(!nt_urb->ctrlDescReq.urbLink); USBTRACE("desctype = %d, descindex = %d, " "transferBuf = %p, transferBufLen = %ld", nt_urb->ctrlDescReq.desctype, nt_urb->ctrlDescReq.descindex, nt_urb->ctrlDescReq.transferBuf, nt_urb->ctrlDescReq.transferBufLen); ret = usb_get_descriptor(dev, nt_urb->ctrlDescReq.desctype, nt_urb->ctrlDescReq.descindex, nt_urb->ctrlDescReq.transferBuf, nt_urb->ctrlDescReq.transferBufLen); if (ret < 0) { ERROR("usb_get_descriptor() = %d", ret); break; } nt_urb->ctrlDescReq.transferBufLen = ret; USBTRACEEXIT(return STATUS_SUCCESS); case URB_FUNCTION_VENDOR_DEVICE: case URB_FUNCTION_VENDOR_INTERFACE: case URB_FUNCTION_CLASS_INTERFACE: USBTRACE("func: %d", nt_urb->header.function); ret = usb_vendor_or_class_intf(dev, nt_urb, irp); if (ret < 0) break; USBTRACEEXIT(return STATUS_PENDING); case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL: ret = usb_reset_pipe(dev, nt_urb->pipeReq.pipeHandle); if (ret < 0) { ERROR("usb_reset_pipe() = %d", ret); break; } USBTRACEEXIT(return STATUS_SUCCESS); default: ERROR("function %X NOT IMPLEMENTED!\n", nt_urb->header.function); } nt_urb->header.status = USB_STATUS_ERROR; USBTRACEEXIT(return STATUS_FAILURE);}unsigned long usb_reset_port(struct usb_device *dev){ int ret; USBTRACEENTER("%s", ""); ret = usb_reset_device(dev); if (ret < 0) { ERROR("usb_reset_device() = %d", ret); USBTRACEEXIT(return STATUS_FAILURE); } USBTRACEEXIT(return STATUS_SUCCESS);}STDCALL union nt_urb *WRAP_EXPORT(USBD_CreateConfigurationRequest) (struct usb_config_descriptor *config, unsigned short *urb_size){ union nt_urb *urb; struct usb_interface_descriptor *intf_desc; struct usbd_interface_information *intf_info; char *pos = (char *)config; int cfg_size = config->wTotalLength; int found = 0; USBTRACEENTER("config = %p, urb_size = %p", config, urb_size); ASSERT(config->bNumInterfaces < 2); while ((char *)pos - (char *)config < cfg_size) { intf_desc = (struct usb_interface_descriptor *)pos; pos = pos + intf_desc->bLength; if (intf_desc->bDescriptorType != USB_DT_INTERFACE) continue; USBTRACE("selected interface = %p", intf_desc); found = 1; break; } if (!found) USBTRACEEXIT(return NULL); *urb_size = sizeof(union nt_urb) + sizeof(struct usbd_pipe_information) * (intf_desc->bNumEndpoints - 1); /* FIXME: we should better check what GFP_ is required */ urb = kmalloc(*urb_size, GFP_ATOMIC); if (urb) { urb->selConf.header.length = *urb_size; urb->selConf.header.function = URB_FUNCTION_SELECT_CONFIGURATION; urb->selConf.config = config; intf_info = &urb->selConf.intf; intf_info->length = sizeof(struct usbd_interface_information)+ sizeof(struct usbd_pipe_information) * (intf_desc->bNumEndpoints - 1); intf_info->intfNum = intf_desc->bInterfaceNumber; intf_info->altSet = intf_desc->bAlternateSetting; intf_info->class = intf_desc->bInterfaceClass; intf_info->subClass = intf_desc->bInterfaceSubClass; intf_info->proto = intf_desc->bInterfaceProtocol; intf_info->pipeNum = intf_desc->bNumEndpoints; } USBTRACEEXIT(return urb);}STDCALL union nt_urb * WRAP_EXPORT(USBD_CreateConfigurationRequestEx) (struct usb_config_descriptor *config, struct usbd_interface_list_entry *intfList){ union nt_urb *urb; int urb_size; struct usb_interface_descriptor *intf_desc; struct usbd_interface_information *intf_info; /* * Note: This function is more or less a hack - due to a lack * of understanding of the underlying USB details. It only * sets up an URB with one interface inside. This is what the * WUSB54G driver requests or what the WUSB54G device * provides. However, this function warns if the assumption is * incorrect. */ USBTRACEENTER("config = %p, intfList = %p", config, intfList); ASSERT(config->bNumInterfaces < 2); intf_desc = intfList->intfDesc; urb_size = sizeof(union nt_urb) + sizeof(struct usbd_pipe_information) * (intf_desc->bNumEndpoints - 1); /* FIXME: we should better check what GFP_ is required */ urb = kmalloc(urb_size, GFP_ATOMIC); if (urb) { urb->selConf.header.length = urb_size; urb->selConf.header.function = URB_FUNCTION_SELECT_CONFIGURATION; urb->selConf.config = config; intf_info = &urb->selConf.intf; intfList->intf = intf_info; intf_info->length = sizeof(struct usbd_interface_information)+ sizeof(struct usbd_pipe_information) * (intf_desc->bNumEndpoints - 1); intf_info->intfNum = intf_desc->bInterfaceNumber; intf_info->altSet = intf_desc->bAlternateSetting; intf_info->class = intf_desc->bInterfaceClass; intf_info->subClass = intf_desc->bInterfaceSubClass; intf_info->proto = intf_desc->bInterfaceProtocol; intf_info->pipeNum = intf_desc->bNumEndpoints; ASSERT(!(intfList+1)->intfDesc); } USBTRACEEXIT(return urb);}WRAP_EXPORT_MAP("_USBD_CreateConfigurationRequestEx@8", USBD_CreateConfigurationRequestEx);STDCALL struct usb_interface_descriptor * WRAP_EXPORT(USBD_ParseConfigurationDescriptorEx) (struct usb_config_descriptor *config, void *startPos, LONG intfNum, LONG altSet, LONG intfClass, LONG intfSubClass, LONG intfProto){ int size = config->wTotalLength; char *pos = startPos; struct usb_interface_descriptor *intf; USBTRACEENTER("config = %p, startPos = %p, intfNum = %d, altSet = %d," " intfClass = %d, intfSubClass = %d, intfProto = %d", config, startPos, intfNum, altSet, intfClass, intfSubClass, intfProto); while ((char *)pos - (char *)config < size) { intf = (struct usb_interface_descriptor *)pos; pos = pos + intf->bLength; if (intf->bDescriptorType != USB_DT_INTERFACE) continue; if ((intfNum != -1) && (intf->bInterfaceNumber != intfNum)) continue; if ((altSet != -1) && (intf->bAlternateSetting != altSet)) continue; if ((intfClass != -1) && (intf->bInterfaceClass != intfClass)) continue; if ((intfSubClass != -1) && (intf->bInterfaceSubClass != intfSubClass)) continue; if ((intfProto != -1) && (intf->bInterfaceProtocol != intfProto)) continue; USBTRACE("selected interface = %p", intf); USBTRACEEXIT(return intf); } USBTRACEEXIT(return NULL);}WRAP_EXPORT_MAP("_USBD_ParseConfigurationDescriptorEx@28", USBD_ParseConfigurationDescriptorEx);STDCALL struct usb_interface_descriptor * WRAP_EXPORT(USBD_ParseConfigurationDescriptor) (struct usb_config_descriptor *config, unsigned char intfNum, unsigned char altSet){ return USBD_ParseConfigurationDescriptorEx(config, config, intfNum, altSet, -1, -1, -1);}#include "usb_exports.h"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -