/* * listen for our device */ static int bthidev_listen(struct bthidev_softc *sc) { struct sockaddr_bt sa; int err; memset(&sa, 0, sizeof(sa)); sa.bt_len = sizeof(sa); sa.bt_family = AF_BLUETOOTH; bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr); /* * Listen on control PSM */ err = l2cap_attach(&sc->sc_ctl_l, &bthidev_ctl_proto, sc); if (err) return err; err = l2cap_setopt(sc->sc_ctl_l, &sc->sc_mode); if (err) return err; sa.bt_psm = sc->sc_ctlpsm; err = l2cap_bind(sc->sc_ctl_l, &sa); if (err) return err; err = l2cap_listen(sc->sc_ctl_l); if (err) return err; /* * Listen on interrupt PSM */ err = l2cap_attach(&sc->sc_int_l, &bthidev_int_proto, sc); if (err) return err; err = l2cap_setopt(sc->sc_int_l, &sc->sc_mode); if (err) return err; sa.bt_psm = sc->sc_intpsm; err = l2cap_bind(sc->sc_int_l, &sa); if (err) return err; err = l2cap_listen(sc->sc_int_l); if (err) return err; sc->sc_state = BTHID_WAIT_CTL; return 0; }
static void bthidev_ctl_connected(void *arg) { struct sockaddr_bt sa; struct bthidev_softc *sc = arg; int err; if (sc->sc_state != BTHID_WAIT_CTL) return; KASSERT(sc->sc_ctl != NULL); KASSERT(sc->sc_int == NULL); if (sc->sc_flags & BTHID_CONNECTING) { /* initiate connect on interrupt PSM */ err = l2cap_attach(&sc->sc_int, &bthidev_int_proto, sc); if (err) goto fail; err = l2cap_setopt(sc->sc_int, &sc->sc_mode); if (err) goto fail; memset(&sa, 0, sizeof(sa)); sa.bt_len = sizeof(sa); sa.bt_family = AF_BLUETOOTH; bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr); err = l2cap_bind(sc->sc_int, &sa); if (err) goto fail; sa.bt_psm = sc->sc_intpsm; bdaddr_copy(&sa.bt_bdaddr, &sc->sc_raddr); err = l2cap_connect(sc->sc_int, &sa); if (err) goto fail; } sc->sc_state = BTHID_WAIT_INT; return; fail: l2cap_detach(&sc->sc_ctl); sc->sc_ctl = NULL; aprint_error_dev(sc->sc_dev, "connect failed (%d)\n", err); }
/* * l2cap_ctloutput(request, socket, level, optname, opt) * * Apply configuration commands to channel. This corresponds to * "Reconfigure Channel Request" in the L2CAP specification. */ int l2cap_ctloutput(int req, struct socket *so, int level, int optname, struct mbuf **opt) { struct l2cap_channel *pcb = so->so_pcb; struct mbuf *m; int err = 0; #ifdef notyet /* XXX */ DPRINTFN(2, "%s\n", prcorequests[req]); #endif if (pcb == NULL) return EINVAL; if (level != BTPROTO_L2CAP) { err = EINVAL; if (req == PRCO_SETOPT && *opt) m_free(*opt); } else switch(req) { case PRCO_GETOPT: m = m_get(M_WAIT, MT_SOOPTS); m->m_len = l2cap_getopt(pcb, optname, mtod(m, void *)); if (m->m_len == 0) { m_freem(m); m = NULL; err = ENOPROTOOPT; } *opt = m; break; case PRCO_SETOPT: m = *opt; err = l2cap_setopt(pcb, optname, m); m_freem(m); break; default: err = ENOPROTOOPT; break; } return err; }
/* * start connecting to our device */ static int bthidev_connect(struct bthidev_softc *sc) { struct sockaddr_bt sa; int err; if (sc->sc_attempts++ > 0) aprint_verbose_dev(sc->sc_dev, "connect (#%d)\n", sc->sc_attempts); memset(&sa, 0, sizeof(sa)); sa.bt_len = sizeof(sa); sa.bt_family = AF_BLUETOOTH; err = l2cap_attach_pcb(&sc->sc_ctl, &bthidev_ctl_proto, sc); if (err) { aprint_error_dev(sc->sc_dev, "l2cap_attach failed (%d)\n", err); return err; } err = l2cap_setopt(sc->sc_ctl, &sc->sc_mode); if (err) { aprint_error_dev(sc->sc_dev, "l2cap_setopt failed (%d)\n", err); return err; } bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr); err = l2cap_bind_pcb(sc->sc_ctl, &sa); if (err) { aprint_error_dev(sc->sc_dev, "l2cap_bind_pcb failed (%d)\n", err); return err; } sa.bt_psm = sc->sc_ctlpsm; bdaddr_copy(&sa.bt_bdaddr, &sc->sc_raddr); err = l2cap_connect_pcb(sc->sc_ctl, &sa); if (err) { aprint_error_dev(sc->sc_dev, "l2cap_connect_pcb failed (%d)\n", err); return err; } sc->sc_state = BTHID_WAIT_CTL; return 0; }