2 * Linux driver for TerraTec DMX 6Fire USB
4 * Main routines and module definitions.
6 * Author: Torsten Schenk <torsten.schenk@zoho.com>
7 * Created: Jan 01, 2011
9 * Copyright: (C) Torsten Schenk
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.
24 #include <linux/moduleparam.h>
25 #include <linux/interrupt.h>
26 #include <linux/module.h>
27 #include <linux/init.h>
28 #include <linux/gfp.h>
29 #include <sound/initval.h>
31 MODULE_AUTHOR("Torsten Schenk <torsten.schenk@zoho.com>");
32 MODULE_DESCRIPTION("TerraTec DMX 6Fire USB audio driver, version 0.3.0");
33 MODULE_LICENSE("GPL v2");
34 MODULE_SUPPORTED_DEVICE("{{TerraTec, DMX 6Fire USB}}");
36 static int index
[SNDRV_CARDS
] = SNDRV_DEFAULT_IDX
; /* Index 0-max */
37 static char *id
[SNDRV_CARDS
] = SNDRV_DEFAULT_STR
; /* Id for card */
38 static int enable
[SNDRV_CARDS
] = SNDRV_DEFAULT_ENABLE_PNP
; /* Enable card */
39 static struct sfire_chip
*chips
[SNDRV_CARDS
] = SNDRV_DEFAULT_PTR
;
40 static struct usb_device
*devices
[SNDRV_CARDS
] = SNDRV_DEFAULT_PTR
;
42 module_param_array(index
, int, NULL
, 0444);
43 MODULE_PARM_DESC(index
, "Index value for the 6fire sound device");
44 module_param_array(id
, charp
, NULL
, 0444);
45 MODULE_PARM_DESC(id
, "ID string for the 6fire sound device.");
46 module_param_array(enable
, bool, NULL
, 0444);
47 MODULE_PARM_DESC(enable
, "Enable the 6fire sound device.");
49 static DEFINE_MUTEX(register_mutex
);
51 static void usb6fire_chip_abort(struct sfire_chip
*chip
)
55 usb6fire_pcm_abort(chip
);
57 usb6fire_midi_abort(chip
);
59 usb6fire_comm_abort(chip
);
61 usb6fire_control_abort(chip
);
63 snd_card_disconnect(chip
->card
);
64 snd_card_free_when_closed(chip
->card
);
70 static void usb6fire_chip_destroy(struct sfire_chip
*chip
)
74 usb6fire_pcm_destroy(chip
);
76 usb6fire_midi_destroy(chip
);
78 usb6fire_comm_destroy(chip
);
80 usb6fire_control_destroy(chip
);
82 snd_card_free(chip
->card
);
86 static int __devinit
usb6fire_chip_probe(struct usb_interface
*intf
,
87 const struct usb_device_id
*usb_id
)
91 struct sfire_chip
*chip
= NULL
;
92 struct usb_device
*device
= interface_to_usbdev(intf
);
93 int regidx
= -1; /* index in module parameter array */
94 struct snd_card
*card
= NULL
;
96 /* look if we already serve this card and return if so */
97 mutex_lock(®ister_mutex
);
98 for (i
= 0; i
< SNDRV_CARDS
; i
++) {
99 if (devices
[i
] == device
) {
101 chips
[i
]->intf_count
++;
102 usb_set_intfdata(intf
, chips
[i
]);
103 mutex_unlock(®ister_mutex
);
105 } else if (regidx
< 0)
109 mutex_unlock(®ister_mutex
);
110 snd_printk(KERN_ERR PREFIX
"too many cards registered.\n");
113 devices
[regidx
] = device
;
114 mutex_unlock(®ister_mutex
);
116 /* check, if firmware is present on device, upload it if not */
117 ret
= usb6fire_fw_init(intf
);
120 else if (ret
== FW_NOT_READY
) /* firmware update performed */
123 /* if we are here, card can be registered in alsa. */
124 if (usb_set_interface(device
, 0, 0) != 0) {
125 snd_printk(KERN_ERR PREFIX
"can't set first interface.\n");
128 ret
= snd_card_create(index
[regidx
], id
[regidx
], THIS_MODULE
,
129 sizeof(struct sfire_chip
), &card
);
131 snd_printk(KERN_ERR PREFIX
"cannot create alsa card.\n");
134 strcpy(card
->driver
, "6FireUSB");
135 strcpy(card
->shortname
, "TerraTec DMX6FireUSB");
136 sprintf(card
->longname
, "%s at %d:%d", card
->shortname
,
137 device
->bus
->busnum
, device
->devnum
);
138 snd_card_set_dev(card
, &intf
->dev
);
140 chip
= card
->private_data
;
141 chips
[regidx
] = chip
;
143 chip
->regidx
= regidx
;
144 chip
->intf_count
= 1;
147 ret
= usb6fire_comm_init(chip
);
149 usb6fire_chip_destroy(chip
);
153 ret
= usb6fire_midi_init(chip
);
155 usb6fire_chip_destroy(chip
);
159 ret
= usb6fire_pcm_init(chip
);
161 usb6fire_chip_destroy(chip
);
165 ret
= usb6fire_control_init(chip
);
167 usb6fire_chip_destroy(chip
);
171 ret
= snd_card_register(card
);
173 snd_printk(KERN_ERR PREFIX
"cannot register card.");
174 usb6fire_chip_destroy(chip
);
177 usb_set_intfdata(intf
, chip
);
181 static void usb6fire_chip_disconnect(struct usb_interface
*intf
)
183 struct sfire_chip
*chip
;
184 struct snd_card
*card
;
186 chip
= usb_get_intfdata(intf
);
187 if (chip
) { /* if !chip, fw upload has been performed */
190 if (!chip
->intf_count
) {
191 mutex_lock(®ister_mutex
);
192 devices
[chip
->regidx
] = NULL
;
193 chips
[chip
->regidx
] = NULL
;
194 mutex_unlock(®ister_mutex
);
196 chip
->shutdown
= true;
197 usb6fire_chip_abort(chip
);
198 usb6fire_chip_destroy(chip
);
203 static struct usb_device_id device_table
[] = {
205 .match_flags
= USB_DEVICE_ID_MATCH_DEVICE
,
212 MODULE_DEVICE_TABLE(usb
, device_table
);
214 static struct usb_driver driver
= {
215 .name
= "snd-usb-6fire",
216 .probe
= usb6fire_chip_probe
,
217 .disconnect
= usb6fire_chip_disconnect
,
218 .id_table
= device_table
,
221 static int __init
usb6fire_chip_init(void)
223 return usb_register(&driver
);
226 static void __exit
usb6fire_chip_cleanup(void)
228 usb_deregister(&driver
);
231 module_init(usb6fire_chip_init
);
232 module_exit(usb6fire_chip_cleanup
);