예제 #1
0
gboolean gatt_parse_record(const sdp_record_t *rec,
					uuid_t *prim_uuid, uint16_t *psm,
					uint16_t *start, uint16_t *end)
{
	sdp_list_t *list;
	uuid_t uuid;
	gboolean ret;

	if (sdp_get_service_classes(rec, &list) < 0)
		return FALSE;

	memcpy(&uuid, list->data, sizeof(uuid));
	sdp_list_free(list, free);

	if (sdp_get_access_protos(rec, &list) < 0)
		return FALSE;

	ret = parse_proto_params(list, psm, start, end);

	sdp_list_foreach(list, (sdp_list_func_t) sdp_list_free, NULL);
	sdp_list_free(list, NULL);

	/* FIXME: replace by bt_uuid_t after uuid_t/sdp code cleanup */
	if (ret && prim_uuid)
		memcpy(prim_uuid, &uuid, sizeof(uuid_t));

	return ret;
}
예제 #2
0
static gboolean set_sdp_services_uuid(sdp_record_t *record, HdpRole role)
{
	uuid_t svc_uuid_source, svc_uuid_sink;
	sdp_list_t *svc_list = NULL;

	sdp_uuid16_create(&svc_uuid_sink, HDP_SINK_SVCLASS_ID);
	sdp_uuid16_create(&svc_uuid_source, HDP_SOURCE_SVCLASS_ID);

	sdp_get_service_classes(record, &svc_list);

	if (role == HDP_SOURCE) {
		if (!sdp_list_find(svc_list, &svc_uuid_source, sdp_uuid_cmp))
			svc_list = sdp_list_append(svc_list, &svc_uuid_source);
	} else if (role == HDP_SINK) {
		if (!sdp_list_find(svc_list, &svc_uuid_sink, sdp_uuid_cmp))
			svc_list = sdp_list_append(svc_list, &svc_uuid_sink);
	}

	if (sdp_set_service_classes(record, svc_list) < 0) {
		sdp_list_free(svc_list, NULL);
		return FALSE;
	}

	sdp_list_free(svc_list, NULL);

	return TRUE;
}
예제 #3
0
파일: health.c 프로젝트: ghent360/bluez
static int set_sdp_services_uuid(sdp_record_t *rec, uint8_t role)
{
	uuid_t source, sink;
	sdp_list_t *list = NULL;

	sdp_uuid16_create(&sink, HDP_SINK_SVCLASS_ID);
	sdp_uuid16_create(&source, HDP_SOURCE_SVCLASS_ID);
	sdp_get_service_classes(rec, &list);

	switch (role) {
	case HAL_HEALTH_MDEP_ROLE_SOURCE:
		if (!sdp_list_find(list, &source, sdp_uuid_cmp))
			list = sdp_list_append(list, &source);
		break;
	case HAL_HEALTH_MDEP_ROLE_SINK:
		if (!sdp_list_find(list, &sink, sdp_uuid_cmp))
			list = sdp_list_append(list, &sink);
		break;
	}

	if (sdp_set_service_classes(rec, list) < 0) {
		sdp_list_free(list, NULL);
		return -1;
	}

	sdp_list_free(list, NULL);

	return 0;
}
예제 #4
0
sdp_record_t *find_record_in_list(sdp_list_t *recs, const char *uuid)
{
	sdp_list_t *seq;

	for (seq = recs; seq; seq = seq->next) {
		sdp_record_t *rec = (sdp_record_t *) seq->data;
		sdp_list_t *svcclass = NULL;
		char *uuid_str;

		if (sdp_get_service_classes(rec, &svcclass) < 0)
			continue;

		/* Extract the uuid */
		uuid_str = bt_uuid2string(svcclass->data);
		if (!uuid_str) {
			sdp_list_free(svcclass, free);
			continue;
		}

		if (!strcasecmp(uuid_str, uuid)) {
			sdp_list_free(svcclass, free);
			free(uuid_str);
			return rec;
		}

		sdp_list_free(svcclass, free);
		free(uuid_str);
	}
	return NULL;
}
예제 #5
0
/*
 * utility function to perform an SDP search on a connected session.  Builds
 * and returns a python list of dictionaries.  Each dictionary represents a
 * service record match
 */
