コード例 #1
0
ファイル: rfcomm.c プロジェクト: bernard-xl/pi-io
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;
}
コード例 #2
0
ファイル: hidclient.c プロジェクト: AlexandreTK/hidclient
/*
 * 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;
}
コード例 #3
0
ファイル: avrcp.c プロジェクト: mjbshaw/bluez
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;
}
コード例 #4
0
ファイル: sdp_register.c プロジェクト: atwilc3000/sample
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;
}
コード例 #5
0
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;
}
コード例 #6
0
ファイル: sdp.c プロジェクト: jirislaby/L2cap
int get_sdp_device_info(const bdaddr_t *src, const bdaddr_t *dst, struct hidp_connadd_req *req)
{
	struct sockaddr_l2 addr;
	socklen_t addrlen;
	bdaddr_t bdaddr;
	uint32_t range = 0x0000ffff;
	sdp_session_t *s;
	sdp_list_t *search, *attrid, *pnp_rsp;
	sdp_record_t *rec;
	sdp_data_t *pdlist;
	uuid_t svclass;
	int err;

	s = sdp_connect(src, dst, SDP_RETRY_IF_BUSY | SDP_WAIT_ON_CLOSE);
	if (!s)
		return -1;

	sdp_uuid16_create(&svclass, PNP_INFO_SVCLASS_ID);
	search = sdp_list_append(NULL, &svclass);
	attrid = sdp_list_append(NULL, &range);

	err = sdp_service_search_attr_req(s, search,
					SDP_ATTR_REQ_RANGE, attrid, &pnp_rsp);

	sdp_list_free(search, NULL);
	sdp_list_free(attrid, NULL);

	memset(&addr, 0, sizeof(addr));
	addrlen = sizeof(addr);

	if (getsockname(s->sock, (struct sockaddr *) &addr, &addrlen) < 0)
		bacpy(&bdaddr, src);
	else
		bacpy(&bdaddr, &addr.l2_bdaddr);

	sdp_close(s);

	if (err)
		return -1;

	if (pnp_rsp) {
		rec = (sdp_record_t *) pnp_rsp->data;

		pdlist = sdp_data_get(rec, 0x0201);
		req->vendor = pdlist ? pdlist->val.uint16 : 0x0000;

		pdlist = sdp_data_get(rec, 0x0202);
		req->product = pdlist ? pdlist->val.uint16 : 0x0000;

		pdlist = sdp_data_get(rec, 0x0203);
		req->version = pdlist ? pdlist->val.uint16 : 0x0000;

		sdp_record_free(rec);
	}

	req->parser = 0x0100;
	req->subclass = 0xc0;
	req->country = 0;

	if (bacmp(&bdaddr, BDADDR_ANY))
		store_device_info(&bdaddr, dst, req);

	return 0;
}
コード例 #7
0
ファイル: hdp_util.c プロジェクト: AlanApter/steamlink-sdk
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;
}
コード例 #8
0
int register_record(int descriptor_is_relative){


		// Connect to to local SDP-Servicer on localhost, to publish
		// the new service record.

		// Session will be established.
		sdp_session_t *session;

		session = sdp_connect ( BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY );

			if ( ! session )
			{

				//	LOGCAT:
				__android_log_print(ANDROID_LOG_DEBUG, TAG, "SDP: Connection to SDP failed.");

				return CODE_SDP_SESSION_FAILED;
			}

				//	LOGCAT:
				__android_log_print(ANDROID_LOG_DEBUG, TAG, "SDP: Connection to SDP established.");

				//	Service record, to be included in the registry of the SDP-Server
				sdp_record_t record;

				//	To create the record, several lists must be put together
				sdp_list_t *languages, *service_class_id, *profile_sequence, *access_protocol_sequence, *root_list, *access_protocol, *protocol_list[3];

				//	The uuid_t data type is used to represent the 128-bit UUID that
				//	is used as un universal unique identifier. SEE THE THESIS, SUBSECTION 2.2.2
				uuid_t root_uuid, hid_uuid, l2cap_uuid, hidp_uuid;

				//	BluetoothProfileDescriptorList. SEE THE THESIS, SUBSECTION 4.2.6
				sdp_profile_desc_t sdp_profile[1];

				//	LanguageBaseAttributeIDList, SEE THE THESIS, SUBSECTION 4.2.4
				sdp_lang_attr_t base_language;

				//	The sdp_data_t structure stores information in a service record
				sdp_data_t *psm, *hid_descriptor_list, *hid_descriptor_formatted_list, *language_base_list, *language_base_formatted_list;

				//	SDP-specific types: 8- and 16- bit unsigned integers and a 8-bit string
				uint8_t data_type_uint8 	= SDP_UINT8;
				uint8_t data_type_uint16 	= SDP_UINT16;
				uint8_t data_type_str8	 	= SDP_TEXT_STR8;


				int length[2];

				//	arrays used to form the sdp specific strcuture of sequence attribites: descriptor and language base
				void *data_types[2] , *descriptor_array[2], *language_base_array[2];

				memset(&record, 0, sizeof(sdp_record_t));

				//	Assigning the Record Handle, SEE THE THESIS, SUBSECTION 4.2.2
				record.handle = handle;

				// Putting together attributes, common to all services.
				// SEE THE THESIS, SECTION 4.2

			    // Setting the Browse Group and making
				// the service record publicly available.
				// SEE THE THESIS, SUBSECTION 4.2.3
			    sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
			    root_list = sdp_list_append(0, &root_uuid);
			    sdp_set_browse_groups( &record, root_list );


				// The LanguageBaseAttributeIDList
			    // SEE THE THESIS, SUBSECTION 4.2.4
				base_language.code_ISO639 = (0x65 << 8) | 0x6e;
				base_language.base_offset = SDP_PRIMARY_LANG_BASE;
				base_language.encoding = 106;

				languages = sdp_list_append(0, &base_language);
				sdp_set_lang_attr(&record, languages);
				sdp_list_free(languages, 0);


				//	The ServiceClassIDList
				//	SEE THE THESIS, SUBSECTION 4.2.1
				sdp_uuid16_create(&hid_uuid, HID_SVCLASS_ID);
				service_class_id = sdp_list_append(0, &hid_uuid);
				sdp_set_service_classes(&record, service_class_id);

				// The BluetoothProfileDescriptorList
				// SEE THE THESIS, SUBSECTION 4.2.6
				sdp_uuid16_create(&sdp_profile[0].uuid, HID_PROFILE_ID);
				sdp_profile[0].version = 0x0100;
				profile_sequence = sdp_list_append(0, sdp_profile);
				sdp_set_profile_descs(&record, profile_sequence);


				// The ProtocolDescriptorList
				// SEE THE THESIS, SUBSECTION 4.2.5

				//	We set information about:

				//	A) Control Channel ->
				//	B) Interruption Channel

				//	We use the protocol_list to bind information
				//	about L2CAP and HID stack level

				//	A) Control Channel (PSM: 0x11)
				// 	1) Set info on L2CAP
				sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
				protocol_list[1] = sdp_list_append(0, &l2cap_uuid);
				psm = sdp_data_alloc(SDP_UINT16, &control_channel_psm);
				protocol_list[1] = sdp_list_append(protocol_list[1], psm);
				access_protocol_sequence = sdp_list_append(0, protocol_list[1]);
				// 	2) Set info on HID
				sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
				protocol_list[2] = sdp_list_append(0, &hidp_uuid);
				access_protocol_sequence = sdp_list_append(access_protocol_sequence, protocol_list[2]);
				// bind to DecriptorList
				access_protocol = sdp_list_append(0, access_protocol_sequence);
				sdp_set_access_protos(&record, access_protocol);

				//	B) Interruption Channel (PSM: 0x13)
				// 	1) Set info on L2CAP
				protocol_list[1] = sdp_list_append(0, &l2cap_uuid);
				psm = sdp_data_alloc(SDP_UINT16, &interruption_channel_psm);
				protocol_list[1] = sdp_list_append(protocol_list[1], psm);
				access_protocol_sequence = sdp_list_append(0, protocol_list[1]);
				// 	2) Set info on HID
				sdp_uuid16_create(&hidp_uuid, HIDP_UUID);
				protocol_list[2] = sdp_list_append(0, &hidp_uuid);
				access_protocol_sequence = sdp_list_append(access_protocol_sequence, protocol_list[2]);

				access_protocol = sdp_list_append(0, access_protocol_sequence);
				sdp_set_add_access_protos(&record, access_protocol);



				//	Setting the information on device, author and service,
				//	throuth the human-readable attributes
				//  SEE THE THESIS, SUBSECTION 4.2.4
				sdp_set_info_attr(&record, SERVICE_NAME, SERVICE_INFO, AUTHOR_INFO);

				// After putting together the attributes, common to all services,
				// we bind the attributes that are specific to the HID service.
				// SEE THE THESIS, SECTION 4.3

				//	Adding all HID attributes (mandatory or optional)
				//	explained in the THESIS (4.3.1 - 4.3.13)

				//  SEE THE THESIS, SUBSECTION 4.3.1
				if(descriptor_is_relative){

					sdp_attr_add_new(	&record,
										SDP_ATTR_HID_DEVICE_RELEASE_NUMBER,
										SDP_UINT16,
										&attr_release_number_mouse_keyboard);

				}else{

					sdp_attr_add_new(	&record,
										SDP_ATTR_HID_DEVICE_RELEASE_NUMBER,
										SDP_UINT16,
										&attr_release_number_pointer_keyboard);

				}



					//	 SEE THE THESIS, SUBSECTION 4.3.2
					sdp_attr_add_new(	&record,
										SDP_ATTR_HID_PARSER_VERSION,
										SDP_UINT16,
										&attr_parser_version);

					//  SEE THE THESIS, SUBSECTION 4.3.3
					sdp_attr_add_new(	&record,
										SDP_ATTR_HID_DEVICE_SUBCLASS,
										SDP_UINT8,
										&attr_device_subclass);

					//  SEE THE THESIS, SUBSECTION 4.3.4
					sdp_attr_add_new(	&record,
										SDP_ATTR_HID_COUNTRY_CODE,
										SDP_UINT8,
										&attr_country_code);

					//  SEE THE THESIS, SUBSECTION 4.3.5
					sdp_attr_add_new(	&record,
										SDP_ATTR_HID_VIRTUAL_CABLE,
										SDP_BOOL,
										&attr_virtual_cable);

					//  SEE THE THESIS, SUBSECTION 4.3.6
					sdp_attr_add_new(	&record,
										SDP_ATTR_HID_RECONNECT_INITIATE,
										SDP_BOOL,
										&attr_reconnect_initiate);


					//	SEE THE THESIS, SUBSECTION 4.3.13

					//	Adding the HIDDescriptorList attribute is more complex,
					//  thus it is data sequence.
					//
					//	The attribute contains two things:
					// 	A) The descriptor type as unsigned integer (In our case it is a report descriptor)
					//  B) The two descriptors as string sequence (keyboard + mouse or keyboard + pointer)

					data_types[0] = &data_type_uint8;
					data_types[1] = &data_type_str8;

					// We check the descriptor_is_realtive value to
					// find out, if the keyboard + mouse or keyboard + pointer
					// service description is to be added.
					if(descriptor_is_relative){

					descriptor_array[0] = &hid_descriptor_type;
					descriptor_array[1] =(uint8_t *) attr_hid_descriptor_relative;
					length[0] = 0;
					length[1] = sizeof(attr_hid_descriptor_relative);

					}else{

					descriptor_array[0] = &hid_descriptor_type;
					descriptor_array[1] =(uint8_t *) attr_hid_descriptor_absolute;
					length[0] = 0;
					length[1] = sizeof(attr_hid_descriptor_absolute);

					}
					//	We bind the array containing the type and the array containing the values
					//  with the  sdp_seq_alloc_with_length function
					hid_descriptor_list = sdp_seq_alloc_with_length( data_types, descriptor_array, length, 2 );

					//	The newly created array contains all information, so it is used to create
					//  the list from the right SDP-specific type (SDP_SEQ8)
					hid_descriptor_formatted_list = sdp_data_alloc( SDP_SEQ8, hid_descriptor_list );
					//	Finally the list is added as un SDP-attribute
					sdp_attr_add( &record, SDP_ATTR_HID_DESCRIPTOR_LIST, hid_descriptor_formatted_list );
					// Done!

					//	The same is also done with the HIDLANGIDBaseList
					//	SEE THE THESIS, SUBSECTION 4.3.12
					data_types[0] = &data_type_uint16;
					data_types[1] = &data_type_uint16;
					language_base_array[0] = &attr_language_base[0];
					language_base_array[1] = &attr_language_base[1];

					//sizeof(attr_language_base) is devided by two, since values are 16-bit integers (not 8-bit like with the HIDDecriptorList)
					language_base_list = sdp_seq_alloc(data_types, language_base_array, sizeof(attr_language_base) / 2);
					language_base_formatted_list = sdp_data_alloc(SDP_SEQ8, language_base_list);
					sdp_attr_add(&record, SDP_ATTR_HID_LANG_ID_BASE_LIST, language_base_formatted_list);
					// Done!

					//	 SEE THE THESIS, SUBSECTION 4.3.7
					sdp_attr_add_new(	&record,
										SDP_ATTR_HID_SDP_DISABLE,
										SDP_BOOL,
										&attr_sdp_disable);

					//	 SEE THE THESIS, SUBSECTION 4.3.8
					sdp_attr_add_new(	&record,
										SDP_ATTR_HID_BATTERY_POWER,
										SDP_BOOL,
										&attr_battery_power);

					//	 SEE THE THESIS, SUBSECTION 4.3.9
					sdp_attr_add_new(	&record,
										SDP_ATTR_HID_REMOTE_WAKEUP,
										SDP_BOOL,
										&attr_remote_wake);

					//	 SEE THE THESIS, SUBSECTION 4.3.10
					sdp_attr_add_new(	&record,
										SDP_ATTR_HID_PROFILE_VERSION,
										SDP_UINT16,
										&attr_profile_version);

//					sdp_attr_add_new(	&record,
//										SDP_ATTR_HID_SUPERVISION_TIMEOUT,
//										SDP_UINT16,
//										&attr_supervision_timeout);

					//	 SEE THE THESIS, SUBSECTION 4.3.6
					sdp_attr_add_new(	&record,
										SDP_ATTR_HID_NORMALLY_CONNECTABLE,
										SDP_BOOL,
										&attr_normally_connectable);

					//	 SEE THE THESIS, SUBSECTION 4.3.11
					sdp_attr_add_new(	&record,
										SDP_ATTR_HID_BOOT_DEVICE,
										SDP_BOOL,
										&attr_boot_device);


					//	At last the record is good to go and could be added to the sdp registry!
					if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) {

						//	LOGCAT:
						__android_log_print(ANDROID_LOG_DEBUG, TAG, "SDP: Registration of new record failed.");
						return CODE_RECORD_REGISTRATION_FAILED;

					}

					//	LOGCAT:
					__android_log_print(ANDROID_LOG_DEBUG, TAG, "SDP: Registration of new record successful.");

			sdp_close(session);

			return CODE_RECORD_REGISTERED;
	
}
コード例 #9
0
ファイル: health.c プロジェクト: ghent360/bluez
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;
}
コード例 #10
0
ファイル: bluetooth.c プロジェクト: Keerecles/AOA-Proxy
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;
}
コード例 #11
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;
}
コード例 #12
0
ファイル: main.cpp プロジェクト: Sagaragrawal/2gisqt5android
int main(int argc, char **argv)
{
    if (argc != 3) {
        usage();
        return RETURN_USAGE;
    }

    fprintf(stderr, "SDP for %s %s\n", argv[1], argv[2]);

    bdaddr_t remote;
    bdaddr_t local;
    int result = str2ba(argv[1], &remote);
    if (result < 0) {
        fprintf(stderr, "Invalid remote address: %s\n", argv[1]);
        return RETURN_INVALPARAM;
    }

    result = str2ba(argv[2], &local);
    if (result < 0) {
        fprintf(stderr, "Invalid local address: %s\n", argv[2]);
        return RETURN_INVALPARAM;
    }

    sdp_session_t *session = sdp_connect( &local, &remote, SDP_RETRY_IF_BUSY);
    if (!session) {
        //try one more time if first time failed
        session = sdp_connect( &local, &remote, SDP_RETRY_IF_BUSY);
    }

    if (!session) {
        fprintf(stderr, "Cannot establish sdp session\n");
        return RETURN_SDP_ERROR;
    }

    // set the filter for service matches
    uuid_t publicBrowseGroupUuid;
    sdp_uuid16_create(&publicBrowseGroupUuid, PUBLIC_BROWSE_GROUP);
    sdp_list_t *serviceFilter;
    serviceFilter = sdp_list_append(0, &publicBrowseGroupUuid);

    uint32_t attributeRange = 0x0000ffff; //all attributes
    sdp_list_t *attributes;
    attributes = sdp_list_append(0, &attributeRange);

    sdp_list_t *sdpResults, *previous;
    result = sdp_service_search_attr_req(session, serviceFilter,
                                         SDP_ATTR_REQ_RANGE,
                                         attributes, &sdpResults);
    sdp_list_free(attributes, 0);
    sdp_list_free(serviceFilter, 0);

    if (result != 0) {
        fprintf(stderr, "sdp_service_search_attr_req failed\n");
        sdp_close(session);
        return RETURN_SDP_ERROR;
    }

    QByteArray total;
    while (sdpResults) {
        sdp_record_t *record = (sdp_record_t *) sdpResults->data;

        const QByteArray xml = parseSdpRecord(record);
        total += xml;

        previous = sdpResults;
        sdpResults = sdpResults->next;
        free(previous);
        sdp_record_free(record);
    }

    if (!total.isEmpty()) {
        printf("%s", total.toBase64().constData());
    }

    sdp_close(session);

    return RETURN_SUCCESS;
}
コード例 #13
0
ファイル: session.c プロジェクト: Commers/obexd
struct session_data *session_create(const char *source,
			const char *destination, const char *target,
			uint8_t channel, session_callback_t function,
			void *user_data)
{
	struct session_data *session;
	struct callback_data *callback;
	int err;

	if (destination == NULL)
		return NULL;

	session = g_try_malloc0(sizeof(*session));
	if (session == NULL)
		return NULL;

	session->refcount = 1;
	session->channel = channel;

	session->conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
	if (session->conn == NULL) {
		session_free(session);
		return NULL;
	}

	if (source == NULL)
		bacpy(&session->src, BDADDR_ANY);
	else
		str2ba(source, &session->src);

	str2ba(destination, &session->dst);

	if (!g_ascii_strncasecmp(target, "OPP", 3)) {
		sdp_uuid16_create(&session->uuid, OBEX_OBJPUSH_SVCLASS_ID);
	} else if (!g_ascii_strncasecmp(target, "FTP", 3)) {
		sdp_uuid16_create(&session->uuid, OBEX_FILETRANS_SVCLASS_ID);
		session->target = OBEX_FTP_UUID;
		session->target_len = OBEX_FTP_UUID_LEN;
	} else if (!g_ascii_strncasecmp(target, "PBAP", 4)) {
		sdp_uuid16_create(&session->uuid, PBAP_PSE_SVCLASS_ID);
		session->target = OBEX_PBAP_UUID;
		session->target_len = OBEX_PBAP_UUID_LEN;
	} else if (!g_ascii_strncasecmp(target, "SYNC", 4)) {
		sdp_uuid16_create(&session->uuid, IRMC_SYNC_SVCLASS_ID);
		session->target = OBEX_SYNC_UUID;
		session->target_len = OBEX_SYNC_UUID_LEN;
	} else if (!g_ascii_strncasecmp(target, "PCSUITE", 7)) {
		sdp_uuid128_create(&session->uuid, pcsuite_uuid);
	} else {
		return NULL;
	}

	callback = g_try_malloc0(sizeof(*callback));
	if (callback == NULL) {
		session_free(session);
		return NULL;
	}

	callback->session = session_ref(session);
	callback->func = function;
	callback->data = user_data;

	if (session->channel > 0) {
		session->io = rfcomm_connect(&session->src, &session->dst,
							session->channel,
							rfcomm_callback,
							callback);
		err = (session->io == NULL) ? -EINVAL : 0;
	} else {
		callback->sdp = service_connect(&session->src, &session->dst,
						service_callback, callback);
		err = (callback->sdp == NULL) ? -ENOMEM : 0;
	}

	if (err < 0) {
		session_free(session);
		g_free(callback);
		return NULL;
	}

	return session;
}
コード例 #14
0
ファイル: manager.c プロジェクト: dev-life/GT-I9300_Platform
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;
}
コード例 #15
0
ファイル: hidhost.c プロジェクト: aguedes/bluez
static void connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
{
	struct hid_device *dev;
	bdaddr_t dst;
	char address[18];
	uint16_t psm;
	GError *gerr = NULL;
	GSList *l;
	uuid_t uuid;

	if (err) {
		error("hidhost: Connect failed (%s)", err->message);
		return;
	}

	bt_io_get(chan, &gerr,
			BT_IO_OPT_DEST_BDADDR, &dst,
			BT_IO_OPT_PSM, &psm,
			BT_IO_OPT_INVALID);
	if (gerr) {
		error("hidhost: Failed to read remote address (%s)",
								gerr->message);
		g_io_channel_shutdown(chan, TRUE, NULL);
		g_error_free(gerr);
		return;
	}

	ba2str(&dst, address);
	DBG("Incoming connection from %s on PSM %d", address, psm);

	switch (psm) {
	case L2CAP_PSM_HIDP_CTRL:
		l = g_slist_find_custom(devices, &dst, device_cmp);
		if (l)
			return;

		dev = hid_device_new(&dst);
		dev->ctrl_io = g_io_channel_ref(chan);

		sdp_uuid16_create(&uuid, PNP_INFO_SVCLASS_ID);
		if (bt_search_service(&adapter_addr, &dev->dst, &uuid,
				hid_sdp_did_search_cb, dev, NULL, 0) < 0) {
			error("hidhost: Failed to search DID SDP details");
			hid_device_remove(dev);
			return;
		}

		dev->ctrl_watch = g_io_add_watch(dev->ctrl_io,
					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
					ctrl_watch_cb, dev);
		bt_hid_notify_state(dev, HAL_HIDHOST_STATE_CONNECTING);
		break;

	case L2CAP_PSM_HIDP_INTR:
		l = g_slist_find_custom(devices, &dst, device_cmp);
		if (!l)
			return;

		dev = l->data;
		dev->intr_io = g_io_channel_ref(chan);
		dev->intr_watch = g_io_add_watch(dev->intr_io,
				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
				intr_watch_cb, dev);
		bt_hid_notify_state(dev, HAL_HIDHOST_STATE_CONNECTED);
		break;
	}
}
コード例 #16
0
static DBusMessage *create_connection(DBusConnection *conn,
						DBusMessage *msg, void *data)
{
	struct pending_reply *pr;
	const char *addr;
	const char *str;
	bdaddr_t src;
	uint16_t id;
	int dev_id, err;
	char key[32];
	GSList *l;
	uuid_t uuid;

	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &addr,
			DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID) == FALSE)
		return NULL;

	id = bnep_service_id(str);
	if (id != BNEP_SVC_GN && id != BNEP_SVC_NAP && id != BNEP_SVC_PANU)
		return not_supported(msg);

	snprintf(key, 32, "%s#%s", addr, bnep_name(id));

	/* Checks if the connection was already been made */
	for (l = connection_paths; l; l = l->next) {
		if (connection_find_data(l->data, key) == 0)
			return already_exists(msg);
	}

	bacpy(&src, BDADDR_ANY);
	dev_id = hci_get_route(&src);
	if (dev_id < 0 || hci_devba(dev_id, &src) < 0)
		return adapter_not_available(msg);

	pr = g_new0(struct pending_reply, 1);

	/* FIXME just to maintain compatibility */
	pr->adapter_path = g_strdup_printf("/org/bluez/hci%d", dev_id);
	if (!pr->adapter_path) {
		pending_reply_free (pr);
		return adapter_not_available(msg);
	}

	pr->conn = dbus_connection_ref(conn);
	pr->msg = dbus_message_ref(msg);
	bacpy(&pr->src, &src);
	str2ba(addr, &pr->dst);
	pr->addr = g_strdup(addr);
	pr->id = id;
	pr->path = g_new0(char, MAX_PATH_LENGTH);
	snprintf(pr->path, MAX_PATH_LENGTH,
				NETWORK_PATH "/connection%d", net_uid++);

	sdp_uuid16_create(&uuid, pr->id);
	err = bt_search_service(&pr->src, &pr->dst, &uuid, records_cb, pr,
				NULL);
	if (err < 0) {
		pending_reply_free(pr);
		return not_supported(msg);
	}

	return NULL;
}
コード例 #17
0
ファイル: control.c プロジェクト: LittoCats/OT_4010D
static sdp_record_t *avrcp_tg_record()
{
	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, *proto[2];
	sdp_record_t *record;
	sdp_data_t *psm, *version, *features;
	uint16_t lp = AVCTP_PSM;
	uint16_t avrcp_ver = 0x0100, avctp_ver = 0x0103, feat = 0x000f;

#ifdef ANDROID
	feat = 0x0001;
#endif
	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);

	/* Service Class ID List */
	sdp_uuid16_create(&avrtg, AV_REMOTE_TARGET_SVCLASS_ID);
	svclass_id = sdp_list_append(0, &avrtg);
	sdp_set_service_classes(record, svclass_id);

	/* Protocol Descriptor List */
	sdp_uuid16_create(&l2cap, L2CAP_UUID);
	proto[0] = sdp_list_append(0, &l2cap);
	psm = sdp_data_alloc(SDP_UINT16, &lp);
	proto[0] = sdp_list_append(proto[0], psm);
	apseq = sdp_list_append(0, proto[0]);

	sdp_uuid16_create(&avctp, AVCTP_UUID);
	proto[1] = sdp_list_append(0, &avctp);
	version = sdp_data_alloc(SDP_UINT16, &avctp_ver);
	proto[1] = sdp_list_append(proto[1], version);
	apseq = sdp_list_append(apseq, proto[1]);

	aproto = sdp_list_append(0, apseq);
	sdp_set_access_protos(record, aproto);

	/* Bluetooth Profile Descriptor List */
	sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID);
	profile[0].version = avrcp_ver;
	pfseq = sdp_list_append(0, &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", 0, 0);

	free(psm);
	free(version);
	sdp_list_free(proto[0], 0);
	sdp_list_free(proto[1], 0);
	sdp_list_free(apseq, 0);
	sdp_list_free(aproto, 0);
	sdp_list_free(pfseq, 0);
	sdp_list_free(root, 0);
	sdp_list_free(svclass_id, 0);

	return record;
}
コード例 #18
0
ファイル: pcm_a2dp.c プロジェクト: fullstory-morgue/btsco
// Detect whether A2DP Sink is present at the destination or not
static int detect_a2dp(bdaddr_t *src, bdaddr_t *dst, unsigned short *psm, unsigned long *flags)
{
	sdp_session_t *sess;
	sdp_list_t *attrid, *search, *seq, *next;
	sdp_data_t *pdlist;
	uuid_t group;
	uint32_t range = 0x0000ffff;
	int err;
	int tries;

	tries = 0;
	while(!(sess = sdp_connect(src, dst, SDP_RETRY_IF_BUSY))) {
		DBG("retrying sdp connect: %s", strerror(errno));
		sleep(1);
		if(++tries > 10) {
			break;
		}
	}
	if (!sess) {
		DBG( "Warning: failed to connect to SDP server: %s", strerror(errno));
		if(psm) *psm = 25;
		if(flags) *flags = 0;
		return 0;
	}

	/* 0x1108->all? 0x1101->rf sink 0x111e->handsfree 0x1108->headset */
	sdp_uuid16_create(&group, 0x110d);
	search = sdp_list_append(0, &group);
	attrid = sdp_list_append(0, &range);
	err = sdp_service_search_attr_req(sess, search,
					SDP_ATTR_REQ_RANGE, attrid, &seq);
	sdp_list_free(search, 0);
	sdp_list_free(attrid, 0);

	if (err) {
		DBG( "Service Search failed: %s", strerror(errno));
		sdp_close(sess);
		return -1;
	}

	for (; seq; seq = next) {
		sdp_record_t *rec = (sdp_record_t *) seq->data;

		DBG( "Found A2DP Sink");
		if (psm)
			*psm = 25;

		next = seq->next;
		free(seq);
		sdp_record_free(rec);
	}

	sdp_uuid16_create(&group, PNP_INFO_SVCLASS_ID);
	search = sdp_list_append(0, &group);
	attrid = sdp_list_append(0, &range);
	err = sdp_service_search_attr_req(sess, search,
					SDP_ATTR_REQ_RANGE, attrid, &seq);
	sdp_list_free(search, 0);
	sdp_list_free(attrid, 0);

	if (err)
		goto done;

	if (flags)
		*flags = 0;

	for (; seq; seq = next) {
		sdp_record_t *rec = (sdp_record_t *) seq->data;
		uint16_t vendor, product, version;

		pdlist = sdp_data_get(rec, 0x0201);
		vendor = pdlist ? pdlist->val.uint16 : 0x0000;

		pdlist = sdp_data_get(rec, 0x0202);
		product = pdlist ? pdlist->val.uint16 : 0x0000;

		pdlist = sdp_data_get(rec, 0x0203);
		version = pdlist ? pdlist->val.uint16 : 0x0000;

		DBG( "Product ID %04x:%04x:%04x", vendor, product, version);

		if (vendor == 0x1310 && product == 0x0100 && version == 0x0104) {
			DBG( "Enabling GCT media payload workaround");
			if (flags)
				*flags |= NONSPECAUDIO;
		}

		next = seq->next;
		free(seq);
		sdp_record_free(rec);
	}

done:
	sdp_close(sess);
	return 0;
}
コード例 #19
0
ファイル: dual_pair.c プロジェクト: shayp/BlackTooth
uint8_t sdp_lookup_uuid_rfcomm_channel(bdaddr_t *addr, uint16_t wanted_uuid)
{
	uuid_t uuid;
	sdp_list_t *sdp_res, *sdp_search, *sdp_wanted_attr;
	sdp_session_t *sdp_session;
	uint32_t wanted_attr_range = 0xFFFF;
	bdaddr_t bdaddr = *addr;
	uint8_t rfcomm_channel = 0;
	int err;

	sdp_session = sdp_connect(BDADDR_ANY, &bdaddr, SDP_RETRY_IF_BUSY);

	if (NULL != sdp_session)
		printf("Connected to target SDP server\n");

	sdp_uuid16_create(&uuid, wanted_uuid);

	sdp_search = sdp_list_append( NULL, &uuid );
    	sdp_wanted_attr = sdp_list_append( NULL, &wanted_attr_range );

	// get a list of service records that have UUID 0xabcd
	err = sdp_service_search_attr_req(sdp_session, sdp_search, SDP_ATTR_REQ_RANGE, sdp_wanted_attr, &sdp_res);
	
	printf("SDP service search result: %p\n", sdp_res);

	sdp_list_t *r = sdp_res;

	// go through each of the service records
	for (; r; r = r->next ) 
	{
		sdp_record_t *rec = (sdp_record_t*) r->data;
		sdp_list_t *proto_list;
		
		// get a list of the protocol sequences
		if( sdp_get_access_protos( rec, &proto_list ) == 0 ) {
		sdp_list_t *p = proto_list;

		// go through each protocol sequence
		for( ; p ; p = p->next ) {
		    sdp_list_t *pds = (sdp_list_t*)p->data;

		    // go through each protocol list of the protocol sequence
		    for( ; pds ; pds = pds->next ) {

		        // check the protocol attributes
		        sdp_data_t *d = (sdp_data_t*)pds->data;
		        int proto = 0;
		        for( ; d; d = d->next ) {
		            switch( d->dtd ) { 
		                case SDP_UUID16:
		                case SDP_UUID32:
		                case SDP_UUID128:
		                    proto = sdp_uuid_to_proto( &d->val.uuid );
					printf("Proto: %d\n", proto);
		                    break;
		                case SDP_UINT8:
		                    if( proto == RFCOMM_UUID ) 
				    {
					rfcomm_channel = d->val.int8;
		                        printf("Found RFCOMM channel: %d\n",d->val.int8);
		                    }
		                    break;
		            }
		        }
		    }

		    sdp_list_free( (sdp_list_t*)p->data, 0 );
		}
		
		sdp_list_free( proto_list, 0 );

		}

		sdp_record_free( rec );
	}

	sdp_close(sdp_session);

	return rfcomm_channel;
}
コード例 #20
0
/**
 * Creates the SDP record for PS3 keypad HID emulation. Works well with many different
 * clients: windows, linux (ubuntu), PS3, and motorola android devices.
 */
