int snd_seq_oss_write(seq_oss_devinfo_t *dp, const char __user *buf, int count, struct file *opt) { int rc, c, p, ev_size; evrec_t rec; if (! is_write_mode(dp->file_mode) || dp->writeq == NULL) return -EIO; c = count; p = 0; while (c >= SHORT_EVENT_SIZE) { if (copy_from_user(rec.c, buf + p, SHORT_EVENT_SIZE)) break; p += SHORT_EVENT_SIZE; if (rec.s.code == SEQ_FULLSIZE) { /* load patch */ int fmt = (*(unsigned short *)rec.c) & 0xffff; return snd_seq_oss_synth_load_patch(dp, rec.s.dev, fmt, buf, p, c); } if (ev_is_long(&rec)) { /* extended code */ if (rec.s.code == SEQ_EXTENDED && dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) return -EINVAL; ev_size = LONG_EVENT_SIZE; if (c < ev_size) break; /* copy the reset 4 bytes */ if (copy_from_user(rec.c + SHORT_EVENT_SIZE, buf + p, LONG_EVENT_SIZE - SHORT_EVENT_SIZE)) break; p += LONG_EVENT_SIZE - SHORT_EVENT_SIZE; } else { /* old-type code */ if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) return -EINVAL; ev_size = SHORT_EVENT_SIZE; } /* insert queue */ if ((rc = insert_queue(dp, &rec, opt)) < 0) break; c -= ev_size; } if (count == c && is_nonblock_mode(dp->file_mode)) return -EAGAIN; return count - c; }
int snd_seq_oss_write(struct seq_oss_devinfo *dp, const char __user *buf, int count, struct file *opt) { int result = 0, err = 0; int ev_size, fmt; union evrec rec; if (! is_write_mode(dp->file_mode) || dp->writeq == NULL) return -ENXIO; while (count >= SHORT_EVENT_SIZE) { if (copy_from_user(&rec, buf, SHORT_EVENT_SIZE)) { err = -EFAULT; break; } if (rec.s.code == SEQ_FULLSIZE) { /* load patch */ if (result > 0) { err = -EINVAL; break; } fmt = (*(unsigned short *)rec.c) & 0xffff; /* FIXME the return value isn't correct */ return snd_seq_oss_synth_load_patch(dp, rec.s.dev, fmt, buf, 0, count); } if (ev_is_long(&rec)) { /* extended code */ if (rec.s.code == SEQ_EXTENDED && dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) { err = -EINVAL; break; } ev_size = LONG_EVENT_SIZE; if (count < ev_size) break; /* copy the reset 4 bytes */ if (copy_from_user(rec.c + SHORT_EVENT_SIZE, buf + SHORT_EVENT_SIZE, LONG_EVENT_SIZE - SHORT_EVENT_SIZE)) { err = -EFAULT; break; } } else { /* old-type code */ if (dp->seq_mode == SNDRV_SEQ_OSS_MODE_MUSIC) { err = -EINVAL; break; } ev_size = SHORT_EVENT_SIZE; } /* insert queue */ if ((err = insert_queue(dp, &rec, opt)) < 0) break; result += ev_size; buf += ev_size; count -= ev_size; } return result > 0 ? result : err; }