static gboolean io_conn_ind(GIOChannel *chan, GIOCondition cond, gpointer data) { struct vhci_link_info info; struct vhci_conn *conn; struct sockaddr_in sa; socklen_t len; int sk, nsk, h; if (cond & G_IO_NVAL) return FALSE; sk = g_io_channel_unix_get_fd(chan); len = sizeof(sa); if ((nsk = accept(sk, (struct sockaddr *) &sa, &len)) < 0) return TRUE; if (read_n(nsk, &info, sizeof(info)) < 0) { syslog(LOG_ERR, "Can't read link info"); return TRUE; } if (!(conn = malloc(sizeof(*conn)))) { syslog(LOG_ERR, "Can't alloc new connection"); close(nsk); return TRUE; } bacpy(&conn->dest, &info.bdaddr); for (h = 0; h < VHCI_MAX_CONN; h++) if (!vconn[h]) goto accepted; syslog(LOG_ERR, "Too many connections"); free(conn); close(nsk); return TRUE; accepted: vconn[h] = conn; conn->handle = h + 1; conn->chan = g_io_channel_unix_new(nsk); connect_request(conn); return TRUE; }
int sco_connect(struct sock *sk) { bdaddr_t *src = &bluez_pi(sk)->src; bdaddr_t *dst = &bluez_pi(sk)->dst; struct sco_conn *conn; struct hci_conn *hcon; struct hci_dev *hdev; int err = 0; BT_DBG("%s -> %s", batostr(src), batostr(dst)); if (!(hdev = hci_get_route(dst, src))) return -EHOSTUNREACH; hci_dev_lock_bh(hdev); err = -ENOMEM; hcon = hci_connect(hdev, SCO_LINK, dst); if (!hcon) goto done; conn = sco_conn_add(hcon, 0); if (!conn) { hci_conn_put(hcon); goto done; } /* Update source addr of the socket */ bacpy(src, conn->src); err = sco_chan_add(conn, sk, NULL); if (err) goto done; if (hcon->state == BT_CONNECTED) { sco_sock_clear_timer(sk); sk->state = BT_CONNECTED; } else { sk->state = BT_CONNECT; sco_sock_set_timer(sk, sk->sndtimeo); } done: hci_dev_unlock_bh(hdev); hci_dev_put(hdev); return err; }
int connection_init(int dev_id, char *addr, struct conn_info_handles *ci) { struct hci_conn_info_req *cr = NULL; bdaddr_t bdaddr; int dd; int ret = 1; str2ba(addr, &bdaddr); if (dev_id < 0) { dev_id = hci_for_each_dev(HCI_UP, find_conn, (long) &bdaddr); if (dev_id < 0) { ret = ERR_NOT_CONNECTED; goto out; } } dd = hci_open_dev(dev_id); if (dd < 0) { ret = ERR_HCI_DEV_OPEN_FAILED; goto out; } cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info)); if (!cr) { ret = ERR_CANNOT_ALLOCATE; goto out; } bacpy(&cr->bdaddr, &bdaddr); cr->type = ACL_LINK; if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) { ret = ERR_GET_CONN_INFO_FAILED; goto out; } ci->dd = dd; ci->handle = cr->conn_info->handle; out: if (cr) free(cr); return ret; }
static int l2cap_accept(int sk, bdaddr_t *bdaddr) { struct sockaddr_l2 addr; socklen_t addrlen; int nsk; memset(&addr, 0, sizeof(addr)); addrlen = sizeof(addr); if ((nsk = accept(sk, (struct sockaddr *) &addr, &addrlen)) < 0) return -1; if (bdaddr) bacpy(bdaddr, &addr.l2_bdaddr); return nsk; }
bool bt_avrcp_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode) { GError *err = NULL; sdp_record_t *rec; DBG(""); bacpy(&adapter_addr, addr); server = bt_io_listen(NULL, confirm_cb, NULL, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, &adapter_addr, BT_IO_OPT_PSM, L2CAP_PSM_AVCTP, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM, BT_IO_OPT_INVALID); if (!server) { error("Failed to listen on AVDTP channel: %s", err->message); g_error_free(err); return false; } rec = avrcp_record(); if (!rec) { error("Failed to allocate AVRCP record"); goto fail; } if (bt_adapter_add_record(rec, 0) < 0) { error("Failed to register AVRCP record"); sdp_record_free(rec); goto fail; } record_id = rec->handle; hal_ipc = ipc; ipc_register(hal_ipc, HAL_SERVICE_ID_AVRCP, cmd_handlers, G_N_ELEMENTS(cmd_handlers)); return true; fail: g_io_channel_shutdown(server, TRUE, NULL); g_io_channel_unref(server); server = NULL; return false; }
static void confirm_event(GIOChannel *chan, gpointer user_data) { struct network_adapter *na = user_data; bdaddr_t src, dst; char address[18]; GError *err = NULL; guint ret; bt_io_get(chan, &err, BT_IO_OPT_SOURCE_BDADDR, &src, BT_IO_OPT_DEST_BDADDR, &dst, BT_IO_OPT_DEST, address, BT_IO_OPT_INVALID); if (err) { error("%s", err->message); g_error_free(err); goto drop; } DBG("BNEP: incoming connect from %s", address); if (na->setup) { error("Refusing connect from %s: setup in progress", address); goto drop; } if (!na->servers) goto drop; na->setup = g_new0(struct network_session, 1); bacpy(&na->setup->dst, &dst); na->setup->io = g_io_channel_ref(chan); ret = btd_request_authorization(&src, &dst, BNEP_SVC_UUID, auth_cb, na); if (ret == 0) { error("Refusing connect from %s", address); setup_destroy(na); goto drop; } return; drop: g_io_channel_shutdown(chan, TRUE, NULL); }
/** * Called by run_scan when we receive a complete EVT_INQUIRY_RESULT_WITH_RSSI * message. * * Writes a byte with value EVT_INQUIRY_RESULT_WITH_RSSI and then a * bluetrax_inquiry_result_with_rssi_t structure (in binary format) to out_file. * * Reference: [BTSPEC, volume 2, section 7.7.33, page 756] * * @param out_file to write record to * * @param time that the message was received * * @param hdr the event header * * @param data all data after the header; length is at least hdr->plen * * @return EXIT_SUCCESS if no errors */ static int handle_inquiry_result_with_rssi(FILE *out_file, struct timeval time, hci_event_hdr *hdr, unsigned char *data) { int num_rsp, i; inquiry_info_with_rssi *info; bluetrax_inquiry_result_with_rssi_t record; if (hdr->plen <= 0) { syslog(LOG_ERR, "handle_inquiry_result_with_rssi: bad plen: plen=%hhd", hdr->plen); return EXIT_FAILURE; } /* note: we never seem to get num_rsp > 1 here, but handle it anyway */ num_rsp = data[0]; syslog(LOG_DEBUG, "handle_inquiry_result_with_rssi: num_rsp=%d", num_rsp); /* sanity check */ if (hdr->plen != num_rsp * sizeof(inquiry_info_with_rssi) + 1) { syslog(LOG_ERR, "handle_inquiry_result_with_rssi: bad plen: num_rsp=%d, plen=%hhd", num_rsp, hdr->plen); return EXIT_FAILURE; } record.time = time; info = (inquiry_info_with_rssi *)(data + 1); for (i = 0; i < num_rsp; ++i) { bacpy(&record.bdaddr, &info[i].bdaddr); memcpy(&record.dev_class, info[i].dev_class, sizeof(record.dev_class)); record.rssi = info[i].rssi; /* write the event type and then the event record */ if (EVT_INQUIRY_RESULT_WITH_RSSI != fputc(EVT_INQUIRY_RESULT_WITH_RSSI, out_file)) { syslog(LOG_ERR, "handle_inquiry_result_with_rssi: fputc: %m"); return EXIT_FAILURE; } if (1 != fwrite(&record, sizeof(record), 1, out_file)) { syslog(LOG_ERR, "handle_inquiry_result_with_rssi: fwrite: %m"); return EXIT_FAILURE; } } return EXIT_SUCCESS; }
static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_remote_features *ev = (void *) skb->data; struct hci_conn *conn; BT_DBG("%s status %d", hdev->name, ev->status); hci_dev_lock(hdev); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); if (!conn) goto unlock; if (!ev->status) memcpy(conn->features, ev->features, 8); if (conn->state != BT_CONFIG) goto unlock; if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { struct hci_cp_read_remote_ext_features cp; cp.handle = ev->handle; cp.page = 0x01; hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, sizeof(cp), &cp); goto unlock; } if (!ev->status) { struct hci_cp_remote_name_req cp; memset(&cp, 0, sizeof(cp)); bacpy(&cp.bdaddr, &conn->dst); cp.pscan_rep_mode = 0x02; hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); } if (!hci_outgoing_auth_needed(hdev, conn)) { conn->state = BT_CONNECTED; hci_proto_connect_cfm(conn, ev->status); hci_conn_put(conn); } unlock: hci_dev_unlock(hdev); }
static int sco_listen(pa_bluetooth_transport *t) { struct transport_data *trd = t->userdata; struct sockaddr_sco addr; int sock, i; bdaddr_t src; const char *src_addr; sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET | SOCK_NONBLOCK | SOCK_CLOEXEC, BTPROTO_SCO); if (sock < 0) { pa_log_error("socket(SEQPACKET, SCO) %s", pa_cstrerror(errno)); return -1; } src_addr = t->device->adapter->address; /* don't use ba2str to avoid -lbluetooth */ for (i = 5; i >= 0; i--, src_addr += 3) src.b[i] = strtol(src_addr, NULL, 16); /* Bind to local address */ memset(&addr, 0, sizeof(addr)); addr.sco_family = AF_BLUETOOTH; bacpy(&addr.sco_bdaddr, &src); if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { pa_log_error("bind(): %s", pa_cstrerror(errno)); goto fail_close; } pa_log_info ("doing listen"); if (listen(sock, 1) < 0) { pa_log_error("listen(): %s", pa_cstrerror(errno)); goto fail_close; } trd->sco_fd = sock; trd->sco_io = trd->mainloop->io_new(trd->mainloop, sock, PA_IO_EVENT_INPUT, sco_io_callback, t); return sock; fail_close: close(sock); return -1; }
static void bt_hid_connect(const void *buf, uint16_t len) { const struct hal_cmd_hidhost_connect *cmd = buf; struct hid_device *dev; uint8_t status; char addr[18]; bdaddr_t dst; GSList *l; uuid_t uuid; DBG(""); android2bdaddr(&cmd->bdaddr, &dst); l = g_slist_find_custom(devices, &dst, device_cmp); if (l) { status = HAL_STATUS_FAILED; goto failed; } dev = g_new0(struct hid_device, 1); bacpy(&dev->dst, &dst); dev->uhid_fd = -1; ba2str(&dev->dst, addr); DBG("connecting to %s", addr); sdp_uuid16_create(&uuid, PNP_INFO_SVCLASS_ID); if (bt_search_service(&adapter_addr, &dev->dst, &uuid, hid_sdp_did_search_cb, dev, NULL, 0) < 0) { error("Failed to search DeviceID SDP details"); hid_device_remove(dev); status = HAL_STATUS_FAILED; goto failed; } devices = g_slist_append(devices, dev); bt_hid_notify_state(dev, HAL_HIDHOST_STATE_CONNECTING); status = HAL_STATUS_SUCCESS; failed: ipc_send_rsp(hal_ipc, HAL_SERVICE_ID_HIDHOST, HAL_OP_HIDHOST_CONNECT, status); }
int main(int argc, char **argv) { struct sockaddr_rc loc_addr = { 0 }; /* local bluetooth adapter's info */ struct sockaddr_rc client_addr = { 0 }; /* filled in with remote (client) bluetooth device's info */ char buf[1024] = { 0 }; int server_sock, client_sock, bytes_read; unsigned int opt = sizeof(client_addr); printf("Start Bluetooth RFCOMM server...\n"); /* allocate socket */ server_sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); loc_addr.rc_family = AF_BLUETOOTH; /* Addressing family, always AF_BLUETOOTH */ bacpy(&loc_addr.rc_bdaddr, BDADDR_ANY); /* Bluetooth address of local bluetooth adapter */ loc_addr.rc_channel = RFCOMM_SERVER_PORT_NUM; /* port number of local bluetooth adapter */ printf("binding\n"); if(bind(server_sock, (struct sockaddr *)&loc_addr, sizeof(loc_addr)) < 0) { perror("failed to bind"); exit(1); } printf("listening\n"); /* put socket into listening mode */ listen(server_sock, 1); /* backlog is one */ /* accept one connection */ client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &opt); /* return new socket for connection with a client */ ba2str( &client_addr.rc_bdaddr, buf ); printf("connected from %s\n", buf); /* read data from the client */ memset(buf, 0, sizeof(buf)); bytes_read = recv(client_sock, buf, sizeof(buf), 0); if( bytes_read > 0 ) { printf("received [%s]\n", buf); } /* close connection */ close(client_sock); close(server_sock); return 0; }
static uint8_t get_serial_channel(bdaddr_t *device, int only_gnapplet) { bdaddr_t src; int channel; uint8_t retval; bacpy(&src, BDADDR_ANY); channel = find_service_channel(&src, device, only_gnapplet, GNOKII_SERIAL_PORT_CLASS); if (channel < 0) channel = find_service_channel(&src, device, only_gnapplet, GNOKII_DIALUP_NETWORK_CLASS); if (channel < 0) retval = 0; else retval = channel; return retval; }
/* * Add a service record to the repository */ void sdp_record_add(const bdaddr_t *device, sdp_record_t *rec) { sdp_access_t *dev; SDPDBG("Adding rec : 0x%lx", (long) rec); SDPDBG("with handle : 0x%x", rec->handle); service_db = sdp_list_insert_sorted(service_db, rec, record_sort); dev = malloc(sizeof(*dev)); if (!dev) return; bacpy(&dev->device, device); dev->handle = rec->handle; access_db = sdp_list_insert_sorted(access_db, dev, access_sort); }
static void adapter_ready(int err, const bdaddr_t *addr) { if (err < 0) { error("Adapter initialization failed: %s", strerror(-err)); exit(EXIT_FAILURE); } bacpy(&adapter_bdaddr, addr); if (bluetooth_start_timeout > 0) { g_source_remove(bluetooth_start_timeout); bluetooth_start_timeout = 0; } info("Adapter initialized"); ipc_init(); }
void hcid_dbus_request_pin(int dev, struct hci_conn_info *ci) { DBusMessage *message; DBusMessageIter iter; DBusPendingCall *pending = NULL; struct pin_request *req; message = dbus_message_new_method_call(SERVICE_NAME, PATH_NAME, INTERFACE_NAME, REQUEST_NAME); if (message == NULL) { syslog(LOG_ERR, "Couldn't allocate D-BUS message"); goto failed; } req = malloc(sizeof(*req)); req->dev = dev; bacpy(&req->bda, &ci->bdaddr); dbus_message_append_iter_init(message, &iter); dbus_message_iter_append_boolean(&iter, ci->out); dbus_message_iter_append_byte_array(&iter, (unsigned char *) &ci->bdaddr, sizeof(ci->bdaddr)); if (dbus_connection_send_with_reply(connection, message, &pending, TIMEOUT) == FALSE) { syslog(LOG_ERR, "D-BUS send failed"); goto failed; } dbus_pending_call_set_notify(pending, reply_handler_function, req, free_pin_req); dbus_connection_flush (connection); dbus_message_unref (message); return; failed: dbus_message_unref (message); hci_send_cmd(dev, OGF_LINK_CTL, OCF_PIN_CODE_NEG_REPLY, 6, &ci->bdaddr); }
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 mgmt_user_confirm_request(int sk, uint16_t index, void *buf, size_t len) { struct mgmt_ev_user_confirm_request *ev = buf; struct controller_info *info; char addr[18]; int err; if (len < sizeof(*ev)) { error("Too small user_confirm_request event"); return; } ba2str(&ev->bdaddr, addr); DBG("hci%u %s confirm_hint %u", index, addr, ev->confirm_hint); if (index > max_index) { error("Unexpected index %u in user_confirm_request event", index); return; } if (ev->confirm_hint) { struct confirm_data *data; data = g_new0(struct confirm_data, 1); data->index = index; bacpy(&data->bdaddr, &ev->bdaddr); g_timeout_add_seconds_full(G_PRIORITY_DEFAULT, 1, confirm_accept, data, g_free); return; } info = &controllers[index]; err = btd_event_user_confirm(&info->bdaddr, &ev->bdaddr, btohl(ev->value)); if (err < 0) { error("btd_event_user_confirm: %s", strerror(-err)); mgmt_confirm_reply(index, &ev->bdaddr, FALSE); } }
static void auth_cb(DBusError *derr, void *user_data) { struct service_adapter *serv_adapter = user_data; DBusMessage *reply; struct pending_auth *auth; bdaddr_t src; auth = next_pending(serv_adapter); if (auth == NULL) { info("Authorization cancelled: Client exited"); return; } if (derr) { error("Access denied: %s", derr->message); reply = btd_error_not_authorized(auth->msg); dbus_message_unref(auth->msg); g_dbus_send_message(auth->conn, reply); goto done; } g_dbus_send_reply(auth->conn, auth->msg, DBUS_TYPE_INVALID); done: 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) return; 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); }
static int mgmt_load_link_keys(int sk, uint16_t index, uint16_t nb_keys, bdaddr_t bdaddrs[nb_keys], unsigned char keys[nb_keys][16]) { char *buf; struct mgmt_hdr *hdr; struct mgmt_cp_load_link_keys *cp; struct mgmt_link_key_info *key; size_t cp_size; int err = 0; cp_size = sizeof(*cp) + (nb_keys * sizeof(*key)); buf = calloc(sizeof(*hdr) + cp_size, 1); if (buf == NULL) return -ENOMEM; hdr = (void *) buf; hdr->opcode = htobs(MGMT_OP_LOAD_LINK_KEYS); hdr->len = htobs(cp_size); hdr->index = htobs(index); cp = (void *) (buf + sizeof(*hdr)); cp->debug_keys = 0x00; cp->key_count = htobs(nb_keys); unsigned int i; for (i=0, key=cp->keys; i<nb_keys; ++i, ++key) { bacpy(&key->addr.bdaddr, bdaddrs+i); key->addr.type = BDADDR_BREDR; key->type = HCI_LK_UNAUTH_COMBINATION; memcpy(key->val, keys[i], 16); key->pin_len = 0x00; } if (write(sk, buf, sizeof(*hdr) + cp_size) < 0) { perror("write"); err = -1; } free(buf); return err; }
bool bt_hid_register(struct ipc *ipc, const bdaddr_t *addr, uint8_t mode) { GError *err = NULL; DBG(""); bacpy(&adapter_addr, addr); ctrl_io = bt_io_listen(connect_cb, NULL, NULL, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, &adapter_addr, BT_IO_OPT_PSM, L2CAP_PSM_HIDP_CTRL, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, BT_IO_OPT_INVALID); if (!ctrl_io) { error("hidhost: Failed to listen on control channel: %s", err->message); g_error_free(err); return false; } intr_io = bt_io_listen(connect_cb, NULL, NULL, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, &adapter_addr, BT_IO_OPT_PSM, L2CAP_PSM_HIDP_INTR, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, BT_IO_OPT_INVALID); if (!intr_io) { error("hidhost: Failed to listen on interrupt channel: %s", err->message); g_error_free(err); g_io_channel_shutdown(ctrl_io, TRUE, NULL); g_io_channel_unref(ctrl_io); ctrl_io = NULL; return false; } hal_ipc = ipc; ipc_register(hal_ipc, HAL_SERVICE_ID_HIDHOST, cmd_handlers, G_N_ELEMENTS(cmd_handlers)); return true; }
static void nap_confirm_cb(GIOChannel *chan, gpointer data) { struct pan_device *dev; bdaddr_t dst; char address[18]; GError *err = NULL; DBG(""); bt_io_get(chan, &err, BT_IO_OPT_DEST_BDADDR, &dst, BT_IO_OPT_DEST, address, BT_IO_OPT_INVALID); if (err) { error("%s", err->message); g_error_free(err); return; } DBG("incoming connect request from %s", address); dev = g_new0(struct pan_device, 1); bacpy(&dev->dst, &dst); local_role = HAL_PAN_ROLE_NAP; dev->role = HAL_PAN_ROLE_PANU; strncpy(dev->iface, BNEP_NAP_INTERFACE, 16); dev->iface[15] = '\0'; dev->io = g_io_channel_ref(chan); g_io_channel_set_close_on_unref(dev->io, TRUE); if (!bt_io_accept(dev->io, nap_connect_cb, dev, NULL, &err)) { error("bt_io_accept: %s", err->message); g_error_free(err); goto failed; } devices = g_slist_append(devices, dev); bt_pan_notify_conn_state(dev, HAL_PAN_STATE_CONNECTING); return; failed: bt_pan_notify_conn_state(dev, HAL_PAN_STATE_DISCONNECTED); }
static int create_rfcomm_sock(bdaddr_t *address, uint8_t channel) { int sk; struct sockaddr_rc addr; sk = socket(PF_BLUETOOTH, SOCK_STREAM | SOCK_NONBLOCK, BTPROTO_RFCOMM); memset(&addr, 0, sizeof(addr)); addr.rc_family = AF_BLUETOOTH; addr.rc_channel = channel; bacpy(&addr.rc_bdaddr, address); if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { close(sk); return -1; } return sk; }
static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_remote_ext_features *ev = (void *) skb->data; struct hci_conn *conn; BT_DBG("%s", hdev->name); hci_dev_lock(hdev); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); if (!conn) goto unlock; if (!ev->status && ev->page == 0x01) { struct inquiry_entry *ie; ie = hci_inquiry_cache_lookup(hdev, &conn->dst); if (ie) ie->data.ssp_mode = (ev->features[0] & 0x01); conn->ssp_mode = (ev->features[0] & 0x01); } if (conn->state != BT_CONFIG) goto unlock; if (!ev->status) { struct hci_cp_remote_name_req cp; memset(&cp, 0, sizeof(cp)); bacpy(&cp.bdaddr, &conn->dst); cp.pscan_rep_mode = 0x02; hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); } if (!hci_outgoing_auth_needed(hdev, conn)) { conn->state = BT_CONNECTED; hci_proto_connect_cfm(conn, ev->status); hci_conn_put(conn); } unlock: hci_dev_unlock(hdev); }
static void device_info(int fd, uint16_t index, uint8_t *type, uint8_t *bus, bdaddr_t *bdaddr, char *name) { struct hci_dev_info di; memset(&di, 0, sizeof(di)); di.dev_id = index; if (ioctl(fd, HCIGETDEVINFO, (void *) &di) < 0) { perror("Failed to get device information"); return; } *type = di.type >> 4; *bus = di.type & 0x0f; bacpy(bdaddr, &di.bdaddr); memcpy(name, di.name, 8); }
static void device_list(int fd, int max_dev) { struct hci_dev_list_req *dl; struct hci_dev_req *dr; int i; dl = malloc(max_dev * sizeof(*dr) + sizeof(*dl)); if (!dl) { perror("Failed to allocate device list memory"); return; } memset(dl, 0, max_dev * sizeof(*dr) + sizeof(*dl)); dl->dev_num = max_dev; dr = dl->dev_req; if (ioctl(fd, HCIGETDEVLIST, (void *) dl) < 0) { perror("Failed to get device list"); goto done; } for (i = 0; i < dl->dev_num; i++, dr++) { struct timeval tmp_tv, *tv = NULL; uint8_t type = 0xff, bus = 0xff; char str[18], name[8] = ""; bdaddr_t bdaddr; bacpy(&bdaddr, BDADDR_ANY); if (!gettimeofday(&tmp_tv, NULL)) tv = &tmp_tv; device_info(fd, dr->dev_id, &type, &bus, &bdaddr, name); ba2str(&bdaddr, str); packet_new_index(tv, dr->dev_id, str, type, bus, name); open_device(dr->dev_id); } done: free(dl); }
int avdtp_connect(avdtp_t *avdtp, bdaddr_t *bdaddr, uint8_t seid) { struct avdtp_session *session; int sk; if (!avdtp) return -EIO; session = avdtp; bacpy(&session->dst, bdaddr); sk = l2cap_connect(&session->src, &session->dst, AVDTP_PSM, NULL); if (sk < 0) return -EIO; session->ssk = sk; return 0; }
static int add_xml_record(DBusConnection *conn, const char *sender, struct service_adapter *serv_adapter, const char *record, dbus_uint32_t *handle) { struct record_data *user_record; sdp_record_t *sdp_record; bdaddr_t src; sdp_record = sdp_xml_parse_record(record, strlen(record)); if (!sdp_record) { error("Parsing of XML service record failed"); return -EIO; } if (serv_adapter->adapter) adapter_get_address(serv_adapter->adapter, &src); else bacpy(&src, BDADDR_ANY); if (add_record_to_server(&src, sdp_record) < 0) { error("Failed to register service record"); sdp_record_free(sdp_record); return -EIO; } user_record = g_new0(struct record_data, 1); user_record->handle = sdp_record->handle; user_record->sender = g_strdup(sender); user_record->serv_adapter = serv_adapter; user_record->listener_id = g_dbus_add_disconnect_watch(conn, sender, exit_callback, user_record, NULL); serv_adapter->records = g_slist_append(serv_adapter->records, user_record); DBG("listener_id %d", user_record->listener_id); *handle = user_record->handle; return 0; }
/* Inquiry Result With RSSI */ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) { inquiry_info_with_rssi *info = (inquiry_info_with_rssi *) (skb->data + 1); int num_rsp = *((__u8 *) skb->data); BT_DBG("%s num_rsp %d", hdev->name, num_rsp); hci_dev_lock(hdev); for (; num_rsp; num_rsp--) { inquiry_info tmp; bacpy(&tmp.bdaddr, &info->bdaddr); tmp.pscan_rep_mode = info->pscan_rep_mode; tmp.pscan_period_mode = info->pscan_period_mode; tmp.pscan_mode = 0x00; memcpy(tmp.dev_class, &info->dev_class, 3); tmp.clock_offset = info->clock_offset; info++; inquiry_cache_update(hdev, &tmp); } hci_dev_unlock(hdev); }
static void return_link_keys(int dev, bdaddr_t *sba, void *ptr) { evt_return_link_keys *evt = ptr; uint8_t num = evt->num_keys; unsigned char key[16]; char sa[18], da[18]; bdaddr_t dba; int i; ba2str(sba, sa); ptr++; for (i = 0; i < num; i++) { bacpy(&dba, ptr); ba2str(&dba, da); memcpy(key, ptr + 6, 16); syslog(LOG_INFO, "return_link_keys (sba=%s, dba=%s)", sa, da); ptr += 22; } }
static void cmd_unpair(int argcp, char **argvp) { struct mgmt_cp_unpair_device cp; bdaddr_t bdaddr; uint8_t addr_type = BDADDR_LE_RANDOM; if (argcp != 3) { resp_mgmt(err_BAD_PARAM); return; } if (str2ba(argvp[1], &bdaddr)) { DBG("str2ba failed"); resp_mgmt(err_NOT_FOUND); return; } if (!memcmp(argvp[2], "public", 6)) { addr_type = BDADDR_LE_PUBLIC; } memset(&cp, 0, sizeof(cp)); bacpy(&cp.addr.bdaddr, &bdaddr); cp.addr.type = addr_type; cp.disconnect = 1; if (!mgmt_master) { resp_error(err_NO_MGMT); return; } if (mgmt_send(mgmt_master, MGMT_OP_UNPAIR_DEVICE, opt_src_idx, sizeof(cp), &cp, unpair_device_complete, NULL, NULL) == 0) { DBG("mgmt_send(MGMT_OP_UNPAIR_DEVICE) failed for %s for hci%u", opt_dst, MGMT_INDEX_NONE); resp_mgmt(err_PROTO_ERR); return; } }