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