1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133#include <sound/driver.h>
134#include <linux/init.h>
135#include <linux/module.h>
136#include <linux/moduleparam.h>
137#include <linux/interrupt.h>
138#include <linux/usb.h>
139#include <sound/core.h>
140#include <sound/initval.h>
141#include <sound/pcm.h>
142
143#include <sound/rawmidi.h>
144#include "usx2y.h"
145#include "usbusx2y.h"
146#include "usX2Yhwdep.h"
147
148
149
150MODULE_AUTHOR("Karsten Wiese <annabellesgarden@yahoo.de>");
151MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS" Version 0.8.7.2");
152MODULE_LICENSE("GPL");
153MODULE_SUPPORTED_DEVICE("{{TASCAM(0x1604), "NAME_ALLCAPS"(0x8001)(0x8005)(0x8007) }}");
154
155static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
156static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
157static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
158
159module_param_array(index, int, NULL, 0444);
160MODULE_PARM_DESC(index, "Index value for "NAME_ALLCAPS".");
161module_param_array(id, charp, NULL, 0444);
162MODULE_PARM_DESC(id, "ID string for "NAME_ALLCAPS".");
163module_param_array(enable, bool, NULL, 0444);
164MODULE_PARM_DESC(enable, "Enable "NAME_ALLCAPS".");
165
166
167static int snd_usX2Y_card_used[SNDRV_CARDS];
168
169static void usX2Y_usb_disconnect(struct usb_device* usb_device, void* ptr);
170static void snd_usX2Y_card_private_free(struct snd_card *card);
171
172
173
174
175static void i_usX2Y_Out04Int(struct urb *urb)
176{
177#ifdef CONFIG_SND_DEBUG
178 if (urb->status) {
179 int i;
180 struct usX2Ydev *usX2Y = urb->context;
181 for (i = 0; i < 10 && usX2Y->AS04.urb[i] != urb; i++);
182 snd_printdd("i_usX2Y_Out04Int() urb %i status=%i\n", i, urb->status);
183 }
184#endif
185}
186
187static void i_usX2Y_In04Int(struct urb *urb)
188{
189 int err = 0;
190 struct usX2Ydev *usX2Y = urb->context;
191 struct us428ctls_sharedmem *us428ctls = usX2Y->us428ctls_sharedmem;
192
193 usX2Y->In04IntCalls++;
194
195 if (urb->status) {
196 snd_printdd("Interrupt Pipe 4 came back with status=%i\n", urb->status);
197 return;
198 }
199
200
201 if (us428ctls) {
202 int diff = -1;
203 if (-2 == us428ctls->CtlSnapShotLast) {
204 diff = 0;
205 memcpy(usX2Y->In04Last, usX2Y->In04Buf, sizeof(usX2Y->In04Last));
206 us428ctls->CtlSnapShotLast = -1;
207 } else {
208 int i;
209 for (i = 0; i < 21; i++) {
210 if (usX2Y->In04Last[i] != ((char*)usX2Y->In04Buf)[i]) {
211 if (diff < 0)
212 diff = i;
213 usX2Y->In04Last[i] = ((char*)usX2Y->In04Buf)[i];
214 }
215 }
216 }
217 if (0 <= diff) {
218 int n = us428ctls->CtlSnapShotLast + 1;
219 if (n >= N_us428_ctl_BUFS || n < 0)
220 n = 0;
221 memcpy(us428ctls->CtlSnapShot + n, usX2Y->In04Buf, sizeof(us428ctls->CtlSnapShot[0]));
222 us428ctls->CtlSnapShotDiffersAt[n] = diff;
223 us428ctls->CtlSnapShotLast = n;
224 wake_up(&usX2Y->us428ctls_wait_queue_head);
225 }
226 }
227
228
229 if (usX2Y->US04) {
230 if (0 == usX2Y->US04->submitted)
231 do
232 err = usb_submit_urb(usX2Y->US04->urb[usX2Y->US04->submitted++], GFP_ATOMIC);
233 while (!err && usX2Y->US04->submitted < usX2Y->US04->len);
234 } else
235 if (us428ctls && us428ctls->p4outLast >= 0 && us428ctls->p4outLast < N_us428_p4out_BUFS) {
236 if (us428ctls->p4outLast != us428ctls->p4outSent) {
237 int j, send = us428ctls->p4outSent + 1;
238 if (send >= N_us428_p4out_BUFS)
239 send = 0;
240 for (j = 0; j < URBS_AsyncSeq && !err; ++j)
241 if (0 == usX2Y->AS04.urb[j]->status) {
242 struct us428_p4out *p4out = us428ctls->p4out + send;
243 usb_fill_bulk_urb(usX2Y->AS04.urb[j], usX2Y->chip.dev,
244 usb_sndbulkpipe(usX2Y->chip.dev, 0x04), &p4out->val.vol,
245 p4out->type == eLT_Light ? sizeof(struct us428_lights) : 5,
246 i_usX2Y_Out04Int, usX2Y);
247 err = usb_submit_urb(usX2Y->AS04.urb[j], GFP_ATOMIC);
248 us428ctls->p4outSent = send;
249 break;
250 }
251 }
252 }
253
254 if (err)
255 snd_printk(KERN_ERR "In04Int() usb_submit_urb err=%i\n", err);
256
257 urb->dev = usX2Y->chip.dev;
258 usb_submit_urb(urb, GFP_ATOMIC);
259}
260
261
262
263
264int usX2Y_AsyncSeq04_init(struct usX2Ydev *usX2Y)
265{
266 int err = 0,
267 i;
268
269 if (NULL == (usX2Y->AS04.buffer = kmalloc(URB_DataLen_AsyncSeq*URBS_AsyncSeq, GFP_KERNEL))) {
270 err = -ENOMEM;
271 } else
272 for (i = 0; i < URBS_AsyncSeq; ++i) {
273 if (NULL == (usX2Y->AS04.urb[i] = usb_alloc_urb(0, GFP_KERNEL))) {
274 err = -ENOMEM;
275 break;
276 }
277 usb_fill_bulk_urb( usX2Y->AS04.urb[i], usX2Y->chip.dev,
278 usb_sndbulkpipe(usX2Y->chip.dev, 0x04),
279 usX2Y->AS04.buffer + URB_DataLen_AsyncSeq*i, 0,
280 i_usX2Y_Out04Int, usX2Y
281 );
282 }
283 return err;
284}
285
286int usX2Y_In04_init(struct usX2Ydev *usX2Y)
287{
288 if (! (usX2Y->In04urb = usb_alloc_urb(0, GFP_KERNEL)))
289 return -ENOMEM;
290
291 if (! (usX2Y->In04Buf = kmalloc(21, GFP_KERNEL))) {
292 usb_free_urb(usX2Y->In04urb);
293 return -ENOMEM;
294 }
295
296 init_waitqueue_head(&usX2Y->In04WaitQueue);
297 usb_fill_int_urb(usX2Y->In04urb, usX2Y->chip.dev, usb_rcvintpipe(usX2Y->chip.dev, 0x4),
298 usX2Y->In04Buf, 21,
299 i_usX2Y_In04Int, usX2Y,
300 10);
301 return usb_submit_urb(usX2Y->In04urb, GFP_KERNEL);
302}
303
304static void usX2Y_unlinkSeq(struct snd_usX2Y_AsyncSeq *S)
305{
306 int i;
307 for (i = 0; i < URBS_AsyncSeq; ++i) {
308 if (S[i].urb) {
309 usb_kill_urb(S->urb[i]);
310 usb_free_urb(S->urb[i]);
311 S->urb[i] = NULL;
312 }
313 }
314 kfree(S->buffer);
315}
316
317
318static struct usb_device_id snd_usX2Y_usb_id_table[] = {
319 {
320 .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
321 .idVendor = 0x1604,
322 .idProduct = USB_ID_US428
323 },
324 {
325 .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
326 .idVendor = 0x1604,
327 .idProduct = USB_ID_US122
328 },
329 {
330 .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
331 .idVendor = 0x1604,
332 .idProduct = USB_ID_US224
333 },
334 { }
335};
336
337static struct snd_card *usX2Y_create_card(struct usb_device *device)
338{
339 int dev;
340 struct snd_card * card;
341 for (dev = 0; dev < SNDRV_CARDS; ++dev)
342 if (enable[dev] && !snd_usX2Y_card_used[dev])
343 break;
344 if (dev >= SNDRV_CARDS)
345 return NULL;
346 card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct usX2Ydev));
347 if (!card)
348 return NULL;
349 snd_usX2Y_card_used[usX2Y(card)->chip.index = dev] = 1;
350 card->private_free = snd_usX2Y_card_private_free;
351 usX2Y(card)->chip.dev = device;
352 usX2Y(card)->chip.card = card;
353 init_waitqueue_head(&usX2Y(card)->prepare_wait_queue);
354 mutex_init(&usX2Y(card)->prepare_mutex);
355 INIT_LIST_HEAD(&usX2Y(card)->chip.midi_list);
356 strcpy(card->driver, "USB "NAME_ALLCAPS"");
357 sprintf(card->shortname, "TASCAM "NAME_ALLCAPS"");
358 sprintf(card->longname, "%s (%x:%x if %d at %03d/%03d)",
359 card->shortname,
360 le16_to_cpu(device->descriptor.idVendor),
361 le16_to_cpu(device->descriptor.idProduct),
362 0,
363 usX2Y(card)->chip.dev->bus->busnum, usX2Y(card)->chip.dev->devnum
364 );
365 snd_card_set_dev(card, &device->dev);
366 return card;
367}
368
369
370static void *usX2Y_usb_probe(struct usb_device *device, struct usb_interface *intf, const struct usb_device_id *device_id)
371{
372 int err;
373 struct snd_card * card;
374 if (le16_to_cpu(device->descriptor.idVendor) != 0x1604 ||
375 (le16_to_cpu(device->descriptor.idProduct) != USB_ID_US122 &&
376 le16_to_cpu(device->descriptor.idProduct) != USB_ID_US224 &&
377 le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428) ||
378 !(card = usX2Y_create_card(device)))
379 return NULL;
380 if ((err = usX2Y_hwdep_new(card, device)) < 0 ||
381 (err = snd_card_register(card)) < 0) {
382 snd_card_free(card);
383 return NULL;
384 }
385 return card;
386}
387
388
389
390
391static int snd_usX2Y_probe(struct usb_interface *intf, const struct usb_device_id *id)
392{
393 void *chip;
394 chip = usX2Y_usb_probe(interface_to_usbdev(intf), intf, id);
395 if (chip) {
396 dev_set_drvdata(&intf->dev, chip);
397 return 0;
398 } else
399 return -EIO;
400}
401
402static void snd_usX2Y_disconnect(struct usb_interface *intf)
403{
404 usX2Y_usb_disconnect(interface_to_usbdev(intf),
405 dev_get_drvdata(&intf->dev));
406}
407
408MODULE_DEVICE_TABLE(usb, snd_usX2Y_usb_id_table);
409static struct usb_driver snd_usX2Y_usb_driver = {
410 .name = "snd-usb-usx2y",
411 .probe = snd_usX2Y_probe,
412 .disconnect = snd_usX2Y_disconnect,
413 .id_table = snd_usX2Y_usb_id_table,
414};
415
416static void snd_usX2Y_card_private_free(struct snd_card *card)
417{
418 kfree(usX2Y(card)->In04Buf);
419 usb_free_urb(usX2Y(card)->In04urb);
420 if (usX2Y(card)->us428ctls_sharedmem)
421 snd_free_pages(usX2Y(card)->us428ctls_sharedmem, sizeof(*usX2Y(card)->us428ctls_sharedmem));
422 if (usX2Y(card)->chip.index >= 0 && usX2Y(card)->chip.index < SNDRV_CARDS)
423 snd_usX2Y_card_used[usX2Y(card)->chip.index] = 0;
424}
425
426
427
428
429static void usX2Y_usb_disconnect(struct usb_device *device, void* ptr)
430{
431 if (ptr) {
432 struct snd_card *card = ptr;
433 struct usX2Ydev *usX2Y = usX2Y(card);
434 struct list_head *p;
435 usX2Y->chip.shutdown = 1;
436 usX2Y->chip_status = USX2Y_STAT_CHIP_HUP;
437 usX2Y_unlinkSeq(&usX2Y->AS04);
438 usb_kill_urb(usX2Y->In04urb);
439 snd_card_disconnect(card);
440
441 list_for_each(p, &usX2Y->chip.midi_list) {
442 snd_usbmidi_disconnect(p);
443 }
444 if (usX2Y->us428ctls_sharedmem)
445 wake_up(&usX2Y->us428ctls_wait_queue_head);
446 snd_card_free(card);
447 }
448}
449
450static int __init snd_usX2Y_module_init(void)
451{
452 return usb_register(&snd_usX2Y_usb_driver);
453}
454
455static void __exit snd_usX2Y_module_exit(void)
456{
457 usb_deregister(&snd_usX2Y_usb_driver);
458}
459
460module_init(snd_usX2Y_module_init)
461module_exit(snd_usX2Y_module_exit)
462