• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Stanton Control System 1 MIDI driver
3  *
4  * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
5  * Licensed under the terms of the GNU General Public License, version 2.
6  */
7 
8 #include <linux/device.h>
9 #include <linux/firewire.h>
10 #include <linux/firewire-constants.h>
11 #include <linux/interrupt.h>
12 #include <linux/module.h>
13 #include <linux/mod_devicetable.h>
14 #include <linux/slab.h>
15 #include <linux/string.h>
16 #include <linux/wait.h>
17 #include <sound/core.h>
18 #include <sound/initval.h>
19 #include <sound/rawmidi.h>
20 #include "lib.h"
21 
22 #define OUI_STANTON	0x001260
23 #define MODEL_SCS_1M	0x001000
24 #define MODEL_SCS_1D	0x002000
25 
26 #define HSS1394_ADDRESS			0xc007dedadadaULL
27 #define HSS1394_MAX_PACKET_SIZE		64
28 
29 #define HSS1394_TAG_USER_DATA		0x00
30 #define HSS1394_TAG_CHANGE_ADDRESS	0xf1
31 
32 struct scs {
33 	struct snd_card *card;
34 	struct fw_unit *unit;
35 	struct fw_address_handler hss_handler;
36 	struct fw_transaction transaction;
37 	bool transaction_running;
38 	bool output_idle;
39 	u8 output_status;
40 	u8 output_bytes;
41 	bool output_escaped;
42 	bool output_escape_high_nibble;
43 	u8 input_escape_count;
44 	struct snd_rawmidi_substream *output;
45 	struct snd_rawmidi_substream *input;
46 	struct tasklet_struct tasklet;
47 	wait_queue_head_t idle_wait;
48 	u8 *buffer;
49 };
50 
51 static const u8 sysex_escape_prefix[] = {
52 	0xf0,			/* SysEx begin */
53 	0x00, 0x01, 0x60,	/* Stanton DJ */
54 	0x48, 0x53, 0x53,	/* "HSS" */
55 };
56 
scs_output_open(struct snd_rawmidi_substream * stream)57 static int scs_output_open(struct snd_rawmidi_substream *stream)
58 {
59 	struct scs *scs = stream->rmidi->private_data;
60 
61 	scs->output_status = 0;
62 	scs->output_bytes = 1;
63 	scs->output_escaped = false;
64 
65 	return 0;
66 }
67 
scs_output_close(struct snd_rawmidi_substream * stream)68 static int scs_output_close(struct snd_rawmidi_substream *stream)
69 {
70 	return 0;
71 }
72 
scs_output_trigger(struct snd_rawmidi_substream * stream,int up)73 static void scs_output_trigger(struct snd_rawmidi_substream *stream, int up)
74 {
75 	struct scs *scs = stream->rmidi->private_data;
76 
77 	ACCESS_ONCE(scs->output) = up ? stream : NULL;
78 	if (up) {
79 		scs->output_idle = false;
80 		tasklet_schedule(&scs->tasklet);
81 	}
82 }
83 
scs_write_callback(struct fw_card * card,int rcode,void * data,size_t length,void * callback_data)84 static void scs_write_callback(struct fw_card *card, int rcode,
85 			       void *data, size_t length, void *callback_data)
86 {
87 	struct scs *scs = callback_data;
88 
89 	if (rcode == RCODE_GENERATION) {
90 		/* TODO: retry this packet */
91 	}
92 
93 	scs->transaction_running = false;
94 	tasklet_schedule(&scs->tasklet);
95 }
96 
is_valid_running_status(u8 status)97 static bool is_valid_running_status(u8 status)
98 {
99 	return status >= 0x80 && status <= 0xef;
100 }
101 
is_one_byte_cmd(u8 status)102 static bool is_one_byte_cmd(u8 status)
103 {
104 	return status == 0xf6 ||
105 	       status >= 0xf8;
106 }
107 
is_two_bytes_cmd(u8 status)108 static bool is_two_bytes_cmd(u8 status)
109 {
110 	return (status >= 0xc0 && status <= 0xdf) ||
111 	       status == 0xf1 ||
112 	       status == 0xf3;
113 }
114 
is_three_bytes_cmd(u8 status)115 static bool is_three_bytes_cmd(u8 status)
116 {
117 	return (status >= 0x80 && status <= 0xbf) ||
118 	       (status >= 0xe0 && status <= 0xef) ||
119 	       status == 0xf2;
120 }
121 
is_invalid_cmd(u8 status)122 static bool is_invalid_cmd(u8 status)
123 {
124 	return status == 0xf4 ||
125 	       status == 0xf5 ||
126 	       status == 0xf9 ||
127 	       status == 0xfd;
128 }
129 
scs_output_tasklet(unsigned long data)130 static void scs_output_tasklet(unsigned long data)
131 {
132 	struct scs *scs = (void *)data;
133 	struct snd_rawmidi_substream *stream;
134 	unsigned int i;
135 	u8 byte;
136 	struct fw_device *dev;
137 	int generation;
138 
139 	if (scs->transaction_running)
140 		return;
141 
142 	stream = ACCESS_ONCE(scs->output);
143 	if (!stream) {
144 		scs->output_idle = true;
145 		wake_up(&scs->idle_wait);
146 		return;
147 	}
148 
149 	i = scs->output_bytes;
150 	for (;;) {
151 		if (snd_rawmidi_transmit(stream, &byte, 1) != 1) {
152 			scs->output_bytes = i;
153 			scs->output_idle = true;
154 			wake_up(&scs->idle_wait);
155 			return;
156 		}
157 		/*
158 		 * Convert from real MIDI to what I think the device expects (no
159 		 * running status, one command per packet, unescaped SysExs).
160 		 */
161 		if (scs->output_escaped && byte < 0x80) {
162 			if (scs->output_escape_high_nibble) {
163 				if (i < HSS1394_MAX_PACKET_SIZE) {
164 					scs->buffer[i] = byte << 4;
165 					scs->output_escape_high_nibble = false;
166 				}
167 			} else {
168 				scs->buffer[i++] |= byte & 0x0f;
169 				scs->output_escape_high_nibble = true;
170 			}
171 		} else if (byte < 0x80) {
172 			if (i == 1) {
173 				if (!is_valid_running_status(scs->output_status))
174 					continue;
175 				scs->buffer[0] = HSS1394_TAG_USER_DATA;
176 				scs->buffer[i++] = scs->output_status;
177 			}
178 			scs->buffer[i++] = byte;
179 			if ((i == 3 && is_two_bytes_cmd(scs->output_status)) ||
180 			    (i == 4 && is_three_bytes_cmd(scs->output_status)))
181 				break;
182 			if (i == 1 + ARRAY_SIZE(sysex_escape_prefix) &&
183 			    !memcmp(scs->buffer + 1, sysex_escape_prefix,
184 				    ARRAY_SIZE(sysex_escape_prefix))) {
185 				scs->output_escaped = true;
186 				scs->output_escape_high_nibble = true;
187 				i = 0;
188 			}
189 			if (i >= HSS1394_MAX_PACKET_SIZE)
190 				i = 1;
191 		} else if (byte == 0xf7) {
192 			if (scs->output_escaped) {
193 				if (i >= 1 && scs->output_escape_high_nibble &&
194 				    scs->buffer[0] != HSS1394_TAG_CHANGE_ADDRESS)
195 					break;
196 			} else {
197 				if (i > 1 && scs->output_status == 0xf0) {
198 					scs->buffer[i++] = 0xf7;
199 					break;
200 				}
201 			}
202 			i = 1;
203 			scs->output_escaped = false;
204 		} else if (!is_invalid_cmd(byte) &&
205 			   byte < 0xf8) {
206 			i = 1;
207 			scs->buffer[0] = HSS1394_TAG_USER_DATA;
208 			scs->buffer[i++] = byte;
209 			scs->output_status = byte;
210 			scs->output_escaped = false;
211 			if (is_one_byte_cmd(byte))
212 				break;
213 		}
214 	}
215 	scs->output_bytes = 1;
216 	scs->output_escaped = false;
217 
218 	scs->transaction_running = true;
219 	dev = fw_parent_device(scs->unit);
220 	generation = dev->generation;
221 	smp_rmb(); /* node_id vs. generation */
222 	fw_send_request(dev->card, &scs->transaction, TCODE_WRITE_BLOCK_REQUEST,
223 			dev->node_id, generation, dev->max_speed,
224 			HSS1394_ADDRESS, scs->buffer, i,
225 			scs_write_callback, scs);
226 }
227 
scs_output_drain(struct snd_rawmidi_substream * stream)228 static void scs_output_drain(struct snd_rawmidi_substream *stream)
229 {
230 	struct scs *scs = stream->rmidi->private_data;
231 
232 	wait_event(scs->idle_wait, scs->output_idle);
233 }
234 
235 static struct snd_rawmidi_ops output_ops = {
236 	.open    = scs_output_open,
237 	.close   = scs_output_close,
238 	.trigger = scs_output_trigger,
239 	.drain   = scs_output_drain,
240 };
241 
scs_input_open(struct snd_rawmidi_substream * stream)242 static int scs_input_open(struct snd_rawmidi_substream *stream)
243 {
244 	struct scs *scs = stream->rmidi->private_data;
245 
246 	scs->input_escape_count = 0;
247 
248 	return 0;
249 }
250 
scs_input_close(struct snd_rawmidi_substream * stream)251 static int scs_input_close(struct snd_rawmidi_substream *stream)
252 {
253 	return 0;
254 }
255 
scs_input_trigger(struct snd_rawmidi_substream * stream,int up)256 static void scs_input_trigger(struct snd_rawmidi_substream *stream, int up)
257 {
258 	struct scs *scs = stream->rmidi->private_data;
259 
260 	ACCESS_ONCE(scs->input) = up ? stream : NULL;
261 }
262 
scs_input_escaped_byte(struct snd_rawmidi_substream * stream,u8 byte)263 static void scs_input_escaped_byte(struct snd_rawmidi_substream *stream,
264 				   u8 byte)
265 {
266 	u8 nibbles[2];
267 
268 	nibbles[0] = byte >> 4;
269 	nibbles[1] = byte & 0x0f;
270 	snd_rawmidi_receive(stream, nibbles, 2);
271 }
272 
scs_input_midi_byte(struct scs * scs,struct snd_rawmidi_substream * stream,u8 byte)273 static void scs_input_midi_byte(struct scs *scs,
274 				struct snd_rawmidi_substream *stream,
275 				u8 byte)
276 {
277 	if (scs->input_escape_count > 0) {
278 		scs_input_escaped_byte(stream, byte);
279 		scs->input_escape_count--;
280 		if (scs->input_escape_count == 0)
281 			snd_rawmidi_receive(stream, (const u8[]) { 0xf7 }, 1);
282 	} else if (byte == 0xf9) {
283 		snd_rawmidi_receive(stream, sysex_escape_prefix,
284 				    ARRAY_SIZE(sysex_escape_prefix));
285 		scs_input_escaped_byte(stream, 0x00);
286 		scs_input_escaped_byte(stream, 0xf9);
287 		scs->input_escape_count = 3;
288 	} else {
289 		snd_rawmidi_receive(stream, &byte, 1);
290 	}
291 }
292 
scs_input_packet(struct scs * scs,struct snd_rawmidi_substream * stream,const u8 * data,unsigned int bytes)293 static void scs_input_packet(struct scs *scs,
294 			     struct snd_rawmidi_substream *stream,
295 			     const u8 *data, unsigned int bytes)
296 {
297 	unsigned int i;
298 
299 	if (data[0] == HSS1394_TAG_USER_DATA) {
300 		for (i = 1; i < bytes; ++i)
301 			scs_input_midi_byte(scs, stream, data[i]);
302 	} else {
303 		snd_rawmidi_receive(stream, sysex_escape_prefix,
304 				    ARRAY_SIZE(sysex_escape_prefix));
305 		for (i = 0; i < bytes; ++i)
306 			scs_input_escaped_byte(stream, data[i]);
307 		snd_rawmidi_receive(stream, (const u8[]) { 0xf7 }, 1);
308 	}
309 }
310 
311 static struct snd_rawmidi_ops input_ops = {
312 	.open    = scs_input_open,
313 	.close   = scs_input_close,
314 	.trigger = scs_input_trigger,
315 };
316 
scs_create_midi(struct scs * scs)317 static int scs_create_midi(struct scs *scs)
318 {
319 	struct snd_rawmidi *rmidi;
320 	int err;
321 
322 	err = snd_rawmidi_new(scs->card, "SCS.1x", 0, 1, 1, &rmidi);
323 	if (err < 0)
324 		return err;
325 	snprintf(rmidi->name, sizeof(rmidi->name),
326 		 "%s MIDI", scs->card->shortname);
327 	rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
328 	                    SNDRV_RAWMIDI_INFO_INPUT |
329 	                    SNDRV_RAWMIDI_INFO_DUPLEX;
330 	rmidi->private_data = scs;
331 	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &output_ops);
332 	snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &input_ops);
333 
334 	return 0;
335 }
336 
handle_hss(struct fw_card * card,struct fw_request * request,int tcode,int destination,int source,int generation,unsigned long long offset,void * data,size_t length,void * callback_data)337 static void handle_hss(struct fw_card *card, struct fw_request *request,
338 		       int tcode, int destination, int source, int generation,
339 		       unsigned long long offset, void *data, size_t length,
340 		       void *callback_data)
341 {
342 	struct scs *scs = callback_data;
343 	struct snd_rawmidi_substream *stream;
344 
345 	if (offset != scs->hss_handler.offset) {
346 		fw_send_response(card, request, RCODE_ADDRESS_ERROR);
347 		return;
348 	}
349 	if (tcode != TCODE_WRITE_QUADLET_REQUEST &&
350 	    tcode != TCODE_WRITE_BLOCK_REQUEST) {
351 		fw_send_response(card, request, RCODE_TYPE_ERROR);
352 		return;
353 	}
354 
355 	if (length >= 1) {
356 		stream = ACCESS_ONCE(scs->input);
357 		if (stream)
358 			scs_input_packet(scs, stream, data, length);
359 	}
360 
361 	fw_send_response(card, request, RCODE_COMPLETE);
362 }
363 
scs_init_hss_address(struct scs * scs)364 static int scs_init_hss_address(struct scs *scs)
365 {
366 	__be64 data;
367 	int err;
368 
369 	data = cpu_to_be64(((u64)HSS1394_TAG_CHANGE_ADDRESS << 56) |
370 			   scs->hss_handler.offset);
371 	err = snd_fw_transaction(scs->unit, TCODE_WRITE_BLOCK_REQUEST,
372 				 HSS1394_ADDRESS, &data, 8);
373 	if (err < 0)
374 		dev_err(&scs->unit->device, "HSS1394 communication failed\n");
375 
376 	return err;
377 }
378 
scs_card_free(struct snd_card * card)379 static void scs_card_free(struct snd_card *card)
380 {
381 	struct scs *scs = card->private_data;
382 
383 	fw_core_remove_address_handler(&scs->hss_handler);
384 	kfree(scs->buffer);
385 }
386 
scs_probe(struct device * unit_dev)387 static int scs_probe(struct device *unit_dev)
388 {
389 	struct fw_unit *unit = fw_unit(unit_dev);
390 	struct fw_device *fw_dev = fw_parent_device(unit);
391 	struct snd_card *card;
392 	struct scs *scs;
393 	int err;
394 
395 	err = snd_card_create(-16, NULL, THIS_MODULE, sizeof(*scs), &card);
396 	if (err < 0)
397 		return err;
398 	snd_card_set_dev(card, unit_dev);
399 
400 	scs = card->private_data;
401 	scs->card = card;
402 	scs->unit = unit;
403 	tasklet_init(&scs->tasklet, scs_output_tasklet, (unsigned long)scs);
404 	init_waitqueue_head(&scs->idle_wait);
405 	scs->output_idle = true;
406 
407 	scs->buffer = kmalloc(HSS1394_MAX_PACKET_SIZE, GFP_KERNEL);
408 	if (!scs->buffer)
409 		goto err_card;
410 
411 	scs->hss_handler.length = HSS1394_MAX_PACKET_SIZE;
412 	scs->hss_handler.address_callback = handle_hss;
413 	scs->hss_handler.callback_data = scs;
414 	err = fw_core_add_address_handler(&scs->hss_handler,
415 					  &fw_high_memory_region);
416 	if (err < 0)
417 		goto err_buffer;
418 
419 	card->private_free = scs_card_free;
420 
421 	strcpy(card->driver, "SCS.1x");
422 	strcpy(card->shortname, "SCS.1x");
423 	fw_csr_string(unit->directory, CSR_MODEL,
424 		      card->shortname, sizeof(card->shortname));
425 	snprintf(card->longname, sizeof(card->longname),
426 		 "Stanton DJ %s (GUID %08x%08x) at %s, S%d",
427 		 card->shortname, fw_dev->config_rom[3], fw_dev->config_rom[4],
428 		 dev_name(&unit->device), 100 << fw_dev->max_speed);
429 	strcpy(card->mixername, card->shortname);
430 
431 	err = scs_init_hss_address(scs);
432 	if (err < 0)
433 		goto err_card;
434 
435 	err = scs_create_midi(scs);
436 	if (err < 0)
437 		goto err_card;
438 
439 	err = snd_card_register(card);
440 	if (err < 0)
441 		goto err_card;
442 
443 	dev_set_drvdata(unit_dev, scs);
444 
445 	return 0;
446 
447 err_buffer:
448 	kfree(scs->buffer);
449 err_card:
450 	snd_card_free(card);
451 	return err;
452 }
453 
scs_remove(struct device * dev)454 static int scs_remove(struct device *dev)
455 {
456 	struct scs *scs = dev_get_drvdata(dev);
457 
458 	snd_card_disconnect(scs->card);
459 
460 	ACCESS_ONCE(scs->output) = NULL;
461 	ACCESS_ONCE(scs->input) = NULL;
462 
463 	wait_event(scs->idle_wait, scs->output_idle);
464 
465 	tasklet_kill(&scs->tasklet);
466 
467 	snd_card_free_when_closed(scs->card);
468 
469 	return 0;
470 }
471 
scs_update(struct fw_unit * unit)472 static void scs_update(struct fw_unit *unit)
473 {
474 	struct scs *scs = dev_get_drvdata(&unit->device);
475 	__be64 data;
476 
477 	data = cpu_to_be64(((u64)HSS1394_TAG_CHANGE_ADDRESS << 56) |
478 			   scs->hss_handler.offset);
479 	snd_fw_transaction(scs->unit, TCODE_WRITE_BLOCK_REQUEST,
480 			   HSS1394_ADDRESS, &data, 8);
481 }
482 
483 static const struct ieee1394_device_id scs_id_table[] = {
484 	{
485 		.match_flags = IEEE1394_MATCH_VENDOR_ID |
486 		               IEEE1394_MATCH_MODEL_ID,
487 		.vendor_id   = OUI_STANTON,
488 		.model_id    = MODEL_SCS_1M,
489 	},
490 	{
491 		.match_flags = IEEE1394_MATCH_VENDOR_ID |
492 		               IEEE1394_MATCH_MODEL_ID,
493 		.vendor_id   = OUI_STANTON,
494 		.model_id    = MODEL_SCS_1D,
495 	},
496 	{}
497 };
498 MODULE_DEVICE_TABLE(ieee1394, scs_id_table);
499 
500 MODULE_DESCRIPTION("SCS.1x MIDI driver");
501 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
502 MODULE_LICENSE("GPL v2");
503 
504 static struct fw_driver scs_driver = {
505 	.driver = {
506 		.owner  = THIS_MODULE,
507 		.name   = KBUILD_MODNAME,
508 		.bus    = &fw_bus_type,
509 		.probe  = scs_probe,
510 		.remove = scs_remove,
511 	},
512 	.update   = scs_update,
513 	.id_table = scs_id_table,
514 };
515 
alsa_scs1x_init(void)516 static int __init alsa_scs1x_init(void)
517 {
518 	return driver_register(&scs_driver.driver);
519 }
520 
alsa_scs1x_exit(void)521 static void __exit alsa_scs1x_exit(void)
522 {
523 	driver_unregister(&scs_driver.driver);
524 }
525 
526 module_init(alsa_scs1x_init);
527 module_exit(alsa_scs1x_exit);
528