我试图通过IOCTL命令访问USB扫描器。 这是在Windows 7上。我之前没有处理IOCTL编码,所以我首先根据我能find的快速search尝试下面的代码片段。
#include "stdafx.h" #include <stddef.h> #include <Windows.h> #include <ntddscsi.h> #include <usbscan.h> typedef struct { SCSI_PASS_THROUGH spt; BYTE sense[18]; BYTE data[36]; } SPTSD; LPTSTR ErrorMessage(DWORD error) { LPTSTR errorText = NULL; FormatMessage( FORMAT_MESSAGE_FROM_SYstem |FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_IGnorE_INSERTS,NULL,error,MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPTSTR)&errorText,NULL); return errorText; } int _tmain(int argc,_TCHAR* argv[]) { HANDLE h = CreateFile(L"\\.\Usbscan0",GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,OPEN_EXISTING,FILE_ATTRIBUTE_norMAL,NULL); if (INVALID_HANDLE_VALUE != h) { SPTSD sptsd={0}; sptsd.spt.Length = sizeof (sptsd.spt); sptsd.spt.SenseInfoLength = sizeof(sptsd.sense); sptsd.spt.DataTransferLength = sizeof(sptsd.data); sptsd.spt.SenseInfoOffset = offsetof (SPTSD,sense); sptsd.spt.DataBufferOffset = offsetof (SPTSD,data); sptsd.spt.TimeOutValue = 30; sptsd.spt.DataIn = SCSI_IOCTL_DATA_IN; sptsd.spt.CdbLength = 6; sptsd.spt.Cdb[0] = 0x12; // SCSI INQUIRY command sptsd.spt.Cdb[1] = 0; sptsd.spt.Cdb[2] = 0; sptsd.spt.Cdb[3] = 0; sptsd.spt.Cdb[4] = sizeof(sptsd.data); sptsd.spt.Cdb[5] = 0; DWORD dwReturnedBytes; BOOL b; b = DeviceIoControl(h,IOCTL_SCSI_PASS_THROUGH,&sptsd,sizeof(sptsd),&dwReturnedBytes,NULL); if (b == 0) { LPTSTR errortext = ErrorMessage(GetLastError()); wprintf(L"DeviceIoControl(IOCTL_SCSI_PASS_THROUGH-INQUIRY) Failed with error %d : %srn",GetLastError(),errortext); LocalFree(errortext); } else { wprintf(L"DeviceIoControl(IOCTL_SCSI_PASS_THROUGH-INQUIRY) succeededrn"); for (int i=0; i<dwReturnedBytes; i++) { wprintf(L"%02x ",sptsd.data[i]); } wprintf(L"rnEnd of returned datarn"); } DEVICE_DESCRIPTOR dd; b = DeviceIoControl(h,IOCTL_GET_DEVICE_DESCRIPTOR,&dd,sizeof(dd),NULL); if (b == 0) { LPTSTR errortext = ErrorMessage(GetLastError()); wprintf(L"DeviceIoControl(IOCTL_GET_DEVICE_DESCRIPTOR) Failed with error %d : %srn",errortext); LocalFree(errortext); } else { wprintf(L"DeviceIoControl(IOCTL_GET_DEVICE_DESCRIPTOR) succeededrn"); wprintf(L"vendorId = %x,ProductId = %x,Version = %xrn",dd.usvendorId,dd.usProductId,dd.usBcdDevice); wprintf(L"End of returned datarn"); } CloseHandle(h); } return 0; }
我尝试了Windows 7的32位和64位版本,但结果是两者相同(错误50:请求不受支持)。 有趣的是,第二个DeviceIoControl调用工作并返回设备的VID / PID以及固件版本。
根据错误信息,我会认为这个IOCTL不被支持。 然而,我研究了它,发现这个IOCTL代码对所有设备都是强制性的,所以肯定有一些我做错了。 如何修改这个代码以使INQUIRY命令成功?
如何擦除硬盘驱动器
如何使用Application Verifier来查找内存泄漏
定时器和信号中的问题
什么是USB HID col参数
创build可通过在背景区域中的任意位置拖动来移动的非矩形窗体
Windows:直接读取另一个进程的内存
恶魔不加载图像与Linux版本
什么导致这种内存泄漏?
根据http://msdn.microsoft.com/en-us/library/ff548569%28v=vs.85%29.aspx ,这些IOCTL代码被USB总线的内核模式静态图像驱动程序识别。
IOCTL_CANCEL_IO
IOCTL_GET_CHANNEL_ALIGN_RQST
IOCTL_GET_DEVICE_DESCRIPTOR
IOCTL_GET_PIPE_CONfigURATION
IOCTL_GET_USB_DESCRIPTOR
IOCTL_GET_VERSION
IOCTL_READ_REGISTERS
IOCTL_RESET_PIPE
IOCTL_SEND_USB_REQUEST
IOCTL_SET_TIMEOUT
IOCTL_WAIT_ON_DEVICE_EVENT IOCTL_WRITE_REGISTERS
我的理解是,任何其他IOCTL代码应通过IOCTL_SEND_USB_REQUEST控制代码发送。 这就解释了为什么试图使用上面的代码发送一个INQURY命令不起作用。
编辑:这只是使用WriteFile发送INQUIRY命令和ReadFile读取响应的问题。 但是,似乎还有一个额外的问题,我不明白:设备需要一个额外的字节在6个字节的INQUIRY命令发送响应。 否则,ReadFile将只返回一个字节(0x3)。 我会再次更新这个答复,如果我弄清楚这里发生了什么。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。