struct sink *sink_init(struct audio_device *dev, struct btd_service *service) { struct sink *sink; DBG("%s", device_get_path(dev->btd_dev)); sink = g_new0(struct sink, 1); sink->dev = dev; sink->service = btd_service_ref(service); sink->avdtp_callback_id = avdtp_add_state_cb(dev, avdtp_state_callback); return sink; }
struct source *source_init(struct audio_device *dev) { struct source *source; DBG("%s", device_get_path(dev->btd_dev)); source = g_new0(struct source, 1); source->dev = dev; source->avdtp_callback_id = avdtp_add_state_cb(dev, avdtp_state_callback); return source; }
static void register_reporter_device(struct btd_device *device, struct reporter_adapter *radapter) { const char *path = device_get_path(device); DBG("register on device %s", path); g_dbus_register_interface(radapter->conn, path, PROXIMITY_REPORTER_INTERFACE, reporter_methods, reporter_signals, NULL, device, NULL); btd_device_ref(device); radapter->devices = g_slist_prepend(radapter->devices, device); }
static void register_reporter_device(struct btd_device *device, struct reporter_adapter *radapter) { const char *path = device_get_path(device); DBG("register on device %s", path); g_dbus_register_interface(btd_get_dbus_connection(), path, PROXIMITY_REPORTER_INTERFACE, NULL, NULL, reporter_device_properties, device, NULL); btd_device_ref(device); radapter->devices = g_slist_prepend(radapter->devices, device); }
static void immediate_written(gpointer user_data) { struct monitor *monitor = user_data; const char *path = device_get_path(monitor->device); g_free(monitor->fallbacklevel); monitor->fallbacklevel = NULL; g_dbus_emit_property_changed(btd_get_dbus_connection(), path, PROXIMITY_INTERFACE, "ImmediateAlertLevel"); monitor->immediateto = g_timeout_add_seconds(IMMEDIATE_TIMEOUT, immediate_timeout, monitor); }
static void audio_remove(struct btd_device *device) { struct audio_device *dev; const char *path; path = device_get_path(device); dev = manager_find_device(path, NULL, NULL, NULL, FALSE); if (!dev) return; devices = g_slist_remove(devices, dev); audio_device_unregister(dev); }
static void imm_alert_emit_alert_signal(struct connected_device *condev, uint8_t alert_level) { const char *path, *alert_level_str; if (!condev) return; path = device_get_path(condev->device); alert_level_str = get_alert_level_string(alert_level); DBG("alert %s remote %s", alert_level_str, path); g_dbus_emit_property_changed(btd_get_dbus_connection(), path, PROXIMITY_REPORTER_INTERFACE, "ImmediateAlertLevel"); }
struct media_transport *media_transport_create(struct audio_device *device, uint8_t *configuration, size_t size, void *data) { struct media_endpoint *endpoint = data; struct media_transport *transport; const char *uuid; static int fd = 0; transport = g_new0(struct media_transport, 1); transport->device = device; transport->endpoint = endpoint; transport->configuration = g_new(uint8_t, size); memcpy(transport->configuration, configuration, size); transport->size = size; transport->path = g_strdup_printf("%s/fd%d", device_get_path(device->btd_dev), fd++); transport->fd = -1; uuid = media_endpoint_get_uuid(endpoint); if (strcasecmp(uuid, A2DP_SOURCE_UUID) == 0 || strcasecmp(uuid, A2DP_SINK_UUID) == 0) { struct a2dp_transport *a2dp; a2dp = g_new0(struct a2dp_transport, 1); transport->resume = resume_a2dp; transport->suspend = suspend_a2dp; transport->cancel = cancel_a2dp; transport->data = a2dp; transport->destroy = destroy_a2dp; if (strcasecmp(uuid, A2DP_SOURCE_UUID) == 0) { a2dp->volume = -1; transport->sink_watch = sink_add_state_cb(device, sink_state_changed, transport); } else { a2dp->volume = 127; avrcp_set_volume(device, a2dp->volume); transport->source_watch = source_add_state_cb(device, source_state_changed, transport); } } else goto fail;
static int csc_device_probe(struct btd_service *service) { struct btd_device *device = btd_service_get_device(service); struct btd_adapter *adapter; struct csc_adapter *cadapter; struct csc *csc; struct gatt_primary *prim; prim = btd_device_get_primary(device, CYCLING_SC_UUID); if (prim == NULL) return -EINVAL; adapter = device_get_adapter(device); cadapter = find_csc_adapter(adapter); if (cadapter == NULL) return -1; csc = g_new0(struct csc, 1); csc->dev = btd_device_ref(device); csc->cadapter = cadapter; if (!g_dbus_register_interface(btd_get_dbus_connection(), device_get_path(device), CYCLINGSPEED_INTERFACE, cyclingspeed_device_methods, NULL, cyclingspeed_device_properties, csc, destroy_csc)) { error("D-Bus failed to register %s interface", CYCLINGSPEED_INTERFACE); destroy_csc(csc); return -EIO; } csc->svc_range = g_new0(struct att_range, 1); csc->svc_range->start = prim->range.start; csc->svc_range->end = prim->range.end; cadapter->devices = g_slist_prepend(cadapter->devices, csc); csc->attioid = btd_device_add_attio_callback(device, attio_connected_cb, attio_disconnected_cb, csc); return 0; }
static struct service *service_create(struct gatt_db_attribute *attr, struct btd_gatt_client *client) { struct service *service; const char *device_path = device_get_path(client->device); bt_uuid_t uuid; service = new0(struct service, 1); service->chrcs = queue_new(); service->pending_ext_props = queue_new(); service->client = client; gatt_db_attribute_get_service_data(attr, &service->start_handle, &service->end_handle, &service->primary, &uuid); bt_uuid_to_uuid128(&uuid, &service->uuid); service->path = g_strdup_printf("%s/service%04x", device_path, service->start_handle); if (!g_dbus_register_interface(btd_get_dbus_connection(), service->path, GATT_SERVICE_IFACE, NULL, NULL, service_properties, service, service_free)) { error("Unable to register GATT service with handle 0x%04x for " "device %s", service->start_handle, client->devaddr); service_free(service); return NULL; } DBG("Exported GATT service: %s", service->path); /* Set service active so we can skip discovering next time */ gatt_db_service_set_active(attr, true); /* Mark the service as claimed since it going to be exported */ gatt_db_service_set_claimed(attr, true); return service; }
struct media_transport *media_transport_create(struct btd_device *device, uint8_t *configuration, size_t size, void *data) { struct media_endpoint *endpoint = data; struct media_transport *transport; const char *uuid; static int fd = 0; transport = g_new0(struct media_transport, 1); transport->device = device; transport->endpoint = endpoint; transport->configuration = g_new(uint8_t, size); memcpy(transport->configuration, configuration, size); transport->size = size; transport->path = g_strdup_printf("%s/fd%d", device_get_path(device), fd++); transport->fd = -1; uuid = media_endpoint_get_uuid(endpoint); if (strcasecmp(uuid, A2DP_SOURCE_UUID) == 0) { if (media_transport_init_source(transport) < 0) goto fail; } else if (strcasecmp(uuid, A2DP_SINK_UUID) == 0) { if (media_transport_init_sink(transport) < 0) goto fail; } else goto fail; if (g_dbus_register_interface(btd_get_dbus_connection(), transport->path, MEDIA_TRANSPORT_INTERFACE, transport_methods, NULL, transport_properties, transport, media_transport_free) == FALSE) { error("Could not register transport %s", transport->path); goto fail; } transports = g_slist_append(transports, transport); return transport; fail: media_transport_free(transport); return NULL; }
static int hid_device_probe(struct btd_device *device, GSList *uuids) { struct btd_adapter *adapter = device_get_adapter(device); const gchar *path = device_get_path(device); const sdp_record_t *rec = btd_device_get_record(device, uuids->data); bdaddr_t src, dst; DBG("path %s", path); if (!rec) return -1; adapter_get_address(adapter, &src); device_get_address(device, &dst); return input_device_register(connection, device, path, &src, &dst, HID_UUID, rec->handle, idle_timeout * 60); }
int sink_init(struct btd_service *service) { struct btd_device *dev = btd_service_get_device(service); struct sink *sink; DBG("%s", device_get_path(dev)); sink = g_new0(struct sink, 1); sink->service = btd_service_ref(service); sink->avdtp_callback_id = avdtp_add_state_cb(dev, avdtp_state_callback, sink); btd_service_set_user_data(service, sink); return 0; }
static void bnep_conn_cb(GIOChannel *chan, char *iface, int err, void *data) { struct network_conn *nc = data; const char *path; DBusConnection *conn; DBG(""); if (err < 0) { error("connect failed %s", strerror(-err)); goto failed; } info("%s connected", nc->dev); memcpy(nc->dev, iface, sizeof(nc->dev)); btd_service_connecting_complete(nc->service, 0); if (nc->connect) local_connect_cb(nc, 0); conn = btd_get_dbus_connection(); path = device_get_path(nc->peer->device); g_dbus_emit_property_changed(conn, path, NETWORK_PEER_INTERFACE, "Connected"); g_dbus_emit_property_changed(conn, path, NETWORK_PEER_INTERFACE, "Interface"); g_dbus_emit_property_changed(conn, path, NETWORK_PEER_INTERFACE, "UUID"); nc->state = CONNECTED; nc->dc_id = device_add_disconnect_watch(nc->peer->device, disconnect_cb, nc, NULL); g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL, bnep_watchdog_cb, nc); g_io_channel_unref(nc->io); nc->io = NULL; return; failed: cancel_connection(nc, -EIO); }
struct audio_device *manager_get_device(const bdaddr_t *src, const bdaddr_t *dst, gboolean create) { struct audio_device *dev; struct btd_adapter *adapter; struct btd_device *device; char addr[18]; const char *path; dev = manager_find_device(NULL, src, dst, NULL, FALSE); if (dev) return dev; if (!create) return NULL; ba2str(src, addr); adapter = manager_find_adapter(src); if (!adapter) { error("Unable to get a btd_adapter object for %s", addr); return NULL; } ba2str(dst, addr); device = adapter_get_device(connection, adapter, addr); if (!device) { error("Unable to get btd_device object for %s", addr); return NULL; } path = device_get_path(device); dev = audio_device_register(connection, device, path, src, dst); if (!dev) return NULL; devices = g_slist_append(devices, dev); return dev; }
static void update_watcher(gpointer data, gpointer user_data) { struct watcher *w = data; struct measurement *m = user_data; struct heartrate *hr = m->hr; const gchar *path = device_get_path(hr->dev); DBusMessageIter iter; DBusMessageIter dict; DBusMessage *msg; msg = dbus_message_new_method_call(w->srv, w->path, HEART_RATE_WATCHER_INTERFACE, "MeasurementReceived"); if (msg == NULL) return; dbus_message_iter_init_append(msg, &iter); dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH , &path); dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); dict_append_entry(&dict, "Value", DBUS_TYPE_UINT16, &m->value); if (m->has_energy) dict_append_entry(&dict, "Energy", DBUS_TYPE_UINT16, &m->energy); if (m->has_contact) dict_append_entry(&dict, "Contact", DBUS_TYPE_BOOLEAN, &m->contact); if (m->num_interval > 0) dict_append_array(&dict, "Interval", DBUS_TYPE_UINT16, &m->interval, m->num_interval); dbus_message_iter_close_container(&iter, &dict); dbus_message_set_no_reply(msg, TRUE); g_dbus_send_message(btd_get_dbus_connection(), msg); }
static void update_watcher(gpointer data, gpointer user_data) { struct watcher *w = data; struct measurement *m = user_data; struct csc *csc = m->csc; const char *path = device_get_path(csc->dev); DBusMessageIter iter; DBusMessageIter dict; DBusMessage *msg; msg = dbus_message_new_method_call(w->srv, w->path, CYCLINGSPEED_WATCHER_INTERFACE, "MeasurementReceived"); if (msg == NULL) return; dbus_message_iter_init_append(msg, &iter); dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH , &path); dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); if (m->has_wheel_rev) { dict_append_entry(&dict, "WheelRevolutions", DBUS_TYPE_UINT32, &m->wheel_rev); dict_append_entry(&dict, "LastWheelEventTime", DBUS_TYPE_UINT16, &m->last_wheel_time); } if (m->has_crank_rev) { dict_append_entry(&dict, "CrankRevolutions", DBUS_TYPE_UINT16, &m->crank_rev); dict_append_entry(&dict, "LastCrankEventTime", DBUS_TYPE_UINT16, &m->last_crank_time); } dbus_message_iter_close_container(&iter, &dict); dbus_message_set_no_reply(msg, TRUE); g_dbus_send_message(btd_get_dbus_connection(), msg); }
static int heartrate_device_register(struct btd_device *device, struct gatt_primary *prim) { struct btd_adapter *adapter; struct heartrate_adapter *hradapter; struct heartrate *hr; adapter = device_get_adapter(device); hradapter = find_heartrate_adapter(adapter); if (hradapter == NULL) return -1; hr = g_new0(struct heartrate, 1); hr->dev = btd_device_ref(device); hr->hradapter = hradapter; if (!g_dbus_register_interface(btd_get_dbus_connection(), device_get_path(device), HEART_RATE_INTERFACE, heartrate_device_methods, NULL, heartrate_device_properties, hr, destroy_heartrate)) { error("D-Bus failed to register %s interface", HEART_RATE_INTERFACE); destroy_heartrate(hr); return -EIO; } hr->svc_range = g_new0(struct att_range, 1); hr->svc_range->start = prim->range.start; hr->svc_range->end = prim->range.end; hradapter->devices = g_slist_prepend(hradapter->devices, hr); hr->attioid = btd_device_add_attio_callback(device, attio_connected_cb, attio_disconnected_cb, hr); return 0; }
static void path_unregister(void *data) { struct control *control = data; DBG("Unregistered interface %s on path %s", AUDIO_CONTROL_INTERFACE, device_get_path(control->dev)); if (control->session) avctp_disconnect(control->session); avctp_remove_state_cb(control->avctp_id); if (control->target) btd_service_unref(control->target); if (control->remote) btd_service_unref(control->remote); devices = g_slist_remove(devices, control); g_free(control); }
int monitor_register(DBusConnection *conn, struct btd_device *device, struct att_primary *linkloss, struct att_primary *txpower, struct att_primary *immediate, struct enabled *enabled) { const char *path = device_get_path(device); struct monitor *monitor; bdaddr_t sba, dba; char *level; adapter_get_address(device_get_adapter(device), &sba); device_get_address(device, &dba); level = read_proximity_config(&sba, &dba, "LinkLossAlertLevel"); monitor = g_new0(struct monitor, 1); monitor->device = btd_device_ref(device); monitor->conn = dbus_connection_ref(conn); monitor->linklosslevel = (level ? : g_strdup("high")); monitor->signallevel = g_strdup("unknown"); monitor->immediatelevel = g_strdup("none"); if (g_dbus_register_interface(conn, path, PROXIMITY_INTERFACE, monitor_methods, monitor_signals, NULL, monitor, monitor_destroy) == FALSE) { error("D-Bus failed to register %s interface", PROXIMITY_INTERFACE); monitor_destroy(monitor); return -1; } DBG("Registered interface %s on path %s", PROXIMITY_INTERFACE, path); if (linkloss && enabled->linkloss) { monitor->linkloss = g_new0(struct att_range, 1); monitor->linkloss->start = linkloss->start; monitor->linkloss->end = linkloss->end; monitor->enabled.linkloss = TRUE; }
struct audio_device *audio_device_register(struct btd_device *device) { struct audio_device *dev; DBG("%s", device_get_path(device)); dev = g_new0(struct audio_device, 1); dev->btd_dev = btd_device_ref(device); dev->priv = g_new0(struct dev_priv, 1); dev->priv->state = AUDIO_STATE_DISCONNECTED; if (sink_callback_id == 0) sink_callback_id = sink_add_state_cb(device_sink_cb, NULL); if (avdtp_callback_id == 0) avdtp_callback_id = avdtp_add_state_cb(device_avdtp_cb, NULL); if (avctp_callback_id == 0) avctp_callback_id = avctp_add_state_cb(device_avctp_cb, NULL); return dev; }
static void update_watcher(gpointer data, gpointer user_data) { struct watcher *w = data; struct measurement *m = user_data; const char *path = device_get_path(m->t->dev); DBusMessageIter iter; DBusMessageIter dict; DBusMessage *msg; msg = dbus_message_new_method_call(w->srv, w->path, THERMOMETER_WATCHER_INTERFACE, "MeasurementReceived"); if (msg == NULL) return; dbus_message_iter_init_append(msg, &iter); dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH , &path); dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); dict_append_entry(&dict, "Exponent", DBUS_TYPE_INT16, &m->exp); dict_append_entry(&dict, "Mantissa", DBUS_TYPE_INT32, &m->mant); dict_append_entry(&dict, "Unit", DBUS_TYPE_STRING, &m->unit); if (m->suptime) dict_append_entry(&dict, "Time", DBUS_TYPE_UINT64, &m->time); dict_append_entry(&dict, "Type", DBUS_TYPE_STRING, &m->type); dict_append_entry(&dict, "Measurement", DBUS_TYPE_STRING, &m->value); dbus_message_iter_close_container(&iter, &dict); dbus_message_set_no_reply(msg, TRUE); g_dbus_send_message(btd_get_dbus_connection(), msg); }
static void attio_disconnected_cb(gpointer user_data) { struct monitor *monitor = user_data; const char *path = device_get_path(monitor->device); g_attrib_unref(monitor->attrib); monitor->attrib = NULL; if (monitor->immediateto == 0) return; g_source_remove(monitor->immediateto); monitor->immediateto = 0; if (g_strcmp0(monitor->immediatelevel, "none") == 0) return; g_free(monitor->immediatelevel); monitor->immediatelevel = g_strdup("none"); emit_property_changed(monitor->conn, path, PROXIMITY_INTERFACE, "ImmediateAlertLevel", DBUS_TYPE_STRING, &monitor->immediatelevel); }
static void linkloss_written(guint8 status, const guint8 *pdu, guint16 plen, gpointer user_data) { struct monitor *monitor = user_data; struct btd_device *device = monitor->device; const char *path = device_get_path(device); if (status != 0) { error("Link Loss Write Request failed: %s", att_ecode2str(status)); return; } if (!dec_write_resp(pdu, plen)) { error("Link Loss Write Request: protocol error"); return; } DBG("Link Loss Alert Level written"); g_dbus_emit_property_changed(btd_get_dbus_connection(), path, PROXIMITY_INTERFACE, "LinkLossAlertLevel"); }
static int headset_probe(struct btd_device *device, GSList *uuids) { struct btd_adapter *adapter = device_get_adapter(device); const gchar *path = device_get_path(device); const sdp_record_t *record; sdp_list_t *protos; int ch; bdaddr_t src, dst; DBG("path %s", path); if (!g_slist_find_custom(uuids, HSP_HS_UUID, (GCompareFunc) strcasecmp)) return -EINVAL; record = btd_device_get_record(device, uuids->data); if (!record || sdp_get_access_protos(record, &protos) < 0) { error("Invalid record"); return -EINVAL; } 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("Invalid RFCOMM channel"); return -EINVAL; } adapter_get_address(adapter, &src); device_get_address(device, &dst); return fake_input_register(connection, device, path, &src, &dst, HSP_HS_UUID, ch); }
void heartrate_device_unregister(struct btd_device *device) { struct btd_adapter *adapter; struct heartrate_adapter *hradapter; struct heartrate *hr; GSList *l; adapter = device_get_adapter(device); hradapter = find_heartrate_adapter(adapter); if (hradapter == NULL) return; l = g_slist_find_custom(hradapter->devices, device, cmp_device); if (l == NULL) return; hr = l->data; hradapter->devices = g_slist_remove(hradapter->devices, hr); g_dbus_unregister_interface(btd_get_dbus_connection(), device_get_path(device), HEART_RATE_INTERFACE); }
static bool send_new_connection(struct ext_profile *ext, struct ext_io *conn, struct btd_device *dev) { DBusMessage *msg; const char *path; int fd; msg = dbus_message_new_method_call(ext->owner, ext->path, "org.bluez.Profile", "NewConnection"); if (!msg) { error("Unable to create NewConnection call for %s", ext->name); return false; } path = device_get_path(dev); fd = g_io_channel_unix_get_fd(conn->io); dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_UNIX_FD, &fd, DBUS_TYPE_INVALID); if (!dbus_connection_send_with_reply(btd_get_dbus_connection(), msg, &conn->new_conn, -1)) { error("%s: sending NewConnection failed", ext->name); dbus_message_unref(msg); return false; } dbus_message_unref(msg); dbus_pending_call_set_notify(conn->new_conn, new_conn_reply, conn, NULL); return true; }
static void change_property(struct thermometer *t, const char *name, gpointer value) { if (g_strcmp0(name, "Intermediate") == 0) { gboolean *intermediate = value; if (t->intermediate == *intermediate) return; t->intermediate = *intermediate; } else if (g_strcmp0(name, "Interval") == 0) { uint16_t *interval = value; if (t->has_interval && t->interval == *interval) return; t->has_interval = TRUE; t->interval = *interval; } else if (g_strcmp0(name, "Maximum") == 0) { uint16_t *max = value; if (t->max == *max) return; t->max = *max; } else if (g_strcmp0(name, "Minimum") == 0) { uint16_t *min = value; if (t->min == *min) return; t->min = *min; } else { DBG("%s is not a thermometer property", name); return; } g_dbus_emit_property_changed(btd_get_dbus_connection(), device_get_path(t->dev), THERMOMETER_INTERFACE, name); }
static gboolean immediate_timeout(gpointer user_data) { struct monitor *monitor = user_data; const char *path = device_get_path(monitor->device); monitor->immediateto = 0; if (g_strcmp0(monitor->immediatelevel, "none") == 0) return FALSE; if (monitor->attrib) { uint8_t value = ALERT_NONE; gatt_write_cmd(monitor->attrib, monitor->immediatehandle, &value, 1, NULL, NULL); } g_free(monitor->immediatelevel); monitor->immediatelevel = g_strdup("none"); emit_property_changed(monitor->conn, path, PROXIMITY_INTERFACE, "ImmediateAlertLevel", DBUS_TYPE_STRING, &monitor->immediatelevel); return FALSE; }
void source_unregister(struct audio_device *dev) { DBG("%s", device_get_path(dev->btd_dev)); source_free(dev); }