1/* $NetBSD: btsco.c,v 1.34 2015/07/10 22:03:12 nat 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.34 2015/07/10 22:03:12 nat 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/kmem.h>
45#include <sys/mbuf.h>
46#include <sys/proc.h>
47#include <sys/socketvar.h>
48#include <sys/systm.h>
49#include <sys/intr.h>
50
51#include <prop/proplib.h>
52
53#include <netbt/bluetooth.h>
54#include <netbt/rfcomm.h>
55#include <netbt/sco.h>
56
57#include <dev/audio_if.h>
58#include <dev/auconv.h>
59#include <dev/mulaw.h>
60
61#include <dev/bluetooth/btdev.h>
62#include <dev/bluetooth/btsco.h>
63
64#undef DPRINTF
65#undef DPRINTFN
66
67#ifdef BTSCO_DEBUG
68int btsco_debug = BTSCO_DEBUG;
69#define DPRINTF(...) do { \
70 if (btsco_debug) { \
71 printf("%s: ", __func__); \
72 printf(__VA_ARGS__); \
73 } \
74} while (/* CONSTCOND */0)
75
76#define DPRINTFN(n, ...) do { \
77 if (btsco_debug > (n)) { \
78 printf("%s: ", __func__); \
79 printf(__VA_ARGS__); \
80 } \
81} while (/* CONSTCOND */0)
82#else
83#define DPRINTF(...)
84#define DPRINTFN(...)
85#endif
86
87/*****************************************************************************
88 *
89 * Bluetooth SCO Audio device
90 */
91
92/* btsco softc */
93struct btsco_softc {
94 uint16_t sc_flags;
95 const char *sc_name; /* our device_xname */
96
97 device_t sc_audio; /* MI audio device */
98 void *sc_intr; /* interrupt cookie */
99 kcondvar_t sc_connect; /* connect wait */
100 kmutex_t sc_intr_lock; /* for audio */
101
102 /* Bluetooth */
103 bdaddr_t sc_laddr; /* local address */
104 bdaddr_t sc_raddr; /* remote address */
105 uint16_t sc_state; /* link state */
106 struct sco_pcb *sc_sco; /* SCO handle */
107 struct sco_pcb *sc_sco_l; /* SCO listen handle */
108 uint16_t sc_mtu; /* SCO mtu */
109 uint8_t sc_channel; /* RFCOMM channel */
110 int sc_err; /* stored error */
111
112 /* Receive */
113 int sc_rx_want; /* bytes wanted */
114 uint8_t *sc_rx_block; /* receive block */
115 void (*sc_rx_intr)(void *); /* callback */
116 void *sc_rx_intrarg; /* callback arg */
117 struct mbuf *sc_rx_mbuf; /* leftover mbuf */
118
119 /* Transmit */
120 int sc_tx_size; /* bytes to send */
121 int sc_tx_pending; /* packets pending */
122 uint8_t *sc_tx_block; /* transmit block */
123 void (*sc_tx_intr)(void *); /* callback */
124 void *sc_tx_intrarg; /* callback arg */
125 void *sc_tx_buf; /* transmit buffer */
126 int sc_tx_refcnt; /* buffer refcnt */
127
128 /* mixer data */
129 int sc_vgs; /* speaker volume */
130 int sc_vgm; /* mic volume */
131};
132
133/* sc_state */
134#define BTSCO_CLOSED 0
135#define BTSCO_WAIT_CONNECT 1
136#define BTSCO_OPEN 2
137
138/* sc_flags */
139#define BTSCO_LISTEN (1 << 1)
140
141/* autoconf(9) glue */
142static int btsco_match(device_t, cfdata_t, void *);
143static void btsco_attach(device_t, device_t, void *);
144static int btsco_detach(device_t, int);
145
146CFATTACH_DECL_NEW(btsco, sizeof(struct btsco_softc),
147 btsco_match, btsco_attach, btsco_detach, NULL);
148
149/* audio(9) glue */
150static int btsco_open(void *, int);
151static void btsco_close(void *);
152static int btsco_query_encoding(void *, struct audio_encoding *);
153static int btsco_set_params(void *, int, int, audio_params_t *, audio_params_t *,
154 stream_filter_list_t *, stream_filter_list_t *);
155static int btsco_round_blocksize(void *, int, int, const audio_params_t *);
156static int btsco_start_output(void *, void *, int, void (*)(void *), void *);
157static int btsco_start_input(void *, void *, int, void (*)(void *), void *);
158static int btsco_halt_output(void *);
159static int btsco_halt_input(void *);
160static int btsco_getdev(void *, struct audio_device *);
161static int btsco_setfd(void *, int);
162static int btsco_set_port(void *, mixer_ctrl_t *);
163static int btsco_get_port(void *, mixer_ctrl_t *);
164static int btsco_query_devinfo(void *, mixer_devinfo_t *);
165static void *btsco_allocm(void *, int, size_t);
166static void btsco_freem(void *, void *, size_t);
167static int btsco_get_props(void *);
168static int btsco_dev_ioctl(void *, u_long, void *, int, struct lwp *);
169static void btsco_get_locks(void *, kmutex_t **, kmutex_t **);
170
171static const struct audio_hw_if btsco_if = {
172 btsco_open, /* open */
173 btsco_close, /* close */
174 NULL, /* drain */
175 btsco_query_encoding, /* query_encoding */
176 btsco_set_params, /* set_params */
177 btsco_round_blocksize, /* round_blocksize */
178 NULL, /* commit_settings */
179 NULL, /* init_output */
180 NULL, /* init_input */
181 btsco_start_output, /* start_output */
182 btsco_start_input, /* start_input */
183 btsco_halt_output, /* halt_output */
184 btsco_halt_input, /* halt_input */
185 NULL, /* speaker_ctl */
186 btsco_getdev, /* getdev */
187 btsco_setfd, /* setfd */
188 btsco_set_port, /* set_port */
189 btsco_get_port, /* get_port */
190 btsco_query_devinfo, /* query_devinfo */
191 btsco_allocm, /* allocm */
192 btsco_freem, /* freem */
193 NULL, /* round_buffersize */
194 NULL, /* mappage */
195 btsco_get_props, /* get_props */
196 NULL, /* trigger_output */
197 NULL, /* trigger_input */
198 btsco_dev_ioctl, /* dev_ioctl */
199 btsco_get_locks, /* get_locks */
200};
201
202static const struct audio_device btsco_device = {
203 "Bluetooth Audio",
204 "",
205 "btsco"
206};
207
208/* Voice_Setting == 0x0060: 8000Hz, mono, 16-bit, slinear_le */
209static const struct audio_format btsco_format = {
210 NULL, /* driver_data */
211 (AUMODE_PLAY | AUMODE_RECORD), /* mode */
212 AUDIO_ENCODING_SLINEAR_LE, /* encoding */
213 16, /* validbits */
214 16, /* precision */
215 1, /* channels */
216 AUFMT_MONAURAL, /* channel_mask */
217 1, /* frequency_type */
218 { 8000 } /* frequency */
219};
220
221/* bluetooth(9) glue for SCO */
222static void btsco_sco_connecting(void *);
223static void btsco_sco_connected(void *);
224static void btsco_sco_disconnected(void *, int);
225static void *btsco_sco_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *);
226static void btsco_sco_complete(void *, int);
227static void btsco_sco_linkmode(void *, int);
228static void btsco_sco_input(void *, struct mbuf *);
229
230static const struct btproto btsco_sco_proto = {
231 btsco_sco_connecting,
232 btsco_sco_connected,
233 btsco_sco_disconnected,
234 btsco_sco_newconn,
235 btsco_sco_complete,
236 btsco_sco_linkmode,
237 btsco_sco_input,
238};
239
240
241/*****************************************************************************
242 *
243 * btsco definitions
244 */
245
246/*
247 * btsco mixer class
248 */
249#define BTSCO_VGS 0
250#define BTSCO_VGM 1
251#define BTSCO_INPUT_CLASS 2
252#define BTSCO_OUTPUT_CLASS 3
253
254/* connect timeout */
255#define BTSCO_TIMEOUT (30 * hz)
256
257/* misc btsco functions */
258static void btsco_extfree(struct mbuf *, void *, size_t, void *);
259static void btsco_intr(void *);
260
261
262/*****************************************************************************
263 *
264 * btsco autoconf(9) routines
265 */
266
267static int
268btsco_match(device_t self, cfdata_t cfdata, void *aux)
269{
270 prop_dictionary_t dict = aux;
271 prop_object_t obj;
272
273 obj = prop_dictionary_get(dict, BTDEVservice);
274 if (prop_string_equals_cstring(obj, "HSET"))
275 return 1;
276
277 if (prop_string_equals_cstring(obj, "HF"))
278 return 1;
279
280 return 0;
281}
282
283static void
284btsco_attach(device_t parent, device_t self, void *aux)
285{
286 struct btsco_softc *sc = device_private(self);
287 prop_dictionary_t dict = aux;
288 prop_object_t obj;
289
290 /*
291 * Init softc
292 */
293 sc->sc_vgs = 200;
294 sc->sc_vgm = 200;
295 sc->sc_state = BTSCO_CLOSED;
296 sc->sc_name = device_xname(self);
297 cv_init(&sc->sc_connect, "connect");
298 mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_NONE);
299
300 /*
301 * copy in our configuration info
302 */
303 obj = prop_dictionary_get(dict, BTDEVladdr);
304 bdaddr_copy(&sc->sc_laddr, prop_data_data_nocopy(obj));
305
306 obj = prop_dictionary_get(dict, BTDEVraddr);
307 bdaddr_copy(&sc->sc_raddr, prop_data_data_nocopy(obj));
308
309 obj = prop_dictionary_get(dict, BTDEVservice);
310 if (prop_string_equals_cstring(obj, "HF")) {
311 sc->sc_flags |= BTSCO_LISTEN;
312 aprint_verbose(" listen mode");
313 }
314
315 obj = prop_dictionary_get(dict, BTSCOchannel);
316 if (prop_object_type(obj) != PROP_TYPE_NUMBER
317 || prop_number_integer_value(obj) < RFCOMM_CHANNEL_MIN
318 || prop_number_integer_value(obj) > RFCOMM_CHANNEL_MAX) {
319 aprint_error(" invalid %s", BTSCOchannel);
320 return;
321 }
322 sc->sc_channel = prop_number_integer_value(obj);
323
324 aprint_verbose(" channel %d", sc->sc_channel);
325 aprint_normal("\n");
326
327 DPRINTF("sc=%p\n", sc);
328
329 /*
330 * set up transmit interrupt
331 */
332 sc->sc_intr = softint_establish(SOFTINT_NET, btsco_intr, sc);
333 if (sc->sc_intr == NULL) {
334 aprint_error_dev(self, "softint_establish failed\n");
335 return;
336 }
337
338 /*
339 * attach audio device
340 */
341 sc->sc_audio = audio_attach_mi(&btsco_if, sc, self);
342 if (sc->sc_audio == NULL) {
343 aprint_error_dev(self, "audio_attach_mi failed\n");
344 return;
345 }
346
347 pmf_device_register(self, NULL, NULL);
348}
349
350static int
351btsco_detach(device_t self, int flags)
352{
353 struct btsco_softc *sc = device_private(self);
354
355 DPRINTF("sc=%p\n", sc);
356
357 pmf_device_deregister(self);
358
359 mutex_enter(bt_lock);
360 if (sc->sc_sco != NULL) {
361 DPRINTF("sc_sco=%p\n", sc->sc_sco);
362 sco_disconnect_pcb(sc->sc_sco, 0);
363 sco_detach_pcb(&sc->sc_sco);
364 sc->sc_sco = NULL;
365 }
366
367 if (sc->sc_sco_l != NULL) {
368 DPRINTF("sc_sco_l=%p\n", sc->sc_sco_l);
369 sco_detach_pcb(&sc->sc_sco_l);
370 sc->sc_sco_l = NULL;
371 }
372 mutex_exit(bt_lock);
373
374 if (sc->sc_audio != NULL) {
375 DPRINTF("sc_audio=%p\n", sc->sc_audio);
376 config_detach(sc->sc_audio, flags);
377 sc->sc_audio = NULL;
378 }
379
380 if (sc->sc_intr != NULL) {
381 softint_disestablish(sc->sc_intr);
382 sc->sc_intr = NULL;
383 }
384
385 if (sc->sc_rx_mbuf != NULL) {
386 m_freem(sc->sc_rx_mbuf);
387 sc->sc_rx_mbuf = NULL;
388 }
389
390 if (sc->sc_tx_refcnt > 0) {
391 aprint_error_dev(self, "tx_refcnt=%d!\n", sc->sc_tx_refcnt);
392
393 if ((flags & DETACH_FORCE) == 0)
394 return EAGAIN;
395 }
396
397 cv_destroy(&sc->sc_connect);
398 mutex_destroy(&sc->sc_intr_lock);
399
400 return 0;
401}
402
403/*****************************************************************************
404 *
405 * bluetooth(9) methods for SCO
406 *
407 * All these are called from Bluetooth Protocol code, in a soft
408 * interrupt context at IPL_SOFTNET.
409 */
410
411static void
412btsco_sco_connecting(void *arg)
413{
414/* struct btsco_softc *sc = arg; */
415
416 /* dont care */
417}
418
419static void
420btsco_sco_connected(void *arg)
421{
422 struct btsco_softc *sc = arg;
423
424 DPRINTF("%s\n", sc->sc_name);
425
426 KASSERT(sc->sc_sco != NULL);
427 KASSERT(sc->sc_state == BTSCO_WAIT_CONNECT);
428
429 /*
430 * If we are listening, no more need
431 */
432 if (sc->sc_sco_l != NULL)
433 sco_detach_pcb(&sc->sc_sco_l);
434
435 sc->sc_state = BTSCO_OPEN;
436 cv_broadcast(&sc->sc_connect);
437}
438
439static void
440btsco_sco_disconnected(void *arg, int err)
441{
442 struct btsco_softc *sc = arg;
443
444 DPRINTF("%s sc_state %d\n", sc->sc_name, sc->sc_state);
445
446 KASSERT(sc->sc_sco != NULL);
447
448 sc->sc_err = err;
449 sco_detach_pcb(&sc->sc_sco);
450
451 switch (sc->sc_state) {
452 case BTSCO_CLOSED: /* dont think this can happen */
453 break;
454
455 case BTSCO_WAIT_CONNECT: /* connect failed */
456 cv_broadcast(&sc->sc_connect);
457 break;
458
459 case BTSCO_OPEN: /* link lost */
460 /*
461 * If IO is in progress, tell the audio driver that it
462 * has completed so that when it tries to send more, we
463 * can indicate an error.
464 */
465 mutex_enter(&sc->sc_intr_lock);
466 if (sc->sc_tx_pending > 0) {
467 sc->sc_tx_pending = 0;
468 (*sc->sc_tx_intr)(sc->sc_tx_intrarg);
469 }
470 if (sc->sc_rx_want > 0) {
471 sc->sc_rx_want = 0;
472 (*sc->sc_rx_intr)(sc->sc_rx_intrarg);
473 }
474 mutex_exit(&sc->sc_intr_lock);
475 break;
476
477 default:
478 UNKNOWN(sc->sc_state);
479 }
480
481 sc->sc_state = BTSCO_CLOSED;
482}
483
484static void *
485btsco_sco_newconn(void *arg, struct sockaddr_bt *laddr,
486 struct sockaddr_bt *raddr)
487{
488 struct btsco_softc *sc = arg;
489
490 DPRINTF("%s\n", sc->sc_name);
491
492 if (bdaddr_same(&raddr->bt_bdaddr, &sc->sc_raddr) == 0
493 || sc->sc_state != BTSCO_WAIT_CONNECT
494 || sc->sc_sco != NULL)
495 return NULL;
496
497 sco_attach_pcb(&sc->sc_sco, &btsco_sco_proto, sc);
498 return sc->sc_sco;
499}
500
501static void
502btsco_sco_complete(void *arg, int count)
503{
504 struct btsco_softc *sc = arg;
505
506 DPRINTFN(10, "%s count %d\n", sc->sc_name, count);
507
508 mutex_enter(&sc->sc_intr_lock);
509 if (sc->sc_tx_pending > 0) {
510 sc->sc_tx_pending -= count;
511 if (sc->sc_tx_pending == 0)
512 (*sc->sc_tx_intr)(sc->sc_tx_intrarg);
513 }
514 mutex_exit(&sc->sc_intr_lock);
515}
516
517static void
518btsco_sco_linkmode(void *arg, int new)
519{
520/* struct btsco_softc *sc = arg; */
521
522 /* dont care */
523}
524
525static void
526btsco_sco_input(void *arg, struct mbuf *m)
527{
528 struct btsco_softc *sc = arg;
529 int len;
530
531 DPRINTFN(10, "%s len=%d\n", sc->sc_name, m->m_pkthdr.len);
532
533 mutex_enter(&sc->sc_intr_lock);
534 if (sc->sc_rx_want == 0) {
535 m_freem(m);
536 } else {
537 KASSERT(sc->sc_rx_intr != NULL);
538 KASSERT(sc->sc_rx_block != NULL);
539
540 len = MIN(sc->sc_rx_want, m->m_pkthdr.len);
541 m_copydata(m, 0, len, sc->sc_rx_block);
542
543 sc->sc_rx_want -= len;
544 sc->sc_rx_block += len;
545
546 if (len > m->m_pkthdr.len) {
547 if (sc->sc_rx_mbuf != NULL)
548 m_freem(sc->sc_rx_mbuf);
549
550 m_adj(m, len);
551 sc->sc_rx_mbuf = m;
552 } else {
553 m_freem(m);
554 }
555
556 if (sc->sc_rx_want == 0)
557 (*sc->sc_rx_intr)(sc->sc_rx_intrarg);
558 }
559 mutex_exit(&sc->sc_intr_lock);
560}
561
562
563/*****************************************************************************
564 *
565 * audio(9) methods
566 *
567 */
568
569static int
570btsco_open(void *hdl, int flags)
571{
572 struct sockaddr_bt sa;
573 struct btsco_softc *sc = hdl;
574 struct sockopt sopt;
575 int err, timo;
576
577 DPRINTF("%s flags 0x%x\n", sc->sc_name, flags);
578 /* flags FREAD & FWRITE? */
579
580 if (sc->sc_sco != NULL || sc->sc_sco_l != NULL)
581 return EIO;
582
583 KASSERT(mutex_owned(bt_lock));
584
585 memset(&sa, 0, sizeof(sa));
586 sa.bt_len = sizeof(sa);
587 sa.bt_family = AF_BLUETOOTH;
588 bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr);
589
590 if (sc->sc_flags & BTSCO_LISTEN) {
591 err = sco_attach_pcb(&sc->sc_sco_l, &btsco_sco_proto, sc);
592 if (err)
593 goto done;
594
595 err = sco_bind_pcb(sc->sc_sco_l, &sa);
596 if (err) {
597 sco_detach_pcb(&sc->sc_sco_l);
598 goto done;
599 }
600
601 err = sco_listen_pcb(sc->sc_sco_l);
602 if (err) {
603 sco_detach_pcb(&sc->sc_sco_l);
604 goto done;
605 }
606
607 timo = 0; /* no timeout */
608 } else {
609 err = sco_attach_pcb(&sc->sc_sco, &btsco_sco_proto, sc);
610 if (err)
611 goto done;
612
613 err = sco_bind_pcb(sc->sc_sco, &sa);
614 if (err) {
615 sco_detach_pcb(&sc->sc_sco);
616 goto done;
617 }
618
619 bdaddr_copy(&sa.bt_bdaddr, &sc->sc_raddr);
620 err = sco_connect_pcb(sc->sc_sco, &sa);
621 if (err) {
622 sco_detach_pcb(&sc->sc_sco);
623 goto done;
624 }
625
626 timo = BTSCO_TIMEOUT;
627 }
628
629 sc->sc_state = BTSCO_WAIT_CONNECT;
630 while (err == 0 && sc->sc_state == BTSCO_WAIT_CONNECT)
631 err = cv_timedwait_sig(&sc->sc_connect, bt_lock, timo);
632
633 switch (sc->sc_state) {
634 case BTSCO_CLOSED: /* disconnected */
635 err = sc->sc_err;
636
637 /* fall through to */
638 case BTSCO_WAIT_CONNECT: /* error */
639 if (sc->sc_sco != NULL)
640 sco_detach_pcb(&sc->sc_sco);
641
642 if (sc->sc_sco_l != NULL)
643 sco_detach_pcb(&sc->sc_sco_l);
644
645 break;
646
647 case BTSCO_OPEN: /* hurrah */
648 sockopt_init(&sopt, BTPROTO_SCO, SO_SCO_MTU, 0);
649 (void)sco_getopt(sc->sc_sco, &sopt);
650 (void)sockopt_get(&sopt, &sc->sc_mtu, sizeof(sc->sc_mtu));
651 sockopt_destroy(&sopt);
652 break;
653
654 default:
655 UNKNOWN(sc->sc_state);
656 break;
657 }
658
659done:
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
665static void
666btsco_close(void *hdl)
667{
668 struct btsco_softc *sc = hdl;
669
670 DPRINTF("%s\n", sc->sc_name);
671
672 KASSERT(mutex_owned(bt_lock));
673
674 if (sc->sc_sco != NULL) {
675 sco_disconnect_pcb(sc->sc_sco, 0);
676 sco_detach_pcb(&sc->sc_sco);
677 }
678
679 if (sc->sc_sco_l != NULL) {
680 sco_detach_pcb(&sc->sc_sco_l);
681 }
682
683 if (sc->sc_rx_mbuf != NULL) {
684 m_freem(sc->sc_rx_mbuf);
685 sc->sc_rx_mbuf = NULL;
686 }
687
688 sc->sc_rx_want = 0;
689 sc->sc_rx_block = NULL;
690 sc->sc_rx_intr = NULL;
691 sc->sc_rx_intrarg = NULL;
692
693 sc->sc_tx_size = 0;
694 sc->sc_tx_block = NULL;
695 sc->sc_tx_pending = 0;
696 sc->sc_tx_intr = NULL;
697 sc->sc_tx_intrarg = NULL;
698}
699
700static int
701btsco_query_encoding(void *hdl, struct audio_encoding *ae)
702{
703/* struct btsco_softc *sc = hdl; */
704 int err = 0;
705
706 switch (ae->index) {
707 case 0:
708 strcpy(ae->name, AudioEslinear_le);
709 ae->encoding = AUDIO_ENCODING_SLINEAR_LE;
710 ae->precision = 16;
711 ae->flags = 0;
712 break;
713
714 default:
715 err = EINVAL;
716 }
717
718 return err;
719}
720
721static int
722btsco_set_params(void *hdl, int setmode, int usemode,
723 audio_params_t *play, audio_params_t *rec,
724 stream_filter_list_t *pfil, stream_filter_list_t *rfil)
725{
726/* struct btsco_softc *sc = hdl; */
727 const struct audio_format *f;
728 int rv;
729
730 DPRINTF("setmode 0x%x usemode 0x%x\n", setmode, usemode);
731 DPRINTF("rate %d, precision %d, channels %d encoding %d\n",
732 play->sample_rate, play->precision, play->channels, play->encoding);
733
734 /*
735 * If we had a list of formats, we could check the HCI_Voice_Setting
736 * and select the appropriate one to use. Currently only one is
737 * supported: 0x0060 == 8000Hz, mono, 16-bit, slinear_le
738 */
739 f = &btsco_format;
740
741 if (setmode & AUMODE_PLAY) {
742 rv = auconv_set_converter(f, 1, AUMODE_PLAY, play, TRUE, pfil);
743 if (rv < 0)
744 return EINVAL;
745 }
746
747 if (setmode & AUMODE_RECORD) {
748 rv = auconv_set_converter(f, 1, AUMODE_RECORD, rec, TRUE, rfil);
749 if (rv < 0)
750 return EINVAL;
751 }
752
753 return 0;
754}
755
756/*
757 * If we have an MTU value to use, round the blocksize to that.
758 */
759static int
760btsco_round_blocksize(void *hdl, int bs, int mode,
761 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 sc->sc_name, 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 with sc_intr_lock held
781 * so make a note of what is to be sent, and schedule an interrupt to
782 * bundle it up and queue it.
783 */
784static int
785btsco_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", sc->sc_name, blksize);
791
792 if (sc->sc_sco == NULL)
793 return ENOTCONN; /* connection lost */
794
795 sc->sc_tx_block = block;
796 sc->sc_tx_pending = 0;
797 sc->sc_tx_size = blksize;
798 sc->sc_tx_intr = intr;
799 sc->sc_tx_intrarg = intrarg;
800
801 kpreempt_disable();
802 softint_schedule(sc->sc_intr);
803 kpreempt_enable();
804 return 0;
805}
806
807/*
808 * Start Input
809 *
810 * When the SCO link is up, we are getting data in any case, so all we do
811 * is note what we want and where to put it and let the sco_input routine
812 * fill in the data.
813 *
814 * If there was any leftover data that didnt fit in the last block, retry
815 * it now.
816 */
817static int
818btsco_start_input(void *hdl, void *block, int blksize,
819 void (*intr)(void *), void *intrarg)
820{
821 struct btsco_softc *sc = hdl;
822 struct mbuf *m;
823
824 DPRINTFN(5, "%s blksize %d\n", sc->sc_name, 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 */
850static int
851btsco_halt_output(void *hdl)
852{
853 struct btsco_softc *sc = hdl;
854
855 DPRINTFN(5, "%s\n", sc->sc_name);
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 */
873static int
874btsco_halt_input(void *hdl)
875{
876 struct btsco_softc *sc = hdl;
877
878 DPRINTFN(5, "%s\n", sc->sc_name);
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
893static int
894btsco_getdev(void *hdl, struct audio_device *ret)
895{
896
897 *ret = btsco_device;
898 return 0;
899}
900
901static int
902btsco_setfd(void *hdl, int fd)
903{
904 DPRINTF("set %s duplex\n", fd ? "full" : "half");
905
906 return 0;
907}
908
909static int
910btsco_set_port(void *hdl, mixer_ctrl_t *mc)
911{
912 struct btsco_softc *sc = hdl;
913 int err = 0;
914
915 DPRINTF("%s dev %d type %d\n", sc->sc_name, mc->dev, mc->type);
916
917 switch (mc->dev) {
918 case BTSCO_VGS:
919 if (mc->type != AUDIO_MIXER_VALUE ||
920 mc->un.value.num_channels != 1) {
921 err = EINVAL;
922 break;
923 }
924
925 sc->sc_vgs = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
926 break;
927
928 case BTSCO_VGM:
929 if (mc->type != AUDIO_MIXER_VALUE ||
930 mc->un.value.num_channels != 1) {
931 err = EINVAL;
932 break;
933 }
934
935 sc->sc_vgm = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
936 break;
937
938 default:
939 err = EINVAL;
940 break;
941 }
942
943 return err;
944}
945
946static int
947btsco_get_port(void *hdl, mixer_ctrl_t *mc)
948{
949 struct btsco_softc *sc = hdl;
950 int err = 0;
951
952 DPRINTF("%s dev %d\n", sc->sc_name, mc->dev);
953
954 switch (mc->dev) {
955 case BTSCO_VGS:
956 mc->type = AUDIO_MIXER_VALUE;
957 mc->un.value.num_channels = 1;
958 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_vgs;
959 break;
960
961 case BTSCO_VGM:
962 mc->type = AUDIO_MIXER_VALUE;
963 mc->un.value.num_channels = 1;
964 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_vgm;
965 break;
966
967 default:
968 err = EINVAL;
969 break;
970 }
971
972 return err;
973}
974
975static int
976btsco_query_devinfo(void *hdl, mixer_devinfo_t *di)
977{
978/* struct btsco_softc *sc = hdl; */
979 int err = 0;
980
981 switch(di->index) {
982 case BTSCO_VGS:
983 di->mixer_class = BTSCO_INPUT_CLASS;
984 di->next = di->prev = AUDIO_MIXER_LAST;
985 strcpy(di->label.name, AudioNspeaker);
986 di->type = AUDIO_MIXER_VALUE;
987 strcpy(di->un.v.units.name, AudioNvolume);
988 di->un.v.num_channels = 1;
989 di->un.v.delta = BTSCO_DELTA;
990 break;
991
992 case BTSCO_VGM:
993 di->mixer_class = BTSCO_INPUT_CLASS;
994 di->next = di->prev = AUDIO_MIXER_LAST;
995 strcpy(di->label.name, AudioNmicrophone);
996 di->type = AUDIO_MIXER_VALUE;
997 strcpy(di->un.v.units.name, AudioNvolume);
998 di->un.v.num_channels = 1;
999 di->un.v.delta = BTSCO_DELTA;
1000 break;
1001
1002 case BTSCO_INPUT_CLASS:
1003 di->mixer_class = BTSCO_INPUT_CLASS;
1004 di->next = di->prev = AUDIO_MIXER_LAST;
1005 strcpy(di->label.name, AudioCinputs);
1006 di->type = AUDIO_MIXER_CLASS;
1007 break;
1008
1009 default:
1010 err = ENXIO;
1011 break;
1012 }
1013
1014 return err;
1015}
1016
1017/*
1018 * Allocate Ring Buffers.
1019 */
1020static void *
1021btsco_allocm(void *hdl, int direction, size_t size)
1022{
1023 struct btsco_softc *sc = hdl;
1024 void *addr;
1025
1026 DPRINTF("%s: size %d direction %d\n", sc->sc_name, size, direction);
1027
1028 addr = kmem_alloc(size, KM_SLEEP);
1029
1030 if (addr != NULL && direction == AUMODE_PLAY) {
1031 sc->sc_tx_buf = addr;
1032 sc->sc_tx_refcnt = 0;
1033 }
1034
1035 return addr;
1036}
1037
1038/*
1039 * Free Ring Buffers.
1040 *
1041 * Because we used external memory for the tx mbufs, we dont
1042 * want to free the memory until all the mbufs are done with
1043 *
1044 * Just to be sure, dont free if something is still pending.
1045 * This would be a memory leak but at least there is a warning..
1046 */
1047static void
1048btsco_freem(void *hdl, void *addr, size_t size)
1049{
1050 struct btsco_softc *sc = hdl;
1051 int count = hz / 2;
1052
1053 if (addr == sc->sc_tx_buf) {
1054 DPRINTF("%s: tx_refcnt=%d\n", sc->sc_name, sc->sc_tx_refcnt);
1055
1056 sc->sc_tx_buf = NULL;
1057
1058 while (sc->sc_tx_refcnt> 0 && count-- > 0)
1059 kpause("drain", false, 1, NULL);
1060
1061 if (sc->sc_tx_refcnt > 0) {
1062 aprint_error("%s: ring buffer unreleased!\n", sc->sc_name);
1063 return;
1064 }
1065 }
1066
1067 kmem_free(addr, size);
1068}
1069
1070static int
1071btsco_get_props(void *hdl)
1072{
1073
1074 return AUDIO_PROP_FULLDUPLEX;
1075}
1076
1077static void
1078btsco_get_locks(void *hdl, kmutex_t **intr, kmutex_t **thread)
1079{
1080 struct btsco_softc *sc = hdl;
1081
1082 *intr = &sc->sc_intr_lock;
1083 *thread = bt_lock;
1084}
1085
1086/*
1087 * Handle private ioctl. We pass information out about how to talk
1088 * to the device and mixer.
1089 */
1090static int
1091btsco_dev_ioctl(void *hdl, u_long cmd, void *addr, int flag,
1092 struct lwp *l)
1093{
1094 struct btsco_softc *sc = hdl;
1095 struct btsco_info *bi = (struct btsco_info *)addr;
1096 int err = 0;
1097
1098 DPRINTF("%s cmd 0x%lx flag %d\n", sc->sc_name, cmd, flag);
1099
1100 switch (cmd) {
1101 case BTSCO_GETINFO:
1102 memset(bi, 0, sizeof(*bi));
1103 bdaddr_copy(&bi->laddr, &sc->sc_laddr);
1104 bdaddr_copy(&bi->raddr, &sc->sc_raddr);
1105 bi->channel = sc->sc_channel;
1106 bi->vgs = BTSCO_VGS;
1107 bi->vgm = BTSCO_VGM;
1108 break;
1109
1110 default:
1111 err = EPASSTHROUGH;
1112 break;
1113 }
1114
1115 return err;
1116}
1117
1118
1119/*****************************************************************************
1120 *
1121 * misc btsco functions
1122 *
1123 */
1124
1125/*
1126 * Our transmit interrupt. This is triggered when a new block is to be
1127 * sent. We send mtu sized chunks of the block as mbufs with external
1128 * storage to sco_send_pcb()
1129 */
1130static void
1131btsco_intr(void *arg)
1132{
1133 struct btsco_softc *sc = arg;
1134 struct mbuf *m;
1135 uint8_t *block;
1136 int mlen, size;
1137
1138 DPRINTFN(10, "%s block %p size %d\n",
1139 sc->sc_name, sc->sc_tx_block, sc->sc_tx_size);
1140
1141 if (sc->sc_sco == NULL)
1142 return; /* connection is lost */
1143
1144 block = sc->sc_tx_block;
1145 size = sc->sc_tx_size;
1146 sc->sc_tx_block = NULL;
1147 sc->sc_tx_size = 0;
1148
1149 mutex_enter(bt_lock);
1150 while (size > 0) {
1151 MGETHDR(m, M_DONTWAIT, MT_DATA);
1152 if (m == NULL)
1153 break;
1154
1155 mlen = MIN(sc->sc_mtu, size);
1156
1157 /* I think M_DEVBUF is true but not relevant */
1158 MEXTADD(m, block, mlen, M_DEVBUF, btsco_extfree, sc);
1159 if ((m->m_flags & M_EXT) == 0) {
1160 m_free(m);
1161 break;
1162 }
1163 sc->sc_tx_refcnt++;
1164
1165 m->m_pkthdr.len = m->m_len = mlen;
1166 sc->sc_tx_pending++;
1167
1168 if (sco_send_pcb(sc->sc_sco, m) > 0) {
1169 sc->sc_tx_pending--;
1170 break;
1171 }
1172
1173 block += mlen;
1174 size -= mlen;
1175 }
1176 mutex_exit(bt_lock);
1177}
1178
1179/*
1180 * Release the mbuf, we keep a reference count on the tx buffer so
1181 * that we dont release it before its free.
1182 */
1183static void
1184btsco_extfree(struct mbuf *m, void *addr, size_t size,
1185 void *arg)
1186{
1187 struct btsco_softc *sc = arg;
1188
1189 if (m != NULL)
1190 pool_cache_put(mb_cache, m);
1191
1192 sc->sc_tx_refcnt--;
1193}
1194