1 // SPDX-License-Identifier: GPL-2.0-only
3 * oxfw-scs1x.c - a part of driver for OXFW970/971 based devices
5 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
6 * Copyright (c) 2015 Takashi Sakamoto <o-takashi@sakamocchi.jp>
11 #define HSS1394_ADDRESS 0xc007dedadadaULL
12 #define HSS1394_MAX_PACKET_SIZE 64
13 #define HSS1394_TAG_USER_DATA 0x00
14 #define HSS1394_TAG_CHANGE_ADDRESS 0xf1
17 struct fw_address_handler hss_handler
;
18 u8 input_escape_count
;
19 struct snd_rawmidi_substream
*input
;
21 /* For MIDI playback. */
22 struct snd_rawmidi_substream
*output
;
27 bool output_escape_high_nibble
;
28 struct work_struct work
;
29 wait_queue_head_t idle_wait
;
30 u8 buffer
[HSS1394_MAX_PACKET_SIZE
];
31 bool transaction_running
;
32 struct fw_transaction transaction
;
33 unsigned int transaction_bytes
;
35 struct fw_device
*fw_dev
;
38 static const u8 sysex_escape_prefix
[] = {
39 0xf0, /* SysEx begin */
40 0x00, 0x01, 0x60, /* Stanton DJ */
41 0x48, 0x53, 0x53, /* "HSS" */
44 static void midi_input_escaped_byte(struct snd_rawmidi_substream
*stream
,
49 nibbles
[0] = byte
>> 4;
50 nibbles
[1] = byte
& 0x0f;
51 snd_rawmidi_receive(stream
, nibbles
, 2);
54 static void midi_input_byte(struct fw_scs1x
*scs
,
55 struct snd_rawmidi_substream
*stream
, u8 byte
)
59 if (scs
->input_escape_count
> 0) {
60 midi_input_escaped_byte(stream
, byte
);
61 scs
->input_escape_count
--;
62 if (scs
->input_escape_count
== 0)
63 snd_rawmidi_receive(stream
, &eox
, sizeof(eox
));
64 } else if (byte
== 0xf9) {
65 snd_rawmidi_receive(stream
, sysex_escape_prefix
,
66 ARRAY_SIZE(sysex_escape_prefix
));
67 midi_input_escaped_byte(stream
, 0x00);
68 midi_input_escaped_byte(stream
, 0xf9);
69 scs
->input_escape_count
= 3;
71 snd_rawmidi_receive(stream
, &byte
, 1);
75 static void midi_input_packet(struct fw_scs1x
*scs
,
76 struct snd_rawmidi_substream
*stream
,
77 const u8
*data
, unsigned int bytes
)
82 if (data
[0] == HSS1394_TAG_USER_DATA
) {
83 for (i
= 1; i
< bytes
; ++i
)
84 midi_input_byte(scs
, stream
, data
[i
]);
86 snd_rawmidi_receive(stream
, sysex_escape_prefix
,
87 ARRAY_SIZE(sysex_escape_prefix
));
88 for (i
= 0; i
< bytes
; ++i
)
89 midi_input_escaped_byte(stream
, data
[i
]);
90 snd_rawmidi_receive(stream
, &eox
, sizeof(eox
));
94 static void handle_hss(struct fw_card
*card
, struct fw_request
*request
,
95 int tcode
, int destination
, int source
, int generation
,
96 unsigned long long offset
, void *data
, size_t length
,
99 struct fw_scs1x
*scs
= callback_data
;
100 struct snd_rawmidi_substream
*stream
;
103 if (offset
!= scs
->hss_handler
.offset
) {
104 rcode
= RCODE_ADDRESS_ERROR
;
107 if (tcode
!= TCODE_WRITE_QUADLET_REQUEST
&&
108 tcode
!= TCODE_WRITE_BLOCK_REQUEST
) {
109 rcode
= RCODE_TYPE_ERROR
;
114 stream
= READ_ONCE(scs
->input
);
116 midi_input_packet(scs
, stream
, data
, length
);
119 rcode
= RCODE_COMPLETE
;
121 fw_send_response(card
, request
, rcode
);
124 static void scs_write_callback(struct fw_card
*card
, int rcode
,
125 void *data
, size_t length
, void *callback_data
)
127 struct fw_scs1x
*scs
= callback_data
;
129 if (!rcode_is_permanent_error(rcode
)) {
130 /* Don't retry for this data. */
131 if (rcode
== RCODE_COMPLETE
)
132 scs
->transaction_bytes
= 0;
137 scs
->transaction_running
= false;
138 schedule_work(&scs
->work
);
141 static bool is_valid_running_status(u8 status
)
143 return status
>= 0x80 && status
<= 0xef;
146 static bool is_one_byte_cmd(u8 status
)
148 return status
== 0xf6 ||
152 static bool is_two_bytes_cmd(u8 status
)
154 return (status
>= 0xc0 && status
<= 0xdf) ||
159 static bool is_three_bytes_cmd(u8 status
)
161 return (status
>= 0x80 && status
<= 0xbf) ||
162 (status
>= 0xe0 && status
<= 0xef) ||
166 static bool is_invalid_cmd(u8 status
)
168 return status
== 0xf4 ||
174 static void scs_output_work(struct work_struct
*work
)
176 struct fw_scs1x
*scs
= container_of(work
, struct fw_scs1x
, work
);
177 struct snd_rawmidi_substream
*stream
;
182 if (scs
->transaction_running
)
185 stream
= READ_ONCE(scs
->output
);
186 if (!stream
|| scs
->error
) {
187 scs
->output_idle
= true;
188 wake_up(&scs
->idle_wait
);
192 if (scs
->transaction_bytes
> 0)
195 i
= scs
->output_bytes
;
197 if (snd_rawmidi_transmit(stream
, &byte
, 1) != 1) {
198 scs
->output_bytes
= i
;
199 scs
->output_idle
= true;
200 wake_up(&scs
->idle_wait
);
204 * Convert from real MIDI to what I think the device expects (no
205 * running status, one command per packet, unescaped SysExs).
207 if (scs
->output_escaped
&& byte
< 0x80) {
208 if (scs
->output_escape_high_nibble
) {
209 if (i
< HSS1394_MAX_PACKET_SIZE
) {
210 scs
->buffer
[i
] = byte
<< 4;
211 scs
->output_escape_high_nibble
= false;
214 scs
->buffer
[i
++] |= byte
& 0x0f;
215 scs
->output_escape_high_nibble
= true;
217 } else if (byte
< 0x80) {
219 if (!is_valid_running_status(
222 scs
->buffer
[0] = HSS1394_TAG_USER_DATA
;
223 scs
->buffer
[i
++] = scs
->output_status
;
225 scs
->buffer
[i
++] = byte
;
226 if ((i
== 3 && is_two_bytes_cmd(scs
->output_status
)) ||
227 (i
== 4 && is_three_bytes_cmd(scs
->output_status
)))
229 if (i
== 1 + ARRAY_SIZE(sysex_escape_prefix
) &&
230 !memcmp(scs
->buffer
+ 1, sysex_escape_prefix
,
231 ARRAY_SIZE(sysex_escape_prefix
))) {
232 scs
->output_escaped
= true;
233 scs
->output_escape_high_nibble
= true;
236 if (i
>= HSS1394_MAX_PACKET_SIZE
)
238 } else if (byte
== 0xf7) {
239 if (scs
->output_escaped
) {
240 if (i
>= 1 && scs
->output_escape_high_nibble
&&
242 HSS1394_TAG_CHANGE_ADDRESS
)
245 if (i
> 1 && scs
->output_status
== 0xf0) {
246 scs
->buffer
[i
++] = 0xf7;
251 scs
->output_escaped
= false;
252 } else if (!is_invalid_cmd(byte
) && byte
< 0xf8) {
254 scs
->buffer
[0] = HSS1394_TAG_USER_DATA
;
255 scs
->buffer
[i
++] = byte
;
256 scs
->output_status
= byte
;
257 scs
->output_escaped
= false;
258 if (is_one_byte_cmd(byte
))
262 scs
->output_bytes
= 1;
263 scs
->output_escaped
= false;
265 scs
->transaction_bytes
= i
;
267 scs
->transaction_running
= true;
268 generation
= scs
->fw_dev
->generation
;
269 smp_rmb(); /* node_id vs. generation */
270 fw_send_request(scs
->fw_dev
->card
, &scs
->transaction
,
271 TCODE_WRITE_BLOCK_REQUEST
, scs
->fw_dev
->node_id
,
272 generation
, scs
->fw_dev
->max_speed
, HSS1394_ADDRESS
,
273 scs
->buffer
, scs
->transaction_bytes
,
274 scs_write_callback
, scs
);
277 static int midi_capture_open(struct snd_rawmidi_substream
*stream
)
282 static int midi_capture_close(struct snd_rawmidi_substream
*stream
)
287 static void midi_capture_trigger(struct snd_rawmidi_substream
*stream
, int up
)
289 struct fw_scs1x
*scs
= stream
->rmidi
->private_data
;
292 scs
->input_escape_count
= 0;
293 WRITE_ONCE(scs
->input
, stream
);
295 WRITE_ONCE(scs
->input
, NULL
);
299 static int midi_playback_open(struct snd_rawmidi_substream
*stream
)
304 static int midi_playback_close(struct snd_rawmidi_substream
*stream
)
309 static void midi_playback_trigger(struct snd_rawmidi_substream
*stream
, int up
)
311 struct fw_scs1x
*scs
= stream
->rmidi
->private_data
;
314 scs
->output_status
= 0;
315 scs
->output_bytes
= 1;
316 scs
->output_escaped
= false;
317 scs
->output_idle
= false;
318 scs
->transaction_bytes
= 0;
321 WRITE_ONCE(scs
->output
, stream
);
322 schedule_work(&scs
->work
);
324 WRITE_ONCE(scs
->output
, NULL
);
327 static void midi_playback_drain(struct snd_rawmidi_substream
*stream
)
329 struct fw_scs1x
*scs
= stream
->rmidi
->private_data
;
331 wait_event(scs
->idle_wait
, scs
->output_idle
);
334 static int register_address(struct snd_oxfw
*oxfw
)
336 struct fw_scs1x
*scs
= oxfw
->spec
;
339 data
= cpu_to_be64(((u64
)HSS1394_TAG_CHANGE_ADDRESS
<< 56) |
340 scs
->hss_handler
.offset
);
341 return snd_fw_transaction(oxfw
->unit
, TCODE_WRITE_BLOCK_REQUEST
,
342 HSS1394_ADDRESS
, &data
, sizeof(data
), 0);
345 static void remove_scs1x(struct snd_rawmidi
*rmidi
)
347 struct fw_scs1x
*scs
= rmidi
->private_data
;
349 fw_core_remove_address_handler(&scs
->hss_handler
);
352 void snd_oxfw_scs1x_update(struct snd_oxfw
*oxfw
)
354 register_address(oxfw
);
357 int snd_oxfw_scs1x_add(struct snd_oxfw
*oxfw
)
359 static const struct snd_rawmidi_ops midi_capture_ops
= {
360 .open
= midi_capture_open
,
361 .close
= midi_capture_close
,
362 .trigger
= midi_capture_trigger
,
364 static const struct snd_rawmidi_ops midi_playback_ops
= {
365 .open
= midi_playback_open
,
366 .close
= midi_playback_close
,
367 .trigger
= midi_playback_trigger
,
368 .drain
= midi_playback_drain
,
370 struct snd_rawmidi
*rmidi
;
371 struct fw_scs1x
*scs
;
374 scs
= devm_kzalloc(&oxfw
->card
->card_dev
, sizeof(struct fw_scs1x
),
378 scs
->fw_dev
= fw_parent_device(oxfw
->unit
);
381 /* Allocate own handler for imcoming asynchronous transaction. */
382 scs
->hss_handler
.length
= HSS1394_MAX_PACKET_SIZE
;
383 scs
->hss_handler
.address_callback
= handle_hss
;
384 scs
->hss_handler
.callback_data
= scs
;
385 err
= fw_core_add_address_handler(&scs
->hss_handler
,
386 &fw_high_memory_region
);
390 err
= register_address(oxfw
);
394 /* Use unique name for backward compatibility to scs1x module. */
395 err
= snd_rawmidi_new(oxfw
->card
, "SCS.1x", 0, 1, 1, &rmidi
);
398 rmidi
->private_data
= scs
;
399 rmidi
->private_free
= remove_scs1x
;
401 snprintf(rmidi
->name
, sizeof(rmidi
->name
),
402 "%s MIDI", oxfw
->card
->shortname
);
404 rmidi
->info_flags
= SNDRV_RAWMIDI_INFO_INPUT
|
405 SNDRV_RAWMIDI_INFO_OUTPUT
|
406 SNDRV_RAWMIDI_INFO_DUPLEX
;
407 snd_rawmidi_set_ops(rmidi
, SNDRV_RAWMIDI_STREAM_INPUT
,
409 snd_rawmidi_set_ops(rmidi
, SNDRV_RAWMIDI_STREAM_OUTPUT
,
412 INIT_WORK(&scs
->work
, scs_output_work
);
413 init_waitqueue_head(&scs
->idle_wait
);
414 scs
->output_idle
= true;
418 fw_core_remove_address_handler(&scs
->hss_handler
);