?? libusb_driver.c
字號:
/* LIBUSB-WIN32, Generic Windows USB Library * Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de> * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#define __LIBUSB_DRIVER_C__#include "libusb_driver.h"extern int debug_level;static void DDKAPI unload(DRIVER_OBJECT *driver_object);static NTSTATUS DDKAPI on_usbd_complete(DEVICE_OBJECT *device_object, IRP *irp, void *context);NTSTATUS DDKAPI DriverEntry(DRIVER_OBJECT *driver_object, UNICODE_STRING *registry_path){ int i; DEBUG_MESSAGE("DriverEntry(): loading driver"); /* initialize global variables */ debug_level = LIBUSB_DEBUG_MSG; /* initialize the driver object's dispatch table */ for(i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) { driver_object->MajorFunction[i] = dispatch; } driver_object->DriverExtension->AddDevice = add_device; driver_object->DriverUnload = unload; return STATUS_SUCCESS;}NTSTATUS DDKAPI add_device(DRIVER_OBJECT *driver_object, DEVICE_OBJECT *physical_device_object){ NTSTATUS status; DEVICE_OBJECT *device_object = NULL; libusb_device_t *dev; ULONG device_type; UNICODE_STRING nt_device_name; UNICODE_STRING symbolic_link_name; WCHAR tmp_name_0[128]; WCHAR tmp_name_1[128]; char id[256]; int i; /* get the hardware ID from the registry */ if(!reg_get_hardware_id(physical_device_object, id, sizeof(id))) { DEBUG_ERROR("add_device(): unable to read registry"); return STATUS_SUCCESS; } /* only attach the (filter) driver to USB devices, skip hubs */ /* and interfaces of composite devices */ if(!strstr(id, "usb\\") || strstr(id, "hub") || strstr(id, "&mi_")) { return STATUS_SUCCESS; } /* retrieve the type of the lower device object */ device_object = IoGetAttachedDeviceReference(physical_device_object); if(device_object) { device_type = device_object->DeviceType; ObDereferenceObject(device_object); } else { device_type = FILE_DEVICE_UNKNOWN; } /* try to create a new device object */ for(i = 1; i < LIBUSB_MAX_NUMBER_OF_DEVICES; i++) { /* initialize some unicode strings */ _snwprintf(tmp_name_0, sizeof(tmp_name_0)/sizeof(WCHAR), L"%s%04d", LIBUSB_NT_DEVICE_NAME, i); _snwprintf(tmp_name_1, sizeof(tmp_name_1)/sizeof(WCHAR), L"%s%04d", LIBUSB_SYMBOLIC_LINK_NAME, i); RtlInitUnicodeString(&nt_device_name, tmp_name_0); RtlInitUnicodeString(&symbolic_link_name, tmp_name_1); /* create the object */ status = IoCreateDevice(driver_object, sizeof(libusb_device_t), &nt_device_name, device_type, 0, FALSE, &device_object); if(NT_SUCCESS(status)) { DEBUG_MESSAGE("add_device(): device #%d created", i); break; } device_object = NULL; /* continue until an unused device name is found */ } if(!device_object) { DEBUG_ERROR("add_device(): creating device failed"); return status; } status = IoCreateSymbolicLink(&symbolic_link_name, &nt_device_name); if(!NT_SUCCESS(status)) { DEBUG_ERROR("add_device(): creating symbolic link failed"); IoDeleteDevice(device_object); return status; } /* setup the "device object" */ dev = device_object->DeviceExtension; memset(dev, 0, sizeof(libusb_device_t)); /* attach the newly created device object to the stack */ dev->next_stack_device = IoAttachDeviceToDeviceStack(device_object, physical_device_object); if(!dev->next_stack_device) { DEBUG_ERROR("add_device(): attaching to device stack failed"); IoDeleteSymbolicLink(&symbolic_link_name); IoDeleteDevice(device_object); return STATUS_NO_SUCH_DEVICE; } dev->self = device_object; dev->physical_device_object = physical_device_object; dev->id = i; /* set initial power states */ dev->power_state.DeviceState = PowerDeviceD0; dev->power_state.SystemState = PowerSystemWorking; /* get device properties from the registry */ reg_get_properties(dev); if(dev->is_filter) { /* send all USB requests to the PDO in filter driver mode */ dev->target_device = dev->physical_device_object; /* use the same flags as the underlying object */ device_object->Flags |= dev->next_stack_device->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE); } else { /* send all USB requests to the lower object in device driver mode */ dev->target_device = dev->next_stack_device; device_object->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE; } clear_pipe_info(dev); remove_lock_initialize(dev); device_object->Flags &= ~DO_DEVICE_INITIALIZING; return status;}VOID DDKAPI unload(DRIVER_OBJECT *driver_object){ DEBUG_MESSAGE("unload(): unloading driver");}NTSTATUS complete_irp(IRP *irp, NTSTATUS status, ULONG info){ irp->IoStatus.Status = status; irp->IoStatus.Information = info; IoCompleteRequest(irp, IO_NO_INCREMENT); return status;}NTSTATUS call_usbd(libusb_device_t *dev, void *urb, ULONG control_code, int timeout){ KEVENT event; NTSTATUS status; IRP *irp; IO_STACK_LOCATION *next_irp_stack; LARGE_INTEGER _timeout; IO_STATUS_BLOCK io_status; if(timeout > LIBUSB_MAX_CONTROL_TRANSFER_TIMEOUT) { timeout = LIBUSB_MAX_CONTROL_TRANSFER_TIMEOUT; } KeInitializeEvent(&event, NotificationEvent, FALSE); irp = IoBuildDeviceIoControlRequest(control_code, dev->target_device, NULL, 0, NULL, 0, TRUE, NULL, &io_status); if(!irp) { return STATUS_NO_MEMORY; } next_irp_stack = IoGetNextIrpStackLocation(irp); next_irp_stack->Parameters.Others.Argument1 = urb; next_irp_stack->Parameters.Others.Argument2 = NULL; IoSetCompletionRoutine(irp, on_usbd_complete, &event, TRUE, TRUE, TRUE); status = IoCallDriver(dev->target_device, irp); if(status == STATUS_PENDING) { _timeout.QuadPart = -(timeout * 10000); if(KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, &_timeout) == STATUS_TIMEOUT) { DEBUG_ERROR("call_usbd(): request timed out"); IoCancelIrp(irp); } } /* wait until completion routine is called */ KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); status = irp->IoStatus.Status; /* complete the request */ IoCompleteRequest(irp, IO_NO_INCREMENT); return status;}static NTSTATUS DDKAPI on_usbd_complete(DEVICE_OBJECT *device_object, IRP *irp, void *context){ KeSetEvent((KEVENT *) context, IO_NO_INCREMENT, FALSE); return STATUS_MORE_PROCESSING_REQUIRED;}NTSTATUS pass_irp_down(libusb_device_t *dev, IRP *irp, PIO_COMPLETION_ROUTINE completion_routine, void *context){ if(completion_routine) { IoCopyCurrentIrpStackLocationToNext(irp); IoSetCompletionRoutine(irp, completion_routine, context, TRUE, TRUE, TRUE); } else { IoSkipCurrentIrpStackLocation(irp); } return IoCallDriver(dev->next_stack_device, irp);}bool_t accept_irp(libusb_device_t *dev, IRP *irp){ /* check if the IRP is sent to libusb's device object or to */ /* the lower one. This check is neccassary since the device object */ /* might be a filter */ if(irp->Tail.Overlay.OriginalFileObject) { return irp->Tail.Overlay.OriginalFileObject->DeviceObject == dev->self ? TRUE : FALSE; } return FALSE;}bool_t get_pipe_handle(libusb_device_t *dev, int endpoint_address, USBD_PIPE_HANDLE *pipe_handle){ int i, j; *pipe_handle = NULL; for(i = 0; i < LIBUSB_MAX_NUMBER_OF_INTERFACES; i++) { if(dev->config.interfaces[i].valid) { for(j = 0; j < LIBUSB_MAX_NUMBER_OF_ENDPOINTS; j++) { if(dev->config.interfaces[i].endpoints[j].address == endpoint_address) { *pipe_handle = dev->config.interfaces[i].endpoints[j].handle; return !*pipe_handle ? FALSE : TRUE; } } } } return FALSE;}void clear_pipe_info(libusb_device_t *dev){ memset(dev->config.interfaces, 0 , sizeof(dev->config.interfaces));}bool_t update_pipe_info(libusb_device_t *dev, USBD_INTERFACE_INFORMATION *interface_info){ int i; int number; if(!interface_info) { return FALSE; } number = interface_info->InterfaceNumber; if(interface_info->InterfaceNumber >= LIBUSB_MAX_NUMBER_OF_INTERFACES) { return FALSE; } DEBUG_MESSAGE("update_pipe_info(): interface %d", number); dev->config.interfaces[number].valid = TRUE; for(i = 0; i < LIBUSB_MAX_NUMBER_OF_ENDPOINTS; i++) { dev->config.interfaces[number].endpoints[i].address = 0; dev->config.interfaces[number].endpoints[i].handle = NULL; } if(interface_info) { for(i = 0; i < (int)interface_info->NumberOfPipes && i < LIBUSB_MAX_NUMBER_OF_ENDPOINTS; i++) { DEBUG_MESSAGE("update_pipe_info(): endpoint address 0x%02x", interface_info->Pipes[i].EndpointAddress); dev->config.interfaces[number].endpoints[i].handle = interface_info->Pipes[i].PipeHandle; dev->config.interfaces[number].endpoints[i].address = interface_info->Pipes[i].EndpointAddress; } } return TRUE;}void remove_lock_initialize(libusb_device_t *dev){ KeInitializeEvent(&dev->remove_lock.event, NotificationEvent, FALSE); dev->remove_lock.usage_count = 1; dev->remove_lock.remove_pending = FALSE;}NTSTATUS remove_lock_acquire(libusb_device_t *dev){ InterlockedIncrement(&dev->remove_lock.usage_count); if(dev->remove_lock.remove_pending) { if(InterlockedDecrement(&dev->remove_lock.usage_count) == 0) { KeSetEvent(&dev->remove_lock.event, 0, FALSE); } return STATUS_DELETE_PENDING; } return STATUS_SUCCESS;}void remove_lock_release(libusb_device_t *dev){ if(InterlockedDecrement(&dev->remove_lock.usage_count) == 0) { KeSetEvent(&dev->remove_lock.event, 0, FALSE); }}void remove_lock_release_and_wait(libusb_device_t *dev){ dev->remove_lock.remove_pending = TRUE; remove_lock_release(dev); remove_lock_release(dev); KeWaitForSingleObject(&dev->remove_lock.event, Executive, KernelMode, FALSE, NULL);}USB_INTERFACE_DESCRIPTOR *find_interface_desc(USB_CONFIGURATION_DESCRIPTOR *config_desc, unsigned int size, int interface_number, int altsetting){ usb_descriptor_header_t *desc = (usb_descriptor_header_t *)config_desc; char *p = (char *)desc; USB_INTERFACE_DESCRIPTOR *if_desc = NULL; if(!config_desc || (size < config_desc->wTotalLength)) return NULL; while(size && desc->length <= size) { if(desc->type == USB_INTERFACE_DESCRIPTOR_TYPE) { if_desc = (USB_INTERFACE_DESCRIPTOR *)desc; if((if_desc->bInterfaceNumber == (UCHAR)interface_number) && (if_desc->bAlternateSetting == (UCHAR)altsetting)) { return if_desc; } } size -= desc->length; p += desc->length; desc = (usb_descriptor_header_t *)p; } return NULL;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -