| From 3cfdaba109ba7e2496759ed9d007a0934947a182 Mon Sep 17 00:00:00 2001 |
| From: Alex Deymo <deymo@chromium.org> |
| Date: Tue, 26 Feb 2013 19:40:52 -0800 |
| Subject: [PATCH] Add GetCachedServices to device API. |
| |
| This fix implements a new GetCachedServices() function with similar |
| functionality as DiscoverServices(), except it only retrieves information |
| from an internal cache. |
| |
| diff --git a/doc/device-api.txt b/doc/device-api.txt |
| index e8fc314..bcdfcab 100644 |
| --- a/doc/device-api.txt |
| +++ b/doc/device-api.txt |
| @@ -47,6 +47,25 @@ Methods dict GetProperties() |
| org.bluez.Error.Failed |
| org.bluez.Error.InProgress |
| |
| + dict GetCachedServices(string pattern) |
| + |
| + This method is similar to DiscoverServices(pattern) |
| + except that the retrieved service records are from |
| + an internal cache instead of initiating a remote |
| + service discovery. This cache is updated every time |
| + DiscoverServices() returns any result. The pattern |
| + parameter can be used to specify specific UUIDs. |
| + An empty string will return all the records known for |
| + this device. |
| + |
| + The return value is a dictionary with the record |
| + handles as keys and the service record in XML format |
| + as values. The key is uint32 and the value a string |
| + for this dictionary. If the cache is empty, an empty |
| + dictionary is returned. |
| + |
| + Possible errors: org.bluez.Error.InvalidArguments |
| + |
| void CancelDiscovery() |
| |
| This method will cancel any previous DiscoverServices |
| diff --git a/src/device.c b/src/device.c |
| index e55f1de..648f93f 100644 |
| --- a/src/device.c |
| +++ b/src/device.c |
| @@ -186,6 +186,9 @@ static uint16_t uuid_list[] = { |
| |
| static GSList *device_drivers = NULL; |
| |
| +static DBusMessage *build_services_reply(struct browse_req *req, int err, |
| + sdp_list_t *recs); |
| + |
| static void browse_request_free(struct browse_req *req) |
| { |
| if (req->listener_id) |
| @@ -669,6 +672,62 @@ static void discover_services_req_exit(DBusConnection *conn, void *user_data) |
| browse_request_cancel(req); |
| } |
| |
| +static DBusMessage *device_cached_sdp(struct btd_device *device, |
| + DBusConnection *conn, DBusMessage *msg, uuid_t *search) |
| +{ |
| + DBusMessage *reply = NULL; |
| + struct btd_adapter *adapter = device->adapter; |
| + struct browse_req *req; |
| + sdp_list_t *records; |
| + bdaddr_t src; |
| + |
| + if (!msg) |
| + return NULL; |
| + |
| + adapter_get_address(adapter, &src); |
| + |
| + req = g_new0(struct browse_req, 1); |
| + req->device = btd_device_ref(device); |
| + |
| + if (conn == NULL) |
| + conn = get_dbus_connection(); |
| + req->conn = dbus_connection_ref(conn); |
| + req->msg = dbus_message_ref(msg); |
| + |
| + if (search) { |
| + sdp_list_t *tmp_records = NULL; |
| + sdp_record_t *rec = NULL; |
| + gchar *uuid; |
| + tmp_records = read_records(&src, &device->bdaddr); |
| + |
| + uuid = bt_uuid2string(search); |
| + if (uuid) |
| + rec = find_record_in_list(tmp_records, uuid); |
| + if (rec) { |
| + records = sdp_list_append(NULL, rec); |
| + tmp_records = sdp_list_remove(tmp_records, rec); |
| + } else |
| + records = NULL; |
| + |
| + if (tmp_records) |
| + sdp_list_free(tmp_records, |
| + (sdp_free_func_t) sdp_record_free); |
| + if (uuid) |
| + g_free(uuid); |
| + } else { |
| + records = read_records(&src, &device->bdaddr); |
| + } |
| + |
| + reply = build_services_reply(req, 0, records); |
| + |
| + if (records) |
| + sdp_list_free(records, (sdp_free_func_t) sdp_record_free); |
| + |
| + browse_request_free(req); |
| + |
| + return reply; |
| +} |
| + |
| static DBusMessage *discover_services(DBusConnection *conn, |
| DBusMessage *msg, void *user_data) |
| { |
| @@ -706,6 +765,33 @@ fail: |
| return btd_error_failed(msg, strerror(-err)); |
| } |
| |
| +static DBusMessage *get_cached_services(DBusConnection *conn, |
| + DBusMessage *msg, void *user_data) |
| +{ |
| + struct btd_device *device = user_data; |
| + const char *pattern; |
| + DBusMessage *reply = NULL; |
| + |
| + if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &pattern, |
| + DBUS_TYPE_INVALID) == FALSE) |
| + return btd_error_invalid_args(msg); |
| + |
| + if (strlen(pattern) == 0) { |
| + reply = device_cached_sdp(device, conn, msg, NULL); |
| + } else { |
| + uuid_t uuid; |
| + |
| + if (bt_string2uuid(&uuid, pattern) < 0) |
| + return btd_error_invalid_args(msg); |
| + |
| + sdp_uuid128_to_uuid(&uuid); |
| + |
| + reply = device_cached_sdp(device, conn, msg, &uuid); |
| + } |
| + |
| + return reply; |
| +} |
| + |
| static const char *browse_request_get_requestor(struct browse_req *req) |
| { |
| if (!req->msg) |
| @@ -729,7 +815,7 @@ static void iter_append_record(DBusMessageIter *dict, uint32_t handle, |
| dbus_message_iter_close_container(dict, &entry); |
| } |
| |
| -static void discover_services_reply(struct browse_req *req, int err, |
| +static DBusMessage *build_services_reply(struct browse_req *req, int err, |
| sdp_list_t *recs) |
| { |
| DBusMessage *reply; |
| @@ -746,13 +832,12 @@ static void discover_services_reply(struct browse_req *req, int err, |
| |
| reply = dbus_message_new_error(req->msg, err_if, |
| strerror(-err)); |
| - g_dbus_send_message(req->conn, reply); |
| - return; |
| + return reply; |
| } |
| |
| reply = dbus_message_new_method_return(req->msg); |
| if (!reply) |
| - return; |
| + return NULL; |
| |
| dbus_message_iter_init_append(reply, &iter); |
| |
| @@ -781,7 +866,17 @@ static void discover_services_reply(struct browse_req *req, int err, |
| |
| dbus_message_iter_close_container(&iter, &dict); |
| |
| - g_dbus_send_message(req->conn, reply); |
| + return reply; |
| +} |
| + |
| +static void discover_services_reply(struct browse_req *req, int err, |
| + sdp_list_t *recs) |
| +{ |
| + DBusMessage *reply; |
| + |
| + reply = build_services_reply(req, err, recs); |
| + if (reply) |
| + g_dbus_send_message(req->conn, reply); |
| } |
| |
| static DBusMessage *cancel_discover(DBusConnection *conn, |
| @@ -888,6 +983,7 @@ static GDBusMethodTable device_methods[] = { |
| { "SetProperty", "sv", "", set_property }, |
| { "DiscoverServices", "s", "a{us}", discover_services, |
| G_DBUS_METHOD_FLAG_ASYNC}, |
| + { "GetCachedServices", "s", "a{us}", get_cached_services}, |
| { "CancelDiscovery", "", "", cancel_discover }, |
| { "Disconnect", "", "", disconnect, |
| G_DBUS_METHOD_FLAG_ASYNC}, |