Ogni dispositivo bluetooth generalmente ha in esecuzione un server SDP
che risponde alle richieste provenienti dagli altri dispositivi bluetooth.
In Bluez, l'implementazione del server SDP è chiamata sdpd e di solito è
avviata dagli script di boot di sistema. sdpd gestisce tutte le richieste
SPD in entrata. Le applicazioni che hanno bisogno di esportare un servizio
Bluetooth devono utilizzare i metodi di comunicazione interprocesso per
informare sdpd su cosa vogliono esportare. Ciò viene fatto
attraverso la named pipe /var/run/sdp. Comunque BlueZ fornisce delle funzioni
per rendere questo processo più semplice.
Registrare un servizio con sdpd consiste nel descrivere il servizio da esportare,
nella connettersi a sdpd, istruire sdpd su cosa esportare, ed in fine disconnettersi.
Descrivere un servizio consiste essenzialmente nel riempire la struttura
sdp_record_t. Questo comporta la creazione di alcune liste e del loro popolamento con
degli attributi.
L'esempio 4-9 mostra come descrivere un servizio con UUID 0xABCD che funziona
sul canale RFCOMM 11, che viene chiamato "Roto-Rooter Data Router" e fornito da
"Roto-Rooter", ed ha come descrizione "An experimental plumbing router".
Example 4-9. Describing a service
#include <bluetooth/bluetooth.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
sdp_session_t *register_service()
{
uint32_t service_uuid_int[] = { 0, 0, 0, 0xABCD };
uint8_t rfcomm_channel = 11;
const char *service_name = "Roto-Rooter Data Router";
const char *service_dsc = "An experimental plumbing router";
const char *service_prov = "Roto-Rooter";
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, &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);
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);
.
.
Creare la descrizione in se è abbastanza semplice, si tratta di prendere
quei cinque campi e inserirli nelle strutture dati. Il più del lavoro è quello
di unire le liste insieme.
Una volta che la struct è stata riempita, l'applicazione si deve connettere
al server SDP locale e registrare il nuovo servizio, avendo cura dopo di ciò
di liberare la memoria della struct allocata in precedenza.
.
.
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;
}
L'argomento speciale BDADDR_LOCAL fa in modo che sdp_connect si connetta al
server SDP locale (attraverso la named pipe /var/run/sdp) invece che ad una
periferica remota. Una volta che si è stabilita una sessione attiva con il
server, sdp_record_register esporta i dati del servizio. Il servizio sarà
esportato finchè la sessione con il server SDP sarà tenuta aperta. Non appena
il server SDP rileverà che il socket viene chiuso, smetterà di esportare il
servizio. spd_close chiude la sessione con il server SDP.
sdp_session_t *sdp_connect( const bdaddr_t *src, const bdaddr_t *dst, uint32_t
flags );
int sdp_close( sdp_session_t *session );
int sdp_record_register(sdp_session_t *sess, sdp_record_t *rec, uint8_t flags);