Команда DeviceIoControl for SCSI INQUIRY возвращает ошибку 50

Я пытаюсь получить доступ к USB-сканеру с помощью команд IOCTL. Это на 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 : %s\r\n", GetLastError(), errortext);
LocalFree(errortext);
}
else
{
wprintf(L"DeviceIoControl(IOCTL_SCSI_PASS_THROUGH-INQUIRY) succeeded\r\n");
for (int i=0; i<dwReturnedBytes; i++)
{
wprintf(L"%02x ", sptsd.data[i]);
}

wprintf(L"\r\nEnd of returned data\r\n");
}

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 : %s\r\n", GetLastError(), errortext);
LocalFree(errortext);
}
else
{
wprintf(L"DeviceIoControl(IOCTL_GET_DEVICE_DESCRIPTOR) succeeded\r\n");
wprintf(L"VendorId = %x, ProductId = %x, Version = %x\r\n", dd.usVendorId, dd.usProductId, dd.usBcdDevice);
wprintf(L"End of returned data\r\n");
}

CloseHandle(h);
}

return 0;
}

Я пробовал как 32-разрядную, так и 64-разрядную версии Windows 7, но результат одинаков для обеих (ошибка 50: запрос не поддерживается). Интересно, что второй вызов DeviceIoControl работает и возвращает VID / PID устройства вместе с версией прошивки.

Исходя из сообщения об ошибке, я думаю, что этот IOCTL не поддерживается. Однако я изучил его и обнаружил, что этот код IOCTL является обязательным для всех устройств, поэтому, должно быть, я что-то не так делаю. Как изменить этот код, чтобы команда INQUIRY была успешной?

0

Решение

В соответствии с 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 отправить команду ЗАПРОС и ReadFile читать ответ. Тем не менее, мне кажется, что есть еще одна проблема, которую я не понимаю: устройству требуется дополнительный байт после 6 байтов команды INQUIRY для отправки ответа. В противном случае ReadFile вернет только один байт (0x3). Я обновлю этот ответ снова, если выясню, что здесь происходит.

0

Другие решения


По вопросам рекламы [email protected]