Re-evaluate BenQ input switching

The manufacturer-specific KVM feature is necessary,
because Input Source alone won't let me wake up
the particular computer's video output.
This commit is contained in:
Přemysl Eric Janouch 2021-11-06 03:32:07 +01:00
parent c6a93b5d9e
commit d057e903b7
Signed by: p
GPG Key ID: A0420B94F92B9493
2 changed files with 39 additions and 8 deletions

View File

@ -30,6 +30,8 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
typedef bool (*ActionFunc) (int fd, int param, struct error **);
static bool
set_input_source (int fd, int input, struct error **e)
{
@ -49,8 +51,31 @@ set_input_source (int fd, int input, struct error **e)
return true;
}
static bool
set_bnq_kvm (int fd, int kvm, struct error **e)
{
// This function does a leap of faith, should check the actual manufacturer
enum { VCP_BNQ_KVM = 0xE4 };
struct vcp_feature_readout readout = {};
if (!vcp_get_feature (fd, VCP_BNQ_KVM, &readout, e))
return false;
if (kvm < 0 || kvm > readout.max)
return error_set (e, "KVM index out of range");
uint8_t set_req[] = { VCP_BNQ_KVM, kvm >> 8, kvm };
if (!ddc_send (fd, DDC_SET_VCP_FEATURE, set_req, sizeof set_req, e))
return false;
wait_ms (50);
printf ("KVM set from %d to %d of %d\n", readout.cur, kvm, readout.max);
return true;
}
static void
i2c (int input)
i2c (ActionFunc action, int param)
{
DIR *dev = opendir ("/dev");
if (!dev)
@ -76,7 +101,7 @@ i2c (int input)
struct error *e = NULL;
if (!is_a_display (fd, &e)
|| !set_input_source (fd, input, &e))
|| !action (fd, param, &e))
{
printf ("%s\n", e->message);
error_free (e);
@ -116,7 +141,7 @@ g_inputs[] =
{ 0x10, "dp", 2, }, // DisplayPort 2
{ 0x11, "hdmi", 1, }, // Digital Video (TMDS) 3 HDMI 1
{ 0x12, "hdmi", 2, }, // Digital Video (TMDS) 4 HDMI 2
{ 0x15, "tb", 1, }, // Thunderbolt on BenQ PD3220U (no spec)
{ 0x15, "bnq-tb", 1, }, // Thunderbolt on BenQ PD3220U (no spec)
};
int
@ -133,13 +158,21 @@ main (int argc, char *argv[])
unsigned long input_source = 0;
if (xstrtoul (&input_source, argv[1], 10))
{
i2c (input_source);
i2c (set_input_source, input_source);
exit (EXIT_SUCCESS);
}
unsigned long index = 1;
if (argc > 2 && !xstrtoul (&index, argv[2], 10))
exit_fatal ("given index is not a number: %s", argv[2]);
// Manufacturer-specific, argument currently necessary, but we could rotate
if (argc > 2 && !strcasecmp (argv[1], "bnq-kvm"))
{
i2c (set_bnq_kvm, index);
exit (EXIT_SUCCESS);
}
for (size_t i = 0; i < N_ELEMENTS (g_inputs); i++)
if (!strcasecmp_ascii (g_inputs[i].name, argv[1])
&& g_inputs[i].index == (int) index)
@ -147,7 +180,6 @@ main (int argc, char *argv[])
if (!input_source)
exit_fatal ("unknown input source: %s %lu", argv[1], index);
i2c (input_source);
i2c (set_input_source, input_source);
return 0;
}

View File

@ -2306,7 +2306,7 @@ on_input_switch (struct app_context *ctx, int arg)
{
(void) ctx;
char *values[] = { "vga", "dvi", "hdmi", "dp", "tb" },
char *values[] = { "vga", "dvi", "hdmi", "dp" },
*numbers[] = { "1", "2" };
char *argv[] = { "input-switch",
values[arg & 0xf], numbers[arg >> 4], NULL };
@ -2444,7 +2444,6 @@ g_keys[] =
{ Mod4Mask | CSMask, XK_F3, on_input_switch, 16 | 2 },
{ Mod4Mask | ControlMask, XK_F4, on_input_switch, 3 },
{ Mod4Mask | CSMask, XK_F4, on_input_switch, 16 | 3 },
{ Mod4Mask | ControlMask, XK_F5, on_input_switch, 4 },
// Brightness
{ Mod4Mask, XK_Home, on_brightness, 10 },