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

TestShell.cpp

Committer:
networker
Date:
2011-07-01
Revision:
13:327622e38551

File content as of revision 13:327622e38551:


/*
Copyright (c) 2010 Peter Barrett

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "mbed.h"
#include <vector>
#include "Utils.h"
#include "USBHost.h"
#include "hci.h"
#include "HCITransportUSB.h"
#include "RFCOMM.h"
#include "ftclasslibusbdevbt.h"
#include "sdp_data.h"
#include "sdp.h"
#include "btserial.h"
#include "neighbourhood.h"

/************************************************
TODO:
mtu and credits are completely unhandled - in progress
multiple rfcomm sessions should be possible - done
SDP would be nice - beta
multiple rfcomm channels are untested
decoupling of rfcomm and application - much better
packets are not reassembled - some are (HCI and ft application level)
disconnect and timeouts
************************************************/
#define DEBUG   1
int state = 0;

//int bulk = 0;
void printf(const BD_ADDR* addr) {
    const u8* a = addr->addr;
    printf("%02X:%02X:%02X:%02X:%02X:%02X",a[5],a[4],a[3],a[2],a[1],a[0]);
}

const char FtDevClass[3] = {0x00, 0x1F, 0x82 };
const char SerDevClass[3] = {4, 1, 0x00};
//  Instance
//RFCOMMManager rfcomm_manager;

class application : public HCI {
    BTDevice* devs[8];
    int count, i, pending;
public:
    //  We have connected to a device
    void ConnectionComplete(connection_info* info) {
        printf("ConnectionComplete ");
        BD_ADDR* a = &info->bdaddr;
        printf(a);
        printf("\n");
        RemoteNameRequest(a);
        for (i++; i < count; i++) {//find the next device to open
            printfBytes("DEVICE CLASS",devs[i]->_info.dev_class,3);
            if (devs[i]->_handle == 0 && memcmp(devs[i]->_info.dev_class, FtDevClass, 3)==0) {//or some other way to connect to RFCOMM devices
                BD_ADDR* bd = &devs[i]->_info.bdaddr;
                printf("Connecting to ");
                printf(bd);
                printf("\n");
                pending++;
                CreateConnection(bd); //some low level connect, just let it happen for now (sets pin, mtu etc.)
                printf("connection cmd was sent\n");
                return;
            }
        }
        //state = 1; //start the real application
    }

    void ConnectDevices() {
        count = GetDevices(devs,8);//get pointers to all bluetooth devices
        pending = 0;
        for (i = 0; i < count; i++) {
            printfBytes("DEVICE CLASS",devs[i]->_info.dev_class,3);
            if (devs[i]->_handle == 0 /*&& memcmp(devs[i]->_info.dev_class, FtDevClass, 3)==0*/) {//or some other way to connect to RFCOMM devices
                BD_ADDR* bd = &devs[i]->_info.bdaddr;
                printf("Connecting to ");
                printf(bd);
                printf("\n");
                pending++;
                CreateConnection(bd); //some low level connect, just let it happen for now (sets pin, mtu etc.)
                printf("connection cmd was sent\n");
                return;
            }
        }
        if (pending == 0) state = 1;//for the case when there are no ft devices
    }
    virtual void Callback(HCI_CALLBACK_EVENT c, const u8* data, int len);
    int csr_write_bd_addr(BD_ADDR *bdaddr, bool transient=true);
    int csr_reset_device(bool transient=true);
} App; //application instance

extern "C" void mbed_reset();


void application::Callback(HCI_CALLBACK_EVENT evt, const u8* data, int len) {//these events are forwarded (in)directly from HCIRecv
    unsigned char pin[] = "1234";
    unsigned char newaddr[] = {0x2c, 0x07, 0x54, 0x7b, 0x13, 0x00};//possible ft TX address (ROBO TX-277)
//    unsigned char newaddr[] = {0x57, 0x0a, 0x3d, 0x83, 0x15, 0x00};//original address of the cheap round BT dongle
    printf("\x1b[%dm", 33);
    switch (evt) {
        case CALLBACK_READY:
            printf("CALLBACK_READY\n");
            printf("my address = ");
            printf((BD_ADDR*)data);
            if (memcmp(newaddr, data, 6) != 0) { //csr_write_bd_addr((BD_ADDR*)newaddr, false);
            }
            Inquiry();//start the second phase of the discovery
            break;

        case CALLBACK_INQUIRY_RESULT: //optionally build the list of FT devices here
            printf("CALLBACK_INQUIRY_RESULT ");
            printf((BD_ADDR*)data);
            printf("\n");//data points to inquiry_info struct
//          RemoteNameRequest((BD_ADDR*)data);
            break;

        case CALLBACK_INQUIRY_DONE:
            printf("CALLBACK_INQUIRY_DONE\n");
            neighbors = new neighbourhood(&App);
            neighbors->read();
            ConnectDevices();
            break;

        case CALLBACK_REMOTE_NAME: {
            BD_ADDR* addr = (BD_ADDR*)data;
            const char* name = (const char*)(data + 6);
            printf(addr);
            printf(" = % s\n",name);
            pending--;
            if (pending == 0) state = 1;
        }
        break;

        case CALLBACK_CONNECTION_COMPLETE: {
            connection_info *ci = (connection_info*)data;
            if (ci->status>0) {
                printf("Connection failed, status=0x%02X\n", ci->status);
                break;
            }
            ConnectionComplete(ci);
            printf("Going to open sdp socket\n");
            L2CAPAddr addr;
            memcpy(&addr.bdaddr, &ci->bdaddr, 6);
            //int s = SDP.Open(&addr.hdr);
        }
        break;
        case CALLBACK_PIN_REQ:
            printf("Enter PIN for ");
            printf((BD_ADDR*)data);
            printf(" :  submitting %s\n", pin);
            //USBLoop(); wait(1.0); USBLoop();
            //for(int k=0; k<2000000;k++) USBLoop();
            PinCodeReply(data, pin);
            break;
        case CALLBACK_VENDOR:
            printfBytes("Vendor Reply:", data, len);
            //mbed_reset();
            if (data[0] == 0xc2)
                csr_reset_device(false);
            break;
        default:
            printf("Unhandled HCI Callback %d\n", evt);
    };
    printf("\x1b[%dm", 0);
}

