1 /* $NetBSD: bth5.c,v 1.9 2024/07/05 04:31:50 rin Exp $ */
2 /*
3 * Copyright (c) 2017 Nathanial Sloss <nathanialsloss@yahoo.com.au>
4 * All rights reserved.
5 *
6 * Copyright (c) 2007 KIYOHARA Takashi
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: bth5.c,v 1.9 2024/07/05 04:31:50 rin Exp $");
33
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/callout.h>
37 #include <sys/conf.h>
38 #include <sys/device.h>
39 #include <sys/errno.h>
40 #include <sys/fcntl.h>
41 #include <sys/kauth.h>
42 #include <sys/kernel.h>
43 #include <sys/malloc.h>
44 #include <sys/mbuf.h>
45 #include <sys/proc.h>
46 #include <sys/sysctl.h>
47 #include <sys/syslimits.h>
48 #include <sys/systm.h>
49 #include <sys/tty.h>
50
51 #include <netbt/bluetooth.h>
52 #include <netbt/hci.h>
53
54 #include <dev/bluetooth/bth5.h>
55
56 #include "ioconf.h"
57
58 #ifdef BTH5_DEBUG
59 #ifdef DPRINTF
60 #undef DPRINTF
61 #endif
62 #ifdef DPRINTFN
63 #undef DPRINTFN
64 #endif
65
66 #define DPRINTF(x) printf x
67 #define DPRINTFN(n, x) do { if (bth5_debug > (n)) printf x; } while (0)
68 int bth5_debug = 3;
69 #else
70 #undef DPRINTF
71 #undef DPRINTFN
72
73 #define DPRINTF(x)
74 #define DPRINTFN(n, x)
75 #endif
76
77 struct bth5_softc {
78 device_t sc_dev;
79
80 struct tty *sc_tp;
81 struct hci_unit *sc_unit; /* Bluetooth HCI Unit */
82 struct bt_stats sc_stats;
83
84 int sc_flags;
85
86 /* output queues */
87 MBUFQ_HEAD() sc_cmdq;
88 MBUFQ_HEAD() sc_aclq;
89 MBUFQ_HEAD() sc_scoq;
90
91 int sc_baud;
92 int sc_init_baud;
93
94 /* variables of SLIP Layer */
95 struct mbuf *sc_txp; /* outgoing packet */
96 struct mbuf *sc_rxp; /* incoming packet */
97 int sc_slip_txrsv; /* reserved byte data */
98 int sc_slip_rxexp; /* expected byte data */
99 void (*sc_transmit_callback)(struct bth5_softc *, struct mbuf *);
100
101 /* variables of Packet Integrity Layer */
102 int sc_pi_txcrc; /* use CRC, if true */
103
104 /* variables of MUX Layer */
105 bool sc_mux_send_ack; /* flag for send_ack */
106 bool sc_mux_choke; /* Choke signal */
107 struct timeval sc_mux_lastrx; /* Last Rx Pkt Time */
108
109 /* variables of Sequencing Layer */
110 MBUFQ_HEAD() sc_seqq; /* Sequencing Layer queue */
111 MBUFQ_HEAD() sc_seq_retryq; /* retry queue */
112 uint32_t sc_seq_txseq;
113 uint32_t sc_seq_expected_rxseq;
114 uint32_t sc_seq_total_rxpkts;
115 uint32_t sc_seq_winack;
116 uint32_t sc_seq_winspace;
117 uint32_t sc_seq_retries;
118 callout_t sc_seq_timer;
119 uint32_t sc_seq_timeout;
120 uint32_t sc_seq_winsize;
121 uint32_t sc_seq_retry_limit;
122 bool sc_oof_flow_control;
123
124 /* variables of Datagram Queue Layer */
125 MBUFQ_HEAD() sc_dgq; /* Datagram Queue Layer queue */
126
127 /* variables of BTH5 Link Establishment Protocol */
128 bool sc_le_muzzled;
129 bth5_le_state_t sc_le_state;
130 callout_t sc_le_timer;
131
132 struct sysctllog *sc_log; /* sysctl log */
133 };
134
135 /* sc_flags */
136 #define BTH5_XMIT (1 << 0) /* transmit active */
137 #define BTH5_ENABLED (1 << 1) /* is enabled */
138
139 static int bthfive_match(device_t, cfdata_t, void *);
140 static void bthfive_attach(device_t, device_t, void *);
141 static int bthfive_detach(device_t, int);
142
143 /* tty functions */
144 static int bth5open(dev_t, struct tty *);
145 static int bth5close(struct tty *, int);
146 static int bth5ioctl(struct tty *, u_long, void *, int, struct lwp *);
147
148 static int bth5_slip_transmit(struct tty *);
149 static int bth5_slip_receive(int, struct tty *);
150
151 static void bth5_pktintegrity_transmit(struct bth5_softc *);
152 static void bth5_pktintegrity_receive(struct bth5_softc *, struct mbuf *);
153 static void bth5_crc_update(uint16_t *, uint8_t);
154 static uint16_t bth5_crc_reverse(uint16_t);
155
156 static void bth5_mux_transmit(struct bth5_softc *sc);
157 static void bth5_mux_receive(struct bth5_softc *sc, struct mbuf *m);
158 static __inline void bth5_send_ack_command(struct bth5_softc *sc);
159 static __inline struct mbuf *bth5_create_ackpkt(void);
160 static __inline void bth5_set_choke(struct bth5_softc *, bool);
161
162 static void bth5_sequencing_receive(struct bth5_softc *, struct mbuf *);
163 static bool bth5_tx_reliable_pkt(struct bth5_softc *, struct mbuf *, u_int);
164 static __inline u_int bth5_get_txack(struct bth5_softc *);
165 static void bth5_signal_rxack(struct bth5_softc *, uint32_t);
166 static void bth5_reliabletx_callback(struct bth5_softc *, struct mbuf *);
167 static void bth5_timer_timeout(void *);
168 static void bth5_sequencing_reset(struct bth5_softc *);
169
170 static void bth5_datagramq_receive(struct bth5_softc *, struct mbuf *);
171 static bool bth5_tx_unreliable_pkt(struct bth5_softc *, struct mbuf *, u_int);
172 static void bth5_unreliabletx_callback(struct bth5_softc *, struct mbuf *);
173
174 static int bth5_start_le(struct bth5_softc *);
175 static void bth5_terminate_le(struct bth5_softc *);
176 static void bth5_input_le(struct bth5_softc *, struct mbuf *);
177 static void bth5_le_timeout(void *);
178
179 static void bth5_start(struct bth5_softc *);
180
181 /* bluetooth hci functions */
182 static int bth5_enable(device_t);
183 static void bth5_disable(device_t);
184 static void bth5_output_cmd(device_t, struct mbuf *);
185 static void bth5_output_acl(device_t, struct mbuf *);
186 static void bth5_output_sco(device_t, struct mbuf *);
187 static void bth5_stats(device_t, struct bt_stats *, int);
188
189 #ifdef BTH5_DEBUG
190 static void bth5_packet_print(struct mbuf *m);
191 #endif
192
193
194 /*
195 * It doesn't need to be exported, as only bth5attach() uses it,
196 * but there's no "official" way to make it static.
197 */
198 CFATTACH_DECL_NEW(bthfive, sizeof(struct bth5_softc),
199 bthfive_match, bthfive_attach, bthfive_detach, NULL);
200
201 static struct linesw bth5_disc = {
202 .l_name = "bth5",
203 .l_open = bth5open,
204 .l_close = bth5close,
205 .l_read = ttyerrio,
206 .l_write = ttyerrio,
207 .l_ioctl = bth5ioctl,
208 .l_rint = bth5_slip_receive,
209 .l_start = bth5_slip_transmit,
210 .l_modem = ttymodem,
211 .l_poll = ttyerrpoll
212 };
213
214 static const struct hci_if bth5_hci = {
215 .enable = bth5_enable,
216 .disable = bth5_disable,
217 .output_cmd = bth5_output_cmd,
218 .output_acl = bth5_output_acl,
219 .output_sco = bth5_output_sco,
220 .get_stats = bth5_stats,
221 .ipl = IPL_TTY,
222 };
223
224 /* ARGSUSED */
225 void
bthfiveattach(int num __unused)226 bthfiveattach(int num __unused)
227 {
228 int error;
229
230 error = ttyldisc_attach(&bth5_disc);
231 if (error) {
232 aprint_error("%s: unable to register line discipline, "
233 "error = %d\n", bthfive_cd.cd_name, error);
234 return;
235 }
236
237 error = config_cfattach_attach(bthfive_cd.cd_name, &bthfive_ca);
238 if (error) {
239 aprint_error("%s: unable to register cfattach, error = %d\n",
240 bthfive_cd.cd_name, error);
241 config_cfdriver_detach(&bthfive_cd);
242 (void) ttyldisc_detach(&bth5_disc);
243 }
244 }
245
246 /*
247 * Autoconf match routine.
248 *
249 * XXX: unused: config_attach_pseudo(9) does not call ca_match.
250 */
251 /* ARGSUSED */
252 static int
bthfive_match(device_t self __unused,cfdata_t cfdata __unused,void * arg __unused)253 bthfive_match(device_t self __unused, cfdata_t cfdata __unused,
254 void *arg __unused)
255 {
256
257 /* pseudo-device; always present */
258 return 1;
259 }
260
261 /*
262 * Autoconf attach routine. Called by config_attach_pseudo(9) when we
263 * open the line discipline.
264 */
265 /* ARGSUSED */
266 static void
bthfive_attach(device_t parent __unused,device_t self,void * aux __unused)267 bthfive_attach(device_t parent __unused, device_t self, void *aux __unused)
268 {
269 struct bth5_softc *sc = device_private(self);
270 const struct sysctlnode *node;
271 int rc, bth5_node_num;
272
273 aprint_normal("\n");
274 aprint_naive("\n");
275
276 sc->sc_dev = self;
277 callout_init(&sc->sc_seq_timer, 0);
278 callout_setfunc(&sc->sc_seq_timer, bth5_timer_timeout, sc);
279 callout_init(&sc->sc_le_timer, 0);
280 callout_setfunc(&sc->sc_le_timer, bth5_le_timeout, sc);
281 sc->sc_seq_timeout = BTH5_SEQ_TX_TIMEOUT;
282 sc->sc_seq_winsize = BTH5_SEQ_TX_WINSIZE;
283 sc->sc_seq_retry_limit = BTH5_SEQ_TX_RETRY_LIMIT;
284 MBUFQ_INIT(&sc->sc_seqq);
285 MBUFQ_INIT(&sc->sc_seq_retryq);
286 MBUFQ_INIT(&sc->sc_dgq);
287 MBUFQ_INIT(&sc->sc_cmdq);
288 MBUFQ_INIT(&sc->sc_aclq);
289 MBUFQ_INIT(&sc->sc_scoq);
290
291 /* Attach Bluetooth unit */
292 sc->sc_unit = hci_attach_pcb(&bth5_hci, self, 0);
293
294 if ((rc = sysctl_createv(&sc->sc_log, 0, NULL, &node,
295 0, CTLTYPE_NODE, device_xname(self),
296 SYSCTL_DESCR("bth5 controls"),
297 NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL)) != 0) {
298 goto err;
299 }
300 bth5_node_num = node->sysctl_num;
301 if ((rc = sysctl_createv(&sc->sc_log, 0, NULL, &node,
302 CTLFLAG_READWRITE, CTLTYPE_BOOL,
303 "muzzled", SYSCTL_DESCR("muzzled for Link-establishment Layer"),
304 NULL, 0, &sc->sc_le_muzzled,
305 0, CTL_HW, bth5_node_num, CTL_CREATE, CTL_EOL)) != 0) {
306 goto err;
307 }
308 if ((rc = sysctl_createv(&sc->sc_log, 0, NULL, &node,
309 CTLFLAG_READWRITE, CTLTYPE_INT,
310 "txcrc", SYSCTL_DESCR("txcrc for Packet Integrity Layer"),
311 NULL, 0, &sc->sc_pi_txcrc,
312 0, CTL_HW, bth5_node_num, CTL_CREATE, CTL_EOL)) != 0) {
313 goto err;
314 }
315 if ((rc = sysctl_createv(&sc->sc_log, 0, NULL, &node,
316 CTLFLAG_READWRITE, CTLTYPE_INT,
317 "timeout", SYSCTL_DESCR("timeout for Sequencing Layer"),
318 NULL, 0, &sc->sc_seq_timeout,
319 0, CTL_HW, bth5_node_num, CTL_CREATE, CTL_EOL)) != 0) {
320 goto err;
321 }
322 if ((rc = sysctl_createv(&sc->sc_log, 0, NULL, &node,
323 CTLFLAG_READWRITE, CTLTYPE_INT,
324 "winsize", SYSCTL_DESCR("winsize for Sequencing Layer"),
325 NULL, 0, &sc->sc_seq_winsize,
326 0, CTL_HW, bth5_node_num, CTL_CREATE, CTL_EOL)) != 0) {
327 goto err;
328 }
329 if ((rc = sysctl_createv(&sc->sc_log, 0, NULL, &node,
330 CTLFLAG_READWRITE, CTLTYPE_INT,
331 "retry_limit", SYSCTL_DESCR("retry limit for Sequencing Layer"),
332 NULL, 0, &sc->sc_seq_retry_limit,
333 0, CTL_HW, bth5_node_num, CTL_CREATE, CTL_EOL)) != 0) {
334 goto err;
335 }
336 return;
337
338 err:
339 aprint_error_dev(self, "sysctl_createv failed (rc = %d)\n", rc);
340 }
341
342 /*
343 * Autoconf detach routine. Called when we close the line discipline.
344 */
345 /* ARGSUSED */
346 static int
bthfive_detach(device_t self,int flags __unused)347 bthfive_detach(device_t self, int flags __unused)
348 {
349 struct bth5_softc *sc = device_private(self);
350
351 if (sc->sc_unit != NULL) {
352 hci_detach_pcb(sc->sc_unit);
353 sc->sc_unit = NULL;
354 }
355
356 callout_halt(&sc->sc_seq_timer, NULL);
357 callout_destroy(&sc->sc_seq_timer);
358
359 callout_halt(&sc->sc_le_timer, NULL);
360 callout_destroy(&sc->sc_le_timer);
361
362 return 0;
363 }
364
365
366 /*
367 * Line discipline functions.
368 */
369 /* ARGSUSED */
370 static int
bth5open(dev_t device __unused,struct tty * tp)371 bth5open(dev_t device __unused, struct tty *tp)
372 {
373 struct bth5_softc *sc;
374 device_t dev;
375 cfdata_t cfdata;
376 struct lwp *l = curlwp; /* XXX */
377 int error, unit, s;
378 static char name[] = "bthfive";
379
380 error = kauth_authorize_device(l->l_cred, KAUTH_DEVICE_BLUETOOTH_BCSP,
381 KAUTH_ARG(KAUTH_REQ_DEVICE_BLUETOOTH_BCSP_ADD), NULL, NULL, NULL);
382 if (error)
383 return (error);
384
385 s = spltty();
386
387 if (tp->t_linesw == &bth5_disc) {
388 sc = tp->t_sc;
389 if (sc != NULL) {
390 splx(s);
391 return EBUSY;
392 }
393 }
394
395 cfdata = malloc(sizeof(struct cfdata), M_DEVBUF, M_WAITOK);
396 for (unit = 0; unit < bthfive_cd.cd_ndevs; unit++)
397 if (device_lookup(&bthfive_cd, unit) == NULL)
398 break;
399 cfdata->cf_name = name;
400 cfdata->cf_atname = name;
401 cfdata->cf_unit = unit;
402 cfdata->cf_fstate = FSTATE_STAR;
403
404 aprint_normal("%s%d at tty major %llu minor %llu",
405 name, unit, (unsigned long long)major(tp->t_dev),
406 (unsigned long long)minor(tp->t_dev));
407 dev = config_attach_pseudo(cfdata);
408 if (dev == NULL) {
409 splx(s);
410 return EIO;
411 }
412 sc = device_private(dev);
413
414 ttylock(tp);
415 tp->t_sc = sc;
416 sc->sc_tp = tp;
417 ttyflush(tp, FREAD | FWRITE);
418 ttyunlock(tp);
419
420 splx(s);
421
422 sc->sc_slip_txrsv = BTH5_SLIP_PKTSTART;
423 bth5_sequencing_reset(sc);
424
425 /* start link-establishment */
426 bth5_start_le(sc);
427
428 return 0;
429 }
430
431 /* ARGSUSED */
432 static int
bth5close(struct tty * tp,int flag __unused)433 bth5close(struct tty *tp, int flag __unused)
434 {
435 struct bth5_softc *sc = tp->t_sc;
436 cfdata_t cfdata;
437 int s;
438
439 /* terminate link-establishment */
440 bth5_terminate_le(sc);
441
442 s = spltty();
443
444 MBUFQ_DRAIN(&sc->sc_dgq);
445 bth5_sequencing_reset(sc);
446
447 ttylock(tp);
448 ttyflush(tp, FREAD | FWRITE);
449 ttyunlock(tp); /* XXX */
450 ttyldisc_release(tp->t_linesw);
451 tp->t_linesw = ttyldisc_default();
452 if (sc != NULL) {
453 tp->t_sc = NULL;
454 if (sc->sc_tp == tp) {
455 cfdata = device_cfdata(sc->sc_dev);
456 config_detach(sc->sc_dev, 0);
457 free(cfdata, M_DEVBUF);
458 }
459
460 }
461 splx(s);
462 return 0;
463 }
464
465 /* ARGSUSED */
466 static int
bth5ioctl(struct tty * tp,u_long cmd,void * data,int flag __unused,struct lwp * l __unused)467 bth5ioctl(struct tty *tp, u_long cmd, void *data, int flag __unused,
468 struct lwp *l __unused)
469 {
470 struct bth5_softc *sc = tp->t_sc;
471 int error;
472
473 if (sc == NULL || tp != sc->sc_tp)
474 return EPASSTHROUGH;
475
476 error = 0;
477 switch (cmd) {
478 default:
479 error = EPASSTHROUGH;
480 break;
481 }
482
483 return error;
484 }
485
486
487 /*
488 * UART Driver Layer is supported by com-driver.
489 */
490
491 /*
492 * BTH5 SLIP Layer functions:
493 * Supports to transmit/receive a byte stream.
494 * SLIP protocol described in Internet standard RFC 1055.
495 */
496 static int
bth5_slip_transmit(struct tty * tp)497 bth5_slip_transmit(struct tty *tp)
498 {
499 struct bth5_softc *sc = tp->t_sc;
500 struct mbuf *m;
501 int count, rlen;
502 uint8_t *rptr;
503 int s;
504
505 m = sc->sc_txp;
506 if (m == NULL) {
507 s = spltty();
508 sc->sc_flags &= ~BTH5_XMIT;
509 splx(s);
510 bth5_mux_transmit(sc);
511 return 0;
512 }
513
514 count = 0;
515 rlen = 0;
516 rptr = mtod(m, uint8_t *);
517
518 if (sc->sc_slip_txrsv != 0) {
519 #ifdef BTH5_DEBUG
520 if (sc->sc_slip_txrsv == BTH5_SLIP_PKTSTART)
521 DPRINTFN(4, ("%s: slip transmit start\n",
522 device_xname(sc->sc_dev)));
523 else
524 DPRINTFN(4, ("0x%02x ", sc->sc_slip_txrsv));
525 #endif
526
527 if (putc(sc->sc_slip_txrsv, &tp->t_outq) < 0)
528 return 0;
529 count++;
530
531 if (sc->sc_slip_txrsv == BTH5_SLIP_ESCAPE_PKTEND ||
532 sc->sc_slip_txrsv == BTH5_SLIP_ESCAPE_ESCAPE) {
533 rlen++;
534 rptr++;
535 }
536 if (sc->sc_oof_flow_control == true) {
537 if (sc->sc_slip_txrsv == BTH5_SLIP_ESCAPE_XON ||
538 sc->sc_slip_txrsv == BTH5_SLIP_ESCAPE_XOFF) {
539 rlen++;
540 rptr++;
541 }
542 }
543
544 sc->sc_slip_txrsv = 0;
545 }
546
547 for(;;) {
548 if (rlen >= m->m_len) {
549 m = m->m_next;
550 if (m == NULL) {
551 if (putc(BTH5_SLIP_PKTEND, &tp->t_outq) < 0)
552 break;
553
554 DPRINTFN(4, ("\n%s: slip transmit end\n",
555 device_xname(sc->sc_dev)));
556
557 m = sc->sc_txp;
558 sc->sc_txp = NULL;
559 sc->sc_slip_txrsv = BTH5_SLIP_PKTSTART;
560
561 sc->sc_transmit_callback(sc, m);
562 m = NULL;
563 break;
564 }
565
566 rlen = 0;
567 rptr = mtod(m, uint8_t *);
568 continue;
569 }
570
571 if (*rptr == BTH5_SLIP_PKTEND) {
572 if (putc(BTH5_SLIP_ESCAPE, &tp->t_outq) < 0)
573 break;
574 count++;
575 DPRINTFN(4, (" esc "));
576
577 if (putc(BTH5_SLIP_ESCAPE_PKTEND, &tp->t_outq) < 0) {
578 sc->sc_slip_txrsv = BTH5_SLIP_ESCAPE_PKTEND;
579 break;
580 }
581 DPRINTFN(4, ("0x%02x ", BTH5_SLIP_ESCAPE_PKTEND));
582 rptr++;
583 } else if (sc->sc_oof_flow_control == true && *rptr ==
584 BTH5_SLIP_XON) {
585 if (putc(BTH5_SLIP_ESCAPE, &tp->t_outq) < 0)
586 break;
587 count++;
588 DPRINTFN(4, (" esc "));
589
590 if (putc(BTH5_SLIP_ESCAPE_XON, &tp->t_outq) < 0) {
591 sc->sc_slip_txrsv = BTH5_SLIP_ESCAPE_XON;
592 break;
593 }
594 DPRINTFN(4, ("0x%02x ", BTH5_SLIP_ESCAPE_XON));
595 rptr++;
596 } else if (sc->sc_oof_flow_control == true && *rptr ==
597 BTH5_SLIP_XOFF) {
598 if (putc(BTH5_SLIP_ESCAPE, &tp->t_outq) < 0)
599 break;
600 count++;
601 DPRINTFN(4, (" esc "));
602
603 if (putc(BTH5_SLIP_ESCAPE_XOFF, &tp->t_outq) < 0) {
604 sc->sc_slip_txrsv = BTH5_SLIP_ESCAPE_XOFF;
605 break;
606 }
607 DPRINTFN(4, ("0x%02x ", BTH5_SLIP_ESCAPE_XOFF));
608 rptr++;
609 } else if (*rptr == BTH5_SLIP_ESCAPE) {
610 if (putc(BTH5_SLIP_ESCAPE, &tp->t_outq) < 0)
611 break;
612 count++;
613 DPRINTFN(4, (" esc "));
614
615 if (putc(BTH5_SLIP_ESCAPE_ESCAPE, &tp->t_outq) < 0) {
616 sc->sc_slip_txrsv = BTH5_SLIP_ESCAPE_ESCAPE;
617 break;
618 }
619 DPRINTFN(4, ("0x%02x ", BTH5_SLIP_ESCAPE_ESCAPE));
620 rptr++;
621 } else {
622 if (putc(*rptr++, &tp->t_outq) < 0)
623 break;
624 DPRINTFN(4, ("0x%02x ", *(rptr - 1)));
625 }
626 rlen++;
627 count++;
628 }
629 if (m != NULL)
630 m_adj(m, rlen);
631
632 sc->sc_stats.byte_tx += count;
633
634 if (tp->t_outq.c_cc != 0 && tp->t_oproc != NULL)
635 (*tp->t_oproc)(tp);
636
637 return 0;
638 }
639
640 static int
bth5_slip_receive(int c,struct tty * tp)641 bth5_slip_receive(int c, struct tty *tp)
642 {
643 struct bth5_softc *sc = tp->t_sc;
644 struct mbuf *m = sc->sc_rxp;
645 int discard = 0;
646 const char *errstr;
647
648 c &= TTY_CHARMASK;
649
650 /* If we already started a packet, find the trailing end of it. */
651 if (m) {
652 while (m->m_next)
653 m = m->m_next;
654
655 if (M_TRAILINGSPACE(m) == 0) {
656 /* extend mbuf */
657 MGET(m->m_next, M_DONTWAIT, MT_DATA);
658 if (m->m_next == NULL) {
659 aprint_error_dev(sc->sc_dev,
660 "out of memory\n");
661 sc->sc_stats.err_rx++;
662 return 0; /* (lost sync) */
663 }
664
665 m = m->m_next;
666 m->m_len = 0;
667 }
668 } else
669 if (c != BTH5_SLIP_PKTSTART) {
670 discard = 1;
671 errstr = "not sync";
672 goto discarded;
673 }
674
675 switch (c) {
676 case BTH5_SLIP_PKTSTART /* or _PKTEND */:
677 if (m == NULL) {
678 /* BTH5_SLIP_PKTSTART */
679
680 DPRINTFN(4, ("%s: slip receive start\n",
681 device_xname(sc->sc_dev)));
682
683 /* new packet */
684 MGETHDR(m, M_DONTWAIT, MT_DATA);
685 if (m == NULL) {
686 aprint_error_dev(sc->sc_dev,
687 "out of memory\n");
688 sc->sc_stats.err_rx++;
689 return 0; /* (lost sync) */
690 }
691
692 sc->sc_rxp = m;
693 m->m_pkthdr.len = m->m_len = 0;
694 sc->sc_slip_rxexp = 0;
695 } else {
696 /* BTH5_SLIP_PKTEND */
697
698 if (m == sc->sc_rxp && m->m_len == 0) {
699 DPRINTFN(4, ("%s: resynchronises\n",
700 device_xname(sc->sc_dev)));
701
702 sc->sc_stats.byte_rx++;
703 return 0;
704 }
705
706 DPRINTFN(4, ("%s%s: slip receive end\n",
707 (m->m_len % 16 != 0) ? "\n" : "",
708 device_xname(sc->sc_dev)));
709
710 bth5_pktintegrity_receive(sc, sc->sc_rxp);
711 sc->sc_rxp = NULL;
712 sc->sc_slip_rxexp = BTH5_SLIP_PKTSTART;
713 }
714 sc->sc_stats.byte_rx++;
715 return 0;
716
717 case BTH5_SLIP_ESCAPE:
718
719 DPRINTFN(4, (" esc"));
720
721 if (sc->sc_slip_rxexp == BTH5_SLIP_ESCAPE) {
722 discard = 1;
723 errstr = "waiting 0xdc or 0xdb or 0xde of 0xdf";
724 } else
725 sc->sc_slip_rxexp = BTH5_SLIP_ESCAPE;
726 break;
727
728 default:
729 DPRINTFN(4, (" 0x%02x%s",
730 c, (m->m_len % 16 == 15) ? "\n" : ""));
731
732 switch (sc->sc_slip_rxexp) {
733 case BTH5_SLIP_PKTSTART:
734 discard = 1;
735 errstr = "waiting 0xc0";
736 break;
737
738 case BTH5_SLIP_ESCAPE:
739 if (c == BTH5_SLIP_ESCAPE_PKTEND)
740 mtod(m, uint8_t *)[m->m_len++] =
741 BTH5_SLIP_PKTEND;
742 else if (sc->sc_oof_flow_control == true &&
743 c == BTH5_SLIP_ESCAPE_XON)
744 mtod(m, uint8_t *)[m->m_len++] =
745 BTH5_SLIP_XON;
746 else if (sc->sc_oof_flow_control == true &&
747 c == BTH5_SLIP_ESCAPE_XOFF)
748 mtod(m, uint8_t *)[m->m_len++] =
749 BTH5_SLIP_XOFF;
750 else if (c == BTH5_SLIP_ESCAPE_ESCAPE)
751 mtod(m, uint8_t *)[m->m_len++] =
752 BTH5_SLIP_ESCAPE;
753 else {
754 discard = 1;
755 errstr = "unknown escape";
756 }
757 sc->sc_slip_rxexp = 0;
758 break;
759
760 default:
761 mtod(m, uint8_t *)[m->m_len++] = c;
762 }
763 sc->sc_rxp->m_pkthdr.len++;
764 }
765 if (discard) {
766 discarded:
767 #ifdef BTH5_DEBUG
768 DPRINTFN(4, ("%s: receives unexpected byte 0x%02x: %s\n",
769 device_xname(sc->sc_dev), c, errstr));
770 #else
771 __USE(errstr);
772 #endif
773 }
774 sc->sc_stats.byte_rx++;
775
776 return 0;
777 }
778
779
780 /*
781 * BTH5 Packet Integrity Layer functions:
782 * handling Payload Length, Checksum, CRC.
783 */
784 static void
bth5_pktintegrity_transmit(struct bth5_softc * sc)785 bth5_pktintegrity_transmit(struct bth5_softc *sc)
786 {
787 struct mbuf *m = sc->sc_txp;
788 bth5_hdr_t *hdrp = mtod(m, bth5_hdr_t *);
789 int pldlen;
790
791 DPRINTFN(3, ("%s: pi transmit\n", device_xname(sc->sc_dev)));
792
793 pldlen = m->m_pkthdr.len - sizeof(bth5_hdr_t);
794
795 if (sc->sc_pi_txcrc)
796 hdrp->flags |= BTH5_FLAGS_CRC_PRESENT;
797
798 BTH5_SET_PLEN(hdrp, pldlen);
799 BTH5_SET_CSUM(hdrp);
800
801 if (sc->sc_pi_txcrc) {
802 struct mbuf *_m;
803 int n = 0;
804 uint16_t crc = 0xffff;
805 uint8_t *buf;
806
807 for (_m = m; _m != NULL; _m = _m->m_next) {
808 buf = mtod(_m, uint8_t *);
809 for (n = 0; n < _m->m_len; n++)
810 bth5_crc_update(&crc, *(buf + n));
811 }
812 crc = htobe16(bth5_crc_reverse(crc));
813 m_copyback(m, m->m_pkthdr.len, sizeof(crc), &crc);
814 }
815
816 #ifdef BTH5_DEBUG
817 if (bth5_debug == 3)
818 bth5_packet_print(m);
819 #endif
820
821 bth5_slip_transmit(sc->sc_tp);
822 }
823
824 static void
bth5_pktintegrity_receive(struct bth5_softc * sc,struct mbuf * m)825 bth5_pktintegrity_receive(struct bth5_softc *sc, struct mbuf *m)
826 {
827 bth5_hdr_t *hdrp = mtod(m, bth5_hdr_t *);
828 u_int pldlen;
829 int discard = 0;
830 uint16_t crc = 0xffff;
831 const char *errstr;
832
833 DPRINTFN(3, ("%s: pi receive\n", device_xname(sc->sc_dev)));
834 #ifdef BTH5_DEBUG
835 if (bth5_debug == 4)
836 bth5_packet_print(m);
837 #endif
838
839 KASSERT(m->m_len >= sizeof(bth5_hdr_t));
840
841 pldlen = m->m_pkthdr.len - sizeof(bth5_hdr_t) -
842 ((hdrp->flags & BTH5_FLAGS_CRC_PRESENT) ? sizeof(crc) : 0);
843 if (pldlen > 0xfff) {
844 discard = 1;
845 errstr = "Payload Length";
846 goto discarded;
847 }
848 if (hdrp->csum != BTH5_GET_CSUM(hdrp)) {
849 discard = 1;
850 errstr = "Checksum";
851 goto discarded;
852 }
853 if (BTH5_GET_PLEN(hdrp) != pldlen) {
854 discard = 1;
855 errstr = "Payload Length";
856 goto discarded;
857 }
858 if (hdrp->flags & BTH5_FLAGS_CRC_PRESENT) {
859 struct mbuf *_m;
860 int i, n;
861 uint16_t crc0;
862 uint8_t *buf;
863
864 i = 0;
865 n = 0;
866 for (_m = m; _m != NULL; _m = _m->m_next) {
867 buf = mtod(m, uint8_t *);
868 for (n = 0;
869 n < _m->m_len && i < sizeof(bth5_hdr_t) + pldlen;
870 n++, i++)
871 bth5_crc_update(&crc, *(buf + n));
872 }
873
874 m_copydata(_m, n, sizeof(crc0), &crc0);
875 if (be16toh(crc0) != bth5_crc_reverse(crc)) {
876 discard = 1;
877 errstr = "CRC";
878 } else
879 /* Shaves CRC */
880 m_adj(m, (int)(0 - sizeof(crc)));
881 }
882
883 if (discard) {
884 discarded:
885 #ifdef BTH5_DEBUG
886 DPRINTFN(3, ("%s: receives unexpected packet: %s\n",
887 device_xname(sc->sc_dev), errstr));
888 #else
889 __USE(errstr);
890 #endif
891 m_freem(m);
892 } else
893 bth5_mux_receive(sc, m);
894 }
895
896 static const uint16_t crctbl[] = {
897 0x0000, 0x1081, 0x2102, 0x3183,
898 0x4204, 0x5285, 0x6306, 0x7387,
899 0x8408, 0x9489, 0xa50a, 0xb58b,
900 0xc60c, 0xd68d, 0xe70e, 0xf78f,
901 };
902
903 static void
bth5_crc_update(uint16_t * crc,uint8_t d)904 bth5_crc_update(uint16_t *crc, uint8_t d)
905 {
906 uint16_t reg = *crc;
907
908 reg = (reg >> 4) ^ crctbl[(reg ^ d) & 0x000f];
909 reg = (reg >> 4) ^ crctbl[(reg ^ (d >> 4)) & 0x000f];
910
911 *crc = reg;
912 }
913
914 static uint16_t
bth5_crc_reverse(uint16_t crc)915 bth5_crc_reverse(uint16_t crc)
916 {
917 uint16_t b, rev;
918
919 for (b = 0, rev = 0; b < 16; b++) {
920 rev = rev << 1;
921 rev |= (crc & 1);
922 crc = crc >> 1;
923 }
924
925 return rev;
926 }
927
928
929 /*
930 * BTH5 MUX Layer functions
931 */
932 static void
bth5_mux_transmit(struct bth5_softc * sc)933 bth5_mux_transmit(struct bth5_softc *sc)
934 {
935 struct mbuf *m;
936 bth5_hdr_t *hdrp;
937 int s;
938
939 DPRINTFN(2, ("%s: mux transmit: sc_flags=0x%x, choke=%d",
940 device_xname(sc->sc_dev), sc->sc_flags, sc->sc_mux_choke));
941
942 if (sc->sc_mux_choke) {
943 struct mbuf *_m = NULL;
944
945 /* In this case, send only Link Establishment packet */
946 for (m = MBUFQ_FIRST(&sc->sc_dgq); m != NULL;
947 _m = m, m = MBUFQ_NEXT(m)) {
948 hdrp = mtod(m, bth5_hdr_t *);
949 if (hdrp->ident == BTH5_CHANNEL_LE) {
950 if (m == MBUFQ_FIRST(&sc->sc_dgq))
951 MBUFQ_DEQUEUE(&sc->sc_dgq, m);
952 else {
953 if (m->m_nextpkt == NULL)
954 sc->sc_dgq.mq_last =
955 &_m->m_nextpkt;
956 _m->m_nextpkt = m->m_nextpkt;
957 m->m_nextpkt = NULL;
958 }
959 goto transmit;
960 }
961 }
962 DPRINTFN(2, ("\n"));
963 return;
964 }
965
966 /*
967 * The MUX Layer always gives priority to packets from the Datagram
968 * Queue Layer over the Sequencing Layer.
969 */
970 if (MBUFQ_FIRST(&sc->sc_dgq)) {
971 MBUFQ_DEQUEUE(&sc->sc_dgq, m);
972 goto transmit;
973 }
974 if (MBUFQ_FIRST(&sc->sc_seqq)) {
975 MBUFQ_DEQUEUE(&sc->sc_seqq, m);
976 hdrp = mtod(m, bth5_hdr_t *);
977 hdrp->flags |= BTH5_FLAGS_PROTOCOL_REL; /* Reliable */
978 goto transmit;
979 }
980
981 s = spltty();
982 if ((sc->sc_flags & BTH5_XMIT) == 0)
983 bth5_start(sc);
984 splx(s);
985
986 if (sc->sc_mux_send_ack == true) {
987 m = bth5_create_ackpkt();
988 if (m != NULL)
989 goto transmit;
990 aprint_error_dev(sc->sc_dev, "out of memory\n");
991 sc->sc_stats.err_tx++;
992 }
993
994 /* Nothing to send */
995 DPRINTFN(2, ("\n"));
996
997 return;
998
999 transmit:
1000 DPRINTFN(2, (", txack=%d, send_ack=%d\n",
1001 bth5_get_txack(sc), sc->sc_mux_send_ack));
1002
1003 hdrp = mtod(m, bth5_hdr_t *);
1004 hdrp->flags |=
1005 (bth5_get_txack(sc) << BTH5_FLAGS_ACK_SHIFT) & BTH5_FLAGS_ACK_MASK;
1006 if (sc->sc_mux_send_ack == true)
1007 sc->sc_mux_send_ack = false;
1008
1009 #ifdef BTH5_DEBUG
1010 if (bth5_debug == 3)
1011 bth5_packet_print(m);
1012 #endif
1013
1014 sc->sc_txp = m;
1015 bth5_pktintegrity_transmit(sc);
1016 }
1017
1018 static void
bth5_mux_receive(struct bth5_softc * sc,struct mbuf * m)1019 bth5_mux_receive(struct bth5_softc *sc, struct mbuf *m)
1020 {
1021 bth5_hdr_t *hdrp = mtod(m, bth5_hdr_t *);
1022 const u_int rxack = BTH5_FLAGS_ACK(hdrp->flags);
1023
1024 DPRINTFN(2, ("%s: mux receive: flags=0x%x, ident=%d, rxack=%d\n",
1025 device_xname(sc->sc_dev), hdrp->flags, hdrp->ident, rxack));
1026 #ifdef BTH5_DEBUG
1027 if (bth5_debug == 3)
1028 bth5_packet_print(m);
1029 #endif
1030
1031 bth5_signal_rxack(sc, rxack);
1032
1033 microtime(&sc->sc_mux_lastrx);
1034
1035 /* if the Ack Packet received then discard */
1036 if (BTH5_FLAGS_SEQ(hdrp->flags) == 0 &&
1037 hdrp->ident == BTH5_IDENT_ACKPKT &&
1038 BTH5_GET_PLEN(hdrp) == 0) {
1039 sc->sc_seq_txseq = BTH5_FLAGS_ACK(hdrp->flags);
1040 bth5_send_ack_command(sc);
1041 bth5_mux_transmit(sc);
1042 m_freem(m);
1043 return;
1044 }
1045
1046 if (hdrp->flags & BTH5_FLAGS_PROTOCOL_REL)
1047 bth5_sequencing_receive(sc, m);
1048 else
1049 bth5_datagramq_receive(sc, m);
1050 }
1051
1052 static __inline void
bth5_send_ack_command(struct bth5_softc * sc)1053 bth5_send_ack_command(struct bth5_softc *sc)
1054 {
1055
1056 DPRINTFN(2, ("%s: mux send_ack_command\n", device_xname(sc->sc_dev)));
1057
1058 sc->sc_mux_send_ack = true;
1059 }
1060
1061 static __inline struct mbuf *
bth5_create_ackpkt(void)1062 bth5_create_ackpkt(void)
1063 {
1064 struct mbuf *m;
1065 bth5_hdr_t *hdrp;
1066
1067 MGETHDR(m, M_DONTWAIT, MT_DATA);
1068 if (m != NULL) {
1069 m->m_pkthdr.len = m->m_len = sizeof(bth5_hdr_t);
1070 hdrp = mtod(m, bth5_hdr_t *);
1071 /*
1072 * An Ack Packet has the following fields:
1073 * Ack Field: txack (not set yet)
1074 * Seq Field: 0
1075 * Protocol Identifier Field: 0
1076 * Protocol Type Field: Any value
1077 * Payload Length Field: 0
1078 */
1079 memset(hdrp, 0, sizeof(bth5_hdr_t));
1080 }
1081 return m;
1082 }
1083
1084 static __inline void
bth5_set_choke(struct bth5_softc * sc,bool choke)1085 bth5_set_choke(struct bth5_softc *sc, bool choke)
1086 {
1087
1088 DPRINTFN(2, ("%s: mux set choke=%d\n", device_xname(sc->sc_dev), choke));
1089
1090 sc->sc_mux_choke = choke;
1091 }
1092
1093
1094 /*
1095 * BTH5 Sequencing Layer functions
1096 */
1097 static void
bth5_sequencing_receive(struct bth5_softc * sc,struct mbuf * m)1098 bth5_sequencing_receive(struct bth5_softc *sc, struct mbuf *m)
1099 {
1100 bth5_hdr_t hdr;
1101 uint32_t exp_rxseq, rxack, rxseq;
1102
1103 exp_rxseq = sc->sc_seq_expected_rxseq & BTH5_FLAGS_SEQ_MASK;
1104 m_copydata(m, 0, sizeof(bth5_hdr_t), &hdr);
1105 rxseq = BTH5_FLAGS_SEQ(hdr.flags);
1106 rxack = BTH5_FLAGS_ACK(hdr.flags);
1107
1108 DPRINTFN(1, ("%s: seq receive: rxseq=%d, expected %d\n",
1109 device_xname(sc->sc_dev), rxseq, exp_rxseq));
1110 #ifdef BTH5_DEBUG
1111 if (bth5_debug == 2)
1112 bth5_packet_print(m);
1113 #endif
1114
1115 /*
1116 * We remove the header of BTH5 and add the 'uint8_t type' of
1117 * hci_*_hdr_t to the head.
1118 */
1119 m_adj(m, sizeof(bth5_hdr_t) - sizeof(uint8_t));
1120
1121 if (rxseq != exp_rxseq) {
1122 m_freem(m);
1123
1124 bth5_send_ack_command(sc);
1125 /* send ack packet, if needly */
1126 bth5_mux_transmit(sc);
1127
1128 return;
1129 }
1130
1131 switch (hdr.ident) {
1132 case BTH5_CHANNEL_HCI_CMD:
1133 *(mtod(m, uint8_t *)) = HCI_CMD_PKT;
1134 if (!hci_input_event(sc->sc_unit, m))
1135 sc->sc_stats.err_rx++;
1136
1137 sc->sc_stats.evt_rx++;
1138 break;
1139
1140 case BTH5_CHANNEL_HCI_EVT:
1141 *(mtod(m, uint8_t *)) = HCI_EVENT_PKT;
1142 if (!hci_input_event(sc->sc_unit, m))
1143 sc->sc_stats.err_rx++;
1144
1145 sc->sc_stats.evt_rx++;
1146 break;
1147
1148 case BTH5_CHANNEL_HCI_ACL:
1149 *(mtod(m, uint8_t *)) = HCI_ACL_DATA_PKT;
1150 if (!hci_input_acl(sc->sc_unit, m))
1151 sc->sc_stats.err_rx++;
1152
1153 sc->sc_stats.acl_rx++;
1154 break;
1155
1156 case BTH5_CHANNEL_HCI_SCO:
1157 *(mtod(m, uint8_t *)) = HCI_SCO_DATA_PKT;
1158 if (!hci_input_sco(sc->sc_unit, m))
1159 sc->sc_stats.err_rx++;
1160
1161 sc->sc_stats.sco_rx++;
1162 break;
1163
1164 default:
1165 aprint_error_dev(sc->sc_dev,
1166 "received reliable packet with not support channel %d\n",
1167 hdr.ident);
1168 m_freem(m);
1169 break;
1170 }
1171 bth5_send_ack_command(sc);
1172 sc->sc_seq_txseq = rxack;
1173 sc->sc_seq_expected_rxseq = (rxseq + 1) & BTH5_FLAGS_SEQ_MASK;
1174 sc->sc_seq_total_rxpkts++;
1175
1176 if (sc->sc_seq_total_rxpkts % sc->sc_seq_winack == 0)
1177 bth5_mux_transmit(sc);
1178 }
1179
1180 static bool
bth5_tx_reliable_pkt(struct bth5_softc * sc,struct mbuf * m,u_int protocol_id)1181 bth5_tx_reliable_pkt(struct bth5_softc *sc, struct mbuf *m, u_int protocol_id)
1182 {
1183 bth5_hdr_t *hdrp;
1184 struct mbuf *_m;
1185 struct mbuf *_retrans;
1186 u_int pldlen;
1187 int s;
1188
1189 DPRINTFN(1, ("%s: seq transmit:"
1190 "protocol_id=%d, winspace=%d, txseq=%d\n", device_xname(sc->sc_dev),
1191 protocol_id, sc->sc_seq_winspace, sc->sc_seq_txseq));
1192
1193 for (pldlen = 0, _m = m; _m != NULL; _m = _m->m_next) {
1194 if (_m->m_len < 0)
1195 goto out;
1196 pldlen += _m->m_len;
1197 }
1198 if (pldlen > 0xfff)
1199 goto out;
1200 if (protocol_id == BTH5_IDENT_ACKPKT || protocol_id > 15)
1201 goto out;
1202
1203 if (sc->sc_seq_winspace == 0)
1204 goto out;
1205
1206 M_PREPEND(m, sizeof(bth5_hdr_t), M_DONTWAIT);
1207 if (m == NULL) {
1208 aprint_error_dev(sc->sc_dev, "out of memory\n");
1209 return false;
1210 }
1211 KASSERT(m->m_len >= sizeof(bth5_hdr_t));
1212
1213 hdrp = mtod(m, bth5_hdr_t *);
1214 memset(hdrp, 0, sizeof(bth5_hdr_t));
1215 hdrp->flags |= sc->sc_seq_txseq;
1216 hdrp->ident = protocol_id;
1217
1218 callout_schedule(&sc->sc_seq_timer, sc->sc_seq_timeout);
1219
1220 s = splserial();
1221 MBUFQ_ENQUEUE(&sc->sc_seqq, m);
1222 splx(s);
1223 sc->sc_transmit_callback = bth5_reliabletx_callback;
1224
1225 #ifdef BTH5_DEBUG
1226 if (bth5_debug == 2)
1227 bth5_packet_print(m);
1228 #endif
1229
1230 sc->sc_seq_winspace--;
1231 _retrans = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
1232 if (_retrans == NULL) {
1233 aprint_error_dev(sc->sc_dev, "out of memory\n");
1234 goto out;
1235 }
1236 MBUFQ_ENQUEUE(&sc->sc_seq_retryq, _retrans);
1237 bth5_mux_transmit(sc);
1238 sc->sc_seq_txseq = (sc->sc_seq_txseq + 1) & BTH5_FLAGS_SEQ_MASK;
1239
1240 return true;
1241 out:
1242 m_freem(m);
1243 return false;
1244 }
1245
1246 static __inline u_int
bth5_get_txack(struct bth5_softc * sc)1247 bth5_get_txack(struct bth5_softc *sc)
1248 {
1249
1250 return sc->sc_seq_expected_rxseq;
1251 }
1252
1253 static void
bth5_signal_rxack(struct bth5_softc * sc,uint32_t rxack)1254 bth5_signal_rxack(struct bth5_softc *sc, uint32_t rxack)
1255 {
1256 bth5_hdr_t *hdrp;
1257 struct mbuf *m;
1258 uint32_t seqno = (rxack - 1) & BTH5_FLAGS_SEQ_MASK;
1259 int s;
1260
1261 DPRINTFN(1, ("%s: seq signal rxack: rxack=%d\n",
1262 device_xname(sc->sc_dev), rxack));
1263
1264 s = splserial();
1265 m = MBUFQ_FIRST(&sc->sc_seq_retryq);
1266 while (m != NULL) {
1267 hdrp = mtod(m, bth5_hdr_t *);
1268 if (BTH5_FLAGS_SEQ(hdrp->flags) == seqno) {
1269 struct mbuf *m0;
1270
1271 for (m0 = MBUFQ_FIRST(&sc->sc_seq_retryq);
1272 m0 != MBUFQ_NEXT(m);
1273 m0 = MBUFQ_FIRST(&sc->sc_seq_retryq)) {
1274 MBUFQ_DEQUEUE(&sc->sc_seq_retryq, m0);
1275 m_freem(m0);
1276 sc->sc_seq_winspace++;
1277 if (sc->sc_seq_winspace > sc->sc_seq_winsize)
1278 sc->sc_seq_winspace = sc->sc_seq_winsize;
1279 }
1280 break;
1281 }
1282 m = MBUFQ_NEXT(m);
1283 }
1284 splx(s);
1285 sc->sc_seq_retries = 0;
1286
1287 if (sc->sc_seq_winspace == sc->sc_seq_winsize)
1288 callout_stop(&sc->sc_seq_timer);
1289 else
1290 callout_schedule(&sc->sc_seq_timer, sc->sc_seq_timeout);
1291 }
1292
1293 static void
bth5_reliabletx_callback(struct bth5_softc * sc,struct mbuf * m)1294 bth5_reliabletx_callback(struct bth5_softc *sc, struct mbuf *m)
1295 {
1296
1297 m_freem(m);
1298 }
1299
1300 static void
bth5_timer_timeout(void * arg)1301 bth5_timer_timeout(void *arg)
1302 {
1303 struct bth5_softc *sc = arg;
1304 struct mbuf *m, *_m;
1305 int s, i = 0;
1306
1307 DPRINTFN(1, ("%s: seq timeout: retries=%d\n",
1308 device_xname(sc->sc_dev), sc->sc_seq_retries));
1309
1310 bth5_send_ack_command(sc);
1311 bth5_mux_transmit(sc);
1312 s = splserial();
1313 for (m = MBUFQ_FIRST(&sc->sc_seq_retryq); m != NULL;
1314 m = MBUFQ_NEXT(m)) {
1315 _m = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
1316 if (_m == NULL) {
1317 aprint_error_dev(sc->sc_dev, "out of memory\n");
1318 return;
1319 }
1320 MBUFQ_ENQUEUE(&sc->sc_seqq, _m);
1321 i++;
1322 }
1323 splx(s);
1324
1325 if (i != 0) {
1326 if (++sc->sc_seq_retries < sc->sc_seq_retry_limit)
1327 callout_schedule(&sc->sc_seq_timer, sc->sc_seq_timeout);
1328 else {
1329 aprint_error_dev(sc->sc_dev,
1330 "reached the retry limit."
1331 " restart the link-establishment\n");
1332 bth5_sequencing_reset(sc);
1333 bth5_start_le(sc);
1334 return;
1335 }
1336 }
1337 bth5_mux_transmit(sc);
1338 }
1339
1340 static void
bth5_sequencing_reset(struct bth5_softc * sc)1341 bth5_sequencing_reset(struct bth5_softc *sc)
1342 {
1343 int s;
1344
1345 s = splserial();
1346 MBUFQ_DRAIN(&sc->sc_seqq);
1347 MBUFQ_DRAIN(&sc->sc_seq_retryq);
1348 splx(s);
1349
1350
1351 sc->sc_seq_txseq = 0;
1352 sc->sc_seq_winspace = sc->sc_seq_winsize;
1353 sc->sc_seq_retries = 0;
1354 callout_stop(&sc->sc_seq_timer);
1355
1356 sc->sc_mux_send_ack = false;
1357
1358 /* XXXX: expected_rxseq should be set by MUX Layer */
1359 sc->sc_seq_expected_rxseq = 0;
1360 sc->sc_seq_total_rxpkts = 0;
1361 }
1362
1363
1364 /*
1365 * BTH5 Datagram Queue Layer functions
1366 */
1367 static void
bth5_datagramq_receive(struct bth5_softc * sc,struct mbuf * m)1368 bth5_datagramq_receive(struct bth5_softc *sc, struct mbuf *m)
1369 {
1370 bth5_hdr_t hdr;
1371
1372 DPRINTFN(1, ("%s: dgq receive\n", device_xname(sc->sc_dev)));
1373 #ifdef BTH5_DEBUG
1374 if (bth5_debug == 2)
1375 bth5_packet_print(m);
1376 #endif
1377
1378 m_copydata(m, 0, sizeof(bth5_hdr_t), &hdr);
1379
1380 switch (hdr.ident) {
1381 case BTH5_CHANNEL_LE:
1382 m_adj(m, sizeof(bth5_hdr_t));
1383 bth5_input_le(sc, m);
1384 break;
1385
1386 case BTH5_CHANNEL_HCI_SCO:
1387 /*
1388 * We remove the header of BTH5 and add the 'uint8_t type' of
1389 * hci_scodata_hdr_t to the head.
1390 */
1391 m_adj(m, sizeof(bth5_hdr_t) - sizeof(uint8_t));
1392 *(mtod(m, uint8_t *)) = HCI_SCO_DATA_PKT;
1393 if (!hci_input_sco(sc->sc_unit, m))
1394 sc->sc_stats.err_rx++;
1395
1396 sc->sc_stats.sco_rx++;
1397 break;
1398
1399 default:
1400 aprint_error_dev(sc->sc_dev,
1401 "received unreliable packet with not support channel %d\n",
1402 hdr.ident);
1403 m_freem(m);
1404 break;
1405 }
1406 }
1407
1408 static bool
bth5_tx_unreliable_pkt(struct bth5_softc * sc,struct mbuf * m,u_int protocol_id)1409 bth5_tx_unreliable_pkt(struct bth5_softc *sc, struct mbuf *m, u_int protocol_id)
1410 {
1411 bth5_hdr_t *hdrp;
1412 struct mbuf *_m;
1413 u_int pldlen;
1414 int s;
1415
1416 DPRINTFN(1, ("%s: dgq transmit: protocol_id=%d,",
1417 device_xname(sc->sc_dev), protocol_id));
1418
1419 for (pldlen = 0, _m = m; _m != NULL; _m = m->m_next) {
1420 if (_m->m_len < 0)
1421 goto out;
1422 pldlen += _m->m_len;
1423 }
1424 DPRINTFN(1, (" pldlen=%d\n", pldlen));
1425 if (pldlen > 0xfff)
1426 goto out;
1427 if (protocol_id == BTH5_IDENT_ACKPKT || protocol_id > 15)
1428 goto out;
1429
1430 M_PREPEND(m, sizeof(bth5_hdr_t), M_DONTWAIT);
1431 if (m == NULL) {
1432 aprint_error_dev(sc->sc_dev, "out of memory\n");
1433 return false;
1434 }
1435 KASSERT(m->m_len >= sizeof(bth5_hdr_t));
1436
1437 hdrp = mtod(m, bth5_hdr_t *);
1438 memset(hdrp, 0, sizeof(bth5_hdr_t));
1439 hdrp->ident = protocol_id;
1440
1441 s = splserial();
1442 MBUFQ_ENQUEUE(&sc->sc_dgq, m);
1443 splx(s);
1444 sc->sc_transmit_callback = bth5_unreliabletx_callback;
1445
1446 #ifdef BTH5_DEBUG
1447 if (bth5_debug == 2)
1448 bth5_packet_print(m);
1449 #endif
1450
1451 bth5_mux_transmit(sc);
1452
1453 return true;
1454 out:
1455 m_freem(m);
1456 return false;
1457 }
1458
1459 static void
bth5_unreliabletx_callback(struct bth5_softc * sc,struct mbuf * m)1460 bth5_unreliabletx_callback(struct bth5_softc *sc, struct mbuf *m)
1461 {
1462
1463 if (M_GETCTX(m, void *) == NULL)
1464 m_freem(m);
1465 else if (!hci_complete_sco(sc->sc_unit, m))
1466 sc->sc_stats.err_tx++;
1467 }
1468
1469
1470 /*
1471 * BTUART H5 Link Establishment Protocol functions
1472 */
1473 static const uint8_t sync[] = BTH5_LE_SYNC;
1474 static const uint8_t syncresp[] = BTH5_LE_SYNCRESP;
1475 static const uint8_t conf[] = BTH5_LE_CONF;
1476 static const uint8_t confresp[] = BTH5_LE_CONFRESP;
1477
1478 static int
bth5_start_le(struct bth5_softc * sc)1479 bth5_start_le(struct bth5_softc *sc)
1480 {
1481
1482 DPRINTF(("%s: start link-establish\n", device_xname(sc->sc_dev)));
1483
1484 bth5_set_choke(sc, true);
1485
1486 if (!sc->sc_le_muzzled) {
1487 struct mbuf *m;
1488
1489 m = m_gethdr(M_DONTWAIT, MT_DATA);
1490 if (m == NULL) {
1491 aprint_error_dev(sc->sc_dev,
1492 "le-packet transmit out of memory\n");
1493 return ENOMEM;
1494 }
1495 m->m_pkthdr.len = m->m_len = 0;
1496 m_copyback(m, 0, sizeof(sync), sync);
1497 if (!bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_LE)) {
1498 aprint_error_dev(sc->sc_dev,
1499 "le-packet transmit failed\n");
1500 return EINVAL;
1501 }
1502 }
1503 callout_schedule(&sc->sc_le_timer, BTH5_LE_TSHY_TIMEOUT);
1504
1505 sc->sc_le_state = le_state_shy;
1506 return 0;
1507 }
1508
1509 static void
bth5_terminate_le(struct bth5_softc * sc)1510 bth5_terminate_le(struct bth5_softc *sc)
1511 {
1512 struct mbuf *m;
1513
1514 /* terminate link-establishment */
1515 callout_stop(&sc->sc_le_timer);
1516 bth5_set_choke(sc, true);
1517 MGETHDR(m, M_DONTWAIT, MT_DATA);
1518 if (m == NULL)
1519 aprint_error_dev(sc->sc_dev, "out of memory\n");
1520 else {
1521 /* length of le packets is 4 */
1522 m->m_pkthdr.len = m->m_len = 0;
1523 m_copyback(m, 0, sizeof(sync), sync);
1524 if (!bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_LE))
1525 aprint_error_dev(sc->sc_dev,
1526 "link-establishment terminations failed\n");
1527 }
1528 }
1529
1530 static void
bth5_input_le(struct bth5_softc * sc,struct mbuf * m)1531 bth5_input_le(struct bth5_softc *sc, struct mbuf *m)
1532 {
1533 uint16_t *rcvpkt;
1534 int i, len;
1535 uint8_t config[3];
1536 const uint8_t *rplypkt;
1537 static struct {
1538 const char *type;
1539 const uint8_t *datap;
1540 } pkt[] = {
1541 { "sync", sync },
1542 { "sync-resp", syncresp },
1543 { "conf", conf },
1544 { "conf-resp", confresp },
1545
1546 { NULL, 0 }
1547 };
1548
1549 DPRINTFN(0, ("%s: le input: state %d, muzzled %d\n",
1550 device_xname(sc->sc_dev), sc->sc_le_state, sc->sc_le_muzzled));
1551 #ifdef BTH5_DEBUG
1552 if (bth5_debug == 1)
1553 bth5_packet_print(m);
1554 #endif
1555
1556 rcvpkt = mtod(m, uint16_t *);
1557 i = 0;
1558
1559 /* length of le packets is 2 */
1560 if (m->m_len >= sizeof(uint16_t))
1561 for (i = 0; pkt[i].type != NULL; i++)
1562 if (*(const uint16_t *)pkt[i].datap == *rcvpkt)
1563 break;
1564 if (m->m_len < sizeof(uint16_t) || pkt[i].type == NULL) {
1565 aprint_error_dev(sc->sc_dev, "received unknown packet\n");
1566 m_freem(m);
1567 return;
1568 }
1569
1570 len = m->m_len;
1571
1572 rplypkt = NULL;
1573 switch (sc->sc_le_state) {
1574 case le_state_shy:
1575 if (*rcvpkt == *(const uint16_t *)sync) {
1576 sc->sc_le_muzzled = false;
1577 rplypkt = syncresp;
1578 } else if (*rcvpkt == *(const uint16_t *)syncresp) {
1579 DPRINTF(("%s: state change to curious\n",
1580 device_xname(sc->sc_dev)));
1581 rplypkt = conf;
1582 callout_schedule(&sc->sc_le_timer,
1583 BTH5_LE_TCONF_TIMEOUT);
1584 sc->sc_le_state = le_state_curious;
1585 } else
1586 aprint_error_dev(sc->sc_dev,
1587 "received an unknown packet at shy\n");
1588 break;
1589
1590 case le_state_curious:
1591 if (*rcvpkt == *(const uint16_t *)sync)
1592 rplypkt = syncresp;
1593 else if (*rcvpkt == *(const uint16_t *)syncresp) {
1594 rplypkt = conf;
1595 len = 3;
1596 }
1597 else if (*rcvpkt == *(const uint16_t *)conf)
1598 rplypkt = confresp;
1599 else if (*rcvpkt == *(const uint16_t *)confresp &&
1600 m->m_len == 3) {
1601 DPRINTF(("%s: state change to garrulous:\n",
1602 device_xname(sc->sc_dev)));
1603
1604 memcpy(config, conf, sizeof(uint16_t));
1605 config[2] = (uint8_t)rcvpkt[1];
1606 sc->sc_seq_winack = config[2] & BTH5_CONFIG_ACK_MASK;
1607 if (config[2] & BTH5_CONFIG_FLOW_MASK)
1608 sc->sc_oof_flow_control = true;
1609 else
1610 sc->sc_oof_flow_control = false;
1611
1612 bth5_sequencing_reset(sc);
1613 bth5_set_choke(sc, false);
1614 callout_stop(&sc->sc_le_timer);
1615 sc->sc_le_state = le_state_garrulous;
1616 } else
1617 aprint_error_dev(sc->sc_dev,
1618 "received unknown packet at curious\n");
1619 break;
1620
1621 case le_state_garrulous:
1622 if (*rcvpkt == *(const uint16_t *)conf)
1623 rplypkt = confresp;
1624 else if (*rcvpkt == *(const uint16_t *)sync) {
1625 /* XXXXX */
1626 aprint_error_dev(sc->sc_dev,
1627 "received sync! peer to reset?\n");
1628
1629 bth5_sequencing_reset(sc);
1630 rplypkt = syncresp;
1631 sc->sc_le_state = le_state_shy;
1632 } else
1633 aprint_error_dev(sc->sc_dev,
1634 "received unknown packet at garrulous\n");
1635 break;
1636 }
1637
1638 m_freem(m);
1639
1640 if (rplypkt != NULL) {
1641 MGETHDR(m, M_DONTWAIT, MT_DATA);
1642 if (m == NULL)
1643 aprint_error_dev(sc->sc_dev, "out of memory\n");
1644 else {
1645 /* length of le packets is 2 */
1646 m->m_pkthdr.len = m->m_len = 0;
1647 if (rplypkt == (const uint8_t *)&config
1648 || rplypkt == confresp || rplypkt == conf)
1649 m_copyback(m, 0, len, rplypkt);
1650 else
1651 m_copyback(m, 0, 2, rplypkt);
1652 if (!bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_LE))
1653 aprint_error_dev(sc->sc_dev,
1654 "le-packet transmit failed\n");
1655 }
1656 }
1657 }
1658
1659 static void
bth5_le_timeout(void * arg)1660 bth5_le_timeout(void *arg)
1661 {
1662 struct bth5_softc *sc = arg;
1663 struct mbuf *m;
1664 int timeout;
1665 const uint8_t *sndpkt = NULL;
1666
1667 DPRINTFN(0, ("%s: le timeout: state %d, muzzled %d\n",
1668 device_xname(sc->sc_dev), sc->sc_le_state, sc->sc_le_muzzled));
1669
1670 switch (sc->sc_le_state) {
1671 case le_state_shy:
1672 if (!sc->sc_le_muzzled)
1673 sndpkt = sync;
1674 timeout = BTH5_LE_TSHY_TIMEOUT;
1675 break;
1676
1677 case le_state_curious:
1678 sndpkt = conf;
1679 timeout = BTH5_LE_TCONF_TIMEOUT;
1680 break;
1681
1682 default:
1683 aprint_error_dev(sc->sc_dev,
1684 "timeout happen at unknown state %d\n", sc->sc_le_state);
1685 return;
1686 }
1687
1688 if (sndpkt != NULL) {
1689 MGETHDR(m, M_DONTWAIT, MT_DATA);
1690 if (m == NULL)
1691 aprint_error_dev(sc->sc_dev, "out of memory\n");
1692 else {
1693 /* length of le packets is 4 */
1694 m->m_pkthdr.len = m->m_len = 0;
1695 if (sndpkt == conf || sndpkt == confresp)
1696 m_copyback(m, 0, 3, sndpkt);
1697 else
1698 m_copyback(m, 0, 2, sndpkt);
1699 if (!bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_LE))
1700 aprint_error_dev(sc->sc_dev,
1701 "le-packet transmit failed\n");
1702 }
1703 }
1704
1705 callout_schedule(&sc->sc_le_timer, timeout);
1706 }
1707
1708
1709 /*
1710 * BTUART H5 Serial Protocol functions.
1711 */
1712 static int
bth5_enable(device_t self)1713 bth5_enable(device_t self)
1714 {
1715 struct bth5_softc *sc = device_private(self);
1716 int s;
1717
1718 if (sc->sc_flags & BTH5_ENABLED)
1719 return 0;
1720
1721 s = spltty();
1722
1723 sc->sc_flags |= BTH5_ENABLED;
1724 sc->sc_flags &= ~BTH5_XMIT;
1725
1726 splx(s);
1727
1728 return 0;
1729 }
1730
1731 static void
bth5_disable(device_t self)1732 bth5_disable(device_t self)
1733 {
1734 struct bth5_softc *sc = device_private(self);
1735 int s;
1736
1737 if ((sc->sc_flags & BTH5_ENABLED) == 0)
1738 return;
1739
1740 s = spltty();
1741
1742 m_freem(sc->sc_rxp);
1743 sc->sc_rxp = NULL;
1744
1745 m_freem(sc->sc_txp);
1746 sc->sc_txp = NULL;
1747
1748 MBUFQ_DRAIN(&sc->sc_cmdq);
1749 MBUFQ_DRAIN(&sc->sc_aclq);
1750 MBUFQ_DRAIN(&sc->sc_scoq);
1751
1752 sc->sc_flags &= ~BTH5_ENABLED;
1753 splx(s);
1754 }
1755
1756 static void
bth5_start(struct bth5_softc * sc)1757 bth5_start(struct bth5_softc *sc)
1758 {
1759 struct mbuf *m;
1760
1761 KASSERT((sc->sc_flags & BTH5_XMIT) == 0);
1762 KASSERT(sc->sc_txp == NULL);
1763
1764 if (MBUFQ_FIRST(&sc->sc_aclq)) {
1765 MBUFQ_DEQUEUE(&sc->sc_aclq, m);
1766 sc->sc_stats.acl_tx++;
1767 sc->sc_flags |= BTH5_XMIT;
1768 bth5_tx_reliable_pkt(sc, m, BTH5_CHANNEL_HCI_ACL);
1769 }
1770
1771 if (MBUFQ_FIRST(&sc->sc_cmdq)) {
1772 MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
1773 sc->sc_stats.cmd_tx++;
1774 sc->sc_flags |= BTH5_XMIT;
1775 bth5_tx_reliable_pkt(sc, m, BTH5_CHANNEL_HCI_CMD);
1776 }
1777
1778 if (MBUFQ_FIRST(&sc->sc_scoq)) {
1779 MBUFQ_DEQUEUE(&sc->sc_scoq, m);
1780 sc->sc_stats.sco_tx++;
1781 /* XXXX: We can transmit with reliable */
1782 sc->sc_flags |= BTH5_XMIT;
1783 bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_HCI_SCO);
1784 }
1785
1786 return;
1787 }
1788
1789 static void
bth5_output_cmd(device_t self,struct mbuf * m)1790 bth5_output_cmd(device_t self, struct mbuf *m)
1791 {
1792 struct bth5_softc *sc = device_private(self);
1793 int s;
1794
1795 KASSERT(sc->sc_flags & BTH5_ENABLED);
1796
1797 m_adj(m, sizeof(uint8_t));
1798 M_SETCTX(m, NULL);
1799
1800 s = spltty();
1801 MBUFQ_ENQUEUE(&sc->sc_cmdq, m);
1802 if ((sc->sc_flags & BTH5_XMIT) == 0)
1803 bth5_start(sc);
1804
1805 splx(s);
1806 }
1807
1808 static void
bth5_output_acl(device_t self,struct mbuf * m)1809 bth5_output_acl(device_t self, struct mbuf *m)
1810 {
1811 struct bth5_softc *sc = device_private(self);
1812 int s;
1813
1814 KASSERT(sc->sc_flags & BTH5_ENABLED);
1815
1816 m_adj(m, sizeof(uint8_t));
1817 M_SETCTX(m, NULL);
1818
1819 s = spltty();
1820 MBUFQ_ENQUEUE(&sc->sc_aclq, m);
1821 if ((sc->sc_flags & BTH5_XMIT) == 0)
1822 bth5_start(sc);
1823
1824 splx(s);
1825 }
1826
1827 static void
bth5_output_sco(device_t self,struct mbuf * m)1828 bth5_output_sco(device_t self, struct mbuf *m)
1829 {
1830 struct bth5_softc *sc = device_private(self);
1831 int s;
1832
1833 KASSERT(sc->sc_flags & BTH5_ENABLED);
1834
1835 m_adj(m, sizeof(uint8_t));
1836
1837 s = spltty();
1838 MBUFQ_ENQUEUE(&sc->sc_scoq, m);
1839 if ((sc->sc_flags & BTH5_XMIT) == 0)
1840 bth5_start(sc);
1841
1842 splx(s);
1843 }
1844
1845 static void
bth5_stats(device_t self,struct bt_stats * dest,int flush)1846 bth5_stats(device_t self, struct bt_stats *dest, int flush)
1847 {
1848 struct bth5_softc *sc = device_private(self);
1849 int s;
1850
1851 s = spltty();
1852 memcpy(dest, &sc->sc_stats, sizeof(struct bt_stats));
1853
1854 if (flush)
1855 memset(&sc->sc_stats, 0, sizeof(struct bt_stats));
1856
1857 splx(s);
1858 }
1859
1860
1861 #ifdef BTH5_DEBUG
1862 static void
bth5_packet_print(struct mbuf * m)1863 bth5_packet_print(struct mbuf *m)
1864 {
1865 int i;
1866 uint8_t *p;
1867
1868 for ( ; m != NULL; m = m->m_next) {
1869 p = mtod(m, uint8_t *);
1870 for (i = 0; i < m->m_len; i++) {
1871 if (i % 16 == 0)
1872 printf(" ");
1873 printf(" %02x", *(p + i));
1874 if (i % 16 == 15)
1875 printf("\n");
1876 }
1877 printf("\n");
1878 }
1879 }
1880 #endif
1881