Skip to content

Commit 6b41e64

Browse files
committed
ALSA: ump: Redirect rawmidi substream access via own helpers
This is a code refactoring for abstracting the rawmidi access to the UMP's own helpers. It's a preliminary work for the later code refactoring of the UMP layer. Until now, we access to the rawmidi substream directly from the driver via rawmidi access helpers, but after this change, the driver is supposed to access via the newly introduced snd_ump_ops and receive/transmit via snd_ump_receive() and snd_ump_transmit() helpers. As of this commit, those are merely wrappers for the rawmidi substream, and no much function change is seen here. Reviewed-by: Jaroslav Kysela <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent d9c9987 commit 6b41e64

File tree

3 files changed

+149
-47
lines changed

3 files changed

+149
-47
lines changed

include/sound/ump.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,30 @@
99

1010
struct snd_ump_endpoint;
1111
struct snd_ump_block;
12+
struct snd_ump_ops;
1213

1314
struct snd_ump_endpoint {
1415
struct snd_rawmidi core; /* raw UMP access */
1516

1617
struct snd_ump_endpoint_info info;
1718

19+
const struct snd_ump_ops *ops; /* UMP ops set by the driver */
20+
struct snd_rawmidi_substream *substreams[2]; /* opened substreams */
21+
1822
void *private_data;
1923
void (*private_free)(struct snd_ump_endpoint *ump);
2024

2125
struct list_head block_list; /* list of snd_ump_block objects */
2226
};
2327

