linux/sound/core/seq/seq_compat.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *   32bit -> 64bit ioctl wrapper for sequencer API
   4 *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
   5 */
   6
   7/* This file included from seq.c */
   8
   9#include <linux/compat.h>
  10#include <linux/slab.h>
  11
  12struct snd_seq_port_info32 {
  13        struct snd_seq_addr addr;       /* client/port numbers */
  14        char name[64];                  /* port name */
  15
  16        u32 capability; /* port capability bits */
  17        u32 type;               /* port type bits */
  18        s32 midi_channels;              /* channels per MIDI port */
  19        s32 midi_voices;                /* voices per MIDI port */
  20        s32 synth_voices;               /* voices per SYNTH port */
  21
  22        s32 read_use;                   /* R/O: subscribers for output (from this port) */
  23        s32 write_use;                  /* R/O: subscribers for input (to this port) */
  24
  25        u32 kernel;                     /* reserved for kernel use (must be NULL) */
  26        u32 flags;              /* misc. conditioning */
  27        unsigned char time_queue;       /* queue # for timestamping */
  28        char reserved[59];              /* for future use */
  29};
  30
  31static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned int cmd,
  32                                        struct snd_seq_port_info32 __user *data32)
  33{
  34        int err = -EFAULT;
  35        struct snd_seq_port_info *data;
  36
  37        data = kmalloc(sizeof(*data), GFP_KERNEL);
  38        if (!data)
  39                return -ENOMEM;
  40
  41        if (copy_from_user(data, data32, sizeof(*data32)) ||
  42            get_user(data->flags, &data32->flags) ||
  43            get_user(data->time_queue, &data32->time_queue))
  44                goto error;
  45        data->kernel = NULL;
  46
  47        err = snd_seq_kernel_client_ctl(client->number, cmd, data);
  48        if (err < 0)
  49                goto error;
  50
  51        if (copy_to_user(data32, data, sizeof(*data32)) ||
  52            put_user(data->flags, &data32->flags) ||
  53            put_user(data->time_queue, &data32->time_queue))
  54                err = -EFAULT;
  55
  56 error:
  57        kfree(data);
  58        return err;
  59}
  60
  61
  62
  63/*
  64 */
  65
  66enum {
  67        SNDRV_SEQ_IOCTL_CREATE_PORT32 = _IOWR('S', 0x20, struct snd_seq_port_info32),
  68        SNDRV_SEQ_IOCTL_DELETE_PORT32 = _IOW ('S', 0x21, struct snd_seq_port_info32),
  69        SNDRV_SEQ_IOCTL_GET_PORT_INFO32 = _IOWR('S', 0x22, struct snd_seq_port_info32),
  70        SNDRV_SEQ_IOCTL_SET_PORT_INFO32 = _IOW ('S', 0x23, struct snd_seq_port_info32),
  71        SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32 = _IOWR('S', 0x52, struct snd_seq_port_info32),
  72};
  73
  74static long snd_seq_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
  75{
  76        struct snd_seq_client *client = file->private_data;
  77        void __user *argp = compat_ptr(arg);
  78
  79        if (snd_BUG_ON(!client))
  80                return -ENXIO;
  81
  82        switch (cmd) {
  83        case SNDRV_SEQ_IOCTL_PVERSION:
  84        case SNDRV_SEQ_IOCTL_CLIENT_ID:
  85        case SNDRV_SEQ_IOCTL_SYSTEM_INFO:
  86        case SNDRV_SEQ_IOCTL_GET_CLIENT_INFO:
  87        case SNDRV_SEQ_IOCTL_SET_CLIENT_INFO:
  88        case SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT:
  89        case SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT:
  90        case SNDRV_SEQ_IOCTL_CREATE_QUEUE:
  91        case SNDRV_SEQ_IOCTL_DELETE_QUEUE:
  92        case SNDRV_SEQ_IOCTL_GET_QUEUE_INFO:
  93        case SNDRV_SEQ_IOCTL_SET_QUEUE_INFO:
  94        case SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE:
  95        case SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS:
  96        case SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO:
  97        case SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO:
  98        case SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER:
  99        case SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER:
 100        case SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT:
 101        case SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT:
 102        case SNDRV_SEQ_IOCTL_GET_CLIENT_POOL:
 103        case SNDRV_SEQ_IOCTL_SET_CLIENT_POOL:
 104        case SNDRV_SEQ_IOCTL_REMOVE_EVENTS:
 105        case SNDRV_SEQ_IOCTL_QUERY_SUBS:
 106        case SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION:
 107        case SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT:
 108        case SNDRV_SEQ_IOCTL_RUNNING_MODE:
 109                return snd_seq_ioctl(file, cmd, arg);
 110        case SNDRV_SEQ_IOCTL_CREATE_PORT32:
 111                return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, argp);
 112        case SNDRV_SEQ_IOCTL_DELETE_PORT32:
 113                return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_DELETE_PORT, argp);
 114        case SNDRV_SEQ_IOCTL_GET_PORT_INFO32:
 115                return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_GET_PORT_INFO, argp);
 116        case SNDRV_SEQ_IOCTL_SET_PORT_INFO32:
 117                return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_SET_PORT_INFO, argp);
 118        case SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32:
 119                return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, argp);
 120        }
 121        return -ENOIOCTLCMD;
 122}
 123