btsco.c revision 1.18.14.1 1 /* $NetBSD: btsco.c,v 1.18.14.1 2008/04/03 12:42:38 mjf 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.14.1 2008/04/03 12:42:38 mjf 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 uint16_t sc_flags;
90 const char *sc_name; /* our device_xname */
91
92 device_t sc_audio; /* MI audio device */
93 void *sc_intr; /* interrupt cookie */
94
95 /* Bluetooth */
96 bdaddr_t sc_laddr; /* local address */
97 bdaddr_t sc_raddr; /* remote address */
98 uint16_t sc_state; /* link state */
99 struct sco_pcb *sc_sco; /* SCO handle */
100 struct sco_pcb *sc_sco_l; /* SCO listen handle */
101 uint16_t sc_mtu; /* SCO mtu */
102 uint8_t sc_channel; /* RFCOMM channel */
103 int sc_err; /* stored error */
104
105 /* Receive */
106 int sc_rx_want; /* bytes wanted */
107 uint8_t *sc_rx_block; /* receive block */
108 void (*sc_rx_intr)(void *); /* callback */
109 void *sc_rx_intrarg; /* callback arg */
110 struct mbuf *sc_rx_mbuf; /* leftover mbuf */
111
112 /* Transmit */
113 int sc_tx_size; /* bytes to send */
114 int sc_tx_pending; /* packets pending */
115 uint8_t *sc_tx_block; /* transmit block */
116 void (*sc_tx_intr)(void *); /* callback */
117 void *sc_tx_intrarg; /* callback arg */
118 void *sc_tx_buf; /* transmit buffer */
119 int sc_tx_refcnt; /* buffer refcnt */
120
121 /* mixer data */
122 int sc_vgs; /* speaker volume */
123 int sc_vgm; /* mic volume */
124 };
125
126 /* sc_state */
127 #define BTSCO_CLOSED 0
128 #define BTSCO_WAIT_CONNECT 1
129 #define BTSCO_OPEN 2
130
131 /* sc_flags */
132 #define BTSCO_LISTEN (1 << 1)
133
134 /* autoconf(9) glue */
135 static int btsco_match(device_t, struct cfdata *, void *);
136 static void btsco_attach(device_t, device_t, void *);
137 static int btsco_detach(device_t, int);
138
139 CFATTACH_DECL_NEW(btsco, sizeof(struct btsco_softc),
140 btsco_match, btsco_attach, btsco_detach, NULL);
141
142 /* audio(9) glue */
143 static int btsco_open(void *, int);
144 static void btsco_close(void *);
145 static int btsco_query_encoding(void *, struct audio_encoding *);
146 static int btsco_set_params(void *, int, int, audio_params_t *, audio_params_t *,
147 stream_filter_list_t *, stream_filter_list_t *);
148 static int btsco_round_blocksize(void *, int, int, const audio_params_t *);
149 static int btsco_start_output(void *, void *, int, void (*)(void *), void *);
150 static int btsco_start_input(void *, void *, int, void (*)(void *), void *);
151 static int btsco_halt_output(void *);
152 static int btsco_halt_input(void *);
153 static int btsco_getdev(void *, struct audio_device *);
154 static int btsco_setfd(void *, int);
155 static int btsco_set_port(void *, mixer_ctrl_t *);
156 static int btsco_get_port(void *, mixer_ctrl_t *);
157 static int btsco_query_devinfo(void *, mixer_devinfo_t *);
158 static void *btsco_allocm(void *, int, size_t, struct malloc_type *, int);
159 static void btsco_freem(void *, void *, struct malloc_type *);
160 static int btsco_get_props(void *);
161 static int btsco_dev_ioctl(void *, u_long, void *, int, struct lwp *);
162
163 static const struct audio_hw_if btsco_if = {
164 btsco_open, /* open */
165 btsco_close, /* close */
166 NULL, /* drain */
167 btsco_query_encoding, /* query_encoding */
168 btsco_set_params, /* set_params */
169 btsco_round_blocksize, /* round_blocksize */
170 NULL, /* commit_settings */
171 NULL, /* init_output */
172 NULL, /* init_input */
173 btsco_start_output, /* start_output */
174 btsco_start_input, /* start_input */
175 btsco_halt_output, /* halt_output */
176 btsco_halt_input, /* halt_input */
177 NULL, /* speaker_ctl */
178 btsco_getdev, /* getdev */
179 btsco_setfd, /* setfd */
180 btsco_set_port, /* set_port */
181 btsco_get_port, /* get_port */
182 btsco_query_devinfo, /* query_devinfo */
183 btsco_allocm, /* allocm */
184 btsco_freem, /* freem */
185 NULL, /* round_buffersize */
186 NULL, /* mappage */
187 btsco_get_props, /* get_props */
188 NULL, /* trigger_output */
189 NULL, /* trigger_input */
190 btsco_dev_ioctl, /* dev_ioctl */
191 NULL, /* powerstate */
192 };
193
194 static const struct audio_device btsco_device = {
195 "Bluetooth Audio",
196 "",
197 "btsco"
198 };
199
200 /* Voice_Setting == 0x0060: 8000Hz, mono, 16-bit, slinear_le */
201 static const struct audio_format btsco_format = {
202 NULL, /* driver_data */
203 (AUMODE_PLAY | AUMODE_RECORD), /* mode */
204 AUDIO_ENCODING_SLINEAR_LE, /* encoding */
205 16, /* validbits */
206 16, /* precision */
207 1, /* channels */
208 AUFMT_MONAURAL, /* channel_mask */
209 1, /* frequency_type */
210 { 8000 } /* frequency */
211 };
212
213 /* bluetooth(9) glue for SCO */
214 static void btsco_sco_connecting(void *);
215 static void btsco_sco_connected(void *);
216 static void btsco_sco_disconnected(void *, int);
217 static void *btsco_sco_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *);
218 static void btsco_sco_complete(void *, int);
219 static void btsco_sco_linkmode(void *, int);
220 static void btsco_sco_input(void *, struct mbuf *);
221
222 static const struct btproto btsco_sco_proto = {
223 btsco_sco_connecting,
224 btsco_sco_connected,
225 btsco_sco_disconnected,
226 btsco_sco_newconn,
227 btsco_sco_complete,
228 btsco_sco_linkmode,
229 btsco_sco_input,
230 };
231
232
233 /*****************************************************************************
234 *
235 * btsco definitions
236 */
237
238 /*
239 * btsco mixer class
240 */
241 #define BTSCO_VGS 0
242 #define BTSCO_VGM 1
243 #define BTSCO_INPUT_CLASS 2
244 #define BTSCO_OUTPUT_CLASS 3
245
246 /* connect timeout */
247 #define BTSCO_TIMEOUT (30 * hz)
248
249 /* misc btsco functions */
250 static void btsco_extfree(struct mbuf *, void *, size_t, void *);
251 static void btsco_intr(void *);
252
253
254 /*****************************************************************************
255 *
256 * btsco autoconf(9) routines
257 */
258
259 static int
260 btsco_match(device_t self, struct cfdata *cfdata, void *aux)
261 {
262 prop_dictionary_t dict = aux;
263 prop_object_t obj;
264
265 obj = prop_dictionary_get(dict, BTDEVservice);
266 if (prop_string_equals_cstring(obj, "HSET"))
267 return 1;
268
269 if (prop_string_equals_cstring(obj, "HF"))
270 return 1;
271
272 return 0;
273 }
274
275 static void
276 btsco_attach(device_t parent, device_t self, void *aux)
277 {
278 struct btsco_softc *sc = device_private(self);
279 prop_dictionary_t dict = aux;
280 prop_object_t obj;
281
282 /*
283 * Init softc
284 */
285 sc->sc_vgs = 200;
286 sc->sc_vgm = 200;
287 sc->sc_state = BTSCO_CLOSED;
288 sc->sc_name = device_xname(self);
289
290 /*
291 * copy in our configuration info
292 */
293 obj = prop_dictionary_get(dict, BTDEVladdr);
294 bdaddr_copy(&sc->sc_laddr, prop_data_data_nocopy(obj));
295
296 obj = prop_dictionary_get(dict, BTDEVraddr);
297 bdaddr_copy(&sc->sc_raddr, prop_data_data_nocopy(obj));
298
299 obj = prop_dictionary_get(dict, BTDEVservice);
300 if (prop_string_equals_cstring(obj, "HF")) {
301 sc->sc_flags |= BTSCO_LISTEN;
302 aprint_verbose(" listen mode");
303 }
304
305 obj = prop_dictionary_get(dict, BTSCOchannel);
306 if (prop_object_type(obj) != PROP_TYPE_NUMBER
307 || prop_number_integer_value(obj) < RFCOMM_CHANNEL_MIN
308 || prop_number_integer_value(obj) > RFCOMM_CHANNEL_MAX) {
309 aprint_error(" invalid %s", BTSCOchannel);
310 return;
311 }
312 sc->sc_channel = prop_number_integer_value(obj);
313
314 aprint_verbose(" channel %d", sc->sc_channel);
315 aprint_normal("\n");
316
317 DPRINTF("sc=%p\n", sc);
318
319 /*
320 * set up transmit interrupt
321 */
322 sc->sc_intr = softint_establish(SOFTINT_NET, btsco_intr, sc);
323 if (sc->sc_intr == NULL) {
324 aprint_error_dev(self, "softint_establish failed\n");
325 return;
326 }
327
328 /*
329 * attach audio device
330 */
331 sc->sc_audio = audio_attach_mi(&btsco_if, sc, self);
332 if (sc->sc_audio == NULL) {
333 aprint_error_dev(self, "audio_attach_mi failed\n");
334 return;
335 }
336 }
337
338 static int
339 btsco_detach(device_t self, int flags)
340 {
341 struct btsco_softc *sc = device_private(self);
342 int s;
343
344 DPRINTF("sc=%p\n", sc);
345
346 s = splsoftnet();
347 if (sc->sc_sco != NULL) {
348 DPRINTF("sc_sco=%p\n", sc->sc_sco);
349 sco_disconnect(sc->sc_sco, 0);
350 sco_detach(&sc->sc_sco);
351 sc->sc_sco = NULL;
352 }
353
354 if (sc->sc_sco_l != NULL) {
355 DPRINTF("sc_sco_l=%p\n", sc->sc_sco_l);
356 sco_detach(&sc->sc_sco_l);
357 sc->sc_sco_l = NULL;
358 }
359 splx(s);
360
361 if (sc->sc_audio != NULL) {
362 DPRINTF("sc_audio=%p\n", sc->sc_audio);
363 config_detach(sc->sc_audio, flags);
364 sc->sc_audio = NULL;
365 }
366
367 if (sc->sc_intr != NULL) {
368 softint_disestablish(sc->sc_intr);
369 sc->sc_intr = NULL;
370 }
371
372 if (sc->sc_rx_mbuf != NULL) {
373 m_freem(sc->sc_rx_mbuf);
374 sc->sc_rx_mbuf = NULL;
375 }
376
377 if (sc->sc_tx_refcnt > 0) {
378 aprint_error_dev(self, "tx_refcnt=%d!\n", 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", sc->sc_name);
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", sc->sc_name, sc->sc_state);
430
431 KASSERT(sc->sc_sco != NULL);
432
433 sc->sc_err = err;
434 sco_detach(&sc->sc_sco);
435
436 switch (sc->sc_state) {
437 case BTSCO_CLOSED: /* dont think this can happen */
438 break;
439
440 case BTSCO_WAIT_CONNECT: /* connect failed */
441 wakeup(sc);
442 break;
443
444 case BTSCO_OPEN: /* link lost */
445 /*
446 * If IO is in progress, tell the audio driver that it
447 * has completed so that when it tries to send more, we
448 * can indicate an error.
449 */
450 s = splaudio();
451 if (sc->sc_tx_pending > 0) {
452 sc->sc_tx_pending = 0;
453 (*sc->sc_tx_intr)(sc->sc_tx_intrarg);
454 }
455 if (sc->sc_rx_want > 0) {
456 sc->sc_rx_want = 0;
457 (*sc->sc_rx_intr)(sc->sc_rx_intrarg);
458 }
459 splx(s);
460 break;
461
462 default:
463 UNKNOWN(sc->sc_state);
464 }
465
466 sc->sc_state = BTSCO_CLOSED;
467 }
468
469 static void *
470 btsco_sco_newconn(void *arg, struct sockaddr_bt *laddr,
471 struct sockaddr_bt *raddr)
472 {
473 struct btsco_softc *sc = arg;
474
475 DPRINTF("%s\n", sc->sc_name);
476
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", sc->sc_name, count);
493
494 s = splaudio();
495 if (sc->sc_tx_pending > 0) {
496 sc->sc_tx_pending -= count;
497 if (sc->sc_tx_pending == 0)
498 (*sc->sc_tx_intr)(sc->sc_tx_intrarg);
499 }
500 splx(s);
501 }
502
503 static void
504 btsco_sco_linkmode(void *arg, int new)
505 {
506 /* struct btsco_softc *sc = arg; */
507
508 /* dont care */
509 }
510
511 static void
512 btsco_sco_input(void *arg, struct mbuf *m)
513 {
514 struct btsco_softc *sc = arg;
515 int len, s;
516
517 DPRINTFN(10, "%s len=%d\n", sc->sc_name, m->m_pkthdr.len);
518
519 s = splaudio();
520 if (sc->sc_rx_want == 0) {
521 m_freem(m);
522 } else {
523 KASSERT(sc->sc_rx_intr != NULL);
524 KASSERT(sc->sc_rx_block != NULL);
525
526 len = MIN(sc->sc_rx_want, m->m_pkthdr.len);
527 m_copydata(m, 0, len, sc->sc_rx_block);
528
529 sc->sc_rx_want -= len;
530 sc->sc_rx_block += len;
531
532 if (len > m->m_pkthdr.len) {
533 if (sc->sc_rx_mbuf != NULL)
534 m_freem(sc->sc_rx_mbuf);
535
536 m_adj(m, len);
537 sc->sc_rx_mbuf = m;
538 } else {
539 m_freem(m);
540 }
541
542 if (sc->sc_rx_want == 0)
543 (*sc->sc_rx_intr)(sc->sc_rx_intrarg);
544 }
545 splx(s);
546 }
547
548
549 /*****************************************************************************
550 *
551 * audio(9) methods
552 *
553 */
554
555 static int
556 btsco_open(void *hdl, int flags)
557 {
558 struct sockaddr_bt sa;
559 struct btsco_softc *sc = hdl;
560 int err, s, timo;
561
562 DPRINTF("%s flags 0x%x\n", sc->sc_name, flags);
563 /* flags FREAD & FWRITE? */
564
565 if (sc->sc_sco != NULL || sc->sc_sco_l != NULL)
566 return EIO;
567
568 s = splsoftnet();
569
570 memset(&sa, 0, sizeof(sa));
571 sa.bt_len = sizeof(sa);
572 sa.bt_family = AF_BLUETOOTH;
573 bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr);
574
575 if (sc->sc_flags & BTSCO_LISTEN) {
576 err = sco_attach(&sc->sc_sco_l, &btsco_sco_proto, sc);
577 if (err)
578 goto done;
579
580 err = sco_bind(sc->sc_sco_l, &sa);
581 if (err) {
582 sco_detach(&sc->sc_sco_l);
583 goto done;
584 }
585
586 err = sco_listen(sc->sc_sco_l);
587 if (err) {
588 sco_detach(&sc->sc_sco_l);
589 goto done;
590 }
591
592 timo = 0; /* no timeout */
593 } else {
594 err = sco_attach(&sc->sc_sco, &btsco_sco_proto, sc);
595 if (err)
596 goto done;
597
598 err = sco_bind(sc->sc_sco, &sa);
599 if (err) {
600 sco_detach(&sc->sc_sco);
601 goto done;
602 }
603
604 bdaddr_copy(&sa.bt_bdaddr, &sc->sc_raddr);
605 err = sco_connect(sc->sc_sco, &sa);
606 if (err) {
607 sco_detach(&sc->sc_sco);
608 goto done;
609 }
610
611 timo = BTSCO_TIMEOUT;
612 }
613
614 sc->sc_state = BTSCO_WAIT_CONNECT;
615 while (err == 0 && sc->sc_state == BTSCO_WAIT_CONNECT)
616 err = tsleep(sc, PWAIT | PCATCH, "btsco", timo);
617
618 switch (sc->sc_state) {
619 case BTSCO_CLOSED: /* disconnected */
620 err = sc->sc_err;
621
622 /* fall through to */
623 case BTSCO_WAIT_CONNECT: /* error */
624 if (sc->sc_sco != NULL)
625 sco_detach(&sc->sc_sco);
626
627 if (sc->sc_sco_l != NULL)
628 sco_detach(&sc->sc_sco_l);
629
630 break;
631
632 case BTSCO_OPEN: /* hurrah */
633 sco_getopt(sc->sc_sco, SO_SCO_MTU, &sc->sc_mtu);
634 break;
635
636 default:
637 UNKNOWN(sc->sc_state);
638 break;
639 }
640
641 done:
642 splx(s);
643
644 DPRINTF("done err=%d, sc_state=%d, sc_mtu=%d\n",
645 err, sc->sc_state, sc->sc_mtu);
646 return err;
647 }
648
649 static void
650 btsco_close(void *hdl)
651 {
652 struct btsco_softc *sc = hdl;
653 int s;
654
655 DPRINTF("%s\n", sc->sc_name);
656
657 s = splsoftnet();
658 if (sc->sc_sco != NULL) {
659 sco_disconnect(sc->sc_sco, 0);
660 sco_detach(&sc->sc_sco);
661 }
662
663 if (sc->sc_sco_l != NULL) {
664 sco_detach(&sc->sc_sco_l);
665 }
666 splx(s);
667
668 if (sc->sc_rx_mbuf != NULL) {
669 m_freem(sc->sc_rx_mbuf);
670 sc->sc_rx_mbuf = NULL;
671 }
672
673 sc->sc_rx_want = 0;
674 sc->sc_rx_block = NULL;
675 sc->sc_rx_intr = NULL;
676 sc->sc_rx_intrarg = NULL;
677
678 sc->sc_tx_size = 0;
679 sc->sc_tx_block = NULL;
680 sc->sc_tx_pending = 0;
681 sc->sc_tx_intr = NULL;
682 sc->sc_tx_intrarg = NULL;
683 }
684
685 static int
686 btsco_query_encoding(void *hdl, struct audio_encoding *ae)
687 {
688 /* struct btsco_softc *sc = hdl; */
689 int err = 0;
690
691 switch (ae->index) {
692 case 0:
693 strcpy(ae->name, AudioEslinear_le);
694 ae->encoding = AUDIO_ENCODING_SLINEAR_LE;
695 ae->precision = 16;
696 ae->flags = 0;
697 break;
698
699 default:
700 err = EINVAL;
701 }
702
703 return err;
704 }
705
706 static int
707 btsco_set_params(void *hdl, int setmode, int usemode,
708 audio_params_t *play, audio_params_t *rec,
709 stream_filter_list_t *pfil, stream_filter_list_t *rfil)
710 {
711 /* struct btsco_softc *sc = hdl; */
712 const struct audio_format *f;
713 int rv;
714
715 DPRINTF("setmode 0x%x usemode 0x%x\n", setmode, usemode);
716 DPRINTF("rate %d, precision %d, channels %d encoding %d\n",
717 play->sample_rate, play->precision, play->channels, play->encoding);
718
719 /*
720 * If we had a list of formats, we could check the HCI_Voice_Setting
721 * and select the appropriate one to use. Currently only one is
722 * supported: 0x0060 == 8000Hz, mono, 16-bit, slinear_le
723 */
724 f = &btsco_format;
725
726 if (setmode & AUMODE_PLAY) {
727 rv = auconv_set_converter(f, 1, AUMODE_PLAY, play, TRUE, pfil);
728 if (rv < 0)
729 return EINVAL;
730 }
731
732 if (setmode & AUMODE_RECORD) {
733 rv = auconv_set_converter(f, 1, AUMODE_RECORD, rec, TRUE, rfil);
734 if (rv < 0)
735 return EINVAL;
736 }
737
738 return 0;
739 }
740
741 /*
742 * If we have an MTU value to use, round the blocksize to that.
743 */
744 static int
745 btsco_round_blocksize(void *hdl, int bs, int mode,
746 const audio_params_t *param)
747 {
748 struct btsco_softc *sc = hdl;
749
750 if (sc->sc_mtu > 0) {
751 bs = (bs / sc->sc_mtu) * sc->sc_mtu;
752 if (bs == 0)
753 bs = sc->sc_mtu;
754 }
755
756 DPRINTF("%s mode=0x%x, bs=%d, sc_mtu=%d\n",
757 sc->sc_name, mode, bs, sc->sc_mtu);
758
759 return bs;
760 }
761
762 /*
763 * Start Output
764 *
765 * We dont want to be calling the network stack at splaudio() so make
766 * a note of what is to be sent, and schedule an interrupt to bundle
767 * it up and queue it.
768 */
769 static int
770 btsco_start_output(void *hdl, void *block, int blksize,
771 void (*intr)(void *), void *intrarg)
772 {
773 struct btsco_softc *sc = hdl;
774
775 DPRINTFN(5, "%s blksize %d\n", sc->sc_name, blksize);
776
777 if (sc->sc_sco == NULL)
778 return ENOTCONN; /* connection lost */
779
780 sc->sc_tx_block = block;
781 sc->sc_tx_pending = 0;
782 sc->sc_tx_size = blksize;
783 sc->sc_tx_intr = intr;
784 sc->sc_tx_intrarg = intrarg;
785
786 softint_schedule(sc->sc_intr);
787 return 0;
788 }
789
790 /*
791 * Start Input
792 *
793 * When the SCO link is up, we are getting data in any case, so all we do
794 * is note what we want and where to put it and let the sco_input routine
795 * fill in the data.
796 *
797 * If there was any leftover data that didnt fit in the last block, retry
798 * it now.
799 */
800 static int
801 btsco_start_input(void *hdl, void *block, int blksize,
802 void (*intr)(void *), void *intrarg)
803 {
804 struct btsco_softc *sc = hdl;
805 struct mbuf *m;
806
807 DPRINTFN(5, "%s blksize %d\n", sc->sc_name, blksize);
808
809 if (sc->sc_sco == NULL)
810 return ENOTCONN;
811
812 sc->sc_rx_want = blksize;
813 sc->sc_rx_block = block;
814 sc->sc_rx_intr = intr;
815 sc->sc_rx_intrarg = intrarg;
816
817 if (sc->sc_rx_mbuf != NULL) {
818 m = sc->sc_rx_mbuf;
819 sc->sc_rx_mbuf = NULL;
820 btsco_sco_input(sc, m);
821 }
822
823 return 0;
824 }
825
826 /*
827 * Halt Output
828 *
829 * This doesnt really halt the output, but it will look
830 * that way to the audio driver. The current block will
831 * still be transmitted.
832 */
833 static int
834 btsco_halt_output(void *hdl)
835 {
836 struct btsco_softc *sc = hdl;
837
838 DPRINTFN(5, "%s\n", sc->sc_name);
839
840 sc->sc_tx_size = 0;
841 sc->sc_tx_block = NULL;
842 sc->sc_tx_pending = 0;
843 sc->sc_tx_intr = NULL;
844 sc->sc_tx_intrarg = NULL;
845
846 return 0;
847 }
848
849 /*
850 * Halt Input
851 *
852 * This doesnt really halt the input, but it will look
853 * that way to the audio driver. Incoming data will be
854 * discarded.
855 */
856 static int
857 btsco_halt_input(void *hdl)
858 {
859 struct btsco_softc *sc = hdl;
860
861 DPRINTFN(5, "%s\n", sc->sc_name);
862
863 sc->sc_rx_want = 0;
864 sc->sc_rx_block = NULL;
865 sc->sc_rx_intr = NULL;
866 sc->sc_rx_intrarg = NULL;
867
868 if (sc->sc_rx_mbuf != NULL) {
869 m_freem(sc->sc_rx_mbuf);
870 sc->sc_rx_mbuf = NULL;
871 }
872
873 return 0;
874 }
875
876 static int
877 btsco_getdev(void *hdl, struct audio_device *ret)
878 {
879
880 *ret = btsco_device;
881 return 0;
882 }
883
884 static int
885 btsco_setfd(void *hdl, int fd)
886 {
887 DPRINTF("set %s duplex\n", fd ? "full" : "half");
888
889 return 0;
890 }
891
892 static int
893 btsco_set_port(void *hdl, mixer_ctrl_t *mc)
894 {
895 struct btsco_softc *sc = hdl;
896 int err = 0;
897
898 DPRINTF("%s dev %d type %d\n", sc->sc_name, mc->dev, mc->type);
899
900 switch (mc->dev) {
901 case BTSCO_VGS:
902 if (mc->type != AUDIO_MIXER_VALUE ||
903 mc->un.value.num_channels != 1) {
904 err = EINVAL;
905 break;
906 }
907
908 sc->sc_vgs = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
909 break;
910
911 case BTSCO_VGM:
912 if (mc->type != AUDIO_MIXER_VALUE ||
913 mc->un.value.num_channels != 1) {
914 err = EINVAL;
915 break;
916 }
917
918 sc->sc_vgm = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
919 break;
920
921 default:
922 err = EINVAL;
923 break;
924 }
925
926 return err;
927 }
928
929 static int
930 btsco_get_port(void *hdl, mixer_ctrl_t *mc)
931 {
932 struct btsco_softc *sc = hdl;
933 int err = 0;
934
935 DPRINTF("%s dev %d\n", sc->sc_name, mc->dev);
936
937 switch (mc->dev) {
938 case BTSCO_VGS:
939 mc->type = AUDIO_MIXER_VALUE;
940 mc->un.value.num_channels = 1;
941 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_vgs;
942 break;
943
944 case BTSCO_VGM:
945 mc->type = AUDIO_MIXER_VALUE;
946 mc->un.value.num_channels = 1;
947 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_vgm;
948 break;
949
950 default:
951 err = EINVAL;
952 break;
953 }
954
955 return err;
956 }
957
958 static int
959 btsco_query_devinfo(void *hdl, mixer_devinfo_t *di)
960 {
961 /* struct btsco_softc *sc = hdl; */
962 int err = 0;
963
964 switch(di->index) {
965 case BTSCO_VGS:
966 di->mixer_class = BTSCO_INPUT_CLASS;
967 di->next = di->prev = AUDIO_MIXER_LAST;
968 strcpy(di->label.name, AudioNspeaker);
969 di->type = AUDIO_MIXER_VALUE;
970 strcpy(di->un.v.units.name, AudioNvolume);
971 di->un.v.num_channels = 1;
972 di->un.v.delta = BTSCO_DELTA;
973 break;
974
975 case BTSCO_VGM:
976 di->mixer_class = BTSCO_INPUT_CLASS;
977 di->next = di->prev = AUDIO_MIXER_LAST;
978 strcpy(di->label.name, AudioNmicrophone);
979 di->type = AUDIO_MIXER_VALUE;
980 strcpy(di->un.v.units.name, AudioNvolume);
981 di->un.v.num_channels = 1;
982 di->un.v.delta = BTSCO_DELTA;
983 break;
984
985 case BTSCO_INPUT_CLASS:
986 di->mixer_class = BTSCO_INPUT_CLASS;
987 di->next = di->prev = AUDIO_MIXER_LAST;
988 strcpy(di->label.name, AudioCinputs);
989 di->type = AUDIO_MIXER_CLASS;
990 break;
991
992 default:
993 err = ENXIO;
994 break;
995 }
996
997 return err;
998 }
999
1000 /*
1001 * Allocate Ring Buffers.
1002 */
1003 static void *
1004 btsco_allocm(void *hdl, int direction, size_t size,
1005 struct malloc_type *type, int flags)
1006 {
1007 struct btsco_softc *sc = hdl;
1008 void *addr;
1009
1010 DPRINTF("%s: size %d direction %d\n", sc->sc_name, 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", sc->sc_name, sc->sc_tx_refcnt);
1039
1040 sc->sc_tx_buf = NULL;
1041
1042 while (sc->sc_tx_refcnt> 0 && count-- > 0)
1043 tsleep(sc, PWAIT, "drain", 1);
1044
1045 if (sc->sc_tx_refcnt > 0) {
1046 aprint_error("%s: ring buffer unreleased!\n", sc->sc_name);
1047 return;
1048 }
1049 }
1050
1051 free(addr, type);
1052 }
1053
1054 static int
1055 btsco_get_props(void *hdl)
1056 {
1057
1058 return AUDIO_PROP_FULLDUPLEX;
1059 }
1060
1061 /*
1062 * Handle private ioctl. We pass information out about how to talk
1063 * to the device and mixer.
1064 */
1065 static int
1066 btsco_dev_ioctl(void *hdl, u_long cmd, void *addr, int flag,
1067 struct lwp *l)
1068 {
1069 struct btsco_softc *sc = hdl;
1070 struct btsco_info *bi = (struct btsco_info *)addr;
1071 int err = 0;
1072
1073 DPRINTF("%s cmd 0x%lx flag %d\n", sc->sc_name, cmd, flag);
1074
1075 switch (cmd) {
1076 case BTSCO_GETINFO:
1077 memset(bi, 0, sizeof(*bi));
1078 bdaddr_copy(&bi->laddr, &sc->sc_laddr);
1079 bdaddr_copy(&bi->raddr, &sc->sc_raddr);
1080 bi->channel = sc->sc_channel;
1081 bi->vgs = BTSCO_VGS;
1082 bi->vgm = BTSCO_VGM;
1083 break;
1084
1085 default:
1086 err = EPASSTHROUGH;
1087 break;
1088 }
1089
1090 return err;
1091 }
1092
1093
1094 /*****************************************************************************
1095 *
1096 * misc btsco functions
1097 *
1098 */
1099
1100 /*
1101 * Our transmit interrupt. This is triggered when a new block is to be
1102 * sent. We send mtu sized chunks of the block as mbufs with external
1103 * storage to sco_send()
1104 */
1105 static void
1106 btsco_intr(void *arg)
1107 {
1108 struct btsco_softc *sc = arg;
1109 struct mbuf *m;
1110 uint8_t *block;
1111 int mlen, size;
1112
1113 DPRINTFN(10, "%s block %p size %d\n",
1114 sc->sc_name, sc->sc_tx_block, sc->sc_tx_size);
1115
1116 if (sc->sc_sco == NULL)
1117 return; /* connection is lost */
1118
1119 block = sc->sc_tx_block;
1120 size = sc->sc_tx_size;
1121 sc->sc_tx_block = NULL;
1122 sc->sc_tx_size = 0;
1123
1124 while (size > 0) {
1125 MGETHDR(m, M_DONTWAIT, MT_DATA);
1126 if (m == NULL)
1127 break;
1128
1129 mlen = MIN(sc->sc_mtu, size);
1130
1131 /* I think M_DEVBUF is true but not relevant */
1132 MEXTADD(m, block, mlen, M_DEVBUF, btsco_extfree, sc);
1133 if ((m->m_flags & M_EXT) == 0) {
1134 m_free(m);
1135 break;
1136 }
1137 sc->sc_tx_refcnt++;
1138
1139 m->m_pkthdr.len = m->m_len = mlen;
1140 sc->sc_tx_pending++;
1141
1142 if (sco_send(sc->sc_sco, m) > 0) {
1143 sc->sc_tx_pending--;
1144 break;
1145 }
1146
1147 block += mlen;
1148 size -= mlen;
1149 }
1150 }
1151
1152 /*
1153 * Release the mbuf, we keep a reference count on the tx buffer so
1154 * that we dont release it before its free.
1155 */
1156 static void
1157 btsco_extfree(struct mbuf *m, void *addr, size_t size,
1158 void *arg)
1159 {
1160 struct btsco_softc *sc = arg;
1161
1162 if (m != NULL)
1163 pool_cache_put(mb_cache, m);
1164
1165 sc->sc_tx_refcnt--;
1166 }
1167