btsco.c revision 1.12 1 /* $NetBSD: btsco.c,v 1.12 2007/03/04 06:01:45 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.12 2007/03/04 06:01:45 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, void *, 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 *, void *, 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, void *addr, int flag,
1069 struct lwp *l)
1070 {
1071 struct btsco_softc *sc = hdl;
1072 struct btsco_info *bi = (struct btsco_info *)addr;
1073 int err = 0;
1074
1075 DPRINTF("%s cmd 0x%lx flag %d\n",
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, void *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