/drivers/staging/line6/midi.c

https://bitbucket.org/cyanogenmod/android_kernel_asus_tf300t · C · 429 lines · 307 code · 77 blank · 45 comment · 36 complexity · 91e971171a76dbc297fd4cd5bc4caa99 MD5 · raw file

  1. /*
  2. * Line6 Linux USB driver - 0.9.1beta
  3. *
  4. * Copyright (C) 2004-2010 Markus Grabner (grabner@icg.tugraz.at)
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation, version 2.
  9. *
  10. */
  11. #include <linux/slab.h>
  12. #include <linux/usb.h>
  13. #include <sound/core.h>
  14. #include <sound/rawmidi.h>
  15. #include "audio.h"
  16. #include "driver.h"
  17. #include "midi.h"
  18. #include "pod.h"
  19. #include "usbdefs.h"
  20. #define line6_rawmidi_substream_midi(substream) \
  21. ((struct snd_line6_midi *)((substream)->rmidi->private_data))
  22. static int send_midi_async(struct usb_line6 *line6, unsigned char *data,
  23. int length);
  24. /*
  25. Pass data received via USB to MIDI.
  26. */
  27. void line6_midi_receive(struct usb_line6 *line6, unsigned char *data,
  28. int length)
  29. {
  30. if (line6->line6midi->substream_receive)
  31. snd_rawmidi_receive(line6->line6midi->substream_receive,
  32. data, length);
  33. }
  34. /*
  35. Read data from MIDI buffer and transmit them via USB.
  36. */
  37. static void line6_midi_transmit(struct snd_rawmidi_substream *substream)
  38. {
  39. struct usb_line6 *line6 =
  40. line6_rawmidi_substream_midi(substream)->line6;
  41. struct snd_line6_midi *line6midi = line6->line6midi;
  42. struct MidiBuffer *mb = &line6midi->midibuf_out;
  43. unsigned long flags;
  44. unsigned char chunk[line6->max_packet_size];
  45. int req, done;
  46. spin_lock_irqsave(&line6->line6midi->midi_transmit_lock, flags);
  47. for (;;) {
  48. req = min(line6_midibuf_bytes_free(mb), line6->max_packet_size);
  49. done = snd_rawmidi_transmit_peek(substream, chunk, req);
  50. if (done == 0)
  51. break;
  52. #ifdef CONFIG_LINE6_USB_DUMP_MIDI
  53. line6_write_hexdump(line6, 's', chunk, done);
  54. #endif
  55. line6_midibuf_write(mb, chunk, done);
  56. snd_rawmidi_transmit_ack(substream, done);
  57. }
  58. for (;;) {
  59. done = line6_midibuf_read(mb, chunk, line6->max_packet_size);
  60. if (done == 0)
  61. break;
  62. if (line6_midibuf_skip_message
  63. (mb, line6midi->midi_mask_transmit))
  64. continue;
  65. send_midi_async(line6, chunk, done);
  66. }
  67. spin_unlock_irqrestore(&line6->line6midi->midi_transmit_lock, flags);
  68. }
  69. /*
  70. Notification of completion of MIDI transmission.
  71. */
  72. static void midi_sent(struct urb *urb)
  73. {
  74. unsigned long flags;
  75. int status;
  76. int num;
  77. struct usb_line6 *line6 = (struct usb_line6 *)urb->context;
  78. status = urb->status;
  79. kfree(urb->transfer_buffer);
  80. usb_free_urb(urb);
  81. if (status == -ESHUTDOWN)
  82. return;
  83. spin_lock_irqsave(&line6->line6midi->send_urb_lock, flags);
  84. num = --line6->line6midi->num_active_send_urbs;
  85. if (num == 0) {
  86. line6_midi_transmit(line6->line6midi->substream_transmit);
  87. num = line6->line6midi->num_active_send_urbs;
  88. }
  89. if (num == 0)
  90. wake_up(&line6->line6midi->send_wait);
  91. spin_unlock_irqrestore(&line6->line6midi->send_urb_lock, flags);
  92. }
  93. /*
  94. Send an asynchronous MIDI message.
  95. Assumes that line6->line6midi->send_urb_lock is held
  96. (i.e., this function is serialized).
  97. */
  98. static int send_midi_async(struct usb_line6 *line6, unsigned char *data,
  99. int length)
  100. {
  101. struct urb *urb;
  102. int retval;
  103. unsigned char *transfer_buffer;
  104. urb = usb_alloc_urb(0, GFP_ATOMIC);
  105. if (urb == NULL) {
  106. dev_err(line6->ifcdev, "Out of memory\n");
  107. return -ENOMEM;
  108. }
  109. #ifdef CONFIG_LINE6_USB_DUMP_CTRL
  110. line6_write_hexdump(line6, 'S', data, length);
  111. #endif
  112. transfer_buffer = kmalloc(length, GFP_ATOMIC);
  113. if (transfer_buffer == NULL) {
  114. usb_free_urb(urb);
  115. dev_err(line6->ifcdev, "Out of memory\n");
  116. return -ENOMEM;
  117. }
  118. memcpy(transfer_buffer, data, length);
  119. usb_fill_int_urb(urb, line6->usbdev,
  120. usb_sndbulkpipe(line6->usbdev,
  121. line6->ep_control_write),
  122. transfer_buffer, length, midi_sent, line6,
  123. line6->interval);
  124. urb->actual_length = 0;
  125. retval = usb_submit_urb(urb, GFP_ATOMIC);
  126. if (retval < 0) {
  127. dev_err(line6->ifcdev, "usb_submit_urb failed\n");
  128. usb_free_urb(urb);
  129. return -EINVAL;
  130. }
  131. ++line6->line6midi->num_active_send_urbs;
  132. switch (line6->usbdev->descriptor.idProduct) {
  133. case LINE6_DEVID_BASSPODXT:
  134. case LINE6_DEVID_BASSPODXTLIVE:
  135. case LINE6_DEVID_BASSPODXTPRO:
  136. case LINE6_DEVID_PODXT:
  137. case LINE6_DEVID_PODXTLIVE:
  138. case LINE6_DEVID_PODXTPRO:
  139. case LINE6_DEVID_POCKETPOD:
  140. line6_pod_midi_postprocess((struct usb_line6_pod *)line6, data,
  141. length);
  142. break;
  143. case LINE6_DEVID_VARIAX:
  144. break;
  145. default:
  146. MISSING_CASE;
  147. }
  148. return 0;
  149. }
  150. static int line6_midi_output_open(struct snd_rawmidi_substream *substream)
  151. {
  152. return 0;
  153. }
  154. static int line6_midi_output_close(struct snd_rawmidi_substream *substream)
  155. {
  156. return 0;
  157. }
  158. static void line6_midi_output_trigger(struct snd_rawmidi_substream *substream,
  159. int up)
  160. {
  161. unsigned long flags;
  162. struct usb_line6 *line6 =
  163. line6_rawmidi_substream_midi(substream)->line6;
  164. line6->line6midi->substream_transmit = substream;
  165. spin_lock_irqsave(&line6->line6midi->send_urb_lock, flags);
  166. if (line6->line6midi->num_active_send_urbs == 0)
  167. line6_midi_transmit(substream);
  168. spin_unlock_irqrestore(&line6->line6midi->send_urb_lock, flags);
  169. }
  170. static void line6_midi_output_drain(struct snd_rawmidi_substream *substream)
  171. {
  172. struct usb_line6 *line6 =
  173. line6_rawmidi_substream_midi(substream)->line6;
  174. struct snd_line6_midi *midi = line6->line6midi;
  175. wait_event_interruptible(midi->send_wait,
  176. midi->num_active_send_urbs == 0);
  177. }
  178. static int line6_midi_input_open(struct snd_rawmidi_substream *substream)
  179. {
  180. return 0;
  181. }
  182. static int line6_midi_input_close(struct snd_rawmidi_substream *substream)
  183. {
  184. return 0;
  185. }
  186. static void line6_midi_input_trigger(struct snd_rawmidi_substream *substream,
  187. int up)
  188. {
  189. struct usb_line6 *line6 =
  190. line6_rawmidi_substream_midi(substream)->line6;
  191. if (up)
  192. line6->line6midi->substream_receive = substream;
  193. else
  194. line6->line6midi->substream_receive = 0;
  195. }
  196. static struct snd_rawmidi_ops line6_midi_output_ops = {
  197. .open = line6_midi_output_open,
  198. .close = line6_midi_output_close,
  199. .trigger = line6_midi_output_trigger,
  200. .drain = line6_midi_output_drain,
  201. };
  202. static struct snd_rawmidi_ops line6_midi_input_ops = {
  203. .open = line6_midi_input_open,
  204. .close = line6_midi_input_close,
  205. .trigger = line6_midi_input_trigger,
  206. };
  207. /*
  208. Cleanup the Line6 MIDI device.
  209. */
  210. static void line6_cleanup_midi(struct snd_rawmidi *rmidi)
  211. {
  212. }
  213. /* Create a MIDI device */
  214. static int snd_line6_new_midi(struct snd_line6_midi *line6midi)
  215. {
  216. struct snd_rawmidi *rmidi;
  217. int err;
  218. err = snd_rawmidi_new(line6midi->line6->card, "Line6 MIDI", 0, 1, 1,
  219. &rmidi);
  220. if (err < 0)
  221. return err;
  222. rmidi->private_data = line6midi;
  223. rmidi->private_free = line6_cleanup_midi;
  224. strcpy(rmidi->id, line6midi->line6->properties->id);
  225. strcpy(rmidi->name, line6midi->line6->properties->name);
  226. rmidi->info_flags =
  227. SNDRV_RAWMIDI_INFO_OUTPUT |
  228. SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
  229. snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
  230. &line6_midi_output_ops);
  231. snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
  232. &line6_midi_input_ops);
  233. return 0;
  234. }
  235. /*
  236. "read" request on "midi_mask_transmit" special file.
  237. */
  238. static ssize_t midi_get_midi_mask_transmit(struct device *dev,
  239. struct device_attribute *attr,
  240. char *buf)
  241. {
  242. struct usb_interface *interface = to_usb_interface(dev);
  243. struct usb_line6 *line6 = usb_get_intfdata(interface);
  244. return sprintf(buf, "%d\n", line6->line6midi->midi_mask_transmit);
  245. }
  246. /*
  247. "write" request on "midi_mask" special file.
  248. */
  249. static ssize_t midi_set_midi_mask_transmit(struct device *dev,
  250. struct device_attribute *attr,
  251. const char *buf, size_t count)
  252. {
  253. struct usb_interface *interface = to_usb_interface(dev);
  254. struct usb_line6 *line6 = usb_get_intfdata(interface);
  255. unsigned long value;
  256. int ret;
  257. ret = strict_strtoul(buf, 10, &value);
  258. if (ret)
  259. return ret;
  260. line6->line6midi->midi_mask_transmit = value;
  261. return count;
  262. }
  263. /*
  264. "read" request on "midi_mask_receive" special file.
  265. */
  266. static ssize_t midi_get_midi_mask_receive(struct device *dev,
  267. struct device_attribute *attr,
  268. char *buf)
  269. {
  270. struct usb_interface *interface = to_usb_interface(dev);
  271. struct usb_line6 *line6 = usb_get_intfdata(interface);
  272. return sprintf(buf, "%d\n", line6->line6midi->midi_mask_receive);
  273. }
  274. /*
  275. "write" request on "midi_mask" special file.
  276. */
  277. static ssize_t midi_set_midi_mask_receive(struct device *dev,
  278. struct device_attribute *attr,
  279. const char *buf, size_t count)
  280. {
  281. struct usb_interface *interface = to_usb_interface(dev);
  282. struct usb_line6 *line6 = usb_get_intfdata(interface);
  283. unsigned long value;
  284. int ret;
  285. ret = strict_strtoul(buf, 10, &value);
  286. if (ret)
  287. return ret;
  288. line6->line6midi->midi_mask_receive = value;
  289. return count;
  290. }
  291. static DEVICE_ATTR(midi_mask_transmit, S_IWUSR | S_IRUGO,
  292. midi_get_midi_mask_transmit, midi_set_midi_mask_transmit);
  293. static DEVICE_ATTR(midi_mask_receive, S_IWUSR | S_IRUGO,
  294. midi_get_midi_mask_receive, midi_set_midi_mask_receive);
  295. /* MIDI device destructor */
  296. static int snd_line6_midi_free(struct snd_device *device)
  297. {
  298. struct snd_line6_midi *line6midi = device->device_data;
  299. device_remove_file(line6midi->line6->ifcdev,
  300. &dev_attr_midi_mask_transmit);
  301. device_remove_file(line6midi->line6->ifcdev,
  302. &dev_attr_midi_mask_receive);
  303. line6_midibuf_destroy(&line6midi->midibuf_in);
  304. line6_midibuf_destroy(&line6midi->midibuf_out);
  305. return 0;
  306. }
  307. /*
  308. Initialize the Line6 MIDI subsystem.
  309. */
  310. int line6_init_midi(struct usb_line6 *line6)
  311. {
  312. static struct snd_device_ops midi_ops = {
  313. .dev_free = snd_line6_midi_free,
  314. };
  315. int err;
  316. struct snd_line6_midi *line6midi;
  317. if (!(line6->properties->capabilities & LINE6_BIT_CONTROL)) {
  318. /* skip MIDI initialization and report success */
  319. return 0;
  320. }
  321. line6midi = kzalloc(sizeof(struct snd_line6_midi), GFP_KERNEL);
  322. if (line6midi == NULL)
  323. return -ENOMEM;
  324. err = line6_midibuf_init(&line6midi->midibuf_in, MIDI_BUFFER_SIZE, 0);
  325. if (err < 0)
  326. return err;
  327. err = line6_midibuf_init(&line6midi->midibuf_out, MIDI_BUFFER_SIZE, 1);
  328. if (err < 0)
  329. return err;
  330. line6midi->line6 = line6;
  331. line6midi->midi_mask_transmit = 1;
  332. line6midi->midi_mask_receive = 4;
  333. line6->line6midi = line6midi;
  334. err = snd_device_new(line6->card, SNDRV_DEV_RAWMIDI, line6midi,
  335. &midi_ops);
  336. if (err < 0)
  337. return err;
  338. snd_card_set_dev(line6->card, line6->ifcdev);
  339. err = snd_line6_new_midi(line6midi);
  340. if (err < 0)
  341. return err;
  342. err = device_create_file(line6->ifcdev, &dev_attr_midi_mask_transmit);
  343. if (err < 0)
  344. return err;
  345. err = device_create_file(line6->ifcdev, &dev_attr_midi_mask_receive);
  346. if (err < 0)
  347. return err;
  348. init_waitqueue_head(&line6midi->send_wait);
  349. spin_lock_init(&line6midi->send_urb_lock);
  350. spin_lock_init(&line6midi->midi_transmit_lock);
  351. return 0;
  352. }