sound/core/seq/oss/seq_oss_ioctl.c

Source file repositories/reference/linux-study-clean/sound/core/seq/oss/seq_oss_ioctl.c

File Facts

System
Linux kernel
Corpus path
sound/core/seq/oss/seq_oss_ioctl.c
Extension
.c
Size
4428 bytes
Lines
180
Domain
Driver Families
Bucket
sound/core
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * OSS compatible sequencer driver
 *
 * OSS compatible i/o control
 *
 * Copyright (C) 1998,99 Takashi Iwai <tiwai@suse.de>
 */

#include "seq_oss_device.h"
#include "seq_oss_readq.h"
#include "seq_oss_writeq.h"
#include "seq_oss_timer.h"
#include "seq_oss_synth.h"
#include "seq_oss_midi.h"
#include "seq_oss_event.h"

static int snd_seq_oss_synth_info_user(struct seq_oss_devinfo *dp, void __user *arg)
{
	struct synth_info info;

	if (copy_from_user(&info, arg, sizeof(info)))
		return -EFAULT;
	if (snd_seq_oss_synth_make_info(dp, info.device, &info) < 0)
		return -EINVAL;
	if (copy_to_user(arg, &info, sizeof(info)))
		return -EFAULT;
	return 0;
}

static int snd_seq_oss_midi_info_user(struct seq_oss_devinfo *dp, void __user *arg)
{
	struct midi_info info;

	if (copy_from_user(&info, arg, sizeof(info)))
		return -EFAULT;
	if (snd_seq_oss_midi_make_info(dp, info.device, &info) < 0)
		return -EINVAL;
	if (copy_to_user(arg, &info, sizeof(info)))
		return -EFAULT;
	return 0;
}

static int snd_seq_oss_oob_user(struct seq_oss_devinfo *dp, void __user *arg)
{
	unsigned char ev[8];
	struct snd_seq_event tmpev;

	if (copy_from_user(ev, arg, 8))
		return -EFAULT;
	memset(&tmpev, 0, sizeof(tmpev));
	snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.client, dp->addr.port);
	tmpev.time.tick = 0;

	snd_use_lock_t *lock __free(seq_oss_use_lock) = NULL;

	if (!snd_seq_oss_process_event(dp, (union evrec *)ev, &tmpev, &lock))
		snd_seq_oss_dispatch(dp, &tmpev, 0, 0);
	return 0;
}

int
snd_seq_oss_ioctl(struct seq_oss_devinfo *dp, unsigned int cmd, unsigned long carg)
{
	int dev, val;
	void __user *arg = (void __user *)carg;
	int __user *p = arg;

	switch (cmd) {
	case SNDCTL_TMR_TIMEBASE:
	case SNDCTL_TMR_TEMPO:
	case SNDCTL_TMR_START:
	case SNDCTL_TMR_STOP:
	case SNDCTL_TMR_CONTINUE:
	case SNDCTL_TMR_METRONOME:
	case SNDCTL_TMR_SOURCE:
	case SNDCTL_TMR_SELECT:
	case SNDCTL_SEQ_CTRLRATE:
		return snd_seq_oss_timer_ioctl(dp->timer, cmd, arg);

	case SNDCTL_SEQ_PANIC:
		snd_seq_oss_reset(dp);
		return -EINVAL;

	case SNDCTL_SEQ_SYNC:
		if (! is_write_mode(dp->file_mode) || dp->writeq == NULL)
			return 0;
		while (snd_seq_oss_writeq_sync(dp->writeq))
			;
		if (signal_pending(current))

Annotation

Implementation Notes