Bluetooth USB communication

10 May 2011

Hi - I've got two mbeds each with a USB bluetooth dongle attached. I just want them to make a connection and share a few bytes of data. I'm looking at the BlueUSB and WiiRacing examples but can't seem to decypher them. Both my mbeds will connect to my iPhone, so are wired in correctly, but will not connect to each other. When the BlueUSB code boots to 'Inquiry' they just dont see each other. I'm happy to have one as a master and one as a slave if necessary, but basically need to

  • make the systems both bluetooth 'visable' (?)
  • initialise the connection (including PIN verification?)
  • move a few bytes of data between the two to prove the comms

any ideas most appreciated, or is this a stretch too far at present...?

10 May 2011

Hi,

I'm working on BT communication as well. My starting point was also BlueUSB. My communication has been between an MBED and another (listening) device, which I found relatively easy and between a client PC and a listening MBED (which I found quite difficult). Using two MBEDs is an advantage and a disadvantage. The advantage is that you can choose the protocol yourself, the disadvantage is that you have to get it right at both ends because it is diffult to test one side against a PC unless you implement the full SPP profile. The BlueUSB stack is very incomplete but it provides a reasonable L2CAP implementation without fragmentation/recombination and without flow-control. I have made an attempt to add this to the HCI/L2CAP layer but maybe you can live without. When you look at the class BTDevice, you see the 'Connect' function which connects to another device. You can also use the Socket_Open function which provides a socket and then calls Connect. At the other end there will be a notification of a connection attempt in function 'Control', case L2CAP_CONN_REQ. Here you should respond with the appropriate reply. BlueUSB 'as is' does not have the concept of a listening socket so you have to build your own (look at my code for ideas). This will give you a simple bidirectional connection but the original stack has little concept of MTUs and flow control. PIN verification will not be a problem because the original provides '0000' as a default PIN and as long as that's the same on both sides you're OK. When you need a higher level of communication that is also suitable for connection to other devices like a PC you need to implement the SPP profile. This means that you need to implement the SDP and the RFCOMM protocol and, worse, that you need to implement both the client and the server side. I have this running in my particular situation, I don't know if it is usable for you. All code has been published.

11 May 2011

wow, thanks Ad for such a detailed reply - that's got me plenty to think about for a few days! I'll let you know how I get on...

11 May 2011

Hi, I have also been using BlueUSB as a starting point for a communication project between a PS3 Sixaxis and a MBED with a USB Bluetooth dongle. As a PS3 Sixaxis will try to establish both a HCI and L2CAP connection (and hence the MBED has to listen to incoming connections) I created a Socket_Listen function (listening socket) as Ad described above. See: PS3_BlueUSB

HTH - Bart

11 May 2011

Hi guys - thanks for your replies but I have to say I'm struggling with this. I'm using the latest myBlueUSB program as a template and straight off the two mbeds seem to connect ie both return each others mac address. But now I need to add something to the TestShell.cpp file to send data between the two. I think I should add something to the

case 2://main loop 

condition which should allow me to send a data byte from my master and flash an led on my slave dependent on the value of the data byte. Of course they aren't really master and slave, but I'm just trying to get comms in one directioj working first. But I'm unsure how to send and receive the data. I've tried with Socket_Send, putc and getc, but I just haven't found the method that works, could you suggest something please?

I suppose I'm also not certain that the devices are listening properly, in which case I wouldn't get a response even if i did code the send/put/get commands correctly. When I boot one of the mbeds, I automatically get the connection to the other mbed but then i get the statement '0 ft BT devices have been found'. I assume this is an issue? and could you tell me what 'ft' refers to please? your help is most appreciated as always :)

11 May 2011

Hi Rob,

don't panic, it took me 3 months to figure out how it works and still it puzzles me sometimes. I consider the version of Peter Barrett as the original version. From your post I understand that you are using another version, possibly mine. In that case my question is which protocol you want to use. Roll your own on top of L2CAP or use the socket interface to RFCOMM or use the 'btserial' port adaptation? In my code you see some things with ft in their name, these have to do with my specific application and you can ignore those. Your client and server program are typically different, the client uses Socket_Open somewhere to initate the connection and the server uses Socket_Listen somewhere to listen to an incoming connection. These calls are made in the constructors of btserial. So if you use btserial make sure that client and server use different constructors and that they use the same channel. What I have implemented is way more than what I needed myself, a consequence of this is that it is very poorly tested. In fact, what you see is all that is tested, a simple echo program with the mbed as a server. For my own application (the stuff with ft) I only used the client and without the btserial adaptation. Hence I'm sure you will encounter loads of bugs and code with all signs of organic growth. I guess it is still better than to start from almost scratch like I did, although there was some fun in it as well. The switch statement you are referring to is a state-machine that I use to enforce the different phases of the program because most things happen asynchronously and USBLoop() must be frequently called for anything to happen at all. In state 2 I do the copying (for echo) until the connection breaks and I proceed to state 3. BTW. when a listening rfcomm socket is accepted it is moved from the set of listeners to the set of open rfcomm sockets and when it is closed it is just closed and not returned to the listening sockets. So it is not like tcpip where on every accept a new task is spawned. I hope this helps you somewhat, I'll be glad to help you repair some bugs.

