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