📄 usb.c
字号:
if (control_desc->desc_type == USB_DT_STRING) { USBTRACE("langid: %x", control_desc->language_id); ret = wrap_usb_get_string(udev, control_desc->language_id, control_desc->index, control_desc->transfer_buffer, control_desc->transfer_buffer_length); } else { ret = usb_get_descriptor(udev, control_desc->desc_type, control_desc->index, control_desc->transfer_buffer, control_desc->transfer_buffer_length); } if (ret < 0) { USBTRACE("request %d failed: %d", control_desc->desc_type, ret); control_desc->transfer_buffer_length = 0; return wrap_urb_status(ret); } else { USBTRACE("ret: %08x", ret); control_desc->transfer_buffer_length = ret; irp->io_status.info = ret; return USBD_STATUS_SUCCESS; }}static USBD_STATUS wrap_process_nt_urb(struct irp *irp){ union nt_urb *nt_urb; struct usb_device *udev; USBD_STATUS status; struct wrap_device *wd; wd = IRP_WRAP_DEVICE(irp); udev = wd->usb.udev; nt_urb = IRP_URB(irp); USBENTER("nt_urb = %p, irp = %p, length = %d, function = %x", nt_urb, irp, nt_urb->header.length, nt_urb->header.function); DUMP_IRP(irp); switch (nt_urb->header.function) { /* bulk/int and vendor/class urbs are submitted to * Linux USB core; if the call is sucessful, urb's * completion worker will return IRP later */ case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: USBTRACE("submitting bulk/int irp: %p", irp); status = wrap_bulk_or_intr_trans(irp); break; case URB_FUNCTION_VENDOR_DEVICE: case URB_FUNCTION_VENDOR_INTERFACE: case URB_FUNCTION_VENDOR_ENDPOINT: case URB_FUNCTION_VENDOR_OTHER: case URB_FUNCTION_CLASS_DEVICE: case URB_FUNCTION_CLASS_INTERFACE: case URB_FUNCTION_CLASS_ENDPOINT: case URB_FUNCTION_CLASS_OTHER: USBTRACE("submitting vendor/class irp: %p", irp); status = wrap_vendor_or_class_req(irp); break; /* rest are synchronous */ case URB_FUNCTION_SELECT_CONFIGURATION: status = wrap_select_configuration(wd, nt_urb, irp); NT_URB_STATUS(nt_urb) = status; break; case URB_FUNCTION_SELECT_INTERFACE: status = wrap_select_interface(wd, nt_urb, irp); NT_URB_STATUS(nt_urb) = status; break; case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: status = wrap_get_descriptor(wd, nt_urb, irp); NT_URB_STATUS(nt_urb) = status; break; case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL: status = wrap_reset_pipe(udev, irp); NT_URB_STATUS(nt_urb) = status; break; case URB_FUNCTION_ABORT_PIPE: status = wrap_abort_pipe(udev, irp); break; default: ERROR("function %x not implemented", nt_urb->header.function); status = NT_URB_STATUS(nt_urb) = USBD_STATUS_NOT_SUPPORTED; break; } USBTRACE("status: %08X", status); return status;}static USBD_STATUS wrap_reset_port(struct irp *irp){ no_warn_unused int ret, lock = 0; struct wrap_device *wd; wd = IRP_WRAP_DEVICE(irp); USBENTER("%p, %p", wd, wd->usb.udev);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) lock = usb_lock_device_for_reset(wd->usb.udev, wd->usb.intf); if (lock < 0) { WARNING("locking failed: %d", lock); return wrap_urb_status(lock); }#endif ret = usb_reset_device(wd->usb.udev); if (ret < 0) USBTRACE("reset failed: %d", ret); /* TODO: should reconfigure? */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) if (lock) usb_unlock_device(wd->usb.udev);#endif return wrap_urb_status(ret);}static USBD_STATUS wrap_get_port_status(struct irp *irp){ struct wrap_device *wd; ULONG *status; wd = IRP_WRAP_DEVICE(irp); USBENTER("%p, %p", wd, wd->usb.udev); status = IoGetCurrentIrpStackLocation(irp)->params.others.arg1;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) { enum usb_device_state state; state = wd->usb.udev->state; if (state != USB_STATE_NOTATTACHED && state != USB_STATE_SUSPENDED) { *status |= USBD_PORT_CONNECTED; if (state == USB_STATE_CONFIGURED) *status |= USBD_PORT_ENABLED; } USBTRACE("state: %d, *status: %08X", state, *status); }#else /* TODO: how to get current status? */ *status = USBD_PORT_CONNECTED | USBD_PORT_ENABLED;#endif return USBD_STATUS_SUCCESS;}NTSTATUS wrap_submit_irp(struct device_object *pdo, struct irp *irp){ struct io_stack_location *irp_sl; struct wrap_device *wd; USBD_STATUS status; struct usbd_idle_callback *idle_callback; USBTRACE("%p, %p", pdo, irp); wd = pdo->reserved;// if (wd->usb.intf == NULL)// USBEXIT(return STATUS_DEVICE_REMOVED); IRP_WRAP_DEVICE(irp) = wd; irp_sl = IoGetCurrentIrpStackLocation(irp); switch (irp_sl->params.dev_ioctl.code) { case IOCTL_INTERNAL_USB_SUBMIT_URB: status = wrap_process_nt_urb(irp); break; case IOCTL_INTERNAL_USB_RESET_PORT: status = wrap_reset_port(irp); break; case IOCTL_INTERNAL_USB_GET_PORT_STATUS: status = wrap_get_port_status(irp); break; case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION: idle_callback = irp_sl->params.dev_ioctl.type3_input_buf; USBTRACE("suspend function: %p", idle_callback->callback); status = USBD_STATUS_NOT_SUPPORTED; break; default: ERROR("ioctl %08X NOT IMPLEMENTED", irp_sl->params.dev_ioctl.code); status = USBD_STATUS_NOT_SUPPORTED; break; } USBTRACE("status: %08X", status); if (status == USBD_STATUS_PENDING) { /* don't touch this IRP - it may have been already * completed/returned */ return STATUS_PENDING; } else { irp->io_status.status = nt_urb_irp_status(status); if (status != USBD_STATUS_SUCCESS) irp->io_status.info = 0; USBEXIT(return irp->io_status.status); }}/* TODO: The example on msdn in reference section suggests that second * argument should be an array of usbd_interface_information, but * description and examples elsewhere suggest that it should be * usbd_interface_list_entry structre. Which is correct? */wstdcall union nt_urb *WIN_FUNC(USBD_CreateConfigurationRequestEx,2) (struct usb_config_descriptor *config, struct usbd_interface_list_entry *intf_list){ int size, i, n; struct usbd_interface_information *intf; struct usbd_pipe_information *pipe; struct usb_interface_descriptor *intf_desc; struct usbd_select_configuration *select_conf; USBENTER("config = %p, intf_list = %p", config, intf_list); /* calculate size required; select_conf already has space for * one intf structure */ size = sizeof(*select_conf) - sizeof(*intf); for (n = 0; n < config->bNumInterfaces; n++) { i = intf_list[n].intf_desc->bNumEndpoints; /* intf already has space for one pipe */ size += sizeof(*intf) + (i - 1) * sizeof(*pipe); } /* don't use kmalloc - driver frees it with ExFreePool */ select_conf = ExAllocatePoolWithTag(NonPagedPool, size, POOL_TAG('L', 'U', 'S', 'B')); if (!select_conf) { WARNING("couldn't allocate memory"); return NULL; } memset(select_conf, 0, size); intf = &select_conf->intf; select_conf->handle = config; for (n = 0; n < config->bNumInterfaces && intf_list[n].intf_desc; n++) { /* initialize 'intf' fields in intf_list so they point * to appropriate entry; these may be read/written by * driver after this function returns */ intf_list[n].intf = intf; intf_desc = intf_list[n].intf_desc; i = intf_desc->bNumEndpoints; intf->bLength = sizeof(*intf) + (i - 1) * sizeof(*pipe); intf->bInterfaceNumber = intf_desc->bInterfaceNumber; intf->bAlternateSetting = intf_desc->bAlternateSetting; intf->bInterfaceClass = intf_desc->bInterfaceClass; intf->bInterfaceSubClass = intf_desc->bInterfaceSubClass; intf->bInterfaceProtocol = intf_desc->bInterfaceProtocol; intf->bNumEndpoints = intf_desc->bNumEndpoints; pipe = &intf->pipes[0]; for (i = 0; i < intf->bNumEndpoints; i++) { memset(&pipe[i], 0, sizeof(*pipe)); pipe[i].max_tx_size = USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE; } intf->handle = intf_desc; intf = (((void *)intf) + intf->bLength); } select_conf->header.function = URB_FUNCTION_SELECT_CONFIGURATION; select_conf->header.length = size; select_conf->config = config; USBEXIT(return (union nt_urb *)select_conf);}WIN_SYMBOL_MAP("_USBD_CreateConfigurationRequestEx@8", USBD_CreateConfigurationRequestEx)wstdcall struct usb_interface_descriptor *WIN_FUNC(USBD_ParseConfigurationDescriptorEx,7) (struct usb_config_descriptor *config, void *start, LONG bInterfaceNumber, LONG bAlternateSetting, LONG bInterfaceClass, LONG bInterfaceSubClass, LONG bInterfaceProtocol){ void *pos; struct usb_interface_descriptor *intf; USBENTER("config = %p, start = %p, ifnum = %d, alt_setting = %d," " class = %d, subclass = %d, proto = %d", config, start, bInterfaceNumber, bAlternateSetting, bInterfaceClass, bInterfaceSubClass, bInterfaceProtocol); for (pos = start; pos < ((void *)config + config->wTotalLength); pos += intf->bLength) { intf = pos; if ((intf->bDescriptorType == USB_DT_INTERFACE) && ((bInterfaceNumber == -1) || (intf->bInterfaceNumber == bInterfaceNumber)) && ((bAlternateSetting == -1) || (intf->bAlternateSetting == bAlternateSetting)) && ((bInterfaceClass == -1) || (intf->bInterfaceClass == bInterfaceClass)) && ((bInterfaceSubClass == -1) || (intf->bInterfaceSubClass == bInterfaceSubClass)) && ((bInterfaceProtocol == -1) || (intf->bInterfaceProtocol == bInterfaceProtocol))) { USBTRACE("selected interface = %p", intf); USBEXIT(return intf); } } USBEXIT(return NULL);}WIN_SYMBOL_MAP("_USBD_ParseConfigurationDescriptorEx@28", USBD_ParseConfigurationDescriptorEx)wstdcall union nt_urb *WIN_FUNC(USBD_CreateConfigurationRequest,2) (struct usb_config_descriptor *config, USHORT *size){ union nt_urb *nt_urb; struct usbd_interface_list_entry intf_list[2]; struct usb_interface_descriptor *intf_desc; USBENTER("config = %p, urb_size = %p", config, size); intf_desc = USBD_ParseConfigurationDescriptorEx(config, config, -1, -1, -1, -1, -1); intf_list[0].intf_desc = intf_desc; intf_list[0].intf = NULL; intf_list[1].intf_desc = NULL; intf_list[1].intf = NULL; nt_urb = USBD_CreateConfigurationRequestEx(config, intf_list); if (!nt_urb) return NULL; *size = nt_urb->select_conf.header.length; USBEXIT(return nt_urb);}wstdcall struct usb_interface_descriptor *WIN_FUNC(USBD_ParseConfigurationDescriptor,3) (struct usb_config_descriptor *config, UCHAR bInterfaceNumber, UCHAR bAlternateSetting){ return USBD_ParseConfigurationDescriptorEx(config, config, bInterfaceNumber, bAlternateSetting, -1, -1, -1);}wstdcall usb_common_descriptor_t *WIN_FUNC(USBD_ParseDescriptors,4) (void *buf, ULONG length, void *start, LONG type){ usb_common_descriptor_t *descr = start; while ((void *)descr < buf + length) { if (descr->bDescriptorType == type) return descr; if (descr->bLength == 0) break; descr = (void *)descr + descr->bLength; } USBEXIT(return NULL);}WIN_SYMBOL_MAP("_USBD_ParseDescriptors@16", USBD_ParseDescriptors)wstdcall void WIN_FUNC(USBD_GetUSBDIVersion,1) (struct usbd_version_info *version_info){ /* this function is obsolete in Windows XP */ if (version_info) { version_info->usbdi_version = USBDI_VERSION_XP; /* TODO: how do we get this correctly? */ version_info->supported_usb_version = 0x110; } USBEXIT(return);}wstdcall voidUSBD_InterfaceGetUSBDIVersion(void *context, struct usbd_version_info *version_info, ULONG *hcd_capa){ struct wrap_device *wd = context; if (version_info) { version_info->usbdi_version = USBDI_VERSION_XP; if (wd->usb.udev->speed == USB_SPEED_HIGH) version_info->supported_usb_version = 0x200; else version_info->supported_usb_version = 0x110; } *hcd_capa = USB_HCD_CAPS_SUPPORTS_RT_THREADS; USBEXIT(return);}wstdcall BOOLEAN USBD_InterfaceIsDeviceHighSpeed(void *context){ struct wrap_device *wd = context; USBTRACE("wd: %p", wd); if (wd->usb.udev->speed == USB_SPEED_HIGH) USBEXIT(return TRUE); else USBEXIT(return FALSE);}wstdcall void USBD_InterfaceReference(void *context){ USBTRACE("%p", context); TODO();}wstdcall void USBD_InterfaceDereference(void *context){ USBTRACE("%p", context); TODO();}wstdcall NTSTATUS USBD_InterfaceQueryBusTime(void *context, ULONG *frame){ struct wrap_device *wd = context; *frame = usb_get_current_frame_number(wd->usb.udev); USBEXIT(return STATUS_SUCCESS);}wstdcall NTSTATUS USBD_InterfaceSubmitIsoOutUrb(void *context, union nt_urb *nt_urb){ /* TODO: implement this */ TODO(); USBEXIT(return STATUS_NOT_IMPLEMENTED);}wstdcall NTSTATUSUSBD_InterfaceQueryBusInformation(void *context, ULONG level, void *buf, ULONG *buf_length, ULONG *buf_actual_length){ struct wrap_device *wd = context; struct usb_bus_information_level *bus_info; struct usb_bus *bus; bus = wd->usb.udev->bus; bus_info = buf; TODO(); USBEXIT(return STATUS_NOT_IMPLEMENTED);}wstdcall NTSTATUSUSBD_InterfaceLogEntry(void *context, ULONG driver_tag, ULONG enum_tag, ULONG p1, ULONG p2){ ERROR("%p, %x, %x, %x, %x", context, driver_tag, enum_tag, p1, p2); USBEXIT(return STATUS_SUCCESS);}#include "usb_exports.h"int usb_init(void){ InitializeListHead(&wrap_urb_complete_list); nt_spin_lock_init(&wrap_urb_complete_list_lock);#ifdef USB_TASKLET tasklet_init(&wrap_urb_complete_work, wrap_urb_complete_worker, 0);#else initialize_work(&wrap_urb_complete_work, wrap_urb_complete_worker, NULL);#endif#ifdef USB_DEBUG urb_id = 0;#endif return 0;}void usb_exit(void){#ifdef USB_TASKLET tasklet_kill(&wrap_urb_complete_work);#endif USBEXIT(return);}int usb_init_device(struct wrap_device *wd){ InitializeListHead(&wd->usb.wrap_urb_list); wd->usb.num_alloc_urbs = 0; USBEXIT(return 0);}void usb_exit_device(struct wrap_device *wd){ kill_all_urbs(wd, 0); USBEXIT(return);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -