Sami Alshorman / Mbed 2 deprecated BluetoothNONIN

Dependencies:   C12832 GPS GSM mbed

Fork of myBlueUSB_localfix by Nobuaki Aoki

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers hci.cpp Source File

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 //===================================================================