0001
0002
0003
0004
0005
0006
0007
0008 #include <sound/core.h>
0009 #include <linux/slab.h>
0010 #include <linux/module.h>
0011 #include "seq_system.h"
0012 #include "seq_ports.h"
0013 #include "seq_clientmgr.h"
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 struct snd_seq_client_port *snd_seq_port_use_ptr(struct snd_seq_client *client,
0045 int num)
0046 {
0047 struct snd_seq_client_port *port;
0048
0049 if (client == NULL)
0050 return NULL;
0051 read_lock(&client->ports_lock);
0052 list_for_each_entry(port, &client->ports_list_head, list) {
0053 if (port->addr.port == num) {
0054 if (port->closing)
0055 break;
0056 snd_use_lock_use(&port->use_lock);
0057 read_unlock(&client->ports_lock);
0058 return port;
0059 }
0060 }
0061 read_unlock(&client->ports_lock);
0062 return NULL;
0063 }
0064
0065
0066
0067 struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *client,
0068 struct snd_seq_port_info *pinfo)
0069 {
0070 int num;
0071 struct snd_seq_client_port *port, *found;
0072
0073 num = pinfo->addr.port;
0074 found = NULL;
0075 read_lock(&client->ports_lock);
0076 list_for_each_entry(port, &client->ports_list_head, list) {
0077 if (port->addr.port < num)
0078 continue;
0079 if (port->addr.port == num) {
0080 found = port;
0081 break;
0082 }
0083 if (found == NULL || port->addr.port < found->addr.port)
0084 found = port;
0085 }
0086 if (found) {
0087 if (found->closing)
0088 found = NULL;
0089 else
0090 snd_use_lock_use(&found->use_lock);
0091 }
0092 read_unlock(&client->ports_lock);
0093 return found;
0094 }
0095
0096
0097
0098 static void port_subs_info_init(struct snd_seq_port_subs_info *grp)
0099 {
0100 INIT_LIST_HEAD(&grp->list_head);
0101 grp->count = 0;
0102 grp->exclusive = 0;
0103 rwlock_init(&grp->list_lock);
0104 init_rwsem(&grp->list_mutex);
0105 grp->open = NULL;
0106 grp->close = NULL;
0107 }
0108
0109
0110
0111
0112
0113 struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
0114 int port)
0115 {
0116 struct snd_seq_client_port *new_port, *p;
0117 int num = -1;
0118
0119
0120 if (snd_BUG_ON(!client))
0121 return NULL;
0122
0123 if (client->num_ports >= SNDRV_SEQ_MAX_PORTS) {
0124 pr_warn("ALSA: seq: too many ports for client %d\n", client->number);
0125 return NULL;
0126 }
0127
0128
0129 new_port = kzalloc(sizeof(*new_port), GFP_KERNEL);
0130 if (!new_port)
0131 return NULL;
0132
0133 new_port->addr.client = client->number;
0134 new_port->addr.port = -1;
0135 new_port->owner = THIS_MODULE;
0136 sprintf(new_port->name, "port-%d", num);
0137 snd_use_lock_init(&new_port->use_lock);
0138 port_subs_info_init(&new_port->c_src);
0139 port_subs_info_init(&new_port->c_dest);
0140 snd_use_lock_use(&new_port->use_lock);
0141
0142 num = max(port, 0);
0143 mutex_lock(&client->ports_mutex);
0144 write_lock_irq(&client->ports_lock);
0145 list_for_each_entry(p, &client->ports_list_head, list) {
0146 if (p->addr.port > num)
0147 break;
0148 if (port < 0)
0149 num = p->addr.port + 1;
0150 }
0151
0152 list_add_tail(&new_port->list, &p->list);
0153 client->num_ports++;
0154 new_port->addr.port = num;
0155 sprintf(new_port->name, "port-%d", num);
0156 write_unlock_irq(&client->ports_lock);
0157 mutex_unlock(&client->ports_mutex);
0158
0159 return new_port;
0160 }
0161
0162
0163 static int subscribe_port(struct snd_seq_client *client,
0164 struct snd_seq_client_port *port,
0165 struct snd_seq_port_subs_info *grp,
0166 struct snd_seq_port_subscribe *info, int send_ack);
0167 static int unsubscribe_port(struct snd_seq_client *client,
0168 struct snd_seq_client_port *port,
0169 struct snd_seq_port_subs_info *grp,
0170 struct snd_seq_port_subscribe *info, int send_ack);
0171
0172
0173 static struct snd_seq_client_port *get_client_port(struct snd_seq_addr *addr,
0174 struct snd_seq_client **cp)
0175 {
0176 struct snd_seq_client_port *p;
0177 *cp = snd_seq_client_use_ptr(addr->client);
0178 if (*cp) {
0179 p = snd_seq_port_use_ptr(*cp, addr->port);
0180 if (! p) {
0181 snd_seq_client_unlock(*cp);
0182 *cp = NULL;
0183 }
0184 return p;
0185 }
0186 return NULL;
0187 }
0188
0189 static void delete_and_unsubscribe_port(struct snd_seq_client *client,
0190 struct snd_seq_client_port *port,
0191 struct snd_seq_subscribers *subs,
0192 bool is_src, bool ack);
0193
0194 static inline struct snd_seq_subscribers *
0195 get_subscriber(struct list_head *p, bool is_src)
0196 {
0197 if (is_src)
0198 return list_entry(p, struct snd_seq_subscribers, src_list);
0199 else
0200 return list_entry(p, struct snd_seq_subscribers, dest_list);
0201 }
0202
0203
0204
0205
0206
0207 static void clear_subscriber_list(struct snd_seq_client *client,
0208 struct snd_seq_client_port *port,
0209 struct snd_seq_port_subs_info *grp,
0210 int is_src)
0211 {
0212 struct list_head *p, *n;
0213
0214 list_for_each_safe(p, n, &grp->list_head) {
0215 struct snd_seq_subscribers *subs;
0216 struct snd_seq_client *c;
0217 struct snd_seq_client_port *aport;
0218
0219 subs = get_subscriber(p, is_src);
0220 if (is_src)
0221 aport = get_client_port(&subs->info.dest, &c);
0222 else
0223 aport = get_client_port(&subs->info.sender, &c);
0224 delete_and_unsubscribe_port(client, port, subs, is_src, false);
0225
0226 if (!aport) {
0227
0228
0229
0230
0231 if (atomic_dec_and_test(&subs->ref_count))
0232 kfree(subs);
0233 continue;
0234 }
0235
0236
0237 delete_and_unsubscribe_port(c, aport, subs, !is_src, true);
0238 kfree(subs);
0239 snd_seq_port_unlock(aport);
0240 snd_seq_client_unlock(c);
0241 }
0242 }
0243
0244
0245 static int port_delete(struct snd_seq_client *client,
0246 struct snd_seq_client_port *port)
0247 {
0248
0249 port->closing = 1;
0250 snd_use_lock_sync(&port->use_lock);
0251
0252
0253 clear_subscriber_list(client, port, &port->c_src, true);
0254 clear_subscriber_list(client, port, &port->c_dest, false);
0255
0256 if (port->private_free)
0257 port->private_free(port->private_data);
0258
0259 snd_BUG_ON(port->c_src.count != 0);
0260 snd_BUG_ON(port->c_dest.count != 0);
0261
0262 kfree(port);
0263 return 0;
0264 }
0265
0266
0267
0268 int snd_seq_delete_port(struct snd_seq_client *client, int port)
0269 {
0270 struct snd_seq_client_port *found = NULL, *p;
0271
0272 mutex_lock(&client->ports_mutex);
0273 write_lock_irq(&client->ports_lock);
0274 list_for_each_entry(p, &client->ports_list_head, list) {
0275 if (p->addr.port == port) {
0276
0277 list_del(&p->list);
0278 client->num_ports--;
0279 found = p;
0280 break;
0281 }
0282 }
0283 write_unlock_irq(&client->ports_lock);
0284 mutex_unlock(&client->ports_mutex);
0285 if (found)
0286 return port_delete(client, found);
0287 else
0288 return -ENOENT;
0289 }
0290
0291
0292 int snd_seq_delete_all_ports(struct snd_seq_client *client)
0293 {
0294 struct list_head deleted_list;
0295 struct snd_seq_client_port *port, *tmp;
0296
0297
0298
0299
0300 mutex_lock(&client->ports_mutex);
0301 write_lock_irq(&client->ports_lock);
0302 if (! list_empty(&client->ports_list_head)) {
0303 list_add(&deleted_list, &client->ports_list_head);
0304 list_del_init(&client->ports_list_head);
0305 } else {
0306 INIT_LIST_HEAD(&deleted_list);
0307 }
0308 client->num_ports = 0;
0309 write_unlock_irq(&client->ports_lock);
0310
0311
0312 list_for_each_entry_safe(port, tmp, &deleted_list, list) {
0313 list_del(&port->list);
0314 snd_seq_system_client_ev_port_exit(port->addr.client, port->addr.port);
0315 port_delete(client, port);
0316 }
0317 mutex_unlock(&client->ports_mutex);
0318 return 0;
0319 }
0320
0321
0322 int snd_seq_set_port_info(struct snd_seq_client_port * port,
0323 struct snd_seq_port_info * info)
0324 {
0325 if (snd_BUG_ON(!port || !info))
0326 return -EINVAL;
0327
0328
0329 if (info->name[0])
0330 strscpy(port->name, info->name, sizeof(port->name));
0331
0332
0333 port->capability = info->capability;
0334
0335
0336 port->type = info->type;
0337
0338
0339 port->midi_channels = info->midi_channels;
0340 port->midi_voices = info->midi_voices;
0341 port->synth_voices = info->synth_voices;
0342
0343
0344 port->timestamping = (info->flags & SNDRV_SEQ_PORT_FLG_TIMESTAMP) ? 1 : 0;
0345 port->time_real = (info->flags & SNDRV_SEQ_PORT_FLG_TIME_REAL) ? 1 : 0;
0346 port->time_queue = info->time_queue;
0347
0348 return 0;
0349 }
0350
0351
0352 int snd_seq_get_port_info(struct snd_seq_client_port * port,
0353 struct snd_seq_port_info * info)
0354 {
0355 if (snd_BUG_ON(!port || !info))
0356 return -EINVAL;
0357
0358
0359 strscpy(info->name, port->name, sizeof(info->name));
0360
0361
0362 info->capability = port->capability;
0363
0364
0365 info->type = port->type;
0366
0367
0368 info->midi_channels = port->midi_channels;
0369 info->midi_voices = port->midi_voices;
0370 info->synth_voices = port->synth_voices;
0371
0372
0373 info->read_use = port->c_src.count;
0374 info->write_use = port->c_dest.count;
0375
0376
0377 info->flags = 0;
0378 if (port->timestamping) {
0379 info->flags |= SNDRV_SEQ_PORT_FLG_TIMESTAMP;
0380 if (port->time_real)
0381 info->flags |= SNDRV_SEQ_PORT_FLG_TIME_REAL;
0382 info->time_queue = port->time_queue;
0383 }
0384
0385 return 0;
0386 }
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400 static int subscribe_port(struct snd_seq_client *client,
0401 struct snd_seq_client_port *port,
0402 struct snd_seq_port_subs_info *grp,
0403 struct snd_seq_port_subscribe *info,
0404 int send_ack)
0405 {
0406 int err = 0;
0407
0408 if (!try_module_get(port->owner))
0409 return -EFAULT;
0410 grp->count++;
0411 if (grp->open && grp->count == 1) {
0412 err = grp->open(port->private_data, info);
0413 if (err < 0) {
0414 module_put(port->owner);
0415 grp->count--;
0416 }
0417 }
0418 if (err >= 0 && send_ack && client->type == USER_CLIENT)
0419 snd_seq_client_notify_subscription(port->addr.client, port->addr.port,
0420 info, SNDRV_SEQ_EVENT_PORT_SUBSCRIBED);
0421
0422 return err;
0423 }
0424
0425 static int unsubscribe_port(struct snd_seq_client *client,
0426 struct snd_seq_client_port *port,
0427 struct snd_seq_port_subs_info *grp,
0428 struct snd_seq_port_subscribe *info,
0429 int send_ack)
0430 {
0431 int err = 0;
0432
0433 if (! grp->count)
0434 return -EINVAL;
0435 grp->count--;
0436 if (grp->close && grp->count == 0)
0437 err = grp->close(port->private_data, info);
0438 if (send_ack && client->type == USER_CLIENT)
0439 snd_seq_client_notify_subscription(port->addr.client, port->addr.port,
0440 info, SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED);
0441 module_put(port->owner);
0442 return err;
0443 }
0444
0445
0446
0447
0448 static inline int addr_match(struct snd_seq_addr *r, struct snd_seq_addr *s)
0449 {
0450 return (r->client == s->client) && (r->port == s->port);
0451 }
0452
0453
0454
0455 static int match_subs_info(struct snd_seq_port_subscribe *r,
0456 struct snd_seq_port_subscribe *s)
0457 {
0458 if (addr_match(&r->sender, &s->sender) &&
0459 addr_match(&r->dest, &s->dest)) {
0460 if (r->flags && r->flags == s->flags)
0461 return r->queue == s->queue;
0462 else if (! r->flags)
0463 return 1;
0464 }
0465 return 0;
0466 }
0467
0468 static int check_and_subscribe_port(struct snd_seq_client *client,
0469 struct snd_seq_client_port *port,
0470 struct snd_seq_subscribers *subs,
0471 bool is_src, bool exclusive, bool ack)
0472 {
0473 struct snd_seq_port_subs_info *grp;
0474 struct list_head *p;
0475 struct snd_seq_subscribers *s;
0476 int err;
0477
0478 grp = is_src ? &port->c_src : &port->c_dest;
0479 err = -EBUSY;
0480 down_write(&grp->list_mutex);
0481 if (exclusive) {
0482 if (!list_empty(&grp->list_head))
0483 goto __error;
0484 } else {
0485 if (grp->exclusive)
0486 goto __error;
0487
0488 list_for_each(p, &grp->list_head) {
0489 s = get_subscriber(p, is_src);
0490 if (match_subs_info(&subs->info, &s->info))
0491 goto __error;
0492 }
0493 }
0494
0495 err = subscribe_port(client, port, grp, &subs->info, ack);
0496 if (err < 0) {
0497 grp->exclusive = 0;
0498 goto __error;
0499 }
0500
0501
0502 write_lock_irq(&grp->list_lock);
0503 if (is_src)
0504 list_add_tail(&subs->src_list, &grp->list_head);
0505 else
0506 list_add_tail(&subs->dest_list, &grp->list_head);
0507 grp->exclusive = exclusive;
0508 atomic_inc(&subs->ref_count);
0509 write_unlock_irq(&grp->list_lock);
0510 err = 0;
0511
0512 __error:
0513 up_write(&grp->list_mutex);
0514 return err;
0515 }
0516
0517
0518 static void __delete_and_unsubscribe_port(struct snd_seq_client *client,
0519 struct snd_seq_client_port *port,
0520 struct snd_seq_subscribers *subs,
0521 bool is_src, bool ack)
0522 {
0523 struct snd_seq_port_subs_info *grp;
0524 struct list_head *list;
0525 bool empty;
0526
0527 grp = is_src ? &port->c_src : &port->c_dest;
0528 list = is_src ? &subs->src_list : &subs->dest_list;
0529 write_lock_irq(&grp->list_lock);
0530 empty = list_empty(list);
0531 if (!empty)
0532 list_del_init(list);
0533 grp->exclusive = 0;
0534 write_unlock_irq(&grp->list_lock);
0535
0536 if (!empty)
0537 unsubscribe_port(client, port, grp, &subs->info, ack);
0538 }
0539
0540 static void delete_and_unsubscribe_port(struct snd_seq_client *client,
0541 struct snd_seq_client_port *port,
0542 struct snd_seq_subscribers *subs,
0543 bool is_src, bool ack)
0544 {
0545 struct snd_seq_port_subs_info *grp;
0546
0547 grp = is_src ? &port->c_src : &port->c_dest;
0548 down_write(&grp->list_mutex);
0549 __delete_and_unsubscribe_port(client, port, subs, is_src, ack);
0550 up_write(&grp->list_mutex);
0551 }
0552
0553
0554 int snd_seq_port_connect(struct snd_seq_client *connector,
0555 struct snd_seq_client *src_client,
0556 struct snd_seq_client_port *src_port,
0557 struct snd_seq_client *dest_client,
0558 struct snd_seq_client_port *dest_port,
0559 struct snd_seq_port_subscribe *info)
0560 {
0561 struct snd_seq_subscribers *subs;
0562 bool exclusive;
0563 int err;
0564
0565 subs = kzalloc(sizeof(*subs), GFP_KERNEL);
0566 if (!subs)
0567 return -ENOMEM;
0568
0569 subs->info = *info;
0570 atomic_set(&subs->ref_count, 0);
0571 INIT_LIST_HEAD(&subs->src_list);
0572 INIT_LIST_HEAD(&subs->dest_list);
0573
0574 exclusive = !!(info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE);
0575
0576 err = check_and_subscribe_port(src_client, src_port, subs, true,
0577 exclusive,
0578 connector->number != src_client->number);
0579 if (err < 0)
0580 goto error;
0581 err = check_and_subscribe_port(dest_client, dest_port, subs, false,
0582 exclusive,
0583 connector->number != dest_client->number);
0584 if (err < 0)
0585 goto error_dest;
0586
0587 return 0;
0588
0589 error_dest:
0590 delete_and_unsubscribe_port(src_client, src_port, subs, true,
0591 connector->number != src_client->number);
0592 error:
0593 kfree(subs);
0594 return err;
0595 }
0596
0597
0598 int snd_seq_port_disconnect(struct snd_seq_client *connector,
0599 struct snd_seq_client *src_client,
0600 struct snd_seq_client_port *src_port,
0601 struct snd_seq_client *dest_client,
0602 struct snd_seq_client_port *dest_port,
0603 struct snd_seq_port_subscribe *info)
0604 {
0605 struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
0606 struct snd_seq_subscribers *subs;
0607 int err = -ENOENT;
0608
0609
0610
0611
0612 down_write(&dest->list_mutex);
0613
0614 list_for_each_entry(subs, &dest->list_head, dest_list) {
0615 if (match_subs_info(info, &subs->info)) {
0616 __delete_and_unsubscribe_port(dest_client, dest_port,
0617 subs, false,
0618 connector->number != dest_client->number);
0619 err = 0;
0620 break;
0621 }
0622 }
0623 up_write(&dest->list_mutex);
0624 if (err < 0)
0625 return err;
0626
0627 delete_and_unsubscribe_port(src_client, src_port, subs, true,
0628 connector->number != src_client->number);
0629 kfree(subs);
0630 return 0;
0631 }
0632
0633
0634
0635 int snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp,
0636 struct snd_seq_addr *dest_addr,
0637 struct snd_seq_port_subscribe *subs)
0638 {
0639 struct snd_seq_subscribers *s;
0640 int err = -ENOENT;
0641
0642 down_read(&src_grp->list_mutex);
0643 list_for_each_entry(s, &src_grp->list_head, src_list) {
0644 if (addr_match(dest_addr, &s->info.dest)) {
0645 *subs = s->info;
0646 err = 0;
0647 break;
0648 }
0649 }
0650 up_read(&src_grp->list_mutex);
0651 return err;
0652 }
0653
0654
0655
0656
0657
0658
0659
0660
0661 int snd_seq_event_port_attach(int client,
0662 struct snd_seq_port_callback *pcbp,
0663 int cap, int type, int midi_channels,
0664 int midi_voices, char *portname)
0665 {
0666 struct snd_seq_port_info portinfo;
0667 int ret;
0668
0669
0670 memset(&portinfo, 0, sizeof(portinfo));
0671 portinfo.addr.client = client;
0672 strscpy(portinfo.name, portname ? portname : "Unnamed port",
0673 sizeof(portinfo.name));
0674
0675 portinfo.capability = cap;
0676 portinfo.type = type;
0677 portinfo.kernel = pcbp;
0678 portinfo.midi_channels = midi_channels;
0679 portinfo.midi_voices = midi_voices;
0680
0681
0682 ret = snd_seq_kernel_client_ctl(client,
0683 SNDRV_SEQ_IOCTL_CREATE_PORT,
0684 &portinfo);
0685
0686 if (ret >= 0)
0687 ret = portinfo.addr.port;
0688
0689 return ret;
0690 }
0691 EXPORT_SYMBOL(snd_seq_event_port_attach);
0692
0693
0694
0695
0696
0697 int snd_seq_event_port_detach(int client, int port)
0698 {
0699 struct snd_seq_port_info portinfo;
0700 int err;
0701
0702 memset(&portinfo, 0, sizeof(portinfo));
0703 portinfo.addr.client = client;
0704 portinfo.addr.port = port;
0705 err = snd_seq_kernel_client_ctl(client,
0706 SNDRV_SEQ_IOCTL_DELETE_PORT,
0707 &portinfo);
0708
0709 return err;
0710 }
0711 EXPORT_SYMBOL(snd_seq_event_port_detach);