static PyObject *
do_search( sdp_session_t *sess, uuid_t *uuid )
{
    sdp_list_t *response_list = NULL, *attrid_list, *search_list, *r;
    uint32_t range = 0x0000ffff;
    char buf[1024] = { 0 };
    int err = 0;
    PyObject *result = 0;

    PyObject *rtn_list = PyList_New(0);
    if( ! rtn_list ) return 0;
    search_list = sdp_list_append( 0, uuid );
    attrid_list = sdp_list_append( 0, &range );

    // perform the search
    Py_BEGIN_ALLOW_THREADS
    err = sdp_service_search_attr_req( sess, search_list, \
                                       SDP_ATTR_REQ_RANGE, attrid_list, &response_list);
    Py_END_ALLOW_THREADS
    if( err ) {
        PyErr_SetFromErrno( bluetooth_error );
        result = 0;
        goto cleanup;
    }

    // parse the results (ewww....)

    // go through each of the service records
    for (r = response_list; r; r = r->next ) {
        PyObject *dict = PyDict_New();
        sdp_record_t *rec = (sdp_record_t*) r->data;
        sdp_list_t *proto_list = NULL,
                    *svc_class_list = NULL,
                     *profile_list = NULL;
        PyObject *py_class_list = NULL, *py_profile_list = NULL;
        uuid_t service_id = { 0 };

        if( ! dict ) return 0;

        // initialize service class list
        py_class_list = PyList_New(0);
        if( ! py_class_list ) return 0;
        dict_set_str_pyobj( dict, "service-classes", py_class_list );
        Py_DECREF( py_class_list );

        // initialize profile list
        py_profile_list = PyList_New(0);
        if( ! py_profile_list ) return 0;
        dict_set_str_pyobj( dict, "profiles", py_profile_list );
        Py_DECREF( py_profile_list );

        // set service name
        if( ! sdp_get_service_name( rec, buf, sizeof(buf) ) ) {
            dict_set_strings( dict, "name", buf );
            memset(buf, 0, sizeof( buf ) );
        } else {
            dict_set_str_pyobj( dict, "name", Py_None );
        }

        // set service description
        if( ! sdp_get_service_desc( rec, buf, sizeof(buf) ) ) {
            dict_set_strings( dict, "description", buf );
            memset(buf, 0, sizeof( buf ) );
        } else {
            dict_set_str_pyobj( dict, "description", Py_None );
        }

        // set service provider name
        if( ! sdp_get_provider_name( rec, buf, sizeof(buf) ) ) {
            dict_set_strings( dict, "provider", buf );
            memset(buf, 0, sizeof( buf ) );
        } else {
            dict_set_str_pyobj( dict, "provider", Py_None );
        }

        // set service id
        if( ! sdp_get_service_id( rec, &service_id ) ) {
            uuid2str( &service_id, buf );
            dict_set_strings( dict, "service-id", buf );
            memset(buf, 0, sizeof( buf ) );
        } else {
            dict_set_str_pyobj( dict, "service-id", Py_None );
        }

        // get a list of the protocol sequences
        if( sdp_get_access_protos( rec, &proto_list ) == 0 ) {
            sdp_list_t *p = proto_list;
            int port;

            if( ( port = sdp_get_proto_port( p, RFCOMM_UUID ) ) != 0 ) {
                dict_set_strings( dict, "protocol", "RFCOMM" );
                dict_set_str_long( dict, "port", port );
            } else if ( (port = sdp_get_proto_port( p, L2CAP_UUID ) ) != 0 ) {
                dict_set_strings( dict, "protocol", "L2CAP" );
                dict_set_str_long( dict, "port", port );
            } else {
                dict_set_strings( dict, "protocol", "UNKNOWN" );
                dict_set_str_pyobj( dict, "port", Py_None );
            }

            // sdp_get_access_protos allocates data on the heap for the
            // protocol list, so we need to free the results...
            for( ; p ; p = p->next ) {
                sdp_list_free( (sdp_list_t*)p->data, 0 );
            }
            sdp_list_free( proto_list, 0 );
        } else {
            dict_set_str_pyobj( dict, "protocol", Py_None );
            dict_set_str_pyobj( dict, "port", Py_None );
        }

        // get a list of the service classes
        if( sdp_get_service_classes( rec, &svc_class_list ) == 0 ) {
            sdp_list_t *iter;
            for( iter = svc_class_list; iter != NULL; iter = iter->next ) {
                PyObject *pystr;
                char uuid_str[40] = { 0 };

                uuid2str( (uuid_t*)iter->data, uuid_str );
                pystr = PyString_FromString( uuid_str );
                PyList_Append( py_class_list, pystr );
                Py_DECREF( pystr );
            }

            sdp_list_free( svc_class_list, free );
        }

        // get a list of the profiles
        if( sdp_get_profile_descs( rec, &profile_list ) == 0 ) {
            sdp_list_t *iter;
            for( iter = profile_list; iter != NULL; iter = iter->next ) {
                PyObject *tuple, *py_uuid, *py_version;
                sdp_profile_desc_t *desc = (sdp_profile_desc_t*)iter->data;
                char uuid_str[40] = { 0 };

                uuid2str( &desc->uuid, uuid_str );
                py_uuid = PyString_FromString( uuid_str );
                py_version = PyInt_FromLong( desc->version );

                tuple = PyTuple_New( 2 );
                PyList_Append( py_profile_list, tuple );
                Py_DECREF( tuple );

                PyTuple_SetItem( tuple, 0, py_uuid );
                PyTuple_SetItem( tuple, 1, py_version );
//                Py_DECREF( py_uuid );
//                Py_DECREF( py_version );
            }
            sdp_list_free( profile_list, free );
        }

        PyList_Append( rtn_list, dict );
        Py_DECREF( dict );

        sdp_record_free( rec );
    }

    result = rtn_list;

cleanup:
    sdp_list_free( response_list, 0 );
    sdp_list_free( search_list, 0 );
    sdp_list_free( attrid_list, 0 );
    return result;
}
예제 #6
0
파일: service.c 프로젝트: 520lly/bluez
static DBusMessage *request_authorization(DBusConnection *conn,
						DBusMessage *msg, void *data)
{
	struct record_data *user_record;
	struct service_adapter *serv_adapter = data;
	sdp_record_t *record;
	sdp_list_t *services;
	const char *sender;
	dbus_uint32_t handle;
	const char *address;
	struct pending_auth *auth;
	char uuid_str[MAX_LEN_UUID_STR];
	uuid_t *uuid, *uuid128;
	bdaddr_t src;

	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address,
					DBUS_TYPE_UINT32, &handle,
					DBUS_TYPE_INVALID) == FALSE)
		return NULL;

	sender = dbus_message_get_sender(msg);
	if (find_pending_by_sender(serv_adapter, sender))
		return btd_error_does_not_exist(msg);

	user_record = find_record(serv_adapter, handle, sender);
	if (!user_record) {
		user_record = find_record(serv_adapter_any, handle, sender);
		if (!user_record)
			return btd_error_not_authorized(msg);
	}

	record = sdp_record_find(user_record->handle);
	if (record == NULL)
		return btd_error_not_authorized(msg);

	if (sdp_get_service_classes(record, &services) < 0) {
		sdp_record_free(record);
		return btd_error_not_authorized(msg);
	}

	if (services == NULL)
		return btd_error_not_authorized(msg);

	uuid = services->data;
	uuid128 = sdp_uuid_to_uuid128(uuid);

	sdp_list_free(services, bt_free);

	if (sdp_uuid2strn(uuid128, uuid_str, MAX_LEN_UUID_STR) < 0) {
		bt_free(uuid128);
		return btd_error_not_authorized(msg);
	}
	bt_free(uuid128);

	auth = g_new0(struct pending_auth, 1);
	auth->msg = dbus_message_ref(msg);
	auth->conn = dbus_connection_ref(connection);
	auth->sender = user_record->sender;
	memcpy(auth->uuid, uuid_str, MAX_LEN_UUID_STR);
	str2ba(address, &auth->dst);

	serv_adapter->pending_list = g_slist_append(serv_adapter->pending_list,
									auth);

	auth = next_pending(serv_adapter);
	if (auth == NULL)
		return btd_error_does_not_exist(msg);

	if (serv_adapter->adapter)
		adapter_get_address(serv_adapter->adapter, &src);
	else
		bacpy(&src, BDADDR_ANY);

	if (btd_request_authorization(&src, &auth->dst, auth->uuid, auth_cb,
							serv_adapter) < 0) {
		serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list,
									auth);
		g_free(auth);
		return btd_error_not_authorized(msg);
	}

	return NULL;
}
예제 #7
0
파일: gateway.c 프로젝트: intgr/bluez
static void get_record_cb(sdp_list_t *recs, int err, gpointer user_data)
{
	struct audio_device *dev = user_data;
	struct gateway *gw = dev->gateway;
	int ch;
	sdp_list_t *protos, *classes;
	uuid_t uuid;
	GIOChannel *io;
	GError *gerr = NULL;

	if (err < 0) {
		error("Unable to get service record: %s (%d)", strerror(-err),
					-err);
		goto fail;
	}

	if (!recs || !recs->data) {
		error("No records found");
		err = -EIO;
		goto fail;
	}

	if (sdp_get_service_classes(recs->data, &classes) < 0) {
		error("Unable to get service classes from record");
		err = -EINVAL;
		goto fail;
	}

	if (sdp_get_access_protos(recs->data, &protos) < 0) {
		error("Unable to get access protocols from record");
		err = -ENODATA;
		goto fail;
	}

	gw->version = get_remote_profile_version(recs->data);
	if (gw->version == 0) {
		error("Unable to get profile version from record");
		err = -EINVAL;
		goto fail;
	}

	memcpy(&uuid, classes->data, sizeof(uuid));
	sdp_list_free(classes, free);

	if (!sdp_uuid128_to_uuid(&uuid) || uuid.type != SDP_UUID16 ||
			uuid.value.uuid16 != HANDSFREE_AGW_SVCLASS_ID) {
		sdp_list_free(protos, NULL);
		error("Invalid service record or not HFP");
		err = -EIO;
		goto fail;
	}

	ch = sdp_get_proto_port(protos, RFCOMM_UUID);
	sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL);
	sdp_list_free(protos, NULL);
	if (ch <= 0) {
		error("Unable to extract RFCOMM channel from service record");
		err = -EIO;
		goto fail;
	}

	io = bt_io_connect(rfcomm_connect_cb, dev, NULL, &gerr,
				BT_IO_OPT_SOURCE_BDADDR, &dev->src,
				BT_IO_OPT_DEST_BDADDR, &dev->dst,
				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
				BT_IO_OPT_CHANNEL, ch,
				BT_IO_OPT_INVALID);
	if (!io) {
		error("Unable to connect: %s", gerr->message);
		goto fail;
	}

	g_io_channel_unref(io);
	return;

fail:
	if (gw->msg) {
		DBusMessage *reply = btd_error_failed(gw->msg,
					gerr ? gerr->message : strerror(-err));
		g_dbus_send_message(btd_get_dbus_connection(), reply);
	}

	gateway_close(dev);

	if (gerr)
		g_error_free(gerr);
}