Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed myUSBHost AvailableMemory
Dependents: mbed_TANK_Kinect myBlueUSB_ros ftusbClass
Diff: hci.cpp
- Revision:
- 1:0dde58e0cccf
- Parent:
- 0:81ed8b6e4a8b
- Child:
- 2:0118da9e5169
--- a/hci.cpp Mon Apr 04 16:41:03 2011 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,421 +0,0 @@
-
-/*
-Copyright (c) 2010 Peter Barrett
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "Utils.h"
-#include "hci.h"
-#include "hci_private.h"
-#include "USBHost.h" //for USBLoop
-
-enum hci_callback_evt {
- NONE,
- CONNECT,
- DISCONECT,
- INQUIRYRESULT
-};
-
-#define MAX_BLUETOOTH_ADAPTERS 1
-
-enum StateMask {
- MASK_RESET = 1,
- MASK_READ_BUFFER_SIZE = 2,
- MASK_READ_BD_ADDR = 4,
- MASK_INITED = 8,
- MASK_INQUIRY = 16,
- MASK_REMOTE_NAME = 32,
- MASK_CREATE_CONNECTION = 64
-};
-
-int HCI::Open(HCITransport* transport, HCICallback callback) {
- _transport = transport;
- _transport->Set(this);
- _callback = callback;
- _state = 0;
- for (int i = 0; i < MAX_BTDEVICES; i++) {
- _devices[i].Init();
- _devices[i]._transport = transport;
- }
- cmd_credits = 1;
- return SendCmd(HCI_OP_RESET);
-}
-
-void printf(const BD_ADDR* addr);
-
-BTDevice* HCI::Find(const BD_ADDR* addr) {
- for (int i = 0; i < MAX_BTDEVICES; i++)
- if (_devices[i]._state != 0 && memcmp(addr,&_devices[i]._info.bdaddr,6) == 0)
- return &_devices[i];
- return 0;
-}
-
-BTDevice* HCI::Find(int handle) {
- for (int i = 0; i < MAX_BTDEVICES; i++)
- if (_devices[i]._state != 0 && handle == _devices[i]._handle)
- return &_devices[i];
- return 0;
-}
-//
-bool HCI::Busy() {
- return (_state & (MASK_INQUIRY | MASK_REMOTE_NAME | MASK_CREATE_CONNECTION)) != 0;
-}
-
-int HCI::Inquiry(int duration) {
- _state |= MASK_INQUIRY;
- u8 buf[5];
- buf[0] = 0x33;//LAP=0x9e8b33
- buf[1] = 0x8B;
- buf[2] = 0x9E;
- buf[3] = duration;
- buf[4] = 5; // 5 results
- SendCmd(HCI_OP_INQUIRY,buf,sizeof(buf));
- return 0;
-}
-
-int HCI::SendCmd(int cmd, const u8* params, int len) {
- u8 b[32];
- b[0] = cmd;
- b[1] = (cmd >> 8);
- b[2] = len;
- if (params)
- memcpy(b+3,params,len);
- //printf("%d cmd_credits\n", cmd_credits);
- while (cmd_credits == 0) {
- USBLoop();
- putc('_', stdout);
- }
- _transport->HCISend(b,len+3);
- return 0;
-}
-
-void HCI::OnCommandComplete(int cmd, const u8* data, int len) {
- printf("%04X %s",cmd,CmdStr(cmd));
- if (len < 0)
- return;
- printfBytes(" complete",data,min(16,len));
-
- switch (cmd) {
- // Init phase 0
- case HCI_OP_RESET: // Reset done, init chain to HCI_OP_READ_LOCAL_NAME
- SendCmd(HCI_OP_READ_BUFFER_SIZE);
- _state |= MASK_RESET;
- break;
-
- // Init phase 1
- case HCI_OP_READ_BUFFER_SIZE:
- _acl_mtu = LE16(data);
- _sco_mtu = data[2];
- _acl_max_pkt = LE16(data+3);
- _sco_max_pkt = LE16(data+5);
- printf("acl_mtu=%d, acl_max_pkt=%d\n", _acl_mtu, _acl_max_pkt);
- SendCmd(HCI_OP_READ_BD_ADDR);
- _state |= MASK_READ_BUFFER_SIZE;
- break;
-
- // Init phase 2
- case HCI_OP_READ_BD_ADDR:
- _localAddr = *((BD_ADDR*)data); // Local Address
- _state |= MASK_READ_BD_ADDR;
- _state |= MASK_INITED;
- Callback(CALLBACK_READY,data,6);
- break;
-
- // 0CXX
- case HCI_OP_READ_LOCAL_NAME:
- case HCI_OP_LINK_KEY_NEG_REPLY:
- break;
-
- case HCI_OP_READ_LOCAL_VERSION:
- // params
- //SendCmd(HCI_OP_READ_LOCAL_NAME);
- break;
-
- case HCI_OP_READ_LOCAL_COMMANDS:
- break;
-
- case HCI_OP_READ_LOCAL_FEATURES:
- //SendCmd(HCI_OP_READ_LOCAL_VERSION);
- break;
-
- case HCI_OP_READ_LOCAL_EXT_FEATURES:
- break;
-
- case HCI_OP_PIN_CODE_REPLY:
- printf("Got pin reply\n");
- break;
-
- default:
- printf("Unrecognized Command %04X\n",cmd);
- break;
- }
-}
-
-void HCI::Callback(HCI_CALLBACK_EVENT c, const u8* data, int len) {
- if (_callback) _callback(this,c,data,len);
-// (this->*_callback)(c, data, len);
-}
-
-int HCI::RemoteNameRequest(const BD_ADDR* addr) {
- _state |= MASK_REMOTE_NAME;
- u8 buf[6+4];
- memset(buf,0,sizeof(buf));
- memcpy(buf,addr,6);
- //buf[7] = 1;
- return SendCmd(HCI_OP_REMOTE_NAME_REQ,buf,sizeof(buf));
-}
-int HCI::RemoteNameRequest(inquiry_info *ii) {
- _state |= MASK_REMOTE_NAME;
- u8 buf[6+4];
- //memset(buf,0,sizeof(buf));
- memcpy(buf,&ii->bdaddr,6);
- buf[6] = ii->pscan_rep_mode;
- buf[7] = 0;
- *(unsigned short*)(buf+8) = 0;
- return SendCmd(HCI_OP_REMOTE_NAME_REQ,buf,sizeof(buf));
-}
-
-
-int HCI::CreateConnection(const BD_ADDR* remoteAddr) {
- _state |= MASK_CREATE_CONNECTION;
- u8 buf[6+7];
- memset(buf,0,sizeof(buf));
- memcpy(buf,remoteAddr,6);
- buf[6] = 0x18; // DM1,DH1
- buf[7] = 0xCC; // DM3, DH3, DM5, DH5
- buf[8] = 1; // Page Repetition R1
- return SendCmd(HCI_OP_CREATE_CONN,buf,sizeof(buf));
-}
-
-int HCI::Disconnect(const BD_ADDR* bdaddr) {
- BTDevice* d = Find(bdaddr);
- if (!d)
- return ERR_HCI_DEVICE_NOT_FOUND;
- int handle = d->_handle;
- printf("Disconnect from %d\n",handle);
- _state |= MASK_CREATE_CONNECTION;
- u8 buf[3];
- buf[0] = handle;
- buf[1] = (handle >> 8);
- buf[2] = 0x13;
- return SendCmd(HCI_OP_DISCONNECT,buf,sizeof(buf));
-}
-
-void HCI::DisconnectComplete(int handle) {
- BTDevice* d = Find(handle);
- if (!d)
- return;
- d->_handle = 0;
-}
-
-int HCI::DisconnectAll() {
- BTDevice* devs[8];
- int count = GetDevices(devs,8);
- for (int i = 0; i < count; i++)
- Disconnect(&devs[i]->_info.bdaddr);
- return 0;
-}
-
-int HCI::PinCodeReply(const u8* data, const u8* pin) {
- u8 b[6+1+16];
- memset(b,0,sizeof(b));
- memcpy(b,data,6);
- b[6] = 4;
- memcpy(b+7, pin, 4);
- return SendCmd(HCI_OP_PIN_CODE_REPLY,b,sizeof(b));
-}
-
-void HCI::InquiryResult(const inquiry_info* info) {
- BTDevice* bt = Find(&info->bdaddr);
- if (!bt) { // new device
- for (int i = 0; i < MAX_BTDEVICES; i++) {
- if (_devices[i]._state == 0) {
- bt = _devices + i;
- bt->_state = 1;
- break;
- }
- }
- if (!bt) {
- printf("HCI::InquiryResult too many devices\n");
- return; // Too many devices!
- }
- }
-
- bt->_info = *info;
-}
-
-int HCI::GetDevices(BTDevice** devices, int maxDevices) {
- int j = 0;
- for (int i = 0; i < MAX_BTDEVICES; i++) {
- if (_devices[i]._state != 0) {
- devices[j++] = _devices + i;
- if (j == maxDevices)
- break;
- }
- }
- return j;
-}
-
-void HCI::RemoteName(const BD_ADDR* addr, const char* name) {
- BTDevice* d = Find(addr);
- if (d) {
- strncpy(d->_name,name,sizeof(d->_name)-1);
- d->_name[sizeof(d->_name)-1] = 0;
- }
-}
-
-void HCI::ConnectComplete(const connection_info* info) {
- BTDevice* d = Find(&info->bdaddr);
- if (!d)
- return;
- if (info->status == 0) {
- d->_handle = info->handle;
- printf("Connected on %04X\n",info->handle);
- } else
- printf("Connection failed with %d\n",info->status);
-}
-
-void HCI::HCIRecv(const u8* data, int len) {
- // printfBytes(EvtStr(data[0]),data,min(len,16));
- switch (data[0]) {
- case HCI_EV_INQUIRY_COMPLETE:
- printfBytes("Inquiry Complete",data,data[1]);
- _state &= ~MASK_INQUIRY;
- Callback(CALLBACK_INQUIRY_DONE,0,0);
- break;
-
- case HCI_EV_INQUIRY_RESULT: {
- const u8* end = data[1] + data + 2;
- data += 3;
- while (data < end) {
- inquiry_info align;
- memcpy(&align,data,sizeof(inquiry_info));
- InquiryResult(&align);
- Callback(CALLBACK_INQUIRY_RESULT,(u8*)&align,sizeof(inquiry_info));
- data += 14;
- }
- }
- break;
-
- case HCI_EV_CONN_COMPLETE:
- _state &= ~MASK_CREATE_CONNECTION;
- {
- connection_info align;
- memcpy(&align,data+2,sizeof(connection_info));
- ConnectComplete(&align);
- Callback(CALLBACK_CONNECTION_COMPLETE,(u8*)&align,sizeof(connection_info));
- }
- break;
-
- case HCI_EV_CONN_REQUEST:
- break;
-
- case HCI_EV_DISCONN_COMPLETE:
- DisconnectComplete(LE16(data+3));
- break;
-
- case HCI_EV_REMOTE_NAME: {
- BD_ADDR* addr = (BD_ADDR*)(data+3);
- const char* name = (const char*)(data + 9);
- RemoteName(addr,name);
- }
- Callback(CALLBACK_REMOTE_NAME,data+3,LE16(data+1)); // addr is in here too
- _state &= ~MASK_REMOTE_NAME;
- break;
-
- case HCI_EV_CMD_STATUS: {
- const char* errs = HCIErrStr(data[2]);
- printf("Status %s %s %d cmd pkts\n",CmdStr(LE16(data+4)),errs, data[3]);
- cmd_credits = data[3];
- }
- Callback(CALLBACK_CMD_STATUS, data+2, 4);
- break;
-
- case HCI_EV_CMD_COMPLETE:
- OnCommandComplete(data[3] | (data[4] << 8),data+6,data[1]-4);
- cmd_credits = data[2];
- break;
-
- case HCI_EV_PIN_CODE_REQ:
- Callback(CALLBACK_PIN_REQ, data+2, 6);
- //PinCodeReply(data+2);
- break;
-
- case HCI_EV_LINK_KEY_REQ:
- SendCmd(HCI_OP_LINK_KEY_NEG_REPLY,data+2,6);
- break;
- case HCI_EV_NUM_COMP_PKTS:
- case HCI_EV_LINK_KEY_NOTIFY:
- break;
- default:
-
- printfBytes("HCIRecv:",data,data[1]+2);
- break;
- }
-}
-
-int HCI::Open(SocketInternal* sock, SocketAddrHdr* addr) {
- L2CAPSocket* l2capsock = (L2CAPSocket*)sock;
- L2CAPAddr* l2capaddr = (L2CAPAddr*)addr;
- BTDevice* bt = Find(&l2capaddr->bdaddr);
- if (!bt) {
- printf("Can't open l2cap %d on ",l2capaddr->psm);
- printf(&l2capaddr->bdaddr);
- printf("\n");
- return ERR_HCI_DEVICE_NOT_FOUND;
- }
- l2capsock->btdevice = bt;
- return bt->Open(sock,addr);
-}
-
-int HCI::Send(SocketInternal* sock, const u8* data, int len) {//check here for appropriate buffersize on the device
-//assume acl packet
-#if OFFSET==8 //sizeof ACL/L2CAP is include in data/len
- if (len > _acl_max_pkt)
-#else //OFFSET==0, data is bare application frame
- if (len+8 > _acl_mtu)
-#endif
- { printf("Max outgoing packet(%d) size exceeded, segmenting necessary, pktlen = %d\n", _acl_mtu, len);
- }
- L2CAPSocket* l2capsock = (L2CAPSocket*)sock;
- return l2capsock->btdevice->Send(sock,data,len); // Pointless double dispatch
-}
-
-int HCI::Close(SocketInternal* sock) {
- L2CAPSocket* l2capsock = (L2CAPSocket*)sock;
- return l2capsock->btdevice->Close(sock); // Pointless double dispatch
-}
-
-void HCI::ACLRecv(const u8* data, int len) {
- int handle = LE16(data);
- BTDevice* d = Find(handle & 0x0FFF);
- if (d)
- d->ACLRecv(data,len);
- else
- printfBytes("HCI:ACLRecv ", data, len);
-}
-
-//===================================================================
-//===================================================================