Simons Wii controlled m3pi program

Dependencies:   mbed m3pi ID12RFIDIRQ

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 enum hci_callback_evt
00034 {
00035     NONE,
00036     CONNECT,
00037     DISCONECT,
00038     INQUIRYRESULT
00039 };
00040 
00041 #define MAX_BLUETOOTH_ADAPTERS 1
00042 
00043 enum StateMask {
00044     MASK_RESET = 1,
00045     MASK_READ_BUFFER_SIZE = 2,
00046     MASK_READ_BD_ADDR = 4,
00047     MASK_INITED = 8,
00048     MASK_INQUIRY = 16,
00049     MASK_REMOTE_NAME = 32,
00050     MASK_CREATE_CONNECTION = 64
00051 };
00052 
00053 int  HCI::Open(HCITransport* transport, HCICallback callback)
00054 {
00055     _transport = transport;
00056     _transport->Set(this);
00057     _callback = callback;
00058     _state = 0;
00059     for (int i = 0; i < MAX_BTDEVICES; i++)
00060     {
00061         _devices[i].Init();
00062         _devices[i]._transport = transport;
00063     }
00064     return SendCmd(HCI_OP_RESET);
00065 }
00066 
00067 void printf(const BD_ADDR* addr);
00068 
00069 BTDevice* HCI::Find(const BD_ADDR* addr)
00070 {
00071     for (int i = 0; i < MAX_BTDEVICES; i++)
00072         if (_devices[i]._state != 0 && memcmp(addr,&_devices[i]._info.bdaddr,6) == 0)
00073             return &_devices[i];
00074     return 0;
00075 }
00076 
00077 BTDevice* HCI::Find(int handle)
00078 {
00079     for (int i = 0; i < MAX_BTDEVICES; i++)
00080         if (_devices[i]._state != 0 && handle == _devices[i]._handle)
00081             return &_devices[i];
00082     return 0;
00083 }
00084 //
00085 bool HCI::Busy()
00086 {
00087     return (_state & (MASK_INQUIRY | MASK_REMOTE_NAME | MASK_CREATE_CONNECTION)) != 0;
00088 }
00089 
00090 int HCI::Inquiry(int duration)
00091 {
00092     _state |= MASK_INQUIRY;
00093     u8 buf[5];
00094     buf[0] = 0x33;
00095     buf[1] = 0x8B;
00096     buf[2] = 0x9E;
00097     buf[3] = duration;
00098     buf[4] = 5;  // 5 results
00099     SendCmd(HCI_OP_INQUIRY,buf,sizeof(buf));
00100     return 0;
00101 }
00102 
00103 int HCI::SendCmd(int cmd, const u8* params, int len)
00104 {
00105     u8 b[32];
00106     b[0] = cmd;
00107     b[1] = (cmd >> 8);
00108     b[2] = len;
00109     if (params)
00110         memcpy(b+3,params,len);
00111     _transport->HCISend(b,len+3);
00112     return 0;
00113 }
00114 
00115 void HCI::OnCommandComplete(int cmd, const u8* data, int len)
00116 {
00117    // printf("%04X %s",cmd,CmdStr(cmd));
00118     if (len < 0)
00119         return;
00120     //printfBytes(" complete",data,min(16,len));
00121 
00122     switch (cmd)
00123     {
00124         //  Init phase 0
00125         case HCI_OP_RESET:  // Reset done, init chain to HCI_OP_READ_LOCAL_NAME
00126             SendCmd(HCI_OP_READ_BUFFER_SIZE);
00127             _state |= MASK_RESET;
00128             break;
00129 
00130         //  Init phase 1
00131         case HCI_OP_READ_BUFFER_SIZE:
00132             _acl_mtu = LE16(data);
00133             _sco_mtu = data[2];
00134             _acl_max_pkt = LE16(data+3);
00135             _sco_max_pkt = LE16(data+5);
00136             SendCmd(HCI_OP_READ_BD_ADDR);
00137             _state |= MASK_READ_BUFFER_SIZE;
00138             break;
00139 
00140         //  Init phase 2
00141         case HCI_OP_READ_BD_ADDR:
00142             _localAddr = *((BD_ADDR*)data); // Local Address
00143             _state |= MASK_READ_BD_ADDR;
00144             _state |= MASK_INITED;
00145             Callback(CALLBACK_READY,data,6);
00146             break;
00147 
00148                    // 0CXX
00149         case HCI_OP_READ_LOCAL_NAME:
00150             break;
00151 
00152         case HCI_OP_READ_LOCAL_VERSION:
00153             // params
00154             //SendCmd(HCI_OP_READ_LOCAL_NAME);
00155             break;
00156 
00157         case HCI_OP_READ_LOCAL_COMMANDS:
00158             break;
00159 
00160         case HCI_OP_READ_LOCAL_FEATURES:
00161             //SendCmd(HCI_OP_READ_LOCAL_VERSION);
00162             break;
00163 
00164         case HCI_OP_READ_LOCAL_EXT_FEATURES:
00165             break;
00166 
00167         case HCI_OP_PIN_CODE_REPLY:
00168             printf("Got pin reply\n");
00169             break;
00170 
00171         default:
00172             printf("Unrecognized Command %04X\n",cmd);
00173             break;
00174     }
00175 }
00176 
00177 void HCI::Callback(HCI_CALLBACK_EVENT c, const u8* data, int len)
00178 {
00179     _callback(this,c,data,len);
00180 }
00181 
00182 int HCI::RemoteNameRequest(const BD_ADDR* addr)
00183 {
00184     _state |= MASK_REMOTE_NAME;
00185     u8 buf[6+4];
00186     memset(buf,0,sizeof(buf));
00187     memcpy(buf,addr,6);
00188     buf[7] = 1;
00189     return SendCmd(HCI_OP_REMOTE_NAME_REQ,buf,sizeof(buf));
00190 }
00191 
00192 int HCI::CreateConnection(const BD_ADDR* remoteAddr)
00193 {
00194     _state |= MASK_CREATE_CONNECTION;
00195     u8 buf[6+7];
00196     memset(buf,0,sizeof(buf));
00197     memcpy(buf,remoteAddr,6);
00198     buf[6] = 0x18;  // DM1,DH1
00199     buf[7] = 0xCC;  // DM3, DH3, DM5, DH5
00200     buf[8] = 1;     // Page Repetition R1
00201     return SendCmd(HCI_OP_CREATE_CONN,buf,sizeof(buf));
00202 }
00203 
00204 int HCI::Disconnect(const BD_ADDR* bdaddr)
00205 {
00206     BTDevice* d = Find(bdaddr);
00207     if (!d)
00208         return ERR_HCI_DEVICE_NOT_FOUND;
00209     int handle = d->_handle;
00210     printf("Disconnect from %d\n",handle);
00211     _state |= MASK_CREATE_CONNECTION;
00212     u8 buf[3];
00213     buf[0] = handle;
00214     buf[1] = (handle >> 8);
00215     buf[2] = 0x13;
00216     return SendCmd(HCI_OP_DISCONNECT,buf,sizeof(buf));
00217 }
00218 
00219 void HCI::DisconnectComplete(int handle)
00220 {
00221     BTDevice* d = Find(handle);
00222     if (!d)
00223         return;
00224     d->_handle = 0;
00225 }
00226 
00227 int HCI::DisconnectAll()
00228 {
00229     BTDevice* devs[8];
00230     int count = GetDevices(devs,8);
00231     for (int i = 0; i < count; i++)
00232         Disconnect(&devs[i]->_info.bdaddr);
00233     return 0;
00234 }
00235 
00236 int HCI::PinCodeReply(const u8* data)
00237 {
00238     u8 b[6+1+16];
00239     memset(b,0,sizeof(b));
00240     memcpy(b,data,6);
00241     b[6] = 4;
00242     b[7] = '0';
00243     b[8] = '0';
00244     b[9] = '0';
00245     b[10] = '0';
00246     return SendCmd(HCI_OP_PIN_CODE_REPLY,b,sizeof(b));
00247 }
00248 
00249 void HCI::InquiryResult(const inquiry_info* info)
00250 {
00251     BTDevice* bt = Find(&info->bdaddr);
00252     if (!bt)    // new device
00253     {
00254         for (int i = 0; i < MAX_BTDEVICES; i++)
00255         {
00256             if (_devices[i]._state == 0)
00257             {
00258                 bt = _devices + i;
00259                 bt->_state = 1;
00260                 break;
00261             }
00262         }
00263         if (!bt)
00264         {
00265             printf("HCI::InquiryResult too many devices\n");
00266             return; // Too many devices!
00267         }
00268     }
00269 
00270     bt->_info = *info;
00271 }
00272 
00273 int HCI::GetDevices(BTDevice** devices, int maxDevices)
00274 {
00275     int j = 0;
00276     for (int i = 0; i < MAX_BTDEVICES; i++)
00277     {
00278         if (_devices[i]._state != 0)
00279         {
00280             devices[j++] = _devices + i;
00281             if (j == maxDevices)
00282                 break;
00283         }
00284     }
00285     return j;
00286 }
00287 
00288 void HCI::RemoteName(const BD_ADDR* addr, const char* name)
00289 {
00290     BTDevice* d = Find(addr);
00291     if (d)
00292     {
00293         strncpy(d->_name,name,sizeof(d->_name)-1);
00294         d->_name[sizeof(d->_name)-1] = 0;
00295     }
00296 }
00297 
00298 void HCI::ConnectComplete(const connection_info* info)
00299 {
00300     BTDevice* d = Find(&info->bdaddr);
00301     if (!d)
00302         return;
00303     if (info->status == 0)
00304     {
00305         d->_handle = info->handle;
00306         printf("Connected on %04X\n",info->handle);
00307     } else
00308         printf("Connection failed with %d\n",info->status);
00309 }
00310 
00311 void HCI::HCIRecv(const u8* data, int len)
00312 {
00313    // printfBytes(EvtStr(data[0]),data,min(len,16));
00314     switch (data[0])
00315     {
00316         case HCI_EV_INQUIRY_COMPLETE:
00317             printfBytes("Inquiry Complete",data,data[1]);
00318             _state &= ~MASK_INQUIRY;
00319             Callback(CALLBACK_INQUIRY_DONE,0,0);
00320             break;
00321 
00322         case HCI_EV_INQUIRY_RESULT:
00323             {
00324                 const u8* end = data[1] + data + 2;
00325                 data += 3;
00326                 while (data < end)
00327                 {
00328                     inquiry_info align;
00329                     memcpy(&align,data,sizeof(inquiry_info));
00330                     InquiryResult(&align);
00331                     Callback(CALLBACK_INQUIRY_RESULT,(u8*)&align,sizeof(inquiry_info));
00332                     data += 14;
00333                 }
00334             }
00335             break;
00336 
00337         case HCI_EV_CONN_COMPLETE:
00338             _state &= ~MASK_CREATE_CONNECTION;
00339             {
00340                 connection_info align;
00341                 memcpy(&align,data+2,sizeof(connection_info));
00342                 ConnectComplete(&align);
00343                 Callback(CALLBACK_CONNECTION_COMPLETE,(u8*)&align,sizeof(connection_info));
00344             }
00345             break;
00346 
00347         case HCI_EV_CONN_REQUEST:
00348             break;
00349 
00350         case HCI_EV_DISCONN_COMPLETE:
00351             DisconnectComplete(LE16(data+3));
00352             break;
00353 
00354         case HCI_EV_REMOTE_NAME:
00355             {
00356                 BD_ADDR* addr = (BD_ADDR*)(data+3);
00357                 const char* name = (const char*)(data + 9);
00358                 RemoteName(addr,name);
00359             }
00360             Callback(CALLBACK_REMOTE_NAME,data+3,LE16(data+1));    // addr is in here too
00361             _state &= ~MASK_REMOTE_NAME;
00362             break;
00363 
00364         case HCI_EV_CMD_STATUS:
00365             {
00366                 const char* errs = HCIErrStr(data[2]);
00367                 printf("Status %s %s\n",CmdStr(LE16(data+4)),errs);
00368             }
00369             break;
00370 
00371         case HCI_EV_CMD_COMPLETE:
00372             OnCommandComplete(data[3] | (data[4] << 8),data+6,data[1]-4);
00373             break;
00374 
00375         case HCI_EV_PIN_CODE_REQ:
00376             PinCodeReply(data+2);
00377             break;
00378 
00379         case HCI_EV_LINK_KEY_REQ:
00380             SendCmd(HCI_OP_LINK_KEY_NEG_REPLY,data+2,6);
00381             break;
00382 
00383         default:
00384         ;
00385            // printfBytes(":",data,data[1]+2);
00386     }
00387 }
00388 
00389 int HCI::Open(SocketInternal* sock, SocketAddrHdr* addr)
00390 {
00391     L2CAPSocket* l2capsock = (L2CAPSocket*)sock;
00392     L2CAPAddr* l2capaddr = (L2CAPAddr*)addr;
00393     BTDevice* bt = Find(&l2capaddr->bdaddr);
00394     if (!bt)
00395     {
00396         printf("Can't open l2cap %d on ",l2capaddr->psm);
00397         printf(&l2capaddr->bdaddr);
00398         printf("\n");
00399         return ERR_HCI_DEVICE_NOT_FOUND;
00400     }
00401     l2capsock->btdevice = bt;
00402     return bt->Open(sock,addr);
00403 }
00404 
00405 int HCI::Send(SocketInternal* sock, const u8* data, int len)
00406 {
00407     L2CAPSocket* l2capsock = (L2CAPSocket*)sock;
00408     return l2capsock->btdevice->Send(sock,data,len);    // Pointless double dispatch
00409 }
00410 
00411 int HCI::Close(SocketInternal* sock)
00412 {
00413     L2CAPSocket* l2capsock = (L2CAPSocket*)sock;
00414     return l2capsock->btdevice->Close(sock);    // Pointless double dispatch
00415 }
00416 
00417 void HCI::ACLRecv(const u8* data, int len)
00418 {
00419     int handle = LE16(data);
00420     BTDevice* d = Find(handle & 0x0FFF);
00421     if (d)
00422         d->ACLRecv(data,len);
00423 }
00424 
00425 //===================================================================
00426 //===================================================================