brintos

brintos / linux-shallow public Read only

0
0
Text · 58.1 KiB · 03306be Raw
2135 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *  Abstract layer for MIDI v1.0 stream4 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>5 */6 7#include <sound/core.h>8#include <linux/major.h>9#include <linux/init.h>10#include <linux/sched/signal.h>11#include <linux/slab.h>12#include <linux/time.h>13#include <linux/wait.h>14#include <linux/mutex.h>15#include <linux/module.h>16#include <linux/delay.h>17#include <linux/mm.h>18#include <linux/nospec.h>19#include <sound/rawmidi.h>20#include <sound/info.h>21#include <sound/control.h>22#include <sound/minors.h>23#include <sound/initval.h>24#include <sound/ump.h>25 26MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");27MODULE_DESCRIPTION("Midlevel RawMidi code for ALSA.");28MODULE_LICENSE("GPL");29 30#ifdef CONFIG_SND_OSSEMUL31static int midi_map[SNDRV_CARDS];32static int amidi_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};33module_param_array(midi_map, int, NULL, 0444);34MODULE_PARM_DESC(midi_map, "Raw MIDI device number assigned to 1st OSS device.");35module_param_array(amidi_map, int, NULL, 0444);36MODULE_PARM_DESC(amidi_map, "Raw MIDI device number assigned to 2nd OSS device.");37#endif /* CONFIG_SND_OSSEMUL */38 39static int snd_rawmidi_dev_free(struct snd_device *device);40static int snd_rawmidi_dev_register(struct snd_device *device);41static int snd_rawmidi_dev_disconnect(struct snd_device *device);42 43static LIST_HEAD(snd_rawmidi_devices);44static DEFINE_MUTEX(register_mutex);45 46#define rmidi_err(rmidi, fmt, args...) \47	dev_err((rmidi)->dev, fmt, ##args)48#define rmidi_warn(rmidi, fmt, args...) \49	dev_warn((rmidi)->dev, fmt, ##args)50#define rmidi_dbg(rmidi, fmt, args...) \51	dev_dbg((rmidi)->dev, fmt, ##args)52 53struct snd_rawmidi_status32 {54	s32 stream;55	s32 tstamp_sec;			/* Timestamp */56	s32 tstamp_nsec;57	u32 avail;			/* available bytes */58	u32 xruns;			/* count of overruns since last status (in bytes) */59	unsigned char reserved[16];	/* reserved for future use */60};61 62#define SNDRV_RAWMIDI_IOCTL_STATUS32	_IOWR('W', 0x20, struct snd_rawmidi_status32)63 64struct snd_rawmidi_status64 {65	int stream;66	u8 rsvd[4];			/* alignment */67	s64 tstamp_sec;			/* Timestamp */68	s64 tstamp_nsec;69	size_t avail;			/* available bytes */70	size_t xruns;			/* count of overruns since last status (in bytes) */71	unsigned char reserved[16];	/* reserved for future use */72};73 74#define SNDRV_RAWMIDI_IOCTL_STATUS64	_IOWR('W', 0x20, struct snd_rawmidi_status64)75 76#define rawmidi_is_ump(rmidi) \77	(IS_ENABLED(CONFIG_SND_UMP) && ((rmidi)->info_flags & SNDRV_RAWMIDI_INFO_UMP))78 79static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device)80{81	struct snd_rawmidi *rawmidi;82 83	list_for_each_entry(rawmidi, &snd_rawmidi_devices, list)84		if (rawmidi->card == card && rawmidi->device == device)85			return rawmidi;86	return NULL;87}88 89static inline unsigned short snd_rawmidi_file_flags(struct file *file)90{91	switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {92	case FMODE_WRITE:93		return SNDRV_RAWMIDI_LFLG_OUTPUT;94	case FMODE_READ:95		return SNDRV_RAWMIDI_LFLG_INPUT;96	default:97		return SNDRV_RAWMIDI_LFLG_OPEN;98	}99}100 101static inline bool __snd_rawmidi_ready(struct snd_rawmidi_runtime *runtime)102{103	return runtime->avail >= runtime->avail_min;104}105 106static bool snd_rawmidi_ready(struct snd_rawmidi_substream *substream)107{108	guard(spinlock_irqsave)(&substream->lock);109	return __snd_rawmidi_ready(substream->runtime);110}111 112static inline int snd_rawmidi_ready_append(struct snd_rawmidi_substream *substream,113					   size_t count)114{115	struct snd_rawmidi_runtime *runtime = substream->runtime;116 117	return runtime->avail >= runtime->avail_min &&118	       (!substream->append || runtime->avail >= count);119}120 121static void snd_rawmidi_input_event_work(struct work_struct *work)122{123	struct snd_rawmidi_runtime *runtime =124		container_of(work, struct snd_rawmidi_runtime, event_work);125 126	if (runtime->event)127		runtime->event(runtime->substream);128}129 130/* buffer refcount management: call with substream->lock held */131static inline void snd_rawmidi_buffer_ref(struct snd_rawmidi_runtime *runtime)132{133	runtime->buffer_ref++;134}135 136static inline void snd_rawmidi_buffer_unref(struct snd_rawmidi_runtime *runtime)137{138	runtime->buffer_ref--;139}140 141static void snd_rawmidi_buffer_ref_sync(struct snd_rawmidi_substream *substream)142{143	int loop = HZ;144 145	spin_lock_irq(&substream->lock);146	while (substream->runtime->buffer_ref) {147		spin_unlock_irq(&substream->lock);148		if (!--loop) {149			rmidi_err(substream->rmidi, "Buffer ref sync timeout\n");150			return;151		}152		schedule_timeout_uninterruptible(1);153		spin_lock_irq(&substream->lock);154	}155	spin_unlock_irq(&substream->lock);156}157 158static int snd_rawmidi_runtime_create(struct snd_rawmidi_substream *substream)159{160	struct snd_rawmidi_runtime *runtime;161 162	runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);163	if (!runtime)164		return -ENOMEM;165	runtime->substream = substream;166	init_waitqueue_head(&runtime->sleep);167	INIT_WORK(&runtime->event_work, snd_rawmidi_input_event_work);168	runtime->event = NULL;169	runtime->buffer_size = PAGE_SIZE;170	runtime->avail_min = 1;171	if (substream->stream == SNDRV_RAWMIDI_STREAM_INPUT)172		runtime->avail = 0;173	else174		runtime->avail = runtime->buffer_size;175	runtime->buffer = kvzalloc(runtime->buffer_size, GFP_KERNEL);176	if (!runtime->buffer) {177		kfree(runtime);178		return -ENOMEM;179	}180	runtime->appl_ptr = runtime->hw_ptr = 0;181	substream->runtime = runtime;182	if (rawmidi_is_ump(substream->rmidi))183		runtime->align = 3;184	return 0;185}186 187/* get the current alignment (either 0 or 3) */188static inline int get_align(struct snd_rawmidi_runtime *runtime)189{190	if (IS_ENABLED(CONFIG_SND_UMP))191		return runtime->align;192	else193		return 0;194}195 196/* get the trimmed size with the current alignment */197#define get_aligned_size(runtime, size) ((size) & ~get_align(runtime))198 199static int snd_rawmidi_runtime_free(struct snd_rawmidi_substream *substream)200{201	struct snd_rawmidi_runtime *runtime = substream->runtime;202 203	kvfree(runtime->buffer);204	kfree(runtime);205	substream->runtime = NULL;206	return 0;207}208 209static inline void snd_rawmidi_output_trigger(struct snd_rawmidi_substream *substream, int up)210{211	if (!substream->opened)212		return;213	substream->ops->trigger(substream, up);214}215 216static void snd_rawmidi_input_trigger(struct snd_rawmidi_substream *substream, int up)217{218	if (!substream->opened)219		return;220	substream->ops->trigger(substream, up);221	if (!up)222		cancel_work_sync(&substream->runtime->event_work);223}224 225static void __reset_runtime_ptrs(struct snd_rawmidi_runtime *runtime,226				 bool is_input)227{228	runtime->drain = 0;229	runtime->appl_ptr = runtime->hw_ptr = 0;230	runtime->avail = is_input ? 0 : runtime->buffer_size;231}232 233static void reset_runtime_ptrs(struct snd_rawmidi_substream *substream,234			       bool is_input)235{236	guard(spinlock_irqsave)(&substream->lock);237	if (substream->opened && substream->runtime)238		__reset_runtime_ptrs(substream->runtime, is_input);239}240 241int snd_rawmidi_drop_output(struct snd_rawmidi_substream *substream)242{243	snd_rawmidi_output_trigger(substream, 0);244	reset_runtime_ptrs(substream, false);245	return 0;246}247EXPORT_SYMBOL(snd_rawmidi_drop_output);248 249int snd_rawmidi_drain_output(struct snd_rawmidi_substream *substream)250{251	int err = 0;252	long timeout;253	struct snd_rawmidi_runtime *runtime;254 255	scoped_guard(spinlock_irq, &substream->lock) {256		runtime = substream->runtime;257		if (!substream->opened || !runtime || !runtime->buffer)258			return -EINVAL;259		snd_rawmidi_buffer_ref(runtime);260		runtime->drain = 1;261	}262 263	timeout = wait_event_interruptible_timeout(runtime->sleep,264				(runtime->avail >= runtime->buffer_size),265				10*HZ);266 267	scoped_guard(spinlock_irq, &substream->lock) {268		if (signal_pending(current))269			err = -ERESTARTSYS;270		if (runtime->avail < runtime->buffer_size && !timeout) {271			rmidi_warn(substream->rmidi,272				   "rawmidi drain error (avail = %li, buffer_size = %li)\n",273				   (long)runtime->avail, (long)runtime->buffer_size);274			err = -EIO;275		}276		runtime->drain = 0;277	}278 279	if (err != -ERESTARTSYS) {280		/* we need wait a while to make sure that Tx FIFOs are empty */281		if (substream->ops->drain)282			substream->ops->drain(substream);283		else284			msleep(50);285		snd_rawmidi_drop_output(substream);286	}287 288	scoped_guard(spinlock_irq, &substream->lock)289		snd_rawmidi_buffer_unref(runtime);290 291	return err;292}293EXPORT_SYMBOL(snd_rawmidi_drain_output);294 295int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream)296{297	snd_rawmidi_input_trigger(substream, 0);298	reset_runtime_ptrs(substream, true);299	return 0;300}301EXPORT_SYMBOL(snd_rawmidi_drain_input);302 303/* look for an available substream for the given stream direction;304 * if a specific subdevice is given, try to assign it305 */306static int assign_substream(struct snd_rawmidi *rmidi, int subdevice,307			    int stream, int mode,308			    struct snd_rawmidi_substream **sub_ret)309{310	struct snd_rawmidi_substream *substream;311	struct snd_rawmidi_str *s = &rmidi->streams[stream];312	static const unsigned int info_flags[2] = {313		[SNDRV_RAWMIDI_STREAM_OUTPUT] = SNDRV_RAWMIDI_INFO_OUTPUT,314		[SNDRV_RAWMIDI_STREAM_INPUT] = SNDRV_RAWMIDI_INFO_INPUT,315	};316 317	if (!(rmidi->info_flags & info_flags[stream]))318		return -ENXIO;319	if (subdevice >= 0 && subdevice >= s->substream_count)320		return -ENODEV;321 322	list_for_each_entry(substream, &s->substreams, list) {323		if (substream->opened) {324			if (stream == SNDRV_RAWMIDI_STREAM_INPUT ||325			    !(mode & SNDRV_RAWMIDI_LFLG_APPEND) ||326			    !substream->append)327				continue;328		}329		if (subdevice < 0 || subdevice == substream->number) {330			*sub_ret = substream;331			return 0;332		}333	}334	return -EAGAIN;335}336 337/* open and do ref-counting for the given substream */338static int open_substream(struct snd_rawmidi *rmidi,339			  struct snd_rawmidi_substream *substream,340			  int mode)341{342	int err;343 344	if (substream->use_count == 0) {345		err = snd_rawmidi_runtime_create(substream);346		if (err < 0)347			return err;348		err = substream->ops->open(substream);349		if (err < 0) {350			snd_rawmidi_runtime_free(substream);351			return err;352		}353		guard(spinlock_irq)(&substream->lock);354		substream->opened = 1;355		substream->active_sensing = 0;356		if (mode & SNDRV_RAWMIDI_LFLG_APPEND)357			substream->append = 1;358		substream->pid = get_pid(task_pid(current));359		rmidi->streams[substream->stream].substream_opened++;360	}361	substream->use_count++;362	return 0;363}364 365static void close_substream(struct snd_rawmidi *rmidi,366			    struct snd_rawmidi_substream *substream,367			    int cleanup);368 369static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode,370			     struct snd_rawmidi_file *rfile)371{372	struct snd_rawmidi_substream *sinput = NULL, *soutput = NULL;373	int err;374 375	rfile->input = rfile->output = NULL;376	if (mode & SNDRV_RAWMIDI_LFLG_INPUT) {377		err = assign_substream(rmidi, subdevice,378				       SNDRV_RAWMIDI_STREAM_INPUT,379				       mode, &sinput);380		if (err < 0)381			return err;382	}383	if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {384		err = assign_substream(rmidi, subdevice,385				       SNDRV_RAWMIDI_STREAM_OUTPUT,386				       mode, &soutput);387		if (err < 0)388			return err;389	}390 391	if (sinput) {392		err = open_substream(rmidi, sinput, mode);393		if (err < 0)394			return err;395	}396	if (soutput) {397		err = open_substream(rmidi, soutput, mode);398		if (err < 0) {399			if (sinput)400				close_substream(rmidi, sinput, 0);401			return err;402		}403	}404 405	rfile->rmidi = rmidi;406	rfile->input = sinput;407	rfile->output = soutput;408	return 0;409}410 411/* called from sound/core/seq/seq_midi.c */412int snd_rawmidi_kernel_open(struct snd_rawmidi *rmidi, int subdevice,413			    int mode, struct snd_rawmidi_file *rfile)414{415	int err;416 417	if (snd_BUG_ON(!rfile))418		return -EINVAL;419	if (!try_module_get(rmidi->card->module))420		return -ENXIO;421 422	guard(mutex)(&rmidi->open_mutex);423	err = rawmidi_open_priv(rmidi, subdevice, mode, rfile);424	if (err < 0)425		module_put(rmidi->card->module);426	return err;427}428EXPORT_SYMBOL(snd_rawmidi_kernel_open);429 430static int snd_rawmidi_open(struct inode *inode, struct file *file)431{432	int maj = imajor(inode);433	struct snd_card *card;434	int subdevice;435	unsigned short fflags;436	int err;437	struct snd_rawmidi *rmidi;438	struct snd_rawmidi_file *rawmidi_file = NULL;439	wait_queue_entry_t wait;440 441	if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK))442		return -EINVAL;		/* invalid combination */443 444	err = stream_open(inode, file);445	if (err < 0)446		return err;447 448	if (maj == snd_major) {449		rmidi = snd_lookup_minor_data(iminor(inode),450					      SNDRV_DEVICE_TYPE_RAWMIDI);451#ifdef CONFIG_SND_OSSEMUL452	} else if (maj == SOUND_MAJOR) {453		rmidi = snd_lookup_oss_minor_data(iminor(inode),454						  SNDRV_OSS_DEVICE_TYPE_MIDI);455#endif456	} else457		return -ENXIO;458 459	if (rmidi == NULL)460		return -ENODEV;461 462	if (!try_module_get(rmidi->card->module)) {463		snd_card_unref(rmidi->card);464		return -ENXIO;465	}466 467	mutex_lock(&rmidi->open_mutex);468	card = rmidi->card;469	err = snd_card_file_add(card, file);470	if (err < 0)471		goto __error_card;472	fflags = snd_rawmidi_file_flags(file);473	if ((file->f_flags & O_APPEND) || maj == SOUND_MAJOR) /* OSS emul? */474		fflags |= SNDRV_RAWMIDI_LFLG_APPEND;475	rawmidi_file = kmalloc(sizeof(*rawmidi_file), GFP_KERNEL);476	if (rawmidi_file == NULL) {477		err = -ENOMEM;478		goto __error;479	}480	rawmidi_file->user_pversion = 0;481	init_waitqueue_entry(&wait, current);482	add_wait_queue(&rmidi->open_wait, &wait);483	while (1) {484		subdevice = snd_ctl_get_preferred_subdevice(card, SND_CTL_SUBDEV_RAWMIDI);485		err = rawmidi_open_priv(rmidi, subdevice, fflags, rawmidi_file);486		if (err >= 0)487			break;488		if (err == -EAGAIN) {489			if (file->f_flags & O_NONBLOCK) {490				err = -EBUSY;491				break;492			}493		} else494			break;495		set_current_state(TASK_INTERRUPTIBLE);496		mutex_unlock(&rmidi->open_mutex);497		schedule();498		mutex_lock(&rmidi->open_mutex);499		if (rmidi->card->shutdown) {500			err = -ENODEV;501			break;502		}503		if (signal_pending(current)) {504			err = -ERESTARTSYS;505			break;506		}507	}508	remove_wait_queue(&rmidi->open_wait, &wait);509	if (err < 0) {510		kfree(rawmidi_file);511		goto __error;512	}513#ifdef CONFIG_SND_OSSEMUL514	if (rawmidi_file->input && rawmidi_file->input->runtime)515		rawmidi_file->input->runtime->oss = (maj == SOUND_MAJOR);516	if (rawmidi_file->output && rawmidi_file->output->runtime)517		rawmidi_file->output->runtime->oss = (maj == SOUND_MAJOR);518#endif519	file->private_data = rawmidi_file;520	mutex_unlock(&rmidi->open_mutex);521	snd_card_unref(rmidi->card);522	return 0;523 524 __error:525	snd_card_file_remove(card, file);526 __error_card:527	mutex_unlock(&rmidi->open_mutex);528	module_put(rmidi->card->module);529	snd_card_unref(rmidi->card);530	return err;531}532 533static void close_substream(struct snd_rawmidi *rmidi,534			    struct snd_rawmidi_substream *substream,535			    int cleanup)536{537	if (--substream->use_count)538		return;539 540	if (cleanup) {541		if (substream->stream == SNDRV_RAWMIDI_STREAM_INPUT)542			snd_rawmidi_input_trigger(substream, 0);543		else {544			if (substream->active_sensing) {545				unsigned char buf = 0xfe;546				/* sending single active sensing message547				 * to shut the device up548				 */549				snd_rawmidi_kernel_write(substream, &buf, 1);550			}551			if (snd_rawmidi_drain_output(substream) == -ERESTARTSYS)552				snd_rawmidi_output_trigger(substream, 0);553		}554		snd_rawmidi_buffer_ref_sync(substream);555	}556	scoped_guard(spinlock_irq, &substream->lock) {557		substream->opened = 0;558		substream->append = 0;559	}560	substream->ops->close(substream);561	if (substream->runtime->private_free)562		substream->runtime->private_free(substream);563	snd_rawmidi_runtime_free(substream);564	put_pid(substream->pid);565	substream->pid = NULL;566	rmidi->streams[substream->stream].substream_opened--;567}568 569static void rawmidi_release_priv(struct snd_rawmidi_file *rfile)570{571	struct snd_rawmidi *rmidi;572 573	rmidi = rfile->rmidi;574	guard(mutex)(&rmidi->open_mutex);575	if (rfile->input) {576		close_substream(rmidi, rfile->input, 1);577		rfile->input = NULL;578	}579	if (rfile->output) {580		close_substream(rmidi, rfile->output, 1);581		rfile->output = NULL;582	}583	rfile->rmidi = NULL;584	wake_up(&rmidi->open_wait);585}586 587/* called from sound/core/seq/seq_midi.c */588int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile)589{590	struct snd_rawmidi *rmidi;591 592	if (snd_BUG_ON(!rfile))593		return -ENXIO;594 595	rmidi = rfile->rmidi;596	rawmidi_release_priv(rfile);597	module_put(rmidi->card->module);598	return 0;599}600EXPORT_SYMBOL(snd_rawmidi_kernel_release);601 602static int snd_rawmidi_release(struct inode *inode, struct file *file)603{604	struct snd_rawmidi_file *rfile;605	struct snd_rawmidi *rmidi;606	struct module *module;607 608	rfile = file->private_data;609	rmidi = rfile->rmidi;610	rawmidi_release_priv(rfile);611	kfree(rfile);612	module = rmidi->card->module;613	snd_card_file_remove(rmidi->card, file);614	module_put(module);615	return 0;616}617 618static int snd_rawmidi_info(struct snd_rawmidi_substream *substream,619			    struct snd_rawmidi_info *info)620{621	struct snd_rawmidi *rmidi;622 623	if (substream == NULL)624		return -ENODEV;625	rmidi = substream->rmidi;626	memset(info, 0, sizeof(*info));627	info->card = rmidi->card->number;628	info->device = rmidi->device;629	info->subdevice = substream->number;630	info->stream = substream->stream;631	info->flags = rmidi->info_flags;632	strcpy(info->id, rmidi->id);633	strcpy(info->name, rmidi->name);634	strcpy(info->subname, substream->name);635	info->subdevices_count = substream->pstr->substream_count;636	info->subdevices_avail = (substream->pstr->substream_count -637				  substream->pstr->substream_opened);638	return 0;639}640 641static int snd_rawmidi_info_user(struct snd_rawmidi_substream *substream,642				 struct snd_rawmidi_info __user *_info)643{644	struct snd_rawmidi_info info;645	int err;646 647	err = snd_rawmidi_info(substream, &info);648	if (err < 0)649		return err;650	if (copy_to_user(_info, &info, sizeof(struct snd_rawmidi_info)))651		return -EFAULT;652	return 0;653}654 655static int __snd_rawmidi_info_select(struct snd_card *card,656				     struct snd_rawmidi_info *info)657{658	struct snd_rawmidi *rmidi;659	struct snd_rawmidi_str *pstr;660	struct snd_rawmidi_substream *substream;661 662	rmidi = snd_rawmidi_search(card, info->device);663	if (!rmidi)664		return -ENXIO;665	if (info->stream < 0 || info->stream > 1)666		return -EINVAL;667	info->stream = array_index_nospec(info->stream, 2);668	pstr = &rmidi->streams[info->stream];669	if (pstr->substream_count == 0)670		return -ENOENT;671	if (info->subdevice >= pstr->substream_count)672		return -ENXIO;673	list_for_each_entry(substream, &pstr->substreams, list) {674		if ((unsigned int)substream->number == info->subdevice)675			return snd_rawmidi_info(substream, info);676	}677	return -ENXIO;678}679 680int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info)681{682	guard(mutex)(&register_mutex);683	return __snd_rawmidi_info_select(card, info);684}685EXPORT_SYMBOL(snd_rawmidi_info_select);686 687static int snd_rawmidi_info_select_user(struct snd_card *card,688					struct snd_rawmidi_info __user *_info)689{690	int err;691	struct snd_rawmidi_info info;692 693	if (get_user(info.device, &_info->device))694		return -EFAULT;695	if (get_user(info.stream, &_info->stream))696		return -EFAULT;697	if (get_user(info.subdevice, &_info->subdevice))698		return -EFAULT;699	err = snd_rawmidi_info_select(card, &info);700	if (err < 0)701		return err;702	if (copy_to_user(_info, &info, sizeof(struct snd_rawmidi_info)))703		return -EFAULT;704	return 0;705}706 707static int resize_runtime_buffer(struct snd_rawmidi_substream *substream,708				 struct snd_rawmidi_params *params,709				 bool is_input)710{711	struct snd_rawmidi_runtime *runtime = substream->runtime;712	char *newbuf, *oldbuf;713	unsigned int framing = params->mode & SNDRV_RAWMIDI_MODE_FRAMING_MASK;714 715	if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L)716		return -EINVAL;717	if (framing == SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP && (params->buffer_size & 0x1f) != 0)718		return -EINVAL;719	if (params->avail_min < 1 || params->avail_min > params->buffer_size)720		return -EINVAL;721	if (params->buffer_size & get_align(runtime))722		return -EINVAL;723	if (params->buffer_size != runtime->buffer_size) {724		newbuf = kvzalloc(params->buffer_size, GFP_KERNEL);725		if (!newbuf)726			return -ENOMEM;727		guard(spinlock_irq)(&substream->lock);728		if (runtime->buffer_ref) {729			kvfree(newbuf);730			return -EBUSY;731		}732		oldbuf = runtime->buffer;733		runtime->buffer = newbuf;734		runtime->buffer_size = params->buffer_size;735		__reset_runtime_ptrs(runtime, is_input);736		kvfree(oldbuf);737	}738	runtime->avail_min = params->avail_min;739	return 0;740}741 742int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,743			      struct snd_rawmidi_params *params)744{745	int err;746 747	snd_rawmidi_drain_output(substream);748	guard(mutex)(&substream->rmidi->open_mutex);749	if (substream->append && substream->use_count > 1)750		return -EBUSY;751	err = resize_runtime_buffer(substream, params, false);752	if (!err)753		substream->active_sensing = !params->no_active_sensing;754	return err;755}756EXPORT_SYMBOL(snd_rawmidi_output_params);757 758int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream,759			     struct snd_rawmidi_params *params)760{761	unsigned int framing = params->mode & SNDRV_RAWMIDI_MODE_FRAMING_MASK;762	unsigned int clock_type = params->mode & SNDRV_RAWMIDI_MODE_CLOCK_MASK;763	int err;764 765	snd_rawmidi_drain_input(substream);766	guard(mutex)(&substream->rmidi->open_mutex);767	if (framing == SNDRV_RAWMIDI_MODE_FRAMING_NONE && clock_type != SNDRV_RAWMIDI_MODE_CLOCK_NONE)768		err = -EINVAL;769	else if (clock_type > SNDRV_RAWMIDI_MODE_CLOCK_MONOTONIC_RAW)770		err = -EINVAL;771	else if (framing > SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP)772		err = -EINVAL;773	else774		err = resize_runtime_buffer(substream, params, true);775 776	if (!err) {777		substream->framing = framing;778		substream->clock_type = clock_type;779	}780	return 0;781}782EXPORT_SYMBOL(snd_rawmidi_input_params);783 784static int snd_rawmidi_output_status(struct snd_rawmidi_substream *substream,785				     struct snd_rawmidi_status64 *status)786{787	struct snd_rawmidi_runtime *runtime = substream->runtime;788 789	memset(status, 0, sizeof(*status));790	status->stream = SNDRV_RAWMIDI_STREAM_OUTPUT;791	guard(spinlock_irq)(&substream->lock);792	status->avail = runtime->avail;793	return 0;794}795 796static int snd_rawmidi_input_status(struct snd_rawmidi_substream *substream,797				    struct snd_rawmidi_status64 *status)798{799	struct snd_rawmidi_runtime *runtime = substream->runtime;800 801	memset(status, 0, sizeof(*status));802	status->stream = SNDRV_RAWMIDI_STREAM_INPUT;803	guard(spinlock_irq)(&substream->lock);804	status->avail = runtime->avail;805	status->xruns = runtime->xruns;806	runtime->xruns = 0;807	return 0;808}809 810static int snd_rawmidi_ioctl_status32(struct snd_rawmidi_file *rfile,811				      struct snd_rawmidi_status32 __user *argp)812{813	int err = 0;814	struct snd_rawmidi_status32 __user *status = argp;815	struct snd_rawmidi_status32 status32;816	struct snd_rawmidi_status64 status64;817 818	if (copy_from_user(&status32, argp,819			   sizeof(struct snd_rawmidi_status32)))820		return -EFAULT;821 822	switch (status32.stream) {823	case SNDRV_RAWMIDI_STREAM_OUTPUT:824		if (rfile->output == NULL)825			return -EINVAL;826		err = snd_rawmidi_output_status(rfile->output, &status64);827		break;828	case SNDRV_RAWMIDI_STREAM_INPUT:829		if (rfile->input == NULL)830			return -EINVAL;831		err = snd_rawmidi_input_status(rfile->input, &status64);832		break;833	default:834		return -EINVAL;835	}836	if (err < 0)837		return err;838 839	status32 = (struct snd_rawmidi_status32) {840		.stream = status64.stream,841		.tstamp_sec = status64.tstamp_sec,842		.tstamp_nsec = status64.tstamp_nsec,843		.avail = status64.avail,844		.xruns = status64.xruns,845	};846 847	if (copy_to_user(status, &status32, sizeof(*status)))848		return -EFAULT;849 850	return 0;851}852 853static int snd_rawmidi_ioctl_status64(struct snd_rawmidi_file *rfile,854				      struct snd_rawmidi_status64 __user *argp)855{856	int err = 0;857	struct snd_rawmidi_status64 status;858 859	if (copy_from_user(&status, argp, sizeof(struct snd_rawmidi_status64)))860		return -EFAULT;861 862	switch (status.stream) {863	case SNDRV_RAWMIDI_STREAM_OUTPUT:864		if (rfile->output == NULL)865			return -EINVAL;866		err = snd_rawmidi_output_status(rfile->output, &status);867		break;868	case SNDRV_RAWMIDI_STREAM_INPUT:869		if (rfile->input == NULL)870			return -EINVAL;871		err = snd_rawmidi_input_status(rfile->input, &status);872		break;873	default:874		return -EINVAL;875	}876	if (err < 0)877		return err;878	if (copy_to_user(argp, &status,879			 sizeof(struct snd_rawmidi_status64)))880		return -EFAULT;881	return 0;882}883 884static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)885{886	struct snd_rawmidi_file *rfile;887	struct snd_rawmidi *rmidi;888	void __user *argp = (void __user *)arg;889 890	rfile = file->private_data;891	if (((cmd >> 8) & 0xff) != 'W')892		return -ENOTTY;893	switch (cmd) {894	case SNDRV_RAWMIDI_IOCTL_PVERSION:895		return put_user(SNDRV_RAWMIDI_VERSION, (int __user *)argp) ? -EFAULT : 0;896	case SNDRV_RAWMIDI_IOCTL_INFO:897	{898		int stream;899		struct snd_rawmidi_info __user *info = argp;900 901		if (get_user(stream, &info->stream))902			return -EFAULT;903		switch (stream) {904		case SNDRV_RAWMIDI_STREAM_INPUT:905			return snd_rawmidi_info_user(rfile->input, info);906		case SNDRV_RAWMIDI_STREAM_OUTPUT:907			return snd_rawmidi_info_user(rfile->output, info);908		default:909			return -EINVAL;910		}911	}912	case SNDRV_RAWMIDI_IOCTL_USER_PVERSION:913		if (get_user(rfile->user_pversion, (unsigned int __user *)arg))914			return -EFAULT;915		return 0;916 917	case SNDRV_RAWMIDI_IOCTL_PARAMS:918	{919		struct snd_rawmidi_params params;920 921		if (copy_from_user(&params, argp, sizeof(struct snd_rawmidi_params)))922			return -EFAULT;923		if (rfile->user_pversion < SNDRV_PROTOCOL_VERSION(2, 0, 2)) {924			params.mode = 0;925			memset(params.reserved, 0, sizeof(params.reserved));926		}927		switch (params.stream) {928		case SNDRV_RAWMIDI_STREAM_OUTPUT:929			if (rfile->output == NULL)930				return -EINVAL;931			return snd_rawmidi_output_params(rfile->output, &params);932		case SNDRV_RAWMIDI_STREAM_INPUT:933			if (rfile->input == NULL)934				return -EINVAL;935			return snd_rawmidi_input_params(rfile->input, &params);936		default:937			return -EINVAL;938		}939	}940	case SNDRV_RAWMIDI_IOCTL_STATUS32:941		return snd_rawmidi_ioctl_status32(rfile, argp);942	case SNDRV_RAWMIDI_IOCTL_STATUS64:943		return snd_rawmidi_ioctl_status64(rfile, argp);944	case SNDRV_RAWMIDI_IOCTL_DROP:945	{946		int val;947 948		if (get_user(val, (int __user *) argp))949			return -EFAULT;950		switch (val) {951		case SNDRV_RAWMIDI_STREAM_OUTPUT:952			if (rfile->output == NULL)953				return -EINVAL;954			return snd_rawmidi_drop_output(rfile->output);955		default:956			return -EINVAL;957		}958	}959	case SNDRV_RAWMIDI_IOCTL_DRAIN:960	{961		int val;962 963		if (get_user(val, (int __user *) argp))964			return -EFAULT;965		switch (val) {966		case SNDRV_RAWMIDI_STREAM_OUTPUT:967			if (rfile->output == NULL)968				return -EINVAL;969			return snd_rawmidi_drain_output(rfile->output);970		case SNDRV_RAWMIDI_STREAM_INPUT:971			if (rfile->input == NULL)972				return -EINVAL;973			return snd_rawmidi_drain_input(rfile->input);974		default:975			return -EINVAL;976		}977	}978	default:979		rmidi = rfile->rmidi;980		if (rmidi->ops && rmidi->ops->ioctl)981			return rmidi->ops->ioctl(rmidi, cmd, argp);982		rmidi_dbg(rmidi, "rawmidi: unknown command = 0x%x\n", cmd);983	}984	return -ENOTTY;985}986 987/* ioctl to find the next device; either legacy or UMP depending on @find_ump */988static int snd_rawmidi_next_device(struct snd_card *card, int __user *argp,989				   bool find_ump)990 991{992	struct snd_rawmidi *rmidi;993	int device;994	bool is_ump;995 996	if (get_user(device, argp))997		return -EFAULT;998	if (device >= SNDRV_RAWMIDI_DEVICES) /* next device is -1 */999		device = SNDRV_RAWMIDI_DEVICES - 1;1000	scoped_guard(mutex, &register_mutex) {1001		device = device < 0 ? 0 : device + 1;1002		for (; device < SNDRV_RAWMIDI_DEVICES; device++) {1003			rmidi = snd_rawmidi_search(card, device);1004			if (!rmidi)1005				continue;1006			is_ump = rawmidi_is_ump(rmidi);1007			if (find_ump == is_ump)1008				break;1009		}1010		if (device == SNDRV_RAWMIDI_DEVICES)1011			device = -1;1012	}1013	if (put_user(device, argp))1014		return -EFAULT;1015	return 0;1016}1017 1018#if IS_ENABLED(CONFIG_SND_UMP)1019/* inquiry of UMP endpoint and block info via control API */1020static int snd_rawmidi_call_ump_ioctl(struct snd_card *card, int cmd,1021				      void __user *argp)1022{1023	struct snd_ump_endpoint_info __user *info = argp;1024	struct snd_rawmidi *rmidi;1025	int device;1026 1027	if (get_user(device, &info->device))1028		return -EFAULT;1029	guard(mutex)(&register_mutex);1030	rmidi = snd_rawmidi_search(card, device);1031	if (rmidi && rmidi->ops && rmidi->ops->ioctl)1032		return rmidi->ops->ioctl(rmidi, cmd, argp);1033	else1034		return -ENXIO;1035}1036#endif1037 1038static int snd_rawmidi_control_ioctl(struct snd_card *card,1039				     struct snd_ctl_file *control,1040				     unsigned int cmd,1041				     unsigned long arg)1042{1043	void __user *argp = (void __user *)arg;1044 1045	switch (cmd) {1046	case SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE:1047		return snd_rawmidi_next_device(card, argp, false);1048#if IS_ENABLED(CONFIG_SND_UMP)1049	case SNDRV_CTL_IOCTL_UMP_NEXT_DEVICE:1050		return snd_rawmidi_next_device(card, argp, true);1051	case SNDRV_CTL_IOCTL_UMP_ENDPOINT_INFO:1052		return snd_rawmidi_call_ump_ioctl(card, SNDRV_UMP_IOCTL_ENDPOINT_INFO, argp);1053	case SNDRV_CTL_IOCTL_UMP_BLOCK_INFO:1054		return snd_rawmidi_call_ump_ioctl(card, SNDRV_UMP_IOCTL_BLOCK_INFO, argp);1055#endif1056	case SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE:1057	{1058		int val;1059 1060		if (get_user(val, (int __user *)argp))1061			return -EFAULT;1062		control->preferred_subdevice[SND_CTL_SUBDEV_RAWMIDI] = val;1063		return 0;1064	}1065	case SNDRV_CTL_IOCTL_RAWMIDI_INFO:1066		return snd_rawmidi_info_select_user(card, argp);1067	}1068	return -ENOIOCTLCMD;1069}1070 1071static int receive_with_tstamp_framing(struct snd_rawmidi_substream *substream,1072			const unsigned char *buffer, int src_count, const struct timespec64 *tstamp)1073{1074	struct snd_rawmidi_runtime *runtime = substream->runtime;1075	struct snd_rawmidi_framing_tstamp *dest_ptr;1076	struct snd_rawmidi_framing_tstamp frame = { .tv_sec = tstamp->tv_sec, .tv_nsec = tstamp->tv_nsec };1077	int orig_count = src_count;1078	int frame_size = sizeof(struct snd_rawmidi_framing_tstamp);1079	int align = get_align(runtime);1080 1081	BUILD_BUG_ON(frame_size != 0x20);1082	if (snd_BUG_ON((runtime->hw_ptr & 0x1f) != 0))1083		return -EINVAL;1084 1085	while (src_count > align) {1086		if ((int)(runtime->buffer_size - runtime->avail) < frame_size) {1087			runtime->xruns += src_count;1088			break;1089		}1090		if (src_count >= SNDRV_RAWMIDI_FRAMING_DATA_LENGTH)1091			frame.length = SNDRV_RAWMIDI_FRAMING_DATA_LENGTH;1092		else {1093			frame.length = get_aligned_size(runtime, src_count);1094			if (!frame.length)1095				break;1096			memset(frame.data, 0, SNDRV_RAWMIDI_FRAMING_DATA_LENGTH);1097		}1098		memcpy(frame.data, buffer, frame.length);1099		buffer += frame.length;1100		src_count -= frame.length;1101		dest_ptr = (struct snd_rawmidi_framing_tstamp *) (runtime->buffer + runtime->hw_ptr);1102		*dest_ptr = frame;1103		runtime->avail += frame_size;1104		runtime->hw_ptr += frame_size;1105		runtime->hw_ptr %= runtime->buffer_size;1106	}1107	return orig_count - src_count;1108}1109 1110static struct timespec64 get_framing_tstamp(struct snd_rawmidi_substream *substream)1111{1112	struct timespec64 ts64 = {0, 0};1113 1114	switch (substream->clock_type) {1115	case SNDRV_RAWMIDI_MODE_CLOCK_MONOTONIC_RAW:1116		ktime_get_raw_ts64(&ts64);1117		break;1118	case SNDRV_RAWMIDI_MODE_CLOCK_MONOTONIC:1119		ktime_get_ts64(&ts64);1120		break;1121	case SNDRV_RAWMIDI_MODE_CLOCK_REALTIME:1122		ktime_get_real_ts64(&ts64);1123		break;1124	}1125	return ts64;1126}1127 1128/**1129 * snd_rawmidi_receive - receive the input data from the device1130 * @substream: the rawmidi substream1131 * @buffer: the buffer pointer1132 * @count: the data size to read1133 *1134 * Reads the data from the internal buffer.1135 *1136 * Return: The size of read data, or a negative error code on failure.1137 */1138int snd_rawmidi_receive(struct snd_rawmidi_substream *substream,1139			const unsigned char *buffer, int count)1140{1141	struct timespec64 ts64 = get_framing_tstamp(substream);1142	int result = 0, count1;1143	struct snd_rawmidi_runtime *runtime;1144 1145	guard(spinlock_irqsave)(&substream->lock);1146	if (!substream->opened)1147		return -EBADFD;1148	runtime = substream->runtime;1149	if (!runtime || !runtime->buffer) {1150		rmidi_dbg(substream->rmidi,1151			  "snd_rawmidi_receive: input is not active!!!\n");1152		return -EINVAL;1153	}1154 1155	count = get_aligned_size(runtime, count);1156	if (!count)1157		return result;1158 1159	if (substream->framing == SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP) {1160		result = receive_with_tstamp_framing(substream, buffer, count, &ts64);1161	} else if (count == 1) {	/* special case, faster code */1162		substream->bytes++;1163		if (runtime->avail < runtime->buffer_size) {1164			runtime->buffer[runtime->hw_ptr++] = buffer[0];1165			runtime->hw_ptr %= runtime->buffer_size;1166			runtime->avail++;1167			result++;1168		} else {1169			runtime->xruns++;1170		}1171	} else {1172		substream->bytes += count;1173		count1 = runtime->buffer_size - runtime->hw_ptr;1174		if (count1 > count)1175			count1 = count;1176		if (count1 > (int)(runtime->buffer_size - runtime->avail))1177			count1 = runtime->buffer_size - runtime->avail;1178		count1 = get_aligned_size(runtime, count1);1179		if (!count1)1180			return result;1181		memcpy(runtime->buffer + runtime->hw_ptr, buffer, count1);1182		runtime->hw_ptr += count1;1183		runtime->hw_ptr %= runtime->buffer_size;1184		runtime->avail += count1;1185		count -= count1;1186		result += count1;1187		if (count > 0) {1188			buffer += count1;1189			count1 = count;1190			if (count1 > (int)(runtime->buffer_size - runtime->avail)) {1191				count1 = runtime->buffer_size - runtime->avail;1192				runtime->xruns += count - count1;1193			}1194			if (count1 > 0) {1195				memcpy(runtime->buffer, buffer, count1);1196				runtime->hw_ptr = count1;1197				runtime->avail += count1;1198				result += count1;1199			}1200		}1201	}1202	if (result > 0) {1203		if (runtime->event)1204			schedule_work(&runtime->event_work);1205		else if (__snd_rawmidi_ready(runtime))1206			wake_up(&runtime->sleep);1207	}1208	return result;1209}1210EXPORT_SYMBOL(snd_rawmidi_receive);1211 1212static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,1213				     unsigned char __user *userbuf,1214				     unsigned char *kernelbuf, long count)1215{1216	unsigned long flags;1217	long result = 0, count1;1218	struct snd_rawmidi_runtime *runtime = substream->runtime;1219	unsigned long appl_ptr;1220	int err = 0;1221 1222	spin_lock_irqsave(&substream->lock, flags);1223	snd_rawmidi_buffer_ref(runtime);1224	while (count > 0 && runtime->avail) {1225		count1 = runtime->buffer_size - runtime->appl_ptr;1226		if (count1 > count)1227			count1 = count;1228		if (count1 > (int)runtime->avail)1229			count1 = runtime->avail;1230 1231		/* update runtime->appl_ptr before unlocking for userbuf */1232		appl_ptr = runtime->appl_ptr;1233		runtime->appl_ptr += count1;1234		runtime->appl_ptr %= runtime->buffer_size;1235		runtime->avail -= count1;1236 1237		if (kernelbuf)1238			memcpy(kernelbuf + result, runtime->buffer + appl_ptr, count1);1239		if (userbuf) {1240			spin_unlock_irqrestore(&substream->lock, flags);1241			if (copy_to_user(userbuf + result,1242					 runtime->buffer + appl_ptr, count1))1243				err = -EFAULT;1244			spin_lock_irqsave(&substream->lock, flags);1245			if (err)1246				goto out;1247		}1248		result += count1;1249		count -= count1;1250	}1251 out:1252	snd_rawmidi_buffer_unref(runtime);1253	spin_unlock_irqrestore(&substream->lock, flags);1254	return result > 0 ? result : err;1255}1256 1257long snd_rawmidi_kernel_read(struct snd_rawmidi_substream *substream,1258			     unsigned char *buf, long count)1259{1260	snd_rawmidi_input_trigger(substream, 1);1261	return snd_rawmidi_kernel_read1(substream, NULL/*userbuf*/, buf, count);1262}1263EXPORT_SYMBOL(snd_rawmidi_kernel_read);1264 1265static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t count,1266				loff_t *offset)1267{1268	long result;1269	int count1;1270	struct snd_rawmidi_file *rfile;1271	struct snd_rawmidi_substream *substream;1272	struct snd_rawmidi_runtime *runtime;1273 1274	rfile = file->private_data;1275	substream = rfile->input;1276	if (substream == NULL)1277		return -EIO;1278	runtime = substream->runtime;1279	snd_rawmidi_input_trigger(substream, 1);1280	result = 0;1281	while (count > 0) {1282		spin_lock_irq(&substream->lock);1283		while (!__snd_rawmidi_ready(runtime)) {1284			wait_queue_entry_t wait;1285 1286			if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {1287				spin_unlock_irq(&substream->lock);1288				return result > 0 ? result : -EAGAIN;1289			}1290			init_waitqueue_entry(&wait, current);1291			add_wait_queue(&runtime->sleep, &wait);1292			set_current_state(TASK_INTERRUPTIBLE);1293			spin_unlock_irq(&substream->lock);1294			schedule();1295			remove_wait_queue(&runtime->sleep, &wait);1296			if (rfile->rmidi->card->shutdown)1297				return -ENODEV;1298			if (signal_pending(current))1299				return result > 0 ? result : -ERESTARTSYS;1300			spin_lock_irq(&substream->lock);1301			if (!runtime->avail) {1302				spin_unlock_irq(&substream->lock);1303				return result > 0 ? result : -EIO;1304			}1305		}1306		spin_unlock_irq(&substream->lock);1307		count1 = snd_rawmidi_kernel_read1(substream,1308						  (unsigned char __user *)buf,1309						  NULL/*kernelbuf*/,1310						  count);1311		if (count1 < 0)1312			return result > 0 ? result : count1;1313		result += count1;1314		buf += count1;1315		count -= count1;1316	}1317	return result;1318}1319 1320/**1321 * snd_rawmidi_transmit_empty - check whether the output buffer is empty1322 * @substream: the rawmidi substream1323 *1324 * Return: 1 if the internal output buffer is empty, 0 if not.1325 */1326int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream)1327{1328	struct snd_rawmidi_runtime *runtime;1329 1330	guard(spinlock_irqsave)(&substream->lock);1331	runtime = substream->runtime;1332	if (!substream->opened || !runtime || !runtime->buffer) {1333		rmidi_dbg(substream->rmidi,1334			  "snd_rawmidi_transmit_empty: output is not active!!!\n");1335		return 1;1336	}1337	return (runtime->avail >= runtime->buffer_size);1338}1339EXPORT_SYMBOL(snd_rawmidi_transmit_empty);1340 1341/*1342 * __snd_rawmidi_transmit_peek - copy data from the internal buffer1343 * @substream: the rawmidi substream1344 * @buffer: the buffer pointer1345 * @count: data size to transfer1346 *1347 * This is a variant of snd_rawmidi_transmit_peek() without spinlock.1348 */1349static int __snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,1350				       unsigned char *buffer, int count)1351{1352	int result, count1;1353	struct snd_rawmidi_runtime *runtime = substream->runtime;1354 1355	if (runtime->buffer == NULL) {1356		rmidi_dbg(substream->rmidi,1357			  "snd_rawmidi_transmit_peek: output is not active!!!\n");1358		return -EINVAL;1359	}1360	result = 0;1361	if (runtime->avail >= runtime->buffer_size) {1362		/* warning: lowlevel layer MUST trigger down the hardware */1363		goto __skip;1364	}1365	if (count == 1) {	/* special case, faster code */1366		*buffer = runtime->buffer[runtime->hw_ptr];1367		result++;1368	} else {1369		count1 = runtime->buffer_size - runtime->hw_ptr;1370		if (count1 > count)1371			count1 = count;1372		if (count1 > (int)(runtime->buffer_size - runtime->avail))1373			count1 = runtime->buffer_size - runtime->avail;1374		count1 = get_aligned_size(runtime, count1);1375		if (!count1)1376			goto __skip;1377		memcpy(buffer, runtime->buffer + runtime->hw_ptr, count1);1378		count -= count1;1379		result += count1;1380		if (count > 0) {1381			if (count > (int)(runtime->buffer_size - runtime->avail - count1))1382				count = runtime->buffer_size - runtime->avail - count1;1383			count = get_aligned_size(runtime, count);1384			if (!count)1385				goto __skip;1386			memcpy(buffer + count1, runtime->buffer, count);1387			result += count;1388		}1389	}1390      __skip:1391	return result;1392}1393 1394/**1395 * snd_rawmidi_transmit_peek - copy data from the internal buffer1396 * @substream: the rawmidi substream1397 * @buffer: the buffer pointer1398 * @count: data size to transfer1399 *1400 * Copies data from the internal output buffer to the given buffer.1401 *1402 * Call this in the interrupt handler when the midi output is ready,1403 * and call snd_rawmidi_transmit_ack() after the transmission is1404 * finished.1405 *1406 * Return: The size of copied data, or a negative error code on failure.1407 */1408int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,1409			      unsigned char *buffer, int count)1410{1411	guard(spinlock_irqsave)(&substream->lock);1412	if (!substream->opened || !substream->runtime)1413		return -EBADFD;1414	return __snd_rawmidi_transmit_peek(substream, buffer, count);1415}1416EXPORT_SYMBOL(snd_rawmidi_transmit_peek);1417 1418/*1419 * __snd_rawmidi_transmit_ack - acknowledge the transmission1420 * @substream: the rawmidi substream1421 * @count: the transferred count1422 *1423 * This is a variant of __snd_rawmidi_transmit_ack() without spinlock.1424 */1425static int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream,1426				      int count)1427{1428	struct snd_rawmidi_runtime *runtime = substream->runtime;1429 1430	if (runtime->buffer == NULL) {1431		rmidi_dbg(substream->rmidi,1432			  "snd_rawmidi_transmit_ack: output is not active!!!\n");1433		return -EINVAL;1434	}1435	snd_BUG_ON(runtime->avail + count > runtime->buffer_size);1436	count = get_aligned_size(runtime, count);1437	runtime->hw_ptr += count;1438	runtime->hw_ptr %= runtime->buffer_size;1439	runtime->avail += count;1440	substream->bytes += count;1441	if (count > 0) {1442		if (runtime->drain || __snd_rawmidi_ready(runtime))1443			wake_up(&runtime->sleep);1444	}1445	return count;1446}1447 1448/**1449 * snd_rawmidi_transmit_ack - acknowledge the transmission1450 * @substream: the rawmidi substream1451 * @count: the transferred count1452 *1453 * Advances the hardware pointer for the internal output buffer with1454 * the given size and updates the condition.1455 * Call after the transmission is finished.1456 *1457 * Return: The advanced size if successful, or a negative error code on failure.1458 */1459int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)1460{1461	guard(spinlock_irqsave)(&substream->lock);1462	if (!substream->opened || !substream->runtime)1463		return -EBADFD;1464	return __snd_rawmidi_transmit_ack(substream, count);1465}1466EXPORT_SYMBOL(snd_rawmidi_transmit_ack);1467 1468/**1469 * snd_rawmidi_transmit - copy from the buffer to the device1470 * @substream: the rawmidi substream1471 * @buffer: the buffer pointer1472 * @count: the data size to transfer1473 *1474 * Copies data from the buffer to the device and advances the pointer.1475 *1476 * Return: The copied size if successful, or a negative error code on failure.1477 */1478int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,1479			 unsigned char *buffer, int count)1480{1481	guard(spinlock_irqsave)(&substream->lock);1482	if (!substream->opened)1483		return -EBADFD;1484	count = __snd_rawmidi_transmit_peek(substream, buffer, count);1485	if (count <= 0)1486		return count;1487	return __snd_rawmidi_transmit_ack(substream, count);1488}1489EXPORT_SYMBOL(snd_rawmidi_transmit);1490 1491/**1492 * snd_rawmidi_proceed - Discard the all pending bytes and proceed1493 * @substream: rawmidi substream1494 *1495 * Return: the number of discarded bytes1496 */1497int snd_rawmidi_proceed(struct snd_rawmidi_substream *substream)1498{1499	struct snd_rawmidi_runtime *runtime;1500	int count = 0;1501 1502	guard(spinlock_irqsave)(&substream->lock);1503	runtime = substream->runtime;1504	if (substream->opened && runtime &&1505	    runtime->avail < runtime->buffer_size) {1506		count = runtime->buffer_size - runtime->avail;1507		__snd_rawmidi_transmit_ack(substream, count);1508	}1509	return count;1510}1511EXPORT_SYMBOL(snd_rawmidi_proceed);1512 1513static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,1514				      const unsigned char __user *userbuf,1515				      const unsigned char *kernelbuf,1516				      long count)1517{1518	unsigned long flags;1519	long count1, result;1520	struct snd_rawmidi_runtime *runtime = substream->runtime;1521	unsigned long appl_ptr;1522 1523	if (!kernelbuf && !userbuf)1524		return -EINVAL;1525	if (snd_BUG_ON(!runtime->buffer))1526		return -EINVAL;1527 1528	result = 0;1529	spin_lock_irqsave(&substream->lock, flags);1530	if (substream->append) {1531		if ((long)runtime->avail < count) {1532			spin_unlock_irqrestore(&substream->lock, flags);1533			return -EAGAIN;1534		}1535	}1536	snd_rawmidi_buffer_ref(runtime);1537	while (count > 0 && runtime->avail > 0) {1538		count1 = runtime->buffer_size - runtime->appl_ptr;1539		if (count1 > count)1540			count1 = count;1541		if (count1 > (long)runtime->avail)1542			count1 = runtime->avail;1543 1544		/* update runtime->appl_ptr before unlocking for userbuf */1545		appl_ptr = runtime->appl_ptr;1546		runtime->appl_ptr += count1;1547		runtime->appl_ptr %= runtime->buffer_size;1548		runtime->avail -= count1;1549 1550		if (kernelbuf)1551			memcpy(runtime->buffer + appl_ptr,1552			       kernelbuf + result, count1);1553		else if (userbuf) {1554			spin_unlock_irqrestore(&substream->lock, flags);1555			if (copy_from_user(runtime->buffer + appl_ptr,1556					   userbuf + result, count1)) {1557				spin_lock_irqsave(&substream->lock, flags);1558				result = result > 0 ? result : -EFAULT;1559				goto __end;1560			}1561			spin_lock_irqsave(&substream->lock, flags);1562		}1563		result += count1;1564		count -= count1;1565	}1566      __end:1567	count1 = runtime->avail < runtime->buffer_size;1568	snd_rawmidi_buffer_unref(runtime);1569	spin_unlock_irqrestore(&substream->lock, flags);1570	if (count1)1571		snd_rawmidi_output_trigger(substream, 1);1572	return result;1573}1574 1575long snd_rawmidi_kernel_write(struct snd_rawmidi_substream *substream,1576			      const unsigned char *buf, long count)1577{1578	return snd_rawmidi_kernel_write1(substream, NULL, buf, count);1579}1580EXPORT_SYMBOL(snd_rawmidi_kernel_write);1581 1582static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,1583				 size_t count, loff_t *offset)1584{1585	long result, timeout;1586	int count1;1587	struct snd_rawmidi_file *rfile;1588	struct snd_rawmidi_runtime *runtime;1589	struct snd_rawmidi_substream *substream;1590 1591	rfile = file->private_data;1592	substream = rfile->output;1593	runtime = substream->runtime;1594	/* we cannot put an atomic message to our buffer */1595	if (substream->append && count > runtime->buffer_size)1596		return -EIO;1597	result = 0;1598	while (count > 0) {1599		spin_lock_irq(&substream->lock);1600		while (!snd_rawmidi_ready_append(substream, count)) {1601			wait_queue_entry_t wait;1602 1603			if (file->f_flags & O_NONBLOCK) {1604				spin_unlock_irq(&substream->lock);1605				return result > 0 ? result : -EAGAIN;1606			}1607			init_waitqueue_entry(&wait, current);1608			add_wait_queue(&runtime->sleep, &wait);1609			set_current_state(TASK_INTERRUPTIBLE);1610			spin_unlock_irq(&substream->lock);1611			timeout = schedule_timeout(30 * HZ);1612			remove_wait_queue(&runtime->sleep, &wait);1613			if (rfile->rmidi->card->shutdown)1614				return -ENODEV;1615			if (signal_pending(current))1616				return result > 0 ? result : -ERESTARTSYS;1617			spin_lock_irq(&substream->lock);1618			if (!runtime->avail && !timeout) {1619				spin_unlock_irq(&substream->lock);1620				return result > 0 ? result : -EIO;1621			}1622		}1623		spin_unlock_irq(&substream->lock);1624		count1 = snd_rawmidi_kernel_write1(substream, buf, NULL, count);1625		if (count1 < 0)1626			return result > 0 ? result : count1;1627		result += count1;1628		buf += count1;1629		if ((size_t)count1 < count && (file->f_flags & O_NONBLOCK))1630			break;1631		count -= count1;1632	}1633	if (file->f_flags & O_DSYNC) {1634		spin_lock_irq(&substream->lock);1635		while (runtime->avail != runtime->buffer_size) {1636			wait_queue_entry_t wait;1637			unsigned int last_avail = runtime->avail;1638 1639			init_waitqueue_entry(&wait, current);1640			add_wait_queue(&runtime->sleep, &wait);1641			set_current_state(TASK_INTERRUPTIBLE);1642			spin_unlock_irq(&substream->lock);1643			timeout = schedule_timeout(30 * HZ);1644			remove_wait_queue(&runtime->sleep, &wait);1645			if (signal_pending(current))1646				return result > 0 ? result : -ERESTARTSYS;1647			if (runtime->avail == last_avail && !timeout)1648				return result > 0 ? result : -EIO;1649			spin_lock_irq(&substream->lock);1650		}1651		spin_unlock_irq(&substream->lock);1652	}1653	return result;1654}1655 1656static __poll_t snd_rawmidi_poll(struct file *file, poll_table *wait)1657{1658	struct snd_rawmidi_file *rfile;1659	struct snd_rawmidi_runtime *runtime;1660	__poll_t mask;1661 1662	rfile = file->private_data;1663	if (rfile->input != NULL) {1664		runtime = rfile->input->runtime;1665		snd_rawmidi_input_trigger(rfile->input, 1);1666		poll_wait(file, &runtime->sleep, wait);1667	}1668	if (rfile->output != NULL) {1669		runtime = rfile->output->runtime;1670		poll_wait(file, &runtime->sleep, wait);1671	}1672	mask = 0;1673	if (rfile->input != NULL) {1674		if (snd_rawmidi_ready(rfile->input))1675			mask |= EPOLLIN | EPOLLRDNORM;1676	}1677	if (rfile->output != NULL) {1678		if (snd_rawmidi_ready(rfile->output))1679			mask |= EPOLLOUT | EPOLLWRNORM;1680	}1681	return mask;1682}1683 1684/*1685 */1686#ifdef CONFIG_COMPAT1687#include "rawmidi_compat.c"1688#else1689#define snd_rawmidi_ioctl_compat	NULL1690#endif1691 1692/*1693 */1694 1695static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,1696				       struct snd_info_buffer *buffer)1697{1698	struct snd_rawmidi *rmidi;1699	struct snd_rawmidi_substream *substream;1700	struct snd_rawmidi_runtime *runtime;1701	unsigned long buffer_size, avail, xruns;1702	unsigned int clock_type;1703	static const char *clock_names[4] = { "none", "realtime", "monotonic", "monotonic raw" };1704 1705	rmidi = entry->private_data;1706	snd_iprintf(buffer, "%s\n\n", rmidi->name);1707	if (IS_ENABLED(CONFIG_SND_UMP))1708		snd_iprintf(buffer, "Type: %s\n",1709			    rawmidi_is_ump(rmidi) ? "UMP" : "Legacy");1710	if (rmidi->ops && rmidi->ops->proc_read)1711		rmidi->ops->proc_read(entry, buffer);1712	guard(mutex)(&rmidi->open_mutex);1713	if (rmidi->info_flags & SNDRV_RAWMIDI_INFO_OUTPUT) {1714		list_for_each_entry(substream,1715				    &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams,1716				    list) {1717			snd_iprintf(buffer,1718				    "Output %d\n"1719				    "  Tx bytes     : %lu\n",1720				    substream->number,1721				    (unsigned long) substream->bytes);1722			if (substream->opened) {1723				snd_iprintf(buffer,1724				    "  Owner PID    : %d\n",1725				    pid_vnr(substream->pid));1726				runtime = substream->runtime;1727				scoped_guard(spinlock_irq, &substream->lock) {1728					buffer_size = runtime->buffer_size;1729					avail = runtime->avail;1730				}1731				snd_iprintf(buffer,1732				    "  Mode         : %s\n"1733				    "  Buffer size  : %lu\n"1734				    "  Avail        : %lu\n",1735				    runtime->oss ? "OSS compatible" : "native",1736				    buffer_size, avail);1737			}1738		}1739	}1740	if (rmidi->info_flags & SNDRV_RAWMIDI_INFO_INPUT) {1741		list_for_each_entry(substream,1742				    &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams,1743				    list) {1744			snd_iprintf(buffer,1745				    "Input %d\n"1746				    "  Rx bytes     : %lu\n",1747				    substream->number,1748				    (unsigned long) substream->bytes);1749			if (substream->opened) {1750				snd_iprintf(buffer,1751					    "  Owner PID    : %d\n",1752					    pid_vnr(substream->pid));1753				runtime = substream->runtime;1754				scoped_guard(spinlock_irq, &substream->lock) {1755					buffer_size = runtime->buffer_size;1756					avail = runtime->avail;1757					xruns = runtime->xruns;1758				}1759				snd_iprintf(buffer,1760					    "  Buffer size  : %lu\n"1761					    "  Avail        : %lu\n"1762					    "  Overruns     : %lu\n",1763					    buffer_size, avail, xruns);1764				if (substream->framing == SNDRV_RAWMIDI_MODE_FRAMING_TSTAMP) {1765					clock_type = substream->clock_type >> SNDRV_RAWMIDI_MODE_CLOCK_SHIFT;1766					if (!snd_BUG_ON(clock_type >= ARRAY_SIZE(clock_names)))1767						snd_iprintf(buffer,1768							    "  Framing      : tstamp\n"1769							    "  Clock type   : %s\n",1770							    clock_names[clock_type]);1771				}1772			}1773		}1774	}1775}1776 1777/*1778 *  Register functions1779 */1780 1781static const struct file_operations snd_rawmidi_f_ops = {1782	.owner =	THIS_MODULE,1783	.read =		snd_rawmidi_read,1784	.write =	snd_rawmidi_write,1785	.open =		snd_rawmidi_open,1786	.release =	snd_rawmidi_release,1787	.poll =		snd_rawmidi_poll,1788	.unlocked_ioctl =	snd_rawmidi_ioctl,1789	.compat_ioctl =	snd_rawmidi_ioctl_compat,1790};1791 1792static int snd_rawmidi_alloc_substreams(struct snd_rawmidi *rmidi,1793					struct snd_rawmidi_str *stream,1794					int direction,1795					int count)1796{1797	struct snd_rawmidi_substream *substream;1798	int idx;1799 1800	for (idx = 0; idx < count; idx++) {1801		substream = kzalloc(sizeof(*substream), GFP_KERNEL);1802		if (!substream)1803			return -ENOMEM;1804		substream->stream = direction;1805		substream->number = idx;1806		substream->rmidi = rmidi;1807		substream->pstr = stream;1808		spin_lock_init(&substream->lock);1809		list_add_tail(&substream->list, &stream->substreams);1810		stream->substream_count++;1811	}1812	return 0;1813}1814 1815/* used for both rawmidi and ump */1816int snd_rawmidi_init(struct snd_rawmidi *rmidi,1817		     struct snd_card *card, char *id, int device,1818		     int output_count, int input_count,1819		     unsigned int info_flags)1820{1821	int err;1822	static const struct snd_device_ops ops = {1823		.dev_free = snd_rawmidi_dev_free,1824		.dev_register = snd_rawmidi_dev_register,1825		.dev_disconnect = snd_rawmidi_dev_disconnect,1826	};1827 1828	rmidi->card = card;1829	rmidi->device = device;1830	mutex_init(&rmidi->open_mutex);1831	init_waitqueue_head(&rmidi->open_wait);1832	INIT_LIST_HEAD(&rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams);1833	INIT_LIST_HEAD(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams);1834	rmidi->info_flags = info_flags;1835 1836	if (id != NULL)1837		strscpy(rmidi->id, id, sizeof(rmidi->id));1838 1839	err = snd_device_alloc(&rmidi->dev, card);1840	if (err < 0)1841		return err;1842	if (rawmidi_is_ump(rmidi))1843		dev_set_name(rmidi->dev, "umpC%iD%i", card->number, device);1844	else1845		dev_set_name(rmidi->dev, "midiC%iD%i", card->number, device);1846 1847	err = snd_rawmidi_alloc_substreams(rmidi,1848					   &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT],1849					   SNDRV_RAWMIDI_STREAM_INPUT,1850					   input_count);1851	if (err < 0)1852		return err;1853	err = snd_rawmidi_alloc_substreams(rmidi,1854					   &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT],1855					   SNDRV_RAWMIDI_STREAM_OUTPUT,1856					   output_count);1857	if (err < 0)1858		return err;1859	err = snd_device_new(card, SNDRV_DEV_RAWMIDI, rmidi, &ops);1860	if (err < 0)1861		return err;1862	return 0;1863}1864EXPORT_SYMBOL_GPL(snd_rawmidi_init);1865 1866/**1867 * snd_rawmidi_new - create a rawmidi instance1868 * @card: the card instance1869 * @id: the id string1870 * @device: the device index1871 * @output_count: the number of output streams1872 * @input_count: the number of input streams1873 * @rrawmidi: the pointer to store the new rawmidi instance1874 *1875 * Creates a new rawmidi instance.1876 * Use snd_rawmidi_set_ops() to set the operators to the new instance.1877 *1878 * Return: Zero if successful, or a negative error code on failure.1879 */1880int snd_rawmidi_new(struct snd_card *card, char *id, int device,1881		    int output_count, int input_count,1882		    struct snd_rawmidi **rrawmidi)1883{1884	struct snd_rawmidi *rmidi;1885	int err;1886 1887	if (rrawmidi)1888		*rrawmidi = NULL;1889	rmidi = kzalloc(sizeof(*rmidi), GFP_KERNEL);1890	if (!rmidi)1891		return -ENOMEM;1892	err = snd_rawmidi_init(rmidi, card, id, device,1893			       output_count, input_count, 0);1894	if (err < 0) {1895		snd_rawmidi_free(rmidi);1896		return err;1897	}1898	if (rrawmidi)1899		*rrawmidi = rmidi;1900	return 0;1901}1902EXPORT_SYMBOL(snd_rawmidi_new);1903 1904static void snd_rawmidi_free_substreams(struct snd_rawmidi_str *stream)1905{1906	struct snd_rawmidi_substream *substream;1907 1908	while (!list_empty(&stream->substreams)) {1909		substream = list_entry(stream->substreams.next, struct snd_rawmidi_substream, list);1910		list_del(&substream->list);1911		kfree(substream);1912	}1913}1914 1915/* called from ump.c, too */1916int snd_rawmidi_free(struct snd_rawmidi *rmidi)1917{1918	if (!rmidi)1919		return 0;1920 1921	snd_info_free_entry(rmidi->proc_entry);1922	rmidi->proc_entry = NULL;1923	if (rmidi->ops && rmidi->ops->dev_unregister)1924		rmidi->ops->dev_unregister(rmidi);1925 1926	snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]);1927	snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]);1928	if (rmidi->private_free)1929		rmidi->private_free(rmidi);1930	put_device(rmidi->dev);1931	kfree(rmidi);1932	return 0;1933}1934EXPORT_SYMBOL_GPL(snd_rawmidi_free);1935 1936static int snd_rawmidi_dev_free(struct snd_device *device)1937{1938	struct snd_rawmidi *rmidi = device->device_data;1939 1940	return snd_rawmidi_free(rmidi);1941}1942 1943#if IS_ENABLED(CONFIG_SND_SEQUENCER)1944static void snd_rawmidi_dev_seq_free(struct snd_seq_device *device)1945{1946	struct snd_rawmidi *rmidi = device->private_data;1947 1948	rmidi->seq_dev = NULL;1949}1950#endif1951 1952static int snd_rawmidi_dev_register(struct snd_device *device)1953{1954	int err;1955	struct snd_info_entry *entry;1956	char name[16];1957	struct snd_rawmidi *rmidi = device->device_data;1958 1959	if (rmidi->device >= SNDRV_RAWMIDI_DEVICES)1960		return -ENOMEM;1961	err = 0;1962	scoped_guard(mutex, &register_mutex) {1963		if (snd_rawmidi_search(rmidi->card, rmidi->device))1964			err = -EBUSY;1965		else1966			list_add_tail(&rmidi->list, &snd_rawmidi_devices);1967	}1968	if (err < 0)1969		return err;1970 1971	err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI,1972				  rmidi->card, rmidi->device,1973				  &snd_rawmidi_f_ops, rmidi, rmidi->dev);1974	if (err < 0) {1975		rmidi_err(rmidi, "unable to register\n");1976		goto error;1977	}1978	if (rmidi->ops && rmidi->ops->dev_register) {1979		err = rmidi->ops->dev_register(rmidi);1980		if (err < 0)1981			goto error_unregister;1982	}1983#ifdef CONFIG_SND_OSSEMUL1984	rmidi->ossreg = 0;1985	if (!rawmidi_is_ump(rmidi) &&1986	    (int)rmidi->device == midi_map[rmidi->card->number]) {1987		if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI,1988					    rmidi->card, 0, &snd_rawmidi_f_ops,1989					    rmidi) < 0) {1990			rmidi_err(rmidi,1991				  "unable to register OSS rawmidi device %i:%i\n",1992				  rmidi->card->number, 0);1993		} else {1994			rmidi->ossreg++;1995#ifdef SNDRV_OSS_INFO_DEV_MIDI1996			snd_oss_info_register(SNDRV_OSS_INFO_DEV_MIDI, rmidi->card->number, rmidi->name);1997#endif1998		}1999	}2000	if (!rawmidi_is_ump(rmidi) &&2001	    (int)rmidi->device == amidi_map[rmidi->card->number]) {2002		if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI,2003					    rmidi->card, 1, &snd_rawmidi_f_ops,2004					    rmidi) < 0) {2005			rmidi_err(rmidi,2006				  "unable to register OSS rawmidi device %i:%i\n",2007				  rmidi->card->number, 1);2008		} else {2009			rmidi->ossreg++;2010		}2011	}2012#endif /* CONFIG_SND_OSSEMUL */2013	sprintf(name, "midi%d", rmidi->device);2014	entry = snd_info_create_card_entry(rmidi->card, name, rmidi->card->proc_root);2015	if (entry) {2016		entry->private_data = rmidi;2017		entry->c.text.read = snd_rawmidi_proc_info_read;2018		if (snd_info_register(entry) < 0) {2019			snd_info_free_entry(entry);2020			entry = NULL;2021		}2022	}2023	rmidi->proc_entry = entry;2024#if IS_ENABLED(CONFIG_SND_SEQUENCER)2025	/* no own registration mechanism? */2026	if (!rmidi->ops || !rmidi->ops->dev_register) {2027		if (snd_seq_device_new(rmidi->card, rmidi->device, SNDRV_SEQ_DEV_ID_MIDISYNTH, 0, &rmidi->seq_dev) >= 0) {2028			rmidi->seq_dev->private_data = rmidi;2029			rmidi->seq_dev->private_free = snd_rawmidi_dev_seq_free;2030			sprintf(rmidi->seq_dev->name, "MIDI %d-%d", rmidi->card->number, rmidi->device);2031			snd_device_register(rmidi->card, rmidi->seq_dev);2032		}2033	}2034#endif2035	return 0;2036 2037 error_unregister:2038	snd_unregister_device(rmidi->dev);2039 error:2040	scoped_guard(mutex, &register_mutex)2041		list_del(&rmidi->list);2042	return err;2043}2044 2045static int snd_rawmidi_dev_disconnect(struct snd_device *device)2046{2047	struct snd_rawmidi *rmidi = device->device_data;2048	int dir;2049 2050	guard(mutex)(&register_mutex);2051	guard(mutex)(&rmidi->open_mutex);2052	wake_up(&rmidi->open_wait);2053	list_del_init(&rmidi->list);2054	for (dir = 0; dir < 2; dir++) {2055		struct snd_rawmidi_substream *s;2056 2057		list_for_each_entry(s, &rmidi->streams[dir].substreams, list) {2058			if (s->runtime)2059				wake_up(&s->runtime->sleep);2060		}2061	}2062 2063#ifdef CONFIG_SND_OSSEMUL2064	if (rmidi->ossreg) {2065		if ((int)rmidi->device == midi_map[rmidi->card->number]) {2066			snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI, rmidi->card, 0);2067#ifdef SNDRV_OSS_INFO_DEV_MIDI2068			snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_MIDI, rmidi->card->number);2069#endif2070		}2071		if ((int)rmidi->device == amidi_map[rmidi->card->number])2072			snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI, rmidi->card, 1);2073		rmidi->ossreg = 0;2074	}2075#endif /* CONFIG_SND_OSSEMUL */2076	snd_unregister_device(rmidi->dev);2077	return 0;2078}2079 2080/**2081 * snd_rawmidi_set_ops - set the rawmidi operators2082 * @rmidi: the rawmidi instance2083 * @stream: the stream direction, SNDRV_RAWMIDI_STREAM_XXX2084 * @ops: the operator table2085 *2086 * Sets the rawmidi operators for the given stream direction.2087 */2088void snd_rawmidi_set_ops(struct snd_rawmidi *rmidi, int stream,2089			 const struct snd_rawmidi_ops *ops)2090{2091	struct snd_rawmidi_substream *substream;2092 2093	list_for_each_entry(substream, &rmidi->streams[stream].substreams, list)2094		substream->ops = ops;2095}2096EXPORT_SYMBOL(snd_rawmidi_set_ops);2097 2098/*2099 *  ENTRY functions2100 */2101 2102static int __init alsa_rawmidi_init(void)2103{2104 2105	snd_ctl_register_ioctl(snd_rawmidi_control_ioctl);2106	snd_ctl_register_ioctl_compat(snd_rawmidi_control_ioctl);2107#ifdef CONFIG_SND_OSSEMUL2108	{ int i;2109	/* check device map table */2110	for (i = 0; i < SNDRV_CARDS; i++) {2111		if (midi_map[i] < 0 || midi_map[i] >= SNDRV_RAWMIDI_DEVICES) {2112			pr_err("ALSA: rawmidi: invalid midi_map[%d] = %d\n",2113			       i, midi_map[i]);2114			midi_map[i] = 0;2115		}2116		if (amidi_map[i] < 0 || amidi_map[i] >= SNDRV_RAWMIDI_DEVICES) {2117			pr_err("ALSA: rawmidi: invalid amidi_map[%d] = %d\n",2118			       i, amidi_map[i]);2119			amidi_map[i] = 1;2120		}2121	}2122	}2123#endif /* CONFIG_SND_OSSEMUL */2124	return 0;2125}2126 2127static void __exit alsa_rawmidi_exit(void)2128{2129	snd_ctl_unregister_ioctl(snd_rawmidi_control_ioctl);2130	snd_ctl_unregister_ioctl_compat(snd_rawmidi_control_ioctl);2131}2132 2133module_init(alsa_rawmidi_init)2134module_exit(alsa_rawmidi_exit)2135