11 May 2011

Rob, it's me again. I'm not sure but maybe you've missed this: The program 'as is' is the server with: btdevice *incoming = new btdevice(CHANNEL); on the client however you need something like: char addr[6] = {/* the other mbed's MAC */}; btdevice *outgoing = new btdevice(addr, CHANNEL); Never tested it as I have only 1 mbed.

15 May 2011

Hey Ad, thanks again for your help. OK, I have made some progress. I don't understand everything, but the two meds with USB bluetooth dongles are now communicating. Here's what I did...

I took Ad van der Weiden's myBlueUSB program (http://mbed.org/users/networker/programs/myBlueUSB/lqmn75) and modified it for two mbeds. I've called them mbed A and mbed B. For the A mbed I modified the TestShell.cpp file to have a TestShell function which sets up an incoming btserial communication (i.e. it goes into a 'listening' mode). Once this has initialised the A mbed continually performs an incoming->getc() command to read any bytes being sent over Bluetooth. It then outputs the read char to a 4-bit LED bus (the onboard mbed LEDs). Here's the important code for mbed A:

//A mbed Code
BusOut leds(LED1,LED2,LED3,LED4);    // create 4 bit data bus of onboard leds
btserial *incoming;
void TestShell() {
    int c_in;
    USBInit();
    for (;;) {
        switch (state) {
            case 0: //inquiry and low-level connection
                break;
            case 1: {//initialisation
                printf("A mbed listening\n");
                incoming = new btserial(2);  // setup btserial for incoming data on channel 2(listen)
                state = 2;
            }
            break;
            case 2://main loop
                wait(0.5);
                if (incoming->readable()>0) {    // if data is readable
                    c_in = incoming->getc();     // get char
                    leds=c_in;                   // output char to leds bus
                }
                break;
            default:
                break;
        }
        USBLoop();
    }
}

mbed B is set up to initiate an outgoing connection to mbed A and then send outgoing data every 4 seconds. To do this I need to know the MAC address of the USB dongle to be communacated with. The data byte sent is either a count value between 0x00-0x0F, or, by switching a digital input latch, this can be overidden to be always 0x0F. The value is also displayed to the on baord LEDs as a 4-bit binary count value. Here's the TestShell.cpp code of importance:

//B mbed Code
BusOut leds(LED1, LED2, LED3, LED4); // create 4 bit data bus of onboard leds
DigitalIn latch(p14);                // digital switch input on pin 14
btserial *outgoing;
void TestShell() {
    char Aaddr[6]={0x16,0x87,0x50,0xDD,0x09,0x00};  //A mbed MAC address (defined byb the USB bluetooth module)
    int c_out=1;
    USBInit();
    for (;;) {
        switch (state) {
            case 0: //inquiry and low-level connection
                break;
            case 1: {//initialisation
                printf("B ready to connect\n");
                outgoing = new btserial(Aaddr,2);// setup btserial for outgoing data on ch2 to mbed A MAC address
                state = 2;
            }
            break;
            case 2://main loop
                wait(4);
                if (latch==1) {             // if switch is high
                    c_out=0x0F;             // override count to 15 (all leds on)
                } else {
                    c_out++;                // else incrmenet count
                    if (c_out>0x0F) {       // reset if abover 15
                        c_out=0x01;
                    }
                }
                outgoing->putc(c_out);  // send outgoing comms message
                leds=c_out;             // output value to leds also
                break;
            default:
                break;
        }
        USBLoop();
    }
}

The only other change I made was that for each program I changed the data buffer size to 1, i.e.

static const int bufsize = 1

in btserial.h - this ensures that only one byte at a time is communicated.

So I'm still trying to understand exactly how this all hangs together, but at least it shows communications are there. There is also a lot of latency in the system which I don't fully understand the cause of, so for that reason I made loops and broadcast messages quite slow, but hopefully they can be sped up as I understand the code and remove unnecessary functions.

I've also posted a video of this working on YouTube, its here:

15 May 2011

Hi Rob,

I'm glad it kinda works. Two remarks: 1) btserial buffers data until either buffer full or end-of-line (setting the size to 1 indeed forces the buffer to flush). 2) The funny state-machine in the main loop is the way it is because the USB Host stack is predominantly polled (by the USBLoop() function). Using wait blocks the main loop, polling doesn't take place and USB (and ergo BT) events do not get serviced. You should make this completely event driven by e.g. starting a Timer and testing the value. The idea is that you always keep running through the loop and when there is something to do you take some action.

