⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 seq_clientmgr.c

📁 鼎力推荐!本程序是基于嵌入式LUNUX系统开发的源程序代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (snd_seq_ev_is_variable(&event)) {			int extlen = event.data.ext.len & ~SNDRV_SEQ_EXT_MASK;			if ((size_t)(extlen + len) > count) {				/* back out, will get an error this time or next */				err = -EINVAL;				break;			}			/* set user space pointer */			event.data.ext.len = extlen | SNDRV_SEQ_EXT_USRPTR;			event.data.ext.ptr = (char*)buf + sizeof(snd_seq_event_t);			len += extlen; /* increment data length */		} else {#if defined(CONFIG_SND_BIT32_EMUL) || defined(CONFIG_SND_BIT32_EMUL_MODULE)			if (client->convert32 && snd_seq_ev_is_varusr(&event)) {				void *ptr = compat_ptr(event.data.raw32.d[1]);				event.data.ext.ptr = ptr;			}#endif		}		/* ok, enqueue it */		err = snd_seq_client_enqueue_event(client, &event, file,						   !(file->f_flags & O_NONBLOCK),						   0, 0);		if (err < 0)			break;	__skip_event:		/* Update pointers and counts */		count -= len;		buf += len;		written += len;	}	return written ? written : err;}/* * handle polling */static unsigned int snd_seq_poll(struct file *file, poll_table * wait){	client_t *client = (client_t *) file->private_data;	unsigned int mask = 0;	/* check client structures are in place */	snd_assert(client != NULL, return -ENXIO);	if ((snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_INPUT) &&	    client->data.user.fifo) {		/* check if data is available in the outqueue */		if (snd_seq_fifo_poll_wait(client->data.user.fifo, file, wait))			mask |= POLLIN | POLLRDNORM;	}	if (snd_seq_file_flags(file) & SNDRV_SEQ_LFLG_OUTPUT) {		/* check if data is available in the pool */		if (!snd_seq_write_pool_allocated(client) ||		    snd_seq_pool_poll_wait(client->pool, file, wait))			mask |= POLLOUT | POLLWRNORM;	}	return mask;}/*-----------------------------------------------------*//* SYSTEM_INFO ioctl() */static int snd_seq_ioctl_system_info(client_t *client, void __user *arg){	snd_seq_system_info_t info;	memset(&info, 0, sizeof(info));	/* fill the info fields */	info.queues = SNDRV_SEQ_MAX_QUEUES;	info.clients = SNDRV_SEQ_MAX_CLIENTS;	info.ports = 256;	/* fixed limit */	info.channels = 256;	/* fixed limit */	info.cur_clients = client_usage.cur;	info.cur_queues = snd_seq_queue_get_cur_queues();	if (copy_to_user(arg, &info, sizeof(info)))		return -EFAULT;	return 0;}/* RUNNING_MODE ioctl() */static int snd_seq_ioctl_running_mode(client_t *client, void __user *arg){	struct sndrv_seq_running_info info;	client_t *cptr;	int err = 0;	if (copy_from_user(&info, arg, sizeof(info)))		return -EFAULT;	/* requested client number */	cptr = snd_seq_client_use_ptr(info.client);	if (cptr == NULL)		return -ENOENT;		/* don't change !!! */#ifdef SNDRV_BIG_ENDIAN	if (! info.big_endian) {		err = -EINVAL;		goto __err;	}#else	if (info.big_endian) {		err = -EINVAL;		goto __err;	}#endif	if (info.cpu_mode > sizeof(long)) {		err = -EINVAL;		goto __err;	}	cptr->convert32 = (info.cpu_mode < sizeof(long)); __err:	snd_seq_client_unlock(cptr);	return err;}/* CLIENT_INFO ioctl() */static void get_client_info(client_t *cptr, snd_seq_client_info_t *info){	info->client = cptr->number;	/* fill the info fields */	info->type = cptr->type;	strcpy(info->name, cptr->name);	info->filter = cptr->filter;	info->event_lost = cptr->event_lost;	memcpy(info->event_filter, cptr->event_filter, 32);	info->num_ports = cptr->num_ports;	memset(info->reserved, 0, sizeof(info->reserved));}static int snd_seq_ioctl_get_client_info(client_t * client, void __user *arg){	client_t *cptr;	snd_seq_client_info_t client_info;	if (copy_from_user(&client_info, arg, sizeof(client_info)))		return -EFAULT;	/* requested client number */	cptr = snd_seq_client_use_ptr(client_info.client);	if (cptr == NULL)		return -ENOENT;		/* don't change !!! */	get_client_info(cptr, &client_info);	snd_seq_client_unlock(cptr);	if (copy_to_user(arg, &client_info, sizeof(client_info)))		return -EFAULT;	return 0;}/* CLIENT_INFO ioctl() */static int snd_seq_ioctl_set_client_info(client_t * client, void __user *arg){	snd_seq_client_info_t client_info;	if (copy_from_user(&client_info, arg, sizeof(client_info)))		return -EFAULT;	/* it is not allowed to set the info fields for an another client */	if (client->number != client_info.client)		return -EPERM;	/* also client type must be set now */	if (client->type != client_info.type)		return -EINVAL;	/* fill the info fields */	if (client_info.name[0])		strlcpy(client->name, client_info.name, sizeof(client->name));	client->filter = client_info.filter;	client->event_lost = client_info.event_lost;	memcpy(client->event_filter, client_info.event_filter, 32);	return 0;}/*  * CREATE PORT ioctl()  */static int snd_seq_ioctl_create_port(client_t * client, void __user *arg){	client_port_t *port;	snd_seq_port_info_t info;	snd_seq_port_callback_t *callback;	if (copy_from_user(&info, arg, sizeof(info)))		return -EFAULT;	/* it is not allowed to create the port for an another client */	if (info.addr.client != client->number)		return -EPERM;	port = snd_seq_create_port(client, (info.flags & SNDRV_SEQ_PORT_FLG_GIVEN_PORT) ? info.addr.port : -1);	if (port == NULL)		return -ENOMEM;	if (client->type == USER_CLIENT && info.kernel) {		snd_seq_delete_port(client, port->addr.port);		return -EINVAL;	}	if (client->type == KERNEL_CLIENT) {		if ((callback = info.kernel) != NULL) {			if (callback->owner)				port->owner = callback->owner;			port->private_data = callback->private_data;			port->private_free = callback->private_free;			port->callback_all = callback->callback_all;			port->event_input = callback->event_input;			port->c_src.open = callback->subscribe;			port->c_src.close = callback->unsubscribe;			port->c_dest.open = callback->use;			port->c_dest.close = callback->unuse;		}	}	info.addr = port->addr;	snd_seq_set_port_info(port, &info);	snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port);	if (copy_to_user(arg, &info, sizeof(info)))		return -EFAULT;	return 0;}/*  * DELETE PORT ioctl()  */static int snd_seq_ioctl_delete_port(client_t * client, void __user *arg){	snd_seq_port_info_t info;	int err;	/* set passed parameters */	if (copy_from_user(&info, arg, sizeof(info)))		return -EFAULT;		/* it is not allowed to remove the port for an another client */	if (info.addr.client != client->number)		return -EPERM;	err = snd_seq_delete_port(client, info.addr.port);	if (err >= 0)		snd_seq_system_client_ev_port_exit(client->number, info.addr.port);	return err;}/*  * GET_PORT_INFO ioctl() (on any client)  */static int snd_seq_ioctl_get_port_info(client_t *client, void __user *arg){	client_t *cptr;	client_port_t *port;	snd_seq_port_info_t info;	if (copy_from_user(&info, arg, sizeof(info)))		return -EFAULT;	cptr = snd_seq_client_use_ptr(info.addr.client);	if (cptr == NULL)		return -ENXIO;	port = snd_seq_port_use_ptr(cptr, info.addr.port);	if (port == NULL) {		snd_seq_client_unlock(cptr);		return -ENOENT;			/* don't change */	}	/* get port info */	snd_seq_get_port_info(port, &info);	snd_seq_port_unlock(port);	snd_seq_client_unlock(cptr);	if (copy_to_user(arg, &info, sizeof(info)))		return -EFAULT;	return 0;}/*  * SET_PORT_INFO ioctl() (only ports on this/own client)  */static int snd_seq_ioctl_set_port_info(client_t * client, void __user *arg){	client_port_t *port;	snd_seq_port_info_t info;	if (copy_from_user(&info, arg, sizeof(info)))		return -EFAULT;	if (info.addr.client != client->number) /* only set our own ports ! */		return -EPERM;	port = snd_seq_port_use_ptr(client, info.addr.port);	if (port) {		snd_seq_set_port_info(port, &info);		snd_seq_port_unlock(port);	}	return 0;}/* * port subscription (connection) */#define PERM_RD		(SNDRV_SEQ_PORT_CAP_READ|SNDRV_SEQ_PORT_CAP_SUBS_READ)#define PERM_WR		(SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_SUBS_WRITE)static int check_subscription_permission(client_t *client, client_port_t *sport,					 client_port_t *dport,					 snd_seq_port_subscribe_t *subs){	if (client->number != subs->sender.client &&	    client->number != subs->dest.client) {		/* connection by third client - check export permission */		if (check_port_perm(sport, SNDRV_SEQ_PORT_CAP_NO_EXPORT))			return -EPERM;		if (check_port_perm(dport, SNDRV_SEQ_PORT_CAP_NO_EXPORT))			return -EPERM;	}	/* check read permission */	/* if sender or receiver is the subscribing client itself,	 * no permission check is necessary	 */	if (client->number != subs->sender.client) {		if (! check_port_perm(sport, PERM_RD))			return -EPERM;	}	/* check write permission */	if (client->number != subs->dest.client) {		if (! check_port_perm(dport, PERM_WR))			return -EPERM;	}	return 0;}/* * send an subscription notify event to user client: * client must be user client. */int snd_seq_client_notify_subscription(int client, int port,				       snd_seq_port_subscribe_t *info, int evtype){	snd_seq_event_t event;	memset(&event, 0, sizeof(event));	event.type = evtype;	event.data.connect.dest = info->dest;	event.data.connect.sender = info->sender;	return snd_seq_system_notify(client, port, &event);  /* non-atomic */}/*  * add to port's subscription list IOCTL interface  */static int snd_seq_ioctl_subscribe_port(client_t * client, void __user *arg){	int result = -EINVAL;	client_t *receiver = NULL, *sender = NULL;	client_port_t *sport = NULL, *dport = NULL;	snd_seq_port_subscribe_t subs;	if (copy_from_user(&subs, arg, sizeof(subs)))		return -EFAULT;	if ((receiver = snd_seq_client_use_ptr(subs.dest.client)) == NULL)		goto __end;	if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL)		goto __end;	if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL)		goto __end;	if ((dport = snd_seq_port_use_ptr(receiver, subs.dest.port)) == NULL)		goto __end;	result = check_subscription_permission(client, sport, dport, &subs);	if (result < 0)		goto __end;	/* connect them */	result = snd_seq_port_connect(client, sender, sport, receiver, dport, &subs);	if (! result) /* broadcast announce */		snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0,						   &subs, SNDRV_SEQ_EVENT_PORT_SUBSCRIBED);      __end:      	if (sport)		snd_seq_port_unlock(sport);	if (dport)		snd_seq_port_unlock(dport);	if (sender)		snd_seq_client_unlock(sender);	if (receiver)		snd_seq_client_unlock(receiver);	return result;}/*  * remove from port's subscription list  */static int snd_seq_ioctl_unsubscribe_port(client_t * client, void __user *arg){	int result = -ENXIO;	client_t *receiver = NULL, *sender = NULL;	client_port_t *sport = NULL, *dport = NULL;	snd_seq_port_subscribe_t subs;	if (copy_from_user(&subs, arg, sizeof(subs)))		return -EFAULT;	if ((receiver = snd_seq_client_use_ptr(subs.dest.client)) == NULL)		goto __end;	if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL)		goto __end;	if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL)		goto __end;	if ((dport = snd_seq_port_use_ptr(receiver, subs.dest.port)) == NULL)		goto __end;	result = check_subscription_permission(client, sport, dport, &subs);	if (result < 0)		goto __end;	result = snd_seq_port_disconnect(client, sender, sport, receiver, dport, &subs);	if (! result) /* broadcast announce */		snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0,						   &subs, SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED);      __end:      	if (sport)		snd_seq_port_unlock(sport);	if (dport)		snd_seq_port_unlock(dport);	if (sender)		snd_seq_client_unlock(sender);	if (receiver)		snd_seq_client_unlock(receiver);	return result;}/* CREATE_QUEUE ioctl() */static int snd_seq_ioctl_create_queue(client_t *client, void __user *arg){	snd_seq_queue_info_t info;	int result;	queue_t *q;	if (copy_from_user(&info, arg, sizeof(info)))		return -EFAULT;	result = snd_seq_queue_alloc(client->number, info.locked, info.flags);	if (result < 0)		return result;	q = queueptr(result);	if (q == NULL)		return -EINVAL;	info.queue = q->queue;	info.locked = q->locked;	info.owner = q->owner;	/* set queue name */	if (! info.name[0])		snprintf(info.name, sizeof(info.name), "Queue-%d", q->queue);	strlcpy(q->name, info.name, sizeof(q->name));	queuefree(q);	if (copy_to_user(arg, &info, sizeof(info)))		return -EFAULT;	return 0;}/* DELETE_QUEUE ioctl() */static int snd_seq_ioctl_delete_queue(client_t *client, void __user *arg){	snd_seq_queue_info_t info;	if (copy_from_user(&info, arg, sizeof(info)))		return -EFAULT;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -