tech-kern archive

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

btuart and SOCKET Bluetooth CF



Hi! Iain and all,


I am supporting NOKIA DTL-1/4 now.
(SOCKET Bluetooth CF 8510-00159F and older version)
Linux supported it by drivers/bluetooth/dtl1_cs.c.

This obtains BDADDR now and does inquiry.  However, this should attach/
detach the 4byte header at btuart.


The support of DTL can change some parameters.  I think that ioctl is
necessary for that.

@@ -191,6 +210,24 @@
        sc->sc_unit = hci_attach(&btuart_hci, self, 0);
        if (sc->sc_unit == NULL)
                aprint_error_dev(self, "HCI attach failed\n");
+
+if (1) {
+       struct hci_if *btuart_dtl_hci =
+           malloc(sizeof(struct hci_if), M_BLUETOOTH, M_ZERO | M_WAITOK);
+
+       memcpy(btuart_dtl_hci, sc->sc_unit->hci_if, sizeof(struct hci_if));
+       btuart_dtl_hci->output_cmd = btuart_dtl_output_cmd;
+       btuart_dtl_hci->output_acl = btuart_dtl_output_acl;
+       btuart_dtl_hci->output_sco = btuart_dtl_output_sco;
+       sc->sc_unit->hci_if = btuart_dtl_hci;
+       sc->sc_input = btuart_dtl_input;
+       sc->sc_state = BTUART_RECV_DTL_HDR;
+       sc->sc_want = sizeof(struct btuart_dtl_header);
+} else {
+       sc->sc_input = btuart_input;
+       sc->sc_state = BTUART_RECV_PKT_TYPE;
+       sc->sc_want = 1;
+}


Should we support ioctl for this?  Or, do you have a better idea?

Thanks,
--
kiyohara

Index: btuart.c
===================================================================
RCS file: /cvsroot/src/sys/dev/bluetooth/btuart.c,v
retrieving revision 1.23
diff -u -r1.23 btuart.c
--- btuart.c    12 May 2009 12:10:46 -0000      1.23
+++ btuart.c    18 Jan 2010 12:01:42 -0000
@@ -1,7 +1,7 @@
 /*     $NetBSD: btuart.c,v 1.23 2009/05/12 12:10:46 cegger 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
@@ -59,6 +59,7 @@
        struct hci_unit *sc_unit;       /* Bluetooth HCI handle */
        struct bt_stats sc_stats;
 
+       void            (*sc_input)(struct btuart_softc *, struct mbuf *);
        int             sc_state;       /* receive state */
        int             sc_want;        /* how much we want */
        struct mbuf *   sc_rxp;         /* incoming packet */
@@ -73,13 +74,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;
+       uint8_t rsvd;
+       uint16_t len;
+} __packed;
+#define BTUART_DTL_HEADER_TYPE 0x80
 
 void btuartattach(int);
 static int btuart_match(device_t, cfdata_t, void *);
@@ -99,6 +112,12 @@
 static void btuart_output_sco(device_t, struct mbuf *);
 static void btuart_stats(device_t, struct bt_stats *, int);
 
+static void btuart_input(struct btuart_softc *, struct mbuf *);
+static void btuart_dtl_input(struct btuart_softc *, struct mbuf *);
+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.
@@ -191,6 +210,24 @@
        sc->sc_unit = hci_attach(&btuart_hci, self, 0);
        if (sc->sc_unit == NULL)
                aprint_error_dev(self, "HCI attach failed\n");
+
+if (1) {
+       struct hci_if *btuart_dtl_hci =
+           malloc(sizeof(struct hci_if), M_BLUETOOTH, M_ZERO | M_WAITOK);
+
+       memcpy(btuart_dtl_hci, sc->sc_unit->hci_if, sizeof(struct hci_if));
+       btuart_dtl_hci->output_cmd = btuart_dtl_output_cmd;
+       btuart_dtl_hci->output_acl = btuart_dtl_output_acl;
+       btuart_dtl_hci->output_sco = btuart_dtl_output_sco;
+       sc->sc_unit->hci_if = btuart_dtl_hci;
+       sc->sc_input = btuart_dtl_input;
+       sc->sc_state = BTUART_RECV_DTL_HDR;
+       sc->sc_want = sizeof(struct btuart_dtl_header);
+} else {
+       sc->sc_input = btuart_input;
+       sc->sc_state = BTUART_RECV_PKT_TYPE;
+       sc->sc_want = 1;
+}
 }
 
 /*
@@ -351,8 +388,7 @@
                        /* new packet */
                        MGETHDR(m, M_DONTWAIT, MT_DATA);
                        if (m == NULL) {
-                               aprint_error_dev(sc->sc_dev,
-                                   "out of memory\n");
+                               aprint_error_dev(sc->sc_dev, "out of memory\n");
                                sc->sc_stats.err_rx++;
                                return 0;       /* (lost sync) */
                        }
