Note: ADK 6

因為網友拿到一塊 CSR/Qualcomm, QCC5120 開發版註記一下東西, 這ADK看起來源自以前的BlueLab, 當然因為Bluetooth/BLE的蓬勃發展, 整個架構變得更大更複雜了, 但是一般如果開發基本的藍芽設備, 實際上已經有完整的template project, 而且用內建的選項它會複製一份code 並且可以直接搭VCS 的SCM tools 不過目前看起來內建選擇是svn與 Perforce, 沒有git 是比較奇怪的

MotherBoard (Carrier Board)
是 CF376
QCC5120 Board
是CFG212
版上的 QSPI 是WINBOND 25Q64FWS16G

編譯Sink Application 要選 HwVariant
QCC5124-AA_DEV-BRD-R2-AA

device name 與bdaddress的pskey 在

$(project)\apps\applications\sink\qcc512x_qcc302x\common\subsys1_config2.htf

基礎的設定要讀

80_CG040_1_AD_ADK_6_X_AUDIO_SINK_APPLICATION_USER_.pdf

廣告

Note: Android Bluetooth HCI Req.

Android 從 4.3 開始導入 Bluetooth Low Energy, 但是因為總總原因API 直到5.0之後才算相對穩定, 所以想要在Android 導入BLE相關應用最好是 Android 5.0 and later 當然現在2018年應該不是啥大問題了, 但是個人覺的真的要有成果要等Android Oreo (8.0)普及後才會比較廣泛的使用到新的Bluetooth 5 的新增的功能.
之前有遇過使用的Bluethooth module 對BLE支援有問題的情況, 這時要依據module 支援的BT版本與使用的Android 版本去驗證, Android 有提供HCI Requirements 文件可以使用

分別是 Android 5.0 HCI Requirements , Android 6.0 HCI Requirements , 然後現在線上版本的Oreo

ref.

Note: GATT service with Bluetooth Low Energy

傳統的Bluetooth Device 透過 SDP service 使用Profile UUID 去讓兩者相連, 但是BLE則擴充了這個方法, 透過提供 GATT (Generic Attributes) Profile 去取代 SDP的功能,使用GATT Service 內的 Service/Characteristics 功能可以更方便跟分類各種服務跟屬性值, 並且透過GATT 可以自我宣告特定應用的Service與Characteristics 去創建自己的特殊應用 常見有iBeacon/Eddystone Beacon 或是 像是 TI SensorTags 可以參考這個 Andorid Source 去使用Ti 自定義的Barometers service

官方說法 from https://www.bluetooth.com/specifications/profiles-overview
For two Bluetooth devices to be compatible, they must support the same profiles. And while profiles generally describe the same use case behaviors, they are different for Bluetooth BR/EDR and Bluetooth Low Energy (LE) implementations. Compatibility between Bluetooth BR/EDR and Bluetooth LE implementations requires a dual-mode controller on at least one. For BR/EDR, a wide range of adopted Bluetooth profiles describe many different, commonly used types of applications or use cases for devices. For Bluetooth LE, developers can use a comprehensive set of adopted profiles, or they can use Generic Attribute Profile (GATT) to create new profiles. This flexibility helps support innovative new applications that maintain interoperability with other Bluetooth devices.

Get Bluetooth Dongle Address for WINCE 5.0/WM5/WM6

Just need 2 step.

  1. Get “BTD0:" handle
  2. Call DeviceIOControl, ReadLocalAddr (14)
BOOL GetBTH_ADDR(BT_ADDR *btaddr)
{
	HANDLE hDev = INVALID_HANDLE_VALUE;

	unsigned buff[8];

	memset(buff, 0, sizeof(buff));

	*btaddr = 0;

	hDev = CreateFile(L"BTD0:", GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_READ | FILE_SHARE_WRITE,
		NULL,
		OPEN_EXISTING,
		0,
		NULL);

	if (hDev == INVALID_HANDLE_VALUE)
	{
		return FALSE;
	}

#define BT_IOCTL_ReadLocalAddr 14

	int iErr = DeviceIoControl(hDev, BT_IOCTL_ReadLocalAddr, &buff, sizeof(buff), NULL, NULL, NULL, NULL);
	CloseHandle(hDev);
	hDev = INVALID_HANDLE_VALUE;

	if (iErr)
	{
		*btaddr = *((BT_ADDR*)buff);
		return TRUE;
	}

	return FALSE;
}

