File Index
Files and directories
Sign in
FILE

seq_oss_ioctl.c

File preview with syntax highlighting.

linux-6.19.14/sound/core/seq/oss/seq_oss_ioctl.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * OSS compatible sequencer driver
  4 *
  5 * OSS compatible i/o control
  6 *
  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
 60int
 61snd_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		else
167			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
~/ Read-only file preview.