1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * usbusy2y.c - ALSA USB US-428 Driver 4 * 52005-04-14 Karsten Wiese 6 Version 0.8.7.2: 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. 9 102004-12-14 Karsten Wiese 11 Version 0.8.7.1: 12 snd_pcm_open for rawusb pcm-devices now returns -EBUSY if called without rawusb's hwdep device being open. 13 142004-12-02 Karsten Wiese 15 Version 0.8.7: 16 Use macro usb_maxpacket() for portability. 17 182004-10-26 Karsten Wiese 19 Version 0.8.6: 20 wake_up() process waiting in usx2y_urbs_start() on error. 21 222004-10-21 Karsten Wiese 23 Version 0.8.5: 24 nrpacks is runtime or compiletime configurable now with tested values from 1 to 4. 25 262004-10-03 Karsten Wiese 27 Version 0.8.2: 28 Avoid any possible racing while in prepare callback. 29 302004-09-30 Karsten Wiese 31 Version 0.8.0: 32 Simplified things and made ohci work again. 33 342004-09-20 Karsten Wiese 35 Version 0.7.3: 36 Use usb_kill_urb() instead of deprecated (kernel 2.6.9) usb_unlink_urb(). 37 382004-07-13 Karsten Wiese 39 Version 0.7.1: 40 Don't sleep in START/STOP callbacks anymore. 41 us428 channels C/D not handled just for this version, sorry. 42 432004-06-21 Karsten Wiese 44 Version 0.6.4: 45 Temporarely suspend midi input 46 to sanely call usb_set_interface() when setting format. 47 482004-06-12 Karsten Wiese 49 Version 0.6.3: 50 Made it thus the following rule is enforced: 51 "All pcm substreams of one usx2y have to operate at the same rate & format." 52 532004-04-06 Karsten Wiese 54 Version 0.6.0: 55 Runs on 2.6.5 kernel without any "--with-debug=" things. 56 us224 reported running. 57 582004-01-14 Karsten Wiese 59 Version 0.5.1: 60 Runs with 2.6.1 kernel. 61 622003-12-30 Karsten Wiese 63 Version 0.4.1: 64 Fix 24Bit 4Channel capturing for the us428. 65 662003-11-27 Karsten Wiese, Martin Langer 67 Version 0.4: 68 us122 support. 69 us224 could be tested by uncommenting the sections containing USB_ID_US224 70 712003-11-03 Karsten Wiese 72 Version 0.3: 73 24Bit support. 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. 75 762003-08-22 Karsten Wiese 77 Version 0.0.8: 78 Removed EZUSB Firmware. First Stage Firmwaredownload is now done by tascam-firmware downloader. 79 See: 80 http://usb-midi-fw.sourceforge.net/tascam-firmware.tar.gz 81 822003-06-18 Karsten Wiese 83 Version 0.0.5: 84 changed to compile with kernel 2.4.21 and alsa 0.9.4 85 862002-10-16 Karsten Wiese 87 Version 0.0.4: 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. 91 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 99 to /etc/modules.conf. 100 101 known problems: 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. 105 106 1072002-08-31 Karsten Wiese 108 Version 0.0.3: audio also simplex; 109 simplifying: iso urbs only 1 packet, melted structs. 110 ASYNC_UNLINK not used anymore: no more crashes so far..... 111 for alsa 0.9 rc3. 112 1132002-08-09 Karsten Wiese 114 Version 0.0.2: midi works with snd-usb-midi, audio (only fullduplex now) with i.e. bristol. 115 The firmware has been sniffed from win2k us-428 driver 3.09. 116 117 * Copyright (c) 2002 - 2004 Karsten Wiese 118*/ 119 120#include <linux/init.h> 121#include <linux/module.h> 122#include <linux/moduleparam.h> 123#include <linux/slab.h> 124#include <linux/interrupt.h> 125#include <linux/usb.h> 126#include <sound/core.h> 127#include <sound/initval.h> 128#include <sound/pcm.h> 129 130#include <sound/rawmidi.h> 131#include "usx2y.h" 132#include "usbusx2y.h" 133#include "usX2Yhwdep.h" 134 135 136 137MODULE_AUTHOR("Karsten Wiese <annabellesgarden@yahoo.de>"); 138MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS" Version 0.8.7.2"); 139MODULE_LICENSE("GPL"); 140MODULE_SUPPORTED_DEVICE("{{TASCAM(0x1604),"NAME_ALLCAPS"(0x8001)(0x8005)(0x8007)}}"); 141 142static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ 143static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */ 144static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ 145 146module_param_array(index, int, NULL, 0444); 147MODULE_PARM_DESC(index, "Index value for "NAME_ALLCAPS"."); 148module_param_array(id, charp, NULL, 0444); 149MODULE_PARM_DESC(id, "ID string for "NAME_ALLCAPS"."); 150module_param_array(enable, bool, NULL, 0444); 151MODULE_PARM_DESC(enable, "Enable "NAME_ALLCAPS"."); 152 153 154static int snd_usx2y_card_used[SNDRV_CARDS]; 155 156static void usx2y_usb_disconnect(struct usb_device* usb_device, void* ptr); 157static void snd_usx2y_card_private_free(struct snd_card *card); 158 159/* 160 * pipe 4 is used for switching the lamps, setting samplerate, volumes .... 161 */ 162static void i_usx2y_out04_int(struct urb *urb) 163{ 164#ifdef CONFIG_SND_DEBUG 165 if (urb->status) { 166 int i; 167 struct usx2ydev *usx2y = urb->context; 168 for (i = 0; i < 10 && usx2y->as04.urb[i] != urb; i++); 169 snd_printdd("i_usx2y_out04_int() urb %i status=%i\n", i, urb->status); 170 } 171#endif 172} 173 174static void i_usx2y_in04_int(struct urb *urb) 175{ 176 int err = 0; 177 struct usx2ydev *usx2y = urb->context; 178 struct us428ctls_sharedmem *us428ctls = usx2y->us428ctls_sharedmem; 179 180 usx2y->in04_int_calls++; 181 182 if (urb->status) { 183 snd_printdd("Interrupt Pipe 4 came back with status=%i\n", urb->status); 184 return; 185 } 186 187 // printk("%i:0x%02X ", 8, (int)((unsigned char*)usx2y->in04_buf)[8]); Master volume shows 0 here if fader is at max during boot ?!? 188 if (us428ctls) { 189 int diff = -1; 190 if (-2 == us428ctls->ctl_snapshot_last) { 191 diff = 0; 192 memcpy(usx2y->in04_last, usx2y->in04_buf, sizeof(usx2y->in04_last)); 193 us428ctls->ctl_snapshot_last = -1; 194 } else { 195 int i; 196 for (i = 0; i < 21; i++) { 197 if (usx2y->in04_last[i] != ((char*)usx2y->in04_buf)[i]) { 198 if (diff < 0) 199 diff = i; 200 usx2y->in04_last[i] = ((char*)usx2y->in04_buf)[i]; 201 } 202 } 203 } 204 if (0 <= diff) { 205 int n = us428ctls->ctl_snapshot_last + 1; 206 if (n >= N_US428_CTL_BUFS || n < 0) 207 n = 0; 208 memcpy(us428ctls->ctl_snapshot + n, usx2y->in04_buf, sizeof(us428ctls->ctl_snapshot[0])); 209 us428ctls->ctl_snapshot_differs_at[n] = diff; 210 us428ctls->ctl_snapshot_last = n; 211 wake_up(&usx2y->us428ctls_wait_queue_head); 212 } 213 } 214 215 216 if (usx2y->us04) { 217 if (0 == usx2y->us04->submitted) 218 do { 219 err = usb_submit_urb(usx2y->us04->urb[usx2y->us04->submitted++], GFP_ATOMIC); 220 } while (!err && usx2y->us04->submitted < usx2y->us04->len); 221 } else 222 if (us428ctls && us428ctls->p4out_last >= 0 && us428ctls->p4out_last < N_US428_P4OUT_BUFS) { 223 if (us428ctls->p4out_last != us428ctls->p4out_sent) { 224 int j, send = us428ctls->p4out_sent + 1; 225 if (send >= N_US428_P4OUT_BUFS) 226 send = 0; 227 for (j = 0; j < URBS_ASYNC_SEQ && !err; ++j) 228 if (0 == usx2y->as04.urb[j]->status) { 229 struct us428_p4out *p4out = us428ctls->p4out + send; // FIXME if more than 1 p4out is new, 1 gets lost. 230 usb_fill_bulk_urb(usx2y->as04.urb[j], usx2y->dev, 231 usb_sndbulkpipe(usx2y->dev, 0x04), &p4out->val.vol, 232 p4out->type == ELT_LIGHT ? sizeof(struct us428_lights) : 5, 233 i_usx2y_out04_int, usx2y); 234 err = usb_submit_urb(usx2y->as04.urb[j], GFP_ATOMIC); 235 us428ctls->p4out_sent = send; 236 break; 237 } 238 } 239 } 240 241 if (err) 242 snd_printk(KERN_ERR "in04_int() usb_submit_urb err=%i\n", err); 243 244 urb->dev = usx2y->dev; 245 usb_submit_urb(urb, GFP_ATOMIC); 246} 247 248/* 249 * Prepare some urbs 250 */ 251int usx2y_async_seq04_init(struct usx2ydev *usx2y) 252{ 253 int err = 0, 254 i; 255 256 usx2y->as04.buffer = kmalloc_array(URBS_ASYNC_SEQ, 257 URB_DATA_LEN_ASYNC_SEQ, GFP_KERNEL); 258 if (NULL == usx2y->as04.buffer) { 259 err = -ENOMEM; 260 } else 261 for (i = 0; i < URBS_ASYNC_SEQ; ++i) { 262 if (NULL == (usx2y->as04.urb[i] = usb_alloc_urb(0, GFP_KERNEL))) { 263 err = -ENOMEM; 264 break; 265 } 266 usb_fill_bulk_urb( usx2y->as04.urb[i], usx2y->dev, 267 usb_sndbulkpipe(usx2y->dev, 0x04), 268 usx2y->as04.buffer + URB_DATA_LEN_ASYNC_SEQ*i, 0, 269 i_usx2y_out04_int, usx2y 270 ); 271 err = usb_urb_ep_type_check(usx2y->as04.urb[i]); 272 if (err < 0) 273 break; 274 } 275 return err; 276} 277 278int usx2y_in04_init(struct usx2ydev *usx2y) 279{ 280 if (! (usx2y->in04_urb = usb_alloc_urb(0, GFP_KERNEL))) 281 return -ENOMEM; 282 283 if (! (usx2y->in04_buf = kmalloc(21, GFP_KERNEL))) 284 return -ENOMEM; 285 286 init_waitqueue_head(&usx2y->in04_wait_queue); 287 usb_fill_int_urb(usx2y->in04_urb, usx2y->dev, usb_rcvintpipe(usx2y->dev, 0x4), 288 usx2y->in04_buf, 21, 289 i_usx2y_in04_int, usx2y, 290 10); 291 if (usb_urb_ep_type_check(usx2y->in04_urb)) 292 return -EINVAL; 293 return usb_submit_urb(usx2y->in04_urb, GFP_KERNEL); 294} 295 296static void usx2y_unlinkseq(struct snd_usx2y_async_seq *s) 297{ 298 int i; 299 for (i = 0; i < URBS_ASYNC_SEQ; ++i) { 300 usb_kill_urb(s->urb[i]); 301 usb_free_urb(s->urb[i]); 302 s->urb[i] = NULL; 303 } 304 kfree(s->buffer); 305} 306 307 308static const struct usb_device_id snd_usx2y_usb_id_table[] = { 309 { 310 .match_flags = USB_DEVICE_ID_MATCH_DEVICE, 311 .idVendor = 0x1604, 312 .idProduct = USB_ID_US428 313 }, 314 { 315 .match_flags = USB_DEVICE_ID_MATCH_DEVICE, 316 .idVendor = 0x1604, 317 .idProduct = USB_ID_US122 318 }, 319 { 320 .match_flags = USB_DEVICE_ID_MATCH_DEVICE, 321 .idVendor = 0x1604, 322 .idProduct = USB_ID_US224 323 }, 324 { /* terminator */ } 325}; 326 327static int usx2y_create_card(struct usb_device *device, 328 struct usb_interface *intf, 329 struct snd_card **cardp) 330{ 331 int dev; 332 struct snd_card * card; 333 int err; 334 335 for (dev = 0; dev < SNDRV_CARDS; ++dev) 336 if (enable[dev] && !snd_usx2y_card_used[dev]) 337 break; 338 if (dev >= SNDRV_CARDS) 339 return -ENODEV; 340 err = snd_card_new(&intf->dev, index[dev], id[dev], THIS_MODULE, 341 sizeof(struct usx2ydev), &card); 342 if (err < 0) 343 return err; 344 snd_usx2y_card_used[usx2y(card)->card_index = dev] = 1; 345 card->private_free = snd_usx2y_card_private_free; 346 usx2y(card)->dev = device; 347 init_waitqueue_head(&usx2y(card)->prepare_wait_queue); 348 mutex_init(&usx2y(card)->pcm_mutex); 349 INIT_LIST_HEAD(&usx2y(card)->midi_list); 350 strcpy(card->driver, "USB "NAME_ALLCAPS""); 351 sprintf(card->shortname, "TASCAM "NAME_ALLCAPS""); 352 sprintf(card->longname, "%s (%x:%x if %d at %03d/%03d)", 353 card->shortname, 354 le16_to_cpu(device->descriptor.idVendor), 355 le16_to_cpu(device->descriptor.idProduct), 356 0,//us428(card)->usbmidi.ifnum, 357 usx2y(card)->dev->bus->busnum, usx2y(card)->dev->devnum 358 ); 359 *cardp = card; 360 return 0; 361} 362 363 364static int usx2y_usb_probe(struct usb_device *device, 365 struct usb_interface *intf, 366 const struct usb_device_id *device_id, 367 struct snd_card **cardp) 368{ 369 int err; 370 struct snd_card * card; 371 372 *cardp = NULL; 373 if (le16_to_cpu(device->descriptor.idVendor) != 0x1604 || 374 (le16_to_cpu(device->descriptor.idProduct) != USB_ID_US122 && 375 le16_to_cpu(device->descriptor.idProduct) != USB_ID_US224 && 376 le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428)) 377 return -EINVAL; 378 379 err = usx2y_create_card(device, intf, &card); 380 if (err < 0) 381 return err; 382 if ((err = usx2y_hwdep_new(card, device)) < 0 || 383 (err = snd_card_register(card)) < 0) { 384 snd_card_free(card); 385 return err; 386 } 387 *cardp = card; 388 return 0; 389} 390 391/* 392 * new 2.5 USB kernel API 393 */ 394static int snd_usx2y_probe(struct usb_interface *intf, const struct usb_device_id *id) 395{ 396 struct snd_card *card; 397 int err; 398 399 err = usx2y_usb_probe(interface_to_usbdev(intf), intf, id, &card); 400 if (err < 0) 401 return err; 402 dev_set_drvdata(&intf->dev, card); 403 return 0; 404} 405 406static void snd_usx2y_disconnect(struct usb_interface *intf) 407{ 408 usx2y_usb_disconnect(interface_to_usbdev(intf), 409 usb_get_intfdata(intf)); 410} 411 412MODULE_DEVICE_TABLE(usb, snd_usx2y_usb_id_table); 413static struct usb_driver snd_usx2y_usb_driver = { 414 .name = "snd-usb-usx2y", 415 .probe = snd_usx2y_probe, 416 .disconnect = snd_usx2y_disconnect, 417 .id_table = snd_usx2y_usb_id_table, 418}; 419 420static void snd_usx2y_card_private_free(struct snd_card *card) 421{ 422 kfree(usx2y(card)->in04_buf); 423 usb_free_urb(usx2y(card)->in04_urb); 424 if (usx2y(card)->us428ctls_sharedmem) 425 free_pages_exact(usx2y(card)->us428ctls_sharedmem, 426 sizeof(*usx2y(card)->us428ctls_sharedmem)); 427 if (usx2y(card)->card_index >= 0 && usx2y(card)->card_index < SNDRV_CARDS) 428 snd_usx2y_card_used[usx2y(card)->card_index] = 0; 429} 430 431/* 432 * Frees the device. 433 */ 434static void usx2y_usb_disconnect(struct usb_device *device, void* ptr) 435{ 436 if (ptr) { 437 struct snd_card *card = ptr; 438 struct usx2ydev *usx2y = usx2y(card); 439 struct list_head *p; 440 usx2y->chip_status = USX2Y_STAT_CHIP_HUP; 441 usx2y_unlinkseq(&usx2y->as04); 442 usb_kill_urb(usx2y->in04_urb); 443 snd_card_disconnect(card); 444 /* release the midi resources */ 445 list_for_each(p, &usx2y->midi_list) { 446 snd_usbmidi_disconnect(p); 447 } 448 if (usx2y->us428ctls_sharedmem) 449 wake_up(&usx2y->us428ctls_wait_queue_head); 450 snd_card_free(card); 451 } 452} 453 454module_usb_driver(snd_usx2y_usb_driver); 455