static void rfcomm_connect(const char *src, const char *dst, uint8_t ch, int disconn, int sec) { struct io_data *data; GError *err = NULL; printf("Connecting to %s RFCOMM channel %u\n", dst, ch); data = io_data_new(NULL, -1, disconn, -1); if (src) data->io = bt_io_connect(connect_cb, data, (GDestroyNotify) io_data_unref, &err, BT_IO_OPT_SOURCE, src, BT_IO_OPT_DEST, dst, BT_IO_OPT_CHANNEL, ch, BT_IO_OPT_SEC_LEVEL, sec, BT_IO_OPT_INVALID); else data->io = bt_io_connect(connect_cb, data, (GDestroyNotify) io_data_unref, &err, BT_IO_OPT_DEST, dst, BT_IO_OPT_CHANNEL, ch, BT_IO_OPT_SEC_LEVEL, sec, BT_IO_OPT_INVALID); if (!data->io) { printf("Connecting to %s failed: %s\n", dst, err->message); g_error_free(err); exit(EXIT_FAILURE); } }
static GIOChannel *l2cap_connect(GObexTransportType transport, GError **err) { if (option_source) return bt_io_connect(conn_callback, GUINT_TO_POINTER(transport), NULL, err, BT_IO_OPT_SOURCE, option_source, BT_IO_OPT_DEST, option_dest, BT_IO_OPT_PSM, option_channel, BT_IO_OPT_MODE, BT_IO_MODE_ERTM, BT_IO_OPT_OMTU, option_omtu, BT_IO_OPT_IMTU, option_imtu, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, BT_IO_OPT_INVALID); return bt_io_connect(conn_callback, GUINT_TO_POINTER(transport), NULL, err, BT_IO_OPT_DEST, option_dest, BT_IO_OPT_PSM, option_channel, BT_IO_OPT_MODE, BT_IO_MODE_ERTM, BT_IO_OPT_OMTU, option_omtu, BT_IO_OPT_IMTU, option_imtu, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, BT_IO_OPT_INVALID); }
static void sco_connect(const char *src, const char *dst, int disconn, int voice) { struct io_data *data; GError *err = NULL; printf("Connecting SCO to %s\n", dst); data = io_data_new(NULL, -1, disconn, -1); if (src) data->io = bt_io_connect(connect_cb, data, (GDestroyNotify) io_data_unref, &err, BT_IO_OPT_SOURCE, src, BT_IO_OPT_DEST, dst, BT_IO_OPT_VOICE, voice, BT_IO_OPT_INVALID); else data->io = bt_io_connect(connect_cb, data, (GDestroyNotify) io_data_unref, &err, BT_IO_OPT_DEST, dst, BT_IO_OPT_VOICE, voice, BT_IO_OPT_INVALID); if (!data->io) { printf("Connecting to %s failed: %s\n", dst, err->message); g_error_free(err); exit(EXIT_FAILURE); } }
GIOChannel *gatt_connect(const char *src, const char *dst, const char *dst_type, const char *sec_level, int psm, int mtu, BtIOConnect connect_cb, GError **gerr) { GIOChannel *chan; bdaddr_t sba, dba; uint8_t dest_type; GError *tmp_err = NULL; BtIOSecLevel sec; str2ba(dst, &dba); /* Local adapter */ if (src != NULL) { if (!strncmp(src, "hci", 3)) hci_devba(atoi(src + 3), &sba); else str2ba(src, &sba); } else bacpy(&sba, BDADDR_ANY); /* Not used for BR/EDR */ if (strcmp(dst_type, "random") == 0) dest_type = BDADDR_LE_RANDOM; else dest_type = BDADDR_LE_PUBLIC; if (strcmp(sec_level, "medium") == 0) sec = BT_IO_SEC_MEDIUM; else if (strcmp(sec_level, "high") == 0) sec = BT_IO_SEC_HIGH; else sec = BT_IO_SEC_LOW; if (psm == 0) chan = bt_io_connect(connect_cb, NULL, NULL, &tmp_err, BT_IO_OPT_SOURCE_BDADDR, &sba, BT_IO_OPT_SOURCE_TYPE, BDADDR_LE_PUBLIC, BT_IO_OPT_DEST_BDADDR, &dba, BT_IO_OPT_DEST_TYPE, dest_type, BT_IO_OPT_CID, ATT_CID, BT_IO_OPT_SEC_LEVEL, sec, BT_IO_OPT_INVALID); else chan = bt_io_connect(connect_cb, NULL, NULL, &tmp_err, BT_IO_OPT_SOURCE_BDADDR, &sba, BT_IO_OPT_DEST_BDADDR, &dba, BT_IO_OPT_PSM, psm, BT_IO_OPT_IMTU, mtu, BT_IO_OPT_SEC_LEVEL, sec, BT_IO_OPT_INVALID); if (tmp_err) { g_propagate_error(gerr, tmp_err); return NULL; } return chan; }
static void l2cap_connect(const char *src, const char *dst, uint8_t addr_type, uint16_t psm, uint16_t cid, int disconn, int sec, int prio) { struct io_data *data; GError *err = NULL; uint8_t src_type; printf("Connecting to %s L2CAP PSM %u\n", dst, psm); data = io_data_new(NULL, -1, disconn, -1); if (addr_type != BDADDR_BREDR) src_type = BDADDR_LE_PUBLIC; else src_type = BDADDR_BREDR; if (src) data->io = bt_io_connect(connect_cb, data, (GDestroyNotify) io_data_unref, &err, BT_IO_OPT_SOURCE, src, BT_IO_OPT_SOURCE_TYPE, src_type, BT_IO_OPT_DEST, dst, BT_IO_OPT_DEST_TYPE, addr_type, BT_IO_OPT_PSM, psm, BT_IO_OPT_CID, cid, BT_IO_OPT_SEC_LEVEL, sec, BT_IO_OPT_PRIORITY, prio, BT_IO_OPT_INVALID); else data->io = bt_io_connect(connect_cb, data, (GDestroyNotify) io_data_unref, &err, BT_IO_OPT_SOURCE_TYPE, src_type, BT_IO_OPT_DEST, dst, BT_IO_OPT_DEST_TYPE, addr_type, BT_IO_OPT_PSM, psm, BT_IO_OPT_CID, cid, BT_IO_OPT_SEC_LEVEL, sec, BT_IO_OPT_PRIORITY, prio, BT_IO_OPT_INVALID); if (!data->io) { printf("Connecting to %s failed: %s\n", dst, err->message); g_error_free(err); exit(EXIT_FAILURE); } }
static void dev_connect(struct input_device *idev, struct input_conn *iconn, GError **err) { struct fake_input *fake; DBG(""); fake = iconn->fake; if (fake) { /* Fake input device */ if (fake->connect(iconn, err)) fake->flags |= FI_FLAG_CONNECTED; } else { /* HID devices */ GIOChannel *io; if (idev->disable_sdp) bt_clear_cached_session(&idev->src, &idev->dst); io = bt_io_connect(BT_IO_L2CAP, control_connect_cb, iconn, NULL, err, BT_IO_OPT_SOURCE_BDADDR, &idev->src, BT_IO_OPT_DEST_BDADDR, &idev->dst, BT_IO_OPT_PSM, L2CAP_PSM_HIDP_CTRL, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, BT_IO_OPT_INVALID); iconn->ctrl_io = io; } }
/* 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 = btd_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 dev_connect(struct input_device *idev) { GError *err = NULL; GIOChannel *io; if (idev->disable_sdp) bt_clear_cached_session(&idev->src, &idev->dst); io = bt_io_connect(control_connect_cb, idev, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, &idev->src, BT_IO_OPT_DEST_BDADDR, &idev->dst, BT_IO_OPT_PSM, L2CAP_PSM_HIDP_CTRL, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, BT_IO_OPT_INVALID); idev->ctrl_io = io; if (err == NULL) return 0; error("%s", err->message); g_error_free(err); return -EIO; }
/* These are functions to be called from unix.c for audio system * ifaces (alsa, gstreamer, etc.) */ unsigned int gateway_request_stream(struct audio_device *dev, gateway_stream_cb_t cb, void *user_data) { struct gateway *gw = dev->gateway; GError *err = NULL; GIOChannel *io; if (!gw->rfcomm) { if (get_records(dev) < 0) return 0; } else if (!gw->sco) { io = bt_io_connect(sco_connect_cb, dev, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, &dev->src, BT_IO_OPT_DEST_BDADDR, &dev->dst, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM, BT_IO_OPT_INVALID); if (!io) { error("%s", err->message); g_error_free(err); return 0; } } else g_idle_add(request_stream_cb, dev); return connect_cb_new(gw, cb, user_data); }
struct avctp *avctp_connect(const bdaddr_t *src, const bdaddr_t *dst) { struct avctp *session; GError *err = NULL; GIOChannel *io; session = avctp_get_internal(src, dst); if (!session) return NULL; if (session->state > AVCTP_STATE_DISCONNECTED) return session; avctp_set_state(session, AVCTP_STATE_CONNECTING); io = bt_io_connect(BT_IO_L2CAP, avctp_connect_cb, session, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, &session->server->src, BT_IO_OPT_DEST_BDADDR, &session->dst, BT_IO_OPT_PSM, AVCTP_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->io = io; return session; }
static void get_record_cb(sdp_list_t *recs, int err, gpointer user_data) { struct serial_port *port = user_data; struct serial_device *device = port->device; sdp_record_t *record = NULL; sdp_list_t *protos; DBusMessage *reply; GError *gerr = NULL; if (!port->listener_id) { reply = NULL; goto failed; } if (err < 0) { error("Unable to get service record: %s (%d)", strerror(-err), -err); reply = failed(port->msg, strerror(-err)); goto failed; } if (!recs || !recs->data) { error("No record found"); reply = failed(port->msg, "No record found"); goto failed; } record = recs->data; if (sdp_get_access_protos(record, &protos) < 0) { error("Unable to get access protos from port record"); reply = failed(port->msg, "Invalid channel"); goto failed; } port->channel = sdp_get_proto_port(protos, RFCOMM_UUID); sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL); sdp_list_free(protos, NULL); port->io = bt_io_connect(BT_IO_RFCOMM, rfcomm_connect_cb, port, NULL, &gerr, BT_IO_OPT_SOURCE_BDADDR, &device->src, BT_IO_OPT_DEST_BDADDR, &device->dst, BT_IO_OPT_CHANNEL, port->channel, BT_IO_OPT_INVALID); if (!port->io) { error("%s", gerr->message); reply = failed(port->msg, gerr->message); g_error_free(gerr); goto failed; } return; failed: g_dbus_remove_watch(device->conn, port->listener_id); port->listener_id = 0; g_dbus_send_message(device->conn, reply); }
static int connect_port(struct serial_port *port) { struct serial_device *device = port->device; uuid_t uuid; int err; if (!port->uuid) goto connect; err = bt_string2uuid(&uuid, port->uuid); if (err < 0) return err; sdp_uuid128_to_uuid(&uuid); return bt_search_service(&device->src, &device->dst, &uuid, get_record_cb, port, NULL); connect: port->io = bt_io_connect(BT_IO_RFCOMM, rfcomm_connect_cb, port, NULL, NULL, BT_IO_OPT_SOURCE_BDADDR, &device->src, BT_IO_OPT_DEST_BDADDR, &device->dst, BT_IO_OPT_CHANNEL, port->channel, BT_IO_OPT_INVALID); if (port->io) return 0; return -errno; }
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; }
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; }
gboolean avrcp_connect(struct audio_device *dev) { struct control *control = dev->control; GError *err = NULL; GIOChannel *io; if (control->state > AVCTP_STATE_DISCONNECTED) return TRUE; avctp_set_state(control, AVCTP_STATE_CONNECTING); io = bt_io_connect(BT_IO_L2CAP, avctp_connect_cb, control, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, &dev->src, BT_IO_OPT_DEST_BDADDR, &dev->dst, BT_IO_OPT_PSM, AVCTP_PSM, BT_IO_OPT_INVALID); if (err) { avctp_set_state(control, AVCTP_STATE_DISCONNECTED); error("%s", err->message); g_error_free(err); return FALSE; } control->io = io; return TRUE; }
/* These are functions to be called from unix.c for audio system * ifaces (alsa, gstreamer, etc.) */ gboolean gateway_request_stream(struct audio_device *dev, gateway_stream_cb_t cb, void *user_data) { struct gateway *gw = dev->gateway; GError *err = NULL; GIOChannel *io; if (!gw->rfcomm) { gw->sco_start_cb = cb; gw->sco_start_cb_data = user_data; get_records(dev); } else if (!gw->sco) { gw->sco_start_cb = cb; gw->sco_start_cb_data = user_data; io = bt_io_connect(BT_IO_SCO, sco_connect_cb, dev, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, &dev->src, BT_IO_OPT_DEST_BDADDR, &dev->dst, BT_IO_OPT_INVALID); if (!io) { error("%s", err->message); g_error_free(err); return FALSE; } } else if (cb) cb(dev, err, user_data); return TRUE; }
static GIOChannel *do_connect(GError **err) { if (fragment) return bt_io_connect(connect_cb, NULL, NULL, err, BT_IO_OPT_SOURCE_BDADDR, &src, BT_IO_OPT_DEST_BDADDR, &dst, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, BT_IO_OPT_PSM, AVDTP_PSM, BT_IO_OPT_MTU, 48, BT_IO_OPT_INVALID); return bt_io_connect(connect_cb, NULL, NULL, err, BT_IO_OPT_SOURCE_BDADDR, &src, BT_IO_OPT_DEST_BDADDR, &dst, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, BT_IO_OPT_PSM, AVDTP_PSM, BT_IO_OPT_INVALID); }
// 0 1 2 3 4 5 // gatt_write hci0 destaddr handle filename mtu int main(int argc, char *argv[]) { if (argc != 5 && argc != 6) { std::cout << "Usage: " << argv[0] << " adapter destaddr handle filename [mtu]" << std::endl; std::cout << "e.g.): " << argv[0] << " hci0 01:23:45:67:89:AB 0x000b test.txt 100" << std::endl; exit(EXIT_FAILURE); } GError *gerr = NULL; char const* src = argv[1]; bdaddr_t sba; if (!strncmp(src, "hci", 3)) hci_devba(atoi(src + 3), &sba); else str2ba(src, &sba); char const* dst = argv[2]; bdaddr_t dba; str2ba(dst, &dba); int handle = std::strtol(argv[3], nullptr, 0); char const* fn = argv[4]; std::ifstream ifs(fn, std::ifstream::in | std::ifstream::binary); std::vector<std::uint8_t> content = std::vector<std::uint8_t>( std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>()); uint8_t dest_type = BDADDR_LE_PUBLIC; // OR BDADDR_RANDOM BtIOSecLevel sec = BT_IO_SEC_LOW; // OR BT_IO_SEC_HIGH, BT_IO_SEC_LOW user_data_t ud { handle , content, ATT_DEFAULT_LE_MTU }; if (argc == 6) { ud.mtu = std::strtol(argv[5], nullptr, 0); } GIOChannel* chan = bt_io_connect( connect_cb, &ud, NULL, &gerr, BT_IO_OPT_SOURCE_BDADDR, &sba, BT_IO_OPT_SOURCE_TYPE, BDADDR_LE_PUBLIC, BT_IO_OPT_DEST_BDADDR, &dba, BT_IO_OPT_DEST_TYPE, dest_type, BT_IO_OPT_CID, ATT_CID, BT_IO_OPT_SEC_LEVEL, sec, BT_IO_OPT_INVALID); if (chan == NULL) { std::cout << gerr->message << std::endl; exit(EXIT_FAILURE); } event_loop = g_main_loop_new(NULL, FALSE); g_main_loop_run(event_loop); g_main_loop_unref(event_loop); exit(EXIT_SUCCESS); }
static GIOChannel *rfcomm_connect(GObexTransportType transport, GError **err) { if (option_source) return bt_io_connect(conn_callback, GUINT_TO_POINTER(transport), NULL, err, BT_IO_OPT_SOURCE, option_source, BT_IO_OPT_DEST, option_dest, BT_IO_OPT_CHANNEL, option_channel, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, BT_IO_OPT_INVALID); return bt_io_connect(conn_callback, GUINT_TO_POINTER(transport), NULL, err, BT_IO_OPT_DEST, option_dest, BT_IO_OPT_CHANNEL, option_channel, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, BT_IO_OPT_INVALID); }
// 0 1 2 3 4 5 // gatt_write hci0 destaddr handle value mtu int main(int argc, char *argv[]) { if (argc != 5 && argc != 6) { std::cout << "Usage: " << argv[0] << " adapter destaddr handle value [mtu]" << std::endl; std::cout << "e.g.): " << argv[0] << " hci0 01:23:45:67:89:AB 0x000c 0x0300 100" << std::endl; std::cout << "value: " << argv[0] << " 0x0100: start notify, 0x0200 start indicate, 0x0300 both" << std::endl; exit(EXIT_FAILURE); } GError *gerr = NULL; char const* src = argv[1]; bdaddr_t sba; if (!strncmp(src, "hci", 3)) hci_devba(atoi(src + 3), &sba); else str2ba(src, &sba); char const* dst = argv[2]; bdaddr_t dba; str2ba(dst, &dba); int handle = std::strtol(argv[3], nullptr, 0); uint16_t value = std::strtol(argv[4], nullptr, 0); uint8_t dest_type = BDADDR_LE_PUBLIC; // OR BDADDR_RANDOM BtIOSecLevel sec = BT_IO_SEC_LOW; // OR BT_IO_SEC_HIGH, BT_IO_SEC_LOW user_data_t ud { handle, value, ATT_DEFAULT_LE_MTU }; if (argc == 6) { ud.mtu = std::strtol(argv[5], nullptr, 0); } ud.chan = bt_io_connect( connect_cb, &ud, NULL, &gerr, BT_IO_OPT_SOURCE_BDADDR, &sba, BT_IO_OPT_SOURCE_TYPE, BDADDR_LE_PUBLIC, BT_IO_OPT_DEST_BDADDR, &dba, BT_IO_OPT_DEST_TYPE, dest_type, BT_IO_OPT_CID, ATT_CID, BT_IO_OPT_SEC_LEVEL, sec, BT_IO_OPT_INVALID); if (ud.chan == NULL) { std::cout << gerr->message << std::endl; exit(EXIT_FAILURE); } event_loop = g_main_loop_new(NULL, FALSE); g_main_loop_run(event_loop); g_main_loop_unref(event_loop); exit(EXIT_SUCCESS); }
static DBusMessage *input_device_connect(DBusConnection *conn, DBusMessage *msg, void *data) { struct input_device *idev = data; struct input_conn *iconn; struct fake_input *fake; DBusMessage *reply; GError *err = NULL; iconn = find_connection(idev->connections, "HID"); if (!iconn) return not_supported(msg); if (iconn->pending_connect) return in_progress(msg); if (is_connected(iconn)) return already_connected(msg); iconn->pending_connect = dbus_message_ref(msg); fake = iconn->fake; if (fake) { /* Fake input device */ if (fake->connect(iconn, &err)) fake->flags |= FI_FLAG_CONNECTED; } else { /* HID devices */ GIOChannel *io; io = bt_io_connect(BT_IO_L2CAP, control_connect_cb, iconn, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, &idev->src, BT_IO_OPT_DEST_BDADDR, &idev->dst, BT_IO_OPT_PSM, L2CAP_PSM_HIDP_CTRL, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, BT_IO_OPT_INVALID); iconn->ctrl_io = io; } if (err == NULL) return NULL; error("%s", err->message); dbus_message_unref(iconn->pending_connect); iconn->pending_connect = NULL; reply = connection_attempt_failed(msg, err->message); g_error_free(err); return reply; }
static void control_connect_cb(GIOChannel *chan, GError *conn_err, gpointer user_data) { struct input_conn *iconn = user_data; struct input_device *idev = iconn->idev; DBusMessage *reply = NULL; GIOChannel *io; GError *err = NULL; DBG(""); if (conn_err) { error("%s", conn_err->message); if (iconn->pending_connect) reply = btd_error_failed(iconn->pending_connect, conn_err->message); goto failed; } /* Connect to the HID interrupt channel */ io = bt_io_connect(BT_IO_L2CAP, interrupt_connect_cb, iconn, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, &idev->src, BT_IO_OPT_DEST_BDADDR, &idev->dst, BT_IO_OPT_PSM, L2CAP_PSM_HIDP_INTR, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, BT_IO_OPT_INVALID); if (!io) { error("%s", err->message); if (iconn->pending_connect) reply = btd_error_failed(iconn->pending_connect, err->message); g_error_free(err); goto failed; } iconn->intr_io = io; return; failed: g_io_channel_unref(iconn->ctrl_io); iconn->ctrl_io = NULL; if (reply) g_dbus_send_message(idev->conn, reply); if (iconn->pending_connect) { dbus_message_unref(iconn->pending_connect); iconn->pending_connect = NULL; } }
static GIOChannel *transport_connect(const bdaddr_t *src, const bdaddr_t *dst, uint16_t port, BtIOConnect function, gpointer user_data) { GIOChannel *io; GError *err = NULL; DBG("port %u", port); if (port > 31) { io = bt_io_connect(BT_IO_L2CAP, function, user_data, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, src, BT_IO_OPT_DEST_BDADDR, dst, BT_IO_OPT_PSM, port, BT_IO_OPT_MODE, BT_IO_MODE_ERTM, BT_IO_OPT_OMTU, BT_TX_MTU, BT_IO_OPT_IMTU, BT_RX_MTU, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, BT_IO_OPT_INVALID); } else { io = bt_io_connect(BT_IO_RFCOMM, function, user_data, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, src, BT_IO_OPT_DEST_BDADDR, dst, BT_IO_OPT_CHANNEL, port, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, BT_IO_OPT_INVALID); } if (io != NULL) return io; error("%s", err->message); g_error_free(err); return NULL; }
/* Connect and initiate BNEP session */ static DBusMessage *connection_connect(DBusConnection *conn, DBusMessage *msg, void *data) { struct network_peer *peer = data; struct network_conn *nc; const char *svc; uint16_t id; GError *err = NULL; if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &svc, DBUS_TYPE_INVALID) == FALSE) return NULL; id = bnep_service_id(svc); nc = find_connection(peer->connections, id); if (!nc) return btd_error_not_supported(msg); if (nc->state != DISCONNECTED) return btd_error_already_connected(msg); nc->io = bt_io_connect(BT_IO_L2CAP, connect_cb, nc, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, &peer->src, BT_IO_OPT_DEST_BDADDR, &peer->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) { DBusMessage *reply; error("%s", err->message); reply = btd_error_failed(msg, err->message); g_error_free(err); return reply; } nc->state = CONNECTING; nc->msg = dbus_message_ref(msg); nc->watch = g_dbus_add_disconnect_watch(conn, dbus_message_get_sender(msg), connection_destroy, nc, NULL); return NULL; }
static gboolean rfcomm_connect(struct input_conn *iconn, GError **err) { struct input_device *idev = iconn->idev; GIOChannel *io; io = bt_io_connect(BT_IO_RFCOMM, rfcomm_connect_cb, iconn, NULL, err, BT_IO_OPT_SOURCE_BDADDR, &idev->src, BT_IO_OPT_DEST_BDADDR, &idev->dst, BT_IO_OPT_INVALID); if (!io) return FALSE; g_io_channel_unref(io); return TRUE; }
static bool avrcp_device_connect(struct avrcp_device *dev, BtIOConnect cb) { GError *err = NULL; dev->io = bt_io_connect(cb, dev, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, &adapter_addr, BT_IO_OPT_DEST_BDADDR, &dev->dst, BT_IO_OPT_PSM, L2CAP_PSM_AVCTP, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM, BT_IO_OPT_INVALID); if (err) { error("%s", err->message); g_error_free(err); return false; } return true; }
static int cmd_connect(const char *dst, gpointer user_data) { bdaddr_t sba, dba; uint8_t dest_type; BtIOSecLevel sec; if (get_state() != STATE_DISCONNECTED) { return -1; } set_state(STATE_CONNECTING); str2ba(dst, &dba); bacpy(&sba, BDADDR_ANY); /* {0, 0, 0, 0, 0, 0} */ dest_type = BDADDR_LE_PUBLIC; /* 0x01 */ sec = BT_IO_SEC_LOW; /* Connection happens at low security. Change later */ GError *gerr = NULL; /* iochannel is declared global for now * source: src/device.c in bluez tree for more details */ iochannel = bt_io_connect(connect_cb, user_data, NULL, &gerr, BT_IO_OPT_SOURCE_BDADDR, &sba, BT_IO_OPT_SOURCE_TYPE, BDADDR_LE_PUBLIC, BT_IO_OPT_DEST_BDADDR, &dba, BT_IO_OPT_DEST_TYPE, dest_type, BT_IO_OPT_CID, ATT_CID, BT_IO_OPT_SEC_LEVEL, sec, BT_IO_OPT_INVALID); if (gerr) { set_state(STATE_DISCONNECTED); set_error(ERR_CONNECT_FAILED, gerr->message, user_data); printf("Error: %d %s\n", gerr->code, gerr->message); g_error_free(gerr); return -2; } else { g_io_add_watch(iochannel, G_IO_HUP, channel_hangup_watcher, user_data); g_main_loop_run(event_loop); } return 0; }
static void control_connect_cb(GIOChannel *chan, GError *conn_err, gpointer user_data) { struct input_device *idev = user_data; GIOCondition cond = G_IO_HUP | G_IO_ERR | G_IO_NVAL; GIOChannel *io; GError *err = NULL; if (conn_err) { error("%s", conn_err->message); goto failed; } /* Connect to the HID interrupt channel */ io = bt_io_connect(interrupt_connect_cb, idev, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, &idev->src, BT_IO_OPT_DEST_BDADDR, &idev->dst, BT_IO_OPT_PSM, L2CAP_PSM_HIDP_INTR, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, BT_IO_OPT_INVALID); if (!io) { error("%s", err->message); g_error_free(err); goto failed; } idev->intr_io = io; if (idev->uhid) cond |= G_IO_IN; idev->ctrl_watch = g_io_add_watch(idev->ctrl_io, cond, ctrl_watch_cb, idev); return; failed: btd_service_connecting_complete(idev->service, -EIO); g_io_channel_unref(idev->ctrl_io); idev->ctrl_io = NULL; }
static GIOChannel *rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel, BtIOConnect function, gpointer user_data) { GIOChannel *io; GError *err = NULL; io = bt_io_connect(BT_IO_RFCOMM, function, user_data, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, src, BT_IO_OPT_DEST_BDADDR, dst, BT_IO_OPT_CHANNEL, channel, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, BT_IO_OPT_INVALID); if (io != NULL) return io; error("%s", err->message); g_error_free(err); return NULL; }
static void control_connect_cb(GIOChannel *chan, GError *conn_err, gpointer user_data) { struct hid_device *dev = user_data; GError *err = NULL; DBG(""); if (conn_err) { bt_hid_notify_state(dev, HAL_HIDHOST_STATE_DISCONNECTED); error("hidhost: Failed to connect control channel (%s)", conn_err->message); goto failed; } /* Connect to the HID interrupt channel */ dev->intr_io = bt_io_connect(interrupt_connect_cb, dev, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, &adapter_addr, BT_IO_OPT_DEST_BDADDR, &dev->dst, BT_IO_OPT_PSM, L2CAP_PSM_HIDP_INTR, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, BT_IO_OPT_INVALID); if (!dev->intr_io) { error("hidhost: Failed to connect interrupt channel (%s)", err->message); g_error_free(err); goto failed; } dev->ctrl_watch = g_io_add_watch(dev->ctrl_io, G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL, ctrl_watch_cb, dev); return; failed: hid_device_remove(dev); }