Skip to content

Commit 46757a3

Browse files
geoffreybennetttiwai
authored andcommitted
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 <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent bb5f86e commit 46757a3

File tree

7 files changed

+1277
-4
lines changed

7 files changed

+1277
-4
lines changed

MAINTAINERS

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8951,14 +8951,16 @@ L: [email protected]
89518951
S: Maintained
89528952
F: drivers/input/joystick/fsia6b.c
89538953

8954-
FOCUSRITE SCARLETT2 MIXER DRIVER (Scarlett Gen 2+ and Clarett)
8954+
FOCUSRITE CONTROL PROTOCOL/SCARLETT2 MIXER DRIVERS (Scarlett Gen 2+, Clarett, and Vocaster)
89558955
M: Geoffrey D. Bennett <[email protected]>
89568956
89578957
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
89618962
F: include/uapi/sound/scarlett2.h
8963+
F: sound/usb/fcp.c
89628964
F: sound/usb/mixer_scarlett2.c
89638965

89648966
FORCEDETH GIGABIT ETHERNET DRIVER

include/uapi/sound/fcp.h

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
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 */

include/uapi/sound/tlv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#define SNDRV_CTL_TLVT_CHMAP_VAR 0x102 /* channels freely swappable */
1919
#define SNDRV_CTL_TLVT_CHMAP_PAIRED 0x103 /* pair-wise swappable */
2020

21+
#define SNDRV_CTL_TLVT_FCP_CHANNEL_LABELS 0x110 /* channel labels */
22+
2123
/*
2224
* TLV structure is right behind the struct snd_ctl_tlv:
2325
* unsigned int type - see SNDRV_CTL_TLVT_*

sound/usb/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
snd-usb-audio-y := card.o \
77
clock.o \
88
endpoint.o \
9+
fcp.o \
910
format.o \
1011
helper.o \
1112
implicit.o \

0 commit comments

Comments
 (0)