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 and all,
From: Iain Hibbert <plunky%rya-online.net@localhost>
Date: Wed, 27 Jan 2010 20:35:31 +0000 (GMT)
> "output" path. On the input at least I think it would be more efficient
> to just use the sc_drop flag instead of adding the pad byte into the mbuf
> and using m_adj to remove it later - mbuf operations can be quite
> expensive in this manner.. for the output you also cannot sleep at this
> time, so must deal with failure to prepend/append data to the mbuf.
Why?
DTL always adjusts the header. And, the pad is adjusted if necessary.
Is the efficiency that you think about a memory size? Or, is it a speed?
The count of the m_adj() and the 'if (...)' is the same as you and me in
the source of C. And, I leave efficiency to the compiler.
> > In my understanding, the cfdata->cf_flags is a flag that each driver
> > can use. You can find it used in arch/PORT/conf/GENERIC by wdc(4)
> > and wd(4).
>
> imo all of cfdata is not for drivers to set
hmm... There are none of discussions about this. ;-<
I devised a different method. This executes processing to attach
different according to cfdata->cf_atname.
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 8 Feb 2010 18:05:29 -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
@@ -29,6 +29,8 @@
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: btuart.c,v 1.23 2009/05/12 12:10:46 cegger 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 */
@@ -73,13 +81,28 @@
};
/* 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 */
+enum state {
+ BTUART_RECV_PKT_TYPE, /* packet type */
+ BTUART_RECV_ACL_HDR, /* acl header */
+ BTUART_RECV_SCO_HDR, /* sco header */
+ BTUART_RECV_EVENT_HDR, /* event header */
+ BTUART_RECV_ACL_DATA, /* acl packet data */
+ BTUART_RECV_SCO_DATA, /* sco packet data */
+ BTUART_RECV_EVENT_DATA, /* event packet data */
+
+ BTUART_RECV_DTL_HDR, /* DTL header */
+ BTUART_RECV_DTL_CTRL_DATA, /* DTL control data */
+ BTUART_RECV_DTL_ACL_DATA, /* DTL acl data */
+ BTUART_RECV_DTL_SCO_DATA, /* DTL sco data */
+ BTUART_RECV_DTL_EVENT_DATA, /* 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 +122,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 +159,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 +195,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 +235,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 +269,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 +300,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;
@@ -351,8 +405,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 +413,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) */
}
@@ -435,12 +484,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 */
@@ -448,7 +497,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 */
@@ -456,7 +507,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 */
@@ -464,8 +517,129 @@
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 + 1) & ~0x0001;
+ break;
+ }
+
+ case BTUART_RECV_DTL_CTRL_DATA: /* Control Packet Complete */
+ {
+ struct btuart_dtl_header *dtlh =
+ mtod(m, 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 */
+ {
+ struct btuart_dtl_header *dtlh =
+ mtod(m, struct btuart_dtl_header *);
+
+ 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 */
+ {
+ struct btuart_dtl_header *dtlh =
+ mtod(m, struct btuart_dtl_header *);
+
+ 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 */
+ {
+ struct btuart_dtl_header *dtlh =
+ mtod(m, struct btuart_dtl_header *);
+
+ 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",
@@ -667,3 +841,143 @@
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 */
+ 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);
+}
Home |
Main Index |
Thread Index |
Old Index