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.
hci.cpp
00001 /* 00002 Copyright (c) 2010 Peter Barrett 00003 00004 Permission is hereby granted, free of charge, to any person obtaining a copy 00005 of this software and associated documentation files (the "Software"), to deal 00006 in the Software without restriction, including without limitation the rights 00007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 copies of the Software, and to permit persons to whom the Software is 00009 furnished to do so, subject to the following conditions: 00010 00011 The above copyright notice and this permission notice shall be included in 00012 all copies or substantial portions of the Software. 00013 00014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00020 THE SOFTWARE. 00021 */ 00022 00023 /* 00024 Tue Apr 26 2011 Bart Janssens: added HCI connection accept 00025 */ 00026 00027 #include <stdio.h> 00028 #include <stdlib.h> 00029 #include <stdio.h> 00030 #include <string.h> 00031 00032 #include "Utils.h" 00033 #include "hci.h" 00034 #include "hci_private.h" 00035 00036 enum hci_callback_evt 00037 { 00038 NONE, 00039 CONNECT, 00040 DISCONECT, 00041 INQUIRYRESULT 00042 }; 00043 00044 #define MAX_BLUETOOTH_ADAPTERS 1 00045 00046 enum StateMask { 00047 MASK_RESET = 1, 00048 MASK_READ_BUFFER_SIZE = 2, 00049 MASK_READ_BD_ADDR = 4, 00050 MASK_INITED = 8, 00051 MASK_INQUIRY = 16, 00052 MASK_REMOTE_NAME = 32, 00053 MASK_CREATE_CONNECTION = 64 00054 }; 00055 00056 int HCI::Open(HCITransport* transport, HCICallback callback) 00057 { 00058 _transport = transport; 00059 _transport->Set(this); 00060 _callback = callback; 00061 _state = 0; 00062 for (int i = 0; i < MAX_BTDEVICES; i++) 00063 { 00064 _devices[i].Init(); 00065 _devices[i]._transport = transport; 00066 } 00067 return SendCmd(HCI_OP_RESET); 00068 } 00069 00070 void printf(const BD_ADDR* addr); 00071 00072 BTDevice* HCI::Find(const BD_ADDR* addr) 00073 { 00074 for (int i = 0; i < MAX_BTDEVICES; i++) 00075 if (_devices[i]._state != 0 && memcmp(addr,&_devices[i]._info.bdaddr,6) == 0) 00076 return &_devices[i]; 00077 return 0; 00078 } 00079 00080 BTDevice* HCI::Find(int handle) 00081 { 00082 for (int i = 0; i < MAX_BTDEVICES; i++) 00083 if (_devices[i]._state != 0 && handle == _devices[i]._handle) 00084 return &_devices[i]; 00085 return 0; 00086 } 00087 // 00088 bool HCI::Busy() 00089 { 00090 return (_state & (MASK_INQUIRY | MASK_REMOTE_NAME | MASK_CREATE_CONNECTION)) != 0; 00091 } 00092 00093 int HCI::Inquiry(int duration) 00094 { 00095 _state |= MASK_INQUIRY; 00096 u8 buf[5]; 00097 buf[0] = 0x33; 00098 buf[1] = 0x8B; 00099 buf[2] = 0x9E; 00100 buf[3] = duration; 00101 buf[4] = 5; // 5 results 00102 SendCmd(HCI_OP_INQUIRY,buf,sizeof(buf)); 00103 return 0; 00104 } 00105 00106 int HCI::WriteScanEnable() 00107 { 00108 00109 // u8 buf[2]; 00110 // buf[0] = 0x03; 00111 // buf[1] = 0x01; 00112 00113 u8 buf[1]; 00114 buf[0] = 0x03; 00115 00116 SendCmd(HCI_OP_WRITE_SCAN_ENABLE,buf,sizeof(buf)); 00117 return 0; 00118 } 00119 00120 int HCI::AcceptConnection(const BD_ADDR* addr) 00121 { 00122 // u8 buf[6+4]; 00123 // memset(buf,0,sizeof(buf)); 00124 // memcpy(buf,addr,6); 00125 // buf[7] = 0; 00126 00127 u8 buf[6+1]; 00128 memset(buf,0,sizeof(buf)); 00129 memcpy(buf,addr,6); 00130 buf[6] = 0; 00131 00132 SendCmd(HCI_OP_ACCEPT_CONN_REQ,buf,sizeof(buf)); 00133 return 0; 00134 } 00135 00136 int HCI::SendCmd(int cmd, const u8* params, int len) 00137 { 00138 u8 b[32]; 00139 b[0] = cmd; 00140 b[1] = (cmd >> 8); 00141 b[2] = len; 00142 if (params) 00143 memcpy(b+3,params,len); 00144 _transport->HCISend(b,len+3); 00145 return 0; 00146 } 00147 00148 void HCI::OnCommandComplete(int cmd, const u8* data, int len) 00149 { 00150 // printf("%04X %s",cmd,CmdStr(cmd)); 00151 if (len < 0) 00152 return; 00153 //printfBytes(" complete",data,min(16,len)); 00154 00155 switch (cmd) 00156 { 00157 // Init phase 0 00158 case HCI_OP_RESET: // Reset done, init chain to HCI_OP_READ_LOCAL_NAME 00159 SendCmd(HCI_OP_READ_BUFFER_SIZE); 00160 _state |= MASK_RESET; 00161 break; 00162 00163 // Init phase 1 00164 case HCI_OP_READ_BUFFER_SIZE: 00165 _acl_mtu = LE16(data); 00166 _sco_mtu = data[2]; 00167 _acl_max_pkt = LE16(data+3); 00168 _sco_max_pkt = LE16(data+5); 00169 SendCmd(HCI_OP_READ_BD_ADDR); 00170 _state |= MASK_READ_BUFFER_SIZE; 00171 break; 00172 00173 // Init phase 2 00174 case HCI_OP_READ_BD_ADDR: 00175 _localAddr = *((BD_ADDR*)data); // Local Address 00176 printf("Local Address: "); 00177 printf(&_localAddr); 00178 printf("\r\n"); 00179 00180 _state |= MASK_READ_BD_ADDR; 00181 _state |= MASK_INITED; 00182 Callback(CALLBACK_READY,data,6); 00183 break; 00184 00185 // 0CXX 00186 case HCI_OP_READ_LOCAL_NAME: 00187 break; 00188 00189 case HCI_OP_READ_LOCAL_VERSION: 00190 // params 00191 //SendCmd(HCI_OP_READ_LOCAL_NAME); 00192 break; 00193 00194 case HCI_OP_READ_LOCAL_COMMANDS: 00195 break; 00196 00197 case HCI_OP_READ_LOCAL_FEATURES: 00198 //SendCmd(HCI_OP_READ_LOCAL_VERSION); 00199 break; 00200 00201 case HCI_OP_READ_LOCAL_EXT_FEATURES: 00202 break; 00203 00204 case HCI_OP_PIN_CODE_REPLY: 00205 printf("Got pin reply\r\n"); 00206 break; 00207 00208 default: 00209 //printf("Unrecognized Command %04X\r\n",cmd); 00210 break; 00211 } 00212 } 00213 00214 void HCI::Callback(HCI_CALLBACK_EVENT c, const u8* data, int len) 00215 { 00216 _callback(this,c,data,len); 00217 } 00218 00219 int HCI::RemoteNameRequest(const BD_ADDR* addr) 00220 { 00221 _state |= MASK_REMOTE_NAME; 00222 u8 buf[6+4]; 00223 memset(buf,0,sizeof(buf)); 00224 memcpy(buf,addr,6); 00225 buf[7] = 1; 00226 return SendCmd(HCI_OP_REMOTE_NAME_REQ,buf,sizeof(buf)); 00227 } 00228 00229 int HCI::CreateConnection(const BD_ADDR* remoteAddr) 00230 { 00231 _state |= MASK_CREATE_CONNECTION; 00232 u8 buf[6+7]; 00233 memset(buf,0,sizeof(buf)); 00234 memcpy(buf,remoteAddr,6); 00235 buf[6] = 0x18; // DM1,DH1 00236 buf[7] = 0xCC; // DM3, DH3, DM5, DH5 00237 buf[8] = 1; // Page Repetition R1 00238 return SendCmd(HCI_OP_CREATE_CONN,buf,sizeof(buf)); 00239 } 00240 00241 int HCI::Disconnect(const BD_ADDR* bdaddr) 00242 { 00243 BTDevice* d = Find(bdaddr); 00244 if (!d) 00245 return ERR_HCI_DEVICE_NOT_FOUND; 00246 int handle = d->_handle; 00247 printf("Disconnect from %d\r\n",handle); 00248 _state |= MASK_CREATE_CONNECTION; 00249 u8 buf[3]; 00250 buf[0] = handle; 00251 buf[1] = (handle >> 8); 00252 buf[2] = 0x13; 00253 return SendCmd(HCI_OP_DISCONNECT,buf,sizeof(buf)); 00254 } 00255 00256 void HCI::DisconnectComplete(int handle) 00257 { 00258 BTDevice* d = Find(handle); 00259 if (!d) 00260 return; 00261 d->_handle = 0; 00262 } 00263 00264 int HCI::DisconnectAll() 00265 { 00266 BTDevice* devs[8]; 00267 int count = GetDevices(devs,8); 00268 for (int i = 0; i < count; i++) 00269 Disconnect(&devs[i]->_info.bdaddr); 00270 return 0; 00271 } 00272 00273 int HCI::PinCodeReply(const u8* data) 00274 { 00275 u8 b[6+1+16]; 00276 memset(b,0,sizeof(b)); 00277 memcpy(b,data,6); 00278 b[6] = 4; 00279 b[7] = '0'; 00280 b[8] = '0'; 00281 b[9] = '0'; 00282 b[10] = '0'; 00283 return SendCmd(HCI_OP_PIN_CODE_REPLY,b,sizeof(b)); 00284 } 00285 00286 void HCI::InquiryResult(const inquiry_info* info) 00287 { 00288 BTDevice* bt = Find(&info->bdaddr); 00289 if (!bt) // new device 00290 { 00291 for (int i = 0; i < MAX_BTDEVICES; i++) 00292 { 00293 if (_devices[i]._state == 0) 00294 { 00295 bt = _devices + i; 00296 bt->_state = 1; 00297 break; 00298 } 00299 } 00300 if (!bt) 00301 { 00302 printf("HCI::InquiryResult too many devices\r\n"); 00303 return; // Too many devices! 00304 } 00305 } 00306 00307 bt->_info = *info; 00308 } 00309 00310 int HCI::GetDevices(BTDevice** devices, int maxDevices) 00311 { 00312 int j = 0; 00313 for (int i = 0; i < MAX_BTDEVICES; i++) 00314 { 00315 if (_devices[i]._state != 0) 00316 { 00317 devices[j++] = _devices + i; 00318 if (j == maxDevices) 00319 break; 00320 } 00321 } 00322 return j; 00323 } 00324 00325 void HCI::RemoteName(const BD_ADDR* addr, const char* name) 00326 { 00327 BTDevice* d = Find(addr); 00328 if (d) 00329 { 00330 strncpy(d->_name,name,sizeof(d->_name)-1); 00331 d->_name[sizeof(d->_name)-1] = 0; 00332 } 00333 } 00334 00335 void HCI::ConnectComplete(const connection_info* info) 00336 { 00337 BTDevice* d = Find(&info->bdaddr); 00338 if (!d) 00339 return; 00340 if (info->status == 0) 00341 { 00342 d->_handle = info->handle; 00343 printf("Connected on %04X\r\n",info->handle); 00344 } else 00345 printf("Connection failed with %d\r\n",info->status); 00346 } 00347 00348 void HCI::ConnectRequest(const request_info* info) 00349 { 00350 BTDevice* bt = Find(&info->bdaddr); 00351 if (!bt) // new device 00352 { 00353 for (int i = 0; i < MAX_BTDEVICES; i++) 00354 { 00355 if (_devices[i]._state == 0) 00356 { 00357 bt = _devices + i; 00358 bt->_state = 1; 00359 break; 00360 } 00361 } 00362 if (!bt) 00363 { 00364 printf("HCI::ConnectRequest too many devices\r\n"); 00365 return; // Too many devices! 00366 } 00367 } 00368 bt->_info.bdaddr = info->bdaddr; 00369 memcpy(bt->_info.dev_class,info->dev_class,3); 00370 AcceptConnection(&info->bdaddr); 00371 } 00372 00373 void HCI::HCIRecv(const u8* data, int len) 00374 { 00375 //printfBytes(EvtStr(data[0]),data,len); 00376 //printfBytes(EvtStr(data[0]),data,min(len,16)); 00377 //printf("HCI Event %02X\r\n",data[0]); 00378 switch (data[0]) 00379 { 00380 case HCI_EV_INQUIRY_COMPLETE: 00381 printfBytes("Inquiry Complete",data,data[1]); 00382 _state &= ~MASK_INQUIRY; 00383 Callback(CALLBACK_INQUIRY_DONE,0,0); 00384 WriteScanEnable(); 00385 break; 00386 00387 case HCI_EV_INQUIRY_RESULT: 00388 { 00389 const u8* end = data[1] + data + 2; 00390 data += 3; 00391 while (data < end) 00392 { 00393 inquiry_info align; 00394 memcpy(&align,data,sizeof(inquiry_info)); 00395 InquiryResult(&align); 00396 Callback(CALLBACK_INQUIRY_RESULT,(u8*)&align,sizeof(inquiry_info)); 00397 data += 14; 00398 } 00399 } 00400 break; 00401 00402 case HCI_EV_CONN_COMPLETE: 00403 _state &= ~MASK_CREATE_CONNECTION; 00404 { 00405 connection_info align; 00406 memcpy(&align,data+2,sizeof(connection_info)); 00407 ConnectComplete(&align); 00408 Callback(CALLBACK_CONNECTION_COMPLETE,(u8*)&align,sizeof(connection_info)); 00409 } 00410 break; 00411 00412 case HCI_EV_CONN_REQUEST: 00413 { 00414 request_info align; 00415 memcpy(&align,data+2,sizeof(request_info)); 00416 ConnectRequest(&align); 00417 } 00418 break; 00419 00420 case HCI_EV_DISCONN_COMPLETE: 00421 DisconnectComplete(LE16(data+3)); 00422 break; 00423 00424 case HCI_EV_REMOTE_NAME: 00425 { 00426 BD_ADDR* addr = (BD_ADDR*)(data+3); 00427 const char* name = (const char*)(data + 9); 00428 RemoteName(addr,name); 00429 } 00430 Callback(CALLBACK_REMOTE_NAME,data+3,LE16(data+1)); // addr is in here too 00431 _state &= ~MASK_REMOTE_NAME; 00432 break; 00433 00434 case HCI_EV_CMD_STATUS: 00435 { 00436 const char* errs = HCIErrStr(data[2]); 00437 printf("Status %s %s\r\n",CmdStr(LE16(data+4)),errs); 00438 } 00439 break; 00440 00441 case HCI_EV_CMD_COMPLETE: 00442 OnCommandComplete(data[3] | (data[4] << 8),data+6,data[1]-4); 00443 break; 00444 00445 case HCI_EV_PIN_CODE_REQ: 00446 PinCodeReply(data+2); 00447 break; 00448 00449 case HCI_EV_LINK_KEY_REQ: 00450 SendCmd(HCI_OP_LINK_KEY_NEG_REPLY,data+2,6); 00451 break; 00452 00453 default: 00454 ; 00455 // printfBytes("HCI Event:",data,data[1]+2); 00456 } 00457 } 00458 00459 int HCI::Open(SocketInternal* sock, SocketAddrHdr* addr) 00460 { 00461 L2CAPSocket* l2capsock = (L2CAPSocket*)sock; 00462 L2CAPAddr* l2capaddr = (L2CAPAddr*)addr; 00463 BTDevice* bt = Find(&l2capaddr->bdaddr); 00464 if (!bt) 00465 { 00466 printf("Can't open l2cap %d on ",l2capaddr->psm); 00467 printf(&l2capaddr->bdaddr); 00468 printf("\r\n"); 00469 return ERR_HCI_DEVICE_NOT_FOUND; 00470 } 00471 l2capsock->btdevice = bt; 00472 return bt->Open(sock,addr); 00473 } 00474 00475 int HCI::Create(SocketInternal* sock, SocketAddrHdr* addr) 00476 { 00477 L2CAPSocket* l2capsock = (L2CAPSocket*)sock; 00478 L2CAPAddr* l2capaddr = (L2CAPAddr*)addr; 00479 BTDevice* bt = Find(&l2capaddr->bdaddr); 00480 if (!bt) 00481 { 00482 printf("HCI Create: Can't open l2cap on "); 00483 printf(&l2capaddr->bdaddr); 00484 printf("\r\n"); 00485 return ERR_HCI_DEVICE_NOT_FOUND; 00486 } 00487 l2capsock->btdevice = bt; 00488 //return 0; 00489 return bt->Create(sock,addr); 00490 } 00491 00492 00493 int HCI::Accept(SocketInternal* sock, SocketAddrHdr* addr) 00494 { 00495 00496 printf("Call to HCI Accept \r\n"); 00497 00498 L2CAPSocket* l2capsock = (L2CAPSocket*)sock; 00499 L2CAPAddr* l2capaddr = (L2CAPAddr*)addr; 00500 BTDevice* bt = Find(&l2capaddr->bdaddr); 00501 if (!bt) 00502 { 00503 //printf("Can't open l2cap %d on ",l2capaddr->psm); 00504 printf("HCI Accept: Can't open l2cap on "); 00505 printf(&l2capaddr->bdaddr); 00506 printf("\r\n"); 00507 return ERR_HCI_DEVICE_NOT_FOUND; 00508 } 00509 //l2capsock->btdevice = bt; 00510 return bt->Open(sock,addr); 00511 00512 } 00513 00514 /** 00515 SocketInternal* HCI::Create(SocketInternal* sock) 00516 { 00517 return sock; 00518 } 00519 **/ 00520 00521 00522 int HCI::Send(SocketInternal* sock, const u8* data, int len) 00523 { 00524 L2CAPSocket* l2capsock = (L2CAPSocket*)sock; 00525 return l2capsock->btdevice->Send(sock,data,len); // Pointless double dispatch 00526 } 00527 00528 int HCI::Close(SocketInternal* sock) 00529 { 00530 L2CAPSocket* l2capsock = (L2CAPSocket*)sock; 00531 return l2capsock->btdevice->Close(sock); // Pointless double dispatch 00532 } 00533 00534 void HCI::ACLRecv(const u8* data, int len) 00535 { 00536 int handle = LE16(data); 00537 BD_ADDR* addr; 00538 BTDevice* d = Find(handle & 0x0FFF); 00539 addr = &d->_info.bdaddr; 00540 00541 if (d) 00542 d->ACLRecv(addr,data,len); 00543 } 00544 00545 //=================================================================== 00546 //===================================================================
Generated on Thu Jul 21 2022 21:54:43 by
1.7.2