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 <nathanialsl...@yahoo.com.au> * 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 <nathanialsl...@yahoo.com.au> * 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 */