struct BT_SDESC {
unsigned char channel;
unsigned int uuid;
char * serviceName;
char * serviceDescription;
char * serviceProvider;
void * session;
int hciID;
};
// Bluetooth server
struct BT_SRV {
struct BT_SDESC * sd;
int socketClient;
int socketServer;
};
...
struct BT_SDESC * btBuildSDesc (int channel) {
struct BT_SDESC * sd;
sd = (struct BT_SDESC *) malloc (sizeof (struct BT_SDESC));
if (! sd) {
return NULL;
}
memset (sd, 0, sizeof (struct BT_SDESC));
sd-> channel = channel;
sd-> uuid = 0xAFFF; / * TODO: check what is this value * /
if (! (sd-> serviceName = strdup ("TeleComp: W-Shell"))
|| ! (sd-> serviceDescription = strdup ("User Shell for Wearable Computer"))
|| ! (sd-> serviceProvider = strdup ("kiborgov.net"))
) {
btDestroySDesc (sd);
return NULL;
}
return sd;
}
int btSDescribe (struct BT_SDESC * sd) {
uint32_t serviceUuidInt [] = {0,0,0, sd-> uuid};
uuid_t serviceUuid, rootUuid, l2capUuid, rfcommUuid;
sdp_record_t * record = sdp_record_alloc ();
sdp_session_t * session = NULL;
sdp_list_t * rootList = NULL, * svClassID = NULL, * profilesList = NULL, * l2capList = NULL, * protocolList = NULL, * rfcommList = NULL, * accessProtocolList = NULL;
sdp_profile_desc_t profile;
sdp_data_t * channel = NULL;
int ret = -2;
/ * Set general service ID * /
sdp_uuid128_create (& serviceUuid, & serviceUuidInt);
sdp_set_service_id (record, serviceUuid);
/ * Public service record * /
sdp_uuid16_create (& rootUuid, PUBLIC_BROWSE_GROUP);
rootList = sdp_list_append (0, & rootUuid);
sdp_set_browse_groups (record, rootList);
/ * Set port attributes * /
sdp_uuid16_create (& rootUuid, SERIAL_PORT_SVCLASS_ID);
svClassID = sdp_list_append (0, & rootUuid);
sdp_set_service_classes (record, svClassID);
sdp_uuid16_create (& profile.uuid, SERIAL_PORT_PROFILE_ID);
profile.version = 0x100;
profilesList = sdp_list_append (0, & profile);
sdp_set_profile_descs (record, profilesList);
/ * Set l2cap info * /
sdp_uuid16_create (& l2capUuid, L2CAP_UUID);
l2capList = sdp_list_append (0, & l2capUuid);
protocolList = sdp_list_append (0, l2capList);
/ * Set rfcomm info * /
sdp_uuid16_create (& rfcommUuid, RFCOMM_UUID);
channel = sdp_data_alloc (SDP_UINT8, & (sd-> channel));
rfcommList = sdp_list_append (0, & rfcommUuid);
sdp_list_append (rfcommList, channel);
sdp_list_append (protocolList, rfcommList);
/ * Attach protocol information to service record * /
accessProtocolList = sdp_list_append (0, protocolList);
sdp_set_access_protos (record, accessProtocolList);
/ * Set name, provider, description * /
sdp_set_info_attr (record, sd-> serviceName, sd-> serviceProvider, sd-> serviceDescription);
/ * Connect local SDP server, register service record, then disconnect * /
if ((session = sdp_connect (BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY))) {
ret = sdp_record_register (session, record, 0);
}
/ * Free allocated resources * /
sdp_data_free (channel);
sdp_list_free (l2capList, 0);
sdp_list_free (rfcommList, 0);
sdp_list_free (rootList, 0);
sdp_list_free (accessProtocolList, 0);
sdp_list_free (svClassID, 0);
sdp_list_free (profilesList, 0);
sd-> session = (void *) session;
return ret;
}
int btBuildSocket (unsigned int channel, struct BT_SDESC * sd) {
struct sockaddr_rc localAddr;
int s = -1, res = -1;
if ((sd-> hciID = btCheckDevice ()) == - 1) {
return -1;
}
if (hci_open_dev (sd-> hciID) <0) {
return -1;
}
hci_close_dev (sd-> hciID);
memset (& localAddr, 0, sizeof (struct sockaddr_rc));
if ((s = socket (AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) == - 1) {
return -1;
}
/ * TODO: replace code below with code uses SDP * /
localAddr.rc_family = AF_BLUETOOTH;
localAddr.rc_bdaddr = * BDADDR_ANY;
localAddr.rc_channel = (uint8_t) channel;
if ((res = bind (s, (struct sockaddr *) & localAddr, sizeof (localAddr))) == - 1) {
close (s);
return -1;
}
return s;
}
struct BT_SRV * btStartServer (int channel) {
struct BT_SRV * bt = malloc (sizeof (struct BT_SRV));
if (! bt) {
btErr = BT_ERR_START_SERVER;
btKillServer (bt);
return NULL;
}
memset (bt, 0, sizeof (struct BT_SRV));
bt-> socketServer = bt-> socketClient = -1;
btErr = BT_OK;
if (btCheckDevice () <0) {
btErr = BT_ERR_NO_DEVICE;
btKillServer (bt);
return NULL;
}
if (! (bt-> sd = btBuildSDesc (channel))) {
btErr = BT_ERR_SDESC_CREATION;
btKillServer (bt);
return NULL;
}
if (btSDescribe (bt-> sd) == - 1) {
btErr = BT_ERR_SDESC_REGISTRATION;
btKillServer (bt);
return NULL;
}
if ((bt-> socketServer = btBuildSocket (channel, bt-> sd)) == - 1) {
btErr = BT_ERR_BUILD_SOCKET;
btKillServer (bt);
return NULL;
}
if (listen (bt-> socketServer, 10)) {
btErr = BT_ERR_SOCKET_LISTENING;
btKillServer (bt);
return NULL;
}
return bt;
}
...
struct BT_SRV * bt = NULL;
int sendFileToClient (char * fname) {
static char buf [1024];
int h;
long int bufsize = 1024;
long int sent = 0;
long int loaded;
struct stat stbuf;
logPrint ("Send file \"% s \ "to client.", fname);
if (stat (fname, & stbuf) == - 1) {
logPrint ("ERROR: cannot retreive file information.");
return -1;
}
if ((h = open (fname, O_RDWR)) <1) {
logPrint ("ERROR: cannot open file.");
return -2;
}
sprintf (buf, "% 010ld", stbuf.st_size);
logPrint ("Sending% ld bytes of data ...", stbuf.st_size);
write (bt-> socketClient, buf, 10);
while (sent <stbuf.st_size) {
loaded = (stbuf.st_size> bufsize)? bufsize: stbuf.st_size;
loaded = read (h, & buf, loaded);
if (loaded <1) {
break;
}
sent + = loaded;
write (bt-> socketClient, buf, loaded);
logPrint ("sent:% ld", sent);
}
close (h);
logPrint ("File is sent.% ld bytes transmitted.", sent);
return sent;
}
...
bt = btStartServer (cfgBtChannel);
...
bt-> socketClient = accept (bt-> socketServer, NULL, NULL);
fcntl (bt-> socketClient, F_SETFL, O_NONBLOCK);
sendFileToClient ("./ projects / cloud / bin / Cloud.jar");
Source: https://habr.com/ru/post/49729/
All Articles