linux/sound/core/seq/seq_ports.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *   ALSA sequencer Ports
   4 *   Copyright (c) 1998 by Frank van de Pol <fvdpol@coil.demon.nl>
   5 *                         Jaroslav Kysela <perex@perex.cz>
   6 */
   7
   8#include <sound/core.h>
   9#include <linux/slab.h>
  10#include <linux/module.h>
  11#include "seq_system.h"
  12#include "seq_ports.h"
  13#include "seq_clientmgr.h"
  14
  15/*
  16
  17   registration of client ports
  18
  19 */
  20
  21
  22/* 
  23
  24NOTE: the current implementation of the port structure as a linked list is
  25not optimal for clients that have many ports. For sending messages to all
  26subscribers of a port we first need to find the address of the port
  27structure, which means we have to traverse the list. A direct access table
  28(array) would be better, but big preallocated arrays waste memory.
  29
  30Possible actions:
  31
  321) leave it this way, a client does normaly does not have more than a few
  33ports
  34
  352) replace the linked list of ports by a array of pointers which is
  36dynamicly kmalloced. When a port is added or deleted we can simply allocate
  37a new array, copy the corresponding pointers, and delete the old one. We
  38then only need a pointer to this array, and an integer that tells us how
  39much elements are in array.
  40
  41*/
  42
  43/* return pointer to port structure - port is locked if found */
  44struct snd_seq_client_port *snd_seq_port_use_ptr(struct snd_seq_client *client,
  45                                                 int num)
  46{
  47        struct snd_seq_client_port *port;
  48
  49        if (client == NULL)
  50                return NULL;
  51        read_lock(&client->ports_lock);
  52        list_for_each_entry(port, &client->ports_list_head, list) {
  53                if (port->addr.port == num) {
  54                        if (port->closing)
  55                                break; /* deleting now */
  56                        snd_use_lock_use(&port->use_lock);
  57                        read_unlock(&client->ports_lock);
  58                        return port;
  59                }
  60        }
  61        read_unlock(&client->ports_lock);
  62        return NULL;            /* not found */
  63}
  64
  65
  66/* search for the next port - port is locked if found */
  67struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *client,
  68                                                       struct snd_seq_port_info *pinfo)
  69{
  70        int num;
  71        struct snd_seq_client_port *port, *found;
  72
  73        num = pinfo->addr.port;
  74        found = NULL;
  75        read_lock(&client->ports_lock);
  76        list_for_each_entry(port, &client->ports_list_head, list) {
  77                if (port->addr.port < num)
  78                        continue;
  79                if (port->addr.port == num) {
  80                        found = port;
  81                        break;
  82                }
  83                if (found == NULL || port->addr.port < found->addr.port)
  84                        found = port;
  85        }
  86        if (found) {
  87                if (found->closing)
  88                        found = NULL;
  89                else
  90                        snd_use_lock_use(&found->use_lock);
  91        }
  92        read_unlock(&client->ports_lock);
  93        return found;
  94}
  95
  96
  97/* initialize snd_seq_port_subs_info */
  98static void port_subs_info_init(struct snd_seq_port_subs_info *grp)
  99{
 100        INIT_LIST_HEAD(&grp->list_head);
 101        grp->count = 0;
 102        grp->exclusive = 0;
 103        rwlock_init(&grp->list_lock);
 104        init_rwsem(&grp->list_mutex);
 105        grp->open = NULL;
 106        grp->close = NULL;
 107}
 108
 109
 110/* create a port, port number is returned (-1 on failure);
 111 * the caller needs to unref the port via snd_seq_port_unlock() appropriately
 112 */
 113struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
 114                                                int port)
 115{
 116        struct snd_seq_client_port *new_port, *p;
 117        int num = -1;
 118        
 119        /* sanity check */
 120        if (snd_BUG_ON(!client))
 121                return NULL;
 122
 123        if (client->num_ports >= SNDRV_SEQ_MAX_PORTS) {
 124                pr_warn("ALSA: seq: too many ports for client %d\n", client->number);
 125                return NULL;
 126        }
 127
 128        /* create a new port */
 129        new_port = kzalloc(sizeof(*new_port), GFP_KERNEL);
 130        if (!new_port)
 131                return NULL;    /* failure, out of memory */
 132        /* init port data */
 133        new_port->addr.client = client->number;
 134        new_port->addr.port = -1;
 135        new_port->owner = THIS_MODULE;
 136        sprintf(new_port->name, "port-%d", num);
 137        snd_use_lock_init(&new_port->use_lock);
 138        port_subs_info_init(&new_port->c_src);
 139        port_subs_info_init(&new_port->c_dest);
 140        snd_use_lock_use(&new_port->use_lock);
 141
 142        num = port >= 0 ? port : 0;
 143        mutex_lock(&client->ports_mutex);
 144        write_lock_irq(&client->ports_lock);
 145        list_for_each_entry(p, &client->ports_list_head, list) {
 146                if (p->addr.port > num)
 147                        break;
 148                if (port < 0) /* auto-probe mode */
 149                        num = p->addr.port + 1;
 150        }
 151        /* insert the new port */
 152        list_add_tail(&new_port->list, &p->list);
 153        client->num_ports++;
 154        new_port->addr.port = num;      /* store the port number in the port */
 155        sprintf(new_port->name, "port-%d", num);
 156        write_unlock_irq(&client->ports_lock);
 157        mutex_unlock(&client->ports_mutex);
 158
 159        return new_port;
 160}
 161
 162/* */
 163static int subscribe_port(struct snd_seq_client *client,
 164                          struct snd_seq_client_port *port,
 165                          struct snd_seq_port_subs_info *grp,
 166                          struct snd_seq_port_subscribe *info, int send_ack);
 167static int unsubscribe_port(struct snd_seq_client *client,
 168                            struct snd_seq_client_port *port,
 169                            struct snd_seq_port_subs_info *grp,
 170                            struct snd_seq_port_subscribe *info, int send_ack);
 171
 172
 173static struct snd_seq_client_port *get_client_port(struct snd_seq_addr *addr,
 174                                                   struct snd_seq_client **cp)
 175{
 176        struct snd_seq_client_port *p;
 177        *cp = snd_seq_client_use_ptr(addr->client);
 178        if (*cp) {
 179                p = snd_seq_port_use_ptr(*cp, addr->port);
 180                if (! p) {
 181                        snd_seq_client_unlock(*cp);
 182                        *cp = NULL;
 183                }
 184                return p;
 185        }
 186        return NULL;
 187}
 188
 189static void delete_and_unsubscribe_port(struct snd_seq_client *client,
 190                                        struct snd_seq_client_port *port,
 191                                        struct snd_seq_subscribers *subs,
 192                                        bool is_src, bool ack);
 193
 194static inline struct snd_seq_subscribers *
 195get_subscriber(struct list_head *p, bool is_src)
 196{
 197        if (is_src)
 198                return list_entry(p, struct snd_seq_subscribers, src_list);
 199        else
 200                return list_entry(p, struct snd_seq_subscribers, dest_list);
 201}
 202
 203/*
 204 * remove all subscribers on the list
 205 * this is called from port_delete, for each src and dest list.
 206 */
 207static void clear_subscriber_list(struct snd_seq_client *client,
 208                                  struct snd_seq_client_port *port,
 209                                  struct snd_seq_port_subs_info *grp,
 210                                  int is_src)
 211{
 212        struct list_head *p, *n;
 213
 214        list_for_each_safe(p, n, &grp->list_head) {
 215                struct snd_seq_subscribers *subs;
 216                struct snd_seq_client *c;
 217                struct snd_seq_client_port *aport;
 218
 219                subs = get_subscriber(p, is_src);
 220                if (is_src)
 221                        aport = get_client_port(&subs->info.dest, &c);
 222                else
 223                        aport = get_client_port(&subs->info.sender, &c);
 224                delete_and_unsubscribe_port(client, port, subs, is_src, false);
 225
 226                if (!aport) {
 227                        /* looks like the connected port is being deleted.
 228                         * we decrease the counter, and when both ports are deleted
 229                         * remove the subscriber info
 230                         */
 231                        if (atomic_dec_and_test(&subs->ref_count))
 232                                kfree(subs);
 233                        continue;
 234                }
 235
 236                /* ok we got the connected port */
 237                delete_and_unsubscribe_port(c, aport, subs, !is_src, true);
 238                kfree(subs);
 239                snd_seq_port_unlock(aport);
 240                snd_seq_client_unlock(c);
 241        }
 242}
 243
 244/* delete port data */
 245static int port_delete(struct snd_seq_client *client,
 246                       struct snd_seq_client_port *port)
 247{
 248        /* set closing flag and wait for all port access are gone */
 249        port->closing = 1;
 250        snd_use_lock_sync(&port->use_lock); 
 251
 252        /* clear subscribers info */
 253        clear_subscriber_list(client, port, &port->c_src, true);
 254        clear_subscriber_list(client, port, &port->c_dest, false);
 255
 256        if (port->private_free)
 257                port->private_free(port->private_data);
 258
 259        snd_BUG_ON(port->c_src.count != 0);
 260        snd_BUG_ON(port->c_dest.count != 0);
 261
 262        kfree(port);
 263        return 0;
 264}
 265
 266
 267/* delete a port with the given port id */
 268int snd_seq_delete_port(struct snd_seq_client *client, int port)
 269{
 270        struct snd_seq_client_port *found = NULL, *p;
 271
 272        mutex_lock(&client->ports_mutex);
 273        write_lock_irq(&client->ports_lock);
 274        list_for_each_entry(p, &client->ports_list_head, list) {
 275                if (p->addr.port == port) {
 276                        /* ok found.  delete from the list at first */
 277                        list_del(&p->list);
 278                        client->num_ports--;
 279                        found = p;
 280                        break;
 281                }
 282        }
 283        write_unlock_irq(&client->ports_lock);
 284        mutex_unlock(&client->ports_mutex);
 285        if (found)
 286                return port_delete(client, found);
 287        else
 288                return -ENOENT;
 289}
 290
 291/* delete the all ports belonging to the given client */
 292int snd_seq_delete_all_ports(struct snd_seq_client *client)
 293{
 294        struct list_head deleted_list;
 295        struct snd_seq_client_port *port, *tmp;
 296        
 297        /* move the port list to deleted_list, and
 298         * clear the port list in the client data.
 299         */
 300        mutex_lock(&client->ports_mutex);
 301        write_lock_irq(&client->ports_lock);
 302        if (! list_empty(&client->ports_list_head)) {
 303                list_add(&deleted_list, &client->ports_list_head);
 304                list_del_init(&client->ports_list_head);
 305        } else {
 306                INIT_LIST_HEAD(&deleted_list);
 307        }
 308        client->num_ports = 0;
 309        write_unlock_irq(&client->ports_lock);
 310
 311        /* remove each port in deleted_list */
 312        list_for_each_entry_safe(port, tmp, &deleted_list, list) {
 313                list_del(&port->list);
 314                snd_seq_system_client_ev_port_exit(port->addr.client, port->addr.port);
 315                port_delete(client, port);
 316        }
 317        mutex_unlock(&client->ports_mutex);
 318        return 0;
 319}
 320
 321/* set port info fields */
 322int snd_seq_set_port_info(struct snd_seq_client_port * port,
 323                          struct snd_seq_port_info * info)
 324{
 325        if (snd_BUG_ON(!port || !info))
 326                return -EINVAL;
 327
 328        /* set port name */
 329        if (info->name[0])
 330                strlcpy(port->name, info->name, sizeof(port->name));
 331        
 332        /* set capabilities */
 333        port->capability = info->capability;
 334        
 335        /* get port type */
 336        port->type = info->type;
 337
 338        /* information about supported channels/voices */
 339        port->midi_channels = info->midi_channels;
 340        port->midi_voices = info->midi_voices;
 341        port->synth_voices = info->synth_voices;
 342
 343        /* timestamping */
 344        port->timestamping = (info->flags & SNDRV_SEQ_PORT_FLG_TIMESTAMP) ? 1 : 0;
 345        port->time_real = (info->flags & SNDRV_SEQ_PORT_FLG_TIME_REAL) ? 1 : 0;
 346        port->time_queue = info->time_queue;
 347
 348        return 0;
 349}
 350
 351/* get port info fields */
 352int snd_seq_get_port_info(struct snd_seq_client_port * port,
 353                          struct snd_seq_port_info * info)
 354{
 355        if (snd_BUG_ON(!port || !info))
 356                return -EINVAL;
 357
 358        /* get port name */
 359        strlcpy(info->name, port->name, sizeof(info->name));
 360        
 361        /* get capabilities */
 362        info->capability = port->capability;
 363
 364        /* get port type */
 365        info->type = port->type;
 366
 367        /* information about supported channels/voices */
 368        info->midi_channels = port->midi_channels;
 369        info->midi_voices = port->midi_voices;
 370        info->synth_voices = port->synth_voices;
 371
 372        /* get subscriber counts */
 373        info->read_use = port->c_src.count;
 374        info->write_use = port->c_dest.count;
 375        
 376        /* timestamping */
 377        info->flags = 0;
 378        if (port->timestamping) {
 379                info->flags |= SNDRV_SEQ_PORT_FLG_TIMESTAMP;
 380                if (port->time_real)
 381                        info->flags |= SNDRV_SEQ_PORT_FLG_TIME_REAL;
 382                info->time_queue = port->time_queue;
 383        }
 384
 385        return 0;
 386}
 387
 388
 389
 390/*
 391 * call callback functions (if any):
 392 * the callbacks are invoked only when the first (for connection) or
 393 * the last subscription (for disconnection) is done.  Second or later
 394 * subscription results in increment of counter, but no callback is
 395 * invoked.
 396 * This feature is useful if these callbacks are associated with
 397 * initialization or termination of devices (see seq_midi.c).
 398 */
 399
 400static int subscribe_port(struct snd_seq_client *client,
 401                          struct snd_seq_client_port *port,
 402                          struct snd_seq_port_subs_info *grp,
 403                          struct snd_seq_port_subscribe *info,
 404                          int send_ack)
 405{
 406        int err = 0;
 407
 408        if (!try_module_get(port->owner))
 409                return -EFAULT;
 410        grp->count++;
 411        if (grp->open && grp->count == 1) {
 412                err = grp->open(port->private_data, info);
 413                if (err < 0) {
 414                        module_put(port->owner);
 415                        grp->count--;
 416                }
 417        }
 418        if (err >= 0 && send_ack && client->type == USER_CLIENT)
 419                snd_seq_client_notify_subscription(port->addr.client, port->addr.port,
 420                                                   info, SNDRV_SEQ_EVENT_PORT_SUBSCRIBED);
 421
 422        return err;
 423}
 424
 425static int unsubscribe_port(struct snd_seq_client *client,
 426                            struct snd_seq_client_port *port,
 427                            struct snd_seq_port_subs_info *grp,
 428                            struct snd_seq_port_subscribe *info,
 429                            int send_ack)
 430{
 431        int err = 0;
 432
 433        if (! grp->count)
 434                return -EINVAL;
 435        grp->count--;
 436        if (grp->close && grp->count == 0)
 437                err = grp->close(port->private_data, info);
 438        if (send_ack && client->type == USER_CLIENT)
 439                snd_seq_client_notify_subscription(port->addr.client, port->addr.port,
 440                                                   info, SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED);
 441        module_put(port->owner);
 442        return err;
 443}
 444
 445
 446
 447/* check if both addresses are identical */
 448static inline int addr_match(struct snd_seq_addr *r, struct snd_seq_addr *s)
 449{
 450        return (r->client == s->client) && (r->port == s->port);
 451}
 452
 453/* check the two subscribe info match */
 454/* if flags is zero, checks only sender and destination addresses */
 455static int match_subs_info(struct snd_seq_port_subscribe *r,
 456                           struct snd_seq_port_subscribe *s)
 457{
 458        if (addr_match(&r->sender, &s->sender) &&
 459            addr_match(&r->dest, &s->dest)) {
 460                if (r->flags && r->flags == s->flags)
 461                        return r->queue == s->queue;
 462                else if (! r->flags)
 463                        return 1;
 464        }
 465        return 0;
 466}
 467
 468static int check_and_subscribe_port(struct snd_seq_client *client,
 469                                    struct snd_seq_client_port *port,
 470                                    struct snd_seq_subscribers *subs,
 471                                    bool is_src, bool exclusive, bool ack)
 472{
 473        struct snd_seq_port_subs_info *grp;
 474        struct list_head *p;
 475        struct snd_seq_subscribers *s;
 476        int err;
 477
 478        grp = is_src ? &port->c_src : &port->c_dest;
 479        err = -EBUSY;
 480        down_write(&grp->list_mutex);
 481        if (exclusive) {
 482                if (!list_empty(&grp->list_head))
 483                        goto __error;
 484        } else {
 485                if (grp->exclusive)
 486                        goto __error;
 487                /* check whether already exists */
 488                list_for_each(p, &grp->list_head) {
 489                        s = get_subscriber(p, is_src);
 490                        if (match_subs_info(&subs->info, &s->info))
 491                                goto __error;
 492                }
 493        }
 494
 495        err = subscribe_port(client, port, grp, &subs->info, ack);
 496        if (err < 0) {
 497                grp->exclusive = 0;
 498                goto __error;
 499        }
 500
 501        /* add to list */
 502        write_lock_irq(&grp->list_lock);
 503        if (is_src)
 504                list_add_tail(&subs->src_list, &grp->list_head);
 505        else
 506                list_add_tail(&subs->dest_list, &grp->list_head);
 507        grp->exclusive = exclusive;
 508        atomic_inc(&subs->ref_count);
 509        write_unlock_irq(&grp->list_lock);
 510        err = 0;
 511
 512 __error:
 513        up_write(&grp->list_mutex);
 514        return err;
 515}
 516
 517static void delete_and_unsubscribe_port(struct snd_seq_client *client,
 518                                        struct snd_seq_client_port *port,
 519                                        struct snd_seq_subscribers *subs,
 520                                        bool is_src, bool ack)
 521{
 522        struct snd_seq_port_subs_info *grp;
 523        struct list_head *list;
 524        bool empty;
 525
 526        grp = is_src ? &port->c_src : &port->c_dest;
 527        list = is_src ? &subs->src_list : &subs->dest_list;
 528        down_write(&grp->list_mutex);
 529        write_lock_irq(&grp->list_lock);
 530        empty = list_empty(list);
 531        if (!empty)
 532                list_del_init(list);
 533        grp->exclusive = 0;
 534        write_unlock_irq(&grp->list_lock);
 535
 536        if (!empty)
 537                unsubscribe_port(client, port, grp, &subs->info, ack);
 538        up_write(&grp->list_mutex);
 539}
 540
 541/* connect two ports */
 542int snd_seq_port_connect(struct snd_seq_client *connector,
 543                         struct snd_seq_client *src_client,
 544                         struct snd_seq_client_port *src_port,
 545                         struct snd_seq_client *dest_client,
 546                         struct snd_seq_client_port *dest_port,
 547                         struct snd_seq_port_subscribe *info)
 548{
 549        struct snd_seq_subscribers *subs;
 550        bool exclusive;
 551        int err;
 552
 553        subs = kzalloc(sizeof(*subs), GFP_KERNEL);
 554        if (!subs)
 555                return -ENOMEM;
 556
 557        subs->info = *info;
 558        atomic_set(&subs->ref_count, 0);
 559        INIT_LIST_HEAD(&subs->src_list);
 560        INIT_LIST_HEAD(&subs->dest_list);
 561
 562        exclusive = !!(info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE);
 563
 564        err = check_and_subscribe_port(src_client, src_port, subs, true,
 565                                       exclusive,
 566                                       connector->number != src_client->number);
 567        if (err < 0)
 568                goto error;
 569        err = check_and_subscribe_port(dest_client, dest_port, subs, false,
 570                                       exclusive,
 571                                       connector->number != dest_client->number);
 572        if (err < 0)
 573                goto error_dest;
 574
 575        return 0;
 576
 577 error_dest:
 578        delete_and_unsubscribe_port(src_client, src_port, subs, true,
 579                                    connector->number != src_client->number);
 580 error:
 581        kfree(subs);
 582        return err;
 583}
 584
 585/* remove the connection */
 586int snd_seq_port_disconnect(struct snd_seq_client *connector,
 587                            struct snd_seq_client *src_client,
 588                            struct snd_seq_client_port *src_port,
 589                            struct snd_seq_client *dest_client,
 590                            struct snd_seq_client_port *dest_port,
 591                            struct snd_seq_port_subscribe *info)
 592{
 593        struct snd_seq_port_subs_info *src = &src_port->c_src;
 594        struct snd_seq_subscribers *subs;
 595        int err = -ENOENT;
 596
 597        down_write(&src->list_mutex);
 598        /* look for the connection */
 599        list_for_each_entry(subs, &src->list_head, src_list) {
 600                if (match_subs_info(info, &subs->info)) {
 601                        atomic_dec(&subs->ref_count); /* mark as not ready */
 602                        err = 0;
 603                        break;
 604                }
 605        }
 606        up_write(&src->list_mutex);
 607        if (err < 0)
 608                return err;
 609
 610        delete_and_unsubscribe_port(src_client, src_port, subs, true,
 611                                    connector->number != src_client->number);
 612        delete_and_unsubscribe_port(dest_client, dest_port, subs, false,
 613                                    connector->number != dest_client->number);
 614        kfree(subs);
 615        return 0;
 616}
 617
 618
 619/* get matched subscriber */
 620int snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp,
 621                                  struct snd_seq_addr *dest_addr,
 622                                  struct snd_seq_port_subscribe *subs)
 623{
 624        struct snd_seq_subscribers *s;
 625        int err = -ENOENT;
 626
 627        down_read(&src_grp->list_mutex);
 628        list_for_each_entry(s, &src_grp->list_head, src_list) {
 629                if (addr_match(dest_addr, &s->info.dest)) {
 630                        *subs = s->info;
 631                        err = 0;
 632                        break;
 633                }
 634        }
 635        up_read(&src_grp->list_mutex);
 636        return err;
 637}
 638
 639/*
 640 * Attach a device driver that wants to receive events from the
 641 * sequencer.  Returns the new port number on success.
 642 * A driver that wants to receive the events converted to midi, will
 643 * use snd_seq_midisynth_register_port().
 644 */
 645/* exported */
 646int snd_seq_event_port_attach(int client,
 647                              struct snd_seq_port_callback *pcbp,
 648                              int cap, int type, int midi_channels,
 649                              int midi_voices, char *portname)
 650{
 651        struct snd_seq_port_info portinfo;
 652        int  ret;
 653
 654        /* Set up the port */
 655        memset(&portinfo, 0, sizeof(portinfo));
 656        portinfo.addr.client = client;
 657        strlcpy(portinfo.name, portname ? portname : "Unnamed port",
 658                sizeof(portinfo.name));
 659
 660        portinfo.capability = cap;
 661        portinfo.type = type;
 662        portinfo.kernel = pcbp;
 663        portinfo.midi_channels = midi_channels;
 664        portinfo.midi_voices = midi_voices;
 665
 666        /* Create it */
 667        ret = snd_seq_kernel_client_ctl(client,
 668                                        SNDRV_SEQ_IOCTL_CREATE_PORT,
 669                                        &portinfo);
 670
 671        if (ret >= 0)
 672                ret = portinfo.addr.port;
 673
 674        return ret;
 675}
 676EXPORT_SYMBOL(snd_seq_event_port_attach);
 677
 678/*
 679 * Detach the driver from a port.
 680 */
 681/* exported */
 682int snd_seq_event_port_detach(int client, int port)
 683{
 684        struct snd_seq_port_info portinfo;
 685        int  err;
 686
 687        memset(&portinfo, 0, sizeof(portinfo));
 688        portinfo.addr.client = client;
 689        portinfo.addr.port   = port;
 690        err = snd_seq_kernel_client_ctl(client,
 691                                        SNDRV_SEQ_IOCTL_DELETE_PORT,
 692                                        &portinfo);
 693
 694        return err;
 695}
 696EXPORT_SYMBOL(snd_seq_event_port_detach);
 697