cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

seq_oss_ioctl.c (4371B)


      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