tech-kern archive

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

Re: btuart and SOCKET Bluetooth CF



Hi! Iain,


From: Iain Hibbert <plunky%rya-online.net@localhost>
Date: Wed, 17 Feb 2010 10:12:28 +0000 (GMT)

> On Tue, 16 Feb 2010, KIYOHARA Takashi wrote:
> 
>  /* sc_state */
> -#define BTUART_RECV_PKT_TYPE 0       /* packet type */
> +enum state {
> +     BTUART_RECV_PKT_TYPE,           /* packet type */
> 
> please don't make this unrelated change. I don't like it because sc_state
> should really become "enum state" rather than int but then you need to add
> forward declarations..

It relates.
I have increased the value for DTL.  However, this value doesn't have
the meaning.  And, this is not used to calculate.  Then, I think that
the enum that should not consider the value is more convenient.  There
is danger of defining the same value for the macro.


> (btw, no comma is permitted on final enum values)

This is because of convenient for the addition in the future.  The diff
becomes smaller.  ;-)


> --- btattach.c        6 Dec 2009 12:55:46 -0000       1.5
> +++ btattach.c        16 Feb 2010 03:28:53 -0000
> @@ -54,13 +54,6 @@

 :

> This is unrelated, and I did it just now..

Thanks.



> +static int
> +btuart_dtl_probe(dev_t dev)
> +{
> +#if NCOM > 0

   :

> +#endif
> +     return 0;
> +}
> 
> I really dislike this function, it depends on internals of com driver [btw
> COMUNIT(x) would be (minor(x) & COMUNIT_MASK)] and pcmcia and using this
> method prevents a soft emulator and/or needs kernel modifications to
> handle any new device.

We are expecting the minor number to be obtained.  In my opinion, it is
necessary to open() the device node for that.  Therefore, only minor()
is called.  It thinks dependence on the structure of pcmcia(4) for other
way not to exist though it is very regrettable.  ;-<

Thanks,
--
kiyohara
Index: btuart.c
===================================================================
RCS file: /cvsroot/src/sys/dev/bluetooth/btuart.c,v
retrieving revision 1.24
diff -u -r1.24 btuart.c
--- btuart.c    18 Feb 2010 07:24:16 -0000      1.24
+++ btuart.c    18 Feb 2010 07:30:01 -0000
@@ -1,7 +1,7 @@
 /*     $NetBSD: btuart.c,v 1.24 2010/02/18 07:24:16 kiyohara Exp $     */
 
 /*-
- * Copyright (c) 2006, 2007 KIYOHARA Takashi
+ * Copyright (c) 2006, 2007, 2010 KIYOHARA Takashi
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -29,6 +29,8 @@
 #include <sys/cdefs.h>
 __KERNEL_RCSID(0, "$NetBSD: btuart.c,v 1.24 2010/02/18 07:24:16 kiyohara Exp 
$");
 
+#include "com.h"
+
 #include <sys/param.h>
 #include <sys/conf.h>
 #include <sys/device.h>
@@ -49,8 +51,14 @@
 #include <netbt/bluetooth.h>
 #include <netbt/hci.h>
 
+#if NCOM > 0
+#include <dev/pcmcia/pcmciadevs.h>
+#include <dev/pcmcia/pcmciavar.h>
+#endif
+
 #include "ioconf.h"
 
+
 struct btuart_softc {
        device_t        sc_dev;
        struct tty *    sc_tp;          /* tty pointer */
@@ -61,6 +69,7 @@
 
        int             sc_state;       /* receive state */
        int             sc_want;        /* how much we want */
+       bool            sc_pad;         /* pad will receive before next pkt */
        struct mbuf *   sc_rxp;         /* incoming packet */
 
        bool            sc_xmit;        /* transmit is active */
@@ -73,13 +82,25 @@
 };
 
 /* sc_state */
-#define BTUART_RECV_PKT_TYPE   0       /* packet type */
-#define BTUART_RECV_ACL_HDR    1       /* acl header */
-#define BTUART_RECV_SCO_HDR    2       /* sco header */
-#define BTUART_RECV_EVENT_HDR  3       /* event header */
-#define BTUART_RECV_ACL_DATA   4       /* acl packet data */
-#define BTUART_RECV_SCO_DATA   5       /* sco packet data */
-#define BTUART_RECV_EVENT_DATA 6       /* event packet data */
+#define BTUART_RECV_PKT_TYPE           0       /* packet type */
+#define BTUART_RECV_ACL_HDR            1       /* acl header */
+#define BTUART_RECV_SCO_HDR            2       /* sco header */
+#define BTUART_RECV_EVENT_HDR          3       /* event header */
+#define BTUART_RECV_ACL_DATA           4       /* acl packet data */
+#define BTUART_RECV_SCO_DATA           5       /* sco packet data */
+#define BTUART_RECV_EVENT_DATA         6       /* event packet data */
+#define BTUART_RECV_DTL_HDR            7       /* DTL header */
+#define BTUART_RECV_DTL_CTRL_DATA      8       /* DTL control data */
+#define BTUART_RECV_DTL_ACL_DATA       9       /* DTL acl data */
+#define BTUART_RECV_DTL_SCO_DATA       10      /* DTL sco data */
+#define BTUART_RECV_DTL_EVENT_DATA     11      /* DTL event data */
+
+struct btuart_dtl_header {     /* NOKIA DTL-1/4 header */
+       uint8_t type;           /*   packet type */
+       uint8_t rsvd;
+       uint16_t len;           /*   data length */
+} __packed;
+#define BTUART_DTL_HEADER_TYPE 0x80
 
 void btuartattach(int);
 static int btuart_match(device_t, cfdata_t, void *);
@@ -99,12 +120,20 @@
 static void btuart_output_sco(device_t, struct mbuf *);
 static void btuart_stats(device_t, struct bt_stats *, int);
 
+static int btuart_dtl_probe(dev_t);
+static void btuart_dtl_attach(device_t, device_t, void *);
+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 *);
+
 /*
  * It doesn't need to be exported, as only btuartattach() uses it,
  * but there's no "official" way to make it static.
  */
 CFATTACH_DECL_NEW(btuart, sizeof(struct btuart_softc),
     btuart_match, btuart_attach, btuart_detach, NULL);
+CFATTACH_DECL_NEW(btuart_dtl, sizeof(struct btuart_softc),
+    btuart_match, btuart_dtl_attach, btuart_detach, NULL);
 
 static struct linesw btuart_disc = {
        .l_name =       "btuart",
@@ -128,6 +157,15 @@
        .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,
+};
 
 /*****************************************************************************
  *
@@ -155,9 +193,17 @@
                aprint_error("%s: unable to register cfattach, error = %d\n",
                    btuart_cd.cd_name, error);
 
-               config_cfdriver_detach(&btuart_cd);
                (void) ttyldisc_detach(&btuart_disc);
        }
+       error = config_cfattach_attach(btuart_cd.cd_name, &btuart_dtl_ca);
+       if (error) {
+               aprint_error("%s: unable to register cfattach(2), error = %d\n",
+                   btuart_cd.cd_name, error);
+
+               config_cfattach_detach(btuart_cd.cd_name, &btuart_ca);
+               (void) ttyldisc_detach(&btuart_disc);
+       }
+       return;
 }
 
 /*
@@ -187,6 +233,9 @@
        MBUFQ_INIT(&sc->sc_aclq);
        MBUFQ_INIT(&sc->sc_scoq);
 
+       sc->sc_state = BTUART_RECV_PKT_TYPE;
+       sc->sc_want = 1;
+
        /* Attach Bluetooth unit */
        sc->sc_unit = hci_attach(&btuart_hci, self, 0);
        if (sc->sc_unit == NULL)
@@ -218,7 +267,7 @@
  */
 
 static int