28+
/* ops filled by UMP drivers */
29+
struct snd_ump_ops {
30+
int (*open)(struct snd_ump_endpoint *ump, int dir);
31+
void (*close)(struct snd_ump_endpoint *ump, int dir);
32+
void (*trigger)(struct snd_ump_endpoint *ump, int dir, int up);
33+
void (*drain)(struct snd_ump_endpoint *ump, int dir);
34+
};
35+
2436
struct snd_ump_block {
2537
struct snd_ump_block_info info;
2638
struct snd_ump_endpoint *ump;
@@ -39,6 +51,8 @@ int snd_ump_endpoint_new(struct snd_card *card, char *id, int device,
3951
int snd_ump_block_new(struct snd_ump_endpoint *ump, unsigned int blk,
4052
unsigned int direction, unsigned int first_group,
4153
unsigned int num_groups, struct snd_ump_block **blk_ret);
54+
int snd_ump_receive(struct snd_ump_endpoint *ump, const u32 *buffer, int count);
55+
int snd_ump_transmit(struct snd_ump_endpoint *ump, u32 *buffer, int count);
4256

4357
/*
4458
* Some definitions for UMP

sound/core/ump.c

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ static long snd_ump_ioctl(struct snd_rawmidi *rmidi, unsigned int cmd,
2323
void __user *argp);
2424
static void snd_ump_proc_read(struct snd_info_entry *entry,
2525
struct snd_info_buffer *buffer);
26+
static int snd_ump_rawmidi_open(struct snd_rawmidi_substream *substream);
27+
static int snd_ump_rawmidi_close(struct snd_rawmidi_substream *substream);
28+
static void snd_ump_rawmidi_trigger(struct snd_rawmidi_substream *substream,
29+
int up);
30+
static void snd_ump_rawmidi_drain(struct snd_rawmidi_substream *substream);
2631

2732
static const struct snd_rawmidi_global_ops snd_ump_rawmidi_ops = {
2833
.dev_register = snd_ump_dev_register,
@@ -31,6 +36,19 @@ static const struct snd_rawmidi_global_ops snd_ump_rawmidi_ops = {
3136
.proc_read = snd_ump_proc_read,
3237
};
3338

39+
static const struct snd_rawmidi_ops snd_ump_rawmidi_input_ops = {
40+
.open = snd_ump_rawmidi_open,
41+
.close = snd_ump_rawmidi_close,
42+
.trigger = snd_ump_rawmidi_trigger,
43+
};
44+
45+
static const struct snd_rawmidi_ops snd_ump_rawmidi_output_ops = {
46+
.open = snd_ump_rawmidi_open,
47+
.close = snd_ump_rawmidi_close,
48+
.trigger = snd_ump_rawmidi_trigger,
49+
.drain = snd_ump_rawmidi_drain,
50+
};
51+
3452
static void snd_ump_endpoint_free(struct snd_rawmidi *rmidi)
3553
{
3654
struct snd_ump_endpoint *ump = rawmidi_to_ump(rmidi);
@@ -104,6 +122,12 @@ int snd_ump_endpoint_new(struct snd_card *card, char *id, int device,
104122

105123
ump->core.private_free = snd_ump_endpoint_free;
106124
ump->core.ops = &snd_ump_rawmidi_ops;
125+
if (input)
126+
snd_rawmidi_set_ops(&ump->core, SNDRV_RAWMIDI_STREAM_INPUT,
127+
&snd_ump_rawmidi_input_ops);
128+
if (output)
129+
snd_rawmidi_set_ops(&ump->core, SNDRV_RAWMIDI_STREAM_OUTPUT,
130+
&snd_ump_rawmidi_output_ops);
107131

108132
ump_dbg(ump, "Created a UMP EP #%d (%s)\n", device, id);
109133
*ump_ret = ump;
@@ -137,6 +161,93 @@ snd_ump_get_block(struct snd_ump_endpoint *ump, unsigned char id)
137161
return NULL;
138162
}
139163

164+
/*
165+
* rawmidi ops for UMP endpoint
166+
*/
167+
static int snd_ump_rawmidi_open(struct snd_rawmidi_substream *substream)
168+
{
169+
struct snd_ump_endpoint *ump = rawmidi_to_ump(substream->rmidi);
170+
int dir = substream->stream;
171+
int err;
172+
173+
if (ump->substreams[dir])
174+
return -EBUSY;
175+
err = ump->ops->open(ump, dir);
176+
if (err < 0)
177+
return err;
178+
ump->substreams[dir] = substream;
179+
return 0;
180+
}
181+
182+
static int snd_ump_rawmidi_close(struct snd_rawmidi_substream *substream)
183+
{
184+
struct snd_ump_endpoint *ump = rawmidi_to_ump(substream->rmidi);
185+
int dir = substream->stream;
186+
187+
ump->substreams[dir] = NULL;
188+
ump->ops->close(ump, dir);
189+
return 0;
190+
}
191+
192+
static void snd_ump_rawmidi_trigger(struct snd_rawmidi_substream *substream,
193+
int up)
194+
{
195+
struct snd_ump_endpoint *ump = rawmidi_to_ump(substream->rmidi);
196+
int dir = substream->stream;
197+
198+
ump->ops->trigger(ump, dir, up);
199+
}
200+
201+
static void snd_ump_rawmidi_drain(struct snd_rawmidi_substream *substream)
202+
{
203+
struct snd_ump_endpoint *ump = rawmidi_to_ump(substream->rmidi);
204+
205+
if (ump->ops->drain)
206+
ump->ops->drain(ump, SNDRV_RAWMIDI_STREAM_OUTPUT);
207+
}
208+
209+
/**
210+
* snd_ump_receive - transfer UMP packets from the device
211+
* @ump: the UMP endpoint
212+
* @buffer: the buffer pointer to transfer
213+
* @count: byte size to transfer
214+
*
215+
* Called from the driver to submit the received UMP packets from the device
216+
* to user-space. It's essentially a wrapper of rawmidi_receive().
217+
* The data to receive is in CPU-native endianness.
218+
*/
219+
int snd_ump_receive(struct snd_ump_endpoint *ump, const u32 *buffer, int count)
220+
{
221+
struct snd_rawmidi_substream *substream =
222+
ump->substreams[SNDRV_RAWMIDI_STREAM_INPUT];
223+
224+
if (!substream)
225+
return 0;
226+
return snd_rawmidi_receive(substream, (const char *)buffer, count);
227+
}
228+
EXPORT_SYMBOL_GPL(snd_ump_receive);
229+
230+
/**
231+
* snd_ump_transmit - transmit UMP packets
232+
* @ump: the UMP endpoint
233+
* @buffer: the buffer pointer to transfer
234+
* @count: byte size to transfer
235+
*
236+
* Called from the driver to obtain the UMP packets from user-space to the
237+
* device. It's essentially a wrapper of rawmidi_transmit().
238+
* The data to transmit is in CPU-native endianness.
239+
*/
240+
int snd_ump_transmit(struct snd_ump_endpoint *ump, u32 *buffer, int count)
241+
{
242+
struct snd_rawmidi_substream *substream =
243+
ump->substreams[SNDRV_RAWMIDI_STREAM_OUTPUT];
244+
245+
if (!substream)
246+
return -ENODEV;
247+
return snd_rawmidi_transmit(substream, (char *)buffer, count);
248+
}
249+
EXPORT_SYMBOL_GPL(snd_ump_transmit);
250+
140251
/**
141252
* snd_ump_block_new - Create a UMP block
142253
* @ump: UMP object

sound/usb/midi2.c

Lines changed: 24 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ struct snd_usb_midi2_endpoint {
5252
struct usb_device *dev;
5353
const struct usb_ms20_endpoint_descriptor *ms_ep; /* reference to EP descriptor */
5454
struct snd_usb_midi2_endpoint *pair; /* bidirectional pair EP */
55-
struct snd_usb_midi2_ump *rmidi; /* assigned UMP EP */
55+
struct snd_usb_midi2_ump *rmidi; /* assigned UMP EP pair */
56+
struct snd_ump_endpoint *ump; /* assigned UMP EP */
5657
int direction; /* direction (STR_IN/OUT) */
5758
unsigned int endpoint; /* EP number */
5859
unsigned int pipe; /* URB pipe */
@@ -133,12 +134,8 @@ static int prepare_output_urb(struct snd_usb_midi2_endpoint *ep,
133134
{
134135
int count;
135136

136-
if (ep->substream)
137-
count = snd_rawmidi_transmit(ep->substream,
138-
urb->transfer_buffer,
139-
ep->packets);
140-
else
141-
count = -ENODEV;
137+
count = snd_ump_transmit(ep->ump, urb->transfer_buffer,
138+
ep->packets);
142139
if (count < 0) {
143140
dev_dbg(&ep->dev->dev, "rawmidi transmit error %d\n", count);
144141
return count;
@@ -197,9 +194,9 @@ static void input_urb_complete(struct urb *urb)
197194
len &= ~3; /* align UMP */
198195
if (len > ep->packets)
199196
len = ep->packets;
200-
if (len > 0 && ep->substream) {
197+
if (len > 0) {
201198
le32_to_cpu_array((u32 *)urb->transfer_buffer, len >> 2);
202-
snd_rawmidi_receive(ep->substream, urb->transfer_buffer, len);
199+
snd_ump_receive(ep->ump, (u32 *)urb->transfer_buffer, len);
203200
}
204201
dequeue:
205202
set_bit(ctx->index, &ep->urb_free);
@@ -330,68 +327,58 @@ static int alloc_midi_urbs(struct snd_usb_midi2_endpoint *ep)
330327
}
331328

332329
static struct snd_usb_midi2_endpoint *
333-
substream_to_endpoint(struct snd_rawmidi_substream *substream)
330+
ump_to_endpoint(struct snd_ump_endpoint *ump, int dir)
334331
{
335-
struct snd_ump_endpoint *ump = rawmidi_to_ump(substream->rmidi);
336332
struct snd_usb_midi2_ump *rmidi = ump->private_data;
337333

338-
return rmidi->eps[substream->stream];
334+
return rmidi->eps[dir];
339335
}
340336

341-
/* rawmidi open callback */
342-
static int snd_usb_midi_v2_open(struct snd_rawmidi_substream *substream)
337+
/* ump open callback */
338+
static int snd_usb_midi_v2_open(struct snd_ump_endpoint *ump, int dir)
343339
{
344-
struct snd_usb_midi2_endpoint *ep = substream_to_endpoint(substream);
340+
struct snd_usb_midi2_endpoint *ep = ump_to_endpoint(ump, dir);
345341
int err = 0;
346342

347343
if (!ep || !ep->endpoint)
348344
return -ENODEV;
349345
if (ep->disconnected)
350346
return -EIO;
351-
if (ep->substream)
352-
return -EBUSY;
353347
if (ep->direction == STR_OUT) {
354348
err = alloc_midi_urbs(ep);
355349
if (err)
356350
return err;
357351
}
358-
spin_lock_irq(&ep->lock);
359-
ep->substream = substream;
360-
spin_unlock_irq(&ep->lock);
361352
return 0;
362353
}
363354

364-
/* rawmidi close callback */
365-
static int snd_usb_midi_v2_close(struct snd_rawmidi_substream *substream)
355+
/* ump close callback */
356+
static void snd_usb_midi_v2_close(struct snd_ump_endpoint *ump, int dir)
366357
{
367-
struct snd_usb_midi2_endpoint *ep = substream_to_endpoint(substream);
358+
struct snd_usb_midi2_endpoint *ep = ump_to_endpoint(ump, dir);
368359

369-
spin_lock_irq(&ep->lock);
370-
ep->substream = NULL;
371-
spin_unlock_irq(&ep->lock);
372360
if (ep->direction == STR_OUT) {
373361
kill_midi_urbs(ep, false);
374362
drain_urb_queue(ep);
375363
free_midi_urbs(ep);
376364
}
377-
return 0;
378365
}
379366

380-
/* rawmidi trigger callback */
381-
static void snd_usb_midi_v2_trigger(struct snd_rawmidi_substream *substream,
367+
/* ump trigger callback */
368+
static void snd_usb_midi_v2_trigger(struct snd_ump_endpoint *ump, int dir,
382369
int up)
383370
{
384-
struct snd_usb_midi2_endpoint *ep = substream_to_endpoint(substream);
371+
struct snd_usb_midi2_endpoint *ep = ump_to_endpoint(ump, dir);
385372

386373
atomic_set(&ep->running, up);
387374
if (up && ep->direction == STR_OUT && !ep->disconnected)
388375
submit_io_urbs(ep);
389376
}
390377

391-
/* rawmidi drain callback */
392-
static void snd_usb_midi_v2_drain(struct snd_rawmidi_substream *substream)
378+
/* ump drain callback */
379+
static void snd_usb_midi_v2_drain(struct snd_ump_endpoint *ump, int dir)
393380
{
394-
struct snd_usb_midi2_endpoint *ep = substream_to_endpoint(substream);
381+
struct snd_usb_midi2_endpoint *ep = ump_to_endpoint(ump, dir);
395382

396383
drain_urb_queue(ep);
397384
}
@@ -426,19 +413,13 @@ static int start_input_streams(struct snd_usb_midi2_interface *umidi)
426413
return err;
427414
}
428415

429-
static const struct snd_rawmidi_ops output_ops = {
416+
static const struct snd_ump_ops snd_usb_midi_v2_ump_ops = {
430417
.open = snd_usb_midi_v2_open,
431418
.close = snd_usb_midi_v2_close,
432419
.trigger = snd_usb_midi_v2_trigger,
433420
.drain = snd_usb_midi_v2_drain,
434421
};
435422

436-
static const struct snd_rawmidi_ops input_ops = {
437-
.open = snd_usb_midi_v2_open,
438-
.close = snd_usb_midi_v2_close,
439-
.trigger = snd_usb_midi_v2_trigger,
440-
};
441-
442423
/* create a USB MIDI 2.0 endpoint object */
443424
static int create_midi2_endpoint(struct snd_usb_midi2_interface *umidi,
444425
struct usb_host_endpoint *hostep,
@@ -729,23 +710,19 @@ static int create_midi2_ump(struct snd_usb_midi2_interface *umidi,
729710
umidi->chip->num_rawmidis++;
730711

731712
ump->private_data = rmidi;
732-
733-
if (input)
734-
snd_rawmidi_set_ops(&ump->core, SNDRV_RAWMIDI_STREAM_INPUT,
735-
&input_ops);
736-
if (output)
737-
snd_rawmidi_set_ops(&ump->core, SNDRV_RAWMIDI_STREAM_OUTPUT,
738-
&output_ops);
713+
ump->ops = &snd_usb_midi_v2_ump_ops;
739714

740715
rmidi->eps[STR_IN] = ep_in;
741716
rmidi->eps[STR_OUT] = ep_out;
742717
if (ep_in) {
743718
ep_in->pair = ep_out;
744719
ep_in->rmidi = rmidi;
720+
ep_in->ump = ump;
745721
}
746722
if (ep_out) {
747723
ep_out->pair = ep_in;
748724
ep_out->rmidi = rmidi;
725+
ep_out->ump = ump;
749726
}
750727

751728
list_add_tail(&rmidi->list, &umidi->rawmidi_list);

0 commit comments

Comments
 (0)