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