From e7916cfa1041b6835551bb50d650e757aa1855b3 Mon Sep 17 00:00:00 2001 From: N-Storm Date: Mon, 29 Apr 2024 19:53:06 +0300 Subject: [PATCH] Squash merge dev branch into main. Changes: * Refactoring: moved global defines to digilivolo.h, code split into 2 additional units based on functions: usb_func.[ch] which handles USB HID related things & args.[ch] which handles command line options, help and copyright messages. * Some text messages from software improved. * Added comment headers to source files. * hidapi version requirement set to 0.13 (as it's in fact). * Added arm-linux-gnueabihf-gcc-toolchain.cmake file for cross-compiling arm binaries. --- ...ware-platformio.yml => build-firmware.yml} | 2 +- ...-software-cmake.yml => build-software.yml} | 2 +- firmware/lib/DLUSB/DLUSB.cpp | 10 +- firmware/lib/DLUSB/DLUSB.h | 12 +- firmware/lib/Livolo/Livolo.cpp | 1 - firmware/src/DigiLivolo.cpp | 20 ++ software/CMakeLists.txt | 8 +- software/build.sh | 3 + .../arm-linux-gnueabihf-gcc-toolchain.cmake | 22 ++ software/src/args.c | 119 ++++++++++ software/src/args.h | 56 +++++ software/src/digilivolo.c | 216 ++++-------------- software/src/digilivolo.h | 36 +++ software/src/git_version.h.in | 19 +- software/src/usb_func.c | 90 ++++++++ software/src/usb_func.h | 33 +++ 16 files changed, 461 insertions(+), 188 deletions(-) rename .github/workflows/{build-firmware-platformio.yml => build-firmware.yml} (96%) rename .github/workflows/{build-software-cmake.yml => build-software.yml} (97%) create mode 100644 software/cmake/arm-linux-gnueabihf-gcc-toolchain.cmake create mode 100644 software/src/args.c create mode 100644 software/src/args.h create mode 100644 software/src/digilivolo.h create mode 100644 software/src/usb_func.c create mode 100644 software/src/usb_func.h diff --git a/.github/workflows/build-firmware-platformio.yml b/.github/workflows/build-firmware.yml similarity index 96% rename from .github/workflows/build-firmware-platformio.yml rename to .github/workflows/build-firmware.yml index 3bc375c..e3d4728 100644 --- a/.github/workflows/build-firmware-platformio.yml +++ b/.github/workflows/build-firmware.yml @@ -1,4 +1,4 @@ -name: Build firmware +name: Build DigiLivolo firmware on: # Triggers the workflow on push or pull request events but only for the main branch push: diff --git a/.github/workflows/build-software-cmake.yml b/.github/workflows/build-software.yml similarity index 97% rename from .github/workflows/build-software-cmake.yml rename to .github/workflows/build-software.yml index e7e3766..62c3cfd 100644 --- a/.github/workflows/build-software-cmake.yml +++ b/.github/workflows/build-software.yml @@ -22,7 +22,7 @@ jobs: - { os: ubuntu-latest, shell: bash, c_compiler: clang } - { os: windows-latest, shell: 'msys2 {0}', c_compiler: gcc, binary_orig: digilivolo.exe, binary_target: digilivolo-win-x86_64.exe } - { os: windows-latest, shell: pwsh, c_compiler: gcc } - - { os: windows-latest, shell: pwsh, c_compiler: clang } + - { os: windows-latest, shell: pwsh, c_compiler: clang } build_type: [Release] defaults: run: diff --git a/firmware/lib/DLUSB/DLUSB.cpp b/firmware/lib/DLUSB/DLUSB.cpp index 98feec8..cb2cbe1 100644 --- a/firmware/lib/DLUSB/DLUSB.cpp +++ b/firmware/lib/DLUSB/DLUSB.cpp @@ -1,4 +1,8 @@ /* Name: DLUSB.c + * Part of the DigiLivolo firmware. + * https://github.com/N-Storm/DigiLivolo/ + * Copyright (c) 2024 GitHub user N-Storm. + * * Based on DLUSB library from Digistump Arduino: https://github.com/ArminJo/DigistumpArduino * Based on V-USB Arduino Examples by Philip J. Lindsay * Modification for the Digispark by Erik Kettenburg, Digistump LLC @@ -9,11 +13,11 @@ * Original author: Christian Starkjohann * Arduino modifications by: Philip J. Lindsay * Creation Date: 2008-04-11 - * Tabsize: 4 * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH - * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) - * This Revision: $Id: main.c 692 2008-11-07 15:07:40Z cs $ + * License: GNU GPL v3 or later + * SPDX-License-Identifier: GPL-3.0-or-later */ + #include #include #include diff --git a/firmware/lib/DLUSB/DLUSB.h b/firmware/lib/DLUSB/DLUSB.h index dfd871f..b3de31a 100644 --- a/firmware/lib/DLUSB/DLUSB.h +++ b/firmware/lib/DLUSB/DLUSB.h @@ -1,9 +1,15 @@ -/* +/* Name: DLUSB.h + * Part of the DigiLivolo firmware. + * https://github.com/N-Storm/DigiLivolo/ + * Copyright (c) 2024 GitHub user N-Storm. + * * Based on DigiUSB library from Digistump Arduino: https://github.com/ArminJo/DigistumpArduino - * Based on Obdev's AVRUSB code and under the same license. + * Based on Obdev's AVRUSB code. * - * TODO: Make a proper file header. :-) + * License: GNU GPL v3 or later + * SPDX-License-Identifier: GPL-3.0-or-later */ + #ifndef __DLUSB_h__ #define __DLUSB_h__ diff --git a/firmware/lib/Livolo/Livolo.cpp b/firmware/lib/Livolo/Livolo.cpp index 74b50de..145306f 100644 --- a/firmware/lib/Livolo/Livolo.cpp +++ b/firmware/lib/Livolo/Livolo.cpp @@ -4,7 +4,6 @@ Released into the public domain. 01/12/2013 - code optimization, thanks Maarten! http://forum.arduino.cc/index.php?topic=153525.msg1489857#msg1489857 - */ #include "Arduino.h" diff --git a/firmware/src/DigiLivolo.cpp b/firmware/src/DigiLivolo.cpp index 68eed2c..46c0f04 100644 --- a/firmware/src/DigiLivolo.cpp +++ b/firmware/src/DigiLivolo.cpp @@ -1,3 +1,23 @@ +/* Part of the DigiLivolo firmware. + * https://github.com/N-Storm/DigiLivolo/ + * Copyright (c) 2024 GitHub user N-Storm. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + #include #include #include diff --git a/software/CMakeLists.txt b/software/CMakeLists.txt index bb2418f..245309a 100644 --- a/software/CMakeLists.txt +++ b/software/CMakeLists.txt @@ -2,7 +2,9 @@ cmake_minimum_required(VERSION 3.5 FATAL_ERROR) set(PROJECT_NAME "digilivolo") project(${PROJECT_NAME} C) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -std=gnu11 -flto -ffunction-sections -fdata-sections -ffat-lto-objects -Wall -Wl,--warn-common -Wl,--gc-sections") +if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -std=gnu11 -flto -ffunction-sections -fdata-sections -ffat-lto-objects -Wall -Wl,--warn-common -Wl,--gc-sections") +endif() set(HIDAPI_WITH_LIBUSB FALSE) set(BUILD_SHARED_LIBS FALSE) # HIDAPI as static library on all platforms @@ -30,7 +32,7 @@ if(NOT USE_SYSTEM_HIDAPI) message(STATUS "hidapi will be built from sources") else() message(STATUS "Finding library hidapi") - find_package(hidapi 0.12 REQUIRED) + find_package(hidapi 0.13 REQUIRED) endif() message(STATUS "Using HIDAPI: ${hidapi_VERSION}") @@ -38,7 +40,7 @@ message(STATUS "Using HIDAPI: ${hidapi_VERSION}") add_subdirectory(lib/argp-standalone) configure_file(src/git_version.h.in src/git_version.h @ONLY) -add_executable(${PROJECT_NAME} src/digilivolo.c) +add_executable(${PROJECT_NAME} src/args.c src/digilivolo.c src/usb_func.c) target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/src") target_link_libraries(${PROJECT_NAME} hidapi::hidapi argp-standalone) diff --git a/software/build.sh b/software/build.sh index 847fdcf..65d96f5 100644 --- a/software/build.sh +++ b/software/build.sh @@ -1,8 +1,11 @@ #!/bin/bash # Part of the DigiLivolo control software. # https://github.com/N-Storm/DigiLivolo/ +# # Builds project from sources with a cmake. # If called with an argument "full" (build.sh full), does a full rebuild. +# +# SPDX-License-Identifier: GPL-3.0-or-later SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) diff --git a/software/cmake/arm-linux-gnueabihf-gcc-toolchain.cmake b/software/cmake/arm-linux-gnueabihf-gcc-toolchain.cmake new file mode 100644 index 0000000..e5a1bbb --- /dev/null +++ b/software/cmake/arm-linux-gnueabihf-gcc-toolchain.cmake @@ -0,0 +1,22 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR arm) + +SET (TRIPLET arm-linux-gnueabihf) +SET(CMAKE_C_COMPILER ${TRIPLET}-gcc) + +# Build for Cortex-A7 if required +# SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mcpu=cortex-a7 -mtune=cortex-a7") + +# set path(s) to search for libraries/binaries/headers +# SET (CMAKE_FIND_ROOT_PATH /usr/${TRIPLET} /usr/lib/${TRIPLET} /usr/include /usr/include/${TRIPLET}) +# ensure only cross-dirs are searched +# SET (ONLY_CMAKE_FIND_ROOT_PATH TRUE) + +# We have cross pkg-config installed instead +SET(PKG_CONFIG_EXECUTABLE ${TRIPLET}-pkg-config) + +# search for programs in the build host directories +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +# for libraries and headers in the target directories +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/software/src/args.c b/software/src/args.c new file mode 100644 index 0000000..533970b --- /dev/null +++ b/software/src/args.c @@ -0,0 +1,119 @@ +/* Part of the DigiLivolo control software. + * https://github.com/N-Storm/DigiLivolo/ + * Copyright (c) 2024 GitHub user N-Storm. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ +#include +#include +#include +#include +#include +#include + +#include "digilivolo.h" + +#include +#include "usb_func.h" + +#include "git_version.h" +#include "args.h" + +// [argp] Program documentation. +// const char* argp_program_version = GIT_VERSION; +const char prognamever[] = "digilivolo " GIT_VERSION "\n"; +const char doc[] = "\nSoftware to control DigiLivolo devices.\n"; + +const char* argp_program_bug_address = "https://github.com/N-Storm/DigiLivolo/\n\ +Copyright (c) 2024 GitHub user N-Storm.\n\ +License GPLv3+: GNU GPL version 3 or later "; + +// [argp] A description of the arguments we accept. +char args_doc[] = "REMOTE_ID KEY_ID"; + +// [argp] The options we understand. +struct argp_option options[] = { + {0, 0, 0, 0, "Positional arguments:" }, + {"REMOTE_ID", 0, 0, OPTION_DOC | OPTION_NO_USAGE, "Livilo Remote ID (1-65535)" }, + {"KEY_ID", 0, 0, OPTION_DOC | OPTION_NO_USAGE, "Livilo Key ID (1-255)" }, + {0, 0, 0, 0, "Options:" }, + {"verbose", 'v', 0, 0, "Produce verbose output" }, + { 0 } +}; + +// [argp] Command-line arguments. +arguments_t arguments; + +// [argp] Parse a single option. +error_t parse_opt(int key, char* arg, struct argp_state* state) +{ + /* Get the input argument from argp_parse, which we + * know is a pointer to our arguments structure. */ + struct arguments* arguments = state->input; + + switch (key) { + case 'v': + arguments->verbose = true; + break; + + case ARGP_KEY_ARG: + if (state->arg_num >= 2) + // Too many arguments. + argp_usage(state); + + char* endptr; + // Convert argument to long + long value = strtol(arg, &endptr, 0); + // Check if it was valid long value + if (*endptr == '\0') { + switch (state->arg_num) { + case 0: + // Out of range + if (value > 65535 || value <= 0) + argp_usage(state); + else + arguments->remote_id = (uint16_t)value; + break; + + case 1: + // Out of range + if (value > 255 || value <= 0) + argp_usage(state); + else + arguments->key_id = (uint8_t)value; + break; + + default: + return ARGP_ERR_UNKNOWN; + } + } + else + // REMOTE_ID or KEY_ID not an unsigned integer + argp_usage(state); + + break; + + case ARGP_KEY_END: + if (state->arg_num < 2) + // Not enough arguments. + argp_usage(state); + break; + + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} diff --git a/software/src/args.h b/software/src/args.h new file mode 100644 index 0000000..1c5e171 --- /dev/null +++ b/software/src/args.h @@ -0,0 +1,56 @@ +/* Part of the DigiLivolo control software. + * https://github.com/N-Storm/DigiLivolo/ + * Copyright (c) 2024 GitHub user N-Storm. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#ifndef __args_h__ +#define __args_h__ + +#include +#include +#include + +#include "digilivolo.h" + +#include "git_version.h" +#include + +// [argp] A description of the arguments we accept. +extern char args_doc[]; + +// [argp] The options we understand. +extern struct argp_option options[]; + +// [argp] Program documentation. +// const char* argp_program_version = GIT_VERSION; +extern const char prognamever[]; +extern const char doc[]; +extern const char* argp_program_bug_address; + +// [argp] Command-line arguments. +typedef struct arguments { + uint16_t remote_id; + uint8_t key_id; + bool verbose; +} arguments_t; + +extern arguments_t arguments; + +extern error_t parse_opt(int key, char* arg, struct argp_state* state); + +#endif // __args_h__ diff --git a/software/src/digilivolo.c b/software/src/digilivolo.c index 24c93fa..fefe723 100644 --- a/software/src/digilivolo.c +++ b/software/src/digilivolo.c @@ -1,5 +1,22 @@ /* Part of the DigiLivolo control software. - * https://github.com/N-Storm/DigiLivolo/ */ + * https://github.com/N-Storm/DigiLivolo/ + * Copyright (c) 2024 GitHub user N-Storm. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ #include #include @@ -8,167 +25,11 @@ #include #include -#include - -#include "git_version.h" -#include - -// [argp] Program documentation. -// const char* argp_program_version = GIT_VERSION; -const char prognamever[] = "digilivolo " GIT_VERSION; -const char doc[] = "\nSoftware to control DigiLivolo devices.\n"; -const char* argp_program_bug_address = "https://github.com/N-Storm/DigiLivolo/"; - -// [argp] A description of the arguments we accept. -static char args_doc[] = "REMOTE_ID KEY_ID"; - -// [argp] The options we understand. -static struct argp_option options[] = { - {0, 0, 0, 0, "Positional arguments:" }, - {"REMOTE_ID", 0, 0, OPTION_DOC | OPTION_NO_USAGE, "Livilo Remote ID (1-65535)" }, - {"KEY_ID", 0, 0, OPTION_DOC | OPTION_NO_USAGE, "Livilo Key ID (1-255)" }, - {0, 0, 0, 0, "Options:" }, - {"verbose", 'v', 0, 0, "Produce verbose output" }, - { 0 } -}; - -// [argp] Command-line arguments. -struct arguments { - uint16_t remote_id; - uint8_t key_id; - bool verbose; -} arguments; - -#define DIGILIVOLO_VID 0x16c0 -#define DIGILIVOLO_PID 0x05df -#define DIGILIVOLO_MANUFACTURER_STRING L"digilivolo@yandex.com" -#define DIGILIVOLO_PRODUCT_STRING L"DigiLivolo" - -#define REPORT_ID 0x4c - -#define CMD_SWITCH 0x01 // IN,OUT send Livolo keycode command or send ACK to the host -#define CMD_RDY 0x10 // OUT, device ready command - -// Fallback/example -#ifndef HID_API_MAKE_VERSION -#define HID_API_MAKE_VERSION(mj, mn, p) (((mj) << 24) | ((mn) << 8) | (p)) -#endif -#ifndef HID_API_VERSION -#define HID_API_VERSION HID_API_MAKE_VERSION(HID_API_VERSION_MAJOR, HID_API_VERSION_MINOR, HID_API_VERSION_PATCH) -#endif - -const char* hid_bus_name(hid_bus_type bus_type) { - static const char* const HidBusTypeName[] = { - "Unknown", - "USB", - "Bluetooth", - "I2C", - "SPI", - }; - - if ((int)bus_type < 0) - bus_type = HID_API_BUS_UNKNOWN; - if ((int)bus_type >= (int)(sizeof(HidBusTypeName) / sizeof(HidBusTypeName[0]))) - bus_type = HID_API_BUS_UNKNOWN; - - return HidBusTypeName[bus_type]; -} - -void print_device_details(struct hid_device_info* cur_dev) { - printf("Device 0x%04hx:0x%04hx found:\n", cur_dev->vendor_id, cur_dev->product_id); - printf(" Path: %s\n", cur_dev->path); - printf(" Manufacturer: %ls\n", cur_dev->manufacturer_string); - printf(" Product: %ls\n", cur_dev->product_string); - printf(" Serial Number: %ls\n", cur_dev->serial_number); - printf(" Release: %hx\n", cur_dev->release_number); - printf(" Interface: %d\n", cur_dev->interface_number); - printf(" Usage (page): 0x%hx (0x%hx)\n", cur_dev->usage, cur_dev->usage_page); - printf(" Bus type: %d (%s)\n", cur_dev->bus_type, hid_bus_name(cur_dev->bus_type)); - printf("\n"); -} - -void print_device(struct hid_device_info* cur_dev) { - printf("VID/PID: 0x%04hx:0x%04hx, Product: %ls, Manufacturer: %ls, FW Ver: %d.%02d.\n", \ - cur_dev->vendor_id, cur_dev->product_id, cur_dev->product_string, cur_dev->manufacturer_string, \ - cur_dev->release_number >> 8, cur_dev->release_number & 0xFF); -} - -void print_devices(struct hid_device_info* cur_dev) { - for (; cur_dev; cur_dev = cur_dev->next) { - print_device(cur_dev); - } -} - -struct hid_device_info* find_digilivolo(struct hid_device_info* cur_dev) { - for (; cur_dev; cur_dev = cur_dev->next) { - if ( (wcscmp(cur_dev->manufacturer_string, DIGILIVOLO_MANUFACTURER_STRING) == 0) && \ - (wcscmp(cur_dev->product_string, DIGILIVOLO_PRODUCT_STRING) == 0) ) - return cur_dev; - } - - return NULL; -} - -// [argp] Parse a single option. -static error_t parse_opt(int key, char* arg, struct argp_state* state) -{ - /* Get the input argument from argp_parse, which we - * know is a pointer to our arguments structure. */ - struct arguments* arguments = state->input; - - switch (key) { - case 'v': - arguments->verbose = true; - break; - - case ARGP_KEY_ARG: - if (state->arg_num >= 2) - // Too many arguments. - argp_usage(state); - - char* endptr; - // Convert argument to long - long value = strtol(arg, &endptr, 0); - // Check if it was valid long value - if (*endptr == '\0') { - switch (state->arg_num) { - case 0: - // Out of range - if (value > 65535 || value <= 0) - argp_usage(state); - else - arguments->remote_id = (uint16_t)value; - break; - - case 1: - // Out of range - if (value > 255 || value <= 0) - argp_usage(state); - else - arguments->key_id = (uint8_t)value; - break; - - default: - return ARGP_ERR_UNKNOWN; - } - } - else - // REMOTE_ID or KEY_ID not an unsigned integer - argp_usage(state); - - break; - - case ARGP_KEY_END: - if (state->arg_num < 2) - // Not enough arguments. - argp_usage(state); - break; +#include "digilivolo.h" +#include "args.h" - default: - return ARGP_ERR_UNKNOWN; - } - return 0; -} +#include +#include "usb_func.h" // [argp] Our argp parser. static struct argp argp = { options, parse_opt, args_doc, doc }; @@ -180,7 +41,7 @@ int main(int argc, char* argv[]) hid_device* handle = NULL; int i; - struct hid_device_info *devs, *dev; + struct hid_device_info *devices, *dl_dev; // [argp] Default values. arguments.remote_id = 0; @@ -208,32 +69,37 @@ int main(int argc, char* argv[]) hid_darwin_set_open_exclusive(0); #endif - devs = hid_enumerate(DIGILIVOLO_VID, DIGILIVOLO_PID); - dev = find_digilivolo(devs); - if (!dev) { + devices = hid_enumerate(DIGILIVOLO_VID, DIGILIVOLO_PID); + dl_dev = find_digilivolo(devices); + if (!dl_dev) { printf("ERROR: unable to find device\n"); - if (arguments.verbose) { - printf("All devices with matching VID & PID:\n"); - print_devices(devs); - } + if (arguments.verbose) + if (devices) { + printf("Devices with matching VID/PID (0x%04x:0x%04x), but wrong product or manufacturer string:\n", DIGILIVOLO_VID, DIGILIVOLO_PID); + print_devices(devices); + } + else { + hid_free_enumeration(devices); + devices = hid_enumerate(0, 0); + printf("All enumerated devices, but none of them match VID/PID (0x%04x:0x%04x):\n", DIGILIVOLO_VID, DIGILIVOLO_PID); + print_devices(devices); + } } else { if (arguments.verbose) { printf("Device found: "); - print_device(dev); - printf("Opening device path: %s\n", dev->path); + print_device(dl_dev); + printf("Opening device path: %s\n", dl_dev->path); } - handle = hid_open_path(dev->path); + handle = hid_open_path(dl_dev->path); } - - hid_free_enumeration(devs); + hid_free_enumeration(devices); // Set up the command buffer. memset(buf, 0x00, sizeof(buf)); // Open the device using VID & PID - // handle = hid_open(DIGILIVOLO_VID, DIGILIVOLO_PID, NULL); if (!handle) { printf("ERROR: unable to open device\n"); hid_exit(); diff --git a/software/src/digilivolo.h b/software/src/digilivolo.h new file mode 100644 index 0000000..cd6d1d4 --- /dev/null +++ b/software/src/digilivolo.h @@ -0,0 +1,36 @@ +/* Part of the DigiLivolo control software. + * https://github.com/N-Storm/DigiLivolo/ + * Copyright (c) 2024 GitHub user N-Storm. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#ifndef __digilivolo_h__ +#define __digilivolo_h__ + +#include + +#define DIGILIVOLO_VID 0x16c0 +#define DIGILIVOLO_PID 0x05df +#define DIGILIVOLO_MANUFACTURER_STRING L"digilivolo@yandex.com" +#define DIGILIVOLO_PRODUCT_STRING L"DigiLivolo" + +#define REPORT_ID 0x4c + +#define CMD_SWITCH 0x01 // IN,OUT send Livolo keycode command or send ACK to the host +#define CMD_RDY 0x10 // OUT, device ready command + +#endif // __digilivolo_h__ diff --git a/software/src/git_version.h.in b/software/src/git_version.h.in index 69fc35a..5977afa 100644 --- a/software/src/git_version.h.in +++ b/software/src/git_version.h.in @@ -1,5 +1,22 @@ /* Part of the DigiLivolo control software. - * https://github.com/N-Storm/DigiLivolo/ */ + * https://github.com/N-Storm/DigiLivolo/ + * Copyright (c) 2024 GitHub user N-Storm. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ #ifndef GIT_VERSION_H #define GIT_VERSION_H diff --git a/software/src/usb_func.c b/software/src/usb_func.c new file mode 100644 index 0000000..075f9dd --- /dev/null +++ b/software/src/usb_func.c @@ -0,0 +1,90 @@ +/* Part of the DigiLivolo control software. + * https://github.com/N-Storm/DigiLivolo/ + * Copyright (c) 2024 GitHub user N-Storm. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include +#include +#include +#include +#include +#include + +#include "digilivolo.h" + +#include + +// Fallback/example +#ifndef HID_API_MAKE_VERSION +#define HID_API_MAKE_VERSION(mj, mn, p) (((mj) << 24) | ((mn) << 8) | (p)) +#endif +#ifndef HID_API_VERSION +#define HID_API_VERSION HID_API_MAKE_VERSION(HID_API_VERSION_MAJOR, HID_API_VERSION_MINOR, HID_API_VERSION_PATCH) +#endif + +const char* hid_bus_name(hid_bus_type bus_type) { + static const char* const HidBusTypeName[] = { + "Unknown", + "USB", + "Bluetooth", + "I2C", + "SPI", + }; + + if ((int)bus_type < 0) + bus_type = HID_API_BUS_UNKNOWN; + if ((int)bus_type >= (int)(sizeof(HidBusTypeName) / sizeof(HidBusTypeName[0]))) + bus_type = HID_API_BUS_UNKNOWN; + + return HidBusTypeName[bus_type]; +} + +void print_device_details(struct hid_device_info* cur_dev) { + printf("Device 0x%04hx:0x%04hx found:\n", cur_dev->vendor_id, cur_dev->product_id); + printf(" Path: %s\n", cur_dev->path); + printf(" Manufacturer: %ls\n", cur_dev->manufacturer_string); + printf(" Product: %ls\n", cur_dev->product_string); + printf(" Serial Number: %ls\n", cur_dev->serial_number); + printf(" Release: %hx\n", cur_dev->release_number); + printf(" Interface: %d\n", cur_dev->interface_number); + printf(" Usage (page): 0x%hx (0x%hx)\n", cur_dev->usage, cur_dev->usage_page); + printf(" Bus type: %d (%s)\n", cur_dev->bus_type, hid_bus_name(cur_dev->bus_type)); + printf("\n"); +} + +void print_device(struct hid_device_info* cur_dev) { + printf("VID/PID: 0x%04hx:0x%04hx, Product: %ls, Manufacturer: %ls, FW Ver: %d.%02d.\n", \ + cur_dev->vendor_id, cur_dev->product_id, cur_dev->product_string, cur_dev->manufacturer_string, \ + cur_dev->release_number >> 8, cur_dev->release_number & 0xFF); +} + +void print_devices(struct hid_device_info* cur_dev) { + for (; cur_dev; cur_dev = cur_dev->next) { + print_device(cur_dev); + } +} + +struct hid_device_info* find_digilivolo(struct hid_device_info* cur_dev) { + for (; cur_dev; cur_dev = cur_dev->next) { + if ( (wcscmp(cur_dev->manufacturer_string, DIGILIVOLO_MANUFACTURER_STRING) == 0) && \ + (wcscmp(cur_dev->product_string, DIGILIVOLO_PRODUCT_STRING) == 0) ) + return cur_dev; + } + + return NULL; +} diff --git a/software/src/usb_func.h b/software/src/usb_func.h new file mode 100644 index 0000000..ebdc826 --- /dev/null +++ b/software/src/usb_func.h @@ -0,0 +1,33 @@ +/* Part of the DigiLivolo control software. + * https://github.com/N-Storm/DigiLivolo/ + * Copyright (c) 2024 GitHub user N-Storm. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#ifndef __usb_func_h__ +#define __usb_func_h__ + +#include +#include + +extern const char* hid_bus_name(hid_bus_type bus_type); +extern void print_device_details(struct hid_device_info* cur_dev); +extern void print_device(struct hid_device_info* cur_dev); +extern void print_devices(struct hid_device_info* cur_dev); +extern struct hid_device_info* find_digilivolo(struct hid_device_info* cur_dev); + +#endif // __usb_func_h__