Bluetooth support for MBED with $2 Bluetooth dongles. Includes a USB host and built in support for bluetooth HID devices such as mice, keyboards and wii controllers.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers TestShell.cpp Source File

TestShell.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 "USBHost.h"
00031 #include "hci.h"
00032 
00033 void printf(const BD_ADDR* addr)
00034 {
00035     const u8* a = addr->addr;
00036     printf("%02X:%02X:%02X:%02X:%02X:%02X",a[5],a[4],a[3],a[2],a[1],a[0]);
00037 }
00038 
00039 #define MAX_HCL_SIZE 260
00040 #define MAX_ACL_SIZE 400
00041 
00042 class HCITransportUSB : public HCITransport
00043 {
00044     int _device;
00045     u8* _hciBuffer;
00046     u8* _aclBuffer;
00047 
00048     public:
00049     void Open(int device, u8* hciBuffer, u8* aclBuffer)
00050     {
00051         _device = device;
00052         _hciBuffer = hciBuffer;
00053         _aclBuffer = aclBuffer;
00054         USBInterruptTransfer(_device,0x81,_hciBuffer,MAX_HCL_SIZE,HciCallback,this);
00055         USBBulkTransfer(_device,0x82,_aclBuffer,MAX_ACL_SIZE,AclCallback,this);
00056     }
00057 
00058     static void HciCallback(int device, int endpoint, int status, u8* data, int len, void* userData)
00059     {
00060         HCI* t = ((HCITransportUSB*)userData)->_target;
00061         if (t)
00062             t->HCIRecv(data,len);
00063         USBInterruptTransfer(device,0x81,data,MAX_HCL_SIZE,HciCallback,userData);
00064     }
00065 
00066     static void AclCallback(int device, int endpoint, int status, u8* data, int len, void* userData)
00067     {
00068         HCI* t = ((HCITransportUSB*)userData)->_target;
00069         if (t)
00070             t->ACLRecv(data,len);
00071         USBBulkTransfer(device,0x82,data,MAX_ACL_SIZE,AclCallback,userData);
00072     }
00073 
00074     virtual void HCISend(const u8* data, int len)
00075     {
00076         USBControlTransfer(_device,REQUEST_TYPE_CLASS, 0, 0, 0,(u8*)data,len);
00077     }
00078 
00079     virtual void ACLSend(const u8* data, int len)
00080     {
00081         USBBulkTransfer(_device,0x02,(u8*)data,len);
00082     }
00083 };
00084 
00085 
00086 #define WII_REMOTE 0x042500
00087 
00088 class HIDBluetooth
00089 {
00090     int _control;   // Sockets for control (out) and interrupt (in)
00091     int _interrupt;
00092     int _devClass;
00093     BD_ADDR _addr;
00094     u8  _pad[2];    // Struct align
00095     
00096 public:
00097     HIDBluetooth() : _control(0),_interrupt(0),_devClass(0) {};
00098 
00099     bool InUse()
00100     {
00101         return _control != 0;
00102     }
00103 
00104     static void OnHidInterrupt(int socket, SocketState state, const u8* data, int len, void* userData)
00105     {
00106         HIDBluetooth* t = (HIDBluetooth*)userData;
00107         if (data)
00108         {
00109             if (t->_devClass == WII_REMOTE && data[1] == 0x30)
00110             {
00111                 printf("================wii====================\n");
00112                 t->Led();
00113                 t->Hid();   // ask for accelerometer
00114                 t->_devClass = 0;
00115             }
00116 
00117             const u8* d = data;
00118             switch (d[1])
00119             {
00120                 case 0x02:
00121                 {
00122                     int x = (signed char)d[3];
00123                     int y = (signed char)d[4];
00124                     printf("Mouse %2X dx:%d dy:%d\n",d[2],x,y);
00125                 }
00126                 break;
00127 
00128                 case 0x37: // Accelerometer http://wiki.wiimoteproject.com/Reports
00129                 {
00130                     int pad = (d[2] & 0x9F) | ((d[3] & 0x9F) << 8);
00131                     int x = (d[2] & 0x60) >> 5 | d[4] << 2;
00132                     int y = (d[3] & 0x20) >> 4 | d[5] << 2;
00133                     int z = (d[3] & 0x40) >> 5 | d[6] << 2;
00134                     printf("WII %04X %d %d %d\n",pad,x,y,z);
00135                 }
00136                 break;
00137                 default:
00138                     printHex(data,len);
00139             }
00140         }
00141     }
00142 
00143     static void OnHidControl(int socket, SocketState state, const u8* data, int len, void* userData)
00144     {
00145         printf("OnHidControl\n");
00146         if (data)
00147             printHex(data,len);
00148     }
00149 
00150     void Open(BD_ADDR* bdAddr, inquiry_info* info)
00151     {
00152         printf("L2CAPAddr size %d\n",sizeof(L2CAPAddr));
00153         _addr = *bdAddr;
00154         L2CAPAddr sockAddr;
00155         sockAddr.bdaddr = _addr;
00156         sockAddr.psm = L2CAP_PSM_HID_INTR;
00157                 printf("Socket_Open size %d\n",sizeof(L2CAPAddr));
00158         _interrupt = Socket_Open(SOCKET_L2CAP,&sockAddr.hdr,OnHidInterrupt,this);
00159         sockAddr.psm = L2CAP_PSM_HID_CNTL;
00160         _control = Socket_Open(SOCKET_L2CAP,&sockAddr.hdr,OnHidControl,this);
00161 
00162         printfBytes("OPEN DEVICE CLASS",info->dev_class,3);
00163         _devClass = (info->dev_class[0] << 16) | (info->dev_class[1] << 8) | info->dev_class[2];
00164     }
00165 
00166     void Close()
00167     {
00168         if (_control)
00169             Socket_Close(_control);
00170         if (_interrupt)
00171             Socket_Close(_interrupt);
00172        _control = _interrupt = 0;
00173     }
00174 
00175     void Led(int id = 0x10)
00176     {
00177         u8 led[3] = {0x52, 0x11, id};
00178         if (_control)
00179             Socket_Send(_control,led,3);
00180     }
00181 
00182     void Hid(int report = 0x37)
00183     {
00184         u8 hid[4] = { 0x52, 0x12, 0x00, report };
00185         if (_control != -1)
00186             Socket_Send(_control,hid,4);
00187     }
00188 };
00189 
00190 
00191 HCI* gHCI = 0;
00192 
00193 #define MAX_HID_DEVICES 8
00194 
00195 int GetConsoleChar();
00196 class ShellApp
00197 {
00198     char _line[64];
00199     HIDBluetooth    _hids[MAX_HID_DEVICES];
00200 
00201 public:
00202     void Ready()
00203     {
00204     printf("HIDBluetooth %d\n",sizeof(HIDBluetooth));
00205          memset(_hids,0,sizeof(_hids));
00206         Inquiry();
00207 
00208     }
00209 
00210     //  We have connected to a device
00211     void ConnectionComplete(HCI* hci, connection_info* info)
00212     {
00213     printf("ConnectionComplete ");
00214         BD_ADDR* a = &info->bdaddr;
00215         printf(a);
00216         BTDevice* bt = hci->Find(a);
00217         HIDBluetooth* hid = NewHIDBluetooth();
00218         printf("%08x %08x\n",bt,hid);
00219         if (hid)
00220             hid->Open(a,&bt->_info);
00221     }
00222 
00223     HIDBluetooth* NewHIDBluetooth()
00224     {
00225         for (int i = 0; i < MAX_HID_DEVICES; i++)
00226             if (!_hids[i].InUse())
00227                 return _hids+i;
00228         return 0;
00229     }
00230 
00231     void ConnectDevices()
00232     {
00233         BTDevice* devs[8];
00234         int count = gHCI->GetDevices(devs,8);
00235         for (int i = 0; i < count; i++)
00236         {
00237             printfBytes("DEVICE CLASS",devs[i]->_info.dev_class,3);
00238             if (devs[i]->_handle == 0)
00239             {
00240                 BD_ADDR* bd = &devs[i]->_info.bdaddr;
00241                 printf("Connecting to ");
00242                 printf(bd);
00243                 printf("\n");
00244                 gHCI->CreateConnection(bd);
00245             }
00246         }
00247     }
00248 
00249     const char* ReadLine()
00250     {
00251         int i;
00252         for (i = 0; i < 255; )
00253         {
00254             USBLoop();
00255             int c = GetConsoleChar();
00256             if (c == -1)
00257                 continue;
00258             if (c == '\n' || c == 13)
00259                 break;
00260             _line[i++] = c;
00261         }
00262         _line[i] = 0;
00263         return _line;
00264     }
00265 
00266     void Inquiry()
00267     {
00268         printf("Inquiry..\n");
00269         gHCI->Inquiry();
00270     }
00271 
00272     void List()
00273     {
00274         #if 0
00275         printf("%d devices\n",_deviceCount);
00276         for (int i = 0; i < _deviceCount; i++)
00277         {
00278             printf(&_devices[i].info.bdaddr);
00279             printf("\n");
00280         }
00281         #endif
00282     }
00283 
00284     void Connect()
00285     {
00286         ConnectDevices();
00287     }
00288 
00289     void Disconnect()
00290     {
00291         gHCI->DisconnectAll();
00292     }
00293 
00294     void CloseMouse()
00295     {
00296     }
00297 
00298     void Quit()
00299     {
00300         CloseMouse();
00301     }
00302 
00303     void Run()
00304     {
00305         for(;;)
00306         {
00307             const char* cmd = ReadLine();
00308             if (strcmp(cmd,"scan") == 0 || strcmp(cmd,"inquiry") == 0)
00309                 Inquiry();
00310             else if (strcmp(cmd,"ls") == 0)
00311                 List();
00312             else if (strcmp(cmd,"connect") == 0)
00313                 Connect();
00314             else if (strcmp(cmd,"disconnect") == 0)
00315                 Disconnect();
00316             else if (strcmp(cmd,"q")== 0)
00317             {
00318                 Quit();
00319                 break;
00320             } else {
00321                 printf("eh? %s\n",cmd);
00322             }
00323         }
00324     }
00325 };
00326 
00327 //  Instance
00328 ShellApp gApp;
00329 
00330 static int HciCallback(HCI* hci, HCI_CALLBACK_EVENT evt, const u8* data, int len)
00331 {
00332     switch (evt)
00333     {
00334         case CALLBACK_READY:
00335             printf("CALLBACK_READY\n");
00336             gApp.Ready();
00337             break;
00338 
00339         case CALLBACK_INQUIRY_RESULT:
00340             printf("CALLBACK_INQUIRY_RESULT ");
00341             printf((BD_ADDR*)data);
00342             printf("\n");
00343             break;
00344 
00345         case CALLBACK_INQUIRY_DONE:
00346             printf("CALLBACK_INQUIRY_DONE\n");
00347             gApp.ConnectDevices();
00348             break;
00349 
00350         case CALLBACK_REMOTE_NAME:
00351             {
00352                 BD_ADDR* addr = (BD_ADDR*)data;
00353                 const char* name = (const char*)(data + 6);
00354                 printf(addr);
00355                 printf(" % s\n",name);
00356             }
00357             break;
00358 
00359         case CALLBACK_CONNECTION_COMPLETE:
00360             gApp.ConnectionComplete(hci,(connection_info*)data);
00361             break;
00362     };
00363     return 0;
00364 }
00365 
00366 //  these should be placed in the DMA SRAM
00367 typedef struct
00368 {
00369     u8 _hciBuffer[MAX_HCL_SIZE];
00370     u8 _aclBuffer[MAX_ACL_SIZE];
00371 } SRAMPlacement;
00372 
00373 HCITransportUSB _HCITransportUSB;
00374 HCI _HCI;
00375 
00376 u8* USBGetBuffer(u32* len);
00377 int OnBluetoothInsert(int device)
00378 {
00379     printf("Bluetooth inserted of %d\n",device);
00380     u32 sramLen;
00381     u8* sram =  USBGetBuffer(&sramLen);
00382     sram = (u8*)(((u32)sram + 1023) & ~1023);
00383     SRAMPlacement* s = (SRAMPlacement*)sram;
00384     _HCITransportUSB.Open(device,s->_hciBuffer,s->_aclBuffer);
00385     _HCI.Open(&_HCITransportUSB,HciCallback);
00386     RegisterSocketHandler(SOCKET_L2CAP,&_HCI);
00387     gHCI = &_HCI;
00388     gApp.Inquiry();
00389     return 0;
00390 }
00391 
00392 void TestShell()
00393 {
00394     USBInit();
00395     gApp.Run();
00396 }