btsco.c revision 1.18 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