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