[alsa-devel] [PATCH RFC RESEND] ALSA: usb-audio: Scarlett mixer interface for 18i20 Gen 2
Takashi Iwai
tiwai at suse.de
Wed Apr 24 12:55:17 CEST 2019
On Wed, 24 Apr 2019 01:58:42 +0200,
Geoffrey D. Bennett wrote:
>
> Add mixer quirk for the Focusrite Scarlett 18i20 Gen 2 audio
> interface. Although the interface is USB compliant, additional
> hardware mixing, routing, and metering functionality is available
> using proprietary USB requests.
>
> Signed-off-by: Geoffrey D. Bennett <g at b4.vu>
> ---
> (ping resend (no changes) as no feedback received for 3 weeks)
Oh sorry, I must have overlooked the post.
>
> Hi all,
>
> This patch adds the following controls for the Scarlett 18i20 Gen 2:
> - Master volume knob indicator
> - Volume controls for the 10 analogue HW outputs
> - HW/SW volume switches for the 10 analogue HW outputs
> - Output mux (where the sound for the HW outputs comes from; defaults
> to PCM outputs 1-20)
> - Capture mux (where the sound for PCM recording comes from; defaults
> to HW inputs 1-18)
> - Matrix mux (where the sound going into the mixer comes from; 18
> inputs default off)
> - Mixer matrix (18 inputs * 10 outputs = 180 controls)
> - Mute and dim indicators
> - Level meters
>
> This is my first attempt at writing any kernel device driver code, so
> apologies in advance if I missed something. There's a couple of
> things I'm particularly unsure about:
>
> - I added a private field to struct snd_usb_audio for storing the
> private mixer data. This seems wrong, but I didn't know where else I
> could/should put that data.
Hm, this is a thing I'd like to avoid as much as possible.
Currently, each usb_mixer_elem_info may have a private pointer, and
the original scarlett quirk uses it for storing its own "type"
information. This could be used for storing the data instead?
> - I've #define'd the vendor-specific interface, endpoint, max_data,
> and interval values. Is it okay to leave these hard-coded (they
> match the values provided by lsusb -v; I presume they never
> change?), or should they be looked up at runtime instead? (and if at
> runtime, how?)
In a case of USB-audio quirk entry, it's not too bad to hard-code the
values in the entry table, indeed.
> - I'm not sure if those snd_printk()s for unexpected responses from
> the hardware should be left in there? Removed? Reworded?
First off, avoid snd_printk() but use usb_audio_err() or dev_err()
directly. The error should be fine to be there unless you can trigger
the error too frequently from user-space intentionally.
> Comments and feedback would be very welcome.
Below are some more comments:
> +/* map from (dB + 80) * 2 to mixer value
> + * for dB in 0 .. 172: int(8192 * pow(10, ((dB - 160) / 2 / 20)))
> + */
> +static const __u16 scarlett2_mixer_values[173] = {
The "__" prefix can be dropped here. In general, __u16 or friends are
used for uapi definitions, and for the explicit type in the code, use
u16, etc, instead.
> +struct __attribute__((__packed__)) scarlett2_usb_volume_status {
We have __packed definition for __attribute__((__packed__).
And put it rather after the closing brace, e.g.
struct scarlett2_usb_volume_status {
....
} __packed;
> +/* Send a proprietary format request to the Scarlett interface. */
> +static int scarlett2_usb(
> + struct usb_mixer_interface *mixer, __u32 cmd,
> + void *req_data, __u16 req_size, void *resp_data, __u16 resp_size)
> +{
> + struct scarlett2_chip_data *private = mixer->chip->private;
> +
> + /* proprietary request/response format */
> + struct scarlett2_usb_packet {
> + __u32 cmd;
> + __u16 size;
> + __u16 seq;
> + __u32 error;
> + __u32 pad;
> + __u8 data[];
> + };
Better to define outside the function.
> +
> + __u16 req_buf_size =
> + sizeof(struct scarlett2_usb_packet) + req_size;
> + __u16 resp_buf_size =
> + sizeof(struct scarlett2_usb_packet) + resp_size;
> +
> + struct scarlett2_usb_packet *req, *resp;
> +
> + int seq, err;
> + __u32 resp_cmd;
> + __u32 resp_seq;
> + __u16 size;
> +
> + mutex_lock(&private->usb_mutex);
> +
> + /* build request message and send it */
> +
> + req = kmalloc(req_buf_size, GFP_KERNEL);
> + if (!req) {
> + mutex_unlock(&private->usb_mutex);
> + return -ENOMEM;
The standard idiom is to move the whole mutex_unlock() calls into the
end of the function and use goto here.
if (!req) {
err = -ENOMEM;
goto unlock;
}
....
unlock:
mutex_lock(&private->usb_mutex);
return err;
> +int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer)
> +{
....
> + /* Initialise private data, routing, sequence number */
> + if ((err = scarlett2_init_private(mixer, info)) < 0)
> + return err;
Try to run checkpatch.pl once and fix the errors reported there.
thanks,
Takashi
More information about the Alsa-devel
mailing list