From 813b674bce1aab009e7f2d14d1825f603330563d Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 3 Sep 2012 14:11:36 +0300 Subject: [PATCH] Add profile abstraction (replaces btd_device drivers) This patch removes the btd_device_driver concept and replaces it with btd_profile. The new construct also contains the necessary parts for adapter drivers, so btd_adapter_driver is only needed for non-profile related functionality (most of which is in plugins/*). The main purpose of this new construct is to facilitate a centralized connection creation mechanism for profiles, ultimately enabling the addition of a Device.Connect() method instead of requiring a UI to know to call e.g. Input.Connect or Audio.Connect. This feature will also be extended to externally implemented profiles once the internal implementation gets more stable, such as OBEX (obexd) and HFP (oFono). The new D-Bus interface will also partially restore functionality which was previously available through the Serial interface. --- attrib/client.c | 1 + audio/avctp.c | 1 + audio/avdtp.c | 1 + audio/avrcp.c | 1 + audio/control.c | 12 +- audio/control.h | 4 +- audio/device.c | 1 + audio/gateway.h | 2 +- audio/headset.c | 81 +++------ audio/headset.h | 8 +- audio/manager.c | 283 +++++++++++++---------------- audio/manager.h | 2 - audio/sink.c | 1 + audio/source.c | 1 + plugins/adaptername.c | 1 + plugins/dbusoob.c | 2 + plugins/wiimote.c | 2 + profiles/deviceinfo/deviceinfo.c | 2 + profiles/deviceinfo/manager.c | 15 +- profiles/gatt/gas.c | 2 + profiles/gatt/manager.c | 15 +- profiles/health/hdp.c | 1 + profiles/health/hdp_manager.c | 30 +-- profiles/health/hdp_util.c | 1 + profiles/input/device.c | 1 + profiles/input/fakehid.c | 1 + profiles/input/hog_device.c | 1 + profiles/input/hog_manager.c | 15 +- profiles/input/manager.c | 43 ++--- profiles/network/connection.c | 14 +- profiles/network/connection.h | 2 +- profiles/network/manager.c | 91 +++------- profiles/proximity/immalert.c | 2 + profiles/proximity/linkloss.c | 2 + profiles/proximity/manager.c | 43 ++--- profiles/proximity/monitor.c | 1 + profiles/proximity/reporter.c | 21 +-- profiles/proximity/reporter.h | 3 + profiles/sap/manager.c | 15 +- profiles/thermometer/manager.c | 15 +- profiles/thermometer/thermometer.c | 5 +- profiles/time/manager.c | 17 +- src/adapter.c | 50 ++++- src/agent.c | 1 + src/attrib-server.c | 1 + src/device.c | 190 ++++++++++--------- src/device.h | 46 +++-- src/event.c | 1 + src/mgmt.c | 1 + 49 files changed, 516 insertions(+), 536 deletions(-) diff --git a/attrib/client.c b/attrib/client.c index bb6adf848..906d34542 100644 --- a/attrib/client.c +++ b/attrib/client.c @@ -29,6 +29,7 @@ #include #include +#include #include #include diff --git a/audio/avctp.c b/audio/avctp.c index 29709863e..03f3e7f1d 100644 --- a/audio/avctp.c +++ b/audio/avctp.c @@ -29,6 +29,7 @@ #include #include +#include #include #include #include diff --git a/audio/avdtp.c b/audio/avdtp.c index eafafc009..d44c50405 100644 --- a/audio/avdtp.c +++ b/audio/avdtp.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include diff --git a/audio/avrcp.c b/audio/avrcp.c index d9253650d..0688ffaa1 100644 --- a/audio/avrcp.c +++ b/audio/avrcp.c @@ -29,6 +29,7 @@ #include #include +#include #include #include #include diff --git a/audio/control.c b/audio/control.c index 187f838b8..5477c2d9e 100644 --- a/audio/control.c +++ b/audio/control.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -58,9 +59,7 @@ static unsigned int avctp_id = 0; struct control { - struct audio_device *dev; struct avctp *session; - gboolean target; }; @@ -238,13 +237,13 @@ void control_unregister(struct audio_device *dev) AUDIO_CONTROL_INTERFACE); } -void control_update(struct control *control, uint16_t uuid16) +void control_update(struct control *control, GSList *uuids) { - if (uuid16 == AV_REMOTE_TARGET_SVCLASS_ID) + if (g_slist_find_custom(uuids, AVRCP_TARGET_UUID, bt_uuid_strcmp)) control->target = TRUE; } -struct control *control_init(struct audio_device *dev, uint16_t uuid16) +struct control *control_init(struct audio_device *dev, GSList *uuids) { struct control *control; @@ -258,9 +257,8 @@ struct control *control_init(struct audio_device *dev, uint16_t uuid16) AUDIO_CONTROL_INTERFACE, dev->path); control = g_new0(struct control, 1); - control->dev = dev; - control_update(control, uuid16); + control_update(control, uuids); if (!avctp_id) avctp_id = avctp_add_state_cb(state_changed, NULL); diff --git a/audio/control.h b/audio/control.h index 2219e5f11..5f4f728bb 100644 --- a/audio/control.h +++ b/audio/control.h @@ -24,7 +24,7 @@ #define AUDIO_CONTROL_INTERFACE "org.bluez.Control" -struct control *control_init(struct audio_device *dev, uint16_t uuid16); -void control_update(struct control *control, uint16_t uuid16); +struct control *control_init(struct audio_device *dev, GSList *uuids); +void control_update(struct control *control, GSList *uuids); void control_unregister(struct audio_device *dev); gboolean control_is_active(struct audio_device *dev); diff --git a/audio/device.c b/audio/device.c index 9507eac7f..4952b5734 100644 --- a/audio/device.c +++ b/audio/device.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include diff --git a/audio/gateway.h b/audio/gateway.h index 77f57872b..6fde4459c 100644 --- a/audio/gateway.h +++ b/audio/gateway.h @@ -56,7 +56,7 @@ typedef void (*gateway_stream_cb_t) (struct audio_device *dev, GError *err, void gateway_set_state(struct audio_device *dev, gateway_state_t new_state); void gateway_unregister(struct audio_device *dev); -struct gateway *gateway_init(struct audio_device *device); +struct gateway *gateway_init(struct audio_device *dev); gboolean gateway_is_active(struct audio_device *dev); gboolean gateway_is_connected(struct audio_device *dev); int gateway_connect_rfcomm(struct audio_device *dev, GIOChannel *io); diff --git a/audio/headset.c b/audio/headset.c index 0ddd1344f..1ef6c491c 100644 --- a/audio/headset.c +++ b/audio/headset.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +43,7 @@ #include #include #include +#include #include #include @@ -1956,45 +1958,23 @@ static const GDBusSignalTable headset_signals[] = { { } }; -void headset_update(struct audio_device *dev, uint16_t svc, - const char *uuidstr) +void headset_update(struct audio_device *dev, struct headset *headset, + GSList *uuids) { - struct headset *headset = dev->headset; const sdp_record_t *record; - record = btd_device_get_record(dev->btd_dev, uuidstr); - if (!record) - return; - - switch (svc) { - case HANDSFREE_SVCLASS_ID: - if (headset->hfp_handle && - (headset->hfp_handle != record->handle)) { - error("More than one HFP record found on device"); - return; - } - - headset->hfp_handle = record->handle; - break; - - case HEADSET_SVCLASS_ID: - if (headset->hsp_handle && - (headset->hsp_handle != record->handle)) { - error("More than one HSP record found on device"); - return; - } - - headset->hsp_handle = record->handle; - - /* Ignore this record if we already have access to HFP */ - if (headset->hfp_handle) - return; - - break; + if (g_slist_find_custom(uuids, HFP_HS_UUID, bt_uuid_strcmp) && + headset->hfp_handle == 0) { + record = btd_device_get_record(dev->btd_dev, HFP_HS_UUID); + if (record) + headset->hfp_handle = record->handle; + } - default: - DBG("Invalid record passed to headset_update"); - return; + if (g_slist_find_custom(uuids, HSP_HS_UUID, bt_uuid_strcmp) && + headset->hsp_handle == 0) { + record = btd_device_get_record(dev->btd_dev, HSP_HS_UUID); + if (record) + headset->hsp_handle = record->handle; } } @@ -2057,36 +2037,17 @@ void headset_unregister(struct audio_device *dev) AUDIO_HEADSET_INTERFACE); } -struct headset *headset_init(struct audio_device *dev, uint16_t svc, - const char *uuidstr) +struct headset *headset_init(struct audio_device *dev, GSList *uuids, + gboolean hfp_enabled) { struct headset *hs; - const sdp_record_t *record; hs = g_new0(struct headset, 1); hs->rfcomm_ch = -1; - hs->search_hfp = server_is_enabled(&dev->src, HANDSFREE_SVCLASS_ID); - - record = btd_device_get_record(dev->btd_dev, uuidstr); - if (!record) - goto register_iface; + hs->search_hfp = hfp_enabled; - switch (svc) { - case HANDSFREE_SVCLASS_ID: - hs->hfp_handle = record->handle; - break; - - case HEADSET_SVCLASS_ID: - hs->hsp_handle = record->handle; - break; + headset_update(dev, hs, uuids); - default: - DBG("Invalid record passed to headset_init"); - g_free(hs); - return NULL; - } - -register_iface: if (!g_dbus_register_interface(dev->conn, dev->path, AUDIO_HEADSET_INTERFACE, headset_methods, headset_signals, NULL, @@ -2095,8 +2056,8 @@ register_iface: return NULL; } - DBG("Registered interface %s on path %s", - AUDIO_HEADSET_INTERFACE, dev->path); + DBG("Registered interface %s on path %s", AUDIO_HEADSET_INTERFACE, + dev->path); return hs; } diff --git a/audio/headset.h b/audio/headset.h index 465c2d67c..736e4fe1f 100644 --- a/audio/headset.h +++ b/audio/headset.h @@ -57,15 +57,15 @@ void headset_connect_cb(GIOChannel *chan, GError *err, gpointer user_data); GIOChannel *headset_get_rfcomm(struct audio_device *dev); -struct headset *headset_init(struct audio_device *dev, uint16_t svc, - const char *uuidstr); +struct headset *headset_init(struct audio_device *dev, GSList *uuids, + gboolean hfp_enabled); void headset_unregister(struct audio_device *dev); uint32_t headset_config_init(GKeyFile *config); -void headset_update(struct audio_device *dev, uint16_t svc, - const char *uuidstr); +void headset_update(struct audio_device *dev, struct headset *headset, + GSList *uuids); unsigned int headset_config_stream(struct audio_device *dev, gboolean auto_dc, diff --git a/audio/manager.c b/audio/manager.c index 7406a1f68..5b34f9b40 100644 --- a/audio/manager.c +++ b/audio/manager.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -128,104 +129,6 @@ static struct audio_adapter *find_adapter(GSList *list, return NULL; } -gboolean server_is_enabled(bdaddr_t *src, uint16_t svc) -{ - switch (svc) { - case HEADSET_SVCLASS_ID: - return enabled.headset; - case HEADSET_AGW_SVCLASS_ID: - return FALSE; - case HANDSFREE_SVCLASS_ID: - return enabled.headset && enabled.hfp; - case HANDSFREE_AGW_SVCLASS_ID: - return enabled.gateway; - case AUDIO_SINK_SVCLASS_ID: - return enabled.sink; - case AUDIO_SOURCE_SVCLASS_ID: - return enabled.source; - case AV_REMOTE_TARGET_SVCLASS_ID: - case AV_REMOTE_SVCLASS_ID: - return enabled.control; - default: - return FALSE; - } -} - -static void handle_uuid(const char *uuidstr, struct audio_device *device) -{ - uuid_t uuid; - uint16_t uuid16; - - if (bt_string2uuid(&uuid, uuidstr) < 0) { - error("%s not detected as an UUID-128", uuidstr); - return; - } - - if (!sdp_uuid128_to_uuid(&uuid) && uuid.type != SDP_UUID16) { - error("Could not convert %s to a UUID-16", uuidstr); - return; - } - - uuid16 = uuid.value.uuid16; - - if (!server_is_enabled(&device->src, uuid16)) { - DBG("server not enabled for %s (0x%04x)", uuidstr, uuid16); - return; - } - - switch (uuid16) { - case HEADSET_SVCLASS_ID: - DBG("Found Headset record"); - if (device->headset) - headset_update(device, uuid16, uuidstr); - else - device->headset = headset_init(device, uuid16, - uuidstr); - break; - case HEADSET_AGW_SVCLASS_ID: - DBG("Found Headset AG record"); - break; - case HANDSFREE_SVCLASS_ID: - DBG("Found Handsfree record"); - if (device->headset) - headset_update(device, uuid16, uuidstr); - else - device->headset = headset_init(device, uuid16, - uuidstr); - break; - case HANDSFREE_AGW_SVCLASS_ID: - DBG("Found Handsfree AG record"); - if (enabled.gateway && (device->gateway == NULL)) - device->gateway = gateway_init(device); - break; - case AUDIO_SINK_SVCLASS_ID: - DBG("Found Audio Sink"); - if (device->sink == NULL) - device->sink = sink_init(device); - break; - case AUDIO_SOURCE_SVCLASS_ID: - DBG("Found Audio Source"); - if (device->source == NULL) - device->source = source_init(device); - break; - case AV_REMOTE_SVCLASS_ID: - case AV_REMOTE_TARGET_SVCLASS_ID: - DBG("Found AV %s", uuid16 == AV_REMOTE_SVCLASS_ID ? - "Remote" : "Target"); - if (device->control) - control_update(device->control, uuid16); - else - device->control = control_init(device, uuid16); - - if (device->sink && sink_is_active(device)) - avrcp_connect(device); - break; - default: - DBG("Unrecognized UUID: 0x%04X", uuid16); - break; - } -} - static sdp_record_t *hsp_ag_record(uint8_t ch) { sdp_list_t *svclass_id, *pfseq, *apseq, *root; @@ -769,41 +672,106 @@ failed: return -1; } -static int audio_probe(struct btd_device *device, GSList *uuids) +static struct audio_device *get_audio_dev(struct btd_device *device) { struct btd_adapter *adapter = device_get_adapter(device); bdaddr_t src, dst; - struct audio_device *audio_dev; adapter_get_address(adapter, &src); device_get_address(device, &dst, NULL); - audio_dev = manager_get_device(&src, &dst, TRUE); + return manager_get_device(&src, &dst, TRUE); +} + +static void audio_remove(struct btd_device *device) +{ + struct audio_device *dev; + + dev = get_audio_dev(device); + if (!dev) + return; + + devices = g_slist_remove(devices, dev); + audio_device_unregister(dev); +} + +static int hs_probe(struct btd_device *device, GSList *uuids) +{ + struct audio_device *audio_dev; + + audio_dev = get_audio_dev(device); if (!audio_dev) { DBG("unable to get a device object"); return -1; } - g_slist_foreach(uuids, (GFunc) handle_uuid, audio_dev); + if (audio_dev->headset) + headset_update(audio_dev, audio_dev->headset, uuids); + else + audio_dev->headset = headset_init(audio_dev, uuids, + enabled.hfp); return 0; } -static void audio_remove(struct btd_device *device) +static int ag_probe(struct btd_device *device, GSList *uuids) { - struct audio_device *dev; - const char *path; + struct audio_device *audio_dev; - path = device_get_path(device); + audio_dev = get_audio_dev(device); + if (!audio_dev) { + DBG("unable to get a device object"); + return -1; + } - dev = manager_find_device(path, NULL, NULL, NULL, FALSE); - if (!dev) - return; + if (!audio_dev->gateway) + return -EALREADY; - devices = g_slist_remove(devices, dev); + audio_dev->gateway = gateway_init(audio_dev); - audio_device_unregister(dev); + return 0; +} + +static int a2dp_probe(struct btd_device *device, GSList *uuids) +{ + struct audio_device *audio_dev; + + audio_dev = get_audio_dev(device); + if (!audio_dev) { + DBG("unable to get a device object"); + return -1; + } + if (g_slist_find_custom(uuids, A2DP_SINK_UUID, bt_uuid_strcmp) && + audio_dev->sink == NULL) + audio_dev->sink = sink_init(audio_dev); + + if (g_slist_find_custom(uuids, A2DP_SOURCE_UUID, bt_uuid_strcmp) && + audio_dev->source == NULL) + audio_dev->source = source_init(audio_dev); + + return 0; +} + +static int avrcp_probe(struct btd_device *device, GSList *uuids) +{ + struct audio_device *audio_dev; + + audio_dev = get_audio_dev(device); + if (!audio_dev) { + DBG("unable to get a device object"); + return -1; + } + + if (audio_dev->control) + control_update(audio_dev->control, uuids); + else + audio_dev->control = control_init(audio_dev, uuids); + + if (audio_dev->sink && sink_is_active(audio_dev)) + avrcp_connect(audio_dev); + + return 0; } static struct audio_adapter *audio_adapter_ref(struct audio_adapter *adp) @@ -1113,40 +1081,51 @@ static void media_server_remove(struct btd_adapter *adapter) audio_adapter_unref(adp); } -static struct btd_device_driver audio_driver = { - .name = "audio", - .uuids = BTD_UUIDS(HSP_HS_UUID, HFP_HS_UUID, HSP_AG_UUID, HFP_AG_UUID, - ADVANCED_AUDIO_UUID, A2DP_SOURCE_UUID, A2DP_SINK_UUID, - AVRCP_TARGET_UUID, AVRCP_REMOTE_UUID), - .probe = audio_probe, - .remove = audio_remove, -}; +static struct btd_profile headset_profile = { + .name = "audio-headset", -static struct btd_adapter_driver headset_server_driver = { - .name = "audio-headset", - .probe = headset_server_probe, - .remove = headset_server_remove, + .remote_uuids = BTD_UUIDS(HSP_HS_UUID, HFP_HS_UUID), + .device_probe = hs_probe, + .device_remove = audio_remove, + + .adapter_probe = headset_server_probe, + .adapter_remove = headset_server_remove, }; -static struct btd_adapter_driver gateway_server_driver = { - .name = "audio-gateway", - .probe = gateway_server_probe, - .remove = gateway_server_remove, +static struct btd_profile gateway_profile = { + .name = "audio-gateway", + + .remote_uuids = BTD_UUIDS(HSP_AG_UUID, HFP_AG_UUID), + .device_probe = ag_probe, + .device_remove = audio_remove, + + .adapter_probe = gateway_server_probe, + .adapter_remove = gateway_server_remove, }; -static struct btd_adapter_driver a2dp_server_driver = { - .name = "audio-a2dp", - .probe = a2dp_server_probe, - .remove = a2dp_server_remove, +static struct btd_profile a2dp_profile = { + .name = "audio-a2dp", + + .remote_uuids = BTD_UUIDS(A2DP_SOURCE_UUID, A2DP_SINK_UUID), + .device_probe = a2dp_probe, + .device_remove = audio_remove, + + .adapter_probe = a2dp_server_probe, + .adapter_remove = a2dp_server_remove, }; -static struct btd_adapter_driver avrcp_server_driver = { - .name = "audio-control", - .probe = avrcp_server_probe, - .remove = avrcp_server_remove, +static struct btd_profile avrcp_profile = { + .name = "audio-avrcp", + + .remote_uuids = BTD_UUIDS(AVRCP_TARGET_UUID, AVRCP_REMOTE_UUID), + .device_probe = avrcp_probe, + .device_remove = audio_remove, + + .adapter_probe = avrcp_server_probe, + .adapter_remove = avrcp_server_remove, }; -static struct btd_adapter_driver media_server_driver = { +static struct btd_adapter_driver media_driver = { .name = "media", .probe = media_server_probe, .remove = media_server_remove, @@ -1228,22 +1207,20 @@ int audio_manager_init(DBusConnection *conn, GKeyFile *conf, max_connected_headsets = i; proceed: - if (enabled.control) - btd_register_adapter_driver(&avrcp_server_driver); - - if (enabled.media) - btd_register_adapter_driver(&media_server_driver); - if (enabled.headset) - btd_register_adapter_driver(&headset_server_driver); + btd_profile_register(&headset_profile); if (enabled.gateway) - btd_register_adapter_driver(&gateway_server_driver); + btd_profile_register(&gateway_profile); if (enabled.source || enabled.sink) - btd_register_adapter_driver(&a2dp_server_driver); + btd_profile_register(&a2dp_profile); - btd_register_device_driver(&audio_driver); + if (enabled.control) + btd_profile_register(&avrcp_profile); + + if (enabled.media) + btd_register_adapter_driver(&media_driver); *enable_sco = (enabled.gateway || enabled.headset); @@ -1264,22 +1241,20 @@ void audio_manager_exit(void) config = NULL; } - if (enabled.media) - btd_unregister_adapter_driver(&media_server_driver); - if (enabled.headset) - btd_unregister_adapter_driver(&headset_server_driver); + btd_profile_unregister(&headset_profile); if (enabled.gateway) - btd_unregister_adapter_driver(&gateway_server_driver); + btd_profile_unregister(&gateway_profile); if (enabled.source || enabled.sink) - btd_unregister_adapter_driver(&a2dp_server_driver); + btd_profile_unregister(&a2dp_profile); if (enabled.control) - btd_unregister_adapter_driver(&avrcp_server_driver); + btd_profile_unregister(&avrcp_profile); - btd_unregister_device_driver(&audio_driver); + if (enabled.media) + btd_unregister_adapter_driver(&media_driver); } GSList *manager_find_devices(const char *path, diff --git a/audio/manager.h b/audio/manager.h index f1d302143..1320c7121 100644 --- a/audio/manager.h +++ b/audio/manager.h @@ -38,8 +38,6 @@ int audio_manager_init(DBusConnection *conn, GKeyFile *config, gboolean *enable_sco); void audio_manager_exit(void); -gboolean server_is_enabled(bdaddr_t *src, uint16_t svc); - struct audio_device *manager_find_device(const char *path, const bdaddr_t *src, const bdaddr_t *dst, diff --git a/audio/sink.c b/audio/sink.c index 64e38f425..53a0b80ce 100644 --- a/audio/sink.c +++ b/audio/sink.c @@ -27,6 +27,7 @@ #endif #include +#include #include #include diff --git a/audio/source.c b/audio/source.c index 6dabd1b40..e4ba21143 100644 --- a/audio/source.c +++ b/audio/source.c @@ -28,6 +28,7 @@ #endif #include +#include #include #include diff --git a/plugins/adaptername.c b/plugins/adaptername.c index d3341b5f5..c109b4481 100644 --- a/plugins/adaptername.c +++ b/plugins/adaptername.c @@ -30,6 +30,7 @@ #endif #include +#include #include #include diff --git a/plugins/dbusoob.c b/plugins/dbusoob.c index ef2a7e72c..a7259bacd 100644 --- a/plugins/dbusoob.c +++ b/plugins/dbusoob.c @@ -27,6 +27,8 @@ #include #endif +#include + #include #include diff --git a/plugins/wiimote.c b/plugins/wiimote.c index 9c69c6d18..337d4080b 100644 --- a/plugins/wiimote.c +++ b/plugins/wiimote.c @@ -25,6 +25,8 @@ #include #endif +#include + #include #include diff --git a/profiles/deviceinfo/deviceinfo.c b/profiles/deviceinfo/deviceinfo.c index ca849adfd..e7c442fac 100644 --- a/profiles/deviceinfo/deviceinfo.c +++ b/profiles/deviceinfo/deviceinfo.c @@ -24,6 +24,8 @@ #include #endif +#include + #include #include diff --git a/profiles/deviceinfo/manager.c b/profiles/deviceinfo/manager.c index 1d5991871..914ec4060 100644 --- a/profiles/deviceinfo/manager.c +++ b/profiles/deviceinfo/manager.c @@ -22,6 +22,7 @@ #include #include +#include #include #include "adapter.h" @@ -62,19 +63,19 @@ static void deviceinfo_driver_remove(struct btd_device *device) deviceinfo_unregister(device); } -static struct btd_device_driver deviceinfo_device_driver = { - .name = "deviceinfo-driver", - .uuids = BTD_UUIDS(DEVICE_INFORMATION_UUID), - .probe = deviceinfo_driver_probe, - .remove = deviceinfo_driver_remove +static struct btd_profile deviceinfo_profile = { + .name = "deviceinfo", + .remote_uuids = BTD_UUIDS(DEVICE_INFORMATION_UUID), + .device_probe = deviceinfo_driver_probe, + .device_remove = deviceinfo_driver_remove }; int deviceinfo_manager_init(void) { - return btd_register_device_driver(&deviceinfo_device_driver); + return btd_profile_register(&deviceinfo_profile); } void deviceinfo_manager_exit(void) { - btd_unregister_device_driver(&deviceinfo_device_driver); + btd_profile_unregister(&deviceinfo_profile); } diff --git a/profiles/gatt/gas.c b/profiles/gatt/gas.c index 67cc5aea6..ddd4e7074 100644 --- a/profiles/gatt/gas.c +++ b/profiles/gatt/gas.c @@ -24,6 +24,8 @@ #include #endif +#include + #include #include diff --git a/profiles/gatt/manager.c b/profiles/gatt/manager.c index 0702d2645..9c5ea14b4 100644 --- a/profiles/gatt/manager.c +++ b/profiles/gatt/manager.c @@ -22,6 +22,7 @@ #include #include +#include #include #include "adapter.h" @@ -69,19 +70,19 @@ static void gatt_driver_remove(struct btd_device *device) gas_unregister(device); } -static struct btd_device_driver gatt_device_driver = { - .name = "gap-gatt-driver", - .uuids = BTD_UUIDS(GAP_UUID, GATT_UUID), - .probe = gatt_driver_probe, - .remove = gatt_driver_remove +static struct btd_profile gatt_profile = { + .name = "gap-gatt-profile", + .remote_uuids = BTD_UUIDS(GAP_UUID, GATT_UUID), + .device_probe = gatt_driver_probe, + .device_remove = gatt_driver_remove }; int gatt_manager_init(void) { - return btd_register_device_driver(&gatt_device_driver); + return btd_profile_register(&gatt_profile); } void gatt_manager_exit(void) { - btd_unregister_device_driver(&gatt_device_driver); + btd_profile_unregister(&gatt_profile); } diff --git a/profiles/health/hdp.c b/profiles/health/hdp.c index b54733b3e..5d62d3576 100644 --- a/profiles/health/hdp.c +++ b/profiles/health/hdp.c @@ -22,6 +22,7 @@ #include #include +#include #include #include diff --git a/profiles/health/hdp_manager.c b/profiles/health/hdp_manager.c index ffaed5d64..416286ee6 100644 --- a/profiles/health/hdp_manager.c +++ b/profiles/health/hdp_manager.c @@ -24,6 +24,8 @@ #include #endif +#include + #include #include #include @@ -51,12 +53,6 @@ static void hdp_adapter_remove(struct btd_adapter *adapter) hdp_adapter_unregister(adapter); } -static struct btd_adapter_driver hdp_adapter_driver = { - .name = "hdp-adapter-driver", - .probe = hdp_adapter_probe, - .remove = hdp_adapter_remove, -}; - static int hdp_driver_probe(struct btd_device *device, GSList *uuids) { return hdp_device_register(connection, device); @@ -67,11 +63,15 @@ static void hdp_driver_remove(struct btd_device *device) hdp_device_unregister(device); } -static struct btd_device_driver hdp_device_driver = { - .name = "hdp-device-driver", - .uuids = BTD_UUIDS(HDP_UUID, HDP_SOURCE_UUID, HDP_SINK_UUID), - .probe = hdp_driver_probe, - .remove = hdp_driver_remove +static struct btd_profile hdp_profile = { + .name = "hdp-profile", + .remote_uuids = BTD_UUIDS(HDP_UUID, HDP_SOURCE_UUID, HDP_SINK_UUID), + + .device_probe = hdp_driver_probe, + .device_remove = hdp_driver_remove, + + .adapter_probe = hdp_adapter_probe, + .adapter_remove = hdp_adapter_remove, }; int hdp_manager_init(DBusConnection *conn) @@ -80,16 +80,16 @@ int hdp_manager_init(DBusConnection *conn) return -1; connection = dbus_connection_ref(conn); - btd_register_adapter_driver(&hdp_adapter_driver); - btd_register_device_driver(&hdp_device_driver); + + btd_profile_register(&hdp_profile); return 0; } void hdp_manager_exit(void) { - btd_unregister_device_driver(&hdp_device_driver); - btd_unregister_adapter_driver(&hdp_adapter_driver); + btd_profile_unregister(&hdp_profile); + hdp_manager_stop(); dbus_connection_unref(connection); diff --git a/profiles/health/hdp_util.c b/profiles/health/hdp_util.c index 744e3902c..761e07d90 100644 --- a/profiles/health/hdp_util.c +++ b/profiles/health/hdp_util.c @@ -25,6 +25,7 @@ #endif #include +#include #include diff --git a/profiles/input/device.c b/profiles/input/device.c index e3f9dacf7..f1e1af0b3 100644 --- a/profiles/input/device.c +++ b/profiles/input/device.c @@ -26,6 +26,7 @@ #endif #include +#include #include #include #include diff --git a/profiles/input/fakehid.c b/profiles/input/fakehid.c index 3be148926..d9af2dd57 100644 --- a/profiles/input/fakehid.c +++ b/profiles/input/fakehid.c @@ -25,6 +25,7 @@ #include #endif +#include #include #include diff --git a/profiles/input/hog_device.c b/profiles/input/hog_device.c index 000f1731e..664c52be8 100644 --- a/profiles/input/hog_device.c +++ b/profiles/input/hog_device.c @@ -28,6 +28,7 @@ #endif #include +#include #include #include #include diff --git a/profiles/input/hog_manager.c b/profiles/input/hog_manager.c index c544e79f3..6d971fa01 100644 --- a/profiles/input/hog_manager.c +++ b/profiles/input/hog_manager.c @@ -27,6 +27,7 @@ #endif #include +#include #include "log.h" #include "../src/adapter.h" @@ -55,21 +56,21 @@ static void hog_device_remove(struct btd_device *device) hog_device_unregister(path); } -static struct btd_device_driver hog_driver = { - .name = "input-hog", - .uuids = BTD_UUIDS(HOG_UUID), - .probe = hog_device_probe, - .remove = hog_device_remove, +static struct btd_profile hog_profile = { + .name = "input-hog", + .remote_uuids = BTD_UUIDS(HOG_UUID), + .device_probe = hog_device_probe, + .device_remove = hog_device_remove, }; static int hog_manager_init(void) { - return btd_register_device_driver(&hog_driver); + return btd_profile_register(&hog_profile); } static void hog_manager_exit(void) { - btd_unregister_device_driver(&hog_driver); + btd_profile_register(&hog_profile); } static int hog_init(void) diff --git a/profiles/input/manager.c b/profiles/input/manager.c index add9789ac..2f9e087af 100644 --- a/profiles/input/manager.c +++ b/profiles/input/manager.c @@ -26,6 +26,7 @@ #endif #include +#include #include #include @@ -139,24 +140,23 @@ static void hid_server_remove(struct btd_adapter *adapter) btd_adapter_unref(adapter); } -static struct btd_device_driver input_hid_driver = { - .name = "input-hid", - .uuids = BTD_UUIDS(HID_UUID), - .probe = hid_device_probe, - .remove = hid_device_remove, -}; +static struct btd_profile input_profile = { + .name = "input-hid", + .remote_uuids = BTD_UUIDS(HID_UUID), + + .device_probe = hid_device_probe, + .device_remove = hid_device_remove, -static struct btd_device_driver input_headset_driver = { - .name = "input-headset", - .uuids = BTD_UUIDS(HSP_HS_UUID), - .probe = headset_probe, - .remove = headset_remove, + .adapter_probe = hid_server_probe, + .adapter_remove = hid_server_remove, }; -static struct btd_adapter_driver input_server_driver = { - .name = "input-server", - .probe = hid_server_probe, - .remove = hid_server_remove, +static struct btd_profile input_headset_profile = { + .name = "input-headset", + .remote_uuids = BTD_UUIDS(HSP_HS_UUID), + + .device_probe = headset_probe, + .device_remove = headset_remove, }; int input_manager_init(DBusConnection *conn, GKeyFile *config) @@ -174,22 +174,17 @@ int input_manager_init(DBusConnection *conn, GKeyFile *config) connection = dbus_connection_ref(conn); - btd_register_adapter_driver(&input_server_driver); - - btd_register_device_driver(&input_hid_driver); - btd_register_device_driver(&input_headset_driver); + btd_profile_register(&input_profile); + btd_profile_register(&input_headset_profile); return 0; } void input_manager_exit(void) { - btd_unregister_device_driver(&input_hid_driver); - btd_unregister_device_driver(&input_headset_driver); - - btd_unregister_adapter_driver(&input_server_driver); + btd_profile_unregister(&input_profile); + btd_profile_unregister(&input_headset_profile); dbus_connection_unref(connection); - connection = NULL; } diff --git a/profiles/network/connection.c b/profiles/network/connection.c index 40b360f94..dba448e80 100644 --- a/profiles/network/connection.c +++ b/profiles/network/connection.c @@ -26,6 +26,7 @@ #endif #include +#include #include #include #include @@ -573,23 +574,16 @@ static const GDBusSignalTable connection_signals[] = { { } }; -void connection_unregister(const char *path, uint16_t id) +void connection_unregister(const char *path) { struct network_peer *peer; - struct network_conn *nc; peer = find_peer(peers, path); if (!peer) return; - nc = find_connection(peer->connections, id); - if (!nc) - return; - - peer->connections = g_slist_remove(peer->connections, nc); - connection_free(nc); - if (peer->connections) - return; + g_slist_free_full(peer->connections, connection_free); + peer->connections = NULL; g_dbus_unregister_interface(connection, path, NETWORK_PEER_INTERFACE); } diff --git a/profiles/network/connection.h b/profiles/network/connection.h index 5ea4147db..a5e0e613c 100644 --- a/profiles/network/connection.h +++ b/profiles/network/connection.h @@ -25,4 +25,4 @@ int connection_init(DBusConnection *conn); void connection_exit(void); int connection_register(struct btd_device *device, const char *path, bdaddr_t *src, bdaddr_t *dst, uint16_t id); -void connection_unregister(const char *path, uint16_t id); +void connection_unregister(const char *path); diff --git a/profiles/network/manager.c b/profiles/network/manager.c index 7fcd8f08b..ac36406e9 100644 --- a/profiles/network/manager.c +++ b/profiles/network/manager.c @@ -25,6 +25,8 @@ #include #endif +#include + #include #include #include @@ -72,7 +74,7 @@ done: conf_security ? "true" : "false"); } -static int network_probe(struct btd_device *device, GSList *uuids, uint16_t id) +static int network_probe(struct btd_device *device, GSList *uuids) { struct btd_adapter *adapter = device_get_adapter(device); const gchar *path = device_get_path(device); @@ -83,46 +85,23 @@ static int network_probe(struct btd_device *device, GSList *uuids, uint16_t id) adapter_get_address(adapter, &src); device_get_address(device, &dst, NULL); - return connection_register(device, path, &src, &dst, id); + if (g_slist_find_custom(uuids, PANU_UUID, bt_uuid_strcmp)) + connection_register(device, path, &src, &dst, BNEP_SVC_PANU); + if (g_slist_find_custom(uuids, GN_UUID, bt_uuid_strcmp)) + connection_register(device, path, &src, &dst, BNEP_SVC_GN); + if (g_slist_find_custom(uuids, NAP_UUID, bt_uuid_strcmp)) + connection_register(device, path, &src, &dst, BNEP_SVC_NAP); + + return 0; } -static void network_remove(struct btd_device *device, uint16_t id) +static void network_remove(struct btd_device *device) { const gchar *path = device_get_path(device); DBG("path %s", path); - connection_unregister(path, id); -} - -static int panu_probe(struct btd_device *device, GSList *uuids) -{ - return network_probe(device, uuids, BNEP_SVC_PANU); -} - -static void panu_remove(struct btd_device *device) -{ - network_remove(device, BNEP_SVC_PANU); -} - -static int gn_probe(struct btd_device *device, GSList *uuids) -{ - return network_probe(device, uuids, BNEP_SVC_GN); -} - -static void gn_remove(struct btd_device *device) -{ - network_remove(device, BNEP_SVC_GN); -} - -static int nap_probe(struct btd_device *device, GSList *uuids) -{ - return network_probe(device, uuids, BNEP_SVC_NAP); -} - -static void nap_remove(struct btd_device *device) -{ - network_remove(device, BNEP_SVC_NAP); + connection_unregister(path); } static int network_server_probe(struct btd_adapter *adapter) @@ -143,31 +122,14 @@ static void network_server_remove(struct btd_adapter *adapter) server_unregister(adapter); } -static struct btd_device_driver network_panu_driver = { - .name = "network-panu", - .uuids = BTD_UUIDS(PANU_UUID), - .probe = panu_probe, - .remove = panu_remove, -}; - -static struct btd_device_driver network_gn_driver = { - .name = "network-gn", - .uuids = BTD_UUIDS(GN_UUID), - .probe = gn_probe, - .remove = gn_remove, -}; +static struct btd_profile network_profile = { + .name = "network", + .remote_uuids = BTD_UUIDS(PANU_UUID, GN_UUID, NAP_UUID), + .device_probe = network_probe, + .device_remove = network_remove, -static struct btd_device_driver network_nap_driver = { - .name = "network-nap", - .uuids = BTD_UUIDS(NAP_UUID), - .probe = nap_probe, - .remove = nap_remove, -}; - -static struct btd_adapter_driver network_server_driver = { - .name = "network-server", - .probe = network_server_probe, - .remove = network_server_remove, + .adapter_probe = network_server_probe, + .adapter_remove = network_server_remove, }; int network_manager_init(DBusConnection *conn) @@ -189,16 +151,11 @@ int network_manager_init(DBusConnection *conn) if (server_init(conn, conf_security) < 0) return -1; - /* Register network server if it doesn't exist */ - btd_register_adapter_driver(&network_server_driver); + btd_profile_register(&network_profile); if (connection_init(conn) < 0) return -1; - btd_register_device_driver(&network_panu_driver); - btd_register_device_driver(&network_gn_driver); - btd_register_device_driver(&network_nap_driver); - connection = dbus_connection_ref(conn); return 0; @@ -208,13 +165,9 @@ void network_manager_exit(void) { server_exit(); - btd_unregister_device_driver(&network_panu_driver); - btd_unregister_device_driver(&network_gn_driver); - btd_unregister_device_driver(&network_nap_driver); - connection_exit(); - btd_unregister_adapter_driver(&network_server_driver); + btd_profile_unregister(&network_profile); dbus_connection_unref(connection); connection = NULL; diff --git a/profiles/proximity/immalert.c b/profiles/proximity/immalert.c index 1540b6132..cc7c26ad1 100644 --- a/profiles/proximity/immalert.c +++ b/profiles/proximity/immalert.c @@ -24,6 +24,8 @@ #include #endif +#include + #include #include #include diff --git a/profiles/proximity/linkloss.c b/profiles/proximity/linkloss.c index 14403cbc8..7be5223ad 100644 --- a/profiles/proximity/linkloss.c +++ b/profiles/proximity/linkloss.c @@ -24,6 +24,8 @@ #include #endif +#include + #include #include #include diff --git a/profiles/proximity/manager.c b/profiles/proximity/manager.c index f2e49a6c0..6368221ef 100644 --- a/profiles/proximity/manager.c +++ b/profiles/proximity/manager.c @@ -26,6 +26,8 @@ #include #endif +#include + #include #include #include @@ -60,6 +62,8 @@ static int attio_device_probe(struct btd_device *device, GSList *uuids) struct gatt_primary *linkloss, *txpower, *immediate; GSList *l, *primaries; + reporter_device_probe(device); + primaries = btd_device_get_primaries(device); l = g_slist_find_custom(primaries, IMMEDIATE_ALERT_UUID, @@ -79,19 +83,18 @@ static int attio_device_probe(struct btd_device *device, GSList *uuids) static void attio_device_remove(struct btd_device *device) { monitor_unregister(connection, device); + reporter_device_remove(device); } -static struct btd_device_driver monitor_driver = { - .name = "Proximity GATT Monitor Driver", - .uuids = BTD_UUIDS(IMMEDIATE_ALERT_UUID, LINK_LOSS_UUID, TX_POWER_UUID), - .probe = attio_device_probe, - .remove = attio_device_remove, -}; +static struct btd_profile pxp_profile = { + .name = "Proximity GATT Driver", + .remote_uuids = BTD_UUIDS(GATT_UUID, IMMEDIATE_ALERT_UUID, + LINK_LOSS_UUID, TX_POWER_UUID), + .device_probe = attio_device_probe, + .device_remove = attio_device_remove, -static struct btd_adapter_driver reporter_server_driver = { - .name = "Proximity GATT Reporter Driver", - .probe = reporter_init, - .remove = reporter_exit, + .adapter_probe = reporter_init, + .adapter_remove = reporter_exit, }; static void load_config_file(GKeyFile *config) @@ -122,29 +125,17 @@ int proximity_manager_init(DBusConnection *conn, GKeyFile *config) load_config_file(config); - connection = dbus_connection_ref(conn); - - ret = btd_register_device_driver(&monitor_driver); + ret = btd_profile_register(&pxp_profile); if (ret < 0) - goto fail_monitor; + return ret; - ret = btd_register_adapter_driver(&reporter_server_driver); - if (ret < 0) - goto fail_reporter; + connection = dbus_connection_ref(conn); return 0; - -fail_reporter: - btd_unregister_device_driver(&monitor_driver); - -fail_monitor: - dbus_connection_unref(connection); - return ret; } void proximity_manager_exit(void) { - btd_unregister_device_driver(&monitor_driver); - btd_unregister_adapter_driver(&reporter_server_driver); + btd_profile_unregister(&pxp_profile); dbus_connection_unref(connection); } diff --git a/profiles/proximity/monitor.c b/profiles/proximity/monitor.c index f22d6f4eb..a5f265e57 100644 --- a/profiles/proximity/monitor.c +++ b/profiles/proximity/monitor.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include diff --git a/profiles/proximity/reporter.c b/profiles/proximity/reporter.c index 607de2bd6..d2eb1946a 100644 --- a/profiles/proximity/reporter.c +++ b/profiles/proximity/reporter.c @@ -26,10 +26,12 @@ #include #endif +#include +#include + #include #include #include -#include #include #include @@ -223,7 +225,7 @@ static void register_reporter_device(struct btd_device *device, radapter->devices = g_slist_prepend(radapter->devices, device); } -static int reporter_device_probe(struct btd_device *device, GSList *uuids) +int reporter_device_probe(struct btd_device *device) { struct reporter_adapter *radapter; struct btd_adapter *adapter = device_get_adapter(device); @@ -233,10 +235,11 @@ static int reporter_device_probe(struct btd_device *device, GSList *uuids) return -1; register_reporter_device(device, radapter); + return 0; } -static void reporter_device_remove(struct btd_device *device) +void reporter_device_remove(struct btd_device *device) { struct reporter_adapter *radapter; struct btd_adapter *adapter = device_get_adapter(device); @@ -248,14 +251,6 @@ static void reporter_device_remove(struct btd_device *device) unregister_reporter_device(device, radapter); } -/* device driver for tracking remote GATT client devices */ -static struct btd_device_driver reporter_device_driver = { - .name = "Proximity GATT Reporter Device Tracker Driver", - .uuids = BTD_UUIDS(GATT_UUID), - .probe = reporter_device_probe, - .remove = reporter_device_remove, -}; - int reporter_init(struct btd_adapter *adapter) { struct reporter_adapter *radapter; @@ -278,8 +273,6 @@ int reporter_init(struct btd_adapter *adapter) register_tx_power(adapter); imm_alert_register(adapter, radapter->conn); - btd_register_device_driver(&reporter_device_driver); - reporter_adapters = g_slist_prepend(reporter_adapters, radapter); DBG("Proximity Reporter for adapter %p", adapter); @@ -292,8 +285,6 @@ void reporter_exit(struct btd_adapter *adapter) if (!radapter) return; - btd_unregister_device_driver(&reporter_device_driver); - g_slist_foreach(radapter->devices, unregister_reporter_device, radapter); diff --git a/profiles/proximity/reporter.h b/profiles/proximity/reporter.h index 5ae0eb2ff..4f3bee241 100644 --- a/profiles/proximity/reporter.h +++ b/profiles/proximity/reporter.h @@ -36,6 +36,9 @@ enum { HIGH_ALERT = 0x02, }; +void reporter_device_remove(struct btd_device *device); +int reporter_device_probe(struct btd_device *device); + int reporter_init(struct btd_adapter *adapter); void reporter_exit(struct btd_adapter *adapter); diff --git a/profiles/sap/manager.c b/profiles/sap/manager.c index 9fa9c56e5..b563d7b0d 100644 --- a/profiles/sap/manager.c +++ b/profiles/sap/manager.c @@ -22,8 +22,11 @@ #include #endif +#include + #include "log.h" #include "adapter.h" +#include "device.h" #include "manager.h" #include "server.h" @@ -51,10 +54,10 @@ static void sap_server_remove(struct btd_adapter *adapter) sap_server_unregister(path); } -static struct btd_adapter_driver sap_server_driver = { - .name = "sap-server", - .probe = sap_server_probe, - .remove = sap_server_remove, +static struct btd_profile sap_profile = { + .name = "sap-server", + .adapter_probe = sap_server_probe, + .adapter_remove = sap_server_remove, }; int sap_manager_init(DBusConnection *conn) @@ -67,14 +70,14 @@ int sap_manager_init(DBusConnection *conn) return -1; } - btd_register_adapter_driver(&sap_server_driver); + btd_profile_register(&sap_profile); return 0; } void sap_manager_exit(void) { - btd_unregister_adapter_driver(&sap_server_driver); + btd_profile_unregister(&sap_profile); dbus_connection_unref(connection); connection = NULL; diff --git a/profiles/thermometer/manager.c b/profiles/thermometer/manager.c index 3d5452bfe..9e909a37b 100644 --- a/profiles/thermometer/manager.c +++ b/profiles/thermometer/manager.c @@ -22,6 +22,7 @@ #include #include +#include #include #include "adapter.h" @@ -64,18 +65,18 @@ static void thermometer_driver_remove(struct btd_device *device) thermometer_unregister(device); } -static struct btd_device_driver thermometer_device_driver = { - .name = "thermometer-device-driver", - .uuids = BTD_UUIDS(HEALTH_THERMOMETER_UUID), - .probe = thermometer_driver_probe, - .remove = thermometer_driver_remove +static struct btd_profile thermometer_profile = { + .name = "thermometer-device-driver", + .remote_uuids = BTD_UUIDS(HEALTH_THERMOMETER_UUID), + .device_probe = thermometer_driver_probe, + .device_remove = thermometer_driver_remove }; int thermometer_manager_init(DBusConnection *conn) { int ret; - ret = btd_register_device_driver(&thermometer_device_driver); + ret = btd_profile_register(&thermometer_profile); if (ret < 0) return ret; @@ -85,7 +86,7 @@ int thermometer_manager_init(DBusConnection *conn) void thermometer_manager_exit(void) { - btd_unregister_device_driver(&thermometer_device_driver); + btd_profile_unregister(&thermometer_profile); dbus_connection_unref(connection); connection = NULL; diff --git a/profiles/thermometer/thermometer.c b/profiles/thermometer/thermometer.c index 6652a41c5..f58e55856 100644 --- a/profiles/thermometer/thermometer.c +++ b/profiles/thermometer/thermometer.c @@ -24,10 +24,13 @@ #include #endif -#include +#include #include + #include +#include + #include "dbus-common.h" #include "adapter.h" #include "device.h" diff --git a/profiles/time/manager.c b/profiles/time/manager.c index 285c7b152..c29951c35 100644 --- a/profiles/time/manager.c +++ b/profiles/time/manager.c @@ -26,24 +26,27 @@ #include #endif -#include "adapter.h" +#include + #include "manager.h" +#include "adapter.h" +#include "device.h" #include "server.h" -struct btd_adapter_driver time_server_driver = { - .name = "gatt-time-server", - .probe = time_server_init, - .remove = time_server_exit, +struct btd_profile time_profile = { + .name = "gatt-time-server", + .adapter_probe = time_server_init, + .adapter_remove = time_server_exit, }; int time_manager_init(void) { - btd_register_adapter_driver(&time_server_driver); + btd_profile_register(&time_profile); return 0; } void time_manager_exit(void) { - btd_unregister_adapter_driver(&time_server_driver); + btd_profile_unregister(&time_profile); } diff --git a/src/adapter.c b/src/adapter.c index 50779fdf9..31fa87dae 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -150,7 +151,8 @@ struct btd_adapter { GSList *powered_callbacks; GSList *pin_callbacks; - GSList *loaded_drivers; + GSList *drivers; + GSList *profiles; }; static void dev_info_free(void *data) @@ -1703,7 +1705,7 @@ static void create_stored_device_from_profiles(char *key, char *value, if (list) device_register_services(connection, device, list, ATT_PSM); - device_probe_drivers(device, uuids); + device_probe_profiles(device, uuids); g_slist_free_full(uuids, g_free); } @@ -1946,7 +1948,7 @@ static void create_stored_device_from_primaries(char *key, char *value, device_register_services(connection, device, services, -1); - device_probe_drivers(device, uuids); + device_probe_profiles(device, uuids); g_slist_free(uuids); } @@ -2038,8 +2040,7 @@ static void probe_driver(struct btd_adapter *adapter, gpointer user_data) return; } - adapter->loaded_drivers = g_slist_prepend(adapter->loaded_drivers, - driver); + adapter->drivers = g_slist_prepend(adapter->drivers, driver); } static void load_drivers(struct btd_adapter *adapter) @@ -2050,6 +2051,23 @@ static void load_drivers(struct btd_adapter *adapter) probe_driver(adapter, l->data); } +static void probe_profile(struct btd_profile *profile, void *data) +{ + struct btd_adapter *adapter = data; + int err; + + if (profile->adapter_probe == NULL) + return; + + err = profile->adapter_probe(adapter); + if (err < 0) { + error("%s: %s (%d)", profile->name, strerror(-err), -err); + return; + } + + adapter->profiles = g_slist_prepend(adapter->profiles, profile); +} + static void load_connections(struct btd_adapter *adapter) { GSList *l, *conns; @@ -2229,11 +2247,24 @@ static void remove_driver(gpointer data, gpointer user_data) driver->remove(adapter); } +static void remove_profile(gpointer data, gpointer user_data) +{ + struct btd_profile *profile = data; + struct btd_adapter *adapter = user_data; + + if (profile->adapter_remove) + profile->adapter_remove(adapter); +} + static void unload_drivers(struct btd_adapter *adapter) { - g_slist_foreach(adapter->loaded_drivers, remove_driver, adapter); - g_slist_free(adapter->loaded_drivers); - adapter->loaded_drivers = NULL; + g_slist_foreach(adapter->drivers, remove_driver, adapter); + g_slist_free(adapter->drivers); + adapter->drivers = NULL; + + g_slist_foreach(adapter->profiles, remove_profile, adapter); + g_slist_free(adapter->profiles); + adapter->profiles = NULL; } static void set_mode_complete(struct btd_adapter *adapter) @@ -2414,6 +2445,7 @@ gboolean adapter_init(struct btd_adapter *adapter, gboolean up) btd_adapter_gatt_server_start(adapter); load_drivers(adapter); + btd_profile_foreach(probe_profile, adapter); clear_blocked(adapter); load_devices(adapter); @@ -3049,7 +3081,7 @@ int btd_register_adapter_driver(struct btd_adapter_driver *driver) static void unload_driver(struct btd_adapter *adapter, gpointer data) { - adapter->loaded_drivers = g_slist_remove(adapter->loaded_drivers, data); + adapter->drivers = g_slist_remove(adapter->drivers, data); } void btd_unregister_adapter_driver(struct btd_adapter_driver *driver) diff --git a/src/agent.c b/src/agent.c index e54242592..b6ddd826d 100644 --- a/src/agent.c +++ b/src/agent.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include diff --git a/src/attrib-server.c b/src/attrib-server.c index 5cb1383e6..9b03e541e 100644 --- a/src/attrib-server.c +++ b/src/attrib-server.c @@ -28,6 +28,7 @@ #include #include +#include #include #include #include diff --git a/src/device.c b/src/device.c index 3b44d9b93..8cb087619 100644 --- a/src/device.c +++ b/src/device.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -136,7 +137,8 @@ struct btd_device { GSList *uuids; GSList *services; /* Primary services path */ GSList *primaries; /* List of primary services */ - GSList *drivers; /* List of device drivers */ + GSList *profiles; /* Probed profiles */ + GSList *conns; /* Connected profiles */ GSList *watches; /* List of disconnect_data */ gboolean temporary; struct agent *agent; @@ -169,6 +171,8 @@ struct btd_device { guint cleanup_id; }; +static GSList *profiles = NULL; + static uint16_t uuid_list[] = { L2CAP_UUID, PNP_INFO_SVCLASS_ID, @@ -176,8 +180,6 @@ static uint16_t uuid_list[] = { 0 }; -static GSList *device_drivers = NULL; - static void browse_request_free(struct browse_req *req) { if (req->listener_id) @@ -499,12 +501,12 @@ static DBusMessage *set_trust(DBusConnection *conn, DBusMessage *msg, return dbus_message_new_method_return(msg); } -static void driver_remove(struct btd_device_driver *driver, +static void profile_remove(struct btd_profile *profile, struct btd_device *device) { - driver->remove(device); + profile->device_remove(device); - device->drivers = g_slist_remove(device->drivers, driver); + device->profiles = g_slist_remove(device->profiles, profile); } static gboolean do_disconnect(gpointer user_data) @@ -531,7 +533,7 @@ int device_block(DBusConnection *conn, struct btd_device *device, if (device->connected) do_disconnect(device); - g_slist_foreach(device->drivers, (GFunc) driver_remove, device); + g_slist_foreach(device->profiles, (GFunc) profile_remove, device); if (!update_only) err = btd_adapter_block_address(device->adapter, @@ -584,7 +586,7 @@ int device_unblock(DBusConnection *conn, struct btd_device *device, emit_property_changed(conn, device->path, DEVICE_INTERFACE, "Blocked", DBUS_TYPE_BOOLEAN, &device->blocked); - device_probe_drivers(device, device->uuids); + device_probe_profiles(device, device->uuids); } return 0; @@ -1209,9 +1211,9 @@ void device_remove(struct btd_device *device, gboolean remove_stored) if (remove_stored) device_remove_stored(device); - g_slist_foreach(device->drivers, (GFunc) driver_remove, device); - g_slist_free(device->drivers); - device->drivers = NULL; + g_slist_foreach(device->profiles, (GFunc) profile_remove, device); + g_slist_free(device->profiles); + device->profiles = NULL; attrib_client_unregister(device->services); @@ -1252,112 +1254,114 @@ static gboolean record_has_uuid(const sdp_record_t *rec, static GSList *device_match_pattern(struct btd_device *device, const char *match_uuid, - GSList *profiles) + GSList *uuids) { - GSList *l, *uuids = NULL; + GSList *l, *match_uuids = NULL; - for (l = profiles; l; l = l->next) { - char *profile_uuid = l->data; + for (l = uuids; l; l = l->next) { + char *uuid = l->data; const sdp_record_t *rec; - rec = btd_device_get_record(device, profile_uuid); + rec = btd_device_get_record(device, uuid); if (!rec) continue; if (record_has_uuid(rec, match_uuid)) - uuids = g_slist_append(uuids, profile_uuid); + match_uuids = g_slist_append(match_uuids, uuid); } - return uuids; + return match_uuids; } -static GSList *device_match_driver(struct btd_device *device, - struct btd_device_driver *driver, - GSList *profiles) +static GSList *device_match_profile(struct btd_device *device, + struct btd_profile *profile, + GSList *uuids) { const char **uuid; - GSList *uuids = NULL; + GSList *match_uuids = NULL; - for (uuid = driver->uuids; *uuid; uuid++) { + for (uuid = profile->remote_uuids; *uuid; uuid++) { GSList *match; /* skip duplicated uuids */ - if (g_slist_find_custom(uuids, *uuid, + if (g_slist_find_custom(match_uuids, *uuid, (GCompareFunc) strcasecmp)) continue; - /* match profile driver */ - match = g_slist_find_custom(profiles, *uuid, + /* match profile uuid */ + match = g_slist_find_custom(uuids, *uuid, (GCompareFunc) strcasecmp); if (match) { - uuids = g_slist_append(uuids, match->data); + match_uuids = g_slist_append(match_uuids, match->data); continue; } /* match pattern driver */ - match = device_match_pattern(device, *uuid, profiles); - uuids = g_slist_concat(uuids, match); + match = device_match_pattern(device, *uuid, uuids); + match_uuids = g_slist_concat(match_uuids, match); } - return uuids; + return match_uuids; } -void device_probe_drivers(struct btd_device *device, GSList *profiles) +void device_probe_profiles(struct btd_device *device, GSList *uuids) { - GSList *list; char addr[18]; - int err; + GSList *l; ba2str(&device->bdaddr, addr); if (device->blocked) { - DBG("Skipping drivers for blocked device %s", addr); + DBG("Skipping profiles for blocked device %s", addr); goto add_uuids; } - DBG("Probing drivers for %s", addr); + DBG("Probing profiles for device %s", addr); - for (list = device_drivers; list; list = list->next) { - struct btd_device_driver *driver = list->data; + for (l = profiles; l != NULL; l = g_slist_next(l)) { + struct btd_profile *profile = l->data; GSList *probe_uuids; + int err; - probe_uuids = device_match_driver(device, driver, profiles); + if (profile->device_probe == NULL) + continue; + probe_uuids = device_match_profile(device, profile, uuids); if (!probe_uuids) continue; - err = driver->probe(device, probe_uuids); + err = profile->device_probe(device, probe_uuids); if (err < 0) { - error("%s driver probe failed for device %s", - driver->name, addr); + error("%s profile probe failed for device %s", + profile->name, addr); g_slist_free(probe_uuids); continue; } - device->drivers = g_slist_append(device->drivers, driver); + device->profiles = g_slist_append(device->profiles, profile); g_slist_free(probe_uuids); } add_uuids: - for (list = profiles; list; list = list->next) { - GSList *l = g_slist_find_custom(device->uuids, list->data, + for (l = uuids; l != NULL; l = g_slist_next(l)) { + GSList *match = g_slist_find_custom(device->uuids, l->data, (GCompareFunc) strcasecmp); - if (l) + if (match) continue; device->uuids = g_slist_insert_sorted(device->uuids, - g_strdup(list->data), + g_strdup(l->data), (GCompareFunc) strcasecmp); } } -static void device_remove_drivers(struct btd_device *device, GSList *uuids) +static void device_remove_profiles(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; + GSList *l; adapter_get_address(adapter, &src); ba2str(&src, srcaddr); @@ -1365,35 +1369,32 @@ static void device_remove_drivers(struct btd_device *device, GSList *uuids) records = read_records(&src, &device->bdaddr); - DBG("Removing drivers for %s", dstaddr); + DBG("Removing profiles for %s", dstaddr); - for (list = device->drivers; list; list = next) { - struct btd_device_driver *driver = list->data; + for (l = profiles; l != NULL; l = g_slist_next(l)) { + struct btd_profile *profile = l->data; const char **uuid; - next = list->next; - - for (uuid = driver->uuids; *uuid; uuid++) { + for (uuid = profile->remote_uuids; *uuid; uuid++) { if (!g_slist_find_custom(uuids, *uuid, (GCompareFunc) strcasecmp)) continue; - DBG("UUID %s was removed from device %s", - *uuid, dstaddr); + DBG("UUID %s was removed from device %s", *uuid, dstaddr); - driver->remove(device); - device->drivers = g_slist_remove(device->drivers, - driver); + profile->device_remove(device); + device->profiles = g_slist_remove(device->profiles, + profile); break; } } - for (list = uuids; list; list = list->next) { + for (l = uuids; l != NULL; l = g_slist_next(l)) { sdp_record_t *rec; - device->uuids = g_slist_remove(device->uuids, list->data); + device->uuids = g_slist_remove(device->uuids, l->data); - rec = find_record_in_list(records, list->data); + rec = find_record_in_list(records, l->data); if (!rec) continue; @@ -1402,7 +1403,6 @@ static void device_remove_drivers(struct btd_device *device, GSList *uuids) records = sdp_list_remove(records, rec); sdp_record_free(rec); - } if (records) @@ -1672,7 +1672,7 @@ static void search_cb(sdp_list_t *recs, int err, gpointer user_data) goto send_reply; } - /* Probe matching drivers for services added */ + /* Probe matching profiles for services added */ if (req->profiles_added) { GSList *list; @@ -1681,12 +1681,12 @@ static void search_cb(sdp_list_t *recs, int err, gpointer user_data) device_register_services(req->conn, device, list, ATT_PSM); - device_probe_drivers(device, req->profiles_added); + device_probe_profiles(device, req->profiles_added); } - /* Remove drivers for services removed */ + /* Remove profiles for services removed */ if (req->profiles_removed) - device_remove_drivers(device, req->profiles_removed); + device_remove_profiles(device, req->profiles_removed); /* Propagate services changes */ uuids_changed(req->device); @@ -1903,9 +1903,9 @@ static void primary_cb(GSList *services, guint8 status, gpointer user_data) device_register_services(req->conn, device, g_slist_copy(services), -1); if (req->profiles_removed) - device_remove_drivers(device, req->profiles_removed); + device_remove_profiles(device, req->profiles_removed); - device_probe_drivers(device, req->profiles_added); + device_probe_profiles(device, req->profiles_added); if (device->attios == NULL && device->attios_offline == NULL) attio_cleanup(device); @@ -2965,7 +2965,7 @@ void btd_device_add_uuid(struct btd_device *device, const char *uuid) new_uuid = g_strdup(uuid); uuid_list = g_slist_append(NULL, new_uuid); - device_probe_drivers(device, uuid_list); + device_probe_profiles(device, uuid_list); g_free(new_uuid); g_slist_free(uuid_list); @@ -3000,18 +3000,6 @@ const sdp_record_t *btd_device_get_record(struct btd_device *device, 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); - - return 0; -} - -void btd_unregister_device_driver(struct btd_device_driver *driver) -{ - device_drivers = g_slist_remove(device_drivers, driver); -} - struct btd_device *btd_device_ref(struct btd_device *device) { device->ref++; @@ -3190,3 +3178,41 @@ void device_set_pnpid(struct btd_device *device, uint8_t vendor_id_src, device_set_product(device, product_id); device_set_version(device, product_ver); } + +void btd_profile_foreach(void (*func)(struct btd_profile *p, void *data), + void *data) +{ + GSList *l, *next; + + for (l = profiles; l != NULL; l = next) { + struct btd_profile *profile = l->data; + + next = g_slist_next(l); + + func(profile, data); + } +} + +int btd_profile_register(struct btd_profile *profile) +{ + profiles = g_slist_append(profiles, profile); + return 0; +} + +void btd_profile_unregister(struct btd_profile *profile) +{ + profiles = g_slist_remove(profiles, profile); +} + +void btd_profile_connected(struct btd_profile *profile, + struct btd_device *device, int err) +{ + if (err == 0) + device->conns = g_slist_append(device->conns, profile); +} + +void btd_profile_disconnected(struct btd_profile *profile, + struct btd_device *device) +{ + device->conns = g_slist_remove(device->conns, profile); +} diff --git a/src/device.h b/src/device.h index a65de2681..ccb15fc80 100644 --- a/src/device.h +++ b/src/device.h @@ -34,9 +34,41 @@ typedef enum { AUTH_TYPE_NOTIFY_PINCODE, } auth_type_t; +#define BTD_UUIDS(args...) ((const char *[]) { args, NULL } ) + +struct btd_profile { + const char *name; + + const char *local_uuid; + const char **remote_uuids; + + bool auto_connect; + + int (*device_probe) (struct btd_device *device, GSList *uuids); + void (*device_remove) (struct btd_device *device); + + void (*connect) (struct btd_device *device); + void (*disconnect) (struct btd_device *device); + + int (*adapter_probe) (struct btd_adapter *adapter); + void (*adapter_remove) (struct btd_adapter *adapter); +}; + +void btd_profile_foreach(void (*func)(struct btd_profile *p, void *data), + void *data); + +int btd_profile_register(struct btd_profile *profile); +void btd_profile_unregister(struct btd_profile *profile); + +void btd_profile_connected(struct btd_profile *profile, + struct btd_device *device, int err); +void btd_profile_disconnected(struct btd_profile *profile, + struct btd_device *device); + struct btd_device *device_create(DBusConnection *conn, struct btd_adapter *adapter, const char *address, uint8_t bdaddr_type); + void device_set_name(struct btd_device *device, const char *name); void device_get_name(struct btd_device *device, char *name, size_t len); uint16_t btd_device_get_vendor(struct btd_device *device); @@ -49,7 +81,7 @@ int device_browse_primary(struct btd_device *device, DBusConnection *conn, DBusMessage *msg, gboolean secure); int device_browse_sdp(struct btd_device *device, DBusConnection *conn, DBusMessage *msg, uuid_t *search, gboolean reverse); -void device_probe_drivers(struct btd_device *device, GSList *profiles); +void device_probe_profiles(struct btd_device *device, GSList *profiles); const sdp_record_t *btd_device_get_record(struct btd_device *device, const char *uuid); GSList *btd_device_get_primaries(struct btd_device *device); @@ -108,18 +140,6 @@ void device_set_class(struct btd_device *device, uint32_t value); int device_get_appearance(struct btd_device *device, uint16_t *value); void device_set_appearance(struct btd_device *device, uint16_t value); -#define BTD_UUIDS(args...) ((const char *[]) { args, NULL } ) - -struct btd_device_driver { - const char *name; - const char **uuids; - int (*probe) (struct btd_device *device, GSList *uuids); - void (*remove) (struct btd_device *device); -}; - -int btd_register_device_driver(struct btd_device_driver *driver); -void btd_unregister_device_driver(struct btd_device_driver *driver); - struct btd_device *btd_device_ref(struct btd_device *device); void btd_device_unref(struct btd_device *device); diff --git a/src/event.c b/src/event.c index 158629331..42d05b692 100644 --- a/src/event.c +++ b/src/event.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include diff --git a/src/mgmt.c b/src/mgmt.c index 58aab2d09..45a5c9085 100644 --- a/src/mgmt.c +++ b/src/mgmt.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include -- 2.47.3