summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--audio/main.c6
-rw-r--r--hcid/adapter.c60
-rw-r--r--hcid/device.c57
-rw-r--r--hcid/device.h4
-rw-r--r--input/main.c2
-rw-r--r--network/main.c2
-rw-r--r--serial/main.c2
7 files changed, 105 insertions, 28 deletions
diff --git a/audio/main.c b/audio/main.c
index 2ea2a1a3..8e4c8055 100644
--- a/audio/main.c
+++ b/audio/main.c
@@ -43,7 +43,7 @@
static DBusConnection *conn;
-static int headset_probe(struct btd_device *device)
+static int headset_probe(struct btd_device *device, GSList *records)
{
const gchar *path = device_get_path(device);
DBG("path %s", path);
@@ -64,7 +64,7 @@ static struct btd_device_driver headset_driver = {
.remove = headset_remove,
};
-static int a2dp_probe(struct btd_device *device)
+static int a2dp_probe(struct btd_device *device, GSList *records)
{
const gchar *path = device_get_path(device);
DBG("path %s", path);
@@ -85,7 +85,7 @@ static struct btd_device_driver a2dp_driver = {
.remove = a2dp_remove,
};
-static int audio_probe(struct btd_device *device)
+static int audio_probe(struct btd_device *device, GSList *records)
{
const gchar *path = device_get_path(device);
DBG("path %s", path);
diff --git a/hcid/adapter.c b/hcid/adapter.c
index 7b655fda..2d0d6e21 100644
--- a/hcid/adapter.c
+++ b/hcid/adapter.c
@@ -74,6 +74,11 @@
static DBusConnection *connection = NULL;
+struct record_list {
+ sdp_list_t *recs;
+ const gchar *addr;
+};
+
struct mode_req {
struct adapter *adapter;
DBusConnection *conn; /* Connection reference */
@@ -2115,24 +2120,67 @@ static int active_conn_append(GSList **list, bdaddr_t *bdaddr,
return 0;
}
+static void create_stored_records_from_keys(char *key, char *value,
+ void *user_data)
+{
+ struct record_list *rec_list = user_data;
+ const gchar *addr = rec_list->addr;
+ sdp_record_t *rec;
+ int size, i, len;
+ uint8_t *pdata;
+ char tmp[3] = "";
+
+ if (strstr(key, addr) == NULL)
+ return;
+
+ size = strlen(value)/2;
+ pdata = g_malloc0(size);
+
+ for (i = 0; i < size; i++) {
+ memcpy(tmp, value + (i*2), 2);
+ pdata[i] = (uint8_t) strtol(tmp, NULL, 16);
+ }
+
+ rec = sdp_extract_pdu(pdata, &len);
+ free(pdata);
+
+ rec_list->recs = sdp_list_append(rec_list->recs, rec);
+}
+
static void create_stored_device_from_profiles(char *key, char *value,
void *user_data)
{
+ char filename[PATH_MAX + 1];
struct adapter *adapter = user_data;
GSList *uuids = bt_string2list(value);
struct btd_device *device;
+ const gchar *src;
+ struct record_list rec_list;
if (g_slist_find_custom(adapter->devices,
key, (GCompareFunc) device_address_cmp))
return;
device = device_create(connection, adapter, key);
- if (device) {
- device_set_temporary(device, FALSE);
- adapter->devices = g_slist_append(adapter->devices, device);
- device_probe_drivers(device, uuids);
- g_slist_free(uuids);
- }
+ if (!device)
+ return;
+
+ device_set_temporary(device, FALSE);
+ adapter->devices = g_slist_append(adapter->devices, device);
+
+ src = adapter->address;
+ rec_list.addr = device_get_address(device);
+ rec_list.recs = NULL;
+
+ create_name(filename, PATH_MAX, STORAGEDIR, src, "sdp");
+ textfile_foreach(filename, create_stored_records_from_keys, &rec_list);
+
+ device_probe_drivers(device, uuids, rec_list.recs);
+
+ if (rec_list.recs != NULL)
+ sdp_list_free(rec_list.recs, (sdp_free_func_t) sdp_record_free);
+
+ g_slist_free(uuids);
}
static void create_stored_device_from_linkkeys(char *key, char *value,
diff --git a/hcid/device.c b/hcid/device.c
index 85b469c1..cfbab920 100644
--- a/hcid/device.c
+++ b/hcid/device.c
@@ -572,14 +572,35 @@ gint device_address_cmp(struct btd_device *device, const gchar *address)
return strcasecmp(device->address, address);
}
-static int cmp_by_name(const void *data, const void *user_data)
+sdp_record_t *get_record(sdp_list_t *recs, const char *uuid)
{
- const struct btd_device_driver *dev_driver = data, *driver = user_data;
+ 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)
+ continue;
- return (strcmp(dev_driver->name, driver->name));
+ 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;
}
-void device_probe_drivers(struct btd_device *device, GSList *uuids)
+void device_probe_drivers(struct btd_device *device, GSList *uuids, sdp_list_t *recs)
{
GSList *list;
const char **uuid;
@@ -589,21 +610,20 @@ void device_probe_drivers(struct btd_device *device, GSList *uuids)
for (list = drivers; list; list = list->next) {
struct btd_device_driver *driver = list->data;
- gboolean do_probe = FALSE;
+ GSList *records = NULL;
for (uuid = driver->uuids; *uuid; uuid++) {
GSList *match = g_slist_find_custom(uuids, *uuid,
(GCompareFunc) strcasecmp);
if (match) {
- do_probe = TRUE;
- break;
+ sdp_record_t *rec = get_record(recs, *uuid);
+
+ records = g_slist_append(records, rec);
}
}
- if (do_probe == TRUE && !g_slist_find_custom(device->drivers,
- driver, (GCompareFunc) cmp_by_name)) {
-
- err = driver->probe(device);
+ if (records) {
+ err = driver->probe(device, records);
if (err < 0) {
error("probe failed for driver %s",
driver->name);
@@ -620,8 +640,11 @@ void device_probe_drivers(struct btd_device *device, GSList *uuids)
list->data, (GCompareFunc) strcmp);
}
-void device_remove_drivers(struct btd_device *device, GSList *uuids)
+void device_remove_drivers(struct btd_device *device, GSList *uuids, sdp_list_t *recs)
{
+ struct adapter *adapter = device_get_adapter(device);
+ const gchar *src = adapter->address;
+ const gchar *dst = device_get_address(device);
GSList *list;
debug("Remove drivers for %s", device->path);
@@ -640,6 +663,8 @@ void device_remove_drivers(struct btd_device *device, GSList *uuids)
driver->remove(device);
device->drivers = g_slist_remove(device->drivers,
driver);
+ sdp_record_t *rec = get_record(recs, *uuid);
+ delete_record(src, dst, rec->handle);
}
}
@@ -760,6 +785,9 @@ static void services_changed(struct browse_req *req)
static void update_services(struct browse_req *req, sdp_list_t *recs)
{
struct btd_device *device = req->device;
+ struct adapter *adapter = device_get_adapter(device);
+ const gchar *src = adapter->address;
+ const gchar *dst = device_get_address(device);
sdp_list_t *seq;
for (seq = recs; seq; seq = seq->next) {
@@ -773,6 +801,7 @@ static void update_services(struct browse_req *req, sdp_list_t *recs)
if (sdp_get_service_classes(rec, &svcclass) < 0)
continue;
+ store_record(src, dst, rec);
/* Extract the first element and skip the remainning */
uuid_str = bt_uuid2string(svcclass->data);
@@ -846,11 +875,11 @@ probe:
/* Probe matching drivers for services added */
if (req->uuids_added)
- device_probe_drivers(device, req->uuids_added);
+ device_probe_drivers(device, req->uuids_added, recs);
/* Remove drivers for services removed */
if (req->uuids_removed)
- device_remove_drivers(device, req->uuids_removed);
+ device_remove_drivers(device, req->uuids_removed, recs);
/* Store the device's profiles in the filesystem */
store(device);
diff --git a/hcid/device.h b/hcid/device.h
index 0e6944b3..bbb0846f 100644
--- a/hcid/device.h
+++ b/hcid/device.h
@@ -30,7 +30,7 @@ void device_remove(DBusConnection *conn, struct btd_device *device);
gint device_address_cmp(struct btd_device *device, const gchar *address);
int device_browse(struct btd_device *device, DBusConnection *conn,
DBusMessage *msg, uuid_t *search);
-void device_probe_drivers(struct btd_device *device, GSList *uuids);
+void device_probe_drivers(struct btd_device *device, GSList *uuids, sdp_list_t *recs);
struct adapter *device_get_adapter(struct btd_device *device);
const gchar *device_get_address(struct btd_device *device);
const gchar *device_get_path(struct btd_device *device);
@@ -48,7 +48,7 @@ uint8_t device_get_auth(struct btd_device *device);
struct btd_device_driver {
const char *name;
const char **uuids;
- int (*probe) (struct btd_device *device);
+ int (*probe) (struct btd_device *device, GSList *records);
void (*remove) (struct btd_device *device);
};
diff --git a/input/main.c b/input/main.c
index 713335ee..8462967a 100644
--- a/input/main.c
+++ b/input/main.c
@@ -76,7 +76,7 @@ static GDBusSignalTable input_signals[] = {
static DBusConnection *conn;
-static int input_probe(struct btd_device *device)
+static int input_probe(struct btd_device *device, GSList *records)
{
const gchar *path = device_get_path(device);
DBG("path %s", path);
diff --git a/network/main.c b/network/main.c
index 219c4417..4fcf5192 100644
--- a/network/main.c
+++ b/network/main.c
@@ -83,7 +83,7 @@ static GDBusSignalTable network_signals[] = {
static DBusConnection *conn;
-static int network_probe(struct btd_device *device)
+static int network_probe(struct btd_device *device, GSList *records)
{
const gchar *path = device_get_path(device);
DBG("path %s", path);
diff --git a/serial/main.c b/serial/main.c
index 518649e0..7a8d01f3 100644
--- a/serial/main.c
+++ b/serial/main.c
@@ -97,7 +97,7 @@ static GDBusMethodTable serial_methods[] = {
static DBusConnection *conn;
-static int serial_probe(struct btd_device *device)
+static int serial_probe(struct btd_device *device, GSList *records)
{
const gchar *path = device_get_path(device);
DBG("path %s", path);