Commit 04a56dd8 authored by Takashi Sakamoto's avatar Takashi Sakamoto Committed by Takashi Iwai

ALSA: seq: change ioctl command operation to get data in kernel space

In previous commit, a new table for functions with data in kernel space
is added to replace current table.

This commit changes existent functions to fit the table. These functions
are added to the new table and removed from the old table.
Signed-off-by: default avatarTakashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 8ce8eb60
...@@ -1128,59 +1128,69 @@ static unsigned int snd_seq_poll(struct file *file, poll_table * wait) ...@@ -1128,59 +1128,69 @@ static unsigned int snd_seq_poll(struct file *file, poll_table * wait)
/*-----------------------------------------------------*/ /*-----------------------------------------------------*/
static int snd_seq_ioctl_pversion(struct snd_seq_client *client, void *arg)
{
int *pversion = arg;
*pversion = SNDRV_SEQ_VERSION;
return 0;
}
static int snd_seq_ioctl_client_id(struct snd_seq_client *client, void *arg)
{
int *client_id = arg;
*client_id = client->number;
return 0;
}
/* SYSTEM_INFO ioctl() */ /* SYSTEM_INFO ioctl() */
static int snd_seq_ioctl_system_info(struct snd_seq_client *client, void __user *arg) static int snd_seq_ioctl_system_info(struct snd_seq_client *client, void *arg)
{ {
struct snd_seq_system_info info; struct snd_seq_system_info *info = arg;
memset(&info, 0, sizeof(info)); memset(info, 0, sizeof(*info));
/* fill the info fields */ /* fill the info fields */
info.queues = SNDRV_SEQ_MAX_QUEUES; info->queues = SNDRV_SEQ_MAX_QUEUES;
info.clients = SNDRV_SEQ_MAX_CLIENTS; info->clients = SNDRV_SEQ_MAX_CLIENTS;
info.ports = SNDRV_SEQ_MAX_PORTS; info->ports = SNDRV_SEQ_MAX_PORTS;
info.channels = 256; /* fixed limit */ info->channels = 256; /* fixed limit */
info.cur_clients = client_usage.cur; info->cur_clients = client_usage.cur;
info.cur_queues = snd_seq_queue_get_cur_queues(); info->cur_queues = snd_seq_queue_get_cur_queues();
if (copy_to_user(arg, &info, sizeof(info)))
return -EFAULT;
return 0; return 0;
} }
/* RUNNING_MODE ioctl() */ /* RUNNING_MODE ioctl() */
static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void __user *arg) static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void *arg)
{ {
struct snd_seq_running_info info; struct snd_seq_running_info *info = arg;
struct snd_seq_client *cptr; struct snd_seq_client *cptr;
int err = 0; int err = 0;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
/* requested client number */ /* requested client number */
cptr = snd_seq_client_use_ptr(info.client); cptr = snd_seq_client_use_ptr(info->client);
if (cptr == NULL) if (cptr == NULL)
return -ENOENT; /* don't change !!! */ return -ENOENT; /* don't change !!! */
#ifdef SNDRV_BIG_ENDIAN #ifdef SNDRV_BIG_ENDIAN
if (! info.big_endian) { if (!info->big_endian) {
err = -EINVAL; err = -EINVAL;
goto __err; goto __err;
} }
#else #else
if (info.big_endian) { if (info->big_endian) {
err = -EINVAL; err = -EINVAL;
goto __err; goto __err;
} }
#endif #endif
if (info.cpu_mode > sizeof(long)) { if (info->cpu_mode > sizeof(long)) {
err = -EINVAL; err = -EINVAL;
goto __err; goto __err;
} }
cptr->convert32 = (info.cpu_mode < sizeof(long)); cptr->convert32 = (info->cpu_mode < sizeof(long));
__err: __err:
snd_seq_client_unlock(cptr); snd_seq_client_unlock(cptr);
return err; return err;
...@@ -1214,51 +1224,43 @@ static void get_client_info(struct snd_seq_client *cptr, ...@@ -1214,51 +1224,43 @@ static void get_client_info(struct snd_seq_client *cptr,
} }
static int snd_seq_ioctl_get_client_info(struct snd_seq_client *client, static int snd_seq_ioctl_get_client_info(struct snd_seq_client *client,
void __user *arg) void *arg)
{ {
struct snd_seq_client_info *client_info = arg;
struct snd_seq_client *cptr; struct snd_seq_client *cptr;
struct snd_seq_client_info client_info;
if (copy_from_user(&client_info, arg, sizeof(client_info)))
return -EFAULT;
/* requested client number */ /* requested client number */
cptr = snd_seq_client_use_ptr(client_info.client); cptr = snd_seq_client_use_ptr(client_info->client);
if (cptr == NULL) if (cptr == NULL)
return -ENOENT; /* don't change !!! */ return -ENOENT; /* don't change !!! */
get_client_info(cptr, &client_info); get_client_info(cptr, client_info);
snd_seq_client_unlock(cptr); snd_seq_client_unlock(cptr);
if (copy_to_user(arg, &client_info, sizeof(client_info)))
return -EFAULT;
return 0; return 0;
} }
/* CLIENT_INFO ioctl() */ /* CLIENT_INFO ioctl() */
static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client, static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client,
void __user *arg) void *arg)
{ {
struct snd_seq_client_info client_info; struct snd_seq_client_info *client_info = arg;
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 */ /* it is not allowed to set the info fields for an another client */
if (client->number != client_info.client) if (client->number != client_info->client)
return -EPERM; return -EPERM;
/* also client type must be set now */ /* also client type must be set now */
if (client->type != client_info.type) if (client->type != client_info->type)
return -EINVAL; return -EINVAL;
/* fill the info fields */ /* fill the info fields */
if (client_info.name[0]) if (client_info->name[0])
strlcpy(client->name, client_info.name, sizeof(client->name)); strlcpy(client->name, client_info->name, sizeof(client->name));
client->filter = client_info.filter; client->filter = client_info->filter;
client->event_lost = client_info.event_lost; client->event_lost = client_info->event_lost;
memcpy(client->event_filter, client_info.event_filter, 32); memcpy(client->event_filter, client_info->event_filter, 32);
return 0; return 0;
} }
...@@ -1267,30 +1269,26 @@ static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client, ...@@ -1267,30 +1269,26 @@ static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client,
/* /*
* CREATE PORT ioctl() * CREATE PORT ioctl()
*/ */
static int snd_seq_ioctl_create_port(struct snd_seq_client *client, static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg)
void __user *arg)
{ {
struct snd_seq_port_info *info = arg;
struct snd_seq_client_port *port; struct snd_seq_client_port *port;
struct snd_seq_port_info info;
struct snd_seq_port_callback *callback; struct snd_seq_port_callback *callback;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
/* it is not allowed to create the port for an another client */ /* it is not allowed to create the port for an another client */
if (info.addr.client != client->number) if (info->addr.client != client->number)
return -EPERM; return -EPERM;
port = snd_seq_create_port(client, (info.flags & SNDRV_SEQ_PORT_FLG_GIVEN_PORT) ? info.addr.port : -1); port = snd_seq_create_port(client, (info->flags & SNDRV_SEQ_PORT_FLG_GIVEN_PORT) ? info->addr.port : -1);
if (port == NULL) if (port == NULL)
return -ENOMEM; return -ENOMEM;
if (client->type == USER_CLIENT && info.kernel) { if (client->type == USER_CLIENT && info->kernel) {
snd_seq_delete_port(client, port->addr.port); snd_seq_delete_port(client, port->addr.port);
return -EINVAL; return -EINVAL;
} }
if (client->type == KERNEL_CLIENT) { if (client->type == KERNEL_CLIENT) {
if ((callback = info.kernel) != NULL) { if ((callback = info->kernel) != NULL) {
if (callback->owner) if (callback->owner)
port->owner = callback->owner; port->owner = callback->owner;
port->private_data = callback->private_data; port->private_data = callback->private_data;
...@@ -1303,37 +1301,29 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, ...@@ -1303,37 +1301,29 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client,
} }
} }
info.addr = port->addr; info->addr = port->addr;
snd_seq_set_port_info(port, &info); snd_seq_set_port_info(port, info);
snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port); 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; return 0;
} }
/* /*
* DELETE PORT ioctl() * DELETE PORT ioctl()
*/ */
static int snd_seq_ioctl_delete_port(struct snd_seq_client *client, static int snd_seq_ioctl_delete_port(struct snd_seq_client *client, void *arg)
void __user *arg)
{ {
struct snd_seq_port_info info; struct snd_seq_port_info *info = arg;
int err; 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 */ /* it is not allowed to remove the port for an another client */
if (info.addr.client != client->number) if (info->addr.client != client->number)
return -EPERM; return -EPERM;
err = snd_seq_delete_port(client, info.addr.port); err = snd_seq_delete_port(client, info->addr.port);
if (err >= 0) if (err >= 0)
snd_seq_system_client_ev_port_exit(client->number, info.addr.port); snd_seq_system_client_ev_port_exit(client->number, info->addr.port);
return err; return err;
} }
...@@ -1341,32 +1331,27 @@ static int snd_seq_ioctl_delete_port(struct snd_seq_client *client, ...@@ -1341,32 +1331,27 @@ static int snd_seq_ioctl_delete_port(struct snd_seq_client *client,
/* /*
* GET_PORT_INFO ioctl() (on any client) * GET_PORT_INFO ioctl() (on any client)
*/ */
static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, void *arg)
void __user *arg)
{ {
struct snd_seq_port_info *info = arg;
struct snd_seq_client *cptr; struct snd_seq_client *cptr;
struct snd_seq_client_port *port; struct snd_seq_client_port *port;
struct snd_seq_port_info info;
if (copy_from_user(&info, arg, sizeof(info))) cptr = snd_seq_client_use_ptr(info->addr.client);
return -EFAULT;
cptr = snd_seq_client_use_ptr(info.addr.client);
if (cptr == NULL) if (cptr == NULL)
return -ENXIO; return -ENXIO;
port = snd_seq_port_use_ptr(cptr, info.addr.port); port = snd_seq_port_use_ptr(cptr, info->addr.port);
if (port == NULL) { if (port == NULL) {
snd_seq_client_unlock(cptr); snd_seq_client_unlock(cptr);
return -ENOENT; /* don't change */ return -ENOENT; /* don't change */
} }
/* get port info */ /* get port info */
snd_seq_get_port_info(port, &info); snd_seq_get_port_info(port, info);
snd_seq_port_unlock(port); snd_seq_port_unlock(port);
snd_seq_client_unlock(cptr); snd_seq_client_unlock(cptr);
if (copy_to_user(arg, &info, sizeof(info)))
return -EFAULT;
return 0; return 0;
} }
...@@ -1374,20 +1359,16 @@ static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, ...@@ -1374,20 +1359,16 @@ static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client,
/* /*
* SET_PORT_INFO ioctl() (only ports on this/own client) * SET_PORT_INFO ioctl() (only ports on this/own client)
*/ */
static int snd_seq_ioctl_set_port_info(struct snd_seq_client *client, static int snd_seq_ioctl_set_port_info(struct snd_seq_client *client, void *arg)
void __user *arg)
{ {
struct snd_seq_port_info *info = arg;
struct snd_seq_client_port *port; struct snd_seq_client_port *port;
struct snd_seq_port_info info;
if (copy_from_user(&info, arg, sizeof(info))) if (info->addr.client != client->number) /* only set our own ports ! */
return -EFAULT;
if (info.addr.client != client->number) /* only set our own ports ! */
return -EPERM; return -EPERM;
port = snd_seq_port_use_ptr(client, info.addr.port); port = snd_seq_port_use_ptr(client, info->addr.port);
if (port) { if (port) {
snd_seq_set_port_info(port, &info); snd_seq_set_port_info(port, info);
snd_seq_port_unlock(port); snd_seq_port_unlock(port);
} }
return 0; return 0;
...@@ -1453,34 +1434,31 @@ int snd_seq_client_notify_subscription(int client, int port, ...@@ -1453,34 +1434,31 @@ int snd_seq_client_notify_subscription(int client, int port,
* add to port's subscription list IOCTL interface * add to port's subscription list IOCTL interface
*/ */
static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client, static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client,
void __user *arg) void *arg)
{ {
struct snd_seq_port_subscribe *subs = arg;
int result = -EINVAL; int result = -EINVAL;
struct snd_seq_client *receiver = NULL, *sender = NULL; struct snd_seq_client *receiver = NULL, *sender = NULL;
struct snd_seq_client_port *sport = NULL, *dport = NULL; struct snd_seq_client_port *sport = NULL, *dport = NULL;
struct snd_seq_port_subscribe subs;
if (copy_from_user(&subs, arg, sizeof(subs)))
return -EFAULT;
if ((receiver = snd_seq_client_use_ptr(subs.dest.client)) == NULL) if ((receiver = snd_seq_client_use_ptr(subs->dest.client)) == NULL)
goto __end; goto __end;
if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL) if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL)
goto __end; goto __end;
if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL) if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL)
goto __end; goto __end;
if ((dport = snd_seq_port_use_ptr(receiver, subs.dest.port)) == NULL) if ((dport = snd_seq_port_use_ptr(receiver, subs->dest.port)) == NULL)
goto __end; goto __end;
result = check_subscription_permission(client, sport, dport, &subs); result = check_subscription_permission(client, sport, dport, subs);
if (result < 0) if (result < 0)
goto __end; goto __end;
/* connect them */ /* connect them */
result = snd_seq_port_connect(client, sender, sport, receiver, dport, &subs); result = snd_seq_port_connect(client, sender, sport, receiver, dport, subs);
if (! result) /* broadcast announce */ if (! result) /* broadcast announce */
snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0, snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0,
&subs, SNDRV_SEQ_EVENT_PORT_SUBSCRIBED); subs, SNDRV_SEQ_EVENT_PORT_SUBSCRIBED);
__end: __end:
if (sport) if (sport)
snd_seq_port_unlock(sport); snd_seq_port_unlock(sport);
...@@ -1498,33 +1476,30 @@ static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client, ...@@ -1498,33 +1476,30 @@ static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client,
* remove from port's subscription list * remove from port's subscription list
*/ */
static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client, static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client,
void __user *arg) void *arg)
{ {
struct snd_seq_port_subscribe *subs = arg;
int result = -ENXIO; int result = -ENXIO;
struct snd_seq_client *receiver = NULL, *sender = NULL; struct snd_seq_client *receiver = NULL, *sender = NULL;
struct snd_seq_client_port *sport = NULL, *dport = NULL; struct snd_seq_client_port *sport = NULL, *dport = NULL;
struct snd_seq_port_subscribe subs;
if (copy_from_user(&subs, arg, sizeof(subs))) if ((receiver = snd_seq_client_use_ptr(subs->dest.client)) == NULL)
return -EFAULT;
if ((receiver = snd_seq_client_use_ptr(subs.dest.client)) == NULL)
goto __end; goto __end;
if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL) if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL)
goto __end; goto __end;
if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL) if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL)
goto __end; goto __end;
if ((dport = snd_seq_port_use_ptr(receiver, subs.dest.port)) == NULL) if ((dport = snd_seq_port_use_ptr(receiver, subs->dest.port)) == NULL)
goto __end; goto __end;
result = check_subscription_permission(client, sport, dport, &subs); result = check_subscription_permission(client, sport, dport, subs);
if (result < 0) if (result < 0)
goto __end; goto __end;
result = snd_seq_port_disconnect(client, sender, sport, receiver, dport, &subs); result = snd_seq_port_disconnect(client, sender, sport, receiver, dport, subs);
if (! result) /* broadcast announce */ if (! result) /* broadcast announce */
snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0, snd_seq_client_notify_subscription(SNDRV_SEQ_ADDRESS_SUBSCRIBERS, 0,
&subs, SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED); subs, SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED);
__end: __end:
if (sport) if (sport)
snd_seq_port_unlock(sport); snd_seq_port_unlock(sport);
...@@ -1539,17 +1514,13 @@ static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client, ...@@ -1539,17 +1514,13 @@ static int snd_seq_ioctl_unsubscribe_port(struct snd_seq_client *client,
/* CREATE_QUEUE ioctl() */ /* CREATE_QUEUE ioctl() */
static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, void *arg)
void __user *arg)
{ {
struct snd_seq_queue_info info; struct snd_seq_queue_info *info = arg;
int result; int result;
struct snd_seq_queue *q; struct snd_seq_queue *q;
if (copy_from_user(&info, arg, sizeof(info))) result = snd_seq_queue_alloc(client->number, info->locked, info->flags);
return -EFAULT;
result = snd_seq_queue_alloc(client->number, info.locked, info.flags);
if (result < 0) if (result < 0)
return result; return result;
...@@ -1557,181 +1528,150 @@ static int snd_seq_ioctl_create_queue(struct snd_seq_client *client, ...@@ -1557,181 +1528,150 @@ static int snd_seq_ioctl_create_queue(struct snd_seq_client *client,
if (q == NULL) if (q == NULL)
return -EINVAL; return -EINVAL;
info.queue = q->queue; info->queue = q->queue;
info.locked = q->locked; info->locked = q->locked;
info.owner = q->owner; info->owner = q->owner;
/* set queue name */ /* set queue name */
if (! info.name[0]) if (!info->name[0])
snprintf(info.name, sizeof(info.name), "Queue-%d", q->queue); snprintf(info->name, sizeof(info->name), "Queue-%d", q->queue);
strlcpy(q->name, info.name, sizeof(q->name)); strlcpy(q->name, info->name, sizeof(q->name));
queuefree(q); queuefree(q);
if (copy_to_user(arg, &info, sizeof(info)))
return -EFAULT;
return 0; return 0;
} }
/* DELETE_QUEUE ioctl() */ /* DELETE_QUEUE ioctl() */
static int snd_seq_ioctl_delete_queue(struct snd_seq_client *client, static int snd_seq_ioctl_delete_queue(struct snd_seq_client *client, void *arg)
void __user *arg)
{ {
struct snd_seq_queue_info info; struct snd_seq_queue_info *info = arg;
if (copy_from_user(&info, arg, sizeof(info))) return snd_seq_queue_delete(client->number, info->queue);
return -EFAULT;
return snd_seq_queue_delete(client->number, info.queue);
} }
/* GET_QUEUE_INFO ioctl() */ /* GET_QUEUE_INFO ioctl() */
static int snd_seq_ioctl_get_queue_info(struct snd_seq_client *client, static int snd_seq_ioctl_get_queue_info(struct snd_seq_client *client,
void __user *arg) void *arg)
{ {
struct snd_seq_queue_info info; struct snd_seq_queue_info *info = arg;
struct snd_seq_queue *q; struct snd_seq_queue *q;
if (copy_from_user(&info, arg, sizeof(info))) q = queueptr(info->queue);
return -EFAULT;
q = queueptr(info.queue);
if (q == NULL) if (q == NULL)
return -EINVAL; return -EINVAL;
memset(&info, 0, sizeof(info)); memset(info, 0, sizeof(*info));
info.queue = q->queue; info->queue = q->queue;
info.owner = q->owner; info->owner = q->owner;
info.locked = q->locked; info->locked = q->locked;
strlcpy(info.name, q->name, sizeof(info.name)); strlcpy(info->name, q->name, sizeof(info->name));
queuefree(q); queuefree(q);
if (copy_to_user(arg, &info, sizeof(info)))
return -EFAULT;
return 0; return 0;
} }
/* SET_QUEUE_INFO ioctl() */ /* SET_QUEUE_INFO ioctl() */
static int snd_seq_ioctl_set_queue_info(struct snd_seq_client *client, static int snd_seq_ioctl_set_queue_info(struct snd_seq_client *client,
void __user *arg) void *arg)
{ {
struct snd_seq_queue_info info; struct snd_seq_queue_info *info = arg;
struct snd_seq_queue *q; struct snd_seq_queue *q;
if (copy_from_user(&info, arg, sizeof(info))) if (info->owner != client->number)
return -EFAULT;
if (info.owner != client->number)
return -EINVAL; return -EINVAL;
/* change owner/locked permission */ /* change owner/locked permission */
if (snd_seq_queue_check_access(info.queue, client->number)) { if (snd_seq_queue_check_access(info->queue, client->number)) {
if (snd_seq_queue_set_owner(info.queue, client->number, info.locked) < 0) if (snd_seq_queue_set_owner(info->queue, client->number, info->locked) < 0)
return -EPERM; return -EPERM;
if (info.locked) if (info->locked)
snd_seq_queue_use(info.queue, client->number, 1); snd_seq_queue_use(info->queue, client->number, 1);
} else { } else {
return -EPERM; return -EPERM;
} }
q = queueptr(info.queue); q = queueptr(info->queue);
if (! q) if (! q)
return -EINVAL; return -EINVAL;
if (q->owner != client->number) { if (q->owner != client->number) {
queuefree(q); queuefree(q);
return -EPERM; return -EPERM;
} }
strlcpy(q->name, info.name, sizeof(q->name)); strlcpy(q->name, info->name, sizeof(q->name));
queuefree(q); queuefree(q);
return 0; return 0;
} }
/* GET_NAMED_QUEUE ioctl() */ /* GET_NAMED_QUEUE ioctl() */
static int snd_seq_ioctl_get_named_queue(struct snd_seq_client *client, void __user *arg) static int snd_seq_ioctl_get_named_queue(struct snd_seq_client *client,
void *arg)
{ {
struct snd_seq_queue_info info; struct snd_seq_queue_info *info = arg;
struct snd_seq_queue *q; struct snd_seq_queue *q;
if (copy_from_user(&info, arg, sizeof(info))) q = snd_seq_queue_find_name(info->name);
return -EFAULT;
q = snd_seq_queue_find_name(info.name);
if (q == NULL) if (q == NULL)
return -EINVAL; return -EINVAL;
info.queue = q->queue; info->queue = q->queue;
info.owner = q->owner; info->owner = q->owner;
info.locked = q->locked; info->locked = q->locked;
queuefree(q); queuefree(q);
if (copy_to_user(arg, &info, sizeof(info)))
return -EFAULT;
return 0; return 0;
} }
/* GET_QUEUE_STATUS ioctl() */ /* GET_QUEUE_STATUS ioctl() */
static int snd_seq_ioctl_get_queue_status(struct snd_seq_client *client, static int snd_seq_ioctl_get_queue_status(struct snd_seq_client *client,
void __user *arg) void *arg)
{ {
struct snd_seq_queue_status status; struct snd_seq_queue_status *status = arg;
struct snd_seq_queue *queue; struct snd_seq_queue *queue;
struct snd_seq_timer *tmr; struct snd_seq_timer *tmr;
if (copy_from_user(&status, arg, sizeof(status))) queue = queueptr(status->queue);
return -EFAULT;
queue = queueptr(status.queue);
if (queue == NULL) if (queue == NULL)
return -EINVAL; return -EINVAL;
memset(&status, 0, sizeof(status)); memset(status, 0, sizeof(*status));
status.queue = queue->queue; status->queue = queue->queue;
tmr = queue->timer; tmr = queue->timer;
status.events = queue->tickq->cells + queue->timeq->cells; status->events = queue->tickq->cells + queue->timeq->cells;
status.time = snd_seq_timer_get_cur_time(tmr); status->time = snd_seq_timer_get_cur_time(tmr);
status.tick = snd_seq_timer_get_cur_tick(tmr); status->tick = snd_seq_timer_get_cur_tick(tmr);
status.running = tmr->running; status->running = tmr->running;
status.flags = queue->flags; status->flags = queue->flags;
queuefree(queue); queuefree(queue);
if (copy_to_user(arg, &status, sizeof(status)))
return -EFAULT;
return 0; return 0;
} }
/* GET_QUEUE_TEMPO ioctl() */ /* GET_QUEUE_TEMPO ioctl() */
static int snd_seq_ioctl_get_queue_tempo(struct snd_seq_client *client, static int snd_seq_ioctl_get_queue_tempo(struct snd_seq_client *client,
void __user *arg) void *arg)
{ {
struct snd_seq_queue_tempo tempo; struct snd_seq_queue_tempo *tempo = arg;
struct snd_seq_queue *queue; struct snd_seq_queue *queue;
struct snd_seq_timer *tmr; struct snd_seq_timer *tmr;
if (copy_from_user(&tempo, arg, sizeof(tempo))) queue = queueptr(tempo->queue);
return -EFAULT;
queue = queueptr(tempo.queue);
if (queue == NULL) if (queue == NULL)
return -EINVAL; return -EINVAL;
memset(&tempo, 0, sizeof(tempo)); memset(tempo, 0, sizeof(*tempo));
tempo.queue = queue->queue; tempo->queue = queue->queue;
tmr = queue->timer; tmr = queue->timer;
tempo.tempo = tmr->tempo; tempo->tempo = tmr->tempo;
tempo.ppq = tmr->ppq; tempo->ppq = tmr->ppq;
tempo.skew_value = tmr->skew; tempo->skew_value = tmr->skew;
tempo.skew_base = tmr->skew_base; tempo->skew_base = tmr->skew_base;
queuefree(queue); queuefree(queue);
if (copy_to_user(arg, &tempo, sizeof(tempo)))
return -EFAULT;
return 0; return 0;
} }
...@@ -1747,31 +1687,25 @@ int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo) ...@@ -1747,31 +1687,25 @@ int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo)
EXPORT_SYMBOL(snd_seq_set_queue_tempo); EXPORT_SYMBOL(snd_seq_set_queue_tempo);
static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client, static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client,
void __user *arg) void *arg)
{ {
struct snd_seq_queue_tempo *tempo = arg;
int result; int result;
struct snd_seq_queue_tempo tempo;
if (copy_from_user(&tempo, arg, sizeof(tempo)))
return -EFAULT;
result = snd_seq_set_queue_tempo(client->number, &tempo); result = snd_seq_set_queue_tempo(client->number, tempo);
return result < 0 ? result : 0; return result < 0 ? result : 0;
} }
/* GET_QUEUE_TIMER ioctl() */ /* GET_QUEUE_TIMER ioctl() */
static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client, static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client,
void __user *arg) void *arg)
{ {
struct snd_seq_queue_timer timer; struct snd_seq_queue_timer *timer = arg;
struct snd_seq_queue *queue; struct snd_seq_queue *queue;
struct snd_seq_timer *tmr; struct snd_seq_timer *tmr;
if (copy_from_user(&timer, arg, sizeof(timer))) queue = queueptr(timer->queue);
return -EFAULT;
queue = queueptr(timer.queue);
if (queue == NULL) if (queue == NULL)
return -EINVAL; return -EINVAL;
...@@ -1780,41 +1714,36 @@ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client, ...@@ -1780,41 +1714,36 @@ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client,
return -ERESTARTSYS; return -ERESTARTSYS;
} }
tmr = queue->timer; tmr = queue->timer;
memset(&timer, 0, sizeof(timer)); memset(timer, 0, sizeof(*timer));
timer.queue = queue->queue; timer->queue = queue->queue;
timer.type = tmr->type; timer->type = tmr->type;
if (tmr->type == SNDRV_SEQ_TIMER_ALSA) { if (tmr->type == SNDRV_SEQ_TIMER_ALSA) {
timer.u.alsa.id = tmr->alsa_id; timer->u.alsa.id = tmr->alsa_id;
timer.u.alsa.resolution = tmr->preferred_resolution; timer->u.alsa.resolution = tmr->preferred_resolution;
} }
mutex_unlock(&queue->timer_mutex); mutex_unlock(&queue->timer_mutex);
queuefree(queue); queuefree(queue);
if (copy_to_user(arg, &timer, sizeof(timer)))
return -EFAULT;
return 0; return 0;
} }
/* SET_QUEUE_TIMER ioctl() */ /* SET_QUEUE_TIMER ioctl() */
static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client, static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client,
void __user *arg) void *arg)
{ {
struct snd_seq_queue_timer *timer = arg;
int result = 0; int result = 0;
struct snd_seq_queue_timer timer;
if (copy_from_user(&timer, arg, sizeof(timer))) if (timer->type != SNDRV_SEQ_TIMER_ALSA)
return -EFAULT;
if (timer.type != SNDRV_SEQ_TIMER_ALSA)
return -EINVAL; return -EINVAL;
if (snd_seq_queue_check_access(timer.queue, client->number)) { if (snd_seq_queue_check_access(timer->queue, client->number)) {
struct snd_seq_queue *q; struct snd_seq_queue *q;
struct snd_seq_timer *tmr; struct snd_seq_timer *tmr;
q = queueptr(timer.queue); q = queueptr(timer->queue);
if (q == NULL) if (q == NULL)
return -ENXIO; return -ENXIO;
if (mutex_lock_interruptible(&q->timer_mutex)) { if (mutex_lock_interruptible(&q->timer_mutex)) {
...@@ -1822,13 +1751,13 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client, ...@@ -1822,13 +1751,13 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client,
return -ERESTARTSYS; return -ERESTARTSYS;
} }
tmr = q->timer; tmr = q->timer;
snd_seq_queue_timer_close(timer.queue); snd_seq_queue_timer_close(timer->queue);
tmr->type = timer.type; tmr->type = timer->type;
if (tmr->type == SNDRV_SEQ_TIMER_ALSA) { if (tmr->type == SNDRV_SEQ_TIMER_ALSA) {
tmr->alsa_id = timer.u.alsa.id; tmr->alsa_id = timer->u.alsa.id;
tmr->preferred_resolution = timer.u.alsa.resolution; tmr->preferred_resolution = timer->u.alsa.resolution;
} }
result = snd_seq_queue_timer_open(timer.queue); result = snd_seq_queue_timer_open(timer->queue);
mutex_unlock(&q->timer_mutex); mutex_unlock(&q->timer_mutex);
queuefree(q); queuefree(q);
} else { } else {
...@@ -1841,38 +1770,30 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client, ...@@ -1841,38 +1770,30 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client,
/* GET_QUEUE_CLIENT ioctl() */ /* GET_QUEUE_CLIENT ioctl() */
static int snd_seq_ioctl_get_queue_client(struct snd_seq_client *client, static int snd_seq_ioctl_get_queue_client(struct snd_seq_client *client,
void __user *arg) void *arg)
{ {
struct snd_seq_queue_client info; struct snd_seq_queue_client *info = arg;
int used; int used;
if (copy_from_user(&info, arg, sizeof(info))) used = snd_seq_queue_is_used(info->queue, client->number);
return -EFAULT;
used = snd_seq_queue_is_used(info.queue, client->number);
if (used < 0) if (used < 0)
return -EINVAL; return -EINVAL;
info.used = used; info->used = used;
info.client = client->number; info->client = client->number;
if (copy_to_user(arg, &info, sizeof(info)))
return -EFAULT;
return 0; return 0;
} }
/* SET_QUEUE_CLIENT ioctl() */ /* SET_QUEUE_CLIENT ioctl() */
static int snd_seq_ioctl_set_queue_client(struct snd_seq_client *client, static int snd_seq_ioctl_set_queue_client(struct snd_seq_client *client,
void __user *arg) void *arg)
{ {
struct snd_seq_queue_client *info = arg;
int err; int err;
struct snd_seq_queue_client info;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
if (info.used >= 0) { if (info->used >= 0) {
err = snd_seq_queue_use(info.queue, client->number, info.used); err = snd_seq_queue_use(info->queue, client->number, info->used);
if (err < 0) if (err < 0)
return err; return err;
} }
...@@ -1883,78 +1804,70 @@ static int snd_seq_ioctl_set_queue_client(struct snd_seq_client *client, ...@@ -1883,78 +1804,70 @@ static int snd_seq_ioctl_set_queue_client(struct snd_seq_client *client,
/* GET_CLIENT_POOL ioctl() */ /* GET_CLIENT_POOL ioctl() */
static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client, static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client,
void __user *arg) void *arg)
{ {
struct snd_seq_client_pool info; struct snd_seq_client_pool *info = arg;
struct snd_seq_client *cptr; struct snd_seq_client *cptr;
if (copy_from_user(&info, arg, sizeof(info))) cptr = snd_seq_client_use_ptr(info->client);
return -EFAULT;
cptr = snd_seq_client_use_ptr(info.client);
if (cptr == NULL) if (cptr == NULL)
return -ENOENT; return -ENOENT;
memset(&info, 0, sizeof(info)); memset(info, 0, sizeof(*info));
info.client = cptr->number; info->client = cptr->number;
info.output_pool = cptr->pool->size; info->output_pool = cptr->pool->size;
info.output_room = cptr->pool->room; info->output_room = cptr->pool->room;
info.output_free = info.output_pool; info->output_free = info->output_pool;
info.output_free = snd_seq_unused_cells(cptr->pool); info->output_free = snd_seq_unused_cells(cptr->pool);
if (cptr->type == USER_CLIENT) { if (cptr->type == USER_CLIENT) {
info.input_pool = cptr->data.user.fifo_pool_size; info->input_pool = cptr->data.user.fifo_pool_size;
info.input_free = info.input_pool; info->input_free = info->input_pool;
if (cptr->data.user.fifo) if (cptr->data.user.fifo)
info.input_free = snd_seq_unused_cells(cptr->data.user.fifo->pool); info->input_free = snd_seq_unused_cells(cptr->data.user.fifo->pool);
} else { } else {
info.input_pool = 0; info->input_pool = 0;
info.input_free = 0; info->input_free = 0;
} }
snd_seq_client_unlock(cptr); snd_seq_client_unlock(cptr);
if (copy_to_user(arg, &info, sizeof(info)))
return -EFAULT;
return 0; return 0;
} }
/* SET_CLIENT_POOL ioctl() */ /* SET_CLIENT_POOL ioctl() */
static int snd_seq_ioctl_set_client_pool(struct snd_seq_client *client, static int snd_seq_ioctl_set_client_pool(struct snd_seq_client *client,
void __user *arg) void *arg)
{ {
struct snd_seq_client_pool info; struct snd_seq_client_pool *info = arg;
int rc; int rc;
if (copy_from_user(&info, arg, sizeof(info))) if (client->number != info->client)
return -EFAULT;
if (client->number != info.client)
return -EINVAL; /* can't change other clients */ return -EINVAL; /* can't change other clients */
if (info.output_pool >= 1 && info.output_pool <= SNDRV_SEQ_MAX_EVENTS && if (info->output_pool >= 1 && info->output_pool <= SNDRV_SEQ_MAX_EVENTS &&
(! snd_seq_write_pool_allocated(client) || (! snd_seq_write_pool_allocated(client) ||
info.output_pool != client->pool->size)) { info->output_pool != client->pool->size)) {
if (snd_seq_write_pool_allocated(client)) { if (snd_seq_write_pool_allocated(client)) {
/* remove all existing cells */ /* remove all existing cells */
snd_seq_queue_client_leave_cells(client->number); snd_seq_queue_client_leave_cells(client->number);
snd_seq_pool_done(client->pool); snd_seq_pool_done(client->pool);
} }
client->pool->size = info.output_pool; client->pool->size = info->output_pool;
rc = snd_seq_pool_init(client->pool); rc = snd_seq_pool_init(client->pool);
if (rc < 0) if (rc < 0)
return rc; return rc;
} }
if (client->type == USER_CLIENT && client->data.user.fifo != NULL && if (client->type == USER_CLIENT && client->data.user.fifo != NULL &&
info.input_pool >= 1 && info->input_pool >= 1 &&
info.input_pool <= SNDRV_SEQ_MAX_CLIENT_EVENTS && info->input_pool <= SNDRV_SEQ_MAX_CLIENT_EVENTS &&
info.input_pool != client->data.user.fifo_pool_size) { info->input_pool != client->data.user.fifo_pool_size) {
/* change pool size */ /* change pool size */
rc = snd_seq_fifo_resize(client->data.user.fifo, info.input_pool); rc = snd_seq_fifo_resize(client->data.user.fifo, info->input_pool);
if (rc < 0) if (rc < 0)
return rc; return rc;
client->data.user.fifo_pool_size = info.input_pool; client->data.user.fifo_pool_size = info->input_pool;
} }
if (info.output_room >= 1 && if (info->output_room >= 1 &&
info.output_room <= client->pool->size) { info->output_room <= client->pool->size) {
client->pool->room = info.output_room; client->pool->room = info->output_room;
} }
return snd_seq_ioctl_get_client_pool(client, arg); return snd_seq_ioctl_get_client_pool(client, arg);
...@@ -1963,17 +1876,14 @@ static int snd_seq_ioctl_set_client_pool(struct snd_seq_client *client, ...@@ -1963,17 +1876,14 @@ static int snd_seq_ioctl_set_client_pool(struct snd_seq_client *client,
/* REMOVE_EVENTS ioctl() */ /* REMOVE_EVENTS ioctl() */
static int snd_seq_ioctl_remove_events(struct snd_seq_client *client, static int snd_seq_ioctl_remove_events(struct snd_seq_client *client,
void __user *arg) void *arg)
{ {
struct snd_seq_remove_events info; struct snd_seq_remove_events *info = arg;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
/* /*
* Input mostly not implemented XXX. * Input mostly not implemented XXX.
*/ */
if (info.remove_mode & SNDRV_SEQ_REMOVE_INPUT) { if (info->remove_mode & SNDRV_SEQ_REMOVE_INPUT) {
/* /*
* No restrictions so for a user client we can clear * No restrictions so for a user client we can clear
* the whole fifo * the whole fifo
...@@ -1982,8 +1892,8 @@ static int snd_seq_ioctl_remove_events(struct snd_seq_client *client, ...@@ -1982,8 +1892,8 @@ static int snd_seq_ioctl_remove_events(struct snd_seq_client *client,
snd_seq_fifo_clear(client->data.user.fifo); snd_seq_fifo_clear(client->data.user.fifo);
} }
if (info.remove_mode & SNDRV_SEQ_REMOVE_OUTPUT) if (info->remove_mode & SNDRV_SEQ_REMOVE_OUTPUT)
snd_seq_queue_remove_cells(client->number, &info); snd_seq_queue_remove_cells(client->number, info);
return 0; return 0;
} }
...@@ -1993,26 +1903,23 @@ static int snd_seq_ioctl_remove_events(struct snd_seq_client *client, ...@@ -1993,26 +1903,23 @@ static int snd_seq_ioctl_remove_events(struct snd_seq_client *client,
* get subscription info * get subscription info
*/ */
static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client, static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client,
void __user *arg) void *arg)
{ {
struct snd_seq_port_subscribe *subs = arg;
int result; int result;
struct snd_seq_client *sender = NULL; struct snd_seq_client *sender = NULL;
struct snd_seq_client_port *sport = NULL; struct snd_seq_client_port *sport = NULL;
struct snd_seq_port_subscribe subs;
struct snd_seq_subscribers *p; struct snd_seq_subscribers *p;
if (copy_from_user(&subs, arg, sizeof(subs)))
return -EFAULT;
result = -EINVAL; result = -EINVAL;
if ((sender = snd_seq_client_use_ptr(subs.sender.client)) == NULL) if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL)
goto __end; goto __end;
if ((sport = snd_seq_port_use_ptr(sender, subs.sender.port)) == NULL) if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL)
goto __end; goto __end;
p = snd_seq_port_get_subscription(&sport->c_src, &subs.dest); p = snd_seq_port_get_subscription(&sport->c_src, &subs->dest);
if (p) { if (p) {
result = 0; result = 0;
subs = p->info; *subs = p->info;
} else } else
result = -ENOENT; result = -ENOENT;
...@@ -2021,10 +1928,7 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client, ...@@ -2021,10 +1928,7 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client,
snd_seq_port_unlock(sport); snd_seq_port_unlock(sport);
if (sender) if (sender)
snd_seq_client_unlock(sender); snd_seq_client_unlock(sender);
if (result >= 0) {
if (copy_to_user(arg, &subs, sizeof(subs)))
return -EFAULT;
}
return result; return result;
} }
...@@ -2032,26 +1936,22 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client, ...@@ -2032,26 +1936,22 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client,
/* /*
* get subscription info - check only its presence * get subscription info - check only its presence
*/ */
static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, void *arg)
void __user *arg)
{ {
struct snd_seq_query_subs *subs = arg;
int result = -ENXIO; int result = -ENXIO;
struct snd_seq_client *cptr = NULL; struct snd_seq_client *cptr = NULL;
struct snd_seq_client_port *port = NULL; struct snd_seq_client_port *port = NULL;
struct snd_seq_query_subs subs;
struct snd_seq_port_subs_info *group; struct snd_seq_port_subs_info *group;
struct list_head *p; struct list_head *p;
int i; int i;
if (copy_from_user(&subs, arg, sizeof(subs))) if ((cptr = snd_seq_client_use_ptr(subs->root.client)) == NULL)
return -EFAULT;
if ((cptr = snd_seq_client_use_ptr(subs.root.client)) == NULL)
goto __end; goto __end;
if ((port = snd_seq_port_use_ptr(cptr, subs.root.port)) == NULL) if ((port = snd_seq_port_use_ptr(cptr, subs->root.port)) == NULL)
goto __end; goto __end;
switch (subs.type) { switch (subs->type) {
case SNDRV_SEQ_QUERY_SUBS_READ: case SNDRV_SEQ_QUERY_SUBS_READ:
group = &port->c_src; group = &port->c_src;
break; break;
...@@ -2064,22 +1964,22 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, ...@@ -2064,22 +1964,22 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client,
down_read(&group->list_mutex); down_read(&group->list_mutex);
/* search for the subscriber */ /* search for the subscriber */
subs.num_subs = group->count; subs->num_subs = group->count;
i = 0; i = 0;
result = -ENOENT; result = -ENOENT;
list_for_each(p, &group->list_head) { list_for_each(p, &group->list_head) {
if (i++ == subs.index) { if (i++ == subs->index) {
/* found! */ /* found! */
struct snd_seq_subscribers *s; struct snd_seq_subscribers *s;
if (subs.type == SNDRV_SEQ_QUERY_SUBS_READ) { if (subs->type == SNDRV_SEQ_QUERY_SUBS_READ) {
s = list_entry(p, struct snd_seq_subscribers, src_list); s = list_entry(p, struct snd_seq_subscribers, src_list);
subs.addr = s->info.dest; subs->addr = s->info.dest;
} else { } else {
s = list_entry(p, struct snd_seq_subscribers, dest_list); s = list_entry(p, struct snd_seq_subscribers, dest_list);
subs.addr = s->info.sender; subs->addr = s->info.sender;
} }
subs.flags = s->info.flags; subs->flags = s->info.flags;
subs.queue = s->info.queue; subs->queue = s->info.queue;
result = 0; result = 0;
break; break;
} }
...@@ -2091,10 +1991,7 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, ...@@ -2091,10 +1991,7 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client,
snd_seq_port_unlock(port); snd_seq_port_unlock(port);
if (cptr) if (cptr)
snd_seq_client_unlock(cptr); snd_seq_client_unlock(cptr);
if (result >= 0) {
if (copy_to_user(arg, &subs, sizeof(subs)))
return -EFAULT;
}
return result; return result;
} }
...@@ -2103,31 +2000,26 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, ...@@ -2103,31 +2000,26 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client,
* query next client * query next client
*/ */
static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client, static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client,
void __user *arg) void *arg)
{ {
struct snd_seq_client_info *info = arg;
struct snd_seq_client *cptr = NULL; struct snd_seq_client *cptr = NULL;
struct snd_seq_client_info info;
if (copy_from_user(&info, arg, sizeof(info)))
return -EFAULT;
/* search for next client */ /* search for next client */
info.client++; info->client++;
if (info.client < 0) if (info->client < 0)
info.client = 0; info->client = 0;
for (; info.client < SNDRV_SEQ_MAX_CLIENTS; info.client++) { for (; info->client < SNDRV_SEQ_MAX_CLIENTS; info->client++) {
cptr = snd_seq_client_use_ptr(info.client); cptr = snd_seq_client_use_ptr(info->client);
if (cptr) if (cptr)
break; /* found */ break; /* found */
} }
if (cptr == NULL) if (cptr == NULL)
return -ENOENT; return -ENOENT;
get_client_info(cptr, &info); get_client_info(cptr, info);
snd_seq_client_unlock(cptr); snd_seq_client_unlock(cptr);
if (copy_to_user(arg, &info, sizeof(info)))
return -EFAULT;
return 0; return 0;
} }
...@@ -2135,34 +2027,30 @@ static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client, ...@@ -2135,34 +2027,30 @@ static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client,
* query next port * query next port
*/ */
static int snd_seq_ioctl_query_next_port(struct snd_seq_client *client, static int snd_seq_ioctl_query_next_port(struct snd_seq_client *client,
void __user *arg) void *arg)
{ {
struct snd_seq_port_info *info = arg;
struct snd_seq_client *cptr; struct snd_seq_client *cptr;
struct snd_seq_client_port *port = NULL; struct snd_seq_client_port *port = NULL;
struct snd_seq_port_info info;
if (copy_from_user(&info, arg, sizeof(info))) cptr = snd_seq_client_use_ptr(info->addr.client);
return -EFAULT;
cptr = snd_seq_client_use_ptr(info.addr.client);
if (cptr == NULL) if (cptr == NULL)
return -ENXIO; return -ENXIO;
/* search for next port */ /* search for next port */
info.addr.port++; info->addr.port++;
port = snd_seq_port_query_nearest(cptr, &info); port = snd_seq_port_query_nearest(cptr, info);
if (port == NULL) { if (port == NULL) {
snd_seq_client_unlock(cptr); snd_seq_client_unlock(cptr);
return -ENOENT; return -ENOENT;
} }
/* get port info */ /* get port info */
info.addr = port->addr; info->addr = port->addr;
snd_seq_get_port_info(port, &info); snd_seq_get_port_info(port, info);
snd_seq_port_unlock(port); snd_seq_port_unlock(port);
snd_seq_client_unlock(cptr); snd_seq_client_unlock(cptr);
if (copy_to_user(arg, &info, sizeof(info)))
return -EFAULT;
return 0; return 0;
} }
...@@ -2172,13 +2060,8 @@ static const struct ioctl_handler { ...@@ -2172,13 +2060,8 @@ static const struct ioctl_handler {
unsigned int cmd; unsigned int cmd;
int (*func)(struct snd_seq_client *client, void *arg); int (*func)(struct snd_seq_client *client, void *arg);
} ioctl_handlers[] = { } ioctl_handlers[] = {
{ 0, NULL }, { SNDRV_SEQ_IOCTL_PVERSION, snd_seq_ioctl_pversion },
}; { SNDRV_SEQ_IOCTL_CLIENT_ID, snd_seq_ioctl_client_id },
static struct seq_ioctl_table {
unsigned int cmd;
int (*func)(struct snd_seq_client *client, void __user * arg);
} ioctl_tables[] = {
{ SNDRV_SEQ_IOCTL_SYSTEM_INFO, snd_seq_ioctl_system_info }, { SNDRV_SEQ_IOCTL_SYSTEM_INFO, snd_seq_ioctl_system_info },
{ SNDRV_SEQ_IOCTL_RUNNING_MODE, snd_seq_ioctl_running_mode }, { SNDRV_SEQ_IOCTL_RUNNING_MODE, snd_seq_ioctl_running_mode },
{ SNDRV_SEQ_IOCTL_GET_CLIENT_INFO, snd_seq_ioctl_get_client_info }, { SNDRV_SEQ_IOCTL_GET_CLIENT_INFO, snd_seq_ioctl_get_client_info },
...@@ -2211,6 +2094,13 @@ static struct seq_ioctl_table { ...@@ -2211,6 +2094,13 @@ static struct seq_ioctl_table {
{ 0, NULL }, { 0, NULL },
}; };
static struct seq_ioctl_table {
unsigned int cmd;
int (*func)(struct snd_seq_client *client, void __user * arg);
} ioctl_tables[] = {
{ 0, NULL },
};
static long seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) static long seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{ {
struct snd_seq_client *client = file->private_data; struct snd_seq_client *client = file->private_data;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment