📄 usbdev.cpp
字号:
if ((RegQueryValueEx (hk, L"IsochAltSetting", NULL, &dwType, (LPBYTE)&dwData, &dwSize) == ERROR_SUCCESS) &&
(dwType == REG_DWORD) && (dwSize == sizeof(dwData)))
{
// a setting of zero means don't open any ISOCH pipe
if (dwData <= SCO_MAX_ALT_SETTING)
_dwSuggestedScoAltSetting = dwData;
}
dwSize = sizeof(dwData);
if ((RegQueryValueEx (hk, L"PacketSize", NULL, &dwType, (LPBYTE)&dwData, &dwSize) == ERROR_SUCCESS) &&
(dwType == REG_DWORD) && (dwSize == sizeof(dwData)) && dwData)
_uiPacketSize = dwData;
dwSize = sizeof(dwData);
if ((RegQueryValueEx (hk, L"BlockSize", NULL, &dwType, (LPBYTE)&dwData, &dwSize) == ERROR_SUCCESS) &&
(dwType == REG_DWORD) && (dwSize == sizeof(dwData)) && dwData)
_uiBlockSize = dwData;
dwSize = sizeof(dwData);
if ((RegQueryValueEx (hk, L"Priority256", NULL, &dwType, (LPBYTE)&dwData, &dwSize) == ERROR_SUCCESS) &&
(dwType == REG_DWORD) && (dwSize == sizeof(dwData)) && dwData)
g_USBReadThreadPriority = dwData;
dwSize = sizeof(dwData);
if ((RegQueryValueEx (hk, L"SCOReadPacketsPerTransfer", NULL, &dwType, (LPBYTE)&dwData, &dwSize) == ERROR_SUCCESS) &&
(dwType == REG_DWORD) && (dwSize == sizeof(dwData)) && dwData)
uiSCOReadPackets = dwData;
RegCloseKey (hk);
}
_uiSCOReadFrames = uiSCOReadPackets * SCO_READ_FRAMES_PER_PACKET;
if (_uiSCOReadFrames > MAX_SCO_READ_FRAMES_PER_TRANSFER) {
_uiSCOReadFrames = MAX_SCO_READ_FRAMES_PER_TRANSFER;
}
if (_dwSuggestedScoAltSetting != 0)
{
for (int i = 0 ; i < _nSCOInCount ; ++i)
{
// _dwSuggestedScoAltSetting being zero means don't open any ISOCH pipe
if ((_endpSCOAltSetting[i] == _dwSuggestedScoAltSetting))
{
_nScoPipeIdx = i;
// we only do the _uiMinPacketSize check on the SCO pipe that we will open.
if (((DWORD)_endpSCOIn[i].wMaxPacketSize * _uiSCOReadFrames) > _uiMinPacketSize)
_uiMinPacketSize = _endpSCOIn[i].wMaxPacketSize * _uiSCOReadFrames;
}
}
}
// sanity check -- make sure selected input endpoint has a coressponding output endpoint
if (IsScoActive())
{
if ((_endpSCOOut[_nScoPipeIdx].wMaxPacketSize != _endpSCOIn[_nScoPipeIdx].wMaxPacketSize) || (_nSCOOutCount != _nSCOInCount) )
{
_nScoPipeIdx = -1;
IFDBG(DebugOut (DEBUG_HCI_INIT, L"[HCI] [USB] ISOCH endpoints IN/OUT mismatch!\n"));
SVSUTIL_ASSERT(0);
}
}
#if ! defined (IMMEDIATE_SETUP)
if (_pIntfEvent && _bInitialized)
{
SVSUTIL_ASSERT(_pIntfEvent->Descriptor.bAlternateSetting == 0);
USB_TRANSFER usbTrans = (*_lpUsbFuncs->lpSetInterface)(_hDevice, NULL, NULL, 0,
_pIntfEvent->Descriptor.bInterfaceNumber, 0);
_bInitialized = (usbTrans != NULL);
(*_lpUsbFuncs->lpCloseTransfer)(usbTrans);
}
else
{
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] -OpenConnection : ERROR_NOT_READY (no event interface or transfer failed)\n"));
gpsynchUsbDevice->Unlock();
return ERROR_NOT_READY;
}
#endif
ResetEvent(gheventClose);
ResetEvent(gheventWritten);
if (_usbPipes[EVENT_INTERRUPT]._hPipe && _usbPipes[EVENT_BULK]._hPipe)
{
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] -OpenConnection : ERROR_SUCCESS (already initialized)\n"));
gpsynchUsbDevice->Unlock();
return ERROR_SUCCESS;
}
SVSUTIL_ASSERT(_lpUsbFuncs != NULL);
(*_lpUsbFuncs->lpResetDefaultPipe)(_hDevice);
BOOL fRet = FALSE;
SVSUTIL_ASSERT(NUM_IN_PIPES == 3);
USB_ENDPOINT_DESCRIPTOR *pendpIn[NUM_IN_PIPES] = {&_endpSCOIn[0], &_endpACLIn, &_endpEvents};
SVSUTIL_ASSERT(NUM_OUT_PIPES == 2);
USB_ENDPOINT_DESCRIPTOR *pendpOut[NUM_OUT_PIPES] = {&_endpSCOOut[0], &_endpACLOut};
int i;
BOOL bOpenScoPipes = FALSE;
if (IsScoActive()) {
// ParseConfig() found an acceptable SCO endp
// select the interface on which the SCO pipe can be opened
USB_TRANSFER hTransfer;
hTransfer = _lpUsbFuncs->lpSetInterface(_hDevice,
NULL,
NULL,
0,
SCO_INTERFACE_NUMBER,
_endpSCOAltSetting[_nScoPipeIdx]);
if (!hTransfer) {
DWORD dwError = GetLastError();
IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Failed to SetInterface: intf=%d alt=%d, error %d\n", SCO_INTERFACE_NUMBER, _endpSCOAltSetting[_nScoPipeIdx], dwError));
SetLastError(dwError);
goto Cleanup;
}
_lpUsbFuncs->lpCloseTransfer(hTransfer);
pendpIn [0] = &_endpSCOIn [_nScoPipeIdx];
pendpOut[0] = &_endpSCOOut[_nScoPipeIdx];
bOpenScoPipes = TRUE;
} else {
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[HCI] [USB] SCO endpoint not found\n"));
}
//Open pipes for all incoming endpoints
for (i = (bOpenScoPipes ? 0 : 1); i<NUM_IN_PIPES; i++)
{
_usbPipes[i]._hPipe = (*_lpUsbFuncs->lpOpenPipe)(_hDevice, pendpIn[i]);
if (_usbPipes[i]._hPipe == NULL)
{
IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Failed to open input pipe no: %d\n", i));
goto Cleanup;
}
(*_lpUsbFuncs->lpResetPipe)(_usbPipes[i]._hPipe);
}
//Open pipes for all outgoing endpoints
for (i = (bOpenScoPipes ? 0 : 1); i<NUM_OUT_PIPES; i++)
{
_hOutPipes[i] = (*_lpUsbFuncs->lpOpenPipe)(_hDevice, pendpOut[i]);
if (_hOutPipes[i] == NULL)
{
IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Failed to open output pipe no: %d\n", i));
goto Cleanup;
}
(*_lpUsbFuncs->lpResetPipe)(_hOutPipes[i]);
}
if (_uiPacketSize < _uiMinPacketSize)
_uiPacketSize = _uiMinPacketSize;
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] packet size %d block size %d\n", _uiPacketSize, _uiBlockSize));
if (ERROR_SUCCESS != gpRingBuffer->Init()) {
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] -OpenConnection : Failed to initialize Ring Buffer\n"));
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Cleanup;
}
_pfmdPackets = svsutil_AllocFixedMemDescr (offsetof(PACKET, data) + _uiPacketSize, _uiBlockSize);
if (!_pfmdPackets)
{
IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Failed to allocate fixed memory for packets\n"));
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Cleanup;
}
#if defined (CONNECTION_TRACKING)
_pHandleTree = SVSNewTree();
if (! _pHandleTree)
{
IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Failed to allocate tree for handles\n"));
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Cleanup;
}
#endif
// Ensure all events are reset
for (i=0; i<NUM_IN_PIPES; i++)
{
ResetEvent(gheventRead[i]);
}
DWORD dwThreadId;
SVSUTIL_ASSERT(ghthrdRead == NULL);
ghthrdRead = CreateThread(NULL, 0, ReadThreadProcStub, this, 0, &dwThreadId);
if (!ghthrdRead)
{
IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] Failed to create read thread.\n"));
goto Cleanup;
}
CeSetThreadPriority(ghthrdRead, g_USBReadThreadPriority);
for (i = (bOpenScoPipes ? EVENT_ISOCH : EVENT_BULK); i <= EVENT_INTERRUPT; i++)
{
if (!SubmitReadRequest(i))
{
IFDBG(DebugOut(DEBUG_ERROR, L"[HCI] [USB] ReadRequest to %d failed.\n", i));
goto Cleanup;
}
}
if (bOpenScoPipes) {
_bCloseScoIO = FALSE;
}
#if defined (BT_USE_CELOG)
if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_BASE, L"software\\microsoft\\bluetooth\\debug", 0, KEY_READ, &hk)) {
DWORD dwType;
DWORD dw;
DWORD dwSize = sizeof(dw);
if ((ERROR_SUCCESS == RegQueryValueEx (hk, L"celog", NULL, &dwType, (LPBYTE)&dw, &dwSize)) &&
(dwType == REG_DWORD) && (dwSize == sizeof(dw)) && dw)
g_fCeLog = IsCeLogStatus (CELOGSTATUS_ENABLED_GENERAL);
RegCloseKey (hk);
}
if (g_fCeLog) {
BTH_CELOG_START_DATA sd;
sd.eTransport = USB;
GetLocalTime (&sd.st);
wsprintf (sd.szDriverString, L"USB Driver v. 0x%08x SCO Active: %d", HCI_INTERFACE_VERSION_1_1, IsScoActive ());
CELOGDATAFLAGGED(TRUE, CELID_RAW_UCHAR, &sd, sizeof(sd), 0, CELZONE_ALWAYSON, CELOG_FLAG_START);
}
#endif
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] -OpenConnection : ERROR_SUCCESS\n"));
gpsynchUsbDevice->Unlock();
return ERROR_SUCCESS;
Cleanup:
DWORD dwErr = GetLastError();
gpsynchUsbDevice->Unlock();
CloseConnection();
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] -OpenConnection : %d\n", dwErr));
return dwErr;
}
BOOL CUsbDevice::CloseConnectionHelper()
{
gpsynchUsbDevice->Lock();
if (!_bInitialized)
{
gpsynchUsbDevice->Unlock();
return FALSE;
}
_bCloseScoIO = TRUE;
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[HCI] Calling SetEvent(gheventClose)\n"));
SetEvent(gheventClose);
SVSUTIL_ASSERT(_lpUsbFuncs != NULL);
for (int i=0; i<NUM_IN_PIPES; i++)
{
if (_usbPipes[i]._hTransfer)
{
if (!_lpUsbFuncs->lpIsTransferComplete(_usbPipes[i]._hTransfer)) {
_lpUsbFuncs->lpAbortTransfer(_usbPipes[i]._hTransfer, 0);
}
(*_lpUsbFuncs->lpCloseTransfer)(_usbPipes[i]._hTransfer);
_usbPipes[i]._hTransfer = NULL;
}
if (_usbPipes[i]._hPipe)
{
(*_lpUsbFuncs->lpClosePipe)(_usbPipes[i]._hPipe);
_usbPipes[i]._hPipe = NULL;
}
_usbPipes[i].CUsbPipe::CUsbPipe ();
}
for (i=0; i<NUM_OUT_PIPES; i++)
{
if (_hOutPipes[i])
{
(*_lpUsbFuncs->lpClosePipe)(_hOutPipes[i]);
_hOutPipes[i] = NULL;
}
}
if (_pfmdPackets)
{
svsutil_ReleaseFixedNonEmpty(_pfmdPackets);
_pfmdPackets = NULL;
}
gpRingBuffer->Deinit();
#if defined (CONNECTION_TRACKING)
if (_pHandleTree)
{
delete _pHandleTree;
_pHandleTree = NULL;
}
#endif
#if defined (NATIVE_SEQUENCING)
while (_pPacketList)
{
CompletedPacket *pNext = _pPacketList->pNext;
free (_pPacketList);
_pPacketList = pNext;
}
_pLastPacket = NULL;
#endif
_nScoPipeIdx = -1;
gpsynchUsbDevice->Unlock();
return TRUE;
}
void CUsbDevice::CloseConnection(void)
{
SVSUTIL_ASSERT(!gpsynchUsbDevice->IsLocked());
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] +CloseConnection\n"));
if (!CloseConnectionHelper())
{
IFDBG(DebugOut (DEBUG_ERROR, L"[HCI] [USB] -CloseConnection - device not active\n"));
return;
}
gpsynchUsbDevice->Lock();
HANDLE hThread = NULL;
if (ghthrdRead)
{
hThread = ghthrdRead;
ghthrdRead = NULL;
}
gpsynchUsbDevice->Unlock();
ASSERT(!gpsynchUsbDevice->IsLocked()); //make sure the lock is released before waiting for the thread to die
if (hThread)
{
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
#if defined (BT_USE_CELOG)
if (g_fCeLog) {
BTH_CELOG_STOP_DATA sd;
GetLocalTime (&sd.st);
CELOGDATAFLAGGED(TRUE, CELID_RAW_UCHAR, &sd, sizeof(sd), 0, CELZONE_ALWAYSON, CELOG_FLAG_STOP);
g_fCeLog = FALSE;
}
#endif
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] -CloseConnection\n"));
}
int CUsbDevice::WritePacket (unsigned char *pBuffer, int nLen, HCI_TYPE eType)
{
gpsynchUsbDevice->Lock ();
IFDBG(DebugOut(DEBUG_HCI_TRANSPORT, L"[USB] WritePacket : %s : %d bytes\n", eType == COMMAND_PACKET ? L"COMMAND" : (eType == DATA_PACKET_ACL ? L"ACL" : (eType == DATA_PACKET_SCO ? L"SCO" : L"Error")), nLen));
if (!CheckDevice())
{
gpsynchUsbDevice->Unlock ();
return FALSE;
}
if ((DATA_PACKET_SCO == eType) && !IsScoActive()) {
// HCI wants to send a SCO packet, but an ISOCH endpoint was not found and opened.
// HCI should be smart enough to know that SCO is not supported on this device
// because bthusb could not find an ISOCH endpoint.
// HCI can figure this out from HCI_PARAMETERS struct.
gpsynchUsbDevice->Unlock ();
return FALSE;
}
SVSUTIL_ASSERT(pBuffer);
SVSUTIL_ASSERT(nLen > 0);
SVSUTIL_ASSERT(_lpUsbFuncs != NULL);
switch (eType)
{
case COMMAND_PACKET:
{
USB_DEVICE_REQUEST usbDevReq;
usbDevReq.bmRequestType = USB_REQUEST_HOST_TO_DEVICE | USB_REQUEST_CLASS;
usbDevReq.bRequest = 0;
usbDevReq.wValue = 0;
usbDevReq.wIndex = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -