brintos

brintos / linux-shallow public Read only

0
0
Text · 70.5 KiB · 3930e2f Raw
2766 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *  ALSA sequencer Client Manager4 *  Copyright (c) 1998-2001 by Frank van de Pol <fvdpol@coil.demon.nl>5 *                             Jaroslav Kysela <perex@perex.cz>6 *                             Takashi Iwai <tiwai@suse.de>7 */8 9#include <linux/init.h>10#include <linux/export.h>11#include <linux/slab.h>12#include <sound/core.h>13#include <sound/minors.h>14#include <linux/kmod.h>15 16#include <sound/seq_kernel.h>17#include <sound/ump.h>18#include "seq_clientmgr.h"19#include "seq_memory.h"20#include "seq_queue.h"21#include "seq_timer.h"22#include "seq_info.h"23#include "seq_system.h"24#include "seq_ump_convert.h"25#include <sound/seq_device.h>26#ifdef CONFIG_COMPAT27#include <linux/compat.h>28#endif29 30/* Client Manager31 32 * this module handles the connections of userland and kernel clients33 * 34 */35 36/*37 * There are four ranges of client numbers (last two shared):38 * 0..15: global clients39 * 16..127: statically allocated client numbers for cards 0..2740 * 128..191: dynamically allocated client numbers for cards 28..3141 * 128..191: dynamically allocated client numbers for applications42 */43 44/* number of kernel non-card clients */45#define SNDRV_SEQ_GLOBAL_CLIENTS	1646/* clients per cards, for static clients */47#define SNDRV_SEQ_CLIENTS_PER_CARD	448/* dynamically allocated client numbers (both kernel drivers and user space) */49#define SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN	12850 51#define SNDRV_SEQ_LFLG_INPUT	0x000152#define SNDRV_SEQ_LFLG_OUTPUT	0x000253#define SNDRV_SEQ_LFLG_OPEN	(SNDRV_SEQ_LFLG_INPUT|SNDRV_SEQ_LFLG_OUTPUT)54 55static DEFINE_SPINLOCK(clients_lock);56static DEFINE_MUTEX(register_mutex);57 58/*59 * client table60 */61static char clienttablock[SNDRV_SEQ_MAX_CLIENTS];62static struct snd_seq_client *clienttab[SNDRV_SEQ_MAX_CLIENTS];63static struct snd_seq_usage client_usage;64 65/*66 * prototypes67 */68static int bounce_error_event(struct snd_seq_client *client,69			      struct snd_seq_event *event,70			      int err, int atomic, int hop);71static int snd_seq_deliver_single_event(struct snd_seq_client *client,72					struct snd_seq_event *event,73					int atomic, int hop);74 75#if IS_ENABLED(CONFIG_SND_SEQ_UMP)76static void free_ump_info(struct snd_seq_client *client);77#endif78 79/*80 */81static inline unsigned short snd_seq_file_flags(struct file *file)82{83        switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {84        case FMODE_WRITE:85                return SNDRV_SEQ_LFLG_OUTPUT;86        case FMODE_READ:87                return SNDRV_SEQ_LFLG_INPUT;88        default:89                return SNDRV_SEQ_LFLG_OPEN;90        }91}92 93static inline int snd_seq_write_pool_allocated(struct snd_seq_client *client)94{95	return snd_seq_total_cells(client->pool) > 0;96}97 98/* return pointer to client structure for specified id */99static struct snd_seq_client *clientptr(int clientid)100{101	if (clientid < 0 || clientid >= SNDRV_SEQ_MAX_CLIENTS) {102		pr_debug("ALSA: seq: oops. Trying to get pointer to client %d\n",103			   clientid);104		return NULL;105	}106	return clienttab[clientid];107}108 109struct snd_seq_client *snd_seq_client_use_ptr(int clientid)110{111	unsigned long flags;112	struct snd_seq_client *client;113 114	if (clientid < 0 || clientid >= SNDRV_SEQ_MAX_CLIENTS) {115		pr_debug("ALSA: seq: oops. Trying to get pointer to client %d\n",116			   clientid);117		return NULL;118	}119	spin_lock_irqsave(&clients_lock, flags);120	client = clientptr(clientid);121	if (client)122		goto __lock;123	if (clienttablock[clientid]) {124		spin_unlock_irqrestore(&clients_lock, flags);125		return NULL;126	}127	spin_unlock_irqrestore(&clients_lock, flags);128#ifdef CONFIG_MODULES129	if (!in_interrupt()) {130		static DECLARE_BITMAP(client_requested, SNDRV_SEQ_GLOBAL_CLIENTS);131		static DECLARE_BITMAP(card_requested, SNDRV_CARDS);132 133		if (clientid < SNDRV_SEQ_GLOBAL_CLIENTS) {134			int idx;135			136			if (!test_and_set_bit(clientid, client_requested)) {137				for (idx = 0; idx < 15; idx++) {138					if (seq_client_load[idx] < 0)139						break;140					if (seq_client_load[idx] == clientid) {141						request_module("snd-seq-client-%i",142							       clientid);143						break;144					}145				}146			}147		} else if (clientid < SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN) {148			int card = (clientid - SNDRV_SEQ_GLOBAL_CLIENTS) /149				SNDRV_SEQ_CLIENTS_PER_CARD;150			if (card < snd_ecards_limit) {151				if (!test_and_set_bit(card, card_requested))152					snd_request_card(card);153				snd_seq_device_load_drivers();154			}155		}156		spin_lock_irqsave(&clients_lock, flags);157		client = clientptr(clientid);158		if (client)159			goto __lock;160		spin_unlock_irqrestore(&clients_lock, flags);161	}162#endif163	return NULL;164 165      __lock:166	snd_use_lock_use(&client->use_lock);167	spin_unlock_irqrestore(&clients_lock, flags);168	return client;169}170 171/* Take refcount and perform ioctl_mutex lock on the given client;172 * used only for OSS sequencer173 * Unlock via snd_seq_client_ioctl_unlock() below174 */175bool snd_seq_client_ioctl_lock(int clientid)176{177	struct snd_seq_client *client;178 179	client = snd_seq_client_use_ptr(clientid);180	if (!client)181		return false;182	mutex_lock(&client->ioctl_mutex);183	/* The client isn't unrefed here; see snd_seq_client_ioctl_unlock() */184	return true;185}186EXPORT_SYMBOL_GPL(snd_seq_client_ioctl_lock);187 188/* Unlock and unref the given client; for OSS sequencer use only */189void snd_seq_client_ioctl_unlock(int clientid)190{191	struct snd_seq_client *client;192 193	client = snd_seq_client_use_ptr(clientid);194	if (WARN_ON(!client))195		return;196	mutex_unlock(&client->ioctl_mutex);197	/* The doubly unrefs below are intentional; the first one releases the198	 * leftover from snd_seq_client_ioctl_lock() above, and the second one199	 * is for releasing snd_seq_client_use_ptr() in this function200	 */201	snd_seq_client_unlock(client);202	snd_seq_client_unlock(client);203}204EXPORT_SYMBOL_GPL(snd_seq_client_ioctl_unlock);205 206static void usage_alloc(struct snd_seq_usage *res, int num)207{208	res->cur += num;209	if (res->cur > res->peak)210		res->peak = res->cur;211}212 213static void usage_free(struct snd_seq_usage *res, int num)214{215	res->cur -= num;216}217 218/* initialise data structures */219int __init client_init_data(void)220{221	/* zap out the client table */222	memset(&clienttablock, 0, sizeof(clienttablock));223	memset(&clienttab, 0, sizeof(clienttab));224	return 0;225}226 227 228static struct snd_seq_client *seq_create_client1(int client_index, int poolsize)229{230	int c;231	struct snd_seq_client *client;232 233	/* init client data */234	client = kzalloc(sizeof(*client), GFP_KERNEL);235	if (client == NULL)236		return NULL;237	client->pool = snd_seq_pool_new(poolsize);238	if (client->pool == NULL) {239		kfree(client);240		return NULL;241	}242	client->type = NO_CLIENT;243	snd_use_lock_init(&client->use_lock);244	rwlock_init(&client->ports_lock);245	mutex_init(&client->ports_mutex);246	INIT_LIST_HEAD(&client->ports_list_head);247	mutex_init(&client->ioctl_mutex);248	client->ump_endpoint_port = -1;249 250	/* find free slot in the client table */251	spin_lock_irq(&clients_lock);252	if (client_index < 0) {253		for (c = SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN;254		     c < SNDRV_SEQ_MAX_CLIENTS;255		     c++) {256			if (clienttab[c] || clienttablock[c])257				continue;258			clienttab[client->number = c] = client;259			spin_unlock_irq(&clients_lock);260			return client;261		}262	} else {263		if (clienttab[client_index] == NULL && !clienttablock[client_index]) {264			clienttab[client->number = client_index] = client;265			spin_unlock_irq(&clients_lock);266			return client;267		}268	}269	spin_unlock_irq(&clients_lock);270	snd_seq_pool_delete(&client->pool);271	kfree(client);272	return NULL;	/* no free slot found or busy, return failure code */273}274 275 276static int seq_free_client1(struct snd_seq_client *client)277{278	if (!client)279		return 0;280	spin_lock_irq(&clients_lock);281	clienttablock[client->number] = 1;282	clienttab[client->number] = NULL;283	spin_unlock_irq(&clients_lock);284	snd_seq_delete_all_ports(client);285	snd_seq_queue_client_leave(client->number);286	snd_use_lock_sync(&client->use_lock);287	if (client->pool)288		snd_seq_pool_delete(&client->pool);289	spin_lock_irq(&clients_lock);290	clienttablock[client->number] = 0;291	spin_unlock_irq(&clients_lock);292	return 0;293}294 295 296static void seq_free_client(struct snd_seq_client * client)297{298	mutex_lock(&register_mutex);299	switch (client->type) {300	case NO_CLIENT:301		pr_warn("ALSA: seq: Trying to free unused client %d\n",302			client->number);303		break;304	case USER_CLIENT:305	case KERNEL_CLIENT:306		seq_free_client1(client);307		usage_free(&client_usage, 1);308		break;309 310	default:311		pr_err("ALSA: seq: Trying to free client %d with undefined type = %d\n",312			   client->number, client->type);313	}314	mutex_unlock(&register_mutex);315 316	snd_seq_system_client_ev_client_exit(client->number);317}318 319 320 321/* -------------------------------------------------------- */322 323/* create a user client */324static int snd_seq_open(struct inode *inode, struct file *file)325{326	int c, mode;			/* client id */327	struct snd_seq_client *client;328	struct snd_seq_user_client *user;329	int err;330 331	err = stream_open(inode, file);332	if (err < 0)333		return err;334 335	mutex_lock(&register_mutex);336	client = seq_create_client1(-1, SNDRV_SEQ_DEFAULT_EVENTS);337	if (!client) {338		mutex_unlock(&register_mutex);339		return -ENOMEM;	/* failure code */340	}341 342	mode = snd_seq_file_flags(file);343	if (mode & SNDRV_SEQ_LFLG_INPUT)344		client->accept_input = 1;345	if (mode & SNDRV_SEQ_LFLG_OUTPUT)346		client->accept_output = 1;347 348	user = &client->data.user;349	user->fifo = NULL;350	user->fifo_pool_size = 0;351 352	if (mode & SNDRV_SEQ_LFLG_INPUT) {353		user->fifo_pool_size = SNDRV_SEQ_DEFAULT_CLIENT_EVENTS;354		user->fifo = snd_seq_fifo_new(user->fifo_pool_size);355		if (user->fifo == NULL) {356			seq_free_client1(client);357			kfree(client);358			mutex_unlock(&register_mutex);359			return -ENOMEM;360		}361	}362 363	usage_alloc(&client_usage, 1);364	client->type = USER_CLIENT;365	mutex_unlock(&register_mutex);366 367	c = client->number;368	file->private_data = client;369 370	/* fill client data */371	user->file = file;372	sprintf(client->name, "Client-%d", c);373	client->data.user.owner = get_pid(task_pid(current));374 375	/* make others aware this new client */376	snd_seq_system_client_ev_client_start(c);377 378	return 0;379}380 381/* delete a user client */382static int snd_seq_release(struct inode *inode, struct file *file)383{384	struct snd_seq_client *client = file->private_data;385 386	if (client) {387		seq_free_client(client);388		if (client->data.user.fifo)389			snd_seq_fifo_delete(&client->data.user.fifo);390#if IS_ENABLED(CONFIG_SND_SEQ_UMP)391		free_ump_info(client);392#endif393		put_pid(client->data.user.owner);394		kfree(client);395	}396 397	return 0;398}399 400static bool event_is_compatible(const struct snd_seq_client *client,401				const struct snd_seq_event *ev)402{403	if (snd_seq_ev_is_ump(ev) && !client->midi_version)404		return false;405	if (snd_seq_ev_is_ump(ev) && snd_seq_ev_is_variable(ev))406		return false;407	return true;408}409 410/* handle client read() */411/* possible error values:412 *	-ENXIO	invalid client or file open mode413 *	-ENOSPC	FIFO overflow (the flag is cleared after this error report)414 *	-EINVAL	no enough user-space buffer to write the whole event415 *	-EFAULT	seg. fault during copy to user space416 */417static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count,418			    loff_t *offset)419{420	struct snd_seq_client *client = file->private_data;421	struct snd_seq_fifo *fifo;422	size_t aligned_size;423	int err;424	long result = 0;425	struct snd_seq_event_cell *cell;426 427	if (!(snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_INPUT))428		return -ENXIO;429 430	if (!access_ok(buf, count))431		return -EFAULT;432 433	/* check client structures are in place */434	if (snd_BUG_ON(!client))435		return -ENXIO;436 437	if (!client->accept_input)438		return -ENXIO;439	fifo = client->data.user.fifo;440	if (!fifo)441		return -ENXIO;442 443	if (atomic_read(&fifo->overflow) > 0) {444		/* buffer overflow is detected */445		snd_seq_fifo_clear(fifo);446		/* return error code */447		return -ENOSPC;448	}449 450	cell = NULL;451	err = 0;452	snd_seq_fifo_lock(fifo);453 454	if (IS_ENABLED(CONFIG_SND_SEQ_UMP) && client->midi_version > 0)455		aligned_size = sizeof(struct snd_seq_ump_event);456	else457		aligned_size = sizeof(struct snd_seq_event);458 459	/* while data available in queue */460	while (count >= aligned_size) {461		int nonblock;462 463		nonblock = (file->f_flags & O_NONBLOCK) || result > 0;464		err = snd_seq_fifo_cell_out(fifo, &cell, nonblock);465		if (err < 0)466			break;467		if (!event_is_compatible(client, &cell->event)) {468			snd_seq_cell_free(cell);469			cell = NULL;470			continue;471		}472		if (snd_seq_ev_is_variable(&cell->event)) {473			struct snd_seq_ump_event tmpev;474 475			memcpy(&tmpev, &cell->event, aligned_size);476			tmpev.data.ext.len &= ~SNDRV_SEQ_EXT_MASK;477			if (copy_to_user(buf, &tmpev, aligned_size)) {478				err = -EFAULT;479				break;480			}481			count -= aligned_size;482			buf += aligned_size;483			err = snd_seq_expand_var_event(&cell->event, count,484						       (char __force *)buf, 0,485						       aligned_size);486			if (err < 0)487				break;488			result += err;489			count -= err;490			buf += err;491		} else {492			if (copy_to_user(buf, &cell->event, aligned_size)) {493				err = -EFAULT;494				break;495			}496			count -= aligned_size;497			buf += aligned_size;498		}499		snd_seq_cell_free(cell);500		cell = NULL; /* to be sure */501		result += aligned_size;502	}503 504	if (err < 0) {505		if (cell)506			snd_seq_fifo_cell_putback(fifo, cell);507		if (err == -EAGAIN && result > 0)508			err = 0;509	}510	snd_seq_fifo_unlock(fifo);511 512	return (err < 0) ? err : result;513}514 515 516/*517 * check access permission to the port518 */519static int check_port_perm(struct snd_seq_client_port *port, unsigned int flags)520{521	if ((port->capability & flags) != flags)522		return 0;523	return flags;524}525 526/*527 * check if the destination client is available, and return the pointer528 */529static struct snd_seq_client *get_event_dest_client(struct snd_seq_event *event)530{531	struct snd_seq_client *dest;532 533	dest = snd_seq_client_use_ptr(event->dest.client);534	if (dest == NULL)535		return NULL;536	if (! dest->accept_input)537		goto __not_avail;538	if (snd_seq_ev_is_ump(event))539		return dest; /* ok - no filter checks */540 541	if ((dest->filter & SNDRV_SEQ_FILTER_USE_EVENT) &&542	    ! test_bit(event->type, dest->event_filter))543		goto __not_avail;544 545	return dest; /* ok - accessible */546__not_avail:547	snd_seq_client_unlock(dest);548	return NULL;549}550 551 552/*553 * Return the error event.554 *555 * If the receiver client is a user client, the original event is556 * encapsulated in SNDRV_SEQ_EVENT_BOUNCE as variable length event.  If557 * the original event is also variable length, the external data is558 * copied after the event record. 559 * If the receiver client is a kernel client, the original event is560 * quoted in SNDRV_SEQ_EVENT_KERNEL_ERROR, since this requires no extra561 * kmalloc.562 */563static int bounce_error_event(struct snd_seq_client *client,564			      struct snd_seq_event *event,565			      int err, int atomic, int hop)566{567	struct snd_seq_event bounce_ev;568	int result;569 570	if (client == NULL ||571	    ! (client->filter & SNDRV_SEQ_FILTER_BOUNCE) ||572	    ! client->accept_input)573		return 0; /* ignored */574 575	/* set up quoted error */576	memset(&bounce_ev, 0, sizeof(bounce_ev));577	bounce_ev.type = SNDRV_SEQ_EVENT_KERNEL_ERROR;578	bounce_ev.flags = SNDRV_SEQ_EVENT_LENGTH_FIXED;579	bounce_ev.queue = SNDRV_SEQ_QUEUE_DIRECT;580	bounce_ev.source.client = SNDRV_SEQ_CLIENT_SYSTEM;581	bounce_ev.source.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE;582	bounce_ev.dest.client = client->number;583	bounce_ev.dest.port = event->source.port;584	bounce_ev.data.quote.origin = event->dest;585	bounce_ev.data.quote.event = event;586	bounce_ev.data.quote.value = -err; /* use positive value */587	result = snd_seq_deliver_single_event(NULL, &bounce_ev, atomic, hop + 1);588	if (result < 0) {589		client->event_lost++;590		return result;591	}592 593	return result;594}595 596 597/*598 * rewrite the time-stamp of the event record with the curren time599 * of the given queue.600 * return non-zero if updated.601 */602static int update_timestamp_of_queue(struct snd_seq_event *event,603				     int queue, int real_time)604{605	struct snd_seq_queue *q;606 607	q = queueptr(queue);608	if (! q)609		return 0;610	event->queue = queue;611	event->flags &= ~SNDRV_SEQ_TIME_STAMP_MASK;612	if (real_time) {613		event->time.time = snd_seq_timer_get_cur_time(q->timer, true);614		event->flags |= SNDRV_SEQ_TIME_STAMP_REAL;615	} else {616		event->time.tick = snd_seq_timer_get_cur_tick(q->timer);617		event->flags |= SNDRV_SEQ_TIME_STAMP_TICK;618	}619	queuefree(q);620	return 1;621}622 623/* deliver a single event; called from below and UMP converter */624int __snd_seq_deliver_single_event(struct snd_seq_client *dest,625				   struct snd_seq_client_port *dest_port,626				   struct snd_seq_event *event,627				   int atomic, int hop)628{629	switch (dest->type) {630	case USER_CLIENT:631		if (!dest->data.user.fifo)632			return 0;633		return snd_seq_fifo_event_in(dest->data.user.fifo, event);634	case KERNEL_CLIENT:635		if (!dest_port->event_input)636			return 0;637		return dest_port->event_input(event,638					      snd_seq_ev_is_direct(event),639					      dest_port->private_data,640					      atomic, hop);641	}642	return 0;643}644 645/*646 * deliver an event to the specified destination.647 * if filter is non-zero, client filter bitmap is tested.648 *649 *  RETURN VALUE: 0 : if succeeded650 *		 <0 : error651 */652static int snd_seq_deliver_single_event(struct snd_seq_client *client,653					struct snd_seq_event *event,654					int atomic, int hop)655{656	struct snd_seq_client *dest = NULL;657	struct snd_seq_client_port *dest_port = NULL;658	int result = -ENOENT;659	int direct;660 661	direct = snd_seq_ev_is_direct(event);662 663	dest = get_event_dest_client(event);664	if (dest == NULL)665		goto __skip;666	dest_port = snd_seq_port_use_ptr(dest, event->dest.port);667	if (dest_port == NULL)668		goto __skip;669 670	/* check permission */671	if (! check_port_perm(dest_port, SNDRV_SEQ_PORT_CAP_WRITE)) {672		result = -EPERM;673		goto __skip;674	}675		676	if (dest_port->timestamping)677		update_timestamp_of_queue(event, dest_port->time_queue,678					  dest_port->time_real);679 680#if IS_ENABLED(CONFIG_SND_SEQ_UMP)681	if (!(dest->filter & SNDRV_SEQ_FILTER_NO_CONVERT)) {682		if (snd_seq_ev_is_ump(event)) {683			result = snd_seq_deliver_from_ump(client, dest, dest_port,684							  event, atomic, hop);685			goto __skip;686		} else if (snd_seq_client_is_ump(dest)) {687			result = snd_seq_deliver_to_ump(client, dest, dest_port,688							event, atomic, hop);689			goto __skip;690		}691	}692#endif /* CONFIG_SND_SEQ_UMP */693 694	result = __snd_seq_deliver_single_event(dest, dest_port, event,695						atomic, hop);696 697  __skip:698	if (dest_port)699		snd_seq_port_unlock(dest_port);700	if (dest)701		snd_seq_client_unlock(dest);702 703	if (result < 0 && !direct) {704		result = bounce_error_event(client, event, result, atomic, hop);705	}706	return result;707}708 709 710/*711 * send the event to all subscribers:712 */713static int __deliver_to_subscribers(struct snd_seq_client *client,714				    struct snd_seq_event *event,715				    struct snd_seq_client_port *src_port,716				    int atomic, int hop)717{718	struct snd_seq_subscribers *subs;719	int err, result = 0, num_ev = 0;720	union __snd_seq_event event_saved;721	size_t saved_size;722	struct snd_seq_port_subs_info *grp;723 724	/* save original event record */725	saved_size = snd_seq_event_packet_size(event);726	memcpy(&event_saved, event, saved_size);727	grp = &src_port->c_src;728	729	/* lock list */730	if (atomic)731		read_lock(&grp->list_lock);732	else733		down_read_nested(&grp->list_mutex, hop);734	list_for_each_entry(subs, &grp->list_head, src_list) {735		/* both ports ready? */736		if (atomic_read(&subs->ref_count) != 2)737			continue;738		event->dest = subs->info.dest;739		if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP)740			/* convert time according to flag with subscription */741			update_timestamp_of_queue(event, subs->info.queue,742						  subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIME_REAL);743		err = snd_seq_deliver_single_event(client, event, atomic, hop);744		if (err < 0) {745			/* save first error that occurs and continue */746			if (!result)747				result = err;748			continue;749		}750		num_ev++;751		/* restore original event record */752		memcpy(event, &event_saved, saved_size);753	}754	if (atomic)755		read_unlock(&grp->list_lock);756	else757		up_read(&grp->list_mutex);758	memcpy(event, &event_saved, saved_size);759	return (result < 0) ? result : num_ev;760}761 762static int deliver_to_subscribers(struct snd_seq_client *client,763				  struct snd_seq_event *event,764				  int atomic, int hop)765{766	struct snd_seq_client_port *src_port;767	int ret = 0, ret2;768 769	src_port = snd_seq_port_use_ptr(client, event->source.port);770	if (src_port) {771		ret = __deliver_to_subscribers(client, event, src_port, atomic, hop);772		snd_seq_port_unlock(src_port);773	}774 775	if (client->ump_endpoint_port < 0 ||776	    event->source.port == client->ump_endpoint_port)777		return ret;778 779	src_port = snd_seq_port_use_ptr(client, client->ump_endpoint_port);780	if (!src_port)781		return ret;782	ret2 = __deliver_to_subscribers(client, event, src_port, atomic, hop);783	snd_seq_port_unlock(src_port);784	return ret2 < 0 ? ret2 : ret;785}786 787/* deliver an event to the destination port(s).788 * if the event is to subscribers or broadcast, the event is dispatched789 * to multiple targets.790 *791 * RETURN VALUE: n > 0  : the number of delivered events.792 *               n == 0 : the event was not passed to any client.793 *               n < 0  : error - event was not processed.794 */795static int snd_seq_deliver_event(struct snd_seq_client *client, struct snd_seq_event *event,796				 int atomic, int hop)797{798	int result;799 800	hop++;801	if (hop >= SNDRV_SEQ_MAX_HOPS) {802		pr_debug("ALSA: seq: too long delivery path (%d:%d->%d:%d)\n",803			   event->source.client, event->source.port,804			   event->dest.client, event->dest.port);805		return -EMLINK;806	}807 808	if (snd_seq_ev_is_variable(event) &&809	    snd_BUG_ON(atomic && (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR)))810		return -EINVAL;811 812	if (event->queue == SNDRV_SEQ_ADDRESS_SUBSCRIBERS ||813	    event->dest.client == SNDRV_SEQ_ADDRESS_SUBSCRIBERS)814		result = deliver_to_subscribers(client, event, atomic, hop);815	else816		result = snd_seq_deliver_single_event(client, event, atomic, hop);817 818	return result;819}820 821/*822 * dispatch an event cell:823 * This function is called only from queue check routines in timer824 * interrupts or after enqueued.825 * The event cell shall be released or re-queued in this function.826 *827 * RETURN VALUE: n > 0  : the number of delivered events.828 *		 n == 0 : the event was not passed to any client.829 *		 n < 0  : error - event was not processed.830 */831int snd_seq_dispatch_event(struct snd_seq_event_cell *cell, int atomic, int hop)832{833	struct snd_seq_client *client;834	int result;835 836	if (snd_BUG_ON(!cell))837		return -EINVAL;838 839	client = snd_seq_client_use_ptr(cell->event.source.client);840	if (client == NULL) {841		snd_seq_cell_free(cell); /* release this cell */842		return -EINVAL;843	}844 845	if (!snd_seq_ev_is_ump(&cell->event) &&846	    cell->event.type == SNDRV_SEQ_EVENT_NOTE) {847		/* NOTE event:848		 * the event cell is re-used as a NOTE-OFF event and849		 * enqueued again.850		 */851		struct snd_seq_event tmpev, *ev;852 853		/* reserve this event to enqueue note-off later */854		tmpev = cell->event;855		tmpev.type = SNDRV_SEQ_EVENT_NOTEON;856		result = snd_seq_deliver_event(client, &tmpev, atomic, hop);857 858		/*859		 * This was originally a note event.  We now re-use the860		 * cell for the note-off event.861		 */862 863		ev = &cell->event;864		ev->type = SNDRV_SEQ_EVENT_NOTEOFF;865		ev->flags |= SNDRV_SEQ_PRIORITY_HIGH;866 867		/* add the duration time */868		switch (ev->flags & SNDRV_SEQ_TIME_STAMP_MASK) {869		case SNDRV_SEQ_TIME_STAMP_TICK:870			cell->event.time.tick += ev->data.note.duration;871			break;872		case SNDRV_SEQ_TIME_STAMP_REAL:873			/* unit for duration is ms */874			ev->time.time.tv_nsec += 1000000 * (ev->data.note.duration % 1000);875			ev->time.time.tv_sec += ev->data.note.duration / 1000 +876						ev->time.time.tv_nsec / 1000000000;877			ev->time.time.tv_nsec %= 1000000000;878			break;879		}880		ev->data.note.velocity = ev->data.note.off_velocity;881 882		/* Now queue this cell as the note off event */883		if (snd_seq_enqueue_event(cell, atomic, hop) < 0)884			snd_seq_cell_free(cell); /* release this cell */885 886	} else {887		/* Normal events:888		 * event cell is freed after processing the event889		 */890 891		result = snd_seq_deliver_event(client, &cell->event, atomic, hop);892		snd_seq_cell_free(cell);893	}894 895	snd_seq_client_unlock(client);896	return result;897}898 899 900/* Allocate a cell from client pool and enqueue it to queue:901 * if pool is empty and blocking is TRUE, sleep until a new cell is902 * available.903 */904static int snd_seq_client_enqueue_event(struct snd_seq_client *client,905					struct snd_seq_event *event,906					struct file *file, int blocking,907					int atomic, int hop,908					struct mutex *mutexp)909{910	struct snd_seq_event_cell *cell;911	int err;912 913	/* special queue values - force direct passing */914	if (event->queue == SNDRV_SEQ_ADDRESS_SUBSCRIBERS) {915		event->dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;916		event->queue = SNDRV_SEQ_QUEUE_DIRECT;917	} else if (event->dest.client == SNDRV_SEQ_ADDRESS_SUBSCRIBERS) {918		/* check presence of source port */919		struct snd_seq_client_port *src_port = snd_seq_port_use_ptr(client, event->source.port);920		if (src_port == NULL)921			return -EINVAL;922		snd_seq_port_unlock(src_port);923	}924 925	/* direct event processing without enqueued */926	if (snd_seq_ev_is_direct(event)) {927		if (!snd_seq_ev_is_ump(event) &&928		    event->type == SNDRV_SEQ_EVENT_NOTE)929			return -EINVAL; /* this event must be enqueued! */930		return snd_seq_deliver_event(client, event, atomic, hop);931	}932 933	/* Not direct, normal queuing */934	if (snd_seq_queue_is_used(event->queue, client->number) <= 0)935		return -EINVAL;  /* invalid queue */936	if (! snd_seq_write_pool_allocated(client))937		return -ENXIO; /* queue is not allocated */938 939	/* allocate an event cell */940	err = snd_seq_event_dup(client->pool, event, &cell, !blocking || atomic,941				file, mutexp);942	if (err < 0)943		return err;944 945	/* we got a cell. enqueue it. */946	err = snd_seq_enqueue_event(cell, atomic, hop);947	if (err < 0) {948		snd_seq_cell_free(cell);949		return err;950	}951 952	return 0;953}954 955 956/*957 * check validity of event type and data length.958 * return non-zero if invalid.959 */960static int check_event_type_and_length(struct snd_seq_event *ev)961{962	switch (snd_seq_ev_length_type(ev)) {963	case SNDRV_SEQ_EVENT_LENGTH_FIXED:964		if (snd_seq_ev_is_variable_type(ev))965			return -EINVAL;966		break;967	case SNDRV_SEQ_EVENT_LENGTH_VARIABLE:968		if (! snd_seq_ev_is_variable_type(ev) ||969		    (ev->data.ext.len & ~SNDRV_SEQ_EXT_MASK) >= SNDRV_SEQ_MAX_EVENT_LEN)970			return -EINVAL;971		break;972	case SNDRV_SEQ_EVENT_LENGTH_VARUSR:973		if (! snd_seq_ev_is_direct(ev))974			return -EINVAL;975		break;976	}977	return 0;978}979 980 981/* handle write() */982/* possible error values:983 *	-ENXIO	invalid client or file open mode984 *	-ENOMEM	malloc failed985 *	-EFAULT	seg. fault during copy from user space986 *	-EINVAL	invalid event987 *	-EAGAIN	no space in output pool988 *	-EINTR	interrupts while sleep989 *	-EMLINK	too many hops990 *	others	depends on return value from driver callback991 */992static ssize_t snd_seq_write(struct file *file, const char __user *buf,993			     size_t count, loff_t *offset)994{995	struct snd_seq_client *client = file->private_data;996	int written = 0, len;997	int err, handled;998	union __snd_seq_event __event;999	struct snd_seq_event *ev = &__event.legacy;1000 1001	if (!(snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_OUTPUT))1002		return -ENXIO;1003 1004	/* check client structures are in place */1005	if (snd_BUG_ON(!client))1006		return -ENXIO;1007		1008	if (!client->accept_output || client->pool == NULL)1009		return -ENXIO;1010 1011 repeat:1012	handled = 0;1013	/* allocate the pool now if the pool is not allocated yet */ 1014	mutex_lock(&client->ioctl_mutex);1015	if (client->pool->size > 0 && !snd_seq_write_pool_allocated(client)) {1016		err = snd_seq_pool_init(client->pool);1017		if (err < 0)1018			goto out;1019	}1020 1021	/* only process whole events */1022	err = -EINVAL;1023	while (count >= sizeof(struct snd_seq_event)) {1024		/* Read in the event header from the user */1025		len = sizeof(struct snd_seq_event);1026		if (copy_from_user(ev, buf, len)) {1027			err = -EFAULT;1028			break;1029		}1030		/* read in the rest bytes for UMP events */1031		if (snd_seq_ev_is_ump(ev)) {1032			if (count < sizeof(struct snd_seq_ump_event))1033				break;1034			if (copy_from_user((char *)ev + len, buf + len,1035					   sizeof(struct snd_seq_ump_event) - len)) {1036				err = -EFAULT;1037				break;1038			}1039			len = sizeof(struct snd_seq_ump_event);1040		}1041 1042		ev->source.client = client->number;	/* fill in client number */1043		/* Check for extension data length */1044		if (check_event_type_and_length(ev)) {1045			err = -EINVAL;1046			break;1047		}1048 1049		if (!event_is_compatible(client, ev)) {1050			err = -EINVAL;1051			break;1052		}1053 1054		/* check for special events */1055		if (!snd_seq_ev_is_ump(ev)) {1056			if (ev->type == SNDRV_SEQ_EVENT_NONE)1057				goto __skip_event;1058			else if (snd_seq_ev_is_reserved(ev)) {1059				err = -EINVAL;1060				break;1061			}1062		}1063 1064		if (snd_seq_ev_is_variable(ev)) {1065			int extlen = ev->data.ext.len & ~SNDRV_SEQ_EXT_MASK;1066			if ((size_t)(extlen + len) > count) {1067				/* back out, will get an error this time or next */1068				err = -EINVAL;1069				break;1070			}1071			/* set user space pointer */1072			ev->data.ext.len = extlen | SNDRV_SEQ_EXT_USRPTR;1073			ev->data.ext.ptr = (char __force *)buf + len;1074			len += extlen; /* increment data length */1075		} else {1076#ifdef CONFIG_COMPAT1077			if (client->convert32 && snd_seq_ev_is_varusr(ev))1078				ev->data.ext.ptr =1079					(void __force *)compat_ptr(ev->data.raw32.d[1]);1080#endif1081		}1082 1083		/* ok, enqueue it */1084		err = snd_seq_client_enqueue_event(client, ev, file,1085						   !(file->f_flags & O_NONBLOCK),1086						   0, 0, &client->ioctl_mutex);1087		if (err < 0)1088			break;1089		handled++;1090 1091	__skip_event:1092		/* Update pointers and counts */1093		count -= len;1094		buf += len;1095		written += len;1096 1097		/* let's have a coffee break if too many events are queued */1098		if (++handled >= 200) {1099			mutex_unlock(&client->ioctl_mutex);1100			goto repeat;1101		}1102	}1103 1104 out:1105	mutex_unlock(&client->ioctl_mutex);1106	return written ? written : err;1107}1108 1109 1110/*1111 * handle polling1112 */1113static __poll_t snd_seq_poll(struct file *file, poll_table * wait)1114{1115	struct snd_seq_client *client = file->private_data;1116	__poll_t mask = 0;1117 1118	/* check client structures are in place */1119	if (snd_BUG_ON(!client))1120		return EPOLLERR;1121 1122	if ((snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_INPUT) &&1123	    client->data.user.fifo) {1124 1125		/* check if data is available in the outqueue */1126		if (snd_seq_fifo_poll_wait(client->data.user.fifo, file, wait))1127			mask |= EPOLLIN | EPOLLRDNORM;1128	}1129 1130	if (snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_OUTPUT) {1131 1132		/* check if data is available in the pool */1133		if (!snd_seq_write_pool_allocated(client) ||1134		    snd_seq_pool_poll_wait(client->pool, file, wait))1135			mask |= EPOLLOUT | EPOLLWRNORM;1136	}1137 1138	return mask;1139}1140 1141 1142/*-----------------------------------------------------*/1143 1144static int snd_seq_ioctl_pversion(struct snd_seq_client *client, void *arg)1145{1146	int *pversion = arg;1147 1148	*pversion = SNDRV_SEQ_VERSION;1149	return 0;1150}1151 1152static int snd_seq_ioctl_user_pversion(struct snd_seq_client *client, void *arg)1153{1154	client->user_pversion = *(unsigned int *)arg;1155	return 0;1156}1157 1158static int snd_seq_ioctl_client_id(struct snd_seq_client *client, void *arg)1159{1160	int *client_id = arg;1161 1162	*client_id = client->number;1163	return 0;1164}1165 1166/* SYSTEM_INFO ioctl() */1167static int snd_seq_ioctl_system_info(struct snd_seq_client *client, void *arg)1168{1169	struct snd_seq_system_info *info = arg;1170 1171	memset(info, 0, sizeof(*info));1172	/* fill the info fields */1173	info->queues = SNDRV_SEQ_MAX_QUEUES;1174	info->clients = SNDRV_SEQ_MAX_CLIENTS;1175	info->ports = SNDRV_SEQ_MAX_PORTS;1176	info->channels = 256;	/* fixed limit */1177	info->cur_clients = client_usage.cur;1178	info->cur_queues = snd_seq_queue_get_cur_queues();1179 1180	return 0;1181}1182 1183 1184/* RUNNING_MODE ioctl() */1185static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void  *arg)1186{1187	struct snd_seq_running_info *info = arg;1188	struct snd_seq_client *cptr;1189	int err = 0;1190 1191	/* requested client number */1192	cptr = snd_seq_client_use_ptr(info->client);1193	if (cptr == NULL)1194		return -ENOENT;		/* don't change !!! */1195 1196#ifdef SNDRV_BIG_ENDIAN1197	if (!info->big_endian) {1198		err = -EINVAL;1199		goto __err;1200	}1201#else1202	if (info->big_endian) {1203		err = -EINVAL;1204		goto __err;1205	}1206 1207#endif1208	if (info->cpu_mode > sizeof(long)) {1209		err = -EINVAL;1210		goto __err;1211	}1212	cptr->convert32 = (info->cpu_mode < sizeof(long));1213 __err:1214	snd_seq_client_unlock(cptr);1215	return err;1216}1217 1218/* CLIENT_INFO ioctl() */1219static void get_client_info(struct snd_seq_client *cptr,1220			    struct snd_seq_client_info *info)1221{1222	info->client = cptr->number;1223 1224	/* fill the info fields */1225	info->type = cptr->type;1226	strcpy(info->name, cptr->name);1227	info->filter = cptr->filter;1228	info->event_lost = cptr->event_lost;1229	memcpy(info->event_filter, cptr->event_filter, 32);1230	info->group_filter = cptr->group_filter;1231	info->num_ports = cptr->num_ports;1232 1233	if (cptr->type == USER_CLIENT)1234		info->pid = pid_vnr(cptr->data.user.owner);1235	else1236		info->pid = -1;1237 1238	if (cptr->type == KERNEL_CLIENT)1239		info->card = cptr->data.kernel.card ? cptr->data.kernel.card->number : -1;1240	else1241		info->card = -1;1242 1243	info->midi_version = cptr->midi_version;1244	memset(info->reserved, 0, sizeof(info->reserved));1245}1246 1247static int snd_seq_ioctl_get_client_info(struct snd_seq_client *client,1248					 void *arg)1249{1250	struct snd_seq_client_info *client_info = arg;1251	struct snd_seq_client *cptr;1252 1253	/* requested client number */1254	cptr = snd_seq_client_use_ptr(client_info->client);1255	if (cptr == NULL)1256		return -ENOENT;		/* don't change !!! */1257 1258	get_client_info(cptr, client_info);1259	snd_seq_client_unlock(cptr);1260 1261	return 0;1262}1263 1264 1265/* CLIENT_INFO ioctl() */1266static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client,1267					 void *arg)1268{1269	struct snd_seq_client_info *client_info = arg;1270 1271	/* it is not allowed to set the info fields for an another client */1272	if (client->number != client_info->client)1273		return -EPERM;1274	/* also client type must be set now */1275	if (client->type != client_info->type)1276		return -EINVAL;1277 1278	/* check validity of midi_version field */1279	if (client->user_pversion >= SNDRV_PROTOCOL_VERSION(1, 0, 3) &&1280	    client_info->midi_version > SNDRV_SEQ_CLIENT_UMP_MIDI_2_0)1281		return -EINVAL;1282 1283	/* fill the info fields */1284	if (client_info->name[0])1285		strscpy(client->name, client_info->name, sizeof(client->name));1286 1287	client->filter = client_info->filter;1288	client->event_lost = client_info->event_lost;1289	if (client->user_pversion >= SNDRV_PROTOCOL_VERSION(1, 0, 3))1290		client->midi_version = client_info->midi_version;1291	memcpy(client->event_filter, client_info->event_filter, 32);1292	client->group_filter = client_info->group_filter;1293	return 0;1294}1295 1296 1297/* 1298 * CREATE PORT ioctl() 1299 */1300static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg)1301{1302	struct snd_seq_port_info *info = arg;1303	struct snd_seq_client_port *port;1304	struct snd_seq_port_callback *callback;1305	int port_idx, err;1306 1307	/* it is not allowed to create the port for an another client */1308	if (info->addr.client != client->number)1309		return -EPERM;1310	if (client->type == USER_CLIENT && info->kernel)1311		return -EINVAL;1312	if ((info->capability & SNDRV_SEQ_PORT_CAP_UMP_ENDPOINT) &&1313	    client->ump_endpoint_port >= 0)1314		return -EBUSY;1315 1316	if (info->flags & SNDRV_SEQ_PORT_FLG_GIVEN_PORT)1317		port_idx = info->addr.port;1318	else1319		port_idx = -1;1320	if (port_idx >= SNDRV_SEQ_ADDRESS_UNKNOWN)1321		return -EINVAL;1322	err = snd_seq_create_port(client, port_idx, &port);1323	if (err < 0)1324		return err;1325 1326	if (client->type == KERNEL_CLIENT) {1327		callback = info->kernel;1328		if (callback) {1329			if (callback->owner)1330				port->owner = callback->owner;1331			port->private_data = callback->private_data;1332			port->private_free = callback->private_free;1333			port->event_input = callback->event_input;1334			port->c_src.open = callback->subscribe;1335			port->c_src.close = callback->unsubscribe;1336			port->c_dest.open = callback->use;1337			port->c_dest.close = callback->unuse;1338		}1339	}1340 1341	info->addr = port->addr;1342 1343	snd_seq_set_port_info(port, info);1344	if (info->capability & SNDRV_SEQ_PORT_CAP_UMP_ENDPOINT)1345		client->ump_endpoint_port = port->addr.port;1346	snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port);1347	snd_seq_port_unlock(port);1348 1349	return 0;1350}1351 1352/* 1353 * DELETE PORT ioctl() 1354 */1355static int snd_seq_ioctl_delete_port(struct snd_seq_client *client, void *arg)1356{1357	struct snd_seq_port_info *info = arg;1358	int err;1359 1360	/* it is not allowed to remove the port for an another client */1361	if (info->addr.client != client->number)1362		return -EPERM;1363 1364	err = snd_seq_delete_port(client, info->addr.port);1365	if (err >= 0) {1366		if (client->ump_endpoint_port == info->addr.port)1367			client->ump_endpoint_port = -1;1368		snd_seq_system_client_ev_port_exit(client->number, info->addr.port);1369	}1370	return err;1371}1372 1373 1374/* 1375 * GET_PORT_INFO ioctl() (on any client) 1376 */1377static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, void *arg)1378{1379	struct snd_seq_port_info *info = arg;1380	struct snd_seq_client *cptr;1381	struct snd_seq_client_port *port;1382 1383	cptr = snd_seq_client_use_ptr(info->addr.client);1384	if (cptr == NULL)1385		return -ENXIO;1386 1387	port = snd_seq_port_use_ptr(cptr, info->addr.port);1388	if (port == NULL) {1389		snd_seq_client_unlock(cptr);1390		return -ENOENT;			/* don't change */1391	}1392 1393	/* get port info */1394	snd_seq_get_port_info(port, info);1395	snd_seq_port_unlock(port);1396	snd_seq_client_unlock(cptr);1397 1398	return 0;1399}1400 1401 1402/* 1403 * SET_PORT_INFO ioctl() (only ports on this/own client) 1404 */1405static int snd_seq_ioctl_set_port_info(struct snd_seq_client *client, void *arg)1406{1407	struct snd_seq_port_info *info = arg;1408	struct snd_seq_client_port *port;1409 1410	if (info->addr.client != client->number) /* only set our own ports ! */1411		return -EPERM;1412	port = snd_seq_port_use_ptr(client, info->addr.port);1413	if (port) {1414		snd_seq_set_port_info(port, info);1415		snd_seq_port_unlock(port);1416	}1417	return 0;1418}1419 1420 1421/*1422 * port subscription (connection)1423 */1424#define PERM_RD		(SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ)1425#define PERM_WR		(SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_SUBS_WRITE)1426 1427static int check_subscription_permission(struct snd_seq_client *client,1428					 struct snd_seq_client_port *sport,1429					 struct snd_seq_client_port *dport,1430					 struct snd_seq_port_subscribe *subs)1431{1432	if (client->number != subs->sender.client &&1433	    client->number != subs->dest.client) {1434		/* connection by third client - check export permission */1435		if (check_port_perm(sport, SNDRV_SEQ_PORT_CAP_NO_EXPORT))1436			return -EPERM;1437		if (check_port_perm(dport, SNDRV_SEQ_PORT_CAP_NO_EXPORT))1438			return -EPERM;1439	}1440 1441	/* check read permission */1442	/* if sender or receiver is the subscribing client itself,1443	 * no permission check is necessary1444	 */1445	if (client->number != subs->sender.client) {1446		if (! check_port_perm(sport, PERM_RD))1447			return -EPERM;1448	}1449	/* check write permission */1450	if (client->number != subs->dest.client) {1451		if (! check_port_perm(dport, PERM_WR))1452			return -EPERM;1453	}1454	return 0;1455}1456 1457/*1458 * send an subscription notify event to user client:1459 * client must be user client.1460 */1461int snd_seq_client_notify_subscription(int client, int port,1462				       struct snd_seq_port_subscribe *info,1463				       int evtype)1464{1465	struct snd_seq_event event;1466 1467	memset(&event, 0, sizeof(event));1468	event.type = evtype;1469	event.data.connect.dest = info->dest;1470	event.data.connect.sender = info->sender;1471 1472	return snd_seq_system_notify(client, port, &event);  /* non-atomic */1473}1474 1475 1476/* 1477 * add to port's subscription list IOCTL interface 1478 */1479static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client,1480					void *arg)1481{1482	struct snd_seq_port_subscribe *subs = arg;1483	int result = -EINVAL;1484	struct snd_seq_client *receiver = NULL, *sender = NULL;1485	struct snd_seq_client_port *sport = NULL, *dport = NULL;1486 1487	receiver = snd_seq_client_use_ptr(subs->dest.client);1488	if (!receiver)1489		goto __end;1490	sender = snd_seq_client_use_ptr(subs->sender.client);1491	if (!sender)1492		goto __end;1493	sport = snd_seq_port_use_ptr(sender, subs->sender.port);1494	if (!sport)1495		goto __end;1496	dport = snd_seq_port_use_ptr(receiver, subs->dest.port);1497	if (!dport)1498		goto __end;1499 1500	result = check_subscription_permission(client, sport, dport, subs);1501	if (result < 0)1502		goto __end;1503 1504	/* connect them */1505	result = snd_seq_port_connect(client, sender, sport, receiver, dport, subs);1506	if (! result) /* broadcast announce */1507		snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0,1508						   subs, SNDRV_SEQ_EVENT_PORT_SUBSCRIBED);1509      __end:1510      	if (sport)1511		snd_seq_port_unlock(sport);1512	if (dport)1513		snd_seq_port_unlock(dport);1514	if (sender)1515		snd_seq_client_unlock(sender);1516	if (receiver)1517		snd_seq_client_unlock(receiver);1518	return result;1519}1520 1521 1522/* 1523 * remove from port's subscription list 1524 */1525static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client,1526					  void *arg)1527{1528	struct snd_seq_port_subscribe *subs = arg;1529	int result = -ENXIO;1530	struct snd_seq_client *receiver = NULL, *sender = NULL;1531	struct snd_seq_client_port *sport = NULL, *dport = NULL;1532 1533	receiver = snd_seq_client_use_ptr(subs->dest.client);1534	if (!receiver)1535		goto __end;1536	sender = snd_seq_client_use_ptr(subs->sender.client);1537	if (!sender)1538		goto __end;1539	sport = snd_seq_port_use_ptr(sender, subs->sender.port);1540	if (!sport)1541		goto __end;1542	dport = snd_seq_port_use_ptr(receiver, subs->dest.port);1543	if (!dport)1544		goto __end;1545 1546	result = check_subscription_permission(client, sport, dport, subs);1547	if (result < 0)1548		goto __end;1549 1550	result = snd_seq_port_disconnect(client, sender, sport, receiver, dport, subs);1551	if (! result) /* broadcast announce */1552		snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0,1553						   subs, SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED);1554      __end:1555      	if (sport)1556		snd_seq_port_unlock(sport);1557	if (dport)1558		snd_seq_port_unlock(dport);1559	if (sender)1560		snd_seq_client_unlock(sender);1561	if (receiver)1562		snd_seq_client_unlock(receiver);1563	return result;1564}1565 1566 1567/* CREATE_QUEUE ioctl() */1568static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, void *arg)1569{1570	struct snd_seq_queue_info *info = arg;1571	struct snd_seq_queue *q;1572 1573	q = snd_seq_queue_alloc(client->number, info->locked, info->flags);1574	if (IS_ERR(q))1575		return PTR_ERR(q);1576 1577	info->queue = q->queue;1578	info->locked = q->locked;1579	info->owner = q->owner;1580 1581	/* set queue name */1582	if (!info->name[0])1583		snprintf(info->name, sizeof(info->name), "Queue-%d", q->queue);1584	strscpy(q->name, info->name, sizeof(q->name));1585	snd_use_lock_free(&q->use_lock);1586 1587	return 0;1588}1589 1590/* DELETE_QUEUE ioctl() */1591static int snd_seq_ioctl_delete_queue(struct snd_seq_client *client, void *arg)1592{1593	struct snd_seq_queue_info *info = arg;1594 1595	return snd_seq_queue_delete(client->number, info->queue);1596}1597 1598/* GET_QUEUE_INFO ioctl() */1599static int snd_seq_ioctl_get_queue_info(struct snd_seq_client *client,1600					void *arg)1601{1602	struct snd_seq_queue_info *info = arg;1603	struct snd_seq_queue *q;1604 1605	q = queueptr(info->queue);1606	if (q == NULL)1607		return -EINVAL;1608 1609	memset(info, 0, sizeof(*info));1610	info->queue = q->queue;1611	info->owner = q->owner;1612	info->locked = q->locked;1613	strscpy(info->name, q->name, sizeof(info->name));1614	queuefree(q);1615 1616	return 0;1617}1618 1619/* SET_QUEUE_INFO ioctl() */1620static int snd_seq_ioctl_set_queue_info(struct snd_seq_client *client,1621					void *arg)1622{1623	struct snd_seq_queue_info *info = arg;1624	struct snd_seq_queue *q;1625 1626	if (info->owner != client->number)1627		return -EINVAL;1628 1629	/* change owner/locked permission */1630	if (snd_seq_queue_check_access(info->queue, client->number)) {1631		if (snd_seq_queue_set_owner(info->queue, client->number, info->locked) < 0)1632			return -EPERM;1633		if (info->locked)1634			snd_seq_queue_use(info->queue, client->number, 1);1635	} else {1636		return -EPERM;1637	}	1638 1639	q = queueptr(info->queue);1640	if (! q)1641		return -EINVAL;1642	if (q->owner != client->number) {1643		queuefree(q);1644		return -EPERM;1645	}1646	strscpy(q->name, info->name, sizeof(q->name));1647	queuefree(q);1648 1649	return 0;1650}1651 1652/* GET_NAMED_QUEUE ioctl() */1653static int snd_seq_ioctl_get_named_queue(struct snd_seq_client *client,1654					 void *arg)1655{1656	struct snd_seq_queue_info *info = arg;1657	struct snd_seq_queue *q;1658 1659	q = snd_seq_queue_find_name(info->name);1660	if (q == NULL)1661		return -EINVAL;1662	info->queue = q->queue;1663	info->owner = q->owner;1664	info->locked = q->locked;1665	queuefree(q);1666 1667	return 0;1668}1669 1670/* GET_QUEUE_STATUS ioctl() */1671static int snd_seq_ioctl_get_queue_status(struct snd_seq_client *client,1672					  void *arg)1673{1674	struct snd_seq_queue_status *status = arg;1675	struct snd_seq_queue *queue;1676	struct snd_seq_timer *tmr;1677 1678	queue = queueptr(status->queue);1679	if (queue == NULL)1680		return -EINVAL;1681	memset(status, 0, sizeof(*status));1682	status->queue = queue->queue;1683	1684	tmr = queue->timer;1685	status->events = queue->tickq->cells + queue->timeq->cells;1686 1687	status->time = snd_seq_timer_get_cur_time(tmr, true);1688	status->tick = snd_seq_timer_get_cur_tick(tmr);1689 1690	status->running = tmr->running;1691 1692	status->flags = queue->flags;1693	queuefree(queue);1694 1695	return 0;1696}1697 1698 1699/* GET_QUEUE_TEMPO ioctl() */1700static int snd_seq_ioctl_get_queue_tempo(struct snd_seq_client *client,1701					 void *arg)1702{1703	struct snd_seq_queue_tempo *tempo = arg;1704	struct snd_seq_queue *queue;1705	struct snd_seq_timer *tmr;1706 1707	queue = queueptr(tempo->queue);1708	if (queue == NULL)1709		return -EINVAL;1710	memset(tempo, 0, sizeof(*tempo));1711	tempo->queue = queue->queue;1712	1713	tmr = queue->timer;1714 1715	tempo->tempo = tmr->tempo;1716	tempo->ppq = tmr->ppq;1717	tempo->skew_value = tmr->skew;1718	tempo->skew_base = tmr->skew_base;1719	if (client->user_pversion >= SNDRV_PROTOCOL_VERSION(1, 0, 4))1720		tempo->tempo_base = tmr->tempo_base;1721	queuefree(queue);1722 1723	return 0;1724}1725 1726 1727/* SET_QUEUE_TEMPO ioctl() */1728int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo)1729{1730	if (!snd_seq_queue_check_access(tempo->queue, client))1731		return -EPERM;1732	return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo);1733}1734EXPORT_SYMBOL(snd_seq_set_queue_tempo);1735 1736static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client,1737					 void *arg)1738{1739	struct snd_seq_queue_tempo *tempo = arg;1740	int result;1741 1742	if (client->user_pversion < SNDRV_PROTOCOL_VERSION(1, 0, 4))1743		tempo->tempo_base = 0;1744	result = snd_seq_set_queue_tempo(client->number, tempo);1745	return result < 0 ? result : 0;1746}1747 1748 1749/* GET_QUEUE_TIMER ioctl() */1750static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client,1751					 void *arg)1752{1753	struct snd_seq_queue_timer *timer = arg;1754	struct snd_seq_queue *queue;1755	struct snd_seq_timer *tmr;1756 1757	queue = queueptr(timer->queue);1758	if (queue == NULL)1759		return -EINVAL;1760 1761	mutex_lock(&queue->timer_mutex);1762	tmr = queue->timer;1763	memset(timer, 0, sizeof(*timer));1764	timer->queue = queue->queue;1765 1766	timer->type = tmr->type;1767	if (tmr->type == SNDRV_SEQ_TIMER_ALSA) {1768		timer->u.alsa.id = tmr->alsa_id;1769		timer->u.alsa.resolution = tmr->preferred_resolution;1770	}1771	mutex_unlock(&queue->timer_mutex);1772	queuefree(queue);1773	1774	return 0;1775}1776 1777 1778/* SET_QUEUE_TIMER ioctl() */1779static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client,1780					 void *arg)1781{1782	struct snd_seq_queue_timer *timer = arg;1783	int result = 0;1784 1785	if (timer->type != SNDRV_SEQ_TIMER_ALSA)1786		return -EINVAL;1787 1788	if (snd_seq_queue_check_access(timer->queue, client->number)) {1789		struct snd_seq_queue *q;1790		struct snd_seq_timer *tmr;1791 1792		q = queueptr(timer->queue);1793		if (q == NULL)1794			return -ENXIO;1795		mutex_lock(&q->timer_mutex);1796		tmr = q->timer;1797		snd_seq_queue_timer_close(timer->queue);1798		tmr->type = timer->type;1799		if (tmr->type == SNDRV_SEQ_TIMER_ALSA) {1800			tmr->alsa_id = timer->u.alsa.id;1801			tmr->preferred_resolution = timer->u.alsa.resolution;1802		}1803		result = snd_seq_queue_timer_open(timer->queue);1804		mutex_unlock(&q->timer_mutex);1805		queuefree(q);1806	} else {1807		return -EPERM;1808	}	1809 1810	return result;1811}1812 1813 1814/* GET_QUEUE_CLIENT ioctl() */1815static int snd_seq_ioctl_get_queue_client(struct snd_seq_client *client,1816					  void *arg)1817{1818	struct snd_seq_queue_client *info = arg;1819	int used;1820 1821	used = snd_seq_queue_is_used(info->queue, client->number);1822	if (used < 0)1823		return -EINVAL;1824	info->used = used;1825	info->client = client->number;1826 1827	return 0;1828}1829 1830 1831/* SET_QUEUE_CLIENT ioctl() */1832static int snd_seq_ioctl_set_queue_client(struct snd_seq_client *client,1833					  void *arg)1834{1835	struct snd_seq_queue_client *info = arg;1836	int err;1837 1838	if (info->used >= 0) {1839		err = snd_seq_queue_use(info->queue, client->number, info->used);1840		if (err < 0)1841			return err;1842	}1843 1844	return snd_seq_ioctl_get_queue_client(client, arg);1845}1846 1847 1848/* GET_CLIENT_POOL ioctl() */1849static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client,1850					 void *arg)1851{1852	struct snd_seq_client_pool *info = arg;1853	struct snd_seq_client *cptr;1854 1855	cptr = snd_seq_client_use_ptr(info->client);1856	if (cptr == NULL)1857		return -ENOENT;1858	memset(info, 0, sizeof(*info));1859	info->client = cptr->number;1860	info->output_pool = cptr->pool->size;1861	info->output_room = cptr->pool->room;1862	info->output_free = info->output_pool;1863	info->output_free = snd_seq_unused_cells(cptr->pool);1864	if (cptr->type == USER_CLIENT) {1865		info->input_pool = cptr->data.user.fifo_pool_size;1866		info->input_free = info->input_pool;1867		info->input_free = snd_seq_fifo_unused_cells(cptr->data.user.fifo);1868	} else {1869		info->input_pool = 0;1870		info->input_free = 0;1871	}1872	snd_seq_client_unlock(cptr);1873	1874	return 0;1875}1876 1877/* SET_CLIENT_POOL ioctl() */1878static int snd_seq_ioctl_set_client_pool(struct snd_seq_client *client,1879					 void *arg)1880{1881	struct snd_seq_client_pool *info = arg;1882	int rc;1883 1884	if (client->number != info->client)1885		return -EINVAL; /* can't change other clients */1886 1887	if (info->output_pool >= 1 && info->output_pool <= SNDRV_SEQ_MAX_EVENTS &&1888	    (! snd_seq_write_pool_allocated(client) ||1889	     info->output_pool != client->pool->size)) {1890		if (snd_seq_write_pool_allocated(client)) {1891			/* is the pool in use? */1892			if (atomic_read(&client->pool->counter))1893				return -EBUSY;1894			/* remove all existing cells */1895			snd_seq_pool_mark_closing(client->pool);1896			snd_seq_pool_done(client->pool);1897		}1898		client->pool->size = info->output_pool;1899		rc = snd_seq_pool_init(client->pool);1900		if (rc < 0)1901			return rc;1902	}1903	if (client->type == USER_CLIENT && client->data.user.fifo != NULL &&1904	    info->input_pool >= 1 &&1905	    info->input_pool <= SNDRV_SEQ_MAX_CLIENT_EVENTS &&1906	    info->input_pool != client->data.user.fifo_pool_size) {1907		/* change pool size */1908		rc = snd_seq_fifo_resize(client->data.user.fifo, info->input_pool);1909		if (rc < 0)1910			return rc;1911		client->data.user.fifo_pool_size = info->input_pool;1912	}1913	if (info->output_room >= 1 &&1914	    info->output_room <= client->pool->size) {1915		client->pool->room  = info->output_room;1916	}1917 1918	return snd_seq_ioctl_get_client_pool(client, arg);1919}1920 1921 1922/* REMOVE_EVENTS ioctl() */1923static int snd_seq_ioctl_remove_events(struct snd_seq_client *client,1924				       void *arg)1925{1926	struct snd_seq_remove_events *info = arg;1927 1928	/*1929	 * Input mostly not implemented XXX.1930	 */1931	if (info->remove_mode & SNDRV_SEQ_REMOVE_INPUT) {1932		/*1933		 * No restrictions so for a user client we can clear1934		 * the whole fifo1935		 */1936		if (client->type == USER_CLIENT && client->data.user.fifo)1937			snd_seq_fifo_clear(client->data.user.fifo);1938	}1939 1940	if (info->remove_mode & SNDRV_SEQ_REMOVE_OUTPUT)1941		snd_seq_queue_remove_cells(client->number, info);1942 1943	return 0;1944}1945 1946 1947/*1948 * get subscription info1949 */1950static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client,1951					  void *arg)1952{1953	struct snd_seq_port_subscribe *subs = arg;1954	int result;1955	struct snd_seq_client *sender = NULL;1956	struct snd_seq_client_port *sport = NULL;1957 1958	result = -EINVAL;1959	sender = snd_seq_client_use_ptr(subs->sender.client);1960	if (!sender)1961		goto __end;1962	sport = snd_seq_port_use_ptr(sender, subs->sender.port);1963	if (!sport)1964		goto __end;1965	result = snd_seq_port_get_subscription(&sport->c_src, &subs->dest,1966					       subs);1967      __end:1968      	if (sport)1969		snd_seq_port_unlock(sport);1970	if (sender)1971		snd_seq_client_unlock(sender);1972 1973	return result;1974}1975 1976 1977/*1978 * get subscription info - check only its presence1979 */1980static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, void *arg)1981{1982	struct snd_seq_query_subs *subs = arg;1983	int result = -ENXIO;1984	struct snd_seq_client *cptr = NULL;1985	struct snd_seq_client_port *port = NULL;1986	struct snd_seq_port_subs_info *group;1987	struct list_head *p;1988	int i;1989 1990	cptr = snd_seq_client_use_ptr(subs->root.client);1991	if (!cptr)1992		goto __end;1993	port = snd_seq_port_use_ptr(cptr, subs->root.port);1994	if (!port)1995		goto __end;1996 1997	switch (subs->type) {1998	case SNDRV_SEQ_QUERY_SUBS_READ:1999		group = &port->c_src;2000		break;2001	case SNDRV_SEQ_QUERY_SUBS_WRITE:2002		group = &port->c_dest;2003		break;2004	default:2005		goto __end;2006	}2007 2008	down_read(&group->list_mutex);2009	/* search for the subscriber */2010	subs->num_subs = group->count;2011	i = 0;2012	result = -ENOENT;2013	list_for_each(p, &group->list_head) {2014		if (i++ == subs->index) {2015			/* found! */2016			struct snd_seq_subscribers *s;2017			if (subs->type == SNDRV_SEQ_QUERY_SUBS_READ) {2018				s = list_entry(p, struct snd_seq_subscribers, src_list);2019				subs->addr = s->info.dest;2020			} else {2021				s = list_entry(p, struct snd_seq_subscribers, dest_list);2022				subs->addr = s->info.sender;2023			}2024			subs->flags = s->info.flags;2025			subs->queue = s->info.queue;2026			result = 0;2027			break;2028		}2029	}2030	up_read(&group->list_mutex);2031 2032      __end:2033   	if (port)2034		snd_seq_port_unlock(port);2035	if (cptr)2036		snd_seq_client_unlock(cptr);2037 2038	return result;2039}2040 2041 2042/*2043 * query next client2044 */2045static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client,2046					   void *arg)2047{2048	struct snd_seq_client_info *info = arg;2049	struct snd_seq_client *cptr = NULL;2050 2051	/* search for next client */2052	if (info->client < INT_MAX)2053		info->client++;2054	if (info->client < 0)2055		info->client = 0;2056	for (; info->client < SNDRV_SEQ_MAX_CLIENTS; info->client++) {2057		cptr = snd_seq_client_use_ptr(info->client);2058		if (cptr)2059			break; /* found */2060	}2061	if (cptr == NULL)2062		return -ENOENT;2063 2064	get_client_info(cptr, info);2065	snd_seq_client_unlock(cptr);2066 2067	return 0;2068}2069 2070/* 2071 * query next port2072 */2073static int snd_seq_ioctl_query_next_port(struct snd_seq_client *client,2074					 void *arg)2075{2076	struct snd_seq_port_info *info = arg;2077	struct snd_seq_client *cptr;2078	struct snd_seq_client_port *port = NULL;2079 2080	cptr = snd_seq_client_use_ptr(info->addr.client);2081	if (cptr == NULL)2082		return -ENXIO;2083 2084	/* search for next port */2085	info->addr.port++;2086	port = snd_seq_port_query_nearest(cptr, info);2087	if (port == NULL) {2088		snd_seq_client_unlock(cptr);2089		return -ENOENT;2090	}2091 2092	/* get port info */2093	info->addr = port->addr;2094	snd_seq_get_port_info(port, info);2095	snd_seq_port_unlock(port);2096	snd_seq_client_unlock(cptr);2097 2098	return 0;2099}2100 2101#if IS_ENABLED(CONFIG_SND_SEQ_UMP)2102#define NUM_UMP_INFOS (SNDRV_UMP_MAX_BLOCKS + 1)2103 2104static void free_ump_info(struct snd_seq_client *client)2105{2106	int i;2107 2108	if (!client->ump_info)2109		return;2110	for (i = 0; i < NUM_UMP_INFOS; i++)2111		kfree(client->ump_info[i]);2112	kfree(client->ump_info);2113	client->ump_info = NULL;2114}2115 2116static void terminate_ump_info_strings(void *p, int type)2117{2118	if (type == SNDRV_SEQ_CLIENT_UMP_INFO_ENDPOINT) {2119		struct snd_ump_endpoint_info *ep = p;2120		ep->name[sizeof(ep->name) - 1] = 0;2121	} else {2122		struct snd_ump_block_info *bp = p;2123		bp->name[sizeof(bp->name) - 1] = 0;2124	}2125}2126 2127#ifdef CONFIG_SND_PROC_FS2128static void dump_ump_info(struct snd_info_buffer *buffer,2129			  struct snd_seq_client *client)2130{2131	struct snd_ump_endpoint_info *ep;2132	struct snd_ump_block_info *bp;2133	int i;2134 2135	if (!client->ump_info)2136		return;2137	ep = client->ump_info[SNDRV_SEQ_CLIENT_UMP_INFO_ENDPOINT];2138	if (ep && *ep->name)2139		snd_iprintf(buffer, "  UMP Endpoint: \"%s\"\n", ep->name);2140	for (i = 0; i < SNDRV_UMP_MAX_BLOCKS; i++) {2141		bp = client->ump_info[i + 1];2142		if (bp && *bp->name) {2143			snd_iprintf(buffer, "  UMP Block %d: \"%s\" [%s]\n",2144				    i, bp->name,2145				    bp->active ? "Active" : "Inactive");2146			snd_iprintf(buffer, "    Groups: %d-%d\n",2147				    bp->first_group + 1,2148				    bp->first_group + bp->num_groups);2149		}2150	}2151}2152#endif2153 2154/* UMP-specific ioctls -- called directly without data copy */2155static int snd_seq_ioctl_client_ump_info(struct snd_seq_client *caller,2156					 unsigned int cmd,2157					 unsigned long arg)2158{2159	struct snd_seq_client_ump_info __user *argp =2160		(struct snd_seq_client_ump_info __user *)arg;2161	struct snd_seq_client *cptr;2162	int client, type, err = 0;2163	size_t size;2164	void *p;2165 2166	if (get_user(client, &argp->client) || get_user(type, &argp->type))2167		return -EFAULT;2168	if (cmd == SNDRV_SEQ_IOCTL_SET_CLIENT_UMP_INFO &&2169	    caller->number != client)2170		return -EPERM;2171	if (type < 0 || type >= NUM_UMP_INFOS)2172		return -EINVAL;2173	if (type == SNDRV_SEQ_CLIENT_UMP_INFO_ENDPOINT)2174		size = sizeof(struct snd_ump_endpoint_info);2175	else2176		size = sizeof(struct snd_ump_block_info);2177	cptr = snd_seq_client_use_ptr(client);2178	if (!cptr)2179		return -ENOENT;2180 2181	mutex_lock(&cptr->ioctl_mutex);2182	if (!cptr->midi_version) {2183		err = -EBADFD;2184		goto error;2185	}2186 2187	if (cmd == SNDRV_SEQ_IOCTL_GET_CLIENT_UMP_INFO) {2188		if (!cptr->ump_info)2189			p = NULL;2190		else2191			p = cptr->ump_info[type];2192		if (!p) {2193			err = -ENODEV;2194			goto error;2195		}2196		if (copy_to_user(argp->info, p, size)) {2197			err = -EFAULT;2198			goto error;2199		}2200	} else {2201		if (cptr->type != USER_CLIENT) {2202			err = -EBADFD;2203			goto error;2204		}2205		if (!cptr->ump_info) {2206			cptr->ump_info = kcalloc(NUM_UMP_INFOS,2207						 sizeof(void *), GFP_KERNEL);2208			if (!cptr->ump_info) {2209				err = -ENOMEM;2210				goto error;2211			}2212		}2213		p = memdup_user(argp->info, size);2214		if (IS_ERR(p)) {2215			err = PTR_ERR(p);2216			goto error;2217		}2218		kfree(cptr->ump_info[type]);2219		terminate_ump_info_strings(p, type);2220		cptr->ump_info[type] = p;2221	}2222 2223 error:2224	mutex_unlock(&cptr->ioctl_mutex);2225	snd_seq_client_unlock(cptr);2226	return err;2227}2228#endif2229 2230/* -------------------------------------------------------- */2231 2232static const struct ioctl_handler {2233	unsigned int cmd;2234	int (*func)(struct snd_seq_client *client, void *arg);2235} ioctl_handlers[] = {2236	{ SNDRV_SEQ_IOCTL_PVERSION, snd_seq_ioctl_pversion },2237	{ SNDRV_SEQ_IOCTL_USER_PVERSION, snd_seq_ioctl_user_pversion },2238	{ SNDRV_SEQ_IOCTL_CLIENT_ID, snd_seq_ioctl_client_id },2239	{ SNDRV_SEQ_IOCTL_SYSTEM_INFO, snd_seq_ioctl_system_info },2240	{ SNDRV_SEQ_IOCTL_RUNNING_MODE, snd_seq_ioctl_running_mode },2241	{ SNDRV_SEQ_IOCTL_GET_CLIENT_INFO, snd_seq_ioctl_get_client_info },2242	{ SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, snd_seq_ioctl_set_client_info },2243	{ SNDRV_SEQ_IOCTL_CREATE_PORT, snd_seq_ioctl_create_port },2244	{ SNDRV_SEQ_IOCTL_DELETE_PORT, snd_seq_ioctl_delete_port },2245	{ SNDRV_SEQ_IOCTL_GET_PORT_INFO, snd_seq_ioctl_get_port_info },2246	{ SNDRV_SEQ_IOCTL_SET_PORT_INFO, snd_seq_ioctl_set_port_info },2247	{ SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT, snd_seq_ioctl_subscribe_port },2248	{ SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT, snd_seq_ioctl_unsubscribe_port },2249	{ SNDRV_SEQ_IOCTL_CREATE_QUEUE, snd_seq_ioctl_create_queue },2250	{ SNDRV_SEQ_IOCTL_DELETE_QUEUE, snd_seq_ioctl_delete_queue },2251	{ SNDRV_SEQ_IOCTL_GET_QUEUE_INFO, snd_seq_ioctl_get_queue_info },2252	{ SNDRV_SEQ_IOCTL_SET_QUEUE_INFO, snd_seq_ioctl_set_queue_info },2253	{ SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE, snd_seq_ioctl_get_named_queue },2254	{ SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS, snd_seq_ioctl_get_queue_status },2255	{ SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO, snd_seq_ioctl_get_queue_tempo },2256	{ SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO, snd_seq_ioctl_set_queue_tempo },2257	{ SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER, snd_seq_ioctl_get_queue_timer },2258	{ SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER, snd_seq_ioctl_set_queue_timer },2259	{ SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT, snd_seq_ioctl_get_queue_client },2260	{ SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT, snd_seq_ioctl_set_queue_client },2261	{ SNDRV_SEQ_IOCTL_GET_CLIENT_POOL, snd_seq_ioctl_get_client_pool },2262	{ SNDRV_SEQ_IOCTL_SET_CLIENT_POOL, snd_seq_ioctl_set_client_pool },2263	{ SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION, snd_seq_ioctl_get_subscription },2264	{ SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT, snd_seq_ioctl_query_next_client },2265	{ SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, snd_seq_ioctl_query_next_port },2266	{ SNDRV_SEQ_IOCTL_REMOVE_EVENTS, snd_seq_ioctl_remove_events },2267	{ SNDRV_SEQ_IOCTL_QUERY_SUBS, snd_seq_ioctl_query_subs },2268	{ 0, NULL },2269};2270 2271static long snd_seq_ioctl(struct file *file, unsigned int cmd,2272			  unsigned long arg)2273{2274	struct snd_seq_client *client = file->private_data;2275	/* To use kernel stack for ioctl data. */2276	union {2277		int pversion;2278		int client_id;2279		struct snd_seq_system_info	system_info;2280		struct snd_seq_running_info	running_info;2281		struct snd_seq_client_info	client_info;2282		struct snd_seq_port_info	port_info;2283		struct snd_seq_port_subscribe	port_subscribe;2284		struct snd_seq_queue_info	queue_info;2285		struct snd_seq_queue_status	queue_status;2286		struct snd_seq_queue_tempo	tempo;2287		struct snd_seq_queue_timer	queue_timer;2288		struct snd_seq_queue_client	queue_client;2289		struct snd_seq_client_pool	client_pool;2290		struct snd_seq_remove_events	remove_events;2291		struct snd_seq_query_subs	query_subs;2292	} buf;2293	const struct ioctl_handler *handler;2294	unsigned long size;2295	int err;2296 2297	if (snd_BUG_ON(!client))2298		return -ENXIO;2299 2300#if IS_ENABLED(CONFIG_SND_SEQ_UMP)2301	/* exception - handling large data */2302	switch (cmd) {2303	case SNDRV_SEQ_IOCTL_GET_CLIENT_UMP_INFO:2304	case SNDRV_SEQ_IOCTL_SET_CLIENT_UMP_INFO:2305		return snd_seq_ioctl_client_ump_info(client, cmd, arg);2306	}2307#endif2308 2309	for (handler = ioctl_handlers; handler->cmd > 0; ++handler) {2310		if (handler->cmd == cmd)2311			break;2312	}2313	if (handler->cmd == 0)2314		return -ENOTTY;2315 2316	memset(&buf, 0, sizeof(buf));2317 2318	/*2319	 * All of ioctl commands for ALSA sequencer get an argument of size2320	 * within 13 bits. We can safely pick up the size from the command.2321	 */2322	size = _IOC_SIZE(handler->cmd);2323	if (handler->cmd & IOC_IN) {2324		if (copy_from_user(&buf, (const void __user *)arg, size))2325			return -EFAULT;2326	}2327 2328	mutex_lock(&client->ioctl_mutex);2329	err = handler->func(client, &buf);2330	mutex_unlock(&client->ioctl_mutex);2331	if (err >= 0) {2332		/* Some commands includes a bug in 'dir' field. */2333		if (handler->cmd == SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT ||2334		    handler->cmd == SNDRV_SEQ_IOCTL_SET_CLIENT_POOL ||2335		    (handler->cmd & IOC_OUT))2336			if (copy_to_user((void __user *)arg, &buf, size))2337				return -EFAULT;2338	}2339 2340	return err;2341}2342 2343#ifdef CONFIG_COMPAT2344#include "seq_compat.c"2345#else2346#define snd_seq_ioctl_compat	NULL2347#endif2348 2349/* -------------------------------------------------------- */2350 2351 2352/* exported to kernel modules */2353int snd_seq_create_kernel_client(struct snd_card *card, int client_index,2354				 const char *name_fmt, ...)2355{2356	struct snd_seq_client *client;2357	va_list args;2358 2359	if (snd_BUG_ON(in_interrupt()))2360		return -EBUSY;2361 2362	if (card && client_index >= SNDRV_SEQ_CLIENTS_PER_CARD)2363		return -EINVAL;2364	if (card == NULL && client_index >= SNDRV_SEQ_GLOBAL_CLIENTS)2365		return -EINVAL;2366 2367	mutex_lock(&register_mutex);2368 2369	if (card) {2370		client_index += SNDRV_SEQ_GLOBAL_CLIENTS2371			+ card->number * SNDRV_SEQ_CLIENTS_PER_CARD;2372		if (client_index >= SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN)2373			client_index = -1;2374	}2375 2376	/* empty write queue as default */2377	client = seq_create_client1(client_index, 0);2378	if (client == NULL) {2379		mutex_unlock(&register_mutex);2380		return -EBUSY;	/* failure code */2381	}2382	usage_alloc(&client_usage, 1);2383 2384	client->accept_input = 1;2385	client->accept_output = 1;2386	client->data.kernel.card = card;2387	client->user_pversion = SNDRV_SEQ_VERSION;2388		2389	va_start(args, name_fmt);2390	vsnprintf(client->name, sizeof(client->name), name_fmt, args);2391	va_end(args);2392 2393	client->type = KERNEL_CLIENT;2394	mutex_unlock(&register_mutex);2395 2396	/* make others aware this new client */2397	snd_seq_system_client_ev_client_start(client->number);2398	2399	/* return client number to caller */2400	return client->number;2401}2402EXPORT_SYMBOL(snd_seq_create_kernel_client);2403 2404/* exported to kernel modules */2405int snd_seq_delete_kernel_client(int client)2406{2407	struct snd_seq_client *ptr;2408 2409	if (snd_BUG_ON(in_interrupt()))2410		return -EBUSY;2411 2412	ptr = clientptr(client);2413	if (ptr == NULL)2414		return -EINVAL;2415 2416	seq_free_client(ptr);2417	kfree(ptr);2418	return 0;2419}2420EXPORT_SYMBOL(snd_seq_delete_kernel_client);2421 2422/*2423 * exported, called by kernel clients to enqueue events (w/o blocking)2424 *2425 * RETURN VALUE: zero if succeed, negative if error2426 */2427int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event *ev,2428				  struct file *file, bool blocking)2429{2430	struct snd_seq_client *cptr;2431	int result;2432 2433	if (snd_BUG_ON(!ev))2434		return -EINVAL;2435 2436	if (!snd_seq_ev_is_ump(ev)) {2437		if (ev->type == SNDRV_SEQ_EVENT_NONE)2438			return 0; /* ignore this */2439		if (ev->type == SNDRV_SEQ_EVENT_KERNEL_ERROR)2440			return -EINVAL; /* quoted events can't be enqueued */2441	}2442 2443	/* fill in client number */2444	ev->source.client = client;2445 2446	if (check_event_type_and_length(ev))2447		return -EINVAL;2448 2449	cptr = snd_seq_client_use_ptr(client);2450	if (cptr == NULL)2451		return -EINVAL;2452	2453	if (!cptr->accept_output) {2454		result = -EPERM;2455	} else { /* send it */2456		mutex_lock(&cptr->ioctl_mutex);2457		result = snd_seq_client_enqueue_event(cptr, ev, file, blocking,2458						      false, 0,2459						      &cptr->ioctl_mutex);2460		mutex_unlock(&cptr->ioctl_mutex);2461	}2462 2463	snd_seq_client_unlock(cptr);2464	return result;2465}2466EXPORT_SYMBOL(snd_seq_kernel_client_enqueue);2467 2468/* 2469 * exported, called by kernel clients to dispatch events directly to other2470 * clients, bypassing the queues.  Event time-stamp will be updated.2471 *2472 * RETURN VALUE: negative = delivery failed,2473 *		 zero, or positive: the number of delivered events2474 */2475int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev,2476				   int atomic, int hop)2477{2478	struct snd_seq_client *cptr;2479	int result;2480 2481	if (snd_BUG_ON(!ev))2482		return -EINVAL;2483 2484	/* fill in client number */2485	ev->queue = SNDRV_SEQ_QUEUE_DIRECT;2486	ev->source.client = client;2487 2488	if (check_event_type_and_length(ev))2489		return -EINVAL;2490 2491	cptr = snd_seq_client_use_ptr(client);2492	if (cptr == NULL)2493		return -EINVAL;2494 2495	if (!cptr->accept_output)2496		result = -EPERM;2497	else2498		result = snd_seq_deliver_event(cptr, ev, atomic, hop);2499 2500	snd_seq_client_unlock(cptr);2501	return result;2502}2503EXPORT_SYMBOL(snd_seq_kernel_client_dispatch);2504 2505/**2506 * snd_seq_kernel_client_ctl - operate a command for a client with data in2507 *			       kernel space.2508 * @clientid:	A numerical ID for a client.2509 * @cmd:	An ioctl(2) command for ALSA sequencer operation.2510 * @arg:	A pointer to data in kernel space.2511 *2512 * Against its name, both kernel/application client can be handled by this2513 * kernel API. A pointer of 'arg' argument should be in kernel space.2514 *2515 * Return: 0 at success. Negative error code at failure.2516 */2517int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg)2518{2519	const struct ioctl_handler *handler;2520	struct snd_seq_client *client;2521 2522	client = clientptr(clientid);2523	if (client == NULL)2524		return -ENXIO;2525 2526	for (handler = ioctl_handlers; handler->cmd > 0; ++handler) {2527		if (handler->cmd == cmd)2528			return handler->func(client, arg);2529	}2530 2531	pr_debug("ALSA: seq unknown ioctl() 0x%x (type='%c', number=0x%02x)\n",2532		 cmd, _IOC_TYPE(cmd), _IOC_NR(cmd));2533	return -ENOTTY;2534}2535EXPORT_SYMBOL(snd_seq_kernel_client_ctl);2536 2537/* exported (for OSS emulator) */2538int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table *wait)2539{2540	struct snd_seq_client *client;2541 2542	client = clientptr(clientid);2543	if (client == NULL)2544		return -ENXIO;2545 2546	if (! snd_seq_write_pool_allocated(client))2547		return 1;2548	if (snd_seq_pool_poll_wait(client->pool, file, wait))2549		return 1;2550	return 0;2551}2552EXPORT_SYMBOL(snd_seq_kernel_client_write_poll);2553 2554/* get a sequencer client object; for internal use from a kernel client */2555struct snd_seq_client *snd_seq_kernel_client_get(int id)2556{2557	return snd_seq_client_use_ptr(id);2558}2559EXPORT_SYMBOL_GPL(snd_seq_kernel_client_get);2560 2561/* put a sequencer client object; for internal use from a kernel client */2562void snd_seq_kernel_client_put(struct snd_seq_client *cptr)2563{2564	if (cptr)2565		snd_seq_client_unlock(cptr);2566}2567EXPORT_SYMBOL_GPL(snd_seq_kernel_client_put);2568 2569/*---------------------------------------------------------------------------*/2570 2571#ifdef CONFIG_SND_PROC_FS2572/*2573 *  /proc interface2574 */2575static void snd_seq_info_dump_subscribers(struct snd_info_buffer *buffer,2576					  struct snd_seq_port_subs_info *group,2577					  int is_src, char *msg)2578{2579	struct list_head *p;2580	struct snd_seq_subscribers *s;2581	int count = 0;2582 2583	down_read(&group->list_mutex);2584	if (list_empty(&group->list_head)) {2585		up_read(&group->list_mutex);2586		return;2587	}2588	snd_iprintf(buffer, msg);2589	list_for_each(p, &group->list_head) {2590		if (is_src)2591			s = list_entry(p, struct snd_seq_subscribers, src_list);2592		else2593			s = list_entry(p, struct snd_seq_subscribers, dest_list);2594		if (count++)2595			snd_iprintf(buffer, ", ");2596		snd_iprintf(buffer, "%d:%d",2597			    is_src ? s->info.dest.client : s->info.sender.client,2598			    is_src ? s->info.dest.port : s->info.sender.port);2599		if (s->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP)2600			snd_iprintf(buffer, "[%c:%d]", ((s->info.flags & SNDRV_SEQ_PORT_SUBS_TIME_REAL) ? 'r' : 't'), s->info.queue);2601		if (group->exclusive)2602			snd_iprintf(buffer, "[ex]");2603	}2604	up_read(&group->list_mutex);2605	snd_iprintf(buffer, "\n");2606}2607 2608#define FLAG_PERM_RD(perm) ((perm) & SNDRV_SEQ_PORT_CAP_READ ? ((perm) & SNDRV_SEQ_PORT_CAP_SUBS_READ ? 'R' : 'r') : '-')2609#define FLAG_PERM_WR(perm) ((perm) & SNDRV_SEQ_PORT_CAP_WRITE ? ((perm) & SNDRV_SEQ_PORT_CAP_SUBS_WRITE ? 'W' : 'w') : '-')2610#define FLAG_PERM_EX(perm) ((perm) & SNDRV_SEQ_PORT_CAP_NO_EXPORT ? '-' : 'e')2611 2612#define FLAG_PERM_DUPLEX(perm) ((perm) & SNDRV_SEQ_PORT_CAP_DUPLEX ? 'X' : '-')2613 2614static const char *port_direction_name(unsigned char dir)2615{2616	static const char *names[4] = {2617		"-", "In", "Out", "In/Out"2618	};2619 2620	if (dir > SNDRV_SEQ_PORT_DIR_BIDIRECTION)2621		return "Invalid";2622	return names[dir];2623}2624 2625static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer,2626				    struct snd_seq_client *client)2627{2628	struct snd_seq_client_port *p;2629 2630	mutex_lock(&client->ports_mutex);2631	list_for_each_entry(p, &client->ports_list_head, list) {2632		if (p->capability & SNDRV_SEQ_PORT_CAP_INACTIVE)2633			continue;2634		snd_iprintf(buffer, "  Port %3d : \"%s\" (%c%c%c%c) [%s]",2635			    p->addr.port, p->name,2636			    FLAG_PERM_RD(p->capability),2637			    FLAG_PERM_WR(p->capability),2638			    FLAG_PERM_EX(p->capability),2639			    FLAG_PERM_DUPLEX(p->capability),2640			    port_direction_name(p->direction));2641#if IS_ENABLED(CONFIG_SND_SEQ_UMP)2642		if (snd_seq_client_is_midi2(client) && p->is_midi1)2643			snd_iprintf(buffer, " [MIDI1]");2644#endif2645		snd_iprintf(buffer, "\n");2646		snd_seq_info_dump_subscribers(buffer, &p->c_src, 1, "    Connecting To: ");2647		snd_seq_info_dump_subscribers(buffer, &p->c_dest, 0, "    Connected From: ");2648	}2649	mutex_unlock(&client->ports_mutex);2650}2651 2652static const char *midi_version_string(unsigned int version)2653{2654	switch (version) {2655	case SNDRV_SEQ_CLIENT_LEGACY_MIDI:2656		return "Legacy";2657	case SNDRV_SEQ_CLIENT_UMP_MIDI_1_0:2658		return "UMP MIDI1";2659	case SNDRV_SEQ_CLIENT_UMP_MIDI_2_0:2660		return "UMP MIDI2";2661	default:2662		return "Unknown";2663	}2664}2665 2666/* exported to seq_info.c */2667void snd_seq_info_clients_read(struct snd_info_entry *entry, 2668			       struct snd_info_buffer *buffer)2669{2670	int c;2671	struct snd_seq_client *client;2672 2673	snd_iprintf(buffer, "Client info\n");2674	snd_iprintf(buffer, "  cur  clients : %d\n", client_usage.cur);2675	snd_iprintf(buffer, "  peak clients : %d\n", client_usage.peak);2676	snd_iprintf(buffer, "  max  clients : %d\n", SNDRV_SEQ_MAX_CLIENTS);2677	snd_iprintf(buffer, "\n");2678 2679	/* list the client table */2680	for (c = 0; c < SNDRV_SEQ_MAX_CLIENTS; c++) {2681		client = snd_seq_client_use_ptr(c);2682		if (client == NULL)2683			continue;2684		if (client->type == NO_CLIENT) {2685			snd_seq_client_unlock(client);2686			continue;2687		}2688 2689		snd_iprintf(buffer, "Client %3d : \"%s\" [%s %s]\n",2690			    c, client->name,2691			    client->type == USER_CLIENT ? "User" : "Kernel",2692			    midi_version_string(client->midi_version));2693#if IS_ENABLED(CONFIG_SND_SEQ_UMP)2694		dump_ump_info(buffer, client);2695#endif2696		snd_seq_info_dump_ports(buffer, client);2697		if (snd_seq_write_pool_allocated(client)) {2698			snd_iprintf(buffer, "  Output pool :\n");2699			snd_seq_info_pool(buffer, client->pool, "    ");2700		}2701		if (client->type == USER_CLIENT && client->data.user.fifo &&2702		    client->data.user.fifo->pool) {2703			snd_iprintf(buffer, "  Input pool :\n");2704			snd_seq_info_pool(buffer, client->data.user.fifo->pool, "    ");2705		}2706		snd_seq_client_unlock(client);2707	}2708}2709#endif /* CONFIG_SND_PROC_FS */2710 2711/*---------------------------------------------------------------------------*/2712 2713 2714/*2715 *  REGISTRATION PART2716 */2717 2718static const struct file_operations snd_seq_f_ops =2719{2720	.owner =	THIS_MODULE,2721	.read =		snd_seq_read,2722	.write =	snd_seq_write,2723	.open =		snd_seq_open,2724	.release =	snd_seq_release,2725	.poll =		snd_seq_poll,2726	.unlocked_ioctl =	snd_seq_ioctl,2727	.compat_ioctl =	snd_seq_ioctl_compat,2728};2729 2730static struct device *seq_dev;2731 2732/* 2733 * register sequencer device 2734 */2735int __init snd_sequencer_device_init(void)2736{2737	int err;2738 2739	err = snd_device_alloc(&seq_dev, NULL);2740	if (err < 0)2741		return err;2742	dev_set_name(seq_dev, "seq");2743 2744	mutex_lock(&register_mutex);2745	err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0,2746				  &snd_seq_f_ops, NULL, seq_dev);2747	mutex_unlock(&register_mutex);2748	if (err < 0) {2749		put_device(seq_dev);2750		return err;2751	}2752	2753	return 0;2754}2755 2756 2757 2758/* 2759 * unregister sequencer device 2760 */2761void snd_sequencer_device_done(void)2762{2763	snd_unregister_device(seq_dev);2764	put_device(seq_dev);2765}2766