/* * write the device - load patches */ long snd_opl3_write(struct snd_hwdep *hw, const char __user *buf, long count, loff_t *offset) { struct snd_opl3 *opl3 = hw->private_data; long result = 0; int err = 0; struct sbi_patch inst; while (count >= sizeof(inst)) { unsigned char type; if (copy_from_user(&inst, buf, sizeof(inst))) return -EFAULT; if (!memcmp(inst.key, FM_KEY_SBI, 4) || !memcmp(inst.key, FM_KEY_2OP, 4)) type = FM_PATCH_OPL2; else if (!memcmp(inst.key, FM_KEY_4OP, 4)) type = FM_PATCH_OPL3; else /* invalid type */ break; err = snd_opl3_load_patch(opl3, inst.prog, inst.bank, type, inst.name, inst.extension, inst.data); if (err < 0) break; result += sizeof(inst); count -= sizeof(inst); } return result > 0 ? result : err; }
static int snd_opl3_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, const char __user *buf, int offs, int count) { struct snd_opl3 *opl3; struct sbi_instrument sbi; char name[32]; int err, type; if (snd_BUG_ON(!arg)) return -ENXIO; opl3 = arg->private_data; if (format == FM_PATCH) type = FM_PATCH_OPL2; else if (format == OPL3_PATCH) type = FM_PATCH_OPL3; else return -EINVAL; if (count < (int)sizeof(sbi)) { snd_printk(KERN_ERR "FM Error: Patch record too short\n"); return -EINVAL; } if (copy_from_user(&sbi, buf, sizeof(sbi))) return -EFAULT; if (sbi.channel < 0 || sbi.channel >= SBFM_MAXINSTR) { snd_printk(KERN_ERR "FM Error: Invalid instrument number %d\n", sbi.channel); return -EINVAL; } memset(name, 0, sizeof(name)); sprintf(name, "Chan%d", sbi.channel); err = snd_opl3_load_patch(opl3, sbi.channel, 127, type, name, NULL, sbi.operators); if (err < 0) return err; return sizeof(sbi); }