Bluetooth support for MBED with $2 Bluetooth dongles. Includes a USB host and built in support for bluetooth HID devices such as mice, keyboards and wii controllers.

Dependencies:   mbed

Committer:
meathome
Date:
Tue Mar 01 12:00:17 2011 +0000
Revision:
0:a1f905acca78

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
meathome 0:a1f905acca78 1
meathome 0:a1f905acca78 2 /*
meathome 0:a1f905acca78 3 Copyright (c) 2010 Peter Barrett
meathome 0:a1f905acca78 4
meathome 0:a1f905acca78 5 Permission is hereby granted, free of charge, to any person obtaining a copy
meathome 0:a1f905acca78 6 of this software and associated documentation files (the "Software"), to deal
meathome 0:a1f905acca78 7 in the Software without restriction, including without limitation the rights
meathome 0:a1f905acca78 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
meathome 0:a1f905acca78 9 copies of the Software, and to permit persons to whom the Software is
meathome 0:a1f905acca78 10 furnished to do so, subject to the following conditions:
meathome 0:a1f905acca78 11
meathome 0:a1f905acca78 12 The above copyright notice and this permission notice shall be included in
meathome 0:a1f905acca78 13 all copies or substantial portions of the Software.
meathome 0:a1f905acca78 14
meathome 0:a1f905acca78 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
meathome 0:a1f905acca78 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
meathome 0:a1f905acca78 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
meathome 0:a1f905acca78 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
meathome 0:a1f905acca78 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
meathome 0:a1f905acca78 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
meathome 0:a1f905acca78 21 THE SOFTWARE.
meathome 0:a1f905acca78 22 */
meathome 0:a1f905acca78 23
meathome 0:a1f905acca78 24 #include <stdio.h>
meathome 0:a1f905acca78 25 #include <stdlib.h>
meathome 0:a1f905acca78 26 #include <stdio.h>
meathome 0:a1f905acca78 27 #include <string.h>
meathome 0:a1f905acca78 28
meathome 0:a1f905acca78 29 #include "Utils.h"
meathome 0:a1f905acca78 30 #include "hci.h"
meathome 0:a1f905acca78 31 #include "hci_private.h"
meathome 0:a1f905acca78 32
meathome 0:a1f905acca78 33 enum hci_callback_evt
meathome 0:a1f905acca78 34 {
meathome 0:a1f905acca78 35 NONE,
meathome 0:a1f905acca78 36 CONNECT,
meathome 0:a1f905acca78 37 DISCONECT,
meathome 0:a1f905acca78 38 INQUIRYRESULT
meathome 0:a1f905acca78 39 };
meathome 0:a1f905acca78 40
meathome 0:a1f905acca78 41 #define MAX_BLUETOOTH_ADAPTERS 1
meathome 0:a1f905acca78 42
meathome 0:a1f905acca78 43 enum StateMask {
meathome 0:a1f905acca78 44 MASK_RESET = 1,
meathome 0:a1f905acca78 45 MASK_READ_BUFFER_SIZE = 2,
meathome 0:a1f905acca78 46 MASK_READ_BD_ADDR = 4,
meathome 0:a1f905acca78 47 MASK_INITED = 8,
meathome 0:a1f905acca78 48 MASK_INQUIRY = 16,
meathome 0:a1f905acca78 49 MASK_REMOTE_NAME = 32,
meathome 0:a1f905acca78 50 MASK_CREATE_CONNECTION = 64
meathome 0:a1f905acca78 51 };
meathome 0:a1f905acca78 52
meathome 0:a1f905acca78 53 int HCI::Open(HCITransport* transport, HCICallback callback)
meathome 0:a1f905acca78 54 {
meathome 0:a1f905acca78 55 _transport = transport;
meathome 0:a1f905acca78 56 _transport->Set(this);
meathome 0:a1f905acca78 57 _callback = callback;
meathome 0:a1f905acca78 58 _state = 0;
meathome 0:a1f905acca78 59 for (int i = 0; i < MAX_BTDEVICES; i++)
meathome 0:a1f905acca78 60 {
meathome 0:a1f905acca78 61 _devices[i].Init();
meathome 0:a1f905acca78 62 _devices[i]._transport = transport;
meathome 0:a1f905acca78 63 }
meathome 0:a1f905acca78 64 return SendCmd(HCI_OP_RESET);
meathome 0:a1f905acca78 65 }
meathome 0:a1f905acca78 66
meathome 0:a1f905acca78 67 void printf(const BD_ADDR* addr);
meathome 0:a1f905acca78 68
meathome 0:a1f905acca78 69 BTDevice* HCI::Find(const BD_ADDR* addr)
meathome 0:a1f905acca78 70 {
meathome 0:a1f905acca78 71 for (int i = 0; i < MAX_BTDEVICES; i++)
meathome 0:a1f905acca78 72 if (_devices[i]._state != 0 && memcmp(addr,&_devices[i]._info.bdaddr,6) == 0)
meathome 0:a1f905acca78 73 return &_devices[i];
meathome 0:a1f905acca78 74 return 0;
meathome 0:a1f905acca78 75 }
meathome 0:a1f905acca78 76
meathome 0:a1f905acca78 77 BTDevice* HCI::Find(int handle)
meathome 0:a1f905acca78 78 {
meathome 0:a1f905acca78 79 for (int i = 0; i < MAX_BTDEVICES; i++)
meathome 0:a1f905acca78 80 if (_devices[i]._state != 0 && handle == _devices[i]._handle)
meathome 0:a1f905acca78 81 return &_devices[i];
meathome 0:a1f905acca78 82 return 0;
meathome 0:a1f905acca78 83 }
meathome 0:a1f905acca78 84 //
meathome 0:a1f905acca78 85 bool HCI::Busy()
meathome 0:a1f905acca78 86 {
meathome 0:a1f905acca78 87 return (_state & (MASK_INQUIRY | MASK_REMOTE_NAME | MASK_CREATE_CONNECTION)) != 0;
meathome 0:a1f905acca78 88 }
meathome 0:a1f905acca78 89
meathome 0:a1f905acca78 90 int HCI::Inquiry(int duration)
meathome 0:a1f905acca78 91 {
meathome 0:a1f905acca78 92 _state |= MASK_INQUIRY;
meathome 0:a1f905acca78 93 u8 buf[5];
meathome 0:a1f905acca78 94 buf[0] = 0x33;
meathome 0:a1f905acca78 95 buf[1] = 0x8B;
meathome 0:a1f905acca78 96 buf[2] = 0x9E;
meathome 0:a1f905acca78 97 buf[3] = duration;
meathome 0:a1f905acca78 98 buf[4] = 5; // 5 results
meathome 0:a1f905acca78 99 SendCmd(HCI_OP_INQUIRY,buf,sizeof(buf));
meathome 0:a1f905acca78 100 return 0;
meathome 0:a1f905acca78 101 }
meathome 0:a1f905acca78 102
meathome 0:a1f905acca78 103 int HCI::SendCmd(int cmd, const u8* params, int len)
meathome 0:a1f905acca78 104 {
meathome 0:a1f905acca78 105 u8 b[32];
meathome 0:a1f905acca78 106 b[0] = cmd;
meathome 0:a1f905acca78 107 b[1] = (cmd >> 8);
meathome 0:a1f905acca78 108 b[2] = len;
meathome 0:a1f905acca78 109 if (params)
meathome 0:a1f905acca78 110 memcpy(b+3,params,len);
meathome 0:a1f905acca78 111 _transport->HCISend(b,len+3);
meathome 0:a1f905acca78 112 return 0;
meathome 0:a1f905acca78 113 }
meathome 0:a1f905acca78 114
meathome 0:a1f905acca78 115 void HCI::OnCommandComplete(int cmd, const u8* data, int len)
meathome 0:a1f905acca78 116 {
meathome 0:a1f905acca78 117 // printf("%04X %s",cmd,CmdStr(cmd));
meathome 0:a1f905acca78 118 if (len < 0)
meathome 0:a1f905acca78 119 return;
meathome 0:a1f905acca78 120 //printfBytes(" complete",data,min(16,len));
meathome 0:a1f905acca78 121
meathome 0:a1f905acca78 122 switch (cmd)
meathome 0:a1f905acca78 123 {
meathome 0:a1f905acca78 124 // Init phase 0
meathome 0:a1f905acca78 125 case HCI_OP_RESET: // Reset done, init chain to HCI_OP_READ_LOCAL_NAME
meathome 0:a1f905acca78 126 SendCmd(HCI_OP_READ_BUFFER_SIZE);
meathome 0:a1f905acca78 127 _state |= MASK_RESET;
meathome 0:a1f905acca78 128 break;
meathome 0:a1f905acca78 129
meathome 0:a1f905acca78 130 // Init phase 1
meathome 0:a1f905acca78 131 case HCI_OP_READ_BUFFER_SIZE:
meathome 0:a1f905acca78 132 _acl_mtu = LE16(data);
meathome 0:a1f905acca78 133 _sco_mtu = data[2];
meathome 0:a1f905acca78 134 _acl_max_pkt = LE16(data+3);
meathome 0:a1f905acca78 135 _sco_max_pkt = LE16(data+5);
meathome 0:a1f905acca78 136 SendCmd(HCI_OP_READ_BD_ADDR);
meathome 0:a1f905acca78 137 _state |= MASK_READ_BUFFER_SIZE;
meathome 0:a1f905acca78 138 break;
meathome 0:a1f905acca78 139
meathome 0:a1f905acca78 140 // Init phase 2
meathome 0:a1f905acca78 141 case HCI_OP_READ_BD_ADDR:
meathome 0:a1f905acca78 142 _localAddr = *((BD_ADDR*)data); // Local Address
meathome 0:a1f905acca78 143 _state |= MASK_READ_BD_ADDR;
meathome 0:a1f905acca78 144 _state |= MASK_INITED;
meathome 0:a1f905acca78 145 Callback(CALLBACK_READY,data,6);
meathome 0:a1f905acca78 146 break;
meathome 0:a1f905acca78 147
meathome 0:a1f905acca78 148 // 0CXX
meathome 0:a1f905acca78 149 case HCI_OP_READ_LOCAL_NAME:
meathome 0:a1f905acca78 150 break;
meathome 0:a1f905acca78 151
meathome 0:a1f905acca78 152 case HCI_OP_READ_LOCAL_VERSION:
meathome 0:a1f905acca78 153 // params
meathome 0:a1f905acca78 154 //SendCmd(HCI_OP_READ_LOCAL_NAME);
meathome 0:a1f905acca78 155 break;
meathome 0:a1f905acca78 156
meathome 0:a1f905acca78 157 case HCI_OP_READ_LOCAL_COMMANDS:
meathome 0:a1f905acca78 158 break;
meathome 0:a1f905acca78 159
meathome 0:a1f905acca78 160 case HCI_OP_READ_LOCAL_FEATURES:
meathome 0:a1f905acca78 161 //SendCmd(HCI_OP_READ_LOCAL_VERSION);
meathome 0:a1f905acca78 162 break;
meathome 0:a1f905acca78 163
meathome 0:a1f905acca78 164 case HCI_OP_READ_LOCAL_EXT_FEATURES:
meathome 0:a1f905acca78 165 break;
meathome 0:a1f905acca78 166
meathome 0:a1f905acca78 167 case HCI_OP_PIN_CODE_REPLY:
meathome 0:a1f905acca78 168 printf("Got pin reply\n");
meathome 0:a1f905acca78 169 break;
meathome 0:a1f905acca78 170
meathome 0:a1f905acca78 171 default:
meathome 0:a1f905acca78 172 printf("Unrecognized Command %04X\n",cmd);
meathome 0:a1f905acca78 173 break;
meathome 0:a1f905acca78 174 }
meathome 0:a1f905acca78 175 }
meathome 0:a1f905acca78 176
meathome 0:a1f905acca78 177 void HCI::Callback(HCI_CALLBACK_EVENT c, const u8* data, int len)
meathome 0:a1f905acca78 178 {
meathome 0:a1f905acca78 179 _callback(this,c,data,len);
meathome 0:a1f905acca78 180 }
meathome 0:a1f905acca78 181
meathome 0:a1f905acca78 182 int HCI::RemoteNameRequest(const BD_ADDR* addr)
meathome 0:a1f905acca78 183 {
meathome 0:a1f905acca78 184 _state |= MASK_REMOTE_NAME;
meathome 0:a1f905acca78 185 u8 buf[6+4];
meathome 0:a1f905acca78 186 memset(buf,0,sizeof(buf));
meathome 0:a1f905acca78 187 memcpy(buf,addr,6);
meathome 0:a1f905acca78 188 buf[7] = 1;
meathome 0:a1f905acca78 189 return SendCmd(HCI_OP_REMOTE_NAME_REQ,buf,sizeof(buf));
meathome 0:a1f905acca78 190 }
meathome 0:a1f905acca78 191
meathome 0:a1f905acca78 192 int HCI::CreateConnection(const BD_ADDR* remoteAddr)
meathome 0:a1f905acca78 193 {
meathome 0:a1f905acca78 194 _state |= MASK_CREATE_CONNECTION;
meathome 0:a1f905acca78 195 u8 buf[6+7];
meathome 0:a1f905acca78 196 memset(buf,0,sizeof(buf));
meathome 0:a1f905acca78 197 memcpy(buf,remoteAddr,6);
meathome 0:a1f905acca78 198 buf[6] = 0x18; // DM1,DH1
meathome 0:a1f905acca78 199 buf[7] = 0xCC; // DM3, DH3, DM5, DH5
meathome 0:a1f905acca78 200 buf[8] = 1; // Page Repetition R1
meathome 0:a1f905acca78 201 return SendCmd(HCI_OP_CREATE_CONN,buf,sizeof(buf));
meathome 0:a1f905acca78 202 }
meathome 0:a1f905acca78 203
meathome 0:a1f905acca78 204 int HCI::Disconnect(const BD_ADDR* bdaddr)
meathome 0:a1f905acca78 205 {
meathome 0:a1f905acca78 206 BTDevice* d = Find(bdaddr);
meathome 0:a1f905acca78 207 if (!d)
meathome 0:a1f905acca78 208 return ERR_HCI_DEVICE_NOT_FOUND;
meathome 0:a1f905acca78 209 int handle = d->_handle;
meathome 0:a1f905acca78 210 printf("Disconnect from %d\n",handle);
meathome 0:a1f905acca78 211 _state |= MASK_CREATE_CONNECTION;
meathome 0:a1f905acca78 212 u8 buf[3];
meathome 0:a1f905acca78 213 buf[0] = handle;
meathome 0:a1f905acca78 214 buf[1] = (handle >> 8);
meathome 0:a1f905acca78 215 buf[2] = 0x13;
meathome 0:a1f905acca78 216 return SendCmd(HCI_OP_DISCONNECT,buf,sizeof(buf));
meathome 0:a1f905acca78 217 }
meathome 0:a1f905acca78 218
meathome 0:a1f905acca78 219 void HCI::DisconnectComplete(int handle)
meathome 0:a1f905acca78 220 {
meathome 0:a1f905acca78 221 BTDevice* d = Find(handle);
meathome 0:a1f905acca78 222 if (!d)
meathome 0:a1f905acca78 223 return;
meathome 0:a1f905acca78 224 d->_handle = 0;
meathome 0:a1f905acca78 225 }
meathome 0:a1f905acca78 226
meathome 0:a1f905acca78 227 int HCI::DisconnectAll()
meathome 0:a1f905acca78 228 {
meathome 0:a1f905acca78 229 BTDevice* devs[8];
meathome 0:a1f905acca78 230 int count = GetDevices(devs,8);
meathome 0:a1f905acca78 231 for (int i = 0; i < count; i++)
meathome 0:a1f905acca78 232 Disconnect(&devs[i]->_info.bdaddr);
meathome 0:a1f905acca78 233 return 0;
meathome 0:a1f905acca78 234 }
meathome 0:a1f905acca78 235
meathome 0:a1f905acca78 236 int HCI::PinCodeReply(const u8* data)
meathome 0:a1f905acca78 237 {
meathome 0:a1f905acca78 238 u8 b[6+1+16];
meathome 0:a1f905acca78 239 memset(b,0,sizeof(b));
meathome 0:a1f905acca78 240 memcpy(b,data,6);
meathome 0:a1f905acca78 241 b[6] = 4;
meathome 0:a1f905acca78 242 b[7] = '0';
meathome 0:a1f905acca78 243 b[8] = '0';
meathome 0:a1f905acca78 244 b[9] = '0';
meathome 0:a1f905acca78 245 b[10] = '0';
meathome 0:a1f905acca78 246 return SendCmd(HCI_OP_PIN_CODE_REPLY,b,sizeof(b));
meathome 0:a1f905acca78 247 }
meathome 0:a1f905acca78 248
meathome 0:a1f905acca78 249 void HCI::InquiryResult(const inquiry_info* info)
meathome 0:a1f905acca78 250 {
meathome 0:a1f905acca78 251 BTDevice* bt = Find(&info->bdaddr);
meathome 0:a1f905acca78 252 if (!bt) // new device
meathome 0:a1f905acca78 253 {
meathome 0:a1f905acca78 254 for (int i = 0; i < MAX_BTDEVICES; i++)
meathome 0:a1f905acca78 255 {
meathome 0:a1f905acca78 256 if (_devices[i]._state == 0)
meathome 0:a1f905acca78 257 {
meathome 0:a1f905acca78 258 bt = _devices + i;
meathome 0:a1f905acca78 259 bt->_state = 1;
meathome 0:a1f905acca78 260 break;
meathome 0:a1f905acca78 261 }
meathome 0:a1f905acca78 262 }
meathome 0:a1f905acca78 263 if (!bt)
meathome 0:a1f905acca78 264 {
meathome 0:a1f905acca78 265 printf("HCI::InquiryResult too many devices\n");
meathome 0:a1f905acca78 266 return; // Too many devices!
meathome 0:a1f905acca78 267 }
meathome 0:a1f905acca78 268 }
meathome 0:a1f905acca78 269
meathome 0:a1f905acca78 270 bt->_info = *info;
meathome 0:a1f905acca78 271 }
meathome 0:a1f905acca78 272
meathome 0:a1f905acca78 273 int HCI::GetDevices(BTDevice** devices, int maxDevices)
meathome 0:a1f905acca78 274 {
meathome 0:a1f905acca78 275 int j = 0;
meathome 0:a1f905acca78 276 for (int i = 0; i < MAX_BTDEVICES; i++)
meathome 0:a1f905acca78 277 {
meathome 0:a1f905acca78 278 if (_devices[i]._state != 0)
meathome 0:a1f905acca78 279 {
meathome 0:a1f905acca78 280 devices[j++] = _devices + i;
meathome 0:a1f905acca78 281 if (j == maxDevices)
meathome 0:a1f905acca78 282 break;
meathome 0:a1f905acca78 283 }
meathome 0:a1f905acca78 284 }
meathome 0:a1f905acca78 285 return j;
meathome 0:a1f905acca78 286 }
meathome 0:a1f905acca78 287
meathome 0:a1f905acca78 288 void HCI::RemoteName(const BD_ADDR* addr, const char* name)
meathome 0:a1f905acca78 289 {
meathome 0:a1f905acca78 290 BTDevice* d = Find(addr);
meathome 0:a1f905acca78 291 if (d)
meathome 0:a1f905acca78 292 {
meathome 0:a1f905acca78 293 strncpy(d->_name,name,sizeof(d->_name)-1);
meathome 0:a1f905acca78 294 d->_name[sizeof(d->_name)-1] = 0;
meathome 0:a1f905acca78 295 }
meathome 0:a1f905acca78 296 }
meathome 0:a1f905acca78 297
meathome 0:a1f905acca78 298 void HCI::ConnectComplete(const connection_info* info)
meathome 0:a1f905acca78 299 {
meathome 0:a1f905acca78 300 BTDevice* d = Find(&info->bdaddr);
meathome 0:a1f905acca78 301 if (!d)
meathome 0:a1f905acca78 302 return;
meathome 0:a1f905acca78 303 if (info->status == 0)
meathome 0:a1f905acca78 304 {
meathome 0:a1f905acca78 305 d->_handle = info->handle;
meathome 0:a1f905acca78 306 printf("Connected on %04X\n",info->handle);
meathome 0:a1f905acca78 307 } else
meathome 0:a1f905acca78 308 printf("Connection failed with %d\n",info->status);
meathome 0:a1f905acca78 309 }
meathome 0:a1f905acca78 310
meathome 0:a1f905acca78 311 void HCI::HCIRecv(const u8* data, int len)
meathome 0:a1f905acca78 312 {
meathome 0:a1f905acca78 313 // printfBytes(EvtStr(data[0]),data,min(len,16));
meathome 0:a1f905acca78 314 switch (data[0])
meathome 0:a1f905acca78 315 {
meathome 0:a1f905acca78 316 case HCI_EV_INQUIRY_COMPLETE:
meathome 0:a1f905acca78 317 printfBytes("Inquiry Complete",data,data[1]);
meathome 0:a1f905acca78 318 _state &= ~MASK_INQUIRY;
meathome 0:a1f905acca78 319 Callback(CALLBACK_INQUIRY_DONE,0,0);
meathome 0:a1f905acca78 320 break;
meathome 0:a1f905acca78 321
meathome 0:a1f905acca78 322 case HCI_EV_INQUIRY_RESULT:
meathome 0:a1f905acca78 323 {
meathome 0:a1f905acca78 324 const u8* end = data[1] + data + 2;
meathome 0:a1f905acca78 325 data += 3;
meathome 0:a1f905acca78 326 while (data < end)
meathome 0:a1f905acca78 327 {
meathome 0:a1f905acca78 328 inquiry_info align;
meathome 0:a1f905acca78 329 memcpy(&align,data,sizeof(inquiry_info));
meathome 0:a1f905acca78 330 InquiryResult(&align);
meathome 0:a1f905acca78 331 Callback(CALLBACK_INQUIRY_RESULT,(u8*)&align,sizeof(inquiry_info));
meathome 0:a1f905acca78 332 data += 14;
meathome 0:a1f905acca78 333 }
meathome 0:a1f905acca78 334 }
meathome 0:a1f905acca78 335 break;
meathome 0:a1f905acca78 336
meathome 0:a1f905acca78 337 case HCI_EV_CONN_COMPLETE:
meathome 0:a1f905acca78 338 _state &= ~MASK_CREATE_CONNECTION;
meathome 0:a1f905acca78 339 {
meathome 0:a1f905acca78 340 connection_info align;
meathome 0:a1f905acca78 341 memcpy(&align,data+2,sizeof(connection_info));
meathome 0:a1f905acca78 342 ConnectComplete(&align);
meathome 0:a1f905acca78 343 Callback(CALLBACK_CONNECTION_COMPLETE,(u8*)&align,sizeof(connection_info));
meathome 0:a1f905acca78 344 }
meathome 0:a1f905acca78 345 break;
meathome 0:a1f905acca78 346
meathome 0:a1f905acca78 347 case HCI_EV_CONN_REQUEST:
meathome 0:a1f905acca78 348 break;
meathome 0:a1f905acca78 349
meathome 0:a1f905acca78 350 case HCI_EV_DISCONN_COMPLETE:
meathome 0:a1f905acca78 351 DisconnectComplete(LE16(data+3));
meathome 0:a1f905acca78 352 break;
meathome 0:a1f905acca78 353
meathome 0:a1f905acca78 354 case HCI_EV_REMOTE_NAME:
meathome 0:a1f905acca78 355 {
meathome 0:a1f905acca78 356 BD_ADDR* addr = (BD_ADDR*)(data+3);
meathome 0:a1f905acca78 357 const char* name = (const char*)(data + 9);
meathome 0:a1f905acca78 358 RemoteName(addr,name);
meathome 0:a1f905acca78 359 }
meathome 0:a1f905acca78 360 Callback(CALLBACK_REMOTE_NAME,data+3,LE16(data+1)); // addr is in here too
meathome 0:a1f905acca78 361 _state &= ~MASK_REMOTE_NAME;
meathome 0:a1f905acca78 362 break;
meathome 0:a1f905acca78 363
meathome 0:a1f905acca78 364 case HCI_EV_CMD_STATUS:
meathome 0:a1f905acca78 365 {
meathome 0:a1f905acca78 366 const char* errs = HCIErrStr(data[2]);
meathome 0:a1f905acca78 367 printf("Status %s %s\n",CmdStr(LE16(data+4)),errs);
meathome 0:a1f905acca78 368 }
meathome 0:a1f905acca78 369 break;
meathome 0:a1f905acca78 370
meathome 0:a1f905acca78 371 case HCI_EV_CMD_COMPLETE:
meathome 0:a1f905acca78 372 OnCommandComplete(data[3] | (data[4] << 8),data+6,data[1]-4);
meathome 0:a1f905acca78 373 break;
meathome 0:a1f905acca78 374
meathome 0:a1f905acca78 375 case HCI_EV_PIN_CODE_REQ:
meathome 0:a1f905acca78 376 PinCodeReply(data+2);
meathome 0:a1f905acca78 377 break;
meathome 0:a1f905acca78 378
meathome 0:a1f905acca78 379 case HCI_EV_LINK_KEY_REQ:
meathome 0:a1f905acca78 380 SendCmd(HCI_OP_LINK_KEY_NEG_REPLY,data+2,6);
meathome 0:a1f905acca78 381 break;
meathome 0:a1f905acca78 382
meathome 0:a1f905acca78 383 default:
meathome 0:a1f905acca78 384 ;
meathome 0:a1f905acca78 385 // printfBytes(":",data,data[1]+2);
meathome 0:a1f905acca78 386 }
meathome 0:a1f905acca78 387 }
meathome 0:a1f905acca78 388
meathome 0:a1f905acca78 389 int HCI::Open(SocketInternal* sock, SocketAddrHdr* addr)
meathome 0:a1f905acca78 390 {
meathome 0:a1f905acca78 391 L2CAPSocket* l2capsock = (L2CAPSocket*)sock;
meathome 0:a1f905acca78 392 L2CAPAddr* l2capaddr = (L2CAPAddr*)addr;
meathome 0:a1f905acca78 393 BTDevice* bt = Find(&l2capaddr->bdaddr);
meathome 0:a1f905acca78 394 if (!bt)
meathome 0:a1f905acca78 395 {
meathome 0:a1f905acca78 396 printf("Can't open l2cap %d on ",l2capaddr->psm);
meathome 0:a1f905acca78 397 printf(&l2capaddr->bdaddr);
meathome 0:a1f905acca78 398 printf("\n");
meathome 0:a1f905acca78 399 return ERR_HCI_DEVICE_NOT_FOUND;
meathome 0:a1f905acca78 400 }
meathome 0:a1f905acca78 401 l2capsock->btdevice = bt;
meathome 0:a1f905acca78 402 return bt->Open(sock,addr);
meathome 0:a1f905acca78 403 }
meathome 0:a1f905acca78 404
meathome 0:a1f905acca78 405 int HCI::Send(SocketInternal* sock, const u8* data, int len)
meathome 0:a1f905acca78 406 {
meathome 0:a1f905acca78 407 L2CAPSocket* l2capsock = (L2CAPSocket*)sock;
meathome 0:a1f905acca78 408 return l2capsock->btdevice->Send(sock,data,len); // Pointless double dispatch
meathome 0:a1f905acca78 409 }
meathome 0:a1f905acca78 410
meathome 0:a1f905acca78 411 int HCI::Close(SocketInternal* sock)
meathome 0:a1f905acca78 412 {
meathome 0:a1f905acca78 413 L2CAPSocket* l2capsock = (L2CAPSocket*)sock;
meathome 0:a1f905acca78 414 return l2capsock->btdevice->Close(sock); // Pointless double dispatch
meathome 0:a1f905acca78 415 }
meathome 0:a1f905acca78 416
meathome 0:a1f905acca78 417 void HCI::ACLRecv(const u8* data, int len)
meathome 0:a1f905acca78 418 {
meathome 0:a1f905acca78 419 int handle = LE16(data);
meathome 0:a1f905acca78 420 BTDevice* d = Find(handle & 0x0FFF);
meathome 0:a1f905acca78 421 if (d)
meathome 0:a1f905acca78 422 d->ACLRecv(data,len);
meathome 0:a1f905acca78 423 }
meathome 0:a1f905acca78 424
meathome 0:a1f905acca78 425 //===================================================================
meathome 0:a1f905acca78 426 //===================================================================