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:
Sat Jun 11 19:45:42 2011 +0000
Revision:
6:567607a9a79f
new release because of some changes to the libraries.
Also added functions to spoof the mac address on csr dongles

Who changed what in which revision?

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