1 /* $NetBSD: btuart.c,v 1.17 2007/12/15 00:39:25 perry 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.17 2007/12/15 00:39:25 perry 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