]> git.hungrycats.org Git - linux/commitdiff
Fix up sound driver proc-reading interfaces.
authorLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 9 Aug 2004 09:09:47 +0000 (02:09 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 9 Aug 2004 09:09:47 +0000 (02:09 -0700)
The old ones were not only hard to use, they were in fact
impossible or a low-level sound driver to get right, since
the core sound code didn't even export all the necessary
information.

Add the file offset to the /proc read interfaces, and make
them simpler to use. The core now does a offset updates, and
sanity-checks the values so that the low-level drivers don't
need to worry.

Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
include/sound/info.h
sound/core/info.c
sound/drivers/opl4/opl4_proc.c
sound/isa/gus/gus_mem_proc.c
sound/pci/cs4281.c
sound/pci/cs46xx/cs46xx_lib.c
sound/pci/emu10k1/emuproc.c
sound/pci/mixart/mixart.c

index e384c9f5f5ee3ccdb89c44c3573e8025f459c657..fae0c98cfdca28e411a8190aaa9eabceda31aefd 100644 (file)
@@ -5182,7 +5182,7 @@ struct _snd_pcm_runtime {
       The callback is much more complicated than the text-file
       version. You need to use a low-level i/o functions such as
       <function>copy_from/to_user()</function> to transfer the
-      data. Also, you have to keep tracking the file position, too. 
+      data.
 
       <informalexample>
         <programlisting>
@@ -5190,14 +5190,15 @@ struct _snd_pcm_runtime {
   static long my_file_io_read(snd_info_entry_t *entry,
                               void *file_private_data,
                               struct file *file,
-                              char *buf, long count)
+                              char *buf,
+                              unsigned long count,
+                              unsigned long pos)
   {
           long size = count;
-          if (file->f_pos + size > local_max_size)
-                  size = local_max_size - file->f_pos;
-          if (copy_to_user(buf, local_data + file->f_pos, size))
+          if (pos + size > local_max_size)
+                  size = local_max_size - pos;
+          if (copy_to_user(buf, local_data + pos, size))
                   return -EFAULT;
-          file->f_pos += size;
           return size;
   }
 ]]>
index 9e33b58b8cced3f8fe6acfa739f360afd7883e53..29a6b83d1aeb6d3fbac762e05f02bd74cc6d49fd 100644 (file)
@@ -54,9 +54,11 @@ struct snd_info_entry_ops {
        int (*release) (snd_info_entry_t * entry,
                        unsigned short mode, void *file_private_data);
        long (*read) (snd_info_entry_t *entry, void *file_private_data,
-                     struct file * file, char __user *buf, long count);
+                     struct file * file, char __user *buf,
+                     unsigned long count, unsigned long pos);
        long (*write) (snd_info_entry_t *entry, void *file_private_data,
-                      struct file * file, const char __user *buf, long count);
+                      struct file * file, const char __user *buf,
+                      unsigned long count, unsigned long pos);
        long long (*llseek) (snd_info_entry_t *entry, void *file_private_data,
                            struct file * file, long long offset, int orig);
        unsigned int (*poll) (snd_info_entry_t *entry, void *file_private_data,
index 0b08203d50e5a743b5e13ab81db1d69e6f922ce7..1eb7d916a365159827d7fc688313c4639ea850c6 100644 (file)
@@ -181,30 +181,37 @@ static ssize_t snd_info_entry_read(struct file *file, char __user *buffer,
        struct snd_info_entry *entry;
        snd_info_buffer_t *buf;
        size_t size = 0;
+       loff_t pos;
 
        data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
        snd_assert(data != NULL, return -ENXIO);
+       pos = *offset;
+       if (pos < 0 || (long) pos != pos || (ssize_t) count < 0)
+               return -EIO;
+       if ((unsigned long) pos + (unsigned long) count < (unsigned long) pos)
+               return -EIO;
        entry = data->entry;
        switch (entry->content) {
        case SNDRV_INFO_CONTENT_TEXT:
                buf = data->rbuffer;
                if (buf == NULL)
                        return -EIO;
-               if (file->f_pos >= (long)buf->size)
+               if (pos >= buf->size)
                        return 0;
-               size = buf->size - file->f_pos;
+               size = buf->size - pos;
                size = min(count, size);
-               if (copy_to_user(buffer, buf->buffer + file->f_pos, size))
+               if (copy_to_user(buffer, buf->buffer + pos, size))
                        return -EFAULT;
-               file->f_pos += size;
                break;
        case SNDRV_INFO_CONTENT_DATA:
                if (entry->c.ops->read)
-                       return entry->c.ops->read(entry,
+                       size = entry->c.ops->read(entry,
                                                  data->file_private_data,
-                                                 file, buffer, count);
+                                                 file, buffer, count, pos);
                break;
        }
+       if ((ssize_t) size > 0)
+               *offset = pos + size;
        return size;
 }
 
@@ -215,34 +222,39 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer
        struct snd_info_entry *entry;
        snd_info_buffer_t *buf;
        size_t size = 0;
+       loff_t pos;
 
        data = snd_magic_cast(snd_info_private_data_t, file->private_data, return -ENXIO);
        snd_assert(data != NULL, return -ENXIO);
        entry = data->entry;
+       pos = *offset;
+       if (pos < 0 || (long) pos != pos || (ssize_t) count < 0)
+               return -EIO;
+       if ((unsigned long) pos + (unsigned long) count < (unsigned long) pos)
+               return -EIO;
        switch (entry->content) {
        case SNDRV_INFO_CONTENT_TEXT:
                buf = data->wbuffer;
                if (buf == NULL)
                        return -EIO;
-               if (file->f_pos < 0)
-                       return -EINVAL;
-               if (file->f_pos >= (long)buf->len)
+               if (pos >= buf->len)
                        return -ENOMEM;
-               size = buf->len - file->f_pos;
+               size = buf->len - pos;
                size = min(count, size);
-               if (copy_from_user(buf->buffer + file->f_pos, buffer, size))
+               if (copy_from_user(buf->buffer + pos, buffer, size))
                        return -EFAULT;
-               if ((long)buf->size < file->f_pos + size)
-                       buf->size = file->f_pos + size;
-               file->f_pos += size;
+               if ((long)buf->size < pos + size)
+                       buf->size = pos + size;
                break;
        case SNDRV_INFO_CONTENT_DATA:
                if (entry->c.ops->write)
-                       return entry->c.ops->write(entry,
+                       size = entry->c.ops->write(entry,
                                                   data->file_private_data,
-                                                  file, buffer, count);
+                                                  file, buffer, count, pos);
                break;
        }
+       if ((ssize_t) size > 0)
+               *offset = pos + size;
        return size;
 }
 
