📄 wdu_lib.cpp
字号:
Params.pBuf = *ppDeviceInfo;
// second call with correct pBuf and dwBytes
dwStatus = WD_UGetDeviceData(GET_HWD(hDevice), &Params);
if (dwStatus)
{
WDU_PutDeviceInfo(*ppDeviceInfo);
*ppDeviceInfo = NULL;
}
return dwStatus;
}
// Frees device info allocated with WDU_GetDeviceInfo()
void DLLCALLCONV WDU_PutDeviceInfo(WDU_DEVICE *pDeviceInfo)
{
free(pDeviceInfo);
}
DWORD DLLCALLCONV WDU_GetDeviceAddr(WDU_DEVICE_HANDLE hDevice, ULONG *pAddress)
{
DWORD dwStatus;
WD_GET_DEVICE_PROPERTY Params;
BZERO(Params);
if (!hDevice || FindDeviceByCtx((DEVICE_CTX *)hDevice) != WD_STATUS_SUCCESS)
return WD_DEVICE_NOT_FOUND;
Params.h.dwUniqueID = ((DEVICE_CTX *)hDevice)->dwUniqueID;
Params.pBuf = pAddress;
Params.dwProperty = WdDevicePropertyAddress;
Params.dwOptions = WD_DEVICE_USB;
Params.dwBytes = sizeof(*pAddress);
dwStatus = WD_GetDeviceProperty(GET_HWD(hDevice), &Params);
return dwStatus;
}
//
// simplified transfers
//
DWORD DLLCALLCONV WDU_TransferDefaultPipe(WDU_DEVICE_HANDLE hDevice, DWORD fRead,
DWORD dwOptions, PVOID pBuffer, DWORD dwBufferSize, PDWORD pdwBytesTransferred,
PBYTE pSetupPacket, DWORD dwTimeout)
{
return WDU_Transfer(hDevice, 0, fRead,
dwOptions, pBuffer, dwBufferSize, pdwBytesTransferred,
pSetupPacket, dwTimeout);
}
DWORD DLLCALLCONV WDU_TransferBulk(WDU_DEVICE_HANDLE hDevice, DWORD dwPipeNum, DWORD fRead,
DWORD dwOptions, PVOID pBuffer, DWORD dwBufferSize, PDWORD pdwBytesTransferred,
DWORD dwTimeout)
{
return WDU_Transfer(hDevice, dwPipeNum, fRead,
dwOptions, pBuffer, dwBufferSize, pdwBytesTransferred,
NULL, dwTimeout);
}
DWORD DLLCALLCONV WDU_TransferIsoch(WDU_DEVICE_HANDLE hDevice, DWORD dwPipeNum, DWORD fRead,
DWORD dwOptions, PVOID pBuffer, DWORD dwBufferSize, PDWORD pdwBytesTransferred,
DWORD dwTimeout)
{
return WDU_Transfer(hDevice, dwPipeNum, fRead,
dwOptions, pBuffer, dwBufferSize, pdwBytesTransferred,
NULL, dwTimeout);
}
DWORD DLLCALLCONV WDU_TransferInterrupt(WDU_DEVICE_HANDLE hDevice, DWORD dwPipeNum, DWORD fRead,
DWORD dwOptions, PVOID pBuffer, DWORD dwBufferSize, PDWORD pdwBytesTransferred,
DWORD dwTimeout)
{
return WDU_Transfer(hDevice, dwPipeNum, fRead,
dwOptions, pBuffer, dwBufferSize, pdwBytesTransferred,
NULL, dwTimeout);
}
// Private Functions
static DWORD AddDeviceToDevList(DEVICE_CTX *pDeviceCtx)
{
WDU_DEVICE_LIST_ITEM *pDevItem;
DWORD dwStatus;
TRACE("AddDeviceToDevList: device %p, before %p\n", pDeviceCtx, DevList);
dwStatus = OsEventWait(DevList.hEvent, WDU_DEVLIST_TIMEOUT);
if (dwStatus)
{
ERR("AddDeviceToDevList: error waiting for device list event: dwStatus (0x%lx) - %s\n",
dwStatus, Stat2Str(dwStatus));
return dwStatus;
}
pDevItem = (WDU_DEVICE_LIST_ITEM *) calloc(1, sizeof(WDU_DEVICE_LIST_ITEM));
pDevItem->pDeviceCtx = pDeviceCtx;
pDevItem->next = DevList.pHead;
DevList.pHead = pDevItem;
dwStatus = OsEventSignal(DevList.hEvent);
if (dwStatus)
{
ERR("AddDeviceToDevList: error signaling device list event: dwStatus (0x%lx) - %s\n",
dwStatus, Stat2Str(dwStatus));
}
return dwStatus;
}
static DWORD RemoveAllDevicesFromDevList(DRIVER_CTX *pDriverCtx)
{
#if defined(__KERNEL__)
return WD_NOT_IMPLEMENTED;
#else
DEVICE_CTX *pDeviceCtx;
WDU_DEVICE_LIST_ITEM **ppDev = &DevList.pHead;
WDU_DEVICE_LIST_ITEM *pDevTmp;
DWORD dwStatus;
TRACE("RemoveAllDevicesFromDevList: pDriverCtx %p\n", pDriverCtx);
dwStatus = OsEventWait(DevList.hEvent, WDU_DEVLIST_TIMEOUT);
if (dwStatus)
{
ERR("RemoveAllDevicesFromDevList: error waiting for device list event: dwStatus (0x%lx) - %s\n",
dwStatus, Stat2Str(dwStatus));
return dwStatus;
}
while (*ppDev)
{
pDeviceCtx = (*ppDev)->pDeviceCtx;
if (pDeviceCtx->pDriverCtx == pDriverCtx)
{
pDevTmp = *ppDev;
*ppDev = (*ppDev)->next;
WDU_PutDeviceInfo(pDeviceCtx->pDevice);
free(pDeviceCtx);
free(pDevTmp);
}
else
ppDev = &(*ppDev)->next;
}
dwStatus = OsEventSignal(DevList.hEvent);
if (dwStatus)
{
ERR("RemoveAllDevicesFromDevList: error signaling device list event: dwStatus (0x%lx) - %s\n",
dwStatus, Stat2Str(dwStatus));
}
return dwStatus;
#endif
}
static DWORD FindDeviceByUniqueID(DRIVER_CTX *pDriverCtx, DWORD dwUniqueID, DEVICE_CTX **ppDeviceCtx)
{
WDU_DEVICE_LIST_ITEM *iter;
DWORD dwStatus;
BOOL Found = FALSE;
TRACE("FindDeviceByUniqueID: DevList.pHead %p, dwUniqueID 0x%lx\n", DevList.pHead, dwUniqueID);
*ppDeviceCtx = NULL;
dwStatus = OsEventWait(DevList.hEvent, WDU_DEVLIST_TIMEOUT);
if (dwStatus)
{
ERR("FindDeviceByUniqueID: error waiting for device list event: dwStatus (0x%lx) - %s\n",
dwStatus, Stat2Str(dwStatus));
return dwStatus;
}
for (iter = DevList.pHead; iter; iter = iter->next)
{
if (iter->pDeviceCtx->dwUniqueID == dwUniqueID &&
iter->pDeviceCtx->pDriverCtx == pDriverCtx)
{
Found = TRUE;
break;
}
}
dwStatus = OsEventSignal(DevList.hEvent);
if (dwStatus)
{
ERR("FindDeviceByUniqueID: error signaling device list event: dwStatus (0x%lx) - %s\n",
dwStatus, Stat2Str(dwStatus));
return dwStatus;
}
if (Found)
*ppDeviceCtx = iter->pDeviceCtx;
else
dwStatus = WD_DEVICE_NOT_FOUND;
return dwStatus;
}
static DWORD FindDeviceByCtx(DEVICE_CTX *pDeviceCtx)
{
WDU_DEVICE_LIST_ITEM *iter;
DWORD dwStatus;
BOOL Found = FALSE;
dwStatus = OsEventWait(DevList.hEvent, WDU_DEVLIST_TIMEOUT);
if (dwStatus)
{
ERR("FindDeviceByCtx: error waiting for device list event: dwStatus (0x%lx) - %s\n",
dwStatus, Stat2Str(dwStatus));
return dwStatus;
}
for (iter = DevList.pHead; iter; iter = iter->next)
{
if (iter->pDeviceCtx == pDeviceCtx)
{
Found = TRUE;
break;
}
}
dwStatus = OsEventSignal(DevList.hEvent);
if (dwStatus)
{
ERR("FindDeviceByCtx: error signaling device list event: dwStatus (0x%lx) - %s\n",
dwStatus, Stat2Str(dwStatus));
return dwStatus;
}
if (!Found)
dwStatus = WD_DEVICE_NOT_FOUND;
return dwStatus;
}
static DWORD RemoveDeviceFromDevList(DRIVER_CTX *pDriverCtx, DWORD dwUniqueID, DEVICE_CTX **ppDeviceCtx)
{
WDU_DEVICE_LIST_ITEM **iter, *tmp;
DWORD dwStatus;
BOOL Found = FALSE;
TRACE("RemoveDeviceFromDevList: DevList %p, dwUniqueID 0x%lx\n", DevList, dwUniqueID);
*ppDeviceCtx = NULL;
dwStatus = OsEventWait(DevList.hEvent, WDU_DEVLIST_TIMEOUT);
if (dwStatus)
{
ERR("RemoveDeviceFromDevList: error waiting for device list event: dwStatus (0x%lx) - %s\n",
dwStatus, Stat2Str(dwStatus));
return dwStatus;
}
for (iter = &DevList.pHead; *iter; iter = &(*iter)->next)
{
if ((*iter)->pDeviceCtx->dwUniqueID == dwUniqueID &&
(*iter)->pDeviceCtx->pDriverCtx == pDriverCtx)
{
Found = TRUE;
break;
}
}
if (Found)
{
tmp = *iter;
*ppDeviceCtx = (*iter)->pDeviceCtx;
// remove the device
*iter = (*iter)->next;
free(tmp);
}
dwStatus = OsEventSignal(DevList.hEvent);
if (dwStatus)
{
ERR("RemoveDeviceFromDevList: error signaling device list event: dwStatus (0x%lx) - %s\n",
dwStatus, Stat2Str(dwStatus));
return dwStatus;
}
if (!Found)
dwStatus = WD_DEVICE_NOT_FOUND;
return dwStatus;
}
DWORD DLLCALLCONV WDU_GetLangIDs(WDU_DEVICE_HANDLE hDevice,
PBYTE pbNumSupportedLangIDs, WDU_LANGID *pLangIDs, BYTE bNumLangIDs)
{
DWORD dwStatus;
DWORD dwBytesTransferred;
BYTE bTmpNumIDs, bNumReadIDs;
BYTE bSizeTrans; // size in bytes
WDU_LANGID *pBuf = NULL;
BYTE setupPacket[] = { 0x80, 0x6, 0x0, 0x3, 0x0, 0x0, sizeof(bSizeTrans), 0x0};
if (!pbNumSupportedLangIDs && !bNumLangIDs)
return WD_INVALID_PARAMETER;
// Read number of supported language IDs from the device
dwStatus = WDU_TransferDefaultPipe(hDevice, TRUE, 0, &bSizeTrans, sizeof(bSizeTrans),
&dwBytesTransferred, setupPacket, WDU_TRANSFER_TIMEOUT);
if (dwStatus)
{
ERR("WDU_GetLangIDs: Failed reading number of supported language IDs from the device:\n"
"Error: 0x%lx (\"%s\")\n", dwStatus, Stat2Str(dwStatus));
return dwStatus;
}
bTmpNumIDs = (BYTE)((bSizeTrans - 2)/sizeof(WDU_LANGID)); // First 2 bytes hold length and desc type, respectively
if (pbNumSupportedLangIDs)
*pbNumSupportedLangIDs = bTmpNumIDs;
if (!bTmpNumIDs)
{
TRACE("WDU_GetLangIDs: No language IDs are supported for the device\n");
return WD_STATUS_SUCCESS;
}
// Check if function was called only in order to get the number of supported language IDs
if (!bNumLangIDs)
return WD_STATUS_SUCCESS;
if (!pLangIDs)
{
ERR("WDU_GetLangIDs: Received NULL language IDs array\n");
return WD_INVALID_PARAMETER;
}
// Determine number of language IDs to read
if (bNumLangIDs < bTmpNumIDs)
{
TRACE("WDU_GetLangIDs: Size of language IDs array (%d) is smaller than the number of "
"supported language IDs (%d) - Returning only the first %d supported language IDs\n",
(int)bNumLangIDs, (int)bTmpNumIDs, (int)bNumLangIDs);
bTmpNumIDs = bNumLangIDs;
bSizeTrans = (BYTE)((bTmpNumIDs + 1) * sizeof(WDU_LANGID));
}
pBuf = (WDU_LANGID*)malloc(bSizeTrans);
if (!pBuf)
{
ERR("WDU_GetLangIDs: Failed allocating memory for language IDs array\n");
return WD_INSUFFICIENT_RESOURCES;
}
// update wLength for expected transfer size
setupPacket[6] = (BYTE)(bSizeTrans & 0xFF);
setupPacket[7] = (BYTE)((bSizeTrans & 0xFF00) >> 8);
// Read supported language IDs from the device
dwStatus = WDU_TransferDefaultPipe(hDevice, TRUE, 0, pBuf, bSizeTrans,
&dwBytesTransferred, setupPacket, WDU_TRANSFER_TIMEOUT);
if (dwStatus)
{
ERR("WDU_GetLangIDs: Failed getting supported language IDs from the device:\n"
"Error: 0x%lx (\"%s\")\n", dwStatus, Stat2Str(dwStatus));
goto Exit;
}
bNumReadIDs = (BYTE)(dwBytesTransferred/sizeof(WDU_LANGID) - 1); // First WORD (LANGID) holds length and desc type
if (bNumReadIDs != bTmpNumIDs)
{
ERR("WDU_GetLangIDs: Expected to read %d language IDs, read %d\n",
(int)bTmpNumIDs, (int)bNumReadIDs);
dwStatus = WD_SYSTEM_INTERNAL_ERROR;
goto Exit;
}
memcpy(pLangIDs, pBuf + 1, bSizeTrans - sizeof(WDU_LANGID)); // First WORD (LANGID) holds length and desc type
dwStatus = WD_STATUS_SUCCESS;
Exit:
free(pBuf);
return dwStatus;
}
#define GET_STR_DESC_LEN 4096 /* max buffer size */
DWORD DLLCALLCONV WDU_GetStringDesc(WDU_DEVICE_HANDLE hDevice, BYTE bStrIndex,
PBYTE pbBuf, DWORD dwBufSize, WDU_LANGID langID, PDWORD pdwDescSize)
{
DWORD dwStatus, dwBytesTransferred;
BYTE buf[GET_STR_DESC_LEN];
BYTE setupPacket[] = { 0x80, 0x6, 0x0, 0x3, 0x0, 0x0, (BYTE)(GET_STR_DESC_LEN & 0xFF),
(BYTE)((GET_STR_DESC_LEN & 0xFF00) >> 8) };
DWORD dwDescSize;
if (!pbBuf)
{
ERR("WDU_GetStringDesc: pbBuf is NULL\n");
return WD_INVALID_PARAMETER;
}
if (!bStrIndex)
{
TRACE("WDU_GetStringDesc: Invalid string index (0)\n");
return WD_INVALID_PARAMETER;
}
// set string index in the setup packet request
setupPacket[2] = bStrIndex;
if (!langID)
{
// get first language ID in supported language IDs list
dwStatus = WDU_GetLangIDs(hDevice, NULL, &langID, 1);
if (dwStatus)
return dwStatus;
if (!langID)
{
TRACE("WDU_GetStringDesc: No language IDs are supported for this device\n");
return WD_OPERATION_FAILED;
}
}
// wIndex = selected language ID
setupPacket[4] = (BYTE)(langID & 0xFF);
setupPacket[5] = (BYTE)((langID & 0xFF00) >> 8);
BZERO(buf);
dwStatus = WDU_TransferDefaultPipe(hDevice, TRUE, 0, &buf, GET_STR_DESC_LEN, &dwBytesTransferred,
setupPacket, WDU_TRANSFER_TIMEOUT);
if (dwStatus)
{
ERR("WDU_GetStringDesc: Failed reading string descriptor from the device:\n"
"Error: 0x%lx (\"%s\")\n", dwStatus, Stat2Str(dwStatus));
return dwStatus;
}
if (dwBytesTransferred > 2)
{
dwDescSize = dwBytesTransferred - 2; // The descriptor string begins in the third byte
if (dwDescSize && pdwDescSize)
*pdwDescSize = dwDescSize;
// return descriptor data to user.
// If dwBufSize < dwDescSize the returned buffer will be truncated to dwBufSize
memcpy(pbBuf, buf + 2, MIN(dwDescSize, dwBufSize));
}
else if (pdwDescSize)
*pdwDescSize = 0;
return WD_STATUS_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -