供应商扩展的命令

应用程序可以通过 IWiaItemExtras::Escape 方法将任意命令发送到设备,如Microsoft Windows SDK文档中所述。 通过在根项上调用 QueryInterface ,可以检索指向 IWiaItemExtras 接口的 指针。 然后,应用程序可以使用任何操作码和参数构造 PTP 命令,并将此命令发送到设备。 应用程序还可以向设备发送数据或从设备接收数据。

IWiaItemExtras::Escape 方法返回时,设备会通知应用程序操作的结果,并在 PTP_VENDOR_DATA_OUT 结构中填写响应代码和响应参数。 忽略 PTP_VENDOR_DATA_IN 结构的 SessionIdTransactionId 成员。 驱动程序为这些提供正确的值。

对于除 ESCAPE_PTP_CLEAR_STALLS 之外的供应商定义的命令,必须使用 OR 运算符) 与 IWiaItemExtras::Escape 方法中使用的命令 (将特殊标志ESCAPE_PTP_VENDOR_COMMAND合并。 如果供应商定义的命令使用以下描述的标志在设备上创建或删除对象,驱动程序会在其内部结构中添加或删除对象,并生成 WIA 事件。 所有其他标准命令应通过相应的 WIA 接口发出。

IWiaItemExtras::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 命令是供应商扩展的命令。

当应用程序使用 ESCAPE_PTP_CLEAR_STALL 标志作为此方法的第一个参数调用 IWiaItemExtras::Escape 时,驱动程序会发出 PTP 获取设备状态 请求,以确定是否有任何终结点处于 STALL 条件。 如果 “获取设备状态” 命令成功,驱动程序会为每个此类终结点发出 IOCTL_RESET_PIPE USB 控制代码。 如果 “获取设备状态” 命令失败,驱动程序会发出 PTP 设备重置 请求。 USB SICDD) 的 USB 静止图像捕获设备定义 (PIMA 15740:2000 标准版、第一版和修订版 1.0 中介绍了获取设备状态和设备 重置

以下示例代码演示如何使用供应商扩展的命令接口。 请确保代码包含 ptpusd.h 标头,因为它包含转义代码和其他常量的定义,以及 PTP_VENDOR_DATA_INPTP_VENDOR_DATA_OUT 结构。 IWiaItemExtras 接口是在根项上使用对 QueryInterface 的调用获取的。 例如,可以通过调用 IWiaDevMgr::SelectDeviceDlg (Microsoft Windows SDK文档) 中所述,获取指向此根项 pIWiaRootItem 的指针。

//
// 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.
//