diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-10-12 12:01:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-10-12 12:01:18 -0400 |
commit | 7702f47623e6c029b4ce59ce0ad39b869d5cc933 (patch) | |
tree | ae6a9ea2cc9445f43a9e05a35c717fe69134b274 | |
parent | 467251c69b1b39df78638d0d0cc60cf4d1d639a8 (diff) | |
parent | 99fee508245825765ff60155fed43f970ff83a8f (diff) |
Merge tag 'sound-4.14-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound fixes from Takashi Iwai:
"It's been a busy week for defending the attacks from fuzzer people.
This contains various USB-audio driver fixes and sequencer core fixes
spotted by syzkaller and other fuzzer, as well as one quirk for a
Plantronics USB audio device"
* tag 'sound-4.14-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
ALSA: caiaq: Fix stray URB at probe error path
ALSA: seq: Fix use-after-free at creating a port
ALSA: usb-audio: Kill stray URB at exiting
ALSA: line6: Fix leftover URB at error-path during probe
ALSA: line6: Fix NULL dereference at podhd_disconnect()
ALSA: line6: Fix missing initialization before error path
ALSA: seq: Fix copy_from_user() call inside lock
ALSA: usb-audio: Add sample rate quirk for Plantronics P610
-rw-r--r-- | include/sound/seq_virmidi.h | 1 | ||||
-rw-r--r-- | sound/core/seq/seq_clientmgr.c | 6 | ||||
-rw-r--r-- | sound/core/seq/seq_ports.c | 7 | ||||
-rw-r--r-- | sound/core/seq/seq_virmidi.c | 27 | ||||
-rw-r--r-- | sound/usb/caiaq/device.c | 12 | ||||
-rw-r--r-- | sound/usb/line6/driver.c | 7 | ||||
-rw-r--r-- | sound/usb/line6/podhd.c | 8 | ||||
-rw-r--r-- | sound/usb/mixer.c | 12 | ||||
-rw-r--r-- | sound/usb/mixer.h | 2 | ||||
-rw-r--r-- | sound/usb/quirks.c | 1 |
10 files changed, 61 insertions, 22 deletions
diff --git a/include/sound/seq_virmidi.h b/include/sound/seq_virmidi.h index a03acd0d398a..695257ae64ac 100644 --- a/include/sound/seq_virmidi.h +++ b/include/sound/seq_virmidi.h | |||
@@ -60,6 +60,7 @@ struct snd_virmidi_dev { | |||
60 | int port; /* created/attached port */ | 60 | int port; /* created/attached port */ |
61 | unsigned int flags; /* SNDRV_VIRMIDI_* */ | 61 | unsigned int flags; /* SNDRV_VIRMIDI_* */ |
62 | rwlock_t filelist_lock; | 62 | rwlock_t filelist_lock; |
63 | struct rw_semaphore filelist_sem; | ||
63 | struct list_head filelist; | 64 | struct list_head filelist; |
64 | }; | 65 | }; |
65 | 66 | ||
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index ea2d0ae85bd3..6c9cba2166d9 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c | |||
@@ -1259,6 +1259,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg) | |||
1259 | struct snd_seq_port_info *info = arg; | 1259 | struct snd_seq_port_info *info = arg; |
1260 | struct snd_seq_client_port *port; | 1260 | struct snd_seq_client_port *port; |
1261 | struct snd_seq_port_callback *callback; | 1261 | struct snd_seq_port_callback *callback; |
1262 | int port_idx; | ||
1262 | 1263 | ||
1263 | /* it is not allowed to create the port for an another client */ | 1264 | /* it is not allowed to create the port for an another client */ |
1264 | if (info->addr.client != client->number) | 1265 | if (info->addr.client != client->number) |
@@ -1269,7 +1270,9 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg) | |||
1269 | return -ENOMEM; | 1270 | return -ENOMEM; |
1270 | 1271 | ||
1271 | if (client->type == USER_CLIENT && info->kernel) { | 1272 | if (client->type == USER_CLIENT && info->kernel) { |
1272 | snd_seq_delete_port(client, port->addr.port); | 1273 | port_idx = port->addr.port; |
1274 | snd_seq_port_unlock(port); | ||
1275 | snd_seq_delete_port(client, port_idx); | ||
1273 | return -EINVAL; | 1276 | return -EINVAL; |
1274 | } | 1277 | } |
1275 | if (client->type == KERNEL_CLIENT) { | 1278 | if (client->type == KERNEL_CLIENT) { |
@@ -1290,6 +1293,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg) | |||
1290 | 1293 | ||
1291 | snd_seq_set_port_info(port, info); | 1294 | snd_seq_set_port_info(port, info); |
1292 | snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port); | 1295 | snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port); |
1296 | snd_seq_port_unlock(port); | ||
1293 | 1297 | ||
1294 | return 0; | 1298 | return 0; |
1295 | } | 1299 | } |
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index 0a7020c82bfc..d21ece9f8d73 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c | |||
@@ -122,7 +122,9 @@ static void port_subs_info_init(struct snd_seq_port_subs_info *grp) | |||
122 | } | 122 | } |
123 | 123 | ||
124 | 124 | ||
125 | /* create a port, port number is returned (-1 on failure) */ | 125 | /* create a port, port number is returned (-1 on failure); |
126 | * the caller needs to unref the port via snd_seq_port_unlock() appropriately | ||
127 | */ | ||
126 | struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, | 128 | struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, |
127 | int port) | 129 | int port) |
128 | { | 130 | { |
@@ -151,6 +153,7 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, | |||
151 | snd_use_lock_init(&new_port->use_lock); | 153 | snd_use_lock_init(&new_port->use_lock); |
152 | port_subs_info_init(&new_port->c_src); | 154 | port_subs_info_init(&new_port->c_src); |
153 | port_subs_info_init(&new_port->c_dest); | 155 | port_subs_info_init(&new_port->c_dest); |
156 | snd_use_lock_use(&new_port->use_lock); | ||
154 | 157 | ||
155 | num = port >= 0 ? port : 0; | 158 | num = port >= 0 ? port : 0; |
156 | mutex_lock(&client->ports_mutex); | 159 | mutex_lock(&client->ports_mutex); |
@@ -165,9 +168,9 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client, | |||
165 | list_add_tail(&new_port->list, &p->list); | 168 | list_add_tail(&new_port->list, &p->list); |
166 | client->num_ports++; | 169 | client->num_ports++; |
167 | new_port->addr.port = num; /* store the port number in the port */ | 170 | new_port->addr.port = num; /* store the port number in the port */ |
171 | sprintf(new_port->name, "port-%d", num); | ||
168 | write_unlock_irqrestore(&client->ports_lock, flags); | 172 | write_unlock_irqrestore(&client->ports_lock, flags); |
169 | mutex_unlock(&client->ports_mutex); | 173 | mutex_unlock(&client->ports_mutex); |
170 | sprintf(new_port->name, "port-%d", num); | ||
171 | 174 | ||
172 | return new_port; | 175 | return new_port; |
173 | } | 176 | } |
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index 8d93a4021c78..f48a4cd24ffc 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c | |||
@@ -77,13 +77,17 @@ static void snd_virmidi_init_event(struct snd_virmidi *vmidi, | |||
77 | * decode input event and put to read buffer of each opened file | 77 | * decode input event and put to read buffer of each opened file |
78 | */ | 78 | */ |
79 | static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev, | 79 | static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev, |
80 | struct snd_seq_event *ev) | 80 | struct snd_seq_event *ev, |
81 | bool atomic) | ||
81 | { | 82 | { |
82 | struct snd_virmidi *vmidi; | 83 | struct snd_virmidi *vmidi; |
83 | unsigned char msg[4]; | 84 | unsigned char msg[4]; |
84 | int len; | 85 | int len; |
85 | 86 | ||
86 | read_lock(&rdev->filelist_lock); | 87 | if (atomic) |
88 | read_lock(&rdev->filelist_lock); | ||
89 | else | ||
90 | down_read(&rdev->filelist_sem); | ||
87 | list_for_each_entry(vmidi, &rdev->filelist, list) { | 91 | list_for_each_entry(vmidi, &rdev->filelist, list) { |
88 | if (!vmidi->trigger) | 92 | if (!vmidi->trigger) |
89 | continue; | 93 | continue; |
@@ -97,7 +101,10 @@ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev, | |||
97 | snd_rawmidi_receive(vmidi->substream, msg, len); | 101 | snd_rawmidi_receive(vmidi->substream, msg, len); |
98 | } | 102 | } |
99 | } | 103 | } |
100 | read_unlock(&rdev->filelist_lock); | 104 | if (atomic) |
105 | read_unlock(&rdev->filelist_lock); | ||
106 | else | ||
107 | up_read(&rdev->filelist_sem); | ||
101 | 108 | ||
102 | return 0; | 109 | return 0; |
103 | } | 110 | } |
@@ -115,7 +122,7 @@ int snd_virmidi_receive(struct snd_rawmidi *rmidi, struct snd_seq_event *ev) | |||
115 | struct snd_virmidi_dev *rdev; | 122 | struct snd_virmidi_dev *rdev; |
116 | 123 | ||
117 | rdev = rmidi->private_data; | 124 | rdev = rmidi->private_data; |
118 | return snd_virmidi_dev_receive_event(rdev, ev); | 125 | return snd_virmidi_dev_receive_event(rdev, ev, true); |
119 | } | 126 | } |
120 | #endif /* 0 */ | 127 | #endif /* 0 */ |
121 | 128 | ||
@@ -130,7 +137,7 @@ static int snd_virmidi_event_input(struct snd_seq_event *ev, int direct, | |||
130 | rdev = private_data; | 137 | rdev = private_data; |
131 | if (!(rdev->flags & SNDRV_VIRMIDI_USE)) | 138 | if (!(rdev->flags & SNDRV_VIRMIDI_USE)) |
132 | return 0; /* ignored */ | 139 | return 0; /* ignored */ |
133 | return snd_virmidi_dev_receive_event(rdev, ev); | 140 | return snd_virmidi_dev_receive_event(rdev, ev, atomic); |
134 | } | 141 | } |
135 | 142 | ||
136 | /* | 143 | /* |
@@ -209,7 +216,6 @@ static int snd_virmidi_input_open(struct snd_rawmidi_substream *substream) | |||
209 | struct snd_virmidi_dev *rdev = substream->rmidi->private_data; | 216 | struct snd_virmidi_dev *rdev = substream->rmidi->private_data; |
210 | struct snd_rawmidi_runtime *runtime = substream->runtime; | 217 | struct snd_rawmidi_runtime *runtime = substream->runtime; |
211 | struct snd_virmidi *vmidi; | 218 | struct snd_virmidi *vmidi; |
212 | unsigned long flags; | ||
213 | 219 | ||
214 | vmidi = kzalloc(sizeof(*vmidi), GFP_KERNEL); | 220 | vmidi = kzalloc(sizeof(*vmidi), GFP_KERNEL); |
215 | if (vmidi == NULL) | 221 | if (vmidi == NULL) |
@@ -223,9 +229,11 @@ static int snd_virmidi_input_open(struct snd_rawmidi_substream *substream) | |||
223 | vmidi->client = rdev->client; | 229 | vmidi->client = rdev->client; |
224 | vmidi->port = rdev->port; | 230 | vmidi->port = rdev->port; |
225 | runtime->private_data = vmidi; | 231 | runtime->private_data = vmidi; |
226 | write_lock_irqsave(&rdev->filelist_lock, flags); | 232 | down_write(&rdev->filelist_sem); |
233 | write_lock_irq(&rdev->filelist_lock); | ||
227 | list_add_tail(&vmidi->list, &rdev->filelist); | 234 | list_add_tail(&vmidi->list, &rdev->filelist); |
228 | write_unlock_irqrestore(&rdev->filelist_lock, flags); | 235 | write_unlock_irq(&rdev->filelist_lock); |
236 | up_write(&rdev->filelist_sem); | ||
229 | vmidi->rdev = rdev; | 237 | vmidi->rdev = rdev; |
230 | return 0; | 238 | return 0; |
231 | } | 239 | } |
@@ -264,9 +272,11 @@ static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream) | |||
264 | struct snd_virmidi_dev *rdev = substream->rmidi->private_data; | 272 | struct snd_virmidi_dev *rdev = substream->rmidi->private_data; |
265 | struct snd_virmidi *vmidi = substream->runtime->private_data; | 273 | struct snd_virmidi *vmidi = substream->runtime->private_data; |
266 | 274 | ||
275 | down_write(&rdev->filelist_sem); | ||
267 | write_lock_irq(&rdev->filelist_lock); | 276 | write_lock_irq(&rdev->filelist_lock); |
268 | list_del(&vmidi->list); | 277 | list_del(&vmidi->list); |
269 | write_unlock_irq(&rdev->filelist_lock); | 278 | write_unlock_irq(&rdev->filelist_lock); |
279 | up_write(&rdev->filelist_sem); | ||
270 | snd_midi_event_free(vmidi->parser); | 280 | snd_midi_event_free(vmidi->parser); |
271 | substream->runtime->private_data = NULL; | 281 | substream->runtime->private_data = NULL; |
272 | kfree(vmidi); | 282 | kfree(vmidi); |
@@ -520,6 +530,7 @@ int snd_virmidi_new(struct snd_card *card, int device, struct snd_rawmidi **rrmi | |||
520 | rdev->rmidi = rmidi; | 530 | rdev->rmidi = rmidi; |
521 | rdev->device = device; | 531 | rdev->device = device; |
522 | rdev->client = -1; | 532 | rdev->client = -1; |
533 | init_rwsem(&rdev->filelist_sem); | ||
523 | rwlock_init(&rdev->filelist_lock); | 534 | rwlock_init(&rdev->filelist_lock); |
524 | INIT_LIST_HEAD(&rdev->filelist); | 535 | INIT_LIST_HEAD(&rdev->filelist); |
525 | rdev->seq_mode = SNDRV_VIRMIDI_SEQ_DISPATCH; | 536 | rdev->seq_mode = SNDRV_VIRMIDI_SEQ_DISPATCH; |
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c index 0fb6b1b79261..d8409d9ae55b 100644 --- a/sound/usb/caiaq/device.c +++ b/sound/usb/caiaq/device.c | |||
@@ -469,10 +469,12 @@ static int init_card(struct snd_usb_caiaqdev *cdev) | |||
469 | 469 | ||
470 | err = snd_usb_caiaq_send_command(cdev, EP1_CMD_GET_DEVICE_INFO, NULL, 0); | 470 | err = snd_usb_caiaq_send_command(cdev, EP1_CMD_GET_DEVICE_INFO, NULL, 0); |
471 | if (err) | 471 | if (err) |
472 | return err; | 472 | goto err_kill_urb; |
473 | 473 | ||
474 | if (!wait_event_timeout(cdev->ep1_wait_queue, cdev->spec_received, HZ)) | 474 | if (!wait_event_timeout(cdev->ep1_wait_queue, cdev->spec_received, HZ)) { |
475 | return -ENODEV; | 475 | err = -ENODEV; |
476 | goto err_kill_urb; | ||
477 | } | ||
476 | 478 | ||
477 | usb_string(usb_dev, usb_dev->descriptor.iManufacturer, | 479 | usb_string(usb_dev, usb_dev->descriptor.iManufacturer, |
478 | cdev->vendor_name, CAIAQ_USB_STR_LEN); | 480 | cdev->vendor_name, CAIAQ_USB_STR_LEN); |
@@ -507,6 +509,10 @@ static int init_card(struct snd_usb_caiaqdev *cdev) | |||
507 | 509 | ||
508 | setup_card(cdev); | 510 | setup_card(cdev); |
509 | return 0; | 511 | return 0; |
512 | |||
513 | err_kill_urb: | ||
514 | usb_kill_urb(&cdev->ep1_in_urb); | ||
515 | return err; | ||
510 | } | 516 | } |
511 | 517 | ||
512 | static int snd_probe(struct usb_interface *intf, | 518 | static int snd_probe(struct usb_interface *intf, |
diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index 0ff5a7d2e19f..c8f723c3a033 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c | |||
@@ -779,9 +779,10 @@ int line6_probe(struct usb_interface *interface, | |||
779 | return 0; | 779 | return 0; |
780 | 780 | ||
781 | error: | 781 | error: |
782 | if (line6->disconnect) | 782 | /* we can call disconnect callback here because no close-sync is |
783 | line6->disconnect(line6); | 783 | * needed yet at this point |
784 | snd_card_free(card); | 784 | */ |
785 | line6_disconnect(interface); | ||
785 | return ret; | 786 | return ret; |
786 | } | 787 | } |
787 | EXPORT_SYMBOL_GPL(line6_probe); | 788 | EXPORT_SYMBOL_GPL(line6_probe); |
diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c index 956f847a96e4..451007c27743 100644 --- a/sound/usb/line6/podhd.c +++ b/sound/usb/line6/podhd.c | |||
@@ -301,7 +301,8 @@ static void podhd_disconnect(struct usb_line6 *line6) | |||
301 | 301 | ||
302 | intf = usb_ifnum_to_if(line6->usbdev, | 302 | intf = usb_ifnum_to_if(line6->usbdev, |
303 | pod->line6.properties->ctrl_if); | 303 | pod->line6.properties->ctrl_if); |
304 | usb_driver_release_interface(&podhd_driver, intf); | 304 | if (intf) |
305 | usb_driver_release_interface(&podhd_driver, intf); | ||
305 | } | 306 | } |
306 | } | 307 | } |
307 | 308 | ||
@@ -317,6 +318,9 @@ static int podhd_init(struct usb_line6 *line6, | |||
317 | 318 | ||
318 | line6->disconnect = podhd_disconnect; | 319 | line6->disconnect = podhd_disconnect; |
319 | 320 | ||
321 | init_timer(&pod->startup_timer); | ||
322 | INIT_WORK(&pod->startup_work, podhd_startup_workqueue); | ||
323 | |||
320 | if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) { | 324 | if (pod->line6.properties->capabilities & LINE6_CAP_CONTROL) { |
321 | /* claim the data interface */ | 325 | /* claim the data interface */ |
322 | intf = usb_ifnum_to_if(line6->usbdev, | 326 | intf = usb_ifnum_to_if(line6->usbdev, |
@@ -358,8 +362,6 @@ static int podhd_init(struct usb_line6 *line6, | |||
358 | } | 362 | } |
359 | 363 | ||
360 | /* init device and delay registering */ | 364 | /* init device and delay registering */ |
361 | init_timer(&pod->startup_timer); | ||
362 | INIT_WORK(&pod->startup_work, podhd_startup_workqueue); | ||
363 | podhd_startup(pod); | 365 | podhd_startup(pod); |
364 | return 0; | 366 | return 0; |
365 | } | 367 | } |
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 9732edf77f86..91bc8f18791e 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
@@ -2234,6 +2234,9 @@ static int parse_audio_unit(struct mixer_build *state, int unitid) | |||
2234 | 2234 | ||
2235 | static void snd_usb_mixer_free(struct usb_mixer_interface *mixer) | 2235 | static void snd_usb_mixer_free(struct usb_mixer_interface *mixer) |
2236 | { | 2236 | { |
2237 | /* kill pending URBs */ | ||
2238 | snd_usb_mixer_disconnect(mixer); | ||
2239 | |||
2237 | kfree(mixer->id_elems); | 2240 | kfree(mixer->id_elems); |
2238 | if (mixer->urb) { | 2241 | if (mixer->urb) { |
2239 | kfree(mixer->urb->transfer_buffer); | 2242 | kfree(mixer->urb->transfer_buffer); |
@@ -2584,8 +2587,13 @@ _error: | |||
2584 | 2587 | ||
2585 | void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer) | 2588 | void snd_usb_mixer_disconnect(struct usb_mixer_interface *mixer) |
2586 | { | 2589 | { |
2587 | usb_kill_urb(mixer->urb); | 2590 | if (mixer->disconnected) |
2588 | usb_kill_urb(mixer->rc_urb); | 2591 | return; |
2592 | if (mixer->urb) | ||
2593 | usb_kill_urb(mixer->urb); | ||
2594 | if (mixer->rc_urb) | ||
2595 | usb_kill_urb(mixer->rc_urb); | ||
2596 | mixer->disconnected = true; | ||
2589 | } | 2597 | } |
2590 | 2598 | ||
2591 | #ifdef CONFIG_PM | 2599 | #ifdef CONFIG_PM |
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index 2b4b067646ab..545d99b09706 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h | |||
@@ -22,6 +22,8 @@ struct usb_mixer_interface { | |||
22 | struct urb *rc_urb; | 22 | struct urb *rc_urb; |
23 | struct usb_ctrlrequest *rc_setup_packet; | 23 | struct usb_ctrlrequest *rc_setup_packet; |
24 | u8 rc_buffer[6]; | 24 | u8 rc_buffer[6]; |
25 | |||
26 | bool disconnected; | ||
25 | }; | 27 | }; |
26 | 28 | ||
27 | #define MAX_CHANNELS 16 /* max logical channels */ | 29 | #define MAX_CHANNELS 16 /* max logical channels */ |
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index b8cb57aeec77..9ddaae3784f5 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c | |||
@@ -1138,6 +1138,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip) | |||
1138 | case USB_ID(0x047F, 0x0415): /* Plantronics BT-300 */ | 1138 | case USB_ID(0x047F, 0x0415): /* Plantronics BT-300 */ |
1139 | case USB_ID(0x047F, 0xAA05): /* Plantronics DA45 */ | 1139 | case USB_ID(0x047F, 0xAA05): /* Plantronics DA45 */ |
1140 | case USB_ID(0x047F, 0xC022): /* Plantronics C310 */ | 1140 | case USB_ID(0x047F, 0xC022): /* Plantronics C310 */ |
1141 | case USB_ID(0x047F, 0xC02F): /* Plantronics P610 */ | ||
1141 | case USB_ID(0x047F, 0xC036): /* Plantronics C520-M */ | 1142 | case USB_ID(0x047F, 0xC036): /* Plantronics C520-M */ |
1142 | case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */ | 1143 | case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */ |
1143 | case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */ | 1144 | case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */ |