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
Diff: TestShell.cpp
- Revision:
- 0:003889bc474f
- Child:
- 2:9f25a7fa1a54
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TestShell.cpp Sat Dec 07 14:19:00 2013 +0000 @@ -0,0 +1,314 @@ + +/* +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"); +} + +//********************************************************************************************************************************