I have performance problems as well, right now I'm looking into the credit based flow control. I see a lot of messages that the mbed is waiting for an ACL buffer to become available. This indicates that the mbed cannot write to the local dongle as fast as it would like. I don't know why that is because on a pc the dongle is fast enough with the same remote system.

26 Jul 2011

Nice work from both of you....
So has any one made it to work faster.
when I used the above mentioned code it stops after sometime... looks like it is disconnected automatically after sometime...Any idea about that?

the last message on the screen from transmitting side is

ACL Read pending.
HCICallback: 7: 13 05 01 01 00 01 00
HCI_EV_NUM_COMP_PKTS 7: 13 05 01 01 00 01 00
ACLSend: 13: 01 20 09 00 05 00 41 00 13 EF 03 05 65
Waiting for ACL buffers...
HCICallback: 6: 05 04 00 01 00 08
HCI_EV_DISCONN_COMPLETE 6: 05 04 00 01 00 08

01 May 2012

HI guys!

Im trying to connect my ps3 controller but got stuck the same place every time. I can get the ps3controller to work via cable but offcouse the goal is via bluetooth.

As you can se below in my output it actually dos connect but the gets stuck... I hope somebody can clarify how to get this working:

Bluetooth inserted of 1 Local Address: 00:15:83:15:A3:10 CALLBACK_READY HIDBluetooth 112 Scanning... Status HCI_OP_ACCEPT_CONN_REQ OK Connected on 0001 ConnectionComplete 04:76:6E:1C:AC:CC1000074c 100003a4 listen return code ctrl socket = 0 listen return code data socket = 0 OPEN DEVICE CLASS 3: 08 05 00 From address 04:76:6E:1C:AC:CC : L2CAP_CONN_REQ Result 41708 L2CAP_CONN_REQ is 2 Connection request scid = 1905 psm = 17 Call to BTDevice Create Connection accepted L2CP send: 20: 01 20 10 00 0C 00 01 00 03 01 08 00 40 00 71 07 00 00 00 00 L2CP send: 20: 01 20 10 00 0C 00 01 00 04 00 08 00 71 07 00 00 01 02 A0 02 Call to BTDevice Send L2CP send: 14: 01 20 0A 00 06 00 71 07 53 F4 42 03 00 00 Else... s->scid: 64 From address 04:76:6E:1C:AC:CC : L2CAP_CONF_REQ Result 58922 Config request dcid = 40 flags = 00 L2CP send: 18: 01 20 0E 00 0A 00 01 00 05 02 06 00 71 07 00 00 00 00 From address 04:76:6E:1C:AC:CC : L2CAP_CONF_RSP Result 0

Hardware: mBed - USBhub - CSR Bluetooth dongle - Ps3 Controller

Thanks in advance

/Jakob

01 May 2012

Hello Jakob,

do You use Bart Janssens http://mbed.org/users/BartJanssens/programs/PS3_BlueUSB/lq9h2h PS3 BlueUSB program or BlueUSB host program from Peter Barrett? You will need first one I mentoied.

If DualShock 3 gamepad is connected to USB host via USB cable, host sends special command to controller to set his bdaddr to same which Host's bdaddr is. This is done instead of entering "pin" as on many other device.

Please take look in AutoEvents.cpp in PS3 BlueUSB on line 261 You will see:


u8 my_mac[6] = {0x00, 0x02, 0x72, 0xAD, 0xF3, 0x5B}; // mac address of my Bluetooth device
00262     
00263     u8 buf2[6];
00264     
00265     buf2[0] = 0x00;
00266     buf2[1] = 0x02;
00267     buf2[2] = 0x72;
00268     buf2[3] = 0xAD;
00269     buf2[4] = 0xF3;
00270     buf2[5] = 0x5B;

Change this to bdaddr of Your bluetooth dongle so the bdaddr transfered to DualShock 3 will match bdaddr of Your dongle and pairing should be ok.

Because this bdaddr is hardcoded in program You will need to change it again if You will need use it with another BT dongle with another bdaddr.

I hope this will help You and please excuse my English, not my origin language.

02 May 2012

Hi little llumpu, yes I tried using Barts Janssens code.

Now: I tried importing the program once again and setup the bdaddr. But its still stuck in the same position... any idears on why ?

