Поделиться через


Расширенные команды поставщика

Приложение может отправить произвольную команду на устройство с помощью метода IWiaItemExtras::Escape, который описан в документации по Microsoft Windows SDK. Вызвав QueryInterface для корневого элемента, можно получить указатель на интерфейс IWiaItemExtras . Затем приложение может создать команду PTP, используя любой код операции и параметры, и отправить эту команду на устройство. Приложение также может отправлять данные на устройство или получать данные с устройства.

Устройство сообщает приложению о результате операции при возврате метода IWiaItemExtras::Escape , заполняя код отклика и параметры ответа в PTP_VENDOR_DATA_OUT структуре. Элементы SessionId и TransactionId структуры PTP_VENDOR_DATA_IN игнорируются. Драйвер предоставляет правильные значения для них.

Для определяемых поставщиком команд, отличных от ESCAPE_PTP_CLEAR_STALLS, необходимо объединить специальный флаг ESCAPE_PTP_VENDOR_COMMAND (с помощью оператора OR) с командой, используемой в методе IWiaItemExtras::Escape . Если определяемая поставщиком команда создает или удаляет объект на устройстве с помощью описанных ниже флагов, драйвер добавляет или удаляет объект из его внутренних структур и создает событие WIA. Все остальные стандартные команды должны выполняться через соответствующий интерфейс WIA.

Первый параметр для IWiaItemExtras::Escape — это сочетание одного или нескольких следующих флагов:

Escape-код Значение
ESCAPE_PTP_ADD_OBJ_CMD Добавляется объект , а дескриптор объекта находится в одном из параметров команды.
ESCAPE_PTP_REM_OBJ_CMD Объект удаляется, а дескриптор объекта находится в одном из параметров команды.
ESCAPE_PTP_ADD_OBJ_RESP Добавляется объект , а дескриптор объекта находится в одном из параметров ответа.
ESCAPE_PTP_REM_OBJ_RESP Объект удаляется, а дескриптор объекта находится в одном из параметров ответа.
ESCAPE_PTP_ADDREM_PARM1 Дескриптор добавленного или удаленного объекта находится в первом параметре команды или ответа.
ESCAPE_PTP_ADDREM_PARM2 Дескриптор добавленного или удаленного объекта находится во втором параметре команды или ответа.
ESCAPE_PTP_ADDREM_PARM3 Дескриптор добавленного или удаленного объекта находится в третьем параметре команды или ответа.
ESCAPE_PTP_ADDREM_PARM4 Дескриптор добавленного или удаленного объекта находится в четвертом параметре команды или ответа.
ESCAPE_PTP_ADDREM_PARM5 Дескриптор добавленного или удаленного объекта находится в пятом параметре команды или ответа.
ESCAPE_PTP_CLEAR_STALLS Очистите все ошибки, вызванные расширенной командой поставщика. Этот флаг нельзя использовать в сочетании с другими флагами. Дополнительные сведения об этом флаге см. в примечании к этой таблице.
ESCAPE_PTP_VENDOR_COMMAND Команда является расширенной командой поставщика.

Когда приложение вызывает IWiaItemExtras::Escape с флагом ESCAPE_PTP_CLEAR_STALL в качестве первого аргумента этого метода, драйвер отправляет запрос PTP Get Device Status , чтобы определить, находятся ли какие-либо конечные точки в состоянии STALL. Если команда Получить состояние устройства завершается успешно, драйвер выдает IOCTL_RESET_PIPE код управления USB для каждой такой конечной точки. Если команда Получить состояние устройства завершается сбоем, драйвер отправляет запрос на сброс устройства PTP. Получение состояния устройства и сброс устройства описаны в стандарте PIMA 15740:2000, первом выпуске и редакции 1.0 определения usb-устройства захвата изображений (USB SICDD).

В следующем примере кода показано, как использовать расширенный командный интерфейс поставщика. Убедитесь, что код содержит заголовок ptpusd.h , так как он содержит определения escape-кодов и других констант, а также структуры PTP_VENDOR_DATA_IN и PTP_VENDOR_DATA_OUT . Интерфейс IWiaItemExtras получается с помощью вызова QueryInterface корневого элемента. Указатель на этот корневой элемент pIWiaRootItem можно получить, например, путем вызова IWiaDevMgr::SelectDeviceDlg (описано в документации по Microsoft Windows SDK).

//
// Test IWiaItemExtras::Escape method
//
HRESULT hr = S_OK;
IWiaItemExtras *pIWiaItemExtras = NULL;

hr = pIWiaRootItem->QueryInterface(IID_IWiaItemExtras,
                                   (VOID **) &pIWiaItemExtras);
if (FAILED(hr)) {
    MessageBox("QueryInterface for IWiaItemExtras failed");
    return;
}

PTP_VENDOR_DATA_IN *pDataIn = NULL;
PTP_VENDOR_DATA_OUT *pDataOut = NULL;
DWORD dwDataInSize = SIZEOF_REQUIRED_VENDOR_DATA_IN;
DWORD dwDataOutSize = SIZEOF_REQUIRED_VENDOR_DATA_OUT + 0x1000;
DWORD dwActualDataOutSize = 0;

pDataIn = (PTP_VENDOR_DATA_IN *) CoTaskMemAlloc(dwDataInSize);
if (!pDataIn) {
    MessageBox("CoTaskMemAlloc failed");
    return;
}

pDataOut = (PTP_VENDOR_DATA_OUT *) CoTaskMemAlloc(dwDataOutSize);
if (!pDataOut) {
 CoTaskMemFree(pDataIn);
    MessageBox("CoTaskMemAlloc failed");
    return;
}
ZeroMemory(pDataIn, dwDataInSize);
ZeroMemory(pDataOut, dwDataOutSize);

pDataIn->OpCode = 0x1001;
pDataIn->SessionId = 0;     // The driver will fill this in.
pDataIn->TransactionId = 0; // The driver will fill this in.
pDataIn->NumParams = 0;

//
// pDataIn->NextPhase informs the PTP driver whether to 
// read data from the device (as shown), or
// write data to the device (use PTP_NEXTPHASE_WRITE_DATA),
// to neither read nor write data (use PTP_NEXTPHASE_NO_DATA).
//
pDataIn->NextPhase = PTP_NEXTPHASE_READ_DATA;

hr = pIWiaItemExtras->Escape(ESCAPE_PTP_VENDOR_COMMAND,
                             (BYTE *) pDataIn, dwDataInSize,
                             (BYTE *) pDataOut, dwDataOutSize,
                             &dwActualDataOutSize);

if (FAILED(hr)) {
    MessageBox("Escape failed");
    return;
}

//
// Data returned from device is located at pDataOut->VendorReadData.
//