如何 避免 writepipe/readpipe read write阻塞 winusb

下次自动登录
现在的位置:
& 综合 & 正文
WinUSBeasy
// Include Windows headers
#include &windows.h&
#include &stdio.h&
#include &tchar.h&
#include &strsafe.h&
// Include WinUSB headers
#include &winusb.h&
#include &Usb100.h&
#include &Setupapi.h&
// Linked libraries
#pragma comment (lib , "setupapi.lib" )
#pragma comment (lib , "winusb.lib" )
//为在 INF 文件中提供的用于安装 Winusb.sys 的设备接口标识符声明一个常量。
// Constant for {D696BFEB-A04-86D}
//static const GUID OSR_DEVICE_INTERFACE =
//{ 0xd696bfeb, 0xd, { 0x8a, 0x04, 0x86, 0xd0, 0x10, 0x71, 0xc5, 0x12 } };
//ClassGuid=
{78A1C341--B88D-00C04FAD5171}
//DeviceInterfaceGUIDs,0x10000,"{be16-4a9e-b79bac}"
static const GUID OSR_DEVICE_INTERFACE =
0xbx3e16, 0x4a9e, { 0x97, 0x82, 0x55, 0x24, 0xa4, 0xb7, 0x9b, 0xac } };
BOOL GetDeviceHandle (GUID guidDeviceInterface, PHANDLE hDeviceHandle)
if (guidDeviceInterface==GUID_NULL)
return FALSE;
BOOL bResult = TRUE;
HDEVINFO hDeviceI
SP_DEVINFO_DATA DeviceInfoD
SP_DEVICE_INTERFACE_DATA deviceInterfaceD
PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = NULL;
ULONG requiredLength=0;
LPTSTR lpDevicePath = NULL;
DWORD index = 0;
BOOL SetupRet=FALSE;
// Get information about all the installed devices for the specified
// device interface class.
hDeviceInfo = SetupDiGetClassDevs(
&guidDeviceInterface,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hDeviceInfo == INVALID_HANDLE_VALUE)
printf("Error SetupDiGetClassDevs: %d.\n", GetLastError());
//Enumerate all the device interfaces in the device information set.
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
index = 0;
SetupRet=SetupDiEnumDeviceInfo(hDeviceInfo, index, &DeviceInfoData);
for (; SetupRet!=FALSE ; SetupRet=SetupDiEnumDeviceInfo(hDeviceInfo, ++index, &DeviceInfoData))
//Reset for this iteration
if (lpDevicePath)
LocalFree(lpDevicePath);
if (pInterfaceDetailData)
LocalFree(pInterfaceDetailData);
deviceInterfaceData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);
//Get information about the device interface.
bResult = SetupDiEnumDeviceInterfaces(
hDeviceInfo,
&DeviceInfoData,
&guidDeviceInterface,
&deviceInterfaceData);
// Check if last item
if (GetLastError () == ERROR_NO_MORE_ITEMS)
//Check for some other error
if (!bResult)
printf("Error SetupDiEnumDeviceInterfaces: %d.\n", GetLastError());
//Interface data is returned in SP_DEVICE_INTERFACE_DETAIL_DATA
//which we need to allocate, so we have to call this function twice.
//First to get the size so that we know how much to allocate
//Second, the actual call with the allocated buffer
bResult = SetupDiGetDeviceInterfaceDetail(
hDeviceInfo,
&deviceInterfaceData,
&requiredLength,
//Check for some other error
if (!bResult)
if ((ERROR_INSUFFICIENT_BUFFER==GetLastError()) && (requiredLength&0))
//we got the size, allocate buffer
pInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)LocalAlloc(LPTR, requiredLength);
if (!pInterfaceDetailData)
printf("Error allocating memory for the device detail buffer.\n");
printf("Error SetupDiEnumDeviceInterfaces: %d.\n", GetLastError());
//get the interface detailed data
pInterfaceDetailData-&cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
//Now call it with the correct size and allocated buffer
bResult = SetupDiGetDeviceInterfaceDetail(
hDeviceInfo,
&deviceInterfaceData,
pInterfaceDetailData,
requiredLength,
&DeviceInfoData);
//Check for some other error
if (!bResult)
printf("Error SetupDiGetDeviceInterfaceDetail: %d.\n", GetLastError());
//copy device path
size_t nLength = wcslen (pInterfaceDetailData-&DevicePath) + 1;
lpDevicePath = (TCHAR *) LocalAlloc (LPTR, nLength * sizeof(TCHAR));
StringCchCopy(lpDevicePath, nLength, pInterfaceDetailData-&DevicePath);
lpDevicePath[nLength-1] = 0;
printf("Device path:
%s\n", lpDevicePath);
if (!lpDevicePath)
printf("Error %d.", GetLastError());
//Open the device
*hDeviceHandle = CreateFile (
lpDevicePath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
if (*hDeviceHandle == INVALID_HANDLE_VALUE)
printf("Error %d.", GetLastError());
LocalFree(lpDevicePath);
LocalFree(pInterfaceDetailData);
bResult = SetupDiDestroyDeviceInfoList(hDeviceInfo);
BOOL GetWinUSBHandle(HANDLE hDeviceHandle, PWINUSB_INTERFACE_HANDLE phWinUSBHandle)
if (hDeviceHandle == INVALID_HANDLE_VALUE)
return FALSE;
BOOL bResult = WinUsb_Initialize(hDeviceHandle, phWinUSBHandle);
if(!bResult)
printf("WinUsb_Initialize Error %d.", GetLastError());
return FALSE;
//以下示例获取由 WinUSB 接口句柄指定的设备的速度。
BOOL GetUSBDeviceSpeed(WINUSB_INTERFACE_HANDLE hDeviceHandle, UCHAR* pDeviceSpeed)
if (!pDeviceSpeed || hDeviceHandle==INVALID_HANDLE_VALUE)
return FALSE;
BOOL bResult = TRUE;
ULONG length = sizeof(UCHAR);
bResult = WinUsb_QueryDeviceInformation(hDeviceHandle, DEVICE_SPEED, &length, pDeviceSpeed);
if(!bResult)
printf("Error getting device speed: %d.\n", GetLastError());
if(*pDeviceSpeed == LowSpeed)
printf("Device speed: %d (Low speed).\n", *pDeviceSpeed);
if(*pDeviceSpeed == FullSpeed)
printf("Device speed: %d (Full speed).\n", *pDeviceSpeed);
if(*pDeviceSpeed == HighSpeed)
printf("Device speed: %d (High speed).\n", *pDeviceSpeed);
//以下示例代码查询由 WinUSB 接口句柄指定的 USB 设备的各种描述符。
//此示例函数检索支持的终结点类型及其管道标识符。
//该示例存储所有三个 PipeId 值以供日后使用。
struct PIPE_ID
PipeOutId;
BOOL QueryDeviceEndpoints (WINUSB_INTERFACE_HANDLE hDeviceHandle, PIPE_ID* pipeid)
if (hDeviceHandle==INVALID_HANDLE_VALUE)
return FALSE;
BOOL bResult = TRUE;
USB_INTERFACE_DESCRIPTOR InterfaceD
ZeroMemory(&InterfaceDescriptor, sizeof(USB_INTERFACE_DESCRIPTOR));
WINUSB_PIPE_INFORMATION
ZeroMemory(&Pipe, sizeof(WINUSB_PIPE_INFORMATION));
bResult = WinUsb_QueryInterfaceSettings(hDeviceHandle, 0, &InterfaceDescriptor);
if (bResult)
for (int index = 0; index & InterfaceDescriptor.bNumE index++)
bResult = WinUsb_QueryPipe(hDeviceHandle, 0, index, &Pipe);
if (bResult)
if (Pipe.PipeType == UsbdPipeTypeControl)
printf("Endpoint index: %d Pipe type: Control Pipe ID: %d.\n", index, Pipe.PipeType, Pipe.PipeId);
if (Pipe.PipeType == UsbdPipeTypeIsochronous)
printf("Endpoint index: %d Pipe type: Isochronous Pipe ID: %d.\n", index, Pipe.PipeType, Pipe.PipeId);
if (Pipe.PipeType == UsbdPipeTypeBulk)
if (USB_ENDPOINT_DIRECTION_IN(Pipe.PipeId))
printf("Endpoint index: %d Pipe type: Bulk Pipe ID: %c.\n", index, Pipe.PipeType, Pipe.PipeId);
pipeid-&PipeInId = Pipe.PipeId;
if (USB_ENDPOINT_DIRECTION_OUT(Pipe.PipeId))
printf("Endpoint index: %d Pipe type: Bulk Pipe ID: %c.\n", index, Pipe.PipeType, Pipe.PipeId);
pipeid-&PipeOutId = Pipe.PipeId;
if (Pipe.PipeType == UsbdPipeTypeInterrupt)
printf("Endpoint index: %d Pipe type: Interrupt Pipe ID: %d.\n", index, Pipe.PipeType, Pipe.PipeId);
//向默认终结点发送控制传输
//接下来,通过向默认终结点发送控制请求来与设备通信。
//除了与接口关联的终结点之外,所有 USB 设备都有一个默认终结点。
//默认终结点的主要目的是为主机提供可用于配置设备的信息。
//不过,设备还可以将默认终结点用于特定于设备的目的。
//例如,OSR USB FX2 设备使用默认终结点控制灯条和七段数字显示。
//-------------------------------------------------------
//使用以下步骤发送控制请求。
//1. 分配一个 1 字节的数据缓冲区,并将数据加载到缓冲区,该缓冲区通过设置适当的位指定应亮起的元素。
//2. 在调用方分配的 WINUSB_SETUP_PACKET 结构中构建一个安装包。如下所示初始化成员以表示请求类型和数据:
//RequestType 成员指定请求方向。它设置为 0,指示主机到设备数据传输。对于设备到主机传输,将 RequestType 设置为 1。
//Request 成员设置为此请求的供应商定义的代码 0xD8。为简便起见将其定义为 SET_BARGRAPH_DISPLAY。
//Length 成员设置为数据缓冲区的大小。
//此请求不需要 Index 和 Value 成员,因此它们设置为零。
//3. 调用 WinUsb_ControlTransfer 以通过传递设备的 WinUSB 接口句柄、安装包和数据缓冲区,将请求传输到默认终结点。
//此函数在 LengthTransferred 参数中接收传输到设备的字节数。
//---------------------------------------------------------
//以下代码示例将控制请求发送到指定的 USB 设备来控制灯条上的灯。
BOOL SendDatatoDefaultEndpoint(WINUSB_INTERFACE_HANDLE hDeviceHandle)
if (hDeviceHandle==INVALID_HANDLE_VALUE)
return FALSE;
BOOL bResult = TRUE;
UCHAR bars = 0;
WINUSB_SETUP_PACKET SetupP
ZeroMemory(&SetupPacket, sizeof(WINUSB_SETUP_PACKET));
ULONG cbSent = 0;
//Set bits to light alternate bars
for (short i = 0; i & 7; i+= 2)
bars += 1 &&
//Create the setup packet
SetupPacket.RequestType = 0;
SetupPacket.Request = 0xD8;
SetupPacket.Value = 0;
SetupPacket.Index = 0;
SetupPacket.Length = sizeof(UCHAR);
bResult = WinUsb_ControlTransfer(hDeviceHandle, SetupPacket, &bars, sizeof(UCHAR), &cbSent, 0);
if(!bResult)
printf("Data sent: %d \nActual data transferred: %d.\n", sizeof(bars), cbSent);
//发送 I/O 请求
//接下来,将数据发送到设备的批量传入和批量传出终结点,这些终结点可分别用于读取请求和写入请求。
//在 OSR USB FX2 设备上,这两个终结点配置为用于环回,
//因此该设备可将数据从批量传入终结点移动到批量传出终结点。
//它不更改数据的值或添加任何新数据。对于环回配置,
//读取请求将读取由最近的写入请求发送的数据。
//WinUSB 提供以下函数用于发送读取请求和写入请求:
//" WinUsb_WritePipe
//" WinUsb_ReadPipe
//发送写入请求
//1. 分配一个缓冲区,并使用希望写入设备的数据填充该缓冲区。
//如果应用没有将 RAW_IO 设置为管道的策略类型,则对缓冲区大小没有限制。
//WinUSB 根据需要将缓冲区拆分为适当大小的区块。如果设置了 RAW_IO,
//则缓冲区的大小受 WinUSB 支持的最大缓冲区大小的限制。
//2. 调用 WinUsb_WritePipe 将缓冲区写入设备。传递设备的
// WinUSB 接口句柄、批量传出管道的管道标识符(如本主题的查询设备以获取 USB 描述符部分所述)
// 和缓冲区。此函数返回在 bytesWritten 参数中实际写入设备的字节数。
// Overlapped 参数设置为 NULL 以请求同步操作。要执行异步写请求,
// 请将Overlapped 设置为指向 OVERLAPPED 结构的指针。
//包含零长度数据的写入请求向下转发到 USB 堆栈。如果传输长度大于最大传输长度,
//WinUSB 会将请求拆分为具有最大传输长度的较小请求,并连续提交它们。
//以下代码示例分配一个字符串,并将其发送到设备的批量传出终结点。
BOOL WriteToBulkEndpoint(WINUSB_INTERFACE_HANDLE hDeviceHandle, UCHAR* pID, ULONG* pcbWritten)
if (hDeviceHandle==INVALID_HANDLE_VALUE || !pID || !pcbWritten)
return FALSE;
BOOL bResult = TRUE;
//UCHAR szBuffer[] = "Hello World";
unsigned char sendData=2; //0,1,2,3
while(a&0 || a&3)
printf("input a number between 0~3, (0:1:D32:D43 all off)\n");
scanf("%d",&a);
getchar();
sendData=a;
//ULONG cbSize = strlen((char *)szBuffer);
ULONG cbSize = sizeof(sendData);
ULONG cbSent = 0;
//bResult = WinUsb_WritePipe(hDeviceHandle, *pID, szBuffer, cbSize, &cbSent, 0);
bResult = WinUsb_WritePipe(hDeviceHandle, *pID, &sendData, cbSize, &cbSent, 0);
if(!bResult)
//printf("Wrote to pipe %d: %s \nActual data transferred: %d.\n", *pID, szBuffer, cbSent);
printf("Wrote to pipe %d: %d \nActual data transferred: %d.\n", *pID, sendData, cbSent);
*pcbWritten = cbS
//发送读取请求
//" 调用 WinUsb_ReadPipe 从设备的批量传入终结点读取数据。
//传递设备的 WinUSB 接口句柄、批量传入终结点的管道标识符和适当大小的空缓冲区。
//当该函数返回时,缓冲区包含从设备读取的数据。读取的字节数返回函数的 bytesRead 参数。
//对于读取请求,缓冲区必须是最大包大小的倍数。
//零长度读请求将立即成功完成,并且不向下发送到堆栈。如果传输长度大于最大传输长度,
//WinUSB 会将请求拆分为具有最大传输长度的较小请求,并连续提交它们。
//如果传输长度不是终结点的 MaxPacketSize 的倍数,WinUSB 会将传输大小增加到 MaxPacketSize 的下一个倍数。
//如果设备返回的数据比请求的多,WinUSB 会保存超过的数据。如果数据从以前的读请求中保留,
//WinUSB 会将其复制到下一个读请求的开头,并根据需要完成请求。
//以下代码示例从设备的批量传入终结点读取数据。
//-----------------------------------------------------
BOOL ReadFromBulkEndpoint(WINUSB_INTERFACE_HANDLE hDeviceHandle, UCHAR* pID, ULONG cbSize)
if (hDeviceHandle==INVALID_HANDLE_VALUE)
return FALSE;
BOOL bResult = TRUE;
UCHAR* szBuffer = (UCHAR*)LocalAlloc(LPTR, sizeof(UCHAR)*cbSize);
ULONG cbRead = 0;
bResult = WinUsb_ReadPipe(hDeviceHandle, *pID, szBuffer, cbSize, &cbRead, 0);
if(!bResult)
printf("Read from pipe %d: %s \nActual data read: %d.\n", *pID, szBuffer, cbRead);
LocalFree(szBuffer);
//释放设备句柄
//在完成对设备的所有必要的调用之后,释放设备的文件句柄和 WinUSB 接口句柄。 为此,调用以下函数:
//" CloseHandle 释放由 CreateFile 创建的句柄,如本演练的创建设备的文件句柄一节中所述。
//" WinUsb_Free 释放由 WinUsb_Initialize 返回的设备的 WinUSB 接口句柄。
enum ERR_TYPE{
GetDeviceHandleErr,
GetWinUSBHandleErr,
GetUSBDeviceSpeedErr,
QueryDeviceEndpointsErr,
SendDatatoDefaultEndpointErr,
WriteToBulkEndpointErr,
ReadFromBulkEndpointErr
void perr(ERR_TYPE errcode)
static char err_message[][30]={
"GetDeviceHandleErr",
"GetWinUSBHandleErr",
"GetUSBDeviceSpeedErr",
"QueryDeviceEndpointsErr",
"SendDatatoDefaultEndpointErr",
"WriteToBulkEndpointErr",
"ReadFromBulkEndpointErr"
if (errcode==NoErr)
printf("no error occur!\n");
printf("error message:%s\n",err_message[errcode]);
printf("GetLastError:%d\n",GetLastError());
//实现主函数
//以下代码示例显示了控制台应用程序的主函数。
int _tmain(int argc, _TCHAR* argv[])
ERR_TYPE errcode=NoE
GUID guidDeviceInterface = OSR_DEVICE_INTERFACE; //in the INF file
BOOL bResult = TRUE;
PIPE_ID PipeID;
HANDLE hDeviceHandle = INVALID_HANDLE_VALUE;
WINUSB_INTERFACE_HANDLE hWinUSBHandle = INVALID_HANDLE_VALUE;
UCHAR DeviceS
ULONG cbSize = 0;
bResult = GetDeviceHandle(guidDeviceInterface, &hDeviceHandle);
if(!bResult)
errcode=GetDeviceHandleE
bResult = GetWinUSBHandle(hDeviceHandle, &hWinUSBHandle);
if(!bResult)
errcode=GetWinUSBHandleE
bResult = GetUSBDeviceSpeed(hWinUSBHandle, &DeviceSpeed);
if(!bResult)
errcode=GetUSBDeviceSpeedE
bResult = QueryDeviceEndpoints(hWinUSBHandle, &PipeID);
if(!bResult)
errcode=QueryDeviceEndpointsE
bResult = SendDatatoDefaultEndpoint(hWinUSBHandle);
if(!bResult)
errcode=SendDatatoDefaultEndpointE
bResult = WriteToBulkEndpoint(hWinUSBHandle, &PipeID.PipeOutId, &cbSize);
if(!bResult)
errcode=WriteToBulkEndpointE
bResult = ReadFromBulkEndpoint(hWinUSBHandle, &PipeID.PipeInId, cbSize);
if(!bResult)
errcode=ReadFromBulkEndpointE
CloseHandle(hDeviceHandle);
WinUsb_Free(hWinUSBHandle);
perr(errcode);
system("PAUSE");
Device path:
Device speed: 1 (Low speed).
Endpoint index: 0 Pipe type: Bulk Pipe ID: ..
Endpoint index: 1 Pipe type: Bulk Pipe ID: ..
Endpoint index: 2 Pipe type: Interrupt Pipe ID: 3.
Device path:
Device speed: 1 (Low speed).
Endpoint index: 0 Pipe type: Bulk Pipe ID: ..
Endpoint index: 1 Pipe type: Bulk Pipe ID: ..
Endpoint index: 2 Pipe type: Interrupt Pipe ID: 3.
Wrote to pipe 1: 0
Actual data transferred: 1.
Read from pipe 130:
Actual data read: 0.
no error occur!
请按任意键继续. . .
&&&&推荐文章:
【上篇】【下篇】2143人阅读
在向管道写数据和读数据时我们经常会用到WinUsb_ReadPipe和WinUsb_WritePipe。
现在我对这两个函数还是不太理解,所以打算自己看英文文档说明,在此记录下。
WinUsb_ReadPipe(这个函数一般处理的是IN包后,USB从机向主机发送过来的数据)
BOOL __stdcall WinUsb_ReadPipe(
_In_&&&&&&&WINUSB_INTERFACE_HANDLE InterfaceHandle,
_In_&&&&&&&UCHAR PipeID,
_Out_&&&&&&PUCHAR Buffer,
_In_&&&&&&&ULONG BufferLength,
_Out_opt_&&PULONG LengthTransferred,
_In_opt_&&&LPOVERLAPPED Overlapped
功能:从指定的管道读数据
第一个参数:InterfaceHandle:和那个端点的那个管道联接。
第二个参数:PipeID,就是管道的地址,第7位表示端点数据方向:0表示OUT(主-从),1表示IN(从-主)。
第三个参数:Buffer,接收读取的数据的缓冲区。
第四个参数:BufferLength,读取数据的最大个数,这个值必须小于或等于Buffer缓冲区中的字节个数。
第五个参数:LengthTransferred&,一个无符号长整型指针,接收实际复制到Buffer缓冲区中的个数。
第六个参数:Overlapped,一般定为一个空指针,NULL。
返回值:操作成功返回TRUE,失败返回FALSE。(GetLastError获取错误返回值)
如果设备返回数据(我理解是INpacket)大于最大的传输长度,WinUSB将分离这个数据成一较小段的,并且连续提交。如果这个传输数据的长度不是最大传输长度的整数倍,WINUSB就会把他增加到最大传输个数的倍数。
USB包的大小不考虑传输请求,如果设备响应了一个对现在的缓冲区来说较大的包,并且读请求符合管道上指针的类型,如果管道指针允许部分读取(ALLOW_PARTIAL_READS,),WINUSB将把剩下的数据放在下次传输的开头,
如果第六个参数为非空,第五个参数设置的值是无意义的。
如果PIPE为空,WinUsb_ReadPipe我们函数不返回直到PIPE中有数据,如果出现错误状况或者超时,函数就返回FALSE,(GetLastError获取错误返回值).
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:29713次
排名:千里之外
原创:29篇
(2)(1)(1)(2)(1)(2)(4)(1)(1)(1)(1)(2)(7)(4)WinUsb_ControlTransfer function (Windows Drivers)
WinUsb_ControlTransfer
WinUsb_ControlTransfer function
The WinUsb_ControlTransfer function transmits control data over a default control endpoint.
BOOL __stdcall WinUsb_ControlTransfer(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
WINUSB_SETUP_PACKET
SetupPacket,
BufferLength,
_Out_opt_ PULONG
LengthTransferred,
LPOVERLAPPED
Overlapped
Parameters
InterfaceHandle [in]
An opaque handle to an interface in the selected configuration.
To specify the recipient of
a control request as the entire device or the first interface, use the handle returned by . For all other interfaces, obtain the handle to the target interface by calling , and then call WinUsb_ControlTransfer by specifying the obtained interface handle.
SetupPacket [in]
The 8-byte setup packet of type .
Buffer [out]
A caller-allocated buffer that contains the data to transfer. The length of this buffer must not exceed 4KB.
BufferLength [in]
The number of bytes to transfer, not including the setup packet. This number must be less than or equal to the size, in bytes, of Buffer.
LengthTransferred [out, optional]
A pointer to a ULONG variable that receives the actual number of transferred bytes. If the application does not expect any data to be transferred during the
data phase (BufferLength is zero),
LengthTransferred can be NULL.
Overlapped [in, optional]
An optional pointer to an
structure, which is used for asynchronous operations. If this parameter is specified, WinUsb_ControlTransfer immediately returns, and the event is signaled when the operation is complete. If Overlapped is not supplied, the WinUsb_ControlTransfer function transfers data synchronously.
Return value
WinUsb_ControlTransfer returns TRUE if the operation succeeds. Otherwise, this routine returns FALSE, and the caller can retrieve the logged error by calling GetLastError.
GetLastError
can return one of the following error codes.
Return codeDescription
ERROR_INVALID_HANDLE
The caller passed NULL in the
InterfaceHandle parameter.
ERROR_NOT_ENOUGH_MEMORY
Indicates that there is insufficient memory to perform the operation.
A control request is always sent by the host to the default endpoint of a USB device but the recipient of the request can be the entire device, an interface, or an endpoint in the selected alternate setting. In the WinUsb_ControlTransfer call, the application must indicate the recipient through two parameters: InterfaceHandle and SetupPacket.
If the recipient of a control request is the entire device, the first interface, or any endpoint in that interface, the application must use the handle returned by . If the recipient is any other interface or its endpoint, then the application must obtain the WinUSB handle that is associated with the target interface by calling , and then call WinUsb_ControlTransfer by specifying the obtained interface handle.
As per Section 9.3 of the official USB specification, the setup token of a control transfer contains information about the request. For a WinUSB application, that setup token is described by using the
structure.
Within the setup token, bmRequestType and wIndex fields are used to indicate the recipient of the request. Those fields correspond to RequestType and Index members of , respectively.
The lowest two bits of RequestType indicate the recipient of the request. The recipient can be the device, an interface, endpoint, or other (for vendor request). Depending on the recipient, the lower byte of Index indicates the device-defined index of the recipient. The value of Index depends on the type of request. For example, for standard control requests, the value is 0, or indicates the interface or endpoint number. For certain types of standard requests, such as a GET_DESCRIPTOR request to obtain a string descriptor, the Index value indicates the Language ID.
If the recipient is the device, the application must set RequestType and Index values.
The lowest two bits of RequestType value must be 0. The lower byte of Index value depends on the type of request. The InterfaceHandle must be the WinUSB handle returned by .
If the recipient of the request is an interface, the application must set the lowest two bits of RequestType to 0x01. The application is not required to set the lower byte of Index for any type of request. For
standard, class, and vendor requests,
Winusb.sys sets the value to the interface number of the target interface. The InterfaceHandle must be associated with the target interface. The application can obtain that handle by calling .
If the recipient is an endpoint, the application must set the lowest two bits of RequestType to 0x02 and lower byte of Index to the endpoint address. In this case, InterfaceHandle is associated with the interface that contains the endpoint. The application can obtain that handle by calling .
Requirements
Target platform
Winusb.h (include Winusb.h)
Winusb.lib
Winusb.dll
此页面有帮助吗?
更多反馈?
1500 个剩余字符
我们非常感谢您的反馈。
(C) Microsoft 2017

我要回帖

更多关于 winusb writepipe 的文章

 

随机推荐