comm.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. * Linux driver for TerraTec DMX 6Fire USB
  3. *
  4. * Device communications
  5. *
  6. * Author: Torsten Schenk <torsten.schenk@zoho.com>
  7. * Created: Jan 01, 2011
  8. * Copyright: (C) Torsten Schenk
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 2 of the License, or
  13. * (at your option) any later version.
  14. */
  15. #include "comm.h"
  16. #include "chip.h"
  17. #include "midi.h"
  18. enum {
  19. COMM_EP = 1,
  20. COMM_FPGA_EP = 2
  21. };
  22. static void usb6fire_comm_init_urb(struct comm_runtime *rt, struct urb *urb,
  23. u8 *buffer, void *context, void(*handler)(struct urb *urb))
  24. {
  25. usb_init_urb(urb);
  26. urb->transfer_buffer = buffer;
  27. urb->pipe = usb_sndintpipe(rt->chip->dev, COMM_EP);
  28. urb->complete = handler;
  29. urb->context = context;
  30. urb->interval = 1;
  31. urb->dev = rt->chip->dev;
  32. }
  33. static void usb6fire_comm_receiver_handler(struct urb *urb)
  34. {
  35. struct comm_runtime *rt = urb->context;
  36. struct midi_runtime *midi_rt = rt->chip->midi;
  37. if (!urb->status) {
  38. if (rt->receiver_buffer[0] == 0x10) /* midi in event */
  39. if (midi_rt)
  40. midi_rt->in_received(midi_rt,
  41. rt->receiver_buffer + 2,
  42. rt->receiver_buffer[1]);
  43. }
  44. if (!rt->chip->shutdown) {
  45. urb->status = 0;
  46. urb->actual_length = 0;
  47. if (usb_submit_urb(urb, GFP_ATOMIC) < 0)
  48. snd_printk(KERN_WARNING PREFIX
  49. "comm data receiver aborted.\n");
  50. }
  51. }
  52. static void usb6fire_comm_init_buffer(u8 *buffer, u8 id, u8 request,
  53. u8 reg, u8 vl, u8 vh)
  54. {
  55. buffer[0] = 0x01;
  56. buffer[2] = request;
  57. buffer[3] = id;
  58. switch (request) {
  59. case 0x02:
  60. buffer[1] = 0x05; /* length (starting at buffer[2]) */
  61. buffer[4] = reg;
  62. buffer[5] = vl;
  63. buffer[6] = vh;
  64. break;
  65. case 0x12:
  66. buffer[1] = 0x0b; /* length (starting at buffer[2]) */
  67. buffer[4] = 0x00;
  68. buffer[5] = 0x18;
  69. buffer[6] = 0x05;
  70. buffer[7] = 0x00;
  71. buffer[8] = 0x01;
  72. buffer[9] = 0x00;
  73. buffer[10] = 0x9e;
  74. buffer[11] = reg;
  75. buffer[12] = vl;
  76. break;
  77. case 0x20:
  78. case 0x21:
  79. case 0x22:
  80. buffer[1] = 0x04;
  81. buffer[4] = reg;
  82. buffer[5] = vl;
  83. break;
  84. }
  85. }
  86. static int usb6fire_comm_send_buffer(u8 *buffer, struct usb_device *dev)
  87. {
  88. int ret;
  89. int actual_len;
  90. ret = usb_interrupt_msg(dev, usb_sndintpipe(dev, COMM_EP),
  91. buffer, buffer[1] + 2, &actual_len, HZ);
  92. if (ret < 0)
  93. return ret;
  94. else if (actual_len != buffer[1] + 2)
  95. return -EIO;
  96. return 0;
  97. }
  98. static int usb6fire_comm_write8(struct comm_runtime *rt, u8 request,
  99. u8 reg, u8 value)
  100. {
  101. u8 *buffer;
  102. int ret;
  103. /* 13: maximum length of message */
  104. buffer = kmalloc(13, GFP_KERNEL);
  105. if (!buffer)
  106. return -ENOMEM;
  107. usb6fire_comm_init_buffer(buffer, 0x00, request, reg, value, 0x00);
  108. ret = usb6fire_comm_send_buffer(buffer, rt->chip->dev);
  109. kfree(buffer);
  110. return ret;
  111. }
  112. static int usb6fire_comm_write16(struct comm_runtime *rt, u8 request,
  113. u8 reg, u8 vl, u8 vh)
  114. {
  115. u8 *buffer;
  116. int ret;
  117. /* 13: maximum length of message */
  118. buffer = kmalloc(13, GFP_KERNEL);
  119. if (!buffer)
  120. return -ENOMEM;
  121. usb6fire_comm_init_buffer(buffer, 0x00, request, reg, vl, vh);
  122. ret = usb6fire_comm_send_buffer(buffer, rt->chip->dev);
  123. kfree(buffer);
  124. return ret;
  125. }
  126. int __devinit usb6fire_comm_init(struct sfire_chip *chip)
  127. {
  128. struct comm_runtime *rt = kzalloc(sizeof(struct comm_runtime),
  129. GFP_KERNEL);
  130. struct urb *urb = &rt->receiver;
  131. int ret;
  132. if (!rt)
  133. return -ENOMEM;
  134. rt->receiver_buffer = kzalloc(COMM_RECEIVER_BUFSIZE, GFP_KERNEL);
  135. if (!rt->receiver_buffer) {
  136. kfree(rt);
  137. return -ENOMEM;
  138. }
  139. rt->serial = 1;
  140. rt->chip = chip;
  141. usb_init_urb(urb);
  142. rt->init_urb = usb6fire_comm_init_urb;
  143. rt->write8 = usb6fire_comm_write8;
  144. rt->write16 = usb6fire_comm_write16;
  145. /* submit an urb that receives communication data from device */
  146. urb->transfer_buffer = rt->receiver_buffer;
  147. urb->transfer_buffer_length = COMM_RECEIVER_BUFSIZE;
  148. urb->pipe = usb_rcvintpipe(chip->dev, COMM_EP);
  149. urb->dev = chip->dev;
  150. urb->complete = usb6fire_comm_receiver_handler;
  151. urb->context = rt;
  152. urb->interval = 1;
  153. ret = usb_submit_urb(urb, GFP_KERNEL);
  154. if (ret < 0) {
  155. kfree(rt->receiver_buffer);
  156. kfree(rt);
  157. snd_printk(KERN_ERR PREFIX "cannot create comm data receiver.");
  158. return ret;
  159. }
  160. chip->comm = rt;
  161. return 0;
  162. }
  163. void usb6fire_comm_abort(struct sfire_chip *chip)
  164. {
  165. struct comm_runtime *rt = chip->comm;
  166. if (rt)
  167. usb_poison_urb(&rt->receiver);
  168. }
  169. void usb6fire_comm_destroy(struct sfire_chip *chip)
  170. {
  171. struct comm_runtime *rt = chip->comm;
  172. kfree(rt->receiver_buffer);
  173. kfree(rt);
  174. chip->comm = NULL;
  175. }