index f2f364d15a26bddf86a63fba21bb119c78c30e91..bbea9ab1c859ab19a5e18647b56837e062db549f 100644 (file)
@@ -50,41 +50,42 @@ static int snd_opl4_mem_proc_release(snd_info_entry_t *entry,
 }
 
 static long snd_opl4_mem_proc_read(snd_info_entry_t *entry, void *file_private_data,
-                                  struct file *file, char __user *_buf, long count)
+                                  struct file *file, char __user *_buf,
+                                  unsigned long count, unsigned long pos)
 {
        opl4_t *opl4 = snd_magic_cast(opl4_t, entry->private_data, return -ENXIO);
        long size;
        char* buf;
 
        size = count;
-       if (file->f_pos + size > entry->size)
-               size = entry->size - file->f_pos;
+       if (pos + size > entry->size)
+               size = entry->size - pos;
        if (size > 0) {
                buf = vmalloc(size);
                if (!buf)
                        return -ENOMEM;
-               snd_opl4_read_memory(opl4, buf, file->f_pos, size);
+               snd_opl4_read_memory(opl4, buf, pos, size);
                if (copy_to_user(_buf, buf, size)) {
                        vfree(buf);
                        return -EFAULT;
                }
                vfree(buf);
-               file->f_pos += size;
                return size;
        }
        return 0;
 }
 
 static long snd_opl4_mem_proc_write(snd_info_entry_t *entry, void *file_private_data,
-                                   struct file *file, const char __user *_buf, long count)
+                                   struct file *file, const char __user *_buf,
+                                   unsigned long count, unsigned long pos)
 {
        opl4_t *opl4 = snd_magic_cast(opl4_t, entry->private_data, return -ENXIO);
        long size;
        char *buf;
 
        size = count;
-       if (file->f_pos + size > entry->size)
-               size = entry->size - file->f_pos;
+       if (pos + size > entry->size)
+               size = entry->size - pos;
        if (size > 0) {
                buf = vmalloc(size);
                if (!buf)
@@ -93,9 +94,8 @@ static long snd_opl4_mem_proc_write(snd_info_entry_t *entry, void *file_private_
                        vfree(buf);
                        return -EFAULT;
                }
-               snd_opl4_write_memory(opl4, buf, file->f_pos, size);
+               snd_opl4_write_memory(opl4, buf, pos, size);
                vfree(buf);
-               file->f_pos += size;
                return size;
        }
        return 0;
index 95071a0841840bfb71359479446ab0b1e728a240..6ee2d76ee8286d78e5ad43b7e4e484e995556c80 100644 (file)
@@ -33,7 +33,8 @@ typedef struct gus_proc_private {
 } gus_proc_private_t;
 
 static long snd_gf1_mem_proc_dump(snd_info_entry_t *entry, void *file_private_data,
-                                 struct file *file, char __user *buf, long count)
+                                 struct file *file, char __user *buf,
+                                 unsigned long count, unsigned long pos)
 {
        long size;
        gus_proc_private_t *priv = snd_magic_cast(gus_proc_private_t, entry->private_data, return -ENXIO);
@@ -41,12 +42,11 @@ static long snd_gf1_mem_proc_dump(snd_info_entry_t *entry, void *file_private_da
        int err;
 
        size = count;
-       if (file->f_pos + size > priv->size)
-               size = (long)priv->size - file->f_pos;
+       if (pos + size > priv->size)
+               size = (long)priv->size - pos;
        if (size > 0) {
-               if ((err = snd_gus_dram_read(gus, buf, file->f_pos, size, priv->rom)) < 0)
+               if ((err = snd_gus_dram_read(gus, buf, pos, size, priv->rom)) < 0)
                        return err;
-               file->f_pos += size;
                return size;
        }
        return 0;
index 91a60417e7ec467eb795eaeb7b4648d16c513993..86430a0bcd68a2a8867aad71714067ee77f26c1d 100644 (file)
@@ -1185,35 +1185,35 @@ static void snd_cs4281_proc_read(snd_info_entry_t *entry,
 }
 
 static long snd_cs4281_BA0_read(snd_info_entry_t *entry, void *file_private_data,
-                               struct file *file, char __user *buf, long count)
+                               struct file *file, char __user *buf,
+                               unsigned long count, unsigned long pos)
 {
        long size;
        cs4281_t *chip = snd_magic_cast(cs4281_t, entry->private_data, return -ENXIO);
        
        size = count;
-       if (file->f_pos + size > CS4281_BA0_SIZE)
-               size = (long)CS4281_BA0_SIZE - file->f_pos;
+       if (pos + size > CS4281_BA0_SIZE)
+               size = (long)CS4281_BA0_SIZE - pos;
        if (size > 0) {
-               if (copy_to_user_fromio(buf, chip->ba0 + file->f_pos, size))
+               if (copy_to_user_fromio(buf, chip->ba0 + pos, size))
                        return -EFAULT;
-               file->f_pos += size;
        }
        return size;
 }
 
 static long snd_cs4281_BA1_read(snd_info_entry_t *entry, void *file_private_data,
-                               struct file *file, char __user *buf, long count)
+                               struct file *file, char __user *buf,
+                               unsigned long count, unsigned long pos)
 {
        long size;
        cs4281_t *chip = snd_magic_cast(cs4281_t, entry->private_data, return -ENXIO);
        
        size = count;
-       if (file->f_pos + size > CS4281_BA1_SIZE)
-               size = (long)CS4281_BA1_SIZE - file->f_pos;
+       if (pos + size > CS4281_BA1_SIZE)
+               size = (long)CS4281_BA1_SIZE - pos;
        if (size > 0) {
-               if (copy_to_user_fromio(buf, chip->ba1 + file->f_pos, size))
+               if (copy_to_user_fromio(buf, chip->ba1 + pos, size))
                        return -EFAULT;
-               file->f_pos += size;
        }
        return size;
 }
