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:
Mon Apr 04 16:41:03 2011 +0000
Revision:
0:81ed8b6e4a8b
initial revision

Who changed what in which revision?

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