oxfw-scs1x.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. /*
  2. * oxfw-scs1x.c - a part of driver for OXFW970/971 based devices
  3. *
  4. * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
  5. * Copyright (c) 2015 Takashi Sakamoto <o-takashi@sakamocchi.jp>
  6. *
  7. * Licensed under the terms of the GNU General Public License, version 2.
  8. */
  9. #include "oxfw.h"
  10. #define HSS1394_ADDRESS 0xc007dedadadaULL
  11. #define HSS1394_MAX_PACKET_SIZE 64
  12. #define HSS1394_TAG_USER_DATA 0x00
  13. #define HSS1394_TAG_CHANGE_ADDRESS 0xf1
  14. struct fw_scs1x {
  15. struct fw_address_handler hss_handler;
  16. u8 input_escape_count;
  17. struct snd_rawmidi_substream *input;
  18. /* For MIDI playback. */
  19. struct snd_rawmidi_substream *output;
  20. bool output_idle;
  21. u8 output_status;
  22. u8 output_bytes;
  23. bool output_escaped;
  24. bool output_escape_high_nibble;
  25. struct tasklet_struct tasklet;
  26. wait_queue_head_t idle_wait;
  27. u8 buffer[HSS1394_MAX_PACKET_SIZE];
  28. bool transaction_running;
  29. struct fw_transaction transaction;
  30. struct fw_device *fw_dev;
  31. };
  32. static const u8 sysex_escape_prefix[] = {
  33. 0xf0, /* SysEx begin */
  34. 0x00, 0x01, 0x60, /* Stanton DJ */
  35. 0x48, 0x53, 0x53, /* "HSS" */
  36. };
  37. static void midi_input_escaped_byte(struct snd_rawmidi_substream *stream,
  38. u8 byte)
  39. {
  40. u8 nibbles[2];
  41. nibbles[0] = byte >> 4;
  42. nibbles[1] = byte & 0x0f;
  43. snd_rawmidi_receive(stream, nibbles, 2);
  44. }
  45. static void midi_input_byte(struct fw_scs1x *scs,
  46. struct snd_rawmidi_substream *stream, u8 byte)
  47. {
  48. const u8 eox = 0xf7;
  49. if (scs->input_escape_count > 0) {
  50. midi_input_escaped_byte(stream, byte);
  51. scs->input_escape_count--;
  52. if (scs->input_escape_count == 0)
  53. snd_rawmidi_receive(stream, &eox, sizeof(eox));
  54. } else if (byte == 0xf9) {
  55. snd_rawmidi_receive(stream, sysex_escape_prefix,
  56. ARRAY_SIZE(sysex_escape_prefix));
  57. midi_input_escaped_byte(stream, 0x00);
  58. midi_input_escaped_byte(stream, 0xf9);
  59. scs->input_escape_count = 3;
  60. } else {
  61. snd_rawmidi_receive(stream, &byte, 1);
  62. }
  63. }
  64. static void midi_input_packet(struct fw_scs1x *scs,
  65. struct snd_rawmidi_substream *stream,
  66. const u8 *data, unsigned int bytes)
  67. {
  68. unsigned int i;
  69. const u8 eox = 0xf7;
  70. if (data[0] == HSS1394_TAG_USER_DATA) {
  71. for (i = 1; i < bytes; ++i)
  72. midi_input_byte(scs, stream, data[i]);
  73. } else {
  74. snd_rawmidi_receive(stream, sysex_escape_prefix,
  75. ARRAY_SIZE(sysex_escape_prefix));
  76. for (i = 0; i < bytes; ++i)
  77. midi_input_escaped_byte(stream, data[i]);
  78. snd_rawmidi_receive(stream, &eox, sizeof(eox));
  79. }
  80. }
  81. static void handle_hss(struct fw_card *card, struct fw_request *request,
  82. int tcode, int destination, int source, int generation,
  83. unsigned long long offset, void *data, size_t length,
  84. void *callback_data)
  85. {
  86. struct fw_scs1x *scs = callback_data;
  87. struct snd_rawmidi_substream *stream;
  88. int rcode;
  89. if (offset != scs->hss_handler.offset) {
  90. rcode = RCODE_ADDRESS_ERROR;
  91. goto end;
  92. }
  93. if (tcode != TCODE_WRITE_QUADLET_REQUEST &&
  94. tcode != TCODE_WRITE_BLOCK_REQUEST) {
  95. rcode = RCODE_TYPE_ERROR;
  96. goto end;
  97. }
  98. if (length >= 1) {
  99. stream = ACCESS_ONCE(scs->input);
  100. if (stream)
  101. midi_input_packet(scs, stream, data, length);
  102. }
  103. rcode = RCODE_COMPLETE;
  104. end:
  105. fw_send_response(card, request, rcode);
  106. }
  107. static void scs_write_callback(struct fw_card *card, int rcode,
  108. void *data, size_t length, void *callback_data)
  109. {
  110. struct fw_scs1x *scs = callback_data;
  111. if (rcode == RCODE_GENERATION)
  112. ; /* TODO: retry this packet */
  113. scs->transaction_running = false;
  114. tasklet_schedule(&scs->tasklet);
  115. }
  116. static bool is_valid_running_status(u8 status)
  117. {
  118. return status >= 0x80 && status <= 0xef;
  119. }
  120. static bool is_one_byte_cmd(u8 status)
  121. {
  122. return status == 0xf6 ||
  123. status >= 0xf8;
  124. }
  125. static bool is_two_bytes_cmd(u8 status)
  126. {
  127. return (status >= 0xc0 && status <= 0xdf) ||
  128. status == 0xf1 ||
  129. status == 0xf3;
  130. }
  131. static bool is_three_bytes_cmd(u8 status)
  132. {
  133. return (status >= 0x80 && status <= 0xbf) ||
  134. (status >= 0xe0 && status <= 0xef) ||
  135. status == 0xf2;
  136. }
  137. static bool is_invalid_cmd(u8 status)
  138. {
  139. return status == 0xf4 ||
  140. status == 0xf5 ||
  141. status == 0xf9 ||
  142. status == 0xfd;
  143. }
  144. static void scs_output_tasklet(unsigned long data)
  145. {
  146. struct fw_scs1x *scs = (struct fw_scs1x *)data;
  147. struct snd_rawmidi_substream *stream;
  148. unsigned int i;
  149. u8 byte;
  150. int generation;
  151. if (scs->transaction_running)
  152. return;
  153. stream = ACCESS_ONCE(scs->output);
  154. if (!stream) {
  155. scs->output_idle = true;
  156. wake_up(&scs->idle_wait);
  157. return;
  158. }
  159. i = scs->output_bytes;
  160. for (;;) {
  161. if (snd_rawmidi_transmit(stream, &byte, 1) != 1) {
  162. scs->output_bytes = i;
  163. scs->output_idle = true;
  164. wake_up(&scs->idle_wait);
  165. return;
  166. }
  167. /*
  168. * Convert from real MIDI to what I think the device expects (no
  169. * running status, one command per packet, unescaped SysExs).
  170. */
  171. if (scs->output_escaped && byte < 0x80) {
  172. if (scs->output_escape_high_nibble) {
  173. if (i < HSS1394_MAX_PACKET_SIZE) {
  174. scs->buffer[i] = byte << 4;
  175. scs->output_escape_high_nibble = false;
  176. }
  177. } else {
  178. scs->buffer[i++] |= byte & 0x0f;
  179. scs->output_escape_high_nibble = true;
  180. }
  181. } else if (byte < 0x80) {
  182. if (i == 1) {
  183. if (!is_valid_running_status(
  184. scs->output_status))
  185. continue;
  186. scs->buffer[0] = HSS1394_TAG_USER_DATA;
  187. scs->buffer[i++] = scs->output_status;
  188. }
  189. scs->buffer[i++] = byte;
  190. if ((i == 3 && is_two_bytes_cmd(scs->output_status)) ||
  191. (i == 4 && is_three_bytes_cmd(scs->output_status)))
  192. break;
  193. if (i == 1 + ARRAY_SIZE(sysex_escape_prefix) &&
  194. !memcmp(scs->buffer + 1, sysex_escape_prefix,
  195. ARRAY_SIZE(sysex_escape_prefix))) {
  196. scs->output_escaped = true;
  197. scs->output_escape_high_nibble = true;
  198. i = 0;
  199. }
  200. if (i >= HSS1394_MAX_PACKET_SIZE)
  201. i = 1;
  202. } else if (byte == 0xf7) {
  203. if (scs->output_escaped) {
  204. if (i >= 1 && scs->output_escape_high_nibble &&
  205. scs->buffer[0] !=
  206. HSS1394_TAG_CHANGE_ADDRESS)
  207. break;
  208. } else {
  209. if (i > 1 && scs->output_status == 0xf0) {
  210. scs->buffer[i++] = 0xf7;
  211. break;
  212. }
  213. }
  214. i = 1;
  215. scs->output_escaped = false;
  216. } else if (!is_invalid_cmd(byte) && byte < 0xf8) {
  217. i = 1;
  218. scs->buffer[0] = HSS1394_TAG_USER_DATA;
  219. scs->buffer[i++] = byte;
  220. scs->output_status = byte;
  221. scs->output_escaped = false;
  222. if (is_one_byte_cmd(byte))
  223. break;
  224. }
  225. }
  226. scs->output_bytes = 1;
  227. scs->output_escaped = false;
  228. scs->transaction_running = true;
  229. generation = scs->fw_dev->generation;
  230. smp_rmb(); /* node_id vs. generation */
  231. fw_send_request(scs->fw_dev->card, &scs->transaction,
  232. TCODE_WRITE_BLOCK_REQUEST, scs->fw_dev->node_id,
  233. generation, scs->fw_dev->max_speed, HSS1394_ADDRESS,
  234. scs->buffer, i, scs_write_callback, scs);
  235. }
  236. static int midi_capture_open(struct snd_rawmidi_substream *stream)
  237. {
  238. return 0;
  239. }
  240. static int midi_capture_close(struct snd_rawmidi_substream *stream)
  241. {
  242. return 0;
  243. }
  244. static void midi_capture_trigger(struct snd_rawmidi_substream *stream, int up)
  245. {
  246. struct fw_scs1x *scs = stream->rmidi->private_data;
  247. if (up) {
  248. scs->input_escape_count = 0;
  249. ACCESS_ONCE(scs->input) = stream;
  250. } else {
  251. ACCESS_ONCE(scs->input) = NULL;
  252. }
  253. }
  254. static struct snd_rawmidi_ops midi_capture_ops = {
  255. .open = midi_capture_open,
  256. .close = midi_capture_close,
  257. .trigger = midi_capture_trigger,
  258. };
  259. static int midi_playback_open(struct snd_rawmidi_substream *stream)
  260. {
  261. return 0;
  262. }
  263. static int midi_playback_close(struct snd_rawmidi_substream *stream)
  264. {
  265. return 0;
  266. }
  267. static void midi_playback_trigger(struct snd_rawmidi_substream *stream, int up)
  268. {
  269. struct fw_scs1x *scs = stream->rmidi->private_data;
  270. if (up) {
  271. scs->output_status = 0;
  272. scs->output_bytes = 1;
  273. scs->output_escaped = false;
  274. scs->output_idle = false;
  275. ACCESS_ONCE(scs->output) = stream;
  276. tasklet_schedule(&scs->tasklet);
  277. } else {
  278. ACCESS_ONCE(scs->output) = NULL;
  279. }
  280. }
  281. static void midi_playback_drain(struct snd_rawmidi_substream *stream)
  282. {
  283. struct fw_scs1x *scs = stream->rmidi->private_data;
  284. wait_event(scs->idle_wait, scs->output_idle);
  285. }
  286. static struct snd_rawmidi_ops midi_playback_ops = {
  287. .open = midi_playback_open,
  288. .close = midi_playback_close,
  289. .trigger = midi_playback_trigger,
  290. .drain = midi_playback_drain,
  291. };
  292. static int register_address(struct snd_oxfw *oxfw)
  293. {
  294. struct fw_scs1x *scs = oxfw->spec;
  295. __be64 data;
  296. data = cpu_to_be64(((u64)HSS1394_TAG_CHANGE_ADDRESS << 56) |
  297. scs->hss_handler.offset);
  298. return snd_fw_transaction(oxfw->unit, TCODE_WRITE_BLOCK_REQUEST,
  299. HSS1394_ADDRESS, &data, sizeof(data), 0);
  300. }
  301. static void remove_scs1x(struct snd_rawmidi *rmidi)
  302. {
  303. struct fw_scs1x *scs = rmidi->private_data;
  304. fw_core_remove_address_handler(&scs->hss_handler);
  305. }
  306. void snd_oxfw_scs1x_update(struct snd_oxfw *oxfw)
  307. {
  308. register_address(oxfw);
  309. }
  310. int snd_oxfw_scs1x_add(struct snd_oxfw *oxfw)
  311. {
  312. struct snd_rawmidi *rmidi;
  313. struct fw_scs1x *scs;
  314. int err;
  315. scs = kzalloc(sizeof(struct fw_scs1x), GFP_KERNEL);
  316. if (scs == NULL)
  317. return -ENOMEM;
  318. scs->fw_dev = fw_parent_device(oxfw->unit);
  319. oxfw->spec = scs;
  320. /* Allocate own handler for imcoming asynchronous transaction. */
  321. scs->hss_handler.length = HSS1394_MAX_PACKET_SIZE;
  322. scs->hss_handler.address_callback = handle_hss;
  323. scs->hss_handler.callback_data = scs;
  324. err = fw_core_add_address_handler(&scs->hss_handler,
  325. &fw_high_memory_region);
  326. if (err < 0)
  327. return err;
  328. err = register_address(oxfw);
  329. if (err < 0)
  330. goto err_allocated;
  331. /* Use unique name for backward compatibility to scs1x module. */
  332. err = snd_rawmidi_new(oxfw->card, "SCS.1x", 0, 1, 1, &rmidi);
  333. if (err < 0)
  334. goto err_allocated;
  335. rmidi->private_data = scs;
  336. rmidi->private_free = remove_scs1x;
  337. snprintf(rmidi->name, sizeof(rmidi->name),
  338. "%s MIDI", oxfw->card->shortname);
  339. rmidi->info_flags = SNDRV_RAWMIDI_INFO_INPUT |
  340. SNDRV_RAWMIDI_INFO_OUTPUT |
  341. SNDRV_RAWMIDI_INFO_DUPLEX;
  342. snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
  343. &midi_capture_ops);
  344. snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
  345. &midi_playback_ops);
  346. tasklet_init(&scs->tasklet, scs_output_tasklet, (unsigned long)scs);
  347. init_waitqueue_head(&scs->idle_wait);
  348. scs->output_idle = true;
  349. return 0;
  350. err_allocated:
  351. fw_core_remove_address_handler(&scs->hss_handler);
  352. return err;
  353. }