static sdp_record_t *a2dp_record(void) { sdp_list_t *svclass_id, *pfseq, *apseq, *root; uuid_t root_uuid, l2cap_uuid, avdtp_uuid, a2dp_uuid; sdp_profile_desc_t profile[1]; sdp_list_t *aproto, *proto[2]; sdp_record_t *record; sdp_data_t *psm, *version, *features; uint16_t lp = AVDTP_UUID; uint16_t a2dp_ver = 0x0103, avdtp_ver = 0x0103, feat = 0x000f; record = sdp_record_alloc(); if (!record) return NULL; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(NULL, &root_uuid); sdp_set_browse_groups(record, root); sdp_uuid16_create(&a2dp_uuid, AUDIO_SOURCE_SVCLASS_ID); svclass_id = sdp_list_append(NULL, &a2dp_uuid); sdp_set_service_classes(record, svclass_id); sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID); profile[0].version = a2dp_ver; pfseq = sdp_list_append(NULL, &profile[0]); sdp_set_profile_descs(record, pfseq); sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); proto[0] = sdp_list_append(NULL, &l2cap_uuid); psm = sdp_data_alloc(SDP_UINT16, &lp); proto[0] = sdp_list_append(proto[0], psm); apseq = sdp_list_append(NULL, proto[0]); sdp_uuid16_create(&avdtp_uuid, AVDTP_UUID); proto[1] = sdp_list_append(NULL, &avdtp_uuid); version = sdp_data_alloc(SDP_UINT16, &avdtp_ver); proto[1] = sdp_list_append(proto[1], version); apseq = sdp_list_append(apseq, proto[1]); aproto = sdp_list_append(NULL, apseq); sdp_set_access_protos(record, aproto); features = sdp_data_alloc(SDP_UINT16, &feat); sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features); sdp_set_info_attr(record, "Audio Source", NULL, NULL); sdp_data_free(psm); sdp_data_free(version); sdp_list_free(proto[0], NULL); sdp_list_free(proto[1], NULL); sdp_list_free(apseq, NULL); sdp_list_free(pfseq, NULL); sdp_list_free(aproto, NULL); sdp_list_free(root, NULL); sdp_list_free(svclass_id, NULL); return record; }
static sdp_list_t *mdeps_to_sdp_features(struct mdep_cfg *mdep) { sdp_data_t *mdepid, *dtype = NULL, *role = NULL, *descr = NULL; sdp_list_t *f_list = NULL; DBG(""); mdepid = sdp_data_alloc(SDP_UINT8, &mdep->id); if (!mdepid) return NULL; dtype = sdp_data_alloc(SDP_UINT16, &mdep->data_type); if (!dtype) goto fail; role = sdp_data_alloc(SDP_UINT8, &mdep->role); if (!role) goto fail; if (mdep->descr) { descr = sdp_data_alloc(SDP_TEXT_STR8, mdep->descr); if (!descr) goto fail; } f_list = sdp_list_append(NULL, mdepid); if (!f_list) goto fail; if (!sdp_list_append(f_list, dtype)) goto fail; if (!sdp_list_append(f_list, role)) goto fail; if (descr && !sdp_list_append(f_list, descr)) goto fail; return f_list; fail: sdp_list_free(f_list, NULL); if (mdepid) sdp_data_free(mdepid); if (dtype) sdp_data_free(dtype); if (role) sdp_data_free(role); if (descr) sdp_data_free(descr); return NULL; }
static sdp_list_t *app_to_sdplist(struct mcap_application *app) { DBG(""); sdp_data_t *mdepid, *dtype = NULL, *role = NULL, *desc = NULL; sdp_list_t *f_list = NULL; mdepid = sdp_data_alloc(SDP_UINT8, &app->id); if (!mdepid) return NULL; dtype = sdp_data_alloc(SDP_UINT16, &app->data_type); if (!dtype) goto fail; role = sdp_data_alloc(SDP_UINT8, &app->role); if (!role) goto fail; if (app->description) { desc = sdp_data_alloc(SDP_TEXT_STR8, app->description); if (!desc) goto fail; } f_list = sdp_list_append(NULL, mdepid); if (!f_list) goto fail; if (!sdp_list_append(f_list, dtype)) goto fail; if (!sdp_list_append(f_list, role)) goto fail; if (desc) if (!sdp_list_append(f_list, desc)) goto fail; return f_list; fail: if (f_list) sdp_list_free(f_list, NULL); if (mdepid) sdp_data_free(mdepid); if (dtype) sdp_data_free(dtype); if (role) sdp_data_free(role); if (desc) sdp_data_free(desc); return NULL; }
static sdp_list_t *app_to_sdplist(struct hdp_application *app) { sdp_data_t *mdepid, *dtype = NULL, *role = NULL, *desc = NULL; sdp_list_t *f_list = NULL; mdepid = sdp_data_alloc(SDP_UINT8, &app->id); if (mdepid == NULL) return NULL; dtype = sdp_data_alloc(SDP_UINT16, &app->data_type); if (dtype == NULL) goto fail; role = sdp_data_alloc(SDP_UINT8, &app->role); if (role == NULL) goto fail; if (app->description != NULL) { desc = sdp_data_alloc(SDP_TEXT_STR8, app->description); if (desc == NULL) goto fail; } f_list = sdp_list_append(NULL, mdepid); if (f_list == NULL) goto fail; if (sdp_list_append(f_list, dtype) == NULL) goto fail; if (sdp_list_append(f_list, role) == NULL) goto fail; if (desc != NULL) if (sdp_list_append(f_list, desc) == NULL) goto fail; return f_list; fail: if (f_list != NULL) sdp_list_free(f_list, NULL); if (mdepid != NULL) sdp_data_free(mdepid); if (dtype != NULL) sdp_data_free(dtype); if (role != NULL) sdp_data_free(role); if (desc != NULL) sdp_data_free(desc); return NULL; }
static sdp_record_t *create_rfcomm_record(uint8_t chan, uuid_t *uuid, const char *svc_name, bool has_obex) { sdp_list_t *svclass_id; sdp_list_t *seq, *proto_seq, *pbg_seq; sdp_list_t *proto[3]; uuid_t l2cap_uuid, rfcomm_uuid, obex_uuid, pbg_uuid; sdp_data_t *channel; sdp_record_t *record; record = sdp_record_alloc(); if (!record) return NULL; record->handle = sdp_next_handle(); svclass_id = sdp_list_append(NULL, uuid); sdp_set_service_classes(record, svclass_id); sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); proto[0] = sdp_list_append(NULL, &l2cap_uuid); seq = sdp_list_append(NULL, proto[0]); sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); proto[1] = sdp_list_append(NULL, &rfcomm_uuid); channel = sdp_data_alloc(SDP_UINT8, &chan); proto[1] = sdp_list_append(proto[1], channel); seq = sdp_list_append(seq, proto[1]); if (has_obex) { sdp_uuid16_create(&obex_uuid, OBEX_UUID); proto[2] = sdp_list_append(NULL, &obex_uuid); seq = sdp_list_append(seq, proto[2]); } proto_seq = sdp_list_append(NULL, seq); sdp_set_access_protos(record, proto_seq); sdp_uuid16_create(&pbg_uuid, PUBLIC_BROWSE_GROUP); pbg_seq = sdp_list_append(NULL, &pbg_uuid); sdp_set_browse_groups(record, pbg_seq); if (svc_name) sdp_set_info_attr(record, svc_name, NULL, NULL); sdp_data_free(channel); sdp_list_free(proto[0], NULL); sdp_list_free(proto[1], NULL); if (has_obex) sdp_list_free(proto[2], NULL); sdp_list_free(seq, NULL); sdp_list_free(proto_seq, NULL); sdp_list_free(pbg_seq, NULL); sdp_list_free(svclass_id, NULL); return record; }
static sdp_record_t *hfp_hs_record(uint8_t ch) { sdp_list_t *svclass_id, *pfseq, *apseq, *root; uuid_t root_uuid, svclass_uuid, ga_svclass_uuid; uuid_t l2cap_uuid, rfcomm_uuid; sdp_profile_desc_t profile; sdp_record_t *record; sdp_list_t *aproto, *proto[2]; sdp_data_t *channel; record = sdp_record_alloc(); if (!record) return NULL; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(record, root); sdp_uuid16_create(&svclass_uuid, HANDSFREE_SVCLASS_ID); svclass_id = sdp_list_append(0, &svclass_uuid); sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID); svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid); sdp_set_service_classes(record, svclass_id); sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID); profile.version = 0x0105; pfseq = sdp_list_append(0, &profile); sdp_set_profile_descs(record, pfseq); sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); proto[0] = sdp_list_append(0, &l2cap_uuid); apseq = sdp_list_append(0, proto[0]); sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); proto[1] = sdp_list_append(0, &rfcomm_uuid); channel = sdp_data_alloc(SDP_UINT8, &ch); proto[1] = sdp_list_append(proto[1], channel); apseq = sdp_list_append(apseq, proto[1]); aproto = sdp_list_append(0, apseq); sdp_set_access_protos(record, aproto); sdp_set_info_attr(record, "Hands-Free", 0, 0); sdp_data_free(channel); sdp_list_free(proto[0], 0); sdp_list_free(proto[1], 0); sdp_list_free(apseq, 0); sdp_list_free(pfseq, 0); sdp_list_free(aproto, 0); sdp_list_free(root, 0); sdp_list_free(svclass_id, 0); return record; }
static sdp_record_t *create_sap_record(uint8_t channel) { sdp_list_t *apseq, *aproto, *profiles, *proto[2], *root, *svclass_id; uuid_t sap_uuid, gt_uuid, root_uuid, l2cap, rfcomm; sdp_profile_desc_t profile; sdp_record_t *record; sdp_data_t *ch; record = sdp_record_alloc(); if (!record) return NULL; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(NULL, &root_uuid); sdp_set_browse_groups(record, root); sdp_list_free(root, NULL); sdp_uuid16_create(&sap_uuid, SAP_SVCLASS_ID); svclass_id = sdp_list_append(NULL, &sap_uuid); sdp_uuid16_create(>_uuid, GENERIC_TELEPHONY_SVCLASS_ID); svclass_id = sdp_list_append(svclass_id, >_uuid); sdp_set_service_classes(record, svclass_id); sdp_list_free(svclass_id, NULL); sdp_uuid16_create(&profile.uuid, SAP_PROFILE_ID); profile.version = SAP_VERSION; profiles = sdp_list_append(NULL, &profile); sdp_set_profile_descs(record, profiles); sdp_list_free(profiles, NULL); sdp_uuid16_create(&l2cap, L2CAP_UUID); proto[0] = sdp_list_append(NULL, &l2cap); apseq = sdp_list_append(NULL, proto[0]); sdp_uuid16_create(&rfcomm, RFCOMM_UUID); proto[1] = sdp_list_append(NULL, &rfcomm); ch = sdp_data_alloc(SDP_UINT8, &channel); proto[1] = sdp_list_append(proto[1], ch); apseq = sdp_list_append(apseq, proto[1]); aproto = sdp_list_append(NULL, apseq); sdp_set_access_protos(record, aproto); sdp_set_info_attr(record, "SIM Access Server", NULL, NULL); sdp_data_free(ch); sdp_list_free(proto[0], NULL); sdp_list_free(proto[1], NULL); sdp_list_free(apseq, NULL); sdp_list_free(aproto, NULL); return record; }
static sdp_record_t *dun_record(uint8_t ch) { sdp_list_t *svclass_id, *pfseq, *apseq, *root, *aproto; uuid_t root_uuid, dun, gn, l2cap, rfcomm; sdp_profile_desc_t profile; sdp_list_t *proto[2]; sdp_record_t *record; sdp_data_t *channel; record = sdp_record_alloc(); if (!record) return NULL; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(NULL, &root_uuid); sdp_set_browse_groups(record, root); sdp_uuid16_create(&dun, DIALUP_NET_SVCLASS_ID); svclass_id = sdp_list_append(NULL, &dun); sdp_uuid16_create(&gn, GENERIC_NETWORKING_SVCLASS_ID); svclass_id = sdp_list_append(svclass_id, &gn); sdp_set_service_classes(record, svclass_id); sdp_uuid16_create(&profile.uuid, DIALUP_NET_PROFILE_ID); profile.version = 0x0100; pfseq = sdp_list_append(NULL, &profile); sdp_set_profile_descs(record, pfseq); sdp_uuid16_create(&l2cap, L2CAP_UUID); proto[0] = sdp_list_append(NULL, &l2cap); apseq = sdp_list_append(NULL, proto[0]); sdp_uuid16_create(&rfcomm, RFCOMM_UUID); proto[1] = sdp_list_append(NULL, &rfcomm); channel = sdp_data_alloc(SDP_UINT8, &ch); proto[1] = sdp_list_append(proto[1], channel); apseq = sdp_list_append(apseq, proto[1]); aproto = sdp_list_append(0, apseq); sdp_set_access_protos(record, aproto); sdp_set_info_attr(record, "Dial-Up Networking", 0, 0); sdp_data_free(channel); sdp_list_free(root, NULL); sdp_list_free(svclass_id, NULL); sdp_list_free(proto[0], NULL); sdp_list_free(proto[1], NULL); sdp_list_free(pfseq, NULL); sdp_list_free(apseq, NULL); sdp_list_free(aproto, NULL); return record; }
static sdp_record_t *proxy_record_new(const char *uuid128, uint8_t channel) { sdp_list_t *apseq, *aproto, *profiles, *proto[2], *root, *svclass_id; uuid_t uuid, root_uuid, l2cap, rfcomm; sdp_profile_desc_t profile; sdp_record_t *record; sdp_data_t *ch; record = sdp_record_alloc(); if (!record) return NULL; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(NULL, &root_uuid); sdp_set_browse_groups(record, root); sdp_list_free(root, NULL); bt_string2uuid(&uuid, uuid128); svclass_id = sdp_list_append(NULL, &uuid); sdp_set_service_classes(record, svclass_id); sdp_list_free(svclass_id, NULL); sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID); profile.version = 0x0100; profiles = sdp_list_append(NULL, &profile); sdp_set_profile_descs(record, profiles); sdp_list_free(profiles, NULL); sdp_uuid16_create(&l2cap, L2CAP_UUID); proto[0] = sdp_list_append(NULL, &l2cap); apseq = sdp_list_append(NULL, proto[0]); sdp_uuid16_create(&rfcomm, RFCOMM_UUID); proto[1] = sdp_list_append(NULL, &rfcomm); ch = sdp_data_alloc(SDP_UINT8, &channel); proto[1] = sdp_list_append(proto[1], ch); apseq = sdp_list_append(apseq, proto[1]); aproto = sdp_list_append(NULL, apseq); sdp_set_access_protos(record, aproto); add_lang_attr(record); sdp_set_info_attr(record, "Port Proxy Entity", NULL, "Port Proxy Entity"); sdp_data_free(ch); sdp_list_free(proto[0], NULL); sdp_list_free(proto[1], NULL); sdp_list_free(apseq, NULL); sdp_list_free(aproto, NULL); return record; }
static gboolean register_mcap_features(sdp_record_t *sdp_record) { sdp_data_t *mcap_proc; uint8_t mcap_sup_proc = MCAP_SUP_PROC; mcap_proc = sdp_data_alloc(SDP_UINT8, &mcap_sup_proc); if (mcap_proc == NULL) return FALSE; if (sdp_attr_add(sdp_record, SDP_ATTR_MCAP_SUPPORTED_PROCEDURES, mcap_proc) < 0) { sdp_data_free(mcap_proc); return FALSE; } return TRUE; }
static gboolean register_data_exchange_spec(sdp_record_t *record) { sdp_data_t *spec; uint8_t data_spec = DATA_EXCHANGE_SPEC_11073; /* As by now 11073 is the only supported we set it by default */ spec = sdp_data_alloc(SDP_UINT8, &data_spec); if (spec == NULL) return FALSE; if (sdp_attr_add(record, SDP_ATTR_DATA_EXCHANGE_SPEC, spec) < 0) { sdp_data_free(spec); return FALSE; } return TRUE; }
static int register_mcap_features(sdp_record_t *rec) { sdp_data_t *mcap_proc; uint8_t mcap_sup_proc = MCAP_SUP_PROC; DBG(""); mcap_proc = sdp_data_alloc(SDP_UINT8, &mcap_sup_proc); if (!mcap_proc) return -1; if (sdp_attr_add(rec, SDP_ATTR_MCAP_SUPPORTED_PROCEDURES, mcap_proc) < 0) { sdp_data_free(mcap_proc); return -1; } return 0; }
static int register_data_exchange_spec(sdp_record_t *rec) { sdp_data_t *spec; uint8_t data_spec = DATA_EXCHANGE_SPEC_11073; /* As of now only 11073 is supported, so we set it as default */ DBG(""); spec = sdp_data_alloc(SDP_UINT8, &data_spec); if (!spec) return -1; if (sdp_attr_add(rec, SDP_ATTR_DATA_EXCHANGE_SPEC, spec) < 0) { sdp_data_free(spec); return -1; } return 0; }
static gboolean register_service_additional_protocols( struct hdp_adapter *adapter, sdp_record_t *sdp_record) { gboolean ret = TRUE; uuid_t l2cap_uuid, mcap_d_uuid; sdp_list_t *l2cap_list, *proto_list = NULL, *mcap_list = NULL; sdp_list_t *access_proto_list = NULL; sdp_data_t *psm = NULL; /* set l2cap information */ sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); l2cap_list = sdp_list_append(NULL, &l2cap_uuid); if (l2cap_list == NULL) { ret = FALSE; goto end; } psm = sdp_data_alloc(SDP_UINT16, &adapter->dcpsm); if (psm == NULL) { ret = FALSE; goto end; } if (sdp_list_append(l2cap_list, psm) == NULL) { ret = FALSE; goto end; } proto_list = sdp_list_append(NULL, l2cap_list); if (proto_list == NULL) { ret = FALSE; goto end; } /* set mcap information */ sdp_uuid16_create(&mcap_d_uuid, MCAP_DATA_UUID); mcap_list = sdp_list_append(NULL, &mcap_d_uuid); if (mcap_list == NULL) { ret = FALSE; goto end; } if (sdp_list_append(proto_list, mcap_list) == NULL) { ret = FALSE; goto end; } /* attach protocol information to service record */ access_proto_list = sdp_list_append(NULL, proto_list); if (access_proto_list == NULL) { ret = FALSE; goto end; } sdp_set_add_access_protos(sdp_record, access_proto_list); end: if (l2cap_list != NULL) sdp_list_free(l2cap_list, NULL); if (mcap_list != NULL) sdp_list_free(mcap_list, NULL); if (proto_list != NULL) sdp_list_free(proto_list, NULL); if (access_proto_list != NULL) sdp_list_free(access_proto_list, NULL); if (psm != NULL) sdp_data_free(psm); return ret; }
sdp_session_t *register_service(){ //4e:65:78:75:73:2d:43:6f:6d:70:75:74:69:6e:67 ~ Nexus-Computing :)4e65 7875 732d 436f 6d70 7574 696e 6700 //uint32_t service_uuid_int[] = {0x4e65,0x7875,0x732d,0x436f,0x6d70,0x7574,0x696e,0x6700}; uint8_t service_uuid_int[] = {0x07,0x29,0x3d,0xb4,0xa3, 0x23, 0x4e, 0x07,0x8b, 0x8b,0x25,0x0b,0x34,0x0e, 0x42, 0xa4}; uint8_t rfcomm_channel = SVC_CHANNEL; 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, *class_id_list; 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 ); //service classes IMPORTANT FOR ANDROID! class_id_list = sdp_list_append( 0, &svc_uuid); sdp_set_service_classes( record, class_id_list ); // set the name, provider, and description sdp_set_info_attr(record, SVC_NAME, SVC_PROV, SVC_DESC); 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); if(err != 0) perror("Error registring record"); // 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; }
static int RegisterSdp(uint8_t port) { int ret = 1; // {6A841273-4A97-4eed-A299-C23D571A54E7} // {00001101-0000-1000-8000-00805F9B34FB} uint8_t svc_uuid_int[] = {0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}; 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; sdpRecord = sdp_record_alloc(); // set the general service ID sdp_uuid128_create(&svc_uuid, &svc_uuid_int); sdp_set_service_id(sdpRecord, 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(sdpRecord, 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, &port); 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(sdpRecord, access_proto_list); // set the name, provider, and description sdp_set_info_attr(sdpRecord, "DroidCam", "", "Android Webcam"); // connect to the local SDP server, register the service record sdpSession = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY); if(sdp_record_register(sdpSession, sdpRecord, 0)) { MSG_ERROR("Could not register Bluetooth service"); ret = 0; } 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 ret; }
static gboolean register_service_protocols(struct hdp_adapter *adapter, sdp_record_t *sdp_record) { gboolean ret; uuid_t l2cap_uuid, mcap_c_uuid; sdp_list_t *l2cap_list, *proto_list = NULL, *mcap_list = NULL; sdp_list_t *access_proto_list = NULL; sdp_data_t *psm = NULL, *mcap_ver = NULL; uint16_t version = MCAP_VERSION; /* set l2cap information */ sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); l2cap_list = sdp_list_append(NULL, &l2cap_uuid); if (l2cap_list == NULL) { ret = FALSE; goto end; } psm = sdp_data_alloc(SDP_UINT16, &adapter->ccpsm); if (psm == NULL) { ret = FALSE; goto end; } if (sdp_list_append(l2cap_list, psm) == NULL) { ret = FALSE; goto end; } proto_list = sdp_list_append(NULL, l2cap_list); if (proto_list == NULL) { ret = FALSE; goto end; } /* set mcap information */ sdp_uuid16_create(&mcap_c_uuid, MCAP_CTRL_UUID); mcap_list = sdp_list_append(NULL, &mcap_c_uuid); if (mcap_list == NULL) { ret = FALSE; goto end; } mcap_ver = sdp_data_alloc(SDP_UINT16, &version); if (mcap_ver == NULL) { ret = FALSE; goto end; } if (sdp_list_append(mcap_list, mcap_ver) == NULL) { ret = FALSE; goto end; } if (sdp_list_append(proto_list, mcap_list) == NULL) { ret = FALSE; goto end; } /* attach protocol information to service record */ access_proto_list = sdp_list_append(NULL, proto_list); if (access_proto_list == NULL) { ret = FALSE; goto end; } if (sdp_set_access_protos(sdp_record, access_proto_list) < 0) { ret = FALSE; goto end; } ret = TRUE; end: if (l2cap_list != NULL) sdp_list_free(l2cap_list, NULL); if (mcap_list != NULL) sdp_list_free(mcap_list, NULL); if (proto_list != NULL) sdp_list_free(proto_list, NULL); if (access_proto_list != NULL) sdp_list_free(access_proto_list, NULL); if (psm != NULL) sdp_data_free(psm); if (mcap_ver != NULL) sdp_data_free(mcap_ver); return ret; }
sdp_session_t *register_service() { uint32_t service_uuid_int[] = { 0, 0, 0, 0xABCD }; uint8_t rfcomm_channel = 11; const char *service_name = "Edison Test"; const char *service_dsc = "Edison Experimental"; const char *service_prov = "glfernando"; sdp_session_t *session = 0; bdaddr_t bdaddr_local = {{0, 0, 0, 0xff, 0xff, 0xff}}; 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); // connect to the local SDP server, register the service record, and disconnect session = sdp_connect( BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY); if (!session) { printf("session NULL , err %s\n", strerror(errno)); } 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; }
static sdp_record_t *avrcp_record(void) { sdp_list_t *svclass_id, *pfseq, *apseq, *root; uuid_t root_uuid, l2cap, avctp, avrtg; sdp_profile_desc_t profile[1]; sdp_list_t *aproto_control, *proto_control[2]; sdp_record_t *record; sdp_data_t *psm, *version, *features; uint16_t lp = L2CAP_PSM_AVCTP; uint16_t avrcp_ver = 0x0105, avctp_ver = 0x0104; uint16_t feat = (AVRCP_FEATURE_CATEGORY_1 | AVRCP_FEATURE_CATEGORY_2 | AVRCP_FEATURE_CATEGORY_3 | AVRCP_FEATURE_CATEGORY_4); record = sdp_record_alloc(); if (!record) return NULL; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(NULL, &root_uuid); sdp_set_browse_groups(record, root); /* Service Class ID List */ sdp_uuid16_create(&avrtg, AV_REMOTE_TARGET_SVCLASS_ID); svclass_id = sdp_list_append(NULL, &avrtg); sdp_set_service_classes(record, svclass_id); /* Protocol Descriptor List */ sdp_uuid16_create(&l2cap, L2CAP_UUID); proto_control[0] = sdp_list_append(NULL, &l2cap); psm = sdp_data_alloc(SDP_UINT16, &lp); proto_control[0] = sdp_list_append(proto_control[0], psm); apseq = sdp_list_append(NULL, proto_control[0]); sdp_uuid16_create(&avctp, AVCTP_UUID); proto_control[1] = sdp_list_append(NULL, &avctp); version = sdp_data_alloc(SDP_UINT16, &avctp_ver); proto_control[1] = sdp_list_append(proto_control[1], version); apseq = sdp_list_append(apseq, proto_control[1]); aproto_control = sdp_list_append(NULL, apseq); sdp_set_access_protos(record, aproto_control); /* Bluetooth Profile Descriptor List */ sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID); profile[0].version = avrcp_ver; pfseq = sdp_list_append(NULL, &profile[0]); sdp_set_profile_descs(record, pfseq); features = sdp_data_alloc(SDP_UINT16, &feat); sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features); sdp_set_info_attr(record, "AVRCP TG", NULL, NULL); sdp_data_free(psm); sdp_data_free(version); sdp_list_free(proto_control[0], NULL); sdp_list_free(proto_control[1], NULL); sdp_list_free(apseq, NULL); sdp_list_free(aproto_control, NULL); sdp_list_free(pfseq, NULL); sdp_list_free(root, NULL); sdp_list_free(svclass_id, NULL); return record; }
sdp_session_t *register_service() { uint8_t rfcomm_channel = RFCOMM_CHANNEL; const char *service_name = "NDNBlue"; const char *service_dsc = "Server for NDN over Bluetooth"; const char *service_prov = "NDN"; 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); 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; }
sdp_session_t *register_service(int chnel, int l2_chnel) { uint32_t service_uuid_int[] = { 0, 0, 0, 0xABCD }; uint8_t rfcomm_channel = chnel; uint16_t l2cap_channel = l2_chnel; 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, *class_id_list = 0; sdp_data_t *channel = 0, *psm = 0, *l2cap_port = 0; sdp_record_t *record = sdp_record_alloc(); // set the general service ID sdp_uuid128_create( &svc_uuid, &service_uuid_int ); class_id_list = sdp_list_append(0, &svc_uuid); //sdp_set_service_id( record, svc_uuid ); sdp_set_service_classes( record, class_id_list); // 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 ); l2cap_port = sdp_data_alloc(SDP_UINT16, &l2cap_channel); sdp_list_append( l2cap_list, l2cap_port); 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; }
int register_service(sdp_session_t *session) { uint8_t rfcomm_channel = 11; const char *service_name = "Atmel Simple Test Service"; const char *svc_dsc = "Simple Test for SDP Register"; const char *service_prov = "Tony"; int ret = 0; 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; sdp_profile_desc_t profile; sdp_record_t record = { 0 }; /* set the general service ID */ sdp_uuid128_create( &svc_uuid, &uuid128 ); sdp_set_service_id( &record, svc_uuid ); /* set the service class */ sdp_uuid16_create(&svc_class_uuid, SERIAL_PORT_SVCLASS_ID); svc_class_list = sdp_list_append(0, &svc_class_uuid); sdp_set_service_classes(&record, svc_class_list); /* set the Bluetooth profile information */ sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID); profile.version = 0x0100; profile_list = sdp_list_append(0, &profile); sdp_set_profile_descs(&record, profile_list); /* 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 ); /* register the RFCOMM channel for RFCOMM sockets */ 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 ); 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, svc_dsc); /* register the service record, */ if(sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; } end: // 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); sdp_list_free(svc_class_list, 0); sdp_list_free(profile_list, 0); return ret; }
static int add_service(sdp_session_t *session, uint32_t *handle, uint8_t rfcomm_channel) { int ret = 0; unsigned char service_uuid_int[] = CARBOT_BLUETOOTH_SDP_UUID; const char *service_name = "Carbot Soul"; const char *service_dsc = "General Purpose Android-Auto Interface"; const char *service_prov = "Ubergrund.com"; uuid_t root_uuid; uuid_t rfcomm_uuid, l2cap_uuid, svc_uuid; sdp_list_t *root_list; sdp_list_t *rfcomm_list = 0, *l2cap_list = 0, *proto_list = 0, *access_proto_list = 0, *service_list = 0; sdp_data_t *channel = 0; sdp_record_t *rec; // connect to the local SDP server, register the service record, and // disconnect if (!session) { logDebug("Bad local SDP session\n"); return -1; } rec = sdp_record_alloc(); // set the general service ID sdp_uuid128_create(&svc_uuid, &service_uuid_int); service_list = sdp_list_append(0, &svc_uuid); sdp_set_service_classes(rec, service_list); sdp_set_service_id(rec, 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(rec, 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); rfcomm_list = sdp_list_append(0, &rfcomm_uuid); channel = sdp_data_alloc(SDP_UINT8, &rfcomm_channel); 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(rec, access_proto_list); // set the name, provider, and description sdp_set_info_attr(rec, service_name, service_prov, service_dsc); ret = sdp_record_register(session, rec, 0); if (ret < 0) { logError("Service registration failed\n"); } else { *handle = rec->handle; } // 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(proto_list, 0); sdp_list_free(access_proto_list, 0); sdp_list_free(service_list, 0); sdp_record_free(rec); return ret; }
sdp_session_t* io_rfcomm_advertise(uint8_t ch, const char *name, const char *desc, const uint32_t *uuid128) { uuid_t root_uuid, rfcomm_uuid, svc_uuid, svc_class_uuid, l2cap_uuid; sdp_list_t *rfcomm_list = 0, *root_list = 0, *proto_list = 0, *access_proto_list = 0, *svc_class_list = 0, *profile_list = 0, *l2cap_list = 0; //*l2cap_list sdp_data_t *channel = 0; sdp_profile_desc_t profile; sdp_record_t record = { 0 }; sdp_session_t *session = 0; //set general service ID sdp_uuid128_create(&svc_uuid, &uuid128); sdp_set_service_id(&record, svc_uuid); // set the service class sdp_uuid16_create(&svc_class_uuid, SERIAL_PORT_SVCLASS_ID); svc_class_list = sdp_list_append(0, &svc_class_uuid); sdp_set_service_classes(&record, svc_class_list); // set the Bluetooth profile information sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID); profile.version = 0x0100; profile_list = sdp_list_append(0, &profile); sdp_set_profile_descs(&record, profile_list); // 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 ); // register rfcomm channel for rfcomm sockets sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); channel = sdp_data_alloc(SDP_UINT8, &ch); rfcomm_list = sdp_list_append( 0, &rfcomm_uuid ); sdp_list_append( rfcomm_list, channel ); sdp_list_append( proto_list, rfcomm_list ); access_proto_list = sdp_list_append(0, proto_list); sdp_set_access_protos(&record, access_proto_list); //set name, provider, description sdp_set_info_attr(&record, name, "", desc); //connect to local SDP server, register service record, and disconnect session = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, 0); 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; }
static sdp_record_t *hfp_ag_record(uint8_t ch, uint32_t feat) { sdp_list_t *svclass_id, *pfseq, *apseq, *root; uuid_t root_uuid, svclass_uuid, ga_svclass_uuid; uuid_t l2cap_uuid, rfcomm_uuid; sdp_profile_desc_t profile; sdp_list_t *aproto, *proto[2]; sdp_record_t *record; sdp_data_t *channel, *features; uint8_t netid = 0x01; uint16_t sdpfeat; sdp_data_t *network; record = sdp_record_alloc(); if (!record) return NULL; network = sdp_data_alloc(SDP_UINT8, &netid); if (!network) { sdp_record_free(record); return NULL; } sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(record, root); sdp_uuid16_create(&svclass_uuid, HANDSFREE_AGW_SVCLASS_ID); svclass_id = sdp_list_append(0, &svclass_uuid); sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID); svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid); sdp_set_service_classes(record, svclass_id); sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID); profile.version = 0x0105; pfseq = sdp_list_append(0, &profile); sdp_set_profile_descs(record, pfseq); sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); proto[0] = sdp_list_append(0, &l2cap_uuid); apseq = sdp_list_append(0, proto[0]); sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); proto[1] = sdp_list_append(0, &rfcomm_uuid); channel = sdp_data_alloc(SDP_UINT8, &ch); proto[1] = sdp_list_append(proto[1], channel); apseq = sdp_list_append(apseq, proto[1]); sdpfeat = (uint16_t) feat & 0xF; features = sdp_data_alloc(SDP_UINT16, &sdpfeat); sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features); aproto = sdp_list_append(0, apseq); sdp_set_access_protos(record, aproto); sdp_set_info_attr(record, "Hands-Free Audio Gateway", 0, 0); sdp_attr_add(record, SDP_ATTR_EXTERNAL_NETWORK, network); sdp_data_free(channel); sdp_list_free(proto[0], 0); sdp_list_free(proto[1], 0); sdp_list_free(apseq, 0); sdp_list_free(pfseq, 0); sdp_list_free(aproto, 0); sdp_list_free(root, 0); sdp_list_free(svclass_id, 0); return record; }
static sdp_record_t *server_record_new(const char *name, uint16_t id) { sdp_list_t *svclass, *pfseq, *apseq, *root, *aproto; uuid_t root_uuid, pan, l2cap, bnep; sdp_profile_desc_t profile[1]; sdp_list_t *proto[2]; sdp_data_t *v, *p; uint16_t psm = BNEP_PSM, version = 0x0100; uint16_t security_desc = (security ? 0x0001 : 0x0000); uint16_t net_access_type = 0xfffe; uint32_t max_net_access_rate = 0; const char *desc = "Network service"; sdp_record_t *record; record = sdp_record_alloc(); if (!record) return NULL; record->attrlist = NULL; record->pattern = NULL; switch (id) { case BNEP_SVC_NAP: sdp_uuid16_create(&pan, NAP_SVCLASS_ID); svclass = sdp_list_append(NULL, &pan); sdp_set_service_classes(record, svclass); sdp_uuid16_create(&profile[0].uuid, NAP_PROFILE_ID); profile[0].version = 0x0100; pfseq = sdp_list_append(NULL, &profile[0]); sdp_set_profile_descs(record, pfseq); sdp_set_info_attr(record, name, NULL, desc); sdp_attr_add_new(record, SDP_ATTR_NET_ACCESS_TYPE, SDP_UINT16, &net_access_type); sdp_attr_add_new(record, SDP_ATTR_MAX_NET_ACCESSRATE, SDP_UINT32, &max_net_access_rate); break; case BNEP_SVC_GN: sdp_uuid16_create(&pan, GN_SVCLASS_ID); svclass = sdp_list_append(NULL, &pan); sdp_set_service_classes(record, svclass); sdp_uuid16_create(&profile[0].uuid, GN_PROFILE_ID); profile[0].version = 0x0100; pfseq = sdp_list_append(NULL, &profile[0]); sdp_set_profile_descs(record, pfseq); sdp_set_info_attr(record, name, NULL, desc); break; case BNEP_SVC_PANU: sdp_uuid16_create(&pan, PANU_SVCLASS_ID); svclass = sdp_list_append(NULL, &pan); sdp_set_service_classes(record, svclass); sdp_uuid16_create(&profile[0].uuid, PANU_PROFILE_ID); profile[0].version = 0x0100; pfseq = sdp_list_append(NULL, &profile[0]); sdp_set_profile_descs(record, pfseq); sdp_set_info_attr(record, name, NULL, desc); break; default: sdp_record_free(record); return NULL; } sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(NULL, &root_uuid); sdp_set_browse_groups(record, root); sdp_uuid16_create(&l2cap, L2CAP_UUID); proto[0] = sdp_list_append(NULL, &l2cap); p = sdp_data_alloc(SDP_UINT16, &psm); proto[0] = sdp_list_append(proto[0], p); apseq = sdp_list_append(NULL, proto[0]); sdp_uuid16_create(&bnep, BNEP_UUID); proto[1] = sdp_list_append(NULL, &bnep); v = sdp_data_alloc(SDP_UINT16, &version); proto[1] = sdp_list_append(proto[1], v); /* Supported protocols */ { uint16_t ptype[] = { 0x0800, /* IPv4 */ 0x0806, /* ARP */ }; sdp_data_t *head, *pseq; int p; for (p = 0, head = NULL; p < 2; p++) { sdp_data_t *data = sdp_data_alloc(SDP_UINT16, &ptype[p]); if (head) sdp_seq_append(head, data); else head = data; } pseq = sdp_data_alloc(SDP_SEQ16, head); proto[1] = sdp_list_append(proto[1], pseq); } apseq = sdp_list_append(apseq, proto[1]); aproto = sdp_list_append(NULL, apseq); sdp_set_access_protos(record, aproto); add_lang_attr(record); sdp_attr_add_new(record, SDP_ATTR_SECURITY_DESC, SDP_UINT16, &security_desc); sdp_data_free(p); sdp_data_free(v); sdp_list_free(apseq, NULL); sdp_list_free(root, NULL); sdp_list_free(aproto, NULL); sdp_list_free(proto[0], NULL); sdp_list_free(proto[1], NULL); sdp_list_free(svclass, NULL); sdp_list_free(pfseq, NULL); return record; }
static int register_service_additional_protocols(sdp_record_t *rec, struct health_app *app) { int ret = -1; uuid_t l2cap_uuid, mcap_d_uuid; sdp_list_t *l2cap_list, *proto_list = NULL, *mcap_list = NULL; sdp_list_t *access_proto_list = NULL; sdp_data_t *psm = NULL; uint32_t dcpsm; GError *err = NULL; DBG(""); /* set l2cap information */ sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); l2cap_list = sdp_list_append(NULL, &l2cap_uuid); if (!l2cap_list) goto fail; dcpsm = mcap_get_data_psm(mcap, &err); if (err) goto fail; psm = sdp_data_alloc(SDP_UINT16, &dcpsm); if (!psm) goto fail; if (!sdp_list_append(l2cap_list, psm)) goto fail; proto_list = sdp_list_append(NULL, l2cap_list); if (!proto_list) goto fail; /* set mcap information */ sdp_uuid16_create(&mcap_d_uuid, MCAP_DATA_UUID); mcap_list = sdp_list_append(NULL, &mcap_d_uuid); if (!mcap_list) goto fail; if (!sdp_list_append(proto_list, mcap_list)) goto fail; /* attach protocol information to service record */ access_proto_list = sdp_list_append(NULL, proto_list); if (!access_proto_list) goto fail; sdp_set_add_access_protos(rec, access_proto_list); ret = 0; fail: sdp_list_free(l2cap_list, NULL); sdp_list_free(mcap_list, NULL); sdp_list_free(proto_list, NULL); sdp_list_free(access_proto_list, NULL); if (psm) sdp_data_free(psm); if (err) g_error_free(err); return ret; }
/* Allows this service to be discovered when running sdptool. For example, you can find this service * after starting it by running * * $ sdptool browse local * * (Adapted from http://www.btessentials.com/examples/bluez/sdp-register.c) * */ sdp_session_t *register_service(uint8_t rfcomm_channel) { /* A 128-bit number used to identify this service. The words are ordered from most to least * significant, but within each word, the octets are ordered from least to most significant. * For example, the UUID represneted by this array is 00001101-0000-1000-8000-00805F9B34FB. (The * hyphenation is a convention specified by the Service Discovery Protocol of the Bluetooth Core * Specification, but is not particularly important for this program.) * * This UUID is the Bluetooth Base UUID and is commonly used for simple Bluetooth applications. * Regardless of the UUID used, it must match the one that the Armatus Android app is searching * for. */ uint32_t svc_uuid_int[] = { 0x01110000, 0x00100000, 0x80000080, 0xFB349B5F }; const char *service_name = "Armatus Bluetooth server"; const char *svc_dsc = "A HERMIT server that interfaces with the Armatus Android app"; const char *service_prov = "Armatus"; 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; sdp_profile_desc_t profile; sdp_record_t record = { 0 }; sdp_session_t *session = 0; // set the general service ID sdp_uuid128_create(&svc_uuid, &svc_uuid_int); sdp_set_service_id(&record, svc_uuid); char str[256] = ""; sdp_uuid2strn(&svc_uuid, str, 256); printf("Registering UUID %s\n", str); // set the service class sdp_uuid16_create(&svc_class_uuid, SERIAL_PORT_SVCLASS_ID); svc_class_list = sdp_list_append(0, &svc_class_uuid); sdp_set_service_classes(&record, svc_class_list); // set the Bluetooth profile information sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID); profile.version = 0x0100; profile_list = sdp_list_append(0, &profile); sdp_set_profile_descs(&record, profile_list); // 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); // register the RFCOMM channel for RFCOMM sockets 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); 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, svc_dsc); // connect to the local SDP server, register the service record, // and disconnect session = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY); 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); sdp_list_free(svc_class_list, 0); sdp_list_free(profile_list, 0); return session; }
static sdp_record_t *panu_record(void) { sdp_list_t *svclass, *pfseq, *apseq, *root, *aproto; uuid_t root_uuid, panu, l2cap, bnep; sdp_profile_desc_t profile[1]; sdp_list_t *proto[2]; sdp_data_t *v, *p; uint16_t psm = BNEP_PSM, version = 0x0100; uint16_t security = 0x0001, type = 0xfffe; uint32_t rate = 0; const char *desc = "PAN User", *name = "Network Service"; sdp_record_t *record; uint16_t ptype[] = { 0x0800, /* IPv4 */ 0x0806, /* ARP */ }; sdp_data_t *head, *pseq, *data; record = sdp_record_alloc(); if (!record) return NULL; record->attrlist = NULL; record->pattern = NULL; sdp_uuid16_create(&panu, PANU_SVCLASS_ID); svclass = sdp_list_append(NULL, &panu); sdp_set_service_classes(record, svclass); sdp_uuid16_create(&profile[0].uuid, PANU_PROFILE_ID); profile[0].version = 0x0100; pfseq = sdp_list_append(NULL, &profile[0]); sdp_set_profile_descs(record, pfseq); sdp_set_info_attr(record, name, NULL, desc); sdp_attr_add_new(record, SDP_ATTR_NET_ACCESS_TYPE, SDP_UINT16, &type); sdp_attr_add_new(record, SDP_ATTR_MAX_NET_ACCESSRATE, SDP_UINT32, &rate); sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(NULL, &root_uuid); sdp_set_browse_groups(record, root); sdp_uuid16_create(&l2cap, L2CAP_UUID); proto[0] = sdp_list_append(NULL, &l2cap); p = sdp_data_alloc(SDP_UINT16, &psm); proto[0] = sdp_list_append(proto[0], p); apseq = sdp_list_append(NULL, proto[0]); sdp_uuid16_create(&bnep, BNEP_UUID); proto[1] = sdp_list_append(NULL, &bnep); v = sdp_data_alloc(SDP_UINT16, &version); proto[1] = sdp_list_append(proto[1], v); head = sdp_data_alloc(SDP_UINT16, &ptype[0]); data = sdp_data_alloc(SDP_UINT16, &ptype[1]); sdp_seq_append(head, data); pseq = sdp_data_alloc(SDP_SEQ16, head); proto[1] = sdp_list_append(proto[1], pseq); apseq = sdp_list_append(apseq, proto[1]); aproto = sdp_list_append(NULL, apseq); sdp_set_access_protos(record, aproto); sdp_add_lang_attr(record); sdp_attr_add_new(record, SDP_ATTR_SECURITY_DESC, SDP_UINT16, &security); sdp_data_free(p); sdp_data_free(v); sdp_list_free(apseq, NULL); sdp_list_free(root, NULL); sdp_list_free(aproto, NULL); sdp_list_free(proto[0], NULL); sdp_list_free(proto[1], NULL); sdp_list_free(svclass, NULL); sdp_list_free(pfseq, NULL); return record; }