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