index 9a1758396395b0ee487376ddd3f28802224c2054..e9810d2ea5af30b2e5219091a5620ffd51563428 100644 (file)
@@ -2866,18 +2866,18 @@ void __devinit snd_cs46xx_gameport(cs46xx_t *chip)
  */
 
 static long snd_cs46xx_io_read(snd_info_entry_t *entry, void *file_private_data,
-                              struct file *file, char __user *buf, long count)
+                              struct file *file, char __user *buf,
+                              unsigned long count, unsigned long pos)
 {
        long size;
        snd_cs46xx_region_t *region = (snd_cs46xx_region_t *)entry->private_data;
        
        size = count;
-       if (file->f_pos + (size_t)size > region->size)
-               size = region->size - file->f_pos;
+       if (pos + (size_t)size > region->size)
+               size = region->size - pos;
        if (size > 0) {
-               if (copy_to_user_fromio(buf, region->remap_addr + file->f_pos, size))
+               if (copy_to_user_fromio(buf, region->remap_addr + pos, size))
                        return -EFAULT;
-               file->f_pos += size;
        }
        return size;
 }
index 39f5307e2183f4eec5748b88af982dea5bc7bed9..9582c3179d75ace7e81bfe0d6624bb33a6c48e53 100644 (file)
@@ -191,7 +191,8 @@ static void snd_emu10k1_proc_acode_read(snd_info_entry_t *entry,
 #define TOTAL_SIZE_CODE                (0x200*8)
 
 static long snd_emu10k1_fx8010_read(snd_info_entry_t *entry, void *file_private_data,
-                                   struct file *file, char __user *buf, long count)
+                                   struct file *file, char __user *buf,
+                                   unsigned long count, unsigned long pos)
 {
        long size;
        emu10k1_t *emu = snd_magic_cast(emu10k1_t, entry->private_data, return -ENXIO);
@@ -209,21 +210,20 @@ static long snd_emu10k1_fx8010_read(snd_info_entry_t *entry, void *file_private_
                offset = emu->audigy ? A_FXGPREGBASE : FXGPREGBASE;
        }
        size = count;
-       if (file->f_pos + size > entry->size)
-               size = (long)entry->size - file->f_pos;
+       if (pos + size > entry->size)
+               size = (long)entry->size - pos;
        if (size > 0) {
                unsigned int *tmp;
                long res;
                unsigned int idx;
                if ((tmp = kmalloc(size + 8, GFP_KERNEL)) == NULL)
                        return -ENOMEM;
-               for (idx = 0; idx < ((file->f_pos & 3) + size + 3) >> 2; idx++)
-                       tmp[idx] = snd_emu10k1_ptr_read(emu, offset + idx + (file->f_pos >> 2), 0);
-               if (copy_to_user(buf, ((char *)tmp) + (file->f_pos & 3), size))
+               for (idx = 0; idx < ((pos & 3) + size + 3) >> 2; idx++)
+                       tmp[idx] = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0);
+               if (copy_to_user(buf, ((char *)tmp) + (pos & 3), size))
                        res = -EFAULT;
                else {
                        res = size;
-                       file->f_pos += size;
                }
                kfree(tmp);
                return res;
index 2b918cc7f529bb75c2339b8dbcc44609dc4549f4..7e312df0c5bfe7d3215a5eea5741092935bc31dd 100644 (file)
@@ -1154,18 +1154,18 @@ static long long snd_mixart_BA1_llseek(snd_info_entry_t *entry,
   mixart_BA0 proc interface for BAR 0 - read callback
  */
 static long snd_mixart_BA0_read(snd_info_entry_t *entry, void *file_private_data,
-                               struct file *file, char __user *buf, long count)
+                               struct file *file, char __user *buf,
+                               unsigned long count, unsigned long pos)
 {
        mixart_mgr_t *mgr = snd_magic_cast(mixart_mgr_t, entry->private_data, return -ENXIO);
 
        count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
        if(count <= 0)
                return 0;
-       if(file->f_pos + count > MIXART_BA0_SIZE)
-               count = (long)(MIXART_BA0_SIZE - file->f_pos);
-       if(copy_to_user_fromio(buf, MIXART_MEM( mgr, file->f_pos ), count))
+       if(pos + count > MIXART_BA0_SIZE)
+               count = (long)(MIXART_BA0_SIZE - pos);
+       if(copy_to_user_fromio(buf, MIXART_MEM( mgr, pos ), count))
                return -EFAULT;
-       file->f_pos += count;
        return count;
 }
 
@@ -1173,18 +1173,18 @@ static long snd_mixart_BA0_read(snd_info_entry_t *entry, void *file_private_data
   mixart_BA1 proc interface for BAR 1 - read callback
  */
 static long snd_mixart_BA1_read(snd_info_entry_t *entry, void *file_private_data,
-                               struct file *file, char __user *buf, long count)
+                               struct file *file, char __user *buf,
+                               unsigned long count, unsigned long pos)
 {
        mixart_mgr_t *mgr = snd_magic_cast(mixart_mgr_t, entry->private_data, return -ENXIO);
 
        count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
        if(count <= 0)
                return 0;
-       if(file->f_pos + count > MIXART_BA1_SIZE)
-               count = (long)(MIXART_BA1_SIZE - file->f_pos);
-       if(copy_to_user_fromio(buf, MIXART_REG( mgr, file->f_pos ), count))
+       if(pos + count > MIXART_BA1_SIZE)
+               count = (long)(MIXART_BA1_SIZE - pos);
+       if(copy_to_user_fromio(buf, MIXART_REG( mgr, pos ), count))
                return -EFAULT;
-       file->f_pos += count;
        return count;
 }