string: factorize skip_spaces and export it to be generally available
[safe/jmp/linux-2.6] / sound / core / pcm.c
index 97cb681..6884ae0 100644 (file)
@@ -19,7 +19,6 @@
  *
  */
 
-#include <sound/driver.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/time.h>
@@ -43,7 +42,7 @@ static int snd_pcm_dev_free(struct snd_device *device);
 static int snd_pcm_dev_register(struct snd_device *device);
 static int snd_pcm_dev_disconnect(struct snd_device *device);
 
-static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device)
+static struct snd_pcm *snd_pcm_get(struct snd_card *card, int device)
 {
        struct snd_pcm *pcm;
 
@@ -54,6 +53,37 @@ static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device)
        return NULL;
 }
 
+static int snd_pcm_next(struct snd_card *card, int device)
+{
+       struct snd_pcm *pcm;
+
+       list_for_each_entry(pcm, &snd_pcm_devices, list) {
+               if (pcm->card == card && pcm->device > device)
+                       return pcm->device;
+               else if (pcm->card->number > card->number)
+                       return -1;
+       }
+       return -1;
+}
+
+static int snd_pcm_add(struct snd_pcm *newpcm)
+{
+       struct snd_pcm *pcm;
+
+       list_for_each_entry(pcm, &snd_pcm_devices, list) {
+               if (pcm->card == newpcm->card && pcm->device == newpcm->device)
+                       return -EBUSY;
+               if (pcm->card->number > newpcm->card->number ||
+                               (pcm->card == newpcm->card &&
+                               pcm->device > newpcm->device)) {
+                       list_add(&newpcm->list, pcm->list.prev);
+                       return 0;
+               }
+       }
+       list_add_tail(&newpcm->list, &snd_pcm_devices);
+       return 0;
+}
+
 static int snd_pcm_control_ioctl(struct snd_card *card,
                                 struct snd_ctl_file *control,
                                 unsigned int cmd, unsigned long arg)
@@ -66,14 +96,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
                        if (get_user(device, (int __user *)arg))
                                return -EFAULT;
                        mutex_lock(&register_mutex);
-                       device = device < 0 ? 0 : device + 1;
-                       while (device < SNDRV_PCM_DEVICES) {
-                               if (snd_pcm_search(card, device))
-                                       break;
-                               device++;
-                       }
-                       if (device == SNDRV_PCM_DEVICES)
-                               device = -1;
+                       device = snd_pcm_next(card, device);
                        mutex_unlock(&register_mutex);
                        if (put_user(device, (int __user *)arg))
                                return -EFAULT;
@@ -99,7 +122,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
                        if (get_user(subdevice, &info->subdevice))
                                return -EFAULT;
                        mutex_lock(&register_mutex);
-                       pcm = snd_pcm_search(card, device);
+                       pcm = snd_pcm_get(card, device);
                        if (pcm == NULL) {
                                err = -ENXIO;
                                goto _error;
@@ -139,18 +162,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
        return -ENOIOCTLCMD;
 }
 
-#ifdef CONFIG_SND_VERBOSE_PROCFS
-
-#define STATE(v) [SNDRV_PCM_STATE_##v] = #v
-#define STREAM(v) [SNDRV_PCM_STREAM_##v] = #v
-#define READY(v) [SNDRV_PCM_READY_##v] = #v
-#define XRUN(v) [SNDRV_PCM_XRUN_##v] = #v
-#define SILENCE(v) [SNDRV_PCM_SILENCE_##v] = #v
-#define TSTAMP(v) [SNDRV_PCM_TSTAMP_##v] = #v
-#define ACCESS(v) [SNDRV_PCM_ACCESS_##v] = #v
-#define START(v) [SNDRV_PCM_START_##v] = #v
 #define FORMAT(v) [SNDRV_PCM_FORMAT_##v] = #v
