summaryrefslogtreecommitdiffstats
path: root/sound/firewire/lib.h
blob: c3768cd494a5f3fe3bb9059bd8e588c73b806c86 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#ifndef SOUND_FIREWIRE_LIB_H_INCLUDED
#define SOUND_FIREWIRE_LIB_H_INCLUDED

#include <linux/firewire-constants.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <sound/rawmidi.h>

struct fw_unit;

#define FW_GENERATION_MASK	0x00ff
#define FW_FIXED_GENERATION	0x0100
#define FW_QUIET		0x0200

int snd_fw_transaction(struct fw_unit *unit, int tcode,
		       u64 offset, void *buffer, size_t length,
		       unsigned int flags);

/* returns true if retrying the transaction would not make sense */
static inline bool rcode_is_permanent_error(int rcode)
{
	return rcode == RCODE_TYPE_ERROR || rcode == RCODE_ADDRESS_ERROR;
}

void snd_fw_schedule_registration(struct fw_unit *unit,
				  struct delayed_work *dwork);

struct snd_fw_async_midi_port;
typedef int (*snd_fw_async_midi_port_fill)(
				struct snd_rawmidi_substream *substream,
				u8 *buf);

struct snd_fw_async_midi_port {
	struct fw_device *parent;
	struct work_struct work;
	bool idling;
	ktime_t next_ktime;
	bool error;

	u64 addr;
	struct fw_transaction transaction;

	u8 *buf;
	unsigned int len;

	struct snd_rawmidi_substream *substream;
	snd_fw_async_midi_port_fill fill;
	int consume_bytes;
};

int snd_fw_async_midi_port_init(struct snd_fw_async_midi_port *port,
		struct fw_unit *unit, u64 addr, unsigned int len,
		snd_fw_async_midi_port_fill fill);
void snd_fw_async_midi_port_destroy(struct snd_fw_async_midi_port *port);

/**
 * snd_fw_async_midi_port_run - run transactions for the async MIDI port
 * @port: the asynchronous MIDI port
 * @substream: the MIDI substream
 */
static inline void
snd_fw_async_midi_port_run(struct snd_fw_async_midi_port *port,
			   struct snd_rawmidi_substream *substream)
{
	if (!port->error) {
		port->substream = substream;
		schedule_work(&port->work);
	}
}

/**
 * snd_fw_async_midi_port_finish - finish the asynchronous MIDI port
 * @port: the asynchronous MIDI port
 */
static inline void
snd_fw_async_midi_port_finish(struct snd_fw_async_midi_port *port)
{
	port->substream = NULL;
	port->error = false;
}

#endif