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