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