阅读:2103回复:1
在Kernel态如何访问HID设备?
我在做一个NT式驱动,想要访问HID设备。必须要经过哪些步骤?
我的做法是先用IoRegisterPlugPlayNotification来判断HID设备的插入,然后在回调函数中IoGetDeviceObjectPointer取得设备对象,再向他发出IOCTL_HID_GET_COLLECTION_INFORMATION请求取得PID、VID来判断是否是自己需要访问的设备,再向他发送IOCTL_HID_SET_FEATURE请求时不能成功,不知是否有遗漏之处,请大虾指点,最好给出访问HID设备或如何使用IOCTL_HID_SET_FEATURE的代码片段。 |
|
沙发#
发布于:2005-01-28 17:13
下面是我写的代码片段:
NTSTATUS CallHidIoctl( IN PDEVICE_OBJECT HidDevice, IN ULONG IoControlCode, OUT PVOID Output, IN ULONG OutputLen, IN PVOID Input, IN ULONG InputLen ) { IO_STATUS_BLOCK IoStatus; KEVENT event; KeInitializeEvent(&event, NotificationEvent, FALSE); PIRP Irp = IoBuildDeviceIoControlRequest( IoControlCode, HidDevice, Input, InputLen, Output, OutputLen, FALSE, &event, &IoStatus ); BYTE tmp[6]; DWORD tmplen = IoGetNextIrpStackLocation(Irp)->Parameters.DeviceIoControl.InputBufferLength; tmp[0] = ((BYTE*)Irp->AssociatedIrp.SystemBuffer)[0]; tmp[1] = ((BYTE*)Irp->AssociatedIrp.SystemBuffer)[1]; tmp[2] = ((BYTE*)Irp->AssociatedIrp.SystemBuffer)[2]; tmp[3] = ((BYTE*)Irp->AssociatedIrp.SystemBuffer)[3]; tmp[4] = ((BYTE*)Irp->AssociatedIrp.SystemBuffer)[4]; tmp[5] = ((BYTE*)Irp->AssociatedIrp.SystemBuffer)[5]; NTSTATUS status = IoCallDriver( HidDevice, Irp); if (status == STATUS_PENDING) { status = KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); } else { IoStatus.Status = status; } status = IoStatus.Status; return status; } NTSTATUS HidCallbackRoutine(IN PVOID NotificationStructure, IN PVOID Context) { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_INTERFACE_CHANGE_NOTIFICATION pdicn = (PDEVICE_INTERFACE_CHANGE_NOTIFICATION)NotificationStructure; PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Context; PDEVICE_OBJECT fdo = DriverObject->DeviceObject; PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension; PSMARTCARD_EXTENSION psx = &pdx->SmartcardExtension; KIRQL Irql; if(IsEqualGUID(pdicn->Event, GUID_DEVICE_INTERFACE_ARRIVAL)) { if(pdx->HidObjContext.DeviceObject) { return STATUS_SUCCESS; } PFILE_OBJECT HidFileObject; PDEVICE_OBJECT HidDevice; HID_COLLECTION_INFORMATION HidCi; PIRP pIrp; PIO_STACK_LOCATION pStackLocation; KEVENT Event; IO_STATUS_BLOCK IoStatusBlock; ntStatus = IoGetDeviceObjectPointer(pdicn->SymbolicLinkName, FILE_ALL_ACCESS, &HidFileObject, &HidDevice); if(!NT_SUCCESS(ntStatus)) { return STATUS_SUCCESS; } ObDereferenceObject(HidFileObject); ntStatus = ObReferenceObjectByPointer(HidDevice, FILE_ALL_ACCESS, NULL, KernelMode); /* KeInitializeEvent(&Event, NotificationEvent, FALSE); pIrp = IoBuildDeviceIoControlRequest( 0, HidDevice, NULL, 0, NULL, 0, FALSE, &Event, &IoStatusBlock ); if(pIrp == NULL) { return STATUS_SUCCESS; } pStackLocation = IoGetNextIrpStackLocation(pIrp); pStackLocation->MajorFunction = IRP_MJ_CREATE; pStackLocation->Parameters.Create.SecurityContext = NULL; pStackLocation->Parameters.Create.Options = 0; pStackLocation->Parameters.Create.FileAttributes = 0; pStackLocation->Parameters.Create.ShareAccess = 0; pStackLocation->Parameters.Create.EaLength = 0; ntStatus = IoCallDriver(HidDevice, pIrp); if(ntStatus == STATUS_PENDING) { KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); ntStatus = IoStatusBlock.Status; } if(!NT_SUCCESS(ntStatus)) { return STATUS_SUCCESS; } */ ntStatus = CallHidIoctl(HidDevice, IOCTL_HID_GET_COLLECTION_INFORMATION, &HidCi, sizeof(HidCi)); if(!NT_SUCCESS(ntStatus)) { return STATUS_SUCCESS; } if((HidCi.VendorID == 0x04B4) && (HidCi.ProductID == 0xA112)) { BYTE *CmdBuffer; int CmdLen; int i; CmdBuffer = (BYTE*)ExAllocatePool(NonPagedPool, 256); if(CmdBuffer == NULL) { return STATUS_SUCCESS; } RtlZeroMemory(CmdBuffer, 256); CmdBuffer[1] = 0x21; CmdBuffer[2] = 0xA2; CmdBuffer[3] = 0x00; CmdBuffer[4] = 0x00; for(i=1; i<=3; ++i) { CmdBuffer[4] ^= CmdBuffer; } //下面的这一条语句运行后会瘫痪 ntStatus = CallHidIoctl(HidDevice, IOCTL_HID_SET_FEATURE, NULL, 0, CmdBuffer, 0x41); if(!NT_SUCCESS(ntStatus)) { ExFreePool(CmdBuffer); return STATUS_SUCCESS; } RtlZeroMemory(CmdBuffer, 256); ntStatus = CallHidIoctl(HidDevice, IOCTL_HID_GET_FEATURE, CmdBuffer, 0x41); if(!NT_SUCCESS(ntStatus)) { ExFreePool(CmdBuffer); return STATUS_SUCCESS; } if(CmdBuffer[1] != 0x12) { ExFreePool(CmdBuffer); return STATUS_SUCCESS; } CmdLen = 0; for(i=1; i<CmdBuffer[3]+5; ++i) { CmdLen ^= CmdBuffer; } if(CmdLen != 0) { ExFreePool(CmdBuffer); return STATUS_SUCCESS; } if(CmdBuffer[4] != 0x90) { ExFreePool(CmdBuffer); return STATUS_SUCCESS; } ExFreePool(CmdBuffer); pdx->HidObjContext.DeviceObject = HidDevice; pdx->HidObjContext.SymbolicLinkName.Length = pdicn->SymbolicLinkName->Length; pdx->HidObjContext.SymbolicLinkName.MaximumLength = pdicn->SymbolicLinkName->MaximumLength; pdx->HidObjContext.SymbolicLinkName.Buffer = (PWSTR)ExAllocatePool( PagedPool, pdicn->SymbolicLinkName->Length + sizeof(WCHAR) ); RtlCopyUnicodeString(&pdx->HidObjContext.SymbolicLinkName, pdicn->SymbolicLinkName); KeAcquireSpinLock(&psx->OsData->SpinLock, &Irql); psx->ReaderCapabilities.CurrentState = SCARD_PRESENT; psx->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; psx->CardCapabilities.ATR.Length = 0; KeReleaseSpinLock(&psx->OsData->SpinLock, Irql); HidCompleteTracking(psx); } } else if(IsEqualGUID(pdicn->Event, GUID_DEVICE_INTERFACE_REMOVAL)) { if(!pdx->HidObjContext.DeviceObject) { return STATUS_SUCCESS; } if(RtlCompareUnicodeString(pdicn->SymbolicLinkName, &pdx->HidObjContext.SymbolicLinkName, FALSE)) { return STATUS_SUCCESS; } KeAcquireSpinLock(&psx->OsData->SpinLock, &Irql); psx->ReaderCapabilities.CurrentState = SCARD_ABSENT; psx->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; psx->CardCapabilities.ATR.Length = 0; KeReleaseSpinLock(&psx->OsData->SpinLock, Irql); HidCompleteTracking(psx); if(pdx->HidObjContext.SymbolicLinkName.Buffer != NULL) { RtlFreeUnicodeString(&pdx->HidObjContext.SymbolicLinkName); pdx->HidObjContext.SymbolicLinkName.Buffer = NULL; } ObDereferenceObject(pdx->HidObjContext.DeviceObject); pdx->HidObjContext.DeviceObject = NULL; } return ntStatus; } |
|