阅读:2369回复:3
USB设备识别-草案
在涉及USB设备或USB设备相关的项目开发中,难免会涉及到:
如何识别出插入的USB设备为自己而不是别的厂商? 插入多个USB设备,如何准确实现数据传输等问题。 本帖,以USB的设备识别为题,结合自己的VxClient,以伪代码的形式,和大家一同探索:USB的识别问题。由于水平有限,难免存有不足之处,望同行指正! 1。原理: 代码:总线驱动程序(DDK\Kernel\serenum) 书籍:WDM开发指南 2。流程: (以伪代码为路线) #include "VxClient.h" // our device extension where #pragma warning(error:4100) // Unreferenced formal parameter #pragma warning(error:4101) // Unreferenced local variable // // TAG identifying memory VxClient allocates // #define POOL_TAG 'fFtS' #if WINVER == 0x0500 // // These macros are used to test, set and clear flags respectively // #ifndef FlagOn #define FlagOn(_F,_SF) ((_F) & (_SF)) #endif #ifndef BooleanFlagOn #define BooleanFlagOn(F,SF) ((BOOLEAN)(((F) & (SF)) != 0)) #endif #ifndef SetFlag #define SetFlag(_F,_SF) ((_F) |= (_SF)) #endif #ifndef ClearFlag #define ClearFlag(_F,_SF) ((_F) &= ~(_SF)) #endif #define RtlInitEmptyUnicodeString(_ucStr,_buf,_bufSize) \ ((_ucStr)->Buffer = (_buf), \ (_ucStr)->Length = 0, \ (_ucStr)->MaximumLength = (USHORT)(_bufSize)) #ifndef min #define min(a,b) (((a) < (b)) ? (a) : (b)) #endif #ifndef max #define max(a,b) (((a) > (b)) ? (a) : (b)) #endif // // We want ASSERT defined as an expression, which was fixed after Windows 2000 // #ifdef ASSERT #undef ASSERT #if DBG #define ASSERT( exp ) \ ((!(exp)) ? \ (RtlAssert( #exp, __FILE__, __LINE__, NULL ),FALSE) : \ TRUE) #else #define ASSERT( exp ) ((void) 0) #endif #endif #define ExFreePoolWithTag( a, b ) ExFreePool( (a) ) #endif /* WINVER == 0x0500 */ #define RtlInitEmptyUnicodeString(_ucStr,_buf,_bufSize) \ ((_ucStr)->Buffer = (_buf), \ (_ucStr)->Length = 0, \ (_ucStr)->MaximumLength = (USHORT)(_bufSize)) #define IS_MY_DEVICE_OBJECT(_devObj) \ (((_devObj) != NULL) && \ ((_devObj)->DriverObject == gVxClientDriverObject) && \ ((_devObj)->DeviceExtension != NULL)) #define IS_MY_CONTROL_DEVICE_OBJECT(_devObj) \ (((_devObj) == gVxClientControlDeviceObject) ? \ (ASSERT(((_devObj)->DriverObject == gVxClientDriverObject) && \ ((_devObj)->DeviceExtension == NULL)), TRUE) : \ FALSE) // 全局变量 UNICODE_STRING GlobalRegistryPath; // // Holds pointer to the driver object for this driver // PDRIVER_OBJECT gVxClientDriverObject = NULL; // // Holds pointer to the device object that represents this driver and is used // by external programs to access this driver. This is also known as the // "control device object". // PDEVICE_OBJECT gVxClientControlDeviceObject = NULL; FAST_MUTEX gVxClientAttachLock; #ifdef ALLOC_PRAGMA #pragma alloc_text(INIT, DriverEntry) #if DBG && WINVER >= 0x0501 #pragma alloc_text(PAGE, DriverUnload) #endif #pragma alloc_text(PAGE, VxClientCreate) #pragma alloc_text(PAGE, VxClientClose) #pragma alloc_text(PAGE, VxClientWrite) #pragma alloc_text(PAGE, VxClientRead) #pragma alloc_text(PAGE, VxClientDeviceIoControl) #endif extern "C" NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { NTSTATUS status = STATUS_SUCCESS; USHORT regPathLen; ULONG ulIndex; regPathLen = RegistryPath->Length; GlobalRegistryPath.MaximumLength = regPathLen + sizeof(UNICODE_NULL); GlobalRegistryPath.Lenth = regPathLen; GlobalRegistryPath.Buffer = ExAllocatePoolWithTag( PagedPoll, GlobalRegistryPath.MaximumLength, POOL_TAG ); if (GlobalRegistryPath.Buffer == NULL) { KdPrint(("Couldn't allocate pool for registry path!\n")); return STATUS_INSUFFICIENT_RESOURCES; } RtlCopyUnicodeString(&GlobalRegistryPath, RegistryPath);//GlobalRegistryPath //保存我们的驱动对象,及设置UNLOAD例程 gVxClientDriverObject = DriverObject; #if DBG KdPrint(("VxClient Checked!"); gVxClientDriverObject->DriverUnload = DriverUnload; else KdPrint(("VxClient Checked!"); #endif #define SYS_DEVICE_NAME "\\Device\\VxClient" #define DOS_DEVICE_NAME "\\??\\VxClient" UNICODE_STRING nameString, linkName; RtlInitUnicodeString( &nameString, SYS_DEVICE_NAME); RtlInitUnicodeString( &linkName, DOS_DEVICE_NAME); status = IoCreateDevice( DriverObject, 0, //has no device extension &nameString, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &gVxClientControlDeviceObject); if (!NT_SUCCESS( status )) { KdPrint(( "VxClient!DriverEntry: Error creating control device object \"%wZ\", status=%08x\n", &nameString, status )); return status; } KdPrint(("Creating symbolic link"); status = IoCreateSymbolicLink( &linkString, &nameString ); if (!NT_SUCCESS(status)) { IoDeleteSymbolicLink( &linkString ); status = IoCreateSymbolicLink( &linkString, &nameString ); if (!NT_SUCCESS(status)) { IoDeleteDevice(gVxClientControlDeviceObject); KdPrint(( "VxClient!DriverEntry: Error creating Symbolic Link status=%08x\n",status )); return status; } } /*分发例程暂时不处理 DriverObject->MajorFunction[IRP_MJ_CREATE]= VxClientCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = VxClientClose; DriverObject->MajorFunction[IRP_MJ_WRTIE] = VxClientWrite; DriverObject->MajorFunction[IRP_MJ_READ] = VxClientRead; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = VxClientDeviceIoControl; */ status = RegisterForPnpNotification(DriverObject); if (!NT_SUCCESS(status)) { KdPrint(( "VxClient!DriverEntry: Error registering Pnp change notification, status=%08x\n", status )); IoDeleteDevice(gVxClientDriverObject); return status; } //做些初始化工作....有待整理 ClearFlag( gVxClientControlDeviceObject->Flags, DO_DEVICE_INITIALIZING ); KdPrint(("VxClient!DriverEntry:Completed!!")); return status; } NTSTATUS RegisterForPnpNotification( IN PDRIVER_OBJECT DriverObject ) { PAGED_CODE(); KdPrint(("RegisterForPnpNotification")); NTSTATUS status = IoRegisterPlugPlayNotification( EventCategoryDeviceInterfaceChange, PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, (PVOID)&GUID_CLASS_INPUT, DriverObject, PnpDicnCallback, DriverObject,//注册PnpInterfaceChangeEvent回调函数 &diNotificationEntry); return status; } NTSTATUS PnpDicnCallback( IN PVOID NotificationStructure, IN PVOID Context ) { PAGED_CODE(); PDRIVER_INTERFACE_CHANGE_NOTIFICATION dicn = (PDRIVER_INTERFACE_CHANGE_NOTIFICATION)NotificationStructure; PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Context; if(IsEqualGUID(dicn->Event, GUID_DEVICE_INTERFFACE_ARRIVAL)) //analyse and deal with dicn { KdPrint(("new Device arrvial : dicn->SymbolicLinkNam\"%wZ\"",&dicn->SymbolicLinkName)); CreateDevice(DriverObject,dicn->SymbolicLinkName); } else if(IsEqualGUID(dicn->Event, GUID->DEVICE_INTERFACE_REMOVAL)) { KdPrint(("new Device removal : dicn->SymbolicLinkName\"%wZ\"",&dicn->SymbolicLinkName)); DeleteDevice(DriverObject,dicn->SymbolicLinkName); } return STATUS_SUCCESS; } void CreateDevice( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING HidSymLinkName ) { PFILE_OBJECT HidFileObject = NULL; PDEVICE_OBJECT HidDevice; PDEVICE_OBJECT newHidDeviceObject; PAGED_CODE(); NTSTATUS status = IoGetDeviceObjectPointer( HidSymLinkName, FILE_ALL_ACCESS, &HidFileObject, &HidDevice); if(!NT_SUCCESS(status)) { KdPrint(("IoGetDeviceObjectPointer failed!")); return; } ObDereference(HidFileObject): PHIDP_PREPARSED_DATA HidPreparsedData = NULL; USHORT HidInputReportLen,HidOutputLen; if(!GetCapabilities(HidDevice,HidPreparsedData,HidInputReportLen,HidOutputReportLen)) { KdPrint(("GetCapabilites failed!")); ExFreePool(HidPreparsedData); return; } //got capabilities of the hid_device PWSTR HidSymLinkNameBuffer = (PWSTR)ExAllocatePool( NonPagedPool,HidSymLinkName->MaximumLength); if( HidSymLinkNameBuffer==NULL) { ExFreePool(HidPreparsedData); return; } status = ObReferenceObjectByPointer(HidDevice, FILE_ALL_ACCESS, NULL, KernelMode); if(!NT_SUCCESS(status)) { KdPrint(("ObReferenceObjectByPointer failed")); ExFreePool(HidSymLinkNameBuffer); ExFreePool(HidPreparsedData); return; } status = IoCreateDevice( DriverObject, sizeof( HIDVX_DEVICE_EXTENSION ), NULL, FILE_DEVICE_UNKNOWN,//DeviceType, 0, FALSE, &newHidDeviceObject ); //newDeviceObject 存放在HIDX_DEVICE_EXTENSION中 //HIDX_DEVICE_EXTENSION 说明:CDO与DO都使用这个结构,目的就是形成一个链表,这样,我们就可以通过 //CDO(父)来操作DO(子) if (!NT_SUCCESS( status )) { IoDeleteDevice(newHidDeviceObject); ExFreePool(HidSymLinkNameBuffer); ExFreePool(HidPreparsedData); ObDereferenceObject(HidDevice); return status; } //基本设置 PHIDVX_DEVICE_EXTENSION devExt = (PHIDVX_DEVICE_EXTENSION)newHidDeviceObject->DeviceExtension; devExt->HidDevice = HidDevice; devExt->HidPreparsedData = HidPreparsedData; devExt->HidInputReportLen = HidInputReportLen; devExt->HidOutputReportLen = HidOutputReportLen; devExt->HidMaxReportLen = 0; devExt->HidIrp = NULL; devExt->HidReport = NULL; devExt->HidReportMdl = NULL; devExt->HidSymLinkName.Length = 0; devExt->HidSymLinkName.MaximumLength = HidSymLinkName->MaximumLength; devExt->HidSymLinkName.Buffer = HidSymLinkNameBuffer; RtlCopyUnicodeString( &devExt->HidSymLinkName, HidSymLinkName); newHidDeviceObject->Flags |= DO_BUFFERED_IO; //由于采用不AttachTo的方式,所以自己设定StackSize的大小 newHidDeviceObject->StackSize = HidDevice->StackSize + 1; //OK后,清除DO_DEVICE_INITIALIZING标志,表明设备已经准备好了。可以使用了 newHidDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; KdPrint(("Child Device created OK")); } |
|
沙发#
发布于:2007-05-30 09:41
谢谢指教!
|
|
板凳#
发布于:2009-03-30 12:58
已解决
|
|
地板#
发布于:2009-03-30 15:19
多谢楼主,对我帮助很大。
|
|