btuart.c revision 1.7.2.2 1 /* $NetBSD: btuart.c,v 1.7.2.2 2008/01/09 01:52:27 matt Exp $ */
2 /*
3 * Copyright (c) 2006, 2007 KIYOHARA Takashi
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: btuart.c,v 1.7.2.2 2008/01/09 01:52:27 matt Exp $");
30
31 #include <sys/types.h>
32 #include <sys/param.h>
33 #include <sys/device.h>
34 #include <sys/errno.h>
35
36 #include <sys/conf.h>
37 #include <sys/fcntl.h>
38 #include <sys/kauth.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/mbuf.h>
42 #include <sys/proc.h>
43 #include <sys/syslimits.h>
44 #include <sys/systm.h>
45 #include <sys/tty.h>
46
47 #include <sys/bus.h>
48 #include <sys/intr.h>
49
50 #include <netbt/bluetooth.h>
51 #include <netbt/hci.h>
52
53 #include <dev/bluetooth/btuart.h>
54 #include <dev/firmload.h>
55
56 #include "ioconf.h"
57
58 #ifdef BTUART_DEBUG
59 int btuart_debug = 1;
60 #endif
61
62 struct btuart_softc;
63 struct bth4hci {
64 int type;
65 int init_baud;
66 #define FLOW_CTL 1
67 int flags;
68 int (*init)(struct btuart_softc *);
69 };
70
71 struct btuart_softc {
72 device_t sc_dev;
73 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: %s\n",
326 filename);
327 return error;
328 }
329 size = firmware_get_size(fh);
330 if ((buf = firmware_malloc(size)) != NULL) {
331 aprint_error_dev(sc->sc_dev, "firmware_malloc failed\n");
332 firmware_close(fh);
333 return ENOMEM;
334 }
335
336 if ((error = firmware_read(fh, 0, buf, size)) != 0)
337 aprint_error_dev(sc->sc_dev, "firmware_read failed\n");
338 if (error == 0)
339 error = (*func_firmload)(sc, size, buf);
340
341 firmware_close(fh);
342 firmware_free(buf, size);
343
344 return error;
345 }
346
347 /*
348 * LSI initialize functions.
349 */
350 static int
351 init_ericsson(struct btuart_softc *sc)
352 {
353 struct mbuf *m;
354 hci_cmd_hdr_t *p;
355 int i, error = 0;
356 const uint16_t opcode = htole16(HCI_CMD_ERICSSON_SET_UART_BAUD_RATE);
357 static struct {
358 int baud;
359 uint8_t param;
360 } ericsson_baudtbl[] = {
361 { B460800, 0x00 },
362 { B230400, 0x01 },
363 { B115200, 0x02 },
364 { B57600, 0x03 },
365 { B28800, 0x04 },
366 { B14400, 0x05 },
367 { B7200, 0x06 },
368 #if defined(B3600)
369 { B3600, 0x07 },
370 #endif
371 { B1800, 0x08 },
372 #if defined(B900)
373 { B900, 0x09 },
374 #endif
375 #if defined(B153600)
376 { B153600, 0x10 },
377 #endif
378 { B76800, 0x11 },
379 { B38400, 0x12 },
380 { B19200, 0x13 },
381 { B9600, 0x14 },
382 { B4800, 0x15 },
383 { B2400, 0x16 },
384 { B1200, 0x17 },
385 { B600, 0x18 },
386 { B300, 0x19 },
387 { B921600, 0x20 },
388 { 200000, 0x25 },
389 { 300000, 0x27 },
390 { 400000, 0x2b },
391 { B0, 0xff }
392 };
393
394 for (i = 0; ericsson_baudtbl[i].baud != sc->sc_baud; i++)
395 if (ericsson_baudtbl[i].baud == B0)
396 return EINVAL;
397
398 m = m_gethdr(M_WAIT, MT_DATA);
399 p = mtod(m, hci_cmd_hdr_t *);
400 p->type = HCI_CMD_PKT;
401 p->opcode = opcode;
402 p->length = sizeof(ericsson_baudtbl[0].param);
403 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
404 m_copyback(m, sizeof(hci_cmd_hdr_t), p->length,
405 &ericsson_baudtbl[i].param);
406
407 bth4_output_cmd(sc->sc_dev, m);
408
409 #if 0
410 error = bth4_waitresp(sc, &m, opcode);
411 if (m != NULL) {
412 if (error != 0) {
413 aprint_error_dev(sc->sc_dev,
414 "EricssonSetUARTBaudRate failed: Status 0x%02x\n",
415 error);
416 error = EFAULT;
417 }
418 m_freem(m);
419 }
420 #else
421 /*
422 * XXXX: We cannot correctly receive this response perhaps. Wait
423 * until the transmission of the data of 5 bytes * 10 bit is completed.
424 * 1000000usec * 10bit * 5byte / baud
425 */
426 delay(50000000 / sc->sc_bth4hci.init_baud);
427 #endif
428 return error;
429 }
430
431 static int
432 init_digi(struct btuart_softc *sc)
433 {
434 struct mbuf *m;
435 hci_cmd_hdr_t *p;
436 uint8_t param;
437
438 /* XXXX */
439 switch (sc->sc_baud) {
440 case B57600:
441 param = 0x08;
442 break;
443
444 case B115200:
445 param = 0x09;
446 break;
447
448 default:
449 return EINVAL;
450 }
451
452 m = m_gethdr(M_WAIT, MT_DATA);
453 p = mtod(m, hci_cmd_hdr_t *);
454 p->type = HCI_CMD_PKT;
455 #define HCI_CMD_DIGIANSWER_SET_UART_BAUD_RATE 0xfc07 /* XXXX */
456 p->opcode = htole16(HCI_CMD_DIGIANSWER_SET_UART_BAUD_RATE);
457 p->length = sizeof(param);
458 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
459 m_copyback(m, sizeof(hci_cmd_hdr_t), p->length, ¶m);
460
461 bth4_output_cmd(sc->sc_dev, m);
462
463 /*
464 * XXXX
465 * Wait until the transmission of the data of 5 bytes * 10 bit is
466 * completed.
467 * 1000000usec * 10bit * 5byte / baud
468 */
469 delay(50000000 / sc->sc_bth4hci.init_baud);
470 return 0;
471 }
472
473 static int
474 init_texas(struct btuart_softc *sc)
475 {
476
477 /* XXXX: Should we obtain the version of LMP? */
478 return 0;
479 }
480
481 static int
482 init_csr(struct btuart_softc *sc)
483 {
484 struct mbuf *m;
485 hci_cmd_hdr_t *p;
486 int error;
487 const uint16_t opcode = htole16(HCI_CMD_CSR_EXTN);
488 struct {
489 uint8_t last :1;
490 uint8_t first :1;
491 #define CSR_BCCMD_CHANID_BCCMD 2
492 #define CSR_BCCMD_CHANID_HQ 3
493 #define CSR_BCCMD_CHANID_DEVMGRLIB 4
494 #define CSR_BCCMD_CHANID_L2CAPLIB 8
495 #define CSR_BCCMD_CHANID_RFCOMMLIB 9
496 #define CSR_BCCMD_CHANID_SDPLIB 10
497 #define CSR_BCCMD_CHANID_DFU 12
498 #define CSR_BCCMD_CHANID_VM 13
499 #define CSR_BCCMD_CHANID_LMDEBUG 20
500 uint8_t chanid :6;
501
502 struct {
503 #define CSR_BCCMD_MESSAGE_TYPE_GETREQ 0x0000
504 #define CSR_BCCMD_MESSAGE_TYPE_GETRESP 0x0001
505 #define CSR_BCCMD_MESSAGE_TYPE_SETREQ 0x0002
506 uint16_t type;
507 uint16_t length;
508 uint16_t seqno;
509 #define CSR_BCCMD_MESSAGE_VARID_CONFIG_UART 0x6802
510 #define CSR_BCCMD_MESSAGE_VARID_CONFIG_UART_STOPB 0x2000
511 #define CSR_BCCMD_MESSAGE_VARID_CONFIG_UART_PARENB 0x4000
512 #define CSR_BCCMD_MESSAGE_VARID_CONFIG_UART_PARODD 0x8000
513 uint16_t varid;
514 #define CSR_BCCMD_MESSAGE_STATUS_OK 0x0000
515 #define CSR_BCCMD_MESSAGE_STATUS_NO_SUCH_VARID 0x0001
516 #define CSR_BCCMD_MESSAGE_STATUS_TOO_BIG 0x0002
517 #define CSR_BCCMD_MESSAGE_STATUS_NO_VALUE 0x0003
518 #define CSR_BCCMD_MESSAGE_STATUS_BAD_REQ 0x0004
519 #define CSR_BCCMD_MESSAGE_STATUS_NO_ACCESS 0x0005
520 #define CSR_BCCMD_MESSAGE_STATUS_READ_ONLY 0x0006
521 #define CSR_BCCMD_MESSAGE_STATUS_WRITE_ONLY 0x0007
522 #define CSR_BCCMD_MESSAGE_STATUS_ERROR 0x0008
523 #define CSR_BCCMD_MESSAGE_STATUS_PERMISION_DENIED 0x0009
524 uint16_t status;
525 uint16_t payload[4];
526 } message;
527 } bccmd;
528
529 m = m_gethdr(M_WAIT, MT_DATA);
530 p = mtod(m, hci_cmd_hdr_t *);
531 p->type = HCI_CMD_PKT;
532 p->opcode = opcode;
533 p->length = sizeof(bccmd);
534 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
535
536 /* setup BCSP command packet */
537 bccmd.last = 1;
538 bccmd.first = 1;
539 bccmd.chanid = CSR_BCCMD_CHANID_BCCMD;
540 bccmd.message.type = htole16(CSR_BCCMD_MESSAGE_TYPE_SETREQ);
541 bccmd.message.length = htole16(sizeof(bccmd.message) >> 1);
542 bccmd.message.seqno = htole16(0);
543 bccmd.message.varid = htole16(CSR_BCCMD_MESSAGE_VARID_CONFIG_UART);
544 bccmd.message.status = htole16(CSR_BCCMD_MESSAGE_STATUS_OK);
545 memset(bccmd.message.payload, 0, sizeof(bccmd.message.payload));
546
547 /* Value = (baud rate / 244.140625) | no parity | 1 stop bit. */
548 bccmd.message.payload[0] = htole16((sc->sc_baud * 64 + 7812) / 15625);
549
550 m_copyback(m, sizeof(hci_cmd_hdr_t), p->length, &bccmd);
551 bth4_output_cmd(sc->sc_dev, m);
552
553 error = bth4_waitresp(sc, &m, opcode);
554 if (m != NULL) {
555 /*
556 * XXXX:
557 * We will have to check the HCI_EVENT_VENDOR packet. For
558 * instance, it might be a different HCI_EVENT_VENDOR packet.
559 */
560 if (error != 0) {
561 aprint_error_dev(sc->sc_dev,
562 "CSR set UART speed failed: Status 0x%02x\n",
563 error);
564 error = EFAULT;
565 }
566 m_freem(m);
567 }
568
569 return error;
570 }
571
572 static int
573 init_swave(struct btuart_softc *sc)
574 {
575 struct mbuf *m;
576 hci_cmd_hdr_t *p;
577 hci_event_hdr_t *e;
578 int i, error;
579 #define HCI_CMD_SWAVE_SET_UART_BAUD_RATE 0xfc0b /* XXXX */
580 const uint16_t opcode = htole16(HCI_CMD_SWAVE_SET_UART_BAUD_RATE);
581 char param[6], *resp;
582 static struct { /* XXXX */
583 int baud;
584 uint8_t param;
585 } swave_baudtbl[] = {
586 { B19200, 0x03 },
587 { B38400, 0x02 },
588 { B57600, 0x01 },
589 { B115200, 0x00 },
590 { B0, 0xff }
591 };
592
593 for (i = 0; swave_baudtbl[i].baud != sc->sc_baud; i++)
594 if (swave_baudtbl[i].baud == B0)
595 return EINVAL;
596
597 m = m_gethdr(M_WAIT, MT_DATA);
598 /* first send 'param access set' command. */
599 p = mtod(m, hci_cmd_hdr_t *);
600 p->type = HCI_CMD_PKT;
601 p->opcode = opcode;
602 p->length = sizeof(param);
603 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
604
605 /* XXXX */
606 param[0] = 0x01; /* param sub command */
607 param[1] = 0x11; /* HCI Tranport Params */
608 param[2] = 0x03; /* length of the parameter following */
609 param[3] = 0x01; /* HCI Transport flow control enable */
610 param[4] = 0x01; /* HCI Transport Type = UART */
611 param[5] = swave_baudtbl[i].param;
612 m_copyback(m, sizeof(hci_cmd_hdr_t), p->length, ¶m);
613
614 bth4_output_cmd(sc->sc_dev, m);
615
616 while(1 /* CONSTCOND */) {
617 error = bth4_waitresp(sc, &m, opcode);
618 if (error != 0) {
619 if (m != NULL)
620 m_freem(m);
621 aprint_error_dev(sc->sc_dev,
622 "swave set baud rate command failed: error 0x%02x\n",
623 error);
624 return error;
625 }
626 if (m != NULL) {
627 e = mtod(m, hci_event_hdr_t *);
628 resp = (char *)(e + 1);
629 if (e->length == 7 && *resp == 0xb &&
630 memcmp(resp + 1, param, sizeof(param)) == 0)
631 break;
632 m_freem(m);
633 }
634 }
635
636 /* send 'reset' command consecutively. */
637 p = mtod(m, hci_cmd_hdr_t *);
638 p->type = HCI_CMD_PKT;
639 p->opcode = htole16(HCI_CMD_RESET);
640 p->length = 0;
641 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
642
643 /*
644 * XXXX
645 * Wait until the transmission of the data of 4 bytes * 10 bit is
646 * completed.
647 * 1000000usec * 10bit * 4byte / baud
648 */
649 delay(40000000 / sc->sc_bth4hci.init_baud);
650 return 0;
651 }
652
653 static int
654 init_st(struct btuart_softc *sc)
655 {
656 struct mbuf *m;
657 hci_cmd_hdr_t *p;
658 int i;
659 static struct { /* XXXX */
660 int baud;
661 uint8_t param;
662 } st_baudtbl[] = {
663 { B9600, 0x09 },
664 { B19200, 0x0b },
665 { B38400, 0x0d },
666 { B57600, 0x0e },
667 { B115200, 0x10 },
668 { B230400, 0x12 },
669 { B460800, 0x13 },
670 { B921600, 0x14 },
671 { B0, 0xff }
672 };
673
674 for (i = 0; st_baudtbl[i].baud != sc->sc_baud; i++)
675 if (st_baudtbl[i].baud == B0)
676 return EINVAL;
677
678 m = m_gethdr(M_WAIT, MT_DATA);
679 p = mtod(m, hci_cmd_hdr_t *);
680 p->type = HCI_CMD_PKT;
681 #define HCI_CMD_ST_SET_UART_BAUD_RATE 0xfc46 /* XXXX */
682 p->opcode = htole16(HCI_CMD_ST_SET_UART_BAUD_RATE);
683 p->length = sizeof(st_baudtbl[0].param);
684 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
685 m_copyback(m, sizeof(hci_cmd_hdr_t), p->length, &st_baudtbl[i].param);
686
687 bth4_output_cmd(sc->sc_dev, m);
688
689 /*
690 * XXXX
691 * Wait until the transmission of the data of 5 bytes * 10 bit is
692 * completed.
693 * 1000000usec * 10bit * 5byte / baud
694 */
695 delay(50000000 / sc->sc_bth4hci.init_baud);
696 return 0;
697 }
698
699 static int
700 firmload_stlc2500(struct btuart_softc *sc, int size, char *buf)
701 {
702 struct mbuf *m;
703 hci_cmd_hdr_t *p;
704 int error, offset, n;
705 uint16_t opcode = htole16(0xfc2e); /* XXXX */
706 uint8_t seq;
707
708 m = m_gethdr(M_WAIT, MT_DATA);
709 seq = 0;
710 offset = 0;
711 error = 0;
712 while (offset < size) {
713 n = size - offset < 254 ? size - offset : 254;
714
715 p = mtod(m, hci_cmd_hdr_t *);
716 p->type = HCI_CMD_PKT;
717 p->opcode = opcode;
718 p->length = n;
719 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
720 *(char *)(p + 1) = seq;
721 m_copyback(m,
722 sizeof(hci_cmd_hdr_t) + 1, p->length, buf + offset);
723
724 bth4_output_cmd(sc->sc_dev, m);
725
726 error = bth4_waitresp(sc, &m, opcode);
727 if (m != NULL) {
728 if (error != 0) {
729 aprint_error_dev(sc->sc_dev,
730 "stlc2500 firmware load failed: Status 0x%02x\n",
731 error);
732 error = EFAULT;
733 break;
734 }
735 }
736
737 seq++;
738 offset += n;
739 }
740 m_freem(m);
741
742 return error;
743 }
744
745 static int
746 init_stlc2500(struct btuart_softc *sc)
747 {
748 struct mbuf *m;
749 hci_cmd_hdr_t *p;
750 hci_event_hdr_t *e;
751 hci_read_local_ver_rp *lv;
752 int error, revision, i;
753 uint16_t opcode;
754 char filename[NAME_MAX], param[8];
755 static const char filenametmpl[] = "STLC2500_R%d_%02d%s";
756 const char *suffix[] = { ".ptc", ".ssf", NULL };
757
758 /* STLC2500 has an ericsson core */
759 error = init_ericsson(sc);
760 if (error != 0)
761 return error;
762
763 if (sc->sc_bth4hci.init_baud != 0 &&
764 sc->sc_bth4hci.init_baud != sc->sc_baud) {
765 struct tty *tp = sc->sc_tp;
766 struct termios t;
767
768 t.c_ispeed = 0;
769 t.c_ospeed = sc->sc_baud;
770 t.c_cflag = tp->t_cflag;
771 error = (*tp->t_param)(tp, &t);
772 if (error != 0)
773 return error;
774 }
775
776 m = m_gethdr(M_WAIT, MT_DATA);
777 p = mtod(m, hci_cmd_hdr_t *);
778 #define HCI_CMD_ERICSSON_READ_REVISION_INFORMATION 0xfc0f /* XXXX */
779 opcode = htole16(HCI_CMD_ERICSSON_READ_REVISION_INFORMATION);
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 bth4_output_cmd(sc->sc_dev, m);
786
787 error = bth4_waitresp(sc, &m, opcode);
788 if (m != NULL) {
789 if (error != 0) {
790 aprint_error_dev(sc->sc_dev,
791 "HCI_Ericsson_Read_Reversion_Information failed:"
792 " Status 0x%02x\n", error);
793 error = EFAULT;
794 m_freem(m);
795 }
796 }
797 if (error != 0)
798 return error;
799
800 p = mtod(m, hci_cmd_hdr_t *);
801 opcode = htole16(HCI_CMD_READ_LOCAL_VER);
802 p->type = HCI_CMD_PKT;
803 p->opcode = opcode;
804 p->length = 0;
805 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
806
807 bth4_output_cmd(sc->sc_dev, m);
808
809 error = bth4_waitresp(sc, &m, opcode);
810 if (m != NULL) {
811 if (error != 0) {
812 aprint_error_dev(sc->sc_dev,
813 "HCI_Read_Local_Version_Information failed:"
814 " Status 0x%02x\n", error);
815 error = EFAULT;
816 m_freem(m);
817 }
818 }
819 if (error != 0)
820 return error;
821
822 e = mtod(m, hci_event_hdr_t *);
823 lv = (hci_read_local_ver_rp *)(e + 1);
824 revision = le16toh(lv->hci_revision);
825 for (i = 0; suffix[i] != NULL; i++) {
826 /* send firmware */
827 snprintf(filename, sizeof(filename), filenametmpl,
828 (uint8_t)(revision >> 8), (uint8_t)revision, suffix[i]);
829 bth4_firmload(sc, filename, firmload_stlc2500);
830 }
831
832 /*
833 * XXXX:
834 * We do not know the beginning point of this character string.
835 * Because it doesn't know the event of this packet.
836 *
837 * aprint_error_dev(sc->sc_dev, "%s\n", ???);
838 */
839
840 p = mtod(m, hci_cmd_hdr_t *);
841 #define HCI_CMD_ST_STORE_IN_NVDS 0xfc22 /* XXXX */
842 opcode = htole16(HCI_CMD_ST_STORE_IN_NVDS);
843 p->type = HCI_CMD_PKT;
844 p->opcode = opcode;
845 p->length = sizeof(param);
846 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
847
848 /* XXXX */
849 param[0] = 0xfe;
850 param[1] = 0x06;
851 param[2] = 0xba;
852 param[3] = 0xab;
853 param[4] = 0x00;
854 param[5] = 0xe1;
855 param[6] = 0x80;
856 param[7] = 0x00;
857 m_copyback(m, sizeof(hci_cmd_hdr_t), p->length, param);
858
859 bth4_output_cmd(sc->sc_dev, m);
860
861 error = bth4_waitresp(sc, &m, opcode);
862 if (m != NULL) {
863 if (error != 0) {
864 aprint_error_dev(sc->sc_dev,
865 "failed: opcode 0xfc0f Status 0x%02x\n", error);
866 error = EFAULT;
867 m_freem(m);
868 }
869 }
870 if (error != 0)
871 return error;
872
873 opcode = htole16(HCI_CMD_RESET);
874 p = mtod(m, hci_cmd_hdr_t *);
875 p->type = HCI_CMD_PKT;
876 p->opcode = opcode;
877 p->length = 0;
878 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
879
880 bth4_output_cmd(sc->sc_dev, m);
881
882 error = bth4_waitresp(sc, &m, opcode);
883 if (m != NULL) {
884 if (error != 0) {
885 aprint_error_dev(sc->sc_dev,
886 "HCI_Reset failed: Status 0x%02x\n", error);
887 error = EFAULT;
888 m_freem(m);
889 }
890 }
891
892 return error;
893 }
894
895 static int
896 init_bgb2xx(struct btuart_softc *sc)
897 {
898 struct mbuf *m;
899 hci_cmd_hdr_t *p;
900 int error;
901 uint16_t opcode;
902 char param[8];
903
904 m = m_gethdr(M_WAIT, MT_DATA);
905 p = mtod(m, hci_cmd_hdr_t *);
906 opcode = htole16(HCI_CMD_ST_STORE_IN_NVDS);
907 p->type = HCI_CMD_PKT;
908 p->opcode = opcode;
909 p->length = sizeof(param);
910 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
911
912 /* XXXX */
913 param[0] = 0xfe;
914 param[1] = 0x06;
915 param[2] = 0xbd;
916 param[3] = 0xb2;
917 param[4] = 0x10;
918 param[5] = 0x00;
919 param[6] = 0xab;
920 param[7] = 0xba;
921 m_copyback(m, sizeof(hci_cmd_hdr_t), p->length, param);
922
923 bth4_output_cmd(sc->sc_dev, m);
924
925 error = bth4_waitresp(sc, &m, opcode);
926 if (m != NULL) {
927 if (error != 0) {
928 aprint_error_dev(sc->sc_dev,
929 "failed: opcode 0xfc0f Status 0x%02x\n", error);
930 error = EFAULT;
931 m_freem(m);
932 }
933 }
934 if (error != 0)
935 return error;
936
937 opcode = htole16(HCI_CMD_RESET);
938 p = mtod(m, hci_cmd_hdr_t *);
939 p->type = HCI_CMD_PKT;
940 p->opcode = opcode;
941 p->length = 0;
942 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
943
944 bth4_output_cmd(sc->sc_dev, m);
945
946 error = bth4_waitresp(sc, &m, opcode);
947 if (m != NULL) {
948 if (error != 0) {
949 aprint_error_dev(sc->sc_dev,
950 "HCI_Reset failed: Status 0x%02x\n", error);
951 error = EFAULT;
952 m_freem(m);
953 }
954 }
955
956 return error;
957 }
958
959 static int
960 init_bcm2035(struct btuart_softc *sc)
961 {
962 struct mbuf *m;
963 hci_cmd_hdr_t *p;
964 int i, error;
965 #define HCI_CMD_BCM2035_SET_UART_BAUD_RATE 0xfc18 /* XXXX */
966 const uint16_t opcode = htole16(HCI_CMD_BCM2035_SET_UART_BAUD_RATE);
967 static struct { /* XXXX */
968 int baud;
969 uint16_t param;
970 } bcm2035_baudtbl[] = {
971 { B57600, 0xe600 },
972 { B230400, 0xfa22 },
973 { B460800, 0xfd11 },
974 { B921600, 0xff65 },
975 { B0, 0xffff }
976 };
977
978 for (i = 0; bcm2035_baudtbl[i].baud != sc->sc_baud; i++)
979 if (bcm2035_baudtbl[i].baud == -1)
980 return EINVAL;
981
982 m = m_gethdr(M_WAIT, MT_DATA);
983
984 /*
985 * XXXX: Should we send some commands?
986 * HCI_CMD_RESET and Set BD_ADDR and
987 * HCI_CMD_READ_LOCAL_VER and HCI_CMD_READ_LOCAL_COMMANDS
988 */
989
990 p = mtod(m, hci_cmd_hdr_t *);
991 p->type = HCI_CMD_PKT;
992 p->opcode = opcode;
993 p->length = sizeof(bcm2035_baudtbl[0].param);
994 m->m_pkthdr.len = m->m_len = sizeof(hci_cmd_hdr_t);
995 m_copyback(m, sizeof(hci_cmd_hdr_t), p->length,
996 &bcm2035_baudtbl[i].param);
997
998 bth4_output_cmd(sc->sc_dev, m);
999
1000 error = bth4_waitresp(sc, &m, opcode);
1001 if (m != NULL) {
1002 if (error != 0) {
1003 aprint_error_dev(sc->sc_dev,
1004 "bcm2035 set baud rate failed: Status 0x%02x\n",
1005 error);
1006 error = EFAULT;
1007 }
1008 m_freem(m);
1009 }
1010
1011 return error;
1012 }
1013
1014 static int
1015 bth4init(struct btuart_softc *sc)
1016 {
1017 struct tty *tp = sc->sc_tp;
1018 struct termios t;
1019 int error = 0, s;
1020
1021 sc->sc_baud = tp->t_ospeed;
1022 t.c_cflag = tp->t_cflag;
1023 t.c_ispeed = 0;
1024 t.c_ospeed = tp->t_ospeed;
1025 if ((tp->t_cflag & CRTSCTS) && !(sc->sc_bth4hci.flags & FLOW_CTL))
1026 t.c_cflag &= ~CRTSCTS;
1027 if (sc->sc_bth4hci.init_baud != 0 &&
1028 tp->t_ospeed != sc->sc_bth4hci.init_baud)
1029 t.c_ospeed = sc->sc_bth4hci.init_baud;
1030 if (t.c_ospeed != tp->t_ospeed || t.c_cflag != tp->t_cflag)
1031 error = (*tp->t_param)(tp, &t);
1032
1033 if (error == 0 && sc->sc_bth4hci.init != NULL)
1034 error = (*sc->sc_bth4hci.init)(sc);
1035
1036 s = splserial();
1037 sc->sc_input_acl = hci_input_acl;
1038 sc->sc_input_sco = hci_input_sco;
1039 sc->sc_input_event = hci_input_event;
1040 splx(s);
1041
1042 if (sc->sc_bth4hci.init_baud != 0 &&
1043 sc->sc_bth4hci.init_baud != sc->sc_baud) {
1044 t.c_ospeed = sc->sc_baud;
1045 t.c_cflag = tp->t_cflag;
1046 error = (*tp->t_param)(tp, &t);
1047 }
1048
1049 return error;
1050 }
1051
1052 static bool
1053 bth4init_input(struct hci_unit *unit, struct mbuf *m)
1054 {
1055 int i;
1056 uint8_t *rptr = mtod(m, uint8_t *);
1057 const char *pktstr = NULL;
1058
1059 switch (*rptr) {
1060 case HCI_ACL_DATA_PKT:
1061 pktstr = "acl data";
1062 break;
1063
1064 case HCI_SCO_DATA_PKT:
1065 pktstr = "sco data";
1066 break;
1067
1068 case HCI_EVENT_PKT:
1069 break;
1070
1071 default:
1072 pktstr = "unknown";
1073 break;
1074 }
1075 if (pktstr != NULL)
1076 aprint_error_dev(unit->hci_dev,
1077 "%s packet was received in initialization phase\n", pktstr);
1078 if (
1079 #ifdef BTUART_DEBUG
1080 btuart_debug ||
1081 #endif
1082 pktstr != NULL) {
1083 aprint_error_dev(unit->hci_dev, "%s:", __func__);
1084 for (i = 0; i < m->m_len; i++)
1085 aprint_error(" %02x", *(rptr + i));
1086 aprint_error("\n");
1087 }
1088
1089 if (*rptr == HCI_EVENT_PKT)
1090 if (unit->hci_eventqlen <= hci_eventq_max) {
1091 unit->hci_eventqlen++;
1092 MBUFQ_ENQUEUE(&unit->hci_eventq, m);
1093 m = NULL;
1094 wakeup(&unit->hci_eventq);
1095 }
1096
1097 if (m != NULL)
1098 m_freem(m);
1099
1100 return true;
1101 }
1102
1103
1104 /*
1105 * Line discipline functions.
1106 */
1107 /* ARGSUSED */
1108 static int
1109 bth4open(dev_t device __unused, struct tty *tp)
1110 {
1111 struct btuart_softc *sc;
1112 device_t dev;
1113 struct cfdata *cfdata;
1114 struct lwp *l = curlwp; /* XXX */
1115 int error, unit, s;
1116 static char name[] = "btuart";
1117
1118 if ((error = kauth_authorize_device_tty(l->l_cred,
1119 KAUTH_GENERIC_ISSUSER, tp)) != 0)
1120 return error;
1121
1122 s = spltty();
1123
1124 if (tp->t_linesw == &bth4_disc) {
1125 sc = (struct btuart_softc *)tp->t_sc;
1126 if (sc != NULL) {
1127 splx(s);
1128 return EBUSY;
1129 }
1130 }
1131
1132 KASSERT(tp->t_oproc != NULL);
1133
1134 cfdata = malloc(sizeof(struct cfdata), M_DEVBUF, M_WAITOK);
1135 for (unit = 0; unit < btuart_cd.cd_ndevs; unit++)
1136 if (btuart_cd.cd_devs[unit] == NULL)
1137 break;
1138 cfdata->cf_name = name;
1139 cfdata->cf_atname = name;
1140 cfdata->cf_unit = unit;
1141 cfdata->cf_fstate = FSTATE_STAR;
1142
1143 aprint_normal("%s%d at tty major %d minor %d",
1144 name, unit, major(tp->t_dev), minor(tp->t_dev));
1145 dev = config_attach_pseudo(cfdata);
1146 if (dev == NULL) {
1147 splx(s);
1148 return EIO;
1149 }
1150 sc = device_private(dev);
1151 mutex_spin_enter(&tty_lock);
1152 tp->t_sc = sc;
1153 sc->sc_tp = tp;
1154 ttyflush(tp, FREAD | FWRITE);
1155 mutex_spin_exit(&tty_lock);
1156
1157 splx(s);
1158
1159 return 0;
1160 }
1161
1162 /* ARGSUSED */
1163 static int
1164 bth4close(struct tty *tp, int flag __unused)
1165 {
1166 struct btuart_softc *sc;
1167 struct cfdata *cfdata;
1168 int s, baud;
1169
1170 sc = tp->t_sc;
1171
1172 /* reset to initial speed */
1173 if (sc->sc_bth4hci.init != NULL) {
1174 baud = sc->sc_baud;
1175 sc->sc_baud = sc->sc_bth4hci.init_baud;
1176 sc->sc_bth4hci.init_baud = baud;
1177 s = splserial();
1178 sc->sc_input_acl = bth4init_input;
1179 sc->sc_input_sco = bth4init_input;
1180 sc->sc_input_event = bth4init_input;
1181 splx(s);
1182 if ((*sc->sc_bth4hci.init)(sc) != 0)
1183 aprint_error_dev(sc->sc_dev, "reset speed fail\n");
1184 }
1185
1186 s = spltty();
1187 mutex_spin_enter(&tty_lock);
1188 ttyflush(tp, FREAD | FWRITE);
1189 mutex_spin_exit(&tty_lock); /* XXX */
1190 ttyldisc_release(tp->t_linesw);
1191 tp->t_linesw = ttyldisc_default();
1192 if (sc != NULL) {
1193 tp->t_sc = NULL;
1194 if (sc->sc_tp == tp) {
1195 cfdata = device_cfdata(sc->sc_dev);
1196 config_detach(sc->sc_dev, 0);
1197 free(cfdata, M_DEVBUF);
1198 }
1199
1200 }
1201 splx(s);
1202 return 0;
1203 }
1204
1205 /* ARGSUSED */
1206 static int
1207 bth4ioctl(struct tty *tp, u_long cmd, void *data,
1208 int flag __unused, struct lwp *l __unused)
1209 {
1210 struct btuart_softc *sc = (struct btuart_softc *)tp->t_sc;
1211 int error, i;
1212
1213 if (sc == NULL || tp != sc->sc_tp)
1214 return EPASSTHROUGH;
1215
1216 error = 0;
1217 switch (cmd) {
1218 case BTUART_HCITYPE:
1219 for (i = 0; bth4hci[i].type != -1; i++)
1220 if (bth4hci[i].type == *(uint32_t *)data)
1221 break;
1222 if (bth4hci[i].type != -1)
1223 memcpy(&sc->sc_bth4hci, &bth4hci[i],
1224 sizeof(struct bth4hci));
1225 else
1226 error = EINVAL;
1227 break;
1228
1229 case BTUART_INITSPEED:
1230 sc->sc_bth4hci.init_baud = *(uint32_t *)data;
1231 break;
1232
1233 case BTUART_START:
1234 error = bth4init(sc);
1235 break;
1236
1237 default:
1238 error = EPASSTHROUGH;
1239 break;
1240 }
1241
1242 return error;
1243 }
1244
1245 static int
1246 bth4input(int c, struct tty *tp)
1247 {
1248 struct btuart_softc *sc = (struct btuart_softc *)tp->t_sc;
1249 struct mbuf *m = sc->sc_rxp;
1250 int space = 0;
1251
1252 c &= TTY_CHARMASK;
1253
1254 /* If we already started a packet, find the trailing end of it. */
1255 if (m) {
1256 while (m->m_next)
1257 m = m->m_next;
1258
1259 space = M_TRAILINGSPACE(m);
1260 }
1261
1262 if (space == 0) {
1263 if (m == NULL) {
1264 /* new packet */
1265 MGETHDR(m, M_DONTWAIT, MT_DATA);
1266 if (m == NULL) {
1267 aprint_error_dev(sc->sc_dev,
1268 "out of memory\n");
1269 sc->sc_stats.err_rx++;
1270 return 0; /* (lost sync) */
1271 }
1272
1273 sc->sc_rxp = m;
1274 m->m_pkthdr.len = m->m_len = 0;
1275 space = MHLEN;
1276
1277 sc->sc_state = BTUART_RECV_PKT_TYPE;
1278 sc->sc_want = 1;
1279 } else {
1280 /* extend mbuf */
1281 MGET(m->m_next, M_DONTWAIT, MT_DATA);
1282 if (m->m_next == NULL) {
1283 aprint_error_dev(sc->sc_dev,
1284 "out of memory\n");
1285 sc->sc_stats.err_rx++;
1286 return 0; /* (lost sync) */
1287 }
1288
1289 m = m->m_next;
1290 m->m_len = 0;
1291 space = MLEN;
1292
1293 if (sc->sc_want > MINCLSIZE) {
1294 MCLGET(m, M_DONTWAIT);
1295 if (m->m_flags & M_EXT)
1296 space = MCLBYTES;
1297 }
1298 }
1299 }
1300
1301 mtod(m, uint8_t *)[m->m_len++] = c;
1302 sc->sc_rxp->m_pkthdr.len++;
1303 sc->sc_stats.byte_rx++;
1304
1305 sc->sc_want--;
1306 if (sc->sc_want > 0)
1307 return 0; /* want more */
1308
1309 switch (sc->sc_state) {
1310 case BTUART_RECV_PKT_TYPE: /* Got packet type */
1311
1312 switch (c) {
1313 case HCI_ACL_DATA_PKT:
1314 sc->sc_state = BTUART_RECV_ACL_HDR;
1315 sc->sc_want = sizeof(hci_acldata_hdr_t) - 1;
1316 break;
1317
1318 case HCI_SCO_DATA_PKT:
1319 sc->sc_state = BTUART_RECV_SCO_HDR;
1320 sc->sc_want = sizeof(hci_scodata_hdr_t) - 1;
1321 break;
1322
1323 case HCI_EVENT_PKT:
1324 sc->sc_state = BTUART_RECV_EVENT_HDR;
1325 sc->sc_want = sizeof(hci_event_hdr_t) - 1;
1326 break;
1327
1328 default:
1329 aprint_error_dev(sc->sc_dev,
1330 "Unknown packet type=%#x!\n", c);
1331 sc->sc_stats.err_rx++;
1332 m_freem(sc->sc_rxp);
1333 sc->sc_rxp = NULL;
1334 return 0; /* (lost sync) */
1335 }
1336
1337 break;
1338
1339 /*
1340 * we assume (correctly of course :) that the packet headers all fit
1341 * into a single pkthdr mbuf
1342 */
1343 case BTUART_RECV_ACL_HDR: /* Got ACL Header */
1344 sc->sc_state = BTUART_RECV_ACL_DATA;
1345 sc->sc_want = mtod(m, hci_acldata_hdr_t *)->length;
1346 sc->sc_want = le16toh(sc->sc_want);
1347 break;
1348
1349 case BTUART_RECV_SCO_HDR: /* Got SCO Header */
1350 sc->sc_state = BTUART_RECV_SCO_DATA;
1351 sc->sc_want = mtod(m, hci_scodata_hdr_t *)->length;
1352 break;
1353
1354 case BTUART_RECV_EVENT_HDR: /* Got Event Header */
1355 sc->sc_state = BTUART_RECV_EVENT_DATA;
1356 sc->sc_want = mtod(m, hci_event_hdr_t *)->length;
1357 break;
1358
1359 case BTUART_RECV_ACL_DATA: /* ACL Packet Complete */
1360 if (!(*sc->sc_input_acl)(sc->sc_unit, sc->sc_rxp))
1361 sc->sc_stats.err_rx++;
1362
1363 sc->sc_stats.acl_rx++;
1364 sc->sc_rxp = m = NULL;
1365 break;
1366
1367 case BTUART_RECV_SCO_DATA: /* SCO Packet Complete */
1368 if (!(*sc->sc_input_sco)(sc->sc_unit, sc->sc_rxp))
1369 sc->sc_stats.err_rx++;
1370
1371 sc->sc_stats.sco_rx++;
1372 sc->sc_rxp = m = NULL;
1373 break;
1374
1375 case BTUART_RECV_EVENT_DATA: /* Event Packet Complete */
1376 if (!(*sc->sc_input_event)(sc->sc_unit, sc->sc_rxp))
1377 sc->sc_stats.err_rx++;
1378
1379 sc->sc_stats.evt_rx++;
1380 sc->sc_rxp = m = NULL;
1381 break;
1382
1383 default:
1384 panic("%s: invalid state %d!\n",
1385 device_xname(sc->sc_dev), sc->sc_state);
1386 }
1387
1388 return 0;
1389 }
1390
1391 static int
1392 bth4start(struct tty *tp)
1393 {
1394 struct btuart_softc *sc = (struct btuart_softc *)tp->t_sc;
1395 struct mbuf *m;
1396 int count, rlen;
1397 uint8_t *rptr;
1398
1399 m = sc->sc_txp;
1400 if (m == NULL) {
1401 sc->sc_flags &= ~BTUART_XMIT;
1402 bth4_start(sc);
1403 return 0;
1404 }
1405
1406 count = 0;
1407 rlen = 0;
1408 rptr = mtod(m, uint8_t *);
1409
1410 for(;;) {
1411 if (rlen >= m->m_len) {
1412 m = m->m_next;
1413 if (m == NULL) {
1414 m = sc->sc_txp;
1415 sc->sc_txp = NULL;
1416
1417 if (M_GETCTX(m, void *) == NULL)
1418 m_freem(m);
1419 else if (!hci_complete_sco(sc->sc_unit, m))
1420 sc->sc_stats.err_tx++;
1421
1422 break;
1423 }
1424
1425 rlen = 0;
1426 rptr = mtod(m, uint8_t *);
1427 continue;
1428 }
1429
1430 if (putc(*rptr++, &tp->t_outq) < 0) {
1431 m_adj(m, rlen);
1432 break;
1433 }
1434 rlen++;
1435 count++;
1436 }
1437
1438 sc->sc_stats.byte_tx += count;
1439
1440 if (tp->t_outq.c_cc != 0)
1441 (*tp->t_oproc)(tp);
1442
1443 return 0;
1444 }
1445
1446
1447 /*
1448 * HCI UART (H4) functions.
1449 */
1450 static int
1451 bth4_enable(device_t self)
1452 {
1453 struct btuart_softc *sc = device_private(self);
1454 int s;
1455
1456 if (sc->sc_flags & BTUART_ENABLED)
1457 return 0;
1458
1459 s = spltty();
1460
1461 sc->sc_flags |= BTUART_ENABLED;
1462 sc->sc_flags &= ~BTUART_XMIT;
1463
1464 splx(s);
1465
1466 return 0;
1467 }
1468
1469 static void
1470 bth4_disable(device_t self)
1471 {
1472 struct btuart_softc *sc = device_private(self);
1473 int s;
1474
1475 if ((sc->sc_flags & BTUART_ENABLED) == 0)
1476 return;
1477
1478 s = spltty();
1479
1480 if (sc->sc_rxp) {
1481 m_freem(sc->sc_rxp);
1482 sc->sc_rxp = NULL;
1483 }
1484
1485 if (sc->sc_txp) {
1486 m_freem(sc->sc_txp);
1487 sc->sc_txp = NULL;
1488 }
1489
1490 MBUFQ_DRAIN(&sc->sc_cmdq);
1491 MBUFQ_DRAIN(&sc->sc_aclq);
1492 MBUFQ_DRAIN(&sc->sc_scoq);
1493
1494 sc->sc_flags &= ~BTUART_ENABLED;
1495
1496 splx(s);
1497 }
1498
1499 static void
1500 bth4_start(struct btuart_softc *sc)
1501 {
1502 struct mbuf *m;
1503
1504 KASSERT((sc->sc_flags & BTUART_XMIT) == 0);
1505 KASSERT(sc->sc_txp == NULL);
1506
1507 if (MBUFQ_FIRST(&sc->sc_cmdq)) {
1508 MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
1509 sc->sc_stats.cmd_tx++;
1510 goto start;
1511 }
1512
1513 if (MBUFQ_FIRST(&sc->sc_scoq)) {
1514 MBUFQ_DEQUEUE(&sc->sc_scoq, m);
1515 sc->sc_stats.sco_tx++;
1516 goto start;
1517 }
1518
1519 if (MBUFQ_FIRST(&sc->sc_aclq)) {
1520 MBUFQ_DEQUEUE(&sc->sc_aclq, m);
1521 sc->sc_stats.acl_tx++;
1522 goto start;
1523 }
1524
1525 /* Nothing to send */
1526 return;
1527
1528 start:
1529 sc->sc_txp = m;
1530 sc->sc_flags |= BTUART_XMIT;
1531 bth4start(sc->sc_tp);
1532 }
1533
1534 static void
1535 bth4_output_cmd(device_t self, struct mbuf *m)
1536 {
1537 struct btuart_softc *sc = device_private(self);
1538 int s;
1539
1540 KASSERT(sc->sc_flags & BTUART_ENABLED);
1541
1542 M_SETCTX(m, NULL);
1543
1544 s = spltty();
1545 MBUFQ_ENQUEUE(&sc->sc_cmdq, m);
1546 if ((sc->sc_flags & BTUART_XMIT) == 0)
1547 bth4_start(sc);
1548
1549 splx(s);
1550 }
1551
1552 static void
1553 bth4_output_acl(device_t self, struct mbuf *m)
1554 {
1555 struct btuart_softc *sc = device_private(self);
1556 int s;
1557
1558 KASSERT(sc->sc_flags & BTUART_ENABLED);
1559
1560 M_SETCTX(m, NULL);
1561
1562 s = spltty();
1563 MBUFQ_ENQUEUE(&sc->sc_aclq, m);
1564 if ((sc->sc_flags & BTUART_XMIT) == 0)
1565 bth4_start(sc);
1566
1567 splx(s);
1568 }
1569
1570 static void
1571 bth4_output_sco(device_t self, struct mbuf *m)
1572 {
1573 struct btuart_softc *sc = device_private(self);
1574 int s;
1575
1576 KASSERT(sc->sc_flags & BTUART_ENABLED);
1577
1578 s = spltty();
1579 MBUFQ_ENQUEUE(&sc->sc_scoq, m);
1580 if ((sc->sc_flags & BTUART_XMIT) == 0)
1581 bth4_start(sc);
1582
1583 splx(s);
1584 }
1585
1586 static void
1587 bth4_stats(device_t self, struct bt_stats *dest, int flush)
1588 {
1589 struct btuart_softc *sc = device_private(self);
1590 int s;
1591
1592 s = spltty();
1593
1594 memcpy(dest, &sc->sc_stats, sizeof(struct bt_stats));
1595
1596 if (flush)
1597 memset(&sc->sc_stats, 0, sizeof(struct bt_stats));
1598
1599 splx(s);
1600 }
1601