diff options
author | Geoffrey D. Bennett <g@b4.vu> | 2021-06-21 02:16:52 +0930 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2021-06-21 08:38:11 +0200 |
commit | 6c0a2078134aba6a77291554035304df9e16b85c (patch) | |
tree | 610bd27874cc89ef9f29e6a854cda45d1d779bed /sound/usb | |
parent | 296726319289f0d5ff9b6d1cc039fbab4d413b98 (diff) | |
download | linux-6c0a2078134aba6a77291554035304df9e16b85c.tar.bz2 |
ALSA: usb-audio: scarlett2: Remove hard-coded USB #defines
Remove the hard-coded interface number and related constants for the
vendor-specific interface and look them up from the USB endpoint
descriptor.
Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
Link: https://lore.kernel.org/r/20210620164652.GA9237@m.b4.vu
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/mixer_scarlett_gen2.c | 74 |
1 files changed, 55 insertions, 19 deletions
diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 45fd540920b9..2e1937b072ee 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -230,6 +230,10 @@ struct scarlett2_data { struct mutex data_mutex; /* lock access to this data */ struct delayed_work work; const struct scarlett2_device_info *info; + __u8 bInterfaceNumber; + __u8 bEndpointAddress; + __u16 wMaxPacketSize; + __u8 bInterval; int num_mux_srcs; int num_mux_dsts; u16 scarlett2_seq; @@ -444,12 +448,6 @@ static int scarlett2_get_port_start_num(const struct scarlett2_ports *ports, /*** USB Interactions ***/ -/* Vendor-Specific Interface, Endpoint, MaxPacketSize, Interval */ -#define SCARLETT2_USB_VENDOR_SPECIFIC_INTERFACE 5 -#define SCARLETT2_USB_INTERRUPT_ENDPOINT 4 -#define SCARLETT2_USB_INTERRUPT_MAX_DATA 64 -#define SCARLETT2_USB_INTERRUPT_INTERVAL 3 - /* Interrupt flags for dim/mute button and monitor changes */ #define SCARLETT2_USB_NOTIFY_DIM_MUTE 0x00200000 #define SCARLETT2_USB_NOTIFY_MONITOR 0x00400000 @@ -615,7 +613,7 @@ static int scarlett2_usb( SCARLETT2_USB_VENDOR_SPECIFIC_CMD_REQ, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, 0, - SCARLETT2_USB_VENDOR_SPECIFIC_INTERFACE, + private->bInterfaceNumber, req, req_buf_size); @@ -635,7 +633,7 @@ static int scarlett2_usb( SCARLETT2_USB_VENDOR_SPECIFIC_CMD_RESP, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, 0, - SCARLETT2_USB_VENDOR_SPECIFIC_INTERFACE, + private->bInterfaceNumber, resp, resp_buf_size); @@ -1886,12 +1884,45 @@ static void scarlett2_count_mux_io(struct scarlett2_data *private) private->num_mux_dsts = dsts; } -/* Initialise private data and sequence number */ +/* Look through the interface descriptors for the Focusrite Control + * interface (bInterfaceClass = 255 Vendor Specific Class) and set + * bInterfaceNumber, bEndpointAddress, wMaxPacketSize, and bInterval + * in private + */ +static int scarlett2_find_fc_interface(struct usb_device *dev, + struct scarlett2_data *private) +{ + struct usb_host_config *config = dev->actconfig; + int i; + + for (i = 0; i < config->desc.bNumInterfaces; i++) { + struct usb_interface *intf = config->interface[i]; + struct usb_interface_descriptor *desc = + &intf->altsetting[0].desc; + struct usb_endpoint_descriptor *epd; + + if (desc->bInterfaceClass != 255) + continue; + + epd = get_endpoint(intf->altsetting, 0); + private->bInterfaceNumber = desc->bInterfaceNumber; + private->bEndpointAddress = epd->bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK; + private->wMaxPacketSize = le16_to_cpu(epd->wMaxPacketSize); + private->bInterval = epd->bInterval; + return 0; + } + + return -EINVAL; +} + +/* Initialise private data, sequence number, and get the USB data */ static int scarlett2_init_private(struct usb_mixer_interface *mixer, const struct scarlett2_device_info *info) { struct scarlett2_data *private = kzalloc(sizeof(struct scarlett2_data), GFP_KERNEL); + int err; if (!private) return -ENOMEM; @@ -1899,13 +1930,19 @@ static int scarlett2_init_private(struct usb_mixer_interface *mixer, mutex_init(&private->usb_mutex); mutex_init(&private->data_mutex); INIT_DELAYED_WORK(&private->work, scarlett2_config_save_work); + + mixer->private_data = private; + mixer->private_free = scarlett2_private_free; + mixer->private_suspend = scarlett2_private_suspend; + private->info = info; scarlett2_count_mux_io(private); private->scarlett2_seq = 0; private->mixer = mixer; - mixer->private_data = private; - mixer->private_free = scarlett2_private_free; - mixer->private_suspend = scarlett2_private_suspend; + + err = scarlett2_find_fc_interface(mixer->chip->dev, private); + if (err < 0) + return err; /* Initialise the sequence number used for the proprietary commands */ return scarlett2_usb(mixer, SCARLETT2_USB_INIT_SEQ, NULL, 0, NULL, 0); @@ -2050,8 +2087,8 @@ requeue: static int scarlett2_init_notify(struct usb_mixer_interface *mixer) { struct usb_device *dev = mixer->chip->dev; - unsigned int pipe = usb_rcvintpipe(dev, - SCARLETT2_USB_INTERRUPT_ENDPOINT); + struct scarlett2_data *private = mixer->private_data; + unsigned int pipe = usb_rcvintpipe(dev, private->bEndpointAddress); void *transfer_buffer; if (mixer->urb) { @@ -2067,14 +2104,13 @@ static int scarlett2_init_notify(struct usb_mixer_interface *mixer) if (!mixer->urb) return -ENOMEM; - transfer_buffer = kmalloc(SCARLETT2_USB_INTERRUPT_MAX_DATA, GFP_KERNEL); + transfer_buffer = kmalloc(private->wMaxPacketSize, GFP_KERNEL); if (!transfer_buffer) return -ENOMEM; usb_fill_int_urb(mixer->urb, dev, pipe, - transfer_buffer, SCARLETT2_USB_INTERRUPT_MAX_DATA, - scarlett2_notify, mixer, - SCARLETT2_USB_INTERRUPT_INTERVAL); + transfer_buffer, private->wMaxPacketSize, + scarlett2_notify, mixer, private->bInterval); return usb_submit_urb(mixer->urb, GFP_KERNEL); } @@ -2084,7 +2120,7 @@ static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer, { int err; - /* Initialise private data and sequence number */ + /* Initialise private data, sequence number, and get the USB data */ err = scarlett2_init_private(mixer, info); if (err < 0) return err; |