@@ -360,15 +396,11 @@
                        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);
                        if (m->m_next == NULL) {
-                               aprint_error_dev(sc->sc_dev,
-                                   "out of memory\n");
+                               aprint_error_dev(sc->sc_dev, "out of memory\n");
                                sc->sc_stats.err_rx++;
                                return 0;       /* (lost sync) */
                        }
@@ -390,87 +422,8 @@
        sc->sc_stats.byte_rx++;
 
        sc->sc_want--;
-       if (sc->sc_want > 0)
-               return 0;       /* want more */
-
-       switch (sc->sc_state) {
-       case BTUART_RECV_PKT_TYPE:      /* Got packet type */
-
-               switch (c) {
-               case HCI_ACL_DATA_PKT:
-                       sc->sc_state = BTUART_RECV_ACL_HDR;
-                       sc->sc_want = sizeof(hci_acldata_hdr_t) - 1;
-                       break;
-
-               case HCI_SCO_DATA_PKT:
-                       sc->sc_state = BTUART_RECV_SCO_HDR;
-                       sc->sc_want = sizeof(hci_scodata_hdr_t) - 1;
-                       break;
-
-               case HCI_EVENT_PKT:
-                       sc->sc_state = BTUART_RECV_EVENT_HDR;
-                       sc->sc_want = sizeof(hci_event_hdr_t) - 1;
-                       break;
-
-               default:
-                       aprint_error_dev(sc->sc_dev,
-                           "Unknown packet type=%#x!\n", c);
-                       sc->sc_stats.err_rx++;
-                       m_freem(sc->sc_rxp);
-                       sc->sc_rxp = NULL;
-                       return 0;       /* (lost sync) */
-               }
-
-               break;
-
-       /*
-        * we assume (correctly of course :) that the packet headers all fit
-        * into a single pkthdr mbuf
-        */
-       case BTUART_RECV_ACL_HDR:       /* Got ACL Header */
-               sc->sc_state = BTUART_RECV_ACL_DATA;
-               sc->sc_want = mtod(m, hci_acldata_hdr_t *)->length;
-               sc->sc_want = le16toh(sc->sc_want);
-               break;
-
-       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;
-               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;
-               break;
-
-       case BTUART_RECV_ACL_DATA:      /* ACL Packet Complete */
-               if (!hci_input_acl(sc->sc_unit, sc->sc_rxp))
-                       sc->sc_stats.err_rx++;
-
-               sc->sc_stats.acl_rx++;
-               sc->sc_rxp = m = NULL;
-               break;
-
-       case BTUART_RECV_SCO_DATA:      /* SCO Packet Complete */
-               if (!hci_input_sco(sc->sc_unit, sc->sc_rxp))
-                       sc->sc_stats.err_rx++;
-
-               sc->sc_stats.sco_rx++;
-               sc->sc_rxp = m = NULL;
-               break;
-
-       case BTUART_RECV_EVENT_DATA:    /* Event Packet Complete */
-               if (!hci_input_event(sc->sc_unit, sc->sc_rxp))
-                       sc->sc_stats.err_rx++;
-
-               sc->sc_stats.evt_rx++;
-               sc->sc_rxp = m = NULL;
-               break;
-
-       default:
-               panic("%s: invalid state %d!\n",
-                   device_xname(sc->sc_dev), sc->sc_state);
-       }
+       if (sc->sc_want == 0)
+               sc->sc_input(sc, m);
 
        return 0;
 }
@@ -667,3 +620,304 @@
 
        splx(s);
 }
