📄 glib-helper.c
字号:
err = listen(io_ctxt->fd, 5); if (err < 0) return -errno; io_ctxt->io = g_io_channel_unix_new(io_ctxt->fd); if (!io_ctxt->io) return -ENOMEM; g_io_add_watch(io_ctxt->io, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, (GIOFunc) listen_cb, io); return 0;}static gboolean connect_cb(GIOChannel *gio, GIOCondition cond, gpointer user_data){ BtIO *io = user_data; struct io_context *io_ctxt = io->io_ctxt; int err = 0, ret; socklen_t len; bdaddr_t src, dst; if (cond & G_IO_NVAL) return FALSE; len = sizeof(ret); if (getsockopt(io_ctxt->fd, SOL_SOCKET, SO_ERROR, &ret, &len) < 0) { err = -errno; goto done; } if (ret != 0) { err = -ret; goto done; } if (io_ctxt->resolver) { err = io_ctxt->resolver(io_ctxt->fd, io->src, io->dst); if (err < 0) goto done; } io_ctxt->io = NULL;done: if (io_ctxt->func) io_ctxt->func(io, err, gio, io_ctxt->user_data); if (io_ctxt->cb) { str2ba(io->src, &src); str2ba(io->dst, &dst); io_ctxt->cb(gio, err, &src, &dst, io_ctxt->user_data); } if (io_ctxt->io) { g_io_channel_close(io_ctxt->io); g_io_channel_unref(io_ctxt->io); } g_free(io_ctxt); return FALSE;}static int transport_connect(BtIO *io, struct sockaddr *addr, socklen_t addrlen){ struct io_context *io_ctxt = io->io_ctxt; int err; io_ctxt->io = g_io_channel_unix_new(io_ctxt->fd); if (!io_ctxt->io) return -ENOMEM; err = g_io_channel_set_flags(io_ctxt->io, G_IO_FLAG_NONBLOCK, NULL); if (err != G_IO_STATUS_NORMAL) return -EPERM; err = connect(io_ctxt->fd, addr, addrlen); if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) return -errno; g_io_add_watch(io_ctxt->io, G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL, (GIOFunc) connect_cb, io); return 0;}static BtIOError sco_connect(BtIO *io, BtIOFunc func){ struct io_context *io_ctxt = io->io_ctxt; struct sockaddr_sco addr; int sk, err; io_ctxt->func = func; sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO); if (sk < 0) return -errno; memset(&addr, 0, sizeof(addr)); addr.sco_family = AF_BLUETOOTH; str2ba(io->src, &addr.sco_bdaddr); err = bind(sk, (struct sockaddr *) &addr, sizeof(addr)); if (err < 0) { close(sk); return BT_IO_FAILED; } io_ctxt->fd = sk; memset(&addr, 0, sizeof(addr)); addr.sco_family = AF_BLUETOOTH; str2ba(io->dst, &addr.sco_bdaddr); err = transport_connect(io, (struct sockaddr *) &addr, sizeof(addr)); if (err < 0) { close(sk); return BT_IO_FAILED; } return BT_IO_SUCCESS;}static int l2cap_bind(struct io_context *io_ctxt, const char *address, uint16_t psm, uint16_t mtu, uint32_t flags, struct sockaddr_l2 *addr){ int err; struct l2cap_options l2o; struct sockaddr_l2 l2a; io_ctxt->fd = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); if (io_ctxt->fd < 0) return -errno; if (mtu) { socklen_t olen = sizeof(l2o); memset(&l2o, 0, olen); getsockopt(io_ctxt->fd, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &olen); l2o.imtu = l2o.omtu = mtu; setsockopt(io_ctxt->fd, SOL_L2CAP, L2CAP_OPTIONS, &l2o, sizeof(l2o)); } if (flags) { int opt = flags; err = setsockopt(io_ctxt->fd, SOL_L2CAP, L2CAP_LM, &opt, sizeof(opt)); if (err < 0) { close(io_ctxt->fd); return -errno; } } memset(addr, 0, sizeof(*addr)); addr->l2_family = AF_BLUETOOTH; str2ba(address, &l2a.l2_bdaddr); addr->l2_psm = htobs(psm); err = bind(io_ctxt->fd, (struct sockaddr *) addr, sizeof(*addr)); if (err < 0) { close(io_ctxt->fd); return -errno; } return 0;}static BtIOError l2cap_listen(BtIO *io, BtIOFunc func){ struct io_context *io_ctxt = io->io_ctxt; struct sockaddr_l2 addr; BtIOError err; io_ctxt->func = func; err = l2cap_bind(io_ctxt, io->src, io->psm, io->mtu, io->flags, &addr); if (err < 0) return err; err = transport_listen(io); if (err < 0) { close(io_ctxt->fd); return err; } return BT_IO_SUCCESS;}static BtIOError l2cap_connect(BtIO *io, BtIOFunc func){ struct io_context *io_ctxt = io->io_ctxt; struct sockaddr_l2 l2a; BtIOError err; io_ctxt->func = func; err = l2cap_bind(io_ctxt, io->src, 0, io->mtu, 0, &l2a); if (err < 0) return err; memset(&l2a, 0, sizeof(l2a)); l2a.l2_family = AF_BLUETOOTH; str2ba(io->dst, &l2a.l2_bdaddr); l2a.l2_psm = htobs(io->psm); err = transport_connect(io, (struct sockaddr *) &l2a, sizeof(l2a)); if (err < 0) { close(io_ctxt->fd); return err; } return BT_IO_SUCCESS;}static BtIOError rfcomm_bind(struct io_context *io_ctxt, const char *address, uint8_t channel, uint32_t flags, struct sockaddr_rc *addr){ BtIOError err; io_ctxt->fd = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); if (io_ctxt->fd < 0) return BT_IO_FAILED; if (flags) { int opt = flags; err = setsockopt(io_ctxt->fd, SOL_RFCOMM, RFCOMM_LM, &opt, sizeof(opt)); if (err < 0) { close(io_ctxt->fd); return BT_IO_FAILED; } } memset(addr, 0, sizeof(*addr)); addr->rc_family = AF_BLUETOOTH; str2ba(address, &addr->rc_bdaddr); addr->rc_channel = channel; err = bind(io_ctxt->fd, (struct sockaddr *) addr, sizeof(*addr)); if (err < 0) { close(io_ctxt->fd); return BT_IO_FAILED; } return BT_IO_SUCCESS;}static BtIOError rfcomm_listen(BtIO *io, BtIOFunc func){ struct io_context *io_ctxt = io->io_ctxt; struct sockaddr_rc addr; socklen_t sa_len; BtIOError err; io_ctxt->func = func; err = rfcomm_bind(io_ctxt, io->src, io->channel, io->flags, &addr); if (err < 0) return err; err = transport_listen(io); if (err < 0) { close(io_ctxt->fd); return err; } sa_len = sizeof(struct sockaddr_rc); memset(&addr, 0, sizeof(addr)); if (getsockname(io_ctxt->fd, (struct sockaddr *) &addr, &sa_len) < 0) { err = -errno; close(io_ctxt->fd); return err; } io->channel = addr.rc_channel; return BT_IO_SUCCESS;}static BtIOError rfcomm_connect(BtIO *io, BtIOFunc func){ struct io_context *io_ctxt = io->io_ctxt; struct sockaddr_rc addr; BtIOError err; io_ctxt->func = func; err = rfcomm_bind(io_ctxt, io->src, 0, 0, &addr); if (err < 0) return err; memset(&addr, 0, sizeof(addr)); addr.rc_family = AF_BLUETOOTH; str2ba(io->dst, &addr.rc_bdaddr); addr.rc_channel = io->channel; err = transport_connect(io, (struct sockaddr *) &addr, sizeof(addr)); if (err < 0) { close(io_ctxt->fd); return err; } return BT_IO_SUCCESS;}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;}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; 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 + -