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.
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 }
Generated on Thu Jul 14 2022 11:49:57 by