+
+
+
+static void
+btuart_input(struct btuart_softc *sc, struct mbuf *m)
+{
+
+       switch (sc->sc_state) {
+       case BTUART_RECV_PKT_TYPE:      /* Got packet type */
+               switch (*mtod(m, uint8_t *)) {
+               case HCI_ACL_DATA_PKT:
+                       sc->sc_state = BTUART_RECV_ACL_HDR;
+                       sc->sc_want = sizeof(hci_acldata_hdr_t) - 1;
+                       break;
+
+               case HCI_SCO_DATA_PKT:
+                       sc->sc_state = BTUART_RECV_SCO_HDR;
+                       sc->sc_want = sizeof(hci_scodata_hdr_t) - 1;
+                       break;
+
+               case HCI_EVENT_PKT:
+                       sc->sc_state = BTUART_RECV_EVENT_HDR;
+                       sc->sc_want = sizeof(hci_event_hdr_t) - 1;
+                       break;
+
+               default:
+                       aprint_error_dev(sc->sc_dev,
+                           "Unknown packet type=%#x!\n", *mtod(m, uint8_t *));
+                       sc->sc_stats.err_rx++;
+                       m_freem(sc->sc_rxp);
+                       sc->sc_rxp = NULL;      /* (lost sync) */
+                       break;
+               }
+
+               break;
+
+       /*
+        * we assume (correctly of course :) that the packet headers all fit
+        * into a single pkthdr mbuf
+        */
+       case BTUART_RECV_ACL_HDR:       /* Got ACL Header */
+               sc->sc_state = BTUART_RECV_ACL_DATA;
+               sc->sc_want = mtod(m, hci_acldata_hdr_t *)->length;
+               sc->sc_want = le16toh(sc->sc_want);
+               break;
+
+       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;
+               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;
+               break;
+
+       case BTUART_RECV_ACL_DATA:      /* ACL Packet Complete */
+               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_PKT_TYPE;
+               sc->sc_want = 1;
+               sc->sc_rxp = NULL;
+               break;
+
+       case BTUART_RECV_SCO_DATA:      /* SCO Packet Complete */
+               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_PKT_TYPE;
+               sc->sc_want = 1;
+               sc->sc_rxp = NULL;
+               break;
+
+       case BTUART_RECV_EVENT_DATA:    /* Event Packet Complete */
+               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_PKT_TYPE;
+               sc->sc_want = 1;
+               sc->sc_rxp = NULL;
+               break;
+
+       default:
+               panic("%s: invalid state %d!\n",
+                   device_xname(sc->sc_dev), sc->sc_state);
+       }
+}
+
+/*
+ * NOKIA DTL-1/4 functions
+ */
+
+static void
+btuart_dtl_input(struct btuart_softc *sc, struct mbuf *m)
+{
+       struct btuart_dtl_header *dtlh =
+           mtod(sc->sc_rxp, struct btuart_dtl_header *);
+
+       switch (sc->sc_state) {
+       case BTUART_RECV_DTL_HDR:       /* Got 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) more 1byte... */
+                       return;
+               }
+               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_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 */
+               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_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 */
+               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_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 */
+               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_state = BTUART_RECV_DTL_HDR;
+               sc->sc_want = sizeof(struct btuart_dtl_header);
+               sc->sc_rxp = NULL;
+               break;
+
+       default:
+               panic("%s: invalid state %d!\n",
+                   device_xname(sc->sc_dev), sc->sc_state);
+       }
+}
+
+static void
+btuart_dtl_output_cmd(device_t self, struct mbuf *m)
+{
+       struct btuart_softc *sc = device_private(self);
+       struct btuart_dtl_header *dtlh;
+       hci_cmd_hdr_t hdr;
+       int s;
+
+       KASSERT(sc->sc_enabled);
+
+       m_copydata(m, 0, sizeof(hdr), &hdr);
+       m_adj(m, sizeof(hdr.type));
+
+       M_PREPEND(m, sizeof(struct btuart_dtl_header), M_WAITOK);
+       dtlh = mtod(m, struct btuart_dtl_header *);
+       dtlh->type = hdr.type | BTUART_DTL_HEADER_TYPE;
+       dtlh->rsvd = 0;
+       /* already adjusted size for type of header */
+       dtlh->len = htole16(sizeof(hdr) - sizeof(hdr.type) + hdr.length);
+       if (dtlh->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;
+       hci_acldata_hdr_t hdr;
+       int s;
+
+       KASSERT(sc->sc_enabled);
+
+       m_copydata(m, 0, sizeof(hdr), &hdr);
+       m_adj(m, sizeof(hdr.type));
+
+       M_PREPEND(m, sizeof(struct btuart_dtl_header), M_WAITOK);
+       dtlh = mtod(m, struct btuart_dtl_header *);
+       dtlh->type = hdr.type | BTUART_DTL_HEADER_TYPE;
+       dtlh->rsvd = 0;
+       /* already adjusted size for type of header */
+       dtlh->len =
+           htole16(sizeof(hdr) - sizeof(hdr.type) + le16toh(hdr.length));
+       if (dtlh->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;
+       hci_scodata_hdr_t hdr;
+       int s;
+
+       KASSERT(sc->sc_enabled);
+
+       m_copydata(m, 0, sizeof(hdr), &hdr);
+       m_adj(m, sizeof(hdr.type));
+
+       M_PREPEND(m, sizeof(struct btuart_dtl_header), M_WAITOK);
+       dtlh = mtod(m, struct btuart_dtl_header *);
+       dtlh->type = hdr.type | BTUART_DTL_HEADER_TYPE;
+       dtlh->rsvd = 0;
+       /* already adjusted size for type of header */
+       dtlh->len = htole16(sizeof(hdr) - sizeof(hdr.type) + hdr.length);
+       if (dtlh->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);
+}


Home | Main Index | Thread Index | Old Index