static gboolean bnep_watchdog_cb(GIOChannel *chan, GIOCondition cond, gpointer data) { struct network_conn *nc = data; DBusConnection *conn = btd_get_dbus_connection(); const char *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"); device_remove_disconnect_watch(nc->peer->device, nc->dc_id); nc->dc_id = 0; btd_service_disconnecting_complete(nc->service, 0); info("%s disconnected", nc->dev); bnep_if_down(nc->dev); nc->state = DISCONNECTED; memset(nc->dev, 0, sizeof(nc->dev)); strcpy(nc->dev, "bnep%d"); return FALSE; }
static struct network_peer *create_peer(struct btd_device *device) { struct network_peer *peer; const char *path; peer = g_new0(struct network_peer, 1); peer->device = btd_device_ref(device); path = device_get_path(device); if (g_dbus_register_interface(btd_get_dbus_connection(), path, NETWORK_PEER_INTERFACE, connection_methods, NULL, connection_properties, peer, path_unregister) == FALSE) { error("D-Bus failed to register %s interface", NETWORK_PEER_INTERFACE); peer_free(peer); return NULL; } DBG("Registered interface %s on path %s", NETWORK_PEER_INTERFACE, path); return peer; }
static void sap_io_destroy(void *data) { struct sap_server *server = data; struct sap_connection *conn = server->conn; DBG("conn %p", conn); if (!conn || !conn->io) return; stop_guard_timer(server); if (conn->state != SAP_STATE_CONNECT_IN_PROGRESS && conn->state != SAP_STATE_CONNECT_MODEM_BUSY) g_dbus_emit_property_changed(btd_get_dbus_connection(), adapter_get_path(server->adapter), SAP_SERVER_INTERFACE, "Connected"); if (conn->state == SAP_STATE_CONNECT_IN_PROGRESS || conn->state == SAP_STATE_CONNECT_MODEM_BUSY || conn->state == SAP_STATE_CONNECTED || conn->state == SAP_STATE_GRACEFUL_DISCONNECT) sap_disconnect_req(server, 1); sap_server_remove_conn(server); }
void sap_server_unregister(const char *path) { g_dbus_unregister_interface(btd_get_dbus_connection(), path, SAP_SERVER_INTERFACE); sap_exit(); }
static gboolean agent_sendfd(struct hf_agent *agent, int fd, DBusPendingCallNotifyFunction notify, void *data) { struct audio_device *dev = data; struct gateway *gw = dev->gateway; DBusMessage *msg; if (agent->call) return FALSE; msg = dbus_message_new_method_call(agent->name, agent->path, "org.bluez.HandsfreeAgent", "NewConnection"); dbus_message_append_args(msg, DBUS_TYPE_UNIX_FD, &fd, DBUS_TYPE_UINT16, &gw->version, DBUS_TYPE_INVALID); if (dbus_connection_send_with_reply(btd_get_dbus_connection(), msg, &agent->call, -1) == FALSE) { dbus_message_unref(msg); return FALSE; } dbus_pending_call_set_notify(agent->call, notify, dev, NULL); dbus_message_unref(msg); return TRUE; }
static void controlpoint_method_reply(struct controlpoint_req *req, uint8_t code) { DBusMessage *reply; switch (code) { case RSP_SUCCESS: reply = dbus_message_new_method_return(req->msg); break; case RSP_NOT_SUPPORTED: reply = btd_error_not_supported(req->msg); break; case RSP_INVALID_PARAM: reply = btd_error_invalid_args(req->msg); break; case RSP_FAILED: reply = btd_error_failed(req->msg, "Failed"); break; default: reply = btd_error_failed(req->msg, "Unknown error"); break; } g_dbus_send_message(btd_get_dbus_connection(), reply); dbus_message_unref(req->msg); }
static void read_location_cb(guint8 status, const guint8 *pdu, guint16 len, gpointer user_data) { struct csc *csc = user_data; uint8_t value; ssize_t vlen; if (status) { error("Sensor Location read failed: %s", att_ecode2str(status)); return; } vlen = dec_read_resp(pdu, len, &value, sizeof(value)); if (vlen < 0) { error("Protocol error"); return; } if (vlen != sizeof(value)) { error("Invalid value length for Sensor Location"); return; } csc->has_location = TRUE; csc->location = value; g_dbus_emit_property_changed(btd_get_dbus_connection(), device_get_path(csc->dev), CYCLINGSPEED_INTERFACE, "Location"); }
static struct notify_client *notify_client_create(struct characteristic *chrc, const char *owner) { struct notify_client *client; client = new0(struct notify_client, 1); if (!client) return NULL; client->chrc = chrc; client->owner = strdup(owner); if (!client->owner) { free(client); return NULL; } client->watch = g_dbus_add_disconnect_watch(btd_get_dbus_connection(), owner, notify_client_disconnect, client, NULL); if (!client->watch) { free(client->owner); free(client); return NULL; } return notify_client_ref(client); }
static int display_pincode_request_new(struct agent_request *req, const char *device_path, const char *pincode) { struct agent *agent = req->agent; req->msg = dbus_message_new_method_call(agent->owner, agent->path, AGENT_INTERFACE, "DisplayPinCode"); if (req->msg == NULL) { error("Couldn't allocate D-Bus message"); return -ENOMEM; } dbus_message_append_args(req->msg, DBUS_TYPE_OBJECT_PATH, &device_path, DBUS_TYPE_STRING, &pincode, DBUS_TYPE_INVALID); if (g_dbus_send_message_with_reply(btd_get_dbus_connection(), req->msg, &req->call, REQUEST_TIMEOUT) == FALSE) { error("D-Bus send failed"); return -EIO; } dbus_pending_call_set_notify(req->call, display_pincode_reply, req, NULL); return 0; }
static void csc_device_remove(struct btd_service *service) { struct btd_device *device = btd_service_get_device(service); struct btd_adapter *adapter; struct csc_adapter *cadapter; struct csc *csc; GSList *l; adapter = device_get_adapter(device); cadapter = find_csc_adapter(adapter); if (cadapter == NULL) return; l = g_slist_find_custom(cadapter->devices, device, cmp_device); if (l == NULL) return; csc = l->data; cadapter->devices = g_slist_remove(cadapter->devices, csc); g_dbus_unregister_interface(btd_get_dbus_connection(), device_get_path(device), CYCLINGSPEED_INTERFACE); }
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"); g_dbus_emit_property_changed(btd_get_dbus_connection(), path, PROXIMITY_INTERFACE, "ImmediateAlertLevel"); return FALSE; }
static struct monitor *register_monitor(struct btd_device *device) { const char *path = device_get_path(device); struct monitor *monitor; char *level; monitor = find_monitor(device); if (monitor != NULL) return monitor; level = read_proximity_config(device, "LinkLossAlertLevel"); monitor = g_new0(struct monitor, 1); monitor->device = btd_device_ref(device); monitor->linklosslevel = (level ? : g_strdup("high")); monitor->signallevel = g_strdup("unknown"); monitor->immediatelevel = g_strdup("none"); monitors = g_slist_append(monitors, monitor); if (g_dbus_register_interface(btd_get_dbus_connection(), path, PROXIMITY_INTERFACE, NULL, NULL, monitor_device_properties, monitor, monitor_destroy) == FALSE) { error("D-Bus failed to register %s interface", PROXIMITY_INTERFACE); monitor_destroy(monitor); return NULL; } DBG("Registered interface %s on path %s", PROXIMITY_INTERFACE, path); return monitor; }
static void controlpoint_write_cb(guint8 status, const guint8 *pdu, guint16 len, gpointer user_data) { struct controlpoint_req *req = user_data; if (status == 0) { req->timeout = g_timeout_add_seconds(ATT_TIMEOUT, controlpoint_timeout, req); return; } error("SC Control Point write failed (opcode=%d)", req->opcode); if (req->opcode == UPDATE_SENSOR_LOC) { g_dbus_pending_property_error(req->reply_id, ERROR_INTERFACE ".Failed", "Operation failed (%d)", status); } else if (req->opcode == SET_CUMULATIVE_VALUE) { DBusMessage *reply; reply = btd_error_failed(req->msg, "Operation failed"); g_dbus_send_message(btd_get_dbus_connection(), reply); dbus_message_unref(req->msg); } req->csc->pending_req = NULL; g_free(req); }
static int set_setting(const char *key, const char *value, void *user_data) { struct media_player *mp = user_data; const char *iface = MEDIA_PLAYER_INTERFACE; DBusMessage *msg; DBusMessageIter iter; DBG("%s = %s", key, value); if (!g_hash_table_lookup(mp->settings, key)) return -EINVAL; msg = dbus_message_new_method_call(mp->sender, mp->path, DBUS_INTERFACE_PROPERTIES, "Set"); if (msg == NULL) { error("Couldn't allocate D-Bus message"); return -ENOMEM; } dbus_message_iter_init_append(msg, &iter); dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &iface); if (strcasecmp(key, "Shuffle") == 0) set_shuffle_setting(&iter, value); else if (strcasecmp(key, "Repeat") == 0) set_repeat_setting(&iter, value); g_dbus_send_message(btd_get_dbus_connection(), msg); return 0; }
int agent_display_passkey(struct agent *agent, struct btd_device *device, uint32_t passkey, uint16_t entered) { DBusMessage *message; const char *dev_path = device_get_path(device); message = dbus_message_new_method_call(agent->owner, agent->path, AGENT_INTERFACE, "DisplayPasskey"); if (!message) { error("Couldn't allocate D-Bus message"); return -1; } dbus_message_append_args(message, DBUS_TYPE_OBJECT_PATH, &dev_path, DBUS_TYPE_UINT32, &passkey, DBUS_TYPE_UINT16, &entered, DBUS_TYPE_INVALID); if (!g_dbus_send_message(btd_get_dbus_connection(), message)) { error("D-Bus send failed"); return -1; } return 0; }
static void write_result_cb(bool success, bool reliable_error, uint8_t att_ecode, void *user_data) { struct async_dbus_op *op = user_data; DBusMessage *reply; if (op->complete && !op->complete(op->data)) { reply = btd_error_failed(op->msg, "Operation failed"); goto done; } if (!success) { if (reliable_error) reply = btd_error_failed(op->msg, "Reliable write failed"); else reply = create_gatt_dbus_error(op->msg, att_ecode); goto done; } reply = g_dbus_create_reply(op->msg, DBUS_TYPE_INVALID); if (!reply) { error("Failed to allocate D-Bus message reply"); return; } done: g_dbus_send_message(btd_get_dbus_connection(), reply); }
static void read_ext_props_cb(bool success, uint8_t att_ecode, const uint8_t *value, uint16_t length, void *user_data) { struct characteristic *chrc = user_data; struct service *service = chrc->service; if (!success) { error("Failed to obtain extended properties - error: 0x%02x", att_ecode); return; } if (!value || length != 2) { error("Malformed extended properties value"); return; } chrc->ext_props = get_le16(value); if (chrc->ext_props) g_dbus_emit_property_changed(btd_get_dbus_connection(), chrc->path, GATT_CHARACTERISTIC_IFACE, "Flags"); queue_remove(service->pending_ext_props, chrc); notify_chrcs(service); }
static int confirmation_request_new(struct agent_request *req, const char *device_path, uint32_t passkey) { struct agent *agent = req->agent; req->msg = dbus_message_new_method_call(agent->name, agent->path, "org.bluez.Agent", "RequestConfirmation"); if (req->msg == NULL) { error("Couldn't allocate D-Bus message"); return -ENOMEM; } dbus_message_append_args(req->msg, DBUS_TYPE_OBJECT_PATH, &device_path, DBUS_TYPE_UINT32, &passkey, DBUS_TYPE_INVALID); if (dbus_connection_send_with_reply(btd_get_dbus_connection(), req->msg, &req->call, REQUEST_TIMEOUT) == FALSE) { error("D-Bus send failed"); return -EIO; } dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL); return 0; }
static void cleanup_monitor(struct monitor *monitor) { struct btd_device *device = monitor->device; const char *path = device_get_path(device); if (monitor->immediate != NULL || monitor->txpower != NULL) return; if (monitor->immediateto != 0) { g_source_remove(monitor->immediateto); monitor->immediateto = 0; } if (monitor->linkloss != NULL) return; if (monitor->attioid != 0) { btd_device_remove_attio_callback(device, monitor->attioid); monitor->attioid = 0; } if (monitor->attrib != NULL) { g_attrib_unref(monitor->attrib); monitor->attrib = NULL; } g_dbus_unregister_interface(btd_get_dbus_connection(), path, PROXIMITY_INTERFACE); }
static int confirm_mode_change_request_new(struct agent_request *req, const char *mode) { struct agent *agent = req->agent; req->msg = dbus_message_new_method_call(agent->name, agent->path, "org.bluez.Agent", "ConfirmModeChange"); if (req->msg == NULL) { error("Couldn't allocate D-Bus message"); return -ENOMEM; } dbus_message_append_args(req->msg, DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID); if (dbus_connection_send_with_reply(btd_get_dbus_connection(), req->msg, &req->call, REQUEST_TIMEOUT) == FALSE) { error("D-Bus send failed"); return -EIO; } dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL); return 0; }
static DBusMessage *cancel_authorization(DBusConnection *conn, DBusMessage *msg, void *data) { DBusMessage *reply; struct service_adapter *serv_adapter = data; struct pending_auth *auth; const gchar *sender; sender = dbus_message_get_sender(msg); auth = find_pending_by_sender(serv_adapter, sender); if (auth == NULL) return btd_error_does_not_exist(msg); btd_cancel_authorization(auth->id); reply = btd_error_not_authorized(auth->msg); dbus_message_unref(auth->msg); g_dbus_send_message(btd_get_dbus_connection(), reply); serv_adapter->pending_list = g_slist_remove(serv_adapter->pending_list, auth); g_free(auth); auth = next_pending(serv_adapter); if (auth == NULL) goto done; auth->id = btd_request_authorization(get_address(serv_adapter), &auth->dst, auth->uuid, auth_cb, serv_adapter); done: return dbus_message_new_method_return(msg); }
static int agent_call_authorize(struct agent_request *req, const char *device_path, const char *uuid) { struct agent *agent = req->agent; req->msg = dbus_message_new_method_call(agent->name, agent->path, "org.bluez.Agent", "Authorize"); if (!req->msg) { error("Couldn't allocate D-Bus message"); return -ENOMEM; } dbus_message_append_args(req->msg, DBUS_TYPE_OBJECT_PATH, &device_path, DBUS_TYPE_STRING, &uuid, DBUS_TYPE_INVALID); if (dbus_connection_send_with_reply(btd_get_dbus_connection(), req->msg, &req->call, REQUEST_TIMEOUT) == FALSE) { error("D-Bus send failed"); return -EIO; } dbus_pending_call_set_notify(req->call, simple_agent_reply, req, NULL); return 0; }
static int pincode_request_new(struct agent_request *req, const char *device_path, dbus_bool_t secure) { struct agent *agent = req->agent; /* TODO: Add a new method or a new param to Agent interface to request secure pin. */ req->msg = dbus_message_new_method_call(agent->name, agent->path, "org.bluez.Agent", "RequestPinCode"); if (req->msg == NULL) { error("Couldn't allocate D-Bus message"); return -ENOMEM; } dbus_message_append_args(req->msg, DBUS_TYPE_OBJECT_PATH, &device_path, DBUS_TYPE_INVALID); if (dbus_connection_send_with_reply(btd_get_dbus_connection(), req->msg, &req->call, REQUEST_TIMEOUT) == FALSE) { error("D-Bus send failed"); return -EIO; } dbus_pending_call_set_notify(req->call, pincode_reply, req, NULL); return 0; }
static void media_player_free(gpointer data) { DBusConnection *conn = btd_get_dbus_connection(); struct media_player *mp = data; struct media_adapter *adapter = mp->adapter; if (mp->player) { adapter->players = g_slist_remove(adapter->players, mp); release_player(mp); } g_dbus_remove_watch(conn, mp->watch); g_dbus_remove_watch(conn, mp->properties_watch); g_dbus_remove_watch(conn, mp->seek_watch); if (mp->track) g_hash_table_unref(mp->track); if (mp->settings) g_hash_table_unref(mp->settings); g_timer_destroy(mp->timer); g_free(mp->sender); g_free(mp->path); g_free(mp->status); g_free(mp); }
static void release_endpoint(struct media_endpoint *endpoint) { DBusMessage *msg; DBG("sender=%s path=%s", endpoint->sender, endpoint->path); /* already exit */ if (endpoint->watch == 0) goto done; clear_endpoint(endpoint); msg = dbus_message_new_method_call(endpoint->sender, endpoint->path, MEDIA_ENDPOINT_INTERFACE, "Release"); if (msg == NULL) { error("Couldn't allocate D-Bus message"); return; } g_dbus_send_message(btd_get_dbus_connection(), msg); done: media_endpoint_remove(endpoint); }
static void unregister_interface(const char *path) { DBG("path %s", path); g_dbus_unregister_interface(btd_get_dbus_connection(), path, SERVICE_INTERFACE); }
static int register_interface(const char *path, struct btd_adapter *adapter) { struct service_adapter *serv_adapter; DBG("path %s", path); serv_adapter = g_try_new0(struct service_adapter, 1); if (serv_adapter == NULL) return -ENOMEM; if (adapter != NULL) serv_adapter->adapter = btd_adapter_ref(adapter); serv_adapter->pending_list = NULL; if (g_dbus_register_interface(btd_get_dbus_connection(), path, SERVICE_INTERFACE, service_methods, NULL, NULL, serv_adapter, path_unregister) == FALSE) { error("D-Bus failed to register %s interface", SERVICE_INTERFACE); g_free(serv_adapter); return -EIO; } DBG("Registered interface %s on path %s", SERVICE_INTERFACE, path); if (serv_adapter->adapter == NULL) serv_adapter_any = serv_adapter; 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); if (!service) return NULL; service->chrcs = queue_new(); if (!service->chrcs) { free(service); return NULL; } service->pending_ext_props = queue_new(); if (!service->pending_ext_props) { queue_destroy(service->chrcs, NULL); free(service); return NULL; } 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; }
static struct characteristic *characteristic_create( struct gatt_db_attribute *attr, struct service *service) { struct characteristic *chrc; bt_uuid_t uuid; chrc = new0(struct characteristic, 1); if (!chrc) return NULL; chrc->descs = queue_new(); if (!chrc->descs) { free(chrc); return NULL; } chrc->notify_clients = queue_new(); if (!chrc->notify_clients) { queue_destroy(chrc->descs, NULL); free(chrc); return NULL; } chrc->service = service; gatt_db_attribute_get_char_data(attr, &chrc->handle, &chrc->value_handle, &chrc->props, &uuid); chrc->attr = gatt_db_get_attribute(service->client->db, chrc->value_handle); if (!chrc->attr) { error("Attribute 0x%04x not found", chrc->value_handle); characteristic_free(chrc); return NULL; } bt_uuid_to_uuid128(&uuid, &chrc->uuid); chrc->path = g_strdup_printf("%s/char%04x", service->path, chrc->handle); if (!g_dbus_register_interface(btd_get_dbus_connection(), chrc->path, GATT_CHARACTERISTIC_IFACE, characteristic_methods, NULL, characteristic_properties, chrc, characteristic_free)) { error("Unable to register GATT characteristic with handle " "0x%04x", chrc->handle); characteristic_free(chrc); return NULL; } DBG("Exported GATT characteristic: %s", chrc->path); return chrc; }
void sap_exit(void) { if (--init_cnt) return; g_dbus_unregister_interface(btd_get_dbus_connection(), SAP_DUMMY_PATH, SAP_DUMMY_IFACE); }