diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/adapter.c | 8 | ||||
-rw-r--r-- | src/device.c | 78 | ||||
-rw-r--r-- | src/device.h | 6 | ||||
-rw-r--r-- | src/storage.c | 22 | ||||
-rw-r--r-- | src/storage.h | 2 |
5 files changed, 81 insertions, 35 deletions
diff --git a/src/adapter.c b/src/adapter.c index 1e22b4b3..f983069e 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -2274,7 +2274,6 @@ static void create_stored_device_from_profiles(char *key, char *value, struct btd_adapter *adapter = user_data; GSList *uuids = bt_string2list(value); struct btd_device *device; - sdp_list_t *records; bdaddr_t dst; char srcaddr[18], dstaddr[18]; @@ -2294,12 +2293,7 @@ static void create_stored_device_from_profiles(char *key, char *value, device_get_address(device, &dst); ba2str(&dst, dstaddr); - records = read_records(srcaddr, dstaddr); - - device_probe_drivers(device, uuids, records); - - if (records) - sdp_list_free(records, (sdp_free_func_t) sdp_record_free); + device_probe_drivers(device, uuids); g_slist_free(uuids); } diff --git a/src/device.c b/src/device.c index 1e7747d6..3f70e647 100644 --- a/src/device.c +++ b/src/device.c @@ -87,6 +87,8 @@ struct btd_device { /* Whether were creating a security mode 3 connection */ gboolean secmode3; + + sdp_list_t *tmp_records; }; struct browse_req { @@ -616,7 +618,7 @@ gint device_address_cmp(struct btd_device *device, const gchar *address) return strcasecmp(addr, address); } -void device_probe_drivers(struct btd_device *device, GSList *uuids, sdp_list_t *recs) +void device_probe_drivers(struct btd_device *device, GSList *uuids) { GSList *list; const char **uuid; @@ -626,62 +628,70 @@ void device_probe_drivers(struct btd_device *device, GSList *uuids, sdp_list_t * for (list = device_drivers; list; list = list->next) { struct btd_device_driver *driver = list->data; - GSList *records = NULL; + GSList *probe_uuids = NULL; for (uuid = driver->uuids; *uuid; uuid++) { - sdp_record_t *rec; + GSList *match; - if (!g_slist_find_custom(uuids, *uuid, - (GCompareFunc) strcasecmp)) - continue; - - rec = find_record_in_list(recs, *uuid); - if (!rec) + match = g_slist_find_custom(uuids, *uuid, + (GCompareFunc) strcasecmp); + if (!match) continue; - records = g_slist_append(records, rec); + probe_uuids = g_slist_append(probe_uuids, match->data); } - if (records) { + if (probe_uuids) { struct btd_driver_data *driver_data = g_new0(struct btd_driver_data, 1); - err = driver->probe(device, records); + err = driver->probe(device, probe_uuids); if (err < 0) { error("probe failed for driver %s", driver->name); g_free(driver_data); + g_slist_free(probe_uuids); continue; } driver_data->driver = driver; device->drivers = g_slist_append(device->drivers, driver_data); + g_slist_free(probe_uuids); } } for (list = uuids; list; list = list->next) { GSList *l = g_slist_find_custom(device->uuids, list->data, - (GCompareFunc) strcmp); + (GCompareFunc) strcasecmp); if (l) continue; device->uuids = g_slist_insert_sorted(device->uuids, - list->data, (GCompareFunc) strcmp); + list->data, (GCompareFunc) strcasecmp); + } + + if (device->tmp_records) { + sdp_list_free(device->tmp_records, + (sdp_free_func_t) sdp_record_free); + device->tmp_records = NULL; } } -void device_remove_drivers(struct btd_device *device, GSList *uuids, sdp_list_t *recs) +void device_remove_drivers(struct btd_device *device, GSList *uuids) { struct btd_adapter *adapter = device_get_adapter(device); GSList *list, *next; char srcaddr[18], dstaddr[18]; bdaddr_t src; + sdp_list_t *records; adapter_get_address(adapter, &src); ba2str(&src, srcaddr); ba2str(&device->bdaddr, dstaddr); + records = read_records(&src, &device->bdaddr); + debug("Remove drivers for %s", device->path); for (list = device->drivers; list; list = next) { @@ -698,20 +708,29 @@ void device_remove_drivers(struct btd_device *device, GSList *uuids, sdp_list_t (GCompareFunc) strcasecmp)) continue; + debug("UUID %s was removed from device %s", dstaddr); + driver->remove(device); device->drivers = g_slist_remove(device->drivers, driver_data); g_free(driver_data); - rec = find_record_in_list(recs, *uuid); + + rec = find_record_in_list(records, *uuid); if (!rec) continue; delete_record(srcaddr, dstaddr, rec->handle); + + records = sdp_list_remove(records, rec); + sdp_record_free(rec); } } + if (records) + sdp_list_free(records, (sdp_free_func_t) sdp_record_free); + for (list = uuids; list; list = list->next) device->uuids = g_slist_remove(device->uuids, list->data); } @@ -994,13 +1013,19 @@ static void search_cb(sdp_list_t *recs, int err, gpointer user_data) goto proceed; } + if (device->tmp_records && req->records) { + sdp_list_free(device->tmp_records, (sdp_free_func_t) sdp_record_free); + device->tmp_records = req->records; + req->records = NULL; + } + /* Probe matching drivers for services added */ if (req->uuids_added) - device_probe_drivers(device, req->uuids_added, req->records); + device_probe_drivers(device, req->uuids_added); /* Remove drivers for services removed */ if (req->uuids_removed) - device_remove_drivers(device, req->uuids_removed, req->records); + device_remove_drivers(device, req->uuids_removed); /* Propagate services changes */ services_changed(req); @@ -1314,6 +1339,23 @@ int device_set_paired(DBusConnection *conn, struct btd_device *device, return 0; } +const sdp_record_t *btd_device_get_record(struct btd_device *device, + const char *uuid) +{ + bdaddr_t src; + + if (device->tmp_records) + return find_record_in_list(device->tmp_records, uuid); + + adapter_get_address(device->adapter, &src); + + device->tmp_records = read_records(&src, &device->bdaddr); + if (!device->tmp_records) + return NULL; + + return find_record_in_list(device->tmp_records, uuid); +} + int btd_register_device_driver(struct btd_device_driver *driver) { device_drivers = g_slist_append(device_drivers, driver); diff --git a/src/device.h b/src/device.h index a1fa15ab..e0d334f6 100644 --- a/src/device.h +++ b/src/device.h @@ -30,7 +30,9 @@ 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, gboolean reverse); -void device_probe_drivers(struct btd_device *device, GSList *uuids, sdp_list_t *recs); +void device_probe_drivers(struct btd_device *device, GSList *uuids); +const sdp_record_t *btd_device_get_record(struct btd_device *device, + const char *uuid); struct btd_adapter *device_get_adapter(struct btd_device *device); void device_get_address(struct btd_device *adapter, bdaddr_t *bdaddr); const gchar *device_get_path(struct btd_device *device); @@ -54,7 +56,7 @@ void device_set_secmode3_conn(struct btd_device *device, gboolean enable); struct btd_device_driver { const char *name; const char **uuids; - int (*probe) (struct btd_device *device, GSList *records); + int (*probe) (struct btd_device *device, GSList *uuids); void (*remove) (struct btd_device *device); }; diff --git a/src/storage.c b/src/storage.c index d048ddb4..d99fb33c 100644 --- a/src/storage.c +++ b/src/storage.c @@ -845,15 +845,19 @@ static void create_stored_records_from_keys(char *key, char *value, rec_list->recs = sdp_list_append(rec_list->recs, rec); } -sdp_list_t *read_records(const gchar *src, const gchar *dst) +sdp_list_t *read_records(bdaddr_t *src, bdaddr_t *dst) { char filename[PATH_MAX + 1]; struct record_list rec_list; + char srcaddr[18], dstaddr[18]; - rec_list.addr = dst; + ba2str(src, srcaddr); + ba2str(dst, dstaddr); + + rec_list.addr = dstaddr; rec_list.recs = NULL; - create_name(filename, PATH_MAX, STORAGEDIR, src, "sdp"); + create_name(filename, PATH_MAX, STORAGEDIR, srcaddr, "sdp"); textfile_foreach(filename, create_stored_records_from_keys, &rec_list); return rec_list.recs; @@ -952,16 +956,17 @@ static int read_device_id_from_did(const gchar *src, const gchar *dst, return 0; } -int read_device_id(const gchar *src, const gchar *dst, +int read_device_id(const gchar *srcaddr, const gchar *dstaddr, uint16_t *source, uint16_t *vendor, uint16_t *product, uint16_t *version) { uint16_t lsource, lvendor, lproduct, lversion; sdp_list_t *recs; sdp_record_t *rec; + bdaddr_t src, dst; int err; - err = read_device_id_from_did(src, dst, &lsource, + err = read_device_id_from_did(srcaddr, dstaddr, &lsource, vendor, product, version); if (!err) { if (lsource == 0xffff) @@ -970,7 +975,10 @@ int read_device_id(const gchar *src, const gchar *dst, return err; } - recs = read_records(src, dst); + str2ba(srcaddr, &src); + str2ba(dstaddr, &dst); + + recs = read_records(&src, &dst); rec = find_record_in_list(recs, PNP_UUID); if (rec) { @@ -1004,7 +1012,7 @@ int read_device_id(const gchar *src, const gchar *dst, lversion = 0x0000; } - store_device_id(src, dst, lsource, lvendor, lproduct, lversion); + store_device_id(srcaddr, dstaddr, lsource, lvendor, lproduct, lversion); if (err) return err; diff --git a/src/storage.h b/src/storage.h index d6008a40..bff36a7c 100644 --- a/src/storage.h +++ b/src/storage.h @@ -59,7 +59,7 @@ int delete_entry(bdaddr_t *src, const char *storage, const char *key); int store_record(const gchar *src, const gchar *dst, sdp_record_t *rec); sdp_record_t *fetch_record(const gchar *src, const gchar *dst, const uint32_t handle); int delete_record(const gchar *src, const gchar *dst, const uint32_t handle); -sdp_list_t *read_records(const gchar *src, const gchar *dst); +sdp_list_t *read_records(bdaddr_t *src, bdaddr_t *dst); sdp_record_t *find_record_in_list(sdp_list_t *recs, const char *uuid); int store_device_id(const gchar *src, const gchar *dst, const uint16_t source, const uint16_t vendor, |