1 /* $NetBSD: btsco.c,v 1.22 2008/08/06 15:01:23 plunky Exp $ */
4 * Copyright (c) 2006 Itronix Inc.
7 * Written by Iain Hibbert for Itronix Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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.
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.
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: btsco.c,v 1.22 2008/08/06 15:01:23 plunky Exp $");
37 #include <sys/param.h>
38 #include <sys/audioio.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>
47 #include <sys/socketvar.h>
48 #include <sys/systm.h>
51 #include <prop/proplib.h>
53 #include <netbt/bluetooth.h>
54 #include <netbt/rfcomm.h>
55 #include <netbt/sco.h>
57 #include <dev/audio_if.h>
58 #include <dev/auconv.h>
59 #include <dev/mulaw.h>
61 #include <dev/bluetooth/btdev.h>
62 #include <dev/bluetooth/btsco.h>
68 int btsco_debug
= BTSCO_DEBUG
;
69 #define DPRINTF(fmt, args...) do { \
71 printf("%s: "fmt, __func__ , ##args); \
72 } while (/* CONSTCOND */0)
74 #define DPRINTFN(n, fmt, args...) do { \
75 if (btsco_debug > (n)) \
76 printf("%s: "fmt, __func__ , ##args); \
77 } while (/* CONSTCOND */0)
83 /*****************************************************************************
85 * Bluetooth SCO Audio device
91 const char *sc_name
; /* our device_xname */
93 device_t sc_audio
; /* MI audio device */
94 void *sc_intr
; /* interrupt cookie */
95 kcondvar_t sc_connect
; /* connect wait */
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 */
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 */
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 */
124 int sc_vgs
; /* speaker volume */
125 int sc_vgm
; /* mic volume */
129 #define BTSCO_CLOSED 0
130 #define BTSCO_WAIT_CONNECT 1
134 #define BTSCO_LISTEN (1 << 1)
136 /* autoconf(9) glue */
137 static int btsco_match(device_t
, cfdata_t
, void *);
138 static void btsco_attach(device_t
, device_t
, void *);
139 static int btsco_detach(device_t
, int);
141 CFATTACH_DECL_NEW(btsco
, sizeof(struct btsco_softc
),
142 btsco_match
, btsco_attach
, btsco_detach
, NULL
);
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
*);
165 static const struct audio_hw_if btsco_if
= {
166 btsco_open
, /* open */
167 btsco_close
, /* close */
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 */
189 btsco_get_props
, /* get_props */
190 NULL
, /* trigger_output */
191 NULL
, /* trigger_input */
192 btsco_dev_ioctl
, /* dev_ioctl */
193 NULL
, /* powerstate */
196 static const struct audio_device btsco_device
= {
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 */
210 AUFMT_MONAURAL
, /* channel_mask */
211 1, /* frequency_type */
212 { 8000 } /* frequency */
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
*);
224 static const struct btproto btsco_sco_proto
= {
225 btsco_sco_connecting
,
227 btsco_sco_disconnected
,
235 /*****************************************************************************
245 #define BTSCO_INPUT_CLASS 2
246 #define BTSCO_OUTPUT_CLASS 3
248 /* connect timeout */
249 #define BTSCO_TIMEOUT (30 * hz)
251 /* misc btsco functions */
252 static void btsco_extfree(struct mbuf
*, void *, size_t, void *);
253 static void btsco_intr(void *);
256 /*****************************************************************************
258 * btsco autoconf(9) routines
262 btsco_match(device_t self
, cfdata_t cfdata
, void *aux
)
264 prop_dictionary_t dict
= aux
;
267 obj
= prop_dictionary_get(dict
, BTDEVservice
);
268 if (prop_string_equals_cstring(obj
, "HSET"))
271 if (prop_string_equals_cstring(obj
, "HF"))
278 btsco_attach(device_t parent
, device_t self
, void *aux
)
280 struct btsco_softc
*sc
= device_private(self
);
281 prop_dictionary_t dict
= aux
;
289 sc
->sc_state
= BTSCO_CLOSED
;
290 sc
->sc_name
= device_xname(self
);
291 cv_init(&sc
->sc_connect
, "connect");
294 * copy in our configuration info
296 obj
= prop_dictionary_get(dict
, BTDEVladdr
);
297 bdaddr_copy(&sc
->sc_laddr
, prop_data_data_nocopy(obj
));
299 obj
= prop_dictionary_get(dict
, BTDEVraddr
);
300 bdaddr_copy(&sc
->sc_raddr
, prop_data_data_nocopy(obj
));
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");
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
);
315 sc
->sc_channel
= prop_number_integer_value(obj
);
317 aprint_verbose(" channel %d", sc
->sc_channel
);
320 DPRINTF("sc=%p\n", sc
);
323 * set up transmit interrupt
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");
332 * attach audio device
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");
342 btsco_detach(device_t self
, int flags
)
344 struct btsco_softc
*sc
= device_private(self
);
346 DPRINTF("sc=%p\n", sc
);
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
);
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
);
363 if (sc
->sc_audio
!= NULL
) {
364 DPRINTF("sc_audio=%p\n", sc
->sc_audio
);
365 config_detach(sc
->sc_audio
, flags
);
369 if (sc
->sc_intr
!= NULL
) {
370 softint_disestablish(sc
->sc_intr
);
374 if (sc
->sc_rx_mbuf
!= NULL
) {
375 m_freem(sc
->sc_rx_mbuf
);
376 sc
->sc_rx_mbuf
= NULL
;
379 if (sc
->sc_tx_refcnt
> 0) {
380 aprint_error_dev(self
, "tx_refcnt=%d!\n", sc
->sc_tx_refcnt
);
382 if ((flags
& DETACH_FORCE
) == 0)
386 cv_destroy(&sc
->sc_connect
);
391 /*****************************************************************************
393 * bluetooth(9) methods for SCO
395 * All these are called from Bluetooth Protocol code, in a soft
396 * interrupt context at IPL_SOFTNET.
400 btsco_sco_connecting(void *arg
)
402 /* struct btsco_softc *sc = arg; */
408 btsco_sco_connected(void *arg
)
410 struct btsco_softc
*sc
= arg
;
412 DPRINTF("%s\n", sc
->sc_name
);
414 KASSERT(sc
->sc_sco
!= NULL
);
415 KASSERT(sc
->sc_state
== BTSCO_WAIT_CONNECT
);
418 * If we are listening, no more need
420 if (sc
->sc_sco_l
!= NULL
)
421 sco_detach(&sc
->sc_sco_l
);
423 sc
->sc_state
= BTSCO_OPEN
;
424 cv_broadcast(&sc
->sc_connect
);
428 btsco_sco_disconnected(void *arg
, int err
)
430 struct btsco_softc
*sc
= arg
;
433 DPRINTF("%s sc_state %d\n", sc
->sc_name
, sc
->sc_state
);
435 KASSERT(sc
->sc_sco
!= NULL
);
438 sco_detach(&sc
->sc_sco
);
440 switch (sc
->sc_state
) {
441 case BTSCO_CLOSED
: /* dont think this can happen */
444 case BTSCO_WAIT_CONNECT
: /* connect failed */
445 cv_broadcast(&sc
->sc_connect
);
448 case BTSCO_OPEN
: /* link lost */
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.
455 if (sc
->sc_tx_pending
> 0) {
456 sc
->sc_tx_pending
= 0;
457 (*sc
->sc_tx_intr
)(sc
->sc_tx_intrarg
);
459 if (sc
->sc_rx_want
> 0) {
461 (*sc
->sc_rx_intr
)(sc
->sc_rx_intrarg
);
467 UNKNOWN(sc
->sc_state
);
470 sc
->sc_state
= BTSCO_CLOSED
;
474 btsco_sco_newconn(void *arg
, struct sockaddr_bt
*laddr
,
475 struct sockaddr_bt
*raddr
)
477 struct btsco_softc
*sc
= arg
;
479 DPRINTF("%s\n", sc
->sc_name
);
481 if (bdaddr_same(&raddr
->bt_bdaddr
, &sc
->sc_raddr
) == 0
482 || sc
->sc_state
!= BTSCO_WAIT_CONNECT
483 || sc
->sc_sco
!= NULL
)
486 sco_attach(&sc
->sc_sco
, &btsco_sco_proto
, sc
);
491 btsco_sco_complete(void *arg
, int count
)
493 struct btsco_softc
*sc
= arg
;
496 DPRINTFN(10, "%s count %d\n", sc
->sc_name
, count
);
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
);
508 btsco_sco_linkmode(void *arg
, int new)
510 /* struct btsco_softc *sc = arg; */
516 btsco_sco_input(void *arg
, struct mbuf
*m
)
518 struct btsco_softc
*sc
= arg
;
521 DPRINTFN(10, "%s len=%d\n", sc
->sc_name
, m
->m_pkthdr
.len
);
524 if (sc
->sc_rx_want
== 0) {
527 KASSERT(sc
->sc_rx_intr
!= NULL
);
528 KASSERT(sc
->sc_rx_block
!= NULL
);
530 len
= MIN(sc
->sc_rx_want
, m
->m_pkthdr
.len
);
531 m_copydata(m
, 0, len
, sc
->sc_rx_block
);
533 sc
->sc_rx_want
-= len
;
534 sc
->sc_rx_block
+= len
;
536 if (len
> m
->m_pkthdr
.len
) {
537 if (sc
->sc_rx_mbuf
!= NULL
)
538 m_freem(sc
->sc_rx_mbuf
);
546 if (sc
->sc_rx_want
== 0)
547 (*sc
->sc_rx_intr
)(sc
->sc_rx_intrarg
);
553 /*****************************************************************************
560 btsco_open(void *hdl
, int flags
)
562 struct sockaddr_bt sa
;
563 struct btsco_softc
*sc
= hdl
;
567 DPRINTF("%s flags 0x%x\n", sc
->sc_name
, flags
);
568 /* flags FREAD & FWRITE? */
570 if (sc
->sc_sco
!= NULL
|| sc
->sc_sco_l
!= NULL
)
573 mutex_enter(bt_lock
);
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
);
580 if (sc
->sc_flags
& BTSCO_LISTEN
) {
581 err
= sco_attach(&sc
->sc_sco_l
, &btsco_sco_proto
, sc
);
585 err
= sco_bind(sc
->sc_sco_l
, &sa
);
587 sco_detach(&sc
->sc_sco_l
);
591 err
= sco_listen(sc
->sc_sco_l
);
593 sco_detach(&sc
->sc_sco_l
);
597 timo
= 0; /* no timeout */
599 err
= sco_attach(&sc
->sc_sco
, &btsco_sco_proto
, sc
);
603 err
= sco_bind(sc
->sc_sco
, &sa
);
605 sco_detach(&sc
->sc_sco
);
609 bdaddr_copy(&sa
.bt_bdaddr
, &sc
->sc_raddr
);
610 err
= sco_connect(sc
->sc_sco
, &sa
);
612 sco_detach(&sc
->sc_sco
);
616 timo
= BTSCO_TIMEOUT
;
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
);
623 switch (sc
->sc_state
) {
624 case BTSCO_CLOSED
: /* disconnected */
627 /* fall through to */
628 case BTSCO_WAIT_CONNECT
: /* error */
629 if (sc
->sc_sco
!= NULL
)
630 sco_detach(&sc
->sc_sco
);
632 if (sc
->sc_sco_l
!= NULL
)
633 sco_detach(&sc
->sc_sco_l
);
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
);
645 UNKNOWN(sc
->sc_state
);
652 DPRINTF("done err=%d, sc_state=%d, sc_mtu=%d\n",
653 err
, sc
->sc_state
, sc
->sc_mtu
);
658 btsco_close(void *hdl
)
660 struct btsco_softc
*sc
= hdl
;
662 DPRINTF("%s\n", sc
->sc_name
);
664 mutex_enter(bt_lock
);
665 if (sc
->sc_sco
!= NULL
) {
666 sco_disconnect(sc
->sc_sco
, 0);
667 sco_detach(&sc
->sc_sco
);
670 if (sc
->sc_sco_l
!= NULL
) {
671 sco_detach(&sc
->sc_sco_l
);
675 if (sc
->sc_rx_mbuf
!= NULL
) {
676 m_freem(sc
->sc_rx_mbuf
);
677 sc
->sc_rx_mbuf
= NULL
;
681 sc
->sc_rx_block
= NULL
;
682 sc
->sc_rx_intr
= NULL
;
683 sc
->sc_rx_intrarg
= NULL
;
686 sc
->sc_tx_block
= NULL
;
687 sc
->sc_tx_pending
= 0;
688 sc
->sc_tx_intr
= NULL
;
689 sc
->sc_tx_intrarg
= NULL
;
693 btsco_query_encoding(void *hdl
, struct audio_encoding
*ae
)
695 /* struct btsco_softc *sc = hdl; */
700 strcpy(ae
->name
, AudioEslinear_le
);
701 ae
->encoding
= AUDIO_ENCODING_SLINEAR_LE
;
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
)
718 /* struct btsco_softc *sc = hdl; */
719 const struct audio_format
*f
;
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
);
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
733 if (setmode
& AUMODE_PLAY
) {
734 rv
= auconv_set_converter(f
, 1, AUMODE_PLAY
, play
, TRUE
, pfil
);
739 if (setmode
& AUMODE_RECORD
) {
740 rv
= auconv_set_converter(f
, 1, AUMODE_RECORD
, rec
, TRUE
, rfil
);
749 * If we have an MTU value to use, round the blocksize to that.
752 btsco_round_blocksize(void *hdl
, int bs
, int mode
,
753 const audio_params_t
*param
)
755 struct btsco_softc
*sc
= hdl
;
757 if (sc
->sc_mtu
> 0) {
758 bs
= (bs
/ sc
->sc_mtu
) * sc
->sc_mtu
;
763 DPRINTF("%s mode=0x%x, bs=%d, sc_mtu=%d\n",
764 sc
->sc_name
, mode
, bs
, sc
->sc_mtu
);
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.
777 btsco_start_output(void *hdl
, void *block
, int blksize
,
778 void (*intr
)(void *), void *intrarg
)
780 struct btsco_softc
*sc
= hdl
;
782 DPRINTFN(5, "%s blksize %d\n", sc
->sc_name
, blksize
);
784 if (sc
->sc_sco
== NULL
)
785 return ENOTCONN
; /* connection lost */
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
;
793 softint_schedule(sc
->sc_intr
);
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
804 * If there was any leftover data that didnt fit in the last block, retry
808 btsco_start_input(void *hdl
, void *block
, int blksize
,
809 void (*intr
)(void *), void *intrarg
)
811 struct btsco_softc
*sc
= hdl
;
814 DPRINTFN(5, "%s blksize %d\n", sc
->sc_name
, blksize
);
816 if (sc
->sc_sco
== NULL
)
819 sc
->sc_rx_want
= blksize
;
820 sc
->sc_rx_block
= block
;
821 sc
->sc_rx_intr
= intr
;
822 sc
->sc_rx_intrarg
= intrarg
;
824 if (sc
->sc_rx_mbuf
!= NULL
) {
826 sc
->sc_rx_mbuf
= NULL
;
827 btsco_sco_input(sc
, m
);
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.
841 btsco_halt_output(void *hdl
)
843 struct btsco_softc
*sc
= hdl
;
845 DPRINTFN(5, "%s\n", sc
->sc_name
);
848 sc
->sc_tx_block
= NULL
;
849 sc
->sc_tx_pending
= 0;
850 sc
->sc_tx_intr
= NULL
;
851 sc
->sc_tx_intrarg
= NULL
;
859 * This doesnt really halt the input, but it will look
860 * that way to the audio driver. Incoming data will be
864 btsco_halt_input(void *hdl
)
866 struct btsco_softc
*sc
= hdl
;
868 DPRINTFN(5, "%s\n", sc
->sc_name
);
871 sc
->sc_rx_block
= NULL
;
872 sc
->sc_rx_intr
= NULL
;
873 sc
->sc_rx_intrarg
= NULL
;
875 if (sc
->sc_rx_mbuf
!= NULL
) {
876 m_freem(sc
->sc_rx_mbuf
);
877 sc
->sc_rx_mbuf
= NULL
;
884 btsco_getdev(void *hdl
, struct audio_device
*ret
)
892 btsco_setfd(void *hdl
, int fd
)
894 DPRINTF("set %s duplex\n", fd
? "full" : "half");
900 btsco_set_port(void *hdl
, mixer_ctrl_t
*mc
)
902 struct btsco_softc
*sc
= hdl
;
905 DPRINTF("%s dev %d type %d\n", sc
->sc_name
, mc
->dev
, mc
->type
);
909 if (mc
->type
!= AUDIO_MIXER_VALUE
||
910 mc
->un
.value
.num_channels
!= 1) {
915 sc
->sc_vgs
= mc
->un
.value
.level
[AUDIO_MIXER_LEVEL_MONO
];
919 if (mc
->type
!= AUDIO_MIXER_VALUE
||
920 mc
->un
.value
.num_channels
!= 1) {
925 sc
->sc_vgm
= mc
->un
.value
.level
[AUDIO_MIXER_LEVEL_MONO
];
937 btsco_get_port(void *hdl
, mixer_ctrl_t
*mc
)
939 struct btsco_softc
*sc
= hdl
;
942 DPRINTF("%s dev %d\n", sc
->sc_name
, mc
->dev
);
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
;
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
;
966 btsco_query_devinfo(void *hdl
, mixer_devinfo_t
*di
)
968 /* struct btsco_softc *sc = hdl; */
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
;
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
;
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
;
1008 * Allocate Ring Buffers.
1011 btsco_allocm(void *hdl
, int direction
, size_t size
,
1012 struct malloc_type
*type
, int flags
)
1014 struct btsco_softc
*sc
= hdl
;
1017 DPRINTF("%s: size %d direction %d\n", sc
->sc_name
, size
, direction
);
1019 addr
= malloc(size
, type
, flags
);
1021 if (direction
== AUMODE_PLAY
) {
1022 sc
->sc_tx_buf
= addr
;
1023 sc
->sc_tx_refcnt
= 0;
1030 * Free Ring Buffers.
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
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..
1039 btsco_freem(void *hdl
, void *addr
, struct malloc_type
*type
)
1041 struct btsco_softc
*sc
= hdl
;
1044 if (addr
== sc
->sc_tx_buf
) {
1045 DPRINTF("%s: tx_refcnt=%d\n", sc
->sc_name
, sc
->sc_tx_refcnt
);
1047 sc
->sc_tx_buf
= NULL
;
1049 while (sc
->sc_tx_refcnt
> 0 && count
-- > 0)
1050 tsleep(sc
, PWAIT
, "drain", 1);
1052 if (sc
->sc_tx_refcnt
> 0) {
1053 aprint_error("%s: ring buffer unreleased!\n", sc
->sc_name
);
1062 btsco_get_props(void *hdl
)
1065 return AUDIO_PROP_FULLDUPLEX
;
1069 * Handle private ioctl. We pass information out about how to talk
1070 * to the device and mixer.
1073 btsco_dev_ioctl(void *hdl
, u_long cmd
, void *addr
, int flag
,
1076 struct btsco_softc
*sc
= hdl
;
1077 struct btsco_info
*bi
= (struct btsco_info
*)addr
;
1080 DPRINTF("%s cmd 0x%lx flag %d\n", sc
->sc_name
, cmd
, flag
);
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
;
1101 /*****************************************************************************
1103 * misc btsco functions
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()
1113 btsco_intr(void *arg
)
1115 struct btsco_softc
*sc
= arg
;
1120 DPRINTFN(10, "%s block %p size %d\n",
1121 sc
->sc_name
, sc
->sc_tx_block
, sc
->sc_tx_size
);
1123 if (sc
->sc_sco
== NULL
)
1124 return; /* connection is lost */
1126 block
= sc
->sc_tx_block
;
1127 size
= sc
->sc_tx_size
;
1128 sc
->sc_tx_block
= NULL
;
1131 mutex_enter(bt_lock
);
1133 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
1137 mlen
= MIN(sc
->sc_mtu
, size
);
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) {
1147 m
->m_pkthdr
.len
= m
->m_len
= mlen
;
1148 sc
->sc_tx_pending
++;
1150 if (sco_send(sc
->sc_sco
, m
) > 0) {
1151 sc
->sc_tx_pending
--;
1158 mutex_exit(bt_lock
);
1162 * Release the mbuf, we keep a reference count on the tx buffer so
1163 * that we dont release it before its free.
1166 btsco_extfree(struct mbuf
*m
, void *addr
, size_t size
,
1169 struct btsco_softc
*sc
= arg
;
1172 pool_cache_put(mb_cache
, m
);