Test version of BlueUSB stack. Includes SDP and RFCOMM. As Client it allows to connect to my fischertechnik TX Controller. As Server it echo\\\\\\\'s characters to Putty. PIN=1234

Dependencies:   mbed myUSBHost AvailableMemory

Dependents:   mbed_TANK_Kinect myBlueUSB_ros ftusbClass

Committer:
networker
Date:
Fri Jul 01 09:16:00 2011 +0000
Revision:
13:327622e38551
made some improvements to get massstorage functioning

Who changed what in which revision?

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