📄 usbdev.cpp
字号:
int fRes = GetBuffer (i, 0, nPacketSize, pBuffer, TRUE);
SVSUTIL_ASSERT (fRes);
return TRUE;
}
return FALSE;
#endif
}
BOOL CompressBuffer (
PBYTE pBuffer, // in out
PDWORD pdwFrameDataLens, // in
DWORD dwFrames, // in
DWORD dwFrameSize, // in
PDWORD pdwCompressedSize // out
)
{
PBYTE pFrame;
DWORD dw;
*pdwCompressedSize = 0;
pFrame = pBuffer;
for (dw = 0; dw < dwFrames; dw++)
{
if (*pdwFrameDataLens > dwFrameSize) {
return FALSE;
}
if ( (pFrame != pBuffer) && *pdwFrameDataLens ) {
memmove(pBuffer, pFrame, *pdwFrameDataLens);
}
pFrame += dwFrameSize;
pBuffer += *pdwFrameDataLens;
*pdwCompressedSize += *pdwFrameDataLens;
pdwFrameDataLens++;
}
return TRUE;
}
int CUsbDevice::ReadPacket (unsigned char *pBuffer, int *pnLen, int *pnType)
{
IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[USB] +ReadPacket\n"));
for ( ; ; )
{
gpsynchUsbDevice->Lock ();
if (!CheckDevice())
{
IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[USB] -ReadPacket : FALSE (device dead)\n"));
gpsynchUsbDevice->Unlock();
return FALSE;
}
DWORD dwTimeout = INFINITE;
if (RetrievePacket (pBuffer, pnLen, pnType, &dwTimeout))
{
#if defined (CONNECTION_TRACKING)
if ((*pnType == EVENT_INTERRUPT) && (*pnLen > 4)) {
unsigned short x = pBuffer[3] | (pBuffer[4] << 8);
if (pBuffer[0] == HCI_Connection_Complete_Event) {
IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"USB CONNECTION TRACKING : detected connection 0x%04x\n", x));
if (! _pHandleTree->Locate (x))
_pHandleTree->Insert (x, (void *)1);
} else if ((*pnLen > 4) && (pBuffer[0] == HCI_Disconnection_Complete_Event)) {
IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"USB CONNECTION TRACKING : detected connection drop 0x%04x\n", x));
SVSTNode *pNode = _pHandleTree->Locate (x);
if (pNode)
_pHandleTree->Delete (pNode);
else {
IFDBG(DebugOut (DEBUG_ERROR, L"USB CONNECTION TRACKING : handle 0x%08x not found!\n", x));
}
} else if ((*pnLen > 5) && (pBuffer[0] == HCI_Command_Complete_Event) && (x == HCI_Reset) && (pBuffer[5] == 0)) {
IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"USB CONNECTION TRACKING : detected reset\n"));
_pHandleTree->Empty ();
}
}
#endif
#if defined (BT_USE_CELOG)
if (g_fCeLog) {
unsigned short usFlag = 0;
switch (*pnType) {
case EVENT_BULK:
usFlag = CELOG_FLAG_HCI_ACL_IN;
break;
case EVENT_INTERRUPT:
usFlag = CELOG_FLAG_HCI_EVENT_IN;
break;
case EVENT_ISOCH:
usFlag = CELOG_FLAG_HCI_SCO_IN;
break;
}
if (usFlag) {
CELOGDATAFLAGGED(TRUE, CELID_RAW_UCHAR, pBuffer, (unsigned short)*pnLen, 0, CELZONE_ALWAYSON, usFlag);
}
}
#endif
IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[USB] -ReadPacket : TRUE (got stuff) _usbPipes[%d].iTotalQueue=%d\n",
*pnType, _usbPipes[*pnType].iTotalQueue));
gpsynchUsbDevice->Unlock();
return TRUE;
}
HANDLE hEvents[2] = {gheventPackets, gheventClose};
IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[USB] ReadPacket : WAIT\n"));
gpsynchUsbDevice->Unlock();
DWORD dwEvent = WaitForMultipleObjects(2, hEvents, FALSE, dwTimeout);
if ((dwEvent == WAIT_TIMEOUT) || (dwEvent == WAIT_OBJECT_0))
continue;
IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[USB] -ReadPacket : FALSE (device dead)\n"));
return FALSE;
}
}
DWORD CALLBACK CUsbDevice::ReadThreadProcStub(LPVOID lpvNotifyParameter)
{
#if defined (DEBUG)
SVSUTIL_ASSERT(lpvNotifyParameter == gpUsbDevice);
#endif
return(gpUsbDevice->ReadThreadProc());
}
DWORD CUsbDevice::ReadThreadProc(void)
{
HANDLE hEvents[NUM_IN_PIPES+2];
for (int i=0; i<NUM_IN_PIPES; i++)
hEvents[i] = gheventRead[i];
hEvents[NUM_IN_PIPES] = gheventClose;
hEvents[NUM_IN_PIPES+1] = gheventWritten;
int fStop = FALSE;
while(TRUE)
{
DWORD dwEvent = WaitForMultipleObjects(NUM_IN_PIPES+2, hEvents, FALSE, INFINITE);
if ((dwEvent < WAIT_OBJECT_0) || (dwEvent > WAIT_OBJECT_0 + NUM_IN_PIPES + 2 - 1))
{
IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] ReadThreadProc error in WaitForMultipleObjects... Exiting thread.\n"));
fStop = TRUE;
break;
}
gpsynchUsbDevice->Lock();
int nEvent = dwEvent - WAIT_OBJECT_0;
SVSUTIL_ASSERT(nEvent >= 0 && nEvent <= NUM_IN_PIPES+3);
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"Event %d set.\n", nEvent));
if (nEvent == EVENT_CLOSE)
{
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[HCI] [USB] Close event received. Exiting read thread...\n"));
gpsynchUsbDevice->Unlock();
break;
}
if (!CheckDevice())
{
IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Device closed. Exiting read thread...\n"));
gpsynchUsbDevice->Unlock();
break;
}
if (nEvent == EVENT_WRITTEN) {
if (ERROR_SUCCESS != gpRingBuffer->CompletePackets ()) {
IFDBG(DebugOut (DEBUG_WARN, L"[WARN] USB write completed async but could not complete packets.\n"));
}
gpsynchUsbDevice->Unlock();
continue;
}
SVSUTIL_ASSERT(_lpUsbFuncs != NULL);
PREFAST_ASSERT(_usbPipes[nEvent]._pCurPacket);
DWORD dwErr = USB_NO_ERROR;
BOOL fSuccess;
if (nEvent == EVENT_ISOCH) {
DWORD dwFrameLens[MAX_SCO_READ_FRAMES_PER_TRANSFER];
DWORD dwFrameErrors[MAX_SCO_READ_FRAMES_PER_TRANSFER];
fSuccess = _lpUsbFuncs->lpGetIsochResults ( _usbPipes[nEvent]._hTransfer,
_uiSCOReadFrames,
dwFrameLens,
dwFrameErrors);
if (fSuccess) {
_usbPipes[nEvent]._pCurPacket->nSize = 0;
for (DWORD dw = 0; dw < _uiSCOReadFrames; dw++)
{
if (dwFrameErrors[dw] != USB_NO_ERROR) {
dwErr = dwFrameErrors[dw];
break;
}
}
if (dwErr == USB_NO_ERROR) {
DWORD dwBytes;
BOOL bSuc = CompressBuffer ((PBYTE) _usbPipes[nEvent]._pCurPacket->data,
dwFrameLens,
_uiSCOReadFrames,
(DWORD) _endpSCOOut[_nScoPipeIdx].wMaxPacketSize,
&dwBytes);
if (bSuc) {
_usbPipes[nEvent]._pCurPacket->nSize = (int) dwBytes;
} else {
IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Invalid frame data len for isoch transfer. Ignoring transfer...\n"));
}
}
}
} else {
fSuccess = _lpUsbFuncs->lpGetTransferStatus(_usbPipes[nEvent]._hTransfer,
(DWORD*)&_usbPipes[nEvent]._pCurPacket->nSize,
&dwErr);
}
if (!fSuccess)
{
IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Invalid USB transfer handle. Exiting thread...\n"));
gpsynchUsbDevice->Unlock();
fStop = TRUE;
break;
}
else if (dwErr != USB_NO_ERROR)
{
// IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Err %d on event %d. Ignoring...\n", dwErr, nEvent));
}
else if (_usbPipes[nEvent]._pCurPacket->nSize == 0)
{
if (nEvent!=EVENT_ISOCH) {
IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Packet size 0 : ignoring \n"));
}
}
else if (_usbPipes[nEvent]._pCurPacket->nSize > (int)_uiPacketSize)
{
IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Invalid Packet size %d : ignoring packet\n", _usbPipes[nEvent]._pCurPacket->nSize));
SVSUTIL_ASSERT(0);
_usbPipes[nEvent]._pCurPacket->nSize = 0;
}
else
{
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] GetTransferStatus returns %d bytes transferred. Error=%d\n", _usbPipes[nEvent]._pCurPacket->nSize, dwErr));
DumpBuff(DEBUG_HCI_DUMP, _usbPipes[nEvent]._pCurPacket->data, _usbPipes[nEvent]._pCurPacket->nSize);
SVSUTIL_ASSERT(_usbPipes[nEvent]._pCurPacket->nSize <= (int)_uiPacketSize);
#if defined (CONNECTION_TRACKING)
_usbPipes[nEvent]._pCurPacket->dwWhenReceived = GetTickCount ();
#endif
if (_usbPipes[nEvent]._pLastPacket)
{
SVSUTIL_ASSERT(_usbPipes[nEvent]._pLastPacket->pNext == NULL);
_usbPipes[nEvent]._pLastPacket->pNext = _usbPipes[nEvent]._pCurPacket;
_usbPipes[nEvent]._pLastPacket = _usbPipes[nEvent]._pCurPacket;
}
else
{
SVSUTIL_ASSERT(_usbPipes[nEvent]._pPackets == NULL);
_usbPipes[nEvent]._pLastPacket = _usbPipes[nEvent]._pPackets = _usbPipes[nEvent]._pCurPacket;
}
_usbPipes[nEvent].iTotalQueue += _usbPipes[nEvent]._pCurPacket->nSize;
SVSUTIL_ASSERT (_usbPipes[nEvent]._pLastPacket->pNext == NULL);
_usbPipes[nEvent]._pCurPacket = NULL;
if (CompletePacket (nEvent))
SetEvent(gheventPackets);
}
SVSUTIL_ASSERT(_usbPipes[nEvent]._hTransfer);
(*_lpUsbFuncs->lpCloseTransfer)(_usbPipes[nEvent]._hTransfer);
_usbPipes[nEvent]._hTransfer = NULL;
BOOL bSubmit = SubmitReadRequest(nEvent);
gpsynchUsbDevice->Unlock();
if (!bSubmit)
{
IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] reader thread : Could not resubmit the request. Closing down\n"));
fStop = TRUE;
break;
}
}
if (fStop)
{
IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] reader thread : closing down\n"));
SetEvent (gheventClose);
CloseConnectionHelper();
}
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] reader thread : exited\n"));
return FALSE;
}
BOOL CUsbDevice::SubmitReadRequest(int nEvent)
{
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] SubmitReadRequest %s\n", nEvent == EVENT_BULK ? L"ACL" : (nEvent == EVENT_INTERRUPT ? L"Event" : (nEvent == EVENT_ISOCH ? L"SCO" : L"Error"))));
SVSUTIL_ASSERT(gpsynchUsbDevice->IsLocked());
if ( (nEvent == EVENT_ISOCH) && !IsScoActive() ) {
IFDBG(DebugOut (DEBUG_ERROR, L"[HCI] [USB] -SubmitReadRequest :: SCO read when no ISOCH endpoint found\n"));
return FALSE;
}
ResetEvent(gheventRead[nEvent]);
SVSUTIL_ASSERT(!_usbPipes[nEvent]._hTransfer);
SVSUTIL_ASSERT(_lpUsbFuncs != NULL);
if (! _usbPipes[nEvent]._pCurPacket)
_usbPipes[nEvent]._pCurPacket = new PACKET;
if (! _usbPipes[nEvent]._pCurPacket)
{
IFDBG(DebugOut (DEBUG_ERROR, L"[HCI] [USB] -SubmitReadRequest :: out of memory!\n"));
return FALSE;
}
BOOL bHalted = FALSE;
if ((*_lpUsbFuncs->lpIsPipeHalted)(_usbPipes[nEvent]._hPipe, &bHalted) && bHalted)
{
IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] SubmitReadRequest : Pipe halted -- resetting!\n"));
(*_lpUsbFuncs->lpResetPipe)(_usbPipes[nEvent]._hPipe);
}
unsigned int i;
switch(nEvent)
{
case EVENT_BULK:
_usbPipes[nEvent]._hTransfer = (*_lpUsbFuncs->lpIssueBulkTransfer)(_usbPipes[nEvent]._hPipe, ReadNotify, (void *)nEvent,
USB_IN_TRANSFER | USB_SHORT_TRANSFER_OK | USB_NO_WAIT,
_uiPacketSize, _usbPipes[nEvent]._pCurPacket->data, NULL);
break;
case EVENT_INTERRUPT:
_usbPipes[nEvent]._hTransfer = (*_lpUsbFuncs->lpIssueInterruptTransfer)(_usbPipes[nEvent]._hPipe, ReadNotify, (void *)nEvent,
USB_IN_TRANSFER | USB_SHORT_TRANSFER_OK | USB_SEND_TO_ENDPOINT | USB_NO_WAIT,
_endpEvents.wMaxPacketSize, _usbPipes[nEvent]._pCurPacket->data, NULL);
break;
case EVENT_ISOCH:
for (i = 0; i < _uiSCOReadFrames; i++)
{
_dwInTransferLens[i] = _endpSCOIn[_nScoPipeIdx].wMaxPacketSize;
}
_usbPipes[nEvent]._hTransfer = (*_lpUsbFuncs->lpIssueIsochTransfer)(_usbPipes[nEvent]._hPipe, ReadNotify, (void *)nEvent,
USB_IN_TRANSFER | USB_NO_WAIT | USB_START_ISOCH_ASAP,
0, _uiSCOReadFrames, _dwInTransferLens, _usbPipes[nEvent]._pCurPacket->data, NULL);
break;
default:
SVSUTIL_ASSERT(FALSE);
break;
}
if (_usbPipes[nEvent]._hTransfer == NULL)
{
IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Failed to issue transfer on pipe %d. GetLastError() returns 0x%08x\n", nEvent, GetLastError()));
return FALSE;
}
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] -SubmitReadRequest %s : TRUE\n", nEvent == EVENT_BULK ? L"ACL" : (nEvent == EVENT_INTERRUPT ? L"Event" : (nEvent == EVENT_ISOCH ? L"SCO" : L"Error"))));
return TRUE;
}
DWORD CALLBACK CUsbDevice::ReadNotify(LPVOID lpvNotifyParameter)
{
int nEvent = (int )lpvNotifyParameter;
IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[USB] ReadRequest arrived for %s\n", nEvent == EVENT_BULK ? L"ACL" : (nEvent == EVENT_INTERRUPT ? L"Event" : (nEvent == EVENT_ISOCH ? L"SCO" : L"Error"))));
SVSUTIL_ASSERT(nEvent >=0 && nEvent < NUM_IN_PIPES);
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] Calling SetEvent() on event %d\n", nEvent));
SetEvent(gheventRead[nEvent]);
return 0;
}
DWORD CALLBACK CUsbDevice::WriteNotify(LPVOID lpvNotifyParameter)
{
int dwCookie = (DWORD)lpvNotifyParameter;
IFDBG(DebugOut (DEBUG_HCI_TRANSPORT, L"[USB] Write completed async with cookie %d\n", dwCookie));
gpRingBuffer->SignalComplete (dwCookie);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -