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/slab.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 bool 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->dev,
244 usb_sndbulkpipe(usX2Y->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->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->dev,
278 usb_sndbulkpipe(usX2Y->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->dev, usb_rcvintpipe(usX2Y->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 usb_kill_urb(S->urb[i]);
309 usb_free_urb(S->urb[i]);
310 S->urb[i] = NULL;
311 }
312 kfree(S->buffer);
313}
314
315
316static struct usb_device_id snd_usX2Y_usb_id_table[] = {
317 {
318 .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
319 .idVendor = 0x1604,
320 .idProduct = USB_ID_US428
321 },
322 {
323 .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
324 .idVendor = 0x1604,
325 .idProduct = USB_ID_US122
326 },
327 {
328 .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
329 .idVendor = 0x1604,
330 .idProduct = USB_ID_US224
331 },
332 { }
333};
334
335static int usX2Y_create_card(struct usb_device *device,
336 struct usb_interface *intf,
337 struct snd_card **cardp)
338{
339 int dev;
340 struct snd_card * card;
341 int err;
342
343 for (dev = 0; dev < SNDRV_CARDS; ++dev)
344 if (enable[dev] && !snd_usX2Y_card_used[dev])
345 break;
346 if (dev >= SNDRV_CARDS)
347 return -ENODEV;
348 err = snd_card_new(&intf->dev, index[dev], id[dev], THIS_MODULE,
349 sizeof(struct usX2Ydev), &card);
350 if (err < 0)
351 return err;
352 snd_usX2Y_card_used[usX2Y(card)->card_index = dev] = 1;
353 card->private_free = snd_usX2Y_card_private_free;
354 usX2Y(card)->dev = device;
355 init_waitqueue_head(&usX2Y(card)->prepare_wait_queue);
356 mutex_init(&usX2Y(card)->pcm_mutex);
357 INIT_LIST_HEAD(&usX2Y(card)->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)->dev->bus->busnum, usX2Y(card)->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, intf, &card);
388 if (err < 0)
389 return err;
390 if ((err = usX2Y_hwdep_new(card, device)) < 0 ||
391 (err = snd_card_register(card)) < 0) {
392 snd_card_free(card);
393 return err;
394 }
395 *cardp = card;
396 return 0;
397}
398
399
400
401
402static int snd_usX2Y_probe(struct usb_interface *intf, const struct usb_device_id *id)
403{
404 struct snd_card *card;
405 int err;
406
407 err = usX2Y_usb_probe(interface_to_usbdev(intf), intf, id, &card);
408 if (err < 0)
409 return err;
410 dev_set_drvdata(&intf->dev, card);
411 return 0;
412}
413
414static void snd_usX2Y_disconnect(struct usb_interface *intf)
415{
416 usX2Y_usb_disconnect(interface_to_usbdev(intf),
417 usb_get_intfdata(intf));
418}
419
420MODULE_DEVICE_TABLE(usb, snd_usX2Y_usb_id_table);
421static struct usb_driver snd_usX2Y_usb_driver = {
422 .name = "snd-usb-usx2y",
423 .probe = snd_usX2Y_probe,
424 .disconnect = snd_usX2Y_disconnect,
425 .id_table = snd_usX2Y_usb_id_table,
426};
427
428static void snd_usX2Y_card_private_free(struct snd_card *card)
429{
430 kfree(usX2Y(card)->In04Buf);
431 usb_free_urb(usX2Y(card)->In04urb);
432 if (usX2Y(card)->us428ctls_sharedmem)
433 snd_free_pages(usX2Y(card)->us428ctls_sharedmem, sizeof(*usX2Y(card)->us428ctls_sharedmem));
434 if (usX2Y(card)->card_index >= 0 && usX2Y(card)->card_index < SNDRV_CARDS)
435 snd_usX2Y_card_used[usX2Y(card)->card_index] = 0;
436}
437
438
439
440
441static void usX2Y_usb_disconnect(struct usb_device *device, void* ptr)
442{
443 if (ptr) {
444 struct snd_card *card = ptr;
445 struct usX2Ydev *usX2Y = usX2Y(card);
446 struct list_head *p;
447 usX2Y->chip_status = USX2Y_STAT_CHIP_HUP;
448 usX2Y_unlinkSeq(&usX2Y->AS04);
449 usb_kill_urb(usX2Y->In04urb);
450 snd_card_disconnect(card);
451
452 list_for_each(p, &usX2Y->midi_list) {
453 snd_usbmidi_disconnect(p);
454 }
455 if (usX2Y->us428ctls_sharedmem)
456 wake_up(&usX2Y->us428ctls_wait_queue_head);
457 snd_card_free(card);
458 }
459}
460
461module_usb_driver(snd_usX2Y_usb_driver);
462