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