hc
2024-10-12 a5969cabbb4660eab42b6ef0412cbbd1200cf14d
kernel/sound/core/rawmidi.c
....@@ -1,22 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Abstract layer for MIDI v1.0 stream
34 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
4
- *
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License as published by
8
- * the Free Software Foundation; either version 2 of the License, or
9
- * (at your option) any later version.
10
- *
11
- * This program is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- * GNU General Public License for more details.
15
- *
16
- * You should have received a copy of the GNU General Public License
17
- * along with this program; if not, write to the Free Software
18
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
- *
205 */
216
227 #include <sound/core.h>
....@@ -50,7 +35,7 @@
5035 MODULE_PARM_DESC(amidi_map, "Raw MIDI device number assigned to 2nd OSS device.");
5136 #endif /* CONFIG_SND_OSSEMUL */
5237
53
-static int snd_rawmidi_free(struct snd_rawmidi *rawmidi);
38
+static int snd_rawmidi_free(struct snd_rawmidi *rmidi);
5439 static int snd_rawmidi_dev_free(struct snd_device *device);
5540 static int snd_rawmidi_dev_register(struct snd_device *device);
5641 static int snd_rawmidi_dev_disconnect(struct snd_device *device);
....@@ -64,6 +49,29 @@
6449 dev_warn(&(rmidi)->dev, fmt, ##args)
6550 #define rmidi_dbg(rmidi, fmt, args...) \
6651 dev_dbg(&(rmidi)->dev, fmt, ##args)
52
+
53
+struct snd_rawmidi_status32 {
54
+ s32 stream;
55
+ s32 tstamp_sec; /* Timestamp */
56
+ s32 tstamp_nsec;
57
+ u32 avail; /* available bytes */
58
+ u32 xruns; /* count of overruns since last status (in bytes) */
59
+ unsigned char reserved[16]; /* reserved for future use */
60
+};
61
+
62
+#define SNDRV_RAWMIDI_IOCTL_STATUS32 _IOWR('W', 0x20, struct snd_rawmidi_status32)
63
+
64
+struct snd_rawmidi_status64 {
65
+ int stream;
66
+ u8 rsvd[4]; /* alignment */
67
+ s64 tstamp_sec; /* Timestamp */
68
+ s64 tstamp_nsec;
69
+ size_t avail; /* available bytes */
70
+ size_t xruns; /* count of overruns since last status (in bytes) */
71
+ unsigned char reserved[16]; /* reserved for future use */
72
+};
73
+
74
+#define SNDRV_RAWMIDI_IOCTL_STATUS64 _IOWR('W', 0x20, struct snd_rawmidi_status64)
6775
6876 static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device)
6977 {
....@@ -262,7 +270,7 @@
262270 {
263271 struct snd_rawmidi_substream *substream;
264272 struct snd_rawmidi_str *s = &rmidi->streams[stream];
265
- static unsigned int info_flags[2] = {
273
+ static const unsigned int info_flags[2] = {
266274 [SNDRV_RAWMIDI_STREAM_OUTPUT] = SNDRV_RAWMIDI_INFO_OUTPUT,
267275 [SNDRV_RAWMIDI_STREAM_INPUT] = SNDRV_RAWMIDI_INFO_INPUT,
268276 };
....@@ -403,7 +411,7 @@
403411 if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK))
404412 return -EINVAL; /* invalid combination */
405413
406
- err = nonseekable_open(inode, file);
414
+ err = stream_open(inode, file);
407415 if (err < 0)
408416 return err;
409417
....@@ -718,7 +726,7 @@
718726 EXPORT_SYMBOL(snd_rawmidi_input_params);
719727
720728 static int snd_rawmidi_output_status(struct snd_rawmidi_substream *substream,
721
- struct snd_rawmidi_status *status)
729
+ struct snd_rawmidi_status64 *status)
722730 {
723731 struct snd_rawmidi_runtime *runtime = substream->runtime;
724732
....@@ -731,7 +739,7 @@
731739 }
732740
733741 static int snd_rawmidi_input_status(struct snd_rawmidi_substream *substream,
734
- struct snd_rawmidi_status *status)
742
+ struct snd_rawmidi_status64 *status)
735743 {
736744 struct snd_rawmidi_runtime *runtime = substream->runtime;
737745
....@@ -742,6 +750,80 @@
742750 status->xruns = runtime->xruns;
743751 runtime->xruns = 0;
744752 spin_unlock_irq(&runtime->lock);
753
+ return 0;
754
+}
755
+
756
+static int snd_rawmidi_ioctl_status32(struct snd_rawmidi_file *rfile,
757
+ struct snd_rawmidi_status32 __user *argp)
758
+{
759
+ int err = 0;
760
+ struct snd_rawmidi_status32 __user *status = argp;
761
+ struct snd_rawmidi_status32 status32;
762
+ struct snd_rawmidi_status64 status64;
763
+
764
+ if (copy_from_user(&status32, argp,
765
+ sizeof(struct snd_rawmidi_status32)))
766
+ return -EFAULT;
767
+
768
+ switch (status32.stream) {
769
+ case SNDRV_RAWMIDI_STREAM_OUTPUT:
770
+ if (rfile->output == NULL)
771
+ return -EINVAL;
772
+ err = snd_rawmidi_output_status(rfile->output, &status64);
773
+ break;
774
+ case SNDRV_RAWMIDI_STREAM_INPUT:
775
+ if (rfile->input == NULL)
776
+ return -EINVAL;
777
+ err = snd_rawmidi_input_status(rfile->input, &status64);
778
+ break;
779
+ default:
780
+ return -EINVAL;
781
+ }
782
+ if (err < 0)
783
+ return err;
784
+
785
+ status32 = (struct snd_rawmidi_status32) {
786
+ .stream = status64.stream,
787
+ .tstamp_sec = status64.tstamp_sec,
788
+ .tstamp_nsec = status64.tstamp_nsec,
789
+ .avail = status64.avail,
790
+ .xruns = status64.xruns,
791
+ };
792
+
793
+ if (copy_to_user(status, &status32, sizeof(*status)))
794
+ return -EFAULT;
795
+
796
+ return 0;
797
+}
798
+
799
+static int snd_rawmidi_ioctl_status64(struct snd_rawmidi_file *rfile,
800
+ struct snd_rawmidi_status64 __user *argp)
801
+{
802
+ int err = 0;
803
+ struct snd_rawmidi_status64 status;
804
+
805
+ if (copy_from_user(&status, argp, sizeof(struct snd_rawmidi_status64)))
806
+ return -EFAULT;
807
+
808
+ switch (status.stream) {
809
+ case SNDRV_RAWMIDI_STREAM_OUTPUT:
810
+ if (rfile->output == NULL)
811
+ return -EINVAL;
812
+ err = snd_rawmidi_output_status(rfile->output, &status);
813
+ break;
814
+ case SNDRV_RAWMIDI_STREAM_INPUT:
815
+ if (rfile->input == NULL)
816
+ return -EINVAL;
817
+ err = snd_rawmidi_input_status(rfile->input, &status);
818
+ break;
819
+ default:
820
+ return -EINVAL;
821
+ }
822
+ if (err < 0)
823
+ return err;
824
+ if (copy_to_user(argp, &status,
825
+ sizeof(struct snd_rawmidi_status64)))
826
+ return -EFAULT;
745827 return 0;
746828 }
747829
....@@ -791,33 +873,10 @@
791873 return -EINVAL;
792874 }
793875 }
794
- case SNDRV_RAWMIDI_IOCTL_STATUS:
795
- {
796
- int err = 0;
797
- struct snd_rawmidi_status status;
798
-
799
- if (copy_from_user(&status, argp, sizeof(struct snd_rawmidi_status)))
800
- return -EFAULT;
801
- switch (status.stream) {
802
- case SNDRV_RAWMIDI_STREAM_OUTPUT:
803
- if (rfile->output == NULL)
804
- return -EINVAL;
805
- err = snd_rawmidi_output_status(rfile->output, &status);
806
- break;
807
- case SNDRV_RAWMIDI_STREAM_INPUT:
808
- if (rfile->input == NULL)
809
- return -EINVAL;
810
- err = snd_rawmidi_input_status(rfile->input, &status);
811
- break;
812
- default:
813
- return -EINVAL;
814
- }
815
- if (err < 0)
816
- return err;
817
- if (copy_to_user(argp, &status, sizeof(struct snd_rawmidi_status)))
818
- return -EFAULT;
819
- return 0;
820
- }
876
+ case SNDRV_RAWMIDI_IOCTL_STATUS32:
877
+ return snd_rawmidi_ioctl_status32(rfile, argp);
878
+ case SNDRV_RAWMIDI_IOCTL_STATUS64:
879
+ return snd_rawmidi_ioctl_status64(rfile, argp);
821880 case SNDRV_RAWMIDI_IOCTL_DROP:
822881 {
823882 int val;
....@@ -1271,6 +1330,28 @@
12711330 }
12721331 EXPORT_SYMBOL(snd_rawmidi_transmit);
12731332
1333
+/**
1334
+ * snd_rawmidi_proceed - Discard the all pending bytes and proceed
1335
+ * @substream: rawmidi substream
1336
+ *
1337
+ * Return: the number of discarded bytes
1338
+ */
1339
+int snd_rawmidi_proceed(struct snd_rawmidi_substream *substream)
1340
+{
1341
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
1342
+ unsigned long flags;
1343
+ int count = 0;
1344
+
1345
+ spin_lock_irqsave(&runtime->lock, flags);
1346
+ if (runtime->avail < runtime->buffer_size) {
1347
+ count = runtime->buffer_size - runtime->avail;
1348
+ __snd_rawmidi_transmit_ack(substream, count);
1349
+ }
1350
+ spin_unlock_irqrestore(&runtime->lock, flags);
1351
+ return count;
1352
+}
1353
+EXPORT_SYMBOL(snd_rawmidi_proceed);
1354
+
12741355 static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
12751356 const unsigned char __user *userbuf,
12761357 const unsigned char *kernelbuf,
....@@ -1584,7 +1665,7 @@
15841665 {
15851666 struct snd_rawmidi *rmidi;
15861667 int err;
1587
- static struct snd_device_ops ops = {
1668
+ static const struct snd_device_ops ops = {
15881669 .dev_free = snd_rawmidi_dev_free,
15891670 .dev_register = snd_rawmidi_dev_register,
15901671 .dev_disconnect = snd_rawmidi_dev_disconnect,
....@@ -1655,10 +1736,8 @@
16551736
16561737 snd_info_free_entry(rmidi->proc_entry);
16571738 rmidi->proc_entry = NULL;
1658
- mutex_lock(&register_mutex);
16591739 if (rmidi->ops && rmidi->ops->dev_unregister)
16601740 rmidi->ops->dev_unregister(rmidi);
1661
- mutex_unlock(&register_mutex);
16621741
16631742 snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]);
16641743 snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]);