btuart.c revision 1.7.2.1 1 /* $NetBSD: btuart.c,v 1.7.2.1 2007/11/06 23:25:47 matt Exp $ */
2 /*
3 * Copyright (c) 2006, 2007 KIYOHARA Takashi
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: btuart.c,v 1.7.2.1 2007/11/06 23:25:47 matt Exp $");
30
31 #include <sys/types.h>
32 #include <sys/param.h>
33 #include <sys/device.h>
34 #include <sys/errno.h>
35
36 #include <sys/conf.h>
37 #include <sys/fcntl.h>
38 #include <sys/kauth.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/mbuf.h>
42 #include <sys/proc.h>
43 #include <sys/syslimits.h>
44 #include <sys/systm.h>
45 #include <sys/tty.h>
46
47 #include <sys/bus.h>
48 #include <sys/intr.h>
49
50 #include <netbt/bluetooth.h>
51 #include <netbt/hci.h>
52
53 #include <dev/bluetooth/btuart.h>
54 #include <dev/firmload.h>
55
56 #include "ioconf.h"
57
58 #ifdef BTUART_DEBUG
59 int btuart_debug = 1;
60 #endif
61
62 struct btuart_softc;
63 struct bth4hci {
64 int type;
65 int init_baud;
66 #define FLOW_CTL 1
67 int flags;
68 int (*init)(struct btuart_softc *);
69 };
70
71 struct btuart_softc {
72 device_t sc_dev;
73
74 struct tty *sc_tp;
75 struct hci_unit sc_unit; /* Bluetooth HCI Unit */
76
77 struct bth4hci sc_bth4hci;
78 int sc_baud;
79
80 int sc_state; /* receive state */
81 #define BTUART_RECV_PKT_TYPE 0 /* packet type */
82 #define BTUART_RECV_ACL_HDR 1 /* acl header */
83 #define BTUART_RECV_SCO_HDR 2 /* sco header */
84 #define BTUART_RECV_EVENT_HDR 3 /* event header */
85 #define BTUART_RECV_ACL_DATA 4 /* acl packet data */
86 #define BTUART_RECV_SCO_DATA 5 /* sco packet data */
87 #define BTUART_RECV_EVENT_DATA 6 /* event packet data */
88 int sc_want; /* how much we want */
89 struct mbuf *sc_rxp; /* incoming packet */
90 struct mbuf *sc_txp; /* outgoing packet */
91
92 void (*sc_input_acl)(struct hci_unit *, struct mbuf *);
93 void (*sc_input_sco)(struct hci_unit *, struct mbuf *);
94 void (*sc_input_event)(struct hci_unit *, struct mbuf *);
95 };
96
97 void btuartattach(int);
98 static int btuart_match(device_t, struct cfdata *, void *);
99 static void btuart_attach(device_t, device_t, void *);
100 static int btuart_detach(device_t, int);
101
102 static int bth4_waitresp(struct btuart_softc *, struct mbuf **, uint16_t);
103 static int bth4_firmload(struct btuart_softc *, char *,
104 int (*)(struct btuart_softc *, int, char *));
105 static int init_ericsson(struct btuart_softc *);
106 static int init_digi(struct btuart_softc *);
107 static int init_texas(struct btuart_softc *);
108 static int init_csr(struct btuart_softc *);
109 static int init_swave(struct btuart_softc *);
110 static int init_st(struct btuart_softc *);
111 static int firmload_stlc2500(struct btuart_softc *, int, char *);
112 static int init_stlc2500(struct btuart_softc *);
113 static int init_bcm2035(struct btuart_softc *);
114 static int bth4init(struct btuart_softc *);
115 static void bth4init_input(struct hci_unit *, struct mbuf *);
116
117 static int bth4open(dev_t, struct tty *);
118 static int bth4close(struct tty *, int);
119 static int bth4ioctl(struct tty *, u_long, void *, int, struct lwp *);
120 static int bth4input(int, struct tty *);
121 static int bth4start(struct tty *);
122
123 static int bth4_enable(struct hci_unit *);
124 static void bth4_disable(struct hci_unit *);
125 static void bth4_start(struct hci_unit *);
126
127 /*
128 * It doesn't need to be exported, as only btuartattach() uses it,
129 * but there's no "official" way to make it static.
130 */
131 CFATTACH_DECL_NEW(btuart, sizeof(struct btuart_softc),
132 btuart_match, btuart_attach, btuart_detach, NULL);
133
134 static struct linesw bth4_disc = {
135 .l_name = "btuart",
136 .l_open = bth4open,
137 .l_close = bth4close,
138 .l_read = ttyerrio,
139 .l_write = ttyerrio,
140 .l_ioctl = bth4ioctl,
141 .l_rint = bth4input,
142 .l_start = bth4start,
143 .l_modem = ttymodem,
144 .l_poll = ttyerrpoll
145 };
146
147 static struct bth4hci bth4hci[] = {
148 { BTUART_HCITYPE_ANY, B0, FLOW_CTL, NULL },
149 { BTUART_HCITYPE_ERICSSON, B57600, FLOW_CTL, init_ericsson },
150 { BTUART_HCITYPE_DIGI, B9600, FLOW_CTL, init_digi },
151 { BTUART_HCITYPE_TEXAS, B115200, FLOW_CTL, init_texas },
152 /* CSR Casira serial adapter or BrainBoxes serial dongle (BL642) */
153 { BTUART_HCITYPE_CSR, B115200, FLOW_CTL, init_csr },
154 /* Silicon Wave kits */
155 { BTUART_HCITYPE_SWAVE, B115200, FLOW_CTL, init_swave },
156 /* ST Microelectronics minikits based on STLC2410/STLC2415 */
157 { BTUART_HCITYPE_ST, B57600, FLOW_CTL, init_st },
158 /* ST Microelectronics minikits based on STLC2500 */
159 { BTUART_HCITYPE_STLC2500, B115200, FLOW_CTL, init_stlc2500 },
160 /* AmbiCom BT2000C Bluetooth PC/CF Card */
161 { BTUART_HCITYPE_BT2000C, B57600, FLOW_CTL, init_csr },
162 /* Broadcom BCM2035 */
163 { BTUART_HCITYPE_BCM2035, B115200, 0, init_bcm2035 },
164
165 { -1, B0, 0, NULL }
166 };
167
168
169 /* ARGSUSED */
170 void
171 btuartattach(int num __unused)
172 {
173 int error;
174
175 error = ttyldisc_attach(&bth4_disc);
176 if (error) {
177 aprint_error("%s: unable to register line discipline, "
178 "error = %d\n", btuart_cd.cd_name, error);
179 return;
180 }
181
182 error = config_cfattach_attach(btuart_cd.cd_name, &btuart_ca);
183 if (error) {
184 aprint_error("%s: unable to register cfattach, error = %d\n",
185 btuart_cd.cd_name, error);
186 config_cfdriver_detach(&btuart_cd);
187 (void) ttyldisc_detach(&bth4_disc);
188 }
189 }
190
191 /*
192 * Autoconf match routine.
193 *
194 * XXX: unused: config_attach_pseudo(9) does not call ca_match.
195 */
196 /* ARGSUSED */
197 static int
198 btuart_match(device_t self __unused,
199 struct cfdata *cfdata __unused, void *arg __unused)
200 {
201
202 /* pseudo-device; always present */
203 return 1;
204 }
205
206 /*
207 * Autoconf attach routine. Called by config_attach_pseudo(9) when we
208 * open the line discipline.
209 */
210 /* ARGSUSED */
211 static void
212 btuart_attach(device_t parent __unused,
213 device_t self, void *aux __unused)
214 {
215 struct btuart_softc *sc = device_private(self);
216 int i;
217
218 sc->sc_dev = self;
219
220 aprint_normal("\n");
221 aprint_naive("\n");
222
223 sc->sc_input_acl = bth4init_input;
224 sc->sc_input_sco = bth4init_input;
225 sc->sc_input_event = bth4init_input;
226
227 /* Copy default type */
228 for (i = 0; bth4hci[i].type != BTUART_HCITYPE_ANY; i++);
229 memcpy(&sc->sc_bth4hci, &bth4hci[i], sizeof(struct bth4hci));
230
231 /* Attach Bluetooth unit */
232 sc->sc_unit.hci_softc = sc;
233 sc->sc_unit.hci_devname = device_xname(self);
234 sc->sc_unit.hci_enable = bth4_enable;
235 sc->sc_unit.hci_disable = bth4_disable;
236 sc->sc_unit.hci_start_cmd = bth4_start;
237 sc->sc_unit.hci_start_acl = bth4_start;
238 sc->sc_unit.hci_start_sco = bth4_start;
239 sc->sc_unit.hci_ipl = makeiplcookie(IPL_TTY);
240 hci_attach(&sc->sc_unit);
241 }
242
243 /*
244 * Autoconf detach routine. Called when we close the line discipline.
245 */
246 static int
247 btuart_detach(device_t self, int flags __unused)
248 {
249 struct btuart_softc *sc = device_private(self);
250
251 hci_detach(&sc->sc_unit);
252
253 return 0;
254 }
255
256
257 static int
258 bth4_waitresp(struct btuart_softc *sc, struct mbuf **mp, uint16_t opcode)
259 {
260 struct hci_unit *unit = &sc->sc_unit;
261 hci_event_hdr_t *e;
262 int status = 0, rv;
263
264 *mp = NULL;
265 while (1 /* CONSTCOND */) {
266 if ((rv =
267 tsleep(&unit->hci_eventq, PCATCH, "bth4init", 0)) != 0)
268 return rv;
269
270 MBUFQ_DEQUEUE(&unit->hci_eventq, *mp);
271 unit->hci_eventqlen--;
272 KASSERT(*mp != NULL);
273
274 e = mtod(*mp, hci_event_hdr_t *);
275 if (e->event == HCI_EVENT_COMMAND_COMPL) {
276 hci_command_compl_ep *ep;
277
278 ep = (hci_command_compl_ep *)(e + 1);
279 if (ep->opcode == opcode) {
280 status = *(char *)(ep + 1);
281 break;
282 }
283 } else if (e->event == HCI_EVENT_COMMAND_STATUS) {
284 hci_command_status_ep *ep;
285
286 ep = (hci_command_status_ep *)(e + 1);
287 if (ep->opcode == opcode) {
288 status = ep->status;
289 break;
290 }
291 } else if (e->event == HCI_EVENT_VENDOR)
292 break;
293 }
294
295 return status;
296 }
297
298 static int
299 bth4_firmload(struct btuart_softc *sc, char *filename,
300 int (*func_firmload)(struct btuart_softc *, int, char *))
301 {
302 const cfdriver_t cd = device_cfdriver(sc->sc_dev);
303 firmware_handle_t fh = NULL;
304 int error, size;
305 char *buf;
306
307 if ((error = firmware_open(cd->cd_name, filename, &fh)) != 0) {
308 printf("firmware_open failed\n");
309 return error;
310 }
311 size = firmware_get_size(fh);
312 if ((buf = firmware_malloc(size)) != NULL) {
313 printf("firmware_malloc failed\n");
314 firmware_close(fh);
315 return ENOMEM;
316 }
317
318 if ((error = firmware_read(fh, 0, buf, size)) != 0)
319 printf("firmware_read failed\n");
320 if (error == 0)
321 error = (*func_firmload)(sc, size, buf);
322
323 firmware_close(fh);
324 firmware_free(buf, size);
325
326 return error;
327 }
328
329 /*
330 * LSI initialize functions.
331 */
332 static int
333 init_ericsson(struct btuart_softc *sc)
334 {
335 struct mbuf *m;
336 struct hci_unit *unit = &sc->sc_unit;
337 hci_cmd_hdr_t *p;
338 int i, error = 0;
339 const uint16_t opcode = htole16(HCI_CMD_ERICSSON_SET_UART_BAUD_RATE);
340 static struct {
341 int baud;
342 uint8_t param;
343 } ericsson_baudtbl[] = {
344 { B460800, 0x00 },
345 { B230400, 0x01 },
346 { B115200, 0x02 },
347 { B57600, 0x03 },
348 { B28800, 0x04 },
349 { B14400, 0x05 },
350 { B7200, 0x06 },
351 #if defined(B3600)
352 { B3600, 0x07 },
353 #endif
354 { B1800, 0x08 },
355 #if defined(B900)
356 { B900, 0x09 },
357 #endif
358 #if defined(B153600)
359 { B153600, 0x10 },
360 #endif
361 { B76800, 0x11 },
362 { B38400, 0x12 },
363 { B19200, 0x13 },
364 { B9600, 0x14 },
365 { B4800, 0x15 },
366 { B2400, 0x16 },
367 { B1200, 0x17 },
368 { B600, 0x18 },
369 { B300, 0x19 },
370 { B921600, 0x20 },
371 { B0, 0xff }
372 };
373
374 for (i = 0; ericsson_baudtbl[i].baud != sc->sc_baud; i++)
375 if (ericsson_baudtbl[i].baud == B0)
376 return EINVAL;
377
378 m = m_gethdr(M_WAIT, MT_DATA);
379 p = mtod(m, hci_cmd_hdr_t *);
380 p->type = HCI_CMD_PKT;
381 p->opcode = opcode;
382 p->length = sizeof(ericsson_baudtbl[0].param);
383 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
384 m_copyback(m, sizeof(hci_cmd_hdr_t), p->length,
385 &ericsson_baudtbl[i].param);
386
387 MBUFQ_ENQUEUE(&unit->hci_cmdq, m);
388 bth4_start(unit);
389
390 #if 0
391 error = bth4_waitresp(sc, &m, opcode);
392 if (m != NULL) {
393 if (error != 0) {
394 printf("%s: Ericsson_Set_UART_Baud_Rate failed:"
395 " Status 0x%02x\n", device_xname(sc->sc_dev), error);
396 error = EFAULT;
397 }
398 m_freem(m);
399 }
400 #else
401 /*
402 * XXXX: We cannot correctly receive this response perhaps. Wait
403 * until the transmission of the data of 5 bytes * 10 bit is completed.
404 * 1000000usec * 10bit * 5byte / baud
405 */
406 delay(50000000 / sc->sc_bth4hci.init_baud);
407 #endif
408 return error;
409 }
410
411 static int
412 init_digi(struct btuart_softc *sc)
413 {
414 struct mbuf *m;
415 struct hci_unit *unit = &sc->sc_unit;
416 hci_cmd_hdr_t *p;
417 uint8_t param;
418
419 /* XXXX */
420 switch (sc->sc_baud) {
421 case B57600:
422 param = 0x08;
423 break;
424
425 case B115200:
426 param = 0x09;
427 break;
428
429 default:
430 return EINVAL;
431 }
432
433 m = m_gethdr(M_WAIT, MT_DATA);
434 p = mtod(m, hci_cmd_hdr_t *);
435 p->type = HCI_CMD_PKT;
436 #define HCI_CMD_DIGIANSWER_SET_UART_BAUD_RATE 0xfc07 /* XXXX */
437 p->opcode = htole16(HCI_CMD_DIGIANSWER_SET_UART_BAUD_RATE);
438 p->length = sizeof(param);
439 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
440 m_copyback(m, sizeof(hci_cmd_hdr_t), p->length, ¶m);
441
442 MBUFQ_ENQUEUE(&unit->hci_cmdq, m);
443 bth4_start(unit);
444
445 /*
446 * XXXX
447 * Wait until the transmission of the data of 5 bytes * 10 bit is
448 * completed.
449 * 1000000usec * 10bit * 5byte / baud
450 */
451 delay(50000000 / sc->sc_bth4hci.init_baud);
452 return 0;
453 }
454
455 static int
456 init_texas(struct btuart_softc *sc)
457 {
458
459 /* XXXX: Should we obtain the version of LMP? */
460 return 0;
461 }
462
463 static int
464 init_csr(struct btuart_softc *sc)
465 {
466 struct mbuf *m;
467 struct hci_unit *unit = &sc->sc_unit;
468 hci_cmd_hdr_t *p;
469 int error;
470 const uint16_t opcode = htole16(HCI_CMD_CSR_EXTN);
471 struct {
472 uint8_t last :1;
473 uint8_t first :1;
474 #define CSR_BCCMD_CHANID_BCCMD 2
475 #define CSR_BCCMD_CHANID_HQ 3
476 #define CSR_BCCMD_CHANID_DEVMGRLIB 4
477 #define CSR_BCCMD_CHANID_L2CAPLIB 8
478 #define CSR_BCCMD_CHANID_RFCOMMLIB 9
479 #define CSR_BCCMD_CHANID_SDPLIB 10
480 #define CSR_BCCMD_CHANID_DFU 12
481 #define CSR_BCCMD_CHANID_VM 13
482 #define CSR_BCCMD_CHANID_LMDEBUG 20
483 uint8_t chanid :6;
484
485 struct {
486 #define CSR_BCCMD_MESSAGE_TYPE_GETREQ 0x0000
487 #define CSR_BCCMD_MESSAGE_TYPE_GETRESP 0x0001
488 #define CSR_BCCMD_MESSAGE_TYPE_SETREQ 0x0002
489 uint16_t type;
490 uint16_t length;
491 uint16_t seqno;
492 #define CSR_BCCMD_MESSAGE_VARID_CONFIG_UART 0x6802
493 #define CSR_BCCMD_MESSAGE_VARID_CONFIG_UART_STOPB 0x2000
494 #define CSR_BCCMD_MESSAGE_VARID_CONFIG_UART_PARENB 0x4000
495 #define CSR_BCCMD_MESSAGE_VARID_CONFIG_UART_PARODD 0x8000
496 uint16_t varid;
497 #define CSR_BCCMD_MESSAGE_STATUS_OK 0x0000
498 #define CSR_BCCMD_MESSAGE_STATUS_NO_SUCH_VARID 0x0001
499 #define CSR_BCCMD_MESSAGE_STATUS_TOO_BIG 0x0002
500 #define CSR_BCCMD_MESSAGE_STATUS_NO_VALUE 0x0003
501 #define CSR_BCCMD_MESSAGE_STATUS_BAD_REQ 0x0004
502 #define CSR_BCCMD_MESSAGE_STATUS_NO_ACCESS 0x0005
503 #define CSR_BCCMD_MESSAGE_STATUS_READ_ONLY 0x0006
504 #define CSR_BCCMD_MESSAGE_STATUS_WRITE_ONLY 0x0007
505 #define CSR_BCCMD_MESSAGE_STATUS_ERROR 0x0008
506 #define CSR_BCCMD_MESSAGE_STATUS_PERMISION_DENIED 0x0009
507 uint16_t status;
508 uint16_t payload[4];
509 } message;
510 } bccmd;
511
512 m = m_gethdr(M_WAIT, MT_DATA);
513 p = mtod(m, hci_cmd_hdr_t *);
514 p->type = HCI_CMD_PKT;
515 p->opcode = opcode;
516 p->length = sizeof(bccmd);
517 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
518
519 /* setup BCSP command packet */
520 bccmd.last = 1;
521 bccmd.first = 1;
522 bccmd.chanid = CSR_BCCMD_CHANID_BCCMD;
523 bccmd.message.type = htole16(CSR_BCCMD_MESSAGE_TYPE_SETREQ);
524 bccmd.message.length = htole16(sizeof(bccmd.message) >> 1);
525 bccmd.message.seqno = htole16(0);
526 bccmd.message.varid = htole16(CSR_BCCMD_MESSAGE_VARID_CONFIG_UART);
527 bccmd.message.status = htole16(CSR_BCCMD_MESSAGE_STATUS_OK);
528 memset(bccmd.message.payload, 0, sizeof(bccmd.message.payload));
529
530 /* Value = (baud rate / 244.140625) | no parity | 1 stop bit. */
531 bccmd.message.payload[0] = htole16((sc->sc_baud * 64 + 7812) / 15625);
532
533 m_copyback(m, sizeof(hci_cmd_hdr_t), p->length, &bccmd);
534 MBUFQ_ENQUEUE(&unit->hci_cmdq, m);
535 bth4_start(unit);
536
537 error = bth4_waitresp(sc, &m, opcode);
538 if (m != NULL) {
539 /*
540 * XXXX:
541 * We will have to check the HCI_EVENT_VENDOR packet. For
542 * instance, it might be a different HCI_EVENT_VENDOR packet.
543 */
544 if (error != 0) {
545 printf("%s: CSR set UART speed failed: Status 0x%02x\n",
546 device_xname(sc->sc_dev), error);
547 error = EFAULT;
548 }
549 m_freem(m);
550 }
551
552 return error;
553 }
554
555 static int
556 init_swave(struct btuart_softc *sc)
557 {
558 struct mbuf *m;
559 struct hci_unit *unit = &sc->sc_unit;
560 hci_cmd_hdr_t *p;
561 hci_event_hdr_t *e;
562 int i, error;
563 #define HCI_CMD_SWAVE_SET_UART_BAUD_RATE 0xfc0b /* XXXX */
564 const uint16_t opcode = htole16(HCI_CMD_SWAVE_SET_UART_BAUD_RATE);
565 char param[6], *resp;
566 static struct { /* XXXX */
567 int baud;
568 uint8_t param;
569 } swave_baudtbl[] = {
570 { B19200, 0x03 },
571 { B38400, 0x02 },
572 { B57600, 0x01 },
573 { B115200, 0x00 },
574 { B0, 0xff }
575 };
576
577 for (i = 0; swave_baudtbl[i].baud != sc->sc_baud; i++)
578 if (swave_baudtbl[i].baud == B0)
579 return EINVAL;
580
581 m = m_gethdr(M_WAIT, MT_DATA);
582 /* first send 'param access set' command. */
583 p = mtod(m, hci_cmd_hdr_t *);
584 p->type = HCI_CMD_PKT;
585 p->opcode = opcode;
586 p->length = sizeof(param);
587 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
588
589 /* XXXX */
590 param[0] = 0x01; /* param sub command */
591 param[1] = 0x11; /* HCI Tranport Params */
592 param[2] = 0x03; /* length of the parameter following */
593 param[3] = 0x01; /* HCI Transport flow control enable */
594 param[4] = 0x01; /* HCI Transport Type = UART */
595 param[5] = swave_baudtbl[i].param;
596 m_copyback(m, sizeof(hci_cmd_hdr_t), p->length, ¶m);
597
598 MBUFQ_ENQUEUE(&unit->hci_cmdq, m);
599 bth4_start(unit);
600
601 while(1 /* CONSTCOND */) {
602 error = bth4_waitresp(sc, &m, opcode);
603 if (error != 0) {
604 if (m != NULL)
605 m_freem(m);
606 printf("%s: swave set baud rate command failed:"
607 " error 0x%02x\n", device_xname(sc->sc_dev), error);
608 return error;
609 }
610 if (m != NULL) {
611 e = mtod(m, hci_event_hdr_t *);
612 resp = (char *)(e + 1);
613 if (e->length == 7 && *resp == 0xb &&
614 memcmp(resp + 1, param, sizeof(param)) == 0)
615 break;
616 m_freem(m);
617 }
618 }
619
620 /* send 'reset' command consecutively. */
621 p = mtod(m, hci_cmd_hdr_t *);
622 p->type = HCI_CMD_PKT;
623 p->opcode = htole16(HCI_CMD_RESET);
624 p->length = 0;
625 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
626
627 /*
628 * XXXX
629 * Wait until the transmission of the data of 4 bytes * 10 bit is
630 * completed.
631 * 1000000usec * 10bit * 4byte / baud
632 */
633 delay(40000000 / sc->sc_bth4hci.init_baud);
634 return 0;
635 }
636
637 static int
638 init_st(struct btuart_softc *sc)
639 {
640 struct mbuf *m;
641 struct hci_unit *unit = &sc->sc_unit;
642 hci_cmd_hdr_t *p;
643 int i;
644 static struct { /* XXXX */
645 int baud;
646 uint8_t param;
647 } st_baudtbl[] = {
648 { B9600, 0x09 },
649 { B19200, 0x0b },
650 { B38400, 0x0d },
651 { B57600, 0x0e },
652 { B115200, 0x10 },
653 { B230400, 0x12 },
654 { B460800, 0x13 },
655 { B921600, 0x14 },
656 { B0, 0xff }
657 };
658
659 for (i = 0; st_baudtbl[i].baud != sc->sc_baud; i++)
660 if (st_baudtbl[i].baud == B0)
661 return EINVAL;
662
663 m = m_gethdr(M_WAIT, MT_DATA);
664 p = mtod(m, hci_cmd_hdr_t *);
665 p->type = HCI_CMD_PKT;
666 #define HCI_CMD_ST_SET_UART_BAUD_RATE 0xfc46 /* XXXX */
667 p->opcode = htole16(HCI_CMD_ST_SET_UART_BAUD_RATE);
668 p->length = sizeof(st_baudtbl[0].param);
669 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
670 m_copyback(m, sizeof(hci_cmd_hdr_t), p->length, &st_baudtbl[i].param);
671
672 MBUFQ_ENQUEUE(&unit->hci_cmdq, m);
673 bth4_start(unit);
674
675 /*
676 * XXXX
677 * Wait until the transmission of the data of 5 bytes * 10 bit is
678 * completed.
679 * 1000000usec * 10bit * 5byte / baud
680 */
681 delay(50000000 / sc->sc_bth4hci.init_baud);
682 return 0;
683 }
684
685 static int
686 firmload_stlc2500(struct btuart_softc *sc, int size, char *buf)
687 {
688 struct hci_unit *unit = &sc->sc_unit;
689 struct mbuf *m;
690 hci_cmd_hdr_t *p;
691 int error, offset, n;
692 uint16_t opcode = htole16(0xfc2e); /* XXXX */
693 uint8_t seq;
694
695 m = m_gethdr(M_WAIT, MT_DATA);
696 seq = 0;
697 offset = 0;
698 error = 0;
699 while (offset < size) {
700 n = size - offset < 254 ? size - offset : 254;
701
702 p = mtod(m, hci_cmd_hdr_t *);
703 p->type = HCI_CMD_PKT;
704 p->opcode = opcode;
705 p->length = n;
706 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
707 *(char *)(p + 1) = seq;
708 m_copyback(m,
709 sizeof(hci_cmd_hdr_t) + 1, p->length, buf + offset);
710
711 MBUFQ_ENQUEUE(&unit->hci_cmdq, m);
712 bth4_start(unit);
713
714 error = bth4_waitresp(sc, &m, opcode);
715 if (m != NULL) {
716 if (error != 0) {
717 printf("%s: stlc2500 firmware load failed:"
718 " Status 0x%02x\n",
719 device_xname(sc->sc_dev), error);
720 error = EFAULT;
721 break;
722 }
723 }
724
725 seq++;
726 offset += n;
727 }
728 m_freem(m);
729
730 return error;
731 }
732
733 static int
734 init_stlc2500(struct btuart_softc *sc)
735 {
736 struct mbuf *m;
737 struct hci_unit *unit = &sc->sc_unit;
738 hci_cmd_hdr_t *p;
739 hci_event_hdr_t *e;
740 hci_read_local_ver_rp *lv;
741 int error, revision, i;
742 uint16_t opcode;
743 char filename[NAME_MAX], param[8];
744 static const char filenametmpl[] = "STLC2500_R%d_%02d%s";
745 const char *suffix[] = { ".ptc", ".ssf", NULL };
746
747 m = m_gethdr(M_WAIT, MT_DATA);
748 p = mtod(m, hci_cmd_hdr_t *);
749 opcode = htole16(HCI_CMD_READ_LOCAL_VER);
750 p->type = HCI_CMD_PKT;
751 p->opcode = opcode;
752 p->length = 0;
753 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
754
755 MBUFQ_ENQUEUE(&unit->hci_cmdq, m);
756 bth4_start(unit);
757
758 error = bth4_waitresp(sc, &m, opcode);
759 if (m != NULL) {
760 if (error != 0) {
761 printf("%s: HCI_Read_Local_Version_Information failed:"
762 " Status 0x%02x\n", device_xname(sc->sc_dev), error);
763 error = EFAULT;
764 m_freem(m);
765 }
766 }
767 if (error != 0)
768 return error;
769
770 e = mtod(m, hci_event_hdr_t *);
771 lv = (hci_read_local_ver_rp *)(e + 1);
772 revision = le16toh(lv->hci_revision);
773 opcode = htole16(HCI_CMD_RESET);
774 for (i = 0; suffix[i] != NULL; i++) {
775 /* send firmware */
776 snprintf(filename, sizeof(filename), filenametmpl,
777 (uint8_t)(revision >> 8), (uint8_t)revision, suffix[i]);
778 bth4_firmload(sc, filename, firmload_stlc2500);
779
780 p = mtod(m, hci_cmd_hdr_t *);
781 p->type = HCI_CMD_PKT;
782 p->opcode = opcode;
783 p->length = 0;
784 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
785
786 MBUFQ_ENQUEUE(&unit->hci_cmdq, m);
787 bth4_start(unit);
788
789 error = bth4_waitresp(sc, &m, opcode);
790 if (m != NULL) {
791 if (error != 0) {
792 printf("%s: HCI_Reset (%d) failed:"
793 " Status 0x%02x\n",
794 device_xname(sc->sc_dev), i, error);
795 error = EFAULT;
796 m_freem(m);
797 }
798 }
799 if (error != 0)
800 return error;
801 }
802
803 /* XXXX: We will obtain the character string. But I don't know... */
804 p = mtod(m, hci_cmd_hdr_t *);
805 opcode = htole16(0xfc0f); /* XXXXX ?? */
806 p->type = HCI_CMD_PKT;
807 p->opcode = opcode;
808 p->length = 0;
809 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
810
811 MBUFQ_ENQUEUE(&unit->hci_cmdq, m);
812 bth4_start(unit);
813
814 error = bth4_waitresp(sc, &m, opcode);
815 if (m != NULL) {
816 if (error != 0) {
817 printf("%s: failed: opcode 0xfc0f Status 0x%02x\n",
818 device_xname(sc->sc_dev), error);
819 error = EFAULT;
820 m_freem(m);
821 }
822 }
823 if (error != 0)
824 return error;
825 /*
826 * XXXX:
827 * We do not know the beginning point of this character string.
828 * Because it doesn't know the event of this packet.
829 *
830 * printf("%s: %s\n", device_xname(sc->sc_dev), ???);
831 */
832
833 p = mtod(m, hci_cmd_hdr_t *);
834 opcode = htole16(0xfc22); /* XXXXX ?? */
835 p->type = HCI_CMD_PKT;
836 p->opcode = opcode;
837 p->length = sizeof(param);
838 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
839
840 /* XXXX */
841 param[0] = 0xfe;
842 param[1] = 0x06;
843 param[2] = 0xba;
844 param[3] = 0xab;
845 param[4] = 0x00;
846 param[5] = 0xe1;
847 param[6] = 0x80;
848 param[7] = 0x00;
849 m_copyback(m, sizeof(hci_cmd_hdr_t), p->length, param);
850
851 MBUFQ_ENQUEUE(&unit->hci_cmdq, m);
852 bth4_start(unit);
853
854 error = bth4_waitresp(sc, &m, opcode);
855 if (m != NULL) {
856 if (error != 0) {
857 printf("%s: failed: opcode 0xfc0f Status 0x%02x\n",
858 device_xname(sc->sc_dev), error);
859 error = EFAULT;
860 m_freem(m);
861 }
862 }
863 if (error != 0)
864 return error;
865
866 opcode = htole16(HCI_CMD_RESET);
867 p = mtod(m, hci_cmd_hdr_t *);
868 p->type = HCI_CMD_PKT;
869 p->opcode = opcode;
870 p->length = 0;
871 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
872
873 MBUFQ_ENQUEUE(&unit->hci_cmdq, m);
874 bth4_start(unit);
875
876 error = bth4_waitresp(sc, &m, opcode);
877 if (m != NULL) {
878 if (error != 0) {
879 printf("%s: HCI_Reset failed: Status 0x%02x\n",
880 device_xname(sc->sc_dev), error);
881 error = EFAULT;
882 m_freem(m);
883 }
884 }
885
886 return error;
887 }
888
889 static int
890 init_bcm2035(struct btuart_softc *sc)
891 {
892 struct mbuf *m;
893 struct hci_unit *unit = &sc->sc_unit;
894 hci_cmd_hdr_t *p;
895 int i, error;
896 #define HCI_CMD_BCM2035_SET_UART_BAUD_RATE 0xfc18 /* XXXX */
897 const uint16_t opcode = htole16(HCI_CMD_BCM2035_SET_UART_BAUD_RATE);
898 static struct { /* XXXX */
899 int baud;
900 uint16_t param;
901 } bcm2035_baudtbl[] = {
902 { B57600, 0xe600 },
903 { B230400, 0xfa22 },
904 { B460800, 0xfd11 },
905 { B921600, 0xff65 },
906 { B0, 0xffff }
907 };
908
909 for (i = 0; bcm2035_baudtbl[i].baud != sc->sc_baud; i++)
910 if (bcm2035_baudtbl[i].baud == -1)
911 return EINVAL;
912
913 m = m_gethdr(M_WAIT, MT_DATA);
914
915 /*
916 * XXXX: Should we send some commands?
917 * HCI_CMD_RESET and HCI_CMD_READ_LOCAL_VER and
918 * HCI_CMD_READ_LOCAL_COMMANDS
919 */
920
921 p = mtod(m, hci_cmd_hdr_t *);
922 p->type = HCI_CMD_PKT;
923 p->opcode = opcode;
924 p->length = sizeof(bcm2035_baudtbl[0].param);
925 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
926 m_copyback(m, sizeof(hci_cmd_hdr_t), p->length,
927 &bcm2035_baudtbl[i].param);
928
929 MBUFQ_ENQUEUE(&unit->hci_cmdq, m);
930 bth4_start(unit);
931
932 error = bth4_waitresp(sc, &m, opcode);
933 if (m != NULL) {
934 if (error != 0) {
935 printf("%s: bcm2035 set baud rate failed:"
936 " Status 0x%02x\n", device_xname(sc->sc_dev), error);
937 error = EFAULT;
938 }
939 m_freem(m);
940 }
941
942 return error;
943 }
944
945 static int
946 bth4init(struct btuart_softc *sc)
947 {
948 struct tty *tp = sc->sc_tp;
949 struct termios t;
950 int error = 0, s;
951
952 sc->sc_baud = tp->t_ospeed;
953 t.c_cflag = tp->t_cflag;
954 t.c_ispeed = 0;
955 t.c_ospeed = tp->t_ospeed;
956 if ((tp->t_cflag & CRTSCTS) && !(sc->sc_bth4hci.flags & FLOW_CTL))
957 t.c_cflag &= ~CRTSCTS;
958 if (sc->sc_bth4hci.init_baud != 0 &&
959 tp->t_ospeed != sc->sc_bth4hci.init_baud)
960 t.c_ospeed = sc->sc_bth4hci.init_baud;
961 if (t.c_ospeed != tp->t_ospeed || t.c_cflag != tp->t_cflag)
962 error = (*tp->t_param)(tp, &t);
963
964 if (error == 0 && sc->sc_bth4hci.init != NULL)
965 error = (*sc->sc_bth4hci.init)(sc);
966
967 s = splserial();
968 sc->sc_input_acl = hci_input_acl;
969 sc->sc_input_sco = hci_input_sco;
970 sc->sc_input_event = hci_input_event;
971 splx(s);
972
973 if (sc->sc_bth4hci.init_baud != 0 &&
974 sc->sc_bth4hci.init_baud != sc->sc_baud) {
975 t.c_ospeed = sc->sc_baud;
976 t.c_cflag = tp->t_cflag;
977 error = (*tp->t_param)(tp, &t);
978 }
979
980 return error;
981 }
982
983 static void
984 bth4init_input(struct hci_unit *unit, struct mbuf *m)
985 {
986 int i;
987 uint8_t *rptr = mtod(m, uint8_t *);
988 const char *pktstr = NULL;
989
990 switch (*rptr) {
991 case HCI_ACL_DATA_PKT:
992 pktstr = "acl data";
993 break;
994
995 case HCI_SCO_DATA_PKT:
996 pktstr = "sco data";
997 break;
998
999 case HCI_EVENT_PKT:
1000 break;
1001
1002 default:
1003 pktstr = "unknown";
1004 break;
1005 }
1006 if (pktstr != NULL)
1007 printf("%s: %s packet was received in initialization phase\n",
1008 unit->hci_devname, pktstr);
1009 if (
1010 #ifdef BTUART_DEBUG
1011 btuart_debug ||
1012 #endif
1013 pktstr != NULL) {
1014 printf("%s: %s:", __FUNCTION__, unit->hci_devname);
1015 for (i = 0; i < m->m_len; i++)
1016 printf(" %02x", *(rptr + i));
1017 printf("\n");
1018 }
1019
1020 if (*rptr == HCI_EVENT_PKT)
1021 if (unit->hci_eventqlen <= hci_eventq_max) {
1022 unit->hci_eventqlen++;
1023 MBUFQ_ENQUEUE(&unit->hci_eventq, m);
1024 m = NULL;
1025 wakeup(&unit->hci_eventq);
1026 }
1027
1028 if (m != NULL)
1029 m_freem(m);
1030 }
1031
1032
1033 /*
1034 * Line discipline functions.
1035 */
1036 /* ARGSUSED */
1037 static int
1038 bth4open(dev_t device __unused, struct tty *tp)
1039 {
1040 struct btuart_softc *sc;
1041 struct cfdata *cfdata;
1042 struct lwp *l = curlwp; /* XXX */
1043 int error, unit, s;
1044 static char name[] = "btuart";
1045
1046 if ((error = kauth_authorize_device_tty(l->l_cred,
1047 KAUTH_GENERIC_ISSUSER, tp)) != 0)
1048 return error;
1049
1050 s = spltty();
1051
1052 if (tp->t_linesw == &bth4_disc) {
1053 sc = (struct btuart_softc *)tp->t_sc;
1054 if (sc != NULL) {
1055 splx(s);
1056 return EBUSY;
1057 }
1058 }
1059
1060 KASSERT(tp->t_oproc != NULL);
1061
1062 cfdata = malloc(sizeof(struct cfdata), M_DEVBUF, M_WAITOK);
1063 for (unit = 0; unit < btuart_cd.cd_ndevs; unit++)
1064 if (btuart_cd.cd_devs[unit] == NULL)
1065 break;
1066 cfdata->cf_name = name;
1067 cfdata->cf_atname = name;
1068 cfdata->cf_unit = unit;
1069 cfdata->cf_fstate = FSTATE_STAR;
1070
1071 printf("%s%d at tty major %d minor %d",
1072 name, unit, major(tp->t_dev), minor(tp->t_dev));
1073 sc = (struct btuart_softc *)config_attach_pseudo(cfdata);
1074 if (sc == NULL) {
1075 splx(s);
1076 return EIO;
1077 }
1078 tp->t_sc = sc;
1079 sc->sc_tp = tp;
1080
1081 ttyflush(tp, FREAD | FWRITE);
1082
1083 splx(s);
1084
1085 return 0;
1086 }
1087
1088 /* ARGSUSED */
1089 static int
1090 bth4close(struct tty *tp, int flag __unused)
1091 {
1092 struct btuart_softc *sc;
1093 struct cfdata *cfdata;
1094 int s, baud;
1095
1096 sc = tp->t_sc;
1097
1098 /* reset to initial speed */
1099 if (sc->sc_bth4hci.init != NULL) {
1100 baud = sc->sc_baud;
1101 sc->sc_baud = sc->sc_bth4hci.init_baud;
1102 sc->sc_bth4hci.init_baud = baud;
1103 s = splserial();
1104 sc->sc_input_acl = bth4init_input;
1105 sc->sc_input_sco = bth4init_input;
1106 sc->sc_input_event = bth4init_input;
1107 splx(s);
1108 if ((*sc->sc_bth4hci.init)(sc) != 0)
1109 printf("%s: reset speed fail\n", device_xname(sc->sc_dev));
1110 }
1111
1112 s = spltty();
1113 ttyflush(tp, FREAD | FWRITE);
1114 ttyldisc_release(tp->t_linesw);
1115 tp->t_linesw = ttyldisc_default();
1116 if (sc != NULL) {
1117 tp->t_sc = NULL;
1118 if (sc->sc_tp == tp) {
1119 cfdata = device_cfdata(sc->sc_dev);
1120 config_detach(sc->sc_dev, 0);
1121 free(cfdata, M_DEVBUF);
1122 }
1123
1124 }
1125 splx(s);
1126 return 0;
1127 }
1128
1129 /* ARGSUSED */
1130 static int
1131 bth4ioctl(struct tty *tp, u_long cmd, void *data,
1132 int flag __unused, struct lwp *l __unused)
1133 {
1134 struct btuart_softc *sc = (struct btuart_softc *)tp->t_sc;
1135 int error, i;
1136
1137 if (sc == NULL || tp != sc->sc_tp)
1138 return EPASSTHROUGH;
1139
1140 error = 0;
1141 switch (cmd) {
1142 case BTUART_HCITYPE:
1143 for (i = 0; bth4hci[i].type != -1; i++)
1144 if (bth4hci[i].type == *(uint32_t *)data)
1145 break;
1146 if (bth4hci[i].type != -1)
1147 memcpy(&sc->sc_bth4hci, &bth4hci[i],
1148 sizeof(struct bth4hci));
1149 else
1150 error = EINVAL;
1151 break;
1152
1153 case BTUART_INITSPEED:
1154 sc->sc_bth4hci.init_baud = *(uint32_t *)data;
1155 break;
1156
1157 case BTUART_START:
1158 error = bth4init(sc);
1159 break;
1160
1161 default:
1162 error = EPASSTHROUGH;
1163 break;
1164 }
1165
1166 return error;
1167 }
1168
1169 static int
1170 bth4input(int c, struct tty *tp)
1171 {
1172 struct btuart_softc *sc = (struct btuart_softc *)tp->t_sc;
1173 struct mbuf *m = sc->sc_rxp;
1174 int space = 0;
1175
1176 c &= TTY_CHARMASK;
1177
1178 /* If we already started a packet, find the trailing end of it. */
1179 if (m) {
1180 while (m->m_next)
1181 m = m->m_next;
1182
1183 space = M_TRAILINGSPACE(m);
1184 }
1185
1186 if (space == 0) {
1187 if (m == NULL) {
1188 /* new packet */
1189 MGETHDR(m, M_DONTWAIT, MT_DATA);
1190 if (m == NULL) {
1191 printf("%s: out of memory\n",
1192 device_xname(sc->sc_dev));
1193 ++sc->sc_unit.hci_stats.err_rx;
1194 return 0; /* (lost sync) */
1195 }
1196
1197 sc->sc_rxp = m;
1198 m->m_pkthdr.len = m->m_len = 0;
1199 space = MHLEN;
1200
1201 sc->sc_state = BTUART_RECV_PKT_TYPE;
1202 sc->sc_want = 1;
1203 } else {
1204 /* extend mbuf */
1205 MGET(m->m_next, M_DONTWAIT, MT_DATA);
1206 if (m->m_next == NULL) {
1207 printf("%s: out of memory\n",
1208 device_xname(sc->sc_dev));
1209 ++sc->sc_unit.hci_stats.err_rx;
1210 return 0; /* (lost sync) */
1211 }
1212
1213 m = m->m_next;
1214 m->m_len = 0;
1215 space = MLEN;
1216
1217 if (sc->sc_want > MINCLSIZE) {
1218 MCLGET(m, M_DONTWAIT);
1219 if (m->m_flags & M_EXT)
1220 space = MCLBYTES;
1221 }
1222 }
1223 }
1224
1225 mtod(m, uint8_t *)[m->m_len++] = c;
1226 sc->sc_rxp->m_pkthdr.len++;
1227 sc->sc_unit.hci_stats.byte_rx++;
1228
1229 sc->sc_want--;
1230 if (sc->sc_want > 0)
1231 return 0; /* want more */
1232
1233 switch (sc->sc_state) {
1234 case BTUART_RECV_PKT_TYPE: /* Got packet type */
1235
1236 switch (c) {
1237 case HCI_ACL_DATA_PKT:
1238 sc->sc_state = BTUART_RECV_ACL_HDR;
1239 sc->sc_want = sizeof(hci_acldata_hdr_t) - 1;
1240 break;
1241
1242 case HCI_SCO_DATA_PKT:
1243 sc->sc_state = BTUART_RECV_SCO_HDR;
1244 sc->sc_want = sizeof(hci_scodata_hdr_t) - 1;
1245 break;
1246
1247 case HCI_EVENT_PKT:
1248 sc->sc_state = BTUART_RECV_EVENT_HDR;
1249 sc->sc_want = sizeof(hci_event_hdr_t) - 1;
1250 break;
1251
1252 default:
1253 printf("%s: Unknown packet type=%#x!\n",
1254 device_xname(sc->sc_dev), c);
1255 sc->sc_unit.hci_stats.err_rx++;
1256 m_freem(sc->sc_rxp);
1257 sc->sc_rxp = NULL;
1258 return 0; /* (lost sync) */
1259 }
1260
1261 break;
1262
1263 /*
1264 * we assume (correctly of course :) that the packet headers all fit
1265 * into a single pkthdr mbuf
1266 */
1267 case BTUART_RECV_ACL_HDR: /* Got ACL Header */
1268 sc->sc_state = BTUART_RECV_ACL_DATA;
1269 sc->sc_want = mtod(m, hci_acldata_hdr_t *)->length;
1270 sc->sc_want = le16toh(sc->sc_want);
1271 break;
1272
1273 case BTUART_RECV_SCO_HDR: /* Got SCO Header */
1274 sc->sc_state = BTUART_RECV_SCO_DATA;
1275 sc->sc_want = mtod(m, hci_scodata_hdr_t *)->length;
1276 break;
1277
1278 case BTUART_RECV_EVENT_HDR: /* Got Event Header */
1279 sc->sc_state = BTUART_RECV_EVENT_DATA;
1280 sc->sc_want = mtod(m, hci_event_hdr_t *)->length;
1281 break;
1282
1283 case BTUART_RECV_ACL_DATA: /* ACL Packet Complete */
1284 (*sc->sc_input_acl)(&sc->sc_unit, sc->sc_rxp);
1285 sc->sc_unit.hci_stats.acl_rx++;
1286 sc->sc_rxp = m = NULL;
1287 break;
1288
1289 case BTUART_RECV_SCO_DATA: /* SCO Packet Complete */
1290 (*sc->sc_input_sco)(&sc->sc_unit, sc->sc_rxp);
1291 sc->sc_unit.hci_stats.sco_rx++;
1292 sc->sc_rxp = m = NULL;
1293 break;
1294
1295 case BTUART_RECV_EVENT_DATA: /* Event Packet Complete */
1296 sc->sc_unit.hci_stats.evt_rx++;
1297 (*sc->sc_input_event)(&sc->sc_unit, sc->sc_rxp);
1298 sc->sc_rxp = m = NULL;
1299 break;
1300
1301 default:
1302 panic("%s: invalid state %d!\n",
1303 device_xname(sc->sc_dev), sc->sc_state);
1304 }
1305
1306 return 0;
1307 }
1308
1309 static int
1310 bth4start(struct tty *tp)
1311 {
1312 struct btuart_softc *sc = (struct btuart_softc *)tp->t_sc;
1313 struct mbuf *m;
1314 int count, rlen;
1315 uint8_t *rptr;
1316
1317 m = sc->sc_txp;
1318 if (m == NULL) {
1319 sc->sc_unit.hci_flags &= ~BTF_XMIT;
1320 bth4_start(&sc->sc_unit);
1321 return 0;
1322 }
1323
1324 count = 0;
1325 rlen = 0;
1326 rptr = mtod(m, uint8_t *);
1327
1328 for(;;) {
1329 if (rlen >= m->m_len) {
1330 m = m->m_next;
1331 if (m == NULL) {
1332 m = sc->sc_txp;
1333 sc->sc_txp = NULL;
1334
1335 if (M_GETCTX(m, void *) == NULL)
1336 m_freem(m);
1337 else
1338 hci_complete_sco(&sc->sc_unit, m);
1339
1340 break;
1341 }
1342
1343 rlen = 0;
1344 rptr = mtod(m, uint8_t *);
1345 continue;
1346 }
1347
1348 if (putc(*rptr++, &tp->t_outq) < 0) {
1349 m_adj(m, rlen);
1350 break;
1351 }
1352 rlen++;
1353 count++;
1354 }
1355
1356 sc->sc_unit.hci_stats.byte_tx += count;
1357
1358 if (tp->t_outq.c_cc != 0)
1359 (*tp->t_oproc)(tp);
1360
1361 return 0;
1362 }
1363
1364
1365 /*
1366 * HCI UART (H4) functions.
1367 */
1368 static int
1369 bth4_enable(struct hci_unit *unit)
1370 {
1371
1372 if (unit->hci_flags & BTF_RUNNING)
1373 return 0;
1374
1375 unit->hci_flags |= BTF_RUNNING;
1376 unit->hci_flags &= ~BTF_XMIT;
1377
1378 return 0;
1379 }
1380
1381 static void
1382 bth4_disable(struct hci_unit *unit)
1383 {
1384 struct btuart_softc *sc = unit->hci_softc;
1385
1386 if ((unit->hci_flags & BTF_RUNNING) == 0)
1387 return;
1388
1389 if (sc->sc_rxp) {
1390 m_freem(sc->sc_rxp);
1391 sc->sc_rxp = NULL;
1392 }
1393
1394 if (sc->sc_txp) {
1395 m_freem(sc->sc_txp);
1396 sc->sc_txp = NULL;
1397 }
1398
1399 unit->hci_flags &= ~BTF_RUNNING;
1400 }
1401
1402 static void
1403 bth4_start(struct hci_unit *unit)
1404 {
1405 struct btuart_softc *sc = unit->hci_softc;
1406 struct mbuf *m;
1407
1408 KASSERT((unit->hci_flags & BTF_XMIT) == 0);
1409 KASSERT(sc->sc_txp == NULL);
1410
1411 if (MBUFQ_FIRST(&unit->hci_cmdq)) {
1412 MBUFQ_DEQUEUE(&unit->hci_cmdq, m);
1413 unit->hci_stats.cmd_tx++;
1414 M_SETCTX(m, NULL);
1415 goto start;
1416 }
1417
1418 if (MBUFQ_FIRST(&unit->hci_scotxq)) {
1419 MBUFQ_DEQUEUE(&unit->hci_scotxq, m);
1420 unit->hci_stats.sco_tx++;
1421 goto start;
1422 }
1423
1424 if (MBUFQ_FIRST(&unit->hci_acltxq)) {
1425 MBUFQ_DEQUEUE(&unit->hci_acltxq, m);
1426 unit->hci_stats.acl_tx++;
1427 M_SETCTX(m, NULL);
1428 goto start;
1429 }
1430
1431 /* Nothing to send */
1432 return;
1433
1434 start:
1435 sc->sc_txp = m;
1436 unit->hci_flags |= BTF_XMIT;
1437 bth4start(sc->sc_tp);
1438 }
1439