chip.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*
  2. * Linux driver for TerraTec DMX 6Fire USB
  3. *
  4. * Main routines and module definitions.
  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 "chip.h"
  17. #include "firmware.h"
  18. #include "pcm.h"
  19. #include "control.h"
  20. #include "comm.h"
  21. #include "midi.h"
  22. #include <linux/moduleparam.h>
  23. #include <linux/interrupt.h>
  24. #include <linux/module.h>
  25. #include <linux/init.h>
  26. #include <linux/gfp.h>
  27. #include <sound/initval.h>
  28. MODULE_AUTHOR("Torsten Schenk <torsten.schenk@zoho.com>");
  29. MODULE_DESCRIPTION("TerraTec DMX 6Fire USB audio driver, version 0.3.0");
  30. MODULE_LICENSE("GPL v2");
  31. MODULE_SUPPORTED_DEVICE("{{TerraTec, DMX 6Fire USB}}");
  32. static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
  33. static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for card */
  34. static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable card */
  35. static struct sfire_chip *chips[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
  36. static struct usb_device *devices[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
  37. module_param_array(index, int, NULL, 0444);
  38. MODULE_PARM_DESC(index, "Index value for the 6fire sound device");
  39. module_param_array(id, charp, NULL, 0444);
  40. MODULE_PARM_DESC(id, "ID string for the 6fire sound device.");
  41. module_param_array(enable, bool, NULL, 0444);
  42. MODULE_PARM_DESC(enable, "Enable the 6fire sound device.");
  43. static DEFINE_MUTEX(register_mutex);
  44. static void usb6fire_chip_abort(struct sfire_chip *chip)
  45. {
  46. if (chip) {
  47. if (chip->pcm)
  48. usb6fire_pcm_abort(chip);
  49. if (chip->midi)
  50. usb6fire_midi_abort(chip);
  51. if (chip->comm)
  52. usb6fire_comm_abort(chip);
  53. if (chip->control)
  54. usb6fire_control_abort(chip);
  55. if (chip->card) {
  56. snd_card_disconnect(chip->card);
  57. snd_card_free_when_closed(chip->card);
  58. chip->card = NULL;
  59. }
  60. }
  61. }
  62. static void usb6fire_chip_destroy(struct sfire_chip *chip)
  63. {
  64. if (chip) {
  65. if (chip->pcm)
  66. usb6fire_pcm_destroy(chip);
  67. if (chip->midi)
  68. usb6fire_midi_destroy(chip);
  69. if (chip->comm)
  70. usb6fire_comm_destroy(chip);
  71. if (chip->control)
  72. usb6fire_control_destroy(chip);
  73. if (chip->card)
  74. snd_card_free(chip->card);
  75. }
  76. }
  77. static int __devinit usb6fire_chip_probe(struct usb_interface *intf,
  78. const struct usb_device_id *usb_id)
  79. {
  80. int ret;
  81. int i;
  82. struct sfire_chip *chip = NULL;
  83. struct usb_device *device = interface_to_usbdev(intf);
  84. int regidx = -1; /* index in module parameter array */
  85. struct snd_card *card = NULL;
  86. /* look if we already serve this card and return if so */
  87. mutex_lock(&register_mutex);
  88. for (i = 0; i < SNDRV_CARDS; i++) {
  89. if (devices[i] == device) {
  90. if (chips[i])
  91. chips[i]->intf_count++;
  92. usb_set_intfdata(intf, chips[i]);
  93. mutex_unlock(&register_mutex);
  94. return 0;
  95. } else if (regidx < 0)
  96. regidx = i;
  97. }
  98. if (regidx < 0) {
  99. mutex_unlock(&register_mutex);
  100. snd_printk(KERN_ERR PREFIX "too many cards registered.\n");
  101. return -ENODEV;
  102. }
  103. devices[regidx] = device;
  104. mutex_unlock(&register_mutex);
  105. /* check, if firmware is present on device, upload it if not */
  106. ret = usb6fire_fw_init(intf);
  107. if (ret < 0)
  108. return ret;
  109. else if (ret == FW_NOT_READY) /* firmware update performed */
  110. return 0;
  111. /* if we are here, card can be registered in alsa. */
  112. if (usb_set_interface(device, 0, 0) != 0) {
  113. snd_printk(KERN_ERR PREFIX "can't set first interface.\n");
  114. return -EIO;
  115. }
  116. ret = snd_card_create(index[regidx], id[regidx], THIS_MODULE,
  117. sizeof(struct sfire_chip), &card);
  118. if (ret < 0) {
  119. snd_printk(KERN_ERR PREFIX "cannot create alsa card.\n");
  120. return ret;
  121. }
  122. strcpy(card->driver, "6FireUSB");
  123. strcpy(card->shortname, "TerraTec DMX6FireUSB");
  124. sprintf(card->longname, "%s at %d:%d", card->shortname,
  125. device->bus->busnum, device->devnum);
  126. snd_card_set_dev(card, &intf->dev);
  127. chip = card->private_data;
  128. chips[regidx] = chip;
  129. chip->dev = device;
  130. chip->regidx = regidx;
  131. chip->intf_count = 1;
  132. chip->card = card;
  133. ret = usb6fire_comm_init(chip);
  134. if (ret < 0) {
  135. usb6fire_chip_destroy(chip);
  136. return ret;
  137. }
  138. ret = usb6fire_midi_init(chip);
  139. if (ret < 0) {
  140. usb6fire_chip_destroy(chip);
  141. return ret;
  142. }
  143. ret = usb6fire_pcm_init(chip);
  144. if (ret < 0) {
  145. usb6fire_chip_destroy(chip);
  146. return ret;
  147. }
  148. ret = usb6fire_control_init(chip);
  149. if (ret < 0) {
  150. usb6fire_chip_destroy(chip);
  151. return ret;
  152. }
  153. ret = snd_card_register(card);
  154. if (ret < 0) {
  155. snd_printk(KERN_ERR PREFIX "cannot register card.");
  156. usb6fire_chip_destroy(chip);
  157. return ret;
  158. }
  159. usb_set_intfdata(intf, chip);
  160. return 0;
  161. }
  162. static void usb6fire_chip_disconnect(struct usb_interface *intf)
  163. {
  164. struct sfire_chip *chip;
  165. struct snd_card *card;
  166. chip = usb_get_intfdata(intf);
  167. if (chip) { /* if !chip, fw upload has been performed */
  168. card = chip->card;
  169. chip->intf_count--;
  170. if (!chip->intf_count) {
  171. mutex_lock(&register_mutex);
  172. devices[chip->regidx] = NULL;
  173. chips[chip->regidx] = NULL;
  174. mutex_unlock(&register_mutex);
  175. chip->shutdown = true;
  176. usb6fire_chip_abort(chip);
  177. usb6fire_chip_destroy(chip);
  178. }
  179. }
  180. }
  181. static struct usb_device_id device_table[] = {
  182. {
  183. .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
  184. .idVendor = 0x0ccd,
  185. .idProduct = 0x0080
  186. },
  187. {}
  188. };
  189. MODULE_DEVICE_TABLE(usb, device_table);
  190. static struct usb_driver driver = {
  191. .name = "snd-usb-6fire",
  192. .probe = usb6fire_chip_probe,
  193. .disconnect = usb6fire_chip_disconnect,
  194. .id_table = device_table,
  195. };
  196. static int __init usb6fire_chip_init(void)
  197. {
  198. return usb_register(&driver);
  199. }
  200. static void __exit usb6fire_chip_cleanup(void)
  201. {
  202. usb_deregister(&driver);
  203. }
  204. module_init(usb6fire_chip_init);
  205. module_exit(usb6fire_chip_cleanup);