gboolean hdp_get_dcpsm(struct hdp_device *device, hdp_continue_dcpsm_f func, gpointer data, GDestroyNotify destroy, GError **err) { struct get_dcpsm_data *dcpsm_data; const bdaddr_t *src; const bdaddr_t *dst; uuid_t uuid; src = adapter_get_address(device_get_adapter(device->dev)); dst = device_get_address(device->dev); dcpsm_data = g_new0(struct get_dcpsm_data, 1); dcpsm_data->func = func; dcpsm_data->data = data; dcpsm_data->destroy = destroy; bt_string2uuid(&uuid, HDP_UUID); if (bt_search_service(src, dst, &uuid, get_dcpsm_cb, dcpsm_data, free_dcpsm_data) < 0) { g_set_error(err, HDP_ERROR, HDP_CONNECTION_ERROR, "Can't get remote SDP record"); g_free(dcpsm_data); return FALSE; } return TRUE; }
static void avctp_control_confirm(struct avctp *session, GIOChannel *chan, struct btd_device *dev) { const bdaddr_t *src; const bdaddr_t *dst; if (session->control != NULL) { error("Control: Refusing unexpected connect"); g_io_channel_shutdown(chan, TRUE, NULL); return; } avctp_set_state(session, AVCTP_STATE_CONNECTING); session->control = avctp_channel_create(session, chan, NULL); src = adapter_get_address(device_get_adapter(dev)); dst = device_get_address(dev); session->auth_id = btd_request_authorization(src, dst, AVRCP_TARGET_UUID, auth_cb, session); if (session->auth_id == 0) goto drop; session->control->watch = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL, session_cb, session); return; drop: avctp_set_state(session, AVCTP_STATE_DISCONNECTED); }
/* Connect and initiate BNEP session */ int connection_connect(struct btd_service *service) { struct network_conn *nc = btd_service_get_user_data(service); struct network_peer *peer = nc->peer; uint16_t id = get_service_id(service); GError *err = NULL; const bdaddr_t *src; const bdaddr_t *dst; DBG("id %u", id); if (nc->state != DISCONNECTED) return -EALREADY; src = adapter_get_address(device_get_adapter(peer->device)); dst = device_get_address(peer->device); nc->io = bt_io_connect(connect_cb, nc, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, src, BT_IO_OPT_DEST_BDADDR, dst, BT_IO_OPT_PSM, BNEP_PSM, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM, BT_IO_OPT_OMTU, BNEP_MTU, BT_IO_OPT_IMTU, BNEP_MTU, BT_IO_OPT_INVALID); if (!nc->io) return -EIO; nc->state = CONNECTING; return 0; }
static int serial_probe(struct btd_device *device, const char *uuid) { struct btd_adapter *adapter = device_get_adapter(device); const gchar *path = device_get_path(device); sdp_list_t *protos; int ch; bdaddr_t src, dst; const sdp_record_t *rec; DBG("path %s: %s", path, uuid); rec = btd_device_get_record(device, uuid); if (!rec) return -EINVAL; if (sdp_get_access_protos(rec, &protos) < 0) 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 < 1 || ch > 30) { error("Channel out of range: %d", ch); return -EINVAL; } adapter_get_address(adapter, &src); device_get_address(device, &dst); return port_register(connection, path, &src, &dst, uuid, ch); }
int avctp_connect_browsing(struct avctp *session) { GError *err = NULL; GIOChannel *io; if (session->state != AVCTP_STATE_CONNECTED) return -ENOTCONN; if (session->browsing != NULL) return 0; avctp_set_state(session, AVCTP_STATE_BROWSING_CONNECTING); io = bt_io_connect(avctp_connect_browsing_cb, session, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, adapter_get_address(session->server->adapter), BT_IO_OPT_DEST_BDADDR, device_get_address(session->device), BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM, BT_IO_OPT_PSM, AVCTP_BROWSING_PSM, BT_IO_OPT_MODE, L2CAP_MODE_ERTM, BT_IO_OPT_INVALID); if (err) { error("%s", err->message); g_error_free(err); return -EIO; } session->browsing = avctp_channel_create(session, io, avctp_destroy_browsing); g_io_channel_unref(io); return 0; }
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; sdp_data_t *pdlist; DBG("path %s", path); if (!rec) return -1; adapter_get_address(adapter, &src); device_get_address(device, &dst); if (rec) pdlist = sdp_data_get(rec, SDP_ATTR_HID_SDP_DISABLE); if (pdlist && pdlist->val.uint8) { DBG("cancel discovery is issued"); bt_cancel_discovery(&src, &dst); } return input_device_register(connection, device, path, &src, &dst, HID_UUID, rec->handle, idle_timeout * 60); }
static void pincode_reply(DBusPendingCall *call, void *user_data) { struct agent_request *req = user_data; struct agent *agent = req->agent; struct btd_adapter *adapter = agent->adapter; agent_pincode_cb cb = req->cb; DBusMessage *message; DBusError err; bdaddr_t sba; size_t len; char *pin; adapter_get_address(adapter, &sba); /* steal_reply will always return non-NULL since the callback * is only called after a reply has been received */ message = dbus_pending_call_steal_reply(call); dbus_error_init(&err); if (dbus_set_error_from_message(&err, message)) { error("Agent %s replied with an error: %s, %s", agent->path, err.name, err.message); cb(agent, &err, NULL, req->user_data); dbus_error_free(&err); goto done; } dbus_error_init(&err); if (!dbus_message_get_args(message, &err, DBUS_TYPE_STRING, &pin, DBUS_TYPE_INVALID)) { error("Wrong passkey reply signature: %s", err.message); cb(agent, &err, NULL, req->user_data); dbus_error_free(&err); goto done; } len = strlen(pin); dbus_error_init(&err); if (len > 16 || len < 1) { error("Invalid PIN length (%zu) from agent", len); dbus_set_error_const(&err, "org.bluez.Error.InvalidArgs", "Invalid passkey length"); cb(agent, &err, NULL, req->user_data); dbus_error_free(&err); goto done; } cb(agent, NULL, pin, req->user_data); done: if (message) dbus_message_unref(message); dbus_pending_call_cancel(req->call); agent->request = NULL; agent_request_free(req, TRUE); }
gboolean hdp_establish_mcl(struct hdp_device *device, hdp_continue_proc_f func, gpointer data, GDestroyNotify destroy, GError **err) { struct conn_mcl_data *conn_data; const bdaddr_t *src; const bdaddr_t *dst; uuid_t uuid; src = adapter_get_address(device_get_adapter(device->dev)); dst = device_get_address(device->dev); conn_data = g_new0(struct conn_mcl_data, 1); conn_data->refs = 1; conn_data->func = func; conn_data->data = data; conn_data->destroy = destroy; conn_data->dev = health_device_ref(device); bt_string2uuid(&uuid, HDP_UUID); if (bt_search_service(src, dst, &uuid, search_cb, conn_data, destroy_con_mcl_data) < 0) { g_set_error(err, HDP_ERROR, HDP_CONNECTION_ERROR, "Can't get remote SDP record"); g_free(conn_data); return FALSE; } return TRUE; }
static struct network_adapter *create_adapter(struct btd_adapter *adapter) { struct network_adapter *na; GError *err = NULL; bdaddr_t src; na = g_new0(struct network_adapter, 1); na->adapter = btd_adapter_ref(adapter); adapter_get_address(adapter, &src); na->io = bt_io_listen(BT_IO_L2CAP, NULL, confirm_event, na, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, &src, BT_IO_OPT_PSM, BNEP_PSM, BT_IO_OPT_OMTU, BNEP_MTU, BT_IO_OPT_IMTU, BNEP_MTU, BT_IO_OPT_SEC_LEVEL, security ? BT_IO_SEC_MEDIUM : BT_IO_SEC_LOW, BT_IO_OPT_INVALID); if (!na->io) { error("%s", err->message); g_error_free(err); adapter_free(na); return NULL; } return na; }
int avctp_register(struct btd_adapter *adapter, gboolean master) { struct avctp_server *server; const bdaddr_t *src = adapter_get_address(adapter); server = g_new0(struct avctp_server, 1); server->control_io = avctp_server_socket(src, master, L2CAP_MODE_BASIC, AVCTP_CONTROL_PSM); if (!server->control_io) { g_free(server); return -1; } server->browsing_io = avctp_server_socket(src, master, L2CAP_MODE_ERTM, AVCTP_BROWSING_PSM); if (!server->browsing_io) { if (server->control_io) { g_io_channel_shutdown(server->control_io, TRUE, NULL); g_io_channel_unref(server->control_io); server->control_io = NULL; } g_free(server); return -1; } server->adapter = btd_adapter_ref(adapter); servers = g_slist_append(servers, server); return 0; }
static void pincode_cb(struct agent *agent, DBusError *derr, const char *pincode, struct btd_device *device) { struct btd_adapter *adapter = device_get_adapter(device); bdaddr_t sba, dba; int err; device_get_address(device, &dba); if (derr) { err = btd_adapter_pincode_reply(adapter, &dba, NULL); if (err < 0) goto fail; return; } err = btd_adapter_pincode_reply(adapter, &dba, pincode); if (err < 0) goto fail; adapter_get_address(adapter, &sba); return; fail: error("Sending PIN code reply failed: %s (%d)", strerror(-err), -err); }
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, 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; }
gboolean mcap_get_mdep(struct mcap_device *device, struct mcap_application *app, mcap_continue_mdep_f func, gpointer data, GDestroyNotify destroy, GError **err) { DBG(""); struct get_mdep_data *mdep_data; bdaddr_t dst, src; uuid_t uuid; device_get_address(device->dev, &dst,NULL); adapter_get_address(device_get_adapter(device->dev), &src); mdep_data = g_new0(struct get_mdep_data, 1); mdep_data->app = mcap_application_ref(app); mdep_data->func = func; mdep_data->data = data; mdep_data->destroy = destroy; char dd[100] = {}; ba2str(&dst,dd); DBG("dst device = %s",dd); sdp_uuid32_create(&uuid, 0x1400); // bt_string2uuid(&uuid, 0x1400); if (bt_search_service(&src, &dst, &uuid, get_mdep_cb, mdep_data, free_mdep_data)) { g_set_error(err, MCAP_ERROR, MCAP_CONNECTION_ERROR, "Can't get remote SDP record"); g_free(mdep_data); return FALSE; } return TRUE; }
static DBusMessage *update_record(DBusConnection *conn, DBusMessage *msg, struct service_adapter *serv_adapter, dbus_uint32_t handle, sdp_record_t *sdp_record) { bdaddr_t src; int err; if (remove_record_from_server(handle) < 0) { sdp_record_free(sdp_record); return btd_error_not_available(msg); } if (serv_adapter->adapter) adapter_get_address(serv_adapter->adapter, &src); else bacpy(&src, BDADDR_ANY); sdp_record->handle = handle; err = add_record_to_server(&src, sdp_record); if (err < 0) { sdp_record_free(sdp_record); error("Failed to update the service record"); return btd_error_failed(msg, strerror(-err)); } return dbus_message_new_method_return(msg); }
gboolean mcap_establish_mcl(struct mcap_device *device, mcap_continue_proc_f func, gpointer data, GDestroyNotify destroy, GError **err) { DBG(""); DBG(""); struct conn_mcl_data *conn_data; bdaddr_t dst, src; uuid_t uuid; device_get_address(device->dev, &dst,NULL); adapter_get_address(device_get_adapter(device->dev), &src); conn_data = g_new0(struct conn_mcl_data, 1); conn_data->refs = 1; conn_data->func = func; conn_data->data = data; conn_data->destroy = destroy; conn_data->dev = mcap_device_ref(device); sdp_uuid32_create(&uuid, 0x001e); //bt_string2uuid(&uuid, 0x001e); if (bt_search_service(&src, &dst, &uuid, search_cb, conn_data, destroy_con_mcl_data)) { g_set_error(err, MCAP_ERROR, MCAP_CONNECTION_ERROR, "Can't get remote SDP record"); g_free(conn_data); return FALSE; } return TRUE; }
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); #ifndef BT_ALT_STACK if (!rec) return -1; #endif adapter_get_address(adapter, &src); device_get_address(device, &dst); #ifdef BT_ALT_STACK return input_device_register(connection, device, path, &src, &dst, HID_UUID, 0 /* rec->handle */, idle_timeout * 60); #else return input_device_register(connection, device, path, &src, &dst, HID_UUID, rec->handle, idle_timeout * 60); #endif }
gboolean hdp_get_mdep(struct hdp_device *device, struct hdp_application *app, hdp_continue_mdep_f func, gpointer data, GDestroyNotify destroy, GError **err) { struct get_mdep_data *mdep_data; bdaddr_t dst, src; uuid_t uuid; device_get_address(device->dev, &dst, NULL); adapter_get_address(device_get_adapter(device->dev), &src); mdep_data = g_new0(struct get_mdep_data, 1); mdep_data->app = hdp_application_ref(app); mdep_data->func = func; mdep_data->data = data; mdep_data->destroy = destroy; bt_string2uuid(&uuid, HDP_UUID); if (bt_search_service(&src, &dst, &uuid, get_mdep_cb, mdep_data, free_mdep_data)) { g_set_error(err, HDP_ERROR, HDP_CONNECTION_ERROR, "Can't get remote SDP record"); g_free(mdep_data); return FALSE; } return TRUE; }
static DBusMessage *set_link_loss_alert(DBusConnection *conn, DBusMessage *msg, const char *level, void *data) { struct monitor *monitor = data; struct btd_device *device = monitor->device; bdaddr_t sba, dba; if (!level_is_valid(level)) return btd_error_invalid_args(msg); if (g_strcmp0(monitor->linklosslevel, level) == 0) return dbus_message_new_method_return(msg); g_free(monitor->linklosslevel); monitor->linklosslevel = g_strdup(level); adapter_get_address(device_get_adapter(device), &sba); device_get_address(device, &dba); write_proximity_config(&sba, &dba, "LinkLossAlertLevel", level); if (monitor->attrib) write_alert_level(monitor); return dbus_message_new_method_return(msg); }
struct avctp *avctp_connect(struct audio_device *device) { struct avctp *session; GError *err = NULL; GIOChannel *io; session = avctp_get_internal(device->btd_dev); if (!session) return NULL; if (session->state > AVCTP_STATE_DISCONNECTED) return session; avctp_set_state(session, AVCTP_STATE_CONNECTING); io = bt_io_connect(avctp_connect_cb, session, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, adapter_get_address(session->server->adapter), BT_IO_OPT_DEST_BDADDR, device_get_address(session->device), BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM, BT_IO_OPT_PSM, AVCTP_CONTROL_PSM, BT_IO_OPT_INVALID); if (err) { avctp_set_state(session, AVCTP_STATE_DISCONNECTED); error("%s", err->message); g_error_free(err); return NULL; } session->control = avctp_channel_create(session, io, NULL); g_io_channel_unref(io); return session; }
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; bdaddr_t src; sender = dbus_message_get_sender(msg); auth = find_pending_by_sender(serv_adapter, sender); if (auth == NULL) return btd_error_does_not_exist(msg); if (serv_adapter->adapter) adapter_get_address(serv_adapter->adapter, &src); else bacpy(&src, BDADDR_ANY); btd_cancel_authorization(&src, &auth->dst); reply = btd_error_not_authorized(auth->msg); dbus_message_unref(auth->msg); g_dbus_send_message(auth->conn, reply); dbus_connection_unref(auth->conn); 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; if (serv_adapter->adapter) adapter_get_address(serv_adapter->adapter, &src); else bacpy(&src, BDADDR_ANY); btd_request_authorization(&src, &auth->dst, auth->uuid, auth_cb, serv_adapter); done: return dbus_message_new_method_return(msg); }
static int sap_server_probe(struct btd_profile *p, struct btd_adapter *adapter) { const char *path = adapter_get_path(adapter); DBG("path %s", path); return sap_server_register(path, adapter_get_address(adapter)); }
static void hid_server_remove(struct btd_profile *p, struct btd_adapter *adapter) { server_stop(adapter_get_address(adapter)); adapters = g_slist_remove(adapters, adapter); btd_adapter_unref(adapter); }
static void create_filename(char *filename, struct btd_adapter *adapter) { char srcaddr[18]; ba2str(adapter_get_address(adapter), srcaddr); create_name(filename, PATH_MAX, STORAGEDIR, srcaddr, "ccc"); }
gboolean hdp_update_sdp_record(struct hdp_adapter *adapter, GSList *app_list) { sdp_record_t *sdp_record; bdaddr_t addr; if (adapter->sdp_handler) remove_record_from_server(adapter->sdp_handler); if (!app_list) { adapter->sdp_handler = 0; return TRUE; } sdp_record = sdp_record_alloc(); if (!sdp_record) return FALSE; if (adapter->sdp_handler) sdp_record->handle = adapter->sdp_handler; else sdp_record->handle = 0xffffffff; /* Set automatically */ if (is_app_role(app_list, HDP_SINK)) set_sdp_services_uuid(sdp_record, HDP_SINK); if (is_app_role(app_list, HDP_SOURCE)) set_sdp_services_uuid(sdp_record, HDP_SOURCE); if (!register_service_protocols(adapter, sdp_record)) goto fail; if (!register_service_profiles(sdp_record)) goto fail; if (!register_service_additional_protocols(adapter, sdp_record)) goto fail; sdp_set_info_attr(sdp_record, HDP_SERVICE_NAME, HDP_SERVICE_PROVIDER, HDP_SERVICE_DSC); if (!register_service_sup_features(app_list, sdp_record)) goto fail; if (!register_data_exchange_spec(sdp_record)) goto fail; register_mcap_features(sdp_record); if (sdp_set_record_state(sdp_record, adapter->record_state++)) goto fail; adapter_get_address(adapter->btd_adapter, &addr); if (add_record_to_server(&addr, sdp_record) < 0) goto fail; adapter->sdp_handler = sdp_record->handle; return TRUE; fail: if (sdp_record) sdp_record_free(sdp_record); return FALSE; }
static int ext_start_servers(struct ext_profile *ext, struct btd_adapter *adapter) { struct ext_io *server; BtIOConfirm confirm; BtIOConnect connect; GError *err = NULL; uint16_t handle; GIOChannel *io; handle = ext_register_record(ext, adapter_get_address(adapter)); if (ext->authorize) { confirm = ext_confirm; connect = NULL; } else { confirm = NULL; connect = ext_direct_connect; } if (ext->psm) { server = g_new0(struct ext_io, 1); server->ext = ext; server->rec_handle = handle; io = bt_io_listen(connect, confirm, server, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, adapter_get_address(adapter), BT_IO_OPT_PSM, ext->psm, BT_IO_OPT_SEC_LEVEL, ext->sec_level, BT_IO_OPT_INVALID); if (err != NULL) { error("L2CAP server failed for %s: %s", ext->name, err->message); g_free(server); g_clear_error(&err); } else { server->io = io; server->proto = BTPROTO_L2CAP; server->adapter = btd_adapter_ref(adapter); ext->servers = g_slist_append(ext->servers, server); DBG("%s listening on PSM %u", ext->name, ext->psm); } }
static void gatt_get_address(struct gatt_service *gatt, bdaddr_t *sba, bdaddr_t *dba) { struct btd_device *device = gatt->dev; struct btd_adapter *adapter; adapter = device_get_adapter(device); adapter_get_address(adapter, sba); device_get_address(device, dba, NULL); }
static gint adapter_cmp(gconstpointer a, gconstpointer b) { struct btd_adapter *adapter = (struct btd_adapter *) a; const bdaddr_t *bdaddr = b; bdaddr_t src; adapter_get_address(adapter, &src); return bacmp(&src, bdaddr); }
static int pnat_probe(struct btd_adapter *adapter) { struct dun_server *server; GIOChannel *io; GError *err = NULL; sdp_record_t *record; bdaddr_t src; adapter_get_address(adapter, &src); server = g_new0(struct dun_server, 1); io = bt_io_listen(BT_IO_RFCOMM, NULL, confirm_cb, server, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, &src, BT_IO_OPT_CHANNEL, DUN_CHANNEL, BT_IO_OPT_INVALID); if (err != NULL) { error("Failed to start DUN server: %s", err->message); g_error_free(err); goto fail; } record = dun_record(DUN_CHANNEL); if (!record) { error("Unable to allocate new service record"); goto fail; } if (add_record_to_server(&src, record) < 0) { error("Unable to register DUN service record"); goto fail; } server->rfcomm_ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM); if (server->rfcomm_ctl < 0) { error("Unable to create RFCOMM control socket: %s (%d)", strerror(errno), errno); goto fail; } server->server = io; server->record_handle = record->handle; bacpy(&server->bda, &src); servers = g_slist_append(servers, server); return 0; fail: if (io != NULL) g_io_channel_unref(io); g_free(server); return -EIO; }
static void register_stored(struct serial_adapter *adapter) { char filename[PATH_MAX + 1]; char address[18]; bdaddr_t src; adapter_get_address(adapter->btd_adapter, &src); ba2str(&src, address); snprintf(filename, PATH_MAX, "%s/%s/proxy", STORAGEDIR, address); textfile_foreach(filename, parse_proxy, adapter); }
static void hid_server_remove(struct btd_adapter *adapter) { bdaddr_t src; adapter_get_address(adapter, &src); server_stop(&src); adapters = g_slist_remove(adapters, adapter); btd_adapter_unref(adapter); }