1 /* $NetBSD: btsco.c,v 1.22 2008/08/06 15:01:23 plunky Exp $ */ 2 3 /*- 4 * Copyright (c) 2006 Itronix Inc. 5 * All rights reserved. 6 * 7 * Written by Iain Hibbert for Itronix Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. The name of Itronix Inc. may not be used to endorse 18 * or promote products derived from this software without specific 19 * prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY 25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 28 * ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <sys/cdefs.h> 35 __KERNEL_RCSID(0, "$NetBSD: btsco.c,v 1.22 2008/08/06 15:01:23 plunky Exp $"); 36 37 #include <sys/param.h> 38 #include <sys/audioio.h> 39 #include <sys/conf.h> 40 #include <sys/device.h> 41 #include <sys/fcntl.h> 42 #include <sys/kernel.h> 43 #include <sys/queue.h> 44 #include <sys/malloc.h> 45 #include <sys/mbuf.h> 46 #include <sys/proc.h> 47 #include <sys/socketvar.h> 48 #include <sys/systm.h> 49 #include <sys/intr.h> 50 51 #include <prop/proplib.h> 52 53 #include <netbt/bluetooth.h> 54 #include <netbt/rfcomm.h> 55 #include <netbt/sco.h> 56 57 #include <dev/audio_if.h> 58 #include <dev/auconv.h> 59 #include <dev/mulaw.h> 60 61 #include <dev/bluetooth/btdev.h> 62 #include <dev/bluetooth/btsco.h> 63 64 #undef DPRINTF 65 #undef DPRINTFN 66 67 #ifdef BTSCO_DEBUG 68 int btsco_debug = BTSCO_DEBUG; 69 #define DPRINTF(fmt, args...) do { \ 70 if (btsco_debug) \ 71 printf("%s: "fmt, __func__ , ##args); \ 72 } while (/* CONSTCOND */0) 73 74 #define DPRINTFN(n, fmt, args...) do { \ 75 if (btsco_debug > (n)) \ 76 printf("%s: "fmt, __func__ , ##args); \ 77 } while (/* CONSTCOND */0) 78 #else 79 #define DPRINTF(...) 80 #define DPRINTFN(...) 81 #endif 82 83 /***************************************************************************** 84 * 85 * Bluetooth SCO Audio device 86 */ 87 88 /* btsco softc */ 89 struct btsco_softc { 90 uint16_t sc_flags; 91 const char *sc_name; /* our device_xname */ 92 93 device_t sc_audio; /* MI audio device */ 94 void *sc_intr; /* interrupt cookie */ 95 kcondvar_t sc_connect; /* connect wait */ 96 97 /* Bluetooth */ 98 bdaddr_t sc_laddr; /* local address */ 99 bdaddr_t sc_raddr; /* remote address */ 100 uint16_t sc_state; /* link state */ 101 struct sco_pcb *sc_sco; /* SCO handle */ 102 struct sco_pcb *sc_sco_l; /* SCO listen handle */ 103 uint16_t sc_mtu; /* SCO mtu */ 104 uint8_t sc_channel; /* RFCOMM channel */ 105 int sc_err; /* stored error */ 106 107 /* Receive */ 108 int sc_rx_want; /* bytes wanted */ 109 uint8_t *sc_rx_block; /* receive block */ 110 void (*sc_rx_intr)(void *); /* callback */ 111 void *sc_rx_intrarg; /* callback arg */ 112 struct mbuf *sc_rx_mbuf; /* leftover mbuf */ 113 114 /* Transmit */ 115 int sc_tx_size; /* bytes to send */ 116 int sc_tx_pending; /* packets pending */ 117 uint8_t *sc_tx_block; /* transmit block */ 118 void (*sc_tx_intr)(void *); /* callback */ 119 void *sc_tx_intrarg; /* callback arg */ 120 void *sc_tx_buf; /* transmit buffer */ 121 int sc_tx_refcnt; /* buffer refcnt */ 122 123 /* mixer data */ 124 int sc_vgs; /* speaker volume */ 125 int sc_vgm; /* mic volume */ 126 }; 127 128 /* sc_state */ 129 #define BTSCO_CLOSED 0 130 #define BTSCO_WAIT_CONNECT 1 131 #define BTSCO_OPEN 2 132 133 /* sc_flags */ 134 #define BTSCO_LISTEN (1 << 1) 135 136 /* autoconf(9) glue */ 137 static int btsco_match(device_t, struct cfdata *, void *); 138 static void btsco_attach(device_t, device_t, void *); 139 static int btsco_detach(device_t, int); 140 141 CFATTACH_DECL_NEW(btsco, sizeof(struct btsco_softc), 142 btsco_match, btsco_attach, btsco_detach, NULL); 143 144 /* audio(9) glue */ 145 static int btsco_open(void *, int); 146 static void btsco_close(void *); 147 static int btsco_query_encoding(void *, struct audio_encoding *); 148 static int btsco_set_params(void *, int, int, audio_params_t *, audio_params_t *, 149 stream_filter_list_t *, stream_filter_list_t *); 150 static int btsco_round_blocksize(void *, int, int, const audio_params_t *); 151 static int btsco_start_output(void *, void *, int, void (*)(void *), void *); 152 static int btsco_start_input(void *, void *, int, void (*)(void *), void *); 153 static int btsco_halt_output(void *); 154 static int btsco_halt_input(void *); 155 static int btsco_getdev(void *, struct audio_device *); 156 static int btsco_setfd(void *, int); 157 static int btsco_set_port(void *, mixer_ctrl_t *); 158 static int btsco_get_port(void *, mixer_ctrl_t *); 159 static int btsco_query_devinfo(void *, mixer_devinfo_t *); 160 static void *btsco_allocm(void *, int, size_t, struct malloc_type *, int); 161 static void btsco_freem(void *, void *, struct malloc_type *); 162 static int btsco_get_props(void *); 163 static int btsco_dev_ioctl(void *, u_long, void *, int, struct lwp *); 164 165 static const struct audio_hw_if btsco_if = { 166 btsco_open, /* open */ 167 btsco_close, /* close */ 168 NULL, /* drain */ 169 btsco_query_encoding, /* query_encoding */ 170 btsco_set_params, /* set_params */ 171 btsco_round_blocksize, /* round_blocksize */ 172 NULL, /* commit_settings */ 173 NULL, /* init_output */ 174 NULL, /* init_input */ 175 btsco_start_output, /* start_output */ 176 btsco_start_input, /* start_input */ 177 btsco_halt_output, /* halt_output */ 178 btsco_halt_input, /* halt_input */ 179 NULL, /* speaker_ctl */ 180 btsco_getdev, /* getdev */ 181 btsco_setfd, /* setfd */ 182 btsco_set_port, /* set_port */ 183 btsco_get_port, /* get_port */ 184 btsco_query_devinfo, /* query_devinfo */ 185 btsco_allocm, /* allocm */ 186 btsco_freem, /* freem */ 187 NULL, /* round_buffersize */ 188 NULL, /* mappage */ 189 btsco_get_props, /* get_props */ 190 NULL, /* trigger_output */ 191 NULL, /* trigger_input */ 192 btsco_dev_ioctl, /* dev_ioctl */ 193 NULL, /* powerstate */ 194 }; 195 196 static const struct audio_device btsco_device = { 197 "Bluetooth Audio", 198 "", 199 "btsco" 200 }; 201 202 /* Voice_Setting == 0x0060: 8000Hz, mono, 16-bit, slinear_le */ 203 static const struct audio_format btsco_format = { 204 NULL, /* driver_data */ 205 (AUMODE_PLAY | AUMODE_RECORD), /* mode */ 206 AUDIO_ENCODING_SLINEAR_LE, /* encoding */ 207 16, /* validbits */ 208 16, /* precision */ 209 1, /* channels */ 210 AUFMT_MONAURAL, /* channel_mask */ 211 1, /* frequency_type */ 212 { 8000 } /* frequency */ 213 }; 214 215 /* bluetooth(9) glue for SCO */ 216 static void btsco_sco_connecting(void *); 217 static void btsco_sco_connected(void *); 218 static void btsco_sco_disconnected(void *, int); 219 static void *btsco_sco_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *); 220 static void btsco_sco_complete(void *, int); 221 static void btsco_sco_linkmode(void *, int); 222 static void btsco_sco_input(void *, struct mbuf *); 223 224 static const struct btproto btsco_sco_proto = { 225 btsco_sco_connecting, 226 btsco_sco_connected, 227 btsco_sco_disconnected, 228 btsco_sco_newconn, 229 btsco_sco_complete, 230 btsco_sco_linkmode, 231 btsco_sco_input, 232 }; 233 234 235 /***************************************************************************** 236 * 237 * btsco definitions 238 */ 239 240 /* 241 * btsco mixer class 242 */ 243 #define BTSCO_VGS 0 244 #define BTSCO_VGM 1 245 #define BTSCO_INPUT_CLASS 2 246 #define BTSCO_OUTPUT_CLASS 3 247 248 /* connect timeout */ 249 #define BTSCO_TIMEOUT (30 * hz) 250 251 /* misc btsco functions */ 252 static void btsco_extfree(struct mbuf *, void *, size_t, void *); 253 static void btsco_intr(void *); 254 255 256 /***************************************************************************** 257 * 258 * btsco autoconf(9) routines 259 */ 260 261 static int 262 btsco_match(device_t self, struct cfdata *cfdata, void *aux) 263 { 264 prop_dictionary_t dict = aux; 265 prop_object_t obj; 266 267 obj = prop_dictionary_get(dict, BTDEVservice); 268 if (prop_string_equals_cstring(obj, "HSET")) 269 return 1; 270 271 if (prop_string_equals_cstring(obj, "HF")) 272 return 1; 273 274 return 0; 275 } 276 277 static void 278 btsco_attach(device_t parent, device_t self, void *aux) 279 { 280 struct btsco_softc *sc = device_private(self); 281 prop_dictionary_t dict = aux; 282 prop_object_t obj; 283 284 /* 285 * Init softc 286 */ 287 sc->sc_vgs = 200; 288 sc->sc_vgm = 200; 289 sc->sc_state = BTSCO_CLOSED; 290 sc->sc_name = device_xname(self); 291 cv_init(&sc->sc_connect, "connect"); 292 293 /* 294 * copy in our configuration info 295 */ 296 obj = prop_dictionary_get(dict, BTDEVladdr); 297 bdaddr_copy(&sc->sc_laddr, prop_data_data_nocopy(obj)); 298 299 obj = prop_dictionary_get(dict, BTDEVraddr); 300 bdaddr_copy(&sc->sc_raddr, prop_data_data_nocopy(obj)); 301 302 obj = prop_dictionary_get(dict, BTDEVservice); 303 if (prop_string_equals_cstring(obj, "HF")) { 304 sc->sc_flags |= BTSCO_LISTEN; 305 aprint_verbose(" listen mode"); 306 } 307 308 obj = prop_dictionary_get(dict, BTSCOchannel); 309 if (prop_object_type(obj) != PROP_TYPE_NUMBER 310 || prop_number_integer_value(obj) < RFCOMM_CHANNEL_MIN 311 || prop_number_integer_value(obj) > RFCOMM_CHANNEL_MAX) { 312 aprint_error(" invalid %s", BTSCOchannel); 313 return; 314 } 315 sc->sc_channel = prop_number_integer_value(obj); 316 317 aprint_verbose(" channel %d", sc->sc_channel); 318 aprint_normal("\n"); 319 320 DPRINTF("sc=%p\n", sc); 321 322 /* 323 * set up transmit interrupt 324 */ 325 sc->sc_intr = softint_establish(SOFTINT_NET, btsco_intr, sc); 326 if (sc->sc_intr == NULL) { 327 aprint_error_dev(self, "softint_establish failed\n"); 328 return; 329 } 330 331 /* 332 * attach audio device 333 */ 334 sc->sc_audio = audio_attach_mi(&btsco_if, sc, self); 335 if (sc->sc_audio == NULL) { 336 aprint_error_dev(self, "audio_attach_mi failed\n"); 337 return; 338 } 339 } 340 341 static int 342 btsco_detach(device_t self, int flags) 343 { 344 struct btsco_softc *sc = device_private(self); 345 346 DPRINTF("sc=%p\n", sc); 347 348 mutex_enter(bt_lock); 349 if (sc->sc_sco != NULL) { 350 DPRINTF("sc_sco=%p\n", sc->sc_sco); 351 sco_disconnect(sc->sc_sco, 0); 352 sco_detach(&sc->sc_sco); 353 sc->sc_sco = NULL; 354 } 355 356 if (sc->sc_sco_l != NULL) { 357 DPRINTF("sc_sco_l=%p\n", sc->sc_sco_l); 358 sco_detach(&sc->sc_sco_l); 359 sc->sc_sco_l = NULL; 360 } 361 mutex_exit(bt_lock); 362 363 if (sc->sc_audio != NULL) { 364 DPRINTF("sc_audio=%p\n", sc->sc_audio); 365 config_detach(sc->sc_audio, flags); 366 sc->sc_audio = NULL; 367 } 368 369 if (sc->sc_intr != NULL) { 370 softint_disestablish(sc->sc_intr); 371 sc->sc_intr = NULL; 372 } 373 374 if (sc->sc_rx_mbuf != NULL) { 375 m_freem(sc->sc_rx_mbuf); 376 sc->sc_rx_mbuf = NULL; 377 } 378 379 if (sc->sc_tx_refcnt > 0) { 380 aprint_error_dev(self, "tx_refcnt=%d!\n", sc->sc_tx_refcnt); 381 382 if ((flags & DETACH_FORCE) == 0) 383 return EAGAIN; 384 } 385 386 cv_destroy(&sc->sc_connect); 387 388 return 0; 389 } 390 391 /***************************************************************************** 392 * 393 * bluetooth(9) methods for SCO 394 * 395 * All these are called from Bluetooth Protocol code, in a soft 396 * interrupt context at IPL_SOFTNET. 397 */ 398 399 static void 400 btsco_sco_connecting(void *arg) 401 { 402 /* struct btsco_softc *sc = arg; */ 403 404 /* dont care */ 405 } 406 407 static void 408 btsco_sco_connected(void *arg) 409 { 410 struct btsco_softc *sc = arg; 411 412 DPRINTF("%s\n", sc->sc_name); 413 414 KASSERT(sc->sc_sco != NULL); 415 KASSERT(sc->sc_state == BTSCO_WAIT_CONNECT); 416 417 /* 418 * If we are listening, no more need 419 */ 420 if (sc->sc_sco_l != NULL) 421 sco_detach(&sc->sc_sco_l); 422 423 sc->sc_state = BTSCO_OPEN; 424 cv_broadcast(&sc->sc_connect); 425 } 426 427 static void 428 btsco_sco_disconnected(void *arg, int err) 429 { 430 struct btsco_softc *sc = arg; 431 int s; 432 433 DPRINTF("%s sc_state %d\n", sc->sc_name, sc->sc_state); 434 435 KASSERT(sc->sc_sco != NULL); 436 437 sc->sc_err = err; 438 sco_detach(&sc->sc_sco); 439 440 switch (sc->sc_state) { 441 case BTSCO_CLOSED: /* dont think this can happen */ 442 break; 443 444 case BTSCO_WAIT_CONNECT: /* connect failed */ 445 cv_broadcast(&sc->sc_connect); 446 break; 447 448 case BTSCO_OPEN: /* link lost */ 449 /* 450 * If IO is in progress, tell the audio driver that it 451 * has completed so that when it tries to send more, we 452 * can indicate an error. 453 */ 454 s = splaudio(); 455 if (sc->sc_tx_pending > 0) { 456 sc->sc_tx_pending = 0; 457 (*sc->sc_tx_intr)(sc->sc_tx_intrarg); 458 } 459 if (sc->sc_rx_want > 0) { 460 sc->sc_rx_want = 0; 461 (*sc->sc_rx_intr)(sc->sc_rx_intrarg); 462 } 463 splx(s); 464 break; 465 466 default: 467 UNKNOWN(sc->sc_state); 468 } 469 470 sc->sc_state = BTSCO_CLOSED; 471 } 472 473 static void * 474 btsco_sco_newconn(void *arg, struct sockaddr_bt *laddr, 475 struct sockaddr_bt *raddr) 476 { 477 struct btsco_softc *sc = arg; 478 479 DPRINTF("%s\n", sc->sc_name); 480 481 if (bdaddr_same(&raddr->bt_bdaddr, &sc->sc_raddr) == 0 482 || sc->sc_state != BTSCO_WAIT_CONNECT 483 || sc->sc_sco != NULL) 484 return NULL; 485 486 sco_attach(&sc->sc_sco, &btsco_sco_proto, sc); 487 return sc->sc_sco; 488 } 489 490 static void 491 btsco_sco_complete(void *arg, int count) 492 { 493 struct btsco_softc *sc = arg; 494 int s; 495 496 DPRINTFN(10, "%s count %d\n", sc->sc_name, count); 497 498 s = splaudio(); 499 if (sc->sc_tx_pending > 0) { 500 sc->sc_tx_pending -= count; 501 if (sc->sc_tx_pending == 0) 502 (*sc->sc_tx_intr)(sc->sc_tx_intrarg); 503 } 504 splx(s); 505 } 506 507 static void 508 btsco_sco_linkmode(void *arg, int new) 509 { 510 /* struct btsco_softc *sc = arg; */ 511 512 /* dont care */ 513 } 514 515 static void 516 btsco_sco_input(void *arg, struct mbuf *m) 517 { 518 struct btsco_softc *sc = arg; 519 int len, s; 520 521 DPRINTFN(10, "%s len=%d\n", sc->sc_name, m->m_pkthdr.len); 522 523 s = splaudio(); 524 if (sc->sc_rx_want == 0) { 525 m_freem(m); 526 } else { 527 KASSERT(sc->sc_rx_intr != NULL); 528 KASSERT(sc->sc_rx_block != NULL); 529 530 len = MIN(sc->sc_rx_want, m->m_pkthdr.len); 531 m_copydata(m, 0, len, sc->sc_rx_block); 532 533 sc->sc_rx_want -= len; 534 sc->sc_rx_block += len; 535 536 if (len > m->m_pkthdr.len) { 537 if (sc->sc_rx_mbuf != NULL) 538 m_freem(sc->sc_rx_mbuf); 539 540 m_adj(m, len); 541 sc->sc_rx_mbuf = m; 542 } else { 543 m_freem(m); 544 } 545 546 if (sc->sc_rx_want == 0) 547 (*sc->sc_rx_intr)(sc->sc_rx_intrarg); 548 } 549 splx(s); 550 } 551 552 553 /***************************************************************************** 554 * 555 * audio(9) methods 556 * 557 */ 558 559 static int 560 btsco_open(void *hdl, int flags) 561 { 562 struct sockaddr_bt sa; 563 struct btsco_softc *sc = hdl; 564 struct sockopt sopt; 565 int err, timo; 566 567 DPRINTF("%s flags 0x%x\n", sc->sc_name, flags); 568 /* flags FREAD & FWRITE? */ 569 570 if (sc->sc_sco != NULL || sc->sc_sco_l != NULL) 571 return EIO; 572 573 mutex_enter(bt_lock); 574 575 memset(&sa, 0, sizeof(sa)); 576 sa.bt_len = sizeof(sa); 577 sa.bt_family = AF_BLUETOOTH; 578 bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr); 579 580 if (sc->sc_flags & BTSCO_LISTEN) { 581 err = sco_attach(&sc->sc_sco_l, &btsco_sco_proto, sc); 582 if (err) 583 goto done; 584 585 err = sco_bind(sc->sc_sco_l, &sa); 586 if (err) { 587 sco_detach(&sc->sc_sco_l); 588 goto done; 589 } 590 591 err = sco_listen(sc->sc_sco_l); 592 if (err) { 593 sco_detach(&sc->sc_sco_l); 594 goto done; 595 } 596 597 timo = 0; /* no timeout */ 598 } else { 599 err = sco_attach(&sc->sc_sco, &btsco_sco_proto, sc); 600 if (err) 601 goto done; 602 603 err = sco_bind(sc->sc_sco, &sa); 604 if (err) { 605 sco_detach(&sc->sc_sco); 606 goto done; 607 } 608 609 bdaddr_copy(&sa.bt_bdaddr, &sc->sc_raddr); 610 err = sco_connect(sc->sc_sco, &sa); 611 if (err) { 612 sco_detach(&sc->sc_sco); 613 goto done; 614 } 615 616 timo = BTSCO_TIMEOUT; 617 } 618 619 sc->sc_state = BTSCO_WAIT_CONNECT; 620 while (err == 0 && sc->sc_state == BTSCO_WAIT_CONNECT) 621 err = cv_timedwait_sig(&sc->sc_connect, bt_lock, timo); 622 623 switch (sc->sc_state) { 624 case BTSCO_CLOSED: /* disconnected */ 625 err = sc->sc_err; 626 627 /* fall through to */ 628 case BTSCO_WAIT_CONNECT: /* error */ 629 if (sc->sc_sco != NULL) 630 sco_detach(&sc->sc_sco); 631 632 if (sc->sc_sco_l != NULL) 633 sco_detach(&sc->sc_sco_l); 634 635 break; 636 637 case BTSCO_OPEN: /* hurrah */ 638 sockopt_init(&sopt, BTPROTO_SCO, SO_SCO_MTU, 0); 639 (void)sco_getopt(sc->sc_sco, &sopt); 640 (void)sockopt_get(&sopt, &sc->sc_mtu, sizeof(sc->sc_mtu)); 641 sockopt_destroy(&sopt); 642 break; 643 644 default: 645 UNKNOWN(sc->sc_state); 646 break; 647 } 648 649 done: 650 mutex_exit(bt_lock); 651 652 DPRINTF("done err=%d, sc_state=%d, sc_mtu=%d\n", 653 err, sc->sc_state, sc->sc_mtu); 654 return err; 655 } 656 657 static void 658 btsco_close(void *hdl) 659 { 660 struct btsco_softc *sc = hdl; 661 662 DPRINTF("%s\n", sc->sc_name); 663 664 mutex_enter(bt_lock); 665 if (sc->sc_sco != NULL) { 666 sco_disconnect(sc->sc_sco, 0); 667 sco_detach(&sc->sc_sco); 668 } 669 670 if (sc->sc_sco_l != NULL) { 671 sco_detach(&sc->sc_sco_l); 672 } 673 mutex_exit(bt_lock); 674 675 if (sc->sc_rx_mbuf != NULL) { 676 m_freem(sc->sc_rx_mbuf); 677 sc->sc_rx_mbuf = NULL; 678 } 679 680 sc->sc_rx_want = 0; 681 sc->sc_rx_block = NULL; 682 sc->sc_rx_intr = NULL; 683 sc->sc_rx_intrarg = NULL; 684 685 sc->sc_tx_size = 0; 686 sc->sc_tx_block = NULL; 687 sc->sc_tx_pending = 0; 688 sc->sc_tx_intr = NULL; 689 sc->sc_tx_intrarg = NULL; 690 } 691 692 static int 693 btsco_query_encoding(void *hdl, struct audio_encoding *ae) 694 { 695 /* struct btsco_softc *sc = hdl; */ 696 int err = 0; 697 698 switch (ae->index) { 699 case 0: 700 strcpy(ae->name, AudioEslinear_le); 701 ae->encoding = AUDIO_ENCODING_SLINEAR_LE; 702 ae->precision = 16; 703 ae->flags = 0; 704 break; 705 706 default: 707 err = EINVAL; 708 } 709 710 return err; 711 } 712 713 static int 714 btsco_set_params(void *hdl, int setmode, int usemode, 715 audio_params_t *play, audio_params_t *rec, 716 stream_filter_list_t *pfil, stream_filter_list_t *rfil) 717 { 718 /* struct btsco_softc *sc = hdl; */ 719 const struct audio_format *f; 720 int rv; 721 722 DPRINTF("setmode 0x%x usemode 0x%x\n", setmode, usemode); 723 DPRINTF("rate %d, precision %d, channels %d encoding %d\n", 724 play->sample_rate, play->precision, play->channels, play->encoding); 725 726 /* 727 * If we had a list of formats, we could check the HCI_Voice_Setting 728 * and select the appropriate one to use. Currently only one is 729 * supported: 0x0060 == 8000Hz, mono, 16-bit, slinear_le 730 */ 731 f = &btsco_format; 732 733 if (setmode & AUMODE_PLAY) { 734 rv = auconv_set_converter(f, 1, AUMODE_PLAY, play, TRUE, pfil); 735 if (rv < 0) 736 return EINVAL; 737 } 738 739 if (setmode & AUMODE_RECORD) { 740 rv = auconv_set_converter(f, 1, AUMODE_RECORD, rec, TRUE, rfil); 741 if (rv < 0) 742 return EINVAL; 743 } 744 745 return 0; 746 } 747 748 /* 749 * If we have an MTU value to use, round the blocksize to that. 750 */ 751 static int 752 btsco_round_blocksize(void *hdl, int bs, int mode, 753 const audio_params_t *param) 754 { 755 struct btsco_softc *sc = hdl; 756 757 if (sc->sc_mtu > 0) { 758 bs = (bs / sc->sc_mtu) * sc->sc_mtu; 759 if (bs == 0) 760 bs = sc->sc_mtu; 761 } 762 763 DPRINTF("%s mode=0x%x, bs=%d, sc_mtu=%d\n", 764 sc->sc_name, mode, bs, sc->sc_mtu); 765 766 return bs; 767 } 768 769 /* 770 * Start Output 771 * 772 * We dont want to be calling the network stack at splaudio() so make 773 * a note of what is to be sent, and schedule an interrupt to bundle 774 * it up and queue it. 775 */ 776 static int 777 btsco_start_output(void *hdl, void *block, int blksize, 778 void (*intr)(void *), void *intrarg) 779 { 780 struct btsco_softc *sc = hdl; 781 782 DPRINTFN(5, "%s blksize %d\n", sc->sc_name, blksize); 783 784 if (sc->sc_sco == NULL) 785 return ENOTCONN; /* connection lost */ 786 787 sc->sc_tx_block = block; 788 sc->sc_tx_pending = 0; 789 sc->sc_tx_size = blksize; 790 sc->sc_tx_intr = intr; 791 sc->sc_tx_intrarg = intrarg; 792 793 softint_schedule(sc->sc_intr); 794 return 0; 795 } 796 797 /* 798 * Start Input 799 * 800 * When the SCO link is up, we are getting data in any case, so all we do 801 * is note what we want and where to put it and let the sco_input routine 802 * fill in the data. 803 * 804 * If there was any leftover data that didnt fit in the last block, retry 805 * it now. 806 */ 807 static int 808 btsco_start_input(void *hdl, void *block, int blksize, 809 void (*intr)(void *), void *intrarg) 810 { 811 struct btsco_softc *sc = hdl; 812 struct mbuf *m; 813 814 DPRINTFN(5, "%s blksize %d\n", sc->sc_name, blksize); 815 816 if (sc->sc_sco == NULL) 817 return ENOTCONN; 818 819 sc->sc_rx_want = blksize; 820 sc->sc_rx_block = block; 821 sc->sc_rx_intr = intr; 822 sc->sc_rx_intrarg = intrarg; 823 824 if (sc->sc_rx_mbuf != NULL) { 825 m = sc->sc_rx_mbuf; 826 sc->sc_rx_mbuf = NULL; 827 btsco_sco_input(sc, m); 828 } 829 830 return 0; 831 } 832 833 /* 834 * Halt Output 835 * 836 * This doesnt really halt the output, but it will look 837 * that way to the audio driver. The current block will 838 * still be transmitted. 839 */ 840 static int 841 btsco_halt_output(void *hdl) 842 { 843 struct btsco_softc *sc = hdl; 844 845 DPRINTFN(5, "%s\n", sc->sc_name); 846 847 sc->sc_tx_size = 0; 848 sc->sc_tx_block = NULL; 849 sc->sc_tx_pending = 0; 850 sc->sc_tx_intr = NULL; 851 sc->sc_tx_intrarg = NULL; 852 853 return 0; 854 } 855 856 /* 857 * Halt Input 858 * 859 * This doesnt really halt the input, but it will look 860 * that way to the audio driver. Incoming data will be 861 * discarded. 862 */ 863 static int 864 btsco_halt_input(void *hdl) 865 { 866 struct btsco_softc *sc = hdl; 867 868 DPRINTFN(5, "%s\n", sc->sc_name); 869 870 sc->sc_rx_want = 0; 871 sc->sc_rx_block = NULL; 872 sc->sc_rx_intr = NULL; 873 sc->sc_rx_intrarg = NULL; 874 875 if (sc->sc_rx_mbuf != NULL) { 876 m_freem(sc->sc_rx_mbuf); 877 sc->sc_rx_mbuf = NULL; 878 } 879 880 return 0; 881 } 882 883 static int 884 btsco_getdev(void *hdl, struct audio_device *ret) 885 { 886 887 *ret = btsco_device; 888 return 0; 889 } 890 891 static int 892 btsco_setfd(void *hdl, int fd) 893 { 894 DPRINTF("set %s duplex\n", fd ? "full" : "half"); 895 896 return 0; 897 } 898 899 static int 900 btsco_set_port(void *hdl, mixer_ctrl_t *mc) 901 { 902 struct btsco_softc *sc = hdl; 903 int err = 0; 904 905 DPRINTF("%s dev %d type %d\n", sc->sc_name, mc->dev, mc->type); 906 907 switch (mc->dev) { 908 case BTSCO_VGS: 909 if (mc->type != AUDIO_MIXER_VALUE || 910 mc->un.value.num_channels != 1) { 911 err = EINVAL; 912 break; 913 } 914 915 sc->sc_vgs = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 916 break; 917 918 case BTSCO_VGM: 919 if (mc->type != AUDIO_MIXER_VALUE || 920 mc->un.value.num_channels != 1) { 921 err = EINVAL; 922 break; 923 } 924 925 sc->sc_vgm = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 926 break; 927 928 default: 929 err = EINVAL; 930 break; 931 } 932 933 return err; 934 } 935 936 static int 937 btsco_get_port(void *hdl, mixer_ctrl_t *mc) 938 { 939 struct btsco_softc *sc = hdl; 940 int err = 0; 941 942 DPRINTF("%s dev %d\n", sc->sc_name, mc->dev); 943 944 switch (mc->dev) { 945 case BTSCO_VGS: 946 mc->type = AUDIO_MIXER_VALUE; 947 mc->un.value.num_channels = 1; 948 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_vgs; 949 break; 950 951 case BTSCO_VGM: 952 mc->type = AUDIO_MIXER_VALUE; 953 mc->un.value.num_channels = 1; 954 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_vgm; 955 break; 956 957 default: 958 err = EINVAL; 959 break; 960 } 961 962 return err; 963 } 964 965 static int 966 btsco_query_devinfo(void *hdl, mixer_devinfo_t *di) 967 { 968 /* struct btsco_softc *sc = hdl; */ 969 int err = 0; 970 971 switch(di->index) { 972 case BTSCO_VGS: 973 di->mixer_class = BTSCO_INPUT_CLASS; 974 di->next = di->prev = AUDIO_MIXER_LAST; 975 strcpy(di->label.name, AudioNspeaker); 976 di->type = AUDIO_MIXER_VALUE; 977 strcpy(di->un.v.units.name, AudioNvolume); 978 di->un.v.num_channels = 1; 979 di->un.v.delta = BTSCO_DELTA; 980 break; 981 982 case BTSCO_VGM: 983 di->mixer_class = BTSCO_INPUT_CLASS; 984 di->next = di->prev = AUDIO_MIXER_LAST; 985 strcpy(di->label.name, AudioNmicrophone); 986 di->type = AUDIO_MIXER_VALUE; 987 strcpy(di->un.v.units.name, AudioNvolume); 988 di->un.v.num_channels = 1; 989 di->un.v.delta = BTSCO_DELTA; 990 break; 991 992 case BTSCO_INPUT_CLASS: 993 di->mixer_class = BTSCO_INPUT_CLASS; 994 di->next = di->prev = AUDIO_MIXER_LAST; 995 strcpy(di->label.name, AudioCinputs); 996 di->type = AUDIO_MIXER_CLASS; 997 break; 998 999 default: 1000 err = ENXIO; 1001 break; 1002 } 1003 1004 return err; 1005 } 1006 1007 /* 1008 * Allocate Ring Buffers. 1009 */ 1010 static void * 1011 btsco_allocm(void *hdl, int direction, size_t size, 1012 struct malloc_type *type, int flags) 1013 { 1014 struct btsco_softc *sc = hdl; 1015 void *addr; 1016 1017 DPRINTF("%s: size %d direction %d\n", sc->sc_name, size, direction); 1018 1019 addr = malloc(size, type, flags); 1020 1021 if (direction == AUMODE_PLAY) { 1022 sc->sc_tx_buf = addr; 1023 sc->sc_tx_refcnt = 0; 1024 } 1025 1026 return addr; 1027 } 1028 1029 /* 1030 * Free Ring Buffers. 1031 * 1032 * Because we used external memory for the tx mbufs, we dont 1033 * want to free the memory until all the mbufs are done with 1034 * 1035 * Just to be sure, dont free if something is still pending. 1036 * This would be a memory leak but at least there is a warning.. 1037 */ 1038 static void 1039 btsco_freem(void *hdl, void *addr, struct malloc_type *type) 1040 { 1041 struct btsco_softc *sc = hdl; 1042 int count = hz / 2; 1043 1044 if (addr == sc->sc_tx_buf) { 1045 DPRINTF("%s: tx_refcnt=%d\n", sc->sc_name, sc->sc_tx_refcnt); 1046 1047 sc->sc_tx_buf = NULL; 1048 1049 while (sc->sc_tx_refcnt> 0 && count-- > 0) 1050 tsleep(sc, PWAIT, "drain", 1); 1051 1052 if (sc->sc_tx_refcnt > 0) { 1053 aprint_error("%s: ring buffer unreleased!\n", sc->sc_name); 1054 return; 1055 } 1056 } 1057 1058 free(addr, type); 1059 } 1060 1061 static int 1062 btsco_get_props(void *hdl) 1063 { 1064 1065 return AUDIO_PROP_FULLDUPLEX; 1066 } 1067 1068 /* 1069 * Handle private ioctl. We pass information out about how to talk 1070 * to the device and mixer. 1071 */ 1072 static int 1073 btsco_dev_ioctl(void *hdl, u_long cmd, void *addr, int flag, 1074 struct lwp *l) 1075 { 1076 struct btsco_softc *sc = hdl; 1077 struct btsco_info *bi = (struct btsco_info *)addr; 1078 int err = 0; 1079 1080 DPRINTF("%s cmd 0x%lx flag %d\n", sc->sc_name, cmd, flag); 1081 1082 switch (cmd) { 1083 case BTSCO_GETINFO: 1084 memset(bi, 0, sizeof(*bi)); 1085 bdaddr_copy(&bi->laddr, &sc->sc_laddr); 1086 bdaddr_copy(&bi->raddr, &sc->sc_raddr); 1087 bi->channel = sc->sc_channel; 1088 bi->vgs = BTSCO_VGS; 1089 bi->vgm = BTSCO_VGM; 1090 break; 1091 1092 default: 1093 err = EPASSTHROUGH; 1094 break; 1095 } 1096 1097 return err; 1098 } 1099 1100 1101 /***************************************************************************** 1102 * 1103 * misc btsco functions 1104 * 1105 */ 1106 1107 /* 1108 * Our transmit interrupt. This is triggered when a new block is to be 1109 * sent. We send mtu sized chunks of the block as mbufs with external 1110 * storage to sco_send() 1111 */ 1112 static void 1113 btsco_intr(void *arg) 1114 { 1115 struct btsco_softc *sc = arg; 1116 struct mbuf *m; 1117 uint8_t *block; 1118 int mlen, size; 1119 1120 DPRINTFN(10, "%s block %p size %d\n", 1121 sc->sc_name, sc->sc_tx_block, sc->sc_tx_size); 1122 1123 if (sc->sc_sco == NULL) 1124 return; /* connection is lost */ 1125 1126 block = sc->sc_tx_block; 1127 size = sc->sc_tx_size; 1128 sc->sc_tx_block = NULL; 1129 sc->sc_tx_size = 0; 1130 1131 mutex_enter(bt_lock); 1132 while (size > 0) { 1133 MGETHDR(m, M_DONTWAIT, MT_DATA); 1134 if (m == NULL) 1135 break; 1136 1137 mlen = MIN(sc->sc_mtu, size); 1138 1139 /* I think M_DEVBUF is true but not relevant */ 1140 MEXTADD(m, block, mlen, M_DEVBUF, btsco_extfree, sc); 1141 if ((m->m_flags & M_EXT) == 0) { 1142 m_free(m); 1143 break; 1144 } 1145 sc->sc_tx_refcnt++; 1146 1147 m->m_pkthdr.len = m->m_len = mlen; 1148 sc->sc_tx_pending++; 1149 1150 if (sco_send(sc->sc_sco, m) > 0) { 1151 sc->sc_tx_pending--; 1152 break; 1153 } 1154 1155 block += mlen; 1156 size -= mlen; 1157 } 1158 mutex_exit(bt_lock); 1159 } 1160 1161 /* 1162 * Release the mbuf, we keep a reference count on the tx buffer so 1163 * that we dont release it before its free. 1164 */ 1165 static void 1166 btsco_extfree(struct mbuf *m, void *addr, size_t size, 1167 void *arg) 1168 { 1169 struct btsco_softc *sc = arg; 1170 1171 if (m != NULL) 1172 pool_cache_put(mb_cache, m); 1173 1174 sc->sc_tx_refcnt--; 1175 } 1176