Output:
Connection accepted 
L2CP send:  20: 01 20 10 00 0C 00 01 00 03 01 08 00 40 00 81 07 00 00 00 00
L2CP send:  20: 01 20 10 00 0C 00 01 00 04 00 08 00 81 07 00 00 01 02 A0 02
Call to BTDevice Send 
L2CP send:  14: 01 20 0A 00 06 00 81 07 53 F4 42 03 00 00
From address 04:76:6E:1C:AC:CC : L2CAP_CONF_REQ Result 58922
Config request dcid = 40 flags = 00
L2CP send:  18: 01 20 0E 00 0A 00 01 00 05 02 06 00 81 07 00 00 00 00
From address 04:76:6E:1C:AC:CC : L2CAP_CONF_RSP Result 0
02 May 2012

Is it transferring credits also before getting stuck?

02 May 2012

Hey, yes I guess :-O :

see the full output below:

BlueUSB
Now get a bunch of usb or bluetooth things and plug them in
USB INIT (Controller is 1396 bytes)
HubStatusChange Hub:0 Port:1 00010101
ResetPort Hub:0 Port:1
HubStatusChange Hub:0 Port:1 00100103
Connect Hub:0 Port:1 full
Class E0 found 0A12:0001
AddEndpoint D:01 A:00 T:00 P:0010 I:00
========RETRY ADD DEVICE========
Disconnect Hub:0 Port:1
ResetPort Hub:0 Port:1
HubStatusChange Hub:0 Port:1 00100103
Connect Hub:0 Port:1 full
Class E0 found 0A12:0001
AddEndpoint D:01 A:00 T:00 P:0010 I:00
AddEndpoint D:01 A:81 T:03 P:0010 I:01
AddEndpoint D:01 A:82 T:02 P:0040 I:00
AddEndpoint D:01 A:02 T:02 P:0040 I:00
LoadDevice 1 E0:01:01
Bluetooth inserted of 1
Local Address: 00:15:83:15:A3:10
CALLBACK_READY
HIDBluetooth 112
Scanning...
Status HCI_OP_ACCEPT_CONN_REQ OK
Connected on 0001
ConnectionComplete 04:76:6E:1C:AC:CC1000074c 100003a4
listen return code ctrl socket = 0 
listen return code data socket = 0 
OPEN DEVICE CLASS 3: 08 05 00
From address 04:76:6E:1C:AC:CC : L2CAP_CONN_REQ Result 49836
Connection request scid = 1935 psm = 17 
Call to BTDevice Create 
Connection accepted 
L2CP send:  20: 01 20 10 00 0C 00 01 00 03 01 08 00 40 00 8F 07 00 00 00 00
L2CP send:  20: 01 20 10 00 0C 00 01 00 04 00 08 00 8F 07 00 00 01 02 A0 02
Call to BTDevice Send 
L2CP send:  14: 01 20 0A 00 06 00 8F 07 53 F4 42 03 00 00
From address 04:76:6E:1C:AC:CC : L2CAP_CONF_REQ Result 58922
Config request dcid = 40 flags = 00
L2CP send:  18: 01 20 0E 00 0A 00 01 00 05 02 06 00 8F 07 00 00 00 00
From address 04:76:6E:1C:AC:CC : L2CAP_CONF_RSP Result 0
02 May 2012

from the output it shows that it is not transmitting credit packets and hangs before that.
i also faced the stucking problem but that was due to he credits.
looks like thats not the case for u
good luck

02 May 2012

Hello again Jakob,

I started with PS3BlueUSB last year when I bought mbed. For me it was not working for first time an in that time I found blog post how to fix it.

Because it was long time I forgot that I needed to change more things in code. Today I took time to load my back-up CD with internet bookmarks and YES, after hour I found that blog post for You!!! Many thanks to blog author!!!!

http://blog.goo.ne.jp/roboz80/e/10e7bf38d3a63b996ca2894e9fb5e3b6

I did the same things what are mentoied there and I am using DualShock 3 with mbed for more than year.

First step is what I mentoied yesterday about bdaddr in AutoEvents.cpp, second step is to change some lines of code in hci.cpp, just change to what You see on picture in blog post.

I hope this will help You little bit :o)

03 May 2012

Thank you so much! its fantastic that you took the time an found this information for me. Thank you!

I compiled the code but it still stops at the same spot as before making me wonder if there is something wrong in the code importable from the mbed server ?

When I compile the code right after import it compiles okay, but I get 14 warnings. "missing return statement at the end of non-void fuction..." and variable declared but never used...

I guess it okay but It could be nice if one of you guys whith some code that works would publish it

thanks again for your help so far!

11 Dec 2012

Anyone have an idea why I am able to connect to a controller but the LED and Rumble on connect is not working? I am using the PS3_BlueUSB project. It seems to work fine except that it takes a few resets sometimes to get it to pass the "Searching . . ." prompt.

/media/uploads/srsmitherman/untitled.rtf

06 Sep 2013

I have got MSI Bluetooth dongle and blueUSB ps3 detects it... But the dongle cant detect PS3 controller..... Any help....