sdvxio-bio2: Add sdvxio BIO2 along with bio2drv and aciotest updates

This commit is contained in:
Will Xyen
2020-08-14 18:44:05 -07:00
parent 9246e7f9e0
commit cdefc2b09e
15 changed files with 919 additions and 1 deletions
+9
View File
@@ -0,0 +1,9 @@
libs += bio2drv
libs_bio2drv := \
aciodrv
src_bio2drv := \
detect.c \
config-bio2.c \
bi2a-sdvx.c \
+138
View File
@@ -0,0 +1,138 @@
#define LOG_MODULE "bio2drv-bi2a_sdvx"
#include "bio2drv/bi2a-sdvx.h"
#include <stdio.h>
#include <string.h>
#include "aciodrv/device.h"
#include "util/log.h"
// this is probably InitIO
static bool bio2drv_bi2a_sdvx_init_io(uint8_t node_id)
{
struct ac_io_message msg;
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_CMD_CLEAR);
msg.cmd.nbytes = 1;
msg.cmd.count = 0x3B;
if (!aciodrv_send_and_recv(
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
log_warning("Init node failed");
return 0;
}
log_warning("Init of node %d, status: %d", node_id, msg.cmd.status);
return 1;
}
static bool bio2drv_bi2a_sdvx_watchdog_start(uint8_t node_id)
{
// exit early and don't actually call watchdog
// the watchdog call actually returns different sized packets depending on
// the state this results in an issue during packet processing (see: #68)
return true;
/*
struct ac_io_message msg;
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_WATCHDOG);
msg.cmd.nbytes = 2;
msg.cmd.nbytes = 2;
// uint16_t: 6000
msg.cmd.raw[0] = 23;
msg.cmd.raw[1] = 112;
if (!aciodrv_send_and_recv(
&msg, offsetof(struct ac_io_message, cmd.raw) + 2
)) {
log_warning("Starting watchdog failed"); return false;
}
log_warning("Started watchdog of node %d, status: %d",
node_id, msg.cmd.status);
return true;
*/
}
bool bio2drv_bi2a_sdvx_amp(
uint8_t node_id,
uint8_t unused_1,
uint8_t unused_2,
uint8_t left,
uint8_t right)
{
struct ac_io_message msg;
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_AMP_CONTROL);
msg.cmd.nbytes = 4;
// the BIO2 DOES NOT MATCH THE KFCA for what these mean
// 0 and 1 are ignored, 2 and 3 seem to map to left/right for ALL 3 AMPS
// in the future, maybe use windows APIs and write the volume levels there
msg.cmd.raw[0] = unused_1;
msg.cmd.raw[1] = unused_2;
msg.cmd.raw[2] = left;
msg.cmd.raw[3] = right;
if (!aciodrv_send_and_recv(
&msg, offsetof(struct ac_io_message, cmd.raw) + 1)) {
log_warning("Setting AMP failed");
return false;
}
log_warning("Started AMP node %d", node_id);
return true;
}
bool bio2drv_bi2a_sdvx_init(uint8_t node_id)
{
if (!bio2drv_bi2a_sdvx_init_io(node_id)) {
return false;
}
if (!bio2drv_bi2a_sdvx_watchdog_start(node_id)) {
return false;
}
if (!bio2drv_bi2a_sdvx_amp(node_id, 0, 0, 0, 0)) {
return false;
}
return true;
}
bool bio2drv_bi2a_sdvx_poll(
uint8_t node_id,
const struct bi2a_sdvx_state_out *pout,
struct bi2a_sdvx_state_in *pin)
{
struct ac_io_message msg;
msg.addr = node_id + 1;
msg.cmd.code = ac_io_u16(AC_IO_CMD_KFCA_POLL);
msg.cmd.nbytes = sizeof(*pout);
/* buffer size of data we expect */
*(struct bi2a_sdvx_state_out *) msg.cmd.raw = *pout;
if (!aciodrv_send_and_recv(
&msg, offsetof(struct ac_io_message, cmd.raw) + sizeof(*pin))) {
log_warning("Polling of node %d failed", node_id + 1);
return false;
}
if (pin != NULL) {
memcpy(pin, &msg.cmd.raw, sizeof(*pin));
}
return true;
}
+51
View File
@@ -0,0 +1,51 @@
#ifndef BIO2DRV_BI2A_H
#define BIO2DRV_BI2A_H
#include "bio2/bi2a-sdvx.h"
/**
* Initialize a BI2A node.
*
* @param node_id Id of the node to initialize (0 based).
* @return True if successful, false on error.
* @note This module is supposed to be used in combination with the common
* device driver foundation.
* @see driver.h
*/
bool bio2drv_bi2a_sdvx_init(uint8_t node_id);
/**
* Poll the board
*
* @param node_id Id of the node to query (0 based).
* @param state Pointer to a state struct to return the current state to
* (optional, NULL for none).
* @return True on success, false on error.
* @note This module is supposed to be used in combination with the common
* device driver foundation.
* @see driver.h
*/
bool bio2drv_bi2a_sdvx_poll(
uint8_t node_id,
const struct bi2a_sdvx_state_out *pout,
struct bi2a_sdvx_state_in *pin);
/**
* Set the BIO2 BI2A SDVX digital amp level
*
* @param node_id Id of the node to query (0 based).
* @param primary primary volume (96-0)
* @param headphone headphone volume (96-0)
* @param unused unknown volume (96-0) (unused)
* @param subwoofer subwoofer volume (96-0)
* @return True on success, false on error.
* @note Note 96 is lowest volume level, 0 is highest
*/
bool bio2drv_bi2a_sdvx_amp(
uint8_t node_id,
uint8_t unused_1,
uint8_t unused_2,
uint8_t left,
uint8_t right);
#endif
+75
View File
@@ -0,0 +1,75 @@
#include "cconfig/cconfig-util.h"
#include "bio2drv/config-bio2.h"
#include "util/log.h"
#define BIO2DRV_CONFIG_BIO2_AUTO_KEY "bio2.autodetect"
#define BIO2DRV_CONFIG_BIO2_PORT_KEY "bio2.port"
#define BIO2DRV_CONFIG_BIO2_BAUD_KEY "bio2.baud"
#define BIO2DRV_CONFIG_BIO2_DEFAULT_AUTO_VALUE true
#define BIO2DRV_CONFIG_BIO2_DEFAULT_PORT_VALUE "COM4"
#define BIO2DRV_CONFIG_BIO2_DEFAULT_BAUD_VALUE 115200
void bio2drv_config_bio2_init(struct cconfig *config)
{
cconfig_util_set_bool(
config,
BIO2DRV_CONFIG_BIO2_AUTO_KEY,
BIO2DRV_CONFIG_BIO2_DEFAULT_AUTO_VALUE,
"Autodetect BIO2 port (default: on)");
cconfig_util_set_str(
config,
BIO2DRV_CONFIG_BIO2_PORT_KEY,
BIO2DRV_CONFIG_BIO2_DEFAULT_PORT_VALUE,
"BIO2 serial port");
cconfig_util_set_int(
config,
BIO2DRV_CONFIG_BIO2_BAUD_KEY,
BIO2DRV_CONFIG_BIO2_DEFAULT_BAUD_VALUE,
"BIO2 bus baudrate (real devices expect 115200)");
}
void bio2drv_config_bio2_get(
struct bio2drv_config_bio2 *config_bio2, struct cconfig *config)
{
if (!cconfig_util_get_bool(
config,
BIO2DRV_CONFIG_BIO2_AUTO_KEY,
&config_bio2->autodetect,
BIO2DRV_CONFIG_BIO2_DEFAULT_AUTO_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
BIO2DRV_CONFIG_BIO2_AUTO_KEY,
BIO2DRV_CONFIG_BIO2_DEFAULT_AUTO_VALUE);
}
if (!cconfig_util_get_str(
config,
BIO2DRV_CONFIG_BIO2_PORT_KEY,
config_bio2->port,
sizeof(config_bio2->port) - 1,
BIO2DRV_CONFIG_BIO2_DEFAULT_PORT_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%s'",
BIO2DRV_CONFIG_BIO2_PORT_KEY,
BIO2DRV_CONFIG_BIO2_DEFAULT_PORT_VALUE);
}
if (!cconfig_util_get_int(
config,
BIO2DRV_CONFIG_BIO2_BAUD_KEY,
&config_bio2->baud,
BIO2DRV_CONFIG_BIO2_DEFAULT_BAUD_VALUE)) {
log_warning(
"Invalid value for key '%s' specified, fallback "
"to default '%d'",
BIO2DRV_CONFIG_BIO2_BAUD_KEY,
BIO2DRV_CONFIG_BIO2_DEFAULT_BAUD_VALUE);
}
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef BIO2DRV_CONFIG_BIO2_H
#define BIO2DRV_CONFIG_BIO2_H
#include <windows.h>
#include "cconfig/cconfig.h"
struct bio2drv_config_bio2 {
bool autodetect;
char port[64];
int32_t baud;
};
void bio2drv_config_bio2_init(struct cconfig *config);
void bio2drv_config_bio2_get(
struct bio2drv_config_bio2 *config_bio2, struct cconfig *config);
#endif
+163
View File
@@ -0,0 +1,163 @@
#define LOG_MODULE "bio2drv-detect"
#include <initguid.h>
#include <windows.h>
#include <cfgmgr32.h>
#include <setupapi.h>
#include "bio2drv/detect.h"
#include <stdio.h>
#include <string.h>
#include "util/log.h"
DEFINE_GUID(
GUID_COM_BUS_ENUMERATOR,
0x4D36E978,
0xE325,
0x11CE,
0xBF,
0xC1,
0x08,
0x00,
0x2B,
0xE1,
0x03,
0x18);
static char work_buffer[0x400];
static bool check_property(
HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA PDeviceInfoData, DWORD property)
{
if (SetupDiGetDeviceRegistryPropertyA(
DeviceInfoSet,
PDeviceInfoData,
property,
NULL,
(BYTE *) work_buffer,
sizeof(work_buffer),
NULL)) {
if (strstr(work_buffer, "BIO2(VIDEO)")) {
log_info("Found matching device: %s", work_buffer);
return true;
}
}
log_info("Device with property: %s does not match", work_buffer);
return false;
}
static bool check_id(
HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA PDeviceInfoData)
{
if (CM_Get_Device_IDA(PDeviceInfoData->DevInst, work_buffer, sizeof(work_buffer), 0)) {
return false;
}
if (strstr(work_buffer, "VID_1CCF&PID_804C")) {
log_info("Found matching device: %s", work_buffer);
return true;
}
if (strstr(work_buffer, "VID_1CCF&PID_8040")) {
log_info("Found matching device: %s", work_buffer);
return true;
}
log_info("Device with ID: %s does not match", work_buffer);
return false;
}
static bool get_device_by_filter(
bool id_filter, DWORD property, size_t devnum, char *path, size_t length)
{
HDEVINFO DeviceInfoSet = SetupDiGetClassDevsA(
&GUID_COM_BUS_ENUMERATOR, NULL, NULL, DIGCF_PRESENT);
if (DeviceInfoSet == INVALID_HANDLE_VALUE) {
return false;
}
SP_DEVINFO_DATA DeviceInfoData;
ZeroMemory(&DeviceInfoData, sizeof(SP_DEVINFO_DATA));
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
DWORD idx = 0;
size_t num_found = 0;
while (SetupDiEnumDeviceInfo(DeviceInfoSet, idx, &DeviceInfoData)) {
HKEY DeviceRegKey = SetupDiOpenDevRegKey(
DeviceInfoSet,
&DeviceInfoData,
DICS_FLAG_GLOBAL,
0,
DIREG_DEV,
KEY_QUERY_VALUE);
if (DeviceRegKey) {
bool found = false;
log_info("Found a serial device at index: %d", idx);
if (!id_filter) {
if (check_property(DeviceInfoSet, &DeviceInfoData, property)) {
found = true;
}
} else {
if (check_id(DeviceInfoSet, &DeviceInfoData)) {
found = true;
}
}
if (found) {
if (num_found == devnum) {
DWORD path_length = length;
RegQueryValueExA(
DeviceRegKey,
"PortName",
0,
NULL,
(BYTE *) path,
&path_length);
log_info("Using port: %s", path);
return true;
}
num_found++;
}
}
++idx;
}
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
log_warning("No matching device found");
return false;
}
void bio2drv_set_loggers(
log_formatter_t misc,
log_formatter_t info,
log_formatter_t warning,
log_formatter_t fatal)
{
log_to_external(misc, info, warning, fatal);
}
bool bio2drv_detect(
enum bio2drv_detect_mode mode, size_t index, char *path, size_t length)
{
if (mode == DETECT_DEVICEDESC) {
return get_device_by_filter(
false, SPDRP_DEVICEDESC, index, path, length);
} else if (mode == DETECT_FRIENDLYNAME) {
return get_device_by_filter(
false, SPDRP_FRIENDLYNAME, index, path, length);
} else if (mode == DETECT_DEVICEID) {
return get_device_by_filter(true, -1, index, path, length);
}
log_warning("Unknown autodetect mode: %d", mode);
return false;
}
+23
View File
@@ -0,0 +1,23 @@
#ifndef BIO2DRV_DETECT_H
#define BIO2DRV_DETECT_H
#include <stdbool.h>
#include "bemanitools/glue.h"
enum bio2drv_detect_mode {
DETECT_DEVICEDESC = 0x1, // look for serial devices containing BIO2(VIDEO)
DETECT_FRIENDLYNAME = 0x2, // look for serial devices containing BIO2(VIDEO)
DETECT_DEVICEID = 0x3, // look for serial devices by vid/pid
};
void bio2drv_set_loggers(
log_formatter_t misc,
log_formatter_t info,
log_formatter_t warning,
log_formatter_t fatal);
bool bio2drv_detect(
enum bio2drv_detect_mode mode, size_t devnum, char *path, size_t length);
#endif