static sdp_record_t *create_hid_ps3_keypad_record()
{
	sdp_record_t *sdp_record;
	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 *channel, *lang_lst, *lang_lst2, *hid_spec_lst, *hid_spec_lst2;
	int i;
	uint8_t dtd = SDP_UINT16;
	uint8_t dtd2 = SDP_UINT8;
	uint8_t dtd_data = SDP_TEXT_STR8;
	void *dtds[2];
	void *values[2];
	void *dtds2[2];
	void *values2[2];
	int leng[2];
	uint8_t hid_spec_type = 0x22;
	uint16_t hid_attr_lang[] = {0x409,0x100};
	uint16_t value_int = 0;
	static const uint16_t ctrl = 0x11;
	static const uint16_t intr = 0x13;

	static const uint16_t hid_release_num = 0x100;
	static const uint16_t hid_parser_version = 0x111;
	static const uint8_t hid_dev_subclass = 0x40;
	static const uint8_t hid_country_code = 0x4;
	static const uint8_t hid_virtual_cable = 0x0;
	static const uint8_t hid_reconn_initiate = 0x1;

	static const uint8_t hid_sdp_disable = 0x0;
	static const uint8_t hid_batt_power = 0x1;
	static const uint8_t hid_remote_wake = 0x0;
	static const uint16_t hid_profile_version = 0x100;
	static const uint16_t hid_superv_timeout = 0x1f40;
	static const uint8_t hid_normally_connectable = 0x0;
	static const uint8_t hid_boot_device = 0x1;

	static const uint8_t hid_spec[] = {
			/* Pointer (mouse) */
			0x05, 0x01,         /*  Usage Page (Desktop),               */
			0x09, 0x02,         /*  Usage (Mouse),                      */
			0xA1, 0x01,         /*  Collection (Application),           */
			0x85, 0x02,         /*      Report ID (2),                  */
			0x09, 0x01,         /*      Usage (Pointer),                */
			0xA1, 0x00,         /*      Collection (Physical),          */
			0x05, 0x09,         /*          Usage Page (Button),        */
			0x19, 0x01,         /*          Usage Minimum (01h),        */
			0x29, 0x02,         /*          Usage Maximum (02h),        */
			0x15, 0x00,         /*          Logical Minimum (0),        */
			0x25, 0x01,         /*          Logical Maximum (1),        */
			0x95, 0x02,         /*          Report Count (2),           */
			0x75, 0x01,         /*          Report Size (1),            */
			0x81, 0x02,         /*          Input (Variable),           */
			0x95, 0x01,         /*          Report Count (1),           */
			0x75, 0x06,         /*          Report Size (6),            */
			0x81, 0x03,         /*          Input (Constant, Variable), */
			0x05, 0x01,         /*          Usage Page (Desktop),       */
			0x09, 0x30,         /*          Usage (X),                  */
			0x09, 0x31,         /*          Usage (Y),                  */
			0x15, 0x81,         /*          Logical Minimum (-127),     */
			0x25, 0x7F,         /*          Logical Maximum (127),      */
			0x75, 0x08,         /*          Report Size (8),            */
			0x95, 0x02,         /*          Report Count (2),           */
			0x81, 0x06,         /*          Input (Variable, Relative), */
			0x75, 0x08,         /*          Report Size (8),            */
			0x95, 0x01,         /*          Report Count (1),           */
			0x81, 0x01,         /*          Input (Constant),           */
			0x06, 0x00, 0xFF,   /*          Usage Page (FF00h),         */
			0x09, 0x20,         /*          Usage (20h),                */
			0x15, 0x00,         /*          Logical Minimum (0),        */
			0x26, 0xFF, 0x0F,   /*          Logical Maximum (4095),     */
			0x75, 0x0C,         /*          Report Size (12),           */
			0x95, 0x02,         /*          Report Count (2),           */
			0x81, 0x02,         /*          Input (Variable),           */
			0x09, 0x21,         /*          Usage (21h),                */
			0x15, 0x00,         /*          Logical Minimum (0),        */
			0x26, 0xFF, 0x00,   /*          Logical Maximum (255),      */
			0x75, 0x08,         /*          Report Size (8),            */
			0x95, 0x01,         /*          Report Count (1),           */
			0x81, 0x02,         /*          Input (Variable),           */
			0xC0,               /*      End Collection,                 */
			0xC0,               /*  End Collection,                     */
			/* Keyboard */
			0x05, 0x01,         /*  Usage Page (Desktop),               */
			0x09, 0x06,         /*  Usage (Keyboard),                   */
			0xA1, 0x01,         /*  Collection (Application),           */
			0x85, 0x01,         /*      Report ID (1),                  */
			0x05, 0x07,         /*      Usage Page (Keyboard),          */
			0x19, 0xE0,         /*      Usage Minimum (KB Leftcontrol), */
			0x29, 0xE7,         /*      Usage Maximum (KB Right GUI),   */
			0x15, 0x00,         /*      Logical Minimum (0),            */
			0x25, 0x01,         /*      Logical Maximum (1),            */
			0x75, 0x01,         /*      Report Size (1),                */
			0x95, 0x08,         /*      Report Count (8),               */
			0x81, 0x02,         /*      Input (Variable),               */
			0x95, 0x01,         /*      Report Count (1),               */
			0x75, 0x08,         /*      Report Size (8),                */
			0x81, 0x01,         /*      Input (Constant),               */
			0x95, 0x05,         /*      Report Count (5),               */
			0x75, 0x01,         /*      Report Size (1),                */
			0x05, 0x08,         /*      Usage Page (LED),               */
			0x19, 0x01,         /*      Usage Minimum (01h),            */
			0x29, 0x05,         /*      Usage Maximum (05h),            */
			0x91, 0x02,         /*      Output (Variable),              */
			0x95, 0x01,         /*      Report Count (1),               */
			0x75, 0x03,         /*      Report Size (3),                */
			0x91, 0x01,         /*      Output (Constant),              */
			0x95, 0x06,         /*      Report Count (6),               */
			0x75, 0x08,         /*      Report Size (8),                */
			0x15, 0x00,         /*      Logical Minimum (0),            */
			0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
			0x05, 0x07,         /*      Usage Page (Keyboard),          */
			0x19, 0x00,         /*      Usage Minimum (None),           */
			0x29, 0xE7,         /*      Usage Maximum (KB Right GUI),   */
			0x81, 0x00,         /*      Input,                          */
			0xC0,               /*  End Collection,                     */
			0x06, 0x01, 0xFF,   /*  Usage Page (FF01h),                 */
			0x09, 0x20,         /*  Usage (20h),                        */
			0xA1, 0x01,         /*  Collection (Application),           */
			0x09, 0x21,         /*      Usage (21h),                    */
			0x85, 0x03,         /*      Report ID (3),                  */
			0x75, 0x08,         /*      Report Size (8),                */
			0x95, 0x01,         /*      Report Count (1),               */
			0x15, 0x00,         /*      Logical Minimum (0),            */
			0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
			0x09, 0x22,         /*      Usage (22h),                    */
			0x81, 0x02,         /*      Input (Variable),               */
			0x75, 0x08,         /*      Report Size (8),                */
			0x95, 0x01,         /*      Report Count (1),               */
			0x15, 0x00,         /*      Logical Minimum (0),            */
			0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
			0x09, 0x23,         /*      Usage (23h),                    */
			0x81, 0x02,         /*      Input (Variable),               */
			0x75, 0x08,         /*      Report Size (8),                */
			0x95, 0x06,         /*      Report Count (6),               */
			0x81, 0x01,         /*      Input (Constant),               */
			0x09, 0x24,         /*      Usage (24h),                    */
			0x15, 0x00,         /*      Logical Minimum (0),            */
			0x25, 0x01,         /*      Logical Maximum (1),            */
			0x75, 0x08,         /*      Report Size (8),                */
			0x95, 0x01,         /*      Report Count (1),               */
			0x91, 0x02,         /*      Output (Variable),              */
			0xC0,               /*  End Collection,                     */
			/* ?? PS3 proprietary? */
			0x06, 0x02, 0xFF,   /*  Usage Page (FF02h),                 */
			0x09, 0x20,         /*  Usage (20h),                        */
			0xA1, 0x01,         /*  Collection (Application),           */
			0x09, 0x21,         /*      Usage (21h),                    */
			0x85, 0x04,         /*      Report ID (4),                  */
			0x15, 0x00,         /*      Logical Minimum (0),            */
			0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
			0x75, 0x08,         /*      Report Size (8),                */
			0x95, 0x0F,         /*      Report Count (15),              */
			0xB1, 0x02,         /*      Feature (Variable),             */
			0x09, 0x22,         /*      Usage (22h),                    */
			0x85, 0x05,         /*      Report ID (5),                  */
			0x15, 0x00,         /*      Logical Minimum (0),            */
			0x26, 0xFF, 0x00,   /*      Logical Maximum (255),          */
			0x75, 0x08,         /*      Report Size (8),                */
			0x95, 0x16,         /*      Report Count (22),              */
			0xB1, 0x02,         /*      Feature (Variable),             */
			0xC0                /*  End Collection                      */
	};

	sdp_record = sdp_record_alloc();
	if (!sdp_record) {
		return NULL;
	}

	memset((void*)sdp_record, 0, sizeof(sdp_record_t));
	sdp_record->handle = 0xffffffff;
	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
	root = sdp_list_append(0, &root_uuid);
	sdp_set_browse_groups(sdp_record, root);

	add_lang_attr(sdp_record);

	sdp_uuid16_create(&hidkb_uuid, HID_SVCLASS_ID);
	svclass_id = sdp_list_append(0, &hidkb_uuid);
	sdp_set_service_classes(sdp_record, svclass_id);

	sdp_uuid16_create(&profile[0].uuid, HID_PROFILE_ID);
	profile[0].version = 0x0100;
	pfseq = sdp_list_append(0, profile);
	sdp_set_profile_descs(sdp_record, pfseq);

	/* PROTO */
	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
	proto[1] = sdp_list_append(0, &l2cap_uuid);
	channel = sdp_data_alloc(SDP_UINT8, &ctrl);
	proto[1] = sdp_list_append(proto[1], channel);
	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_access_protos(sdp_record, aproto);

	/* ATTR_ADD_PROTO */
	proto[1] = sdp_list_append(0, &l2cap_uuid);
	channel = sdp_data_alloc(SDP_UINT8, &intr);
	proto[1] = sdp_list_append(proto[1], channel);
	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(sdp_record, aproto);

	sdp_set_info_attr(sdp_record, "Android PS3 Bluetooth Keypad",
		"", "PS3 compatible HID device over Bluetooth for Android");

	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_DEVICE_RELEASE_NUMBER, SDP_UINT16, &hid_release_num);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_PARSER_VERSION, SDP_UINT16, &hid_parser_version);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_DEVICE_SUBCLASS, SDP_UINT8, &hid_dev_subclass);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_COUNTRY_CODE, SDP_UINT8, &hid_country_code);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_VIRTUAL_CABLE, SDP_BOOL, &hid_virtual_cable);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_RECONNECT_INITIATE, SDP_BOOL, &hid_reconn_initiate);

	dtds[0] = &dtd2;
	values[0] = &hid_spec_type;
	dtds[1] = &dtd_data;
	values[1] = (uint8_t*)hid_spec;
	leng[0] = 0;
	leng[1] = sizeof(hid_spec);
	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(sdp_record, SDP_ATTR_HID_DESCRIPTOR_LIST, hid_spec_lst2);

	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(sdp_record, SDP_ATTR_HID_LANG_ID_BASE_LIST, lang_lst2);

	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_SDP_DISABLE, SDP_BOOL, &hid_sdp_disable);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_BATTERY_POWER, SDP_BOOL, &hid_batt_power);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_REMOTE_WAKEUP, SDP_BOOL, &hid_remote_wake);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_PROFILE_VERSION, SDP_UINT16, &hid_profile_version);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_SUPERVISION_TIMEOUT, SDP_UINT16, &hid_superv_timeout);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_NORMALLY_CONNECTABLE, SDP_BOOL, &hid_normally_connectable);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_BOOT_DEVICE, SDP_BOOL, &hid_boot_device);

	return sdp_record;
}
コード例 #21
0
ファイル: a2dp.c プロジェクト: pocketbook-free/bluez-4.62
static sdp_record_t *a2dp_record(uint8_t type, uint16_t avdtp_ver)
{
	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 = 0x0102, feat = 0x000f;

	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);

	if (type == AVDTP_SEP_TYPE_SOURCE)
		sdp_uuid16_create(&a2dp_uuid, AUDIO_SOURCE_SVCLASS_ID);
	else
		sdp_uuid16_create(&a2dp_uuid, AUDIO_SINK_SVCLASS_ID);
	svclass_id = sdp_list_append(0, &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(0, &profile[0]);
	sdp_set_profile_descs(record, pfseq);

	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
	proto[0] = sdp_list_append(0, &l2cap_uuid);
	psm = sdp_data_alloc(SDP_UINT16, &lp);
	proto[0] = sdp_list_append(proto[0], psm);
	apseq = sdp_list_append(0, proto[0]);

	sdp_uuid16_create(&avdtp_uuid, AVDTP_UUID);
	proto[1] = sdp_list_append(0, &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(0, apseq);
	sdp_set_access_protos(record, aproto);

	features = sdp_data_alloc(SDP_UINT16, &feat);
	sdp_attr_add(record, SDP_ATTR_SUPPORTED_FEATURES, features);

	if (type == AVDTP_SEP_TYPE_SOURCE)
		sdp_set_info_attr(record, "Audio Source", 0, 0);
	else
		sdp_set_info_attr(record, "Audio Sink", 0, 0);

	free(psm);
	free(version);
	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;
}
コード例 #22
0
/**
 * Creates the SDP record for HID emulation. Works well with many different
 * clients: windows, linux (ubuntu), PS3, and motorola android devices.
 */
static sdp_record_t *create_hid_generic_record()
{
	sdp_record_t *sdp_record;
	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 *channel, *lang_lst, *lang_lst2, *hid_spec_lst, *hid_spec_lst2;
	int i;
	uint8_t dtd = SDP_UINT16;
	uint8_t dtd2 = SDP_UINT8;
	uint8_t dtd_data = SDP_TEXT_STR8;
	void *dtds[2];
	void *values[2];
	void *dtds2[2];
	void *values2[2];
	int leng[2];
	uint8_t hid_spec_type = 0x22;
	uint16_t hid_attr_lang[] = {0x409,0x100};
	uint16_t value_int = 0;
	static const uint16_t ctrl = 0x11;
	static const uint16_t intr = 0x13;

	static const uint16_t hid_release_num = 0x100;
	static const uint16_t hid_parser_version = 0x111;
	static const uint8_t hid_dev_subclass = 0x40;
	static const uint8_t hid_country_code = 0x4;
	static const uint8_t hid_virtual_cable = 0x0;
	static const uint8_t hid_reconn_initiate = 0x1;

	static const uint8_t hid_sdp_disable = 0x0;
	static const uint8_t hid_batt_power = 0x1;
	static const uint8_t hid_remote_wake = 0x0;
	static const uint16_t hid_profile_version = 0x100;
	static const uint16_t hid_superv_timeout = 0x1f40;
	static const uint8_t hid_normally_connectable = 0x0;
	static const uint8_t hid_boot_device = 0x1;

	static const uint8_t hid_spec[] = {
            /* Generic keyboard */
            0x05, 0x01,         /*  Usage Page (Desktop),                   */
            0x09, 0x06,         /*  Usage (Keyboard),                       */
            0xA1, 0x01,         /*  Collection (Application),               */
            0x85, 0x01,         /*      Report ID (1),                      */
            0x05, 0x07,         /*      Usage Page (Keyboard),              */
            0x19, 0xE0,         /*      Usage Minimum (KB Leftcontrol),     */
            0x29, 0xE7,         /*      Usage Maximum (KB Right GUI),       */
            0x15, 0x00,         /*      Logical Minimum (0),                */
            0x25, 0x01,         /*      Logical Maximum (1),                */
            0x75, 0x01,         /*      Report Size (1),                    */
            0x95, 0x08,         /*      Report Count (8),                   */
            0x81, 0x02,         /*      Input (Variable),                   */
            0x95, 0x01,         /*      Report Count (1),                   */
            0x75, 0x08,         /*      Report Size (8),                    */
            0x81, 0x01,         /*      Input (Constant),                   */
            0x95, 0x05,         /*      Report Count (5),                   */
            0x75, 0x01,         /*      Report Size (1),                    */
            0x05, 0x08,         /*      Usage Page (LED),                   */
            0x19, 0x01,         /*      Usage Minimum (01h),                */
            0x29, 0x05,         /*      Usage Maximum (05h),                */
            0x91, 0x02,         /*      Output (Variable),                  */
            0x95, 0x01,         /*      Report Count (1),                   */
            0x75, 0x03,         /*      Report Size (3),                    */
            0x91, 0x01,         /*      Output (Constant),                  */
            0x95, 0x06,         /*      Report Count (6),                   */
            0x75, 0x08,         /*      Report Size (8),                    */
            0x15, 0x00,         /*      Logical Minimum (0),                */
            0x26, 0xFF, 0x00,   /*      Logical Maximum (255),              */
            0x05, 0x07,         /*      Usage Page (Keyboard),              */
            0x19, 0x00,         /*      Usage Minimum (None),               */
            0x29, 0xE7,         /*      Usage Maximum (KB Right GUI),   */
            0x81, 0x00,         /*      Input,                              */

            /* Consumer specific - volume / mute */
            0xC0,               /*  End Collection,                         */
            0x05, 0x0C,         /*  Usage Page (Consumer),                  */
            0x09, 0x01,         /*  Usage (Consumer Control),               */
            0xA1, 0x01,         /*  Collection (Application),               */
            0x85, 0x01,         /*      Report ID (1),                      */
            0x09, 0xE0,         /*      Usage (Volume),                     */
            0x15, 0xE8,         /*      Logical Minimum (-24),              */
            0x25, 0x18,         /*      Logical Maximum (24),               */
            0x75, 0x07,         /*      Report Size (7),                    */
            0x95, 0x01,         /*      Report Count (1),                   */
            0x81, 0x06,         /*      Input (Variable, Relative),         */
            0x15, 0x00,         /*      Logical Minimum (0),                */
            0x25, 0x01,         /*      Logical Maximum (1),                */
            0x75, 0x01,         /*      Report Size (1),                    */
            0x09, 0xE2,         /*      Usage (Mute),                       */
            0x81, 0x06,         /*      Input (Variable, Relative),         */
            0xC0,               /*  End Collection,                         */

            /* Consumer specific - media controls */
            0x05, 0x0C,         /*  Usage Page (Consumer),                  */
            0x09, 0x01,         /*  Usage (Consumer Control),               */
            0xA1, 0x01,         /*  Collection (Application),               */
            0x85, 0x03,         /*      Report ID (3),                      */
            0x15, 0x00,         /*      Logical Minimum (0),                */
            0x25, 0x01,         /*      Logical Maximum (1),                */
            0x75, 0x01,         /*      Report Size (1),                    */
            0x95, 0x01,         /*      Report Count (1),                   */
            0x0A, 0x27, 0x02,   /*      Usage (AC Refresh),                 */
            0x81, 0x06,         /*      Input (Variable, Relative),         */
            0x0A, 0x94, 0x01,   /*      Usage (AL Local Machine Brwsr),     */
            0x81, 0x06,         /*      Input (Variable, Relative),         */
            0x0A, 0x23, 0x02,   /*      Usage (AC Home),                    */
            0x81, 0x06,         /*      Input (Variable, Relative),         */
            0x0A, 0x8A, 0x01,   /*      Usage (AL Email Reader),            */
            0x81, 0x06,         /*      Input (Variable, Relative),         */
            0x0A, 0x92, 0x01,   /*      Usage (AL Calculator),              */
            0x81, 0x06,         /*      Input (Variable, Relative),         */
            0x0A, 0x26, 0x02,   /*      Usage (AC Stop),                    */
            0x81, 0x06,         /*      Input (Variable, Relative),         */
            0x0A, 0x25, 0x02,   /*      Usage (AC Forward),                 */
            0x81, 0x06,         /*      Input (Variable, Relative),         */
            0x0A, 0x24, 0x02,   /*      Usage (AC Back),                    */
            0x81, 0x06,         /*      Input (Variable, Relative),         */
            0x09, 0xB5,         /*      Usage (Scan Next Track),            */
            0x81, 0x06,         /*      Input (Variable, Relative),         */
            0x09, 0xB6,         /*      Usage (Scan Previous Track),        */
            0x81, 0x06,         /*      Input (Variable, Relative),         */
            0x09, 0xCD,         /*      Usage (Play Pause),                 */
            0x81, 0x06,         /*      Input (Variable, Relative),         */
            0x09, 0xB7,         /*      Usage (Stop),                       */
            0x81, 0x06,         /*      Input (Variable, Relative),         */
            0x0A, 0x83, 0x01,   /*      Usage (AL Consumer Control Config), */
            0x81, 0x06,         /*      Input (Variable, Relative),         */
            0x95, 0x0B,         /*      Report Count (11),                  */
            0x81, 0x01,         /*      Input (Constant),                   */
            0xC0,               /*  End Collection                          */

            /* Generic mouse pointer */
			0x05, 0x01,                    /* USAGE_PAGE (Generic Desktop)              */
			0x09, 0x02,                    /* USAGE (Mouse)                             */
			0xa1, 0x01,                    /* COLLECTION (Application)                  */
			0x85, 0x02,                            /*      Report ID (2),               */
			0x09, 0x01,                    /*   USAGE (Pointer)                         */
			0xa1, 0x00,                    /*   COLLECTION (Physical)                   */
			0x05, 0x09,                    /*     USAGE_PAGE (Button)                   */
			0x19, 0x01,                    /*     USAGE_MINIMUM (Button 1)              */
			0x29, 0x03,                    /*     USAGE_MAXIMUM (Button 3)              */
			0x15, 0x00,                    /*     LOGICAL_MINIMUM (0)                   */
			0x25, 0x01,                    /*     LOGICAL_MAXIMUM (1)                   */
			0x95, 0x03,                    /*     REPORT_COUNT (3)                      */
			0x75, 0x01,                    /*     REPORT_SIZE (1)                       */
			0x81, 0x02,                    /*     INPUT (Data,Var,Abs)                  */
			0x95, 0x01,                    /*     REPORT_COUNT (1)                      */
			0x75, 0x05,                    /*     REPORT_SIZE (5)                       */
			0x81, 0x03,                    /*     INPUT (Cnst,Var,Abs)                  */
			0x05, 0x01,                    /*     USAGE_PAGE (Generic Desktop)          */
			0x09, 0x30,                    /*     USAGE (X)                             */
			0x09, 0x31,                    /*     USAGE (Y)                             */
			0x15, 0x81,                    /*     LOGICAL_MINIMUM (-127)                */
			0x25, 0x7f,                    /*     LOGICAL_MAXIMUM (127)                 */
			0x75, 0x08,                    /*     REPORT_SIZE (8)                       */
			0x95, 0x02,                    /*     REPORT_COUNT (2)                      */
			0x81, 0x06,                    /*     INPUT (Data,Var,Rel)                  */
			0xc0,                          /*   END_COLLECTION                          */
			0xc0                           /* END_COLLECTION                             */

	};

	sdp_record = sdp_record_alloc();
	if (!sdp_record) {
		return NULL;
	}

	memset((void*)sdp_record, 0, sizeof(sdp_record_t));
	sdp_record->handle = 0xffffffff;
	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
	root = sdp_list_append(0, &root_uuid);
	sdp_set_browse_groups(sdp_record, root);

	add_lang_attr(sdp_record);

	sdp_uuid16_create(&hidkb_uuid, HID_SVCLASS_ID);
	svclass_id = sdp_list_append(0, &hidkb_uuid);
	sdp_set_service_classes(sdp_record, svclass_id);

	sdp_uuid16_create(&profile[0].uuid, HID_PROFILE_ID);
	profile[0].version = 0x0100;
	pfseq = sdp_list_append(0, profile);
	sdp_set_profile_descs(sdp_record, pfseq);

	/* PROTO */
	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
	proto[1] = sdp_list_append(0, &l2cap_uuid);
	channel = sdp_data_alloc(SDP_UINT8, &ctrl);
	proto[1] = sdp_list_append(proto[1], channel);
	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_access_protos(sdp_record, aproto);

	/* ATTR_ADD_PROTO */
	proto[1] = sdp_list_append(0, &l2cap_uuid);
	channel = sdp_data_alloc(SDP_UINT8, &intr);
	proto[1] = sdp_list_append(proto[1], channel);
	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(sdp_record, aproto);

	sdp_set_info_attr(sdp_record, "Android Bluetooth Keyboard",
		"", "HID device over Bluetooth for Android");

	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_DEVICE_RELEASE_NUMBER, SDP_UINT16, &hid_release_num);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_PARSER_VERSION, SDP_UINT16, &hid_parser_version);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_DEVICE_SUBCLASS, SDP_UINT8, &hid_dev_subclass);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_COUNTRY_CODE, SDP_UINT8, &hid_country_code);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_VIRTUAL_CABLE, SDP_BOOL, &hid_virtual_cable);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_RECONNECT_INITIATE, SDP_BOOL, &hid_reconn_initiate);

	dtds[0] = &dtd2;
	values[0] = &hid_spec_type;
	dtds[1] = &dtd_data;
	values[1] = (uint8_t*)hid_spec;
	leng[0] = 0;
	leng[1] = sizeof(hid_spec);
	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(sdp_record, SDP_ATTR_HID_DESCRIPTOR_LIST, hid_spec_lst2);

	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(sdp_record, SDP_ATTR_HID_LANG_ID_BASE_LIST, lang_lst2);

	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_SDP_DISABLE, SDP_BOOL, &hid_sdp_disable);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_BATTERY_POWER, SDP_BOOL, &hid_batt_power);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_REMOTE_WAKEUP, SDP_BOOL, &hid_remote_wake);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_PROFILE_VERSION, SDP_UINT16, &hid_profile_version);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_SUPERVISION_TIMEOUT, SDP_UINT16, &hid_superv_timeout);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_NORMALLY_CONNECTABLE, SDP_BOOL, &hid_normally_connectable);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_BOOT_DEVICE, SDP_BOOL, &hid_boot_device);

	return sdp_record;
}
コード例 #23
0
ファイル: sdp_server.c プロジェクト: adhoc-dtn/electroSwitch
sdp_session_t *register_service()
{
  uint32_t svc_uuid_int[] = { 0x00000000,0x00000000,0x00000000,0x0001 };
  uint8_t rfcomm_channel = 1;
  const char *service_name = "Remote Host";
  const char *service_dsc = "What the remote should be connecting to.";
  const char *service_prov = "Your mother";

  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, &svc_uuid_int );
  sdp_set_service_id( record, svc_uuid );
  sdp_list_t service_class = {NULL, &svc_uuid};
  sdp_set_service_classes( record, &service_class);

  // 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;
}
コード例 #24
0
/**
 * Creates the SDP record for BD remtoe HID emulation. Probably works with PS3 only (experimental)
 */
static sdp_record_t *create_hid_bdremote_record()
{
	sdp_record_t *sdp_record;
	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 *channel, *lang_lst, *lang_lst2, *hid_spec_lst, *hid_spec_lst2;
	int i;
	uint8_t dtd = SDP_UINT16;
	uint8_t dtd2 = SDP_UINT8;
	uint8_t dtd_data = SDP_TEXT_STR8;
	void *dtds[2];
	void *values[2];
	void *dtds2[2];
	void *values2[2];
	int leng[2];
	uint8_t hid_spec_type = 0x22;
	uint16_t hid_attr_lang[] = {0x409,0x100};
	uint16_t value_int = 0;
	static const uint16_t ctrl = 0x11;
	static const uint16_t intr = 0x13;

	static const uint16_t hid_release_num = 0x100;
	static const uint16_t hid_parser_version = 0x111;
	static const uint8_t hid_dev_subclass = 0x0c;
	static const uint8_t hid_country_code = 0x21;
	static const uint8_t hid_virtual_cable = 0x1;
	static const uint8_t hid_reconn_initiate = 0x1;

	static const uint8_t hid_sdp_disable = 0x0;
	static const uint8_t hid_batt_power = 0x1;
	static const uint8_t hid_remote_wake = 0x1;
	static const uint16_t hid_profile_version = 0x100;
	static const uint16_t hid_superv_timeout = 0x1f40;
	static const uint8_t hid_normally_connectable = 0x0;
	static const uint8_t hid_boot_device = 0x10;

	const uint8_t hid_spec[] = {
		    /* PS3 blu-ray remote */
		    0x05, 0x01,					/* Usage Page (Generic Desktop)				*/
		    0x09, 0x05,					/* Usage ID (Game Pad)						*/
		    0xa1, 0x01,					/* Collection (Application)					*/
		    0x85, 0x01,					/*	Report ID (1)							*/
		    0x15, 0x00,					/*	Logical Minimum (0)						*/
		    0x26, 0xff, 0x00,			/*  Logical Maximum (255)					*/
		    0x75, 0x08,					/*	Report Size (8)							*/
		    0x95, 0x0b,					/*	Report Count (11)						*/
		    0x06, 0x00, 0xff,			/* Usage Page (Vendor Defined Page 1)		*/
		    0x09, 0x01,					/*	Usage (Vendor Usage 1)					*/
		    0x81, 0x00,					/*	Input (Data,Array,Absolute)				*/
		    0x85, 0x01,					/*	Report ID (1)							*/
		    0x95, 0x0b,					/*	Report Count (11)						*/
		    0x09, 0x01,					/*	Usage (Vendor Usage 1)					*/
		    0xb1, 0x00,					/*	Feature (Data,Array,Absolute)			*/
		    0x85, 0x02,					/*	Report ID (2)							*/
		    0x95, 0x0b,					/*	Report Count (11)						*/
		    0x09, 0x01,					/*	Usage (Vendor Usage 1)					*/
		    0xb1, 0x00,					/*	Feature (Data,Array,Absolute)			*/
		    0x85, 0x03,					/*	Report ID (3)							*/
		    0x95, 0x0b,					/*	Report Count (11)						*/
		    0x09, 0x01,					/*	Usage (Vendor Usage 1)					*/
		    0xb1, 0x00,					/*	Feature (Data,Array,Absolute)			*/
		    0x85, 0x04,					/*	Report ID (4)							*/
		    0x95, 0x0b,					/*	Report Count (11)						*/
		    0x09, 0x01,					/*	Usage (Vendor Usage 1)					*/
		    0xb1, 0x00,					/*	Feature (Data,Array,Absolute)			*/
		    0x85, 0x05,					/*	Report ID (5)							*/
		    0x95, 0x0b,					/*	Report count (11)						*/
		    0x09, 0x01,					/*	Usage (Vendor Usage 1)					*/
		    0xb1, 0x00,					/*	Feature (Data,Array,Absolute)			*/
		    0x85, 0x06,					/*	Report ID (6)							*/
		    0x95, 0x0b,					/*	Report count (11)						*/
		    0x09, 0x01,					/*	Usage (Vendor Usage 1)					*/
		    0xb1, 0x00,					/*	Feature (Data,Array,Absolute)			*/
		    0xc0					/*  End Collection								*/
	};

	sdp_record = sdp_record_alloc();
	if (!sdp_record) {
		return NULL;
	}

	memset((void*)sdp_record, 0, sizeof(sdp_record_t));
	sdp_record->handle = 0xffffffff;
	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
	root = sdp_list_append(0, &root_uuid);
	sdp_set_browse_groups(sdp_record, root);

	add_lang_attr(sdp_record);

	sdp_uuid16_create(&hidkb_uuid, HID_SVCLASS_ID);
	svclass_id = sdp_list_append(0, &hidkb_uuid);
	sdp_set_service_classes(sdp_record, svclass_id);

	sdp_uuid16_create(&profile[0].uuid, HID_PROFILE_ID);
	profile[0].version = 0x0100;
	pfseq = sdp_list_append(0, profile);
	sdp_set_profile_descs(sdp_record, pfseq);

	/* PROTO */
	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
	proto[1] = sdp_list_append(0, &l2cap_uuid);
	channel = sdp_data_alloc(SDP_UINT8, &ctrl);
	proto[1] = sdp_list_append(proto[1], channel);
	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_access_protos(sdp_record, aproto);

	/* ATTR_ADD_PROTO */
	proto[1] = sdp_list_append(0, &l2cap_uuid);
	channel = sdp_data_alloc(SDP_UINT8, &intr);
	proto[1] = sdp_list_append(proto[1], channel);
	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(sdp_record, aproto);

	sdp_set_info_attr(sdp_record, "Android Bluetooth Keyboard",
		"", "HID device over Bluetooth for Android");

	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_DEVICE_RELEASE_NUMBER, SDP_UINT16, &hid_release_num);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_PARSER_VERSION, SDP_UINT16, &hid_parser_version);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_DEVICE_SUBCLASS, SDP_UINT8, &hid_dev_subclass);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_COUNTRY_CODE, SDP_UINT8, &hid_country_code);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_VIRTUAL_CABLE, SDP_BOOL, &hid_virtual_cable);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_RECONNECT_INITIATE, SDP_BOOL, &hid_reconn_initiate);

	dtds[0] = &dtd2;
	values[0] = &hid_spec_type;
	dtds[1] = &dtd_data;
	values[1] = (uint8_t*)hid_spec;
	leng[0] = 0;
	leng[1] = sizeof(hid_spec);
	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(sdp_record, SDP_ATTR_HID_DESCRIPTOR_LIST, hid_spec_lst2);

	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(sdp_record, SDP_ATTR_HID_LANG_ID_BASE_LIST, lang_lst2);

	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_SDP_DISABLE, SDP_BOOL, &hid_sdp_disable);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_BATTERY_POWER, SDP_BOOL, &hid_batt_power);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_REMOTE_WAKEUP, SDP_BOOL, &hid_remote_wake);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_PROFILE_VERSION, SDP_UINT16, &hid_profile_version);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_SUPERVISION_TIMEOUT, SDP_UINT16, &hid_superv_timeout);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_NORMALLY_CONNECTABLE, SDP_BOOL, &hid_normally_connectable);
	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_BOOT_DEVICE, SDP_BOOL, &hid_boot_device);

	return sdp_record;
}
コード例 #25
0
ファイル: server.c プロジェクト: sancane/BlueZ
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;
}
コード例 #26
0
ファイル: sdp.c プロジェクト: 0omega/platform_external_bluez
int dun_sdp_register(bdaddr_t *device, uint8_t channel, int type)
{
	sdp_list_t *svclass, *pfseq, *apseq, *root, *aproto;
	uuid_t root_uuid, l2cap, rfcomm, dun;
	sdp_profile_desc_t profile[1];
	sdp_list_t *proto[2];
	int status;

	session = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, 0);
	if (!session) {
		syslog(LOG_ERR, "Failed to connect to the local SDP server. %s(%d)", 
				strerror(errno), errno);
		return -1;
	}

	record = sdp_record_alloc();
	if (!record) {
		syslog(LOG_ERR, "Failed to alloc service record");
		return -1;
	}

	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);
	apseq    = sdp_list_append(NULL, proto[0]);

	sdp_uuid16_create(&rfcomm, RFCOMM_UUID);
	proto[1] = sdp_list_append(NULL, &rfcomm);
	proto[1] = sdp_list_append(proto[1], sdp_data_alloc(SDP_UINT8, &channel));
	apseq    = sdp_list_append(apseq, proto[1]);

	aproto   = sdp_list_append(NULL, apseq);
	sdp_set_access_protos(record, aproto);

	switch (type) {
	case MROUTER:
		sdp_uuid16_create(&dun, SERIAL_PORT_SVCLASS_ID);
		break;
	case ACTIVESYNC:
		sdp_uuid128_create(&dun, (void *) async_uuid);
		break;
	case DIALUP:
		sdp_uuid16_create(&dun, DIALUP_NET_SVCLASS_ID);
		break;
	default:
		sdp_uuid16_create(&dun, LAN_ACCESS_SVCLASS_ID);
		break;
	}

	svclass = sdp_list_append(NULL, &dun);
	sdp_set_service_classes(record, svclass);

	switch (type) {
	case LANACCESS:
		sdp_uuid16_create(&profile[0].uuid, LAN_ACCESS_PROFILE_ID);
		profile[0].version = 0x0100;
		pfseq = sdp_list_append(NULL, &profile[0]);
		sdp_set_profile_descs(record, pfseq);
		break;
	case DIALUP:
		sdp_uuid16_create(&profile[0].uuid, DIALUP_NET_PROFILE_ID);
		profile[0].version = 0x0100;
		pfseq = sdp_list_append(NULL, &profile[0]);
		sdp_set_profile_descs(record, pfseq);
		break;
	}

	switch (type) {
	case MROUTER:
		sdp_set_info_attr(record, "mRouter", NULL, NULL);
		break;
	case ACTIVESYNC:
		sdp_set_info_attr(record, "ActiveSync", NULL, NULL);
		break;
	case DIALUP:
		sdp_set_info_attr(record, "Dialup Networking", NULL, NULL);
		break;
	default:
		sdp_set_info_attr(record, "LAN Access Point", NULL, NULL);
		break;
	}

	status = sdp_device_record_register(session, device, record, 0);
	if (status) {
		syslog(LOG_ERR, "SDP registration failed.");
		sdp_record_free(record);
		record = NULL;
		return -1;
	}
	return 0;
}
コード例 #27
0
ファイル: sdpd-service.c プロジェクト: intgr/bluez
/*
 * 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;
}
コード例 #28
0
ファイル: example.c プロジェクト: heinervdm/bluez
static int register_attributes(void)
{
	const char *desc_out_temp = "Outside Temperature";
	const char *desc_out_hum = "Outside Relative Humidity";
	const char *desc_weight = "Rucksack Weight";
	const char *manufacturer_name1 = "ACME Temperature Sensor";
	const char *manufacturer_name2 = "ACME Weighing Scales";
	const char *serial1 = "237495-3282-A";
	const char *serial2 = "11267-2327A00239";
	const unsigned char char_weight_uuid[] = { 0x80, 0x88, 0xF2, 0x18, 0x90,
		0x2C, 0x45, 0x0B, 0xB6, 0xC4, 0x62, 0x89, 0x1E, 0x8C, 0x25,
		0xE9 };
	const unsigned char prim_weight_uuid[] = { 0x4F, 0x0A, 0xC0, 0x96, 0x35,
		0xD4, 0x49, 0x11, 0x96, 0x31, 0xDE, 0xA8, 0xDC, 0x74, 0xEE,
		0xFE };
	uint8_t atval[256];
	uuid_t uuid;
	int len;

	/* Battery state service: primary service definition */
	sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
	att_put_u16(BATTERY_STATE_SVC_UUID, &atval[0]);
	attrib_db_add(0x0100, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);

	/* Battery: battery state characteristic */
	sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
	atval[0] = ATT_CHAR_PROPER_READ;
	att_put_u16(0x0110, &atval[1]);
	att_put_u16(BATTERY_STATE_UUID, &atval[3]);
	attrib_db_add(0x0106, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);

	/* Battery: battery state attribute */
	sdp_uuid16_create(&uuid, BATTERY_STATE_UUID);
	atval[0] = 0x04;
	attrib_db_add(0x0110, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 1);

	/* Battery: Client Characteristic Configuration */
	sdp_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
	atval[0] = 0x00;
	atval[1] = 0x00;
	attrib_db_add(0x0111, &uuid, ATT_NONE, ATT_AUTHENTICATION, atval, 2);

	/* Thermometer: primary service definition */
	sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
	att_put_u16(THERM_HUMIDITY_SVC_UUID, &atval[0]);
	attrib_db_add(0x0200, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);

	/* Thermometer: Include */
	sdp_uuid16_create(&uuid, GATT_INCLUDE_UUID);
	att_put_u16(0x0500, &atval[0]);
	att_put_u16(0x0504, &atval[2]);
	att_put_u16(MANUFACTURER_SVC_UUID, &atval[4]);
	attrib_db_add(0x0201, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);

	/* Thermometer: Include */
	att_put_u16(0x0550, &atval[0]);
	att_put_u16(0x0568, &atval[2]);
	attrib_db_add(0x0202, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 4);

	/* Thermometer: temperature characteristic */
	sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
	atval[0] = ATT_CHAR_PROPER_READ;
	att_put_u16(0x0204, &atval[1]);
	att_put_u16(TEMPERATURE_UUID, &atval[3]);
	attrib_db_add(0x0203, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);

	/* Thermometer: temperature characteristic value */
	sdp_uuid16_create(&uuid, TEMPERATURE_UUID);
	atval[0] = 0x8A;
	atval[1] = 0x02;
	attrib_db_add(0x0204, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);

	/* Thermometer: temperature characteristic format */
	sdp_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
	atval[0] = 0x0E;
	atval[1] = 0xFE;
	att_put_u16(FMT_CELSIUS_UUID, &atval[2]);
	atval[4] = 0x01;
	att_put_u16(FMT_OUTSIDE_UUID, &atval[5]);
	attrib_db_add(0x0205, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 7);

	/* Thermometer: characteristic user description */
	sdp_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
	len = strlen(desc_out_temp);
	strncpy((char *) atval, desc_out_temp, len);
	attrib_db_add(0x0206, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);

	/* Thermometer: relative humidity characteristic */
	sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
	atval[0] = ATT_CHAR_PROPER_READ;
	att_put_u16(0x0212, &atval[1]);
	att_put_u16(RELATIVE_HUMIDITY_UUID, &atval[3]);
	attrib_db_add(0x0210, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);

	/* Thermometer: relative humidity value */
	sdp_uuid16_create(&uuid, RELATIVE_HUMIDITY_UUID);
	atval[0] = 0x27;
	attrib_db_add(0x0212, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 1);

	/* Thermometer: relative humidity characteristic format */
	sdp_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
	atval[0] = 0x04;
	atval[1] = 0x00;
	att_put_u16(FMT_PERCENT_UUID, &atval[2]);
	att_put_u16(BLUETOOTH_SIG_UUID, &atval[4]);
	att_put_u16(FMT_OUTSIDE_UUID, &atval[6]);
	attrib_db_add(0x0213, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 8);

	/* Thermometer: characteristic user description */
	sdp_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
	len = strlen(desc_out_hum);
	strncpy((char *) atval, desc_out_hum, len);
	attrib_db_add(0x0214, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);

	/* Secondary Service: Manufacturer Service */
	sdp_uuid16_create(&uuid, GATT_SND_SVC_UUID);
	att_put_u16(MANUFACTURER_SVC_UUID, &atval[0]);
	attrib_db_add(0x0500, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);

	/* Manufacturer name characteristic definition */
	sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
	atval[0] = ATT_CHAR_PROPER_READ;
	att_put_u16(0x0502, &atval[1]);
	att_put_u16(MANUFACTURER_NAME_UUID, &atval[3]);
	attrib_db_add(0x0501, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);

	/* Manufacturer name characteristic value */
	sdp_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
	len = strlen(manufacturer_name1);
	strncpy((char *) atval, manufacturer_name1, len);
	attrib_db_add(0x0502, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);

	/* Manufacturer serial number characteristic */
	sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
	atval[0] = ATT_CHAR_PROPER_READ;
	att_put_u16(0x0504, &atval[1]);
	att_put_u16(MANUFACTURER_SERIAL_UUID, &atval[3]);
	attrib_db_add(0x0503, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);

	/* Manufacturer serial number characteristic value */
	sdp_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
	len = strlen(serial1);
	strncpy((char *) atval, serial1, len);
	attrib_db_add(0x0504, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);

	/* Secondary Service: Manufacturer Service */
	sdp_uuid16_create(&uuid, GATT_SND_SVC_UUID);
	att_put_u16(MANUFACTURER_SVC_UUID, &atval[0]);
	attrib_db_add(0x0505, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);

	/* Manufacturer name characteristic definition */
	sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
	atval[0] = ATT_CHAR_PROPER_READ;
	att_put_u16(0x0507, &atval[1]);
	att_put_u16(MANUFACTURER_NAME_UUID, &atval[3]);
	attrib_db_add(0x0506, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);

	/* Secondary Service: Vendor Specific Service */
	sdp_uuid16_create(&uuid, GATT_SND_SVC_UUID);
	att_put_u16(VENDOR_SPECIFIC_SVC_UUID, &atval[0]);
	attrib_db_add(0x0550, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 2);

	/* Vendor Specific Type characteristic definition */
	sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
	atval[0] = ATT_CHAR_PROPER_READ;
	att_put_u16(0x0568, &atval[1]);
	att_put_u16(VENDOR_SPECIFIC_TYPE_UUID, &atval[3]);
	attrib_db_add(0x0560, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);

	/* Vendor Specific Type characteristic value */
	sdp_uuid16_create(&uuid, VENDOR_SPECIFIC_TYPE_UUID);
	atval[0] = 0x56;
	atval[1] = 0x65;
	atval[2] = 0x6E;
	atval[3] = 0x64;
	atval[4] = 0x6F;
	atval[5] = 0x72;
	attrib_db_add(0x0568, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);

	/* Manufacturer name attribute */
	sdp_uuid16_create(&uuid, MANUFACTURER_NAME_UUID);
	len = strlen(manufacturer_name2);
	strncpy((char *) atval, manufacturer_name2, len);
	attrib_db_add(0x0507, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);

	/* Characteristic: serial number */
	sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
	atval[0] = ATT_CHAR_PROPER_READ;
	att_put_u16(0x0509, &atval[1]);
	att_put_u16(MANUFACTURER_SERIAL_UUID, &atval[3]);
	attrib_db_add(0x0508, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 5);

	/* Serial number characteristic value */
	sdp_uuid16_create(&uuid, MANUFACTURER_SERIAL_UUID);
	len = strlen(serial2);
	strncpy((char *) atval, serial2, len);
	attrib_db_add(0x0509, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);

	/* Weight service: primary service definition */
	sdp_uuid16_create(&uuid, GATT_PRIM_SVC_UUID);
	memcpy(atval, prim_weight_uuid, 16);
	attrib_db_add(0x0680, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 16);

	/* Weight: include */
	sdp_uuid16_create(&uuid, GATT_INCLUDE_UUID);
	att_put_u16(0x0505, &atval[0]);
	att_put_u16(0x0509, &atval[2]);
	att_put_u16(MANUFACTURER_SVC_UUID, &atval[4]);
	attrib_db_add(0x0681, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 6);

	/* Weight: characteristic */
	sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
	atval[0] = ATT_CHAR_PROPER_READ;
	att_put_u16(0x0683, &atval[1]);
	memcpy(&atval[3], char_weight_uuid, 16);
	attrib_db_add(0x0682, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 19);

	/* Weight: characteristic value */
	sdp_uuid128_create(&uuid, char_weight_uuid);
	atval[0] = 0x82;
	atval[1] = 0x55;
	atval[2] = 0x00;
	atval[3] = 0x00;
	attrib_db_add(0x0683, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 4);

	/* Weight: characteristic format */
	sdp_uuid16_create(&uuid, GATT_CHARAC_FMT_UUID);
	atval[0] = 0x08;
	atval[1] = 0xFD;
	att_put_u16(FMT_KILOGRAM_UUID, &atval[2]);
	att_put_u16(BLUETOOTH_SIG_UUID, &atval[4]);
	att_put_u16(FMT_HANGING_UUID, &atval[6]);
	attrib_db_add(0x0684, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, 8);

	/* Weight: characteristic user description */
	sdp_uuid16_create(&uuid, GATT_CHARAC_USER_DESC_UUID);
	len = strlen(desc_weight);
	strncpy((char *) atval, desc_weight, len);
	attrib_db_add(0x0685, &uuid, ATT_NONE, ATT_NOT_PERMITTED, atval, len);

	return 0;
}
コード例 #29
0
ファイル: sdp_server.c プロジェクト: zhenyouluo/sdp_server
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;
}
コード例 #30
0
ファイル: sdp.c プロジェクト: kim0051/HIDSlave
/*
 *  add keyboard descriptor
 */
void sdp_add_keyboard()
{
	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 *channel, *lang_lst, *lang_lst2, *hid_spec_lst, *hid_spec_lst2;
	int i;
	uint8_t dtd = SDP_UINT16;
	uint8_t dtd2 = SDP_UINT8;
	uint8_t dtd_data = SDP_TEXT_STR8;
	sdp_session_t *session;
	void *dtds[2];
	void *values[2];
	void *dtds2[2];
	void *values2[2];
	int leng[2];
	uint8_t hid_spec_type = 0x22;
	uint16_t hid_attr_lang[] = {0x409,0x100};
	static const uint8_t ctrl = 0x11;
	static const uint8_t intr = 0x13;
	static const uint16_t hid_attr[] = {0x100,0x111,0x40,0x0d,0x01,0x01};
	static const uint16_t hid_attr2[] = {0x0,0x01,0x100,0x1f40,0x01,0x01};
	// taken from Apple Wireless Keyboard
	const uint8_t hid_spec[] = { 
		0x05, 0x01, // usage page
		0x09, 0x06, // keyboard
		0xa1, 0x01, // key codes
		0x85, 0x01, // minimum
		0x05, 0x07, // max
		0x19, 0xe0, // logical min
		0x29, 0xe7, // logical max
		0x15, 0x00, // report size
		0x25, 0x01, // report count
		0x75, 0x01, // input data variable absolute
		0x95, 0x08, // report count
		0x81, 0x02, // report size
		0x75, 0x08, 
		0x95, 0x01, 
		0x81, 0x01, 
		0x75, 0x01, 
		0x95, 0x05,
		0x05, 0x08,
		0x19, 0x01,
		0x29, 0x05, 
		0x91, 0x02,
		0x75, 0x03,
		0x95, 0x01,
		0x91, 0x01,
		0x75, 0x08,
		0x95, 0x06,
		0x15, 0x00,
		0x26, 0xff,
		0x00, 0x05,
		0x07, 0x19,
		0x00, 0x2a,
		0xff, 0x00,
		0x81, 0x00,
		0x75, 0x01,
		0x95, 0x01,
		0x15, 0x00,
		0x25, 0x01,
		0x05, 0x0c,
		0x09, 0xb8,
		0x81, 0x06,
		0x09, 0xe2,
		0x81, 0x06,
		0x09, 0xe9,
		0x81, 0x02,
		0x09, 0xea,
		0x81, 0x02,
		0x75, 0x01,
		0x95, 0x04,
		0x81, 0x01,
		0xc0         // end tag
	};


	if (!sdp_session) {
		printf("%s: sdp_session invalid\n", (char*)__func__);
		exit(-1);
	}
	session = sdp_session;

	sdp_record = sdp_record_alloc();
	if (!sdp_record) {
		perror("add_keyboard sdp_record_alloc: ");
		exit(-1);
	}

	memset((void*)sdp_record, 0, sizeof(sdp_record_t));
	sdp_record->handle = 0xffffffff;
	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
	root = sdp_list_append(0, &root_uuid);
	sdp_set_browse_groups(sdp_record, root);

	add_lang_attr(sdp_record);
	
	sdp_uuid16_create(&hidkb_uuid, HID_SVCLASS_ID);
	svclass_id = sdp_list_append(0, &hidkb_uuid);
	sdp_set_service_classes(sdp_record, svclass_id);

	sdp_uuid16_create(&profile[0].uuid, HID_PROFILE_ID);
	profile[0].version = 0x0100;
	pfseq = sdp_list_append(0, profile);
	sdp_set_profile_descs(sdp_record, pfseq);

	// PROTO
	sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
	proto[1] = sdp_list_append(0, &l2cap_uuid);
	channel = sdp_data_alloc(SDP_UINT8, &ctrl);
	proto[1] = sdp_list_append(proto[1], channel);
	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_access_protos(sdp_record, aproto);

	// ATTR_ADD_PROTO
	proto[1] = sdp_list_append(0, &l2cap_uuid);
	channel = sdp_data_alloc(SDP_UINT8, &intr);
	proto[1] = sdp_list_append(proto[1], channel);
	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(sdp_record, aproto);
	
	sdp_set_info_attr(sdp_record, "Collin's Fake Bluetooth Keyboard", 
		"MUlliNER.ORG", "http://www.mulliner.org/bluetooth/");

	for (i = 0; i < sizeof(hid_attr)/2; i++) {
		sdp_attr_add_new(sdp_record, SDP_ATTR_HID_DEVICE_RELEASE_NUMBER+i, SDP_UINT16, &hid_attr[i]);
	}

	dtds[0] = &dtd2;
	values[0] = &hid_spec_type;
	dtds[1] = &dtd_data;
	values[1] = (uint8_t*)hid_spec;
	leng[0] = 0;
	leng[1] = sizeof(hid_spec);
	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(sdp_record, SDP_ATTR_HID_DESCRIPTOR_LIST, hid_spec_lst2);
	
	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(sdp_record, SDP_ATTR_HID_LANG_ID_BASE_LIST, lang_lst2);

	sdp_attr_add_new(sdp_record, SDP_ATTR_HID_SDP_DISABLE, SDP_UINT16, &hid_attr2[0]);
	for (i = 0; i < sizeof(hid_attr2)/2-1; i++) {
		sdp_attr_add_new(sdp_record, SDP_ATTR_HID_REMOTE_WAKEUP+i, SDP_UINT16, &hid_attr2[i+1]);
	}
	
	if (sdp_record_register(session, sdp_record, 0) < 0) {
		printf("%s: HID Device (Keyboard) Service Record registration failed\n", (char*)__func__);
		exit(-1);
	}
}