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