📄 manager.c
字号:
} else { char hs_address[18]; headset_set_authorized(device); ba2str(&device->dst, hs_address); debug("Accepted headset connection from %s for %s", hs_address, device->path); headset_set_state(device, HEADSET_STATE_CONNECTED); }}static void ag_io_cb(GIOChannel *chan, int err, const bdaddr_t *src, const bdaddr_t *dst, gpointer data){ const char *uuid; struct audio_device *device; gboolean hfp_active; if (err < 0) { error("accept: %s (%d)", strerror(-err), -err); return; } if (chan == hsp_ag_server) { hfp_active = FALSE; uuid = HSP_AG_UUID; } else { hfp_active = TRUE; uuid = HFP_AG_UUID; } device = manager_find_device(dst, NULL, FALSE); if (!device) goto drop; if (headset_get_state(device) > HEADSET_STATE_DISCONNECTED) { debug("Refusing new connection since one already exists"); goto drop; } set_hfp_active(device, hfp_active); if (headset_connect_rfcomm(device, chan) < 0) { error("Allocating new GIOChannel failed!"); goto drop; } err = service_req_auth(&device->src, &device->dst, uuid, auth_cb, device); if (err < 0) { debug("Authorization denied: %s", strerror(-err)); headset_close_rfcomm(device); return; } headset_set_state(device, HEADSET_STATE_CONNECT_IN_PROGRESS); return;drop: g_io_channel_close(chan); g_io_channel_unref(chan); return;}static void hs_io_cb(GIOChannel *chan, int err, const bdaddr_t *src, const bdaddr_t *dst, void *data){ /*Stub*/ return;}static int headset_server_init(DBusConnection *conn, GKeyFile *config){ uint8_t chan = DEFAULT_HS_AG_CHANNEL; sdp_record_t *record; gboolean hfp = TRUE, master = TRUE; GError *err = NULL; uint32_t features, flags; if (!enabled.headset) return 0; if (config) { gboolean tmp; tmp = g_key_file_get_boolean(config, "General", "Master", &err); if (err) { debug("audio.conf: %s", err->message); g_error_free(err); err = NULL; } else master = tmp; tmp = g_key_file_get_boolean(config, "Headset", "HFP", &err); if (err) { debug("audio.conf: %s", err->message); g_error_free(err); err = NULL; } else hfp = tmp; } flags = RFCOMM_LM_SECURE; if (master) flags |= RFCOMM_LM_MASTER; hsp_ag_server = bt_rfcomm_listen(BDADDR_ANY, chan, flags, ag_io_cb, NULL); if (!hsp_ag_server) return -1; record = hsp_ag_record(chan); if (!record) { error("Unable to allocate new service record"); return -1; } if (add_record_to_server(BDADDR_ANY, record) < 0) { error("Unable to register HS AG service record"); sdp_record_free(record); g_io_channel_unref(hsp_ag_server); hsp_ag_server = NULL; return -1; } hsp_ag_record_id = record->handle; features = headset_config_init(config); if (!hfp) return 0; chan = DEFAULT_HF_AG_CHANNEL; hfp_ag_server = bt_rfcomm_listen(BDADDR_ANY, chan, flags, ag_io_cb, NULL); if (!hfp_ag_server) return -1; record = hfp_ag_record(chan, features); if (!record) { error("Unable to allocate new service record"); return -1; } if (add_record_to_server(BDADDR_ANY, record) < 0) { error("Unable to register HF AG service record"); sdp_record_free(record); g_io_channel_unref(hfp_ag_server); hfp_ag_server = NULL; return -1; } hfp_ag_record_id = record->handle; return 0;}static int gateway_server_init(DBusConnection *conn, GKeyFile *config){ uint8_t chan = DEFAULT_HSP_HS_CHANNEL; sdp_record_t *record; gboolean master = TRUE; GError *err = NULL; uint32_t flags; if (!enabled.gateway) return 0; if (config) { gboolean tmp; tmp = g_key_file_get_boolean(config, "General", "Master", &err); if (err) { debug("audio.conf: %s", err->message); g_error_free(err); err = NULL; } else master = tmp; } flags = RFCOMM_LM_SECURE; if (master) flags |= RFCOMM_LM_MASTER; hsp_hs_server = bt_rfcomm_listen(BDADDR_ANY, chan, flags, hs_io_cb, NULL); if (!hsp_hs_server) return -1; record = hsp_hs_record(chan); if (!record) { error("Unable to allocate new service record"); return -1; } if (add_record_to_server(BDADDR_ANY, record) < 0) { error("Unable to register HSP HS service record"); sdp_record_free(record); g_io_channel_unref(hsp_hs_server); hsp_hs_server = NULL; return -1; } hsp_hs_record_id = record->handle; return 0;}static void server_exit(void){ if (hsp_ag_record_id) { remove_record_from_server(hsp_ag_record_id); hsp_ag_record_id = 0; } if (hsp_ag_server) { g_io_channel_unref(hsp_ag_server); hsp_ag_server = NULL; } if (hsp_hs_record_id) { remove_record_from_server(hsp_hs_record_id); hsp_hs_record_id = 0; } if (hsp_hs_server) { g_io_channel_unref(hsp_hs_server); hsp_hs_server = NULL; } if (hfp_ag_record_id) { remove_record_from_server(hfp_ag_record_id); hfp_ag_record_id = 0; } if (hfp_ag_server) { g_io_channel_unref(hfp_ag_server); hfp_ag_server = NULL; }}static int audio_probe(struct btd_device_driver *driver, struct btd_device *device, GSList *records){ struct adapter *adapter = device_get_adapter(device); const gchar *path = device_get_path(device); const char *source, *destination; bdaddr_t src, dst; struct audio_device *dev; source = adapter_get_address(adapter); destination = device_get_address(device); str2ba(source, &src); str2ba(destination, &dst); dev = manager_find_device(&dst, NULL, FALSE); if (!dev) { dev = device_register(connection, path, &src, &dst); if (!dev) return -EINVAL; devices = g_slist_append(devices, dev); } g_slist_foreach(records, (GFunc) handle_record, dev); return 0;}static void audio_remove(struct btd_device_driver *driver, struct btd_device *device){ struct audio_device *dev; const char *destination = device_get_address(device); bdaddr_t dst; str2ba(destination, &dst); dev = manager_find_device(&dst, NULL, FALSE); if (!dev) return; devices = g_slist_remove(devices, dev); device_unregister(dev);}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,};int audio_manager_init(DBusConnection *conn, GKeyFile *config){ char **list; int i; connection = dbus_connection_ref(conn); if (!config) goto proceed; list = g_key_file_get_string_list(config, "General", "Enable", NULL, NULL); for (i = 0; list && list[i] != NULL; i++) { if (g_str_equal(list[i], "Headset")) enabled.headset = TRUE; else if (g_str_equal(list[i], "Gateway")) enabled.gateway = TRUE; else if (g_str_equal(list[i], "Sink")) enabled.sink = TRUE; else if (g_str_equal(list[i], "Source")) enabled.source = TRUE; else if (g_str_equal(list[i], "Control")) enabled.control = TRUE; } g_strfreev(list); list = g_key_file_get_string_list(config, "General", "Disable", NULL, NULL); for (i = 0; list && list[i] != NULL; i++) { if (g_str_equal(list[i], "Headset")) enabled.headset = FALSE; else if (g_str_equal(list[i], "Gateway")) enabled.gateway = FALSE; else if (g_str_equal(list[i], "Sink")) enabled.sink = FALSE; else if (g_str_equal(list[i], "Source")) enabled.source = FALSE; else if (g_str_equal(list[i], "Control")) enabled.control = FALSE; } g_strfreev(list);proceed: if (enabled.headset) { if (headset_server_init(conn, config) < 0) goto failed; } if (enabled.gateway) { if (gateway_server_init(conn, config) < 0) goto failed; } if (enabled.source || enabled.sink) { if (a2dp_init(conn, config) < 0) goto failed; } if (enabled.control && avrcp_init(conn, config) < 0) goto failed; btd_register_device_driver(&audio_driver); return 0;failed: audio_manager_exit(); return -1;}void audio_manager_exit(void){ server_exit(); dbus_connection_unref(connection); btd_unregister_device_driver(&audio_driver); connection = NULL;}struct audio_device *manager_get_connected_device(void){ GSList *l; for (l = devices; l != NULL; l = g_slist_next(l)) { struct audio_device *device = l->data; if ((device->sink || device->source) && avdtp_is_connected(&device->src, &device->dst)) return device; if (device->headset && headset_is_active(device)) return device; } return NULL;}struct audio_device *manager_find_device(const bdaddr_t *bda, const char *interface, gboolean connected){ GSList *l; if (!bacmp(bda, BDADDR_ANY) && !interface && !connected) return devices->data; for (l = devices; l != NULL; l = l->next) { struct audio_device *dev = l->data; if (bacmp(bda, BDADDR_ANY) && bacmp(&dev->dst, bda)) continue; if (interface && !strcmp(AUDIO_HEADSET_INTERFACE, interface) && !dev->headset) continue; if (interface && !strcmp(AUDIO_SINK_INTERFACE, interface) && !dev->sink) continue; if (interface && !strcmp(AUDIO_SOURCE_INTERFACE, interface) && !dev->source) continue; if (interface && !strcmp(AUDIO_CONTROL_INTERFACE, interface) && !dev->control) continue; if (connected && !device_is_connected(dev, interface)) continue; return dev; } return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -