btsco.c revision 1.38.2.2 1 /* $NetBSD: btsco.c,v 1.38.2.2 2019/04/24 13:30:34 isaki 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.38.2.2 2019/04/24 13:30:34 isaki 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
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(...) do { \
68 if (btsco_debug) { \
69 printf("%s: ", __func__); \
70 printf(__VA_ARGS__); \
71 } \
72 } while (/* CONSTCOND */0)
73
74 #define DPRINTFN(n, ...) do { \
75 if (btsco_debug > (n)) { \
76 printf("%s: ", __func__); \
77 printf(__VA_ARGS__); \
78 } \
79 } while (/* CONSTCOND */0)
80 #else
81 #define DPRINTF(...)
82 #define DPRINTFN(...)
83 #endif
84
85 /*****************************************************************************
86 *
87 * Bluetooth SCO Audio device
88 */
89
90 /* btsco softc */
91 struct btsco_softc {
92 uint16_t sc_flags;
93 const char *sc_name; /* our device_xname */
94
95 device_t sc_audio; /* MI audio device */
96 void *sc_intr; /* interrupt cookie */
97 kcondvar_t sc_connect; /* connect wait */
98 kmutex_t sc_lock; /* for audio */
99
100 /* Bluetooth */
101 bdaddr_t sc_laddr; /* local address */
102 bdaddr_t sc_raddr; /* remote address */
103 uint16_t sc_state; /* link state */
104 struct sco_pcb *sc_sco; /* SCO handle */
105 struct sco_pcb *sc_sco_l; /* SCO listen handle */
106 uint16_t sc_mtu; /* SCO mtu */
107 uint8_t sc_channel; /* RFCOMM channel */
108 int sc_err; /* stored error */
109
110 /* Receive */
111 int sc_rx_want; /* bytes wanted */
112 uint8_t *sc_rx_block; /* receive block */
113 void (*sc_rx_intr)(void *); /* callback */
114 void *sc_rx_intrarg; /* callback arg */
115 struct mbuf *sc_rx_mbuf; /* leftover mbuf */
116
117 /* Transmit */
118 int sc_tx_size; /* bytes to send */
119 int sc_tx_pending; /* packets pending */
120 uint8_t *sc_tx_block; /* transmit block */
121 void (*sc_tx_intr)(void *); /* callback */
122 void *sc_tx_intrarg; /* callback arg */
123 void *sc_tx_buf; /* transmit buffer */
124 int sc_tx_refcnt; /* buffer refcnt */
125
126 /* mixer data */
127 int sc_vgs; /* speaker volume */
128 int sc_vgm; /* mic volume */
129 };
130
131 /* sc_state */
132 #define BTSCO_CLOSED 0
133 #define BTSCO_WAIT_CONNECT 1
134 #define BTSCO_OPEN 2
135
136 /* sc_flags */
137 #define BTSCO_LISTEN (1 << 1)
138
139 /* autoconf(9) glue */
140 static int btsco_match(device_t, cfdata_t, void *);
141 static void btsco_attach(device_t, device_t, void *);
142 static int btsco_detach(device_t, int);
143
144 CFATTACH_DECL_NEW(btsco, sizeof(struct btsco_softc),
145 btsco_match, btsco_attach, btsco_detach, NULL);
146
147 /* audio(9) glue */
148 static int btsco_open(void *, int);
149 static void btsco_close(void *);
150 static int btsco_query_format(void *, audio_format_query_t *);
151 static int btsco_set_format(void *, int,
152 const audio_params_t *, const audio_params_t *,
153 audio_filter_reg_t *, audio_filter_reg_t *);
154 static int btsco_round_blocksize(void *, int, int, const audio_params_t *);
155 static int btsco_start_output(void *, void *, int, void (*)(void *), void *);
156 static int btsco_start_input(void *, void *, int, void (*)(void *), void *);
157 static int btsco_halt_output(void *);
158 static int btsco_halt_input(void *);
159 static int btsco_getdev(void *, struct audio_device *);
160 static int btsco_setfd(void *, int);
161 static int btsco_set_port(void *, mixer_ctrl_t *);
162 static int btsco_get_port(void *, mixer_ctrl_t *);
163 static int btsco_query_devinfo(void *, mixer_devinfo_t *);
164 static void *btsco_allocm(void *, int, size_t);
165 static void btsco_freem(void *, void *, size_t);
166 static int btsco_get_props(void *);
167 static int btsco_dev_ioctl(void *, u_long, void *, int, struct lwp *);
168 static void btsco_get_locks(void *, kmutex_t **, kmutex_t **);
169
170 static const struct audio_hw_if btsco_if = {
171 .open = btsco_open,
172 .close = btsco_close,
173 .query_format = btsco_query_format,
174 .set_format = btsco_set_format,
175 .round_blocksize = btsco_round_blocksize,
176 .start_output = btsco_start_output,
177 .start_input = btsco_start_input,
178 .halt_output = btsco_halt_output,
179 .halt_input = btsco_halt_input,
180 .getdev = btsco_getdev,
181 .setfd = btsco_setfd,
182 .set_port = btsco_set_port,
183 .get_port = btsco_get_port,
184 .query_devinfo = btsco_query_devinfo,
185 .allocm = btsco_allocm,
186 .freem = btsco_freem,
187 .get_props = btsco_get_props,
188 .dev_ioctl = btsco_dev_ioctl,
189 .get_locks = btsco_get_locks,
190 };
191
192 static const struct audio_device btsco_device = {
193 "Bluetooth Audio",
194 "",
195 "btsco"
196 };
197
198 /* Voice_Setting == 0x0060: 8000Hz, mono, 16-bit, slinear_le */
199 static const struct audio_format btsco_format = {
200 .mode = AUMODE_PLAY | AUMODE_RECORD,
201 .encoding = AUDIO_ENCODING_SLINEAR_LE,
202 .validbits = 16,
203 .precision = 16,
204 .channels = 1,
205 .channel_mask = AUFMT_MONAURAL,
206 .frequency_type = 1,
207 .frequency = { 8000 },
208 };
209
210 /* bluetooth(9) glue for SCO */
211 static void btsco_sco_connecting(void *);
212 static void btsco_sco_connected(void *);
213 static void btsco_sco_disconnected(void *, int);
214 static void *btsco_sco_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *);
215 static void btsco_sco_complete(void *, int);
216 static void btsco_sco_linkmode(void *, int);
217 static void btsco_sco_input(void *, struct mbuf *);
218
219 static const struct btproto btsco_sco_proto = {
220 btsco_sco_connecting,
221 btsco_sco_connected,
222 btsco_sco_disconnected,
223 btsco_sco_newconn,
224 btsco_sco_complete,
225 btsco_sco_linkmode,
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 *, void *, 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(device_t self, cfdata_t 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(device_t parent, device_t self, void *aux)
274 {
275 struct btsco_softc *sc = device_private(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 sc->sc_name = device_xname(self);
286 cv_init(&sc->sc_connect, "connect");
287 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
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 = softint_establish(SOFTINT_NET, btsco_intr, sc);
322 if (sc->sc_intr == NULL) {
323 aprint_error_dev(self, "softint_establish failed\n");
324 return;
325 }
326
327 /*
328 * attach audio device
329 */
330 sc->sc_audio = audio_attach_mi(&btsco_if, sc, self);
331 if (sc->sc_audio == NULL) {
332 aprint_error_dev(self, "audio_attach_mi failed\n");
333 return;
334 }
335
336 pmf_device_register(self, NULL, NULL);
337 }
338
339 static int
340 btsco_detach(device_t self, int flags)
341 {
342 struct btsco_softc *sc = device_private(self);
343
344 DPRINTF("sc=%p\n", sc);
345
346 pmf_device_deregister(self);
347
348 mutex_enter(bt_lock);
349 if (sc->sc_sco != NULL) {
350 DPRINTF("sc_sco=%p\n", sc->sc_sco);
351 sco_disconnect_pcb(sc->sc_sco, 0);
352 sco_detach_pcb(&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_pcb(&sc->sc_sco_l);
359 sc->sc_sco_l = NULL;
360 }
361 mutex_exit(bt_lock);
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 mutex_enter(bt_lock);
375 if (sc->sc_rx_mbuf != NULL) {
376 m_freem(sc->sc_rx_mbuf);
377 sc->sc_rx_mbuf = NULL;
378 }
379 mutex_exit(bt_lock);
380
381 if (sc->sc_tx_refcnt > 0) {
382 aprint_error_dev(self, "tx_refcnt=%d!\n", sc->sc_tx_refcnt);
383
384 if ((flags & DETACH_FORCE) == 0)
385 return EAGAIN;
386 }
387
388 cv_destroy(&sc->sc_connect);
389 mutex_destroy(&sc->sc_lock);
390
391 return 0;
392 }
393
394 /*****************************************************************************
395 *
396 * bluetooth(9) methods for SCO
397 *
398 * All these are called from Bluetooth Protocol code, in a soft
399 * interrupt context at IPL_SOFTNET.
400 */
401
402 static void
403 btsco_sco_connecting(void *arg)
404 {
405 /* struct btsco_softc *sc = arg; */
406
407 /* dont care */
408 }
409
410 static void
411 btsco_sco_connected(void *arg)
412 {
413 struct btsco_softc *sc = arg;
414
415 DPRINTF("%s\n", sc->sc_name);
416
417 KASSERT(sc->sc_sco != NULL);
418 KASSERT(sc->sc_state == BTSCO_WAIT_CONNECT);
419
420 /*
421 * If we are listening, no more need
422 */
423 if (sc->sc_sco_l != NULL)
424 sco_detach_pcb(&sc->sc_sco_l);
425
426 sc->sc_state = BTSCO_OPEN;
427 cv_broadcast(&sc->sc_connect);
428 }
429
430 static void
431 btsco_sco_disconnected(void *arg, int err)
432 {
433 struct btsco_softc *sc = arg;
434
435 DPRINTF("%s sc_state %d\n", sc->sc_name, sc->sc_state);
436
437 KASSERT(sc->sc_sco != NULL);
438
439 sc->sc_err = err;
440 sco_detach_pcb(&sc->sc_sco);
441
442 switch (sc->sc_state) {
443 case BTSCO_CLOSED: /* dont think this can happen */
444 break;
445
446 case BTSCO_WAIT_CONNECT: /* connect failed */
447 cv_broadcast(&sc->sc_connect);
448 break;
449
450 case BTSCO_OPEN: /* link lost */
451 /*
452 * If IO is in progress, tell the audio driver that it
453 * has completed so that when it tries to send more, we
454 * can indicate an error.
455 */
456 mutex_enter(bt_lock);
457 if (sc->sc_tx_pending > 0) {
458 sc->sc_tx_pending = 0;
459 (*sc->sc_tx_intr)(sc->sc_tx_intrarg);
460 }
461 if (sc->sc_rx_want > 0) {
462 sc->sc_rx_want = 0;
463 (*sc->sc_rx_intr)(sc->sc_rx_intrarg);
464 }
465 mutex_exit(bt_lock);
466 break;
467
468 default:
469 UNKNOWN(sc->sc_state);
470 }
471
472 sc->sc_state = BTSCO_CLOSED;
473 }
474
475 static void *
476 btsco_sco_newconn(void *arg, struct sockaddr_bt *laddr,
477 struct sockaddr_bt *raddr)
478 {
479 struct btsco_softc *sc = arg;
480
481 DPRINTF("%s\n", sc->sc_name);
482
483 if (bdaddr_same(&raddr->bt_bdaddr, &sc->sc_raddr) == 0
484 || sc->sc_state != BTSCO_WAIT_CONNECT
485 || sc->sc_sco != NULL)
486 return NULL;
487
488 sco_attach_pcb(&sc->sc_sco, &btsco_sco_proto, sc);
489 return sc->sc_sco;
490 }
491
492 static void
493 btsco_sco_complete(void *arg, int count)
494 {
495 struct btsco_softc *sc = arg;
496
497 DPRINTFN(10, "%s count %d\n", sc->sc_name, count);
498
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 }
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;
519
520 DPRINTFN(10, "%s len=%d\n", sc->sc_name, m->m_pkthdr.len);
521
522 if (sc->sc_rx_want == 0) {
523 m_freem(m);
524 } else {
525 KASSERT(sc->sc_rx_intr != NULL);
526 KASSERT(sc->sc_rx_block != NULL);
527
528 len = MIN(sc->sc_rx_want, m->m_pkthdr.len);
529 m_copydata(m, 0, len, sc->sc_rx_block);
530
531 sc->sc_rx_want -= len;
532 sc->sc_rx_block += len;
533
534 if (len > m->m_pkthdr.len) {
535 if (sc->sc_rx_mbuf != NULL)
536 m_freem(sc->sc_rx_mbuf);
537
538 m_adj(m, len);
539 sc->sc_rx_mbuf = m;
540 } else {
541 m_freem(m);
542 }
543
544 if (sc->sc_rx_want == 0)
545 (*sc->sc_rx_intr)(sc->sc_rx_intrarg);
546 }
547 }
548
549
550 /*****************************************************************************
551 *
552 * audio(9) methods
553 *
554 */
555
556 static int
557 btsco_open(void *hdl, int flags)
558 {
559 struct sockaddr_bt sa;
560 struct btsco_softc *sc = hdl;
561 struct sockopt sopt;
562 int err, timo;
563
564 DPRINTF("%s flags 0x%x\n", sc->sc_name, flags);
565 /* flags FREAD & FWRITE? */
566
567 if (sc->sc_sco != NULL || sc->sc_sco_l != NULL)
568 return EIO;
569
570 KASSERT(mutex_owned(bt_lock));
571
572 memset(&sa, 0, sizeof(sa));
573 sa.bt_len = sizeof(sa);
574 sa.bt_family = AF_BLUETOOTH;
575 bdaddr_copy(&sa.bt_bdaddr, &sc->sc_laddr);
576
577 if (sc->sc_flags & BTSCO_LISTEN) {
578 err = sco_attach_pcb(&sc->sc_sco_l, &btsco_sco_proto, sc);
579 if (err)
580 goto done;
581
582 err = sco_bind_pcb(sc->sc_sco_l, &sa);
583 if (err) {
584 sco_detach_pcb(&sc->sc_sco_l);
585 goto done;
586 }
587
588 err = sco_listen_pcb(sc->sc_sco_l);
589 if (err) {
590 sco_detach_pcb(&sc->sc_sco_l);
591 goto done;
592 }
593
594 timo = 0; /* no timeout */
595 } else {
596 err = sco_attach_pcb(&sc->sc_sco, &btsco_sco_proto, sc);
597 if (err)
598 goto done;
599
600 err = sco_bind_pcb(sc->sc_sco, &sa);
601 if (err) {
602 sco_detach_pcb(&sc->sc_sco);
603 goto done;
604 }
605
606 bdaddr_copy(&sa.bt_bdaddr, &sc->sc_raddr);
607 err = sco_connect_pcb(sc->sc_sco, &sa);
608 if (err) {
609 sco_detach_pcb(&sc->sc_sco);
610 goto done;
611 }
612
613 timo = BTSCO_TIMEOUT;
614 }
615
616 sc->sc_state = BTSCO_WAIT_CONNECT;
617 while (err == 0 && sc->sc_state == BTSCO_WAIT_CONNECT)
618 err = cv_timedwait_sig(&sc->sc_connect, bt_lock, timo);
619
620 switch (sc->sc_state) {
621 case BTSCO_CLOSED: /* disconnected */
622 err = sc->sc_err;
623
624 /* FALLTHROUGH */
625 case BTSCO_WAIT_CONNECT: /* error */
626 if (sc->sc_sco != NULL)
627 sco_detach_pcb(&sc->sc_sco);
628
629 if (sc->sc_sco_l != NULL)
630 sco_detach_pcb(&sc->sc_sco_l);
631
632 break;
633
634 case BTSCO_OPEN: /* hurrah */
635 sockopt_init(&sopt, BTPROTO_SCO, SO_SCO_MTU, 0);
636 (void)sco_getopt(sc->sc_sco, &sopt);
637 (void)sockopt_get(&sopt, &sc->sc_mtu, sizeof(sc->sc_mtu));
638 sockopt_destroy(&sopt);
639 break;
640
641 default:
642 UNKNOWN(sc->sc_state);
643 break;
644 }
645
646 done:
647 DPRINTF("done err=%d, sc_state=%d, sc_mtu=%d\n",
648 err, sc->sc_state, sc->sc_mtu);
649 return err;
650 }
651
652 static void
653 btsco_close(void *hdl)
654 {
655 struct btsco_softc *sc = hdl;
656
657 DPRINTF("%s\n", sc->sc_name);
658
659 KASSERT(mutex_owned(bt_lock));
660
661 if (sc->sc_sco != NULL) {
662 sco_disconnect_pcb(sc->sc_sco, 0);
663 sco_detach_pcb(&sc->sc_sco);
664 }
665
666 if (sc->sc_sco_l != NULL) {
667 sco_detach_pcb(&sc->sc_sco_l);
668 }
669
670 if (sc->sc_rx_mbuf != NULL) {
671 m_freem(sc->sc_rx_mbuf);
672 sc->sc_rx_mbuf = NULL;
673 }
674
675 sc->sc_rx_want = 0;
676 sc->sc_rx_block = NULL;
677 sc->sc_rx_intr = NULL;
678 sc->sc_rx_intrarg = NULL;
679
680 sc->sc_tx_size = 0;
681 sc->sc_tx_block = NULL;
682 sc->sc_tx_pending = 0;
683 sc->sc_tx_intr = NULL;
684 sc->sc_tx_intrarg = NULL;
685 }
686
687 static int
688 btsco_query_format(void *hdl, audio_format_query_t *afp)
689 {
690
691 return audio_query_format(&btsco_format, 1, afp);
692 }
693
694 static int
695 btsco_set_format(void *hdl, int setmode,
696 const audio_params_t *play, const audio_params_t *rec,
697 audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
698 {
699
700 /* We have only one format so nothing to do here. */
701 return 0;
702 }
703
704 /*
705 * If we have an MTU value to use, round the blocksize to that.
706 */
707 static int
708 btsco_round_blocksize(void *hdl, int bs, int mode,
709 const audio_params_t *param)
710 {
711 struct btsco_softc *sc = hdl;
712
713 if (sc->sc_mtu > 0) {
714 bs = (bs / sc->sc_mtu) * sc->sc_mtu;
715 if (bs == 0)
716 bs = sc->sc_mtu;
717 }
718
719 DPRINTF("%s mode=0x%x, bs=%d, sc_mtu=%d\n",
720 sc->sc_name, mode, bs, sc->sc_mtu);
721
722 return bs;
723 }
724
725 /*
726 * Start Output
727 *
728 * We dont want to be calling the network stack with bt_lock held
729 * so make a note of what is to be sent, and schedule an interrupt to
730 * bundle it up and queue it.
731 */
732 static int
733 btsco_start_output(void *hdl, void *block, int blksize,
734 void (*intr)(void *), void *intrarg)
735 {
736 struct btsco_softc *sc = hdl;
737
738 DPRINTFN(5, "%s blksize %d\n", sc->sc_name, blksize);
739
740 if (sc->sc_sco == NULL)
741 return ENOTCONN; /* connection lost */
742
743 sc->sc_tx_block = block;
744 sc->sc_tx_pending = 0;
745 sc->sc_tx_size = blksize;
746 sc->sc_tx_intr = intr;
747 sc->sc_tx_intrarg = intrarg;
748
749 kpreempt_disable();
750 softint_schedule(sc->sc_intr);
751 kpreempt_enable();
752 return 0;
753 }
754
755 /*
756 * Start Input
757 *
758 * When the SCO link is up, we are getting data in any case, so all we do
759 * is note what we want and where to put it and let the sco_input routine
760 * fill in the data.
761 *
762 * If there was any leftover data that didnt fit in the last block, retry
763 * it now.
764 */
765 static int
766 btsco_start_input(void *hdl, void *block, int blksize,
767 void (*intr)(void *), void *intrarg)
768 {
769 struct btsco_softc *sc = hdl;
770 struct mbuf *m;
771
772 DPRINTFN(5, "%s blksize %d\n", sc->sc_name, blksize);
773
774 if (sc->sc_sco == NULL)
775 return ENOTCONN;
776
777 sc->sc_rx_want = blksize;
778 sc->sc_rx_block = block;
779 sc->sc_rx_intr = intr;
780 sc->sc_rx_intrarg = intrarg;
781
782 if (sc->sc_rx_mbuf != NULL) {
783 m = sc->sc_rx_mbuf;
784 sc->sc_rx_mbuf = NULL;
785 btsco_sco_input(sc, m);
786 }
787
788 return 0;
789 }
790
791 /*
792 * Halt Output
793 *
794 * This doesnt really halt the output, but it will look
795 * that way to the audio driver. The current block will
796 * still be transmitted.
797 */
798 static int
799 btsco_halt_output(void *hdl)
800 {
801 struct btsco_softc *sc = hdl;
802
803 DPRINTFN(5, "%s\n", sc->sc_name);
804
805 sc->sc_tx_size = 0;
806 sc->sc_tx_block = NULL;
807 sc->sc_tx_pending = 0;
808 sc->sc_tx_intr = NULL;
809 sc->sc_tx_intrarg = NULL;
810
811 return 0;
812 }
813
814 /*
815 * Halt Input
816 *
817 * This doesnt really halt the input, but it will look
818 * that way to the audio driver. Incoming data will be
819 * discarded.
820 */
821 static int
822 btsco_halt_input(void *hdl)
823 {
824 struct btsco_softc *sc = hdl;
825
826 DPRINTFN(5, "%s\n", sc->sc_name);
827
828 sc->sc_rx_want = 0;
829 sc->sc_rx_block = NULL;
830 sc->sc_rx_intr = NULL;
831 sc->sc_rx_intrarg = NULL;
832
833 if (sc->sc_rx_mbuf != NULL) {
834 m_freem(sc->sc_rx_mbuf);
835 sc->sc_rx_mbuf = NULL;
836 }
837
838 return 0;
839 }
840
841 static int
842 btsco_getdev(void *hdl, struct audio_device *ret)
843 {
844
845 *ret = btsco_device;
846 return 0;
847 }
848
849 static int
850 btsco_setfd(void *hdl, int fd)
851 {
852 DPRINTF("set %s duplex\n", fd ? "full" : "half");
853
854 return 0;
855 }
856
857 static int
858 btsco_set_port(void *hdl, mixer_ctrl_t *mc)
859 {
860 struct btsco_softc *sc = hdl;
861 int err = 0;
862
863 DPRINTF("%s dev %d type %d\n", sc->sc_name, mc->dev, mc->type);
864
865 switch (mc->dev) {
866 case BTSCO_VGS:
867 if (mc->type != AUDIO_MIXER_VALUE ||
868 mc->un.value.num_channels != 1) {
869 err = EINVAL;
870 break;
871 }
872
873 sc->sc_vgs = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
874 break;
875
876 case BTSCO_VGM:
877 if (mc->type != AUDIO_MIXER_VALUE ||
878 mc->un.value.num_channels != 1) {
879 err = EINVAL;
880 break;
881 }
882
883 sc->sc_vgm = mc->un.value.level[AUDIO_MIXER_LEVEL_MONO];
884 break;
885
886 default:
887 err = EINVAL;
888 break;
889 }
890
891 return err;
892 }
893
894 static int
895 btsco_get_port(void *hdl, mixer_ctrl_t *mc)
896 {
897 struct btsco_softc *sc = hdl;
898 int err = 0;
899
900 DPRINTF("%s dev %d\n", sc->sc_name, mc->dev);
901
902 switch (mc->dev) {
903 case BTSCO_VGS:
904 mc->type = AUDIO_MIXER_VALUE;
905 mc->un.value.num_channels = 1;
906 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_vgs;
907 break;
908
909 case BTSCO_VGM:
910 mc->type = AUDIO_MIXER_VALUE;
911 mc->un.value.num_channels = 1;
912 mc->un.value.level[AUDIO_MIXER_LEVEL_MONO] = sc->sc_vgm;
913 break;
914
915 default:
916 err = EINVAL;
917 break;
918 }
919
920 return err;
921 }
922
923 static int
924 btsco_query_devinfo(void *hdl, mixer_devinfo_t *di)
925 {
926 /* struct btsco_softc *sc = hdl; */
927 int err = 0;
928
929 switch(di->index) {
930 case BTSCO_VGS:
931 di->mixer_class = BTSCO_INPUT_CLASS;
932 di->next = di->prev = AUDIO_MIXER_LAST;
933 strcpy(di->label.name, AudioNspeaker);
934 di->type = AUDIO_MIXER_VALUE;
935 strcpy(di->un.v.units.name, AudioNvolume);
936 di->un.v.num_channels = 1;
937 di->un.v.delta = BTSCO_DELTA;
938 break;
939
940 case BTSCO_VGM:
941 di->mixer_class = BTSCO_INPUT_CLASS;
942 di->next = di->prev = AUDIO_MIXER_LAST;
943 strcpy(di->label.name, AudioNmicrophone);
944 di->type = AUDIO_MIXER_VALUE;
945 strcpy(di->un.v.units.name, AudioNvolume);
946 di->un.v.num_channels = 1;
947 di->un.v.delta = BTSCO_DELTA;
948 break;
949
950 case BTSCO_INPUT_CLASS:
951 di->mixer_class = BTSCO_INPUT_CLASS;
952 di->next = di->prev = AUDIO_MIXER_LAST;
953 strcpy(di->label.name, AudioCinputs);
954 di->type = AUDIO_MIXER_CLASS;
955 break;
956
957 default:
958 err = ENXIO;
959 break;
960 }
961
962 return err;
963 }
964
965 /*
966 * Allocate Ring Buffers.
967 */
968 static void *
969 btsco_allocm(void *hdl, int direction, size_t size)
970 {
971 struct btsco_softc *sc = hdl;
972 void *addr;
973
974 DPRINTF("%s: size %d direction %d\n", sc->sc_name, size, direction);
975
976 addr = kmem_alloc(size, KM_SLEEP);
977
978 if (direction == AUMODE_PLAY) {
979 sc->sc_tx_buf = addr;
980 sc->sc_tx_refcnt = 0;
981 }
982
983 return addr;
984 }
985
986 /*
987 * Free Ring Buffers.
988 *
989 * Because we used external memory for the tx mbufs, we dont
990 * want to free the memory until all the mbufs are done with
991 *
992 * Just to be sure, dont free if something is still pending.
993 * This would be a memory leak but at least there is a warning..
994 */
995 static void
996 btsco_freem(void *hdl, void *addr, size_t size)
997 {
998 struct btsco_softc *sc = hdl;
999 int count = hz / 2;
1000
1001 if (addr == sc->sc_tx_buf) {
1002 DPRINTF("%s: tx_refcnt=%d\n", sc->sc_name, sc->sc_tx_refcnt);
1003
1004 sc->sc_tx_buf = NULL;
1005
1006 while (sc->sc_tx_refcnt> 0 && count-- > 0)
1007 kpause("drain", false, 1, NULL);
1008
1009 if (sc->sc_tx_refcnt > 0) {
1010 aprint_error("%s: ring buffer unreleased!\n", sc->sc_name);
1011 return;
1012 }
1013 }
1014
1015 kmem_free(addr, size);
1016 }
1017
1018 static int
1019 btsco_get_props(void *hdl)
1020 {
1021
1022 return AUDIO_PROP_FULLDUPLEX;
1023 }
1024
1025 static void
1026 btsco_get_locks(void *hdl, kmutex_t **intr, kmutex_t **thread)
1027 {
1028 struct btsco_softc *sc = hdl;
1029
1030 *thread = &sc->sc_lock;
1031 *intr = bt_lock;
1032 }
1033
1034 /*
1035 * Handle private ioctl. We pass information out about how to talk
1036 * to the device and mixer.
1037 */
1038 static int
1039 btsco_dev_ioctl(void *hdl, u_long cmd, void *addr, int flag,
1040 struct lwp *l)
1041 {
1042 struct btsco_softc *sc = hdl;
1043 struct btsco_info *bi = (struct btsco_info *)addr;
1044 int err = 0;
1045
1046 DPRINTF("%s cmd 0x%lx flag %d\n", sc->sc_name, cmd, flag);
1047
1048 switch (cmd) {
1049 case BTSCO_GETINFO:
1050 memset(bi, 0, sizeof(*bi));
1051 bdaddr_copy(&bi->laddr, &sc->sc_laddr);
1052 bdaddr_copy(&bi->raddr, &sc->sc_raddr);
1053 bi->channel = sc->sc_channel;
1054 bi->vgs = BTSCO_VGS;
1055 bi->vgm = BTSCO_VGM;
1056 break;
1057
1058 default:
1059 err = EPASSTHROUGH;
1060 break;
1061 }
1062
1063 return err;
1064 }
1065
1066
1067 /*****************************************************************************
1068 *
1069 * misc btsco functions
1070 *
1071 */
1072
1073 /*
1074 * Our transmit interrupt. This is triggered when a new block is to be
1075 * sent. We send mtu sized chunks of the block as mbufs with external
1076 * storage to sco_send_pcb()
1077 */
1078 static void
1079 btsco_intr(void *arg)
1080 {
1081 struct btsco_softc *sc = arg;
1082 struct mbuf *m;
1083 uint8_t *block;
1084 int mlen, size;
1085
1086 DPRINTFN(10, "%s block %p size %d\n",
1087 sc->sc_name, sc->sc_tx_block, sc->sc_tx_size);
1088
1089 if (sc->sc_sco == NULL)
1090 return; /* connection is lost */
1091
1092 mutex_enter(bt_lock);
1093 block = sc->sc_tx_block;
1094 size = sc->sc_tx_size;
1095 sc->sc_tx_block = NULL;
1096 sc->sc_tx_size = 0;
1097
1098 while (size > 0) {
1099 MGETHDR(m, M_DONTWAIT, MT_DATA);
1100 if (m == NULL)
1101 break;
1102
1103 mlen = MIN(sc->sc_mtu, size);
1104
1105 /* I think M_DEVBUF is true but not relevant */
1106 MEXTADD(m, block, mlen, M_DEVBUF, btsco_extfree, sc);
1107 if ((m->m_flags & M_EXT) == 0) {
1108 m_free(m);
1109 break;
1110 }
1111 sc->sc_tx_refcnt++;
1112
1113 m->m_pkthdr.len = m->m_len = mlen;
1114 sc->sc_tx_pending++;
1115
1116 if (sco_send_pcb(sc->sc_sco, m) > 0) {
1117 sc->sc_tx_pending--;
1118 break;
1119 }
1120
1121 block += mlen;
1122 size -= mlen;
1123 }
1124 mutex_exit(bt_lock);
1125 }
1126
1127 /*
1128 * Release the mbuf, we keep a reference count on the tx buffer so
1129 * that we dont release it before its free.
1130 */
1131 static void
1132 btsco_extfree(struct mbuf *m, void *addr, size_t size,
1133 void *arg)
1134 {
1135 struct btsco_softc *sc = arg;
1136
1137 if (m != NULL)
1138 pool_cache_put(mb_cache, m);
1139
1140 sc->sc_tx_refcnt--;
1141 }
1142