bth5.c revision 1.5.6.1 1 /* $NetBSD: bth5.c,v 1.5.6.1 2020/04/13 08:04:19 martin Exp $ */
2 /*
3 * Copyright (c) 2017 Nathanial Sloss <nathanialsloss (at) 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.5.6.1 2020/04/13 08:04:19 martin 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
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
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
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
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
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 KASSERT(tp->t_oproc != NULL);
396
397 cfdata = malloc(sizeof(struct cfdata), M_DEVBUF, M_WAITOK);
398 for (unit = 0; unit < bthfive_cd.cd_ndevs; unit++)
399 if (device_lookup(&bthfive_cd, unit) == NULL)
400 break;
401 cfdata->cf_name = name;
402 cfdata->cf_atname = name;
403 cfdata->cf_unit = unit;
404 cfdata->cf_fstate = FSTATE_STAR;
405
406 aprint_normal("%s%d at tty major %llu minor %llu",
407 name, unit, (unsigned long long)major(tp->t_dev),
408 (unsigned long long)minor(tp->t_dev));
409 dev = config_attach_pseudo(cfdata);
410 if (dev == NULL) {
411 splx(s);
412 return EIO;
413 }
414 sc = device_private(dev);
415
416 mutex_spin_enter(&tty_lock);
417 tp->t_sc = sc;
418 sc->sc_tp = tp;
419 ttyflush(tp, FREAD | FWRITE);
420 mutex_spin_exit(&tty_lock);
421
422 splx(s);
423
424 sc->sc_slip_txrsv = BTH5_SLIP_PKTSTART;
425 bth5_sequencing_reset(sc);
426
427 /* start link-establishment */
428 bth5_start_le(sc);
429
430 return 0;
431 }
432
433 /* ARGSUSED */
434 static int
435 bth5close(struct tty *tp, int flag __unused)
436 {
437 struct bth5_softc *sc = tp->t_sc;
438 cfdata_t cfdata;
439 int s;
440
441 /* terminate link-establishment */
442 bth5_terminate_le(sc);
443
444 s = spltty();
445
446 MBUFQ_DRAIN(&sc->sc_dgq);
447 bth5_sequencing_reset(sc);
448
449 mutex_spin_enter(&tty_lock);
450 ttyflush(tp, FREAD | FWRITE);
451 mutex_spin_exit(&tty_lock); /* XXX */
452 ttyldisc_release(tp->t_linesw);
453 tp->t_linesw = ttyldisc_default();
454 if (sc != NULL) {
455 tp->t_sc = NULL;
456 if (sc->sc_tp == tp) {
457 cfdata = device_cfdata(sc->sc_dev);
458 config_detach(sc->sc_dev, 0);
459 free(cfdata, M_DEVBUF);
460 }
461
462 }
463 splx(s);
464 return 0;
465 }
466
467 /* ARGSUSED */
468 static int
469 bth5ioctl(struct tty *tp, u_long cmd, void *data, int flag __unused,
470 struct lwp *l __unused)
471 {
472 struct bth5_softc *sc = tp->t_sc;
473 int error;
474
475 if (sc == NULL || tp != sc->sc_tp)
476 return EPASSTHROUGH;
477
478 error = 0;
479 switch (cmd) {
480 default:
481 error = EPASSTHROUGH;
482 break;
483 }
484
485 return error;
486 }
487
488
489 /*
490 * UART Driver Layer is supported by com-driver.
491 */
492
493 /*
494 * BTH5 SLIP Layer functions:
495 * Supports to transmit/receive a byte stream.
496 * SLIP protocol described in Internet standard RFC 1055.
497 */
498 static int
499 bth5_slip_transmit(struct tty *tp)
500 {
501 struct bth5_softc *sc = tp->t_sc;
502 struct mbuf *m;
503 int count, rlen;
504 uint8_t *rptr;
505 int s;
506
507 m = sc->sc_txp;
508 if (m == NULL) {
509 s = spltty();
510 sc->sc_flags &= ~BTH5_XMIT;
511 splx(s);
512 bth5_mux_transmit(sc);
513 return 0;
514 }
515
516 count = 0;
517 rlen = 0;
518 rptr = mtod(m, uint8_t *);
519
520 if (sc->sc_slip_txrsv != 0) {
521 #ifdef BTH5_DEBUG
522 if (sc->sc_slip_txrsv == BTH5_SLIP_PKTSTART)
523 DPRINTFN(4, ("%s: slip transmit start\n",
524 device_xname(sc->sc_dev)));
525 else
526 DPRINTFN(4, ("0x%02x ", sc->sc_slip_txrsv));
527 #endif
528
529 if (putc(sc->sc_slip_txrsv, &tp->t_outq) < 0)
530 return 0;
531 count++;
532
533 if (sc->sc_slip_txrsv == BTH5_SLIP_ESCAPE_PKTEND ||
534 sc->sc_slip_txrsv == BTH5_SLIP_ESCAPE_ESCAPE) {
535 rlen++;
536 rptr++;
537 }
538 if (sc->sc_oof_flow_control == true) {
539 if (sc->sc_slip_txrsv == BTH5_SLIP_ESCAPE_XON ||
540 sc->sc_slip_txrsv == BTH5_SLIP_ESCAPE_XOFF) {
541 rlen++;
542 rptr++;
543 }
544 }
545
546 sc->sc_slip_txrsv = 0;
547 }
548
549 for(;;) {
550 if (rlen >= m->m_len) {
551 m = m->m_next;
552 if (m == NULL) {
553 if (putc(BTH5_SLIP_PKTEND, &tp->t_outq) < 0)
554 break;
555
556 DPRINTFN(4, ("\n%s: slip transmit end\n",
557 device_xname(sc->sc_dev)));
558
559 m = sc->sc_txp;
560 sc->sc_txp = NULL;
561 sc->sc_slip_txrsv = BTH5_SLIP_PKTSTART;
562
563 sc->sc_transmit_callback(sc, m);
564 m = NULL;
565 break;
566 }
567
568 rlen = 0;
569 rptr = mtod(m, uint8_t *);
570 continue;
571 }
572
573 if (*rptr == BTH5_SLIP_PKTEND) {
574 if (putc(BTH5_SLIP_ESCAPE, &tp->t_outq) < 0)
575 break;
576 count++;
577 DPRINTFN(4, (" esc "));
578
579 if (putc(BTH5_SLIP_ESCAPE_PKTEND, &tp->t_outq) < 0) {
580 sc->sc_slip_txrsv = BTH5_SLIP_ESCAPE_PKTEND;
581 break;
582 }
583 DPRINTFN(4, ("0x%02x ", BTH5_SLIP_ESCAPE_PKTEND));
584 rptr++;
585 } else if (sc->sc_oof_flow_control == true && *rptr ==
586 BTH5_SLIP_XON) {
587 if (putc(BTH5_SLIP_ESCAPE, &tp->t_outq) < 0)
588 break;
589 count++;
590 DPRINTFN(4, (" esc "));
591
592 if (putc(BTH5_SLIP_ESCAPE_XON, &tp->t_outq) < 0) {
593 sc->sc_slip_txrsv = BTH5_SLIP_ESCAPE_XON;
594 break;
595 }
596 DPRINTFN(4, ("0x%02x ", BTH5_SLIP_ESCAPE_XON));
597 rptr++;
598 } else if (sc->sc_oof_flow_control == true && *rptr ==
599 BTH5_SLIP_XOFF) {
600 if (putc(BTH5_SLIP_ESCAPE, &tp->t_outq) < 0)
601 break;
602 count++;
603 DPRINTFN(4, (" esc "));
604
605 if (putc(BTH5_SLIP_ESCAPE_XOFF, &tp->t_outq) < 0) {
606 sc->sc_slip_txrsv = BTH5_SLIP_ESCAPE_XOFF;
607 break;
608 }
609 DPRINTFN(4, ("0x%02x ", BTH5_SLIP_ESCAPE_XOFF));
610 rptr++;
611 } else if (*rptr == BTH5_SLIP_ESCAPE) {
612 if (putc(BTH5_SLIP_ESCAPE, &tp->t_outq) < 0)
613 break;
614 count++;
615 DPRINTFN(4, (" esc "));
616
617 if (putc(BTH5_SLIP_ESCAPE_ESCAPE, &tp->t_outq) < 0) {
618 sc->sc_slip_txrsv = BTH5_SLIP_ESCAPE_ESCAPE;
619 break;
620 }
621 DPRINTFN(4, ("0x%02x ", BTH5_SLIP_ESCAPE_ESCAPE));
622 rptr++;
623 } else {
624 if (putc(*rptr++, &tp->t_outq) < 0)
625 break;
626 DPRINTFN(4, ("0x%02x ", *(rptr - 1)));
627 }
628 rlen++;
629 count++;
630 }
631 if (m != NULL)
632 m_adj(m, rlen);
633
634 sc->sc_stats.byte_tx += count;
635
636 if (tp->t_outq.c_cc != 0)
637 (*tp->t_oproc)(tp);
638
639 return 0;
640 }
641
642 static int
643 bth5_slip_receive(int c, struct tty *tp)
644 {
645 struct bth5_softc *sc = tp->t_sc;
646 struct mbuf *m = sc->sc_rxp;
647 int discard = 0;
648 const char *errstr;
649
650 c &= TTY_CHARMASK;
651
652 /* If we already started a packet, find the trailing end of it. */
653 if (m) {
654 while (m->m_next)
655 m = m->m_next;
656
657 if (M_TRAILINGSPACE(m) == 0) {
658 /* extend mbuf */
659 MGET(m->m_next, M_DONTWAIT, MT_DATA);
660 if (m->m_next == NULL) {
661 aprint_error_dev(sc->sc_dev,
662 "out of memory\n");
663 sc->sc_stats.err_rx++;
664 return 0; /* (lost sync) */
665 }
666
667 m = m->m_next;
668 m->m_len = 0;
669 }
670 } else
671 if (c != BTH5_SLIP_PKTSTART) {
672 discard = 1;
673 errstr = "not sync";
674 goto discarded;
675 }
676
677 switch (c) {
678 case BTH5_SLIP_PKTSTART /* or _PKTEND */:
679 if (m == NULL) {
680 /* BTH5_SLIP_PKTSTART */
681
682 DPRINTFN(4, ("%s: slip receive start\n",
683 device_xname(sc->sc_dev)));
684
685 /* new packet */
686 MGETHDR(m, M_DONTWAIT, MT_DATA);
687 if (m == NULL) {
688 aprint_error_dev(sc->sc_dev,
689 "out of memory\n");
690 sc->sc_stats.err_rx++;
691 return 0; /* (lost sync) */
692 }
693
694 sc->sc_rxp = m;
695 m->m_pkthdr.len = m->m_len = 0;
696 sc->sc_slip_rxexp = 0;
697 } else {
698 /* BTH5_SLIP_PKTEND */
699
700 if (m == sc->sc_rxp && m->m_len == 0) {
701 DPRINTFN(4, ("%s: resynchronises\n",
702 device_xname(sc->sc_dev)));
703
704 sc->sc_stats.byte_rx++;
705 return 0;
706 }
707
708 DPRINTFN(4, ("%s%s: slip receive end\n",
709 (m->m_len % 16 != 0) ? "\n" : "",
710 device_xname(sc->sc_dev)));
711
712 bth5_pktintegrity_receive(sc, sc->sc_rxp);
713 sc->sc_rxp = NULL;
714 sc->sc_slip_rxexp = BTH5_SLIP_PKTSTART;
715 }
716 sc->sc_stats.byte_rx++;
717 return 0;
718
719 case BTH5_SLIP_ESCAPE:
720
721 DPRINTFN(4, (" esc"));
722
723 if (sc->sc_slip_rxexp == BTH5_SLIP_ESCAPE) {
724 discard = 1;
725 errstr = "waiting 0xdc or 0xdb or 0xde of 0xdf";
726 } else
727 sc->sc_slip_rxexp = BTH5_SLIP_ESCAPE;
728 break;
729
730 default:
731 DPRINTFN(4, (" 0x%02x%s",
732 c, (m->m_len % 16 == 15) ? "\n" : ""));
733
734 switch (sc->sc_slip_rxexp) {
735 case BTH5_SLIP_PKTSTART:
736 discard = 1;
737 errstr = "waiting 0xc0";
738 break;
739
740 case BTH5_SLIP_ESCAPE:
741 if (c == BTH5_SLIP_ESCAPE_PKTEND)
742 mtod(m, uint8_t *)[m->m_len++] =
743 BTH5_SLIP_PKTEND;
744 else if (sc->sc_oof_flow_control == true &&
745 c == BTH5_SLIP_ESCAPE_XON)
746 mtod(m, uint8_t *)[m->m_len++] =
747 BTH5_SLIP_XON;
748 else if (sc->sc_oof_flow_control == true &&
749 c == BTH5_SLIP_ESCAPE_XOFF)
750 mtod(m, uint8_t *)[m->m_len++] =
751 BTH5_SLIP_XOFF;
752 else if (c == BTH5_SLIP_ESCAPE_ESCAPE)
753 mtod(m, uint8_t *)[m->m_len++] =
754 BTH5_SLIP_ESCAPE;
755 else {
756 discard = 1;
757 errstr = "unknown escape";
758 }
759 sc->sc_slip_rxexp = 0;
760 break;
761
762 default:
763 mtod(m, uint8_t *)[m->m_len++] = c;
764 }
765 sc->sc_rxp->m_pkthdr.len++;
766 }
767 if (discard) {
768 discarded:
769 #ifdef BTH5_DEBUG
770 DPRINTFN(4, ("%s: receives unexpected byte 0x%02x: %s\n",
771 device_xname(sc->sc_dev), c, errstr));
772 #else
773 __USE(errstr);
774 #endif
775 }
776 sc->sc_stats.byte_rx++;
777
778 return 0;
779 }
780
781
782 /*
783 * BTH5 Packet Integrity Layer functions:
784 * handling Payload Length, Checksum, CRC.
785 */
786 static void
787 bth5_pktintegrity_transmit(struct bth5_softc *sc)
788 {
789 struct mbuf *m = sc->sc_txp;
790 bth5_hdr_t *hdrp = mtod(m, bth5_hdr_t *);
791 int pldlen;
792
793 DPRINTFN(3, ("%s: pi transmit\n", device_xname(sc->sc_dev)));
794
795 pldlen = m->m_pkthdr.len - sizeof(bth5_hdr_t);
796
797 if (sc->sc_pi_txcrc)
798 hdrp->flags |= BTH5_FLAGS_CRC_PRESENT;
799
800 BTH5_SET_PLEN(hdrp, pldlen);
801 BTH5_SET_CSUM(hdrp);
802
803 if (sc->sc_pi_txcrc) {
804 struct mbuf *_m;
805 int n = 0;
806 uint16_t crc = 0xffff;
807 uint8_t *buf;
808
809 for (_m = m; _m != NULL; _m = _m->m_next) {
810 buf = mtod(_m, uint8_t *);
811 for (n = 0; n < _m->m_len; n++)
812 bth5_crc_update(&crc, *(buf + n));
813 }
814 crc = htobe16(bth5_crc_reverse(crc));
815 m_copyback(m, m->m_pkthdr.len, sizeof(crc), &crc);
816 }
817
818 #ifdef BTH5_DEBUG
819 if (bth5_debug == 3)
820 bth5_packet_print(m);
821 #endif
822
823 bth5_slip_transmit(sc->sc_tp);
824 }
825
826 static void
827 bth5_pktintegrity_receive(struct bth5_softc *sc, struct mbuf *m)
828 {
829 bth5_hdr_t *hdrp = mtod(m, bth5_hdr_t *);
830 u_int pldlen;
831 int discard = 0;
832 uint16_t crc = 0xffff;
833 const char *errstr;
834
835 DPRINTFN(3, ("%s: pi receive\n", device_xname(sc->sc_dev)));
836 #ifdef BTH5_DEBUG
837 if (bth5_debug == 4)
838 bth5_packet_print(m);
839 #endif
840
841 KASSERT(m->m_len >= sizeof(bth5_hdr_t));
842
843 pldlen = m->m_pkthdr.len - sizeof(bth5_hdr_t) -
844 ((hdrp->flags & BTH5_FLAGS_CRC_PRESENT) ? sizeof(crc) : 0);
845 if (pldlen > 0xfff) {
846 discard = 1;
847 errstr = "Payload Length";
848 goto discarded;
849 }
850 if (hdrp->csum != BTH5_GET_CSUM(hdrp)) {
851 discard = 1;
852 errstr = "Checksum";
853 goto discarded;
854 }
855 if (BTH5_GET_PLEN(hdrp) != pldlen) {
856 discard = 1;
857 errstr = "Payload Length";
858 goto discarded;
859 }
860 if (hdrp->flags & BTH5_FLAGS_CRC_PRESENT) {
861 struct mbuf *_m;
862 int i, n;
863 uint16_t crc0;
864 uint8_t *buf;
865
866 i = 0;
867 n = 0;
868 for (_m = m; _m != NULL; _m = _m->m_next) {
869 buf = mtod(m, uint8_t *);
870 for (n = 0;
871 n < _m->m_len && i < sizeof(bth5_hdr_t) + pldlen;
872 n++, i++)
873 bth5_crc_update(&crc, *(buf + n));
874 }
875
876 m_copydata(_m, n, sizeof(crc0), &crc0);
877 if (be16toh(crc0) != bth5_crc_reverse(crc)) {
878 discard = 1;
879 errstr = "CRC";
880 } else
881 /* Shaves CRC */
882 m_adj(m, (int)(0 - sizeof(crc)));
883 }
884
885 if (discard) {
886 discarded:
887 #ifdef BTH5_DEBUG
888 DPRINTFN(3, ("%s: receives unexpected packet: %s\n",
889 device_xname(sc->sc_dev), errstr));
890 #else
891 __USE(errstr);
892 #endif
893 m_freem(m);
894 } else
895 bth5_mux_receive(sc, m);
896 }
897
898 static const uint16_t crctbl[] = {
899 0x0000, 0x1081, 0x2102, 0x3183,
900 0x4204, 0x5285, 0x6306, 0x7387,
901 0x8408, 0x9489, 0xa50a, 0xb58b,
902 0xc60c, 0xd68d, 0xe70e, 0xf78f,
903 };
904
905 static void
906 bth5_crc_update(uint16_t *crc, uint8_t d)
907 {
908 uint16_t reg = *crc;
909
910 reg = (reg >> 4) ^ crctbl[(reg ^ d) & 0x000f];
911 reg = (reg >> 4) ^ crctbl[(reg ^ (d >> 4)) & 0x000f];
912
913 *crc = reg;
914 }
915
916 static uint16_t
917 bth5_crc_reverse(uint16_t crc)
918 {
919 uint16_t b, rev;
920
921 for (b = 0, rev = 0; b < 16; b++) {
922 rev = rev << 1;
923 rev |= (crc & 1);
924 crc = crc >> 1;
925 }
926
927 return rev;
928 }
929
930
931 /*
932 * BTH5 MUX Layer functions
933 */
934 static void
935 bth5_mux_transmit(struct bth5_softc *sc)
936 {
937 struct mbuf *m;
938 bth5_hdr_t *hdrp;
939 int s;
940
941 DPRINTFN(2, ("%s: mux transmit: sc_flags=0x%x, choke=%d",
942 device_xname(sc->sc_dev), sc->sc_flags, sc->sc_mux_choke));
943
944 if (sc->sc_mux_choke) {
945 struct mbuf *_m = NULL;
946
947 /* In this case, send only Link Establishment packet */
948 for (m = MBUFQ_FIRST(&sc->sc_dgq); m != NULL;
949 _m = m, m = MBUFQ_NEXT(m)) {
950 hdrp = mtod(m, bth5_hdr_t *);
951 if (hdrp->ident == BTH5_CHANNEL_LE) {
952 if (m == MBUFQ_FIRST(&sc->sc_dgq))
953 MBUFQ_DEQUEUE(&sc->sc_dgq, m);
954 else {
955 if (m->m_nextpkt == NULL)
956 sc->sc_dgq.mq_last =
957 &_m->m_nextpkt;
958 _m->m_nextpkt = m->m_nextpkt;
959 m->m_nextpkt = NULL;
960 }
961 goto transmit;
962 }
963 }
964 DPRINTFN(2, ("\n"));
965 return;
966 }
967
968 /*
969 * The MUX Layer always gives priority to packets from the Datagram
970 * Queue Layer over the Sequencing Layer.
971 */
972 if (MBUFQ_FIRST(&sc->sc_dgq)) {
973 MBUFQ_DEQUEUE(&sc->sc_dgq, m);
974 goto transmit;
975 }
976 if (MBUFQ_FIRST(&sc->sc_seqq)) {
977 MBUFQ_DEQUEUE(&sc->sc_seqq, m);
978 hdrp = mtod(m, bth5_hdr_t *);
979 hdrp->flags |= BTH5_FLAGS_PROTOCOL_REL; /* Reliable */
980 goto transmit;
981 }
982
983 s = spltty();
984 if ((sc->sc_flags & BTH5_XMIT) == 0)
985 bth5_start(sc);
986 splx(s);
987
988 if (sc->sc_mux_send_ack == true) {
989 m = bth5_create_ackpkt();
990 if (m != NULL)
991 goto transmit;
992 aprint_error_dev(sc->sc_dev, "out of memory\n");
993 sc->sc_stats.err_tx++;
994 }
995
996 /* Nothing to send */
997 DPRINTFN(2, ("\n"));
998
999 return;
1000
1001 transmit:
1002 DPRINTFN(2, (", txack=%d, send_ack=%d\n",
1003 bth5_get_txack(sc), sc->sc_mux_send_ack));
1004
1005 hdrp = mtod(m, bth5_hdr_t *);
1006 hdrp->flags |=
1007 (bth5_get_txack(sc) << BTH5_FLAGS_ACK_SHIFT) & BTH5_FLAGS_ACK_MASK;
1008 if (sc->sc_mux_send_ack == true)
1009 sc->sc_mux_send_ack = false;
1010
1011 #ifdef BTH5_DEBUG
1012 if (bth5_debug == 3)
1013 bth5_packet_print(m);
1014 #endif
1015
1016 sc->sc_txp = m;
1017 bth5_pktintegrity_transmit(sc);
1018 }
1019
1020 static void
1021 bth5_mux_receive(struct bth5_softc *sc, struct mbuf *m)
1022 {
1023 bth5_hdr_t *hdrp = mtod(m, bth5_hdr_t *);
1024 const u_int rxack = BTH5_FLAGS_ACK(hdrp->flags);
1025
1026 DPRINTFN(2, ("%s: mux receive: flags=0x%x, ident=%d, rxack=%d\n",
1027 device_xname(sc->sc_dev), hdrp->flags, hdrp->ident, rxack));
1028 #ifdef BTH5_DEBUG
1029 if (bth5_debug == 3)
1030 bth5_packet_print(m);
1031 #endif
1032
1033 bth5_signal_rxack(sc, rxack);
1034
1035 microtime(&sc->sc_mux_lastrx);
1036
1037 /* if the Ack Packet received then discard */
1038 if (BTH5_FLAGS_SEQ(hdrp->flags) == 0 &&
1039 hdrp->ident == BTH5_IDENT_ACKPKT &&
1040 BTH5_GET_PLEN(hdrp) == 0) {
1041 sc->sc_seq_txseq = BTH5_FLAGS_ACK(hdrp->flags);
1042 bth5_send_ack_command(sc);
1043 bth5_mux_transmit(sc);
1044 m_freem(m);
1045 return;
1046 }
1047
1048 if (hdrp->flags & BTH5_FLAGS_PROTOCOL_REL)
1049 bth5_sequencing_receive(sc, m);
1050 else
1051 bth5_datagramq_receive(sc, m);
1052 }
1053
1054 static __inline void
1055 bth5_send_ack_command(struct bth5_softc *sc)
1056 {
1057
1058 DPRINTFN(2, ("%s: mux send_ack_command\n", device_xname(sc->sc_dev)));
1059
1060 sc->sc_mux_send_ack = true;
1061 }
1062
1063 static __inline struct mbuf *
1064 bth5_create_ackpkt(void)
1065 {
1066 struct mbuf *m;
1067 bth5_hdr_t *hdrp;
1068
1069 MGETHDR(m, M_DONTWAIT, MT_DATA);
1070 if (m != NULL) {
1071 m->m_pkthdr.len = m->m_len = sizeof(bth5_hdr_t);
1072 hdrp = mtod(m, bth5_hdr_t *);
1073 /*
1074 * An Ack Packet has the following fields:
1075 * Ack Field: txack (not set yet)
1076 * Seq Field: 0
1077 * Protocol Identifier Field: 0
1078 * Protocol Type Field: Any value
1079 * Payload Length Field: 0
1080 */
1081 memset(hdrp, 0, sizeof(bth5_hdr_t));
1082 }
1083 return m;
1084 }
1085
1086 static __inline void
1087 bth5_set_choke(struct bth5_softc *sc, bool choke)
1088 {
1089
1090 DPRINTFN(2, ("%s: mux set choke=%d\n", device_xname(sc->sc_dev), choke));
1091
1092 sc->sc_mux_choke = choke;
1093 }
1094
1095
1096 /*
1097 * BTH5 Sequencing Layer functions
1098 */
1099 static void
1100 bth5_sequencing_receive(struct bth5_softc *sc, struct mbuf *m)
1101 {
1102 bth5_hdr_t hdr;
1103 uint32_t exp_rxseq, rxack, rxseq;
1104
1105 exp_rxseq = sc->sc_seq_expected_rxseq & BTH5_FLAGS_SEQ_MASK;
1106 m_copydata(m, 0, sizeof(bth5_hdr_t), &hdr);
1107 rxseq = BTH5_FLAGS_SEQ(hdr.flags);
1108 rxack = BTH5_FLAGS_ACK(hdr.flags);
1109
1110 DPRINTFN(1, ("%s: seq receive: rxseq=%d, expected %d\n",
1111 device_xname(sc->sc_dev), rxseq, exp_rxseq));
1112 #ifdef BTH5_DEBUG
1113 if (bth5_debug == 2)
1114 bth5_packet_print(m);
1115 #endif
1116
1117 /*
1118 * We remove the header of BTH5 and add the 'uint8_t type' of
1119 * hci_*_hdr_t to the head.
1120 */
1121 m_adj(m, sizeof(bth5_hdr_t) - sizeof(uint8_t));
1122
1123 if (rxseq != exp_rxseq) {
1124 m_freem(m);
1125
1126 bth5_send_ack_command(sc);
1127 /* send ack packet, if needly */
1128 bth5_mux_transmit(sc);
1129
1130 return;
1131 }
1132
1133 switch (hdr.ident) {
1134 case BTH5_CHANNEL_HCI_CMD:
1135 *(mtod(m, uint8_t *)) = HCI_CMD_PKT;
1136 if (!hci_input_event(sc->sc_unit, m))
1137 sc->sc_stats.err_rx++;
1138
1139 sc->sc_stats.evt_rx++;
1140 break;
1141
1142 case BTH5_CHANNEL_HCI_EVT:
1143 *(mtod(m, uint8_t *)) = HCI_EVENT_PKT;
1144 if (!hci_input_event(sc->sc_unit, m))
1145 sc->sc_stats.err_rx++;
1146
1147 sc->sc_stats.evt_rx++;
1148 break;
1149
1150 case BTH5_CHANNEL_HCI_ACL:
1151 *(mtod(m, uint8_t *)) = HCI_ACL_DATA_PKT;
1152 if (!hci_input_acl(sc->sc_unit, m))
1153 sc->sc_stats.err_rx++;
1154
1155 sc->sc_stats.acl_rx++;
1156 break;
1157
1158 case BTH5_CHANNEL_HCI_SCO:
1159 *(mtod(m, uint8_t *)) = HCI_SCO_DATA_PKT;
1160 if (!hci_input_sco(sc->sc_unit, m))
1161 sc->sc_stats.err_rx++;
1162
1163 sc->sc_stats.sco_rx++;
1164 break;
1165
1166 default:
1167 aprint_error_dev(sc->sc_dev,
1168 "received reliable packet with not support channel %d\n",
1169 hdr.ident);
1170 m_freem(m);
1171 break;
1172 }
1173 bth5_send_ack_command(sc);
1174 sc->sc_seq_txseq = rxack;
1175 sc->sc_seq_expected_rxseq = (rxseq + 1) & BTH5_FLAGS_SEQ_MASK;
1176 sc->sc_seq_total_rxpkts++;
1177
1178 if (sc->sc_seq_total_rxpkts % sc->sc_seq_winack == 0)
1179 bth5_mux_transmit(sc);
1180 }
1181
1182 static bool
1183 bth5_tx_reliable_pkt(struct bth5_softc *sc, struct mbuf *m, u_int protocol_id)
1184 {
1185 bth5_hdr_t *hdrp;
1186 struct mbuf *_m;
1187 struct mbuf *_retrans;
1188 u_int pldlen;
1189 int s;
1190
1191 DPRINTFN(1, ("%s: seq transmit:"
1192 "protocol_id=%d, winspace=%d, txseq=%d\n", device_xname(sc->sc_dev),
1193 protocol_id, sc->sc_seq_winspace, sc->sc_seq_txseq));
1194
1195 for (pldlen = 0, _m = m; _m != NULL; _m = _m->m_next) {
1196 if (_m->m_len < 0)
1197 goto out;
1198 pldlen += _m->m_len;
1199 }
1200 if (pldlen > 0xfff)
1201 goto out;
1202 if (protocol_id == BTH5_IDENT_ACKPKT || protocol_id > 15)
1203 goto out;
1204
1205 if (sc->sc_seq_winspace == 0)
1206 goto out;
1207
1208 M_PREPEND(m, sizeof(bth5_hdr_t), M_DONTWAIT);
1209 if (m == NULL) {
1210 aprint_error_dev(sc->sc_dev, "out of memory\n");
1211 return false;
1212 }
1213 KASSERT(m->m_len >= sizeof(bth5_hdr_t));
1214
1215 hdrp = mtod(m, bth5_hdr_t *);
1216 memset(hdrp, 0, sizeof(bth5_hdr_t));
1217 hdrp->flags |= sc->sc_seq_txseq;
1218 hdrp->ident = protocol_id;
1219
1220 callout_schedule(&sc->sc_seq_timer, sc->sc_seq_timeout);
1221
1222 s = splserial();
1223 MBUFQ_ENQUEUE(&sc->sc_seqq, m);
1224 splx(s);
1225 sc->sc_transmit_callback = bth5_reliabletx_callback;
1226
1227 #ifdef BTH5_DEBUG
1228 if (bth5_debug == 2)
1229 bth5_packet_print(m);
1230 #endif
1231
1232 sc->sc_seq_winspace--;
1233 _retrans = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
1234 if (_retrans == NULL) {
1235 aprint_error_dev(sc->sc_dev, "out of memory\n");
1236 goto out;
1237 }
1238 MBUFQ_ENQUEUE(&sc->sc_seq_retryq, _retrans);
1239 bth5_mux_transmit(sc);
1240 sc->sc_seq_txseq = (sc->sc_seq_txseq + 1) & BTH5_FLAGS_SEQ_MASK;
1241
1242 return true;
1243 out:
1244 m_freem(m);
1245 return false;
1246 }
1247
1248 static __inline u_int
1249 bth5_get_txack(struct bth5_softc *sc)
1250 {
1251
1252 return sc->sc_seq_expected_rxseq;
1253 }
1254
1255 static void
1256 bth5_signal_rxack(struct bth5_softc *sc, uint32_t rxack)
1257 {
1258 bth5_hdr_t *hdrp;
1259 struct mbuf *m;
1260 uint32_t seqno = (rxack - 1) & BTH5_FLAGS_SEQ_MASK;
1261 int s;
1262
1263 DPRINTFN(1, ("%s: seq signal rxack: rxack=%d\n",
1264 device_xname(sc->sc_dev), rxack));
1265
1266 s = splserial();
1267 m = MBUFQ_FIRST(&sc->sc_seq_retryq);
1268 while (m != NULL) {
1269 hdrp = mtod(m, bth5_hdr_t *);
1270 if (BTH5_FLAGS_SEQ(hdrp->flags) == seqno) {
1271 struct mbuf *m0;
1272
1273 for (m0 = MBUFQ_FIRST(&sc->sc_seq_retryq);
1274 m0 != MBUFQ_NEXT(m);
1275 m0 = MBUFQ_FIRST(&sc->sc_seq_retryq)) {
1276 MBUFQ_DEQUEUE(&sc->sc_seq_retryq, m0);
1277 m_freem(m0);
1278 sc->sc_seq_winspace++;
1279 if (sc->sc_seq_winspace > sc->sc_seq_winsize)
1280 sc->sc_seq_winspace = sc->sc_seq_winsize;
1281 }
1282 break;
1283 }
1284 m = MBUFQ_NEXT(m);
1285 }
1286 splx(s);
1287 sc->sc_seq_retries = 0;
1288
1289 if (sc->sc_seq_winspace == sc->sc_seq_winsize)
1290 callout_stop(&sc->sc_seq_timer);
1291 else
1292 callout_schedule(&sc->sc_seq_timer, sc->sc_seq_timeout);
1293 }
1294
1295 static void
1296 bth5_reliabletx_callback(struct bth5_softc *sc, struct mbuf *m)
1297 {
1298
1299 m_freem(m);
1300 }
1301
1302 static void
1303 bth5_timer_timeout(void *arg)
1304 {
1305 struct bth5_softc *sc = arg;
1306 struct mbuf *m, *_m;
1307 int s, i = 0;
1308
1309 DPRINTFN(1, ("%s: seq timeout: retries=%d\n",
1310 device_xname(sc->sc_dev), sc->sc_seq_retries));
1311
1312 bth5_send_ack_command(sc);
1313 bth5_mux_transmit(sc);
1314 s = splserial();
1315 for (m = MBUFQ_FIRST(&sc->sc_seq_retryq); m != NULL;
1316 m = MBUFQ_NEXT(m)) {
1317 _m = m_copym(m, 0, M_COPYALL, M_DONTWAIT);
1318 if (_m == NULL) {
1319 aprint_error_dev(sc->sc_dev, "out of memory\n");
1320 return;
1321 }
1322 MBUFQ_ENQUEUE(&sc->sc_seqq, _m);
1323 i++;
1324 }
1325 splx(s);
1326
1327 if (i != 0) {
1328 if (++sc->sc_seq_retries < sc->sc_seq_retry_limit)
1329 callout_schedule(&sc->sc_seq_timer, sc->sc_seq_timeout);
1330 else {
1331 aprint_error_dev(sc->sc_dev,
1332 "reached the retry limit."
1333 " restart the link-establishment\n");
1334 bth5_sequencing_reset(sc);
1335 bth5_start_le(sc);
1336 return;
1337 }
1338 }
1339 bth5_mux_transmit(sc);
1340 }
1341
1342 static void
1343 bth5_sequencing_reset(struct bth5_softc *sc)
1344 {
1345 int s;
1346
1347 s = splserial();
1348 MBUFQ_DRAIN(&sc->sc_seqq);
1349 MBUFQ_DRAIN(&sc->sc_seq_retryq);
1350 splx(s);
1351
1352
1353 sc->sc_seq_txseq = 0;
1354 sc->sc_seq_winspace = sc->sc_seq_winsize;
1355 sc->sc_seq_retries = 0;
1356 callout_stop(&sc->sc_seq_timer);
1357
1358 sc->sc_mux_send_ack = false;
1359
1360 /* XXXX: expected_rxseq should be set by MUX Layer */
1361 sc->sc_seq_expected_rxseq = 0;
1362 sc->sc_seq_total_rxpkts = 0;
1363 }
1364
1365
1366 /*
1367 * BTH5 Datagram Queue Layer functions
1368 */
1369 static void
1370 bth5_datagramq_receive(struct bth5_softc *sc, struct mbuf *m)
1371 {
1372 bth5_hdr_t hdr;
1373
1374 DPRINTFN(1, ("%s: dgq receive\n", device_xname(sc->sc_dev)));
1375 #ifdef BTH5_DEBUG
1376 if (bth5_debug == 2)
1377 bth5_packet_print(m);
1378 #endif
1379
1380 m_copydata(m, 0, sizeof(bth5_hdr_t), &hdr);
1381
1382 switch (hdr.ident) {
1383 case BTH5_CHANNEL_LE:
1384 m_adj(m, sizeof(bth5_hdr_t));
1385 bth5_input_le(sc, m);
1386 break;
1387
1388 case BTH5_CHANNEL_HCI_SCO:
1389 /*
1390 * We remove the header of BTH5 and add the 'uint8_t type' of
1391 * hci_scodata_hdr_t to the head.
1392 */
1393 m_adj(m, sizeof(bth5_hdr_t) - sizeof(uint8_t));
1394 *(mtod(m, uint8_t *)) = HCI_SCO_DATA_PKT;
1395 if (!hci_input_sco(sc->sc_unit, m))
1396 sc->sc_stats.err_rx++;
1397
1398 sc->sc_stats.sco_rx++;
1399 break;
1400
1401 default:
1402 aprint_error_dev(sc->sc_dev,
1403 "received unreliable packet with not support channel %d\n",
1404 hdr.ident);
1405 m_freem(m);
1406 break;
1407 }
1408 }
1409
1410 static bool
1411 bth5_tx_unreliable_pkt(struct bth5_softc *sc, struct mbuf *m, u_int protocol_id)
1412 {
1413 bth5_hdr_t *hdrp;
1414 struct mbuf *_m;
1415 u_int pldlen;
1416 int s;
1417
1418 DPRINTFN(1, ("%s: dgq transmit: protocol_id=%d,",
1419 device_xname(sc->sc_dev), protocol_id));
1420
1421 for (pldlen = 0, _m = m; _m != NULL; _m = m->m_next) {
1422 if (_m->m_len < 0)
1423 goto out;
1424 pldlen += _m->m_len;
1425 }
1426 DPRINTFN(1, (" pldlen=%d\n", pldlen));
1427 if (pldlen > 0xfff)
1428 goto out;
1429 if (protocol_id == BTH5_IDENT_ACKPKT || protocol_id > 15)
1430 goto out;
1431
1432 M_PREPEND(m, sizeof(bth5_hdr_t), M_DONTWAIT);
1433 if (m == NULL) {
1434 aprint_error_dev(sc->sc_dev, "out of memory\n");
1435 return false;
1436 }
1437 KASSERT(m->m_len >= sizeof(bth5_hdr_t));
1438
1439 hdrp = mtod(m, bth5_hdr_t *);
1440 memset(hdrp, 0, sizeof(bth5_hdr_t));
1441 hdrp->ident = protocol_id;
1442
1443 s = splserial();
1444 MBUFQ_ENQUEUE(&sc->sc_dgq, m);
1445 splx(s);
1446 sc->sc_transmit_callback = bth5_unreliabletx_callback;
1447
1448 #ifdef BTH5_DEBUG
1449 if (bth5_debug == 2)
1450 bth5_packet_print(m);
1451 #endif
1452
1453 bth5_mux_transmit(sc);
1454
1455 return true;
1456 out:
1457 m_freem(m);
1458 return false;
1459 }
1460
1461 static void
1462 bth5_unreliabletx_callback(struct bth5_softc *sc, struct mbuf *m)
1463 {
1464
1465 if (M_GETCTX(m, void *) == NULL)
1466 m_freem(m);
1467 else if (!hci_complete_sco(sc->sc_unit, m))
1468 sc->sc_stats.err_tx++;
1469 }
1470
1471
1472 /*
1473 * BTUART H5 Link Establishment Protocol functions
1474 */
1475 static const uint8_t sync[] = BTH5_LE_SYNC;
1476 static const uint8_t syncresp[] = BTH5_LE_SYNCRESP;
1477 static const uint8_t conf[] = BTH5_LE_CONF;
1478 static const uint8_t confresp[] = BTH5_LE_CONFRESP;
1479
1480 static int
1481 bth5_start_le(struct bth5_softc *sc)
1482 {
1483
1484 DPRINTF(("%s: start link-establish\n", device_xname(sc->sc_dev)));
1485
1486 bth5_set_choke(sc, true);
1487
1488 if (!sc->sc_le_muzzled) {
1489 struct mbuf *m;
1490
1491 m = m_gethdr(M_DONTWAIT, MT_DATA);
1492 if (m == NULL) {
1493 aprint_error_dev(sc->sc_dev,
1494 "le-packet transmit out of memory\n");
1495 return ENOMEM;
1496 }
1497 m->m_pkthdr.len = m->m_len = 0;
1498 m_copyback(m, 0, sizeof(sync), sync);
1499 if (!bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_LE)) {
1500 aprint_error_dev(sc->sc_dev,
1501 "le-packet transmit failed\n");
1502 return EINVAL;
1503 }
1504 }
1505 callout_schedule(&sc->sc_le_timer, BTH5_LE_TSHY_TIMEOUT);
1506
1507 sc->sc_le_state = le_state_shy;
1508 return 0;
1509 }
1510
1511 static void
1512 bth5_terminate_le(struct bth5_softc *sc)
1513 {
1514 struct mbuf *m;
1515
1516 /* terminate link-establishment */
1517 callout_stop(&sc->sc_le_timer);
1518 bth5_set_choke(sc, true);
1519 MGETHDR(m, M_DONTWAIT, MT_DATA);
1520 if (m == NULL)
1521 aprint_error_dev(sc->sc_dev, "out of memory\n");
1522 else {
1523 /* length of le packets is 4 */
1524 m->m_pkthdr.len = m->m_len = 0;
1525 m_copyback(m, 0, sizeof(sync), sync);
1526 if (!bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_LE))
1527 aprint_error_dev(sc->sc_dev,
1528 "link-establishment terminations failed\n");
1529 }
1530 }
1531
1532 static void
1533 bth5_input_le(struct bth5_softc *sc, struct mbuf *m)
1534 {
1535 uint16_t *rcvpkt;
1536 int i, len;
1537 uint8_t config[3];
1538 const uint8_t *rplypkt;
1539 static struct {
1540 const char *type;
1541 const uint8_t *datap;
1542 } pkt[] = {
1543 { "sync", sync },
1544 { "sync-resp", syncresp },
1545 { "conf", conf },
1546 { "conf-resp", confresp },
1547
1548 { NULL, 0 }
1549 };
1550
1551 DPRINTFN(0, ("%s: le input: state %d, muzzled %d\n",
1552 device_xname(sc->sc_dev), sc->sc_le_state, sc->sc_le_muzzled));
1553 #ifdef BTH5_DEBUG
1554 if (bth5_debug == 1)
1555 bth5_packet_print(m);
1556 #endif
1557
1558 rcvpkt = mtod(m, uint16_t *);
1559 i = 0;
1560
1561 /* length of le packets is 2 */
1562 if (m->m_len >= sizeof(uint16_t))
1563 for (i = 0; pkt[i].type != NULL; i++)
1564 if (*(const uint16_t *)pkt[i].datap == *rcvpkt)
1565 break;
1566 if (m->m_len < sizeof(uint16_t) || pkt[i].type == NULL) {
1567 aprint_error_dev(sc->sc_dev, "received unknown packet\n");
1568 m_freem(m);
1569 return;
1570 }
1571
1572 len = m->m_len;
1573
1574 rplypkt = NULL;
1575 switch (sc->sc_le_state) {
1576 case le_state_shy:
1577 if (*rcvpkt == *(const uint16_t *)sync) {
1578 sc->sc_le_muzzled = false;
1579 rplypkt = syncresp;
1580 } else if (*rcvpkt == *(const uint16_t *)syncresp) {
1581 DPRINTF(("%s: state change to curious\n",
1582 device_xname(sc->sc_dev)));
1583 rplypkt = conf;
1584 callout_schedule(&sc->sc_le_timer,
1585 BTH5_LE_TCONF_TIMEOUT);
1586 sc->sc_le_state = le_state_curious;
1587 } else
1588 aprint_error_dev(sc->sc_dev,
1589 "received an unknown packet at shy\n");
1590 break;
1591
1592 case le_state_curious:
1593 if (*rcvpkt == *(const uint16_t *)sync)
1594 rplypkt = syncresp;
1595 else if (*rcvpkt == *(const uint16_t *)syncresp) {
1596 rplypkt = conf;
1597 len = 3;
1598 }
1599 else if (*rcvpkt == *(const uint16_t *)conf)
1600 rplypkt = confresp;
1601 else if (*rcvpkt == *(const uint16_t *)confresp &&
1602 m->m_len == 3) {
1603 DPRINTF(("%s: state change to garrulous:\n",
1604 device_xname(sc->sc_dev)));
1605
1606 memcpy(config, conf, sizeof(uint16_t));
1607 config[2] = (uint8_t)rcvpkt[1];
1608 sc->sc_seq_winack = config[2] & BTH5_CONFIG_ACK_MASK;
1609 if (config[2] & BTH5_CONFIG_FLOW_MASK)
1610 sc->sc_oof_flow_control = true;
1611 else
1612 sc->sc_oof_flow_control = false;
1613
1614 bth5_sequencing_reset(sc);
1615 bth5_set_choke(sc, false);
1616 callout_stop(&sc->sc_le_timer);
1617 sc->sc_le_state = le_state_garrulous;
1618 } else
1619 aprint_error_dev(sc->sc_dev,
1620 "received unknown packet at curious\n");
1621 break;
1622
1623 case le_state_garrulous:
1624 if (*rcvpkt == *(const uint16_t *)conf)
1625 rplypkt = confresp;
1626 else if (*rcvpkt == *(const uint16_t *)sync) {
1627 /* XXXXX */
1628 aprint_error_dev(sc->sc_dev,
1629 "received sync! peer to reset?\n");
1630
1631 bth5_sequencing_reset(sc);
1632 rplypkt = syncresp;
1633 sc->sc_le_state = le_state_shy;
1634 } else
1635 aprint_error_dev(sc->sc_dev,
1636 "received unknown packet at garrulous\n");
1637 break;
1638 }
1639
1640 m_freem(m);
1641
1642 if (rplypkt != NULL) {
1643 MGETHDR(m, M_DONTWAIT, MT_DATA);
1644 if (m == NULL)
1645 aprint_error_dev(sc->sc_dev, "out of memory\n");
1646 else {
1647 /* length of le packets is 2 */
1648 m->m_pkthdr.len = m->m_len = 0;
1649 if (rplypkt == (const uint8_t *)&config
1650 || rplypkt == confresp || rplypkt == conf)
1651 m_copyback(m, 0, len, rplypkt);
1652 else
1653 m_copyback(m, 0, 2, rplypkt);
1654 if (!bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_LE))
1655 aprint_error_dev(sc->sc_dev,
1656 "le-packet transmit failed\n");
1657 }
1658 }
1659 }
1660
1661 static void
1662 bth5_le_timeout(void *arg)
1663 {
1664 struct bth5_softc *sc = arg;
1665 struct mbuf *m;
1666 int timeout;
1667 const uint8_t *sndpkt = NULL;
1668
1669 DPRINTFN(0, ("%s: le timeout: state %d, muzzled %d\n",
1670 device_xname(sc->sc_dev), sc->sc_le_state, sc->sc_le_muzzled));
1671
1672 switch (sc->sc_le_state) {
1673 case le_state_shy:
1674 if (!sc->sc_le_muzzled)
1675 sndpkt = sync;
1676 timeout = BTH5_LE_TSHY_TIMEOUT;
1677 break;
1678
1679 case le_state_curious:
1680 sndpkt = conf;
1681 timeout = BTH5_LE_TCONF_TIMEOUT;
1682 break;
1683
1684 default:
1685 aprint_error_dev(sc->sc_dev,
1686 "timeout happen at unknown state %d\n", sc->sc_le_state);
1687 return;
1688 }
1689
1690 if (sndpkt != NULL) {
1691 MGETHDR(m, M_DONTWAIT, MT_DATA);
1692 if (m == NULL)
1693 aprint_error_dev(sc->sc_dev, "out of memory\n");
1694 else {
1695 /* length of le packets is 4 */
1696 m->m_pkthdr.len = m->m_len = 0;
1697 if (sndpkt == conf || sndpkt == confresp)
1698 m_copyback(m, 0, 3, sndpkt);
1699 else
1700 m_copyback(m, 0, 2, sndpkt);
1701 if (!bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_LE))
1702 aprint_error_dev(sc->sc_dev,
1703 "le-packet transmit failed\n");
1704 }
1705 }
1706
1707 callout_schedule(&sc->sc_le_timer, timeout);
1708 }
1709
1710
1711 /*
1712 * BTUART H5 Serial Protocol functions.
1713 */
1714 static int
1715 bth5_enable(device_t self)
1716 {
1717 struct bth5_softc *sc = device_private(self);
1718 int s;
1719
1720 if (sc->sc_flags & BTH5_ENABLED)
1721 return 0;
1722
1723 s = spltty();
1724
1725 sc->sc_flags |= BTH5_ENABLED;
1726 sc->sc_flags &= ~BTH5_XMIT;
1727
1728 splx(s);
1729
1730 return 0;
1731 }
1732
1733 static void
1734 bth5_disable(device_t self)
1735 {
1736 struct bth5_softc *sc = device_private(self);
1737 int s;
1738
1739 if ((sc->sc_flags & BTH5_ENABLED) == 0)
1740 return;
1741
1742 s = spltty();
1743
1744 if (sc->sc_rxp) {
1745 m_freem(sc->sc_rxp);
1746 sc->sc_rxp = NULL;
1747 }
1748
1749 if (sc->sc_txp) {
1750 m_freem(sc->sc_txp);
1751 sc->sc_txp = NULL;
1752 }
1753
1754 MBUFQ_DRAIN(&sc->sc_cmdq);
1755 MBUFQ_DRAIN(&sc->sc_aclq);
1756 MBUFQ_DRAIN(&sc->sc_scoq);
1757
1758 sc->sc_flags &= ~BTH5_ENABLED;
1759 splx(s);
1760 }
1761
1762 static void
1763 bth5_start(struct bth5_softc *sc)
1764 {
1765 struct mbuf *m;
1766
1767 KASSERT((sc->sc_flags & BTH5_XMIT) == 0);
1768 KASSERT(sc->sc_txp == NULL);
1769
1770 if (MBUFQ_FIRST(&sc->sc_aclq)) {
1771 MBUFQ_DEQUEUE(&sc->sc_aclq, m);
1772 sc->sc_stats.acl_tx++;
1773 sc->sc_flags |= BTH5_XMIT;
1774 bth5_tx_reliable_pkt(sc, m, BTH5_CHANNEL_HCI_ACL);
1775 }
1776
1777 if (MBUFQ_FIRST(&sc->sc_cmdq)) {
1778 MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
1779 sc->sc_stats.cmd_tx++;
1780 sc->sc_flags |= BTH5_XMIT;
1781 bth5_tx_reliable_pkt(sc, m, BTH5_CHANNEL_HCI_CMD);
1782 }
1783
1784 if (MBUFQ_FIRST(&sc->sc_scoq)) {
1785 MBUFQ_DEQUEUE(&sc->sc_scoq, m);
1786 sc->sc_stats.sco_tx++;
1787 /* XXXX: We can transmit with reliable */
1788 sc->sc_flags |= BTH5_XMIT;
1789 bth5_tx_unreliable_pkt(sc, m, BTH5_CHANNEL_HCI_SCO);
1790 }
1791
1792 return;
1793 }
1794
1795 static void
1796 bth5_output_cmd(device_t self, struct mbuf *m)
1797 {
1798 struct bth5_softc *sc = device_private(self);
1799 int s;
1800
1801 KASSERT(sc->sc_flags & BTH5_ENABLED);
1802
1803 m_adj(m, sizeof(uint8_t));
1804 M_SETCTX(m, NULL);
1805
1806 s = spltty();
1807 MBUFQ_ENQUEUE(&sc->sc_cmdq, m);
1808 if ((sc->sc_flags & BTH5_XMIT) == 0)
1809 bth5_start(sc);
1810
1811 splx(s);
1812 }
1813
1814 static void
1815 bth5_output_acl(device_t self, struct mbuf *m)
1816 {
1817 struct bth5_softc *sc = device_private(self);
1818 int s;
1819
1820 KASSERT(sc->sc_flags & BTH5_ENABLED);
1821
1822 m_adj(m, sizeof(uint8_t));
1823 M_SETCTX(m, NULL);
1824
1825 s = spltty();
1826 MBUFQ_ENQUEUE(&sc->sc_aclq, m);
1827 if ((sc->sc_flags & BTH5_XMIT) == 0)
1828 bth5_start(sc);
1829
1830 splx(s);
1831 }
1832
1833 static void
1834 bth5_output_sco(device_t self, struct mbuf *m)
1835 {
1836 struct bth5_softc *sc = device_private(self);
1837 int s;
1838
1839 KASSERT(sc->sc_flags & BTH5_ENABLED);
1840
1841 m_adj(m, sizeof(uint8_t));
1842
1843 s = spltty();
1844 MBUFQ_ENQUEUE(&sc->sc_scoq, m);
1845 if ((sc->sc_flags & BTH5_XMIT) == 0)
1846 bth5_start(sc);
1847
1848 splx(s);
1849 }
1850
1851 static void
1852 bth5_stats(device_t self, struct bt_stats *dest, int flush)
1853 {
1854 struct bth5_softc *sc = device_private(self);
1855 int s;
1856
1857 s = spltty();
1858 memcpy(dest, &sc->sc_stats, sizeof(struct bt_stats));
1859
1860 if (flush)
1861 memset(&sc->sc_stats, 0, sizeof(struct bt_stats));
1862
1863 splx(s);
1864 }
1865
1866
1867 #ifdef BTH5_DEBUG
1868 static void
1869 bth5_packet_print(struct mbuf *m)
1870 {
1871 int i;
1872 uint8_t *p;
1873
1874 for ( ; m != NULL; m = m->m_next) {
1875 p = mtod(m, uint8_t *);
1876 for (i = 0; i < m->m_len; i++) {
1877 if (i % 16 == 0)
1878 printf(" ");
1879 printf(" %02x", *(p + i));
1880 if (i % 16 == 15)
1881 printf("\n");
1882 }
1883 printf("\n");
1884 }
1885 }
1886 #endif
1887