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