-btuartopen(dev_t devno __unused, struct tty *tp)
+btuartopen(dev_t devno, struct tty *tp)
 {
        struct btuart_softc *sc;
        device_t dev;
@@ -249,7 +298,10 @@
                        break;
 
        cfdata->cf_name = btuart_cd.cd_name;
-       cfdata->cf_atname = btuart_cd.cd_name;
+       if (btuart_dtl_probe(devno))
+               cfdata->cf_atname = "btuart_dtl";
+       else
+               cfdata->cf_atname = "btuart";
        cfdata->cf_unit = unit;
        cfdata->cf_fstate = FSTATE_STAR;
 
@@ -348,6 +400,12 @@
 
        if (space == 0) {
                if (m == NULL) {
+                       /* drop padding between packets (for DTL) */
+                       if (sc->sc_pad) {
+                               sc->sc_pad = false;
+                               return 0;
+                       }
+
                        /* new packet */
                        MGETHDR(m, M_DONTWAIT, MT_DATA);
                        if (m == NULL) {
@@ -359,9 +417,6 @@
                        sc->sc_rxp = m;
                        m->m_pkthdr.len = m->m_len = 0;
                        space = MHLEN;
-
-                       sc->sc_state = BTUART_RECV_PKT_TYPE;
-                       sc->sc_want = 1;
                } else {
                        /* extend mbuf */
                        MGET(m->m_next, M_DONTWAIT, MT_DATA);
@@ -433,12 +488,12 @@
 
        case BTUART_RECV_SCO_HDR:       /* Got SCO Header */
                sc->sc_state = BTUART_RECV_SCO_DATA;
-               sc->sc_want =  mtod(m, hci_scodata_hdr_t *)->length;
+               sc->sc_want = mtod(m, hci_scodata_hdr_t *)->length;
                break;
 
        case BTUART_RECV_EVENT_HDR:     /* Got Event Header */
                sc->sc_state = BTUART_RECV_EVENT_DATA;
-               sc->sc_want =  mtod(m, hci_event_hdr_t *)->length;
+               sc->sc_want = mtod(m, hci_event_hdr_t *)->length;
                break;
 
        case BTUART_RECV_ACL_DATA:      /* ACL Packet Complete */
@@ -446,7 +501,9 @@
                        sc->sc_stats.err_rx++;
 
                sc->sc_stats.acl_rx++;
-               sc->sc_rxp = m = NULL;
+               sc->sc_state = BTUART_RECV_PKT_TYPE;
+               sc->sc_want = 1;
+               sc->sc_rxp = NULL;
                break;
 
        case BTUART_RECV_SCO_DATA:      /* SCO Packet Complete */
@@ -454,7 +511,9 @@
                        sc->sc_stats.err_rx++;
 
                sc->sc_stats.sco_rx++;
-               sc->sc_rxp = m = NULL;
+               sc->sc_state = BTUART_RECV_PKT_TYPE;
+               sc->sc_want = 1;
+               sc->sc_rxp = NULL;
                break;
 
        case BTUART_RECV_EVENT_DATA:    /* Event Packet Complete */
@@ -462,7 +521,112 @@
                        sc->sc_stats.err_rx++;
 
                sc->sc_stats.evt_rx++;
-               sc->sc_rxp = m = NULL;
+               sc->sc_state = BTUART_RECV_PKT_TYPE;
+               sc->sc_want = 1;
+               sc->sc_rxp = NULL;
+               break;
+
+       /*
+        * NOKIA DTL-1/4
+        */
+       case BTUART_RECV_DTL_HDR:       /* Got DTL header */
+       {
+               struct btuart_dtl_header *dtlh =
+                   mtod(m, struct btuart_dtl_header *);
+
+               switch (dtlh->type) {
+               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;
+               sc->sc_pad = dtlh->len & 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 */
+       {
+               struct btuart_dtl_header *dtlh =
+                   mtod(sc->sc_rxp, struct btuart_dtl_header *);
+               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_state = BTUART_RECV_DTL_HDR;
+               sc->sc_want = sizeof(struct btuart_dtl_header);
+               sc->sc_rxp = NULL;
+               break;
+       }
+
+       case BTUART_RECV_DTL_ACL_DATA:  /* ACL Packet Complete */
+               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_state = BTUART_RECV_DTL_HDR;
+               sc->sc_want = sizeof(struct btuart_dtl_header);
+               sc->sc_rxp = NULL;
+               break;
+
+       case BTUART_RECV_DTL_SCO_DATA:  /* SCO Packet Complete */
+               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_state = BTUART_RECV_DTL_HDR;
+               sc->sc_want = sizeof(struct btuart_dtl_header);
+               sc->sc_rxp = NULL;
+               break;
+
+       case BTUART_RECV_DTL_EVENT_DATA:/* Event Packet Complete */
+               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_state = BTUART_RECV_DTL_HDR;
+               sc->sc_want = sizeof(struct btuart_dtl_header);
+               sc->sc_rxp = NULL;
                break;
 
        default:
@@ -665,3 +829,187 @@
 
        splx(s);
 }
+
+
+/*
+ * NOKIA DTL-1/4 functions
+ */
+
+static int
+btuart_dtl_probe(dev_t dev)
+{
+#if NCOM > 0
+       struct pcmcia_softc *pcmcia;
+       struct pcmcia_card *card;
+       device_t com;
+       extern struct cdevsw com_cdevsw;
+       struct {
+               uint32_t vendor;
+               uint32_t product;
+       } dtltbl[] = {
+               { PCMCIA_VENDOR_SOCKET, 0x009f },
+       };
+       int i;
+
+       if (major(dev) != cdevsw_lookup_major(&com_cdevsw))
+               return 0;
+
+       com = device_find_by_driver_unit("com", minor(dev));
+       if (device_is_a(device_parent(com), "pcmcia")) {
+               pcmcia = device_private(device_parent(com));
+               card = &pcmcia->card;
+
+               for (i = 0; i < __arraycount(dtltbl); i++)
+                       if (card->manufacturer == dtltbl[i].vendor &&
+                           card->product == dtltbl[i].product)
+                               return 1;
+       }
+#endif
+       return 0;
+}
+
+static void
+btuart_dtl_attach(device_t parent __unused, device_t self, void *aux __unused)
+{
+       struct btuart_softc *sc = device_private(self);
+
+       sc->sc_dev = self;
+
+       MBUFQ_INIT(&sc->sc_cmdq);
+       MBUFQ_INIT(&sc->sc_aclq);
+       MBUFQ_INIT(&sc->sc_scoq);
+
+       sc->sc_state = BTUART_RECV_DTL_HDR;
+       sc->sc_want = sizeof(struct btuart_dtl_header);
+
+       /* Attach Bluetooth unit */
+       sc->sc_unit = hci_attach(&btuart_dtl_hci, self, 0);
+       if (sc->sc_unit == NULL)
+               aprint_error_dev(self, "HCI attach failed\n");
+}
+
+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;
+
+       KASSERT(sc->sc_enabled);
+
+       m_adj(m, sizeof(uint8_t));      /* remove hci_cmd_hdr_t's type */
+
+       dtlh.type = HCI_CMD_PKT | BTUART_DTL_HEADER_TYPE;
+       dtlh.rsvd = 0;
+       dtlh.len = htole16(m->m_pkthdr.len);
+
+       M_PREPEND(m, sizeof(dtlh), M_DONTWAIT);
+       if (m == NULL) {
+               aprint_error_dev(sc->sc_dev, "output CMD failed (head)\n");
+               sc->sc_stats.err_tx++;
+               return;
+       }
+       m_copyback(m, 0, sizeof(dtlh), &dtlh);
+       if (m->m_pkthdr.len & 0x1) {
+               m_copyback(m, m->m_pkthdr.len, 1, &dtlh.rsvd);  /* Add pad */
+               if (m->m_pkthdr.len & 0x1) {
+                       aprint_error_dev(sc->sc_dev,
+                           "output CMD failed (tail)\n");
+                       sc->sc_stats.err_tx++;
+                       return;
+               }
+       }
+
+       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 */
+
+       dtlh.type = HCI_ACL_DATA_PKT | BTUART_DTL_HEADER_TYPE;
+       dtlh.rsvd = 0;
+       dtlh.len = htole16(m->m_pkthdr.len);
+
+
+       M_PREPEND(m, sizeof(dtlh), M_DONTWAIT);
+       if (m == NULL) {
+               aprint_error_dev(sc->sc_dev, "output ACL failed (head)\n");
+               sc->sc_stats.err_tx++;
+               return;
+       }
+       m_copyback(m, 0, sizeof(dtlh), &dtlh);
+       if (m->m_pkthdr.len & 0x1) {
+               m_copyback(m, m->m_pkthdr.len, 1, &dtlh.rsvd);  /* Add pad */
+               if (m->m_pkthdr.len & 0x1) {
+                       aprint_error_dev(sc->sc_dev,
+                           "output ACL failed (tail)\n");
+                       sc->sc_stats.err_tx++;
+                       return;
+               }
+       }
+
+       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 */
+
+       dtlh.type = HCI_SCO_DATA_PKT | BTUART_DTL_HEADER_TYPE;
+       dtlh.rsvd = 0;
+       dtlh.len = htole16(m->m_pkthdr.len);
+
+
+       M_PREPEND(m, sizeof(dtlh), M_DONTWAIT);
+       if (m == NULL) {
+               aprint_error_dev(sc->sc_dev, "output SCO failed (head)\n");
+               sc->sc_stats.err_tx++;
+               return;
+       }
+       m_copyback(m, 0, sizeof(dtlh), &dtlh);
+       if (m->m_pkthdr.len & 0x1) {
+               m_copyback(m, m->m_pkthdr.len, 1, &dtlh.rsvd);  /* Add pad */
+               if (m->m_pkthdr.len & 0x1) {
+                       aprint_error_dev(sc->sc_dev,
+                           "output SCO failed (tail)\n");
+                       sc->sc_stats.err_tx++;
+                       return;
+               }
+       }
+
+       s = spltty();
+       MBUFQ_ENQUEUE(&sc->sc_scoq, m);
+       if (!sc->sc_xmit)
+               btuartstart(sc->sc_tp);
+
+       splx(s);
+}


Home | Main Index | Thread Index | Old Index