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 <linux/init.h>
134#include <linux/module.h>
135#include <linux/moduleparam.h>
136#include <linux/interrupt.h>
137#include <linux/usb.h>
138#include <sound/core.h>
139#include <sound/initval.h>
140#include <sound/pcm.h>
141
142#include <sound/rawmidi.h>
143#include "usx2y.h"
144#include "usbusx2y.h"
145#include "usX2Yhwdep.h"
146
147
148
149MODULE_AUTHOR("Karsten Wiese <annabellesgarden@yahoo.de>");
150MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS" Version 0.8.7.2");
151MODULE_LICENSE("GPL");
152MODULE_SUPPORTED_DEVICE("{{TASCAM(0x1604), "NAME_ALLCAPS"(0x8001)(0x8005)(0x8007) }}");
153
154static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
155static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
156static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
157
158module_param_array(index, int, NULL, 0444);
159MODULE_PARM_DESC(index, "Index value for "NAME_ALLCAPS".");
160module_param_array(id, charp, NULL, 0444);
161MODULE_PARM_DESC(id, "ID string for "NAME_ALLCAPS".");
162module_param_array(enable, bool, NULL, 0444);
163MODULE_PARM_DESC(enable, "Enable "NAME_ALLCAPS".");
164
165
166static int snd_usX2Y_card_used[SNDRV_CARDS];
167
168static void usX2Y_usb_disconnect(struct usb_device* usb_device, void* ptr);
169static void snd_usX2Y_card_private_free(struct snd_card *card);
170
171
172
173
174static void i_usX2Y_Out04Int(struct urb *urb)
175{
176#ifdef CONFIG_SND_DEBUG
177 if (urb->status) {
178 int i;
179 struct usX2Ydev *usX2Y = urb->context;
180 for (i = 0; i < 10 && usX2Y->AS04.urb[i] != urb; i++);
181 snd_printdd("i_usX2Y_Out04Int() urb %i status=%i\n", i, urb->status);
182 }
183#endif
184}
185
186static void i_usX2Y_In04Int(struct urb *urb)
187{
188 int err = 0;
189 struct usX2Ydev *usX2Y = urb->context;
190 struct us428ctls_sharedmem *us428ctls = usX2Y->us428ctls_sharedmem;
191
192 usX2Y->In04IntCalls++;
193
194 if (urb->status) {
195 snd_printdd("Interrupt Pipe 4 came back with status=%i\n", urb->status);
196 return;
197 }
198
199
200 if (us428ctls) {
201 int diff = -1;
202 if (-2 == us428ctls->CtlSnapShotLast) {
203 diff = 0;
204 memcpy(usX2Y->In04Last, usX2Y->In04Buf, sizeof(usX2Y->In04Last));
205 us428ctls->CtlSnapShotLast = -1;
206 } else {
207 int i;
208 for (i = 0; i < 21; i++) {
209 if (usX2Y->In04Last[i] != ((char*)usX2Y->In04Buf)[i]) {
210 if (diff < 0)
211 diff = i;
212 usX2Y->In04Last[i] = ((char*)usX2Y->In04Buf)[i];
213 }
214 }
215 }
216 if (0 <= diff) {
217 int n = us428ctls->CtlSnapShotLast + 1;
218 if (n >= N_us428_ctl_BUFS || n < 0)
219 n = 0;
220 memcpy(us428ctls->CtlSnapShot + n, usX2Y->In04Buf, sizeof(us428ctls->CtlSnapShot[0]));
221 us428ctls->CtlSnapShotDiffersAt[n] = diff;
222 us428ctls->CtlSnapShotLast = n;
223 wake_up(&usX2Y->us428ctls_wait_queue_head);
224 }
225 }
226
227
228 if (usX2Y->US04) {
229 if (0 == usX2Y->US04->submitted)
230 do {
231 err = usb_submit_urb(usX2Y->US04->urb[usX2Y->US04->submitted++], GFP_ATOMIC);
232 } while (!err && usX2Y->US04->submitted < usX2Y->US04->len);
233 } else
234 if (us428ctls && us428ctls->p4outLast >= 0 && us428ctls->p4outLast < N_us428_p4out_BUFS) {
235 if (us428ctls->p4outLast != us428ctls->p4outSent) {
236 int j, send = us428ctls->p4outSent + 1;
237 if (send >= N_us428_p4out_BUFS)
238 send = 0;
239 for (j = 0; j < URBS_AsyncSeq && !err; ++j)
240 if (0 == usX2Y->AS04.urb[j]->status) {
241 struct us428_p4out *p4out = us428ctls->p4out + send;
242 usb_fill_bulk_urb(usX2Y->AS04.urb[j], usX2Y->chip.dev,
243 usb_sndbulkpipe(usX2Y->chip.dev, 0x04), &p4out->val.vol,
244 p4out->type == eLT_Light ? sizeof(struct us428_lights) : 5,
245 i_usX2Y_Out04Int, usX2Y);
246 err = usb_submit_urb(usX2Y->AS04.urb[j], GFP_ATOMIC);
247 us428ctls->p4outSent = send;
248 break;
249 }
250 }
251 }
252
253 if (err)
254 snd_printk(KERN_ERR "In04Int() usb_submit_urb err=%i\n", err);
255
256 urb->dev = usX2Y->chip.dev;
257 usb_submit_urb(urb, GFP_ATOMIC);
258}
259
260
261
262
263int usX2Y_AsyncSeq04_init(struct usX2Ydev *usX2Y)
264{
265 int err = 0,
266 i;
267
268 if (NULL == (usX2Y->AS04.buffer = kmalloc(URB_DataLen_AsyncSeq*URBS_AsyncSeq, GFP_KERNEL))) {
269 err = -ENOMEM;
270 } else
271 for (i = 0; i < URBS_AsyncSeq; ++i) {
272 if (NULL == (usX2Y->AS04.urb[i] = usb_alloc_urb(0, GFP_KERNEL))) {
273 err = -ENOMEM;
274 break;
275 }
276 usb_fill_bulk_urb( usX2Y->AS04.urb[i], usX2Y->chip.dev,
277 usb_sndbulkpipe(usX2Y->chip.dev, 0x04),
278 usX2Y->AS04.buffer + URB_DataLen_AsyncSeq*i, 0,
279 i_usX2Y_Out04Int, usX2Y
280 );
281 }
282 return err;
283}
284
285int usX2Y_In04_init(struct usX2Ydev *usX2Y)
286{
287 if (! (usX2Y->In04urb = usb_alloc_urb(0, GFP_KERNEL)))
288 return -ENOMEM;
289
290 if (! (usX2Y->In04Buf = kmalloc(21, GFP_KERNEL))) {
291 usb_free_urb(usX2Y->In04urb);
292 return -ENOMEM;
293 }
294
295 init_waitqueue_head(&usX2Y->In04WaitQueue);
296 usb_fill_int_urb(usX2Y->In04urb, usX2Y->chip.dev, usb_rcvintpipe(usX2Y->chip.dev, 0x4),
297 usX2Y->In04Buf, 21,
298 i_usX2Y_In04Int, usX2Y,
299 10);
300 return usb_submit_urb(usX2Y->In04urb, GFP_KERNEL);
301}
302
303static void usX2Y_unlinkSeq(struct snd_usX2Y_AsyncSeq *S)
304{
305 int i;
306 for (i = 0; i < URBS_AsyncSeq; ++i) {
307 if (S[i].urb) {
308 usb_kill_urb(S->urb[i]);
309 usb_free_urb(S->urb[i]);
310 S->urb[i] = NULL;
311 }
312 }
313 kfree(S->buffer);
314}
315
316
317static struct usb_device_id snd_usX2Y_usb_id_table[] = {
318 {
319 .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
320 .idVendor = 0x1604,
321 .idProduct = USB_ID_US428
322 },
323 {
324 .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
325 .idVendor = 0x1604,
326 .idProduct = USB_ID_US122
327 },
328 {
329 .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
330 .idVendor = 0x1604,
331 .idProduct = USB_ID_US224
332 },
333 { }
334};
335
336static int usX2Y_create_card(struct usb_device *device, struct snd_card **cardp)
337{
338 int dev;
339 struct snd_card * card;
340 int err;
341
342 for (dev = 0; dev < SNDRV_CARDS; ++dev)
343 if (enable[dev] && !snd_usX2Y_card_used[dev])
344 break;
345 if (dev >= SNDRV_CARDS)
346 return -ENODEV;
347 err = snd_card_create(index[dev], id[dev], THIS_MODULE,
348 sizeof(struct usX2Ydev), &card);
349 if (err < 0)
350 return err;
351 snd_usX2Y_card_used[usX2Y(card)->chip.index = dev] = 1;
352 card->private_free = snd_usX2Y_card_private_free;
353 usX2Y(card)->chip.dev = device;
354 usX2Y(card)->chip.card = card;
355 init_waitqueue_head(&usX2Y(card)->prepare_wait_queue);
356 mutex_init(&usX2Y(card)->prepare_mutex);
357 INIT_LIST_HEAD(&usX2Y(card)->chip.midi_list);
358 strcpy(card->driver, "USB "NAME_ALLCAPS"");
359 sprintf(card->shortname, "TASCAM "NAME_ALLCAPS"");
360 sprintf(card->longname, "%s (%x:%x if %d at %03d/%03d)",
361 card->shortname,
362 le16_to_cpu(device->descriptor.idVendor),
363 le16_to_cpu(device->descriptor.idProduct),
364 0,
365 usX2Y(card)->chip.dev->bus->busnum, usX2Y(card)->chip.dev->devnum
366 );
367 *cardp = card;
368 return 0;
369}
370
371
372static int usX2Y_usb_probe(struct usb_device *device,
373 struct usb_interface *intf,
374 const struct usb_device_id *device_id,
375 struct snd_card **cardp)
376{
377 int err;
378 struct snd_card * card;
379
380 *cardp = NULL;
381 if (le16_to_cpu(device->descriptor.idVendor) != 0x1604 ||
382 (le16_to_cpu(device->descriptor.idProduct) != USB_ID_US122 &&
383 le16_to_cpu(device->descriptor.idProduct) != USB_ID_US224 &&
384 le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428))
385 return -EINVAL;
386
387 err = usX2Y_create_card(device, &card);
388 if (err < 0)
389 return err;
390 snd_card_set_dev(card, &intf->dev);
391 if ((err = usX2Y_hwdep_new(card, device)) < 0 ||
392 (err = snd_card_register(card)) < 0) {
393 snd_card_free(card);
394 return err;
395 }
396 *cardp = card;
397 return 0;
398}
399
400
401
402
403static int snd_usX2Y_probe(struct usb_interface *intf, const struct usb_device_id *id)
404{
405 struct snd_card *card;
406 int err;
407
408 err = usX2Y_usb_probe(interface_to_usbdev(intf), intf, id, &card);
409 if (err < 0)
410 return err;
411 dev_set_drvdata(&intf->dev, card);
412 return 0;
413}
414
415static void snd_usX2Y_disconnect(struct usb_interface *intf)
416{
417 usX2Y_usb_disconnect(interface_to_usbdev(intf),
418 usb_get_intfdata(intf));
419}
420
421MODULE_DEVICE_TABLE(usb, snd_usX2Y_usb_id_table);
422static struct usb_driver snd_usX2Y_usb_driver = {
423 .name = "snd-usb-usx2y",
424 .probe = snd_usX2Y_probe,
425 .disconnect = snd_usX2Y_disconnect,
426 .id_table = snd_usX2Y_usb_id_table,
427};
428
429static void snd_usX2Y_card_private_free(struct snd_card *card)
430{
431 kfree(usX2Y(card)->In04Buf);
432 usb_free_urb(usX2Y(card)->In04urb);
433 if (usX2Y(card)->us428ctls_sharedmem)
434 snd_free_pages(usX2Y(card)->us428ctls_sharedmem, sizeof(*usX2Y(card)->us428ctls_sharedmem));
435 if (usX2Y(card)->chip.index >= 0 && usX2Y(card)->chip.index < SNDRV_CARDS)
436 snd_usX2Y_card_used[usX2Y(card)->chip.index] = 0;
437}
438
439
440
441
442static void usX2Y_usb_disconnect(struct usb_device *device, void* ptr)
443{
444 if (ptr) {
445 struct snd_card *card = ptr;
446 struct usX2Ydev *usX2Y = usX2Y(card);
447 struct list_head *p;
448 usX2Y->chip.shutdown = 1;
449 usX2Y->chip_status = USX2Y_STAT_CHIP_HUP;
450 usX2Y_unlinkSeq(&usX2Y->AS04);
451 usb_kill_urb(usX2Y->In04urb);
452 snd_card_disconnect(card);
453
454 list_for_each(p, &usX2Y->chip.midi_list) {
455 snd_usbmidi_disconnect(p);
456 }
457 if (usX2Y->us428ctls_sharedmem)
458 wake_up(&usX2Y->us428ctls_wait_queue_head);
459 snd_card_free(card);
460 }
461}
462
463static int __init snd_usX2Y_module_init(void)
464{
465 return usb_register(&snd_usX2Y_usb_driver);
466}
467
468static void __exit snd_usX2Y_module_exit(void)
469{
470 usb_deregister(&snd_usX2Y_usb_driver);
471}
472
473module_init(snd_usX2Y_module_init)
474module_exit(snd_usX2Y_module_exit)
475