Skip to content

Instantly share code, notes, and snippets.

@kelvinabrokwa
Created January 28, 2017 23:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kelvinabrokwa/7f42613eadbf9a13460e5aa21d28f8d6 to your computer and use it in GitHub Desktop.
Save kelvinabrokwa/7f42613eadbf9a13460e5aa21d28f8d6 to your computer and use it in GitHub Desktop.
Bluetooth Server
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/l2cap.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
sdp_session_t *register_service();
int main(int argc, char **argv)
{
register_service();
struct sockaddr_l2 loc_addr = { 0 }, rem_addr = { 0 };
char buf[1024] = { 0 };
int s, client, bytes_read;
socklen_t opt = sizeof(rem_addr);
// allocate socket
s = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
// bind socket to port 0x1001 of the first available
// bluetooth adapter
loc_addr.l2_family = AF_BLUETOOTH;
loc_addr.l2_bdaddr = *BDADDR_ANY;
loc_addr.l2_psm = htobs(0x1001);
bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
// put socket into listening mode
listen(s, 1);
// accept one connection
client = accept(s, (struct sockaddr *)&rem_addr, &opt);
ba2str( &rem_addr.l2_bdaddr, buf );
fprintf(stderr, "accepted connection from %s\n", buf);
memset(buf, 0, sizeof(buf));
// read data from the client
bytes_read = read(client, buf, sizeof(buf));
if( bytes_read > 0 ) {
printf("received [%s]\n", buf);
}
// close connection
close(client);
close(s);
}
sdp_session_t *register_service()
{
uint32_t service_uuid_int[] = { 0, 0, 0, 0x110B };
uint8_t rfcomm_channel = 11;
uint16_t l2cap_psm = 0x1001;
const char *service_name = "Bluetooth Router";
const char *service_dsc = "An experimental plumbing router";
const char *service_prov = "Bitchin Tech Incorporated";
uuid_t root_uuid, l2cap_uuid, rfcomm_uuid, svc_uuid, svc_class_uuid;
sdp_list_t *l2cap_list = 0,
*rfcomm_list = 0,
*root_list = 0,
*proto_list = 0,
*access_proto_list = 0,
*svc_class_list = 0,
*profile_list = 0;
sdp_data_t *channel = 0, *psm = 0;
sdp_record_t *record = sdp_record_alloc();
sdp_profile_desc_t profile;
// set the general service ID
sdp_uuid128_create( &svc_uuid, &service_uuid_int );
sdp_set_service_id( record, svc_uuid );
// 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);
psm = sdp_data_alloc(SDP_UINT16, &l2cap_psm);
l2cap_list = sdp_list_append( 0, &l2cap_uuid );
sdp_list_append( l2cap_list, psm );
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 profile information
sdp_uuid16_create(&profile.uuid, AUDIO_SINK_PROFILE_ID);
profile.version = 0x0100;
profile_list = sdp_list_append(0, &profile);
sdp_set_profile_descs(record, profile_list);
// attach service class information
sdp_uuid16_create(&svc_class_uuid, AUDIO_SINK_SVCLASS_ID);
svc_class_list = sdp_list_append(0, &svc_class_uuid);
sdp_set_service_classes(record, svc_class_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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment