Test version of BlueUSB stack. Includes SDP and RFCOMM. As Client it allows to connect to my fischertechnik TX Controller. As Server it echo\\\\\\\'s characters to Putty. PIN=1234

Dependencies:   mbed myUSBHost AvailableMemory

Dependents:   mbed_TANK_Kinect myBlueUSB_ros ftusbClass

Committer:
networker
Date:
Sat Jun 11 19:43:00 2011 +0000
Revision:
5:378c208637e3
Parent:
2:0118da9e5169

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
networker 2:0118da9e5169 1
networker 2:0118da9e5169 2 /*
networker 2:0118da9e5169 3 Copyright (c) 2010 Peter Barrett
networker 2:0118da9e5169 4
networker 2:0118da9e5169 5 Permission is hereby granted, free of charge, to any person obtaining a copy
networker 2:0118da9e5169 6 of this software and associated documentation files (the "Software"), to deal
networker 2:0118da9e5169 7 in the Software without restriction, including without limitation the rights
networker 2:0118da9e5169 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
networker 2:0118da9e5169 9 copies of the Software, and to permit persons to whom the Software is
networker 2:0118da9e5169 10 furnished to do so, subject to the following conditions:
networker 2:0118da9e5169 11
networker 2:0118da9e5169 12 The above copyright notice and this permission notice shall be included in
networker 2:0118da9e5169 13 all copies or substantial portions of the Software.
networker 2:0118da9e5169 14
networker 2:0118da9e5169 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
networker 2:0118da9e5169 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
networker 2:0118da9e5169 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
networker 2:0118da9e5169 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
networker 2:0118da9e5169 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
networker 2:0118da9e5169 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
networker 2:0118da9e5169 21 THE SOFTWARE.
networker 2:0118da9e5169 22 */
networker 2:0118da9e5169 23
networker 2:0118da9e5169 24 #include <stdio.h>
networker 2:0118da9e5169 25 #include <stdlib.h>
networker 2:0118da9e5169 26 #include <stdio.h>
networker 2:0118da9e5169 27 #include <string.h>
networker 2:0118da9e5169 28
networker 2:0118da9e5169 29 #include "Utils.h"
networker 2:0118da9e5169 30 #include "hci.h"
networker 2:0118da9e5169 31 #include "hci_private.h"
networker 2:0118da9e5169 32 #include "USBHost.h" //for USBLoop
networker 2:0118da9e5169 33 #include "HCITransportUSB.h" //for ACL/HCL buffer size
networker 5:378c208637e3 34 #include "neighbourhood.h"
networker 5:378c208637e3 35
networker 5:378c208637e3 36 extern const char FtDevClass[];
networker 5:378c208637e3 37 const char FtDevClass[3] = {0x00, 0x1F, 0x82 };
networker 2:0118da9e5169 38
networker 2:0118da9e5169 39 enum hci_callback_evt {
networker 2:0118da9e5169 40 NONE,
networker 2:0118da9e5169 41 CONNECT,
networker 2:0118da9e5169 42 DISCONECT,
networker 2:0118da9e5169 43 INQUIRYRESULT
networker 2:0118da9e5169 44 };
networker 2:0118da9e5169 45
networker 2:0118da9e5169 46 #define MAX_BLUETOOTH_ADAPTERS 1
networker 2:0118da9e5169 47
networker 2:0118da9e5169 48 enum StateMask {
networker 2:0118da9e5169 49 MASK_RESET = 1,
networker 2:0118da9e5169 50 MASK_READ_BUFFER_SIZE = 2,
networker 2:0118da9e5169 51 MASK_READ_BD_ADDR = 4,
networker 2:0118da9e5169 52 MASK_INITED = 8,
networker 2:0118da9e5169 53 MASK_INQUIRY = 16,
networker 2:0118da9e5169 54 MASK_REMOTE_NAME = 32,
networker 2:0118da9e5169 55 MASK_CREATE_CONNECTION = 64
networker 2:0118da9e5169 56 };
networker 2:0118da9e5169 57
networker 5:378c208637e3 58 //static const u8 local_name[] = "MBED";
networker 5:378c208637e3 59 static const u8 local_name[] = "ROBO TX-599";
networker 2:0118da9e5169 60
networker 2:0118da9e5169 61 int HCI::Open(HCITransport* transport, HCICallback callback) {
networker 2:0118da9e5169 62 _transport = transport;
networker 2:0118da9e5169 63 _transport->Set(this);
networker 2:0118da9e5169 64 _callback = callback;
networker 2:0118da9e5169 65 _state = 0;
networker 2:0118da9e5169 66 for (int i = 0; i < MAX_BTDEVICES; i++) {
networker 2:0118da9e5169 67 _devices[i].Init();
networker 2:0118da9e5169 68 _devices[i]._transport = transport;
networker 2:0118da9e5169 69 }
networker 2:0118da9e5169 70 #ifdef COMMAND_FLOW
networker 2:0118da9e5169 71 cmd_credits = 1;
networker 2:0118da9e5169 72 #endif
networker 2:0118da9e5169 73 return SendCmd(HCI_OP_RESET);
networker 2:0118da9e5169 74 }
networker 2:0118da9e5169 75
networker 2:0118da9e5169 76 void printf(const BD_ADDR* addr);
networker 2:0118da9e5169 77
networker 2:0118da9e5169 78 BTDevice* HCI::Find(const BD_ADDR* addr) {
networker 2:0118da9e5169 79 for (int i = 0; i < MAX_BTDEVICES; i++)
networker 2:0118da9e5169 80 if (_devices[i]._state != 0 && memcmp(addr,&_devices[i]._info.bdaddr,6) == 0)
networker 2:0118da9e5169 81 return &_devices[i];
networker 2:0118da9e5169 82 return 0;
networker 2:0118da9e5169 83 }
networker 2:0118da9e5169 84
networker 2:0118da9e5169 85 BTDevice* HCI::Find(int handle) {
networker 2:0118da9e5169 86 for (int i = 0; i < MAX_BTDEVICES; i++)
networker 2:0118da9e5169 87 if (_devices[i]._state != 0 && handle == _devices[i]._handle)
networker 2:0118da9e5169 88 return &_devices[i];
networker 2:0118da9e5169 89 return 0;
networker 2:0118da9e5169 90 }
networker 2:0118da9e5169 91
networker 2:0118da9e5169 92 //reports that some commands are still in progress
networker 2:0118da9e5169 93 bool HCI::Busy() {
networker 2:0118da9e5169 94 return (_state & (MASK_INQUIRY | MASK_REMOTE_NAME | MASK_CREATE_CONNECTION)) != 0;
networker 2:0118da9e5169 95 }
networker 2:0118da9e5169 96
networker 2:0118da9e5169 97 int HCI::Inquiry(int duration) {
networker 2:0118da9e5169 98 _state |= MASK_INQUIRY;
networker 2:0118da9e5169 99 u8 buf[5];
networker 2:0118da9e5169 100 buf[0] = 0x33;//LAP=0x9e8b33
networker 2:0118da9e5169 101 buf[1] = 0x8B;
networker 2:0118da9e5169 102 buf[2] = 0x9E;
networker 2:0118da9e5169 103 buf[3] = duration;
networker 2:0118da9e5169 104 buf[4] = 5; // 5 results
networker 2:0118da9e5169 105 SendCmd(HCI_OP_INQUIRY,buf,sizeof(buf));
networker 2:0118da9e5169 106 return 0;
networker 2:0118da9e5169 107 }
networker 2:0118da9e5169 108
networker 2:0118da9e5169 109 int HCI::SendCmd(int cmd, const u8* params, int len) {
networker 2:0118da9e5169 110 u8 b[256];
networker 2:0118da9e5169 111 b[0] = cmd;
networker 2:0118da9e5169 112 b[1] = (cmd >> 8);
networker 2:0118da9e5169 113 b[2] = len;
networker 2:0118da9e5169 114 if (params)
networker 2:0118da9e5169 115 memcpy(b+3,params,len);
networker 2:0118da9e5169 116 #ifdef COMMAND_FLOW
networker 2:0118da9e5169 117 //printf("%d cmd_credits\n", cmd_credits);
networker 2:0118da9e5169 118 while (cmd_credits == 0) {//blocks when command credits run out
networker 2:0118da9e5169 119 USBLoop();
networker 2:0118da9e5169 120 putc('_', stdout);
networker 2:0118da9e5169 121 }
networker 2:0118da9e5169 122 #endif
networker 2:0118da9e5169 123 _transport->HCISend(b,len+3);
networker 2:0118da9e5169 124 return 0;
networker 2:0118da9e5169 125 }
networker 2:0118da9e5169 126
networker 2:0118da9e5169 127 void HCI::OnCommandComplete(int cmd, const u8* data, int len) {//data is exclusive the status byte
networker 2:0118da9e5169 128 //printf("%04X %s",cmd,CmdStr(cmd));
networker 2:0118da9e5169 129 if (len < 0)
networker 2:0118da9e5169 130 return;
networker 2:0118da9e5169 131 //printfBytes(" complete",data,len/*min(16,len)*/);
networker 2:0118da9e5169 132
networker 2:0118da9e5169 133 switch (cmd) {
networker 2:0118da9e5169 134 case 0: //NOP
networker 2:0118da9e5169 135 printf("Received NOP command (for cmd_credits)\n");
networker 2:0118da9e5169 136 break;
networker 2:0118da9e5169 137 // Init phase 0
networker 2:0118da9e5169 138 case HCI_OP_RESET: // Reset done, init chain to HCI_OP_READ_LOCAL_NAME
networker 2:0118da9e5169 139 SendCmd(HCI_OP_READ_BUFFER_SIZE);
networker 2:0118da9e5169 140 _state |= MASK_RESET;
networker 2:0118da9e5169 141 break;
networker 2:0118da9e5169 142
networker 2:0118da9e5169 143 // Init phase 1
networker 2:0118da9e5169 144 case HCI_OP_READ_BUFFER_SIZE:
networker 2:0118da9e5169 145 _acl_mtu = LE16(data);
networker 2:0118da9e5169 146 _sco_mtu = data[2];
networker 2:0118da9e5169 147 _acl_max_pkt = LE16(data+3);
networker 2:0118da9e5169 148 _sco_max_pkt = LE16(data+5);
networker 2:0118da9e5169 149 printf("acl_mtu=%d, acl_max_pkt=%d\n", _acl_mtu, _acl_max_pkt);
networker 2:0118da9e5169 150 #ifdef HOST_CONTR_FLOW
networker 2:0118da9e5169 151 _transport->data_credits = _acl_max_pkt;
networker 2:0118da9e5169 152 _transport->_acl_mtu = _acl_mtu;
networker 2:0118da9e5169 153 #endif
networker 2:0118da9e5169 154 SendCmd(HCI_OP_READ_BD_ADDR);
networker 2:0118da9e5169 155 _state |= MASK_READ_BUFFER_SIZE;
networker 2:0118da9e5169 156 break;
networker 2:0118da9e5169 157
networker 2:0118da9e5169 158 // Init phase 2
networker 2:0118da9e5169 159 case HCI_OP_READ_BD_ADDR:
networker 2:0118da9e5169 160 _localAddr = *((BD_ADDR*)data); // Local Address
networker 2:0118da9e5169 161 _state |= MASK_READ_BD_ADDR;
networker 2:0118da9e5169 162 _state |= MASK_INITED;
networker 2:0118da9e5169 163 {
networker 2:0118da9e5169 164 #ifdef CONTR_HOST_FLOW
networker 2:0118da9e5169 165 unsigned char param[7];
networker 2:0118da9e5169 166 param[0] = (u8)(MAX_ACL_SIZE-8);
networker 2:0118da9e5169 167 param[1] = (u8)((MAX_ACL_SIZE-8)>>8);
networker 2:0118da9e5169 168 param[2] = 0;//MAX_HCL_SIZE-8;
networker 2:0118da9e5169 169 param[3] = 10;
networker 2:0118da9e5169 170 param[4] = 0; //1 ACL buffer
networker 2:0118da9e5169 171 param[5] = 0;
networker 2:0118da9e5169 172 param[6] = 0; //0 Synchronous buffers
networker 2:0118da9e5169 173 SendCmd(HCI_OP_HOST_BUFFER_SIZE, param, 7);
networker 2:0118da9e5169 174 const unsigned char flow = 1;//ACL on, Synchonous off
networker 5:378c208637e3 175 SendCmd(HCI_OP_CONTR_TO_HOST_FLOW, &flow, 1);
networker 5:378c208637e3 176 #endif
networker 2:0118da9e5169 177 const unsigned char scan_enable = 3;
networker 2:0118da9e5169 178 SendCmd(HCI_OP_WRITE_SCAN_ENABLE, &scan_enable, 1);
networker 5:378c208637e3 179 SendCmd(HCI_OP_WRITE_CLASS_OF_DEV, (const u8*)FtDevClass, 3);
networker 5:378c208637e3 180 //SendCmd(HCI_OP_READ_LOCAL_VERSION, 0, 0);
networker 2:0118da9e5169 181 SendCmd(HCI_OP_WRITE_LOCAL_NAME, local_name, 248);
networker 2:0118da9e5169 182 }
networker 2:0118da9e5169 183 Callback(CALLBACK_READY,data,6);
networker 2:0118da9e5169 184 break;
networker 2:0118da9e5169 185
networker 2:0118da9e5169 186 // 0CXX
networker 2:0118da9e5169 187 case HCI_OP_READ_LOCAL_NAME:
networker 2:0118da9e5169 188 case HCI_OP_LINK_KEY_NEG_REPLY:
networker 2:0118da9e5169 189 case HCI_OP_WRITE_SCAN_ENABLE:
networker 2:0118da9e5169 190 case HCI_OP_WRITE_LOCAL_NAME:
networker 2:0118da9e5169 191 break;
networker 2:0118da9e5169 192 #ifdef CONTR_HOST_FLOW
networker 2:0118da9e5169 193 case HCI_OP_CONTR_TO_HOST_FLOW:
networker 2:0118da9e5169 194 case HCI_OP_HOST_BUFFER_SIZE:
networker 2:0118da9e5169 195 break;
networker 2:0118da9e5169 196 case HCI_OP_NUM_COMP_PKTS:
networker 2:0118da9e5169 197 printf("Host number of Completed Packets: Invalid HCI Command Parameter\n");
networker 2:0118da9e5169 198 break;
networker 2:0118da9e5169 199 #endif
networker 2:0118da9e5169 200 case HCI_OP_READ_LOCAL_VERSION:
networker 2:0118da9e5169 201 // params
networker 2:0118da9e5169 202 //SendCmd(HCI_OP_READ_LOCAL_NAME);
networker 2:0118da9e5169 203 break;
networker 2:0118da9e5169 204
networker 2:0118da9e5169 205 case HCI_OP_READ_LOCAL_COMMANDS:
networker 2:0118da9e5169 206 break;
networker 2:0118da9e5169 207
networker 2:0118da9e5169 208 case HCI_OP_READ_LOCAL_FEATURES:
networker 2:0118da9e5169 209 //SendCmd(HCI_OP_READ_LOCAL_VERSION);
networker 2:0118da9e5169 210 break;
networker 2:0118da9e5169 211
networker 2:0118da9e5169 212 case HCI_OP_READ_LOCAL_EXT_FEATURES:
networker 2:0118da9e5169 213 break;
networker 2:0118da9e5169 214
networker 2:0118da9e5169 215 case HCI_OP_PIN_CODE_REPLY:
networker 2:0118da9e5169 216 printf("Got pin reply\n");
networker 2:0118da9e5169 217 break;
networker 5:378c208637e3 218 case HCI_READ_STORED_LINK_KEY:
networker 5:378c208637e3 219 neighbors->set_cap(LE16(data), LE16(data+2));
networker 5:378c208637e3 220 break;
networker 2:0118da9e5169 221
networker 2:0118da9e5169 222 default:
networker 2:0118da9e5169 223 printf("Unrecognized Command Completion %04X\n",cmd);
networker 2:0118da9e5169 224 break;
networker 2:0118da9e5169 225 }
networker 2:0118da9e5169 226 }
networker 2:0118da9e5169 227
networker 2:0118da9e5169 228 void HCI::Callback(HCI_CALLBACK_EVENT c, const u8* data, int len) {
networker 2:0118da9e5169 229 if (_callback) _callback(this,c,data,len);
networker 2:0118da9e5169 230 // (this->*_callback)(c, data, len);
networker 2:0118da9e5169 231 }
networker 2:0118da9e5169 232
networker 2:0118da9e5169 233 int HCI::RemoteNameRequest(const BD_ADDR* addr) {
networker 2:0118da9e5169 234 _state |= MASK_REMOTE_NAME;
networker 2:0118da9e5169 235 u8 buf[6+4];
networker 2:0118da9e5169 236 memset(buf,0,sizeof(buf));
networker 2:0118da9e5169 237 memcpy(buf,addr,6);
networker 2:0118da9e5169 238 //buf[7] = 1;
networker 2:0118da9e5169 239 return SendCmd(HCI_OP_REMOTE_NAME_REQ,buf,sizeof(buf));
networker 2:0118da9e5169 240 }
networker 2:0118da9e5169 241
networker 2:0118da9e5169 242 int HCI::RemoteNameRequest(inquiry_info *ii) {
networker 2:0118da9e5169 243 _state |= MASK_REMOTE_NAME;
networker 2:0118da9e5169 244 u8 buf[6+4];
networker 2:0118da9e5169 245 //memset(buf,0,sizeof(buf));
networker 2:0118da9e5169 246 memcpy(buf,&ii->bdaddr,6);
networker 2:0118da9e5169 247 buf[6] = ii->pscan_rep_mode;
networker 2:0118da9e5169 248 buf[7] = 0;
networker 2:0118da9e5169 249 *(unsigned short*)(buf+8) = 0;
networker 2:0118da9e5169 250 return SendCmd(HCI_OP_REMOTE_NAME_REQ,buf,sizeof(buf));
networker 2:0118da9e5169 251 }
networker 2:0118da9e5169 252
networker 2:0118da9e5169 253 int HCI::CreateConnection(const BD_ADDR* remoteAddr) {
networker 2:0118da9e5169 254 _state |= MASK_CREATE_CONNECTION;
networker 2:0118da9e5169 255 u8 buf[6+7];
networker 2:0118da9e5169 256 memset(buf,0,sizeof(buf));
networker 2:0118da9e5169 257 memcpy(buf,remoteAddr,6);
networker 2:0118da9e5169 258 buf[6] = 0x18; // DM1,DH1
networker 2:0118da9e5169 259 buf[7] = 0xCC; // DM3, DH3, DM5, DH5
networker 2:0118da9e5169 260 buf[8] = 1; // Page Repetition R1
networker 2:0118da9e5169 261 return SendCmd(HCI_OP_CREATE_CONN,buf,sizeof(buf));
networker 2:0118da9e5169 262 }
networker 2:0118da9e5169 263
networker 2:0118da9e5169 264 int HCI::Disconnect(const BD_ADDR* bdaddr) {
networker 2:0118da9e5169 265 BTDevice* d = Find(bdaddr);
networker 2:0118da9e5169 266 if (!d)
networker 2:0118da9e5169 267 return ERR_HCI_DEVICE_NOT_FOUND;
networker 2:0118da9e5169 268 int handle = d->_handle;
networker 2:0118da9e5169 269 printf("Disconnect from %d\n",handle);
networker 2:0118da9e5169 270 _state |= MASK_CREATE_CONNECTION;
networker 2:0118da9e5169 271 u8 buf[3];
networker 2:0118da9e5169 272 buf[0] = handle;
networker 2:0118da9e5169 273 buf[1] = (handle >> 8);
networker 2:0118da9e5169 274 buf[2] = 0x13;
networker 2:0118da9e5169 275 return SendCmd(HCI_OP_DISCONNECT,buf,sizeof(buf));
networker 2:0118da9e5169 276 }
networker 2:0118da9e5169 277
networker 2:0118da9e5169 278 void HCI::DisconnectComplete(int handle) {
networker 2:0118da9e5169 279 BTDevice* d = Find(handle);
networker 2:0118da9e5169 280 if (!d)
networker 2:0118da9e5169 281 return;
networker 2:0118da9e5169 282 d->_handle = 0;
networker 2:0118da9e5169 283 }
networker 2:0118da9e5169 284
networker 2:0118da9e5169 285 int HCI::DisconnectAll() {
networker 2:0118da9e5169 286 BTDevice* devs[8];
networker 2:0118da9e5169 287 int count = GetDevices(devs,8);
networker 2:0118da9e5169 288 for (int i = 0; i < count; i++)
networker 2:0118da9e5169 289 Disconnect(&devs[i]->_info.bdaddr);
networker 2:0118da9e5169 290 return 0;
networker 2:0118da9e5169 291 }
networker 2:0118da9e5169 292
networker 2:0118da9e5169 293 int HCI::PinCodeReply(const u8* data, const u8* pin) {
networker 2:0118da9e5169 294 u8 b[6+1+16];
networker 2:0118da9e5169 295 memset(b,0,sizeof(b));
networker 2:0118da9e5169 296 memcpy(b,data,6);
networker 2:0118da9e5169 297 b[6] = 4;
networker 2:0118da9e5169 298 memcpy(b+7, pin, 4);
networker 2:0118da9e5169 299 return SendCmd(HCI_OP_PIN_CODE_REPLY,b,sizeof(b));
networker 2:0118da9e5169 300 }
networker 2:0118da9e5169 301
networker 2:0118da9e5169 302 void HCI::InquiryResult(const inquiry_info* info) {
networker 2:0118da9e5169 303 BTDevice* bt = Find(&info->bdaddr);
networker 2:0118da9e5169 304 if (!bt) { // new device
networker 2:0118da9e5169 305 for (int i = 0; i < MAX_BTDEVICES; i++) {
networker 2:0118da9e5169 306 if (_devices[i]._state == 0) {
networker 2:0118da9e5169 307 bt = _devices + i;
networker 2:0118da9e5169 308 bt->_state = 1;
networker 2:0118da9e5169 309 break;
networker 2:0118da9e5169 310 }
networker 2:0118da9e5169 311 }
networker 2:0118da9e5169 312 if (!bt) {
networker 2:0118da9e5169 313 printf("HCI::InquiryResult too many devices\n");
networker 2:0118da9e5169 314 return; // Too many devices!
networker 2:0118da9e5169 315 }
networker 2:0118da9e5169 316 }
networker 2:0118da9e5169 317
networker 2:0118da9e5169 318 bt->_info = *info;
networker 2:0118da9e5169 319 }
networker 2:0118da9e5169 320
networker 2:0118da9e5169 321 int HCI::GetDevices(BTDevice** devices, int maxDevices) {
networker 2:0118da9e5169 322 int j = 0;
networker 2:0118da9e5169 323 for (int i = 0; i < MAX_BTDEVICES; i++) {
networker 2:0118da9e5169 324 if (_devices[i]._state != 0) {
networker 2:0118da9e5169 325 devices[j++] = _devices + i;
networker 2:0118da9e5169 326 if (j == maxDevices)
networker 2:0118da9e5169 327 break;
networker 2:0118da9e5169 328 }
networker 2:0118da9e5169 329 }
networker 2:0118da9e5169 330 return j;
networker 2:0118da9e5169 331 }
networker 2:0118da9e5169 332
networker 2:0118da9e5169 333 void HCI::RemoteName(const BD_ADDR* addr, const char* name) {
networker 2:0118da9e5169 334 BTDevice* d = Find(addr);
networker 2:0118da9e5169 335 if (d) {
networker 2:0118da9e5169 336 strncpy(d->_name,name,sizeof(d->_name)-1);
networker 2:0118da9e5169 337 d->_name[sizeof(d->_name)-1] = 0;
networker 2:0118da9e5169 338 }
networker 2:0118da9e5169 339 }
networker 2:0118da9e5169 340
networker 2:0118da9e5169 341 void HCI::ConnectComplete(const connection_info* info) {
networker 2:0118da9e5169 342 BTDevice* d = Find(&info->bdaddr);
networker 2:0118da9e5169 343 if (!d) {
networker 5:378c208637e3 344 printf("BT Device not known!?! ");
networker 5:378c208637e3 345 printf(&info->bdaddr);
networker 5:378c208637e3 346 printf("\n");
networker 2:0118da9e5169 347 return;
networker 2:0118da9e5169 348 }
networker 2:0118da9e5169 349 if (info->status == 0) {
networker 2:0118da9e5169 350 d->_handle = info->handle;
networker 2:0118da9e5169 351 #ifdef HOST_CONTR_FLOW
networker 2:0118da9e5169 352 d->pkts_sent = 0;
networker 2:0118da9e5169 353 #endif
networker 2:0118da9e5169 354 printf("Connected on %04X\n",info->handle);
networker 2:0118da9e5169 355 } else
networker 2:0118da9e5169 356 printf("Connection failed with %d\n",info->status);
networker 2:0118da9e5169 357 }
networker 2:0118da9e5169 358
networker 2:0118da9e5169 359 void HCI::Accept_Connection(const BD_ADDR* addr, bool slave) {
networker 2:0118da9e5169 360 unsigned char b[7];
networker 2:0118da9e5169 361 memcpy(b, addr, 6);
networker 2:0118da9e5169 362 b[6] = slave;
networker 2:0118da9e5169 363 BTDevice* bt = Find(addr);
networker 5:378c208637e3 364 if (!bt) {
networker 2:0118da9e5169 365 printf("Received connection request from undiscovered device\n");
networker 2:0118da9e5169 366 for (int i = 0; i < MAX_BTDEVICES; i++) {
networker 2:0118da9e5169 367 if (_devices[i]._state == 0) {
networker 2:0118da9e5169 368 bt = _devices + i;
networker 2:0118da9e5169 369 bt->_state = 1;
networker 2:0118da9e5169 370 memcpy(&(bt->_info.bdaddr), addr, 6);//rest of inquiry info unknown!!!
networker 2:0118da9e5169 371 break;
networker 2:0118da9e5169 372 }
networker 2:0118da9e5169 373 }
networker 2:0118da9e5169 374 if (!bt) {
networker 2:0118da9e5169 375 printf("HCI::InquiryResult too many devices\n");
networker 2:0118da9e5169 376 return; // Too many devices!
networker 2:0118da9e5169 377 }
networker 2:0118da9e5169 378 }
networker 2:0118da9e5169 379 SendCmd(HCI_OP_ACCEPT_CONN_REQ, b , 7);
networker 2:0118da9e5169 380 }
networker 2:0118da9e5169 381
networker 2:0118da9e5169 382 void HCI::HCIRecv(const u8* data, int len) {//[0]=event, [1]=parlen, [2...]=pars
networker 2:0118da9e5169 383 printfBytes(EvtStr(data[0]),data,min(len,16));
networker 2:0118da9e5169 384 switch (data[0]) {
networker 2:0118da9e5169 385 case HCI_EV_INQUIRY_COMPLETE:
networker 2:0118da9e5169 386 printfBytes("Inquiry Complete",data,data[1]);
networker 2:0118da9e5169 387 _state &= ~MASK_INQUIRY;
networker 2:0118da9e5169 388 Callback(CALLBACK_INQUIRY_DONE,0,0);
networker 2:0118da9e5169 389 break;
networker 2:0118da9e5169 390
networker 2:0118da9e5169 391 case HCI_EV_INQUIRY_RESULT: {
networker 2:0118da9e5169 392 const u8* end = data[1] + data + 2;
networker 2:0118da9e5169 393 data += 3;
networker 2:0118da9e5169 394 while (data < end) {
networker 2:0118da9e5169 395 inquiry_info align;
networker 2:0118da9e5169 396 memcpy(&align,data,sizeof(inquiry_info));
networker 2:0118da9e5169 397 InquiryResult(&align);
networker 2:0118da9e5169 398 Callback(CALLBACK_INQUIRY_RESULT,(u8*)&align,sizeof(inquiry_info));
networker 2:0118da9e5169 399 data += 14;
networker 2:0118da9e5169 400 }
networker 2:0118da9e5169 401 }
networker 2:0118da9e5169 402 break;
networker 2:0118da9e5169 403
networker 2:0118da9e5169 404 case HCI_EV_CONN_COMPLETE:
networker 2:0118da9e5169 405 _state &= ~MASK_CREATE_CONNECTION;
networker 2:0118da9e5169 406 {
networker 2:0118da9e5169 407 connection_info align;
networker 2:0118da9e5169 408 memcpy(&align,data+2,sizeof(connection_info));
networker 2:0118da9e5169 409 ConnectComplete(&align);
networker 2:0118da9e5169 410 Callback(CALLBACK_CONNECTION_COMPLETE,(u8*)&align,sizeof(connection_info));
networker 2:0118da9e5169 411 }
networker 2:0118da9e5169 412 break;
networker 2:0118da9e5169 413
networker 2:0118da9e5169 414 case HCI_EV_CONN_REQUEST:
networker 2:0118da9e5169 415 printf("Got Connection request \n");
networker 2:0118da9e5169 416 Callback(CALLBACK_CONNECTION_REQUEST, data+2, data[1]);
networker 2:0118da9e5169 417 Accept_Connection((BD_ADDR*)(data+2));
networker 2:0118da9e5169 418 break;
networker 2:0118da9e5169 419
networker 2:0118da9e5169 420 case HCI_EV_DISCONN_COMPLETE:
networker 2:0118da9e5169 421 DisconnectComplete(LE16(data+3));
networker 2:0118da9e5169 422 break;
networker 2:0118da9e5169 423
networker 2:0118da9e5169 424 case HCI_EV_REMOTE_NAME: {
networker 2:0118da9e5169 425 BD_ADDR* addr = (BD_ADDR*)(data+3);
networker 2:0118da9e5169 426 const char* name = (const char*)(data + 9);
networker 2:0118da9e5169 427 RemoteName(addr,name);
networker 2:0118da9e5169 428 }
networker 2:0118da9e5169 429 Callback(CALLBACK_REMOTE_NAME,data+3,LE16(data+1)); // addr is in here too
networker 2:0118da9e5169 430 _state &= ~MASK_REMOTE_NAME;
networker 2:0118da9e5169 431 break;
networker 2:0118da9e5169 432
networker 2:0118da9e5169 433 case HCI_EV_CMD_STATUS: {
networker 2:0118da9e5169 434 const char* errs = HCIErrStr(data[2]);
networker 2:0118da9e5169 435 printf("Status %s %s %d cmd pkts\n",CmdStr(LE16(data+4)),errs, data[3]);
networker 2:0118da9e5169 436 #ifdef COMMAND_FLOW
networker 2:0118da9e5169 437 cmd_credits = data[3];
networker 2:0118da9e5169 438 #endif
networker 2:0118da9e5169 439 }
networker 2:0118da9e5169 440 Callback(CALLBACK_CMD_STATUS, data+2, 4);
networker 2:0118da9e5169 441 break;
networker 2:0118da9e5169 442
networker 2:0118da9e5169 443 case HCI_EV_CMD_COMPLETE://[2]=cmd-pkts, [3-4]=cmd, [5...]=pars
networker 2:0118da9e5169 444 if (data[5]) { //[5]=usually status
networker 5:378c208637e3 445 printf("HCIRecv error status: %s\n", HCIErrStr(data[5]));
networker 2:0118da9e5169 446 }
networker 2:0118da9e5169 447 OnCommandComplete(data[3] | (data[4] << 8), data+6, data[1]-4);
networker 2:0118da9e5169 448 #ifdef COMMAND_FLOW
networker 2:0118da9e5169 449 cmd_credits = data[2];
networker 2:0118da9e5169 450 #endif
networker 2:0118da9e5169 451 break;
networker 2:0118da9e5169 452
networker 2:0118da9e5169 453 case HCI_EV_PIN_CODE_REQ:
networker 2:0118da9e5169 454 Callback(CALLBACK_PIN_REQ, data+2, 6);
networker 2:0118da9e5169 455 //PinCodeReply(data+2);
networker 2:0118da9e5169 456 break;
networker 2:0118da9e5169 457
networker 5:378c208637e3 458 case HCI_EV_LINK_KEY_REQ: {
networker 5:378c208637e3 459 u8 param[22];
networker 5:378c208637e3 460 if (neighbors->get((BD_ADDR*)(data+2), param+sizeof(BD_ADDR))){
networker 5:378c208637e3 461 memcpy(param, data+2, sizeof(BD_ADDR));
networker 5:378c208637e3 462 SendCmd(HCI_OP_LINK_KEY_REPLY,param,sizeof(param));
networker 5:378c208637e3 463 } else
networker 5:378c208637e3 464 SendCmd(HCI_OP_LINK_KEY_NEG_REPLY,data+2,6);
networker 5:378c208637e3 465 }
networker 5:378c208637e3 466 break;
networker 2:0118da9e5169 467 #ifdef HOST_CONTR_FLOW
networker 2:0118da9e5169 468 case HCI_EV_NUM_COMP_PKTS:
networker 2:0118da9e5169 469 for (int k = 0; k < data[2]; k++) {//data[2] and 'c' are usually 1
networker 2:0118da9e5169 470 u16 h = LE16(data+3+2*k);
networker 2:0118da9e5169 471 u16 c = LE16(data+5+2*k);
networker 2:0118da9e5169 472 BTDevice *d = Find(h);
networker 2:0118da9e5169 473 if (!d)
networker 5:378c208637e3 474 continue;//skip no existing devices
networker 5:378c208637e3 475 if (d->pkts_sent >= c) {
networker 5:378c208637e3 476 d->pkts_sent -= c;
networker 5:378c208637e3 477 _transport->data_credits += c;
networker 5:378c208637e3 478 } else
networker 5:378c208637e3 479 d->pkts_sent = 0;
networker 2:0118da9e5169 480 //printf("%d Outstanding pkts for handle %03X (total credits=%d)\n", d->pkts_sent, h, _transport->data_credits);
networker 2:0118da9e5169 481 }
networker 2:0118da9e5169 482 break;
networker 2:0118da9e5169 483 #endif
networker 2:0118da9e5169 484 case HCI_EV_LINK_KEY_NOTIFY:
networker 5:378c208637e3 485 neighbors->add((BD_ADDR*)(data+2), data+8);
networker 5:378c208637e3 486 break;
networker 5:378c208637e3 487 case HCI_EV_RETURN_LINK_KEYS:
networker 5:378c208637e3 488 for (int i = 0; i < data[2]; i++)
networker 5:378c208637e3 489 neighbors->add((BD_ADDR*)(data+3+22*i), data+9+22*i, true);
networker 5:378c208637e3 490 break;
networker 2:0118da9e5169 491 case HCI_EV_ENCRYPT_CHANGE:
networker 2:0118da9e5169 492 //for(int k=0; k<1000000;k++) USBLoop();
networker 2:0118da9e5169 493 break;
networker 5:378c208637e3 494 case HCI_EV_VENDOR:
networker 5:378c208637e3 495 Callback(CALLBACK_VENDOR, data+2, data[1]);
networker 5:378c208637e3 496 break;
networker 2:0118da9e5169 497 default:
networker 2:0118da9e5169 498 printfBytes("HCIRecv:",data,data[1]+2);
networker 2:0118da9e5169 499 break;
networker 2:0118da9e5169 500 }
networker 2:0118da9e5169 501 }
networker 2:0118da9e5169 502
networker 2:0118da9e5169 503 int HCI::Open(SocketInternal* sock, SocketAddrHdr* addr) {
networker 2:0118da9e5169 504 L2CAPSocket* l2capsock = (L2CAPSocket*)sock;
networker 2:0118da9e5169 505 L2CAPAddr* l2capaddr = (L2CAPAddr*)addr;
networker 2:0118da9e5169 506 BTDevice* bt = Find(&l2capaddr->bdaddr);
networker 2:0118da9e5169 507 if (!bt) {
networker 2:0118da9e5169 508 printf("Can't open l2cap %d on ",l2capaddr->psm);
networker 2:0118da9e5169 509 printf(&l2capaddr->bdaddr);
networker 2:0118da9e5169 510 printf("\n");
networker 2:0118da9e5169 511 return ERR_HCI_DEVICE_NOT_FOUND;
networker 2:0118da9e5169 512 }
networker 2:0118da9e5169 513 l2capsock->btdevice = bt;
networker 2:0118da9e5169 514 return bt->Open(sock,addr);
networker 2:0118da9e5169 515 }
networker 2:0118da9e5169 516
networker 2:0118da9e5169 517 int HCI::Accept(SocketInternal* sock, int scid, int rxid) {
networker 2:0118da9e5169 518 L2CAPSocket* l2capsock = (L2CAPSocket*)sock;
networker 2:0118da9e5169 519 BTDevice* bt = (BTDevice*)sock->userData;
networker 2:0118da9e5169 520 if (!bt) {
networker 2:0118da9e5169 521 printf("Can't accept l2cap on socket %d\n", sock->ID);
networker 2:0118da9e5169 522 return ERR_HCI_DEVICE_NOT_FOUND;
networker 2:0118da9e5169 523 }
networker 2:0118da9e5169 524 l2capsock->btdevice = bt;
networker 2:0118da9e5169 525 return bt->Accept(sock, scid, rxid);
networker 2:0118da9e5169 526 }
networker 2:0118da9e5169 527
networker 2:0118da9e5169 528 int HCI::Send(SocketInternal* sock, const u8* data, int len) {//check here for appropriate buffersize on the device
networker 5:378c208637e3 529 /* these checks are HCI functions but this 'Send' does not catch all ACL traffic, so it is better done in L2CAP or transport
networker 5:378c208637e3 530 //assume acl packet
networker 5:378c208637e3 531 //FIXME: treatment of OFFSET is dubious, OFFSET is not defined?!
networker 5:378c208637e3 532 #if OFFSET==8 //sizeof ACL/L2CAP is include in data/len
networker 5:378c208637e3 533 if (len > _acl_mtu)
networker 5:378c208637e3 534 #else //OFFSET==0, data is bare application frame
networker 5:378c208637e3 535 if (len+8 > _acl_mtu)
networker 5:378c208637e3 536 #endif
networker 5:378c208637e3 537 { printf("Max outgoing packet(%d) size exceeded, segmenting necessary, pktlen = %d\n", _acl_mtu, len);
networker 5:378c208637e3 538 }
networker 5:378c208637e3 539 if (data_credits == 0) {
networker 5:378c208637e3 540 printf("Out of ACL data credits\n");
networker 5:378c208637e3 541 return 0;
networker 5:378c208637e3 542 }
networker 5:378c208637e3 543 data_credits--;
networker 5:378c208637e3 544 */
networker 2:0118da9e5169 545 L2CAPSocket* l2capsock = (L2CAPSocket*)sock;
networker 2:0118da9e5169 546 return l2capsock->btdevice->Send(sock,data,len); // Pointless double dispatch
networker 2:0118da9e5169 547 }
networker 2:0118da9e5169 548
networker 2:0118da9e5169 549 int HCI::Close(SocketInternal* sock) {
networker 2:0118da9e5169 550 L2CAPSocket* l2capsock = (L2CAPSocket*)sock;
networker 2:0118da9e5169 551 return l2capsock->btdevice->Close(sock); // Pointless double dispatch
networker 2:0118da9e5169 552 }
networker 2:0118da9e5169 553
networker 2:0118da9e5169 554 void HCI::Compl_pkts(int handle, u8 p) {
networker 2:0118da9e5169 555 u8 b[8] = {(u8)HCI_OP_NUM_COMP_PKTS, HCI_OP_NUM_COMP_PKTS >> 8, 5, 1, 0, 0, 1, 0};
networker 2:0118da9e5169 556 b[4] = handle;
networker 2:0118da9e5169 557 b[5] = (handle&0x0f00)>>8;
networker 2:0118da9e5169 558 b[6] = p;//only one packet
networker 2:0118da9e5169 559 _transport->HCISend(b, 8);//directly call the transport layer to prevent the command flow control from interfering
networker 2:0118da9e5169 560 }
networker 2:0118da9e5169 561
networker 2:0118da9e5169 562 void HCI::ACLRecv(const u8* data, int len) {
networker 2:0118da9e5169 563 int handle = LE16(data);
networker 2:0118da9e5169 564 BTDevice* d = Find(handle & 0x0FFF);
networker 2:0118da9e5169 565 int bufs = 1;
networker 5:378c208637e3 566 if (!d) {
networker 2:0118da9e5169 567 printfBytes("unk. dest. HCI:ACLRecv ", data, len);
networker 5:378c208637e3 568 } else
networker 5:378c208637e3 569 bufs = d->ACLRecv(data,len);
networker 2:0118da9e5169 570 //controller to host flow control
networker 2:0118da9e5169 571 #ifdef CONTR_HOST_FLOW
networker 2:0118da9e5169 572 //the ACLRecv function returned so we assume that the buffer is free, and tell this to the controller
networker 2:0118da9e5169 573 if (bufs) {
networker 5:378c208637e3 574 Compl_pkts(handle, bufs);//this packet is completed
networker 5:378c208637e3 575 printf("%d ACL buffers completed\n", bufs);
networker 2:0118da9e5169 576 }
networker 2:0118da9e5169 577 #endif
networker 2:0118da9e5169 578 }
networker 2:0118da9e5169 579
networker 2:0118da9e5169 580 //===================================================================
networker 2:0118da9e5169 581 //===================================================================