~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/usb/usx2y/us122l.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*
  3  * Copyright (C) 2007, 2008 Karsten Wiese <fzu@wemgehoertderstaat.de>
  4  */
  5 
  6 #include <linux/slab.h>
  7 #include <linux/usb.h>
  8 #include <linux/usb/audio.h>
  9 #include <linux/module.h>
 10 #include <sound/core.h>
 11 #include <sound/hwdep.h>
 12 #include <sound/pcm.h>
 13 #include <sound/initval.h>
 14 #define MODNAME "US122L"
 15 #include "usb_stream.c"
 16 #include "../usbaudio.h"
 17 #include "../midi.h"
 18 #include "us122l.h"
 19 
 20 MODULE_AUTHOR("Karsten Wiese <fzu@wemgehoertderstaat.de>");
 21 MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS" Version 0.5");
 22 MODULE_LICENSE("GPL");
 23 
 24 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;      /* Index 0-max */
 25 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;       /* Id for this card */
 26                                                         /* Enable this card */
 27 static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
 28 
 29 module_param_array(index, int, NULL, 0444);
 30 MODULE_PARM_DESC(index, "Index value for "NAME_ALLCAPS".");
 31 module_param_array(id, charp, NULL, 0444);
 32 MODULE_PARM_DESC(id, "ID string for "NAME_ALLCAPS".");
 33 module_param_array(enable, bool, NULL, 0444);
 34 MODULE_PARM_DESC(enable, "Enable "NAME_ALLCAPS".");
 35 
 36 /* driver_info flags */
 37 #define US122L_FLAG_US144       BIT(0)
 38 
 39 static int snd_us122l_card_used[SNDRV_CARDS];
 40 
 41 static int us122l_create_usbmidi(struct snd_card *card)
 42 {
 43         static const struct snd_usb_midi_endpoint_info quirk_data = {
 44                 .out_ep = 4,
 45                 .in_ep = 3,
 46                 .out_cables =   0x001,
 47                 .in_cables =    0x001
 48         };
 49         static const struct snd_usb_audio_quirk quirk = {
 50                 .vendor_name =  "US122L",
 51                 .product_name = NAME_ALLCAPS,
 52                 .ifnum =        1,
 53                 .type = QUIRK_MIDI_US122L,
 54                 .data = &quirk_data
 55         };
 56         struct usb_device *dev = US122L(card)->dev;
 57         struct usb_interface *iface = usb_ifnum_to_if(dev, 1);
 58 
 59         return snd_usbmidi_create(card, iface,
 60                                   &US122L(card)->midi_list, &quirk);
 61 }
 62 
 63 static int us144_create_usbmidi(struct snd_card *card)
 64 {
 65         static const struct snd_usb_midi_endpoint_info quirk_data = {
 66                 .out_ep = 4,
 67                 .in_ep = 3,
 68                 .out_cables =   0x001,
 69                 .in_cables =    0x001
 70         };
 71         static const struct snd_usb_audio_quirk quirk = {
 72                 .vendor_name =  "US144",
 73                 .product_name = NAME_ALLCAPS,
 74                 .ifnum =        0,
 75                 .type = QUIRK_MIDI_US122L,
 76                 .data = &quirk_data
 77         };
 78         struct usb_device *dev = US122L(card)->dev;
 79         struct usb_interface *iface = usb_ifnum_to_if(dev, 0);
 80 
 81         return snd_usbmidi_create(card, iface,
 82                                   &US122L(card)->midi_list, &quirk);
 83 }
 84 
 85 static void pt_info_set(struct usb_device *dev, u8 v)
 86 {
 87         int ret;
 88 
 89         ret = usb_control_msg_send(dev, 0, 'I',
 90                                    USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 91                                    v, 0, NULL, 0, 1000, GFP_NOIO);
 92         snd_printdd(KERN_DEBUG "%i\n", ret);
 93 }
 94 
 95 static void usb_stream_hwdep_vm_open(struct vm_area_struct *area)
 96 {
 97         struct us122l *us122l = area->vm_private_data;
 98 
 99         atomic_inc(&us122l->mmap_count);
100         snd_printdd(KERN_DEBUG "%i\n", atomic_read(&us122l->mmap_count));
101 }
102 
103 static vm_fault_t usb_stream_hwdep_vm_fault(struct vm_fault *vmf)
104 {
105         unsigned long offset;
106         struct page *page;
107         void *vaddr;
108         struct us122l *us122l = vmf->vma->vm_private_data;
109         struct usb_stream *s;
110 
111         mutex_lock(&us122l->mutex);
112         s = us122l->sk.s;
113         if (!s)
114                 goto unlock;
115 
116         offset = vmf->pgoff << PAGE_SHIFT;
117         if (offset < PAGE_ALIGN(s->read_size)) {
118                 vaddr = (char *)s + offset;
119         } else {
120                 offset -= PAGE_ALIGN(s->read_size);
121                 if (offset >= PAGE_ALIGN(s->write_size))
122                         goto unlock;
123 
124                 vaddr = us122l->sk.write_page + offset;
125         }
126         page = virt_to_page(vaddr);
127 
128         get_page(page);
129         mutex_unlock(&us122l->mutex);
130 
131         vmf->page = page;
132 
133         return 0;
134 unlock:
135         mutex_unlock(&us122l->mutex);
136         return VM_FAULT_SIGBUS;
137 }
138 
139 static void usb_stream_hwdep_vm_close(struct vm_area_struct *area)
140 {
141         struct us122l *us122l = area->vm_private_data;
142 
143         atomic_dec(&us122l->mmap_count);
144         snd_printdd(KERN_DEBUG "%i\n", atomic_read(&us122l->mmap_count));
145 }
146 
147 static const struct vm_operations_struct usb_stream_hwdep_vm_ops = {
148         .open = usb_stream_hwdep_vm_open,
149         .fault = usb_stream_hwdep_vm_fault,
150         .close = usb_stream_hwdep_vm_close,
151 };
152 
153 static int usb_stream_hwdep_open(struct snd_hwdep *hw, struct file *file)
154 {
155         struct us122l   *us122l = hw->private_data;
156         struct usb_interface *iface;
157 
158         snd_printdd(KERN_DEBUG "%p %p\n", hw, file);
159         if (hw->used >= 2)
160                 return -EBUSY;
161 
162         if (!us122l->first)
163                 us122l->first = file;
164 
165         if (us122l->is_us144) {
166                 iface = usb_ifnum_to_if(us122l->dev, 0);
167                 usb_autopm_get_interface(iface);
168         }
169         iface = usb_ifnum_to_if(us122l->dev, 1);
170         usb_autopm_get_interface(iface);
171         return 0;
172 }
173 
174 static int usb_stream_hwdep_release(struct snd_hwdep *hw, struct file *file)
175 {
176         struct us122l   *us122l = hw->private_data;
177         struct usb_interface *iface;
178 
179         snd_printdd(KERN_DEBUG "%p %p\n", hw, file);
180 
181         if (us122l->is_us144) {
182                 iface = usb_ifnum_to_if(us122l->dev, 0);
183                 usb_autopm_put_interface(iface);
184         }
185         iface = usb_ifnum_to_if(us122l->dev, 1);
186         usb_autopm_put_interface(iface);
187         if (us122l->first == file)
188                 us122l->first = NULL;
189         mutex_lock(&us122l->mutex);
190         if (us122l->master == file)
191                 us122l->master = us122l->slave;
192 
193         us122l->slave = NULL;
194         mutex_unlock(&us122l->mutex);
195         return 0;
196 }
197 
198 static int usb_stream_hwdep_mmap(struct snd_hwdep *hw,
199                                  struct file *filp, struct vm_area_struct *area)
200 {
201         unsigned long   size = area->vm_end - area->vm_start;
202         struct us122l   *us122l = hw->private_data;
203         unsigned long offset;
204         struct usb_stream *s;
205         int err = 0;
206         bool read;
207 
208         offset = area->vm_pgoff << PAGE_SHIFT;
209         mutex_lock(&us122l->mutex);
210         s = us122l->sk.s;
211         read = offset < s->read_size;
212         if (read && area->vm_flags & VM_WRITE) {
213                 err = -EPERM;
214                 goto out;
215         }
216         snd_printdd(KERN_DEBUG "%lu %u\n", size,
217                     read ? s->read_size : s->write_size);
218         /* if userspace tries to mmap beyond end of our buffer, fail */
219         if (size > PAGE_ALIGN(read ? s->read_size : s->write_size)) {
220                 snd_printk(KERN_WARNING "%lu > %u\n", size,
221                            read ? s->read_size : s->write_size);
222                 err = -EINVAL;
223                 goto out;
224         }
225 
226         area->vm_ops = &usb_stream_hwdep_vm_ops;
227         vm_flags_set(area, VM_DONTDUMP);
228         if (!read)
229                 vm_flags_set(area, VM_DONTEXPAND);
230         area->vm_private_data = us122l;
231         atomic_inc(&us122l->mmap_count);
232 out:
233         mutex_unlock(&us122l->mutex);
234         return err;
235 }
236 
237 static __poll_t usb_stream_hwdep_poll(struct snd_hwdep *hw,
238                                           struct file *file, poll_table *wait)
239 {
240         struct us122l   *us122l = hw->private_data;
241         unsigned int    *polled;
242         __poll_t        mask;
243 
244         poll_wait(file, &us122l->sk.sleep, wait);
245 
246         mask = EPOLLIN | EPOLLOUT | EPOLLWRNORM | EPOLLERR;
247         if (mutex_trylock(&us122l->mutex)) {
248                 struct usb_stream *s = us122l->sk.s;
249 
250                 if (s && s->state == usb_stream_ready) {
251                         if (us122l->first == file)
252                                 polled = &s->periods_polled;
253                         else
254                                 polled = &us122l->second_periods_polled;
255                         if (*polled != s->periods_done) {
256                                 *polled = s->periods_done;
257                                 mask = EPOLLIN | EPOLLOUT | EPOLLWRNORM;
258                         } else {
259                                 mask = 0;
260                         }
261                 }
262                 mutex_unlock(&us122l->mutex);
263         }
264         return mask;
265 }
266 
267 static void us122l_stop(struct us122l *us122l)
268 {
269         struct list_head *p;
270 
271         list_for_each(p, &us122l->midi_list)
272                 snd_usbmidi_input_stop(p);
273 
274         usb_stream_stop(&us122l->sk);
275         usb_stream_free(&us122l->sk);
276 }
277 
278 static int us122l_set_sample_rate(struct usb_device *dev, int rate)
279 {
280         unsigned int ep = 0x81;
281         unsigned char data[3];
282         int err;
283 
284         data[0] = rate;
285         data[1] = rate >> 8;
286         data[2] = rate >> 16;
287         err = usb_control_msg_send(dev, 0, UAC_SET_CUR,
288                                    USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
289                                    UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep, data, 3,
290                                    1000, GFP_NOIO);
291         if (err)
292                 snd_printk(KERN_ERR "%d: cannot set freq %d to ep 0x%x\n",
293                            dev->devnum, rate, ep);
294         return err;
295 }
296 
297 static bool us122l_start(struct us122l *us122l,
298                          unsigned int rate, unsigned int period_frames)
299 {
300         struct list_head *p;
301         int err;
302         unsigned int use_packsize = 0;
303         bool success = false;
304 
305         if (us122l->dev->speed == USB_SPEED_HIGH) {
306                 /* The us-122l's descriptor defaults to iso max_packsize 78,
307                    which isn't needed for samplerates <= 48000.
308                    Lets save some memory:
309                 */
310                 switch (rate) {
311                 case 44100:
312                         use_packsize = 36;
313                         break;
314                 case 48000:
315                         use_packsize = 42;
316                         break;
317                 case 88200:
318                         use_packsize = 72;
319                         break;
320                 }
321         }
322         if (!usb_stream_new(&us122l->sk, us122l->dev, 1, 2,
323                             rate, use_packsize, period_frames, 6))
324                 goto out;
325 
326         err = us122l_set_sample_rate(us122l->dev, rate);
327         if (err < 0) {
328                 us122l_stop(us122l);
329                 snd_printk(KERN_ERR "us122l_set_sample_rate error\n");
330                 goto out;
331         }
332         err = usb_stream_start(&us122l->sk);
333         if (err < 0) {
334                 us122l_stop(us122l);
335                 snd_printk(KERN_ERR "%s error %i\n", __func__, err);
336                 goto out;
337         }
338         list_for_each(p, &us122l->midi_list)
339                 snd_usbmidi_input_start(p);
340         success = true;
341 out:
342         return success;
343 }
344 
345 static int usb_stream_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
346                                   unsigned int cmd, unsigned long arg)
347 {
348         struct usb_stream_config cfg;
349         struct us122l *us122l = hw->private_data;
350         struct usb_stream *s;
351         unsigned int min_period_frames;
352         int err = 0;
353         bool high_speed;
354 
355         if (cmd != SNDRV_USB_STREAM_IOCTL_SET_PARAMS)
356                 return -ENOTTY;
357 
358         if (copy_from_user(&cfg, (void __user *)arg, sizeof(cfg)))
359                 return -EFAULT;
360 
361         if (cfg.version != USB_STREAM_INTERFACE_VERSION)
362                 return -ENXIO;
363 
364         high_speed = us122l->dev->speed == USB_SPEED_HIGH;
365         if ((cfg.sample_rate != 44100 && cfg.sample_rate != 48000  &&
366              (!high_speed ||
367               (cfg.sample_rate != 88200 && cfg.sample_rate != 96000))) ||
368             cfg.frame_size != 6 ||
369             cfg.period_frames > 0x3000)
370                 return -EINVAL;
371 
372         switch (cfg.sample_rate) {
373         case 44100:
374                 min_period_frames = 48;
375                 break;
376         case 48000:
377                 min_period_frames = 52;
378                 break;
379         default:
380                 min_period_frames = 104;
381                 break;
382         }
383         if (!high_speed)
384                 min_period_frames <<= 1;
385         if (cfg.period_frames < min_period_frames)
386                 return -EINVAL;
387 
388         snd_power_wait(hw->card);
389 
390         mutex_lock(&us122l->mutex);
391         s = us122l->sk.s;
392         if (!us122l->master) {
393                 us122l->master = file;
394         } else if (us122l->master != file) {
395                 if (!s || memcmp(&cfg, &s->cfg, sizeof(cfg))) {
396                         err = -EIO;
397                         goto unlock;
398                 }
399                 us122l->slave = file;
400         }
401         if (!s || memcmp(&cfg, &s->cfg, sizeof(cfg)) ||
402             s->state == usb_stream_xrun) {
403                 us122l_stop(us122l);
404                 if (!us122l_start(us122l, cfg.sample_rate, cfg.period_frames))
405                         err = -EIO;
406                 else
407                         err = 1;
408         }
409 unlock:
410         mutex_unlock(&us122l->mutex);
411         wake_up_all(&us122l->sk.sleep);
412         return err;
413 }
414 
415 #define SND_USB_STREAM_ID "USB STREAM"
416 static int usb_stream_hwdep_new(struct snd_card *card)
417 {
418         int err;
419         struct snd_hwdep *hw;
420         struct usb_device *dev = US122L(card)->dev;
421 
422         err = snd_hwdep_new(card, SND_USB_STREAM_ID, 0, &hw);
423         if (err < 0)
424                 return err;
425 
426         hw->iface = SNDRV_HWDEP_IFACE_USB_STREAM;
427         hw->private_data = US122L(card);
428         hw->ops.open = usb_stream_hwdep_open;
429         hw->ops.release = usb_stream_hwdep_release;
430         hw->ops.ioctl = usb_stream_hwdep_ioctl;
431         hw->ops.ioctl_compat = usb_stream_hwdep_ioctl;
432         hw->ops.mmap = usb_stream_hwdep_mmap;
433         hw->ops.poll = usb_stream_hwdep_poll;
434 
435         sprintf(hw->name, "/dev/bus/usb/%03d/%03d/hwdeppcm",
436                 dev->bus->busnum, dev->devnum);
437         return 0;
438 }
439 
440 static bool us122l_create_card(struct snd_card *card)
441 {
442         int err;
443         struct us122l *us122l = US122L(card);
444 
445         if (us122l->is_us144) {
446                 err = usb_set_interface(us122l->dev, 0, 1);
447                 if (err) {
448                         snd_printk(KERN_ERR "usb_set_interface error\n");
449                         return false;
450                 }
451         }
452         err = usb_set_interface(us122l->dev, 1, 1);
453         if (err) {
454                 snd_printk(KERN_ERR "usb_set_interface error\n");
455                 return false;
456         }
457 
458         pt_info_set(us122l->dev, 0x11);
459         pt_info_set(us122l->dev, 0x10);
460 
461         if (!us122l_start(us122l, 44100, 256))
462                 return false;
463 
464         if (us122l->is_us144)
465                 err = us144_create_usbmidi(card);
466         else
467                 err = us122l_create_usbmidi(card);
468         if (err < 0) {
469                 snd_printk(KERN_ERR "us122l_create_usbmidi error %i\n", err);
470                 goto stop;
471         }
472         err = usb_stream_hwdep_new(card);
473         if (err < 0) {
474                 /* release the midi resources */
475                 struct list_head *p;
476 
477                 list_for_each(p, &us122l->midi_list)
478                         snd_usbmidi_disconnect(p);
479 
480                 goto stop;
481         }
482         return true;
483 
484 stop:
485         us122l_stop(us122l);
486         return false;
487 }
488 
489 static void snd_us122l_free(struct snd_card *card)
490 {
491         struct us122l   *us122l = US122L(card);
492         int             index = us122l->card_index;
493 
494         if (index >= 0 && index < SNDRV_CARDS)
495                 snd_us122l_card_used[index] = 0;
496 }
497 
498 static int usx2y_create_card(struct usb_device *device,
499                              struct usb_interface *intf,
500                              struct snd_card **cardp,
501                              unsigned long flags)
502 {
503         int             dev;
504         struct snd_card *card;
505         int err;
506 
507         for (dev = 0; dev < SNDRV_CARDS; ++dev)
508                 if (enable[dev] && !snd_us122l_card_used[dev])
509                         break;
510         if (dev >= SNDRV_CARDS)
511                 return -ENODEV;
512         err = snd_card_new(&intf->dev, index[dev], id[dev], THIS_MODULE,
513                            sizeof(struct us122l), &card);
514         if (err < 0)
515                 return err;
516         snd_us122l_card_used[US122L(card)->card_index = dev] = 1;
517         card->private_free = snd_us122l_free;
518         US122L(card)->dev = device;
519         mutex_init(&US122L(card)->mutex);
520         init_waitqueue_head(&US122L(card)->sk.sleep);
521         US122L(card)->is_us144 = flags & US122L_FLAG_US144;
522         INIT_LIST_HEAD(&US122L(card)->midi_list);
523         strcpy(card->driver, "USB "NAME_ALLCAPS"");
524         sprintf(card->shortname, "TASCAM "NAME_ALLCAPS"");
525         sprintf(card->longname, "%s (%x:%x if %d at %03d/%03d)",
526                 card->shortname,
527                 le16_to_cpu(device->descriptor.idVendor),
528                 le16_to_cpu(device->descriptor.idProduct),
529                 0,
530                 US122L(card)->dev->bus->busnum,
531                 US122L(card)->dev->devnum
532                 );
533         *cardp = card;
534         return 0;
535 }
536 
537 static int us122l_usb_probe(struct usb_interface *intf,
538                             const struct usb_device_id *device_id,
539                             struct snd_card **cardp)
540 {
541         struct usb_device *device = interface_to_usbdev(intf);
542         struct snd_card *card;
543         int err;
544 
545         err = usx2y_create_card(device, intf, &card, device_id->driver_info);
546         if (err < 0)
547                 return err;
548 
549         if (!us122l_create_card(card)) {
550                 snd_card_free(card);
551                 return -EINVAL;
552         }
553 
554         err = snd_card_register(card);
555         if (err < 0) {
556                 snd_card_free(card);
557                 return err;
558         }
559 
560         usb_get_intf(usb_ifnum_to_if(device, 0));
561         usb_get_dev(device);
562         *cardp = card;
563         return 0;
564 }
565 
566 static int snd_us122l_probe(struct usb_interface *intf,
567                             const struct usb_device_id *id)
568 {
569         struct usb_device *device = interface_to_usbdev(intf);
570         struct snd_card *card;
571         int err;
572 
573         if (id->driver_info & US122L_FLAG_US144 &&
574                         device->speed == USB_SPEED_HIGH) {
575                 snd_printk(KERN_ERR "disable ehci-hcd to run US-144\n");
576                 return -ENODEV;
577         }
578 
579         snd_printdd(KERN_DEBUG"%p:%i\n",
580                     intf, intf->cur_altsetting->desc.bInterfaceNumber);
581         if (intf->cur_altsetting->desc.bInterfaceNumber != 1)
582                 return 0;
583 
584         err = us122l_usb_probe(usb_get_intf(intf), id, &card);
585         if (err < 0) {
586                 usb_put_intf(intf);
587                 return err;
588         }
589 
590         usb_set_intfdata(intf, card);
591         return 0;
592 }
593 
594 static void snd_us122l_disconnect(struct usb_interface *intf)
595 {
596         struct snd_card *card;
597         struct us122l *us122l;
598         struct list_head *p;
599 
600         card = usb_get_intfdata(intf);
601         if (!card)
602                 return;
603 
604         snd_card_disconnect(card);
605 
606         us122l = US122L(card);
607         mutex_lock(&us122l->mutex);
608         us122l_stop(us122l);
609         mutex_unlock(&us122l->mutex);
610 
611         /* release the midi resources */
612         list_for_each(p, &us122l->midi_list) {
613                 snd_usbmidi_disconnect(p);
614         }
615 
616         usb_put_intf(usb_ifnum_to_if(us122l->dev, 0));
617         usb_put_intf(usb_ifnum_to_if(us122l->dev, 1));
618         usb_put_dev(us122l->dev);
619 
620         while (atomic_read(&us122l->mmap_count))
621                 msleep(500);
622 
623         snd_card_free(card);
624 }
625 
626 static int snd_us122l_suspend(struct usb_interface *intf, pm_message_t message)
627 {
628         struct snd_card *card;
629         struct us122l *us122l;
630         struct list_head *p;
631 
632         card = usb_get_intfdata(intf);
633         if (!card)
634                 return 0;
635         snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
636 
637         us122l = US122L(card);
638         if (!us122l)
639                 return 0;
640 
641         list_for_each(p, &us122l->midi_list)
642                 snd_usbmidi_input_stop(p);
643 
644         mutex_lock(&us122l->mutex);
645         usb_stream_stop(&us122l->sk);
646         mutex_unlock(&us122l->mutex);
647 
648         return 0;
649 }
650 
651 static int snd_us122l_resume(struct usb_interface *intf)
652 {
653         struct snd_card *card;
654         struct us122l *us122l;
655         struct list_head *p;
656         int err;
657 
658         card = usb_get_intfdata(intf);
659         if (!card)
660                 return 0;
661 
662         us122l = US122L(card);
663         if (!us122l)
664                 return 0;
665 
666         mutex_lock(&us122l->mutex);
667         /* needed, doesn't restart without: */
668         if (us122l->is_us144) {
669                 err = usb_set_interface(us122l->dev, 0, 1);
670                 if (err) {
671                         snd_printk(KERN_ERR "usb_set_interface error\n");
672                         goto unlock;
673                 }
674         }
675         err = usb_set_interface(us122l->dev, 1, 1);
676         if (err) {
677                 snd_printk(KERN_ERR "usb_set_interface error\n");
678                 goto unlock;
679         }
680 
681         pt_info_set(us122l->dev, 0x11);
682         pt_info_set(us122l->dev, 0x10);
683 
684         err = us122l_set_sample_rate(us122l->dev,
685                                      us122l->sk.s->cfg.sample_rate);
686         if (err < 0) {
687                 snd_printk(KERN_ERR "us122l_set_sample_rate error\n");
688                 goto unlock;
689         }
690         err = usb_stream_start(&us122l->sk);
691         if (err)
692                 goto unlock;
693 
694         list_for_each(p, &us122l->midi_list)
695                 snd_usbmidi_input_start(p);
696 unlock:
697         mutex_unlock(&us122l->mutex);
698         snd_power_change_state(card, SNDRV_CTL_POWER_D0);
699         return err;
700 }
701 
702 static const struct usb_device_id snd_us122l_usb_id_table[] = {
703         {
704                 .match_flags =  USB_DEVICE_ID_MATCH_DEVICE,
705                 .idVendor =     0x0644,
706                 .idProduct =    USB_ID_US122L
707         },
708         {       /* US-144 only works at USB1.1! Disable module ehci-hcd. */
709                 .match_flags =  USB_DEVICE_ID_MATCH_DEVICE,
710                 .idVendor =     0x0644,
711                 .idProduct =    USB_ID_US144,
712                 .driver_info =  US122L_FLAG_US144
713         },
714         {
715                 .match_flags =  USB_DEVICE_ID_MATCH_DEVICE,
716                 .idVendor =     0x0644,
717                 .idProduct =    USB_ID_US122MKII
718         },
719         {
720                 .match_flags =  USB_DEVICE_ID_MATCH_DEVICE,
721                 .idVendor =     0x0644,
722                 .idProduct =    USB_ID_US144MKII,
723                 .driver_info =  US122L_FLAG_US144
724         },
725         { /* terminator */ }
726 };
727 MODULE_DEVICE_TABLE(usb, snd_us122l_usb_id_table);
728 
729 static struct usb_driver snd_us122l_usb_driver = {
730         .name =         "snd-usb-us122l",
731         .probe =        snd_us122l_probe,
732         .disconnect =   snd_us122l_disconnect,
733         .suspend =      snd_us122l_suspend,
734         .resume =       snd_us122l_resume,
735         .reset_resume = snd_us122l_resume,
736         .id_table =     snd_us122l_usb_id_table,
737         .supports_autosuspend = 1
738 };
739 
740 module_usb_driver(snd_us122l_usb_driver);
741 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php