Reputation: 7555
I am trying to create a simple and custom Bluetooth connection between my Linux laptop and Android phone. On the Linux side of things, I use the BlueZ libbluetooth library to set up a server. The code for it is very similar to others I've seen floating around on github:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
#include <bluetooth/rfcomm.h>
sdp_session_t *register_service();
int main(int argc, char **argv)
{
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
char buf[1024] = { 0 };
char str[1024] = { 0 };
int s, client, bytes_read;
sdp_session_t *session;
socklen_t opt = sizeof(rem_addr);
session = register_service();
s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = *BDADDR_ANY;
loc_addr.rc_channel = (uint8_t) 11;
printf("Trying to bind...");
fflush(stdout);
bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
printf("bound\n");
fflush(stdout);
printf("Waiting for connection...");
fflush(stdout);
listen(s, 1);
client = accept(s, (struct sockaddr *)&rem_addr, &opt);
ba2str( &rem_addr.rc_bdaddr, buf );
fprintf(stderr, "accepted connection from %s\n", buf);
memset(buf, 0, sizeof(buf));
bytes_read = read(client, buf, sizeof(buf));
if( bytes_read > 0 ) {
printf("received [%s]\n", buf);
}
sprintf(str,"to Android.");
printf("sent [%s]\n",str);
write(client, str, sizeof(str));
close(client);
close(s);
sdp_close( session );
return 0;
}
sdp_session_t *register_service()
{
uint32_t svc_uuid_int[] = { 0x00000000,0x00000000,0x00000000,0x3233 };
uint8_t rfcomm_channel = 11;
const char *service_name = "Remote Host";
const char *service_dsc = "What the remote should be connecting to.";
const char *service_prov = "Your mother";
uuid_t root_uuid, l2cap_uuid, rfcomm_uuid, svc_uuid;
sdp_list_t *l2cap_list = 0,
*rfcomm_list = 0,
*root_list = 0,
*proto_list = 0,
*access_proto_list = 0;
sdp_data_t *channel = 0, *psm = 0;
sdp_record_t *record = sdp_record_alloc();
// set the general service ID
sdp_uuid128_create( &svc_uuid, &svc_uuid_int );
sdp_set_service_id( record, svc_uuid );
sdp_list_t service_class = {NULL, &svc_uuid};
sdp_set_service_classes( record, &service_class);
// make the service record publicly browsable
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
root_list = sdp_list_append(0, &root_uuid);
sdp_set_browse_groups( record, root_list );
// set l2cap information
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
l2cap_list = sdp_list_append( 0, &l2cap_uuid );
proto_list = sdp_list_append( 0, l2cap_list );
// set rfcomm information
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
channel = sdp_data_alloc(SDP_UINT8, &rfcomm_channel);
rfcomm_list = sdp_list_append( 0, &rfcomm_uuid );
sdp_list_append( rfcomm_list, channel );
sdp_list_append( proto_list, rfcomm_list );
// attach protocol information to service record
access_proto_list = sdp_list_append( 0, proto_list );
sdp_set_access_protos( record, access_proto_list );
// set the name, provider, and description
sdp_set_info_attr(record, service_name, service_prov, service_dsc);
int err = 0;
sdp_session_t *session = 0;
// connect to the local SDP server, register the service record, and
// disconnect
session = sdp_connect( BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY );
err = sdp_record_register(session, record, 0);
// cleanup
//sdp_data_free( channel );
sdp_list_free( l2cap_list, 0 );
sdp_list_free( rfcomm_list, 0 );
sdp_list_free( root_list, 0 );
sdp_list_free( access_proto_list, 0 );
return session;
}
I am able to run the server side code in Linux without error:
$ ./bluetooth-server
Trying to bind...bound
Waiting for connection...
I am then able to use sdptool
to see my RFCOMM socket and service (description, channel number, and all other information look correct):
Service Name: Remote Host
Service Description: What the remote should be connecting to.
Service Provider: Your mother
Service RecHandle: 0x10009
Service Class ID List:
UUID 128: 00000000-0000-0000-0000-000033320000
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 11
Now, on the Android side of things I first pair the phone to the Linux server via the standard settings screen. Once paired, I then use code on the Android side of things to scan for Bluetooth devices, and if it is my Linux device then I try to connect to it. I have tried two different methods that people have suggested on stack overflow to make the connection:
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if(device.getName().equals("ubuntu-0")) {
try {
mBluetoothAdapter.cancelDiscovery();
// This returns the value 00001103-0000-1000-8000-00805f9b34fb
UUID uuid = device.getUuids()[0].getUuid();
// This does not work
//BluetoothSocket tmp = device.createRfcommSocketToServiceRecord(uuid);
// And neither does this
Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
BluetoothSocket tmp = (BluetoothSocket) m.invoke(device, 11); // Match channel 11
tmp.connect(); // Exception is thrown here
}
catch(Exception e) {
Log.e("BT", "Could not create RFCOMM socket " + e.toString());
}
}
}
I keep getting the following Exception being thrown when I actually try the tmp.connect()
call:
03-20 14:20:13.089: E/BT(16915): Could not create RFCOMM socket
java.io.IOException: read failed, socket might closed or timeout, read ret: -1
Does anyone see what I am doing wrong here in trying to create the connection? Note that I do get a UUID returned when I call UUID uuid = device.getUuids()[0].getUuid();
... this leads me to believe that the pairing is OK, which returns the value 00001103-0000-1000-8000-00805f9b34fb
.
Upvotes: 3
Views: 4186
Reputation: 344
Maybe this could be reason if you pair your device before running ./bluetooth-server then rfcomm service record is not added and remote device will not information about this and if remote device does not do the service discovery then it will not be able to connect to your device.
Upvotes: 1