#define CSR_WRITE        0xFC00

int application::csr_write_bd_addr(BD_ADDR *bdaddr, bool transient) {
    unsigned char cmd[] = { 0xc2,
                            0x02, 0x00, 0x0c, 0x00, 0x11, 0x47, 0x03, 0x70,
                            0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
                          };

    if (transient)
        cmd[15] = 0x08;

    cmd[17] = bdaddr->addr[2];
    cmd[18] = 0x00;
    cmd[19] = bdaddr->addr[0];
    cmd[20] = bdaddr->addr[1];
    cmd[21] = bdaddr->addr[3];
    cmd[22] = 0x00;
    cmd[23] = bdaddr->addr[4];
    cmd[24] = bdaddr->addr[5];

    return SendCmd(CSR_WRITE, cmd, sizeof(cmd));
}

int application::csr_reset_device(bool transient) {
    unsigned char cmd[] = { 0xc2, 0x02, 0x00, 0x09, 0x00,
                            0x00, 0x00, 0x01, 0x40, 0x00, 0x00,
                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
                          };

    if (transient)
        cmd[7] = 0x02;

    return SendCmd(CSR_WRITE, cmd, sizeof(cmd));
}


//  these should be placed in the DMA SRAM
typedef struct {
    u8 _hciBuffer[MAX_HCL_SIZE];
    u8 _aclBuffer[MAX_ACL_SIZE];
} SRAMPlacement;

HCITransportUSB _HCITransportUSB;  //use USB as the transport to the radio

int OnBluetoothInsert(int device) {//install the HCI and start discovery, user callbacks are made to HciCalback
    printf("Bluetooth inserted of %d\n",device);
    u32 sramLen;
    u8* sram =  USBGetBuffer(&sramLen);
    sram = (u8*)(((u32)sram + 1023) & ~1023);
    SRAMPlacement* s = (SRAMPlacement*)sram;
    _HCITransportUSB.Open(device,s->_hciBuffer,s->_aclBuffer);//setup buffers for USB host, incoming data goes first to HCIRecv and ACLRecv
    RegisterSocketHandler(SOCKET_L2CAP,&App); //register the application::hci as handler for L2CAP events
    RegisterSocketHandler(SOCKET_RFCOM, &rfcomm_manager);//set the RFCOMMManager as the RFCOM socket handler
    if (RegisterSocketHandler(SOCKET_SDP, &SDP))
        printf("Could not register SDP socket type\n");
    App.Open(&_HCITransportUSB);//the callback is virtual
    App.Inquiry();//start discovery of BT devices phase 0
    return 0;
}

DigitalOut led(LED1), loop(LED2);

int comm = 0;
btserial *incoming, *outgoing;

void echo(int socket, SocketState state, const u8* data, int len, void* userData) {
    const u8 connack[] = { 0xbe, 0xef, 8, 'C','O','N','N','_','A','C','K', 0x11};
    printf("Echo: socket %d, state %d, len=%d\n", socket, state, len);
    if (state==SocketState_Open) {
        if (len == 0) {
            printf("Sending CONN_ACK\n");
            Socket_Send(socket, connack, sizeof(connack));
        } else {
            //Socket_Send(socket, data, len);
            printfBytes("echo:", data, len);
        }
    }
}

void TestShell() {
    int n=0;
    USBInit();
    for (;;) {
        switch (state) {
            case 0: //inquiry and low-level connection
                break;
            case 1: {//initialisation
                printf("Ready to open ports\n");
                InitFtBtDeviceList();
                int n = GetNrOfFtBtDevices();
                printf("%d ft BT devices have been found\n", n);
                if (n > 0) {
                    ftbtdev *d = GetFtUsbDeviceHandle(0);
                    if (d==0) printf("could not get device handle\n");
                    int sock = OpenFtBtDevice(d);
                }
                state = 2;
                //comm = Socket_Listen(SOCKET_RFCOM, 1, echo, 0);
                //incoming = new btserial(1);
            }
            break;
            case 2://main loop
                /*   if (incoming->readable()>0){
                     int c= incoming->getc();
                     putc(c, stderr);
                     incoming->putc(c);
                     }
                     else if (incoming->readable()<0){
                       state = 3;
                       printf("end of session");
                       delete incoming;
                     }*/
                break;
            default:
                break;
        }
        loop=1;
        USBLoop();
        loop=0;
        n++;
        if (n>=500000) {
            n=0;
            led = !led;
        }
    }
    //printf("Dropped out of main loop!\n");
}

//********************************************************************************************************************************