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