📄 glib-helper.c
字号:
err = sco_bind(io_ctxt, io->src, io->mtu, &addr); if (err < 0) return err; err = transport_listen(io); if (err < 0) { close(io_ctxt->fd); return err; } return BT_IO_SUCCESS;}static gboolean hci_event_watch(GIOChannel *io, GIOCondition cond, gpointer user_data){ unsigned char buf[HCI_MAX_EVENT_SIZE], *body; struct hci_cmd_data *cmd = user_data; evt_cmd_status *evt_status; evt_auth_complete *evt_auth; evt_encrypt_change *evt_enc; hci_event_hdr *hdr; set_conn_encrypt_cp cp; int dd; uint16_t ocf; uint8_t status = HCI_OE_POWER_OFF; if (cond & G_IO_NVAL) { cmd->cb(status, cmd->caller_data); return FALSE; } if (cond & (G_IO_ERR | G_IO_HUP)) goto failed; dd = g_io_channel_unix_get_fd(io); if (read(dd, buf, sizeof(buf)) < 0) goto failed; hdr = (hci_event_hdr *) (buf + 1); body = buf + (1 + HCI_EVENT_HDR_SIZE); switch (hdr->evt) { case EVT_CMD_STATUS: evt_status = (evt_cmd_status *) body; ocf = cmd_opcode_ocf(evt_status->opcode); if (ocf != cmd->ocf) return TRUE; switch (ocf) { case OCF_AUTH_REQUESTED: case OCF_SET_CONN_ENCRYPT: if (evt_status->status != 0) { /* Baseband rejected command */ status = evt_status->status; goto failed; } break; default: return TRUE; } /* Wait for the next event */ return TRUE; case EVT_AUTH_COMPLETE: evt_auth = (evt_auth_complete *) body; if (evt_auth->handle != cmd->handle) { /* Skipping */ return TRUE; } if (evt_auth->status != 0x00) { status = evt_auth->status; /* Abort encryption */ goto failed; } memset(&cp, 0, sizeof(cp)); cp.handle = cmd->handle; cp.encrypt = 1; cmd->ocf = OCF_SET_CONN_ENCRYPT; if (hci_send_cmd(dd, OGF_LINK_CTL, OCF_SET_CONN_ENCRYPT, SET_CONN_ENCRYPT_CP_SIZE, &cp) < 0) { status = HCI_COMMAND_DISALLOWED; goto failed; } /* Wait for encrypt change event */ return TRUE; case EVT_ENCRYPT_CHANGE: evt_enc = (evt_encrypt_change *) body; if (evt_enc->handle != cmd->handle) return TRUE; /* Procedure finished: reporting status */ status = evt_enc->status; break; default: /* Skipping */ return TRUE; }failed: cmd->cb(status, cmd->caller_data); g_io_channel_close(io); return FALSE;}int bt_acl_encrypt(const bdaddr_t *src, const bdaddr_t *dst, bt_hci_result_t cb, gpointer user_data){ GIOChannel *io; struct hci_cmd_data *cmd; struct hci_conn_info_req *cr; auth_requested_cp cp; struct hci_filter nf; int dd, dev_id, err; char src_addr[18]; uint32_t link_mode; uint16_t handle; ba2str(src, src_addr); dev_id = hci_devid(src_addr); if (dev_id < 0) return -errno; dd = hci_open_dev(dev_id); if (dd < 0) return -errno; cr = g_malloc0(sizeof(*cr) + sizeof(struct hci_conn_info)); cr->type = ACL_LINK; bacpy(&cr->bdaddr, dst); err = ioctl(dd, HCIGETCONNINFO, cr); link_mode = cr->conn_info->link_mode; handle = cr->conn_info->handle; g_free(cr); if (err < 0) { err = errno; goto failed; } if (link_mode & HCI_LM_ENCRYPT) { /* Already encrypted */ err = EALREADY; goto failed; } memset(&cp, 0, sizeof(cp)); cp.handle = htobs(handle); if (hci_send_cmd(dd, OGF_LINK_CTL, OCF_AUTH_REQUESTED, AUTH_REQUESTED_CP_SIZE, &cp) < 0) { err = errno; goto failed; } cmd = g_new0(struct hci_cmd_data, 1); cmd->handle = handle; cmd->ocf = OCF_AUTH_REQUESTED; cmd->cb = cb; cmd->caller_data = user_data; hci_filter_clear(&nf); hci_filter_set_ptype(HCI_EVENT_PKT, &nf); hci_filter_set_event(EVT_CMD_STATUS, &nf); hci_filter_set_event(EVT_AUTH_COMPLETE, &nf); hci_filter_set_event(EVT_ENCRYPT_CHANGE, &nf); if (setsockopt(dd, SOL_HCI, HCI_FILTER, &nf, sizeof(nf)) < 0) { err = errno; goto failed; } io = g_io_channel_unix_new(dd); g_io_channel_set_close_on_unref(io, FALSE); g_io_add_watch_full(io, G_PRIORITY_DEFAULT, G_IO_HUP | G_IO_ERR | G_IO_NVAL | G_IO_IN, hci_event_watch, cmd, g_free); g_io_channel_unref(io); return 0;failed: close(dd); return -err;}static int create_io_context(struct io_context **io_ctxt, BtIOFunc func, gpointer cb, gpointer resolver, gpointer user_data){ *io_ctxt = g_try_malloc0(sizeof(struct search_context)); if (!*io_ctxt) return -ENOMEM; (*io_ctxt)->cb = cb; (*io_ctxt)->func = func; (*io_ctxt)->resolver = resolver; (*io_ctxt)->user_data = user_data; return 0;}static void io_context_cleanup(struct io_context *io_ctxt){ if (io_ctxt->io) { g_io_channel_close(io_ctxt->io); g_io_channel_unref(io_ctxt->io); } g_free(io_ctxt);}GIOChannel *rfcomm_listen_internal(const bdaddr_t *src, uint8_t *channel, uint32_t flags, bt_io_callback_t cb, void *user_data){ BtIO *io; BtIOError err; io = bt_io_create(BT_IO_RFCOMM, user_data, NULL); if (!io) return NULL; ba2str(src, io->src); io->channel = *channel; io->flags = flags; io->io_ctxt->cb = cb; err = bt_io_listen(io, NULL, NULL); if (err != BT_IO_SUCCESS) { bt_io_unref(io); return NULL; } *channel = io->channel; return io->io_ctxt->io;}GIOChannel *bt_rfcomm_listen_allocate(const bdaddr_t *src, uint8_t *channel, uint32_t flags, bt_io_callback_t cb, void *user_data){ if (!channel) return NULL; *channel = 0; return rfcomm_listen_internal(src, channel, flags, cb, user_data);}GIOChannel *bt_rfcomm_listen(const bdaddr_t *src, uint8_t channel, uint32_t flags, bt_io_callback_t cb, void *user_data){ if (channel < 1 || channel > 30) return NULL; return rfcomm_listen_internal(src, &channel, flags, cb, user_data);}int bt_rfcomm_connect(const bdaddr_t *src, const bdaddr_t *dst, uint8_t channel, bt_io_callback_t cb, void *user_data){ BtIO *io; BtIOError err; io = bt_io_create(BT_IO_RFCOMM, user_data, NULL); if (!io) return -1; ba2str(src, io->src); ba2str(dst, io->dst); io->channel = channel; io->io_ctxt->cb = cb; err = bt_io_connect(io, NULL, NULL); if (err != BT_IO_SUCCESS) { bt_io_unref(io); return -1; } return 0;}GIOChannel *bt_l2cap_listen(const bdaddr_t *src, uint16_t psm, uint16_t mtu, uint32_t flags, bt_io_callback_t cb, void *user_data){ BtIO *io; BtIOError err; io = bt_io_create(BT_IO_L2CAP, user_data, NULL); if (!io) return NULL; ba2str(src, io->src); io->psm = psm; io->mtu = mtu; io->flags = flags; io->io_ctxt->cb = cb; err = bt_io_listen(io, NULL, NULL); if (err != BT_IO_SUCCESS) { bt_io_unref(io); return NULL; } return io->io_ctxt->io;}int bt_l2cap_connect(const bdaddr_t *src, const bdaddr_t *dst, uint16_t psm, uint16_t mtu, bt_io_callback_t cb, void *user_data){ BtIO *io; BtIOError err; io = bt_io_create(BT_IO_L2CAP, user_data, NULL); if (!io) return -1; ba2str(src, io->src); ba2str(dst, io->dst); io->psm = psm; io->mtu = mtu; io->io_ctxt->cb = cb; err = bt_io_connect(io, NULL, NULL); if (err != BT_IO_SUCCESS) { bt_io_unref(io); return -1; } return 0;}GIOChannel *bt_sco_listen(const bdaddr_t *src, uint16_t mtu, bt_io_callback_t cb, void *user_data){ BtIO *io; BtIOError err; io = bt_io_create(BT_IO_SCO, user_data, NULL); if (!io) return NULL; ba2str(src, io->src); io->io_ctxt->cb = cb; err = bt_io_listen(io, NULL, NULL); if (err != BT_IO_SUCCESS) { bt_io_unref(io); return NULL; } return io->io_ctxt->io;}int bt_sco_connect(const bdaddr_t *src, const bdaddr_t *dst, bt_io_callback_t cb, void *user_data){ BtIO *io; BtIOError err; io = bt_io_create(BT_IO_SCO, user_data, NULL); if (!io) return -1; ba2str(src, io->src); ba2str(dst, io->dst); io->io_ctxt->cb = cb; err = bt_io_connect(io, NULL, NULL); if (err != BT_IO_SUCCESS) { bt_io_unref(io); return -1; } return 0;}/* Experiemental bt_io API */BtIO *bt_io_create(BtIOTransport type, gpointer user_data, GDestroyNotify notify){ BtIO *io; int err; io = g_new0(BtIO, 1); if (!io) return NULL; io->refcount = 1; switch (type) { case BT_IO_L2CAP: err = create_io_context(&io->io_ctxt, NULL, NULL, l2cap_resolver, user_data); io->connect = l2cap_connect; io->listen = l2cap_listen; break; case BT_IO_RFCOMM: err = create_io_context(&io->io_ctxt, NULL, NULL, rfcomm_resolver, user_data); io->connect = rfcomm_connect; io->listen = rfcomm_listen; break; case BT_IO_SCO: err = create_io_context(&io->io_ctxt, NULL, NULL, sco_resolver, user_data); io->connect = sco_connect; io->listen = sco_listen; break; default: return NULL; } if (err < 0) { bt_io_unref(io); return NULL; } return io;}BtIO *bt_io_ref(BtIO *io){ io->refcount++; return io;}void bt_io_unref(BtIO *io){ io->refcount--; if (io->refcount) return; io_context_cleanup(io->io_ctxt); g_free(io);}gboolean bt_io_set_source(BtIO *io, const char *address){ if (strlen(address) != sizeof(io->src)) return FALSE; memcpy(io->src, address, sizeof(io->src)); return TRUE;}const char *bt_io_get_source(BtIO *io){ return io->src;}gboolean bt_io_set_destination(BtIO *io, const char *address){ if (strlen(address) != sizeof(io->dst)) return FALSE; memcpy(io->dst, address, sizeof(io->dst)); return TRUE;}const char *bt_io_get_destination(BtIO *io){ return io->dst;}gboolean bt_io_set_flags(BtIO *io, guint32 flags){ io->flags = flags; return TRUE;}guint32 bt_io_get_flags(BtIO *io){ return io->flags;}gboolean bt_io_set_channel(BtIO *io, guint8 channel){ if (io->type != BT_IO_RFCOMM) return FALSE; io->channel = channel; return TRUE;}guint8 bt_io_get_channel(BtIO *io){ return io->channel;}gboolean bt_io_set_psm(BtIO *io, guint16 psm){ if (io->type != BT_IO_L2CAP) return FALSE; io->psm = psm; return TRUE;}guint16 bt_io_get_psm(BtIO *io){ return io->psm;}gboolean bt_io_set_mtu(BtIO *io, guint16 mtu){ io->mtu = mtu; return TRUE;}guint16 bt_io_get_mtu(BtIO *io){ return io->mtu;}BtIOError bt_io_connect(BtIO *io, const char *uuid, BtIOFunc func){ if (!io->connect) return BT_IO_FAILED; return io->connect(io, func);}BtIOError bt_io_listen(BtIO *io, const char *uuid, BtIOFunc func){ if (!io->listen) return BT_IO_FAILED; return io->listen(io, func);}BtIOError bt_io_shutdown(BtIO *io){ io_context_cleanup(io->io_ctxt); return BT_IO_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -