1 /* $NetBSD: btsco.c,v 1.18 2007/11/11 12:59:05 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.18 2007/11/11 12:59:05 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 struct btdev sc_btdev; 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 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 291 /* 292 * copy in our configuration info 293 */ 294 obj = prop_dictionary_get(dict, BTDEVladdr); 295 bdaddr_copy(&sc->sc_laddr, prop_data_data_nocopy(obj)); 296 297 obj = prop_dictionary_get(dict, BTDEVraddr); 298 bdaddr_copy(&sc->sc_raddr, prop_data_data_nocopy(obj)); 299 300 obj = prop_dictionary_get(dict, BTDEVservice); 301 if (prop_string_equals_cstring(obj, "HF")) { 302 sc->sc_flags |= BTSCO_LISTEN; 303 aprint_verbose(" listen mode"); 304 } 305 306 obj = prop_dictionary_get(dict, BTSCOchannel); 307 if (prop_object_type(obj) != PROP_TYPE_NUMBER 308 || prop_number_integer_value(obj) < RFCOMM_CHANNEL_MIN 309 || prop_number_integer_value(obj) > RFCOMM_CHANNEL_MAX) { 310 aprint_error(" invalid %s", BTSCOchannel); 311 return; 312 } 313 sc->sc_channel = prop_number_integer_value(obj); 314 315 aprint_verbose(" channel %d", sc->sc_channel); 316 aprint_normal("\n"); 317 318 DPRINTF("sc=%p\n", sc); 319 320 /* 321 * set up transmit interrupt 322 */ 323 sc->sc_intr = softint_establish(SOFTINT_NET, btsco_intr, sc); 324 if (sc->sc_intr == NULL) { 325 aprint_error_dev(self, "softint_establish failed\n"); 326 return; 327 } 328 329 /* 330 * attach audio device 331 */ 332 sc->sc_audio = audio_attach_mi(&btsco_if, sc, self); 333 if (sc->sc_audio == NULL) { 334 aprint_error_dev(self, "audio_attach_mi failed\n"); 335 return; 336 } 337 } 338 339 static int 340 btsco_detach(device_t self, int flags) 341 { 342 struct btsco_softc *sc = device_private(self); 343 int s; 344 345 DPRINTF("sc=%p\n", sc); 346 347 s = splsoftnet(); 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 splx(s); 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 return 0; 386 } 387 388 /***************************************************************************** 389 * 390 * bluetooth(9) methods for SCO 391 * 392 * All these are called from Bluetooth Protocol code, in a soft 393 * interrupt context at IPL_SOFTNET. 394 */ 395 396 static void 397 btsco_sco_connecting(void *arg) 398 { 399 /* struct btsco_softc *sc = arg; */ 400 401 /* dont care */ 402 } 403 404 static void 405 btsco_sco_connected(void *arg) 406 { 407 struct btsco_softc *sc = arg; 408 409 DPRINTF("%s\n", sc->sc_name); 410 411 KASSERT(sc->sc_sco != NULL); 412 KASSERT(sc->sc_state == BTSCO_WAIT_CONNECT); 413 414 /* 415 * If we are listening, no more need 416 */ 417 if (sc->sc_sco_l != NULL) 418 sco_detach(&sc->sc_sco_l); 419 420 sc->sc_state = BTSCO_OPEN; 421 wakeup(sc); 422 } 423 424 static void 425 btsco_sco_disconnected(void *arg, int err) 426 { 427 struct btsco_softc *sc = arg; 428 int s; 429 430 DPRINTF("%s sc_state %d\n", sc->sc_name, sc->sc_state); 431 432 KASSERT(sc->sc_sco != NULL); 433 434 sc->sc_err = err; 435 sco_detach(&sc->sc_sco); 436 437 switch (sc->sc_state) { 438 case BTSCO_CLOSED: /* dont think this can happen */ 439 break; 440 441 case BTSCO_WAIT_CONNECT: /* connect failed */ 442 wakeup(sc); 443 break; 444 445 case BTSCO_OPEN: /* link lost */ 446 /* 447 * If IO is in progress, tell the audio driver that it 448 * has completed so that when it tries to send more, we 449 * can indicate an error. 450 */ 451 s = splaudio(); 452 if (sc->sc_tx_pending > 0) { 453 sc->sc_tx_pending = 0; 454 (*sc->sc_tx_intr)(sc->sc_tx_intrarg); 455 } 456 if (sc->sc_rx_want > 0) { 457 sc->sc_rx_want = 0; 458 (*sc->sc_rx_intr)(sc->sc_rx_intrarg); 459 } 460 splx(s); 461 break; 462 463 default: 464 UNKNOWN(sc->sc_state); 465 } 466 467 sc->sc_state = BTSCO_CLOSED; 468 } 469 470 static void * 471 btsco_sco_newconn(void *arg, struct sockaddr_bt *laddr, 472 struct sockaddr_bt *raddr) 473 { 474 struct btsco_softc *sc = arg; 475 476 DPRINTF("%s\n", sc->sc_name); 477 478 if (bdaddr_same(&raddr->bt_bdaddr, &sc->sc_raddr) == 0 479 || sc->sc_state != BTSCO_WAIT_CONNECT 480 || sc->sc_sco != NULL) 481 return NULL; 482 483 sco_attach(&sc->sc_sco, &btsco_sco_proto, sc); 484 return sc->sc_sco; 485 } 486 487 static void 488 btsco_sco_complete(void *arg, int count) 489 { 490 struct btsco_softc *sc = arg; 491 int s; 492 493 DPRINTFN(10, "%s count %d\n", sc->sc_name, count); 494 495 s = splaudio(); 496 if (sc->sc_tx_pending > 0) { 497 sc->sc_tx_pending -= count; 498 if (sc->sc_tx_pending == 0) 499 (*sc->sc_tx_intr)(sc->sc_tx_intrarg); 500 } 501 splx(s); 502 } 503 504 static void 505 btsco_sco_linkmode(void *arg, int new) 506 { 507 /* struct btsco_softc *sc = arg; */ 508 509 /* dont care */ 510 } 511 512 static void 513 btsco_sco_input(void *arg, struct mbuf *m) 514 { 515 struct btsco_softc *sc = arg; 516 int len, s; 517 518 DPRINTFN(10, "%s len=%d\n", sc->sc_name, m->m_pkthdr.len); 519 520 s = splaudio(); 521 if (sc->sc_rx_want == 0) { 522 m_freem(m); 523 } else { 524 KASSERT(sc->sc_rx_intr != NULL); 525 KASSERT(sc->sc_rx_block != NULL); 526 527 len = MIN(sc->sc_rx_want, m->m_pkthdr.len); 528 m_copydata(m, 0, len, sc->sc_rx_block); 529 530 sc->sc_rx_want -= len; 531 sc->sc_rx_block += len; 532 533 if (len > m->m_pkthdr.len) { 534 if (sc->sc_rx_mbuf != NULL) 535 m_freem(sc->sc_rx_mbuf); 536 537 m_adj(m, len); 538 sc->sc_rx_mbuf = m; 539 } else { 540 m_freem(m); 541 } 542 543 if (sc->sc_rx_want == 0) 544 (*sc->sc_rx_intr)(sc->sc_rx_intrarg); 545 } 546 splx(s); 547 } 548 549 550 /***************************************************************************** 551 * 552 * audio(9) methods 553 * 554 */ 555 556 static int 557 btsco_open(void *hdl, int flags) 558 { 559 struct sockaddr_bt sa; 560 struct btsco_softc *sc = hdl; 561 int err, s, timo; 562 563 DPRINTF("%s flags 0x%x\n", sc->sc_name, flags); 564 /* flags FREAD & FWRITE? */ 565 566 if (sc->sc_sco != NULL || sc->sc_sco_l != NULL) 567 return EIO; 568 569 s = splsoftnet(); 570 571 memset(&sa, 0, sizeof(sa)); 572 sa.bt_len = sizeof(sa); 573 sa.bt_family = AF_BLUETOOTH; 574 bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr); 575 576 if (sc->sc_flags & BTSCO_LISTEN) { 577 err = sco_attach(&sc->sc_sco_l, &btsco_sco_proto, sc); 578 if (err) 579 goto done; 580 581 err = sco_bind(sc->sc_sco_l, &sa); 582 if (err) { 583 sco_detach(&sc->sc_sco_l); 584 goto done; 585 } 586 587 err = sco_listen(sc->sc_sco_l); 588 if (err) { 589 sco_detach(&sc->sc_sco_l); 590 goto done; 591 } 592 593 timo = 0; /* no timeout */ 594 } else { 595 err = sco_attach(&sc->sc_sco, &btsco_sco_proto, sc); 596 if (err) 597 goto done; 598 599 err = sco_bind(sc->sc_sco, &sa); 600 if (err) { 601 sco_detach(&sc->sc_sco); 602 goto done; 603 } 604 605 bdaddr_copy(&sa.bt_bdaddr, &sc->sc_raddr); 606 err = sco_connect(sc->sc_sco, &sa); 607 if (err) { 608 sco_detach(&sc->sc_sco); 609 goto done; 610 } 611 612 timo = BTSCO_TIMEOUT; 613 } 614 615 sc->sc_state = BTSCO_WAIT_CONNECT; 616 while (err == 0 && sc->sc_state == BTSCO_WAIT_CONNECT) 617 err = tsleep(sc, PWAIT | PCATCH, "btsco", timo); 618 619 switch (sc->sc_state) { 620 case BTSCO_CLOSED: /* disconnected */ 621 err = sc->sc_err; 622 623 /* fall through to */ 624 case BTSCO_WAIT_CONNECT: /* error */ 625 if (sc->sc_sco != NULL) 626 sco_detach(&sc->sc_sco); 627 628 if (sc->sc_sco_l != NULL) 629 sco_detach(&sc->sc_sco_l); 630 631 break; 632 633 case BTSCO_OPEN: /* hurrah */ 634 sco_getopt(sc->sc_sco, SO_SCO_MTU, &sc->sc_mtu); 635 break; 636 637 default: 638 UNKNOWN(sc->sc_state); 639 break; 640 } 641 642 done: 643 splx(s); 644 645 DPRINTF("done err=%d, sc_state=%d, sc_mtu=%d\n", 646 err, sc->sc_state, sc->sc_mtu); 647 return err; 648 } 649 650 static void 651 btsco_close(void *hdl) 652 { 653 struct btsco_softc *sc = hdl; 654 int s; 655 656 DPRINTF("%s\n", sc->sc_name); 657 658 s = splsoftnet(); 659 if (sc->sc_sco != NULL) { 660 sco_disconnect(sc->sc_sco, 0); 661 sco_detach(&sc->sc_sco); 662 } 663 664 if (sc->sc_sco_l != NULL) { 665 sco_detach(&sc->sc_sco_l); 666 } 667 splx(s); 668 669 if (sc->sc_rx_mbuf != NULL) { 670 m_freem(sc->sc_rx_mbuf); 671 sc->sc_rx_mbuf = NULL; 672 } 673 674 sc->sc_rx_want = 0; 675 sc->sc_rx_block = NULL; 676 sc->sc_rx_intr = NULL; 677 sc->sc_rx_intrarg = NULL; 678 679 sc->sc_tx_size = 0; 680 sc->sc_tx_block = NULL; 681 sc->sc_tx_pending = 0; 682 sc->sc_tx_intr = NULL; 683 sc->sc_tx_intrarg = NULL; 684 } 685 686 static int 687 btsco_query_encoding(void *hdl, struct audio_encoding *ae) 688 { 689 /* struct btsco_softc *sc = hdl; */ 690 int err = 0; 691 692 switch (ae->index) { 693 case 0: 694 strcpy(ae->name, AudioEslinear_le); 695 ae->encoding = AUDIO_ENCODING_SLINEAR_LE; 696 ae->precision = 16; 697 ae->flags = 0; 698 break; 699 700 default: 701 err = EINVAL; 702 } 703 704 return err; 705 } 706 707 static int 708 btsco_set_params(void *hdl, int setmode, int usemode, 709 audio_params_t *play, audio_params_t *rec, 710 stream_filter_list_t *pfil, stream_filter_list_t *rfil) 711 { 712 /* struct btsco_softc *sc = hdl; */ 713 const struct audio_format *f; 714 int rv; 715 716 DPRINTF("setmode 0x%x usemode 0x%x\n", setmode, usemode); 717 DPRINTF("rate %d, precision %d, channels %d encoding %d\n", 718 play->sample_rate, play->precision, play->channels, play->encoding); 719 720 /* 721 * If we had a list of formats, we could check the HCI_Voice_Setting 722 * and select the appropriate one to use. Currently only one is 723 * supported: 0x0060 == 8000Hz, mono, 16-bit, slinear_le 724 */ 725 f = &btsco_format; 726 727 if (setmode & AUMODE_PLAY) { 728 rv = auconv_set_converter(f, 1, AUMODE_PLAY, play, TRUE, pfil); 729 if (rv < 0) 730 return EINVAL; 731 } 732 733 if (setmode & AUMODE_RECORD) { 734 rv = auconv_set_converter(f, 1, AUMODE_RECORD, rec, TRUE, rfil); 735 if (rv < 0) 736 return EINVAL; 737 } 738 739 return 0; 740 } 741 742 /* 743 * If we have an MTU value to use, round the blocksize to that. 744 */ 745 static int 746 btsco_round_blocksize(void *hdl, int bs, int mode, 747 const audio_params_t *param) 748 { 749 struct btsco_softc *sc = hdl; 750 751 if (sc->sc_mtu > 0) { 752 bs = (bs / sc->sc_mtu) * sc->sc_mtu; 753 if (bs == 0) 754 bs = sc->sc_mtu; 755 } 756 757 DPRINTF("%s mode=0x%x, bs=%d, sc_mtu=%d\n", 758 sc->sc_name, mode, bs, sc->sc_mtu); 759 760 return bs; 761 } 762 763 /* 764 * Start Output 765 * 766 * We dont want to be calling the network stack at splaudio() so make 767 * a note of what is to be sent, and schedule an interrupt to bundle 768 * it up and queue it. 769 */ 770 static int 771 btsco_start_output(void *hdl, void *block, int blksize, 772 void (*intr)(void *), void *intrarg) 773 { 774 struct btsco_softc *sc = hdl; 775 776 DPRINTFN(5, "%s blksize %d\n", sc->sc_name, blksize); 777 778 if (sc->sc_sco == NULL) 779 return ENOTCONN; /* connection lost */ 780 781 sc->sc_tx_block = block; 782 sc->sc_tx_pending = 0; 783 sc->sc_tx_size = blksize; 784 sc->sc_tx_intr = intr; 785 sc->sc_tx_intrarg = intrarg; 786 787 softint_schedule(sc->sc_intr); 788 return 0; 789 } 790 791 /* 792 * Start Input 793 * 794 * When the SCO link is up, we are getting data in any case, so all we do 795 * is note what we want and where to put it and let the sco_input routine 796 * fill in the data. 797 * 798 * If there was any leftover data that didnt fit in the last block, retry 799 * it now. 800 */ 801 static int 802 btsco_start_input(void *hdl, void *block, int blksize, 803 void (*intr)(void *), void *intrarg) 804 { 805 struct btsco_softc *sc = hdl; 806 struct mbuf *m; 807 808 DPRINTFN(5, "%s blksize %d\n", sc->sc_name, blksize); 809 810 if (sc->sc_sco == NULL) 811 return ENOTCONN; 812 813 sc->sc_rx_want = blksize; 814 sc->sc_rx_block = block; 815 sc->sc_rx_intr = intr; 816 sc->sc_rx_intrarg = intrarg; 817 818 if (sc->sc_rx_mbuf != NULL) { 819 m = sc->sc_rx_mbuf; 820 sc->sc_rx_mbuf = NULL; 821 btsco_sco_input(sc, m); 822 } 823 824 return 0; 825 } 826 827 /* 828 * Halt Output 829 * 830 * This doesnt really halt the output, but it will look 831 * that way to the audio driver. The current block will 832 * still be transmitted. 833 */ 834 static int 835 btsco_halt_output(void *hdl) 836 { 837 struct btsco_softc *sc = hdl; 838 839 DPRINTFN(5, "%s\n", sc->sc_name); 840 841 sc->sc_tx_size = 0; 842 sc->sc_tx_block = NULL; 843 sc->sc_tx_pending = 0; 844 sc->sc_tx_intr = NULL; 845 sc->sc_tx_intrarg = NULL; 846 847 return 0; 848 } 849 850 /* 851 * Halt Input 852 * 853 * This doesnt really halt the input, but it will look 854 * that way to the audio driver. Incoming data will be 855 * discarded. 856 */ 857 static int 858 btsco_halt_input(void *hdl) 859 { 860 struct btsco_softc *sc = hdl; 861 862 DPRINTFN(5, "%s\n", sc->sc_name); 863 864 sc->sc_rx_want = 0; 865 sc->sc_rx_block = NULL; 866 sc->sc_rx_intr = NULL; 867 sc->sc_rx_intrarg = NULL; 868 869 if (sc->sc_rx_mbuf != NULL) { 870 m_freem(sc->sc_rx_mbuf); 871 sc->sc_rx_mbuf = NULL; 872 } 873 874 return 0; 875 } 876 877 static int 878 btsco_getdev(void *hdl, struct audio_device *ret) 879 { 880 881 *ret = btsco_device; 882 return 0; 883 } 884 885 static int 886 btsco_setfd(void *hdl, int fd) 887 { 888 DPRINTF("set %s duplex\n", fd ? "full" : "half"); 889 890 return 0; 891 } 892 893 static int 894 btsco_set_port(void *hdl, mixer_ctrl_t *mc) 895 { 896 struct btsco_softc *sc = hdl; 897 int err = 0; 898 899 DPRINTF("%s dev %d type %d\n", sc->sc_name, mc->dev, mc->type); 900 901 switch (mc->dev) { 902 case BTSCO_VGS: 903 if (mc->type != AUDIO_MIXER_VALUE || 904 mc->un.value.num_channels != 1) { 905 err = EINVAL; 906 break; 907 } 908 909 sc->sc_vgs = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 910 break; 911 912 case BTSCO_VGM: 913 if (mc->type != AUDIO_MIXER_VALUE || 914 mc->un.value.num_channels != 1) { 915 err = EINVAL; 916 break; 917 } 918 919 sc->sc_vgm = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 920 break; 921 922 default: 923 err = EINVAL; 924 break; 925 } 926 927 return err; 928 } 929 930 static int 931 btsco_get_port(void *hdl, mixer_ctrl_t *mc) 932 { 933 struct btsco_softc *sc = hdl; 934 int err = 0; 935 936 DPRINTF("%s dev %d\n", sc->sc_name, mc->dev); 937 938 switch (mc->dev) { 939 case BTSCO_VGS: 940 mc->type = AUDIO_MIXER_VALUE; 941 mc->un.value.num_channels = 1; 942 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_vgs; 943 break; 944 945 case BTSCO_VGM: 946 mc->type = AUDIO_MIXER_VALUE; 947 mc->un.value.num_channels = 1; 948 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_vgm; 949 break; 950 951 default: 952 err = EINVAL; 953 break; 954 } 955 956 return err; 957 } 958 959 static int 960 btsco_query_devinfo(void *hdl, mixer_devinfo_t *di) 961 { 962 /* struct btsco_softc *sc = hdl; */ 963 int err = 0; 964 965 switch(di->index) { 966 case BTSCO_VGS: 967 di->mixer_class = BTSCO_INPUT_CLASS; 968 di->next = di->prev = AUDIO_MIXER_LAST; 969 strcpy(di->label.name, AudioNspeaker); 970 di->type = AUDIO_MIXER_VALUE; 971 strcpy(di->un.v.units.name, AudioNvolume); 972 di->un.v.num_channels = 1; 973 di->un.v.delta = BTSCO_DELTA; 974 break; 975 976 case BTSCO_VGM: 977 di->mixer_class = BTSCO_INPUT_CLASS; 978 di->next = di->prev = AUDIO_MIXER_LAST; 979 strcpy(di->label.name, AudioNmicrophone); 980 di->type = AUDIO_MIXER_VALUE; 981 strcpy(di->un.v.units.name, AudioNvolume); 982 di->un.v.num_channels = 1; 983 di->un.v.delta = BTSCO_DELTA; 984 break; 985 986 case BTSCO_INPUT_CLASS: 987 di->mixer_class = BTSCO_INPUT_CLASS; 988 di->next = di->prev = AUDIO_MIXER_LAST; 989 strcpy(di->label.name, AudioCinputs); 990 di->type = AUDIO_MIXER_CLASS; 991 break; 992 993 default: 994 err = ENXIO; 995 break; 996 } 997 998 return err; 999 } 1000 1001 /* 1002 * Allocate Ring Buffers. 1003 */ 1004 static void * 1005 btsco_allocm(void *hdl, int direction, size_t size, 1006 struct malloc_type *type, int flags) 1007 { 1008 struct btsco_softc *sc = hdl; 1009 void *addr; 1010 1011 DPRINTF("%s: size %d direction %d\n", sc->sc_name, size, direction); 1012 1013 addr = malloc(size, type, flags); 1014 1015 if (direction == AUMODE_PLAY) { 1016 sc->sc_tx_buf = addr; 1017 sc->sc_tx_refcnt = 0; 1018 } 1019 1020 return addr; 1021 } 1022 1023 /* 1024 * Free Ring Buffers. 1025 * 1026 * Because we used external memory for the tx mbufs, we dont 1027 * want to free the memory until all the mbufs are done with 1028 * 1029 * Just to be sure, dont free if something is still pending. 1030 * This would be a memory leak but at least there is a warning.. 1031 */ 1032 static void 1033 btsco_freem(void *hdl, void *addr, struct malloc_type *type) 1034 { 1035 struct btsco_softc *sc = hdl; 1036 int count = hz / 2; 1037 1038 if (addr == sc->sc_tx_buf) { 1039 DPRINTF("%s: tx_refcnt=%d\n", sc->sc_name, sc->sc_tx_refcnt); 1040 1041 sc->sc_tx_buf = NULL; 1042 1043 while (sc->sc_tx_refcnt> 0 && count-- > 0) 1044 tsleep(sc, PWAIT, "drain", 1); 1045 1046 if (sc->sc_tx_refcnt > 0) { 1047 aprint_error("%s: ring buffer unreleased!\n", sc->sc_name); 1048 return; 1049 } 1050 } 1051 1052 free(addr, type); 1053 } 1054 1055 static int 1056 btsco_get_props(void *hdl) 1057 { 1058 1059 return AUDIO_PROP_FULLDUPLEX; 1060 } 1061 1062 /* 1063 * Handle private ioctl. We pass information out about how to talk 1064 * to the device and mixer. 1065 */ 1066 static int 1067 btsco_dev_ioctl(void *hdl, u_long cmd, void *addr, int flag, 1068 struct lwp *l) 1069 { 1070 struct btsco_softc *sc = hdl; 1071 struct btsco_info *bi = (struct btsco_info *)addr; 1072 int err = 0; 1073 1074 DPRINTF("%s cmd 0x%lx flag %d\n", sc->sc_name, cmd, flag); 1075 1076 switch (cmd) { 1077 case BTSCO_GETINFO: 1078 memset(bi, 0, sizeof(*bi)); 1079 bdaddr_copy(&bi->laddr, &sc->sc_laddr); 1080 bdaddr_copy(&bi->raddr, &sc->sc_raddr); 1081 bi->channel = sc->sc_channel; 1082 bi->vgs = BTSCO_VGS; 1083 bi->vgm = BTSCO_VGM; 1084 break; 1085 1086 default: 1087 err = EPASSTHROUGH; 1088 break; 1089 } 1090 1091 return err; 1092 } 1093 1094 1095 /***************************************************************************** 1096 * 1097 * misc btsco functions 1098 * 1099 */ 1100 1101 /* 1102 * Our transmit interrupt. This is triggered when a new block is to be 1103 * sent. We send mtu sized chunks of the block as mbufs with external 1104 * storage to sco_send() 1105 */ 1106 static void 1107 btsco_intr(void *arg) 1108 { 1109 struct btsco_softc *sc = arg; 1110 struct mbuf *m; 1111 uint8_t *block; 1112 int mlen, size; 1113 1114 DPRINTFN(10, "%s block %p size %d\n", 1115 sc->sc_name, sc->sc_tx_block, sc->sc_tx_size); 1116 1117 if (sc->sc_sco == NULL) 1118 return; /* connection is lost */ 1119 1120 block = sc->sc_tx_block; 1121 size = sc->sc_tx_size; 1122 sc->sc_tx_block = NULL; 1123 sc->sc_tx_size = 0; 1124 1125 while (size > 0) { 1126 MGETHDR(m, M_DONTWAIT, MT_DATA); 1127 if (m == NULL) 1128 break; 1129 1130 mlen = MIN(sc->sc_mtu, size); 1131 1132 /* I think M_DEVBUF is true but not relevant */ 1133 MEXTADD(m, block, mlen, M_DEVBUF, btsco_extfree, sc); 1134 if ((m->m_flags & M_EXT) == 0) { 1135 m_free(m); 1136 break; 1137 } 1138 sc->sc_tx_refcnt++; 1139 1140 m->m_pkthdr.len = m->m_len = mlen; 1141 sc->sc_tx_pending++; 1142 1143 if (sco_send(sc->sc_sco, m) > 0) { 1144 sc->sc_tx_pending--; 1145 break; 1146 } 1147 1148 block += mlen; 1149 size -= mlen; 1150 } 1151 } 1152 1153 /* 1154 * Release the mbuf, we keep a reference count on the tx buffer so 1155 * that we dont release it before its free. 1156 */ 1157 static void 1158 btsco_extfree(struct mbuf *m, void *addr, size_t size, 1159 void *arg) 1160 { 1161 struct btsco_softc *sc = arg; 1162 1163 if (m != NULL) 1164 pool_cache_put(mb_cache, m); 1165 1166 sc->sc_tx_refcnt--; 1167 } 1168