Skip to content

Commit ea46f79

Browse files
committed
ALSA: seq: Add snd_seq_expand_var_event_at() helper
Create a new variant of snd_seq_expand_var_event() for expanding the data starting from the given byte offset. It'll be used by the new UMP sequencer code later. Reviewed-by: Jaroslav Kysela <perex@perex.cz> Link: https://lore.kernel.org/r/20230523075358.9672-19-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent f80e6d6 commit ea46f79

File tree

2 files changed

+69
-19
lines changed

2 files changed

+69
-19
lines changed

include/sound/seq_kernel.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ int snd_seq_kernel_client_ctl(int client, unsigned int cmd, void *arg);
7070
typedef int (*snd_seq_dump_func_t)(void *ptr, void *buf, int count);
7171
int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char *buf,
7272
int in_kernel, int size_aligned);
73+
int snd_seq_expand_var_event_at(const struct snd_seq_event *event, int count,
74+
char *buf, int offset);
7375
int snd_seq_dump_var_event(const struct snd_seq_event *event,
7476
snd_seq_dump_func_t func, void *private_data);
7577

sound/core/seq/seq_memory.c

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,26 @@ static int get_var_len(const struct snd_seq_event *event)
6363
return event->data.ext.len & ~SNDRV_SEQ_EXT_MASK;
6464
}
6565

66-
int snd_seq_dump_var_event(const struct snd_seq_event *event,
67-
snd_seq_dump_func_t func, void *private_data)
66+
static int dump_var_event(const struct snd_seq_event *event,
67+
snd_seq_dump_func_t func, void *private_data,
68+
int offset, int maxlen)
6869
{
6970
int len, err;
7071
struct snd_seq_event_cell *cell;
7172

7273
len = get_var_len(event);
7374
if (len <= 0)
7475
return len;
76+
if (len <= offset)
77+
return 0;
78+
if (maxlen && len > offset + maxlen)
79+
len = offset + maxlen;
7580

7681
if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
7782
char buf[32];
7883
char __user *curptr = (char __force __user *)event->data.ext.ptr;
84+
curptr += offset;
85+
len -= offset;
7986
while (len > 0) {
8087
int size = sizeof(buf);
8188
if (len < size)
@@ -91,20 +98,35 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event,
9198
return 0;
9299
}
93100
if (!(event->data.ext.len & SNDRV_SEQ_EXT_CHAINED))
94-
return func(private_data, event->data.ext.ptr, len);
101+
return func(private_data, event->data.ext.ptr + offset,
102+
len - offset);
95103

96104
cell = (struct snd_seq_event_cell *)event->data.ext.ptr;
97105
for (; len > 0 && cell; cell = cell->next) {
98106
int size = sizeof(struct snd_seq_event);
107+
char *curptr = (char *)&cell->event;
108+
109+
if (offset >= size) {
110+
offset -= size;
111+
len -= size;
112+
continue;
113+
}
99114
if (len < size)
100115
size = len;
101-
err = func(private_data, &cell->event, size);
116+
err = func(private_data, curptr + offset, size - offset);
102117
if (err < 0)
103118
return err;
119+
offset = 0;
104120
len -= size;
105121
}
106122
return 0;
107123
}
124+
125+
int snd_seq_dump_var_event(const struct snd_seq_event *event,
126+
snd_seq_dump_func_t func, void *private_data)
127+
{
128+
return dump_var_event(event, func, private_data, 0, 0);
129+
}
108130
EXPORT_SYMBOL(snd_seq_dump_var_event);
109131

110132

@@ -132,11 +154,27 @@ static int seq_copy_in_user(void *ptr, void *src, int size)
132154
return 0;
133155
}
134156

157+
static int expand_var_event(const struct snd_seq_event *event,
158+
int offset, int size, char *buf, bool in_kernel)
159+
{
160+
if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
161+
if (! in_kernel)
162+
return -EINVAL;
163+
if (copy_from_user(buf,
164+
(char __force __user *)event->data.ext.ptr + offset,
165+
size))
166+
return -EFAULT;
167+
return 0;
168+
}
169+
return dump_var_event(event,
170+
in_kernel ? seq_copy_in_kernel : seq_copy_in_user,
171+
&buf, offset, size);
172+
}
173+
135174
int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char *buf,
136175
int in_kernel, int size_aligned)
137176
{
138-
int len, newlen;
139-
int err;
177+
int len, newlen, err;
140178

141179
len = get_var_len(event);
142180
if (len < 0)
@@ -146,25 +184,35 @@ int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char
146184
newlen = roundup(len, size_aligned);
147185
if (count < newlen)
148186
return -EAGAIN;
149-
150-
if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
151-
if (! in_kernel)
152-
return -EINVAL;
153-
if (copy_from_user(buf, (void __force __user *)event->data.ext.ptr, len))
154-
return -EFAULT;
155-
} else {
156-
err = snd_seq_dump_var_event(event,
157-
in_kernel ? seq_copy_in_kernel : seq_copy_in_user,
158-
&buf);
159-
if (err < 0)
160-
return err;
161-
}
187+
err = expand_var_event(event, 0, len, buf, in_kernel);
188+
if (err < 0)
189+
return err;
162190
if (len != newlen)
163191
memset(buf + len, 0, newlen - len);
164192
return newlen;
165193
}
166194
EXPORT_SYMBOL(snd_seq_expand_var_event);
167195

196+
int snd_seq_expand_var_event_at(const struct snd_seq_event *event, int count,
197+
char *buf, int offset)
198+
{
199+
int len, err;
200+
201+
len = get_var_len(event);
202+
if (len < 0)
203+
return len;
204+
if (len <= offset)
205+
return 0;
206+
len -= offset;
207+
if (len > count)
208+
len = count;
209+
err = expand_var_event(event, offset, count, buf, true);
210+
if (err < 0)
211+
return err;
212+
return len;
213+
}
214+
EXPORT_SYMBOL_GPL(snd_seq_expand_var_event_at);
215+
168216
/*
169217
* release this cell, free extended data if available
170218
*/

0 commit comments

Comments
 (0)