DeviceIoControl for SCSI查询命令返回错误50
DeviceIoControl for SCSI INQUIRY command returns error 50
我试图通过IOCTL命令访问USB扫描仪。这是在Windows 7上。我以前没有处理过IOCTL编码,所以我首先尝试了下面的代码片段,基于我可以通过快速搜索找到的内容。
#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,
0,
NULL);
return errorText;
}
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE h = CreateFile(L"\\.\Usbscan0", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, 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), &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), &dd, sizeof(dd), &dwReturnedBytes, NULL);
if (b == 0)
{
LPTSTR errortext = ErrorMessage(GetLastError());
wprintf(L"DeviceIoControl(IOCTL_GET_DEVICE_DESCRIPTOR) failed with error %d : %srn", GetLastError(), 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;
}
我尝试了32位和64位版本的Windows 7,但两者的结果都是相同的(错误50:不支持请求。)有趣的是,第二个DeviceIoControl调用工作并返回设备的VID/PID,以及固件版本。
根据错误信息,我认为这个IOCTL是不支持的。然而,我调查了一下,发现这个IOCTL代码对所有设备都是强制性的,所以一定是我做错了什么。如何修改此代码以使INQUIRY命令成功执行?
根据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控制代码发送。这就解释了为什么使用上面的代码发送查询命令不能工作。
编辑:这是一个简单的问题,使用WriteFile发送查询命令和ReadFile读取响应。然而,似乎还有一个我不理解的额外问题:设备需要在INQUIRY命令的6字节之后额外的字节来发送响应。否则,ReadFile将只返回单个字节(0x3)。如果我弄清楚这里发生了什么,我会再次更新此回复。相关文章:
- (C++)分析树以计算返回错误值的简单算术表达式
- glad 导致 glfwSwapBuffers 返回错误消息
- 我的模板类方法返回错误类型?
- 共享内存:MapViewOfFile 返回错误 5
- 使用 std::forward_list 返回错误的队列实现
- FFMPEG:sws_scale返回错误:切片参数 0, 2160 无效
- __int64 CString 返回错误的值 - C++ MFC
- C++ OpenGL 中,绘制形状返回错误
- Python os.system() 返回错误值
- 函数从指针 c++ 中获取错误的值并返回错误的答案
- LibClang clang_getArgType() 返回错误的类型
- 除法函数返回错误的值
- 当命令失败时,gzip 会在 C++ 中返回错误代码吗?
- 矩阵逆变器返回错误的反转
- openCL-创建子缓冲区返回错误代码13
- Qt SQL LIKE语句返回错误
- GetLastError()从FtpPutFile()返回错误6
- PfCreateInterface返回错误120(未实现)
- 为什么 Pa_GetStreamTime() 返回错误?
- G++ 在尝试使用 G++ 使用 openCV 进行编译后返回错误