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.
Dependencies: C12832 GPS GSM mbed
Fork of myBlueUSB_localfix by
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 #include "USBHost.h" //for USBLoop 00033 #include "HCITransportUSB.h" //for ACL/HCL buffer size 00034 #include "neighbourhood.h" 00035 00036 extern const char FtDevClass[]; 00037 const char FtDevClass[3] = {0x00, 0x1F, 0x82 }; 00038 00039 enum hci_callback_evt { 00040 NONE, 00041 CONNECT, 00042 DISCONECT, 00043 INQUIRYRESULT 00044 }; 00045 00046 #define MAX_BLUETOOTH_ADAPTERS 1 00047 00048 enum StateMask { 00049 MASK_RESET = 1, 00050 MASK_READ_BUFFER_SIZE = 2, 00051 MASK_READ_BD_ADDR = 4, 00052 MASK_INITED = 8, 00053 MASK_INQUIRY = 16, 00054 MASK_REMOTE_NAME = 32, 00055 MASK_CREATE_CONNECTION = 64 00056 }; 00057 00058 //static const u8 local_name[] = "MBED"; 00059 static const u8 local_name[] = "Nonin_Medical_Inc._681010"; 00060 00061 int HCI::Open(HCITransport* transport, HCICallback callback) { 00062 _transport = transport; 00063 _transport->Set(this); 00064 _callback = callback; 00065 _state = 0; 00066 for (int i = 0; i < MAX_BTDEVICES; i++) { 00067 _devices[i].Init(); 00068 _devices[i]._transport = transport; 00069 } 00070 #ifdef COMMAND_FLOW 00071 cmd_credits = 1; 00072 #endif 00073 return SendCmd(HCI_OP_RESET); 00074 } 00075 00076 void printf(const BD_ADDR* addr); 00077 00078 BTDevice* HCI::Find(const BD_ADDR* addr) { 00079 for (int i = 0; i < MAX_BTDEVICES; i++) 00080 if (_devices[i]._state != 0 && memcmp(addr,&_devices[i]._info.bdaddr,6) == 0) 00081 return &_devices[i]; 00082 return 0; 00083 } 00084 00085 BTDevice* HCI::Find(int handle) { 00086 for (int i = 0; i < MAX_BTDEVICES; i++) 00087 if (_devices[i]._state != 0 && handle == _devices[i]._handle) 00088 return &_devices[i]; 00089 return 0; 00090 } 00091 00092 //reports that some commands are still in progress 00093 bool HCI::Busy() { 00094 return (_state & (MASK_INQUIRY | MASK_REMOTE_NAME | MASK_CREATE_CONNECTION)) != 0; 00095 } 00096 00097 int HCI::Inquiry(int duration) { 00098 _state |= MASK_INQUIRY; 00099 u8 buf[5]; 00100 buf[0] = 0x33;//LAP=0x9e8b33 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::SetEventFilter(u8 filterType, u8 filterConditionType, u8* condition) { 00110 int len = 2; 00111 u8 buf[8]; 00112 buf[0] = filterType; 00113 buf[1] = filterConditionType; 00114 switch (filterConditionType) { 00115 case 0://all devices 00116 if (filterType==2) { //connection setup 00117 buf[2] = condition[0]; 00118 len++; 00119 } 00120 break; 00121 case 1: //filter by class 00122 case 2: //filter by BDADDR 00123 memcpy(buf+2, condition, 6); 00124 len += 6; 00125 break; 00126 default: 00127 printf("Unknown filter condition type %d, filter type=%d\n", filterConditionType, filterType); 00128 } 00129 SendCmd(HCI_OP_SET_EVENT_FLT, buf, len); 00130 return 0; 00131 } 00132 00133 int HCI::SendCmd(int cmd, const u8* params, int len) { 00134 u8 b[256]; 00135 b[0] = cmd; 00136 b[1] = (cmd >> 8); 00137 b[2] = len; 00138 if (params) 00139 memcpy(b+3,params,len); 00140 #ifdef COMMAND_FLOW 00141 //printf("%d cmd_credits\n", cmd_credits); 00142 while (cmd_credits == 0) {//blocks when command credits run out 00143 USBLoop(); 00144 putc('_', stdout); 00145 } 00146 #endif 00147 _transport->HCISend(b,len+3); 00148 return 0; 00149 } 00150 00151 void HCI::OnCommandComplete(int cmd, const u8* data, int len) {//data is exclusive the status byte 00152 //printf("%04X %s",cmd,CmdStr(cmd)); 00153 if (len < 0) 00154 return; 00155 //printfBytes(" complete",data,len/*min(16,len)*/); 00156 00157 switch (cmd) { 00158 case 0: //NOP 00159 printf("Received NOP command (for cmd_credits)\n"); 00160 break; 00161 // Init phase 0 00162 case HCI_OP_RESET: // Reset done, init chain to HCI_OP_READ_LOCAL_NAME 00163 SendCmd(HCI_OP_READ_BUFFER_SIZE); 00164 _state |= MASK_RESET; 00165 break; 00166 00167 // Init phase 1 00168 case HCI_OP_READ_BUFFER_SIZE: 00169 _acl_mtu = LE16(data); 00170 _sco_mtu = data[2]; 00171 _acl_max_pkt = LE16(data+3); 00172 _sco_max_pkt = LE16(data+5); 00173 printf("acl_mtu=%d, acl_max_pkt=%d\n", _acl_mtu, _acl_max_pkt); 00174 #ifdef HOST_CONTR_FLOW 00175 _transport->data_credits = _acl_max_pkt; 00176 _transport->_acl_mtu = _acl_mtu; 00177 #endif 00178 SendCmd(HCI_OP_READ_BD_ADDR); 00179 _state |= MASK_READ_BUFFER_SIZE; 00180 break; 00181 00182 // Init phase 2 00183 case HCI_OP_READ_BD_ADDR: 00184 _localAddr = *((BD_ADDR*)data); // Local Address 00185 _state |= MASK_READ_BD_ADDR; 00186 _state |= MASK_INITED; 00187 { 00188 #ifdef CONTR_HOST_FLOW 00189 unsigned char param[7]; 00190 param[0] = (u8)(MAX_ACL_SIZE-8); 00191 param[1] = (u8)((MAX_ACL_SIZE-8)>>8); 00192 param[2] = 0;//MAX_HCL_SIZE-8; 00193 param[3] = 10; 00194 param[4] = 0; //1 ACL buffer 00195 param[5] = 0; 00196 param[6] = 0; //0 Synchronous buffers 00197 SendCmd(HCI_OP_HOST_BUFFER_SIZE, param, 7); 00198 const unsigned char flow = 1;//ACL on, Synchonous off 00199 SendCmd(HCI_OP_CONTR_TO_HOST_FLOW, &flow, 1); 00200 #endif 00201 const unsigned char scan_enable = 3; 00202 SendCmd(HCI_OP_WRITE_SCAN_ENABLE, &scan_enable, 1); 00203 SendCmd(HCI_OP_WRITE_CLASS_OF_DEV, (const u8*)FtDevClass, 3); 00204 //SendCmd(HCI_OP_READ_LOCAL_VERSION, 0, 0); 00205 SendCmd(HCI_OP_WRITE_LOCAL_NAME, local_name, 248); 00206 } 00207 Callback(CALLBACK_READY,data,6); 00208 break; 00209 00210 // 0CXX 00211 case HCI_OP_READ_LOCAL_NAME: 00212 case HCI_OP_LINK_KEY_NEG_REPLY: 00213 case HCI_OP_WRITE_SCAN_ENABLE: 00214 case HCI_OP_WRITE_LOCAL_NAME: 00215 break; 00216 #ifdef CONTR_HOST_FLOW 00217 case HCI_OP_CONTR_TO_HOST_FLOW: 00218 case HCI_OP_HOST_BUFFER_SIZE: 00219 break; 00220 case HCI_OP_NUM_COMP_PKTS: 00221 printf("Host number of Completed Packets: Invalid HCI Command Parameter\n"); 00222 break; 00223 #endif 00224 case HCI_OP_READ_LOCAL_VERSION: 00225 // params 00226 //SendCmd(HCI_OP_READ_LOCAL_NAME); 00227 break; 00228 00229 case HCI_OP_READ_LOCAL_COMMANDS: 00230 break; 00231 00232 case HCI_OP_READ_LOCAL_FEATURES: 00233 //SendCmd(HCI_OP_READ_LOCAL_VERSION); 00234 break; 00235 00236 case HCI_OP_READ_LOCAL_EXT_FEATURES: 00237 break; 00238 00239 case HCI_OP_PIN_CODE_REPLY: 00240 printf("Got pin reply\n"); 00241 break; 00242 case HCI_READ_STORED_LINK_KEY: 00243 neighbors->set_cap(LE16(data), LE16(data+2)); 00244 break; 00245 00246 default: 00247 printf("Unrecognized Command Completion %04X\n",cmd); 00248 break; 00249 } 00250 } 00251 00252 void HCI::Callback(HCI_CALLBACK_EVENT c, const u8* data, int len) { 00253 if (_callback) _callback(this,c,data,len); 00254 // (this->*_callback)(c, data, len); 00255 } 00256 00257 int HCI::RemoteNameRequest(const BD_ADDR* addr) { 00258 _state |= MASK_REMOTE_NAME; 00259 u8 buf[6+4]; 00260 memset(buf,0,sizeof(buf)); 00261 memcpy(buf,addr,6); 00262 //buf[7] = 1; 00263 return SendCmd(HCI_OP_REMOTE_NAME_REQ,buf,sizeof(buf)); 00264 } 00265 00266 int HCI::RemoteNameRequest(inquiry_info *ii) { 00267 _state |= MASK_REMOTE_NAME; 00268 u8 buf[6+4]; 00269 //memset(buf,0,sizeof(buf)); 00270 memcpy(buf,&ii->bdaddr,6); 00271 buf[6] = ii->pscan_rep_mode; 00272 buf[7] = 0; 00273 *(unsigned short*)(buf+8) = 0; 00274 return SendCmd(HCI_OP_REMOTE_NAME_REQ,buf,sizeof(buf)); 00275 } 00276 00277 int HCI::CreateConnection(const BD_ADDR* remoteAddr) { 00278 _state |= MASK_CREATE_CONNECTION; 00279 u8 buf[6+7]; 00280 memset(buf,0,sizeof(buf)); 00281 memcpy(buf,remoteAddr,6); 00282 buf[6] = 0x18; // DM1,DH1 00283 buf[7] = 0xCC; // DM3, DH3, DM5, DH5 00284 buf[8] = 1; // Page Repetition R1 00285 return SendCmd(HCI_OP_CREATE_CONN,buf,sizeof(buf)); 00286 } 00287 00288 int HCI::Disconnect(const BD_ADDR* bdaddr) { 00289 BTDevice* d = Find(bdaddr); 00290 if (!d) 00291 return ERR_HCI_DEVICE_NOT_FOUND; 00292 int handle = d->_handle; 00293 printf("Disconnect from %d\n",handle); 00294 _state |= MASK_CREATE_CONNECTION; 00295 u8 buf[3]; 00296 buf[0] = handle; 00297 buf[1] = (handle >> 8); 00298 buf[2] = 0x13; 00299 return SendCmd(HCI_OP_DISCONNECT,buf,sizeof(buf)); 00300 } 00301 00302 void HCI::DisconnectComplete(int handle) { 00303 BTDevice* d = Find(handle); 00304 if (!d) 00305 return; 00306 d->_handle = 0; 00307 } 00308 00309 int HCI::DisconnectAll() { 00310 BTDevice* devs[8]; 00311 int count = GetDevices(devs,8); 00312 for (int i = 0; i < count; i++) 00313 Disconnect(&devs[i]->_info.bdaddr); 00314 return 0; 00315 } 00316 00317 int HCI::PinCodeReply(const u8* data, const u8* pin) { 00318 u8 b[6+1+16]; 00319 memset(b,0,sizeof(b)); 00320 memcpy(b,data,6); 00321 b[6] = 6; 00322 memcpy(b+7, pin, 6); 00323 return SendCmd(HCI_OP_PIN_CODE_REPLY,b,sizeof(b)); 00324 } 00325 00326 void HCI::InquiryResult(const inquiry_info* info) { 00327 BTDevice* bt = Find(&info->bdaddr); 00328 if (!bt) { // new device 00329 for (int i = 0; i < MAX_BTDEVICES; i++) { 00330 if (_devices[i]._state == 0) { 00331 bt = _devices + i; 00332 bt->_state = 1; 00333 break; 00334 } 00335 } 00336 if (!bt) { 00337 printf("HCI::InquiryResult too many devices\n"); 00338 return; // Too many devices! 00339 } 00340 } 00341 00342 bt->_info = *info; 00343 } 00344 00345 int HCI::GetDevices(BTDevice** devices, int maxDevices) { 00346 int j = 0; 00347 for (int i = 0; i < MAX_BTDEVICES; i++) { 00348 if (_devices[i]._state != 0) { 00349 devices[j++] = _devices + i; 00350 if (j == maxDevices) 00351 break; 00352 } 00353 } 00354 return j; 00355 } 00356 00357 void HCI::RemoteName(const BD_ADDR* addr, const char* name) { 00358 BTDevice* d = Find(addr); 00359 if (d) { 00360 strncpy(d->_name,name,sizeof(d->_name)-1); 00361 d->_name[sizeof(d->_name)-1] = 0; 00362 } 00363 } 00364 00365 void HCI::ConnectComplete(const connection_info* info) { 00366 BTDevice* d = Find(&info->bdaddr); 00367 if (!d) { 00368 printf("BT Device not known!?! "); 00369 printf(&info->bdaddr); 00370 printf("\n"); 00371 return; 00372 } 00373 if (info->status == 0) { 00374 d->_handle = info->handle; 00375 #ifdef HOST_CONTR_FLOW 00376 d->pkts_sent = 0; 00377 #endif 00378 printf("Connected on %04X\n",info->handle); 00379 } else 00380 printf("Connection failed with %d\n",info->status); 00381 } 00382 00383 void HCI::Accept_Connection(const BD_ADDR* addr, bool slave) { 00384 unsigned char b[7]; 00385 memcpy(b, addr, 6); 00386 b[6] = slave; 00387 BTDevice* bt = Find(addr); 00388 if (!bt) { 00389 printf("Received connection request from undiscovered device\n"); 00390 for (int i = 0; i < MAX_BTDEVICES; i++) { 00391 if (_devices[i]._state == 0) { 00392 bt = _devices + i; 00393 bt->_state = 1; 00394 memcpy(&(bt->_info.bdaddr), addr, 6);//rest of inquiry info unknown!!! 00395 break; 00396 } 00397 } 00398 if (!bt) { 00399 printf("HCI::InquiryResult too many devices\n"); 00400 return; // Too many devices! 00401 } 00402 } 00403 SendCmd(HCI_OP_ACCEPT_CONN_REQ, b , 7); 00404 } 00405 00406 void HCI::HCIRecv(const u8* data, int len) {//[0]=event, [1]=parlen, [2...]=pars 00407 printfBytes(EvtStr(data[0]),data,min(len,16)); 00408 switch (data[0]) { 00409 case HCI_EV_INQUIRY_COMPLETE: 00410 printfBytes("Inquiry Complete",data,data[1]); 00411 _state &= ~MASK_INQUIRY; 00412 Callback(CALLBACK_INQUIRY_DONE,0,0); 00413 break; 00414 00415 case HCI_EV_INQUIRY_RESULT: { 00416 const u8* end = data[1] + data + 2; 00417 data += 3; 00418 while (data < end) { 00419 inquiry_info align; 00420 memcpy(&align,data,sizeof(inquiry_info)); 00421 InquiryResult(&align); 00422 Callback(CALLBACK_INQUIRY_RESULT,(u8*)&align,sizeof(inquiry_info)); 00423 data += 14; 00424 } 00425 } 00426 break; 00427 00428 case HCI_EV_CONN_COMPLETE: 00429 _state &= ~MASK_CREATE_CONNECTION; 00430 { 00431 connection_info align; 00432 memcpy(&align,data+2,sizeof(connection_info)); 00433 ConnectComplete(&align); 00434 Callback(CALLBACK_CONNECTION_COMPLETE,(u8*)&align,sizeof(connection_info)); 00435 } 00436 break; 00437 00438 case HCI_EV_CONN_REQUEST: 00439 printf("Got Connection request \n"); 00440 Callback(CALLBACK_CONNECTION_REQUEST, data+2, data[1]); 00441 Accept_Connection((BD_ADDR*)(data+2)); 00442 break; 00443 00444 case HCI_EV_DISCONN_COMPLETE: 00445 DisconnectComplete(LE16(data+3)); 00446 break; 00447 00448 case HCI_EV_REMOTE_NAME: { 00449 BD_ADDR* addr = (BD_ADDR*)(data+3); 00450 const char* name = (const char*)(data + 9); 00451 RemoteName(addr,name); 00452 } 00453 Callback(CALLBACK_REMOTE_NAME,data+3,LE16(data+1)); // addr is in here too 00454 _state &= ~MASK_REMOTE_NAME; 00455 break; 00456 00457 case HCI_EV_CMD_STATUS: { 00458 const char* errs = HCIErrStr(data[2]); 00459 printf("Status %s %s %d cmd pkts\n",CmdStr(LE16(data+4)),errs, data[3]); 00460 #ifdef COMMAND_FLOW 00461 cmd_credits = data[3]; 00462 #endif 00463 } 00464 Callback(CALLBACK_CMD_STATUS, data+2, 4); 00465 break; 00466 00467 case HCI_EV_CMD_COMPLETE://[2]=cmd-pkts, [3-4]=cmd, [5...]=pars 00468 if (data[5]) { //[5]=usually status 00469 printf("HCIRecv error status: %s\n", HCIErrStr(data[5])); 00470 } 00471 OnCommandComplete(data[3] | (data[4] << 8), data+6, data[1]-4); 00472 #ifdef COMMAND_FLOW 00473 cmd_credits = data[2]; 00474 #endif 00475 break; 00476 00477 case HCI_EV_PIN_CODE_REQ: 00478 Callback(CALLBACK_PIN_REQ, data+2, 6); 00479 //PinCodeReply(data+2); 00480 break; 00481 00482 case HCI_EV_LINK_KEY_REQ: { 00483 u8 param[22]; 00484 if (neighbors->get((BD_ADDR*)(data+2), param+sizeof(BD_ADDR))){ 00485 memcpy(param, data+2, sizeof(BD_ADDR)); 00486 SendCmd(HCI_OP_LINK_KEY_REPLY,param,sizeof(param)); 00487 } else 00488 SendCmd(HCI_OP_LINK_KEY_NEG_REPLY,data+2,6); 00489 } 00490 break; 00491 #ifdef HOST_CONTR_FLOW 00492 case HCI_EV_NUM_COMP_PKTS: 00493 for (int k = 0; k < data[2]; k++) {//data[2] and 'c' are usually 1 00494 u16 h = LE16(data+3+2*k); 00495 u16 c = LE16(data+5+2*k); 00496 BTDevice *d = Find(h); 00497 if (!d) 00498 continue;//skip no existing devices 00499 if (d->pkts_sent >= c) { 00500 d->pkts_sent -= c; 00501 _transport->data_credits += c; 00502 } else 00503 d->pkts_sent = 0; 00504 //printf("%d Outstanding pkts for handle %03X (total credits=%d)\n", d->pkts_sent, h, _transport->data_credits); 00505 } 00506 break; 00507 #endif 00508 case HCI_EV_LINK_KEY_NOTIFY: 00509 neighbors->add((BD_ADDR*)(data+2), data+8); 00510 break; 00511 case HCI_EV_RETURN_LINK_KEYS: 00512 for (int i = 0; i < data[2]; i++) 00513 neighbors->add((BD_ADDR*)(data+3+22*i), data+9+22*i, true); 00514 break; 00515 case HCI_EV_ENCRYPT_CHANGE: 00516 //for(int k=0; k<1000000;k++) USBLoop(); 00517 break; 00518 case HCI_EV_VENDOR: 00519 Callback(CALLBACK_VENDOR, data+2, data[1]); 00520 break; 00521 default: 00522 printfBytes("HCIRecv:",data,data[1]+2); 00523 break; 00524 } 00525 } 00526 00527 int HCI::Open(SocketInternal* sock, SocketAddrHdr* addr) { 00528 L2CAPSocket* l2capsock = (L2CAPSocket*)sock; 00529 L2CAPAddr* l2capaddr = (L2CAPAddr*)addr; 00530 BTDevice* bt = Find(&l2capaddr->bdaddr); 00531 if (!bt) { 00532 printf("Can't open l2cap %d on ",l2capaddr->psm); 00533 printf(&l2capaddr->bdaddr); 00534 printf("\n"); 00535 return ERR_HCI_DEVICE_NOT_FOUND; 00536 } 00537 l2capsock->btdevice = bt; 00538 return bt->Open(sock,addr); 00539 } 00540 00541 int HCI::Accept(SocketInternal* sock, int scid, int rxid) { 00542 L2CAPSocket* l2capsock = (L2CAPSocket*)sock; 00543 BTDevice* bt = (BTDevice*)sock->userData; 00544 if (!bt) { 00545 printf("Can't accept l2cap on socket %d\n", sock->ID); 00546 return ERR_HCI_DEVICE_NOT_FOUND; 00547 } 00548 l2capsock->btdevice = bt; 00549 return bt->Accept(sock, scid, rxid); 00550 } 00551 00552 int HCI::Send(SocketInternal* sock, const u8* data, int len) {//check here for appropriate buffersize on the device 00553 /* these checks are HCI functions but this 'Send' does not catch all ACL traffic, so it is better done in L2CAP or transport 00554 //assume acl packet 00555 //FIXME: treatment of OFFSET is dubious, OFFSET is not defined?! 00556 #if OFFSET==8 //sizeof ACL/L2CAP is include in data/len 00557 if (len > _acl_mtu) 00558 #else //OFFSET==0, data is bare application frame 00559 if (len+8 > _acl_mtu) 00560 #endif 00561 { printf("Max outgoing packet(%d) size exceeded, segmenting necessary, pktlen = %d\n", _acl_mtu, len); 00562 } 00563 if (data_credits == 0) { 00564 printf("Out of ACL data credits\n"); 00565 return 0; 00566 } 00567 data_credits--; 00568 */ 00569 L2CAPSocket* l2capsock = (L2CAPSocket*)sock; 00570 return l2capsock->btdevice->Send(sock,data,len); // Pointless double dispatch 00571 } 00572 00573 int HCI::Close(SocketInternal* sock) { 00574 L2CAPSocket* l2capsock = (L2CAPSocket*)sock; 00575 return l2capsock->btdevice->Close(sock); // Pointless double dispatch 00576 } 00577 00578 void HCI::Compl_pkts(int handle, u8 p) { 00579 u8 b[8] = {(u8)HCI_OP_NUM_COMP_PKTS, HCI_OP_NUM_COMP_PKTS >> 8, 5, 1, 0, 0, 1, 0}; 00580 b[4] = handle; 00581 b[5] = (handle&0x0f00)>>8; 00582 b[6] = p;//only one packet 00583 _transport->HCISend(b, 8);//directly call the transport layer to prevent the command flow control from interfering 00584 } 00585 00586 void HCI::ACLRecv(const u8* data, int len) { 00587 int handle = LE16(data); 00588 BTDevice* d = Find(handle & 0x0FFF); 00589 int bufs = 1; 00590 if (!d) { 00591 printfBytes("unk. dest. HCI:ACLRecv ", data, len); 00592 } else 00593 bufs = d->ACLRecv(data,len); 00594 //controller to host flow control 00595 #ifdef CONTR_HOST_FLOW 00596 //the ACLRecv function returned so we assume that the buffer is free, and tell this to the controller 00597 if (bufs) { 00598 Compl_pkts(handle, bufs);//this packet is completed 00599 printf("%d ACL buffers completed\n", bufs); 00600 } 00601 #endif 00602 } 00603 00604 //=================================================================== 00605 //===================================================================
Generated on Wed Jul 13 2022 02:37:52 by
1.7.2
