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