Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: FCP: Add Focusrite Control Protocol driver

Add a new kernel driver for the Focusrite Control Protocol (FCP),
which is used by Focusrite Scarlett 2nd Gen, 3rd Gen, 4th Gen, Clarett
USB, Clarett+, and Vocaster series audio interfaces. This driver
provides a user-space control interface via ALSA's hwdep subsystem.

Unlike the existing Scarlett2 driver which implements all ALSA
controls in kernel space, this new FCP driver takes a different
approach by providing a minimal kernel interface that allows a
user-space driver to send FCP commands and receive notifications. The
only control implemented in kernel space is the Level Meter, since it
requires frequent polling of volatile data.

While this driver supports all interfaces that the Scarlett2 driver
works with, it is initially enabled only for 4th Gen 16i16, 18i16,
and 18i20 interfaces that are not supported by the Scarlett2 driver.

Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
Link: https://patch.msgid.link/597741a9b1198b965561547511d3d345f91cba20.1737048528.git.g@b4.vu
Signed-off-by: Takashi Iwai <tiwai@suse.de>

authored by

Geoffrey D. Bennett and committed by
Takashi Iwai
46757a3e bb5f86ea

+1277 -4
+6 -4
MAINTAINERS
··· 8951 8951 S: Maintained 8952 8952 F: drivers/input/joystick/fsia6b.c 8953 8953 8954 - FOCUSRITE SCARLETT2 MIXER DRIVER (Scarlett Gen 2+ and Clarett) 8954 + FOCUSRITE CONTROL PROTOCOL/SCARLETT2 MIXER DRIVERS (Scarlett Gen 2+, Clarett, and Vocaster) 8955 8955 M: Geoffrey D. Bennett <g@b4.vu> 8956 8956 L: linux-sound@vger.kernel.org 8957 8957 S: Maintained 8958 - W: https://github.com/geoffreybennett/scarlett-gen2 8959 - B: https://github.com/geoffreybennett/scarlett-gen2/issues 8960 - T: git https://github.com/geoffreybennett/scarlett-gen2.git 8958 + W: https://github.com/geoffreybennett/linux-fcp 8959 + B: https://github.com/geoffreybennett/linux-fcp/issues 8960 + T: git https://github.com/geoffreybennett/linux-fcp.git 8961 + F: include/uapi/sound/fcp.h 8961 8962 F: include/uapi/sound/scarlett2.h 8963 + F: sound/usb/fcp.c 8962 8964 F: sound/usb/mixer_scarlett2.c 8963 8965 8964 8966 FORCEDETH GIGABIT ETHERNET DRIVER
+120
include/uapi/sound/fcp.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ 2 + /* 3 + * Focusrite Control Protocol Driver for ALSA 4 + * 5 + * Copyright (c) 2024-2025 by Geoffrey D. Bennett <g at b4.vu> 6 + */ 7 + /* 8 + * DOC: FCP (Focusrite Control Protocol) User-Space API 9 + * 10 + * This header defines the interface between the FCP kernel driver and 11 + * user-space programs to enable the use of the proprietary features 12 + * available in Focusrite USB audio interfaces. This includes Scarlett 13 + * 2nd Gen, 3rd Gen, 4th Gen, Clarett USB, Clarett+, and Vocaster 14 + * series devices. 15 + * 16 + * The interface is provided via ALSA's hwdep interface. Opening the 17 + * hwdep device requires CAP_SYS_RAWIO privileges as this interface 18 + * provides near-direct access. 19 + * 20 + * For details on the FCP protocol, refer to the kernel scarlett2 21 + * driver in sound/usb/mixer_scarlett2.c and the fcp-support project 22 + * at https://github.com/geoffreybennett/fcp-support 23 + * 24 + * For examples of using these IOCTLs, see the fcp-server source in 25 + * the fcp-support project. 26 + * 27 + * IOCTL Interface 28 + * -------------- 29 + * FCP_IOCTL_PVERSION: 30 + * Returns the protocol version supported by the driver. 31 + * 32 + * FCP_IOCTL_INIT: 33 + * Initialises the protocol and synchronises sequence numbers 34 + * between the driver and device. Must be called at least once 35 + * before sending commands. Can be safely called again at any time. 36 + * 37 + * FCP_IOCTL_CMD: 38 + * Sends an FCP command to the device and returns the response. 39 + * Requires prior initialisation via FCP_IOCTL_INIT. 40 + * 41 + * FCP_IOCTL_SET_METER_MAP: 42 + * Configures the Level Meter control's mapping between device 43 + * meters and control channels. Requires FCP_IOCTL_INIT to have been 44 + * called first. The map size and number of slots cannot be changed 45 + * after initial configuration, although the map itself can be 46 + * updated. Once configured, the Level Meter remains functional even 47 + * after the hwdep device is closed. 48 + * 49 + * FCP_IOCTL_SET_METER_LABELS: 50 + * Set the labels for the Level Meter control. Requires 51 + * FCP_IOCTL_SET_METER_MAP to have been called first. labels[] 52 + * should contain a sequence of null-terminated labels corresponding 53 + * to the control's channels. 54 + */ 55 + #ifndef __UAPI_SOUND_FCP_H 56 + #define __UAPI_SOUND_FCP_H 57 + 58 + #include <linux/types.h> 59 + #include <linux/ioctl.h> 60 + 61 + #define FCP_HWDEP_MAJOR 2 62 + #define FCP_HWDEP_MINOR 0 63 + #define FCP_HWDEP_SUBMINOR 0 64 + 65 + #define FCP_HWDEP_VERSION \ 66 + ((FCP_HWDEP_MAJOR << 16) | \ 67 + (FCP_HWDEP_MINOR << 8) | \ 68 + FCP_HWDEP_SUBMINOR) 69 + 70 + #define FCP_HWDEP_VERSION_MAJOR(v) (((v) >> 16) & 0xFF) 71 + #define FCP_HWDEP_VERSION_MINOR(v) (((v) >> 8) & 0xFF) 72 + #define FCP_HWDEP_VERSION_SUBMINOR(v) ((v) & 0xFF) 73 + 74 + /* Get protocol version */ 75 + #define FCP_IOCTL_PVERSION _IOR('S', 0x60, int) 76 + 77 + /* Start the protocol */ 78 + 79 + /* Step 0 and step 2 responses are variable length and placed in 80 + * resp[] one after the other. 81 + */ 82 + struct fcp_init { 83 + __u16 step0_resp_size; 84 + __u16 step2_resp_size; 85 + __u32 init1_opcode; 86 + __u32 init2_opcode; 87 + __u8 resp[]; 88 + } __attribute__((packed)); 89 + 90 + #define FCP_IOCTL_INIT _IOWR('S', 0x64, struct fcp_init) 91 + 92 + /* Perform a command */ 93 + 94 + /* The request data is placed in data[] and the response data will 95 + * overwrite it. 96 + */ 97 + struct fcp_cmd { 98 + __u32 opcode; 99 + __u16 req_size; 100 + __u16 resp_size; 101 + __u8 data[]; 102 + } __attribute__((packed)); 103 + #define FCP_IOCTL_CMD _IOWR('S', 0x65, struct fcp_cmd) 104 + 105 + /* Set the meter map */ 106 + struct fcp_meter_map { 107 + __u16 map_size; 108 + __u16 meter_slots; 109 + __s16 map[]; 110 + } __attribute__((packed)); 111 + #define FCP_IOCTL_SET_METER_MAP _IOW('S', 0x66, struct fcp_meter_map) 112 + 113 + /* Set the meter labels */ 114 + struct fcp_meter_labels { 115 + __u16 labels_size; 116 + char labels[]; 117 + } __attribute__((packed)); 118 + #define FCP_IOCTL_SET_METER_LABELS _IOW('S', 0x67, struct fcp_meter_labels) 119 + 120 + #endif /* __UAPI_SOUND_FCP_H */
+2
include/uapi/sound/tlv.h
··· 18 18 #define SNDRV_CTL_TLVT_CHMAP_VAR 0x102 /* channels freely swappable */ 19 19 #define SNDRV_CTL_TLVT_CHMAP_PAIRED 0x103 /* pair-wise swappable */ 20 20 21 + #define SNDRV_CTL_TLVT_FCP_CHANNEL_LABELS 0x110 /* channel labels */ 22 + 21 23 /* 22 24 * TLV structure is right behind the struct snd_ctl_tlv: 23 25 * unsigned int type - see SNDRV_CTL_TLVT_*
+1
sound/usb/Makefile
··· 6 6 snd-usb-audio-y := card.o \ 7 7 clock.o \ 8 8 endpoint.o \ 9 + fcp.o \ 9 10 format.o \ 10 11 helper.o \ 11 12 implicit.o \
+1134
sound/usb/fcp.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Focusrite Control Protocol Driver for ALSA 4 + * 5 + * Copyright (c) 2024-2025 by Geoffrey D. Bennett <g at b4.vu> 6 + */ 7 + /* 8 + * DOC: Theory of Operation 9 + * 10 + * The Focusrite Control Protocol (FCP) driver provides a minimal 11 + * kernel interface that allows a user-space driver (primarily 12 + * fcp-server) to communicate with Focusrite USB audio interfaces 13 + * using their vendor-specific protocol. This protocol is used by 14 + * Scarlett 2nd Gen, 3rd Gen, 4th Gen, Clarett USB, Clarett+, and 15 + * Vocaster series devices. 16 + * 17 + * Unlike the existing scarlett2 driver which implements all controls 18 + * in kernel space, this driver takes a lighter-weight approach by 19 + * moving most functionality to user space. The only control 20 + * implemented in kernel space is the Level Meter, since it requires 21 + * frequent polling of volatile data. 22 + * 23 + * The driver provides an hwdep interface that allows the user-space 24 + * driver to: 25 + * - Initialise the protocol 26 + * - Send arbitrary FCP commands to the device 27 + * - Receive notifications from the device 28 + * - Configure the Level Meter control 29 + * 30 + * Usage Flow 31 + * ---------- 32 + * 1. Open the hwdep device (requires CAP_SYS_RAWIO) 33 + * 2. Get protocol version using FCP_IOCTL_PVERSION 34 + * 3. Initialise protocol using FCP_IOCTL_INIT 35 + * 4. Send commands using FCP_IOCTL_CMD 36 + * 5. Receive notifications using read() 37 + * 6. Optionally set up the Level Meter control using 38 + * FCP_IOCTL_SET_METER_MAP 39 + * 7. Optionally add labels to the Level Meter control using 40 + * FCP_IOCTL_SET_METER_LABELS 41 + * 42 + * Level Meter 43 + * ----------- 44 + * The Level Meter is implemented as an ALSA control that provides 45 + * real-time level monitoring. When the control is read, the driver 46 + * requests the current meter levels from the device, translates the 47 + * levels using the configured mapping, and returns the result to the 48 + * user. The mapping between device meters and the ALSA control's 49 + * channels is configured with FCP_IOCTL_SET_METER_MAP. 50 + * 51 + * Labels for the Level Meter channels can be set using 52 + * FCP_IOCTL_SET_METER_LABELS and read by applications through the 53 + * control's TLV data. The labels are transferred as a sequence of 54 + * null-terminated strings. 55 + */ 56 + 57 + #include <linux/slab.h> 58 + #include <linux/usb.h> 59 + 60 + #include <sound/control.h> 61 + #include <sound/hwdep.h> 62 + #include <sound/tlv.h> 63 + 64 + #include <uapi/sound/fcp.h> 65 + 66 + #include "usbaudio.h" 67 + #include "mixer.h" 68 + #include "helper.h" 69 + 70 + #include "fcp.h" 71 + 72 + /* notify waiting to send to *file */ 73 + struct fcp_notify { 74 + wait_queue_head_t queue; 75 + u32 event; 76 + spinlock_t lock; 77 + }; 78 + 79 + struct fcp_data { 80 + struct usb_mixer_interface *mixer; 81 + 82 + struct mutex mutex; /* serialise access to the device */ 83 + struct completion cmd_done; /* wait for command completion */ 84 + struct file *file; /* hwdep file */ 85 + 86 + struct fcp_notify notify; 87 + 88 + u8 bInterfaceNumber; 89 + u8 bEndpointAddress; 90 + u16 wMaxPacketSize; 91 + u8 bInterval; 92 + 93 + uint16_t step0_resp_size; 94 + uint16_t step2_resp_size; 95 + uint32_t init1_opcode; 96 + uint32_t init2_opcode; 97 + 98 + u8 init; 99 + u16 seq; 100 + 101 + u8 num_meter_slots; 102 + s16 *meter_level_map; 103 + u32 *meter_levels; 104 + struct snd_kcontrol *meter_ctl; 105 + 106 + unsigned int *meter_labels_tlv; 107 + int meter_labels_tlv_size; 108 + }; 109 + 110 + /*** USB Interactions ***/ 111 + 112 + /* FCP Command ACK notification bit */ 113 + #define FCP_NOTIFY_ACK 1 114 + 115 + /* Vendor-specific USB control requests */ 116 + #define FCP_USB_REQ_STEP0 0 117 + #define FCP_USB_REQ_CMD_TX 2 118 + #define FCP_USB_REQ_CMD_RX 3 119 + 120 + /* Focusrite Control Protocol opcodes that the kernel side needs to 121 + * know about 122 + */ 123 + #define FCP_USB_REBOOT 0x00000003 124 + #define FCP_USB_GET_METER 0x00001001 125 + #define FCP_USB_FLASH_ERASE 0x00004002 126 + #define FCP_USB_FLASH_WRITE 0x00004004 127 + 128 + #define FCP_USB_METER_LEVELS_GET_MAGIC 1 129 + 130 + #define FCP_SEGMENT_APP_GOLD 0 131 + 132 + /* Forward declarations */ 133 + static int fcp_init(struct usb_mixer_interface *mixer, 134 + void *step0_resp, void *step2_resp); 135 + 136 + /* FCP command request/response format */ 137 + struct fcp_usb_packet { 138 + __le32 opcode; 139 + __le16 size; 140 + __le16 seq; 141 + __le32 error; 142 + __le32 pad; 143 + u8 data[]; 144 + }; 145 + 146 + static void fcp_fill_request_header(struct fcp_data *private, 147 + struct fcp_usb_packet *req, 148 + u32 opcode, u16 req_size) 149 + { 150 + /* sequence must go up by 1 for each request */ 151 + u16 seq = private->seq++; 152 + 153 + req->opcode = cpu_to_le32(opcode); 154 + req->size = cpu_to_le16(req_size); 155 + req->seq = cpu_to_le16(seq); 156 + req->error = 0; 157 + req->pad = 0; 158 + } 159 + 160 + static int fcp_usb_tx(struct usb_device *dev, int interface, 161 + void *buf, u16 size) 162 + { 163 + return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 164 + FCP_USB_REQ_CMD_TX, 165 + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, 166 + 0, interface, buf, size); 167 + } 168 + 169 + static int fcp_usb_rx(struct usb_device *dev, int interface, 170 + void *buf, u16 size) 171 + { 172 + return snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), 173 + FCP_USB_REQ_CMD_RX, 174 + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, 175 + 0, interface, buf, size); 176 + } 177 + 178 + /* Send an FCP command and get the response */ 179 + static int fcp_usb(struct usb_mixer_interface *mixer, u32 opcode, 180 + const void *req_data, u16 req_size, 181 + void *resp_data, u16 resp_size) 182 + { 183 + struct fcp_data *private = mixer->private_data; 184 + struct usb_device *dev = mixer->chip->dev; 185 + struct fcp_usb_packet *req __free(kfree) = NULL; 186 + struct fcp_usb_packet *resp __free(kfree) = NULL; 187 + size_t req_buf_size = struct_size(req, data, req_size); 188 + size_t resp_buf_size = struct_size(resp, data, resp_size); 189 + int retries = 0; 190 + const int max_retries = 5; 191 + int err; 192 + 193 + if (!mixer->urb) 194 + return -ENODEV; 195 + 196 + req = kmalloc(req_buf_size, GFP_KERNEL); 197 + if (!req) 198 + return -ENOMEM; 199 + 200 + resp = kmalloc(resp_buf_size, GFP_KERNEL); 201 + if (!resp) 202 + return -ENOMEM; 203 + 204 + /* build request message */ 205 + fcp_fill_request_header(private, req, opcode, req_size); 206 + if (req_size) 207 + memcpy(req->data, req_data, req_size); 208 + 209 + /* send the request and retry on EPROTO */ 210 + retry: 211 + err = fcp_usb_tx(dev, private->bInterfaceNumber, req, req_buf_size); 212 + if (err == -EPROTO && ++retries <= max_retries) { 213 + msleep(1 << (retries - 1)); 214 + goto retry; 215 + } 216 + 217 + if (err != req_buf_size) { 218 + usb_audio_err(mixer->chip, 219 + "FCP request %08x failed: %d\n", opcode, err); 220 + return -EINVAL; 221 + } 222 + 223 + if (!wait_for_completion_timeout(&private->cmd_done, 224 + msecs_to_jiffies(1000))) { 225 + usb_audio_err(mixer->chip, 226 + "FCP request %08x timed out\n", opcode); 227 + 228 + return -ETIMEDOUT; 229 + } 230 + 231 + /* send a second message to get the response */ 232 + err = fcp_usb_rx(dev, private->bInterfaceNumber, resp, resp_buf_size); 233 + 234 + /* validate the response */ 235 + 236 + if (err < 0) { 237 + 238 + /* ESHUTDOWN and EPROTO are valid responses to a 239 + * reboot request 240 + */ 241 + if (opcode == FCP_USB_REBOOT && 242 + (err == -ESHUTDOWN || err == -EPROTO)) 243 + return 0; 244 + 245 + usb_audio_err(mixer->chip, 246 + "FCP read response %08x failed: %d\n", 247 + opcode, err); 248 + return -EINVAL; 249 + } 250 + 251 + if (err < sizeof(*resp)) { 252 + usb_audio_err(mixer->chip, 253 + "FCP response %08x too short: %d\n", 254 + opcode, err); 255 + return -EINVAL; 256 + } 257 + 258 + if (req->seq != resp->seq) { 259 + usb_audio_err(mixer->chip, 260 + "FCP response %08x seq mismatch %d/%d\n", 261 + opcode, 262 + le16_to_cpu(req->seq), le16_to_cpu(resp->seq)); 263 + return -EINVAL; 264 + } 265 + 266 + if (req->opcode != resp->opcode) { 267 + usb_audio_err(mixer->chip, 268 + "FCP response %08x opcode mismatch %08x\n", 269 + opcode, le16_to_cpu(resp->opcode)); 270 + return -EINVAL; 271 + } 272 + 273 + if (resp->error) { 274 + usb_audio_err(mixer->chip, 275 + "FCP response %08x error %d\n", 276 + opcode, le32_to_cpu(resp->error)); 277 + return -EINVAL; 278 + } 279 + 280 + if (err != resp_buf_size) { 281 + usb_audio_err(mixer->chip, 282 + "FCP response %08x buffer size mismatch %d/%zu\n", 283 + opcode, err, resp_buf_size); 284 + return -EINVAL; 285 + } 286 + 287 + if (resp_size != le16_to_cpu(resp->size)) { 288 + usb_audio_err(mixer->chip, 289 + "FCP response %08x size mismatch %d/%d\n", 290 + opcode, resp_size, le16_to_cpu(resp->size)); 291 + return -EINVAL; 292 + } 293 + 294 + if (resp_data && resp_size > 0) 295 + memcpy(resp_data, resp->data, resp_size); 296 + 297 + return 0; 298 + } 299 + 300 + static int fcp_reinit(struct usb_mixer_interface *mixer) 301 + { 302 + struct fcp_data *private = mixer->private_data; 303 + void *step0_resp __free(kfree) = NULL; 304 + void *step2_resp __free(kfree) = NULL; 305 + 306 + if (mixer->urb) 307 + return 0; 308 + 309 + step0_resp = kmalloc(private->step0_resp_size, GFP_KERNEL); 310 + if (!step0_resp) 311 + return -ENOMEM; 312 + step2_resp = kmalloc(private->step2_resp_size, GFP_KERNEL); 313 + if (!step2_resp) 314 + return -ENOMEM; 315 + 316 + return fcp_init(mixer, step0_resp, step2_resp); 317 + } 318 + 319 + /*** Control Functions ***/ 320 + 321 + /* helper function to create a new control */ 322 + static int fcp_add_new_ctl(struct usb_mixer_interface *mixer, 323 + const struct snd_kcontrol_new *ncontrol, 324 + int index, int channels, const char *name, 325 + struct snd_kcontrol **kctl_return) 326 + { 327 + struct snd_kcontrol *kctl; 328 + struct usb_mixer_elem_info *elem; 329 + int err; 330 + 331 + elem = kzalloc(sizeof(*elem), GFP_KERNEL); 332 + if (!elem) 333 + return -ENOMEM; 334 + 335 + /* We set USB_MIXER_BESPOKEN type, so that the core USB mixer code 336 + * ignores them for resume and other operations. 337 + * Also, the head.id field is set to 0, as we don't use this field. 338 + */ 339 + elem->head.mixer = mixer; 340 + elem->control = index; 341 + elem->head.id = 0; 342 + elem->channels = channels; 343 + elem->val_type = USB_MIXER_BESPOKEN; 344 + 345 + kctl = snd_ctl_new1(ncontrol, elem); 346 + if (!kctl) { 347 + kfree(elem); 348 + return -ENOMEM; 349 + } 350 + kctl->private_free = snd_usb_mixer_elem_free; 351 + 352 + strscpy(kctl->id.name, name, sizeof(kctl->id.name)); 353 + 354 + err = snd_usb_mixer_add_control(&elem->head, kctl); 355 + if (err < 0) 356 + return err; 357 + 358 + if (kctl_return) 359 + *kctl_return = kctl; 360 + 361 + return 0; 362 + } 363 + 364 + /*** Level Meter Control ***/ 365 + 366 + static int fcp_meter_ctl_info(struct snd_kcontrol *kctl, 367 + struct snd_ctl_elem_info *uinfo) 368 + { 369 + struct usb_mixer_elem_info *elem = kctl->private_data; 370 + 371 + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 372 + uinfo->count = elem->channels; 373 + uinfo->value.integer.min = 0; 374 + uinfo->value.integer.max = 4095; 375 + uinfo->value.integer.step = 1; 376 + return 0; 377 + } 378 + 379 + static int fcp_meter_ctl_get(struct snd_kcontrol *kctl, 380 + struct snd_ctl_elem_value *ucontrol) 381 + { 382 + struct usb_mixer_elem_info *elem = kctl->private_data; 383 + struct usb_mixer_interface *mixer = elem->head.mixer; 384 + struct fcp_data *private = mixer->private_data; 385 + int num_meter_slots, resp_size; 386 + u32 *resp = private->meter_levels; 387 + int i, err = 0; 388 + 389 + struct { 390 + __le16 pad; 391 + __le16 num_meters; 392 + __le32 magic; 393 + } __packed req; 394 + 395 + guard(mutex)(&private->mutex); 396 + 397 + err = fcp_reinit(mixer); 398 + if (err < 0) 399 + return err; 400 + 401 + num_meter_slots = private->num_meter_slots; 402 + resp_size = num_meter_slots * sizeof(u32); 403 + 404 + req.pad = 0; 405 + req.num_meters = cpu_to_le16(num_meter_slots); 406 + req.magic = cpu_to_le32(FCP_USB_METER_LEVELS_GET_MAGIC); 407 + err = fcp_usb(mixer, FCP_USB_GET_METER, 408 + &req, sizeof(req), resp, resp_size); 409 + if (err < 0) 410 + return err; 411 + 412 + /* copy & translate from resp[] using meter_level_map[] */ 413 + for (i = 0; i < elem->channels; i++) { 414 + int idx = private->meter_level_map[i]; 415 + int value = idx < 0 ? 0 : le32_to_cpu(resp[idx]); 416 + 417 + ucontrol->value.integer.value[i] = value; 418 + } 419 + 420 + return 0; 421 + } 422 + 423 + static int fcp_meter_tlv_callback(struct snd_kcontrol *kctl, 424 + int op_flag, unsigned int size, 425 + unsigned int __user *tlv) 426 + { 427 + struct usb_mixer_elem_info *elem = kctl->private_data; 428 + struct usb_mixer_interface *mixer = elem->head.mixer; 429 + struct fcp_data *private = mixer->private_data; 430 + 431 + guard(mutex)(&private->mutex); 432 + 433 + if (op_flag == SNDRV_CTL_TLV_OP_READ) { 434 + if (private->meter_labels_tlv_size == 0) 435 + return 0; 436 + 437 + if (size > private->meter_labels_tlv_size) 438 + size = private->meter_labels_tlv_size; 439 + 440 + if (copy_to_user(tlv, private->meter_labels_tlv, size)) 441 + return -EFAULT; 442 + 443 + return size; 444 + } 445 + 446 + return -EINVAL; 447 + } 448 + 449 + static const struct snd_kcontrol_new fcp_meter_ctl = { 450 + .iface = SNDRV_CTL_ELEM_IFACE_PCM, 451 + .access = SNDRV_CTL_ELEM_ACCESS_READ | 452 + SNDRV_CTL_ELEM_ACCESS_VOLATILE, 453 + .info = fcp_meter_ctl_info, 454 + .get = fcp_meter_ctl_get, 455 + .tlv = { .c = fcp_meter_tlv_callback }, 456 + }; 457 + 458 + /*** hwdep interface ***/ 459 + 460 + /* FCP initialisation */ 461 + static int fcp_ioctl_init(struct usb_mixer_interface *mixer, 462 + struct fcp_init __user *arg) 463 + { 464 + struct fcp_init init; 465 + struct usb_device *dev = mixer->chip->dev; 466 + struct fcp_data *private = mixer->private_data; 467 + void *resp __free(kfree) = NULL; 468 + void *step2_resp; 469 + int err, buf_size; 470 + 471 + if (usb_pipe_type_check(dev, usb_sndctrlpipe(dev, 0))) 472 + return -EINVAL; 473 + 474 + /* Get initialisation parameters */ 475 + if (copy_from_user(&init, arg, sizeof(init))) 476 + return -EFAULT; 477 + 478 + /* Validate the response sizes */ 479 + if (init.step0_resp_size < 1 || 480 + init.step0_resp_size > 255 || 481 + init.step2_resp_size < 1 || 482 + init.step2_resp_size > 255) 483 + return -EINVAL; 484 + 485 + /* Allocate response buffer */ 486 + buf_size = init.step0_resp_size + init.step2_resp_size; 487 + 488 + resp = kmalloc(buf_size, GFP_KERNEL); 489 + if (!resp) 490 + return -ENOMEM; 491 + 492 + private->step0_resp_size = init.step0_resp_size; 493 + private->step2_resp_size = init.step2_resp_size; 494 + private->init1_opcode = init.init1_opcode; 495 + private->init2_opcode = init.init2_opcode; 496 + 497 + step2_resp = resp + private->step0_resp_size; 498 + 499 + err = fcp_init(mixer, resp, step2_resp); 500 + if (err < 0) 501 + return err; 502 + 503 + if (copy_to_user(arg->resp, resp, buf_size)) 504 + return -EFAULT; 505 + 506 + return 0; 507 + } 508 + 509 + /* Check that the command is allowed 510 + * Don't permit erasing/writing segment 0 (App_Gold) 511 + */ 512 + static int fcp_validate_cmd(u32 opcode, void *data, u16 size) 513 + { 514 + if (opcode == FCP_USB_FLASH_ERASE) { 515 + struct { 516 + __le32 segment_num; 517 + __le32 pad; 518 + } __packed *req = data; 519 + 520 + if (size != sizeof(*req)) 521 + return -EINVAL; 522 + 523 + if (le32_to_cpu(req->segment_num) == FCP_SEGMENT_APP_GOLD) 524 + return -EPERM; 525 + 526 + if (req->pad != 0) 527 + return -EINVAL; 528 + 529 + } else if (opcode == FCP_USB_FLASH_WRITE) { 530 + struct { 531 + __le32 segment_num; 532 + __le32 offset; 533 + __le32 pad; 534 + u8 data[]; 535 + } __packed *req = data; 536 + 537 + if (size < sizeof(*req)) 538 + return -EINVAL; 539 + 540 + if (le32_to_cpu(req->segment_num) == FCP_SEGMENT_APP_GOLD) 541 + return -EPERM; 542 + 543 + if (req->pad != 0) 544 + return -EINVAL; 545 + } 546 + 547 + return 0; 548 + } 549 + 550 + /* Execute an FCP command specified by the user */ 551 + static int fcp_ioctl_cmd(struct usb_mixer_interface *mixer, 552 + struct fcp_cmd __user *arg) 553 + { 554 + struct fcp_cmd cmd; 555 + int err, buf_size; 556 + void *data __free(kfree) = NULL; 557 + 558 + /* get opcode and request/response size */ 559 + if (copy_from_user(&cmd, arg, sizeof(cmd))) 560 + return -EFAULT; 561 + 562 + /* validate request and response sizes */ 563 + if (cmd.req_size > 4096 || cmd.resp_size > 4096) 564 + return -EINVAL; 565 + 566 + /* reinit if needed */ 567 + err = fcp_reinit(mixer); 568 + if (err < 0) 569 + return err; 570 + 571 + /* allocate request/response buffer */ 572 + buf_size = max(cmd.req_size, cmd.resp_size); 573 + 574 + if (buf_size > 0) { 575 + data = kmalloc(buf_size, GFP_KERNEL); 576 + if (!data) 577 + return -ENOMEM; 578 + } 579 + 580 + /* copy request from user */ 581 + if (cmd.req_size > 0) 582 + if (copy_from_user(data, arg->data, cmd.req_size)) 583 + return -EFAULT; 584 + 585 + /* check that the command is allowed */ 586 + err = fcp_validate_cmd(cmd.opcode, data, cmd.req_size); 587 + if (err < 0) 588 + return err; 589 + 590 + /* send request, get response */ 591 + err = fcp_usb(mixer, cmd.opcode, 592 + data, cmd.req_size, data, cmd.resp_size); 593 + if (err < 0) 594 + return err; 595 + 596 + /* copy response to user */ 597 + if (cmd.resp_size > 0) 598 + if (copy_to_user(arg->data, data, cmd.resp_size)) 599 + return -EFAULT; 600 + 601 + return 0; 602 + } 603 + 604 + /* Validate the Level Meter map passed by the user */ 605 + static int validate_meter_map(const s16 *map, int map_size, int meter_slots) 606 + { 607 + int i; 608 + 609 + for (i = 0; i < map_size; i++) 610 + if (map[i] < -1 || map[i] >= meter_slots) 611 + return -EINVAL; 612 + 613 + return 0; 614 + } 615 + 616 + /* Set the Level Meter map and add the control */ 617 + static int fcp_ioctl_set_meter_map(struct usb_mixer_interface *mixer, 618 + struct fcp_meter_map __user *arg) 619 + { 620 + struct fcp_meter_map map; 621 + struct fcp_data *private = mixer->private_data; 622 + s16 *tmp_map __free(kfree) = NULL; 623 + int err; 624 + 625 + if (copy_from_user(&map, arg, sizeof(map))) 626 + return -EFAULT; 627 + 628 + /* Don't allow changing the map size or meter slots once set */ 629 + if (private->meter_ctl) { 630 + struct usb_mixer_elem_info *elem = 631 + private->meter_ctl->private_data; 632 + 633 + if (map.map_size != elem->channels || 634 + map.meter_slots != private->num_meter_slots) 635 + return -EINVAL; 636 + } 637 + 638 + /* Validate the map size */ 639 + if (map.map_size < 1 || map.map_size > 255 || 640 + map.meter_slots < 1 || map.meter_slots > 255) 641 + return -EINVAL; 642 + 643 + /* Allocate and copy the map data */ 644 + tmp_map = kmalloc_array(map.map_size, sizeof(s16), GFP_KERNEL); 645 + if (!tmp_map) 646 + return -ENOMEM; 647 + 648 + if (copy_from_user(tmp_map, arg->map, map.map_size * sizeof(s16))) 649 + return -EFAULT; 650 + 651 + err = validate_meter_map(tmp_map, map.map_size, map.meter_slots); 652 + if (err < 0) 653 + return err; 654 + 655 + /* If the control doesn't exist, create it */ 656 + if (!private->meter_ctl) { 657 + s16 *new_map __free(kfree) = NULL; 658 + u32 *meter_levels __free(kfree) = NULL; 659 + 660 + /* Allocate buffer for the map */ 661 + new_map = kmalloc_array(map.map_size, sizeof(s16), GFP_KERNEL); 662 + if (!new_map) 663 + return -ENOMEM; 664 + 665 + /* Allocate buffer for reading meter levels */ 666 + meter_levels = kmalloc_array(map.meter_slots, sizeof(u32), 667 + GFP_KERNEL); 668 + if (!meter_levels) 669 + return -ENOMEM; 670 + 671 + /* Create the Level Meter control */ 672 + err = fcp_add_new_ctl(mixer, &fcp_meter_ctl, 0, map.map_size, 673 + "Level Meter", &private->meter_ctl); 674 + if (err < 0) 675 + return err; 676 + 677 + /* Success; save the pointers in private and don't free them */ 678 + private->meter_level_map = new_map; 679 + private->meter_levels = meter_levels; 680 + private->num_meter_slots = map.meter_slots; 681 + new_map = NULL; 682 + meter_levels = NULL; 683 + } 684 + 685 + /* Install the new map */ 686 + memcpy(private->meter_level_map, tmp_map, map.map_size * sizeof(s16)); 687 + 688 + return 0; 689 + } 690 + 691 + /* Set the Level Meter labels */ 692 + static int fcp_ioctl_set_meter_labels(struct usb_mixer_interface *mixer, 693 + struct fcp_meter_labels __user *arg) 694 + { 695 + struct fcp_meter_labels labels; 696 + struct fcp_data *private = mixer->private_data; 697 + unsigned int *tlv_data; 698 + unsigned int tlv_size, data_size; 699 + 700 + if (copy_from_user(&labels, arg, sizeof(labels))) 701 + return -EFAULT; 702 + 703 + /* Remove existing labels if size is zero */ 704 + if (!labels.labels_size) { 705 + 706 + /* Clear TLV read/callback bits if labels were present */ 707 + if (private->meter_labels_tlv) { 708 + private->meter_ctl->vd[0].access &= 709 + ~(SNDRV_CTL_ELEM_ACCESS_TLV_READ | 710 + SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK); 711 + snd_ctl_notify(mixer->chip->card, 712 + SNDRV_CTL_EVENT_MASK_INFO, 713 + &private->meter_ctl->id); 714 + } 715 + 716 + kfree(private->meter_labels_tlv); 717 + private->meter_labels_tlv = NULL; 718 + private->meter_labels_tlv_size = 0; 719 + 720 + return 0; 721 + } 722 + 723 + /* Validate size */ 724 + if (labels.labels_size > 4096) 725 + return -EINVAL; 726 + 727 + /* Calculate padded data size */ 728 + data_size = ALIGN(labels.labels_size, sizeof(unsigned int)); 729 + 730 + /* Calculate total TLV size including header */ 731 + tlv_size = sizeof(unsigned int) * 2 + data_size; 732 + 733 + /* Allocate, set up TLV header, and copy the labels data */ 734 + tlv_data = kzalloc(tlv_size, GFP_KERNEL); 735 + if (!tlv_data) 736 + return -ENOMEM; 737 + tlv_data[0] = SNDRV_CTL_TLVT_FCP_CHANNEL_LABELS; 738 + tlv_data[1] = data_size; 739 + if (copy_from_user(&tlv_data[2], arg->labels, labels.labels_size)) { 740 + kfree(tlv_data); 741 + return -EFAULT; 742 + } 743 + 744 + /* Set TLV read/callback bits if labels weren't present */ 745 + if (!private->meter_labels_tlv) { 746 + private->meter_ctl->vd[0].access |= 747 + SNDRV_CTL_ELEM_ACCESS_TLV_READ | 748 + SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; 749 + snd_ctl_notify(mixer->chip->card, 750 + SNDRV_CTL_EVENT_MASK_INFO, 751 + &private->meter_ctl->id); 752 + } 753 + 754 + /* Swap in the new labels */ 755 + kfree(private->meter_labels_tlv); 756 + private->meter_labels_tlv = tlv_data; 757 + private->meter_labels_tlv_size = tlv_size; 758 + 759 + return 0; 760 + } 761 + 762 + static int fcp_hwdep_open(struct snd_hwdep *hw, struct file *file) 763 + { 764 + struct usb_mixer_interface *mixer = hw->private_data; 765 + struct fcp_data *private = mixer->private_data; 766 + 767 + if (!capable(CAP_SYS_RAWIO)) 768 + return -EPERM; 769 + 770 + private->file = file; 771 + 772 + return 0; 773 + } 774 + 775 + static int fcp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, 776 + unsigned int cmd, unsigned long arg) 777 + { 778 + struct usb_mixer_interface *mixer = hw->private_data; 779 + struct fcp_data *private = mixer->private_data; 780 + void __user *argp = (void __user *)arg; 781 + 782 + guard(mutex)(&private->mutex); 783 + 784 + switch (cmd) { 785 + 786 + case FCP_IOCTL_PVERSION: 787 + return put_user(FCP_HWDEP_VERSION, 788 + (int __user *)argp) ? -EFAULT : 0; 789 + break; 790 + 791 + case FCP_IOCTL_INIT: 792 + return fcp_ioctl_init(mixer, argp); 793 + 794 + case FCP_IOCTL_CMD: 795 + if (!private->init) 796 + return -EINVAL; 797 + return fcp_ioctl_cmd(mixer, argp); 798 + 799 + case FCP_IOCTL_SET_METER_MAP: 800 + if (!private->init) 801 + return -EINVAL; 802 + return fcp_ioctl_set_meter_map(mixer, argp); 803 + 804 + case FCP_IOCTL_SET_METER_LABELS: 805 + if (!private->init) 806 + return -EINVAL; 807 + if (!private->meter_ctl) 808 + return -EINVAL; 809 + return fcp_ioctl_set_meter_labels(mixer, argp); 810 + 811 + default: 812 + return -ENOIOCTLCMD; 813 + } 814 + 815 + /* not reached */ 816 + } 817 + 818 + static ssize_t fcp_hwdep_read(struct snd_hwdep *hw, char __user *buf, 819 + ssize_t count, loff_t *offset) 820 + { 821 + struct usb_mixer_interface *mixer = hw->private_data; 822 + struct fcp_data *private = mixer->private_data; 823 + unsigned long flags; 824 + ssize_t ret = 0; 825 + u32 event; 826 + 827 + if (count < sizeof(event)) 828 + return -EINVAL; 829 + 830 + ret = wait_event_interruptible(private->notify.queue, 831 + private->notify.event); 832 + if (ret) 833 + return ret; 834 + 835 + spin_lock_irqsave(&private->notify.lock, flags); 836 + event = private->notify.event; 837 + private->notify.event = 0; 838 + spin_unlock_irqrestore(&private->notify.lock, flags); 839 + 840 + if (copy_to_user(buf, &event, sizeof(event))) 841 + return -EFAULT; 842 + 843 + return sizeof(event); 844 + } 845 + 846 + static unsigned int fcp_hwdep_poll(struct snd_hwdep *hw, 847 + struct file *file, 848 + poll_table *wait) 849 + { 850 + struct usb_mixer_interface *mixer = hw->private_data; 851 + struct fcp_data *private = mixer->private_data; 852 + unsigned int mask = 0; 853 + 854 + poll_wait(file, &private->notify.queue, wait); 855 + 856 + if (private->notify.event) 857 + mask |= POLLIN | POLLRDNORM; 858 + 859 + return mask; 860 + } 861 + 862 + static int fcp_hwdep_release(struct snd_hwdep *hw, struct file *file) 863 + { 864 + struct usb_mixer_interface *mixer = hw->private_data; 865 + struct fcp_data *private = mixer->private_data; 866 + 867 + if (!private) 868 + return 0; 869 + 870 + private->file = NULL; 871 + 872 + return 0; 873 + } 874 + 875 + static int fcp_hwdep_init(struct usb_mixer_interface *mixer) 876 + { 877 + struct snd_hwdep *hw; 878 + int err; 879 + 880 + err = snd_hwdep_new(mixer->chip->card, "Focusrite Control", 0, &hw); 881 + if (err < 0) 882 + return err; 883 + 884 + hw->private_data = mixer; 885 + hw->exclusive = 1; 886 + hw->ops.open = fcp_hwdep_open; 887 + hw->ops.ioctl = fcp_hwdep_ioctl; 888 + hw->ops.ioctl_compat = fcp_hwdep_ioctl; 889 + hw->ops.read = fcp_hwdep_read; 890 + hw->ops.poll = fcp_hwdep_poll; 891 + hw->ops.release = fcp_hwdep_release; 892 + 893 + return 0; 894 + } 895 + 896 + /*** Cleanup ***/ 897 + 898 + static void fcp_cleanup_urb(struct usb_mixer_interface *mixer) 899 + { 900 + if (!mixer->urb) 901 + return; 902 + 903 + usb_kill_urb(mixer->urb); 904 + kfree(mixer->urb->transfer_buffer); 905 + usb_free_urb(mixer->urb); 906 + mixer->urb = NULL; 907 + } 908 + 909 + static void fcp_private_free(struct usb_mixer_interface *mixer) 910 + { 911 + struct fcp_data *private = mixer->private_data; 912 + 913 + fcp_cleanup_urb(mixer); 914 + 915 + kfree(private->meter_level_map); 916 + kfree(private->meter_levels); 917 + kfree(private->meter_labels_tlv); 918 + kfree(private); 919 + mixer->private_data = NULL; 920 + } 921 + 922 + static void fcp_private_suspend(struct usb_mixer_interface *mixer) 923 + { 924 + fcp_cleanup_urb(mixer); 925 + } 926 + 927 + /*** Callbacks ***/ 928 + 929 + static void fcp_notify(struct urb *urb) 930 + { 931 + struct usb_mixer_interface *mixer = urb->context; 932 + struct fcp_data *private = mixer->private_data; 933 + int len = urb->actual_length; 934 + int ustatus = urb->status; 935 + u32 data; 936 + 937 + if (ustatus != 0 || len != 8) 938 + goto requeue; 939 + 940 + data = le32_to_cpu(*(__le32 *)urb->transfer_buffer); 941 + 942 + /* Handle command acknowledgement */ 943 + if (data & FCP_NOTIFY_ACK) { 944 + complete(&private->cmd_done); 945 + data &= ~FCP_NOTIFY_ACK; 946 + } 947 + 948 + if (data) { 949 + unsigned long flags; 950 + 951 + spin_lock_irqsave(&private->notify.lock, flags); 952 + private->notify.event |= data; 953 + spin_unlock_irqrestore(&private->notify.lock, flags); 954 + 955 + wake_up_interruptible(&private->notify.queue); 956 + } 957 + 958 + requeue: 959 + if (ustatus != -ENOENT && 960 + ustatus != -ECONNRESET && 961 + ustatus != -ESHUTDOWN) { 962 + urb->dev = mixer->chip->dev; 963 + usb_submit_urb(urb, GFP_ATOMIC); 964 + } else { 965 + complete(&private->cmd_done); 966 + } 967 + } 968 + 969 + /* Submit a URB to receive notifications from the device */ 970 + static int fcp_init_notify(struct usb_mixer_interface *mixer) 971 + { 972 + struct usb_device *dev = mixer->chip->dev; 973 + struct fcp_data *private = mixer->private_data; 974 + unsigned int pipe = usb_rcvintpipe(dev, private->bEndpointAddress); 975 + void *transfer_buffer; 976 + int err; 977 + 978 + /* Already set up */ 979 + if (mixer->urb) 980 + return 0; 981 + 982 + if (usb_pipe_type_check(dev, pipe)) 983 + return -EINVAL; 984 + 985 + mixer->urb = usb_alloc_urb(0, GFP_KERNEL); 986 + if (!mixer->urb) 987 + return -ENOMEM; 988 + 989 + transfer_buffer = kmalloc(private->wMaxPacketSize, GFP_KERNEL); 990 + if (!transfer_buffer) { 991 + usb_free_urb(mixer->urb); 992 + mixer->urb = NULL; 993 + return -ENOMEM; 994 + } 995 + 996 + usb_fill_int_urb(mixer->urb, dev, pipe, 997 + transfer_buffer, private->wMaxPacketSize, 998 + fcp_notify, mixer, private->bInterval); 999 + 1000 + init_completion(&private->cmd_done); 1001 + 1002 + err = usb_submit_urb(mixer->urb, GFP_KERNEL); 1003 + if (err) { 1004 + usb_audio_err(mixer->chip, 1005 + "%s: usb_submit_urb failed: %d\n", 1006 + __func__, err); 1007 + kfree(transfer_buffer); 1008 + usb_free_urb(mixer->urb); 1009 + mixer->urb = NULL; 1010 + } 1011 + 1012 + return err; 1013 + } 1014 + 1015 + /*** Initialisation ***/ 1016 + 1017 + static int fcp_init(struct usb_mixer_interface *mixer, 1018 + void *step0_resp, void *step2_resp) 1019 + { 1020 + struct fcp_data *private = mixer->private_data; 1021 + struct usb_device *dev = mixer->chip->dev; 1022 + int err; 1023 + 1024 + err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), 1025 + FCP_USB_REQ_STEP0, 1026 + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, 1027 + 0, private->bInterfaceNumber, 1028 + step0_resp, private->step0_resp_size); 1029 + if (err < 0) 1030 + return err; 1031 + 1032 + err = fcp_init_notify(mixer); 1033 + if (err < 0) 1034 + return err; 1035 + 1036 + private->seq = 0; 1037 + private->init = 1; 1038 + 1039 + err = fcp_usb(mixer, private->init1_opcode, NULL, 0, NULL, 0); 1040 + if (err < 0) 1041 + return err; 1042 + 1043 + err = fcp_usb(mixer, private->init2_opcode, 1044 + NULL, 0, step2_resp, private->step2_resp_size); 1045 + if (err < 0) 1046 + return err; 1047 + 1048 + return 0; 1049 + } 1050 + 1051 + static int fcp_init_private(struct usb_mixer_interface *mixer) 1052 + { 1053 + struct fcp_data *private = 1054 + kzalloc(sizeof(struct fcp_data), GFP_KERNEL); 1055 + 1056 + if (!private) 1057 + return -ENOMEM; 1058 + 1059 + mutex_init(&private->mutex); 1060 + init_waitqueue_head(&private->notify.queue); 1061 + spin_lock_init(&private->notify.lock); 1062 + 1063 + mixer->private_data = private; 1064 + mixer->private_free = fcp_private_free; 1065 + mixer->private_suspend = fcp_private_suspend; 1066 + 1067 + private->mixer = mixer; 1068 + 1069 + return 0; 1070 + } 1071 + 1072 + /* Look through the interface descriptors for the Focusrite Control 1073 + * interface (bInterfaceClass = 255 Vendor Specific Class) and set 1074 + * bInterfaceNumber, bEndpointAddress, wMaxPacketSize, and bInterval 1075 + * in private 1076 + */ 1077 + static int fcp_find_fc_interface(struct usb_mixer_interface *mixer) 1078 + { 1079 + struct snd_usb_audio *chip = mixer->chip; 1080 + struct fcp_data *private = mixer->private_data; 1081 + struct usb_host_config *config = chip->dev->actconfig; 1082 + int i; 1083 + 1084 + for (i = 0; i < config->desc.bNumInterfaces; i++) { 1085 + struct usb_interface *intf = config->interface[i]; 1086 + struct usb_interface_descriptor *desc = 1087 + &intf->altsetting[0].desc; 1088 + struct usb_endpoint_descriptor *epd; 1089 + 1090 + if (desc->bInterfaceClass != 255) 1091 + continue; 1092 + 1093 + epd = get_endpoint(intf->altsetting, 0); 1094 + private->bInterfaceNumber = desc->bInterfaceNumber; 1095 + private->bEndpointAddress = epd->bEndpointAddress & 1096 + USB_ENDPOINT_NUMBER_MASK; 1097 + private->wMaxPacketSize = le16_to_cpu(epd->wMaxPacketSize); 1098 + private->bInterval = epd->bInterval; 1099 + return 0; 1100 + } 1101 + 1102 + usb_audio_err(chip, "Focusrite vendor-specific interface not found\n"); 1103 + return -EINVAL; 1104 + } 1105 + 1106 + int snd_fcp_init(struct usb_mixer_interface *mixer) 1107 + { 1108 + struct snd_usb_audio *chip = mixer->chip; 1109 + int err; 1110 + 1111 + /* only use UAC_VERSION_2 */ 1112 + if (!mixer->protocol) 1113 + return 0; 1114 + 1115 + err = fcp_init_private(mixer); 1116 + if (err < 0) 1117 + return err; 1118 + 1119 + err = fcp_find_fc_interface(mixer); 1120 + if (err < 0) 1121 + return err; 1122 + 1123 + err = fcp_hwdep_init(mixer); 1124 + if (err < 0) 1125 + return err; 1126 + 1127 + usb_audio_info(chip, 1128 + "Focusrite Control Protocol Driver ready (pid=0x%04x); " 1129 + "report any issues to " 1130 + "https://github.com/geoffreybennett/fcp-support/issues", 1131 + USB_ID_PRODUCT(chip->usb_id)); 1132 + 1133 + return err; 1134 + }
+7
sound/usb/fcp.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef __USBAUDIO_FCP_H 3 + #define __USBAUDIO_FCP_H 4 + 5 + int snd_fcp_init(struct usb_mixer_interface *mixer); 6 + 7 + #endif /* __USBAUDIO_FCP_H */
+7
sound/usb/mixer_quirks.c
··· 38 38 #include "mixer_us16x08.h" 39 39 #include "mixer_s1810c.h" 40 40 #include "helper.h" 41 + #include "fcp.h" 41 42 42 43 struct std_mono_table { 43 44 unsigned int unitid, control, cmask; ··· 4089 4088 case USB_ID(0x1235, 0x820b): /* Focusrite Clarett+ 4Pre */ 4090 4089 case USB_ID(0x1235, 0x820c): /* Focusrite Clarett+ 8Pre */ 4091 4090 err = snd_scarlett2_init(mixer); 4091 + break; 4092 + 4093 + case USB_ID(0x1235, 0x821b): /* Focusrite Scarlett 16i16 4th Gen */ 4094 + case USB_ID(0x1235, 0x821c): /* Focusrite Scarlett 18i16 4th Gen */ 4095 + case USB_ID(0x1235, 0x821d): /* Focusrite Scarlett 18i20 4th Gen */ 4096 + err = snd_fcp_init(mixer); 4092 4097 break; 4093 4098 4094 4099 case USB_ID(0x041e, 0x323b): /* Creative Sound Blaster E1 */