]> git.pld-linux.org Git - packages/kernel.git/blob - kernel-2.6.7-8.24-08-04.patch
- replaced by linux-2.4-sfq.patch
[packages/kernel.git] / kernel-2.6.7-8.24-08-04.patch
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
4 @@ -887,8 +887,12 @@
5  
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)
16                                                 break;
17                                         size = ep->desc.wMaxPacketSize;
18  
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
22 @@ -108,9 +108,10 @@
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 */
27  
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,
31  };
32  
33  struct sndrv_hwdep_info {
34 @@ -135,7 +136,7 @@
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 */
42  };
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
46 @@ -0,0 +1,5 @@
47 +#ifndef __SOUND_BT_SCO_H
48 +#define __SOUND_BT_SCO_H
49 +
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
55 @@ -201,6 +201,8 @@
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
67 @@ -0,0 +1,1023 @@
68 +/*
69 + *  Bluetooth SCO soundcard
70 + *  Copyright (c) 2003, 2004 by Jonathan Paisley <jp@dcs.gla.ac.uk>
71 + *
72 + *  Based on dummy.c which is
73 + *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
74 + *
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.
79 + *
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.
84 + *
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
88 + *
89 + */
90 +
91 +#define chip_t snd_card_bt_sco_t
92 +
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>
106 +
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>
115 +
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}}");
121 +
122 +static char *mod_revision = "$Revision$";
123 +
124 +#undef dprintk
125 +#if 1
126 +#define dprintk(fmt...) printk(KERN_INFO "snd-bt-sco: " fmt)
127 +#else
128 +#define dprintk(fmt...) do {} while(0)
129 +#endif
130 +
131 +#define MAX_BUFFER_SIZE                (32*1024)
132 +
133 +#define MIXER_ADDR_MASTER      0
134 +#define MIXER_ADDR_MIC         1
135 +#define MIXER_ADDR_LAST                1
136 +
137 +#define MIXER_MASK_MASTER      1
138 +#define MIXER_MASK_MIC         2
139 +
140 +#define MIXER_MIN_VOLUME       1
141 +#define MIXER_MAX_VOLUME       15
142 +
143 +struct snd_card_bt_sco_pcm;
144 +
145 +typedef struct snd_card_bt_sco {
146 +       snd_card_t              *card;
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;
151 +       
152 +       spinlock_t              mixer_changed_lock;
153 +       volatile int            mixer_changed;
154 +       wait_queue_head_t       hwdep_wait;
155 +       
156 +       int                     thread_pid;
157 +       struct completion       thread_done;
158 +
159 +       volatile int            thread_exit;
160 +       struct semaphore        thread_sem;
161 +
162 +       volatile struct socket          *sco_sock;
163 +       struct semaphore        sock_sem;
164 +       wait_queue_head_t       wait;
165 +
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;
171 +
172 +typedef struct snd_card_bt_sco_pcm {
173 +       snd_card_bt_sco_t *bt_sco;
174 +       spinlock_t lock;
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;
182 +
183 +static snd_card_t *snd_bt_sco_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
184 +
185 +static int snd_card_bt_sco_playback_trigger(snd_pcm_substream_t *
186 +                                              substream, int cmd)
187 +{
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,
191 +                          return -ENXIO);
192 +       snd_card_bt_sco_t *bt_sco = snd_pcm_substream_chip(substream);
193 +
194 +       dprintk("playback_trigger %d\n", cmd);
195 +
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");
202 +       } else {
203 +               return -EINVAL;
204 +       }
205 +       return 0;
206 +}
207 +
208 +static int snd_card_bt_sco_capture_trigger(snd_pcm_substream_t *
209 +                                             substream, int cmd)
210 +{
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,
214 +                          return -ENXIO);
215 +       snd_card_bt_sco_t *bt_sco = snd_pcm_substream_chip(substream);
216 +
217 +       dprintk("capture_trigger %d\n", cmd);
218 +
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");
225 +       } else {
226 +               return -EINVAL;
227 +       }
228 +       return 0;
229 +}
230 +
231 +static int snd_card_bt_sco_pcm_prepare(snd_pcm_substream_t * substream)
232 +{
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,
236 +                          return -ENXIO);
237 +       unsigned int bps;
238 +
239 +       bps = runtime->rate * runtime->channels;
240 +       bps *= snd_pcm_format_width(runtime->format);
241 +       bps /= 8;
242 +       if (bps <= 0)
243 +               return -EINVAL;
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;
249 +       dprintk(
250 +              "prepare ok bps: %d size: %d count: %d\n",
251 +              bspcm->pcm_bps, bspcm->pcm_size,
252 +              bspcm->pcm_count);
253 +       return 0;
254 +}
255 +
256 +static int snd_card_bt_sco_playback_prepare(snd_pcm_substream_t *
257 +                                              substream)
258 +{
259 +       return snd_card_bt_sco_pcm_prepare(substream);
260 +}
261 +
262 +static int snd_card_bt_sco_capture_prepare(snd_pcm_substream_t *
263 +                                             substream)
264 +{
265 +       dprintk("capture_prepare\n");
266 +       return snd_card_bt_sco_pcm_prepare(substream);
267 +}
268 +
269 +static void snd_card_bt_sco_pcm_receive(snd_card_bt_sco_pcm_t * bspcm,
270 +                                          unsigned char *data,
271 +                                          unsigned int len)
272 +{
273 +       unsigned long flags;
274 +       unsigned int oldptr;
275 +
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,
286 +                      cnt);
287 +               memcpy(bspcm->substream->runtime->dma_area, data + cnt,
288 +                      len - cnt);
289 +       } else {
290 +               memcpy(bspcm->substream->runtime->dma_area + oldptr, data,
291 +                      len);
292 +       }
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);
299 +       } else
300 +               spin_unlock_irqrestore(&bspcm->lock, flags);
301 +
302 +}
303 +
304 +static void snd_card_bt_sco_pcm_send(snd_card_bt_sco_pcm_t * bspcm,
305 +                                       unsigned char *data,
306 +                                       unsigned int len)
307 +{
308 +       unsigned long flags;
309 +       unsigned int oldptr;
310 +
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,
321 +                      cnt);
322 +               memcpy(data + cnt, bspcm->substream->runtime->dma_area,
323 +                      len - cnt);
324 +       } else {
325 +               memcpy(data, bspcm->substream->runtime->dma_area + oldptr,
326 +                      len);
327 +       }
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);
334 +       } else
335 +               spin_unlock_irqrestore(&bspcm->lock, flags);
336 +}
337 +                    
338 +static snd_pcm_uframes_t
339 +snd_card_bt_sco_playback_pointer(snd_pcm_substream_t * substream)
340 +{
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,
344 +                          return -ENXIO);
345 +
346 +       return bytes_to_frames(runtime, bspcm->pcm_buf_pos);
347 +}
348 +
349 +static snd_pcm_uframes_t
350 +snd_card_bt_sco_capture_pointer(snd_pcm_substream_t * substream)
351 +{
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,
355 +                          return -ENXIO);
356 +
357 +       return bytes_to_frames(runtime, bspcm->pcm_buf_pos);
358 +}
359 +
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,
365 +       .rate_min = 8000,
366 +       .rate_max = 8000,
367 +       .channels_min = 1,
368 +       .channels_max = 1,
369 +       .buffer_bytes_max = MAX_BUFFER_SIZE,
370 +       .period_bytes_min = 24,
371 +       .period_bytes_max = MAX_BUFFER_SIZE,
372 +       .periods_min = 1,
373 +       .periods_max = 4*8000/24,
374 +       .fifo_size = 0,
375 +};
376 +
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,
382 +       .rate_min = 8000,
383 +       .rate_max = 8000,
384 +       .channels_min = 1,
385 +       .channels_max = 1,
386 +       .buffer_bytes_max = MAX_BUFFER_SIZE,
387 +       .period_bytes_min = 24,
388 +       .period_bytes_max = MAX_BUFFER_SIZE,
389 +       .periods_min = 1,
390 +       .periods_max = 4*8000/24,
391 +       .fifo_size = 0,
392 +};
393 +
394 +static void snd_card_bt_sco_runtime_free(snd_pcm_runtime_t * runtime)
395 +{
396 +       snd_card_bt_sco_pcm_t *bspcm =
397 +           snd_magic_cast(snd_card_bt_sco_pcm_t, runtime->private_data,
398 +                          return);
399 +       snd_magic_kfree(bspcm);
400 +}
401 +
402 +static int snd_card_bt_sco_playback_open(snd_pcm_substream_t *
403 +                                           substream)
404 +{
405 +       snd_pcm_runtime_t *runtime = substream->runtime;
406 +       snd_card_bt_sco_pcm_t *bspcm;
407 +
408 +       dprintk("playback_open\n");
409 +       
410 +       bspcm = snd_magic_kcalloc(snd_card_bt_sco_pcm_t, 0, GFP_KERNEL);
411 +       if (bspcm == NULL)
412 +               return -ENOMEM;
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);
417 +               return -ENOMEM;
418 +       }
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;
424 +       return 0;
425 +}
426 +
427 +static int snd_card_bt_sco_capture_open(snd_pcm_substream_t * substream)
428 +{
429 +       snd_pcm_runtime_t *runtime = substream->runtime;
430 +       snd_card_bt_sco_pcm_t *bspcm;
431 +
432 +       dprintk("capture_open\n");
433 +
434 +       bspcm = snd_magic_kcalloc(snd_card_bt_sco_pcm_t, 0, GFP_KERNEL);
435 +       if (bspcm == NULL)
436 +               return -ENOMEM;
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);
441 +               return -ENOMEM;
442 +       }
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;
449 +       return 0;
450 +}
451 +
452 +static int snd_card_bt_sco_playback_close(snd_pcm_substream_t *
453 +                                            substream)
454 +{
455 +       snd_pcm_runtime_t *runtime = substream->runtime;
456 +       snd_card_bt_sco_t *bt_sco = snd_pcm_substream_chip(substream);
457 +
458 +       snd_assert(bt_sco->playback == NULL, ;);
459 +       
460 +       /* Ensure any references to this in our thread have finished */
461 +       down(&bt_sco->playback_sem);
462 +       up(&bt_sco->playback_sem);
463 +
464 +       snd_free_pages(runtime->dma_area, runtime->dma_bytes);
465 +       return 0;
466 +}
467 +
468 +static int snd_card_bt_sco_capture_close(snd_pcm_substream_t *
469 +                                           substream)
470 +{
471 +       snd_pcm_runtime_t *runtime = substream->runtime;
472 +       struct snd_card_bt_sco *bt_sco = (struct snd_card_bt_sco *) substream->private_data;
473 +
474 +       snd_assert(bt_sco->capture == NULL, ;);
475 +
476 +       /* Ensure any references to this in our thread have finished */
477 +       down(&bt_sco->capture_sem);
478 +       up(&bt_sco->capture_sem);
479 +
480 +       snd_free_pages(runtime->dma_area, runtime->dma_bytes);
481 +       return 0;
482 +}
483 +
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,
491 +};
492 +
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,
500 +};
501 +
502 +static int __init snd_card_bt_sco_pcm(snd_card_bt_sco_t * bt_sco)
503 +{
504 +       snd_pcm_t *pcm;
505 +       int err;
506 +
507 +       if ((err =
508 +            snd_pcm_new(bt_sco->card, "Bluetooth SCO PCM", 0, 1, 1,
509 +                        &pcm)) < 0)
510 +               return err;
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");
518 +       return 0;
519 +}
520 +
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 }
526 +
527 +static int snd_bt_sco_volume_info(snd_kcontrol_t * kcontrol,
528 +                                    snd_ctl_elem_info_t * uinfo)
529 +{
530 +       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
531 +       uinfo->count = 1;
532 +       uinfo->value.integer.min = MIXER_MIN_VOLUME;
533 +       uinfo->value.integer.max = MIXER_MAX_VOLUME;
534 +       return 0;
535 +}
536 +
537 +static int snd_bt_sco_volume_get(snd_kcontrol_t * kcontrol,
538 +                                   snd_ctl_elem_value_t * ucontrol)
539 +{
540 +       snd_card_bt_sco_t *bt_sco = _snd_kcontrol_chip(kcontrol);
541 +       unsigned long flags;
542 +       int addr = kcontrol->private_value;
543 +
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);
547 +       return 0;
548 +}
549 +
550 +static int snd_bt_sco_volume_put(snd_kcontrol_t * kcontrol,
551 +                                   snd_ctl_elem_value_t * ucontrol)
552 +{
553 +       snd_card_bt_sco_t *bt_sco = _snd_kcontrol_chip(kcontrol);
554 +       unsigned long flags;
555 +       int changed, addr = kcontrol->private_value;
556 +       int vol;
557 +
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);
567 +       if (changed) {
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);
572 +       }
573 +       return changed;
574 +}
575 +
576 +static int snd_bt_sco_boolean_info(snd_kcontrol_t *kcontrol,
577 +                          snd_ctl_elem_info_t *uinfo)
578 +{
579 +       uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
580 +       uinfo->count = 1;
581 +       uinfo->value.integer.min = 0;
582 +       uinfo->value.integer.max = 1;
583 +       return 0;
584 +}
585 +
586 +static int snd_bt_sco_loopback_get(snd_kcontrol_t * kcontrol,
587 +                                   snd_ctl_elem_value_t * ucontrol)
588 +{
589 +       snd_card_bt_sco_t *bt_sco = _snd_kcontrol_chip(kcontrol);
590 +       unsigned long flags;
591 +
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);
595 +       return 0;
596 +}
597 +
598 +static int snd_bt_sco_loopback_put(snd_kcontrol_t * kcontrol,
599 +                                   snd_ctl_elem_value_t * ucontrol)
600 +{
601 +       snd_card_bt_sco_t *bt_sco = _snd_kcontrol_chip(kcontrol);
602 +       unsigned long flags;
603 +       int changed;
604 +       int loopback;
605 +
606 +       loopback = !!ucontrol->value.integer.value[0];
607 +       
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);
612 +       return changed;
613 +}
614 +
615 +#define BT_SCO_CONTROLS (sizeof(snd_bt_sco_controls)/sizeof(snd_kcontrol_new_t))
616 +
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",
622 +               .index = 0, 
623 +                .info = snd_bt_sco_boolean_info,
624 +                .get = snd_bt_sco_loopback_get,
625 +               .put = snd_bt_sco_loopback_put,
626 +       }
627 +};
628 +
629 +int __init snd_card_bt_sco_new_mixer(snd_card_bt_sco_t *bt_sco)
630 +{
631 +       snd_card_t *card = bt_sco->card;
632 +       
633 +       unsigned int idx;
634 +       int err;
635 +
636 +       snd_assert(bt_sco != NULL, return -EINVAL);
637 +       spin_lock_init(&bt_sco->mixer_lock);
638 +       strcpy(card->mixername, "BT Headset Mixer");
639 +
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);
643 +       
644 +               if ((err = snd_ctl_add(card,bt_sco->mixer_controls[idx])) < 0)
645 +                       return err;
646 +       }
647 +       return 0;
648 +}
649 +
650 +static int snd_card_bt_open(snd_hwdep_t * hw, struct file *file)
651 +{
652 +       return 0;
653 +}
654 +
655 +static int snd_card_bt_release(snd_hwdep_t * hw, struct file *file)
656 +{
657 +       return 0;
658 +}
659 +
660 +
661 +static int snd_card_bt_ioctl(snd_hwdep_t * hw, struct file *file,
662 +                               unsigned int cmd, unsigned long arg)
663 +{
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;
667 +       int err = -EINVAL;
668 +       int fd = arg;
669 +
670 +       switch (cmd) {
671 +       case SNDRV_BT_SCO_IOCTL_SET_SCO_SOCKET:
672 +               err = 0;
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));
681 +
682 +                       bt_sco->sco_sock = NULL;
683 +               }
684 +               
685 +               if (fd>=0) {
686 +                       err = -EINVAL;
687 +                       sock = sockfd_lookup(fd, &err);
688 +                       if (sock) {
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);
693 +                                       err = 0;
694 +                               } else {
695 +                                       dprintk("Not a bluetooth SCO socket %d:%d\n",
696 +                                               sock->sk->sk_family,
697 +                                               sock->sk->sk_protocol);
698 +                                       sockfd_put(sock);
699 +                               }
700 +                       }
701 +               }
702 +               up(&bt_sco->sock_sem);
703 +               break;
704 +       }
705 +       return err;
706 +}
707 +
708 +static long snd_card_bt_write(snd_hwdep_t * hw, const char *buf, long count,
709 +                               loff_t * offset)
710 +{
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];
714 +       int retval;
715 +       int i;
716 +       
717 +       if (count != sizeof(mixer_volume))
718 +               return -EINVAL;
719 +       
720 +       if (copy_from_user(mixer_volume,buf,sizeof(mixer_volume)))
721 +               return -EFAULT;
722 +               
723 +       retval = sizeof(mixer_volume);
724 +               
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);
737 +               }
738 +       }
739 +       spin_unlock_irq(&bt_sco->mixer_lock);
740 +       
741 +       return retval;
742 +}
743 +
744 +static long snd_card_bt_read(snd_hwdep_t * hw, char *buf, long count,
745 +                               loff_t * offset)
746 +{
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);
750 +       ssize_t retval;
751 +
752 +       if (count != sizeof(bt_sco->mixer_volume))
753 +               return -EINVAL;
754 +
755 +       add_wait_queue(&bt_sco->hwdep_wait, &wait);
756 +       current->state = TASK_INTERRUPTIBLE;
757 +       do {
758 +               int changed;
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);
763 +
764 +               if (changed != 0)
765 +                       break;
766 +
767 +               if (signal_pending(current)) {
768 +                       retval = -ERESTARTSYS;
769 +                       goto out;
770 +               }
771 +               schedule();
772 +       } while (1);
773 +       if (copy_to_user(buf, bt_sco->mixer_volume, sizeof(bt_sco->mixer_volume)))
774 +               retval = -EFAULT;
775 +       else    retval = sizeof(bt_sco->mixer_volume);
776 +       
777 +      out:
778 +       current->state = TASK_RUNNING;
779 +       remove_wait_queue(&bt_sco->hwdep_wait, &wait);
780 +       return retval;
781 +}
782 +
783 +static unsigned int snd_card_bt_poll(snd_hwdep_t * hw,
784 +                                       struct file *file,
785 +                                       poll_table * wait)
786 +{
787 +       snd_card_bt_sco_t *bt_sco = 
788 +               snd_magic_cast(snd_card_bt_sco_t,hw->card->private_data,return 0);
789 +       int changed;
790 +
791 +       poll_wait(file, &bt_sco->hwdep_wait, wait);
792 +
793 +       spin_lock_irq(&bt_sco->mixer_changed_lock);
794 +       changed = bt_sco->mixer_changed;
795 +       spin_unlock_irq(&bt_sco->mixer_changed_lock);
796 +
797 +       if (changed != 0)
798 +               return POLLIN | POLLRDNORM;
799 +       return 0;
800 +}
801 +
802 +static int snd_card_bt_sco_thread(void *data)
803 +{
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;
808 +       int len;
809 +#define BUF_SIZE 256
810 +       unsigned char buf[BUF_SIZE];
811 +       struct msghdr msg;
812 +       struct iovec iov;
813 +       sigset_t unblocked;
814 +               
815 +       lock_kernel();
816 +
817 +       daemonize("snd-bt-scod");
818 +       sigemptyset(&unblocked);
819 +       sigaddset(&unblocked,SIGINT);
820 +       sigaddset(&unblocked,SIGTERM);
821 +       sigprocmask(SIG_UNBLOCK, &unblocked, NULL);
822 +
823 +       /* Pretend so that copy_to_user and friends work */
824 +       set_fs(KERNEL_DS);
825 +
826 +       dprintk("snd-bt-scod thread starting\n");
827 +       up(&bt_sco->thread_sem);
828 +
829 +       do {
830 +               if (signal_pending(current))
831 +                       flush_signals(current);
832 +
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)
838 +                */
839 +               wait_event_interruptible(bt_sco->wait,
840 +                       bt_sco->sco_sock!=0);
841 +               if (bt_sco->thread_exit)
842 +                       break;
843 +
844 +               down(&bt_sco->sock_sem);
845 +               sock = (struct socket*) bt_sco->sco_sock;
846 +               if (sock)
847 +                   get_file(sock->file);
848 +               up(&bt_sco->sock_sem);
849 +
850 +               if (!sock)
851 +                   continue;
852 +
853 +               /* We have a socket, let's read from it and write to it... */
854 +
855 +               memset(&msg,0,sizeof(msg));
856 +               msg.msg_iov = &iov;
857 +               iov.iov_base = buf;
858 +               iov.iov_len = BUF_SIZE;
859 +               
860 +               /* This will block until we receive data or a signal */
861 +               len = sock_recvmsg(sock, &msg, BUF_SIZE, 0);
862 +               if (len > 0) {
863 +
864 +                       down(&bt_sco->capture_sem);
865 +                       if (bt_sco->capture) {
866 +                               snd_card_bt_sco_pcm_receive
867 +                                   (bt_sco->capture,
868 +                                    buf, len);
869 +                       }
870 +                       up(&bt_sco->capture_sem);
871 +
872 +                       down(&bt_sco->playback_sem);
873 +                                               
874 +                       if (bt_sco->playback || !bt_sco->loopback) {
875 +                               memset(buf, 0, len);
876 +#if 0
877 +                               /* fill with tone instead of silence */
878 +                               int i;
879 +                               
880 +                               for (i=0;i<len/2;i++) {
881 +                                   buf[i] = 0;
882 +                               }
883 +                               for (i=len/2;i<len;i++) {
884 +                                   buf[i] = 127;
885 +                               }
886 +#endif
887 +                       }
888 +                       if (bt_sco->playback) {
889 +                               snd_card_bt_sco_pcm_send
890 +                                   (bt_sco->playback,
891 +                                    buf, len);
892 +                               
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. */
896 +                               
897 +                               int i;
898 +                               int notzero=-1;
899 +                               for (i=0;i<len;i++) {
900 +                                   if (buf[i]!=0) {
901 +                                       if (notzero>=0)
902 +                                           break;
903 +                                       notzero = i;
904 +                                   }   
905 +                               }
906 +                               if (notzero>=0 && i>=len) {
907 +                                   buf[notzero] = 0;
908 +                               }
909 +                       }
910 +                       up(&bt_sco->playback_sem);
911 +                       
912 +#if 0
913 +                       /* This chunk of code lets us record (using arecord)
914 +                          what data alsa is sending out.
915 +                          
916 +                          e.g., when idle, we'd expect something like:
917 +                          
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
922 +                               
923 +                          (this is from 'xxd' of a wav file, that data in
924 +                          which is unsigned, whereas we are dealing with signed).
925 +                        */
926 +                               
927 +                       down(&bt_sco->capture_sem);
928 +                       if (bt_sco->capture) {
929 +                               snd_card_bt_sco_pcm_receive
930 +                                   (bt_sco->capture,
931 +                                    "\001\002\003\004", 4);
932 +                               snd_card_bt_sco_pcm_receive
933 +                                   (bt_sco->capture,
934 +                                    buf, len);
935 +                               snd_card_bt_sco_pcm_receive
936 +                                   (bt_sco->capture,
937 +                                    "\004\003\002\001", 4);
938 +                       }
939 +                       up(&bt_sco->capture_sem);
940 +#endif
941 +                       msg.msg_flags = 0;
942 +                       msg.msg_iov = &iov;
943 +                       iov.iov_base = buf;
944 +                       iov.iov_len = BUF_SIZE;
945 +                       sock_sendmsg(sock, &msg, len);
946 +               }
947 +
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.
950 +                  */
951 +               if (file_count(sock->file) != 3) {
952 +                       dprintk("file_count is %d (expected 3)\n",file_count(sock->file));
953 +               }
954 +               fput(sock->file);
955 +
956 +               schedule();
957 +       } while (!bt_sco->thread_exit);
958 +
959 +       dprintk("thread exiting\n");
960 +
961 +       unlock_kernel();
962 +       complete_and_exit(&bt_sco->thread_done, 0);
963 +}
964 +
965 +static void snd_card_bt_private_free(snd_card_t * card)
966 +{
967 +       snd_card_bt_sco_t *bt_sco = snd_magic_cast(snd_card_bt_sco_t,card->private_data,return);
968 +
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");
974 +
975 +       if (bt_sco->sco_sock) {
976 +               dprintk("shutdown: freeing socket count %d\n",file_count(bt_sco->sco_sock->file));
977 +               
978 +               sockfd_put(((struct socket*) bt_sco->sco_sock));
979 +       }
980 +       
981 +       snd_magic_kfree(bt_sco);
982 +}
983 +
984 +static int __init snd_card_bt_sco_probe(int dev)
985 +{
986 +       snd_card_t *card;
987 +       snd_card_bt_sco_t *bt_sco;
988 +       int err;
989 +       snd_hwdep_t *hw;
990 +
991 +       card =
992 +           snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
993 +                        THIS_MODULE, 0);
994 +       if (card == NULL)
995 +               return -ENOMEM;
996 +               
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;
1000 +
1001 +       bt_sco->card = card;
1002 +
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);
1011 +
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;
1018 +               goto __nodev;
1019 +       }
1020 +
1021 +       down(&bt_sco->thread_sem);
1022 +
1023 +       if ((err = snd_card_bt_sco_pcm(bt_sco)) < 0)
1024 +               goto __nodev;
1025 +       if ((err = snd_card_bt_sco_new_mixer(bt_sco)) < 0)
1026 +               goto __nodev;
1027 +       strcpy(card->driver, "Bluetooth SCO");
1028 +       strcpy(card->shortname, "BT Headset");
1029 +       sprintf(card->longname, "BT Headset %i", dev + 1);
1030 +
1031 +       err = snd_hwdep_new(card, "BTSCO", 0, &hw);
1032 +       if (err < 0)
1033 +               goto __nodev;
1034 +
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;
1043 +
1044 +       if ((err = snd_card_register(card)) == 0) {
1045 +               snd_bt_sco_cards[dev] = card;
1046 +               return 0;
1047 +       }
1048 +      __nodev:
1049 +       snd_card_free(card);
1050 +       return err;
1051 +}
1052 +
1053 +static int __init alsa_card_bt_sco_init(void)
1054 +{
1055 +       printk(KERN_INFO "snd-bt-sco revision %s\n",mod_revision+11);
1056 +       
1057 +       if (snd_card_bt_sco_probe(0) < 0) {
1058 +#ifdef MODULE
1059 +               printk(KERN_ERR
1060 +                      "Bluetooth SCO soundcard not found or device busy\n");
1061 +#endif
1062 +               return -ENODEV;
1063 +       }
1064 +       return 0;
1065 +}
1066 +
1067 +static void __exit alsa_card_bt_sco_exit(void)
1068 +{
1069 +       int idx;
1070 +
1071 +       for (idx = 0; idx < SNDRV_CARDS; idx++)
1072 +               snd_card_free(snd_bt_sco_cards[idx]);
1073 +}
1074 +
1075 +module_init(alsa_card_bt_sco_init)
1076 +    module_exit(alsa_card_bt_sco_exit)
1077 +#ifndef MODULE
1078 +static int __init alsa_card_bt_sco_setup(char *str)
1079 +{
1080 +       static unsigned __initdata nr_dev = 0;
1081 +
1082 +       if (nr_dev >= SNDRV_CARDS)
1083 +               return 0;
1084 +       nr_dev++;
1085 +       return 1;
1086 +}
1087 +
1088 +__setup("snd-bt-sco=", alsa_card_bt_sco_setup);
1089 +
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
1094 @@ -0,0 +1,20 @@
1095 +# ALSA USB drivers
1096 +
1097 +menu "ALSA Bluetooth device"
1098 +       depends on SND!=n && USB!=n
1099 +
1100 +config SND_BT_SCO
1101 +       tristate "USB Bluetooth Alsa driver"
1102 +       depends on SND && USB
1103 +       select SND_HWDEP
1104 +       select SND_USB_AUDIO
1105 +       help
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
1112 +         sourceforge.
1113 +         
1114 +endmenu
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
1118 @@ -0,0 +1,26 @@
1119 +#
1120 +# Makefile for ALSA
1121 +#
1122 +
1123 +snd-bt-sco-objs := btsco.o
1124 +
1125 +# Toplevel Module Dependency
1126 +obj-$(CONFIG_SND_BT_SCO) += snd-bt-sco.o
1127 +
1128 +#ifndef SND_TOPDIR
1129 +#SND_TOPDIR=..
1130 +#endif
1131 +
1132 +#include $(SND_TOPDIR)/toplevel.config
1133 +#include $(SND_TOPDIR)/Makefile.conf
1134 +
1135 +#obj-$(CONFIG_SND_BT_SCO) += snd-bt-sco.o
1136 +#include $(SND_TOPDIR)/alsa-kernel/bluetooth/Makefile
1137 +#
1138 +#EXTRA_CFLAGS += -I$(SND_TOPDIR)/alsa-kernel/bluetooth
1139 +#
1140 +#include $(SND_TOPDIR)/Rules.make
1141 +#
1142 +#snd-bt-sco-objs := btsco.o
1143 +#
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
1148 @@ -59,6 +59,8 @@
1149  # here assuming USB is defined before ALSA
1150  source "sound/usb/Kconfig"
1151  
1152 +source "sound/bluetooth/Kconfig"
1153 +
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
1160 @@ -4,7 +4,7 @@
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/
1166  
1167  ifeq ($(CONFIG_SND),y)
1168    obj-y += last.o
This page took 0.156784 seconds and 3 git commands to generate.