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