Yasuhiko YAMAMOTO / Mbed 2 deprecated mbed_TANK_PS3

Dependencies:   TextLCD mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers hci.cpp Source File

hci.cpp

00001 /*
00002 Copyright (c) 2010 Peter Barrett
00003 
00004 Permission is hereby granted, free of charge, to any person obtaining a copy
00005 of this software and associated documentation files (the "Software"), to deal
00006 in the Software without restriction, including without limitation the rights
00007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008 copies of the Software, and to permit persons to whom the Software is
00009 furnished to do so, subject to the following conditions:
00010 
00011 The above copyright notice and this permission notice shall be included in
00012 all copies or substantial portions of the Software.
00013 
00014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020 THE SOFTWARE.
00021 */
00022 
00023 /* 
00024 Tue Apr 26 2011 Bart Janssens: added HCI connection accept
00025 */
00026 
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <stdio.h>
00030 #include <string.h>
00031 
00032 #include "Utils.h"
00033 #include "hci.h"
00034 #include "hci_private.h"
00035 
00036 enum hci_callback_evt
00037 {
00038     NONE,
00039     CONNECT,
00040     DISCONECT,
00041     INQUIRYRESULT
00042 };
00043 
00044 #define MAX_BLUETOOTH_ADAPTERS 1
00045 
00046 enum StateMask {
00047     MASK_RESET = 1,
00048     MASK_READ_BUFFER_SIZE = 2,
00049     MASK_READ_BD_ADDR = 4,
00050     MASK_INITED = 8,
00051     MASK_INQUIRY = 16,
00052     MASK_REMOTE_NAME = 32,
00053     MASK_CREATE_CONNECTION = 64
00054 };
00055 
00056 int  HCI::Open(HCITransport* transport, HCICallback callback)
00057 {
00058     _transport = transport;
00059     _transport->Set(this);
00060     _callback = callback;
00061     _state = 0;
00062     for (int i = 0; i < MAX_BTDEVICES; i++)
00063     {
00064         _devices[i].Init();
00065         _devices[i]._transport = transport;
00066     }
00067     return SendCmd(HCI_OP_RESET);
00068 }
00069 
00070 void printf(const BD_ADDR* addr);
00071 
00072 BTDevice* HCI::Find(const BD_ADDR* addr)
00073 {
00074     for (int i = 0; i < MAX_BTDEVICES; i++)
00075         if (_devices[i]._state != 0 && memcmp(addr,&_devices[i]._info.bdaddr,6) == 0)
00076             return &_devices[i];
00077     return 0;
00078 }
00079 
00080 BTDevice* HCI::Find(int handle)
00081 {
00082     for (int i = 0; i < MAX_BTDEVICES; i++)
00083         if (_devices[i]._state != 0 && handle == _devices[i]._handle)
00084             return &_devices[i];
00085     return 0;
00086 }
00087 //
00088 bool HCI::Busy()
00089 {
00090     return (_state & (MASK_INQUIRY | MASK_REMOTE_NAME | MASK_CREATE_CONNECTION)) != 0;
00091 }
00092 
00093 int HCI::Inquiry(int duration)
00094 {
00095     _state |= MASK_INQUIRY;
00096     u8 buf[5];
00097     buf[0] = 0x33;
00098     buf[1] = 0x8B;
00099     buf[2] = 0x9E;
00100     buf[3] = duration;
00101     buf[4] = 5;  // 5 results
00102     SendCmd(HCI_OP_INQUIRY,buf,sizeof(buf));
00103     return 0;
00104 }
00105 
00106 int HCI::WriteScanEnable()
00107 {
00108    
00109 //    u8 buf[2];
00110 //    buf[0] = 0x03;
00111 //    buf[1] = 0x01;    
00112 
00113     u8 buf[1];
00114     buf[0] = 0x03;
00115     
00116     SendCmd(HCI_OP_WRITE_SCAN_ENABLE,buf,sizeof(buf));
00117     return 0;
00118 }
00119 
00120 int HCI::AcceptConnection(const BD_ADDR* addr)
00121 {
00122 //    u8 buf[6+4];
00123 //    memset(buf,0,sizeof(buf));
00124 //    memcpy(buf,addr,6);
00125 //    buf[7] = 0;      
00126     
00127     u8 buf[6+1];
00128     memset(buf,0,sizeof(buf));
00129     memcpy(buf,addr,6);
00130     buf[6] = 0;      
00131 
00132     SendCmd(HCI_OP_ACCEPT_CONN_REQ,buf,sizeof(buf));
00133     return 0;
00134 }
00135 
00136 int HCI::SendCmd(int cmd, const u8* params, int len)
00137 {
00138     u8 b[32];
00139     b[0] = cmd;
00140     b[1] = (cmd >> 8);
00141     b[2] = len;
00142     if (params)
00143         memcpy(b+3,params,len);
00144     _transport->HCISend(b,len+3);
00145     return 0;
00146 }
00147 
00148 void HCI::OnCommandComplete(int cmd, const u8* data, int len)
00149 {
00150    // printf("%04X %s",cmd,CmdStr(cmd));
00151     if (len < 0)
00152         return;
00153     //printfBytes(" complete",data,min(16,len));
00154 
00155     switch (cmd)
00156     {
00157         //  Init phase 0
00158         case HCI_OP_RESET:  // Reset done, init chain to HCI_OP_READ_LOCAL_NAME
00159             SendCmd(HCI_OP_READ_BUFFER_SIZE);
00160             _state |= MASK_RESET;
00161             break;
00162 
00163         //  Init phase 1
00164         case HCI_OP_READ_BUFFER_SIZE:
00165             _acl_mtu = LE16(data);
00166             _sco_mtu = data[2];
00167             _acl_max_pkt = LE16(data+3);
00168             _sco_max_pkt = LE16(data+5);
00169             SendCmd(HCI_OP_READ_BD_ADDR);
00170             _state |= MASK_READ_BUFFER_SIZE;
00171             break;
00172 
00173         //  Init phase 2
00174         case HCI_OP_READ_BD_ADDR:
00175             _localAddr = *((BD_ADDR*)data); // Local Address
00176             printf("Local Address: ");
00177              printf(&_localAddr);
00178              printf("\r\n");
00179              
00180             _state |= MASK_READ_BD_ADDR;
00181             _state |= MASK_INITED;
00182             Callback(CALLBACK_READY,data,6);
00183             break;
00184 
00185                    // 0CXX
00186         case HCI_OP_READ_LOCAL_NAME:
00187             break;
00188 
00189         case HCI_OP_READ_LOCAL_VERSION:
00190             // params
00191             //SendCmd(HCI_OP_READ_LOCAL_NAME);
00192             break;
00193 
00194         case HCI_OP_READ_LOCAL_COMMANDS:
00195             break;
00196 
00197         case HCI_OP_READ_LOCAL_FEATURES:
00198             //SendCmd(HCI_OP_READ_LOCAL_VERSION);
00199             break;
00200 
00201         case HCI_OP_READ_LOCAL_EXT_FEATURES:
00202             break;
00203 
00204         case HCI_OP_PIN_CODE_REPLY:
00205             printf("Got pin reply\r\n");
00206             break;
00207 
00208         default:
00209             //printf("Unrecognized Command %04X\r\n",cmd);
00210             break;
00211     }
00212 }
00213 
00214 void HCI::Callback(HCI_CALLBACK_EVENT c, const u8* data, int len)
00215 {
00216     _callback(this,c,data,len);
00217 }
00218 
00219 int HCI::RemoteNameRequest(const BD_ADDR* addr)
00220 {
00221     _state |= MASK_REMOTE_NAME;
00222     u8 buf[6+4];
00223     memset(buf,0,sizeof(buf));
00224     memcpy(buf,addr,6);
00225     buf[7] = 1;
00226     return SendCmd(HCI_OP_REMOTE_NAME_REQ,buf,sizeof(buf));
00227 }
00228 
00229 int HCI::CreateConnection(const BD_ADDR* remoteAddr)
00230 {
00231     _state |= MASK_CREATE_CONNECTION;
00232     u8 buf[6+7];
00233     memset(buf,0,sizeof(buf));
00234     memcpy(buf,remoteAddr,6);
00235     buf[6] = 0x18;  // DM1,DH1
00236     buf[7] = 0xCC;  // DM3, DH3, DM5, DH5
00237     buf[8] = 1;     // Page Repetition R1
00238     return SendCmd(HCI_OP_CREATE_CONN,buf,sizeof(buf));
00239 }
00240 
00241 int HCI::Disconnect(const BD_ADDR* bdaddr)
00242 {
00243     BTDevice* d = Find(bdaddr);
00244     if (!d)
00245         return ERR_HCI_DEVICE_NOT_FOUND;
00246     int handle = d->_handle;
00247     printf("Disconnect from %d\r\n",handle);
00248     _state |= MASK_CREATE_CONNECTION;
00249     u8 buf[3];
00250     buf[0] = handle;
00251     buf[1] = (handle >> 8);
00252     buf[2] = 0x13;
00253     return SendCmd(HCI_OP_DISCONNECT,buf,sizeof(buf));
00254 }
00255 
00256 void HCI::DisconnectComplete(int handle)
00257 {
00258     BTDevice* d = Find(handle);
00259     if (!d)
00260         return;
00261     d->_handle = 0;
00262 }
00263 
00264 int HCI::DisconnectAll()
00265 {
00266     BTDevice* devs[8];
00267     int count = GetDevices(devs,8);
00268     for (int i = 0; i < count; i++)
00269         Disconnect(&devs[i]->_info.bdaddr);
00270     return 0;
00271 }
00272 
00273 int HCI::PinCodeReply(const u8* data)
00274 {
00275     u8 b[6+1+16];
00276     memset(b,0,sizeof(b));
00277     memcpy(b,data,6);
00278     b[6] = 4;
00279     b[7] = '0';
00280     b[8] = '0';
00281     b[9] = '0';
00282     b[10] = '0';
00283     return SendCmd(HCI_OP_PIN_CODE_REPLY,b,sizeof(b));
00284 }
00285 
00286 void HCI::InquiryResult(const inquiry_info* info)
00287 {
00288     BTDevice* bt = Find(&info->bdaddr);
00289     if (!bt)    // new device
00290     {
00291         for (int i = 0; i < MAX_BTDEVICES; i++)
00292         {
00293             if (_devices[i]._state == 0)
00294             {
00295                 bt = _devices + i;
00296                 bt->_state = 1;
00297                 break;
00298             }
00299         }
00300         if (!bt)
00301         {
00302             printf("HCI::InquiryResult too many devices\r\n");
00303             return; // Too many devices!
00304         }
00305     }
00306 
00307     bt->_info = *info;
00308 }
00309 
00310 int HCI::GetDevices(BTDevice** devices, int maxDevices)
00311 {
00312     int j = 0;
00313     for (int i = 0; i < MAX_BTDEVICES; i++)
00314     {
00315         if (_devices[i]._state != 0)
00316         {
00317             devices[j++] = _devices + i;
00318             if (j == maxDevices)
00319                 break;
00320         }
00321     }
00322     return j;
00323 }
00324 
00325 void HCI::RemoteName(const BD_ADDR* addr, const char* name)
00326 {
00327     BTDevice* d = Find(addr);
00328     if (d)
00329     {
00330         strncpy(d->_name,name,sizeof(d->_name)-1);
00331         d->_name[sizeof(d->_name)-1] = 0;
00332     }
00333 }
00334 
00335 void HCI::ConnectComplete(const connection_info* info)
00336 {
00337     BTDevice* d = Find(&info->bdaddr);
00338     if (!d)
00339         return;
00340     if (info->status == 0)
00341     {
00342         d->_handle = info->handle;
00343         printf("Connected on %04X\r\n",info->handle);
00344     } else
00345         printf("Connection failed with %d\r\n",info->status);
00346 }
00347 
00348 void HCI::ConnectRequest(const request_info* info)
00349 {
00350     BTDevice* bt = Find(&info->bdaddr);
00351     if (!bt)    // new device
00352     {
00353         for (int i = 0; i < MAX_BTDEVICES; i++)
00354         {
00355             if (_devices[i]._state == 0)
00356             {
00357                 bt = _devices + i;
00358                 bt->_state = 1;
00359                 break;
00360             }
00361         }
00362         if (!bt)
00363         {
00364             printf("HCI::ConnectRequest too many devices\r\n");
00365             return; // Too many devices!
00366         }
00367     }
00368    bt->_info.bdaddr = info->bdaddr;
00369    memcpy(bt->_info.dev_class,info->dev_class,3);
00370    AcceptConnection(&info->bdaddr);
00371 }
00372 
00373 void HCI::HCIRecv(const u8* data, int len)
00374 {
00375     //printfBytes(EvtStr(data[0]),data,len);
00376     //printfBytes(EvtStr(data[0]),data,min(len,16));
00377     //printf("HCI Event %02X\r\n",data[0]);
00378     switch (data[0])
00379     {
00380         case HCI_EV_INQUIRY_COMPLETE:
00381             printfBytes("Inquiry Complete",data,data[1]);
00382             _state &= ~MASK_INQUIRY;
00383             Callback(CALLBACK_INQUIRY_DONE,0,0);
00384             WriteScanEnable();
00385             break;
00386 
00387         case HCI_EV_INQUIRY_RESULT:
00388             {
00389                 const u8* end = data[1] + data + 2;
00390                 data += 3;
00391                 while (data < end)
00392                 {
00393                     inquiry_info align;
00394                     memcpy(&align,data,sizeof(inquiry_info));
00395                     InquiryResult(&align);
00396                     Callback(CALLBACK_INQUIRY_RESULT,(u8*)&align,sizeof(inquiry_info));
00397                     data += 14;
00398                 }
00399             }
00400             break;
00401 
00402         case HCI_EV_CONN_COMPLETE:
00403             _state &= ~MASK_CREATE_CONNECTION;
00404             {
00405                 connection_info align;
00406                 memcpy(&align,data+2,sizeof(connection_info));
00407                 ConnectComplete(&align);
00408                 Callback(CALLBACK_CONNECTION_COMPLETE,(u8*)&align,sizeof(connection_info));
00409             }
00410             break;
00411 
00412         case HCI_EV_CONN_REQUEST:
00413             {
00414                 request_info align;
00415                 memcpy(&align,data+2,sizeof(request_info));
00416                 ConnectRequest(&align);
00417             }
00418             break;
00419 
00420         case HCI_EV_DISCONN_COMPLETE:
00421             DisconnectComplete(LE16(data+3));
00422             break;
00423 
00424         case HCI_EV_REMOTE_NAME:
00425             {
00426                 BD_ADDR* addr = (BD_ADDR*)(data+3);
00427                 const char* name = (const char*)(data + 9);
00428                 RemoteName(addr,name);
00429             }
00430             Callback(CALLBACK_REMOTE_NAME,data+3,LE16(data+1));    // addr is in here too
00431             _state &= ~MASK_REMOTE_NAME;
00432             break;
00433 
00434         case HCI_EV_CMD_STATUS:
00435             {
00436                 const char* errs = HCIErrStr(data[2]);
00437                 printf("Status %s %s\r\n",CmdStr(LE16(data+4)),errs);
00438             }
00439             break;
00440 
00441         case HCI_EV_CMD_COMPLETE:
00442             OnCommandComplete(data[3] | (data[4] << 8),data+6,data[1]-4);
00443             break;
00444 
00445         case HCI_EV_PIN_CODE_REQ:
00446             PinCodeReply(data+2);
00447             break;
00448 
00449         case HCI_EV_LINK_KEY_REQ:
00450             SendCmd(HCI_OP_LINK_KEY_NEG_REPLY,data+2,6);
00451             break;
00452 
00453         default:
00454         ;
00455            // printfBytes("HCI Event:",data,data[1]+2);
00456     }
00457 }
00458 
00459 int HCI::Open(SocketInternal* sock, SocketAddrHdr* addr)
00460 {
00461     L2CAPSocket* l2capsock = (L2CAPSocket*)sock;
00462     L2CAPAddr* l2capaddr = (L2CAPAddr*)addr;
00463     BTDevice* bt = Find(&l2capaddr->bdaddr);
00464     if (!bt)
00465     {
00466         printf("Can't open l2cap %d on ",l2capaddr->psm);
00467         printf(&l2capaddr->bdaddr);
00468         printf("\r\n");
00469         return ERR_HCI_DEVICE_NOT_FOUND;
00470     }
00471     l2capsock->btdevice = bt;
00472     return bt->Open(sock,addr);
00473 }
00474 
00475 int HCI::Create(SocketInternal* sock, SocketAddrHdr* addr)
00476 {
00477     L2CAPSocket* l2capsock = (L2CAPSocket*)sock;
00478     L2CAPAddr* l2capaddr = (L2CAPAddr*)addr;
00479     BTDevice* bt = Find(&l2capaddr->bdaddr);
00480     if (!bt)
00481     {
00482         printf("HCI Create: Can't open l2cap on ");
00483         printf(&l2capaddr->bdaddr);
00484         printf("\r\n");
00485         return ERR_HCI_DEVICE_NOT_FOUND;
00486     }
00487     l2capsock->btdevice = bt;
00488     //return 0;
00489     return bt->Create(sock,addr);
00490 }
00491 
00492 
00493 int HCI::Accept(SocketInternal* sock, SocketAddrHdr* addr)
00494 {
00495 
00496     printf("Call to HCI Accept \r\n"); 
00497     
00498     L2CAPSocket* l2capsock = (L2CAPSocket*)sock;
00499     L2CAPAddr* l2capaddr = (L2CAPAddr*)addr;
00500     BTDevice* bt = Find(&l2capaddr->bdaddr);
00501     if (!bt)
00502     {
00503         //printf("Can't open l2cap %d on ",l2capaddr->psm);
00504         printf("HCI Accept: Can't open l2cap on ");
00505         printf(&l2capaddr->bdaddr);
00506         printf("\r\n");
00507         return ERR_HCI_DEVICE_NOT_FOUND;
00508     }
00509     //l2capsock->btdevice = bt;
00510     return bt->Open(sock,addr);
00511         
00512 }
00513 
00514 /**
00515 SocketInternal* HCI::Create(SocketInternal* sock)
00516 {
00517     return sock;    
00518 }
00519 **/
00520 
00521 
00522 int HCI::Send(SocketInternal* sock, const u8* data, int len)
00523 {
00524     L2CAPSocket* l2capsock = (L2CAPSocket*)sock;
00525     return l2capsock->btdevice->Send(sock,data,len);    // Pointless double dispatch
00526 }
00527 
00528 int HCI::Close(SocketInternal* sock)
00529 {
00530     L2CAPSocket* l2capsock = (L2CAPSocket*)sock;
00531     return l2capsock->btdevice->Close(sock);    // Pointless double dispatch
00532 }
00533 
00534 void HCI::ACLRecv(const u8* data, int len)
00535 {
00536     int handle = LE16(data);
00537     BD_ADDR* addr;
00538     BTDevice* d = Find(handle & 0x0FFF);
00539     addr = &d->_info.bdaddr;
00540     
00541     if (d)
00542         d->ACLRecv(addr,data,len);
00543 }
00544 
00545 //===================================================================
00546 //===================================================================