int connection_register(struct btd_service *service) { struct btd_device *device = btd_service_get_device(service); struct network_peer *peer; struct network_conn *nc; uint16_t id = get_service_id(service); DBG("%s id %u", device_get_path(device), id); peer = find_peer(peers, device); if (!peer) { peer = create_peer(device); if (!peer) return -1; peers = g_slist_append(peers, peer); } nc = g_new0(struct network_conn, 1); nc->id = id; nc->service = btd_service_ref(service); nc->state = DISCONNECTED; nc->peer = peer; btd_service_set_user_data(service, nc); DBG("id %u registered", id); peer->connections = g_slist_append(peer->connections, nc); return 0; }
static void source_set_state(struct source *source, source_state_t new_state) { struct btd_device *dev = btd_service_get_device(source->service); source_state_t old_state = source->state; GSList *l; source->state = new_state; DBG("State changed %s: %s -> %s", device_get_path(dev), str_state[old_state], str_state[new_state]); for (l = source_callbacks; l != NULL; l = l->next) { struct source_state_callback *cb = l->data; if (cb->service != source->service) continue; cb->cb(source->service, old_state, new_state, cb->user_data); } if (new_state != SOURCE_STATE_DISCONNECTED) return; if (source->session) { avdtp_unref(source->session); source->session = NULL; } }
static int gap_accept(struct btd_service *service) { struct btd_device *device = btd_service_get_device(service); struct gatt_db *db = btd_device_get_gatt_db(device); struct bt_gatt_client *client = btd_device_get_gatt_client(device); struct gas *gas = btd_service_get_user_data(service); char addr[18]; bt_uuid_t gap_uuid; ba2str(device_get_address(device), addr); DBG("GAP profile accept (%s)", addr); if (!gas) { error("GAP service not handled by profile"); return -1; } gas->db = gatt_db_ref(db); gas->client = bt_gatt_client_ref(client); /* Handle the GAP services */ bt_uuid16_create(&gap_uuid, GAP_UUID16); gatt_db_foreach_service(db, &gap_uuid, foreach_gap_service, gas); if (!gas->attr) { error("GAP attribute not found"); gas_reset(gas); return -1; } btd_service_connecting_complete(service, 0); 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); }
int input_device_register(struct btd_service *service) { struct btd_device *device = btd_service_get_device(service); const char *path = device_get_path(device); struct input_device *idev; DBG("%s", path); idev = input_device_new(service); if (!idev) return -EINVAL; if (g_dbus_register_interface(btd_get_dbus_connection(), idev->path, INPUT_INTERFACE, NULL, NULL, input_properties, idev, NULL) == FALSE) { error("Unable to register %s interface", INPUT_INTERFACE); input_device_free(idev); return -EINVAL; } btd_service_set_user_data(service, idev); return 0; }
int source_connect(struct btd_service *service) { struct source *source = btd_service_get_user_data(service); if (!source->session) source->session = a2dp_avdtp_get(btd_service_get_device(service)); if (!source->session) { DBG("Unable to get a session"); return -EIO; } if (source->connect_id > 0 || source->disconnect_id > 0) return -EBUSY; if (source->state == SOURCE_STATE_CONNECTING) return -EBUSY; if (source->stream_state >= AVDTP_STATE_OPEN) return -EALREADY; if (!source_setup_stream(service, NULL)) { DBG("Failed to create a stream"); return -EIO; } DBG("stream creation in progress"); return 0; }
static void target_cb(struct btd_service *service, btd_service_state_t old_state, btd_service_state_t new_state) { struct btd_device *dev = btd_service_get_device(service); struct policy_data *data; data = find_data(dev); if (data == NULL) return; switch (new_state) { case BTD_SERVICE_STATE_UNAVAILABLE: case BTD_SERVICE_STATE_DISCONNECTED: break; case BTD_SERVICE_STATE_CONNECTING: break; case BTD_SERVICE_STATE_CONNECTED: if (data->tg_timer > 0) { g_source_remove(data->tg_timer); data->tg_timer = 0; } break; case BTD_SERVICE_STATE_DISCONNECTING: break; } }
static struct control *control_init(struct btd_service *service) { struct control *control; struct btd_device *dev = btd_service_get_device(service); control = find_control(dev); if (control != NULL) return control; control = g_new0(struct control, 1); if (!g_dbus_register_interface(btd_get_dbus_connection(), device_get_path(dev), AUDIO_CONTROL_INTERFACE, control_methods, NULL, control_properties, control, path_unregister)) { g_free(control); return NULL; } DBG("Registered interface %s on path %s", AUDIO_CONTROL_INTERFACE, device_get_path(dev)); control->dev = dev; control->avctp_id = avctp_add_state_cb(dev, state_changed, control); devices = g_slist_prepend(devices, control); return control; }
static void source_cb(struct btd_service *service, btd_service_state_t old_state, btd_service_state_t new_state) { struct btd_device *dev = btd_service_get_device(service); struct policy_data *data; struct btd_service *target; target = btd_device_get_service(dev, AVRCP_TARGET_UUID); if (target == NULL) return; data = policy_get_data(dev); switch (new_state) { case BTD_SERVICE_STATE_UNAVAILABLE: case BTD_SERVICE_STATE_DISCONNECTED: if (old_state == BTD_SERVICE_STATE_CONNECTING) { int err = btd_service_get_error(service); if (err == -EAGAIN) { if (data->source_retries < SOURCE_RETRIES) policy_set_source_timer(data); else data->source_retries = 0; break; } else if (data->source_timer > 0) { g_source_remove(data->source_timer); data->source_timer = 0; } } if (data->tg_timer > 0) { g_source_remove(data->tg_timer); data->tg_timer = 0; } else if (btd_service_get_state(target) != BTD_SERVICE_STATE_DISCONNECTED) policy_disconnect(data, target); break; case BTD_SERVICE_STATE_CONNECTING: break; case BTD_SERVICE_STATE_CONNECTED: if (data->source_timer > 0) { g_source_remove(data->source_timer); data->source_timer = 0; } /* Check if service initiate the connection then proceed * immediatelly otherwise set timer */ if (old_state == BTD_SERVICE_STATE_CONNECTING) policy_connect(data, target); else if (btd_service_get_state(target) != BTD_SERVICE_STATE_CONNECTED) policy_set_tg_timer(data); break; case BTD_SERVICE_STATE_DISCONNECTING: break; } }
static int hog_probe(struct btd_service *service) { struct btd_device *device = btd_service_get_device(service); const char *path = device_get_path(device); GSList *primaries, *l; DBG("path %s", path); primaries = btd_device_get_primaries(device); if (primaries == NULL) return -EINVAL; for (l = primaries; l; l = g_slist_next(l)) { struct gatt_primary *prim = l->data; struct hog_device *dev; if (strcmp(prim->uuid, HOG_UUID) != 0) continue; dev = hog_device_new(device, prim); btd_service_set_user_data(service, dev); return 0; } return -EINVAL; }
static struct input_device *input_device_new(struct btd_service *service) { struct btd_device *device = btd_service_get_device(service); struct btd_profile *p = btd_service_get_profile(service); const char *path = device_get_path(device); const sdp_record_t *rec = btd_device_get_record(device, p->remote_uuid); struct btd_adapter *adapter = device_get_adapter(device); struct input_device *idev; char name[HCI_MAX_NAME_LENGTH + 1]; idev = g_new0(struct input_device, 1); bacpy(&idev->src, btd_adapter_get_address(adapter)); bacpy(&idev->dst, device_get_address(device)); idev->service = btd_service_ref(service); idev->device = btd_device_ref(device); idev->path = g_strdup(path); idev->handle = rec->handle; idev->disable_sdp = is_device_sdp_disable(rec); device_get_name(device, name, HCI_MAX_NAME_LENGTH); if (strlen(name) > 0) idev->name = g_strdup(name); /* Initialize device properties */ extract_hid_props(idev, rec); return idev; }
static int gap_driver_probe(struct btd_service *service) { struct btd_device *device = btd_service_get_device(service); struct gas *gas; GSList *l; char addr[18]; ba2str(device_get_address(device), addr); DBG("GAP profile probe (%s)", addr); /* Ignore, if we were probed for this device already */ l = g_slist_find_custom(devices, device, cmp_device); if (l) { error("Profile probed twice for the same device!"); return -1; } gas = g_new0(struct gas, 1); if (!gas) return -1; gas->device = btd_device_ref(device); devices = g_slist_append(devices, gas); return 0; }
static int a2dp_sink_probe(struct btd_service *service) { struct btd_device *dev = btd_service_get_device(service); DBG("path %s", device_get_path(dev)); return sink_init(service); }
static int avrcp_remote_probe(struct btd_service *service) { struct btd_device *dev = btd_service_get_device(service); DBG("path %s", device_get_path(dev)); return control_init_remote(service); }
void control_unregister(struct btd_service *service) { struct btd_device *dev = btd_service_get_device(service); g_dbus_unregister_interface(btd_get_dbus_connection(), device_get_path(dev), AUDIO_CONTROL_INTERFACE); }
void source_unregister(struct btd_service *service) { struct btd_device *dev = btd_service_get_device(service); DBG("%s", device_get_path(dev)); source_free(service); }
static int avrcp_control_disconnect(struct btd_service *service) { struct btd_device *dev = btd_service_get_device(service); const char *path = device_get_path(dev); DBG("path %s", path); return control_disconnect(service); }
static int a2dp_sink_disconnect(struct btd_service *service) { struct btd_device *dev = btd_service_get_device(service); const char *path = device_get_path(dev); DBG("path %s", path); return sink_disconnect(service, FALSE); }
static void hog_remove(struct btd_service *service) { struct hog_device *dev = btd_service_get_user_data(service); struct btd_device *device = btd_service_get_device(service); const char *path = device_get_path(device); DBG("path %s", path); hog_device_free(dev); }
static struct reconnect_data *reconnect_add(struct btd_service *service) { struct btd_device *dev = btd_service_get_device(service); struct reconnect_data *reconnect; reconnect = reconnect_find(dev); if (!reconnect) { reconnect = g_new0(struct reconnect_data, 1); reconnect->dev = dev; reconnects = g_slist_append(reconnects, reconnect); }
static int monitor_txpower_probe(struct btd_service *service) { struct btd_device *device = btd_service_get_device(service); struct gatt_primary *txpower; txpower = btd_device_get_primary(device, TX_POWER_UUID); if (txpower == NULL) return -1; return monitor_register_txpower(device, &enabled, txpower); }
static int monitor_linkloss_probe(struct btd_service *service) { struct btd_device *device = btd_service_get_device(service); struct gatt_primary *linkloss; linkloss = btd_device_get_primary(device, LINK_LOSS_UUID); if (linkloss == NULL) return -1; return monitor_register_linkloss(device, &enabled, linkloss); }
static int heartrate_device_probe(struct btd_service *service) { struct btd_device *device = btd_service_get_device(service); struct gatt_primary *prim; prim = btd_device_get_primary(device, HEART_RATE_UUID); if (prim == NULL) return -EINVAL; return heartrate_device_register(device, prim); }
static int monitor_immediate_probe(struct btd_service *service) { struct btd_device *device = btd_service_get_device(service); struct gatt_primary *immediate; immediate = btd_device_get_primary(device, IMMEDIATE_ALERT_UUID); if (immediate == NULL) return -1; return monitor_register_immediate(device, &enabled, immediate); }
static int deviceinfo_driver_probe(struct btd_service *service) { struct btd_device *device = btd_service_get_device(service); struct gatt_primary *prim; prim = btd_device_get_primary(device, DEVICE_INFORMATION_UUID); if (prim == NULL) return -EINVAL; return deviceinfo_register(service, prim); }
void reporter_device_remove(struct btd_service *service) { struct btd_device *device = btd_service_get_device(service); struct reporter_adapter *radapter; struct btd_adapter *adapter = device_get_adapter(device); radapter = find_reporter_adapter(adapter); if (!radapter) return; unregister_reporter_device(device, radapter); }
static int scan_param_probe(struct btd_service *service) { struct btd_device *device = btd_service_get_device(service); struct gatt_primary *prim; DBG("Probing Scan Parameters"); prim = btd_device_get_primary(device, SCAN_PARAMETERS_UUID); if (!prim) return -EINVAL; return scan_register(service, prim); }
void input_device_unregister(struct btd_service *service) { struct btd_device *device = btd_service_get_device(service); const char *path = device_get_path(device); struct input_device *idev = btd_service_get_user_data(service); DBG("%s", path); g_dbus_unregister_interface(btd_get_dbus_connection(), idev->path, INPUT_INTERFACE); input_device_free(idev); }
int reporter_device_probe(struct btd_service *service) { struct btd_device *device = btd_service_get_device(service); struct reporter_adapter *radapter; struct btd_adapter *adapter = device_get_adapter(device); radapter = find_reporter_adapter(adapter); if (!radapter) return -1; register_reporter_device(device, radapter); return 0; }
static void target_cb(struct btd_service *service, btd_service_state_t old_state, btd_service_state_t new_state) { struct btd_device *dev = btd_service_get_device(service); struct policy_data *data; data = find_data(dev); if (data == NULL) return; switch (new_state) { case BTD_SERVICE_STATE_UNAVAILABLE: if (data->tg_timer > 0) { g_source_remove(data->tg_timer); data->tg_timer = 0; } break; case BTD_SERVICE_STATE_DISCONNECTED: if (old_state == BTD_SERVICE_STATE_CONNECTING) { int err = btd_service_get_error(service); if (err == -EAGAIN) { if (data->tg_retries < TG_RETRIES) policy_set_tg_timer(data, TG_RETRY_TIMEOUT); else data->tg_retries = 0; break; } else if (data->tg_timer > 0) { g_source_remove(data->tg_timer); data->tg_timer = 0; } } else if (old_state == BTD_SERVICE_STATE_CONNECTED) { data->tg_retries = 0; } break; case BTD_SERVICE_STATE_CONNECTING: break; case BTD_SERVICE_STATE_CONNECTED: if (data->tg_timer > 0) { g_source_remove(data->tg_timer); data->tg_timer = 0; } break; case BTD_SERVICE_STATE_DISCONNECTING: break; } }