comm.c 4.0 KB

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