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

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 #include "mbed.h"
00024 #include <vector>
00025 #include "Utils.h"
00026 #include "USBHost.h"
00027 #include "hci.h"
00028 #include "HCITransportUSB.h"
00029 #include "RFCOMM.h"
00030 #include "ftclasslibusbdevbt.h"
00031 #include "sdp_data.h"
00032 #include "sdp.h"
00033 #include "btserial.h"
00034 #include "neighbourhood.h"
00035 
00036 /************************************************
00037 TODO:
00038 mtu and credits are completely unhandled - in progress
00039 multiple rfcomm sessions should be possible - done
00040 SDP would be nice - beta
00041 multiple rfcomm channels are untested
00042 decoupling of rfcomm and application - much better
00043 packets are not reassembled - some are (HCI and ft application level)
00044 disconnect and timeouts
00045 ************************************************/
00046 #define DEBUG   1
00047 int state = 0;
00048 
00049 //int bulk = 0;
00050 void printf(const BD_ADDR* addr) {
00051     const u8* a = addr->addr;
00052     printf("%02X:%02X:%02X:%02X:%02X:%02X",a[5],a[4],a[3],a[2],a[1],a[0]);
00053 }
00054 
00055 const char FtDevClass[3] = {0x00, 0x1F, 0x82 };
00056 const char SerDevClass[3] = {4, 1, 0x00};
00057 //  Instance
00058 //RFCOMMManager rfcomm_manager;
00059 
00060 class application : public HCI {
00061     BTDevice* devs[8];
00062     int count, i, pending;
00063 public:
00064     //  We have connected to a device
00065     void ConnectionComplete(connection_info* info) {
00066         printf("ConnectionComplete ");
00067         BD_ADDR* a = &info->bdaddr;
00068         printf(a);
00069         printf("\n");
00070         RemoteNameRequest(a);
00071         for (i++; i < count; i++) {//find the next device to open
00072             printfBytes("DEVICE CLASS",devs[i]->_info.dev_class,3);
00073             //if (devs[i]->_handle == 0 && memcmp(devs[i]->_info.dev_class, FtDevClass, 3)==0) {//or some other way to connect to RFCOMM devices
00074             if (devs[i]->_handle == 0) { // 
00075                 BD_ADDR* bd = &devs[i]->_info.bdaddr;
00076                 printf("Connecting to ");
00077                 printf(bd);
00078                 printf("\n");
00079                 pending++;
00080                 CreateConnection(bd); //some low level connect, just let it happen for now (sets pin, mtu etc.)
00081                 printf("connection cmd was sent\n");
00082                 return;
00083             }
00084         }
00085         //state = 1; //start the real application
00086     }
00087 
00088     void ConnectDevices() {
00089         count = GetDevices(devs,8);//get pointers to all bluetooth devices
00090         pending = 0;
00091         for (i = 0; i < count; i++) {
00092             printfBytes("DEVICE CLASS",devs[i]->_info.dev_class,3);
00093             if (devs[i]->_handle == 0 /*&& memcmp(devs[i]->_info.dev_class, FtDevClass, 3)==0*/) {//or some other way to connect to RFCOMM devices
00094                 BD_ADDR* bd = &devs[i]->_info.bdaddr;
00095                 printf("Connecting to ");
00096                 printf(bd);
00097                 printf("\n");
00098                 pending++;
00099                 CreateConnection(bd); //some low level connect, just let it happen for now (sets pin, mtu etc.)
00100                 printf("connection cmd was sent\n");
00101                 return;
00102             }
00103         }
00104         if (pending == 0) state = 1;//for the case when there are no ft devices
00105     }
00106     virtual void Callback(HCI_CALLBACK_EVENT c, const u8* data, int len);
00107     int csr_write_bd_addr(BD_ADDR *bdaddr, bool transient=true);
00108     int csr_reset_device(bool transient=true);
00109 } App; //application instance
00110 
00111 extern "C" void mbed_reset();
00112 
00113 
00114 void application::Callback(HCI_CALLBACK_EVENT evt, const u8* data, int len) {//these events are forwarded (in)directly from HCIRecv
00115     unsigned char pin[] = "1234";
00116     unsigned char newaddr[] = {0x2c, 0x07, 0x54, 0x7b, 0x13, 0x00};//possible ft TX address (ROBO TX-277)
00117 //    unsigned char newaddr[] = {0x57, 0x0a, 0x3d, 0x83, 0x15, 0x00};//original address of the cheap round BT dongle
00118     printf("\x1b[%dm", 33);
00119     switch (evt) {
00120         case CALLBACK_READY:
00121             printf("CALLBACK_READY\n");
00122             printf("my address = ");
00123             printf((BD_ADDR*)data);
00124             if (memcmp(newaddr, data, 6) != 0) { //csr_write_bd_addr((BD_ADDR*)newaddr, false);
00125             }
00126             Inquiry();//start the second phase of the discovery
00127             break;
00128 
00129         case CALLBACK_INQUIRY_RESULT: //optionally build the list of FT devices here
00130             printf("CALLBACK_INQUIRY_RESULT ");
00131             printf((BD_ADDR*)data);
00132             printf("\n");//data points to inquiry_info struct
00133 //          RemoteNameRequest((BD_ADDR*)data);
00134             break;
00135 
00136         case CALLBACK_INQUIRY_DONE:
00137             printf("CALLBACK_INQUIRY_DONE\n");
00138             neighbors = new neighbourhood(&App);
00139             neighbors->read();
00140             ConnectDevices();
00141             break;
00142 
00143         case CALLBACK_REMOTE_NAME: {
00144             BD_ADDR* addr = (BD_ADDR*)data;
00145             const char* name = (const char*)(data + 6);
00146             printf(addr);
00147             printf(" = % s\n",name);
00148             pending--;
00149             if (pending == 0) state = 1;
00150         }
00151         break;
00152 
00153         case CALLBACK_CONNECTION_COMPLETE: {
00154             connection_info *ci = (connection_info*)data;
00155             if (ci->status>0) {
00156                 printf("Connection failed, status=0x%02X\n", ci->status);
00157                 break;
00158             }
00159             ConnectionComplete(ci);
00160             printf("Going to open sdp socket\n");
00161             L2CAPAddr addr;
00162             memcpy(&addr.bdaddr, &ci->bdaddr, 6);
00163             //int s = SDP.Open(&addr.hdr);
00164         }
00165         break;
00166         case CALLBACK_PIN_REQ:
00167             printf("Enter PIN for ");
00168             printf((BD_ADDR*)data);
00169             printf(" :  submitting %s\n", pin);
00170             //USBLoop(); wait(1.0); USBLoop();
00171             //for(int k=0; k<2000000;k++) USBLoop();
00172             PinCodeReply(data, pin);
00173             break;
00174         case CALLBACK_VENDOR:
00175             printfBytes("Vendor Reply:", data, len);
00176             //mbed_reset();
00177             if (data[0] == 0xc2)
00178                 csr_reset_device(false);
00179             break;
00180         default:
00181             printf("Unhandled HCI Callback %d\n", evt);
00182     };
00183     printf("\x1b[%dm", 0);
00184 }
00185 
00186 #define CSR_WRITE        0xFC00
00187 
00188 int application::csr_write_bd_addr(BD_ADDR *bdaddr, bool transient) {
00189     unsigned char cmd[] = { 0xc2,
00190                             0x02, 0x00, 0x0c, 0x00, 0x11, 0x47, 0x03, 0x70,
00191                             0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
00192                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00193                           };
00194 
00195     if (transient)
00196         cmd[15] = 0x08;
00197 
00198     cmd[17] = bdaddr->addr[2];
00199     cmd[18] = 0x00;
00200     cmd[19] = bdaddr->addr[0];
00201     cmd[20] = bdaddr->addr[1];
00202     cmd[21] = bdaddr->addr[3];
00203     cmd[22] = 0x00;
00204     cmd[23] = bdaddr->addr[4];
00205     cmd[24] = bdaddr->addr[5];
00206 
00207     return SendCmd(CSR_WRITE, cmd, sizeof(cmd));
00208 }
00209 
00210 int application::csr_reset_device(bool transient) {
00211     unsigned char cmd[] = { 0xc2, 0x02, 0x00, 0x09, 0x00,
00212                             0x00, 0x00, 0x01, 0x40, 0x00, 0x00,
00213                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00214                           };
00215 
00216     if (transient)
00217         cmd[7] = 0x02;
00218 
00219     return SendCmd(CSR_WRITE, cmd, sizeof(cmd));
00220 }
00221 
00222 
00223 //  these should be placed in the DMA SRAM
00224 typedef struct {
00225     u8 _hciBuffer[MAX_HCL_SIZE];
00226     u8 _aclBuffer[MAX_ACL_SIZE];
00227 } SRAMPlacement;
00228 
00229 HCITransportUSB _HCITransportUSB;  //use USB as the transport to the radio
00230 
00231 int OnBluetoothInsert(int device) {//install the HCI and start discovery, user callbacks are made to HciCalback
00232     printf("Bluetooth inserted of %d\n",device);
00233     u32 sramLen;
00234     u8* sram =  USBGetBuffer(&sramLen);
00235     sram = (u8*)(((u32)sram + 1023) & ~1023);
00236     SRAMPlacement* s = (SRAMPlacement*)sram;
00237     _HCITransportUSB.Open(device,s->_hciBuffer,s->_aclBuffer);//setup buffers for USB host, incoming data goes first to HCIRecv and ACLRecv
00238     RegisterSocketHandler(SOCKET_L2CAP,&App); //register the application::hci as handler for L2CAP events
00239     RegisterSocketHandler(SOCKET_RFCOM, &rfcomm_manager);//set the RFCOMMManager as the RFCOM socket handler
00240     if (RegisterSocketHandler(SOCKET_SDP, &SDP))
00241         printf("Could not register SDP socket type\n");
00242     App.Open(&_HCITransportUSB);//the callback is virtual
00243     App.Inquiry();//start discovery of BT devices phase 0
00244     return 0;
00245 }
00246 
00247 DigitalOut led(LED1), loop(LED2);
00248 
00249 int comm = 0;
00250 btserial *incoming, *outgoing;
00251 
00252 void echo(int socket, SocketState state, const u8* data, int len, void* userData) {
00253     const u8 connack[] = { 0xbe, 0xef, 8, 'C','O','N','N','_','A','C','K', 0x11};
00254     printf("Echo: socket %d, state %d, len=%d\n", socket, state, len);
00255     if (state==SocketState_Open) {
00256         if (len == 0) {
00257             printf("Sending CONN_ACK\n");
00258             Socket_Send(socket, connack, sizeof(connack));
00259         } else {
00260             printf("echo back: len=%d, data[0]=%x\n", len, data[0]);
00261             Socket_Send(socket, data, len);  // uncomment
00262             printfBytes("echo:", data, len);
00263         }
00264     }
00265 }
00266 
00267 void TestShell() {
00268     int n=0;
00269     USBInit();
00270     for (;;) {
00271         switch (state) {
00272             case 0: //inquiry and low-level connection
00273                 break;
00274             case 1: {//initialisation
00275                 printf("Ready to open ports\n");
00276                 InitFtBtDeviceList();
00277                 int n = GetNrOfFtBtDevices();
00278                 printf("%d ft BT devices have been found\n", n);
00279                 if (n > 0) {
00280                     ftbtdev *d = GetFtUsbDeviceHandle(0);
00281                     if (d==0) printf("could not get device handle\n");
00282                     int sock = OpenFtBtDevice(d);
00283                 }
00284                 state = 2;
00285                 comm = Socket_Listen(SOCKET_RFCOM, 1, echo, 0);  // uncomment
00286                 //incoming = new btserial(1);
00287             }
00288             break;
00289             case 2://main loop
00290                    /*if (incoming->readable()>0){
00291                      int c= incoming->getc();
00292                      putc(c, stderr);
00293                      incoming->putc(c);
00294                      }
00295                     else if (incoming->readable()<0){
00296                        state = 3;
00297                        printf("end of session");
00298                        delete incoming;
00299                      }*/
00300                 break;
00301             default:
00302                 break;
00303         }
00304         loop=1;
00305         USBLoop();
00306         loop=0;
00307         n++;
00308         if (n>=500000) {
00309             n=0;
00310             led = !led;
00311         }
00312     }
00313     //printf("Dropped out of main loop!\n");
00314 }
00315 
00316 //********************************************************************************************************************************