static WCHAR NUM2HEX(UINT i)
{
	const WCHAR idx[] = { L'0', L'1', L'2', L'3',
			L'4', L'5', L'6', L'7',
			L'8', L'9', L'A', L'B',
			L'C', L'D', L'E', L'F' };
	i &= 0xF;
	return idx[i];
/*
	if (i < 10)
	 return i + L'0';

	i -= 10;
	return i + L'A';
*/
}

static WCHAR LOBYTE2WC(const UCHAR x)
{
	return NUM2HEX(x & 0x0F);
}

static WCHAR HIBYTE2WC(const UCHAR x)
{
	return NUM2HEX(x>>4);
}

void BTADDR2WC(WCHAR* buff, BT_ADDR _btAddr, UINT sz)
{
	BYTE *pB = (BYTE*)&_btAddr+5;
	UINT i = 0;

	if (sz < (6*3 + 1))
		return;

	do
	{
		buff[i*3]=HIBYTE2WC(*(pB-i));
		buff[i*3+1]=LOBYTE2WC(*(pB-i));
		buff[i*3+2]=L':';
	} while (++i < 6);
	buff[i*3-1] = L'/0';
}

Bluetooth Service UUID List

今天找了一下 關於 Bluetooth 的標準 Service/Profile 的 UUID ,但是看了一下 Specification Doucments 都只有 16bits 長,這是所謂的UUID16格式

後來才了解,原來Bluetooth 將UUID 的部份固定,只取16bits 作為各種 Service 的區分,這樣可以節省分析 SDP Record and 與程式空間,避免增加 Bluetooth Device 的成本。

底下的值可以從 windows XP or Server 2003 SDK 的 bt_sdp.h or BlueZ 的 sdp.h(UUID16) 中找到定義,可以觀察出 下列的固定序列除了替換 XXXX部份

‘{0000xxxx-0000-1000-8000-00805F9B34FB}’,而XXXX 部份就是 所謂的 UUID16 定義。

