📄 hciuart.cxx
字号:
// Copyright (c) David Vescovi. All rights reserved.
// Part of Project DrumStix
// Windows Embedded Developers Interest Group (WE-DIG) community project.
// http://www.we-dig.org
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//------------------------------------------------------------------------------
//
// Bluetooth HCI UART interface
//
//
// Module Name:
//
// hciuart.cxx
//
// Abstract:
//
// This file implements Bluetooth HCI UART interface for Gumstix
// After reset Ericsson (ROK104001) module will default to 57600 baud
// The Infineon (PBA31307) will default to 115200 baud.
// If the com port registry setting is set to COM5 (BTUART) the
// Infineon module is assumed, if COM4 (HWUART) the Ericsson is assumed
//
//
//------------------------------------------------------------------------------
#include <windows.h>
#include <bt_buffer.h>
#include <bt_hcip.h>
#include <bt_os.h>
#include <bt_debug.h>
#include <bt_tdbg.h>
#include "bsp.h"
static HANDLE hFile = INVALID_HANDLE_VALUE;
static HANDLE hWriteEvent = NULL;
static HANDLE hReadEvent = NULL;
static HCI_TransportCallback gCallback = NULL;
#define PACKET_SIZE_R (64 * 1024 + 128)
#define PACKET_SIZE_W (255 + 3)
#define DEFAULT_COM_NAME L"COM4:" // ROK ERICSSON radio
#define ALT_COM_NAME L"COM5:" // BPA INFINEON radio
#define DEBUG_READ_BUFFER_HEADER 4
#define DEBUG_WRITE_BUFFER_HEADER 8
#define DEBUG_READ_BUFFER_TRAILER 1
#define DEBUG_WRITE_BUFFER_TRAILER 3
DECLARE_DEBUG_VARS();
// specific code for Ericsson module
unsigned char HCC_RESET[] = {01, 03, 0x0c, 00};
unsigned char HCC_INFINEON_READ_VERSION[] = {01, 05, 0xfc, 00};
BOOL Ericsson = TRUE;
#define EricssonBaudRatePos 4
#define InfineonBaudRatePos 5
#define HEAD_LEN 7
unsigned char HCC_ERICSSON_SET_BAUD_RATE[] = {0x01, 0x09, 0xfc, 0x01, 0x02};
unsigned char HCC_INFINEON_SET_BAUD_RATE[] = {0x01, 0x06, 0xfc, 0x02, 0x00, 0x70};
unsigned char HCC_READ_BT_ADDR[] = {0x01, 0x09, 0x01, 0x00};
static BOOL WriteCommPort (unsigned char *pBuffer, unsigned int cSize);
BOOL SendHCC(HANDLE commPort, unsigned char* pHCC, DWORD size)
{
DWORD nWritten = 0;
if(WriteFile(commPort, pHCC, size, &nWritten, 0))
return TRUE;
IFDBG(DebugOut (DEBUG_ERROR, L"BthGum:SendHCC-WriteFile Fail. GetLastError = 0x%08x\n", GetLastError ()));
return FALSE;
}
BOOL ReadHCE(HANDLE commPort)
{
DWORD nRead = 0;
unsigned char received[10];
ZeroMemory(received, sizeof(received));
if(ReadFile(commPort, received, HEAD_LEN, &nRead, 0) && nRead)
{
return TRUE;
}
IFDBG(DebugOut (DEBUG_ERROR, L"BthGum:ReadHCE-ReadFile Fail. GetLastError = 0x%08x\n", GetLastError ()));
return FALSE;
}
BOOL UART_SetBaudRate(HANDLE commPort, DWORD dwBaudRate)
{
DCB dcb;
Sleep(1000);
ZeroMemory(&dcb, sizeof(dcb));
if(!GetCommState(commPort, &dcb))
{
IFDBG(DebugOut (DEBUG_ERROR, L"BthGum:UART_SetBaudRate-GetCommState Fail. GetLastError = 0x%08x\n", GetLastError ()));
}
if (Ericsson)
{
if(SendHCC(commPort, HCC_RESET, sizeof(HCC_RESET)))
{
Sleep(100);
if(!ReadHCE(commPort))
{
return FALSE;
}
PurgeComm(commPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
}
Sleep(100);
switch(dwBaudRate)
{
case 57600:
HCC_ERICSSON_SET_BAUD_RATE[EricssonBaudRatePos] = 3;
break;
case 115200:
HCC_ERICSSON_SET_BAUD_RATE[EricssonBaudRatePos] = 2;
break;
case 230400:
HCC_ERICSSON_SET_BAUD_RATE[EricssonBaudRatePos] = 1;
break;
case 460800:
HCC_ERICSSON_SET_BAUD_RATE[EricssonBaudRatePos] = 0;
break;
case 921600:
HCC_ERICSSON_SET_BAUD_RATE[EricssonBaudRatePos] = 0x20;
break;
default:
{
IFDBG(DebugOut (DEBUG_ERROR, L"Invalid Baud Rate : %d\n", dwBaudRate));
return FALSE;
}
}
if(SendHCC(commPort, HCC_ERICSSON_SET_BAUD_RATE, sizeof(HCC_ERICSSON_SET_BAUD_RATE)))
{
Sleep(100);
if(ReadHCE(commPort))
{
PurgeComm(commPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
//GetCommState(commPort, &dcb);
dcb.BaudRate = dwBaudRate;
if(SetCommState(commPort, &dcb))
{
RETAILMSG(1, (L"ROK104001 Bluetooth module at 921600\r\n"));
return TRUE;
}
else
IFDBG(DebugOut (DEBUG_ERROR, L"BthGum:Failed SetCommState in UART HCI Interface. GetLastError = 0x%08x\n", GetLastError ()));
}
else
IFDBG(DebugOut (DEBUG_ERROR, L"BthGum:HCC_ERICSSON_SET_BAUD_RATE return event fail\n"));
}
else
IFDBG(DebugOut (DEBUG_ERROR, L"BthGum:Send HCC_ERICSSON_SET_BAUD_RATE fail\n"));
}
else // Infineon
{
// detect which Infineon module we are using start at 115200 then try 921600
if(SendHCC(commPort, HCC_INFINEON_READ_VERSION, sizeof(HCC_INFINEON_READ_VERSION)))
{
Sleep(50);
if(ReadHCE(commPort))
{
}
else
{ // try 921600
PurgeComm(commPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
dcb.BaudRate = dwBaudRate;
if(SetCommState(commPort, &dcb))
{
if(SendHCC(commPort, HCC_INFINEON_READ_VERSION, sizeof(HCC_INFINEON_READ_VERSION)))
{
Sleep(50);
if(ReadHCE(commPort))
{ // if we can read it we don't need to change it
RETAILMSG(1, (L"PBA31308 Bluetooth module at 921600\r\n"));
return TRUE;
}
}
}
}
}
PurgeComm(commPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
IFDBG(DebugOut (DEBUG_ERROR, L"BthGum:Failed SetCommState in UART HCI Interface. GetLastError = 0x%08x\n", GetLastError ()));
}
return FALSE;
}
// switch(dwBaudRate)
// {
// case 57600:
// HCC_INFINEON_SET_BAUD_RATE[InfineonBaudRatePos] = 0x1e;
// break;
// case 115200:
// HCC_INFINEON_SET_BAUD_RATE[InfineonBaudRatePos] = 0x70;
// break;
// case 230400:
// HCC_INFINEON_SET_BAUD_RATE[InfineonBaudRatePos] = 0x37;
// break;
// case 460800:
// HCC_INFINEON_SET_BAUD_RATE[InfineonBaudRatePos] = 0x1b;
// break;
// case 921600:
// HCC_INFINEON_SET_BAUD_RATE[InfineonBaudRatePos] = 0x0d;
// break;
// default:
// {
// IFDBG(DebugOut (DEBUG_ERROR, L"Invalid Baud Rate : %d\n", dwBaudRate));
// return FALSE;
// }
// }
//
// if(SendHCC(commPort, HCC_INFINEON_SET_BAUD_RATE, sizeof(HCC_INFINEON_SET_BAUD_RATE)))
// {
// Sleep(50);
// if(ReadHCE(commPort))
// {
// PurgeComm(commPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
// //GetCommState(commPort, &dcb);
// dcb.BaudRate = dwBaudRate;
// if(SetCommState(commPort, &dcb))
// {
// Sleep(100);
// if(ReadHCE(commPort))
// {
// PurgeComm(commPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
// return TRUE;
// }
// else
// IFDBG(DebugOut (DEBUG_ERROR, L"BthGum:Failed SetCommState in UART HCI Interface. GetLastError = 0x%08x\n", GetLastError ()));
// }
// else
// IFDBG(DebugOut (DEBUG_ERROR, L"BthGum:Failed SetCommState in UART HCI Interface. GetLastError = 0x%08x\n", GetLastError ()));
// }
// else
// IFDBG(DebugOut (DEBUG_ERROR, L"BthGum:HCC_INFINEON_SET_BAUD_RATE return event fail\n"));
// }
// else
// IFDBG(DebugOut (DEBUG_ERROR, L"BthGum:Send HCC_INFINEON_SET_BAUD_RATE fail\n"));
// }
//
// return FALSE;
//}
BOOL HardwareRadio(BOOL TurnOn)
{
PHYSETAdrInfo phySetAddr;
phySetAddr.subcode = PHY_SET_ADDR;
if (TurnOn)
phySetAddr.address = PXA255_BASE_REG_PA_GPIO + offsetof(GPIO_REG_T, GPSR0); // set register
else
phySetAddr.address = PXA255_BASE_REG_PA_GPIO + offsetof(GPIO_REG_T, GPCR0); // clear register
phySetAddr.value = GPIO_7_nBTRESET;
phySetAddr.mask = GPIO_7_nBTRESET;
if (!KernelIoControl(IOCTL_HAL_PHYADR, &phySetAddr, sizeof(PHYSETAdrInfo), NULL, 0, NULL))
{
// invalid IOCTL call!
IFDBG(DebugOut (DEBUG_HCI_INIT, L"BthGum:-HardwareRadio (bad IOCTL radio on/off call)\n"));
return FALSE;
}
return TRUE;
}
int HCI_ReadHciParameters (HCI_PARAMETERS *pParms) {
if (pParms->uiSize < sizeof (*pParms))
return FALSE;
memset (pParms, 0, sizeof(*pParms));
pParms->uiSize = sizeof(*pParms);
pParms->fInterfaceVersion = HCI_INTERFACE_VERSION_1_1;
pParms->iMaxSizeRead = PACKET_SIZE_R;
pParms->iMaxSizeWrite = PACKET_SIZE_W;
pParms->iWriteBufferHeader = 4;
pParms->iReadBufferHeader = 4;
pParms->fHardwareVersion = HCI_HARDWARE_VERSION_V_1_0_B;
pParms->uiWriteTimeout = HCI_DEFAULT_WRITE_TIMEOUT;
pParms->uiFlags = HCI_FLAGS_NORESET | HCI_FLAGS_NOROLESWITCH;
#if defined (DEBUG) || defined (_DEBUG)
pParms->iReadBufferHeader = DEBUG_READ_BUFFER_HEADER;
pParms->iReadBufferTrailer = DEBUG_READ_BUFFER_TRAILER;
pParms->iWriteBufferHeader = DEBUG_WRITE_BUFFER_HEADER;
pParms->iWriteBufferTrailer = DEBUG_WRITE_BUFFER_TRAILER;
#endif
return TRUE;
}
int HCI_StartHardware (void) {
IFDBG(DebugOut (DEBUG_HCI_INIT, L"BthGum:+HCI_StartHardware\n"));
if (! HardwareRadio(TRUE))
{
IFDBG(DebugOut (DEBUG_HCI_INIT, L"BthGum:-HCI_StartHardware (can't turn on)\n"));
return FALSE;
}
if (hFile != INVALID_HANDLE_VALUE) {
IFDBG(DebugOut (DEBUG_HCI_INIT, L"BthGum:-HCI_StartHardware (already started)\n"));
return TRUE;
}
if (! gCallback)
{
IFDBG(DebugOut (DEBUG_HCI_INIT, L"BthGum:-HCI_StartHardware (not registered)\n"));
return FALSE;
}
return ERROR_SUCCESS == gCallback (DEVICE_UP, NULL);
}
int HCI_StopHardware (void) {
IFDBG(DebugOut (DEBUG_HCI_INIT, L"BthGum:+HCI_StopHardware\n"));
if (! HardwareRadio(FALSE))
{
IFDBG(DebugOut (DEBUG_HCI_INIT, L"BthGum:-HCI_StopHardware (can't turn off)\n"));
return FALSE;
}
if (hFile == INVALID_HANDLE_VALUE) {
IFDBG(DebugOut (DEBUG_HCI_INIT, L"BthGum:-HCI_StopHardware (already stopped)\n"));
return TRUE;
}
if (! gCallback) {
IFDBG(DebugOut (DEBUG_HCI_INIT, L"BthGum:-HCI_StopHardware (not registered)\n"));
return FALSE;
}
return ERROR_SUCCESS == gCallback (DEVICE_DOWN, NULL);
}
int HCI_SetCallback (HCI_TransportCallback pfCallback) {
gCallback = pfCallback;
if (! HardwareRadio(TRUE))
DebugDeInit();
if (gCallback)
DebugInit();
else
DebugDeInit();
return ERROR_SUCCESS;
}
int HCI_OpenConnection (void) {
IFDBG(DebugOut (DEBUG_HCI_INIT, L"BthGum:HCI_OpenConnection - Started\n"));
DWORD dwHardwareConfig;
DWORD dwBytesReturned;
if (hFile != INVALID_HANDLE_VALUE)
return FALSE;
WCHAR szComPortName[_MAX_PATH];
DWORD dwBaud = 0;
DWORD dwStartBaud = 57600;
HKEY hk;
if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_BASE, L"software\\microsoft\\bluetooth\\hci", 0, KEY_READ, &hk)) {
DWORD dwType;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -