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