local fix version of myBlueUSB (http://mbed.org/users/networker/code/myBlueUSB/). - merge deleted files which are required to compile. - enable echo back of received data via RFCOMM.

Dependencies:   AvailableMemory FatFileSystem mbed myUSBHost

Committer:
nobukuma
Date:
Sat Dec 07 14:19:00 2013 +0000
Revision:
0:003889bc474f
Child:
2:9f25a7fa1a54
http://mbed.org/users/networker/code/myBlueUSB/ rev13??rev12??????????

Who changed what in which revision?

UserRevisionLine numberNew contents of line
nobukuma 0:003889bc474f 1
nobukuma 0:003889bc474f 2 /*
nobukuma 0:003889bc474f 3 Copyright (c) 2010 Peter Barrett
nobukuma 0:003889bc474f 4
nobukuma 0:003889bc474f 5 Permission is hereby granted, free of charge, to any person obtaining a copy
nobukuma 0:003889bc474f 6 of this software and associated documentation files (the "Software"), to deal
nobukuma 0:003889bc474f 7 in the Software without restriction, including without limitation the rights
nobukuma 0:003889bc474f 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
nobukuma 0:003889bc474f 9 copies of the Software, and to permit persons to whom the Software is
nobukuma 0:003889bc474f 10 furnished to do so, subject to the following conditions:
nobukuma 0:003889bc474f 11
nobukuma 0:003889bc474f 12 The above copyright notice and this permission notice shall be included in
nobukuma 0:003889bc474f 13 all copies or substantial portions of the Software.
nobukuma 0:003889bc474f 14
nobukuma 0:003889bc474f 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
nobukuma 0:003889bc474f 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
nobukuma 0:003889bc474f 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
nobukuma 0:003889bc474f 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
nobukuma 0:003889bc474f 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
nobukuma 0:003889bc474f 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
nobukuma 0:003889bc474f 21 THE SOFTWARE.
nobukuma 0:003889bc474f 22 */
nobukuma 0:003889bc474f 23 #include "mbed.h"
nobukuma 0:003889bc474f 24 #include <vector>
nobukuma 0:003889bc474f 25 #include "Utils.h"
nobukuma 0:003889bc474f 26 #include "USBHost.h"
nobukuma 0:003889bc474f 27 #include "hci.h"
nobukuma 0:003889bc474f 28 #include "HCITransportUSB.h"
nobukuma 0:003889bc474f 29 #include "RFCOMM.h"
nobukuma 0:003889bc474f 30 #include "ftclasslibusbdevbt.h"
nobukuma 0:003889bc474f 31 #include "sdp_data.h"
nobukuma 0:003889bc474f 32 #include "sdp.h"
nobukuma 0:003889bc474f 33 #include "btserial.h"
nobukuma 0:003889bc474f 34 #include "neighbourhood.h"
nobukuma 0:003889bc474f 35
nobukuma 0:003889bc474f 36 /************************************************
nobukuma 0:003889bc474f 37 TODO:
nobukuma 0:003889bc474f 38 mtu and credits are completely unhandled - in progress
nobukuma 0:003889bc474f 39 multiple rfcomm sessions should be possible - done
nobukuma 0:003889bc474f 40 SDP would be nice - beta
nobukuma 0:003889bc474f 41 multiple rfcomm channels are untested
nobukuma 0:003889bc474f 42 decoupling of rfcomm and application - much better
nobukuma 0:003889bc474f 43 packets are not reassembled - some are (HCI and ft application level)
nobukuma 0:003889bc474f 44 disconnect and timeouts
nobukuma 0:003889bc474f 45 ************************************************/
nobukuma 0:003889bc474f 46 #define DEBUG 1
nobukuma 0:003889bc474f 47 int state = 0;
nobukuma 0:003889bc474f 48
nobukuma 0:003889bc474f 49 //int bulk = 0;
nobukuma 0:003889bc474f 50 void printf(const BD_ADDR* addr) {
nobukuma 0:003889bc474f 51 const u8* a = addr->addr;
nobukuma 0:003889bc474f 52 printf("%02X:%02X:%02X:%02X:%02X:%02X",a[5],a[4],a[3],a[2],a[1],a[0]);
nobukuma 0:003889bc474f 53 }
nobukuma 0:003889bc474f 54
nobukuma 0:003889bc474f 55 const char FtDevClass[3] = {0x00, 0x1F, 0x82 };
nobukuma 0:003889bc474f 56 const char SerDevClass[3] = {4, 1, 0x00};
nobukuma 0:003889bc474f 57 // Instance
nobukuma 0:003889bc474f 58 //RFCOMMManager rfcomm_manager;
nobukuma 0:003889bc474f 59
nobukuma 0:003889bc474f 60 class application : public HCI {
nobukuma 0:003889bc474f 61 BTDevice* devs[8];
nobukuma 0:003889bc474f 62 int count, i, pending;
nobukuma 0:003889bc474f 63 public:
nobukuma 0:003889bc474f 64 // We have connected to a device
nobukuma 0:003889bc474f 65 void ConnectionComplete(connection_info* info) {
nobukuma 0:003889bc474f 66 printf("ConnectionComplete ");
nobukuma 0:003889bc474f 67 BD_ADDR* a = &info->bdaddr;
nobukuma 0:003889bc474f 68 printf(a);
nobukuma 0:003889bc474f 69 printf("\n");
nobukuma 0:003889bc474f 70 RemoteNameRequest(a);
nobukuma 0:003889bc474f 71 for (i++; i < count; i++) {//find the next device to open
nobukuma 0:003889bc474f 72 printfBytes("DEVICE CLASS",devs[i]->_info.dev_class,3);
nobukuma 0:003889bc474f 73 if (devs[i]->_handle == 0 && memcmp(devs[i]->_info.dev_class, FtDevClass, 3)==0) {//or some other way to connect to RFCOMM devices
nobukuma 0:003889bc474f 74 BD_ADDR* bd = &devs[i]->_info.bdaddr;
nobukuma 0:003889bc474f 75 printf("Connecting to ");
nobukuma 0:003889bc474f 76 printf(bd);
nobukuma 0:003889bc474f 77 printf("\n");
nobukuma 0:003889bc474f 78 pending++;
nobukuma 0:003889bc474f 79 CreateConnection(bd); //some low level connect, just let it happen for now (sets pin, mtu etc.)
nobukuma 0:003889bc474f 80 printf("connection cmd was sent\n");
nobukuma 0:003889bc474f 81 return;
nobukuma 0:003889bc474f 82 }
nobukuma 0:003889bc474f 83 }
nobukuma 0:003889bc474f 84 //state = 1; //start the real application
nobukuma 0:003889bc474f 85 }
nobukuma 0:003889bc474f 86
nobukuma 0:003889bc474f 87 void ConnectDevices() {
nobukuma 0:003889bc474f 88 count = GetDevices(devs,8);//get pointers to all bluetooth devices
nobukuma 0:003889bc474f 89 pending = 0;
nobukuma 0:003889bc474f 90 for (i = 0; i < count; i++) {
nobukuma 0:003889bc474f 91 printfBytes("DEVICE CLASS",devs[i]->_info.dev_class,3);
nobukuma 0:003889bc474f 92 if (devs[i]->_handle == 0 /*&& memcmp(devs[i]->_info.dev_class, FtDevClass, 3)==0*/) {//or some other way to connect to RFCOMM devices
nobukuma 0:003889bc474f 93 BD_ADDR* bd = &devs[i]->_info.bdaddr;
nobukuma 0:003889bc474f 94 printf("Connecting to ");
nobukuma 0:003889bc474f 95 printf(bd);
nobukuma 0:003889bc474f 96 printf("\n");
nobukuma 0:003889bc474f 97 pending++;
nobukuma 0:003889bc474f 98 CreateConnection(bd); //some low level connect, just let it happen for now (sets pin, mtu etc.)
nobukuma 0:003889bc474f 99 printf("connection cmd was sent\n");
nobukuma 0:003889bc474f 100 return;
nobukuma 0:003889bc474f 101 }
nobukuma 0:003889bc474f 102 }
nobukuma 0:003889bc474f 103 if (pending == 0) state = 1;//for the case when there are no ft devices
nobukuma 0:003889bc474f 104 }
nobukuma 0:003889bc474f 105 virtual void Callback(HCI_CALLBACK_EVENT c, const u8* data, int len);
nobukuma 0:003889bc474f 106 int csr_write_bd_addr(BD_ADDR *bdaddr, bool transient=true);
nobukuma 0:003889bc474f 107 int csr_reset_device(bool transient=true);
nobukuma 0:003889bc474f 108 } App; //application instance
nobukuma 0:003889bc474f 109
nobukuma 0:003889bc474f 110 extern "C" void mbed_reset();
nobukuma 0:003889bc474f 111
nobukuma 0:003889bc474f 112
nobukuma 0:003889bc474f 113 void application::Callback(HCI_CALLBACK_EVENT evt, const u8* data, int len) {//these events are forwarded (in)directly from HCIRecv
nobukuma 0:003889bc474f 114 unsigned char pin[] = "1234";
nobukuma 0:003889bc474f 115 unsigned char newaddr[] = {0x2c, 0x07, 0x54, 0x7b, 0x13, 0x00};//possible ft TX address (ROBO TX-277)
nobukuma 0:003889bc474f 116 // unsigned char newaddr[] = {0x57, 0x0a, 0x3d, 0x83, 0x15, 0x00};//original address of the cheap round BT dongle
nobukuma 0:003889bc474f 117 printf("\x1b[%dm", 33);
nobukuma 0:003889bc474f 118 switch (evt) {
nobukuma 0:003889bc474f 119 case CALLBACK_READY:
nobukuma 0:003889bc474f 120 printf("CALLBACK_READY\n");
nobukuma 0:003889bc474f 121 printf("my address = ");
nobukuma 0:003889bc474f 122 printf((BD_ADDR*)data);
nobukuma 0:003889bc474f 123 if (memcmp(newaddr, data, 6) != 0) { //csr_write_bd_addr((BD_ADDR*)newaddr, false);
nobukuma 0:003889bc474f 124 }
nobukuma 0:003889bc474f 125 Inquiry();//start the second phase of the discovery
nobukuma 0:003889bc474f 126 break;
nobukuma 0:003889bc474f 127
nobukuma 0:003889bc474f 128 case CALLBACK_INQUIRY_RESULT: //optionally build the list of FT devices here
nobukuma 0:003889bc474f 129 printf("CALLBACK_INQUIRY_RESULT ");
nobukuma 0:003889bc474f 130 printf((BD_ADDR*)data);
nobukuma 0:003889bc474f 131 printf("\n");//data points to inquiry_info struct
nobukuma 0:003889bc474f 132 // RemoteNameRequest((BD_ADDR*)data);
nobukuma 0:003889bc474f 133 break;
nobukuma 0:003889bc474f 134
nobukuma 0:003889bc474f 135 case CALLBACK_INQUIRY_DONE:
nobukuma 0:003889bc474f 136 printf("CALLBACK_INQUIRY_DONE\n");
nobukuma 0:003889bc474f 137 neighbors = new neighbourhood(&App);
nobukuma 0:003889bc474f 138 neighbors->read();
nobukuma 0:003889bc474f 139 ConnectDevices();
nobukuma 0:003889bc474f 140 break;
nobukuma 0:003889bc474f 141
nobukuma 0:003889bc474f 142 case CALLBACK_REMOTE_NAME: {
nobukuma 0:003889bc474f 143 BD_ADDR* addr = (BD_ADDR*)data;
nobukuma 0:003889bc474f 144 const char* name = (const char*)(data + 6);
nobukuma 0:003889bc474f 145 printf(addr);
nobukuma 0:003889bc474f 146 printf(" = % s\n",name);
nobukuma 0:003889bc474f 147 pending--;
nobukuma 0:003889bc474f 148 if (pending == 0) state = 1;
nobukuma 0:003889bc474f 149 }
nobukuma 0:003889bc474f 150 break;
nobukuma 0:003889bc474f 151
nobukuma 0:003889bc474f 152 case CALLBACK_CONNECTION_COMPLETE: {
nobukuma 0:003889bc474f 153 connection_info *ci = (connection_info*)data;
nobukuma 0:003889bc474f 154 if (ci->status>0) {
nobukuma 0:003889bc474f 155 printf("Connection failed, status=0x%02X\n", ci->status);
nobukuma 0:003889bc474f 156 break;
nobukuma 0:003889bc474f 157 }
nobukuma 0:003889bc474f 158 ConnectionComplete(ci);
nobukuma 0:003889bc474f 159 printf("Going to open sdp socket\n");
nobukuma 0:003889bc474f 160 L2CAPAddr addr;
nobukuma 0:003889bc474f 161 memcpy(&addr.bdaddr, &ci->bdaddr, 6);
nobukuma 0:003889bc474f 162 //int s = SDP.Open(&addr.hdr);
nobukuma 0:003889bc474f 163 }
nobukuma 0:003889bc474f 164 break;
nobukuma 0:003889bc474f 165 case CALLBACK_PIN_REQ:
nobukuma 0:003889bc474f 166 printf("Enter PIN for ");
nobukuma 0:003889bc474f 167 printf((BD_ADDR*)data);
nobukuma 0:003889bc474f 168 printf(" : submitting %s\n", pin);
nobukuma 0:003889bc474f 169 //USBLoop(); wait(1.0); USBLoop();
nobukuma 0:003889bc474f 170 //for(int k=0; k<2000000;k++) USBLoop();
nobukuma 0:003889bc474f 171 PinCodeReply(data, pin);
nobukuma 0:003889bc474f 172 break;
nobukuma 0:003889bc474f 173 case CALLBACK_VENDOR:
nobukuma 0:003889bc474f 174 printfBytes("Vendor Reply:", data, len);
nobukuma 0:003889bc474f 175 //mbed_reset();
nobukuma 0:003889bc474f 176 if (data[0] == 0xc2)
nobukuma 0:003889bc474f 177 csr_reset_device(false);
nobukuma 0:003889bc474f 178 break;
nobukuma 0:003889bc474f 179 default:
nobukuma 0:003889bc474f 180 printf("Unhandled HCI Callback %d\n", evt);
nobukuma 0:003889bc474f 181 };
nobukuma 0:003889bc474f 182 printf("\x1b[%dm", 0);
nobukuma 0:003889bc474f 183 }
nobukuma 0:003889bc474f 184
nobukuma 0:003889bc474f 185 #define CSR_WRITE 0xFC00
nobukuma 0:003889bc474f 186
nobukuma 0:003889bc474f 187 int application::csr_write_bd_addr(BD_ADDR *bdaddr, bool transient) {
nobukuma 0:003889bc474f 188 unsigned char cmd[] = { 0xc2,
nobukuma 0:003889bc474f 189 0x02, 0x00, 0x0c, 0x00, 0x11, 0x47, 0x03, 0x70,
nobukuma 0:003889bc474f 190 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
nobukuma 0:003889bc474f 191 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
nobukuma 0:003889bc474f 192 };
nobukuma 0:003889bc474f 193
nobukuma 0:003889bc474f 194 if (transient)
nobukuma 0:003889bc474f 195 cmd[15] = 0x08;
nobukuma 0:003889bc474f 196
nobukuma 0:003889bc474f 197 cmd[17] = bdaddr->addr[2];
nobukuma 0:003889bc474f 198 cmd[18] = 0x00;
nobukuma 0:003889bc474f 199 cmd[19] = bdaddr->addr[0];
nobukuma 0:003889bc474f 200 cmd[20] = bdaddr->addr[1];
nobukuma 0:003889bc474f 201 cmd[21] = bdaddr->addr[3];
nobukuma 0:003889bc474f 202 cmd[22] = 0x00;
nobukuma 0:003889bc474f 203 cmd[23] = bdaddr->addr[4];
nobukuma 0:003889bc474f 204 cmd[24] = bdaddr->addr[5];
nobukuma 0:003889bc474f 205
nobukuma 0:003889bc474f 206 return SendCmd(CSR_WRITE, cmd, sizeof(cmd));
nobukuma 0:003889bc474f 207 }
nobukuma 0:003889bc474f 208
nobukuma 0:003889bc474f 209 int application::csr_reset_device(bool transient) {
nobukuma 0:003889bc474f 210 unsigned char cmd[] = { 0xc2, 0x02, 0x00, 0x09, 0x00,
nobukuma 0:003889bc474f 211 0x00, 0x00, 0x01, 0x40, 0x00, 0x00,
nobukuma 0:003889bc474f 212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
nobukuma 0:003889bc474f 213 };
nobukuma 0:003889bc474f 214
nobukuma 0:003889bc474f 215 if (transient)
nobukuma 0:003889bc474f 216 cmd[7] = 0x02;
nobukuma 0:003889bc474f 217
nobukuma 0:003889bc474f 218 return SendCmd(CSR_WRITE, cmd, sizeof(cmd));
nobukuma 0:003889bc474f 219 }
nobukuma 0:003889bc474f 220
nobukuma 0:003889bc474f 221
nobukuma 0:003889bc474f 222 // these should be placed in the DMA SRAM
nobukuma 0:003889bc474f 223 typedef struct {
nobukuma 0:003889bc474f 224 u8 _hciBuffer[MAX_HCL_SIZE];
nobukuma 0:003889bc474f 225 u8 _aclBuffer[MAX_ACL_SIZE];
nobukuma 0:003889bc474f 226 } SRAMPlacement;
nobukuma 0:003889bc474f 227
nobukuma 0:003889bc474f 228 HCITransportUSB _HCITransportUSB; //use USB as the transport to the radio
nobukuma 0:003889bc474f 229
nobukuma 0:003889bc474f 230 int OnBluetoothInsert(int device) {//install the HCI and start discovery, user callbacks are made to HciCalback
nobukuma 0:003889bc474f 231 printf("Bluetooth inserted of %d\n",device);
nobukuma 0:003889bc474f 232 u32 sramLen;
nobukuma 0:003889bc474f 233 u8* sram = USBGetBuffer(&sramLen);
nobukuma 0:003889bc474f 234 sram = (u8*)(((u32)sram + 1023) & ~1023);
nobukuma 0:003889bc474f 235 SRAMPlacement* s = (SRAMPlacement*)sram;
nobukuma 0:003889bc474f 236 _HCITransportUSB.Open(device,s->_hciBuffer,s->_aclBuffer);//setup buffers for USB host, incoming data goes first to HCIRecv and ACLRecv
nobukuma 0:003889bc474f 237 RegisterSocketHandler(SOCKET_L2CAP,&App); //register the application::hci as handler for L2CAP events
nobukuma 0:003889bc474f 238 RegisterSocketHandler(SOCKET_RFCOM, &rfcomm_manager);//set the RFCOMMManager as the RFCOM socket handler
nobukuma 0:003889bc474f 239 if (RegisterSocketHandler(SOCKET_SDP, &SDP))
nobukuma 0:003889bc474f 240 printf("Could not register SDP socket type\n");
nobukuma 0:003889bc474f 241 App.Open(&_HCITransportUSB);//the callback is virtual
nobukuma 0:003889bc474f 242 App.Inquiry();//start discovery of BT devices phase 0
nobukuma 0:003889bc474f 243 return 0;
nobukuma 0:003889bc474f 244 }
nobukuma 0:003889bc474f 245
nobukuma 0:003889bc474f 246 DigitalOut led(LED1), loop(LED2);
nobukuma 0:003889bc474f 247
nobukuma 0:003889bc474f 248 int comm = 0;
nobukuma 0:003889bc474f 249 btserial *incoming, *outgoing;
nobukuma 0:003889bc474f 250
nobukuma 0:003889bc474f 251 void echo(int socket, SocketState state, const u8* data, int len, void* userData) {
nobukuma 0:003889bc474f 252 const u8 connack[] = { 0xbe, 0xef, 8, 'C','O','N','N','_','A','C','K', 0x11};
nobukuma 0:003889bc474f 253 printf("Echo: socket %d, state %d, len=%d\n", socket, state, len);
nobukuma 0:003889bc474f 254 if (state==SocketState_Open) {
nobukuma 0:003889bc474f 255 if (len == 0) {
nobukuma 0:003889bc474f 256 printf("Sending CONN_ACK\n");
nobukuma 0:003889bc474f 257 Socket_Send(socket, connack, sizeof(connack));
nobukuma 0:003889bc474f 258 } else {
nobukuma 0:003889bc474f 259 //Socket_Send(socket, data, len);
nobukuma 0:003889bc474f 260 printfBytes("echo:", data, len);
nobukuma 0:003889bc474f 261 }
nobukuma 0:003889bc474f 262 }
nobukuma 0:003889bc474f 263 }
nobukuma 0:003889bc474f 264
nobukuma 0:003889bc474f 265 void TestShell() {
nobukuma 0:003889bc474f 266 int n=0;
nobukuma 0:003889bc474f 267 USBInit();
nobukuma 0:003889bc474f 268 for (;;) {
nobukuma 0:003889bc474f 269 switch (state) {
nobukuma 0:003889bc474f 270 case 0: //inquiry and low-level connection
nobukuma 0:003889bc474f 271 break;
nobukuma 0:003889bc474f 272 case 1: {//initialisation
nobukuma 0:003889bc474f 273 printf("Ready to open ports\n");
nobukuma 0:003889bc474f 274 InitFtBtDeviceList();
nobukuma 0:003889bc474f 275 int n = GetNrOfFtBtDevices();
nobukuma 0:003889bc474f 276 printf("%d ft BT devices have been found\n", n);
nobukuma 0:003889bc474f 277 if (n > 0) {
nobukuma 0:003889bc474f 278 ftbtdev *d = GetFtUsbDeviceHandle(0);
nobukuma 0:003889bc474f 279 if (d==0) printf("could not get device handle\n");
nobukuma 0:003889bc474f 280 int sock = OpenFtBtDevice(d);
nobukuma 0:003889bc474f 281 }
nobukuma 0:003889bc474f 282 state = 2;
nobukuma 0:003889bc474f 283 //comm = Socket_Listen(SOCKET_RFCOM, 1, echo, 0);
nobukuma 0:003889bc474f 284 //incoming = new btserial(1);
nobukuma 0:003889bc474f 285 }
nobukuma 0:003889bc474f 286 break;
nobukuma 0:003889bc474f 287 case 2://main loop
nobukuma 0:003889bc474f 288 /* if (incoming->readable()>0){
nobukuma 0:003889bc474f 289 int c= incoming->getc();
nobukuma 0:003889bc474f 290 putc(c, stderr);
nobukuma 0:003889bc474f 291 incoming->putc(c);
nobukuma 0:003889bc474f 292 }
nobukuma 0:003889bc474f 293 else if (incoming->readable()<0){
nobukuma 0:003889bc474f 294 state = 3;
nobukuma 0:003889bc474f 295 printf("end of session");
nobukuma 0:003889bc474f 296 delete incoming;
nobukuma 0:003889bc474f 297 }*/
nobukuma 0:003889bc474f 298 break;
nobukuma 0:003889bc474f 299 default:
nobukuma 0:003889bc474f 300 break;
nobukuma 0:003889bc474f 301 }
nobukuma 0:003889bc474f 302 loop=1;
nobukuma 0:003889bc474f 303 USBLoop();
nobukuma 0:003889bc474f 304 loop=0;
nobukuma 0:003889bc474f 305 n++;
nobukuma 0:003889bc474f 306 if (n>=500000) {
nobukuma 0:003889bc474f 307 n=0;
nobukuma 0:003889bc474f 308 led = !led;
nobukuma 0:003889bc474f 309 }
nobukuma 0:003889bc474f 310 }
nobukuma 0:003889bc474f 311 //printf("Dropped out of main loop!\n");
nobukuma 0:003889bc474f 312 }
nobukuma 0:003889bc474f 313
nobukuma 0:003889bc474f 314 //********************************************************************************************************************************