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