X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=sound%2Fcore%2Fseq%2Fseq_clientmgr.c;h=2e3fa25ab19ffe8208ba17a1d06023bbf8d0427a;hb=f0163ac45b40bd032b877c747796146d52d4e800;hp=5eab4201c6407cc9def0960eef33e78eb209fa64;hpb=c7e0b5bf9fff1b726495081447c107a2333fb82c;p=safe%2Fjmp%2Flinux-2.6 diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 5eab420..2e3fa25 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1,7 +1,7 @@ /* * ALSA sequencer Client Manager * Copyright (c) 1998-2001 by Frank van de Pol - * Jaroslav Kysela + * Jaroslav Kysela * Takashi Iwai * * @@ -23,7 +23,6 @@ #include #include -#include #include #include #include @@ -47,12 +46,27 @@ * */ +/* + * There are four ranges of client numbers (last two shared): + * 0..15: global clients + * 16..127: statically allocated client numbers for cards 0..27 + * 128..191: dynamically allocated client numbers for cards 28..31 + * 128..191: dynamically allocated client numbers for applications + */ + +/* number of kernel non-card clients */ +#define SNDRV_SEQ_GLOBAL_CLIENTS 16 +/* clients per cards, for static clients */ +#define SNDRV_SEQ_CLIENTS_PER_CARD 4 +/* dynamically allocated client numbers (both kernel drivers and user space) */ +#define SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN 128 + #define SNDRV_SEQ_LFLG_INPUT 0x0001 #define SNDRV_SEQ_LFLG_OUTPUT 0x0002 #define SNDRV_SEQ_LFLG_OPEN (SNDRV_SEQ_LFLG_INPUT|SNDRV_SEQ_LFLG_OUTPUT) static DEFINE_SPINLOCK(clients_lock); -static DECLARE_MUTEX(register_mutex); +static DEFINE_MUTEX(register_mutex); /* * client table @@ -139,14 +153,14 @@ struct snd_seq_client *snd_seq_client_use_ptr(int clientid) spin_unlock_irqrestore(&clients_lock, flags); #ifdef CONFIG_KMOD if (!in_interrupt() && current->fs->root) { - static char client_requested[64]; + static char client_requested[SNDRV_SEQ_GLOBAL_CLIENTS]; static char card_requested[SNDRV_CARDS]; - if (clientid < 64) { + if (clientid < SNDRV_SEQ_GLOBAL_CLIENTS) { int idx; if (! client_requested[clientid] && current->fs->root) { client_requested[clientid] = 1; - for (idx = 0; idx < 64; idx++) { + for (idx = 0; idx < 15; idx++) { if (seq_client_load[idx] < 0) break; if (seq_client_load[idx] == clientid) { @@ -156,8 +170,9 @@ struct snd_seq_client *snd_seq_client_use_ptr(int clientid) } } } - } else if (clientid >= 64 && clientid < 128) { - int card = (clientid - 64) / 8; + } else if (clientid < SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN) { + int card = (clientid - SNDRV_SEQ_GLOBAL_CLIENTS) / + SNDRV_SEQ_CLIENTS_PER_CARD; if (card < snd_ecards_limit) { if (! card_requested[card]) { card_requested[card] = 1; @@ -221,13 +236,15 @@ static struct snd_seq_client *seq_create_client1(int client_index, int poolsize) client->type = NO_CLIENT; snd_use_lock_init(&client->use_lock); rwlock_init(&client->ports_lock); - init_MUTEX(&client->ports_mutex); + mutex_init(&client->ports_mutex); INIT_LIST_HEAD(&client->ports_list_head); /* find free slot in the client table */ spin_lock_irqsave(&clients_lock, flags); if (client_index < 0) { - for (c = 128; c < SNDRV_SEQ_MAX_CLIENTS; c++) { + for (c = SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN; + c < SNDRV_SEQ_MAX_CLIENTS; + c++) { if (clienttab[c] || clienttablock[c]) continue; clienttab[client->number = c] = client; @@ -272,7 +289,7 @@ static int seq_free_client1(struct snd_seq_client *client) static void seq_free_client(struct snd_seq_client * client) { - down(®ister_mutex); + mutex_lock(®ister_mutex); switch (client->type) { case NO_CLIENT: snd_printk(KERN_WARNING "Seq: Trying to free unused client %d\n", @@ -288,7 +305,7 @@ static void seq_free_client(struct snd_seq_client * client) snd_printk(KERN_ERR "Seq: Trying to free client %d with undefined type = %d\n", client->number, client->type); } - up(®ister_mutex); + mutex_unlock(®ister_mutex); snd_seq_system_client_ev_client_exit(client->number); } @@ -304,11 +321,11 @@ static int snd_seq_open(struct inode *inode, struct file *file) struct snd_seq_client *client; struct snd_seq_user_client *user; - if (down_interruptible(®ister_mutex)) + if (mutex_lock_interruptible(®ister_mutex)) return -ERESTARTSYS; client = seq_create_client1(-1, SNDRV_SEQ_DEFAULT_EVENTS); if (client == NULL) { - up(®ister_mutex); + mutex_unlock(®ister_mutex); return -ENOMEM; /* failure code */ } @@ -328,14 +345,14 @@ static int snd_seq_open(struct inode *inode, struct file *file) if (user->fifo == NULL) { seq_free_client1(client); kfree(client); - up(®ister_mutex); + mutex_unlock(®ister_mutex); return -ENOMEM; } } usage_alloc(&client_usage, 1); client->type = USER_CLIENT; - up(®ister_mutex); + mutex_unlock(®ister_mutex); c = client->number; file->private_data = client; @@ -641,7 +658,6 @@ static int deliver_to_subscribers(struct snd_seq_client *client, int err = 0, num_ev = 0; struct snd_seq_event event_saved; struct snd_seq_client_port *src_port; - struct list_head *p; struct snd_seq_port_subs_info *grp; src_port = snd_seq_port_use_ptr(client, event->source.port); @@ -656,8 +672,7 @@ static int deliver_to_subscribers(struct snd_seq_client *client, read_lock(&grp->list_lock); else down_read(&grp->list_mutex); - list_for_each(p, &grp->list_head) { - subs = list_entry(p, struct snd_seq_subscribers, src_list); + list_for_each_entry(subs, &grp->list_head, src_list) { event->dest = subs->info.dest; if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP) /* convert time according to flag with subscription */ @@ -691,15 +706,14 @@ static int port_broadcast_event(struct snd_seq_client *client, { int num_ev = 0, err = 0; struct snd_seq_client *dest_client; - struct list_head *p; + struct snd_seq_client_port *port; dest_client = get_event_dest_client(event, SNDRV_SEQ_FILTER_BROADCAST); if (dest_client == NULL) return 0; /* no matching destination */ read_lock(&dest_client->ports_lock); - list_for_each(p, &dest_client->ports_list_head) { - struct snd_seq_client_port *port = list_entry(p, struct snd_seq_client_port, list); + list_for_each_entry(port, &dest_client->ports_list_head, list) { event->dest.port = port->addr.port; /* pass NULL as source client to avoid error bounce */ err = snd_seq_deliver_single_event(NULL, event, @@ -1696,6 +1710,8 @@ int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo) return snd_seq_queue_timer_set_tempo(tempo->queue, client, tempo); } +EXPORT_SYMBOL(snd_seq_set_queue_tempo); + static int snd_seq_ioctl_set_queue_tempo(struct snd_seq_client *client, void __user *arg) { @@ -1725,7 +1741,7 @@ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client, if (queue == NULL) return -EINVAL; - if (down_interruptible(&queue->timer_mutex)) { + if (mutex_lock_interruptible(&queue->timer_mutex)) { queuefree(queue); return -ERESTARTSYS; } @@ -1738,7 +1754,7 @@ static int snd_seq_ioctl_get_queue_timer(struct snd_seq_client *client, timer.u.alsa.id = tmr->alsa_id; timer.u.alsa.resolution = tmr->preferred_resolution; } - up(&queue->timer_mutex); + mutex_unlock(&queue->timer_mutex); queuefree(queue); if (copy_to_user(arg, &timer, sizeof(timer))) @@ -1767,7 +1783,7 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client, q = queueptr(timer.queue); if (q == NULL) return -ENXIO; - if (down_interruptible(&q->timer_mutex)) { + if (mutex_lock_interruptible(&q->timer_mutex)) { queuefree(q); return -ERESTARTSYS; } @@ -1779,7 +1795,7 @@ static int snd_seq_ioctl_set_queue_timer(struct snd_seq_client *client, tmr->preferred_resolution = timer.u.alsa.resolution; } result = snd_seq_queue_timer_open(timer.queue); - up(&q->timer_mutex); + mutex_unlock(&q->timer_mutex); queuefree(q); } else { return -EPERM; @@ -1848,8 +1864,7 @@ static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client, info.output_pool = cptr->pool->size; info.output_room = cptr->pool->room; info.output_free = info.output_pool; - if (cptr->pool) - info.output_free = snd_seq_unused_cells(cptr->pool); + info.output_free = snd_seq_unused_cells(cptr->pool); if (cptr->type == USER_CLIENT) { info.input_pool = cptr->data.user.fifo_pool_size; info.input_free = info.input_pool; @@ -2200,41 +2215,45 @@ static long snd_seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg /* exported to kernel modules */ int snd_seq_create_kernel_client(struct snd_card *card, int client_index, - struct snd_seq_client_callback *callback) + const char *name_fmt, ...) { struct snd_seq_client *client; + va_list args; snd_assert(! in_interrupt(), return -EBUSY); - if (callback == NULL) - return -EINVAL; - if (card && client_index > 7) + if (card && client_index >= SNDRV_SEQ_CLIENTS_PER_CARD) return -EINVAL; - if (card == NULL && client_index > 63) + if (card == NULL && client_index >= SNDRV_SEQ_GLOBAL_CLIENTS) return -EINVAL; - if (card) - client_index += 64 + (card->number << 3); - if (down_interruptible(®ister_mutex)) + if (mutex_lock_interruptible(®ister_mutex)) return -ERESTARTSYS; + + if (card) { + client_index += SNDRV_SEQ_GLOBAL_CLIENTS + + card->number * SNDRV_SEQ_CLIENTS_PER_CARD; + if (client_index >= SNDRV_SEQ_DYNAMIC_CLIENTS_BEGIN) + client_index = -1; + } + /* empty write queue as default */ client = seq_create_client1(client_index, 0); if (client == NULL) { - up(®ister_mutex); + mutex_unlock(®ister_mutex); return -EBUSY; /* failure code */ } usage_alloc(&client_usage, 1); - client->accept_input = callback->allow_output; - client->accept_output = callback->allow_input; + client->accept_input = 1; + client->accept_output = 1; - /* fill client data */ - client->data.kernel.card = card; - client->data.kernel.private_data = callback->private_data; - sprintf(client->name, "Client-%d", client->number); + va_start(args, name_fmt); + vsnprintf(client->name, sizeof(client->name), name_fmt, args); + va_end(args); client->type = KERNEL_CLIENT; - up(®ister_mutex); + mutex_unlock(®ister_mutex); /* make others aware this new client */ snd_seq_system_client_ev_client_start(client->number); @@ -2243,6 +2262,8 @@ int snd_seq_create_kernel_client(struct snd_card *card, int client_index, return client->number; } +EXPORT_SYMBOL(snd_seq_create_kernel_client); + /* exported to kernel modules */ int snd_seq_delete_kernel_client(int client) { @@ -2259,6 +2280,7 @@ int snd_seq_delete_kernel_client(int client) return 0; } +EXPORT_SYMBOL(snd_seq_delete_kernel_client); /* skeleton to enqueue event, called from snd_seq_kernel_client_enqueue * and snd_seq_kernel_client_enqueue_blocking @@ -2307,6 +2329,8 @@ int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event * ev, return kernel_client_enqueue(client, ev, NULL, 0, atomic, hop); } +EXPORT_SYMBOL(snd_seq_kernel_client_enqueue); + /* * exported, called by kernel clients to enqueue events (with blocking) * @@ -2319,6 +2343,7 @@ int snd_seq_kernel_client_enqueue_blocking(int client, struct snd_seq_event * ev return kernel_client_enqueue(client, ev, file, 1, atomic, hop); } +EXPORT_SYMBOL(snd_seq_kernel_client_enqueue_blocking); /* * exported, called by kernel clients to dispatch events directly to other @@ -2355,6 +2380,7 @@ int snd_seq_kernel_client_dispatch(int client, struct snd_seq_event * ev, return result; } +EXPORT_SYMBOL(snd_seq_kernel_client_dispatch); /* * exported, called by kernel clients to perform same functions as with @@ -2375,6 +2401,7 @@ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg) return result; } +EXPORT_SYMBOL(snd_seq_kernel_client_ctl); /* exported (for OSS emulator) */ int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table *wait) @@ -2392,8 +2419,11 @@ int snd_seq_kernel_client_write_poll(int clientid, struct file *file, poll_table return 0; } +EXPORT_SYMBOL(snd_seq_kernel_client_write_poll); + /*---------------------------------------------------------------------------*/ +#ifdef CONFIG_PROC_FS /* * /proc interface */ @@ -2439,11 +2469,10 @@ static void snd_seq_info_dump_subscribers(struct snd_info_buffer *buffer, static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer, struct snd_seq_client *client) { - struct list_head *l; + struct snd_seq_client_port *p; - down(&client->ports_mutex); - list_for_each(l, &client->ports_list_head) { - struct snd_seq_client_port *p = list_entry(l, struct snd_seq_client_port, list); + mutex_lock(&client->ports_mutex); + list_for_each_entry(p, &client->ports_list_head, list) { snd_iprintf(buffer, " Port %3d : \"%s\" (%c%c%c%c)\n", p->addr.port, p->name, FLAG_PERM_RD(p->capability), @@ -2453,7 +2482,7 @@ static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer, snd_seq_info_dump_subscribers(buffer, &p->c_src, 1, " Connecting To: "); snd_seq_info_dump_subscribers(buffer, &p->c_dest, 0, " Connected From: "); } - up(&client->ports_mutex); + mutex_unlock(&client->ports_mutex); } @@ -2499,7 +2528,7 @@ void snd_seq_info_clients_read(struct snd_info_entry *entry, snd_seq_client_unlock(client); } } - +#endif /* CONFIG_PROC_FS */ /*---------------------------------------------------------------------------*/ @@ -2508,7 +2537,7 @@ void snd_seq_info_clients_read(struct snd_info_entry *entry, * REGISTRATION PART */ -static struct file_operations snd_seq_f_ops = +static const struct file_operations snd_seq_f_ops = { .owner = THIS_MODULE, .read = snd_seq_read, @@ -2520,13 +2549,6 @@ static struct file_operations snd_seq_f_ops = .compat_ioctl = snd_seq_ioctl_compat, }; -static struct snd_minor snd_seq_reg = -{ - .comment = "sequencer", - .f_ops = &snd_seq_f_ops, -}; - - /* * register sequencer device */ @@ -2534,15 +2556,16 @@ int __init snd_sequencer_device_init(void) { int err; - if (down_interruptible(®ister_mutex)) + if (mutex_lock_interruptible(®ister_mutex)) return -ERESTARTSYS; - if ((err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0, &snd_seq_reg, "seq")) < 0) { - up(®ister_mutex); + if ((err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0, + &snd_seq_f_ops, NULL, "seq")) < 0) { + mutex_unlock(®ister_mutex); return err; } - up(®ister_mutex); + mutex_unlock(®ister_mutex); return 0; }