Compare commits

...

12 Commits

Author SHA1 Message Date
b4c1817c10
Update README.adoc
All checks were successful
Alpine 3.20 Success
2025-01-22 13:36:34 +01:00
32ea934947
Update README.adoc
All checks were successful
Alpine 3.20 Success
2025-01-22 13:25:39 +01:00
55984bc7ef
Bump copyright years
All checks were successful
Alpine 3.20 Success
2025-01-18 20:32:02 +01:00
dab190e857
eizoctl: fix message formatting on Windows
This increases the binary size, but at least we stop showing
Chinese characters instead of ASCII.
2025-01-18 20:32:02 +01:00
2594f8467d
eizoctl: also report USB-C from --input '?'
And related cleanup.
2025-01-18 20:32:02 +01:00
9039db44f6
eizoctl: make --events work with GUIs
Also add a --quiet option, and expand the program help.
2025-01-18 20:32:01 +01:00
89cab6fa39
eizoctl: display non-first numbers correctly
Humans count from 1, not from 0.
2025-01-18 18:57:16 +01:00
aea9c334e0
Bump liberty, replace help2man with help2adoc
All checks were successful
Alpine 3.20 Success
2025-01-01 06:09:49 +01:00
e53cddb030
Fix up code style adjustments 2024-12-26 12:26:19 +01:00
8832ba2227
Improve Windows packaging
All checks were successful
macOS Success
Alpine 3.20 Success
2024-12-23 17:14:59 +01:00
7bd6993b59
Bump liberty
All checks were successful
Alpine 3.20 Success
2024-12-17 06:38:47 +01:00
8717f425f4
eizo-pcap-decode.go: update for newer models
All checks were successful
Alpine 3.20 Success
2024-11-28 13:29:55 +01:00
9 changed files with 266 additions and 160 deletions

View File

