Add driver type detection

This commit is contained in:
Geoffrey D. Bennett
2025-02-22 23:43:26 +10:30
parent c88f7796f4
commit 6f0ab1890d
2 changed files with 93 additions and 0 deletions

View File

@@ -5,10 +5,15 @@
#include <alsa/sound/uapi/tlv.h>
#include "alsa.h"
#include "scarlett2.h"
#include "scarlett2-firmware.h"
#include "scarlett2-ioctls.h"
#include "stringhelper.h"
#include "window-iface.h"
#define MAJOR_HWDEP_VERSION_SCARLETT2 1
#define MAJOR_HWDEP_VERSION_FCP 2
#define MAX_TLV_RANGE_SIZE 1024
// TLV type for channel labels
@@ -1067,7 +1072,81 @@ static void alsa_get_serial_number(struct alsa_card *card) {
card->serial = strdup(serial);
}
// return true if the Firmware Version control exists and is writable
// and locked (i.e. the FCP server is running)
static int check_firmware_version_locked(struct alsa_card *card) {
snd_ctl_elem_id_t *id;
snd_ctl_elem_info_t *info;
snd_ctl_elem_id_alloca(&id);
snd_ctl_elem_info_alloca(&info);
// look for the Firmware Version control
snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_CARD);
snd_ctl_elem_id_set_name(id, "Firmware Version");
snd_ctl_elem_info_set_id(info, id);
// no Firmware Version control found
int err = snd_ctl_elem_info(card->handle, info);
if (err < 0)
return 0;
return snd_ctl_elem_info_is_writable(info) &&
snd_ctl_elem_info_is_locked(info);
}
// return the driver type for this card
// DRIVER_TYPE_NONE: no driver
// DRIVER_TYPE_HWDEP: Scarlett2 driver
// DRIVER_TYPE_SOCKET: FCP driver
// DRIVER_TYPE_SOCKET_UNINIT: FCP driver, but not initialised
static int get_driver_type(struct alsa_card *card) {
snd_hwdep_t *hwdep;
int err = scarlett2_open_card(card->device, &hwdep);
// no hwdep for this card - driver type none
if (err == -ENOENT)
return DRIVER_TYPE_NONE;
// if we get EPERM, it's FCP but no server running
if (err == -EPERM)
return DRIVER_TYPE_SOCKET_UNINIT;
// if we get EBUSY, it's FCP
if (err == -EBUSY)
// fcp-server locks the Firmware Version control when it has
// finished starting up
return check_firmware_version_locked(card) ?
DRIVER_TYPE_SOCKET : DRIVER_TYPE_SOCKET_UNINIT;
// failed to open hwdep
if (err < 0)
return DRIVER_TYPE_NONE;
// we can open hwdep, so now check the protocol version
int ver = scarlett2_get_protocol_version(hwdep);
scarlett2_close(hwdep);
// failed to get protocol version
if (ver < 0)
return DRIVER_TYPE_NONE;
// hwdep protocol version 1.x.x is Scarlett2 driver
if (SCARLETT2_HWDEP_VERSION_MAJOR(ver) == MAJOR_HWDEP_VERSION_SCARLETT2)
return DRIVER_TYPE_HWDEP;
// hwdep protocol version 2.x.x is FCP driver (but not initialised,
// because we were able to open the hwdep)
if (SCARLETT2_HWDEP_VERSION_MAJOR(ver) == MAJOR_HWDEP_VERSION_FCP)
return DRIVER_TYPE_SOCKET_UNINIT;
return DRIVER_TYPE_NONE;
}
static void card_init(struct alsa_card *card) {
card->driver_type = get_driver_type(card);
alsa_get_elem_list(card);
alsa_set_lr_nums(card);
alsa_get_routing_controls(card);

View File

@@ -41,6 +41,19 @@ enum {
HW_TYPE_COUNT
};
// driver types
// NONE is 1st Gen or Scarlett2 before hwdep support was added
// (no erase config or firmware update support)
// HWDEP is the Scarlett2 driver after hwdep support was added
// SOCKET is the FCP driver
enum {
DRIVER_TYPE_NONE,
DRIVER_TYPE_HWDEP,
DRIVER_TYPE_SOCKET,
DRIVER_TYPE_SOCKET_UNINIT,
DRIVER_TYPE_COUNT
};
// names for the hardware types
extern const char *hw_type_names[HW_TYPE_COUNT];
@@ -162,6 +175,7 @@ struct alsa_card {
uint32_t pid;
char *serial;
char *name;
int driver_type;
char *fcp_socket;
int best_firmware_version;
snd_ctl_t *handle;