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 err = usb_urb_ep_type_check(usX2Y->AS04.urb[i]);
283 if (err < 0)
284 break;
285 }
286 return err;
287}
288
289int usX2Y_In04_init(struct usX2Ydev *usX2Y)
290{
291 if (! (usX2Y->In04urb = usb_alloc_urb(0, GFP_KERNEL)))
292 return -ENOMEM;
293
294 if (! (usX2Y->In04Buf = kmalloc(21, GFP_KERNEL))) {
295 usb_free_urb(usX2Y->In04urb);
296 return -ENOMEM;
297 }
298
299 init_waitqueue_head(&usX2Y->In04WaitQueue);
300 usb_fill_int_urb(usX2Y->In04urb, usX2Y->dev, usb_rcvintpipe(usX2Y->dev, 0x4),
301 usX2Y->In04Buf, 21,
302 i_usX2Y_In04Int, usX2Y,
303 10);
304 if (usb_urb_ep_type_check(usX2Y->In04urb))
305 return -EINVAL;
306 return usb_submit_urb(usX2Y->In04urb, GFP_KERNEL);
307}
308
309static void usX2Y_unlinkSeq(struct snd_usX2Y_AsyncSeq *S)
310{
311 int i;
312 for (i = 0; i < URBS_AsyncSeq; ++i) {
313 usb_kill_urb(S->urb[i]);
314 usb_free_urb(S->urb[i]);
315 S->urb[i] = NULL;
316 }
317 kfree(S->buffer);
318}
319
320
321static const struct usb_device_id snd_usX2Y_usb_id_table[] = {
322 {
323 .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
324 .idVendor = 0x1604,
325 .idProduct = USB_ID_US428
326 },
327 {
328 .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
329 .idVendor = 0x1604,
330 .idProduct = USB_ID_US122
331 },
332 {
333 .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
334 .idVendor = 0x1604,
335 .idProduct = USB_ID_US224
336 },
337 { }
338};
339
340static int usX2Y_create_card(struct usb_device *device,
341 struct usb_interface *intf,
342 struct snd_card **cardp)
343{
344 int dev;
345 struct snd_card * card;
346 int err;
347
348 for (dev = 0; dev < SNDRV_CARDS; ++dev)
349 if (enable[dev] && !snd_usX2Y_card_used[dev])
350 break;
351 if (dev >= SNDRV_CARDS)
352 return -ENODEV;
353 err = snd_card_new(&intf->dev, index[dev], id[dev], THIS_MODULE,
354 sizeof(struct usX2Ydev), &card);
355 if (err < 0)
356 return err;
357 snd_usX2Y_card_used[usX2Y(card)->card_index = dev] = 1;
358 card->private_free = snd_usX2Y_card_private_free;
359 usX2Y(card)->dev = device;
360 init_waitqueue_head(&usX2Y(card)->prepare_wait_queue);
361 mutex_init(&usX2Y(card)->pcm_mutex);
362 INIT_LIST_HEAD(&usX2Y(card)->midi_list);
363 strcpy(card->driver, "USB "NAME_ALLCAPS"");
364 sprintf(card->shortname, "TASCAM "NAME_ALLCAPS"");
365 sprintf(card->longname, "%s (%x:%x if %d at %03d/%03d)",
366 card->shortname,
367 le16_to_cpu(device->descriptor.idVendor),
368 le16_to_cpu(device->descriptor.idProduct),
369 0,
370 usX2Y(card)->dev->bus->busnum, usX2Y(card)->dev->devnum
371 );
372 *cardp = card;
373 return 0;
374}
375
376
377static int usX2Y_usb_probe(struct usb_device *device,
378 struct usb_interface *intf,
379 const struct usb_device_id *device_id,
380 struct snd_card **cardp)
381{
382 int err;
383 struct snd_card * card;
384
385 *cardp = NULL;
386 if (le16_to_cpu(device->descriptor.idVendor) != 0x1604 ||
387 (le16_to_cpu(device->descriptor.idProduct) != USB_ID_US122 &&
388 le16_to_cpu(device->descriptor.idProduct) != USB_ID_US224 &&
389 le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428))
390 return -EINVAL;
391
392 err = usX2Y_create_card(device, intf, &card);
393 if (err < 0)
394 return err;
395 if ((err = usX2Y_hwdep_new(card, device)) < 0 ||
396 (err = snd_card_register(card)) < 0) {
397 snd_card_free(card);
398 return err;
399 }
400 *cardp = card;
401 return 0;
402}
403
404
405
406
407static int snd_usX2Y_probe(struct usb_interface *intf, const struct usb_device_id *id)
408{
409 struct snd_card *card;
410 int err;
411
412 err = usX2Y_usb_probe(interface_to_usbdev(intf), intf, id, &card);
413 if (err < 0)
414 return err;
415 dev_set_drvdata(&intf->dev, card);
416 return 0;
417}
418
419static void snd_usX2Y_disconnect(struct usb_interface *intf)
420{
421 usX2Y_usb_disconnect(interface_to_usbdev(intf),
422 usb_get_intfdata(intf));
423}
424
425MODULE_DEVICE_TABLE(usb, snd_usX2Y_usb_id_table);
426static struct usb_driver snd_usX2Y_usb_driver = {
427 .name = "snd-usb-usx2y",
428 .probe = snd_usX2Y_probe,
429 .disconnect = snd_usX2Y_disconnect,
430 .id_table = snd_usX2Y_usb_id_table,
431};
432
433static void snd_usX2Y_card_private_free(struct snd_card *card)
434{
435 kfree(usX2Y(card)->In04Buf);
436 usb_free_urb(usX2Y(card)->In04urb);
437 if (usX2Y(card)->us428ctls_sharedmem)
438 snd_free_pages(usX2Y(card)->us428ctls_sharedmem, sizeof(*usX2Y(card)->us428ctls_sharedmem));
439 if (usX2Y(card)->card_index >= 0 && usX2Y(card)->card_index < SNDRV_CARDS)
440 snd_usX2Y_card_used[usX2Y(card)->card_index] = 0;
441}
442
443
444
445
446static void usX2Y_usb_disconnect(struct usb_device *device, void* ptr)
447{
448 if (ptr) {
449 struct snd_card *card = ptr;
450 struct usX2Ydev *usX2Y = usX2Y(card);
451 struct list_head *p;
452 usX2Y->chip_status = USX2Y_STAT_CHIP_HUP;
453 usX2Y_unlinkSeq(&usX2Y->AS04);
454 usb_kill_urb(usX2Y->In04urb);
455 snd_card_disconnect(card);
456
457 list_for_each(p, &usX2Y->midi_list) {
458 snd_usbmidi_disconnect(p);
459 }
460 if (usX2Y->us428ctls_sharedmem)
461 wake_up(&usX2Y->us428ctls_wait_queue_head);
462 snd_card_free(card);
463 }
464}
465
466module_usb_driver(snd_usX2Y_usb_driver);
467