Exemple #1
0
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;
}
Exemple #2
0
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;
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}
Exemple #5
0
/*
 * The service database state is an attribute of the service record
 * of the SDP server itself. This attribute is guaranteed to
 * change if any of the contents of the service repository
 * changes. This function updates the timestamp of value of
 * the svcDBState attribute
 * Set the SDP server DB. Simply a timestamp which is the marker
 * when the DB was modified.
 */
static void update_db_timestamp(void)
{
	if (fixed_dbts) {
		sdp_data_t *d = sdp_data_alloc(SDP_UINT32, &fixed_dbts);
		sdp_attr_replace(server, SDP_ATTR_SVCDB_STATE, d);
	} else {
		uint32_t dbts = sdp_get_time();
		sdp_data_t *d = sdp_data_alloc(SDP_UINT32, &dbts);
		sdp_attr_replace(server, SDP_ATTR_SVCDB_STATE, d);
	}
}
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;
}
Exemple #7
0
void register_device_id(const uint16_t vendor, const uint16_t product,
						const uint16_t version)
{
	const uint16_t spec = 0x0102, source = 0x0002;
	const uint8_t primary = 1;
	sdp_list_t *class_list, *group_list, *profile_list;
	uuid_t class_uuid, group_uuid;
	sdp_data_t *sdp_data, *primary_data, *source_data;
	sdp_data_t *spec_data, *vendor_data, *product_data, *version_data;
	sdp_profile_desc_t profile;
	sdp_record_t *record = sdp_record_alloc();

	info("Adding device id record for %04x:%04x", vendor, product);

	btd_manager_set_did(vendor, product, version);

	record->handle = sdp_next_handle();

	sdp_record_add(BDADDR_ANY, record);
	sdp_data = sdp_data_alloc(SDP_UINT32, &record->handle);
	sdp_attr_add(record, SDP_ATTR_RECORD_HANDLE, sdp_data);

	sdp_uuid16_create(&class_uuid, PNP_INFO_SVCLASS_ID);
	class_list = sdp_list_append(0, &class_uuid);
	sdp_set_service_classes(record, class_list);
	sdp_list_free(class_list, NULL);

	sdp_uuid16_create(&group_uuid, PUBLIC_BROWSE_GROUP);
	group_list = sdp_list_append(NULL, &group_uuid);
	sdp_set_browse_groups(record, group_list);
	sdp_list_free(group_list, NULL);

	sdp_uuid16_create(&profile.uuid, PNP_INFO_PROFILE_ID);
	profile.version = spec;
	profile_list = sdp_list_append(NULL, &profile);
	sdp_set_profile_descs(record, profile_list);
	sdp_list_free(profile_list, NULL);

	spec_data = sdp_data_alloc(SDP_UINT16, &spec);
	sdp_attr_add(record, 0x0200, spec_data);

	vendor_data = sdp_data_alloc(SDP_UINT16, &vendor);
	sdp_attr_add(record, 0x0201, vendor_data);

	product_data = sdp_data_alloc(SDP_UINT16, &product);
	sdp_attr_add(record, 0x0202, product_data);

	version_data = sdp_data_alloc(SDP_UINT16, &version);
	sdp_attr_add(record, 0x0203, version_data);

	primary_data = sdp_data_alloc(SDP_BOOL, &primary);
	sdp_attr_add(record, 0x0204, primary_data);

	source_data = sdp_data_alloc(SDP_UINT16, &source);
	sdp_attr_add(record, 0x0205, source_data);

	update_db_timestamp();
}
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(&gt_uuid, GENERIC_TELEPHONY_SVCLASS_ID);
	svclass_id = sdp_list_append(svclass_id, &gt_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;
}
Exemple #9
0
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;
}
Exemple #10
0
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;
}
Exemple #11
0
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;
}
Exemple #12
0
/*
 * The SDP server must present its own service record to
 * the service repository. This can be accessed by service
 * discovery clients. This method constructs a service record
 * and stores it in the repository
 */
void register_server_service(void)
{
	sdp_list_t *classIDList;
	uuid_t classID;
	void **versions, **versionDTDs;
	uint8_t dtd;
	sdp_data_t *pData;
	int i;

	server = sdp_record_alloc();
	server->pattern = NULL;

	/* Force the record to be SDP_SERVER_RECORD_HANDLE */
	server->handle = SDP_SERVER_RECORD_HANDLE;

	sdp_record_add(BDADDR_ANY, server);
	sdp_attr_add(server, SDP_ATTR_RECORD_HANDLE,
				sdp_data_alloc(SDP_UINT32, &server->handle));

	sdp_uuid16_create(&classID, SDP_SERVER_SVCLASS_ID);
	classIDList = sdp_list_append(0, &classID);
	sdp_set_service_classes(server, classIDList);
	sdp_list_free(classIDList, 0);

	/*
	 * Set the version numbers supported, these are passed as arguments
	 * to the server on command line. Now defaults to 1.0
	 * Build the version number sequence first
	 */
	versions = malloc(sdpServerVnumEntries * sizeof(void *));
	versionDTDs = malloc(sdpServerVnumEntries * sizeof(void *));
	dtd = SDP_UINT16;
	for (i = 0; i < sdpServerVnumEntries; i++) {
		uint16_t *version = malloc(sizeof(uint16_t));
		*version = sdpVnumArray[i].major;
		*version = (*version << 8);
		*version |= sdpVnumArray[i].minor;
		versions[i] = version;
		versionDTDs[i] = &dtd;
	}
	pData = sdp_seq_alloc(versionDTDs, versions, sdpServerVnumEntries);
	for (i = 0; i < sdpServerVnumEntries; i++)
		free(versions[i]);
	free(versions);
	free(versionDTDs);
	sdp_attr_add(server, SDP_ATTR_VERSION_NUM_LIST, pData);

	update_db_timestamp();
}
Exemple #13
0
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;
}
Exemple #14
0
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;
}
Exemple #15
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;
}
Exemple #16
0
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;
}
Exemple #17
0
int add_record_to_server(const bdaddr_t *src, sdp_record_t *rec)
{
	sdp_data_t *data;
	sdp_list_t *pattern;

	if (rec->handle == 0xffffffff) {
		rec->handle = sdp_next_handle();
		if (rec->handle < 0x10000)
			return -ENOSPC;
	} else {
		if (sdp_record_find(rec->handle))
			return -EEXIST;
	}

	DBG("Adding record with handle 0x%05x", rec->handle);

	sdp_record_add(src, rec);

	data = sdp_data_alloc(SDP_UINT32, &rec->handle);
	sdp_attr_replace(rec, SDP_ATTR_RECORD_HANDLE, data);

	if (sdp_data_get(rec, SDP_ATTR_BROWSE_GRP_LIST) == NULL) {
		uuid_t uuid;
		sdp_uuid16_create(&uuid, PUBLIC_BROWSE_GROUP);
		sdp_pattern_add_uuid(rec, &uuid);
	}

	for (pattern = rec->pattern; pattern; pattern = pattern->next) {
		char uuid[32];

		if (pattern->data == NULL)
			continue;

		sdp_uuid2strn((uuid_t *) pattern->data, uuid, sizeof(uuid));
		DBG("Record pattern UUID %s", uuid);
	}

	update_db_timestamp();

	return 0;
}
Exemple #18
0
void register_public_browse_group(void)
{
	sdp_list_t *browselist;
	uuid_t bgscid, pbgid;
	sdp_data_t *sdpdata;
	sdp_record_t *browse = sdp_record_alloc();

	browse->handle = SDP_SERVER_RECORD_HANDLE + 1;

	sdp_record_add(BDADDR_ANY, browse);
	sdpdata = sdp_data_alloc(SDP_UINT32, &browse->handle);
	sdp_attr_add(browse, SDP_ATTR_RECORD_HANDLE, sdpdata);

	sdp_uuid16_create(&bgscid, BROWSE_GRP_DESC_SVCLASS_ID);
	browselist = sdp_list_append(0, &bgscid);
	sdp_set_service_classes(browse, browselist);
	sdp_list_free(browselist, 0);

	sdp_uuid16_create(&pbgid, PUBLIC_BROWSE_GROUP);
	sdp_attr_add_new(browse, SDP_ATTR_GROUP_ID,
				SDP_UUID16, &pbgid.value.uuid16);
}
Exemple #19
0
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;
}
Exemple #20
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;
}
Exemple #21
0
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;
}
Exemple #22
0
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;
}
Exemple #23
0
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;
}
Exemple #24
0
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;
}
Exemple #25
0
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;
}
Exemple #26
0
/*
 * Add the newly created service record to the service repository
 */
