2 * oxfw-scs1x.c - a part of driver for OXFW970/971 based devices
4 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5 * Copyright (c) 2015 Takashi Sakamoto <o-takashi@sakamocchi.jp>
7 * Licensed under the terms of the GNU General Public License, version 2.
12 #define HSS1394_ADDRESS 0xc007dedadadaULL
13 #define HSS1394_MAX_PACKET_SIZE 64
14 #define HSS1394_TAG_USER_DATA 0x00
15 #define HSS1394_TAG_CHANGE_ADDRESS 0xf1
18 struct fw_address_handler hss_handler
;
19 u8 input_escape_count
;
20 struct snd_rawmidi_substream
*input
;
22 /* For MIDI playback. */
23 struct snd_rawmidi_substream
*output
;
28 bool output_escape_high_nibble
;
29 struct work_struct work
;
30 wait_queue_head_t idle_wait
;
31 u8 buffer
[HSS1394_MAX_PACKET_SIZE
];
32 bool transaction_running
;
33 struct fw_transaction transaction
;
34 unsigned int transaction_bytes
;
36 struct fw_device
*fw_dev
;
39 static const u8 sysex_escape_prefix
[] = {
40 0xf0, /* SysEx begin */
41 0x00, 0x01, 0x60, /* Stanton DJ */
42 0x48, 0x53, 0x53, /* "HSS" */
45 static void midi_input_escaped_byte(struct snd_rawmidi_substream
*stream
,
50 nibbles
[0] = byte
>> 4;
51 nibbles
[1] = byte
& 0x0f;
52 snd_rawmidi_receive(stream
, nibbles
, 2);
55 static void midi_input_byte(struct fw_scs1x
*scs
,
56 struct snd_rawmidi_substream
*stream
, u8 byte
)
60 if (scs
->input_escape_count
> 0) {
61 midi_input_escaped_byte(stream
, byte
);
62 scs
->input_escape_count
--;
63 if (scs
->input_escape_count
== 0)
64 snd_rawmidi_receive(stream
, &eox
, sizeof(eox
));
65 } else if (byte
== 0xf9) {
66 snd_rawmidi_receive(stream
, sysex_escape_prefix
,
67 ARRAY_SIZE(sysex_escape_prefix
));
68 midi_input_escaped_byte(stream
, 0x00);
69 midi_input_escaped_byte(stream
, 0xf9);
70 scs
->input_escape_count
= 3;
72 snd_rawmidi_receive(stream
, &byte
, 1);
76 static void midi_input_packet(struct fw_scs1x
*scs
,
77 struct snd_rawmidi_substream
*stream
,
78 const u8
*data
, unsigned int bytes
)
83 if (data
[0] == HSS1394_TAG_USER_DATA
) {
84 for (i
= 1; i
< bytes
; ++i
)
85 midi_input_byte(scs
, stream
, data
[i
]);
87 snd_rawmidi_receive(stream
, sysex_escape_prefix
,
88 ARRAY_SIZE(sysex_escape_prefix
));
89 for (i
= 0; i
< bytes
; ++i
)
90 midi_input_escaped_byte(stream
, data
[i
]);
91 snd_rawmidi_receive(stream
, &eox
, sizeof(eox
));
95 static void handle_hss(struct fw_card
*card
, struct fw_request
*request
,
96 int tcode
, int destination
, int source
, int generation
,
97 unsigned long long offset
, void *data
, size_t length
,
100 struct fw_scs1x
*scs
= callback_data
;
101 struct snd_rawmidi_substream
*stream
;
104 if (offset
!= scs
->hss_handler
.offset
) {
105 rcode
= RCODE_ADDRESS_ERROR
;
108 if (tcode
!= TCODE_WRITE_QUADLET_REQUEST
&&
109 tcode
!= TCODE_WRITE_BLOCK_REQUEST
) {
110 rcode
= RCODE_TYPE_ERROR
;
115 stream
= ACCESS_ONCE(scs
->input
);
117 midi_input_packet(scs
, stream
, data
, length
);
120 rcode
= RCODE_COMPLETE
;
122 fw_send_response(card
, request
, rcode
);
125 static void scs_write_callback(struct fw_card
*card
, int rcode
,
126 void *data
, size_t length
, void *callback_data
)
128 struct fw_scs1x
*scs
= callback_data
;
130 if (!rcode_is_permanent_error(rcode
)) {
131 /* Don't retry for this data. */
132 if (rcode
== RCODE_COMPLETE
)
133 scs
->transaction_bytes
= 0;
138 scs
->transaction_running
= false;
139 schedule_work(&scs
->work
);
142 static bool is_valid_running_status(u8 status
)
144 return status
>= 0x80 && status
<= 0xef;
147 static bool is_one_byte_cmd(u8 status
)
149 return status
== 0xf6 ||
153 static bool is_two_bytes_cmd(u8 status
)
155 return (status
>= 0xc0 && status
<= 0xdf) ||
160 static bool is_three_bytes_cmd(u8 status
)
162 return (status
>= 0x80 && status
<= 0xbf) ||
163 (status
>= 0xe0 && status
<= 0xef) ||
167 static bool is_invalid_cmd(u8 status
)
169 return status
== 0xf4 ||
175 static void scs_output_work(struct work_struct
*work
)
177 struct fw_scs1x
*scs
= container_of(work
, struct fw_scs1x
, work
);
178 struct snd_rawmidi_substream
*stream
;
183 if (scs
->transaction_running
)
186 stream
= ACCESS_ONCE(scs
->output
);
187 if (!stream
|| scs
->error
) {
188 scs
->output_idle
= true;
189 wake_up(&scs
->idle_wait
);
193 if (scs
->transaction_bytes
> 0)
196 i
= scs
->output_bytes
;
198 if (snd_rawmidi_transmit(stream
, &byte
, 1) != 1) {
199 scs
->output_bytes
= i
;
200 scs
->output_idle
= true;
201 wake_up(&scs
->idle_wait
);
205 * Convert from real MIDI to what I think the device expects (no
206 * running status, one command per packet, unescaped SysExs).
208 if (scs
->output_escaped
&& byte
< 0x80) {
209 if (scs
->output_escape_high_nibble
) {
210 if (i
< HSS1394_MAX_PACKET_SIZE
) {
211 scs
->buffer
[i
] = byte
<< 4;
212 scs
->output_escape_high_nibble
= false;
215 scs
->buffer
[i
++] |= byte
& 0x0f;
216 scs
->output_escape_high_nibble
= true;
218 } else if (byte
< 0x80) {
220 if (!is_valid_running_status(
223 scs
->buffer
[0] = HSS1394_TAG_USER_DATA
;
224 scs
->buffer
[i
++] = scs
->output_status
;
226 scs
->buffer
[i
++] = byte
;
227 if ((i
== 3 && is_two_bytes_cmd(scs
->output_status
)) ||
228 (i
== 4 && is_three_bytes_cmd(scs
->output_status
)))
230 if (i
== 1 + ARRAY_SIZE(sysex_escape_prefix
) &&
231 !memcmp(scs
->buffer
+ 1, sysex_escape_prefix
,
232 ARRAY_SIZE(sysex_escape_prefix
))) {
233 scs
->output_escaped
= true;
234 scs
->output_escape_high_nibble
= true;
237 if (i
>= HSS1394_MAX_PACKET_SIZE
)
239 } else if (byte
== 0xf7) {
240 if (scs
->output_escaped
) {
241 if (i
>= 1 && scs
->output_escape_high_nibble
&&
243 HSS1394_TAG_CHANGE_ADDRESS
)
246 if (i
> 1 && scs
->output_status
== 0xf0) {
247 scs
->buffer
[i
++] = 0xf7;
252 scs
->output_escaped
= false;
253 } else if (!is_invalid_cmd(byte
) && byte
< 0xf8) {
255 scs
->buffer
[0] = HSS1394_TAG_USER_DATA
;
256 scs
->buffer
[i
++] = byte
;
257 scs
->output_status
= byte
;
258 scs
->output_escaped
= false;
259 if (is_one_byte_cmd(byte
))
263 scs
->output_bytes
= 1;
264 scs
->output_escaped
= false;
266 scs
->transaction_bytes
= i
;
268 scs
->transaction_running
= true;
269 generation
= scs
->fw_dev
->generation
;
270 smp_rmb(); /* node_id vs. generation */
271 fw_send_request(scs
->fw_dev
->card
, &scs
->transaction
,
272 TCODE_WRITE_BLOCK_REQUEST
, scs
->fw_dev
->node_id
,
273 generation
, scs
->fw_dev
->max_speed
, HSS1394_ADDRESS
,
274 scs
->buffer
, scs
->transaction_bytes
,
275 scs_write_callback
, scs
);
278 static int midi_capture_open(struct snd_rawmidi_substream
*stream
)
283 static int midi_capture_close(struct snd_rawmidi_substream
*stream
)
288 static void midi_capture_trigger(struct snd_rawmidi_substream
*stream
, int up
)
290 struct fw_scs1x
*scs
= stream
->rmidi
->private_data
;
293 scs
->input_escape_count
= 0;
294 ACCESS_ONCE(scs
->input
) = stream
;
296 ACCESS_ONCE(scs
->input
) = NULL
;
300 static struct snd_rawmidi_ops midi_capture_ops
= {
301 .open
= midi_capture_open
,
302 .close
= midi_capture_close
,
303 .trigger
= midi_capture_trigger
,
306 static int midi_playback_open(struct snd_rawmidi_substream
*stream
)
311 static int midi_playback_close(struct snd_rawmidi_substream
*stream
)
316 static void midi_playback_trigger(struct snd_rawmidi_substream
*stream
, int up
)
318 struct fw_scs1x
*scs
= stream
->rmidi
->private_data
;
321 scs
->output_status
= 0;
322 scs
->output_bytes
= 1;
323 scs
->output_escaped
= false;
324 scs
->output_idle
= false;
325 scs
->transaction_bytes
= 0;
328 ACCESS_ONCE(scs
->output
) = stream
;
329 schedule_work(&scs
->work
);
331 ACCESS_ONCE(scs
->output
) = NULL
;
334 static void midi_playback_drain(struct snd_rawmidi_substream
*stream
)
336 struct fw_scs1x
*scs
= stream
->rmidi
->private_data
;
338 wait_event(scs
->idle_wait
, scs
->output_idle
);
341 static struct snd_rawmidi_ops midi_playback_ops
= {
342 .open
= midi_playback_open
,
343 .close
= midi_playback_close
,
344 .trigger
= midi_playback_trigger
,
345 .drain
= midi_playback_drain
,
347 static int register_address(struct snd_oxfw
*oxfw
)
349 struct fw_scs1x
*scs
= oxfw
->spec
;
352 data
= cpu_to_be64(((u64
)HSS1394_TAG_CHANGE_ADDRESS
<< 56) |
353 scs
->hss_handler
.offset
);
354 return snd_fw_transaction(oxfw
->unit
, TCODE_WRITE_BLOCK_REQUEST
,
355 HSS1394_ADDRESS
, &data
, sizeof(data
), 0);
358 static void remove_scs1x(struct snd_rawmidi
*rmidi
)
360 struct fw_scs1x
*scs
= rmidi
->private_data
;
362 fw_core_remove_address_handler(&scs
->hss_handler
);
365 void snd_oxfw_scs1x_update(struct snd_oxfw
*oxfw
)
367 register_address(oxfw
);
370 int snd_oxfw_scs1x_add(struct snd_oxfw
*oxfw
)
372 struct snd_rawmidi
*rmidi
;
373 struct fw_scs1x
*scs
;
376 scs
= kzalloc(sizeof(struct fw_scs1x
), GFP_KERNEL
);
379 scs
->fw_dev
= fw_parent_device(oxfw
->unit
);
382 /* Allocate own handler for imcoming asynchronous transaction. */
383 scs
->hss_handler
.length
= HSS1394_MAX_PACKET_SIZE
;
384 scs
->hss_handler
.address_callback
= handle_hss
;
385 scs
->hss_handler
.callback_data
= scs
;
386 err
= fw_core_add_address_handler(&scs
->hss_handler
,
387 &fw_high_memory_region
);
391 err
= register_address(oxfw
);
395 /* Use unique name for backward compatibility to scs1x module. */
396 err
= snd_rawmidi_new(oxfw
->card
, "SCS.1x", 0, 1, 1, &rmidi
);
399 rmidi
->private_data
= scs
;
400 rmidi
->private_free
= remove_scs1x
;
402 snprintf(rmidi
->name
, sizeof(rmidi
->name
),
403 "%s MIDI", oxfw
->card
->shortname
);
405 rmidi
->info_flags
= SNDRV_RAWMIDI_INFO_INPUT
|
406 SNDRV_RAWMIDI_INFO_OUTPUT
|
407 SNDRV_RAWMIDI_INFO_DUPLEX
;
408 snd_rawmidi_set_ops(rmidi
, SNDRV_RAWMIDI_STREAM_INPUT
,
410 snd_rawmidi_set_ops(rmidi
, SNDRV_RAWMIDI_STREAM_OUTPUT
,
413 INIT_WORK(&scs
->work
, scs_output_work
);
414 init_waitqueue_head(&scs
->idle_wait
);
415 scs
->output_idle
= true;
419 fw_core_remove_address_handler(&scs
->hss_handler
);