#include <sound/driver.h>
#include <linux/init.h>
+#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/minors.h>
client_t *client;
/* init client data */
- client = snd_kcalloc(sizeof(client_t), GFP_KERNEL);
+ client = kcalloc(1, sizeof(*client), GFP_KERNEL);
if (client == NULL)
return NULL;
client->pool = snd_seq_pool_new(poolsize);
}
-/*
- * expand a quoted event.
- */
-static int expand_quoted_event(snd_seq_event_t *event)
-{
- snd_seq_event_t *quoted;
-
- quoted = event->data.quote.event;
- if (quoted == NULL) {
- snd_printd("seq: quoted event is NULL\n");
- return -EINVAL;
- }
-
- event->type = quoted->type;
- event->tag = quoted->tag;
- event->source = quoted->source;
- /* don't use quoted destination */
- event->data = quoted->data;
- /* use quoted timestamp only if subscription/port didn't update it */
- if (event->queue == SNDRV_SEQ_QUEUE_DIRECT) {
- event->flags = quoted->flags;
- event->queue = quoted->queue;
- event->time = quoted->time;
- } else {
- event->flags = (event->flags & SNDRV_SEQ_TIME_STAMP_MASK)
- | (quoted->flags & ~SNDRV_SEQ_TIME_STAMP_MASK);
- }
- return 0;
-}
-
/*
* deliver an event to the specified destination.
* if filter is non-zero, client filter bitmap is tested.
client_t *dest = NULL;
client_port_t *dest_port = NULL;
int result = -ENOENT;
- int direct, quoted = 0;
+ int direct;
direct = snd_seq_ev_is_direct(event);
update_timestamp_of_queue(event, dest_port->time_queue,
dest_port->time_real);
- if (event->type == SNDRV_SEQ_EVENT_KERNEL_QUOTE) {
- quoted = 1;
- if (expand_quoted_event(event) < 0) {
- result = 0; /* do not send bounce error */
- goto __skip;
- }
- }
-
switch (dest->type) {
case USER_CLIENT:
if (dest->data.user.fifo)
snd_seq_client_unlock(dest);
if (result < 0 && !direct) {
- if (quoted) {
- /* return directly to the original source */
- dest = snd_seq_client_use_ptr(event->source.client);
- result = bounce_error_event(dest, event, result, atomic, hop);
- snd_seq_client_unlock(dest);
- } else {
- result = bounce_error_event(client, event, result, atomic, hop);
- }
+ result = bounce_error_event(client, event, result, atomic, hop);
}
return result;
}
/* SET_QUEUE_TEMPO ioctl() */
+int snd_seq_set_queue_tempo(int client, snd_seq_queue_tempo_t *tempo)
+{
+ if (!snd_seq_queue_check_access(tempo->queue, client))
+ return -EPERM;
+ return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo);
+}
+
static int snd_seq_ioctl_set_queue_tempo(client_t * client, void __user *arg)
{
int result;
if (copy_from_user(&tempo, arg, sizeof(tempo)))
return -EFAULT;
- if (snd_seq_queue_check_access(tempo.queue, client->number)) {
- result = snd_seq_queue_timer_set_tempo(tempo.queue, client->number, &tempo);
- if (result < 0)
- return result;
- } else {
- return -EPERM;
- }
-
- return 0;
+ result = snd_seq_set_queue_tempo(client->number, &tempo);
+ return result < 0 ? result : 0;
}
unsigned int cmd, unsigned long arg)
{
client_t *client = (client_t *) file->private_data;
+ int err;
snd_assert(client != NULL, return -ENXIO);
- return snd_seq_do_ioctl(client, cmd, (void __user *) arg);
+ /* FIXME: need to unlock BKL to allow preemption */
+ unlock_kernel();
+ err = snd_seq_do_ioctl(client, cmd, (void __user *) arg);
+ lock_kernel();
+ return err;
}
if (ev->type == SNDRV_SEQ_EVENT_NONE)
return 0; /* ignore this */
- if (ev->type == SNDRV_SEQ_EVENT_KERNEL_ERROR ||
- ev->type == SNDRV_SEQ_EVENT_KERNEL_QUOTE)
+ if (ev->type == SNDRV_SEQ_EVENT_KERNEL_ERROR)
return -EINVAL; /* quoted events can't be enqueued */
/* fill in client number */