Protocols UUID http://www.bluetooth.org/Technical/AssignedNumbers/service_discovery.htm
BASE UUID 00000000-0000-1000-8000-00805F9B34FB
SDP_PROTOCOL_UUID         = '{00000001-0000-1000-8000-00805F9B34FB}';
UDP_PROTOCOL_UUID         = '{00000002-0000-1000-8000-00805F9B34FB}';
RFCOMM_PROTOCOL_UUID      = '{00000003-0000-1000-8000-00805F9B34FB}';
TCP_PROTOCOL_UUID         = '{00000004-0000-1000-8000-00805F9B34FB}';
TCSBIN_PROTOCOL_UUID      = '{00000005-0000-1000-8000-00805F9B34FB}';
TCSAT_PROTOCOL_UUID       = '{00000006-0000-1000-8000-00805F9B34FB}';
OBEX_PROTOCOL_UUID        = '{00000008-0000-1000-8000-00805F9B34FB}';
IP_PROTOCOL_UUID          = '{00000009-0000-1000-8000-00805F9B34FB}';
FTP_PROTOCOL_UUID         = '{0000000A-0000-1000-8000-00805F9B34FB}';
HTTP_PROTOCOL_UUID        = '{0000000C-0000-1000-8000-00805F9B34FB}';
WSP_PROTOCOL_UUID         = '{0000000E-0000-1000-8000-00805F9B34FB}';
BNEP_PROTOCOL_UUID        = '{0000000F-0000-1000-8000-00805F9B34FB}';
UPNP_PROTOCOL_UUID        = '{00000010-0000-1000-8000-00805F9B34FB}';
HID_PROTOCOL_UUID         = '{00000011-0000-1000-8000-00805F9B34FB}';
HCCC_PROTOCOL_UUID        = '{00000012-0000-1000-8000-00805F9B34FB}';
HCDC_PROTOCOL_UUID        = '{00000014-0000-1000-8000-00805F9B34FB}';
HN_PROTOCOL_UUID          = '{00000016-0000-1000-8000-00805F9B34FB}';
AVCTP_PROTOCOL_UUID       = '{00000017-0000-1000-8000-00805F9B34FB}';
AVDTP_PROTOCOL_UUID       = '{00000019-0000-1000-8000-00805F9B34FB}';
CMPT_PROTOCOL_UUID        = '{0000001B-0000-1000-8000-00805F9B34FB}';
UDI_C_PLANE_PROTOCOL_UUID = '{0000001D-0000-1000-8000-00805F9B34FB}';
L2CAP_PROTOCOL_UUID       = '{00000100-0000-1000-8000-00805F9B34FB}';
Ref. Service class IDs http://www.bluetooth.org/Technical/AssignedNumbers/service_discovery.htm
ServiceDiscoveryServerServiceClassID_UUID       = '{00001000-0000-1000-8000-00805F9B34FB}';
BrowseGroupDescriptorServiceClassID_UUID        = '{00001001-0000-1000-8000-00805F9B34FB}';
PublicBrowseGroupServiceClass_UUID              = '{00001002-0000-1000-8000-00805F9B34FB}';
SerialPortServiceClass_UUID                     = '{00001101-0000-1000-8000-00805F9B34FB}';
LANAccessUsingPPPServiceClass_UUID              = '{00001102-0000-1000-8000-00805F9B34FB}';
DialupNetworkingServiceClass_UUID               = '{00001103-0000-1000-8000-00805F9B34FB}';
IrMCSyncServiceClass_UUID                       = '{00001104-0000-1000-8000-00805F9B34FB}';
OBEXObjectPushServiceClass_UUID                 = '{00001105-0000-1000-8000-00805F9B34FB}';
OBEXFileTransferServiceClass_UUID               = '{00001106-0000-1000-8000-00805F9B34FB}';
IrMCSyncCommandServiceClass_UUID                = '{00001107-0000-1000-8000-00805F9B34FB}';
HeadsetServiceClass_UUID                        = '{00001108-0000-1000-8000-00805F9B34FB}';
CordlessTelephonyServiceClass_UUID              = '{00001109-0000-1000-8000-00805F9B34FB}';
AudioSourceServiceClass_UUID                    = '{0000110A-0000-1000-8000-00805F9B34FB}';
AudioSinkServiceClass_UUID                      = '{0000110B-0000-1000-8000-00805F9B34FB}';
AVRemoteControlTargetServiceClass_UUID          = '{0000110C-0000-1000-8000-00805F9B34FB}';
AdvancedAudioDistributionServiceClass_UUID      = '{0000110D-0000-1000-8000-00805F9B34FB}';
AVRemoteControlServiceClass_UUID                = '{0000110E-0000-1000-8000-00805F9B34FB}';
VideoConferencingServiceClass_UUID              = '{0000110F-0000-1000-8000-00805F9B34FB}';
IntercomServiceClass_UUID                       = '{00001110-0000-1000-8000-00805F9B34FB}';
FaxServiceClass_UUID                            = '{00001111-0000-1000-8000-00805F9B34FB}';
HeadsetAudioGatewayServiceClass_UUID            = '{00001112-0000-1000-8000-00805F9B34FB}';
WAPServiceClass_UUID                            = '{00001113-0000-1000-8000-00805F9B34FB}';
WAPClientServiceClass_UUID                      = '{00001114-0000-1000-8000-00805F9B34FB}';
PANUServiceClass_UUID                           = '{00001115-0000-1000-8000-00805F9B34FB}';
NAPServiceClass_UUID                            = '{00001116-0000-1000-8000-00805F9B34FB}';
GNServiceClass_UUID                             = '{00001117-0000-1000-8000-00805F9B34FB}';
DirectPrintingServiceClass_UUID                 = '{00001118-0000-1000-8000-00805F9B34FB}';
ReferencePrintingServiceClass_UUID              = '{00001119-0000-1000-8000-00805F9B34FB}';
ImagingServiceClass_UUID                        = '{0000111A-0000-1000-8000-00805F9B34FB}';
ImagingResponderServiceClass_UUID               = '{0000111B-0000-1000-8000-00805F9B34FB}';
ImagingAutomaticArchiveServiceClass_UUID        = '{0000111C-0000-1000-8000-00805F9B34FB}';
ImagingReferenceObjectsServiceClass_UUID        = '{0000111D-0000-1000-8000-00805F9B34FB}';
HandsfreeServiceClass_UUID                      = '{0000111E-0000-1000-8000-00805F9B34FB}';
HandsfreeAudioGatewayServiceClass_UUID          = '{0000111F-0000-1000-8000-00805F9B34FB}';
DirectPrintingReferenceObjectsServiceClass_UUID = '{00001120-0000-1000-8000-00805F9B34FB}';
ReflectedUIServiceClass_UUID                    = '{00001121-0000-1000-8000-00805F9B34FB}';
BasicPringingServiceClass_UUID                  = '{00001122-0000-1000-8000-00805F9B34FB}';
PrintingStatusServiceClass_UUID                 = '{00001123-0000-1000-8000-00805F9B34FB}';
HumanInterfaceDeviceServiceClass_UUID           = '{00001124-0000-1000-8000-00805F9B34FB}';
HardcopyCableReplacementServiceClass_UUID       = '{00001125-0000-1000-8000-00805F9B34FB}';
HCRPrintServiceClass_UUID                       = '{00001126-0000-1000-8000-00805F9B34FB}';
HCRScanServiceClass_UUID                        = '{00001127-0000-1000-8000-00805F9B34FB}';
CommonISDNAccessServiceClass_UUID               = '{00001128-0000-1000-8000-00805F9B34FB}';
VideoConferencingGWServiceClass_UUID            = '{00001129-0000-1000-8000-00805F9B34FB}';
UDIMTServiceClass_UUID                          = '{0000112A-0000-1000-8000-00805F9B34FB}';
UDITAServiceClass_UUID                          = '{0000112B-0000-1000-8000-00805F9B34FB}';
AudioVideoServiceClass_UUID                     = '{0000112C-0000-1000-8000-00805F9B34FB}';
PnPInformationServiceClass_UUID                 = '{00001200-0000-1000-8000-00805F9B34FB}';
GenericNetworkingServiceClass_UUID              = '{00001201-0000-1000-8000-00805F9B34FB}';
GenericFileTransferServiceClass_UUID            = '{00001202-0000-1000-8000-00805F9B34FB}';
GenericAudioServiceClass_UUID                   = '{00001203-0000-1000-8000-00805F9B34FB}';
GenericAudioServiceClass_UUID                   = '{00001203-0000-1000-8000-00805F9B34FB}';
GenericTelephonyServiceClass_UUID               = '{00001204-0000-1000-8000-00805F9B34FB}';
UPnPServiceClass_UUID                           = '{00001205-0000-1000-8000-00805F9B34FB}';
UPnPIpServiceClass_UUID                         = '{00001206-0000-1000-8000-00805F9B34FB}';
ESdpUPnPIpPanServiceClass_UUID                  = '{00001300-0000-1000-8000-00805F9B34FB}';
ESdpUPnPIpLapServiceClass_UUID                  = '{00001301-0000-1000-8000-00805F9B34FB}';
EdpUPnpIpL2CAPServiceClass_UUID                 = '{00001302-0000-1000-8000-00805F9B34FB}';
Technorati tags: , , , , 

ref. An Introduction to Bluetooth programming in GNU/Linux – Chapter 4. Bluetooth programming in C with BlueZ
4.4. Service Discovery Protocol

CSR HCI Extension Packet

CSR使用一個 HCI Extension 包裹 其 BCCMD 命令
基本的結構就是 OGF: 0x03F, OCF:0x00 => OpCode:0xFC00
BYTE cmdArray[] = { 0x00, 0x0FC, parameters total length, payload description, payload };
其 HCI_EVENT 則為下列結構

BYTE eventArray[] = {0xFF, parameters total length, payload decription, payload };


Payload Description
MSB
  • bit 7, Last Fragment
  • bit 6, First Fragment
  • bit 5~0, Channel ID
LSB
refer CSR HCI Extensions, July 2004.

 


而BCCMD 使用 Channel 2,BCCMD 基本結構是 是被 CSR 稱為 Message,由 5 個 UINT 16bits 的Head 開始

  • Type
    • GETREQ, 0x0000
    • GETRESP, 0x0001
    • SETREQ, 0x0002
  • Length, 整個 Message 的長度
  • Seq. No
  • Varid, 用來識別 CSR 內部獨特的資料庫 像是 PS Key 等, 0x0000 代表沒有使用
  • Status, 在 GETREQ 與 SETREQ 永遠是 0x0000(0K)
    • OK, 0x0000
    • NO_SUCH_VARID, 0x0001
    • TO_BIG, 0x0002
    • NO_VALUE, 0x0003
    • BAD_REG, 0x0004
    • NO_ACCESS, 0x0005
    • READ_ONLY, 0x0006
    • WRITE_ONLY, 0x0007
    • ERROR, 0x0008
    • PERMISSION_DENIED, 0x0009

