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