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