Module Name: src
Committed By: nat
Date: Sun Sep 3 23:11:19 UTC 2017
Modified Files:
src/sys/dev/bluetooth: bth5.c bth5.h
Log Message:
Remove references to BlueCore.
Enable XON/XOFF flowcontrol in SLIP layer depending on config response.
Send an acknowlegment packet on timeout/retry.
Compute tx{ack,seq} and rx{ack,seq} according to the specification.
To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/sys/dev/bluetooth/bth5.c
cvs rdiff -u -r1.1 -r1.2 src/sys/dev/bluetooth/bth5.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/bluetooth/bth5.c
diff -u src/sys/dev/bluetooth/bth5.c:1.4 src/sys/dev/bluetooth/bth5.c:1.5
--- src/sys/dev/bluetooth/bth5.c:1.4 Mon Aug 14 12:51:11 2017
+++ src/sys/dev/bluetooth/bth5.c Sun Sep 3 23:11:19 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: bth5.c,v 1.4 2017/08/14 12:51:11 nat Exp $ */
+/* $NetBSD: bth5.c,v 1.5 2017/09/03 23:11:19 nat Exp $ */
/*
* Copyright (c) 2017 Nathanial Sloss <[email protected]>
* All rights reserved.
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bth5.c,v 1.4 2017/08/14 12:51:11 nat Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bth5.c,v 1.5 2017/09/03 23:11:19 nat Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -110,14 +110,16 @@ struct bth5_softc {
MBUFQ_HEAD() sc_seqq; /* Sequencing Layer queue */
MBUFQ_HEAD() sc_seq_retryq; /* retry queue */
uint32_t sc_seq_txseq;
- uint32_t sc_seq_txack;
uint32_t sc_seq_expected_rxseq;
+ uint32_t sc_seq_total_rxpkts;
+ uint32_t sc_seq_winack;
uint32_t sc_seq_winspace;
uint32_t sc_seq_retries;
callout_t sc_seq_timer;
uint32_t sc_seq_timeout;
uint32_t sc_seq_winsize;
uint32_t sc_seq_retry_limit;
+ bool sc_oof_flow_control;
/* variables of Datagram Queue Layer */
MBUFQ_HEAD() sc_dgq; /* Datagram Queue Layer queue */
@@ -500,10 +502,13 @@ bth5_slip_transmit(struct tty *tp)
struct mbuf *m;
int count, rlen;
uint8_t *rptr;
+ int s;
m = sc->sc_txp;
if (m == NULL) {
+ s = spltty();
sc->sc_flags &= ~BTH5_XMIT;
+ splx(s);
bth5_mux_transmit(sc);
return 0;
}
@@ -526,12 +531,18 @@ bth5_slip_transmit(struct tty *tp)
count++;
if (sc->sc_slip_txrsv == BTH5_SLIP_ESCAPE_PKTEND ||
- sc->sc_slip_txrsv == BTH5_SLIP_ESCAPE_XON ||
- sc->sc_slip_txrsv == BTH5_SLIP_ESCAPE_XOFF ||
sc->sc_slip_txrsv == BTH5_SLIP_ESCAPE_ESCAPE) {
rlen++;
rptr++;
}
+ if (sc->sc_oof_flow_control == true) {
+ if (sc->sc_slip_txrsv == BTH5_SLIP_ESCAPE_XON ||
+ sc->sc_slip_txrsv == BTH5_SLIP_ESCAPE_XOFF) {
+ rlen++;
+ rptr++;
+ }
+ }
+
sc->sc_slip_txrsv = 0;
}
@@ -571,7 +582,8 @@ bth5_slip_transmit(struct tty *tp)
}
DPRINTFN(4, ("0x%02x ", BTH5_SLIP_ESCAPE_PKTEND));
rptr++;
- } else if (*rptr == BTH5_SLIP_XON) {
+ } else if (sc->sc_oof_flow_control == true && *rptr ==
+ BTH5_SLIP_XON) {
if (putc(BTH5_SLIP_ESCAPE, &tp->t_outq) < 0)
break;
count++;
@@ -583,7 +595,8 @@ bth5_slip_transmit(struct tty *tp)
}
DPRINTFN(4, ("0x%02x ", BTH5_SLIP_ESCAPE_XON));
rptr++;
- } else if (*rptr == BTH5_SLIP_XOFF) {
+ } else if (sc->sc_oof_flow_control == true && *rptr ==
+ BTH5_SLIP_XOFF) {
if (putc(BTH5_SLIP_ESCAPE, &tp->t_outq) < 0)
break;
count++;
@@ -728,10 +741,12 @@ bth5_slip_receive(int c, struct tty *tp)
if (c == BTH5_SLIP_ESCAPE_PKTEND)
mtod(m, uint8_t *)[m->m_len++] =
BTH5_SLIP_PKTEND;
- else if (c == BTH5_SLIP_ESCAPE_XON)
+ else if (sc->sc_oof_flow_control == true &&
+ c == BTH5_SLIP_ESCAPE_XON)
mtod(m, uint8_t *)[m->m_len++] =
BTH5_SLIP_XON;
- else if (c == BTH5_SLIP_ESCAPE_XOFF)
+ else if (sc->sc_oof_flow_control == true &&
+ c == BTH5_SLIP_ESCAPE_XOFF)
mtod(m, uint8_t *)[m->m_len++] =
BTH5_SLIP_XOFF;
else if (c == BTH5_SLIP_ESCAPE_ESCAPE)
@@ -921,6 +936,7 @@ bth5_mux_transmit(struct bth5_softc *sc)
{
struct mbuf *m;
bth5_hdr_t *hdrp;
+ int s;
DPRINTFN(2, ("%s: mux transmit: sc_flags=0x%x, choke=%d",
device_xname(sc->sc_dev), sc->sc_flags, sc->sc_mux_choke));
@@ -963,8 +979,12 @@ bth5_mux_transmit(struct bth5_softc *sc)
hdrp->flags |= BTH5_FLAGS_PROTOCOL_REL; /* Reliable */
goto transmit;
}
- sc->sc_flags &= ~BTH5_XMIT;
- bth5_start(sc);
+
+ s = spltty();
+ if ((sc->sc_flags & BTH5_XMIT) == 0)
+ bth5_start(sc);
+ splx(s);
+
if (sc->sc_mux_send_ack == true) {
m = bth5_create_ackpkt();
if (m != NULL)
@@ -975,6 +995,7 @@ bth5_mux_transmit(struct bth5_softc *sc)
/* Nothing to send */
DPRINTFN(2, ("\n"));
+
return;
transmit:
@@ -1017,6 +1038,9 @@ bth5_mux_receive(struct bth5_softc *sc,
if (BTH5_FLAGS_SEQ(hdrp->flags) == 0 &&
hdrp->ident == BTH5_IDENT_ACKPKT &&
BTH5_GET_PLEN(hdrp) == 0) {
+ sc->sc_seq_txseq = BTH5_FLAGS_ACK(hdrp->flags);
+ bth5_send_ack_command(sc);
+ bth5_mux_transmit(sc);
m_freem(m);
return;
}
@@ -1076,11 +1100,12 @@ static void
bth5_sequencing_receive(struct bth5_softc *sc, struct mbuf *m)
{
bth5_hdr_t hdr;
- uint32_t exp_rxseq, rxseq;
+ uint32_t exp_rxseq, rxack, rxseq;
exp_rxseq = sc->sc_seq_expected_rxseq & BTH5_FLAGS_SEQ_MASK;
m_copydata(m, 0, sizeof(bth5_hdr_t), &hdr);
rxseq = BTH5_FLAGS_SEQ(hdr.flags);
+ rxack = BTH5_FLAGS_ACK(hdr.flags);
DPRINTFN(1, ("%s: seq receive: rxseq=%d, expected %d\n",
device_xname(sc->sc_dev), rxseq, exp_rxseq));
@@ -1145,16 +1170,13 @@ bth5_sequencing_receive(struct bth5_soft
m_freem(m);
break;
}
+ bth5_send_ack_command(sc);
+ sc->sc_seq_txseq = rxack;
+ sc->sc_seq_expected_rxseq = (rxseq + 1) & BTH5_FLAGS_SEQ_MASK;
+ sc->sc_seq_total_rxpkts++;
- if (sc->sc_seq_expected_rxseq / sc->sc_seq_winsize ==
- sc->sc_seq_winsize) {
- bth5_send_ack_command(sc);
- sc->sc_seq_txack = sc->sc_seq_expected_rxseq & BTH5_FLAGS_SEQ_MASK;
- } else
- sc->sc_seq_txack = rxseq;
-
- sc->sc_seq_expected_rxseq =
- (sc->sc_seq_expected_rxseq + 1);
+ if (sc->sc_seq_total_rxpkts % sc->sc_seq_winack == 0)
+ bth5_mux_transmit(sc);
}
static bool
@@ -1207,7 +1229,6 @@ bth5_tx_reliable_pkt(struct bth5_softc *
bth5_packet_print(m);
#endif
- sc->sc_seq_txseq = (sc->sc_seq_txseq + 1) & BTH5_FLAGS_SEQ_MASK;
sc->sc_seq_winspace--;
_retrans = m_copym(m, 0, M_COPYALL, M_WAIT);
if (_retrans == NULL) {
@@ -1216,6 +1237,7 @@ bth5_tx_reliable_pkt(struct bth5_softc *
}
MBUFQ_ENQUEUE(&sc->sc_seq_retryq, _retrans);
bth5_mux_transmit(sc);
+ sc->sc_seq_txseq = (sc->sc_seq_txseq + 1) & BTH5_FLAGS_SEQ_MASK;
return true;
out:
@@ -1227,7 +1249,7 @@ static __inline u_int
bth5_get_txack(struct bth5_softc *sc)
{
- return sc->sc_seq_txack;
+ return sc->sc_seq_expected_rxseq;
}
static void
@@ -1254,6 +1276,8 @@ bth5_signal_rxack(struct bth5_softc *sc,
MBUFQ_DEQUEUE(&sc->sc_seq_retryq, m0);
m_freem(m0);
sc->sc_seq_winspace++;
+ if (sc->sc_seq_winspace > sc->sc_seq_winsize)
+ sc->sc_seq_winspace = sc->sc_seq_winsize;
}
break;
}
@@ -1285,6 +1309,8 @@ bth5_timer_timeout(void *arg)
DPRINTFN(1, ("%s: seq timeout: retries=%d\n",
device_xname(sc->sc_dev), sc->sc_seq_retries));
+ bth5_send_ack_command(sc);
+ bth5_mux_transmit(sc);
s = splserial();
for (m = MBUFQ_FIRST(&sc->sc_seq_retryq); m != NULL;
m = MBUFQ_NEXT(m)) {
@@ -1325,7 +1351,6 @@ bth5_sequencing_reset(struct bth5_softc
sc->sc_seq_txseq = 0;
- sc->sc_seq_txack = 0;
sc->sc_seq_winspace = sc->sc_seq_winsize;
sc->sc_seq_retries = 0;
callout_stop(&sc->sc_seq_timer);
@@ -1334,6 +1359,7 @@ bth5_sequencing_reset(struct bth5_softc
/* XXXX: expected_rxseq should be set by MUX Layer */
sc->sc_seq_expected_rxseq = 0;
+ sc->sc_seq_total_rxpkts = 0;
}
@@ -1502,7 +1528,8 @@ static void
bth5_input_le(struct bth5_softc *sc, struct mbuf *m)
{
uint16_t *rcvpkt;
- int i;
+ int i, len;
+ uint8_t config[3];
const uint8_t *rplypkt;
static struct {
const char *type;
@@ -1527,7 +1554,7 @@ bth5_input_le(struct bth5_softc *sc, str
i = 0;
/* length of le packets is 2 */
- if (m->m_len == sizeof(uint16_t))
+ if (m->m_len >= sizeof(uint16_t))
for (i = 0; pkt[i].type != NULL; i++)
if (*(const uint16_t *)pkt[i].datap == *rcvpkt)
break;
@@ -1537,6 +1564,8 @@ bth5_input_le(struct bth5_softc *sc, str
return;
}
+ len = m->m_len;
+
rplypkt = NULL;
switch (sc->sc_le_state) {
case le_state_shy:
@@ -1558,14 +1587,26 @@ bth5_input_le(struct bth5_softc *sc, str
case le_state_curious:
if (*rcvpkt == *(const uint16_t *)sync)
rplypkt = syncresp;
- else if (*rcvpkt == *(const uint16_t *)syncresp)
+ else if (*rcvpkt == *(const uint16_t *)syncresp) {
rplypkt = conf;
+ len = 3;
+ }
else if (*rcvpkt == *(const uint16_t *)conf)
rplypkt = confresp;
- else if (*rcvpkt == *(const uint16_t *)confresp) {
+ else if (*rcvpkt == *(const uint16_t *)confresp &&
+ m->m_len == 3) {
DPRINTF(("%s: state change to garrulous:\n",
device_xname(sc->sc_dev)));
+ memcpy(config, conf, sizeof(uint16_t));
+ config[2] = (uint8_t)rcvpkt[1];
+ sc->sc_seq_winack = config[2] & BTH5_CONFIG_ACK_MASK;
+ if (config[2] & BTH5_CONFIG_FLOW_MASK)
+ sc->sc_oof_flow_control = true;
+ else
+ sc->sc_oof_flow_control = false;
+
+ bth5_sequencing_reset(sc);
bth5_set_choke(sc, false);
callout_stop(&sc->sc_le_timer);
sc->sc_le_state = le_state_garrulous;
@@ -1583,7 +1624,7 @@ bth5_input_le(struct bth5_softc *sc, str
"received sync! peer to reset?\n");
bth5_sequencing_reset(sc);
- rplypkt = sync;
+ rplypkt = syncresp;
sc->sc_le_state = le_state_shy;
} else
aprint_error_dev(sc->sc_dev,
@@ -1591,7 +1632,6 @@ bth5_input_le(struct bth5_softc *sc, str
break;
}
- int len = m->m_len;
m_freem(m);
if (rplypkt != NULL) {
@@ -1601,7 +1641,8 @@ bth5_input_le(struct bth5_softc *sc, str
else {
/* length of le packets is 2 */
m->m_pkthdr.len = m->m_len = 0;
- if (rplypkt == confresp || rplypkt == conf)
+ if (rplypkt == (const uint8_t *)&config
+ || rplypkt == confresp || rplypkt == conf)
m_copyback(m, 0, len, rplypkt);
else
m_copyback(m, 0, 2, rplypkt);
Index: src/sys/dev/bluetooth/bth5.h
diff -u src/sys/dev/bluetooth/bth5.h:1.1 src/sys/dev/bluetooth/bth5.h:1.2
--- src/sys/dev/bluetooth/bth5.h:1.1 Thu Aug 10 13:22:19 2017
+++ src/sys/dev/bluetooth/bth5.h Sun Sep 3 23:11:19 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: bth5.h,v 1.1 2017/08/10 13:22:19 nat Exp $ */
+/* $NetBSD: bth5.h,v 1.2 2017/09/03 23:11:19 nat Exp $ */
/*
* Copyright (c) 2017 Nathanial Sloss <[email protected]>
* All rights reserved.
@@ -62,6 +62,9 @@ typedef struct {
#define BTH5_FLAGS_PROTOCOL_TYPE 0x80
#define BTH5_FLAGS_PROTOCOL_REL 0x80
+#define BTH5_CONFIG_ACK_MASK 0x07
+#define BTH5_CONFIG_FLOW_MASK (1 << 7)
+
#define BTH5_SET_PLEN(hdrp, n) \
do { \
(hdrp)->plen1 = ((n) & 0x00f); \
@@ -76,8 +79,6 @@ typedef struct {
#define BTH5_IDENT_ACKPKT 0 /* Used by MUX Layer */
-/* Other Protocol Identifier values described to bcore-sp-007P */
-
/* definitions of SLIP Layer */
#define BTH5_SLIP_PKTSTART 0xc0
@@ -98,7 +99,6 @@ typedef struct {
/*
- * Reference to bcore-sp-007p.
* Channel Allocation
*/
#define BTH5_CHANNEL_HCI_CMD 1 /* HCI Command and Event */