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