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