1 /* $NetBSD: btsco.c,v 1.6 2006/09/23 16:11:07 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.6 2006/09/23 16:11:07 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 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 /* btdev identity matching */ 142 static int btsco_identify(struct btdev *, prop_dictionary_t); 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, caddr_t, 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 /* bluetooth(9) glue for SCO */ 203 static void btsco_sco_connecting(void *); 204 static void btsco_sco_connected(void *); 205 static void btsco_sco_disconnected(void *, int); 206 static void *btsco_sco_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *); 207 static void btsco_sco_complete(void *, int); 208 static void btsco_sco_input(void *, struct mbuf *); 209 210 static const struct btproto btsco_sco_proto = { 211 btsco_sco_connecting, 212 btsco_sco_connected, 213 btsco_sco_disconnected, 214 btsco_sco_newconn, 215 btsco_sco_complete, 216 btsco_sco_input, 217 }; 218 219 220 /***************************************************************************** 221 * 222 * btsco definitions 223 */ 224 225 /* 226 * btsco mixer class 227 */ 228 #define BTSCO_VGS 0 229 #define BTSCO_VGM 1 230 #define BTSCO_INPUT_CLASS 2 231 #define BTSCO_OUTPUT_CLASS 3 232 233 /* connect timeout */ 234 #define BTSCO_TIMEOUT (30 * hz) 235 236 /* misc btsco functions */ 237 static void btsco_extfree(struct mbuf *, caddr_t, size_t, void *); 238 static void btsco_intr(void *); 239 240 241 /***************************************************************************** 242 * 243 * btsco autoconf(9) routines 244 */ 245 246 static int 247 btsco_match(struct device *self, struct cfdata *cfdata, void *aux) 248 { 249 prop_dictionary_t dict = aux; 250 prop_object_t obj; 251 252 obj = prop_dictionary_get(dict, BTDEVtype); 253 return prop_string_equals_cstring(obj, "btsco"); 254 } 255 256 static void 257 btsco_attach(struct device *parent, struct device *self, void *aux) 258 { 259 struct btsco_softc *sc = (struct btsco_softc *)self; 260 prop_dictionary_t dict = aux; 261 prop_object_t obj; 262 263 /* 264 * Init softc 265 */ 266 sc->sc_vgs = 200; 267 sc->sc_vgm = 200; 268 sc->sc_state = BTSCO_CLOSED; 269 270 sc->sc_btdev.sc_identify = btsco_identify; 271 272 /* 273 * copy in our configuration info 274 */ 275 obj = prop_dictionary_get(dict, BTDEVladdr); 276 bdaddr_copy(&sc->sc_laddr, prop_data_data_nocopy(obj)); 277 278 obj = prop_dictionary_get(dict, BTDEVraddr); 279 bdaddr_copy(&sc->sc_raddr, prop_data_data_nocopy(obj)); 280 281 obj = prop_dictionary_get(dict, BTSCOlisten); 282 if (prop_bool_true(obj)) { 283 sc->sc_flags |= BTSCO_LISTEN; 284 aprint_verbose(" listen mode"); 285 } 286 287 obj = prop_dictionary_get(dict, BTSCOchannel); 288 if (prop_object_type(obj) != PROP_TYPE_NUMBER 289 || prop_number_integer_value(obj) < RFCOMM_CHANNEL_MIN 290 || prop_number_integer_value(obj) > RFCOMM_CHANNEL_MAX) { 291 aprint_error(" invalid %s", BTSCOchannel); 292 return; 293 } 294 sc->sc_channel = prop_number_integer_value(obj); 295 296 aprint_verbose(" channel %d", sc->sc_channel); 297 aprint_normal("\n"); 298 299 DPRINTF("sc=%p\n", sc); 300 301 /* 302 * set up transmit interrupt 303 */ 304 sc->sc_intr = softintr_establish(IPL_SOFTNET, btsco_intr, sc); 305 if (sc->sc_intr == NULL) { 306 aprint_error("%s: softintr_establish failed\n", 307 device_xname((struct device *)sc)); 308 return; 309 } 310 311 /* 312 * attach audio device 313 */ 314 sc->sc_audio = audio_attach_mi(&btsco_if, sc, (struct device *)sc); 315 if (sc->sc_audio == NULL) { 316 aprint_error("%s: audio_attach_mi failed\n", 317 device_xname((struct device *)sc)); 318 return; 319 } 320 } 321 322 static int 323 btsco_detach(struct device *self, int flags) 324 { 325 struct btsco_softc *sc = (struct btsco_softc *)self; 326 int s; 327 328 DPRINTF("sc=%p\n", sc); 329 330 s = splsoftnet(); 331 if (sc->sc_sco != NULL) { 332 DPRINTF("sc_sco=%p\n", sc->sc_sco); 333 sco_disconnect(sc->sc_sco, 0); 334 sco_detach(&sc->sc_sco); 335 sc->sc_sco = NULL; 336 } 337 338 if (sc->sc_sco_l != NULL) { 339 DPRINTF("sc_sco_l=%p\n", sc->sc_sco_l); 340 sco_detach(&sc->sc_sco_l); 341 sc->sc_sco_l = NULL; 342 } 343 splx(s); 344 345 if (sc->sc_audio != NULL) { 346 DPRINTF("sc_audio=%p\n", sc->sc_audio); 347 config_detach(sc->sc_audio, flags); 348 sc->sc_audio = NULL; 349 } 350 351 if (sc->sc_intr != NULL) { 352 softintr_disestablish(sc->sc_intr); 353 sc->sc_intr = NULL; 354 } 355 356 if (sc->sc_rx_mbuf != NULL) { 357 m_freem(sc->sc_rx_mbuf); 358 sc->sc_rx_mbuf = NULL; 359 } 360 361 if (sc->sc_tx_refcnt > 0) { 362 printf("%s: tx_refcnt=%d!\n", 363 device_xname((struct device *)sc), sc->sc_tx_refcnt); 364 365 if ((flags & DETACH_FORCE) == 0) 366 return EAGAIN; 367 } 368 369 return 0; 370 } 371 372 /* 373 * btdev identity matching 374 */ 375 static int 376 btsco_identify(struct btdev *dev, prop_dictionary_t dict) 377 { 378 struct btsco_softc *sc = (struct btsco_softc *)dev; 379 prop_object_t obj; 380 381 obj = prop_dictionary_get(dict, BTDEVtype); 382 if (!prop_string_equals_cstring(obj, "btsco")) 383 return 0; 384 385 obj = prop_dictionary_get(dict, BTDEVladdr); 386 if (!prop_data_equals_data(obj, &sc->sc_laddr, sizeof(bdaddr_t))) 387 return 0; 388 389 obj = prop_dictionary_get(dict, BTDEVraddr); 390 if (!prop_data_equals_data(obj, &sc->sc_raddr, sizeof(bdaddr_t))) 391 return 0; 392 393 return 1; 394 } 395 396 /***************************************************************************** 397 * 398 * bluetooth(9) methods for SCO 399 * 400 * All these are called from Bluetooth Protocol code, in a soft 401 * interrupt context at IPL_SOFTNET. 402 */ 403 404 static void 405 btsco_sco_connecting(void *arg) 406 { 407 /* struct btsco_softc *sc = arg; */ 408 409 /* dont care */ 410 } 411 412 static void 413 btsco_sco_connected(void *arg) 414 { 415 struct btsco_softc *sc = arg; 416 417 DPRINTF("%s\n", device_xname((struct device *)sc)); 418 419 KASSERT(sc->sc_sco != NULL); 420 KASSERT(sc->sc_state == BTSCO_WAIT_CONNECT); 421 422 /* 423 * If we are listening, no more need 424 */ 425 if (sc->sc_sco_l != NULL) 426 sco_detach(&sc->sc_sco_l); 427 428 sc->sc_state = BTSCO_OPEN; 429 wakeup(sc); 430 } 431 432 static void 433 btsco_sco_disconnected(void *arg, int err) 434 { 435 struct btsco_softc *sc = arg; 436 int s; 437 438 DPRINTF("%s sc_state %d\n", 439 device_xname((struct device *)sc), sc->sc_state); 440 441 KASSERT(sc->sc_sco != NULL); 442 443 sc->sc_err = err; 444 sco_detach(&sc->sc_sco); 445 446 switch (sc->sc_state) { 447 case BTSCO_CLOSED: /* dont think this can happen */ 448 break; 449 450 case BTSCO_WAIT_CONNECT: /* connect failed */ 451 wakeup(sc); 452 break; 453 454 case BTSCO_OPEN: /* link lost */ 455 /* 456 * If IO is in progress, tell the audio driver that it 457 * has completed so that when it tries to send more, we 458 * can indicate an error. 459 */ 460 s = splaudio(); 461 if (sc->sc_tx_pending > 0) { 462 sc->sc_tx_pending = 0; 463 (*sc->sc_tx_intr)(sc->sc_tx_intrarg); 464 } 465 if (sc->sc_rx_want > 0) { 466 sc->sc_rx_want = 0; 467 (*sc->sc_rx_intr)(sc->sc_rx_intrarg); 468 } 469 splx(s); 470 break; 471 472 default: 473 UNKNOWN(sc->sc_state); 474 } 475 476 sc->sc_state = BTSCO_CLOSED; 477 } 478 479 static void * 480 btsco_sco_newconn(void *arg, struct sockaddr_bt *laddr, struct sockaddr_bt *raddr) 481 { 482 struct btsco_softc *sc = arg; 483 484 DPRINTF("%s\n", device_xname((struct device *)sc)); 485 if (bdaddr_same(&raddr->bt_bdaddr, &sc->sc_raddr) == 0 486 || sc->sc_state != BTSCO_WAIT_CONNECT 487 || sc->sc_sco != NULL) 488 return NULL; 489 490 sco_attach(&sc->sc_sco, &btsco_sco_proto, sc); 491 return sc->sc_sco; 492 } 493 494 static void 495 btsco_sco_complete(void *arg, int count) 496 { 497 struct btsco_softc *sc = arg; 498 int s; 499 500 DPRINTFN(10, "%s count %d\n", 501 device_xname((struct device *)sc), count); 502 503 s = splaudio(); 504 if (sc->sc_tx_pending > 0) { 505 sc->sc_tx_pending -= count; 506 if (sc->sc_tx_pending == 0) 507 (*sc->sc_tx_intr)(sc->sc_tx_intrarg); 508 } 509 splx(s); 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", 519 device_xname((struct device *)sc), m->m_pkthdr.len); 520 521 s = splaudio(); 522 if (sc->sc_rx_want == 0) { 523 m_freem(m); 524 } else { 525 KASSERT(sc->sc_rx_intr != NULL); 526 KASSERT(sc->sc_rx_block != NULL); 527 528 len = MIN(sc->sc_rx_want, m->m_pkthdr.len); 529 m_copydata(m, 0, len, sc->sc_rx_block); 530 531 sc->sc_rx_want -= len; 532 sc->sc_rx_block += len; 533 534 if (len > m->m_pkthdr.len) { 535 if (sc->sc_rx_mbuf != NULL) 536 m_freem(sc->sc_rx_mbuf); 537 538 m_adj(m, len); 539 sc->sc_rx_mbuf = m; 540 } else { 541 m_freem(m); 542 } 543 544 if (sc->sc_rx_want == 0) 545 (*sc->sc_rx_intr)(sc->sc_rx_intrarg); 546 } 547 splx(s); 548 } 549 550 551 /***************************************************************************** 552 * 553 * audio(9) methods 554 * 555 */ 556 557 static int 558 btsco_open(void *hdl, int flags) 559 { 560 struct sockaddr_bt sa; 561 struct btsco_softc *sc = hdl; 562 int err, s, timo; 563 564 DPRINTF("%s flags 0x%x\n", 565 device_xname((struct device *)sc), flags); 566 /* flags FREAD & FWRITE? */ 567 568 if (sc->sc_sco != NULL || sc->sc_sco_l != NULL) 569 return EIO; 570 571 s = splsoftnet(); 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 = tsleep(sc, PWAIT | PCATCH, "btsco", 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 splx(s); 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 int s; 657 658 DPRINTF("%s\n", device_xname((struct device *)sc)); 659 660 s = splsoftnet(); 661 if (sc->sc_sco != NULL) { 662 sco_disconnect(sc->sc_sco, 0); 663 sco_detach(&sc->sc_sco); 664 } 665 666 if (sc->sc_sco_l != NULL) { 667 sco_detach(&sc->sc_sco_l); 668 } 669 splx(s); 670 671 if (sc->sc_rx_mbuf != NULL) { 672 m_freem(sc->sc_rx_mbuf); 673 sc->sc_rx_mbuf = NULL; 674 } 675 676 sc->sc_rx_want = 0; 677 sc->sc_rx_block = NULL; 678 sc->sc_rx_intr = NULL; 679 sc->sc_rx_intrarg = NULL; 680 681 sc->sc_tx_size = 0; 682 sc->sc_tx_block = NULL; 683 sc->sc_tx_pending = 0; 684 sc->sc_tx_intr = NULL; 685 sc->sc_tx_intrarg = NULL; 686 } 687 688 static int 689 btsco_query_encoding(void *hdl, struct audio_encoding *ae) 690 { 691 /* struct btsco_softc *sc = hdl; */ 692 int err = 0; 693 694 switch (ae->index) { 695 case 0: 696 strcpy(ae->name, AudioEslinear_le); 697 ae->encoding = AUDIO_ENCODING_SLINEAR_LE; 698 ae->precision = 16; 699 ae->flags = 0; 700 break; 701 702 default: 703 err = EINVAL; 704 } 705 706 return err; 707 } 708 709 static int 710 btsco_set_params(void *hdl, int setmode, int usemode, 711 audio_params_t *play, audio_params_t *rec, 712 stream_filter_list_t *pfil, stream_filter_list_t *rfil) 713 { 714 /* struct btsco_softc *sc = hdl; */ 715 audio_params_t hw; 716 int err = 0; 717 718 DPRINTF("setmode 0x%x usemode 0x%x\n", setmode, usemode); 719 DPRINTF("rate %d, precision %d, channels %d encoding %d\n", 720 play->sample_rate, play->precision, play->channels, play->encoding); 721 722 if ((play->precision != 16 && play->precision != 8) 723 || play->sample_rate < 7500 724 || play->sample_rate > 8500 725 || play->channels != 1) 726 return EINVAL; 727 728 play->sample_rate = 8000; 729 hw = *play; 730 731 switch (play->encoding) { 732 case AUDIO_ENCODING_ULAW: 733 hw.encoding = AUDIO_ENCODING_SLINEAR_LE; 734 pfil->append(pfil, mulaw_to_linear16, &hw); 735 break; 736 737 case AUDIO_ENCODING_ALAW: 738 hw.encoding = AUDIO_ENCODING_SLINEAR_LE; 739 pfil->append(pfil, alaw_to_linear16, &hw); 740 break; 741 742 case AUDIO_ENCODING_SLINEAR_LE: 743 break; 744 745 case AUDIO_ENCODING_SLINEAR_BE: 746 if (play->precision == 16) { 747 hw.encoding = AUDIO_ENCODING_SLINEAR_LE; 748 pfil->append(pfil, swap_bytes, &hw); 749 } 750 break; 751 752 case AUDIO_ENCODING_ULINEAR_LE: 753 case AUDIO_ENCODING_ULINEAR_BE: 754 default: 755 err = EINVAL; 756 } 757 758 return err; 759 } 760 761 /* 762 * If we have an MTU value to use, round the blocksize to that. 763 */ 764 static int 765 btsco_round_blocksize(void *hdl, int bs, int mode, const audio_params_t *param) 766 { 767 struct btsco_softc *sc = hdl; 768 769 if (sc->sc_mtu > 0) { 770 bs = (bs / sc->sc_mtu) * sc->sc_mtu; 771 if (bs == 0) 772 bs = sc->sc_mtu; 773 } 774 775 DPRINTF("%s mode=0x%x, bs=%d, sc_mtu=%d\n", 776 device_xname((struct device *)sc), mode, bs, sc->sc_mtu); 777 778 return bs; 779 } 780 781 /* 782 * Start Output 783 * 784 * We dont want to be calling the network stack at splaudio() so make 785 * a note of what is to be sent, and schedule an interrupt to bundle 786 * it up and queue it. 787 */ 788 static int 789 btsco_start_output(void *hdl, void *block, int blksize, 790 void (*intr)(void *), void *intrarg) 791 { 792 struct btsco_softc *sc = hdl; 793 794 DPRINTFN(5, "%s blksize %d\n", 795 device_xname((struct device *)sc), blksize); 796 797 if (sc->sc_sco == NULL) 798 return ENOTCONN; /* connection lost */ 799 800 sc->sc_tx_block = block; 801 sc->sc_tx_pending = 0; 802 sc->sc_tx_size = blksize; 803 sc->sc_tx_intr = intr; 804 sc->sc_tx_intrarg = intrarg; 805 806 softintr_schedule(sc->sc_intr); 807 return 0; 808 } 809 810 /* 811 * Start Input 812 * 813 * When the SCO link is up, we are getting data in any case, so all we do 814 * is note what we want and where to put it and let the sco_input routine 815 * fill in the data. 816 * 817 * If there was any leftover data that didnt fit in the last block, retry 818 * it now. 819 */ 820 static int 821 btsco_start_input(void *hdl, void *block, int blksize, 822 void (*intr)(void *), void *intrarg) 823 { 824 struct btsco_softc *sc = hdl; 825 struct mbuf *m; 826 827 DPRINTFN(5, "%s blksize %d\n", 828 device_xname((struct device *)sc), blksize); 829 830 if (sc->sc_sco == NULL) 831 return ENOTCONN; 832 833 sc->sc_rx_want = blksize; 834 sc->sc_rx_block = block; 835 sc->sc_rx_intr = intr; 836 sc->sc_rx_intrarg = intrarg; 837 838 if (sc->sc_rx_mbuf != NULL) { 839 m = sc->sc_rx_mbuf; 840 sc->sc_rx_mbuf = NULL; 841 btsco_sco_input(sc, m); 842 } 843 844 return 0; 845 } 846 847 /* 848 * Halt Output 849 * 850 * This doesnt really halt the output, but it will look 851 * that way to the audio driver. The current block will 852 * still be transmitted. 853 */ 854 static int 855 btsco_halt_output(void *hdl) 856 { 857 struct btsco_softc *sc = hdl; 858 859 DPRINTFN(5, "%s\n", device_xname((struct device *)sc)); 860 861 sc->sc_tx_size = 0; 862 sc->sc_tx_block = NULL; 863 sc->sc_tx_pending = 0; 864 sc->sc_tx_intr = NULL; 865 sc->sc_tx_intrarg = NULL; 866 867 return 0; 868 } 869 870 /* 871 * Halt Input 872 * 873 * This doesnt really halt the input, but it will look 874 * that way to the audio driver. Incoming data will be 875 * discarded. 876 */ 877 static int 878 btsco_halt_input(void *hdl) 879 { 880 struct btsco_softc *sc = hdl; 881 882 DPRINTFN(5, "%s\n", device_xname((struct device *)sc)); 883 884 sc->sc_rx_want = 0; 885 sc->sc_rx_block = NULL; 886 sc->sc_rx_intr = NULL; 887 sc->sc_rx_intrarg = NULL; 888 889 if (sc->sc_rx_mbuf != NULL) { 890 m_freem(sc->sc_rx_mbuf); 891 sc->sc_rx_mbuf = NULL; 892 } 893 894 return 0; 895 } 896 897 static int 898 btsco_getdev(void *hdl, struct audio_device *ret) 899 { 900 901 *ret = btsco_device; 902 return 0; 903 } 904 905 static int 906 btsco_setfd(void *hdl, int fd) 907 { 908 /* struct btsco_softc *sc = hdl; */ 909 910 DPRINTF("set %s duplex\n", fd ? "full" : "half"); 911 912 return 0; 913 } 914 915 static int 916 btsco_set_port(void *hdl, mixer_ctrl_t *mc) 917 { 918 struct btsco_softc *sc = hdl; 919 int err = 0; 920 921 DPRINTF("%s dev %d type %d\n", 922 device_xname((struct device *)sc), mc->dev, mc->type); 923 924 switch (mc->dev) { 925 case BTSCO_VGS: 926 if (mc->type != AUDIO_MIXER_VALUE || 927 mc->un.value.num_channels != 1) { 928 err = EINVAL; 929 break; 930 } 931 932 sc->sc_vgs = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 933 break; 934 935 case BTSCO_VGM: 936 if (mc->type != AUDIO_MIXER_VALUE || 937 mc->un.value.num_channels != 1) { 938 err = EINVAL; 939 break; 940 } 941 942 sc->sc_vgm = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO]; 943 break; 944 945 default: 946 err = EINVAL; 947 break; 948 } 949 950 return err; 951 } 952 953 static int 954 btsco_get_port(void *hdl, mixer_ctrl_t *mc) 955 { 956 struct btsco_softc *sc = hdl; 957 int err = 0; 958 959 DPRINTF("%s dev %d\n", 960 device_xname((struct device *)sc), mc->dev); 961 962 switch (mc->dev) { 963 case BTSCO_VGS: 964 mc->type = AUDIO_MIXER_VALUE; 965 mc->un.value.num_channels = 1; 966 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_vgs; 967 break; 968 969 case BTSCO_VGM: 970 mc->type = AUDIO_MIXER_VALUE; 971 mc->un.value.num_channels = 1; 972 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_vgm; 973 break; 974 975 default: 976 err = EINVAL; 977 break; 978 } 979 980 return err; 981 } 982 983 static int 984 btsco_query_devinfo(void *hdl, mixer_devinfo_t *di) 985 { 986 /* struct btsco_softc *sc = hdl; */ 987 int err = 0; 988 989 switch(di->index) { 990 case BTSCO_VGS: 991 di->mixer_class = BTSCO_INPUT_CLASS; 992 di->next = di->prev = AUDIO_MIXER_LAST; 993 strcpy(di->label.name, AudioNspeaker); 994 di->type = AUDIO_MIXER_VALUE; 995 strcpy(di->un.v.units.name, AudioNvolume); 996 di->un.v.num_channels = 1; 997 di->un.v.delta = BTSCO_DELTA; 998 break; 999 1000 case BTSCO_VGM: 1001 di->mixer_class = BTSCO_INPUT_CLASS; 1002 di->next = di->prev = AUDIO_MIXER_LAST; 1003 strcpy(di->label.name, AudioNmicrophone); 1004 di->type = AUDIO_MIXER_VALUE; 1005 strcpy(di->un.v.units.name, AudioNvolume); 1006 di->un.v.num_channels = 1; 1007 di->un.v.delta = BTSCO_DELTA; 1008 break; 1009 1010 case BTSCO_INPUT_CLASS: 1011 di->mixer_class = BTSCO_INPUT_CLASS; 1012 di->next = di->prev = AUDIO_MIXER_LAST; 1013 strcpy(di->label.name, AudioCinputs); 1014 di->type = AUDIO_MIXER_CLASS; 1015 break; 1016 1017 default: 1018 err = ENXIO; 1019 break; 1020 } 1021 1022 return err; 1023 } 1024 1025 /* 1026 * Allocate Ring Buffers. 1027 */ 1028 static void * 1029 btsco_allocm(void *hdl, int direction, size_t size, 1030 struct malloc_type *type, int flags) 1031 { 1032 struct btsco_softc *sc = hdl; 1033 void *addr; 1034 1035 DPRINTF("%s: size %d direction %d\n", 1036 device_xname((struct device *)sc), size, direction); 1037 1038 addr = malloc(size, type, flags); 1039 1040 if (direction == AUMODE_PLAY) { 1041 sc->sc_tx_buf = addr; 1042 sc->sc_tx_refcnt = 0; 1043 } 1044 1045 return addr; 1046 } 1047 1048 /* 1049 * Free Ring Buffers. 1050 * 1051 * Because we used external memory for the tx mbufs, we dont 1052 * want to free the memory until all the mbufs are done with 1053 * 1054 * Just to be sure, dont free if something is still pending. 1055 * This would be a memory leak but at least there is a warning.. 1056 */ 1057 static void 1058 btsco_freem(void *hdl, void *addr, struct malloc_type *type) 1059 { 1060 struct btsco_softc *sc = hdl; 1061 int count = hz / 2; 1062 1063 if (addr == sc->sc_tx_buf) { 1064 DPRINTF("%s: tx_refcnt=%d\n", 1065 device_xname((struct device *)sc), sc->sc_tx_refcnt); 1066 1067 sc->sc_tx_buf = NULL; 1068 1069 while (sc->sc_tx_refcnt> 0 && count-- > 0) 1070 tsleep(sc, PWAIT, "drain", 1); 1071 1072 if (sc->sc_tx_refcnt > 0) { 1073 printf("%s: ring buffer unreleased!\n", 1074 device_xname((struct device *)sc)); 1075 return; 1076 } 1077 } 1078 1079 free(addr, type); 1080 } 1081 1082 static int 1083 btsco_get_props(void *hdl) 1084 { 1085 1086 return AUDIO_PROP_FULLDUPLEX; 1087 } 1088 1089 /* 1090 * Handle private ioctl. We pass information out about how to talk 1091 * to the device and mixer. 1092 */ 1093 static int 1094 btsco_dev_ioctl(void *hdl, u_long cmd, caddr_t addr, int flag, struct lwp *l) 1095 { 1096 struct btsco_softc *sc = hdl; 1097 struct btsco_info *bi = (struct btsco_info *)addr; 1098 int err = 0; 1099 1100 DPRINTF("%s cmd 0x%lx flag %d\n", 1101 device_xname((struct device *)sc), cmd, flag); 1102 1103 switch (cmd) { 1104 case BTSCO_GETINFO: 1105 memset(bi, 0, sizeof(*bi)); 1106 bdaddr_copy(&bi->laddr, &sc->sc_laddr); 1107 bdaddr_copy(&bi->raddr, &sc->sc_raddr); 1108 bi->channel = sc->sc_channel; 1109 bi->vgs = BTSCO_VGS; 1110 bi->vgm = BTSCO_VGM; 1111 break; 1112 1113 default: 1114 err = EPASSTHROUGH; 1115 break; 1116 } 1117 1118 return err; 1119 } 1120 1121 1122 /***************************************************************************** 1123 * 1124 * misc btsco functions 1125 * 1126 */ 1127 1128 /* 1129 * Our transmit interrupt. This is triggered when a new block is to be 1130 * sent. We send mtu sized chunks of the block as mbufs with external 1131 * storage to sco_send() 1132 */ 1133 static void 1134 btsco_intr(void *arg) 1135 { 1136 struct btsco_softc *sc = arg; 1137 struct mbuf *m; 1138 uint8_t *block; 1139 int mlen, size; 1140 1141 DPRINTFN(10, "%s block %p size %d\n", 1142 device_xname((struct device *)sc), sc->sc_tx_block, sc->sc_tx_size); 1143 1144 if (sc->sc_sco == NULL) 1145 return; /* connection is lost */ 1146 1147 block = sc->sc_tx_block; 1148 size = sc->sc_tx_size; 1149 sc->sc_tx_block = NULL; 1150 sc->sc_tx_size = 0; 1151 1152 while (size > 0) { 1153 MGETHDR(m, M_DONTWAIT, MT_DATA); 1154 if (m == NULL) 1155 break; 1156 1157 mlen = MIN(sc->sc_mtu, size); 1158 1159 /* I think M_DEVBUF is true but not relevant */ 1160 MEXTADD(m, block, mlen, M_DEVBUF, btsco_extfree, sc); 1161 if ((m->m_flags & M_EXT) == 0) { 1162 m_free(m); 1163 break; 1164 } 1165 sc->sc_tx_refcnt++; 1166 1167 m->m_pkthdr.len = m->m_len = mlen; 1168 sc->sc_tx_pending++; 1169 1170 if (sco_send(sc->sc_sco, m) > 0) { 1171 sc->sc_tx_pending--; 1172 break; 1173 } 1174 1175 block += mlen; 1176 size -= mlen; 1177 } 1178 } 1179 1180 /* 1181 * Release the mbuf, we keep a reference count on the tx buffer so 1182 * that we dont release it before its free. 1183 */ 1184 static void 1185 btsco_extfree(struct mbuf *m, caddr_t addr, size_t size, void *arg) 1186 { 1187 struct btsco_softc *sc = arg; 1188 1189 if (m != NULL) 1190 pool_cache_put(&mbpool_cache, m); 1191 1192 sc->sc_tx_refcnt--; 1193 } 1194