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>
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;
}
]]>
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,
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;
}
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;
}
}
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)
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;
} 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);
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;
}
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;
}
*/
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;
}
#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);
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;
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;
}
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;
}