Commit 27d10f56 authored by Clemens Ladisch's avatar Clemens Ladisch Committed by Jaroslav Kysela

[ALSA] usb-audio - cache vendor/product IDs

USB generic driver
Cache the decoded values of idVendor/idProduct to get rid of most of
those ugly le16_to_cpu() calls.
Signed-off-by: default avatarClemens Ladisch <clemens@ladisch.de>
parent b259b10c
This diff is collapsed.
...@@ -118,6 +118,11 @@ ...@@ -118,6 +118,11 @@
/* maximum number of endpoints per interface */ /* maximum number of endpoints per interface */
#define MIDI_MAX_ENDPOINTS 2 #define MIDI_MAX_ENDPOINTS 2
/* handling of USB vendor/product ID pairs as 32-bit numbers */
#define USB_ID(vendor, product) (((vendor) << 16) | (product))
#define USB_ID_VENDOR(id) ((id) >> 16)
#define USB_ID_PRODUCT(id) ((u16)(id))
/* /*
*/ */
...@@ -127,6 +132,7 @@ struct snd_usb_audio { ...@@ -127,6 +132,7 @@ struct snd_usb_audio {
int index; int index;
struct usb_device *dev; struct usb_device *dev;
snd_card_t *card; snd_card_t *card;
u32 usb_id;
int shutdown; int shutdown;
int num_interfaces; int num_interfaces;
......
...@@ -955,88 +955,87 @@ static snd_rawmidi_substream_t* snd_usbmidi_find_substream(snd_usb_midi_t* umidi ...@@ -955,88 +955,87 @@ static snd_rawmidi_substream_t* snd_usbmidi_find_substream(snd_usb_midi_t* umidi
* such as internal control or synthesizer ports. * such as internal control or synthesizer ports.
*/ */
static struct { static struct {
__u16 vendor; u32 id;
__u16 product;
int port; int port;
const char *name_format; const char *name_format;
} snd_usbmidi_port_names[] = { } snd_usbmidi_port_names[] = {
/* Roland UA-100 */ /* Roland UA-100 */
{0x0582, 0x0000, 2, "%s Control"}, { USB_ID(0x0582, 0x0000), 2, "%s Control" },
/* Roland SC-8850 */ /* Roland SC-8850 */
{0x0582, 0x0003, 0, "%s Part A"}, { USB_ID(0x0582, 0x0003), 0, "%s Part A" },
{0x0582, 0x0003, 1, "%s Part B"}, { USB_ID(0x0582, 0x0003), 1, "%s Part B" },
{0x0582, 0x0003, 2, "%s Part C"}, { USB_ID(0x0582, 0x0003), 2, "%s Part C" },
{0x0582, 0x0003, 3, "%s Part D"}, { USB_ID(0x0582, 0x0003), 3, "%s Part D" },
{0x0582, 0x0003, 4, "%s MIDI 1"}, { USB_ID(0x0582, 0x0003), 4, "%s MIDI 1" },
{0x0582, 0x0003, 5, "%s MIDI 2"}, { USB_ID(0x0582, 0x0003), 5, "%s MIDI 2" },
/* Roland U-8 */ /* Roland U-8 */
{0x0582, 0x0004, 0, "%s MIDI"}, { USB_ID(0x0582, 0x0004), 0, "%s MIDI" },
{0x0582, 0x0004, 1, "%s Control"}, { USB_ID(0x0582, 0x0004), 1, "%s Control" },
/* Roland SC-8820 */ /* Roland SC-8820 */
{0x0582, 0x0007, 0, "%s Part A"}, { USB_ID(0x0582, 0x0007), 0, "%s Part A" },
{0x0582, 0x0007, 1, "%s Part B"}, { USB_ID(0x0582, 0x0007), 1, "%s Part B" },
{0x0582, 0x0007, 2, "%s MIDI"}, { USB_ID(0x0582, 0x0007), 2, "%s MIDI" },
/* Roland SK-500 */ /* Roland SK-500 */
{0x0582, 0x000b, 0, "%s Part A"}, { USB_ID(0x0582, 0x000b), 0, "%s Part A" },
{0x0582, 0x000b, 1, "%s Part B"}, { USB_ID(0x0582, 0x000b), 1, "%s Part B" },
{0x0582, 0x000b, 2, "%s MIDI"}, { USB_ID(0x0582, 0x000b), 2, "%s MIDI" },
/* Roland SC-D70 */ /* Roland SC-D70 */
{0x0582, 0x000c, 0, "%s Part A"}, { USB_ID(0x0582, 0x000c), 0, "%s Part A" },
{0x0582, 0x000c, 1, "%s Part B"}, { USB_ID(0x0582, 0x000c), 1, "%s Part B" },
{0x0582, 0x000c, 2, "%s MIDI"}, { USB_ID(0x0582, 0x000c), 2, "%s MIDI" },
/* Edirol UM-880 */ /* Edirol UM-880 */
{0x0582, 0x0014, 8, "%s Control"}, { USB_ID(0x0582, 0x0014), 8, "%s Control" },
/* Edirol SD-90 */ /* Edirol SD-90 */
{0x0582, 0x0016, 0, "%s Part A"}, { USB_ID(0x0582, 0x0016), 0, "%s Part A" },
{0x0582, 0x0016, 1, "%s Part B"}, { USB_ID(0x0582, 0x0016), 1, "%s Part B" },
{0x0582, 0x0016, 2, "%s MIDI 1"}, { USB_ID(0x0582, 0x0016), 2, "%s MIDI 1" },
{0x0582, 0x0016, 3, "%s MIDI 2"}, { USB_ID(0x0582, 0x0016), 3, "%s MIDI 2" },
/* Edirol UM-550 */ /* Edirol UM-550 */
{0x0582, 0x0023, 5, "%s Control"}, { USB_ID(0x0582, 0x0023), 5, "%s Control" },
/* Edirol SD-20 */ /* Edirol SD-20 */
{0x0582, 0x0027, 0, "%s Part A"}, { USB_ID(0x0582, 0x0027), 0, "%s Part A" },
{0x0582, 0x0027, 1, "%s Part B"}, { USB_ID(0x0582, 0x0027), 1, "%s Part B" },
{0x0582, 0x0027, 2, "%s MIDI"}, { USB_ID(0x0582, 0x0027), 2, "%s MIDI" },
/* Edirol SD-80 */ /* Edirol SD-80 */
{0x0582, 0x0029, 0, "%s Part A"}, { USB_ID(0x0582, 0x0029), 0, "%s Part A" },
{0x0582, 0x0029, 1, "%s Part B"}, { USB_ID(0x0582, 0x0029), 1, "%s Part B" },
{0x0582, 0x0029, 2, "%s MIDI 1"}, { USB_ID(0x0582, 0x0029), 2, "%s MIDI 1" },
{0x0582, 0x0029, 3, "%s MIDI 2"}, { USB_ID(0x0582, 0x0029), 3, "%s MIDI 2" },
/* Edirol UA-700 */ /* Edirol UA-700 */
{0x0582, 0x002b, 0, "%s MIDI"}, { USB_ID(0x0582, 0x002b), 0, "%s MIDI" },
{0x0582, 0x002b, 1, "%s Control"}, { USB_ID(0x0582, 0x002b), 1, "%s Control" },
/* Roland VariOS */ /* Roland VariOS */
{0x0582, 0x002f, 0, "%s MIDI"}, { USB_ID(0x0582, 0x002f), 0, "%s MIDI" },
{0x0582, 0x002f, 1, "%s External MIDI"}, { USB_ID(0x0582, 0x002f), 1, "%s External MIDI" },
{0x0582, 0x002f, 2, "%s Sync"}, { USB_ID(0x0582, 0x002f), 2, "%s Sync" },
/* Edirol PCR */ /* Edirol PCR */
{0x0582, 0x0033, 0, "%s MIDI"}, { USB_ID(0x0582, 0x0033), 0, "%s MIDI" },
{0x0582, 0x0033, 1, "%s 1"}, { USB_ID(0x0582, 0x0033), 1, "%s 1" },
{0x0582, 0x0033, 2, "%s 2"}, { USB_ID(0x0582, 0x0033), 2, "%s 2" },
/* BOSS GS-10 */ /* BOSS GS-10 */
{0x0582, 0x003b, 0, "%s MIDI"}, { USB_ID(0x0582, 0x003b), 0, "%s MIDI" },
{0x0582, 0x003b, 1, "%s Control"}, { USB_ID(0x0582, 0x003b), 1, "%s Control" },
/* Edirol UA-1000 */ /* Edirol UA-1000 */
{0x0582, 0x0044, 0, "%s MIDI"}, { USB_ID(0x0582, 0x0044), 0, "%s MIDI" },
{0x0582, 0x0044, 1, "%s Control"}, { USB_ID(0x0582, 0x0044), 1, "%s Control" },
/* Edirol UR-80 */ /* Edirol UR-80 */
{0x0582, 0x0048, 0, "%s MIDI"}, { USB_ID(0x0582, 0x0048), 0, "%s MIDI" },
{0x0582, 0x0048, 1, "%s 1"}, { USB_ID(0x0582, 0x0048), 1, "%s 1" },
{0x0582, 0x0048, 2, "%s 2"}, { USB_ID(0x0582, 0x0048), 2, "%s 2" },
/* Edirol PCR-A */ /* Edirol PCR-A */
{0x0582, 0x004d, 0, "%s MIDI"}, { USB_ID(0x0582, 0x004d), 0, "%s MIDI" },
{0x0582, 0x004d, 1, "%s 1"}, { USB_ID(0x0582, 0x004d), 1, "%s 1" },
{0x0582, 0x004d, 2, "%s 2"}, { USB_ID(0x0582, 0x004d), 2, "%s 2" },
/* M-Audio MidiSport 8x8 */ /* M-Audio MidiSport 8x8 */
{0x0763, 0x1031, 8, "%s Control"}, { USB_ID(0x0763, 0x1031), 8, "%s Control" },
{0x0763, 0x1033, 8, "%s Control"}, { USB_ID(0x0763, 0x1033), 8, "%s Control" },
/* MOTU Fastlane */ /* MOTU Fastlane */
{0x07fd, 0x0001, 0, "%s MIDI A"}, { USB_ID(0x07fd, 0x0001), 0, "%s MIDI A" },
{0x07fd, 0x0001, 1, "%s MIDI B"}, { USB_ID(0x07fd, 0x0001), 1, "%s MIDI B" },
/* Emagic Unitor8/AMT8/MT4 */ /* Emagic Unitor8/AMT8/MT4 */
{0x086a, 0x0001, 8, "%s Broadcast"}, { USB_ID(0x086a, 0x0001), 8, "%s Broadcast" },
{0x086a, 0x0002, 8, "%s Broadcast"}, { USB_ID(0x086a, 0x0002), 8, "%s Broadcast" },
{0x086a, 0x0003, 4, "%s Broadcast"}, { USB_ID(0x086a, 0x0003), 4, "%s Broadcast" },
}; };
static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi, static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,
...@@ -1044,7 +1043,6 @@ static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi, ...@@ -1044,7 +1043,6 @@ static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,
snd_rawmidi_substream_t** rsubstream) snd_rawmidi_substream_t** rsubstream)
{ {
int i; int i;
__u16 vendor, product;
const char *name_format; const char *name_format;
snd_rawmidi_substream_t* substream = snd_usbmidi_find_substream(umidi, stream, number); snd_rawmidi_substream_t* substream = snd_usbmidi_find_substream(umidi, stream, number);
...@@ -1055,11 +1053,8 @@ static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi, ...@@ -1055,11 +1053,8 @@ static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,
/* TODO: read port name from jack descriptor */ /* TODO: read port name from jack descriptor */
name_format = "%s MIDI %d"; name_format = "%s MIDI %d";
vendor = le16_to_cpu(umidi->chip->dev->descriptor.idVendor);
product = le16_to_cpu(umidi->chip->dev->descriptor.idProduct);
for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_names); ++i) { for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_names); ++i) {
if (snd_usbmidi_port_names[i].vendor == vendor && if (snd_usbmidi_port_names[i].id == umidi->chip->usb_id &&
snd_usbmidi_port_names[i].product == product &&
snd_usbmidi_port_names[i].port == number) { snd_usbmidi_port_names[i].port == number) {
name_format = snd_usbmidi_port_names[i].name_format; name_format = snd_usbmidi_port_names[i].name_format;
break; break;
...@@ -1226,7 +1221,7 @@ static int snd_usbmidi_detect_endpoints(snd_usb_midi_t* umidi, ...@@ -1226,7 +1221,7 @@ static int snd_usbmidi_detect_endpoints(snd_usb_midi_t* umidi,
struct usb_endpoint_descriptor* epd; struct usb_endpoint_descriptor* epd;
int i, out_eps = 0, in_eps = 0; int i, out_eps = 0, in_eps = 0;
if (le16_to_cpu(umidi->chip->dev->descriptor.idVendor) == 0x0582) if (USB_ID_VENDOR(umidi->chip->usb_id) == 0x0582)
snd_usbmidi_switch_roland_altsetting(umidi); snd_usbmidi_switch_roland_altsetting(umidi);
if (endpoint[0].out_ep || endpoint[0].in_ep) if (endpoint[0].out_ep || endpoint[0].in_ep)
......
...@@ -89,8 +89,6 @@ struct usb_mixer_build { ...@@ -89,8 +89,6 @@ struct usb_mixer_build {
struct usb_mixer_interface *mixer; struct usb_mixer_interface *mixer;
unsigned char *buffer; unsigned char *buffer;
unsigned int buflen; unsigned int buflen;
unsigned short vendor;
unsigned short product;
DECLARE_BITMAP(unitbitmap, 256); DECLARE_BITMAP(unitbitmap, 256);
usb_audio_term_t oterm; usb_audio_term_t oterm;
const struct usbmix_name_map *map; const struct usbmix_name_map *map;
...@@ -906,11 +904,16 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc, ...@@ -906,11 +904,16 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc,
/* note that detection between firmware 2.1.1.7 (N101) and later 2.1.1.21 */ /* note that detection between firmware 2.1.1.7 (N101) and later 2.1.1.21 */
/* is not very clear from datasheets */ /* is not very clear from datasheets */
/* I hope that the min value is -15360 for newer firmware --jk */ /* I hope that the min value is -15360 for newer firmware --jk */
if (((state->vendor == 0x471 && (state->product == 0x104 || state->product == 0x105 || state->product == 0x101)) || switch (state->chip->usb_id) {
(state->vendor == 0x672 && state->product == 0x1041)) && !strcmp(kctl->id.name, "PCM Playback Volume") && case USB_ID(0x0471, 0x0101):
cval->min == -15616) { case USB_ID(0x0471, 0x0104):
snd_printk("USB Audio: using volume control quirk for the UDA1321/N101 chip\n"); case USB_ID(0x0471, 0x0105):
cval->max = -256; case USB_ID(0x0672, 0x1041):
if (!strcmp(kctl->id.name, "PCM Playback Volume") &&
cval->min == -15616) {
snd_printk("using volume control quirk for the UDA1321/N101 chip\n");
cval->max = -256;
}
} }
snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
...@@ -1574,7 +1577,6 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) ...@@ -1574,7 +1577,6 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
mixer_build_t state; mixer_build_t state;
int err; int err;
const struct usbmix_ctl_map *map; const struct usbmix_ctl_map *map;
struct usb_device_descriptor *dev = &mixer->chip->dev->descriptor;
struct usb_host_interface *hostif; struct usb_host_interface *hostif;
hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0]; hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0];
...@@ -1583,12 +1585,10 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) ...@@ -1583,12 +1585,10 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
state.mixer = mixer; state.mixer = mixer;
state.buffer = hostif->extra; state.buffer = hostif->extra;
state.buflen = hostif->extralen; state.buflen = hostif->extralen;
state.vendor = le16_to_cpu(dev->idVendor);
state.product = le16_to_cpu(dev->idProduct);
/* check the mapping table */ /* check the mapping table */
for (map = usbmix_ctl_maps; map->vendor; map++) { for (map = usbmix_ctl_maps; map->id; map++) {
if (map->vendor == state.vendor && map->product == state.product) { if (map->id == state.chip->usb_id) {
state.map = map->map; state.map = map->map;
state.selector_map = map->selector_map; state.selector_map = map->selector_map;
mixer->ignore_ctl_error = map->ignore_ctl_error; mixer->ignore_ctl_error = map->ignore_ctl_error;
...@@ -1766,12 +1766,12 @@ static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer) ...@@ -1766,12 +1766,12 @@ static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
snd_hwdep_t *hwdep; snd_hwdep_t *hwdep;
int err, len; int err, len;
switch (le16_to_cpu(mixer->chip->dev->descriptor.idProduct)) { switch (mixer->chip->usb_id) {
case 0x3000: case USB_ID(0x041e, 0x3000):
mixer->rc_type = RC_EXTIGY; mixer->rc_type = RC_EXTIGY;
len = 2; len = 2;
break; break;
case 0x3020: case USB_ID(0x041e, 0x3020):
mixer->rc_type = RC_AUDIGY2NX; mixer->rc_type = RC_AUDIGY2NX;
len = 6; len = 6;
break; break;
...@@ -1844,11 +1844,9 @@ int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif) ...@@ -1844,11 +1844,9 @@ int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif)
return err; return err;
} }
if (le16_to_cpu(chip->dev->descriptor.idVendor) == 0x041e) { if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0) {
if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0) { snd_usb_mixer_free(mixer);
snd_usb_mixer_free(mixer); return err;
return err;
}
} }
err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops); err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops);
......
...@@ -33,8 +33,7 @@ struct usbmix_selector_map { ...@@ -33,8 +33,7 @@ struct usbmix_selector_map {
}; };
struct usbmix_ctl_map { struct usbmix_ctl_map {
int vendor; u32 id;
int product;
const struct usbmix_name_map *map; const struct usbmix_name_map *map;
const struct usbmix_selector_map *selector_map; const struct usbmix_selector_map *selector_map;
int ignore_ctl_error; int ignore_ctl_error;
...@@ -225,26 +224,26 @@ static struct usbmix_name_map justlink_map[] = { ...@@ -225,26 +224,26 @@ static struct usbmix_name_map justlink_map[] = {
static struct usbmix_ctl_map usbmix_ctl_maps[] = { static struct usbmix_ctl_map usbmix_ctl_maps[] = {
{ {
.vendor = 0x41e, .product = 0x3000, .id = USB_ID(0x041e, 0x3000),
.map = extigy_map, .map = extigy_map,
.ignore_ctl_error = 1, .ignore_ctl_error = 1,
}, },
{ {
.vendor = 0x41e, .product = 0x3010, .id = USB_ID(0x041e, 0x3010),
.map = mp3plus_map, .map = mp3plus_map,
}, },
{ {
.vendor = 0x41e, .product = 0x3020, .id = USB_ID(0x041e, 0x3020),
.map = audigy2nx_map, .map = audigy2nx_map,
.selector_map = audigy2nx_selectors, .selector_map = audigy2nx_selectors,
}, },
{ {
.vendor = 0x8bb, .product = 0x2702, .id = USB_ID(0x08bb, 0x2702),
.map = linex_map, .map = linex_map,
.ignore_ctl_error = 1, .ignore_ctl_error = 1,
}, },
{ {
.vendor = 0xc45, .product = 0x1158, .id = USB_ID(0x0c45, 0x1158),
.map = justlink_map, .map = justlink_map,
}, },
{ 0 } /* terminator */ { 0 } /* terminator */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment