1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * usbusx2y.c - ALSA USB US-428 Driver
5 2005-04-14 Karsten Wiese
7 Call snd_card_free() instead of snd_card_free_in_thread() to prevent oops with dead keyboard symptom.
8 Tested ok with kernel 2.6.12-rc2.
10 2004-12-14 Karsten Wiese
12 snd_pcm_open for rawusb pcm-devices now returns -EBUSY if called without rawusb's hwdep device being open.
14 2004-12-02 Karsten Wiese
16 Use macro usb_maxpacket() for portability.
18 2004-10-26 Karsten Wiese
20 wake_up() process waiting in usx2y_urbs_start() on error.
22 2004-10-21 Karsten Wiese
24 nrpacks is runtime or compiletime configurable now with tested values from 1 to 4.
26 2004-10-03 Karsten Wiese
28 Avoid any possible racing while in prepare callback.
30 2004-09-30 Karsten Wiese
32 Simplified things and made ohci work again.
34 2004-09-20 Karsten Wiese
36 Use usb_kill_urb() instead of deprecated (kernel 2.6.9) usb_unlink_urb().
38 2004-07-13 Karsten Wiese
40 Don't sleep in START/STOP callbacks anymore.
41 us428 channels C/D not handled just for this version, sorry.
43 2004-06-21 Karsten Wiese
45 Temporarely suspend midi input
46 to sanely call usb_set_interface() when setting format.
48 2004-06-12 Karsten Wiese
50 Made it thus the following rule is enforced:
51 "All pcm substreams of one usx2y have to operate at the same rate & format."
53 2004-04-06 Karsten Wiese
55 Runs on 2.6.5 kernel without any "--with-debug=" things.
56 us224 reported running.
58 2004-01-14 Karsten Wiese
60 Runs with 2.6.1 kernel.
62 2003-12-30 Karsten Wiese
64 Fix 24Bit 4Channel capturing for the us428.
66 2003-11-27 Karsten Wiese, Martin Langer
69 us224 could be tested by uncommenting the sections containing USB_ID_US224
71 2003-11-03 Karsten Wiese
74 "arecord -D hw:1 -c 2 -r 48000 -M -f S24_3LE|aplay -D hw:1 -c 2 -r 48000 -M -f S24_3LE" works.
76 2003-08-22 Karsten Wiese
78 Removed EZUSB Firmware. First Stage Firmwaredownload is now done by tascam-firmware downloader.
80 http://usb-midi-fw.sourceforge.net/tascam-firmware.tar.gz
82 2003-06-18 Karsten Wiese
84 changed to compile with kernel 2.4.21 and alsa 0.9.4
86 2002-10-16 Karsten Wiese
88 compiles again with alsa-current.
89 USB_ISO_ASAP not used anymore (most of the time), instead
90 urb->start_frame is calculated here now, some calls inside usb-driver don't need to happen anymore.
92 To get the best out of this:
93 Disable APM-support in the kernel as APM-BIOS calls (once each second) hard disable interrupt for many precious milliseconds.
94 This helped me much on my slowish PII 400 & PIII 500.
95 ACPI yet untested but might cause the same bad behaviour.
96 Use a kernel with lowlatency and preemptiv patches applied.
97 To autoload snd-usb-midi append a line
98 post-install snd-usb-us428 modprobe snd-usb-midi
102 sliders, knobs, lights not yet handled except MASTER Volume slider.
103 "pcm -c 2" doesn't work. "pcm -c 2 -m direct_interleaved" does.
104 KDE3: "Enable full duplex operation" deadlocks.
106 2002-08-31 Karsten Wiese
107 Version 0.0.3: audio also simplex;
108 simplifying: iso urbs only 1 packet, melted structs.
109 ASYNC_UNLINK not used anymore: no more crashes so far.....
112 2002-08-09 Karsten Wiese
113 Version 0.0.2: midi works with snd-usb-midi, audio (only fullduplex now) with i.e. bristol.
114 The firmware has been sniffed from win2k us-428 driver 3.09.
116 * Copyright (c) 2002 - 2004 Karsten Wiese
119 #include <linux/init.h>
120 #include <linux/module.h>
121 #include <linux/moduleparam.h>
122 #include <linux/slab.h>
123 #include <linux/interrupt.h>
124 #include <linux/usb.h>
125 #include <sound/core.h>
126 #include <sound/initval.h>
127 #include <sound/pcm.h>
129 #include <sound/rawmidi.h>
131 #include "usbusx2y.h"
132 #include "usX2Yhwdep.h"
134 MODULE_AUTHOR("Karsten Wiese <annabellesgarden@yahoo.de>");
135 MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS
" Version 0.8.7.2");
136 MODULE_LICENSE("GPL");
138 static int index
[SNDRV_CARDS
] = SNDRV_DEFAULT_IDX
; /* Index 0-max */
139 static char *id
[SNDRV_CARDS
] = SNDRV_DEFAULT_STR
; /* Id for this card */
140 static bool enable
[SNDRV_CARDS
] = SNDRV_DEFAULT_ENABLE_PNP
; /* Enable this card */
142 module_param_array(index
, int, NULL
, 0444);
143 MODULE_PARM_DESC(index
, "Index value for "NAME_ALLCAPS
".");
144 module_param_array(id
, charp
, NULL
, 0444);
145 MODULE_PARM_DESC(id
, "ID string for "NAME_ALLCAPS
".");
146 module_param_array(enable
, bool, NULL
, 0444);
147 MODULE_PARM_DESC(enable
, "Enable "NAME_ALLCAPS
".");
149 static int snd_usx2y_card_used
[SNDRV_CARDS
];
151 static void snd_usx2y_card_private_free(struct snd_card
*card
);
152 static void usx2y_unlinkseq(struct snd_usx2y_async_seq
*s
);
155 * pipe 4 is used for switching the lamps, setting samplerate, volumes ....
157 static void i_usx2y_out04_int(struct urb
*urb
)
159 #ifdef CONFIG_SND_DEBUG
162 struct usx2ydev
*usx2y
= urb
->context
;
164 for (i
= 0; i
< 10 && usx2y
->as04
.urb
[i
] != urb
; i
++)
166 dev_dbg(&urb
->dev
->dev
, "%s urb %i status=%i\n", __func__
, i
, urb
->status
);
171 static void i_usx2y_in04_int(struct urb
*urb
)
174 struct usx2ydev
*usx2y
= urb
->context
;
175 struct us428ctls_sharedmem
*us428ctls
= usx2y
->us428ctls_sharedmem
;
176 struct us428_p4out
*p4out
;
177 int i
, j
, n
, diff
, send
;
179 usx2y
->in04_int_calls
++;
182 dev_dbg(&urb
->dev
->dev
, "Interrupt Pipe 4 came back with status=%i\n", urb
->status
);
188 if (us428ctls
->ctl_snapshot_last
== -2) {
190 memcpy(usx2y
->in04_last
, usx2y
->in04_buf
, sizeof(usx2y
->in04_last
));
191 us428ctls
->ctl_snapshot_last
= -1;
193 for (i
= 0; i
< 21; i
++) {
194 if (usx2y
->in04_last
[i
] != ((char *)usx2y
->in04_buf
)[i
]) {
197 usx2y
->in04_last
[i
] = ((char *)usx2y
->in04_buf
)[i
];
202 n
= us428ctls
->ctl_snapshot_last
+ 1;
203 if (n
>= N_US428_CTL_BUFS
|| n
< 0)
205 memcpy(us428ctls
->ctl_snapshot
+ n
, usx2y
->in04_buf
, sizeof(us428ctls
->ctl_snapshot
[0]));
206 us428ctls
->ctl_snapshot_differs_at
[n
] = diff
;
207 us428ctls
->ctl_snapshot_last
= n
;
208 wake_up(&usx2y
->us428ctls_wait_queue_head
);
213 if (!usx2y
->us04
->submitted
) {
215 err
= usb_submit_urb(usx2y
->us04
->urb
[usx2y
->us04
->submitted
++], GFP_ATOMIC
);
216 } while (!err
&& usx2y
->us04
->submitted
< usx2y
->us04
->len
);
219 if (us428ctls
&& us428ctls
->p4out_last
>= 0 && us428ctls
->p4out_last
< N_US428_P4OUT_BUFS
) {
220 if (us428ctls
->p4out_last
!= us428ctls
->p4out_sent
) {
221 send
= us428ctls
->p4out_sent
+ 1;
222 if (send
>= N_US428_P4OUT_BUFS
)
224 for (j
= 0; j
< URBS_ASYNC_SEQ
&& !err
; ++j
) {
225 if (!usx2y
->as04
.urb
[j
]->status
) {
226 p4out
= us428ctls
->p4out
+ send
; // FIXME if more than 1 p4out is new, 1 gets lost.
227 usb_fill_bulk_urb(usx2y
->as04
.urb
[j
], usx2y
->dev
,
228 usb_sndbulkpipe(usx2y
->dev
, 0x04), &p4out
->val
.vol
,
229 p4out
->type
== ELT_LIGHT
? sizeof(struct us428_lights
) : 5,
230 i_usx2y_out04_int
, usx2y
);
231 err
= usb_submit_urb(usx2y
->as04
.urb
[j
], GFP_ATOMIC
);
232 us428ctls
->p4out_sent
= send
;
241 dev_err(&urb
->dev
->dev
, "in04_int() usb_submit_urb err=%i\n", err
);
243 urb
->dev
= usx2y
->dev
;
244 usb_submit_urb(urb
, GFP_ATOMIC
);
250 int usx2y_async_seq04_init(struct usx2ydev
*usx2y
)
254 if (WARN_ON(usx2y
->as04
.buffer
))
257 usx2y
->as04
.buffer
= kmalloc_array(URBS_ASYNC_SEQ
,
258 URB_DATA_LEN_ASYNC_SEQ
, GFP_KERNEL
);
259 if (!usx2y
->as04
.buffer
) {
262 for (i
= 0; i
< URBS_ASYNC_SEQ
; ++i
) {
263 usx2y
->as04
.urb
[i
] = usb_alloc_urb(0, GFP_KERNEL
);
264 if (!usx2y
->as04
.urb
[i
]) {
268 usb_fill_bulk_urb(usx2y
->as04
.urb
[i
], usx2y
->dev
,
269 usb_sndbulkpipe(usx2y
->dev
, 0x04),
270 usx2y
->as04
.buffer
+ URB_DATA_LEN_ASYNC_SEQ
* i
, 0,
271 i_usx2y_out04_int
, usx2y
);
272 err
= usb_urb_ep_type_check(usx2y
->as04
.urb
[i
]);
278 usx2y_unlinkseq(&usx2y
->as04
);
282 int usx2y_in04_init(struct usx2ydev
*usx2y
)
286 if (WARN_ON(usx2y
->in04_urb
))
289 usx2y
->in04_urb
= usb_alloc_urb(0, GFP_KERNEL
);
290 if (!usx2y
->in04_urb
) {
295 usx2y
->in04_buf
= kmalloc(21, GFP_KERNEL
);
296 if (!usx2y
->in04_buf
) {
301 init_waitqueue_head(&usx2y
->in04_wait_queue
);
302 usb_fill_int_urb(usx2y
->in04_urb
, usx2y
->dev
, usb_rcvintpipe(usx2y
->dev
, 0x4),
304 i_usx2y_in04_int
, usx2y
,
306 if (usb_urb_ep_type_check(usx2y
->in04_urb
)) {
310 return usb_submit_urb(usx2y
->in04_urb
, GFP_KERNEL
);
313 kfree(usx2y
->in04_buf
);
314 usb_free_urb(usx2y
->in04_urb
);
315 usx2y
->in04_buf
= NULL
;
316 usx2y
->in04_urb
= NULL
;
320 static void usx2y_unlinkseq(struct snd_usx2y_async_seq
*s
)
324 for (i
= 0; i
< URBS_ASYNC_SEQ
; ++i
) {
327 usb_kill_urb(s
->urb
[i
]);
328 usb_free_urb(s
->urb
[i
]);
335 static const struct usb_device_id snd_usx2y_usb_id_table
[] = {
337 .match_flags
= USB_DEVICE_ID_MATCH_DEVICE
,
339 .idProduct
= USB_ID_US428
342 .match_flags
= USB_DEVICE_ID_MATCH_DEVICE
,
344 .idProduct
= USB_ID_US122
347 .match_flags
= USB_DEVICE_ID_MATCH_DEVICE
,
349 .idProduct
= USB_ID_US224
353 MODULE_DEVICE_TABLE(usb
, snd_usx2y_usb_id_table
);
355 static int usx2y_create_card(struct usb_device
*device
,
356 struct usb_interface
*intf
,
357 struct snd_card
**cardp
)
360 struct snd_card
*card
;
363 for (dev
= 0; dev
< SNDRV_CARDS
; ++dev
)
364 if (enable
[dev
] && !snd_usx2y_card_used
[dev
])
366 if (dev
>= SNDRV_CARDS
)
368 err
= snd_card_new(&intf
->dev
, index
[dev
], id
[dev
], THIS_MODULE
,
369 sizeof(struct usx2ydev
), &card
);
372 snd_usx2y_card_used
[usx2y(card
)->card_index
= dev
] = 1;
373 card
->private_free
= snd_usx2y_card_private_free
;
374 usx2y(card
)->dev
= device
;
375 init_waitqueue_head(&usx2y(card
)->prepare_wait_queue
);
376 init_waitqueue_head(&usx2y(card
)->us428ctls_wait_queue_head
);
377 mutex_init(&usx2y(card
)->pcm_mutex
);
378 INIT_LIST_HEAD(&usx2y(card
)->midi_list
);
379 strcpy(card
->driver
, "USB "NAME_ALLCAPS
"");
380 sprintf(card
->shortname
, "TASCAM "NAME_ALLCAPS
"");
381 sprintf(card
->longname
, "%s (%x:%x if %d at %03d/%03d)",
383 le16_to_cpu(device
->descriptor
.idVendor
),
384 le16_to_cpu(device
->descriptor
.idProduct
),
385 0,//us428(card)->usbmidi.ifnum,
386 usx2y(card
)->dev
->bus
->busnum
, usx2y(card
)->dev
->devnum
);
391 static void snd_usx2y_card_private_free(struct snd_card
*card
)
393 struct usx2ydev
*usx2y
= usx2y(card
);
395 kfree(usx2y
->in04_buf
);
396 usb_free_urb(usx2y
->in04_urb
);
397 if (usx2y
->us428ctls_sharedmem
)
398 free_pages_exact(usx2y
->us428ctls_sharedmem
,
399 US428_SHAREDMEM_PAGES
);
400 if (usx2y
->card_index
>= 0 && usx2y
->card_index
< SNDRV_CARDS
)
401 snd_usx2y_card_used
[usx2y
->card_index
] = 0;
404 static void snd_usx2y_disconnect(struct usb_interface
*intf
)
406 struct snd_card
*card
;
407 struct usx2ydev
*usx2y
;
410 card
= usb_get_intfdata(intf
);
414 usx2y
->chip_status
= USX2Y_STAT_CHIP_HUP
;
415 usx2y_unlinkseq(&usx2y
->as04
);
416 usb_kill_urb(usx2y
->in04_urb
);
417 snd_card_disconnect(card
);
419 /* release the midi resources */
420 list_for_each(p
, &usx2y
->midi_list
) {
421 snd_usbmidi_disconnect(p
);
423 if (usx2y
->us428ctls_sharedmem
)
424 wake_up(&usx2y
->us428ctls_wait_queue_head
);
425 snd_card_free_when_closed(card
);
428 static int snd_usx2y_probe(struct usb_interface
*intf
,
429 const struct usb_device_id
*id
)
431 struct usb_device
*device
= interface_to_usbdev(intf
);
432 struct snd_card
*card
;
435 if (le16_to_cpu(device
->descriptor
.idVendor
) != 0x1604 ||
436 (le16_to_cpu(device
->descriptor
.idProduct
) != USB_ID_US122
&&
437 le16_to_cpu(device
->descriptor
.idProduct
) != USB_ID_US224
&&
438 le16_to_cpu(device
->descriptor
.idProduct
) != USB_ID_US428
))
441 err
= usx2y_create_card(device
, intf
, &card
);
444 err
= usx2y_hwdep_new(card
, device
);
447 err
= snd_card_register(card
);
451 dev_set_drvdata(&intf
->dev
, card
);
459 static struct usb_driver snd_usx2y_usb_driver
= {
460 .name
= "snd-usb-usx2y",
461 .probe
= snd_usx2y_probe
,
462 .disconnect
= snd_usx2y_disconnect
,
463 .id_table
= snd_usx2y_usb_id_table
,
465 module_usb_driver(snd_usx2y_usb_driver
);