comm.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  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[13]; /* 13: maximum length of message */
  102. usb6fire_comm_init_buffer(buffer, 0x00, request, reg, value, 0x00);
  103. return usb6fire_comm_send_buffer(buffer, rt->chip->dev);
  104. }
  105. static int usb6fire_comm_write16(struct comm_runtime *rt, u8 request,
  106. u8 reg, u8 vl, u8 vh)
  107. {
  108. u8 buffer[13]; /* 13: maximum length of message */
  109. usb6fire_comm_init_buffer(buffer, 0x00, request, reg, vl, vh);
  110. return usb6fire_comm_send_buffer(buffer, rt->chip->dev);
  111. }
  112. int __devinit usb6fire_comm_init(struct sfire_chip *chip)
  113. {
  114. struct comm_runtime *rt = kzalloc(sizeof(struct comm_runtime),
  115. GFP_KERNEL);
  116. struct urb *urb = &rt->receiver;
  117. int ret;
  118. if (!rt)
  119. return -ENOMEM;
  120. rt->serial = 1;
  121. rt->chip = chip;
  122. usb_init_urb(urb);
  123. rt->init_urb = usb6fire_comm_init_urb;
  124. rt->write8 = usb6fire_comm_write8;
  125. rt->write16 = usb6fire_comm_write16;
  126. /* submit an urb that receives communication data from device */
  127. urb->transfer_buffer = rt->receiver_buffer;
  128. urb->transfer_buffer_length = COMM_RECEIVER_BUFSIZE;
  129. urb->pipe = usb_rcvintpipe(chip->dev, COMM_EP);
  130. urb->dev = chip->dev;
  131. urb->complete = usb6fire_comm_receiver_handler;
  132. urb->context = rt;
  133. urb->interval = 1;
  134. ret = usb_submit_urb(urb, GFP_KERNEL);
  135. if (ret < 0) {
  136. kfree(rt);
  137. snd_printk(KERN_ERR PREFIX "cannot create comm data receiver.");
  138. return ret;
  139. }
  140. chip->comm = rt;
  141. return 0;
  142. }
  143. void usb6fire_comm_abort(struct sfire_chip *chip)
  144. {
  145. struct comm_runtime *rt = chip->comm;
  146. if (rt)
  147. usb_poison_urb(&rt->receiver);
  148. }
  149. void usb6fire_comm_destroy(struct sfire_chip *chip)
  150. {
  151. kfree(chip->comm);
  152. chip->comm = NULL;
  153. }