tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: btuart and SOCKET Bluetooth CF



On Sat, 23 Jan 2010, KIYOHARA Takashi wrote:

> > But, we already have a method (TIOCSLINED, "btuart") to select the line
> > protocol and the autoconf glue is small. So, I think adding this layer
> > becomes complex for no good reason.
>
> hmm... No one participates in this discussion... ;-<

sometimes that is a good thing :)

> > Ultimately, for this method I think the attach phase becomes subject to
> > race conditions. There is a time between (TIOCSLINED, "btuart") and
> > (BTUART_SELECT_PROTOCOL, DTL) when the driver can not know what to do with
> > received data, which it must process. If you throw it away you risk
> > becoming out of sync with no way to resync. You can add more complexity to
> > handle this..  but I prefer simplicity.
>
> NOKIA DTL doesn't act until our bt-pkt is received in the initial state.

Of course, other devices using btuart driver may not work this way..

> Also we can reset its state by MODEM Control Register.

Perhaps this is also possible with other devices, I fear little is known
about device capabilities when reverse engineering is the only method to
discover their specifications..

> I made new btuart.c.

Now it becomes better. (but please use .l_name = "btdtl")

However, I'm not sure if it is permitted to use cfdata->cf_flags in this
manner?  There seem to be some rare instances of similar use but there is
no mention in the API specification..

> In my opinion, that it is foolish to create btdtl.c.

Mmm, perhaps it is not necessary and I could consent to this lack.

In this direction, I can suggest some optimisation?  diff is attached
(needs some work, is only general cut and paste)

regards,
iain
--- btuart.c.orig       2010-01-23 17:27:34.000000000 +0000
+++ btuart.c    2010-01-23 17:42:05.000000000 +0000
@@ -51,13 +51,11 @@
 
 #include "ioconf.h"
 
-#define BTUART_TYPE_DEFAULT    0
-#define BTUART_TYPE_DTL                1
-
 struct btuart_softc {
        device_t        sc_dev;
        struct tty *    sc_tp;          /* tty pointer */
 
+       bool            sc_dtl;         /* using Nokia DTL headers */
        bool            sc_enabled;     /* device is enabled */
        struct hci_unit *sc_unit;       /* Bluetooth HCI handle */
        struct bt_stats sc_stats;
@@ -114,10 +112,7 @@
 static void btuart_output_sco(device_t, struct mbuf *);
 static void btuart_stats(device_t, struct bt_stats *, int);
 
-static int btuart_dtl_input(int, struct tty *);
-static void btuart_dtl_output_cmd(device_t, struct mbuf *);
-static void btuart_dtl_output_acl(device_t, struct mbuf *);
-static void btuart_dtl_output_sco(device_t, struct mbuf *);
+static int btuart_dtlwrap(struct mbuf *);
 
 /*
  * It doesn't need to be exported, as only btuartattach() uses it,
@@ -138,14 +133,15 @@
        .l_modem =      ttymodem,
        .l_poll =       ttyerrpoll,
 };
-static struct linesw btuart_dtl_disc = {
-       .l_name =       "dtl",
+
+static struct linesw btdtl_disc = {
+       .l_name =       "btdtl",
        .l_open =       btuartopen,
        .l_close =      btuartclose,
        .l_read =       ttyerrio,
        .l_write =      ttyerrio,
        .l_ioctl =      btuartioctl,
-       .l_rint =       btuart_dtl_input,
+       .l_rint =       btuartinput,
        .l_start =      btuartstart,
        .l_modem =      ttymodem,
        .l_poll =       ttyerrpoll,
@@ -160,15 +156,6 @@
        .get_stats =    btuart_stats,
        .ipl =          IPL_TTY,
 };
-static const struct hci_if btuart_dtl_hci = {
-       .enable =       btuart_enable,
-       .disable =      btuart_disable,
-       .output_cmd =   btuart_dtl_output_cmd,
-       .output_acl =   btuart_dtl_output_acl,
-       .output_sco =   btuart_dtl_output_sco,
-       .get_stats =    btuart_stats,
-       .ipl =          IPL_TTY,
-};
 
 /*****************************************************************************
  *
@@ -189,7 +176,7 @@
                    "error = %d\n", btuart_cd.cd_name, error);
                goto fail0;
        }
-       error = ttyldisc_attach(&btuart_dtl_disc);
+       error = ttyldisc_attach(&btdtl_disc);
        if (error) {
                aprint_error("%s: unable to register line discipline (DTL), "
                    "error = %d\n", btuart_cd.cd_name, error);
@@ -206,7 +193,7 @@
 
 fail2:
        config_cfdriver_detach(&btuart_cd);
-       (void) ttyldisc_detach(&btuart_dtl_disc);
+       (void) ttyldisc_detach(&btdtl_disc);
 fail1:
        (void) ttyldisc_detach(&btuart_disc);
 fail0:
@@ -234,7 +221,6 @@
 {
        struct btuart_softc *sc = device_private(self);
        cfdata_t cfdata = device_cfdata(self);
-       const struct hci_if *hci_if;
 
        sc->sc_dev = self;
 
@@ -243,11 +229,7 @@
        MBUFQ_INIT(&sc->sc_scoq);
 
        /* Attach Bluetooth unit */
-       if (cfdata->cf_flags == BTUART_TYPE_DTL)
-               hci_if = &btuart_dtl_hci;
-       else
-               hci_if = &btuart_hci;
-       sc->sc_unit = hci_attach(hci_if, self, 0);
+       sc->sc_unit = hci_attach(&btuart_hci, self, 0);
        if (sc->sc_unit == NULL)
                aprint_error_dev(self, "HCI attach failed\n");
 }
@@ -293,7 +275,7 @@
        s = spltty();
 
        if (tp->t_linesw == &btuart_disc ||
-           tp->t_linesw == &btuart_dtl_disc) {
+           tp->t_linesw == &btdtl_disc) {
                sc = tp->t_sc;
                if (sc != NULL) {
                        splx(s);
@@ -312,11 +294,6 @@
        cfdata->cf_atname = btuart_cd.cd_name;
        cfdata->cf_unit = unit;
        cfdata->cf_fstate = FSTATE_STAR;
-       if (tp->t_linesw == &btuart_dtl_disc)
-               cfdata->cf_flags = BTUART_TYPE_DTL;
-       else
-               cfdata->cf_flags = BTUART_TYPE_DEFAULT;
-cfdata->cf_flags = BTUART_TYPE_DTL;
 
        dev = config_attach_pseudo(cfdata);
        if (dev == NULL) {
@@ -330,6 +307,9 @@
            (unsigned long long)major(tp->t_dev),
            (unsigned long long)minor(tp->t_dev));
 
+       if (tp->t_linesw == &btdtl_disc)
+               sc->sc_dtl = true;
+
        sc->sc_tp = tp;
        tp->t_sc = sc;
 
@@ -425,8 +405,13 @@
                        m->m_pkthdr.len = m->m_len = 0;
                        space = MHLEN;
 
-                       sc->sc_state = BTUART_RECV_PKT_TYPE;
-                       sc->sc_want = 1;
+                       if (sc->sc_dtl) {
+                               sc->sc_state = BTUART_RECV_DTL_HEADER;
+                               sc->sc_want = sizeof(struct btdtl_header);
+                       } else {
+                               sc->sc_state = BTUART_RECV_PKT_TYPE;
+                               sc->sc_want = 1;
+                       }
                } else {
                        /* extend mbuf */
                        MGET(m->m_next, M_DONTWAIT, MT_DATA);
@@ -486,6 +471,37 @@
 
                break;
 
+       case BTUART_RECV_DTL_HEADER:    /* Got Nokia DTL header */
+
+               switch (c) {
+               case BTUART_DTL_HEADER_TYPE:
+                       sc->sc_state = BTUART_RECV_DTL_CTRL_DATA;
+                       break;
+
+               case BTUART_DTL_HEADER_TYPE | HCI_ACL_DATA_PKT:
+                       sc->sc_state = BTUART_RECV_DTL_ACL_DATA;
+                       break;
+
+               case BTUART_DTL_HEADER_TYPE | HCI_SCO_DATA_PKT:
+                       sc->sc_state = BTUART_RECV_DTL_SCO_DATA;
+                       break;
+
+               case BTUART_DTL_HEADER_TYPE | HCI_EVENT_PKT:
+                       sc->sc_state = BTUART_RECV_DTL_EVENT_DATA;
+                       break;
+
+               default:
+                       aprint_error_dev(sc->sc_dev,
+                           "Unknown packet type=%#x!\n", dtlh->type);
+                       sc->sc_stats.err_rx++;
+                       m_adj(m, 1);
+                       sc->sc_want++;          /* (lost sync) try more 1byte */
+                       return 0;
+               }
+               dtlh->len = le16toh(dtlh->len);
+               sc->sc_want = (dtlh->len + 1) & ~0x0001;
+               break;
+
        /*
         * we assume (correctly of course :) that the packet headers all fit
         * into a single pkthdr mbuf
@@ -506,6 +522,20 @@
                sc->sc_want = mtod(m, hci_event_hdr_t *)->length;
                break;
 
+       case BTUART_RECV_DTL_CTRL_DATA: /* Control Packet Complete */
+               btuart_dump(sc->sc_dev, sc->sc_rxp);
+               m_freem(sc->sc_rxp);
+               sc->sc_rxp = NULL;
+               break;
+
+       case BTUART_RECV_DTL_ACL_DATA:  /* ACL Packet Complete */
+               if (dtlh->len & 0x0001)
+                       m_adj(m, -1);
+               m_adj(sc->sc_rxp,
+                   sizeof(struct btuart_dtl_header) - sizeof(uint8_t));
+               *mtod(sc->sc_rxp, uint8_t *) = HCI_ACL_DATA_PKT;
+
+               /* FALLTHROUGH */
        case BTUART_RECV_ACL_DATA:      /* ACL Packet Complete */
                if (!hci_input_acl(sc->sc_unit, sc->sc_rxp))
                        sc->sc_stats.err_rx++;
@@ -514,6 +544,14 @@
                sc->sc_rxp = NULL;
                break;
 
+       case BTUART_RECV_DTL_SCO_DATA:  /* SCO Packet Complete */
+               if (dtlh->len & 0x0001)
+                       m_adj(m, -1);
+               m_adj(sc->sc_rxp,
+                   sizeof(struct btuart_dtl_header) - sizeof(uint8_t));
+               *mtod(sc->sc_rxp, uint8_t *) = HCI_SCO_DATA_PKT;
+
+               /* FALLTHROUGH */
        case BTUART_RECV_SCO_DATA:      /* SCO Packet Complete */
                if (!hci_input_sco(sc->sc_unit, sc->sc_rxp))
                        sc->sc_stats.err_rx++;
@@ -522,6 +560,14 @@
                sc->sc_rxp = NULL;
                break;
 
+       case BTUART_RECV_DTL_EVENT_DATA:/* Event Packet Complete */
+               if (dtlh->len & 0x0001)
+                       m_adj(m, -1);
+               m_adj(sc->sc_rxp,
+                   sizeof(struct btuart_dtl_header) - sizeof(uint8_t));
+               *mtod(sc->sc_rxp, uint8_t *) = HCI_EVENT_PKT;
+
+               /* FALLTHROUGH */
        case BTUART_RECV_EVENT_DATA:    /* Event Packet Complete */
                if (!hci_input_event(sc->sc_unit, sc->sc_rxp))
                        sc->sc_stats.err_rx++;
@@ -671,6 +717,9 @@
 
        KASSERT(sc->sc_enabled);
 
+       if (sc->sc_dtl && !btuart_dtlwrap(m))
+               return;
+
        M_SETCTX(m, NULL);
 
        s = spltty();
@@ -689,6 +738,9 @@
 
        KASSERT(sc->sc_enabled);
 
+       if (sc->sc_dtl && !btuart_dtlwrap(m))
+               return;
+
        M_SETCTX(m, NULL);
 
        s = spltty();
@@ -707,6 +759,9 @@
 
        KASSERT(sc->sc_enabled);
 
+       if (sc->sc_dtl && !btuart_dtlwrap(m))
+               return;
+
        s = spltty();
        MBUFQ_ENQUEUE(&sc->sc_scoq, m);
        if (!sc->sc_xmit)
@@ -731,254 +786,37 @@
        splx(s);
 }
 
-
 /*
- * NOKIA DTL-1/4 functions
+ * wrap mbuf with Nokia DTL-1/4 header
  */
-
-static int
-btuart_dtl_input(int c, struct tty *tp)
+static bool
+btdtl_wrap(struct mbuf *m)
 {
-       struct btuart_softc *sc = tp->t_sc;
-       struct mbuf *m = sc->sc_rxp;
-       struct btuart_dtl_header *dtlh;
-       int space = 0;
-
-       if (!sc->sc_enabled)
-               return 0;
-
-       c &= TTY_CHARMASK;
-
-       /* If we already started a packet, find the trailing end of it. */
-       if (m) {
-               while (m->m_next)
-                       m = m->m_next;
-
-               space = M_TRAILINGSPACE(m);
-       }
-
-       if (space == 0) {
-               if (m == NULL) {
-                       /* new packet */
-                       MGETHDR(m, M_DONTWAIT, MT_DATA);
-                       if (m == NULL) {
-                               aprint_error_dev(sc->sc_dev, "out of memory\n");
-                               sc->sc_stats.err_rx++;
-                               return 0;       /* (lost sync) */
-                       }
-
-                       sc->sc_rxp = m;
-                       m->m_pkthdr.len = m->m_len = 0;
-                       space = MHLEN;
-
-                       sc->sc_state = BTUART_RECV_DTL_HDR;
-                       sc->sc_want = sizeof(struct btuart_dtl_header);
-               } else {
-                       /* extend mbuf */
-                       MGET(m->m_next, M_DONTWAIT, MT_DATA);
-                       if (m->m_next == NULL) {
-                               aprint_error_dev(sc->sc_dev, "out of memory\n");
-                               sc->sc_stats.err_rx++;
-                               return 0;       /* (lost sync) */
-                       }
-
-                       m = m->m_next;
-                       m->m_len = 0;
-                       space = MLEN;
-
-                       if (sc->sc_want > MINCLSIZE) {
-                               MCLGET(m, M_DONTWAIT);
-                               if (m->m_flags & M_EXT)
-                                       space = MCLBYTES;
-                       }
-               }
-       }
-
-       mtod(m, uint8_t *)[m->m_len++] = c;
-       sc->sc_rxp->m_pkthdr.len++;
-       sc->sc_stats.byte_rx++;
-
-       sc->sc_want--;
-       if (sc->sc_want > 0)
-               return 0;       /* want more */
-
-       dtlh = mtod(sc->sc_rxp, struct btuart_dtl_header *);
-       switch (sc->sc_state) {
-       case BTUART_RECV_DTL_HDR:       /* Got DTL header */
-               switch (c) {
-               case BTUART_DTL_HEADER_TYPE:
-                       sc->sc_state = BTUART_RECV_DTL_CTRL_DATA;
-                       break;
-
-               case BTUART_DTL_HEADER_TYPE | HCI_ACL_DATA_PKT:
-                       sc->sc_state = BTUART_RECV_DTL_ACL_DATA;
-                       break;
-
-               case BTUART_DTL_HEADER_TYPE | HCI_SCO_DATA_PKT:
-                       sc->sc_state = BTUART_RECV_DTL_SCO_DATA;
-                       break;
-
-               case BTUART_DTL_HEADER_TYPE | HCI_EVENT_PKT:
-                       sc->sc_state = BTUART_RECV_DTL_EVENT_DATA;
-                       break;
-
-               default:
-                       aprint_error_dev(sc->sc_dev,
-                           "Unknown packet type=%#x!\n", dtlh->type);
-                       sc->sc_stats.err_rx++;
-                       m_adj(m, 1);
-                       sc->sc_want++;          /* (lost sync) try more 1byte */
-                       return 0;
+       struct btdtl_header *hdr;
+       size_t len;
+       uint8_t type;
+       const uint8_t pad = 0;
+
+       m_copydata(m, 0, sizeof(type), &type);
+       m_adj(m, sizeof(type));
+
+       len = m->m_pkthdr.len;
+       if (len & 0x0001) {     /* Add padding */
+               m_copyback(m, len, 1, &pad);
+               if (m->m_pkthdr.len != len + 1) {
+                       m_freem(m);
+                       return false;
                }
-               dtlh->len = le16toh(dtlh->len);
-               sc->sc_want = (dtlh->len + 1) & ~0x0001;
-               break;
-
-       /*
-        * we assume (correctly of course :) that the packet headers all fit
-        * into a single pkthdr mbuf
-        */
-       case BTUART_RECV_DTL_CTRL_DATA: /* Control Packet Complete */
-       {
-               int i;
-
-               aprint_normal_dev(sc->sc_dev, "Control Packet received:");
-               for (i = 0; i < dtlh->len && i < m->m_len - sizeof(*dtlh); i++)
-                       aprint_normal(" %02x",
-                           mtod(sc->sc_rxp, uint8_t *)[sizeof(*dtlh) + i]);
-               if (i < dtlh->len)
-                       aprint_normal("(more %dbyte%s)",
-                           dtlh->len - i, dtlh->len - i > 1 ? "s" : "");
-               aprint_normal("\n");
-               m_freem(sc->sc_rxp);
-               sc->sc_rxp = NULL;
-               break;
-       }
-
-       case BTUART_RECV_DTL_ACL_DATA:  /* ACL Packet Complete */
-               if (dtlh->len & 0x0001)
-                       m_adj(m, -1);
-               m_adj(sc->sc_rxp,
-                   sizeof(struct btuart_dtl_header) - sizeof(uint8_t));
-               *mtod(sc->sc_rxp, uint8_t *) = HCI_ACL_DATA_PKT;
-               if (!hci_input_acl(sc->sc_unit, sc->sc_rxp))
-                       sc->sc_stats.err_rx++;
-
-               sc->sc_stats.acl_rx++;
-               sc->sc_rxp = NULL;
-               break;
-
-       case BTUART_RECV_DTL_SCO_DATA:  /* SCO Packet Complete */
-               if (dtlh->len & 0x0001)
-                       m_adj(m, -1);
-               m_adj(sc->sc_rxp,
-                   sizeof(struct btuart_dtl_header) - sizeof(uint8_t));
-               *mtod(sc->sc_rxp, uint8_t *) = HCI_SCO_DATA_PKT;
-               if (!hci_input_sco(sc->sc_unit, sc->sc_rxp))
-                       sc->sc_stats.err_rx++;
-
-               sc->sc_stats.sco_rx++;
-               sc->sc_rxp = NULL;
-               break;
-
-       case BTUART_RECV_DTL_EVENT_DATA:/* Event Packet Complete */
-               if (dtlh->len & 0x0001)
-                       m_adj(m, -1);
-               m_adj(sc->sc_rxp,
-                   sizeof(struct btuart_dtl_header) - sizeof(uint8_t));
-               *mtod(sc->sc_rxp, uint8_t *) = HCI_EVENT_PKT;
-               if (!hci_input_event(sc->sc_unit, sc->sc_rxp))
-                       sc->sc_stats.err_rx++;
-
-               sc->sc_stats.evt_rx++;
-               sc->sc_rxp = NULL;
-               break;
-
-       default:
-               panic("%s: invalid state %d!\n",
-                   device_xname(sc->sc_dev), sc->sc_state);
        }
-       return 0;
-}
 
-static void
-btuart_dtl_output_cmd(device_t self, struct mbuf *m)
-{
-       struct btuart_softc *sc = device_private(self);
-       struct btuart_dtl_header *dtlh;
-       int s;
+       M_PREPEND(m, sizeof(struct btdtl_header), M_DONTWAIT);
+       if (m == NULL)
+               return false;
+
+       hdr = mtod(m, struct btdtl_header *);
+       hdr->type = type | BTDTL_HEADER_TYPE;
+       hdr->rsvd = 0;
+       hdr->len = htole16(len);
 
-       KASSERT(sc->sc_enabled);
-
-       m_adj(m, sizeof(uint8_t));      /* remove hci_cmd_hdr_t's type */
-       M_PREPEND(m, sizeof(struct btuart_dtl_header), M_WAITOK);
-       dtlh = mtod(m, struct btuart_dtl_header *);
-       dtlh->type = HCI_CMD_PKT | BTUART_DTL_HEADER_TYPE;
-       dtlh->rsvd = 0;
-       dtlh->len = m->m_pkthdr.len - sizeof(struct btuart_dtl_header);
-       if (m->m_pkthdr.len & 0x1)
-               m_copyback(m, m->m_pkthdr.len, 1, &dtlh->rsvd); /* Add pad */
-
-       M_SETCTX(m, NULL);
-
-       s = spltty();
-       MBUFQ_ENQUEUE(&sc->sc_cmdq, m);
-       if (!sc->sc_xmit)
-               btuartstart(sc->sc_tp);
-
-       splx(s);
-}
-
-static void
-btuart_dtl_output_acl(device_t self, struct mbuf *m)
-{
-       struct btuart_softc *sc = device_private(self);
-       struct btuart_dtl_header *dtlh;
-       int s;
-
-       KASSERT(sc->sc_enabled);
-
-       m_adj(m, sizeof(uint8_t));      /* remove hci_acldata_hdr_t's type */
-       M_PREPEND(m, sizeof(struct btuart_dtl_header), M_WAITOK);
-       dtlh = mtod(m, struct btuart_dtl_header *);
-       dtlh->type = HCI_ACL_DATA_PKT | BTUART_DTL_HEADER_TYPE;
-       dtlh->rsvd = 0;
-       dtlh->len = m->m_pkthdr.len - sizeof(struct btuart_dtl_header);
-       if (m->m_pkthdr.len & 0x1)
-               m_copyback(m, m->m_pkthdr.len, 1, &dtlh->rsvd); /* Add pad */
-
-       M_SETCTX(m, NULL);
-
-       s = spltty();
-       MBUFQ_ENQUEUE(&sc->sc_aclq, m);
-       if (!sc->sc_xmit)
-               btuartstart(sc->sc_tp);
-
-       splx(s);
-}
-
-static void
-btuart_dtl_output_sco(device_t self, struct mbuf *m)
-{
-       struct btuart_softc *sc = device_private(self);
-       struct btuart_dtl_header *dtlh;
-       int s;
-
-       KASSERT(sc->sc_enabled);
-
-       m_adj(m, sizeof(uint8_t));      /* remove hci_scodata_hdr_t's type */
-       M_PREPEND(m, sizeof(struct btuart_dtl_header), M_WAITOK);
-       dtlh = mtod(m, struct btuart_dtl_header *);
-       dtlh->type = HCI_SCO_DATA_PKT | BTUART_DTL_HEADER_TYPE;
-       dtlh->rsvd = 0;
-       dtlh->len = m->m_pkthdr.len - sizeof(struct btuart_dtl_header);
-       if (m->m_pkthdr.len & 0x1)
-               m_copyback(m, m->m_pkthdr.len, 1, &dtlh->rsvd); /* Add pad */
-
-       s = spltty();
-       MBUFQ_ENQUEUE(&sc->sc_scoq, m);
-       if (!sc->sc_xmit)
-               btuartstart(sc->sc_tp);
-
-       splx(s);
+       return true;
 }


Home | Main Index | Thread Index | Old Index