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