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

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[] = "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 //===================================================================