int snd_seq_expand_var_event(const snd_seq_event_t *event, int count, char *buf, int in_kernel, int size_aligned) { int len, newlen; int err; if ((len = get_var_len(event)) < 0) return len; newlen = len; if (size_aligned > 0) newlen = ((len + size_aligned - 1) / size_aligned) * size_aligned; if (count < newlen) return -EAGAIN; if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) { if (! in_kernel) return -EINVAL; if (copy_from_user(buf, event->data.ext.ptr, len)) return -EFAULT; return newlen; } err = snd_seq_dump_var_event(event, in_kernel ? (snd_seq_dump_func_t)seq_copy_in_kernel : (snd_seq_dump_func_t)seq_copy_in_user, &buf); return err < 0 ? err : newlen; }
int snd_seq_dump_var_event(const struct snd_seq_event *event, snd_seq_dump_func_t func, void *private_data) { int len, err; struct snd_seq_event_cell *cell; if ((len = get_var_len(event)) <= 0) return len; if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) { char buf[32]; char __user *curptr = (char __force __user *)event->data.ext.ptr; while (len > 0) { int size = sizeof(buf); if (len < size) size = len; if (copy_from_user(buf, curptr, size)) return -EFAULT; err = func(private_data, buf, size); if (err < 0) return err; curptr += size; len -= size; } return 0; } if (! (event->data.ext.len & SNDRV_SEQ_EXT_CHAINED)) { return func(private_data, event->data.ext.ptr, len); } cell = (struct snd_seq_event_cell *)event->data.ext.ptr; for (; len > 0 && cell; cell = cell->next) { int size = sizeof(struct snd_seq_event); if (len < size) size = len; err = func(private_data, &cell->event, size); if (err < 0) return err; len -= size; } return 0; }