int service_register_req(sdp_req_t *req, sdp_buf_t *rsp)
{
	int scanned = 0;
	sdp_data_t *handle;
	uint8_t *p = req->buf + sizeof(sdp_pdu_hdr_t);
	int bufsize = req->len - sizeof(sdp_pdu_hdr_t);
	sdp_record_t *rec;

	req->flags = *p++;
	if (req->flags & SDP_DEVICE_RECORD) {
		bacpy(&req->device, (bdaddr_t *) p);
		p += sizeof(bdaddr_t);
		bufsize -= sizeof(bdaddr_t);
	}

	/* save image of PDU: we need it when clients request this attribute */
	rec = extract_pdu_server(&req->device, p, bufsize, 0xffffffff, &scanned);
	if (!rec)
		goto invalid;

	if (rec->handle == 0xffffffff) {
		rec->handle = sdp_next_handle();
		if (rec->handle < 0x10000) {
			sdp_record_free(rec);
			goto invalid;
		}
	} else {
		if (sdp_record_find(rec->handle)) {
			/* extract_pdu_server will add the record handle
			 * if it is missing. So instead of failing, skip
			 * the record adding to avoid duplication. */
			goto success;
		}
	}

	sdp_record_add(&req->device, rec);
	if (!(req->flags & SDP_RECORD_PERSIST))
		sdp_svcdb_set_collectable(rec, req->sock);

	handle = sdp_data_alloc(SDP_UINT32, &rec->handle);
	sdp_attr_replace(rec, SDP_ATTR_RECORD_HANDLE, handle);

success:
	/* if the browse group descriptor is NULL,
	 * ensure that the record belongs to the ROOT group */
	if (sdp_data_get(rec, SDP_ATTR_BROWSE_GRP_LIST) == NULL) {
		uuid_t uuid;
		sdp_uuid16_create(&uuid, PUBLIC_BROWSE_GROUP);
		sdp_pattern_add_uuid(rec, &uuid);
	}

	update_db_timestamp();

	/* Build a rsp buffer */
	bt_put_be32(rec->handle, rsp->data);
	rsp->data_size = sizeof(uint32_t);

	return 0;

invalid:
	bt_put_be16(SDP_INVALID_SYNTAX, rsp->data);
	rsp->data_size = sizeof(uint16_t);

	return -1;
}
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;
}
Exemple #28
0
static void element_start(GMarkupParseContext *context,
		const gchar *element_name, const gchar **attribute_names,
		const gchar **attribute_values, gpointer user_data, GError **err)
{
	struct context_data *ctx_data = user_data;

	if (!strcmp(element_name, "record"))
		return;

	if (!strcmp(element_name, "attribute")) {
		int i;
		for (i = 0; attribute_names[i]; i++) {
			if (!strcmp(attribute_names[i], "id")) {
				ctx_data->attr_id = strtol(attribute_values[i], 0, 0);
				break;
			}
		}
		DBG("New attribute 0x%04x", ctx_data->attr_id);
		return;
	}

	if (ctx_data->stack_head) {
		struct sdp_xml_data *newelem = sdp_xml_data_alloc();
		newelem->next = ctx_data->stack_head;
		ctx_data->stack_head = newelem;
	} else {
		ctx_data->stack_head = sdp_xml_data_alloc();
		ctx_data->stack_head->next = NULL;
	}

	if (!strcmp(element_name, "sequence"))
		ctx_data->stack_head->data = sdp_data_alloc(SDP_SEQ8, NULL);
	else if (!strcmp(element_name, "alternate"))
		ctx_data->stack_head->data = sdp_data_alloc(SDP_ALT8, NULL);
	else {
		int i;
		/* Parse value, name, encoding */
		for (i = 0; attribute_names[i]; i++) {
			if (!strcmp(attribute_names[i], "value")) {
				int curlen = strlen(ctx_data->stack_head->text);
				int attrlen = strlen(attribute_values[i]);

				/* Ensure we're big enough */
				while ((curlen + 1 + attrlen) > ctx_data->stack_head->size) {
					sdp_xml_data_expand(ctx_data->stack_head);
				}

				memcpy(ctx_data->stack_head->text + curlen,
						attribute_values[i], attrlen);
				ctx_data->stack_head->text[curlen + attrlen] = '\0';
			}

			if (!strcmp(attribute_names[i], "encoding")) {
				if (!strcmp(attribute_values[i], "hex"))
					ctx_data->stack_head->type = 1;
			}

			if (!strcmp(attribute_names[i], "name")) {
				ctx_data->stack_head->name = strdup(attribute_values[i]);
			}
		}

		ctx_data->stack_head->data = sdp_xml_parse_datatype(element_name,
				ctx_data->stack_head, ctx_data->record);

		if (ctx_data->stack_head->data == NULL)
			error("Can't parse element %s", element_name);
	}
}
/* 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;
}
Exemple #30
0
/*
 * dosdpregistration -	Care for the proper SDP record sent to the "sdpd"
 *			so that other BT devices can discover the HID service
 * Parameters: none; Return value: 0 = OK, >0 = failure
 */