一個設定Radio TX testing 範例就是如下

Host –> BlueCore(SETREQ)

    1. BCCMD. TYPE:  SETREQ(0x0002)
    2. BCCMD. LENGTH:  0x0009
    3. BCCMD. SEQ_NO:  ANY from HOST
    4. BCCMD. VARID:  RADIO_TEST(0x5004 or 20484)
    5. BCCMD. STATUS: OK(0x0000)
    6. BCCMD. RADIO_TEST.TYPE: TX_START (0x0001)
    7. BCCMD. RADIO_TEST.TX_START.FREQUENCY(2402 ~ 2495) (Mhz)
    8. BCCMD. RADIO_TEST.TX AMP. default (0xff32)
    9. BCCMD. RADIO_TEST.MODULATION: default (0x0000)

BYTE bccmd[18] = { 0x02, 0x00, 0x09, 0x00, 0x01, 0x00, 0x04, 0x05, 0x00, 0x00, 0x01, 0x00, 0x62, 0x09, 0x32, 0xFF, 0x00, 0x00};

BYTE hci_cmd[] = { 0x00, 0xFC, 19, 0x02, include bccmd};

BlueCore –> Host (GETRESP)

    1. BCCMD. TYPE:  GETRESP(0x0001)
    2. BCCMD. LENGTH:  0x0009
    3. BCCMD. SEQ_NO:  same SETREQ
    4. BCCMD. VARID:  RADIO_TEST(0x5004 or 20484)
    5. BCCMD. STATUS: OK(0x0000)
    6. BCCMD. RADIO_TEST.TYPE: TX_START (0x0001)
    7. BCCMD. RADIO_TEST.TX_START.FREQUENCY(2402 ~ 2495) (Mhz)
    8. BCCMD. RADIO_TEST.TX AMP. default (0xff32)
    9. BCCMD. RADIO_TEST.MODULATION: default (0x0000)

BYTE hci_event[] = { 0xFF, 19, 0x02, 0x01, 0x00, 0x09, 0x01, 0x00, 0x04, 0x05, 0x00, 0x00, 0x01, 0x00, 0x62, 0x09, 0x32, 0xff, 0x00, 0x00 };