brintos

brintos / linux-shallow public Read only

0
0
Text · 4.3 KiB · ccf6826 Raw
179 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * OSS compatible sequencer driver4 *5 * OSS compatible i/o control6 *7 * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>8 */9 10#include "seq_oss_device.h"11#include "seq_oss_readq.h"12#include "seq_oss_writeq.h"13#include "seq_oss_timer.h"14#include "seq_oss_synth.h"15#include "seq_oss_midi.h"16#include "seq_oss_event.h"17 18static int snd_seq_oss_synth_info_user(struct seq_oss_devinfo *dp, void __user *arg)19{20	struct synth_info info;21 22	if (copy_from_user(&info, arg, sizeof(info)))23		return -EFAULT;24	if (snd_seq_oss_synth_make_info(dp, info.device, &info) < 0)25		return -EINVAL;26	if (copy_to_user(arg, &info, sizeof(info)))27		return -EFAULT;28	return 0;29}30 31static int snd_seq_oss_midi_info_user(struct seq_oss_devinfo *dp, void __user *arg)32{33	struct midi_info info;34 35	if (copy_from_user(&info, arg, sizeof(info)))36		return -EFAULT;37	if (snd_seq_oss_midi_make_info(dp, info.device, &info) < 0)38		return -EINVAL;39	if (copy_to_user(arg, &info, sizeof(info)))40		return -EFAULT;41	return 0;42}43 44static int snd_seq_oss_oob_user(struct seq_oss_devinfo *dp, void __user *arg)45{46	unsigned char ev[8];47	struct snd_seq_event tmpev;48 49	if (copy_from_user(ev, arg, 8))50		return -EFAULT;51	memset(&tmpev, 0, sizeof(tmpev));52	snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.client, dp->addr.port);53	tmpev.time.tick = 0;54	if (! snd_seq_oss_process_event(dp, (union evrec *)ev, &tmpev)) {55		snd_seq_oss_dispatch(dp, &tmpev, 0, 0);56	}57	return 0;58}59 60int61snd_seq_oss_ioctl(struct seq_oss_devinfo *dp, unsigned int cmd, unsigned long carg)62{63	int dev, val;64	void __user *arg = (void __user *)carg;65	int __user *p = arg;66 67	switch (cmd) {68	case SNDCTL_TMR_TIMEBASE:69	case SNDCTL_TMR_TEMPO:70	case SNDCTL_TMR_START:71	case SNDCTL_TMR_STOP:72	case SNDCTL_TMR_CONTINUE:73	case SNDCTL_TMR_METRONOME:74	case SNDCTL_TMR_SOURCE:75	case SNDCTL_TMR_SELECT:76	case SNDCTL_SEQ_CTRLRATE:77		return snd_seq_oss_timer_ioctl(dp->timer, cmd, arg);78 79	case SNDCTL_SEQ_PANIC:80		snd_seq_oss_reset(dp);81		return -EINVAL;82 83	case SNDCTL_SEQ_SYNC:84		if (! is_write_mode(dp->file_mode) || dp->writeq == NULL)85			return 0;86		while (snd_seq_oss_writeq_sync(dp->writeq))87			;88		if (signal_pending(current))89			return -ERESTARTSYS;90		return 0;91 92	case SNDCTL_SEQ_RESET:93		snd_seq_oss_reset(dp);94		return 0;95 96	case SNDCTL_SEQ_TESTMIDI:97		if (get_user(dev, p))98			return -EFAULT;99		return snd_seq_oss_midi_open(dp, dev, dp->file_mode);100 101	case SNDCTL_SEQ_GETINCOUNT:102		if (dp->readq == NULL || ! is_read_mode(dp->file_mode))103			return 0;104		return put_user(dp->readq->qlen, p) ? -EFAULT : 0;105 106	case SNDCTL_SEQ_GETOUTCOUNT:107		if (! is_write_mode(dp->file_mode) || dp->writeq == NULL)108			return 0;109		return put_user(snd_seq_oss_writeq_get_free_size(dp->writeq), p) ? -EFAULT : 0;110 111	case SNDCTL_SEQ_GETTIME:112		return put_user(snd_seq_oss_timer_cur_tick(dp->timer), p) ? -EFAULT : 0;113 114	case SNDCTL_SEQ_RESETSAMPLES:115		if (get_user(dev, p))116			return -EFAULT;117		return snd_seq_oss_synth_ioctl(dp, dev, cmd, carg);118 119	case SNDCTL_SEQ_NRSYNTHS:120		return put_user(dp->max_synthdev, p) ? -EFAULT : 0;121 122	case SNDCTL_SEQ_NRMIDIS:123		return put_user(dp->max_mididev, p) ? -EFAULT : 0;124 125	case SNDCTL_SYNTH_MEMAVL:126		if (get_user(dev, p))127			return -EFAULT;128		val = snd_seq_oss_synth_ioctl(dp, dev, cmd, carg);129		return put_user(val, p) ? -EFAULT : 0;130 131	case SNDCTL_FM_4OP_ENABLE:132		if (get_user(dev, p))133			return -EFAULT;134		snd_seq_oss_synth_ioctl(dp, dev, cmd, carg);135		return 0;136 137	case SNDCTL_SYNTH_INFO:138	case SNDCTL_SYNTH_ID:139		return snd_seq_oss_synth_info_user(dp, arg);140 141	case SNDCTL_SEQ_OUTOFBAND:142		return snd_seq_oss_oob_user(dp, arg);143 144	case SNDCTL_MIDI_INFO:145		return snd_seq_oss_midi_info_user(dp, arg);146 147	case SNDCTL_SEQ_THRESHOLD:148		if (! is_write_mode(dp->file_mode))149			return 0;150		if (get_user(val, p))151			return -EFAULT;152		if (val < 1)153			val = 1;154		if (val >= dp->writeq->maxlen)155			val = dp->writeq->maxlen - 1;156		snd_seq_oss_writeq_set_output(dp->writeq, val);157		return 0;158 159	case SNDCTL_MIDI_PRETIME:160		if (dp->readq == NULL || !is_read_mode(dp->file_mode))161			return 0;162		if (get_user(val, p))163			return -EFAULT;164		if (val <= 0)165			val = -1;166		else167			val = (HZ * val) / 10;168		dp->readq->pre_event_timeout = val;169		return put_user(val, p) ? -EFAULT : 0;170 171	default:172		if (! is_write_mode(dp->file_mode))173			return -EIO;174		return snd_seq_oss_synth_ioctl(dp, 0, cmd, carg);175	}176	return 0;177}178 179