Test Ver

Dependencies:   mbed FatFileSystem

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