int	dosdpregistration ( void )
{
	sdp_record_t	record;
	sdp_session_t	*session;
        sdp_list_t	*svclass_id,
			*pfseq,
			*apseq,
			*root;
	uuid_t		root_uuid,
			hidkb_uuid,
			l2cap_uuid,
			hidp_uuid;
        sdp_profile_desc_t	profile[1];
        sdp_list_t	*aproto,
			*proto[3];
	sdp_data_t	*psm,
			*lang_lst,
			*lang_lst2,
			*hid_spec_lst,
			*hid_spec_lst2;
        void		*dtds[2],
			*values[2],
			*dtds2[2],
			*values2[2];
        int		i,
			leng[2];
        uint8_t		dtd=SDP_UINT16,
			dtd2=SDP_UINT8,
			dtd_data=SDP_TEXT_STR8,
			hid_spec_type=0x22;
        uint16_t	hid_attr_lang[]={0x409, 0x100},
			ctrl=PSMHIDCTL,
			intr=PSMHIDINT,
			hid_attr[]={0x100, 0x111, 0x40, 0x00, 0x01, 0x01},
			// Assigned to SDP 0x200...0x205 - see HID SPEC for
			// details. Those values seem to work fine...
			// "it\'s a kind of magic" numbers.
			hid_attr2[]={0x100, 0x0};

	// Connect to SDP server on localhost, to publish service information
	session = sdp_connect ( BDADDR_ANY, BDADDR_LOCAL, 0 );
	if ( ! session )
	{
		fprintf ( stderr, "Failed to connect to SDP server: %s\n",
				strerror ( errno ) );
		return	1;
	}
        memset(&record, 0, sizeof(sdp_record_t));
        record.handle = 0xffffffff;
	// With 0xffffffff, we get assigned the first free record >= 0x10000
	// Make HID service visible (add to PUBLIC BROWSE GROUP)
        sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
        root = sdp_list_append(0, &root_uuid);
        sdp_set_browse_groups(&record, root);
	// Language Information to be added
        add_lang_attr(&record);
	// The descriptor for the keyboard
        sdp_uuid16_create(&hidkb_uuid, HID_SVCLASS_ID);
        svclass_id = sdp_list_append(0, &hidkb_uuid);
        sdp_set_service_classes(&record, svclass_id);
	// And information about the HID profile used
        sdp_uuid16_create(&profile[0].uuid, HIDP_UUID /*HID_PROFILE_ID*/);
        profile[0].version = 0x0100;
        pfseq = sdp_list_append(0, profile);
        sdp_set_profile_descs(&record, pfseq);
	// We are using L2CAP, so add an info about that
        sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
        proto[1] = sdp_list_append(0, &l2cap_uuid);
        psm = sdp_data_alloc(SDP_UINT16, &ctrl);
        proto[1] = sdp_list_append(proto[1], psm);
        apseq = sdp_list_append(0, proto[1]);
	// And about our purpose, the HID protocol data transfer
        sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
        proto[2] = sdp_list_append(0, &hidp_uuid);
        apseq = sdp_list_append(apseq, proto[2]);
        aproto = sdp_list_append(0, apseq);
        sdp_set_access_protos(&record, aproto);
        proto[1] = sdp_list_append(0, &l2cap_uuid);
        psm = sdp_data_alloc(SDP_UINT16, &intr);
        proto[1] = sdp_list_append(proto[1], psm);
        apseq = sdp_list_append(0, proto[1]);
        sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
        proto[2] = sdp_list_append(0, &hidp_uuid);
        apseq = sdp_list_append(apseq, proto[2]);
        aproto = sdp_list_append(0, apseq);
        sdp_set_add_access_protos(&record, aproto);
	// Set service name, description
        sdp_set_info_attr(&record, HIDINFO_NAME, HIDINFO_PROV, HIDINFO_DESC);
	// Add a few HID-specifid pieces of information
        // See the HID spec for details what those codes 0x200+something
	// are good for... we send a fixed set of info that seems to work
        sdp_attr_add_new(&record, SDP_ATTR_HID_DEVICE_RELEASE_NUMBER,
                                        SDP_UINT16, &hid_attr[0]); /* Opt */
        sdp_attr_add_new(&record, SDP_ATTR_HID_PARSER_VERSION,
                                        SDP_UINT16, &hid_attr[1]); /* Mand */
        sdp_attr_add_new(&record, SDP_ATTR_HID_DEVICE_SUBCLASS,
                                        SDP_UINT8, &hid_attr[2]); /* Mand */
        sdp_attr_add_new(&record, SDP_ATTR_HID_COUNTRY_CODE,
                                        SDP_UINT8, &hid_attr[3]); /* Mand */
        sdp_attr_add_new(&record, SDP_ATTR_HID_VIRTUAL_CABLE,
                                  SDP_BOOL, &hid_attr[4]); /* Mand */
        sdp_attr_add_new(&record, SDP_ATTR_HID_RECONNECT_INITIATE,
                                  SDP_BOOL, &hid_attr[5]); /* Mand */
	// Add the HID descriptor (describing the virtual device) as code
	// SDP_ATTR_HID_DESCRIPTOR_LIST (0x206 IIRC)
        dtds[0] = &dtd2;
        values[0] = &hid_spec_type;
	dtd_data= SDPRECORD_BYTES <= 255 ? SDP_TEXT_STR8 : SDP_TEXT_STR16 ;
        dtds[1] = &dtd_data;
        values[1] = (uint8_t *) SDPRECORD;
        leng[0] = 0;
        leng[1] = SDPRECORD_BYTES;
        hid_spec_lst = sdp_seq_alloc_with_length(dtds, values, leng, 2);
        hid_spec_lst2 = sdp_data_alloc(SDP_SEQ8, hid_spec_lst);
        sdp_attr_add(&record, SDP_ATTR_HID_DESCRIPTOR_LIST, hid_spec_lst2);
	// and continue adding further data bytes for 0x206+x values
        for (i = 0; i < sizeof(hid_attr_lang) / 2; i++) {
                dtds2[i] = &dtd;
                values2[i] = &hid_attr_lang[i];
        }
        lang_lst = sdp_seq_alloc(dtds2, values2, sizeof(hid_attr_lang) / 2);
        lang_lst2 = sdp_data_alloc(SDP_SEQ8, lang_lst);
        sdp_attr_add(&record, SDP_ATTR_HID_LANG_ID_BASE_LIST, lang_lst2);
	sdp_attr_add_new ( &record, SDP_ATTR_HID_PROFILE_VERSION,
			SDP_UINT16, &hid_attr2[0] );
	sdp_attr_add_new ( &record, SDP_ATTR_HID_BOOT_DEVICE,
			SDP_UINT16, &hid_attr2[1] );
	// Submit our IDEA of a SDP record to the "sdpd"
        if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {
                fprintf ( stderr, "Service Record registration failed\n" );
                return -1;
        }
	// Store the service handle retrieved from there for reference (i.e.,
	// deleting the service info when this program terminates)
	sdphandle = record.handle;
        fprintf ( stdout, "HID keyboard/mouse service registered\n" );
        return 0;
}