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