@ -34,49 +34,7 @@ endif ()
# Dependencies
set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/liberty/cmake)
# TODO(p): Shove this into IconUtils.cmake.
function (icon_to_iconset_size name svg size iconset outputs)
math (EXPR _size2x "${size} * 2")
set (_dimensions "${size}x${size}")
set (_png1x "${iconset}/icon_${_dimensions}.png")
set (_png2x "${iconset}/icon_${_dimensions}@2x.png")
set (${outputs} "${_png1x};${_png2x}" PARENT_SCOPE)
set (_find_program_REQUIRE)
if (NOT ${CMAKE_VERSION} VERSION_LESS 3.18.0)
set (_find_program_REQUIRE REQUIRED)
endif ()
find_program (rsvg_convert_EXECUTABLE rsvg-convert ${_find_program_REQUIRE})
add_custom_command (OUTPUT "${_png1x}" "${_png2x}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${iconset}"
COMMAND ${rsvg_convert_EXECUTABLE} "--output=${_png1x}"
"--width=${size}" "--height=${size}" -- "${svg}"
COMMAND ${rsvg_convert_EXECUTABLE} "--output=${_png2x}"
"--width=${_size2x}" "--height=${_size2x}" -- "${svg}"
DEPENDS "${svg}"
COMMENT "Generating ${name} ${_dimensions} icons" VERBATIM)
endfunction ()
function (icon_to_icns svg output_basename output)
get_filename_component (_name "${output_basename}" NAME_WE)
set (_iconset "${PROJECT_BINARY_DIR}/${_name}.iconset")
set (_icon "${PROJECT_BINARY_DIR}/${output_basename}")
set (${output} "${_icon}" PARENT_SCOPE)
set (_icon_png_list)
foreach (_icon_size 16 32 128 256 512)
icon_to_iconset_size ("${_name}" "${svg}"
"${_icon_size}" "${_iconset}" _icon_pngs)
list (APPEND _icon_png_list ${_icon_pngs})
endforeach ()
add_custom_command (OUTPUT "${_icon}"
COMMAND iconutil -c icns -o "${_icon}" "${_iconset}"
DEPENDS ${_icon_png_list}
COMMENT "Generating ${_name} icon" VERBATIM)
set_source_files_properties ("${_icon}" PROPERTIES
MACOSX_PACKAGE_LOCATION Resources)
endfunction ()
include (IconUtils)
find_package (PkgConfig REQUIRED)
pkg_check_modules (libusb libusb-1.0)
@ -138,7 +96,6 @@ endif ()
if (WITH_HIDAPI AND WIN32)
list (APPEND targets_gui eizoctltray)
include (IconUtils)
set (icon_png_list)
foreach (icon_size 16 32 48)
icon_to_png (eizoctltray ${PROJECT_SOURCE_DIR}/eizoctltray.svg
@ -181,44 +138,57 @@ endif ()
# Generate documentation from help output
if (NOT WIN32 AND NOT CMAKE_CROSSCOMPILING)
find_program (HELP2MAN_EXECUTABLE help2man)
if (NOT HELP2MAN_EXECUTABLE)
message (FATAL_ERROR "help2man not found")
endif ()
set (HELP2ADOC "${PROJECT_SOURCE_DIR}/liberty/tools/help2adoc.awk")
set (ASCIIMAN "${PROJECT_SOURCE_DIR}/liberty/tools/asciiman.awk")
foreach (target ${targets})
set (page_output "${PROJECT_BINARY_DIR}/${target}.1")
list (APPEND project_MAN_PAGES "${page_output}")
add_custom_command (OUTPUT ${page_output}
COMMAND ${HELP2MAN_EXECUTABLE} -N
"${PROJECT_BINARY_DIR}/${target}" -o ${page_output}
DEPENDS ${target}
COMMENT "Generating man page for ${target}" VERBATIM)
set (page_adoc "${PROJECT_BINARY_DIR}/${target}.1.adoc")
set (page_roff "${PROJECT_BINARY_DIR}/${target}.1")
list (APPEND project_MAN_PAGES "${page_roff}")
# $<TARGET_FILE:tgt> could be used, if we didn't have to escape it.
string (REPLACE "\\" "\\\\"
target_path "${PROJECT_BINARY_DIR}/${target}")
add_custom_command (OUTPUT "${page_adoc}"
COMMAND env LC_ALL=C awk -f "${HELP2ADOC}"
-v "Target=${target_path}" > "${page_adoc}"
DEPENDS "${target}" "${HELP2ADOC}"
COMMENT "Generating AsciiDoc man page for ${target}" VERBATIM)
add_custom_command (OUTPUT "${page_roff}"
COMMAND env LC_ALL=C awk -f "${ASCIIMAN}"
"${page_adoc}" > "${page_roff}"
DEPENDS "${page_adoc}" "${ASCIIMAN}"
COMMENT "Generating roff man page for ${target}" VERBATIM)
endforeach ()
add_custom_target (docs ALL DEPENDS ${project_MAN_PAGES})
endif ()
# The files to be installed
include (GNUInstallDirs)
if (NOT WIN32)
include (GNUInstallDirs)
# These should be accessible by users, but need to touch system devices.
# Use the setuid bit, for simplicity.
set (SETUID "SETUID" CACHE STRING "Set this empty on permission issues")
install (TARGETS ${targets} DESTINATION ${CMAKE_INSTALL_BINDIR}
# These should be accessible by users, but need to touch system devices.
# Use the setuid bit, for simplicity.
set (SETUID "SETUID" CACHE STRING "Set this empty on permission issues")
install (TARGETS ${targets} DESTINATION ${CMAKE_INSTALL_BINDIR}
PERMISSIONS
OWNER_WRITE OWNER_READ OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE
WORLD_READ WORLD_EXECUTE
${SETUID})
install (TARGETS ${targets_gui} DESTINATION ${CMAKE_INSTALL_BINDIR})
install (FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
foreach (page ${project_MAN_PAGES})
install (TARGETS ${targets_gui} DESTINATION ${CMAKE_INSTALL_BINDIR})
install (FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
foreach (page ${project_MAN_PAGES})
string (REGEX MATCH "\\.([0-9])$" manpage_suffix "${page}")
install (FILES "${page}"
DESTINATION "${CMAKE_INSTALL_MANDIR}/man${CMAKE_MATCH_1}")
endforeach ()
endforeach ()
set (CPACK_SET_DESTDIR TRUE)
else ()
install (TARGETS ${targets} ${targets_gui} DESTINATION .)
endif ()
# CPack
set (CPACK_PACKAGE_VENDOR "Premysl Eric Janouch")
@ -232,5 +202,4 @@ set (CPACK_SOURCE_GENERATOR "TGZ;ZIP")
set (CPACK_SOURCE_IGNORE_FILES "/\\\\.git;/build;/CMakeLists.txt.user")
set (CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}")
set (CPACK_SET_DESTDIR TRUE)
include (CPack)

View File

@ -1,4 +1,4 @@
Copyright (c) 2013, 2024, Přemysl Eric Janouch <p@janouch.name>
Copyright (c) 2013, 2024 - 2025, Přemysl Eric Janouch <p@janouch.name>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

7
NEWS
View File

@ -1,3 +1,10 @@
Unreleased
* eizoctl: added a --quiet option to suppress information and/or errors
* eizoctl: fixed input port reporting
1.1.0 (2024-11-28)
* Ported eizoctltray to macOS as well

View File

@ -1,6 +1,7 @@
USB drivers
===========
:compact-option:
:source-highlighter: chroma
_usb-drivers_ is a collection of utilities to control various hardware over USB.
@ -26,6 +27,49 @@ it will also suspend or power off the system, respectively.
image:eizoctltray-win.png["eizoctltray on Windows with expanded menu", 343, 278]
image:eizoctltray-mac.png["eizoctltray on macOS with expanded menu", 343, 278]
Installation
^^^^^^^^^^^^
On Windows, copy it to
__Users\*\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup__.
On macOS, copy it to the _Applications_ folder,
then add it in _System Settings → General → Login Items → Open at Login_.
Automation
^^^^^^^^^^
_eizoctltray_ can also be used the same way as _eizoctl_, just with any output
redirected to message windows, rather than a console window or a terminal.
This is useful for automation, such as with AutoHotkey.
Beware that Windows is not a fan of how rapidly EIZO monitors switch upstream
USB ports. Thus, if you invoke port switching with keyboard shortcuts,
remember to add a small delay, so that pressed modifier keys are not remembered.
You will also want to silence any error messages.
.AutoHotkey example
```autohotkey
#Requires AutoHotkey v2.0
exe := A_Startup . "\eizoctltray.exe"
^#F1:: { ; Windows + Control + F1
Sleep 500
Run exe " -qq --input HDMI"
}
^#F2:: { ; Windows + Control + F2
Sleep 500
Run exe " -qq --input DP"
}
^#F3:: { ; Windows + Control + F3
Sleep 500
Run exe " -qq --input USB-C"
}
#Home:: { ; Windows + Home
Run exe " -q --brightness +0.1"
}
#End:: { ; Windows + End
Run exe " -q --brightness -0.1"
}
```
elksmart-comm
~~~~~~~~~~~~~
_elksmart-comm_ interfaces with ELK Smart infrared dongles EKX4S and EKX5S-T,
@ -53,13 +97,13 @@ Regular releases are sporadic. git master should be stable enough.
You can get a package with the latest development version
as a https://git.janouch.name/p/nixexprs[Nix derivation].
Windows binaries can be downloaded from
Windows/macOS binaries can be downloaded from
https://git.janouch.name/p/usb-drivers/releases[the Releases page on Gitea].
Building
--------
Build dependencies:
CMake, pkg-config, liberty (included), help2man +
CMake, pkg-config, liberty (included) +
Runtime dependencies:
libusb-1.0 (elksmart-comm, razer-bw-te-ctl), hidapi >= 0.14 (eizoctl)

View File

@ -73,10 +73,17 @@ var (
fmtIn, fmtOut, fmtReset string
)
func decodeSubreport(data []byte) string {
if len(data) < 6 {
func decodeSubreport(id byte, data []byte) string {
critical := isCriticalSubreport(id)
if len(data) < 6 || critical && len(data) < 8 {
return fmt.Sprintf("%x", data)
}
var cs uint16
if critical {
data, cs = data[2:], le.Uint16(data[0:2])
}
usage := uint32(le.Uint16(data[:2]))<<16 | uint32(le.Uint16(data[2:4]))
filtered := make([]byte, len(data)-6)
for i, b := range data[6:] {
@ -86,8 +93,17 @@ func decodeSubreport(data []byte) string {
filtered[i] = b
}
}
return fmt.Sprintf("<> %08x %04x %x %s", usage, le.Uint16(data[4:6]),
data[6:], string(filtered))
if critical {
return fmt.Sprintf("<> %08x %04x=%04x %x %s",
usage, cs, le.Uint16(data[4:6]), data[6:], string(filtered))
} else if usage == 0xff0000f1 {
// No idea what this is, but it follows the format.
return fmt.Sprintf("<> %08x %04x %s",
usage, le.Uint16(data[4:6]), decodeMP(data[6:]))
} else {
return fmt.Sprintf("<> %08x %04x %x %s",
usage, le.Uint16(data[4:6]), data[6:], string(filtered))
}
}
func decodeResult(data []byte) string {
@ -131,6 +147,14 @@ func isGetSubreport(id byte) bool {
return false
}
func isCriticalSubreport(id byte) bool {
switch id {
case 11, 12, 13, 14:
return true
}
return false
}
func isSubreport(id byte) bool {
return isSetSubreport(id) || isGetSubreport(id)
}
@ -143,7 +167,7 @@ func processInterrupt(p *Packet) {
if *raw {
fmt.Printf("%s INT %02x %x\n", p.addr(), data[0], data[1:])
} else if isSubreport(data[0]) {
fmt.Printf("%s INT %s\n", p.addr(), decodeSubreport(data[1:]))
fmt.Printf("%s INT %s\n", p.addr(), decodeSubreport(data[0], data[1:]))
}
}
@ -163,7 +187,7 @@ func processControl(p *Packet) {
fmt.Printf("%s IN SR %x\n", p.addr(), data[5:])
} else if isGetSubreport(data[0]) {
fmt.Printf("%s IN %s%s%s\n", p.addr(),
fmtIn, decodeSubreport(data[1:]), fmtReset)
fmtIn, decodeSubreport(data[0], data[1:]), fmtReset)
} else if data[0] == 6 {
fmt.Printf("%s IN PC %04x\n", p.addr(), le.Uint16(data[1:]))
} else if data[0] == 7 {
@ -172,6 +196,8 @@ func processControl(p *Packet) {
fmt.Printf("%s IN ID %s %s\n", p.addr(), data[1:9], data[9:])
} else if data[0] == 9 {
fmt.Printf("%s IN MP %s\n", p.addr(), decodeMP(data[1:]))
} else if data[0] == 10 {
fmt.Printf("%s IN CS %04x\n", p.addr(), le.Uint16(data[1:]))
} else {
fmt.Printf("%s IN %02x %x\n", p.addr(), data[0], data[1:])
}
@ -180,7 +206,9 @@ func processControl(p *Packet) {
fmt.Printf("%s OUT %02x %x\n", p.addr(), data[0], data[1:])
} else if isSetSubreport(data[0]) {
fmt.Printf("%s OUT %s%s%s\n", p.addr(),
fmtOut, decodeSubreport(data[1:]), fmtReset)
fmtOut, decodeSubreport(data[0], data[1:]), fmtReset)
} else if data[0] == 10 {
fmt.Printf("%s OUT CS %04x\n", p.addr(), le.Uint16(data[1:]))
} else if data[0] != 1 && !isGetSubreport(data[0]) {
fmt.Printf("%s OUT %02x %x\n", p.addr(), data[0], data[1:])
}

188
eizoctl.c
View File

@ -4,7 +4,7 @@
* This program stays independent of the liberty library
* in order to build on Windows.
*
* Copyright (c) 2024, Přemysl Eric Janouch <p@janouch.name>
* Copyright (c) 2025, Přemysl Eric Janouch <p@janouch.name>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted.
@ -18,6 +18,14 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
// On Windows, vswprintf() interprets %s in the width of the format string,
// and %hs is not really compliant with any standard:
// https://devblogs.microsoft.com/oldnewthing/20190830-00/?p=102823
#ifdef _WIN32
#define __USE_MINGW_ANSI_STDIO
#endif
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
@ -41,7 +49,9 @@
#define hid_init hidapi_hid_init
#endif
#if defined __GNUC__
#if defined __MINGW_GNU_PRINTF
#define ATTRIBUTE_PRINTF(x, y) __MINGW_GNU_PRINTF((x), (y))
#elif defined __GNUC__
#define ATTRIBUTE_PRINTF(x, y) __attribute__((format(printf, x, y)))
#else
#define ATTRIBUTE_PRINTF(x, y)
@ -803,7 +813,7 @@ eizo_port_by_name(const char *name)
return index;
}
static char *
static const char *
eizo_port_to_name(uint16_t port)
{
const char *stem = NULL;
@ -811,14 +821,14 @@ eizo_port_to_name(uint16_t port)
if (group && group < sizeof g_port_names / sizeof g_port_names[0])
stem = g_port_names[group][0];
static char buffer[32] = "";
static char buf[32] = "";
if (!stem)
snprintf(buffer, sizeof buffer, "%x", port);
snprintf(buf, sizeof buf, "%x", port);
else if (!number)
snprintf(buffer, sizeof buffer, "%s", stem);
snprintf(buf, sizeof buf, "%s", stem);
else
snprintf(buffer, sizeof buffer, "%s %d", stem, number);
return buffer;
snprintf(buf, sizeof buf, "%s %d", stem, (number + 1));
return buf;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -895,7 +905,7 @@ eizo_get_input_ports(struct eizo_monitor *m, uint16_t *ports, size_t size)
}
static uint16_t
eizo_resolve_port(struct eizo_monitor *m, const char *port)
eizo_resolve_port_by_name(struct eizo_monitor *m, const char *port)
{
uint8_t usb_c_index = 0;
if (eizo_port_by_name_in_group(port, g_port_names_usb_c, &usb_c_index)) {
@ -907,6 +917,26 @@ eizo_resolve_port(struct eizo_monitor *m, const char *port)
return eizo_port_by_name(port);
}
static const char *
eizo_resolve_port_to_name(struct eizo_monitor *m, uint16_t port)
{
// USB-C ports are a bit tricky, they only need to be /displayed/ as such.
struct eizo_profile_item *item =
&m->profile[EIZO_PROFILE_KEY_USB_C_INPUT_PORTS];
for (uint8_t i = 0; i < item->len / 2; i++) {
if (port != peek_u16le(item->data + i * 2))
continue;
static char buf[32] = "";
if (!i)
snprintf(buf, sizeof buf, "%s", g_port_names_usb_c[0]);
else
snprintf(buf, sizeof buf, "%s %u", g_port_names_usb_c[0], (i + 1));
return buf;
}
return eizo_port_to_name(port);
}
static bool
eizo_set_input_port(struct eizo_monitor *m, uint16_t port)
{
@ -934,8 +964,40 @@ eizo_restart(struct eizo_monitor *m)
// --- Main --------------------------------------------------------------------
struct catbuf {
char buf[4096];
size_t len;
};
static const char *
catf(struct catbuf *b, const char *format, ...) ATTRIBUTE_PRINTF(2, 3);
static const char *
catf(struct catbuf *b, const char *format, ...)
{
va_list ap;
va_start(ap, format);
int result = vsnprintf(b->buf + b->len, sizeof b->buf - b->len, format, ap);
va_end(ap);
if (result >= 0) {
b->len += result;
if (b->len >= sizeof b->buf)
b->len = sizeof b->buf - 1;
}
return b->buf;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
typedef void (*print_fn)(const char *format, ...) ATTRIBUTE_PRINTF(1, 2);
static void print_dummy(const char *format, ...)
{
(void) format;
}
static bool
eizo_watch(struct eizo_monitor *m)
eizo_watch(struct eizo_monitor *m, print_fn output, print_fn error)
{
uint8_t buf[1024] = {};
int res = 0;
@ -945,57 +1007,72 @@ eizo_watch(struct eizo_monitor *m)
if (buf[0] != EIZO_REPORT_ID_GET &&
buf[0] != EIZO_REPORT_ID_GET_LONG) {
printf("Unknown report ID\n");
error("Unknown report ID: %02x\n", buf[0]);
continue;
}
struct catbuf message = {{0}, 0};
uint16_t page = peek_u16le(&buf[1]), id = peek_u16le(&buf[3]);
uint32_t usage = page << 16 | id;
printf("%08x", usage);
catf(&message, "%08x", usage);
const struct parser_report *r = eizo_monitor_subreport(m, usage);
if (!r) {
printf(" unknown usage\n");
output(catf(&message, " unknown usage\n"));
continue;
}
size_t rlen = r->report_size / 8 * r->report_count;
if ((size_t) res < 7 + rlen) {
printf(" received data too short\n");
output(catf(&message, " received data too short\n"));
continue;
}
if (r->report_size == 16)
for (size_t i = 0; i + 1 < rlen; i += 2)
printf(" %04x", peek_u16le(&buf[7 + i]));
catf(&message, " %04x", peek_u16le(&buf[7 + i]));
else
for (size_t i = 0; i < rlen; i++)
printf(" %02x", buf[7 + i]);
printf("\n");
catf(&message, " %02x", buf[7 + i]);
output(catf(&message, "\n"));
}
}
typedef void (*print_fn)(const char *format, ...) ATTRIBUTE_PRINTF(1, 2);
static const char *usage = "Usage: %s OPTION...\n\n"
" -b, --brightness [+-]BRIGHTNESS\n"
" Change monitor brightness; values go from 0 to 1 and may be relative.\n"
" -i, --input NAME\n"
" Change monitor input ports; use '?' to retrieve current values.\n"
" -r, --restart\n"
" Reboot monitors.\n"
" -e, --events\n"
" Watch for events reported by monitors.\n"
" -q, --quiet\n"
" Use once to suppress informative messages, twice to suppress errors.\n"
" -h, --help\n"
" Display this help and exit.\n"
" -V, --version\n"
" Output version information and exit.\n";
static int
run(int argc, char *argv[], print_fn output, print_fn error, bool verbose)
run(int argc, char *argv[], print_fn output, print_fn error)
{
const char *name = argv[0];
const char *usage = "Usage: %s [--brightness [+-]BRIGHTNESS] [--input NAME]"
" [--restart] [--events]\n";
static struct option opts[] = {
{"input", required_argument, NULL, 'i'},
{"brightness", required_argument, NULL, 'b'},
{"input", required_argument, NULL, 'i'},
{"restart", no_argument, NULL, 'r'},
{"events", no_argument, NULL, 'e'},
{"quiet", no_argument, NULL, 'q'},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'V'},
{}
};
int quiet = 0;
double brightness = NAN;
bool relative = false, restart = false, events = false;
const char *port = NULL;
int c = 0;
while ((c = getopt_long(argc, argv, "b:i:h", opts, NULL)) != -1)
while ((c = getopt_long(argc, argv, "b:i:reqhV", opts, NULL)) != -1)
switch (c) {
case 'b':
relative = *optarg == '+' || *optarg == '-';
@ -1013,6 +1090,9 @@ run(int argc, char *argv[], print_fn output, print_fn error, bool verbose)
case 'e':
events = true;
break;
case 'q':
quiet++;
break;
case 'h':
output(usage, name);
return 0;
@ -1038,6 +1118,10 @@ run(int argc, char *argv[], print_fn output, print_fn error, bool verbose)
error("%ls\n", hid_error(NULL));
return 1;
}
if (quiet > 0)
output = print_dummy;
if (quiet > 1)
error = print_dummy;
// It should be possible to choose a particular monitor,
// but it is generally more useful to operate on all of them.
@ -1057,25 +1141,25 @@ run(int argc, char *argv[], print_fn output, print_fn error, bool verbose)
double next = relative ? brightness + prev : brightness;
if (!eizo_set_brightness(&m, next))
error("Failed to set brightness: %s\n", m.error);
else if (verbose)
else
output("%s %s: brightness: %.2f -> %.2f\n",
m.product, m.serial, prev, next);
}
}
if (port) {
uint16_t prev = 0;
uint16_t next = eizo_resolve_port(&m, port);
uint16_t next = eizo_resolve_port_by_name(&m, port);
if (!eizo_get_input_port(&m, &prev)) {
error("Failed to get input port: %s\n", m.error);
} else if (!strcmp(port, "?")) {
output("%s %s: input: %s\n",
m.product, m.serial, eizo_port_to_name(prev));
m.product, m.serial, eizo_resolve_port_to_name(&m, prev));
} else if (!next) {
error("Failed to resolve port name: %s\n", port);
} else {
if (!eizo_set_input_port(&m, next))
error("Failed to set input port: %s\n", m.error);
else if (verbose)
else
output("%s %s: input: %s -> %s\n",
m.product, m.serial, eizo_port_to_name(prev), port);
}
@ -1083,13 +1167,13 @@ run(int argc, char *argv[], print_fn output, print_fn error, bool verbose)
if (restart) {
if (!eizo_restart(&m))
error("Failed to restart: %s\n", m.error);
else if (verbose)
else
output("%s %s: restart\n", m.product, m.serial);
}
if (events) {
if (!verbose)
if (quiet)
error("Watching events is not possible in this mode\n");
else if (!eizo_watch(&m))
else if (!eizo_watch(&m, output, error))
error("%s\n", m.error);
}
@ -1124,7 +1208,7 @@ stdio_error(const char *format, ...)
int
main(int argc, char *argv[])
{
return run(argc, argv, stdio_output, stdio_error, true);
return run(argc, argv, stdio_output, stdio_error);
}
// --- Windows -----------------------------------------------------------------
@ -1167,8 +1251,8 @@ message_output(const char *format, ...)
wchar_t *message = message_printf(format, ap);
va_end(ap);
if (message) {
MessageBox(
NULL, message, NULL, MB_ICONINFORMATION | MB_OK | MB_APPLMODAL);
MessageBox(NULL, message,
L"Message", MB_ICONINFORMATION | MB_OK | MB_APPLMODAL);
free(message);
}
}
@ -1228,21 +1312,9 @@ append_monitor(struct eizo_monitor *m, HMENU menu, UINT_PTR base)
if (!ports[0])
ports[0] = current;
// USB-C ports are a bit tricky, they only need to be /displayed/ as such.
struct eizo_profile_item *item =
&m->profile[EIZO_PROFILE_KEY_USB_C_INPUT_PORTS];
for (size_t i = 0; ports[i]; i++) {
uint8_t usb_c = 0;
for (size_t u = 0; u < item->len / 2; u++)
if (ports[i] == peek_u16le(item->data + u * 2))
usb_c = u + 1;
if (!usb_c)
snwprintf(buf, sizeof buf, L"%s", eizo_port_to_name(ports[i]));
else if (usb_c == 1)
snwprintf(buf, sizeof buf, L"%s", g_port_names_usb_c[0]);
else
snwprintf(buf, sizeof buf, L"%s %u", g_port_names_usb_c[0], usb_c);
snwprintf(buf, sizeof buf, L"%s",
eizo_resolve_port_to_name(m, ports[i]));
UINT flags = MF_STRING;
if (ports[i] == current)
@ -1395,7 +1467,7 @@ wWinMain(
char *mb = mbargv[i + 1] = calloc(len, sizeof *mb);
wcstombs(mb, argv[i], len);
}
return run(argc + 1, mbargv, message_output, message_error, false);
return run(argc + 1, mbargv, message_output, message_error);
}
LocalFree(argv);
@ -1609,23 +1681,9 @@ message_error(const char *format, ...)
if (!ports[0])
ports[0] = current;
// USB-C ports are a bit tricky, they only need to be /displayed/ as such.
struct eizo_profile_item *item =
&m.monitor->profile[EIZO_PROFILE_KEY_USB_C_INPUT_PORTS];
for (size_t i = 0; ports[i]; i++) {
uint8_t usb_c = 0;
for (size_t u = 0; u < item->len / 2; u++)
if (ports[i] == peek_u16le(item->data + u * 2))
usb_c = u + 1;
NSString *title = nil;
if (!usb_c)
title = [NSString stringWithUTF8String:eizo_port_to_name(ports[i])];
else if (usb_c == 1)
title = [NSString stringWithUTF8String:g_port_names_usb_c[0]];
else
title = [NSString stringWithFormat:@"%s %u",
g_port_names_usb_c[0], usb_c];
NSString *title = [NSString stringWithUTF8String:
eizo_resolve_port_to_name(m.monitor, ports[i])];
NSMenuItem *inputPortItem = [[NSMenuItem alloc]
initWithTitle:title action:@selector(setInputPort:)
@ -1708,7 +1766,7 @@ main(int argc, char *argv[])
{
@autoreleasepool {
if (argc > 1)
return run(argc, argv, message_output, message_error, true);
return run(argc, argv, message_output, message_error);
NSApplication *app = [NSApplication sharedApplication];
ApplicationDelegate *delegate = [ApplicationDelegate new];

View File

@ -196,7 +196,7 @@ compress_value(unsigned value, struct str *encoded)
}
static void
compress_pulses (const struct pulse *pulses, size_t len, struct str *encoded)
compress_pulses(const struct pulse *pulses, size_t len, struct str *encoded)
{
unsigned counts[len];
memset(counts, 0, sizeof counts);
@ -527,15 +527,15 @@ send_identify(libusb_device_handle *device, struct error **e)
#if 0
// The EKX4S does not respond to this request.
static uint8_t c_serial[] = { -5, -5, -5, -5 };
if ((result = libusb_bulk_transfer (device, g.endpoint_out,
if ((result = libusb_bulk_transfer(device, g.endpoint_out,
c_serial, sizeof c_serial, &len, 100)))
return error_set (e, "serial/send: %s", libusb_strerror (result));
if ((result = libusb_bulk_transfer (device, g.endpoint_in,
return error_set(e, "serial/send: %s", libusb_strerror(result));
if ((result = libusb_bulk_transfer(device, g.endpoint_in,
buffer, sizeof buffer, &len, 100)))
return error_set (e, "serial/recv: %s", libusb_strerror (result));
return error_set(e, "serial/recv: %s", libusb_strerror(result));
if (len < (int) sizeof c_serial ||
memcmp (buffer, c_serial, sizeof c_serial))
return error_set (e, "serial retrieval failed");
memcmp(buffer, c_serial, sizeof c_serial))
return error_set(e, "serial retrieval failed");
#endif
return true;
}

@ -1 +1 @@
Subproject commit 492815c8fc38ad6e333b2f1c5094a329e3076155
Subproject commit 9268fb8eba4a60499809965b3b69c2eb7e3798e7

View File

@ -198,8 +198,8 @@ parse_options(int argc, char *argv[],
};
if (argc == 1) {
show_usage (argv[0]);
exit (EXIT_FAILURE);
show_usage(argv[0]);
exit(EXIT_FAILURE);
}
int c;
@ -256,7 +256,7 @@ parse_options(int argc, char *argv[],
!strcasecmp(optarg, "on") ||
!strcasecmp(optarg, "yes")) {
new_config->gaming_mode = true;
} else if (!strcasecmp (optarg, "false") ||
} else if (!strcasecmp(optarg, "false") ||
!strcasecmp(optarg, "off") ||
!strcasecmp(optarg, "no")) {
new_config->gaming_mode = false;
@ -362,7 +362,7 @@ main(int argc, char *argv[])
if ((result = apply_options(device, &options, &new_config)))
FAIL(error_4, "operation failed: %s\n",
libusb_error_name (result));
libusb_error_name(result));
error_4:
if ((result = libusb_release_interface(device, BW_CTL_IFACE)))
FAIL(error_3, "couldn't release interface: %s\n",