cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ff-midi.c (3316B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * ff-midi.c - a part of driver for RME Fireface series
      4 *
      5 * Copyright (c) 2015-2017 Takashi Sakamoto
      6 */
      7
      8#include "ff.h"
      9
     10static int midi_capture_open(struct snd_rawmidi_substream *substream)
     11{
     12	/* Do nothing. */
     13	return 0;
     14}
     15
     16static int midi_playback_open(struct snd_rawmidi_substream *substream)
     17{
     18	struct snd_ff *ff = substream->rmidi->private_data;
     19
     20	/* Initialize internal status. */
     21	ff->on_sysex[substream->number] = 0;
     22	ff->rx_midi_error[substream->number] = false;
     23
     24	WRITE_ONCE(ff->rx_midi_substreams[substream->number], substream);
     25
     26	return 0;
     27}
     28
     29static int midi_capture_close(struct snd_rawmidi_substream *substream)
     30{
     31	/* Do nothing. */
     32	return 0;
     33}
     34
     35static int midi_playback_close(struct snd_rawmidi_substream *substream)
     36{
     37	struct snd_ff *ff = substream->rmidi->private_data;
     38
     39	cancel_work_sync(&ff->rx_midi_work[substream->number]);
     40	WRITE_ONCE(ff->rx_midi_substreams[substream->number], NULL);
     41
     42	return 0;
     43}
     44
     45static void midi_capture_trigger(struct snd_rawmidi_substream *substream,
     46				 int up)
     47{
     48	struct snd_ff *ff = substream->rmidi->private_data;
     49	unsigned long flags;
     50
     51	spin_lock_irqsave(&ff->lock, flags);
     52
     53	if (up)
     54		WRITE_ONCE(ff->tx_midi_substreams[substream->number],
     55			   substream);
     56	else
     57		WRITE_ONCE(ff->tx_midi_substreams[substream->number], NULL);
     58
     59	spin_unlock_irqrestore(&ff->lock, flags);
     60}
     61
     62static void midi_playback_trigger(struct snd_rawmidi_substream *substream,
     63				  int up)
     64{
     65	struct snd_ff *ff = substream->rmidi->private_data;
     66	unsigned long flags;
     67
     68	spin_lock_irqsave(&ff->lock, flags);
     69
     70	if (up || !ff->rx_midi_error[substream->number])
     71		schedule_work(&ff->rx_midi_work[substream->number]);
     72
     73	spin_unlock_irqrestore(&ff->lock, flags);
     74}
     75
     76static void set_midi_substream_names(struct snd_rawmidi_str *stream,
     77				     const char *const name)
     78{
     79	struct snd_rawmidi_substream *substream;
     80
     81	list_for_each_entry(substream, &stream->substreams, list) {
     82		snprintf(substream->name, sizeof(substream->name),
     83			 "%s MIDI %d", name, substream->number + 1);
     84	}
     85}
     86
     87int snd_ff_create_midi_devices(struct snd_ff *ff)
     88{
     89	static const struct snd_rawmidi_ops midi_capture_ops = {
     90		.open		= midi_capture_open,
     91		.close		= midi_capture_close,
     92		.trigger	= midi_capture_trigger,
     93	};
     94	static const struct snd_rawmidi_ops midi_playback_ops = {
     95		.open		= midi_playback_open,
     96		.close		= midi_playback_close,
     97		.trigger	= midi_playback_trigger,
     98	};
     99	struct snd_rawmidi *rmidi;
    100	struct snd_rawmidi_str *stream;
    101	int err;
    102
    103	err = snd_rawmidi_new(ff->card, ff->card->driver, 0,
    104			      ff->spec->midi_out_ports, ff->spec->midi_in_ports,
    105			      &rmidi);
    106	if (err < 0)
    107		return err;
    108
    109	snprintf(rmidi->name, sizeof(rmidi->name),
    110		 "%s MIDI", ff->card->shortname);
    111	rmidi->private_data = ff;
    112
    113	rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
    114	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
    115			    &midi_capture_ops);
    116	stream = &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT];
    117	set_midi_substream_names(stream, ff->card->shortname);
    118
    119	rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT;
    120	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
    121			    &midi_playback_ops);
    122	stream = &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT];
    123	set_midi_substream_names(stream, ff->card->shortname);
    124
    125	rmidi->info_flags |= SNDRV_RAWMIDI_INFO_DUPLEX;
    126
    127	return 0;
    128}