1 diff -urN linux/drivers/bluetooth/hci_usb.c linux.new/drivers/bluetooth/hci_usb.c
2 --- linux/drivers/bluetooth/hci_usb.c 2004-08-23 18:46:43.000000000 +0200
3 +++ linux.new/drivers/bluetooth/hci_usb.c 2004-08-23 19:22:37.000000000 +0200
6 switch (ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
7 case USB_ENDPOINT_XFER_ISOC:
8 - if (ep->desc.wMaxPacketSize < size ||
9 - uif->desc.bAlternateSetting > 2)
10 + /* Use only the 9 byte
11 + "One voice channel with 8 bit encoding"
12 + endpoint until there is support for changing
13 + the endpoint dynamically. See
14 + Bluetooth 1.1 Part H:2, section 2.1 */
15 + if (ep->desc.wMaxPacketSize != 9)
17 size = ep->desc.wMaxPacketSize;
19 diff -urN linux/include/sound/asound.h linux.new/include/sound/asound.h
20 --- linux/include/sound/asound.h 2004-08-23 18:46:43.000000000 +0200
21 +++ linux.new/include/sound/asound.h 2004-08-23 19:22:37.000000000 +0200
23 SNDRV_HWDEP_IFACE_MIXART, /* Digigram miXart cards */
24 SNDRV_HWDEP_IFACE_USX2Y, /* Tascam US122, US224 & US428 usb */
25 SNDRV_HWDEP_IFACE_EMUX_WAVETABLE, /* EmuX wavetable */
26 + SNDRV_HWDEP_IFACE_BT_SCO, /* Bluetooth SCO Headset */
28 /* Don't forget to change the following: */
29 - SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_EMUX_WAVETABLE,
30 + SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_BT_SCO,
33 struct sndrv_hwdep_info {
35 struct sndrv_hwdep_dsp_image {
36 unsigned int index; /* W: DSP index */
37 unsigned char name[64]; /* W: ID (e.g. file name) */
38 - unsigned char __user *image; /* W: binary image */
39 + unsigned char __user *image;/* W: binary image */
40 size_t length; /* W: size of image in bytes */
41 unsigned long driver_data; /* W: driver-specific data */
43 diff -urN linux/include/sound/btsco.h linux.new/include/sound/btsco.h
44 --- linux/include/sound/btsco.h 1970-01-01 01:00:00.000000000 +0100
45 +++ linux.new/include/sound/btsco.h 2004-07-19 19:56:20.000000000 +0200
47 +#ifndef __SOUND_BT_SCO_H
48 +#define __SOUND_BT_SCO_H
50 +#define SNDRV_BT_SCO_IOCTL_SET_SCO_SOCKET _IOW ('H', 0x10, int)
51 +#endif /* __SOUND_BT_SCO_H */
52 diff -urN linux/include/sound/sndmagic.h linux.new/include/sound/sndmagic.h
53 --- linux/include/sound/sndmagic.h 2004-08-23 18:46:43.000000000 +0200
54 +++ linux.new/include/sound/sndmagic.h 2004-08-23 19:22:37.000000000 +0200
56 #define snd_card_harmony_t_magic 0xa15a4300
57 #define bt87x_t_magic 0xa15a4400
58 #define pdacf_t_magic 0xa15a4500
59 +#define snd_card_bt_sco_t_magic 0xa15a4600
60 +#define snd_card_bt_sco_pcm_t_magic 0xa15a4601
61 #define vortex_t_magic 0xa15a4601
62 #define atiixp_t_magic 0xa15a4701
63 #define amd7930_t_magic 0xa15a4801
64 diff -urN linux/sound/bluetooth/btsco.c linux.new/sound/bluetooth/btsco.c
65 --- linux/sound/bluetooth/btsco.c 1970-01-01 01:00:00.000000000 +0100
66 +++ linux.new/sound/bluetooth/btsco.c 2004-07-19 19:56:20.000000000 +0200
69 + * Bluetooth SCO soundcard
70 + * Copyright (c) 2003, 2004 by Jonathan Paisley <jp@dcs.gla.ac.uk>
72 + * Based on dummy.c which is
73 + * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
75 + * This program is free software; you can redistribute it and/or modify
76 + * it under the terms of the GNU General Public License as published by
77 + * the Free Software Foundation; either version 2 of the License, or
78 + * (at your option) any later version.
80 + * This program is distributed in the hope that it will be useful,
81 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
82 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83 + * GNU General Public License for more details.
85 + * You should have received a copy of the GNU General Public License
86 + * along with this program; if not, write to the Free Software
87 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
91 +#define chip_t snd_card_bt_sco_t
93 +#include <sound/driver.h>
94 +#include <linux/version.h>
95 +#include <linux/init.h>
96 +#include <linux/jiffies.h>
97 +#include <linux/slab.h>
98 +#include <linux/time.h>
99 +#include <linux/wait.h>
100 +#include <linux/socket.h>
101 +#include <linux/file.h>
102 +#include <linux/completion.h>
103 +#include <linux/smp_lock.h>
104 +#include <net/sock.h>
105 +#include <net/bluetooth/bluetooth.h>
107 +#include <sound/btsco.h>
108 +#include <sound/core.h>
109 +#include <sound/control.h>
110 +#include <sound/pcm.h>
111 +#include <sound/rawmidi.h>
112 +#include <sound/hwdep.h>
113 +#define SNDRV_GET_ID
114 +#include <sound/initval.h>
116 +MODULE_AUTHOR("Jonathan Paisley <jp@dcs.gla.ac.uk>");
117 +MODULE_DESCRIPTION("Bluetooth SCO Headset Soundcard");
118 +MODULE_LICENSE("GPL");
119 +MODULE_CLASSES("{sound}");
120 +MODULE_DEVICES("{{ALSA,Bluetooth SCO Soundcard}}");
122 +static char *mod_revision = "$Revision$";
126 +#define dprintk(fmt...) printk(KERN_INFO "snd-bt-sco: " fmt)
128 +#define dprintk(fmt...) do {} while(0)
131 +#define MAX_BUFFER_SIZE (32*1024)
133 +#define MIXER_ADDR_MASTER 0
134 +#define MIXER_ADDR_MIC 1
135 +#define MIXER_ADDR_LAST 1
137 +#define MIXER_MASK_MASTER 1
138 +#define MIXER_MASK_MIC 2
140 +#define MIXER_MIN_VOLUME 1
141 +#define MIXER_MAX_VOLUME 15
143 +struct snd_card_bt_sco_pcm;
145 +typedef struct snd_card_bt_sco {
147 + spinlock_t mixer_lock;
148 + int mixer_volume[MIXER_ADDR_LAST + 1];
149 + snd_kcontrol_t *mixer_controls[MIXER_ADDR_LAST + 2]; /* also loopback */
150 + volatile int loopback;
152 + spinlock_t mixer_changed_lock;
153 + volatile int mixer_changed;
154 + wait_queue_head_t hwdep_wait;
157 + struct completion thread_done;
159 + volatile int thread_exit;
160 + struct semaphore thread_sem;
162 + volatile struct socket *sco_sock;
163 + struct semaphore sock_sem;
164 + wait_queue_head_t wait;
166 + struct semaphore playback_sem;
167 + struct snd_card_bt_sco_pcm *playback;
168 + struct semaphore capture_sem;
169 + struct snd_card_bt_sco_pcm *capture;
170 +} snd_card_bt_sco_t;
172 +typedef struct snd_card_bt_sco_pcm {
173 + snd_card_bt_sco_t *bt_sco;
175 + unsigned int pcm_size;
176 + unsigned int pcm_count;
177 + unsigned int pcm_bps; /* bytes per second */
178 + unsigned int pcm_irq_pos; /* IRQ position */
179 + unsigned int pcm_buf_pos; /* position in buffer */
180 + snd_pcm_substream_t *substream;
181 +} snd_card_bt_sco_pcm_t;
183 +static snd_card_t *snd_bt_sco_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
185 +static int snd_card_bt_sco_playback_trigger(snd_pcm_substream_t *
186 + substream, int cmd)
188 + snd_pcm_runtime_t *runtime = substream->runtime;
189 + snd_card_bt_sco_pcm_t *bspcm =
190 + snd_magic_cast(snd_card_bt_sco_pcm_t, runtime->private_data,
192 + snd_card_bt_sco_t *bt_sco = snd_pcm_substream_chip(substream);
194 + dprintk("playback_trigger %d\n", cmd);
196 + if (cmd == SNDRV_PCM_TRIGGER_START) {
197 + bt_sco->playback = bspcm;
198 + dprintk("setting playback to bspcm\n");
199 + } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
200 + bt_sco->playback = NULL;
201 + dprintk("setting playback to NULL\n");
208 +static int snd_card_bt_sco_capture_trigger(snd_pcm_substream_t *
209 + substream, int cmd)
211 + snd_pcm_runtime_t *runtime = substream->runtime;
212 + snd_card_bt_sco_pcm_t *bspcm =
213 + snd_magic_cast(snd_card_bt_sco_pcm_t, runtime->private_data,
215 + snd_card_bt_sco_t *bt_sco = snd_pcm_substream_chip(substream);
217 + dprintk("capture_trigger %d\n", cmd);
219 + if (cmd == SNDRV_PCM_TRIGGER_START) {
220 + bt_sco->capture = bspcm;
221 + dprintk("setting capture to bspcm\n");
222 + } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
223 + bt_sco->capture = NULL;
224 + dprintk("setting capture to NULL\n");
231 +static int snd_card_bt_sco_pcm_prepare(snd_pcm_substream_t * substream)
233 + snd_pcm_runtime_t *runtime = substream->runtime;
234 + snd_card_bt_sco_pcm_t *bspcm =
235 + snd_magic_cast(snd_card_bt_sco_pcm_t, runtime->private_data,
239 + bps = runtime->rate * runtime->channels;
240 + bps *= snd_pcm_format_width(runtime->format);
244 + bspcm->pcm_bps = bps;
245 + bspcm->pcm_size = snd_pcm_lib_buffer_bytes(substream);
246 + bspcm->pcm_count = snd_pcm_lib_period_bytes(substream);
247 + bspcm->pcm_irq_pos = 0;
248 + bspcm->pcm_buf_pos = 0;
250 + "prepare ok bps: %d size: %d count: %d\n",
251 + bspcm->pcm_bps, bspcm->pcm_size,
256 +static int snd_card_bt_sco_playback_prepare(snd_pcm_substream_t *
259 + return snd_card_bt_sco_pcm_prepare(substream);
262 +static int snd_card_bt_sco_capture_prepare(snd_pcm_substream_t *
265 + dprintk("capture_prepare\n");
266 + return snd_card_bt_sco_pcm_prepare(substream);
269 +static void snd_card_bt_sco_pcm_receive(snd_card_bt_sco_pcm_t * bspcm,
270 + unsigned char *data,
273 + unsigned long flags;
274 + unsigned int oldptr;
276 + spin_lock_irqsave(&bspcm->lock, flags);
277 + oldptr = bspcm->pcm_buf_pos;
278 + bspcm->pcm_irq_pos += len;
279 + bspcm->pcm_buf_pos += len;
280 + bspcm->pcm_buf_pos %= bspcm->pcm_size;
281 + spin_unlock_irqrestore(&bspcm->lock, flags);
282 + /* copy a data chunk */
283 + if (oldptr + len > bspcm->pcm_size) {
284 + unsigned int cnt = bspcm->pcm_size - oldptr;
285 + memcpy(bspcm->substream->runtime->dma_area + oldptr, data,
287 + memcpy(bspcm->substream->runtime->dma_area, data + cnt,
290 + memcpy(bspcm->substream->runtime->dma_area + oldptr, data,
293 + /* update the pointer, call callback if necessary */
294 + spin_lock_irqsave(&bspcm->lock, flags);
295 + if (bspcm->pcm_irq_pos >= bspcm->pcm_count) {
296 + bspcm->pcm_irq_pos %= bspcm->pcm_count;
297 + spin_unlock_irqrestore(&bspcm->lock, flags);
298 + snd_pcm_period_elapsed(bspcm->substream);
300 + spin_unlock_irqrestore(&bspcm->lock, flags);
304 +static void snd_card_bt_sco_pcm_send(snd_card_bt_sco_pcm_t * bspcm,
305 + unsigned char *data,
308 + unsigned long flags;
309 + unsigned int oldptr;
311 + spin_lock_irqsave(&bspcm->lock, flags);
312 + oldptr = bspcm->pcm_buf_pos;
313 + bspcm->pcm_irq_pos += len;
314 + bspcm->pcm_buf_pos += len;
315 + bspcm->pcm_buf_pos %= bspcm->pcm_size;
316 + spin_unlock_irqrestore(&bspcm->lock, flags);
317 + /* copy a data chunk */
318 + if (oldptr + len > bspcm->pcm_size) {
319 + unsigned int cnt = bspcm->pcm_size - oldptr;
320 + memcpy(data, bspcm->substream->runtime->dma_area + oldptr,
322 + memcpy(data + cnt, bspcm->substream->runtime->dma_area,
325 + memcpy(data, bspcm->substream->runtime->dma_area + oldptr,
328 + /* update the pointer, call callback if necessary */
329 + spin_lock_irqsave(&bspcm->lock, flags);
330 + if (bspcm->pcm_irq_pos >= bspcm->pcm_count) {
331 + bspcm->pcm_irq_pos %= bspcm->pcm_count;
332 + spin_unlock_irqrestore(&bspcm->lock, flags);
333 + snd_pcm_period_elapsed(bspcm->substream);
335 + spin_unlock_irqrestore(&bspcm->lock, flags);
338 +static snd_pcm_uframes_t
339 +snd_card_bt_sco_playback_pointer(snd_pcm_substream_t * substream)
341 + snd_pcm_runtime_t *runtime = substream->runtime;
342 + snd_card_bt_sco_pcm_t *bspcm =
343 + snd_magic_cast(snd_card_bt_sco_pcm_t, runtime->private_data,
346 + return bytes_to_frames(runtime, bspcm->pcm_buf_pos);
349 +static snd_pcm_uframes_t
350 +snd_card_bt_sco_capture_pointer(snd_pcm_substream_t * substream)
352 + snd_pcm_runtime_t *runtime = substream->runtime;
353 + snd_card_bt_sco_pcm_t *bspcm =
354 + snd_magic_cast(snd_card_bt_sco_pcm_t, runtime->private_data,
357 + return bytes_to_frames(runtime, bspcm->pcm_buf_pos);
360 +static snd_pcm_hardware_t snd_card_bt_sco_playback = {
361 + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
362 + SNDRV_PCM_INFO_MMAP_VALID),
363 + .formats = SNDRV_PCM_FMTBIT_S8 /* | SNDRV_PCM_FMTBIT_S16_LE */ ,
364 + .rates = SNDRV_PCM_RATE_8000,
369 + .buffer_bytes_max = MAX_BUFFER_SIZE,
370 + .period_bytes_min = 24,
371 + .period_bytes_max = MAX_BUFFER_SIZE,
373 + .periods_max = 4*8000/24,
377 +static snd_pcm_hardware_t snd_card_bt_sco_capture = {
378 + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
379 + SNDRV_PCM_INFO_MMAP_VALID),
380 + .formats = SNDRV_PCM_FMTBIT_S8 /* | SNDRV_PCM_FMTBIT_S16_LE */ ,
381 + .rates = SNDRV_PCM_RATE_8000,
386 + .buffer_bytes_max = MAX_BUFFER_SIZE,
387 + .period_bytes_min = 24,
388 + .period_bytes_max = MAX_BUFFER_SIZE,
390 + .periods_max = 4*8000/24,
394 +static void snd_card_bt_sco_runtime_free(snd_pcm_runtime_t * runtime)
396 + snd_card_bt_sco_pcm_t *bspcm =
397 + snd_magic_cast(snd_card_bt_sco_pcm_t, runtime->private_data,
399 + snd_magic_kfree(bspcm);
402 +static int snd_card_bt_sco_playback_open(snd_pcm_substream_t *
405 + snd_pcm_runtime_t *runtime = substream->runtime;
406 + snd_card_bt_sco_pcm_t *bspcm;
408 + dprintk("playback_open\n");
410 + bspcm = snd_magic_kcalloc(snd_card_bt_sco_pcm_t, 0, GFP_KERNEL);
413 + if ((runtime->dma_area =
414 + snd_malloc_pages_fallback(MAX_BUFFER_SIZE, GFP_KERNEL,
415 + &runtime->dma_bytes)) == NULL) {
416 + snd_magic_kfree(bspcm);
419 + spin_lock_init(&bspcm->lock);
420 + bspcm->substream = substream;
421 + runtime->private_data = bspcm;
422 + runtime->private_free = snd_card_bt_sco_runtime_free;
423 + runtime->hw = snd_card_bt_sco_playback;
427 +static int snd_card_bt_sco_capture_open(snd_pcm_substream_t * substream)
429 + snd_pcm_runtime_t *runtime = substream->runtime;
430 + snd_card_bt_sco_pcm_t *bspcm;
432 + dprintk("capture_open\n");
434 + bspcm = snd_magic_kcalloc(snd_card_bt_sco_pcm_t, 0, GFP_KERNEL);
437 + if ((runtime->dma_area =
438 + snd_malloc_pages_fallback(MAX_BUFFER_SIZE, GFP_KERNEL,
439 + &runtime->dma_bytes)) == NULL) {
440 + snd_magic_kfree(bspcm);
443 + memset(runtime->dma_area, 0, runtime->dma_bytes);
444 + spin_lock_init(&bspcm->lock);
445 + bspcm->substream = substream;
446 + runtime->private_data = bspcm;
447 + runtime->private_free = snd_card_bt_sco_runtime_free;
448 + runtime->hw = snd_card_bt_sco_capture;
452 +static int snd_card_bt_sco_playback_close(snd_pcm_substream_t *
455 + snd_pcm_runtime_t *runtime = substream->runtime;
456 + snd_card_bt_sco_t *bt_sco = snd_pcm_substream_chip(substream);
458 + snd_assert(bt_sco->playback == NULL, ;);
460 + /* Ensure any references to this in our thread have finished */
461 + down(&bt_sco->playback_sem);
462 + up(&bt_sco->playback_sem);
464 + snd_free_pages(runtime->dma_area, runtime->dma_bytes);
468 +static int snd_card_bt_sco_capture_close(snd_pcm_substream_t *
471 + snd_pcm_runtime_t *runtime = substream->runtime;
472 + struct snd_card_bt_sco *bt_sco = (struct snd_card_bt_sco *) substream->private_data;
474 + snd_assert(bt_sco->capture == NULL, ;);
476 + /* Ensure any references to this in our thread have finished */
477 + down(&bt_sco->capture_sem);
478 + up(&bt_sco->capture_sem);
480 + snd_free_pages(runtime->dma_area, runtime->dma_bytes);
484 +static snd_pcm_ops_t snd_card_bt_sco_playback_ops = {
485 + .open = snd_card_bt_sco_playback_open,
486 + .close = snd_card_bt_sco_playback_close,
487 + .ioctl = snd_pcm_lib_ioctl,
488 + .prepare = snd_card_bt_sco_playback_prepare,
489 + .trigger = snd_card_bt_sco_playback_trigger,
490 + .pointer = snd_card_bt_sco_playback_pointer,
493 +static snd_pcm_ops_t snd_card_bt_sco_capture_ops = {
494 + .open = snd_card_bt_sco_capture_open,
495 + .close = snd_card_bt_sco_capture_close,
496 + .ioctl = snd_pcm_lib_ioctl,
497 + .prepare = snd_card_bt_sco_capture_prepare,
498 + .trigger = snd_card_bt_sco_capture_trigger,
499 + .pointer = snd_card_bt_sco_capture_pointer,
502 +static int __init snd_card_bt_sco_pcm(snd_card_bt_sco_t * bt_sco)
508 + snd_pcm_new(bt_sco->card, "Bluetooth SCO PCM", 0, 1, 1,
511 + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
512 + &snd_card_bt_sco_playback_ops);
513 + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
514 + &snd_card_bt_sco_capture_ops);
515 + pcm->private_data = bt_sco;
516 + pcm->info_flags = 0;
517 + strcpy(pcm->name, "BT SCO PCM");
521 +#define BT_SCO_VOLUME(xname, xindex, addr) \
522 +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
523 + .info = snd_bt_sco_volume_info, \
524 + .get = snd_bt_sco_volume_get, .put = snd_bt_sco_volume_put, \
525 + .private_value = addr }
527 +static int snd_bt_sco_volume_info(snd_kcontrol_t * kcontrol,
528 + snd_ctl_elem_info_t * uinfo)
530 + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
532 + uinfo->value.integer.min = MIXER_MIN_VOLUME;
533 + uinfo->value.integer.max = MIXER_MAX_VOLUME;
537 +static int snd_bt_sco_volume_get(snd_kcontrol_t * kcontrol,
538 + snd_ctl_elem_value_t * ucontrol)
540 + snd_card_bt_sco_t *bt_sco = _snd_kcontrol_chip(kcontrol);
541 + unsigned long flags;
542 + int addr = kcontrol->private_value;
544 + spin_lock_irqsave(&bt_sco->mixer_lock, flags);
545 + ucontrol->value.integer.value[0] = bt_sco->mixer_volume[addr];
546 + spin_unlock_irqrestore(&bt_sco->mixer_lock, flags);
550 +static int snd_bt_sco_volume_put(snd_kcontrol_t * kcontrol,
551 + snd_ctl_elem_value_t * ucontrol)
553 + snd_card_bt_sco_t *bt_sco = _snd_kcontrol_chip(kcontrol);
554 + unsigned long flags;
555 + int changed, addr = kcontrol->private_value;
558 + vol = ucontrol->value.integer.value[0];
559 + if (vol < MIXER_MIN_VOLUME)
560 + vol =MIXER_MIN_VOLUME;
561 + if (vol > MIXER_MAX_VOLUME)
562 + vol = MIXER_MAX_VOLUME;
563 + spin_lock_irqsave(&bt_sco->mixer_lock, flags);
564 + changed = bt_sco->mixer_volume[addr] != vol;
565 + bt_sco->mixer_volume[addr] = vol;
566 + spin_unlock_irqrestore(&bt_sco->mixer_lock, flags);
568 + spin_lock_irqsave(&bt_sco->mixer_changed_lock, flags);
569 + bt_sco->mixer_changed = 1;
570 + spin_unlock_irqrestore(&bt_sco->mixer_changed_lock, flags);
571 + wake_up(&bt_sco->hwdep_wait);
576 +static int snd_bt_sco_boolean_info(snd_kcontrol_t *kcontrol,
577 + snd_ctl_elem_info_t *uinfo)
579 + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
581 + uinfo->value.integer.min = 0;
582 + uinfo->value.integer.max = 1;
586 +static int snd_bt_sco_loopback_get(snd_kcontrol_t * kcontrol,
587 + snd_ctl_elem_value_t * ucontrol)
589 + snd_card_bt_sco_t *bt_sco = _snd_kcontrol_chip(kcontrol);
590 + unsigned long flags;
592 + spin_lock_irqsave(&bt_sco->mixer_lock, flags);
593 + ucontrol->value.integer.value[0] = bt_sco->loopback;
594 + spin_unlock_irqrestore(&bt_sco->mixer_lock, flags);
598 +static int snd_bt_sco_loopback_put(snd_kcontrol_t * kcontrol,
599 + snd_ctl_elem_value_t * ucontrol)
601 + snd_card_bt_sco_t *bt_sco = _snd_kcontrol_chip(kcontrol);
602 + unsigned long flags;
606 + loopback = !!ucontrol->value.integer.value[0];
608 + spin_lock_irqsave(&bt_sco->mixer_lock, flags);
609 + changed = bt_sco->loopback != loopback;
610 + bt_sco->loopback = loopback;
611 + spin_unlock_irqrestore(&bt_sco->mixer_lock, flags);
615 +#define BT_SCO_CONTROLS (sizeof(snd_bt_sco_controls)/sizeof(snd_kcontrol_new_t))
617 +static snd_kcontrol_new_t snd_bt_sco_controls[] = {
618 + BT_SCO_VOLUME("Master Volume", 0, MIXER_ADDR_MASTER),
619 + BT_SCO_VOLUME("Mic Volume", 0, MIXER_ADDR_MIC),
620 + { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
621 + .name = "Loopback Switch",
623 + .info = snd_bt_sco_boolean_info,
624 + .get = snd_bt_sco_loopback_get,
625 + .put = snd_bt_sco_loopback_put,
629 +int __init snd_card_bt_sco_new_mixer(snd_card_bt_sco_t *bt_sco)
631 + snd_card_t *card = bt_sco->card;
636 + snd_assert(bt_sco != NULL, return -EINVAL);
637 + spin_lock_init(&bt_sco->mixer_lock);
638 + strcpy(card->mixername, "BT Headset Mixer");
640 + for (idx = 0; idx < BT_SCO_CONTROLS; idx++) {
641 + bt_sco->mixer_controls[idx] =
642 + snd_ctl_new1(&snd_bt_sco_controls[idx],bt_sco);
644 + if ((err = snd_ctl_add(card,bt_sco->mixer_controls[idx])) < 0)
650 +static int snd_card_bt_open(snd_hwdep_t * hw, struct file *file)
655 +static int snd_card_bt_release(snd_hwdep_t * hw, struct file *file)
661 +static int snd_card_bt_ioctl(snd_hwdep_t * hw, struct file *file,
662 + unsigned int cmd, unsigned long arg)
664 + snd_card_bt_sco_t *bt_sco =
665 + snd_magic_cast(snd_card_bt_sco_t,hw->card->private_data,return -ENXIO);
666 + struct socket *sock;
671 + case SNDRV_BT_SCO_IOCTL_SET_SCO_SOCKET:
673 + /* Interrupt any socket operations, so that we may
674 + * change the socket */
675 + down(&bt_sco->sock_sem);
676 + kill_proc(bt_sco->thread_pid, SIGINT, 1);
677 + if (bt_sco->sco_sock) {
678 + dprintk("Disposing of previous socket count %d\n",file_count(bt_sco->sco_sock->file));
679 + /* Extra brackets needed here since sockfd_put is a poorly implemented macro */
680 + sockfd_put(((struct socket*) bt_sco->sco_sock));
682 + bt_sco->sco_sock = NULL;
687 + sock = sockfd_lookup(fd, &err);
689 + if (sock->sk->sk_family == PF_BLUETOOTH &&
690 + sock->sk->sk_protocol == BTPROTO_SCO) {
691 + bt_sco->sco_sock = sock;
692 + wake_up(&bt_sco->wait);
695 + dprintk("Not a bluetooth SCO socket %d:%d\n",
696 + sock->sk->sk_family,
697 + sock->sk->sk_protocol);
702 + up(&bt_sco->sock_sem);
708 +static long snd_card_bt_write(snd_hwdep_t * hw, const char *buf, long count,
711 + snd_card_bt_sco_t *bt_sco =
712 + snd_magic_cast(snd_card_bt_sco_t,hw->card->private_data,return -ENXIO);
713 + int mixer_volume[MIXER_ADDR_LAST + 1];
717 + if (count != sizeof(mixer_volume))
720 + if (copy_from_user(mixer_volume,buf,sizeof(mixer_volume)))
723 + retval = sizeof(mixer_volume);
725 + spin_lock_irq(&bt_sco->mixer_lock);
726 + for (i=0;i<=MIXER_ADDR_LAST;i++) {
727 + int vol = mixer_volume[i];
728 + if (vol>MIXER_MAX_VOLUME)
729 + vol = MIXER_MAX_VOLUME;
730 + if (vol<MIXER_MIN_VOLUME)
731 + vol = MIXER_MIN_VOLUME;
732 + if (bt_sco->mixer_volume[i] != vol) {
733 + bt_sco->mixer_volume[i] = vol;
734 + snd_ctl_notify(bt_sco->card,
735 + SNDRV_CTL_EVENT_MASK_VALUE,
736 + &bt_sco->mixer_controls[i]->id);
739 + spin_unlock_irq(&bt_sco->mixer_lock);
744 +static long snd_card_bt_read(snd_hwdep_t * hw, char *buf, long count,
747 + snd_card_bt_sco_t *bt_sco =
748 + snd_magic_cast(snd_card_bt_sco_t,hw->card->private_data,return -ENXIO);
749 + DECLARE_WAITQUEUE(wait, current);
752 + if (count != sizeof(bt_sco->mixer_volume))
755 + add_wait_queue(&bt_sco->hwdep_wait, &wait);
756 + current->state = TASK_INTERRUPTIBLE;
759 + spin_lock_irq(&bt_sco->mixer_changed_lock);
760 + changed = bt_sco->mixer_changed;
761 + bt_sco->mixer_changed = 0;
762 + spin_unlock_irq(&bt_sco->mixer_changed_lock);
767 + if (signal_pending(current)) {
768 + retval = -ERESTARTSYS;
773 + if (copy_to_user(buf, bt_sco->mixer_volume, sizeof(bt_sco->mixer_volume)))
775 + else retval = sizeof(bt_sco->mixer_volume);
778 + current->state = TASK_RUNNING;
779 + remove_wait_queue(&bt_sco->hwdep_wait, &wait);
783 +static unsigned int snd_card_bt_poll(snd_hwdep_t * hw,
787 + snd_card_bt_sco_t *bt_sco =
788 + snd_magic_cast(snd_card_bt_sco_t,hw->card->private_data,return 0);
791 + poll_wait(file, &bt_sco->hwdep_wait, wait);
793 + spin_lock_irq(&bt_sco->mixer_changed_lock);
794 + changed = bt_sco->mixer_changed;
795 + spin_unlock_irq(&bt_sco->mixer_changed_lock);
798 + return POLLIN | POLLRDNORM;
802 +static int snd_card_bt_sco_thread(void *data)
804 + snd_card_t *card = (snd_card_t *) data;
805 + snd_card_bt_sco_t *bt_sco =
806 + snd_magic_cast(snd_card_bt_sco_t,card->private_data,return 0);
807 + struct socket *sock;
809 +#define BUF_SIZE 256
810 + unsigned char buf[BUF_SIZE];
813 + sigset_t unblocked;
817 + daemonize("snd-bt-scod");
818 + sigemptyset(&unblocked);
819 + sigaddset(&unblocked,SIGINT);
820 + sigaddset(&unblocked,SIGTERM);
821 + sigprocmask(SIG_UNBLOCK, &unblocked, NULL);
823 + /* Pretend so that copy_to_user and friends work */
826 + dprintk("snd-bt-scod thread starting\n");
827 + up(&bt_sco->thread_sem);
830 + if (signal_pending(current))
831 + flush_signals(current);
833 + /* This may be woken up by a wake_up() when
834 + * a new socket is installed, or by a signal.
835 + * Signals are sent to terminate the thread,
836 + * in which case thread_exit is set, and to force
837 + * recvmesg() to wake up (from the ioctl handler)
839 + wait_event_interruptible(bt_sco->wait,
840 + bt_sco->sco_sock!=0);
841 + if (bt_sco->thread_exit)
844 + down(&bt_sco->sock_sem);
845 + sock = (struct socket*) bt_sco->sco_sock;
847 + get_file(sock->file);
848 + up(&bt_sco->sock_sem);
853 + /* We have a socket, let's read from it and write to it... */
855 + memset(&msg,0,sizeof(msg));
856 + msg.msg_iov = &iov;
857 + iov.iov_base = buf;
858 + iov.iov_len = BUF_SIZE;
860 + /* This will block until we receive data or a signal */
861 + len = sock_recvmsg(sock, &msg, BUF_SIZE, 0);
864 + down(&bt_sco->capture_sem);
865 + if (bt_sco->capture) {
866 + snd_card_bt_sco_pcm_receive
870 + up(&bt_sco->capture_sem);
872 + down(&bt_sco->playback_sem);
874 + if (bt_sco->playback || !bt_sco->loopback) {
875 + memset(buf, 0, len);
877 + /* fill with tone instead of silence */
880 + for (i=0;i<len/2;i++) {
883 + for (i=len/2;i<len;i++) {
888 + if (bt_sco->playback) {
889 + snd_card_bt_sco_pcm_send
893 + /* Strangely, when the device is open but no audio is
894 + being written by the app, there's an occasional glitch
895 + in the silence data. This hack eliminates it. */
899 + for (i=0;i<len;i++) {
906 + if (notzero>=0 && i>=len) {
910 + up(&bt_sco->playback_sem);
913 + /* This chunk of code lets us record (using arecord)
914 + what data alsa is sending out.
916 + e.g., when idle, we'd expect something like:
918 + 8080 8080 8080 8080 8483 8281 8182 8384
919 + 8080 8080 8080 8080 8080 8080 8080 8080
920 + 8080 8080 8080 8080 8483 8281 8182 8384
921 + 8080 8080 8080 8080 8080 8080 8080 8080
923 + (this is from 'xxd' of a wav file, that data in
924 + which is unsigned, whereas we are dealing with signed).
927 + down(&bt_sco->capture_sem);
928 + if (bt_sco->capture) {
929 + snd_card_bt_sco_pcm_receive
931 + "\001\002\003\004", 4);
932 + snd_card_bt_sco_pcm_receive
935 + snd_card_bt_sco_pcm_receive
937 + "\004\003\002\001", 4);
939 + up(&bt_sco->capture_sem);
942 + msg.msg_iov = &iov;
943 + iov.iov_base = buf;
944 + iov.iov_len = BUF_SIZE;
945 + sock_sendmsg(sock, &msg, len);
948 + /* Expect this to be 3 because we (this thead) have a copy,
949 + the driver process keeps one, and the app has the socket open.
951 + if (file_count(sock->file) != 3) {
952 + dprintk("file_count is %d (expected 3)\n",file_count(sock->file));
957 + } while (!bt_sco->thread_exit);
959 + dprintk("thread exiting\n");
962 + complete_and_exit(&bt_sco->thread_done, 0);
965 +static void snd_card_bt_private_free(snd_card_t * card)
967 + snd_card_bt_sco_t *bt_sco = snd_magic_cast(snd_card_bt_sco_t,card->private_data,return);
969 + dprintk("private_free, killing thread\n");
970 + bt_sco->thread_exit = 1;
971 + kill_proc(bt_sco->thread_pid, SIGTERM, 1);
972 + wait_for_completion(&bt_sco->thread_done);
973 + dprintk("private_free, thread exited\n");
975 + if (bt_sco->sco_sock) {
976 + dprintk("shutdown: freeing socket count %d\n",file_count(bt_sco->sco_sock->file));
978 + sockfd_put(((struct socket*) bt_sco->sco_sock));
981 + snd_magic_kfree(bt_sco);
984 +static int __init snd_card_bt_sco_probe(int dev)
987 + snd_card_bt_sco_t *bt_sco;
992 + snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
997 + bt_sco = snd_magic_kcalloc(snd_card_bt_sco_t, 0, GFP_KERNEL);
998 + card->private_data = bt_sco;
999 + card->private_free = snd_card_bt_private_free;
1001 + bt_sco->card = card;
1003 + init_completion(&bt_sco->thread_done);
1004 + init_MUTEX_LOCKED(&bt_sco->thread_sem);
1005 + init_MUTEX(&bt_sco->sock_sem);
1006 + init_MUTEX(&bt_sco->capture_sem);
1007 + init_MUTEX(&bt_sco->playback_sem);
1008 + init_waitqueue_head(&bt_sco->wait);
1009 + init_waitqueue_head(&bt_sco->hwdep_wait);
1010 + spin_lock_init(&bt_sco->mixer_changed_lock);
1012 + /* These clone flags copied from some other driver.
1013 + Not sure that they're really correct... */
1014 + bt_sco->thread_pid =
1015 + kernel_thread(snd_card_bt_sco_thread, card, CLONE_KERNEL);
1016 + if (bt_sco->thread_pid < 0) {
1017 + err = bt_sco->thread_pid;
1021 + down(&bt_sco->thread_sem);
1023 + if ((err = snd_card_bt_sco_pcm(bt_sco)) < 0)
1025 + if ((err = snd_card_bt_sco_new_mixer(bt_sco)) < 0)
1027 + strcpy(card->driver, "Bluetooth SCO");
1028 + strcpy(card->shortname, "BT Headset");
1029 + sprintf(card->longname, "BT Headset %i", dev + 1);
1031 + err = snd_hwdep_new(card, "BTSCO", 0, &hw);
1035 + sprintf(hw->name, "BTSCO");
1036 + hw->iface = SNDRV_HWDEP_IFACE_BT_SCO;
1037 + hw->ops.open = snd_card_bt_open;
1038 + hw->ops.ioctl = snd_card_bt_ioctl;
1039 + hw->ops.release = snd_card_bt_release;
1040 + hw->ops.read = snd_card_bt_read;
1041 + hw->ops.write = snd_card_bt_write;
1042 + hw->ops.poll = snd_card_bt_poll;
1044 + if ((err = snd_card_register(card)) == 0) {
1045 + snd_bt_sco_cards[dev] = card;
1049 + snd_card_free(card);
1053 +static int __init alsa_card_bt_sco_init(void)
1055 + printk(KERN_INFO "snd-bt-sco revision %s\n",mod_revision+11);
1057 + if (snd_card_bt_sco_probe(0) < 0) {
1060 + "Bluetooth SCO soundcard not found or device busy\n");
1067 +static void __exit alsa_card_bt_sco_exit(void)
1071 + for (idx = 0; idx < SNDRV_CARDS; idx++)
1072 + snd_card_free(snd_bt_sco_cards[idx]);
1075 +module_init(alsa_card_bt_sco_init)
1076 + module_exit(alsa_card_bt_sco_exit)
1078 +static int __init alsa_card_bt_sco_setup(char *str)
1080 + static unsigned __initdata nr_dev = 0;
1082 + if (nr_dev >= SNDRV_CARDS)
1088 +__setup("snd-bt-sco=", alsa_card_bt_sco_setup);
1090 +#endif /* ifndef MODULE */
1091 diff -urN linux/sound/bluetooth/Kconfig linux.new/sound/bluetooth/Kconfig
1092 --- linux/sound/bluetooth/Kconfig 1970-01-01 01:00:00.000000000 +0100
1093 +++ linux.new/sound/bluetooth/Kconfig 2004-08-23 18:41:39.000000000 +0200
1097 +menu "ALSA Bluetooth device"
1098 + depends on SND!=n && USB!=n
1101 + tristate "USB Bluetooth Alsa driver"
1102 + depends on SND && USB
1104 + select SND_USB_AUDIO
1106 + Say 'Y' or 'M' to include support for USB Bluetooth audio devices.
1107 + This will allow you to use a Bluetooth headset. The driver has to
1108 + be used with the btsco client program and will then create a new
1109 + ALSA device you can normally acces through plughw:Headset (see
1110 + README). You can get the client app and the driver patch from
1111 + http://www.gargan.org/linux/snd-bt-sco or maybe later from
1115 diff -urN linux/sound/bluetooth/Makefile linux.new/sound/bluetooth/Makefile
1116 --- linux/sound/bluetooth/Makefile 1970-01-01 01:00:00.000000000 +0100
1117 +++ linux.new/sound/bluetooth/Makefile 2004-07-28 13:39:50.000000000 +0200
1120 +# Makefile for ALSA
1123 +snd-bt-sco-objs := btsco.o
1125 +# Toplevel Module Dependency
1126 +obj-$(CONFIG_SND_BT_SCO) += snd-bt-sco.o
1132 +#include $(SND_TOPDIR)/toplevel.config
1133 +#include $(SND_TOPDIR)/Makefile.conf
1135 +#obj-$(CONFIG_SND_BT_SCO) += snd-bt-sco.o
1136 +#include $(SND_TOPDIR)/alsa-kernel/bluetooth/Makefile
1138 +#EXTRA_CFLAGS += -I$(SND_TOPDIR)/alsa-kernel/bluetooth
1140 +#include $(SND_TOPDIR)/Rules.make
1142 +#snd-bt-sco-objs := btsco.o
1144 +#btsco.o: ../alsa-kernel/bluetooth/btsco.c
1145 diff -urN linux/sound/Kconfig linux.new/sound/Kconfig
1146 --- linux/sound/Kconfig 2004-08-23 18:46:43.000000000 +0200
1147 +++ linux.new/sound/Kconfig 2004-08-23 18:36:41.000000000 +0200
1149 # here assuming USB is defined before ALSA
1150 source "sound/usb/Kconfig"
1152 +source "sound/bluetooth/Kconfig"
1154 # the following will depenend on the order of config.
1155 # here assuming PCMCIA is defined before ALSA
1156 source "sound/pcmcia/Kconfig"
1157 diff -urN linux/sound/Makefile linux.new/sound/Makefile
1158 --- linux/sound/Makefile 2004-08-23 18:46:43.000000000 +0200
1159 +++ linux.new/sound/Makefile 2004-08-23 19:22:46.000000000 +0200
1161 obj-$(CONFIG_SOUND) += soundcore.o
1162 obj-$(CONFIG_SOUND_PRIME) += oss/
1163 obj-$(CONFIG_DMASOUND) += oss/
1164 -obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/
1165 +obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ bluetooth/
1167 ifeq ($(CONFIG_SND),y)