-#define SUBFORMAT(v) [SNDRV_PCM_SUBFORMAT_##v] = #v 
 
 static char *snd_pcm_format_names[] = {
        FORMAT(S8),
@@ -193,10 +205,23 @@ static char *snd_pcm_format_names[] = {
        FORMAT(U18_3BE),
 };
 
-static const char *snd_pcm_format_name(snd_pcm_format_t format)
+const char *snd_pcm_format_name(snd_pcm_format_t format)
 {
        return snd_pcm_format_names[format];
 }
+EXPORT_SYMBOL_GPL(snd_pcm_format_name);
+
+#ifdef CONFIG_SND_VERBOSE_PROCFS
+
+#define STATE(v) [SNDRV_PCM_STATE_##v] = #v
+#define STREAM(v) [SNDRV_PCM_STREAM_##v] = #v
+#define READY(v) [SNDRV_PCM_READY_##v] = #v
+#define XRUN(v) [SNDRV_PCM_XRUN_##v] = #v
+#define SILENCE(v) [SNDRV_PCM_SILENCE_##v] = #v
+#define TSTAMP(v) [SNDRV_PCM_TSTAMP_##v] = #v
+#define ACCESS(v) [SNDRV_PCM_ACCESS_##v] = #v
+#define START(v) [SNDRV_PCM_START_##v] = #v
+#define SUBFORMAT(v) [SNDRV_PCM_SUBFORMAT_##v] = #v 
 
 static char *snd_pcm_stream_names[] = {
        STREAM(PLAYBACK),
@@ -228,12 +253,11 @@ static char *snd_pcm_subformat_names[] = {
 
 static char *snd_pcm_tstamp_mode_names[] = {
        TSTAMP(NONE),
-       TSTAMP(MMAP),
+       TSTAMP(ENABLE),
 };
 
 static const char *snd_pcm_stream_name(int stream)
 {
-       snd_assert(stream <= SNDRV_PCM_STREAM_LAST, return NULL);
        return snd_pcm_stream_names[stream];
 }
 
@@ -249,7 +273,6 @@ static const char *snd_pcm_subformat_name(snd_pcm_subformat_t subformat)
 
 static const char *snd_pcm_tstamp_mode_name(int mode)
 {
-       snd_assert(mode <= SNDRV_PCM_TSTAMP_LAST, return NULL);
        return snd_pcm_tstamp_mode_names[mode];
 }
 
@@ -359,7 +382,6 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry,
        snd_iprintf(buffer, "rate: %u (%u/%u)\n", runtime->rate, runtime->rate_num, runtime->rate_den); 
        snd_iprintf(buffer, "period_size: %lu\n", runtime->period_size);        
        snd_iprintf(buffer, "buffer_size: %lu\n", runtime->buffer_size);        
-       snd_iprintf(buffer, "tick_time: %u\n", runtime->tick_time);
 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
        if (substream->oss.oss) {
                snd_iprintf(buffer, "OSS format: %s\n", snd_pcm_oss_format_name(runtime->oss.format));
@@ -387,7 +409,6 @@ static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,
        }
        snd_iprintf(buffer, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(runtime->tstamp_mode));
        snd_iprintf(buffer, "period_step: %u\n", runtime->period_step);
-       snd_iprintf(buffer, "sleep_min: %u\n", runtime->sleep_min);
        snd_iprintf(buffer, "avail_min: %lu\n", runtime->control->avail_min);
        snd_iprintf(buffer, "start_threshold: %lu\n", runtime->start_threshold);
        snd_iprintf(buffer, "stop_threshold: %lu\n", runtime->stop_threshold);
@@ -414,6 +435,7 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
                return;
        }
        snd_iprintf(buffer, "state: %s\n", snd_pcm_state_name(status.state));
+       snd_iprintf(buffer, "owner_pid   : %d\n", pid_vnr(substream->pid));
        snd_iprintf(buffer, "trigger_time: %ld.%09ld\n",
                status.trigger_tstamp.tv_sec, status.trigger_tstamp.tv_nsec);
        snd_iprintf(buffer, "tstamp      : %ld.%09ld\n",
@@ -648,7 +670,6 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
                spin_lock_init(&substream->self_group.lock);
                INIT_LIST_HEAD(&substream->self_group.substreams);
                list_add_tail(&substream->link_list, &substream->self_group.substreams);
-               spin_lock_init(&substream->timer_lock);
                atomic_set(&substream->mmap_count, 0);
                prev = substream;
        }
@@ -673,7 +694,7 @@ EXPORT_SYMBOL(snd_pcm_new_stream);
  *
  * Returns zero if successful, or a negative error code on failure.
  */
-int snd_pcm_new(struct snd_card *card, char *id, int device,
+int snd_pcm_new(struct snd_card *card, const char *id, int device,
                int playback_count, int capture_count,
                struct snd_pcm ** rpcm)
 {
@@ -685,9 +706,10 @@ int snd_pcm_new(struct snd_card *card, char *id, int device,
                .dev_disconnect = snd_pcm_dev_disconnect,
        };
 
-       snd_assert(rpcm != NULL, return -EINVAL);
-       *rpcm = NULL;
-       snd_assert(card != NULL, return -ENXIO);
+       if (snd_BUG_ON(!card))
+               return -ENXIO;
+       if (rpcm)
+               *rpcm = NULL;
        pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
        if (pcm == NULL) {
                snd_printk(KERN_ERR "Cannot allocate PCM\n");
@@ -711,7 +733,8 @@ int snd_pcm_new(struct snd_card *card, char *id, int device,
                snd_pcm_free(pcm);
                return err;
        }
-       *rpcm = pcm;
+       if (rpcm)
+               *rpcm = pcm;
        return 0;
 }
 
@@ -745,7 +768,8 @@ static int snd_pcm_free(struct snd_pcm *pcm)
 {
        struct snd_pcm_notify *notify;
 
-       snd_assert(pcm != NULL, return -ENXIO);
+       if (!pcm)
+               return 0;
        list_for_each_entry(notify, &snd_pcm_notify_list, list) {
                notify->n_unregister(pcm);
        }
@@ -764,12 +788,6 @@ static int snd_pcm_dev_free(struct snd_device *device)
        return snd_pcm_free(pcm);
 }
 
-static void snd_pcm_tick_timer_func(unsigned long data)
-{
-       struct snd_pcm_substream *substream = (struct snd_pcm_substream *) data;
-       snd_pcm_tick_elapsed(substream);
-}
-
 int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
                             struct file *file,
                             struct snd_pcm_substream **rsubstream)
@@ -782,23 +800,23 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
        int prefer_subdevice = -1;
        size_t size;
 
-       snd_assert(rsubstream != NULL, return -EINVAL);
+       if (snd_BUG_ON(!pcm || !rsubstream))
+               return -ENXIO;
        *rsubstream = NULL;
-       snd_assert(pcm != NULL, return -ENXIO);
        pstr = &pcm->streams[stream];
        if (pstr->substream == NULL || pstr->substream_count == 0)
                return -ENODEV;
 
        card = pcm->card;
-       down_read(&card->controls_rwsem);
+       read_lock(&card->ctl_files_rwlock);
        list_for_each_entry(kctl, &card->ctl_files, list) {
-               if (kctl->pid == current->pid) {
+               if (kctl->pid == task_pid(current)) {
                        prefer_subdevice = kctl->prefer_pcm_subdevice;
                        if (prefer_subdevice != -1)
                                break;
                }
        }
-       up_read(&card->controls_rwsem);
+       read_unlock(&card->ctl_files_rwlock);
 
        switch (stream) {
        case SNDRV_PCM_STREAM_PLAYBACK:
@@ -876,9 +894,6 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
        memset((void*)runtime->control, 0, size);
 
        init_waitqueue_head(&runtime->sleep);
-       init_timer(&runtime->tick_timer);
-       runtime->tick_timer.function = snd_pcm_tick_timer_func;
-       runtime->tick_timer.data = (unsigned long) substream;
 
        runtime->status->state = SNDRV_PCM_STATE_OPEN;
 
@@ -886,6 +901,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
        substream->private_data = pcm->private_data;
        substream->ref_count = 1;
        substream->f_flags = file->f_flags;
+       substream->pid = get_pid(task_pid(current));
        pstr->substream_opened++;
        *rsubstream = substream;
        return 0;
@@ -895,8 +911,9 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime;
 
+       if (PCM_RUNTIME_CHECK(substream))
+               return;
        runtime = substream->runtime;
-       snd_assert(runtime != NULL, return);
        if (runtime->private_free != NULL)
                runtime->private_free(runtime);
        snd_free_pages((void*)runtime->status,
@@ -906,6 +923,8 @@ void snd_pcm_detach_substream(struct snd_pcm_substream *substream)
        kfree(runtime->hw_constraints.rules);
        kfree(runtime);
        substream->runtime = NULL;
+       put_pid(substream->pid);
+       substream->pid = NULL;
        substream->pstr->substream_opened--;
 }
 
@@ -938,16 +957,18 @@ static int snd_pcm_dev_register(struct snd_device *device)
        struct snd_pcm_substream *substream;
        struct snd_pcm_notify *notify;
        char str[16];
-       struct snd_pcm *pcm = device->device_data;
+       struct snd_pcm *pcm;
        struct device *dev;
 
-       snd_assert(pcm != NULL && device != NULL, return -ENXIO);
+       if (snd_BUG_ON(!device || !device->device_data))
+               return -ENXIO;
+       pcm = device->device_data;
        mutex_lock(&register_mutex);
-       if (snd_pcm_search(pcm->card, pcm->device)) {
+       err = snd_pcm_add(pcm);
+       if (err) {
                mutex_unlock(&register_mutex);
-               return -EBUSY;
+               return err;
        }
-       list_add_tail(&pcm->list, &snd_pcm_devices);
        for (cidx = 0; cidx < 2; cidx++) {
                int devtype = -1;
                if (pcm->streams[cidx].substream == NULL)
@@ -1031,10 +1052,11 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
 {
        struct snd_pcm *pcm;
 
-       snd_assert(notify != NULL &&
-                  notify->n_register != NULL &&
-                  notify->n_unregister != NULL &&
-                  notify->n_disconnect, return -EINVAL);
+       if (snd_BUG_ON(!notify ||
+                      !notify->n_register ||
+                      !notify->n_unregister ||
+                      !notify->n_disconnect))
+               return -EINVAL;
        mutex_lock(&register_mutex);
        if (nfree) {
                list_del(&notify->list);