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 32struct 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 51static const u8 sysex_escape_prefix[] = { 52 0xf0, /* SysEx begin */ 53 0x00, 0x01, 0x60, /* Stanton DJ */ 54 0x48, 0x53, 0x53, /* "HSS" */ 55}; 56 57static 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 68static int scs_output_close(struct snd_rawmidi_substream *stream) 69{ 70 return 0; 71} 72 73static 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 84static 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 97static bool is_valid_running_status(u8 status) 98{ 99 return status >= 0x80 && status <= 0xef; 100} 101 102static bool is_one_byte_cmd(u8 status) 103{ 104 return status == 0xf6 || 105 status >= 0xf8; 106} 107 108static bool is_two_bytes_cmd(u8 status) 109{ 110 return (status >= 0xc0 && status <= 0xdf) || 111 status == 0xf1 || 112 status == 0xf3; 113} 114 115static bool is_three_bytes_cmd(u8 status) 116{ 117 return (status >= 0x80 && status <= 0xbf) || 118 (status >= 0xe0 && status <= 0xef) || 119 status == 0xf2; 120} 121 122static bool is_invalid_cmd(u8 status) 123{ 124 return status == 0xf4 || 125 status == 0xf5 || 126 status == 0xf9 || 127 status == 0xfd; 128} 129 130static 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 228static 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 235static 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 242static 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 251static int scs_input_close(struct snd_rawmidi_substream *stream) 252{ 253 return 0; 254} 255 256static 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 263static 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 273static 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 293static 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 311static struct snd_rawmidi_ops input_ops = { 312 .open = scs_input_open, 313 .close = scs_input_close, 314 .trigger = scs_input_trigger, 315}; 316 317static 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 337static 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 364static 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, 0); 373 if (err < 0) 374 dev_err(&scs->unit->device, "HSS1394 communication failed\n"); 375 376 return err; 377} 378 379static 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 387static int scs_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) 388{ 389 struct fw_device *fw_dev = fw_parent_device(unit); 390 struct snd_card *card; 391 struct scs *scs; 392 int err; 393 394 err = snd_card_new(&unit->device, -16, NULL, THIS_MODULE, 395 sizeof(*scs), &card); 396 if (err < 0) 397 return err; 398 399 scs = card->private_data; 400 scs->card = card; 401 scs->unit = unit; 402 tasklet_init(&scs->tasklet, scs_output_tasklet, (unsigned long)scs); 403 init_waitqueue_head(&scs->idle_wait); 404 scs->output_idle = true; 405 406 scs->buffer = kmalloc(HSS1394_MAX_PACKET_SIZE, GFP_KERNEL); 407 if (!scs->buffer) { 408 err = -ENOMEM; 409 goto err_card; 410 } 411 412 scs->hss_handler.length = HSS1394_MAX_PACKET_SIZE; 413 scs->hss_handler.address_callback = handle_hss; 414 scs->hss_handler.callback_data = scs; 415 err = fw_core_add_address_handler(&scs->hss_handler, 416 &fw_high_memory_region); 417 if (err < 0) 418 goto err_buffer; 419 420 card->private_free = scs_card_free; 421 422 strcpy(card->driver, "SCS.1x"); 423 strcpy(card->shortname, "SCS.1x"); 424 fw_csr_string(unit->directory, CSR_MODEL, 425 card->shortname, sizeof(card->shortname)); 426 snprintf(card->longname, sizeof(card->longname), 427 "Stanton DJ %s (GUID %08x%08x) at %s, S%d", 428 card->shortname, fw_dev->config_rom[3], fw_dev->config_rom[4], 429 dev_name(&unit->device), 100 << fw_dev->max_speed); 430 strcpy(card->mixername, card->shortname); 431 432 err = scs_init_hss_address(scs); 433 if (err < 0) 434 goto err_card; 435 436 err = scs_create_midi(scs); 437 if (err < 0) 438 goto err_card; 439 440 err = snd_card_register(card); 441 if (err < 0) 442 goto err_card; 443 444 dev_set_drvdata(&unit->device, scs); 445 446 return 0; 447 448err_buffer: 449 kfree(scs->buffer); 450err_card: 451 snd_card_free(card); 452 return err; 453} 454 455static void scs_update(struct fw_unit *unit) 456{ 457 struct scs *scs = dev_get_drvdata(&unit->device); 458 int generation; 459 __be64 data; 460 461 data = cpu_to_be64(((u64)HSS1394_TAG_CHANGE_ADDRESS << 56) | 462 scs->hss_handler.offset); 463 generation = fw_parent_device(unit)->generation; 464 smp_rmb(); /* node_id vs. generation */ 465 snd_fw_transaction(scs->unit, TCODE_WRITE_BLOCK_REQUEST, 466 HSS1394_ADDRESS, &data, 8, 467 FW_FIXED_GENERATION | generation); 468} 469 470static void scs_remove(struct fw_unit *unit) 471{ 472 struct scs *scs = dev_get_drvdata(&unit->device); 473 474 snd_card_disconnect(scs->card); 475 476 ACCESS_ONCE(scs->output) = NULL; 477 ACCESS_ONCE(scs->input) = NULL; 478 479 wait_event(scs->idle_wait, scs->output_idle); 480 481 tasklet_kill(&scs->tasklet); 482 483 snd_card_free_when_closed(scs->card); 484} 485 486static const struct ieee1394_device_id scs_id_table[] = { 487 { 488 .match_flags = IEEE1394_MATCH_VENDOR_ID | 489 IEEE1394_MATCH_MODEL_ID, 490 .vendor_id = OUI_STANTON, 491 .model_id = MODEL_SCS_1M, 492 }, 493 { 494 .match_flags = IEEE1394_MATCH_VENDOR_ID | 495 IEEE1394_MATCH_MODEL_ID, 496 .vendor_id = OUI_STANTON, 497 .model_id = MODEL_SCS_1D, 498 }, 499 {} 500}; 501MODULE_DEVICE_TABLE(ieee1394, scs_id_table); 502 503MODULE_DESCRIPTION("SCS.1x MIDI driver"); 504MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); 505MODULE_LICENSE("GPL v2"); 506 507static struct fw_driver scs_driver = { 508 .driver = { 509 .owner = THIS_MODULE, 510 .name = KBUILD_MODNAME, 511 .bus = &fw_bus_type, 512 }, 513 .probe = scs_probe, 514 .update = scs_update, 515 .remove = scs_remove, 516 .id_table = scs_id_table, 517}; 518 519static int __init alsa_scs1x_init(void) 520{ 521 return driver_register(&scs_driver.driver); 522} 523 524static void __exit alsa_scs1x_exit(void) 525{ 526 driver_unregister(&scs_driver.driver); 527} 528 529module_init(alsa_scs1x_init); 530module_exit(alsa_scs1x_exit); 531