Date: Mon, 28 Oct 2024 19:14:05 GMT From: Li-Wen Hsu <lwhsu@FreeBSD.org> To: ports-committers@FreeBSD.org, dev-commits-ports-all@FreeBSD.org, dev-commits-ports-main@FreeBSD.org Subject: git: ea2855f6a7bb - main - cad/PrusaSlicer: Update to 2.8.1 Message-ID: <202410281914.49SJE5Tl097587@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by lwhsu: URL: https://cgit.FreeBSD.org/ports/commit/?id=ea2855f6a7bbd7555f46e8437b238aafe8ce8dca commit ea2855f6a7bbd7555f46e8437b238aafe8ce8dca Author: Teodor Sigaev <teodorsigaev@gmail.com> AuthorDate: 2024-10-28 19:13:29 +0000 Commit: Li-Wen Hsu <lwhsu@FreeBSD.org> CommitDate: 2024-10-28 19:13:29 +0000 cad/PrusaSlicer: Update to 2.8.1 PR: 282145 --- cad/PrusaSlicer/Makefile | 3 +- cad/PrusaSlicer/distinfo | 6 +- cad/PrusaSlicer/files/patch-CMakeLists.txt | 21 +- ... patch-bundled__deps_avrdude_avrdude_arduino.c} | 4 +- ...tch-bundled__deps_avrdude_avrdude_libavrdude.h} | 4 +- ... => patch-bundled__deps_avrdude_avrdude_main.c} | 4 +- ...t => patch-bundled__deps_hidapi_CMakeLists.txt} | 10 +- .../files/patch-bundled__deps_hidapi_libusb_hid.c | 1517 ++++++++++++++++++++ ...pp => patch-bundled__deps_hints_HintsToPot.cpp} | 4 +- cad/PrusaSlicer/files/patch-src_CMakeLists.txt | 6 +- .../files/patch-src_hidapi_libusb_hid.c | 2 +- .../files/patch-src_libnanosvg_nanosvgrast.h | 20 +- ...libslic3r_Arrange_Core_NFP_NFPConcave__CGAL.cpp | 11 +- .../files/patch-src_libslic3r_CMakeLists.txt | 12 +- .../files/patch-src_libslic3r_CutSurface.cpp | 9 +- .../files/patch-src_libslic3r_EmbossShape.hpp | 4 +- .../files/patch-src_libslic3r_Format_SL1__SVG.cpp | 15 +- .../files/patch-src_libslic3r_Format_SVG.cpp | 11 + ...tch-src_libslic3r_Geometry_VoronoiUtilsCgal.cpp | 4 +- .../files/patch-src_libslic3r_MeshBoolean.cpp | 10 +- .../files/patch-src_libslic3r_NSVGUtils.cpp | 11 + .../files/patch-src_libslic3r_NSVGUtils.hpp | 10 +- .../files/patch-src_libslic3r_Platform.cpp | 10 +- .../patch-src_libslic3r_SupportSpotsGenerator.cpp | 4 +- .../files/patch-src_libslic3r_Triangulation.cpp | 4 +- .../files/patch-src_occt__wrapper_CMakeLists.txt | 10 +- .../files/patch-src_slic3r_CMakeLists.txt | 45 +- .../files/patch-src_slic3r_GUI_BitmapCache.cpp | 6 +- .../files/patch-src_slic3r_GUI_ConfigWizard.cpp | 28 +- .../files/patch-src_slic3r_GUI_ConfigWizard.hpp | 8 +- ...tch-src_slic3r_GUI_DesktopIntegrationDialog.hpp | 4 +- .../files/patch-src_slic3r_GUI_EditGCodeDialog.cpp | 29 + .../files/patch-src_slic3r_GUI_Field.cpp | 4 +- .../files/patch-src_slic3r_GUI_GLCanvas3D.cpp | 4 +- .../files/patch-src_slic3r_GUI_GLTexture.cpp | 8 +- .../files/patch-src_slic3r_GUI_GUI__App.cpp | 52 +- .../patch-src_slic3r_GUI_Gizmos_GLGizmoSVG.cpp | 8 +- .../patch-src_slic3r_GUI_HintNotification.cpp | 16 + .../files/patch-src_slic3r_GUI_IconManager.cpp | 6 +- .../files/patch-src_slic3r_GUI_ImGuiWrapper.cpp | 6 +- .../files/patch-src_slic3r_GUI_InstanceCheck.cpp | 6 +- .../files/patch-src_slic3r_GUI_OptionsGroup.cpp | 6 +- .../patch-src_slic3r_GUI_PhysicalPrinterDialog.cpp | 4 +- .../files/patch-src_slic3r_GUI_Plater.cpp | 19 +- .../files/patch-src_slic3r_GUI_Preferences.cpp | 8 +- .../files/patch-src_slic3r_GUI_Search.cpp | 20 + cad/PrusaSlicer/files/patch-src_slic3r_GUI_Tab.cpp | 6 +- .../files/patch-src_slic3r_GUI_TopBar.cpp | 11 + .../patch-src_slic3r_GUI_UnsavedChangesDialog.cpp | 16 +- .../files/patch-src_slic3r_GUI_UpdateDialogs.cpp | 6 +- ...tch-src_slic3r_GUI_UserAccountCommunication.cpp | 4 +- .../files/patch-src_slic3r_GUI_WipeTowerDialog.cpp | 11 + .../files/patch-src_slic3r_Utils_AppUpdater.cpp | 11 + .../patch-src_slic3r_Utils_FontConfigHelp.hpp | 6 +- .../files/patch-src_slic3r_Utils_WxFontUtils.cpp | 17 +- .../files/patch-tests_libslic3r_test__emboss.cpp | 4 +- 56 files changed, 1900 insertions(+), 205 deletions(-) diff --git a/cad/PrusaSlicer/Makefile b/cad/PrusaSlicer/Makefile index 1a91b82b1bc4..d770864caeb9 100644 --- a/cad/PrusaSlicer/Makefile +++ b/cad/PrusaSlicer/Makefile @@ -1,7 +1,6 @@ PORTNAME= PrusaSlicer DISTVERSIONPREFIX=version_ -DISTVERSION= 2.8.0 -PORTREVISION= 2 +DISTVERSION= 2.8.1 CATEGORIES= cad DIST_SUBDIR= PrusaSlicer diff --git a/cad/PrusaSlicer/distinfo b/cad/PrusaSlicer/distinfo index 59cb1f3b0a83..dc388786dc81 100644 --- a/cad/PrusaSlicer/distinfo +++ b/cad/PrusaSlicer/distinfo @@ -1,3 +1,3 @@ -TIMESTAMP = 1719924925 -SHA256 (PrusaSlicer/prusa3d-PrusaSlicer-version_2.8.0_GH0.tar.gz) = 58d484f85b34d83026f8220bab983f855fbcd72767d0887f21f5cc382e5b19ab -SIZE (PrusaSlicer/prusa3d-PrusaSlicer-version_2.8.0_GH0.tar.gz) = 69806919 +TIMESTAMP = 1728981634 +SHA256 (PrusaSlicer/prusa3d-PrusaSlicer-version_2.8.1_GH0.tar.gz) = f71033dd4e9fdd8e5ac7b5be5803d0d6d09ec0fd87de92b152b3c6bbae04c103 +SIZE (PrusaSlicer/prusa3d-PrusaSlicer-version_2.8.1_GH0.tar.gz) = 69409077 diff --git a/cad/PrusaSlicer/files/patch-CMakeLists.txt b/cad/PrusaSlicer/files/patch-CMakeLists.txt index 44016fce0aca..64eae04effc9 100644 --- a/cad/PrusaSlicer/files/patch-CMakeLists.txt +++ b/cad/PrusaSlicer/files/patch-CMakeLists.txt @@ -1,4 +1,4 @@ ---- CMakeLists.txt.orig 2024-06-27 09:25:47 UTC +--- CMakeLists.txt.orig 2024-09-18 13:39:04 UTC +++ CMakeLists.txt @@ -14,6 +14,7 @@ include(CMakeDependentOption) include("version.inc") @@ -17,7 +17,7 @@ find_package(PkgConfig REQUIRED) if (CMAKE_VERSION VERSION_LESS "3.1") -@@ -264,6 +265,8 @@ if (NOT MSVC AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL +@@ -263,6 +264,8 @@ if (NOT MSVC AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL # On GCC and Clang, no return from a non-void function is a warning only. Here, we make it an error. add_compile_options(-Werror=return-type) @@ -26,7 +26,20 @@ # removes LOTS of extraneous Eigen warnings (GCC only supports it since 6.1) # https://eigen.tuxfamily.org/bz/show_bug.cgi?id=1221 if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 6.0) -@@ -648,8 +651,8 @@ elseif (SLIC3R_FHS) +@@ -371,10 +374,10 @@ set(MINIMUM_BOOST_VERSION "1.66.0") + # boost::process was introduced first in version 1.64.0, + # boost::beast::detail::base64 was introduced first in version 1.66.0 + set(MINIMUM_BOOST_VERSION "1.66.0") +-set(_boost_components "system;filesystem;thread;log;locale;regex;chrono;atomic;date_time;iostreams;nowide") ++set(_boost_components "system;filesystem;thread;log;log_setup;locale;regex;chrono;atomic;date_time;iostreams;nowide") + find_package(Boost ${MINIMUM_BOOST_VERSION} REQUIRED COMPONENTS ${_boost_components}) + +-find_package(Eigen3 3.3.7 REQUIRED) ++find_package(Eigen3 3.3.7 REQUIRED NO_MODULE) + + add_library(boost_libs INTERFACE) + add_library(boost_headeronly INTERFACE) +@@ -636,8 +639,8 @@ elseif (SLIC3R_FHS) install(DIRECTORY ${SLIC3R_RESOURCES_DIR}/ DESTINATION ${SLIC3R_FHS_RESOURCES} PATTERN "*/udev" EXCLUDE ) @@ -37,7 +50,7 @@ foreach(SIZE 32 128 192) install(FILES ${SLIC3R_RESOURCES_DIR}/icons/PrusaSlicer_${SIZE}px.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/${SIZE}x${SIZE}/apps RENAME PrusaSlicer.png -@@ -658,7 +661,8 @@ elseif (SLIC3R_FHS) +@@ -646,7 +649,8 @@ elseif (SLIC3R_FHS) DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/${SIZE}x${SIZE}/apps RENAME PrusaSlicer-gcodeviewer.png ) endforeach() diff --git a/cad/PrusaSlicer/files/patch-src_avrdude_arduino.c b/cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_arduino.c similarity index 52% rename from cad/PrusaSlicer/files/patch-src_avrdude_arduino.c rename to cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_arduino.c index c7c282d53832..9aad1b125e9a 100644 --- a/cad/PrusaSlicer/files/patch-src_avrdude_arduino.c +++ b/cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_arduino.c @@ -1,5 +1,5 @@ ---- src/avrdude/arduino.c.orig 2023-07-25 13:23:52 UTC -+++ src/avrdude/arduino.c +--- bundled_deps/avrdude/avrdude/arduino.c.orig 2024-09-18 13:39:04 UTC ++++ bundled_deps/avrdude/avrdude/arduino.c @@ -28,6 +28,7 @@ #include "ac_cfg.h" diff --git a/cad/PrusaSlicer/files/patch-src_avrdude_libavrdude.h b/cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_libavrdude.h similarity index 63% rename from cad/PrusaSlicer/files/patch-src_avrdude_libavrdude.h rename to cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_libavrdude.h index ed7c44e0e5bc..6d03bb0bc90d 100644 --- a/cad/PrusaSlicer/files/patch-src_avrdude_libavrdude.h +++ b/cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_libavrdude.h @@ -1,5 +1,5 @@ ---- src/avrdude/libavrdude.h.orig 2022-09-06 07:09:19 UTC -+++ src/avrdude/libavrdude.h +--- bundled_deps/avrdude/avrdude/libavrdude.h.orig 2024-09-18 13:39:04 UTC ++++ bundled_deps/avrdude/avrdude/libavrdude.h @@ -950,6 +950,8 @@ int read_config_builtin(); // Header file for alloca() #if defined(WIN32NATIVE) diff --git a/cad/PrusaSlicer/files/patch-src_avrdude_main.c b/cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_main.c similarity index 84% rename from cad/PrusaSlicer/files/patch-src_avrdude_main.c rename to cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_main.c index 57f18516cc78..a6912d0091ef 100644 --- a/cad/PrusaSlicer/files/patch-src_avrdude_main.c +++ b/cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_main.c @@ -1,5 +1,5 @@ ---- src/avrdude/main.c.orig 2022-09-06 07:09:19 UTC -+++ src/avrdude/main.c +--- bundled_deps/avrdude/avrdude/main.c.orig 2024-09-18 13:39:04 UTC ++++ bundled_deps/avrdude/avrdude/main.c @@ -806,7 +806,7 @@ int avrdude_main(int argc, char * argv []) avrdude_message(MSG_NOTICE, "\n%s: Version %s, compiled on %s at %s\n" "%sCopyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/\n" diff --git a/cad/PrusaSlicer/files/patch-src_hidapi_CMakeLists.txt b/cad/PrusaSlicer/files/patch-bundled__deps_hidapi_CMakeLists.txt similarity index 66% rename from cad/PrusaSlicer/files/patch-src_hidapi_CMakeLists.txt rename to cad/PrusaSlicer/files/patch-bundled__deps_hidapi_CMakeLists.txt index 282d616f9efa..a8f856cd3cf2 100644 --- a/cad/PrusaSlicer/files/patch-src_hidapi_CMakeLists.txt +++ b/cad/PrusaSlicer/files/patch-bundled__deps_hidapi_CMakeLists.txt @@ -1,5 +1,5 @@ ---- src/hidapi/CMakeLists.txt.orig 2022-09-06 07:09:19 UTC -+++ src/hidapi/CMakeLists.txt +--- bundled_deps/hidapi/CMakeLists.txt.orig 2024-09-18 13:39:04 UTC ++++ bundled_deps/hidapi/CMakeLists.txt @@ -1,8 +1,9 @@ - if (WIN32) @@ -11,10 +11,10 @@ else () # Assume Linux or Unix other than Mac OS set(HIDAPI_IMPL linux/hid.c) -@@ -16,4 +17,6 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Linux") +@@ -16,4 +17,6 @@ target_link_libraries(hidapi PRIVATE dl) # Don't link the udev library, as there are two versions out there (libudev.so.0, libudev.so.1), so they are linked explicitely. # target_link_libraries(hidapi udev) - target_link_libraries(hidapi dl) + target_link_libraries(hidapi PRIVATE dl) +elseif (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") -+ target_link_libraries(hidapi usb iconv) ++ target_link_libraries(hidapi usb iconv) endif() diff --git a/cad/PrusaSlicer/files/patch-bundled__deps_hidapi_libusb_hid.c b/cad/PrusaSlicer/files/patch-bundled__deps_hidapi_libusb_hid.c new file mode 100644 index 000000000000..df486242573f --- /dev/null +++ b/cad/PrusaSlicer/files/patch-bundled__deps_hidapi_libusb_hid.c @@ -0,0 +1,1517 @@ +--- bundled_deps/hidapi/libusb/hid.c.orig 2024-10-15 09:17:30 UTC ++++ bundled_deps/hidapi/libusb/hid.c +@@ -0,0 +1,1514 @@ ++/******************************************************* ++ HIDAPI - Multi-Platform library for ++ communication with HID devices. ++ ++ Alan Ott ++ Signal 11 Software ++ ++ 8/22/2009 ++ Linux Version - 6/2/2010 ++ Libusb Version - 8/13/2010 ++ FreeBSD Version - 11/1/2011 ++ ++ Copyright 2009, All Rights Reserved. ++ ++ At the discretion of the user of this library, ++ this software may be licensed under the terms of the ++ GNU General Public License v3, a BSD-Style license, or the ++ original HIDAPI license as outlined in the LICENSE.txt, ++ LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt ++ files located at the root of the source distribution. ++ These files may also be found in the public source ++ code repository located at: ++ http://github.com/signal11/hidapi . ++********************************************************/ ++ ++#define _GNU_SOURCE /* needed for wcsdup() before glibc 2.10 */ ++ ++/* C */ ++#include <stdio.h> ++#include <string.h> ++#include <stdlib.h> ++#include <ctype.h> ++#include <locale.h> ++#include <errno.h> ++ ++/* Unix */ ++#include <unistd.h> ++#include <sys/types.h> ++#include <sys/stat.h> ++#include <sys/ioctl.h> ++#include <sys/utsname.h> ++#include <fcntl.h> ++#include <pthread.h> ++#include <wchar.h> ++ ++/* GNU / LibUSB */ ++#include <libusb.h> ++#ifndef __ANDROID__ ++#include <iconv.h> ++#endif ++ ++#include "hidapi.h" ++ ++#ifdef __ANDROID__ ++ ++/* Barrier implementation because Android/Bionic don't have pthread_barrier. ++ This implementation came from Brent Priddy and was posted on ++ StackOverflow. It is used with his permission. */ ++typedef int pthread_barrierattr_t; ++typedef struct pthread_barrier { ++ pthread_mutex_t mutex; ++ pthread_cond_t cond; ++ int count; ++ int trip_count; ++} pthread_barrier_t; ++ ++static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count) ++{ ++ if(count == 0) { ++ errno = EINVAL; ++ return -1; ++ } ++ ++ if(pthread_mutex_init(&barrier->mutex, 0) < 0) { ++ return -1; ++ } ++ if(pthread_cond_init(&barrier->cond, 0) < 0) { ++ pthread_mutex_destroy(&barrier->mutex); ++ return -1; ++ } ++ barrier->trip_count = count; ++ barrier->count = 0; ++ ++ return 0; ++} ++ ++static int pthread_barrier_destroy(pthread_barrier_t *barrier) ++{ ++ pthread_cond_destroy(&barrier->cond); ++ pthread_mutex_destroy(&barrier->mutex); ++ return 0; ++} ++ ++static int pthread_barrier_wait(pthread_barrier_t *barrier) ++{ ++ pthread_mutex_lock(&barrier->mutex); ++ ++(barrier->count); ++ if(barrier->count >= barrier->trip_count) ++ { ++ barrier->count = 0; ++ pthread_cond_broadcast(&barrier->cond); ++ pthread_mutex_unlock(&barrier->mutex); ++ return 1; ++ } ++ else ++ { ++ pthread_cond_wait(&barrier->cond, &(barrier->mutex)); ++ pthread_mutex_unlock(&barrier->mutex); ++ return 0; ++ } ++} ++ ++#endif ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#ifdef DEBUG_PRINTF ++#define LOG(...) fprintf(stderr, __VA_ARGS__) ++#else ++#define LOG(...) do {} while (0) ++#endif ++ ++#ifndef __FreeBSD__ ++#define DETACH_KERNEL_DRIVER ++#endif ++ ++/* Uncomment to enable the retrieval of Usage and Usage Page in ++hid_enumerate(). Warning, on platforms different from FreeBSD ++this is very invasive as it requires the detach ++and re-attach of the kernel driver. See comments inside hid_enumerate(). ++libusb HIDAPI programs are encouraged to use the interface number ++instead to differentiate between interfaces on a composite HID device. */ ++/*#define INVASIVE_GET_USAGE*/ ++ ++/* Linked List of input reports received from the device. */ ++struct input_report { ++ uint8_t *data; ++ size_t len; ++ struct input_report *next; ++}; ++ ++ ++struct hid_device_ { ++ /* Handle to the actual device. */ ++ libusb_device_handle *device_handle; ++ ++ /* Endpoint information */ ++ int input_endpoint; ++ int output_endpoint; ++ int input_ep_max_packet_size; ++ ++ /* The interface number of the HID */ ++ int interface; ++ ++ /* Indexes of Strings */ ++ int manufacturer_index; ++ int product_index; ++ int serial_index; ++ ++ /* Whether blocking reads are used */ ++ int blocking; /* boolean */ ++ ++ /* Read thread objects */ ++ pthread_t thread; ++ pthread_mutex_t mutex; /* Protects input_reports */ ++ pthread_cond_t condition; ++ pthread_barrier_t barrier; /* Ensures correct startup sequence */ ++ int shutdown_thread; ++ int cancelled; ++ struct libusb_transfer *transfer; ++ ++ /* List of received input reports. */ ++ struct input_report *input_reports; ++}; ++ ++static libusb_context *usb_context = NULL; ++ ++uint16_t get_usb_code_for_current_locale(void); ++static int return_data(hid_device *dev, unsigned char *data, size_t length); ++ ++static hid_device *new_hid_device(void) ++{ ++ hid_device *dev = calloc(1, sizeof(hid_device)); ++ dev->blocking = 1; ++ ++ pthread_mutex_init(&dev->mutex, NULL); ++ pthread_cond_init(&dev->condition, NULL); ++ pthread_barrier_init(&dev->barrier, NULL, 2); ++ ++ return dev; ++} ++ ++static void free_hid_device(hid_device *dev) ++{ ++ /* Clean up the thread objects */ ++ pthread_barrier_destroy(&dev->barrier); ++ pthread_cond_destroy(&dev->condition); ++ pthread_mutex_destroy(&dev->mutex); ++ ++ /* Free the device itself */ ++ free(dev); ++} ++ ++#if 0 ++/*TODO: Implement this funciton on hidapi/libusb.. */ ++static void register_error(hid_device *dev, const char *op) ++{ ++ ++} ++#endif ++ ++#ifdef INVASIVE_GET_USAGE ++/* Get bytes from a HID Report Descriptor. ++ Only call with a num_bytes of 0, 1, 2, or 4. */ ++static uint32_t get_bytes(uint8_t *rpt, size_t len, size_t num_bytes, size_t cur) ++{ ++ /* Return if there aren't enough bytes. */ ++ if (cur + num_bytes >= len) ++ return 0; ++ ++ if (num_bytes == 0) ++ return 0; ++ else if (num_bytes == 1) { ++ return rpt[cur+1]; ++ } ++ else if (num_bytes == 2) { ++ return (rpt[cur+2] * 256 + rpt[cur+1]); ++ } ++ else if (num_bytes == 4) { ++ return (rpt[cur+4] * 0x01000000 + ++ rpt[cur+3] * 0x00010000 + ++ rpt[cur+2] * 0x00000100 + ++ rpt[cur+1] * 0x00000001); ++ } ++ else ++ return 0; ++} ++ ++/* Retrieves the device's Usage Page and Usage from the report ++ descriptor. The algorithm is simple, as it just returns the first ++ Usage and Usage Page that it finds in the descriptor. ++ The return value is 0 on success and -1 on failure. */ ++static int get_usage(uint8_t *report_descriptor, size_t size, ++ unsigned short *usage_page, unsigned short *usage) ++{ ++ unsigned int i = 0; ++ int size_code; ++ int data_len, key_size; ++ int usage_found = 0, usage_page_found = 0; ++ ++ while (i < size) { ++ int key = report_descriptor[i]; ++ int key_cmd = key & 0xfc; ++ ++ //printf("key: %02hhx\n", key); ++ ++ if ((key & 0xf0) == 0xf0) { ++ /* This is a Long Item. The next byte contains the ++ length of the data section (value) for this key. ++ See the HID specification, version 1.11, section ++ 6.2.2.3, titled "Long Items." */ ++ if (i+1 < size) ++ data_len = report_descriptor[i+1]; ++ else ++ data_len = 0; /* malformed report */ ++ key_size = 3; ++ } ++ else { ++ /* This is a Short Item. The bottom two bits of the ++ key contain the size code for the data section ++ (value) for this key. Refer to the HID ++ specification, version 1.11, section 6.2.2.2, ++ titled "Short Items." */ ++ size_code = key & 0x3; ++ switch (size_code) { ++ case 0: ++ case 1: ++ case 2: ++ data_len = size_code; ++ break; ++ case 3: ++ data_len = 4; ++ break; ++ default: ++ /* Can't ever happen since size_code is & 0x3 */ ++ data_len = 0; ++ break; ++ }; ++ key_size = 1; ++ } ++ ++ if (key_cmd == 0x4) { ++ *usage_page = get_bytes(report_descriptor, size, data_len, i); ++ usage_page_found = 1; ++ //printf("Usage Page: %x\n", (uint32_t)*usage_page); ++ } ++ if (key_cmd == 0x8) { ++ *usage = get_bytes(report_descriptor, size, data_len, i); ++ usage_found = 1; ++ //printf("Usage: %x\n", (uint32_t)*usage); ++ } ++ ++ if (usage_page_found && usage_found) ++ return 0; /* success */ ++ ++ /* Skip over this key and it's associated data */ ++ i += data_len + key_size; ++ } ++ ++ return -1; /* failure */ ++} ++#endif /* INVASIVE_GET_USAGE */ ++ ++#if defined(__FreeBSD__) && __FreeBSD__ < 10 ++/* The libusb version included in FreeBSD < 10 doesn't have this function. In ++ mainline libusb, it's inlined in libusb.h. This function will bear a striking ++ resemblance to that one, because there's about one way to code it. ++ ++ Note that the data parameter is Unicode in UTF-16LE encoding. ++ Return value is the number of bytes in data, or LIBUSB_ERROR_*. ++ */ ++static inline int libusb_get_string_descriptor(libusb_device_handle *dev, ++ uint8_t descriptor_index, uint16_t lang_id, ++ unsigned char *data, int length) ++{ ++ return libusb_control_transfer(dev, ++ LIBUSB_ENDPOINT_IN | 0x0, /* Endpoint 0 IN */ ++ LIBUSB_REQUEST_GET_DESCRIPTOR, ++ (LIBUSB_DT_STRING << 8) | descriptor_index, ++ lang_id, data, (uint16_t) length, 1000); ++} ++ ++#endif ++ ++ ++/* Get the first language the device says it reports. This comes from ++ USB string #0. */ ++static uint16_t get_first_language(libusb_device_handle *dev) ++{ ++ uint16_t buf[32]; ++ int len; ++ ++ /* Get the string from libusb. */ ++ len = libusb_get_string_descriptor(dev, ++ 0x0, /* String ID */ ++ 0x0, /* Language */ ++ (unsigned char*)buf, ++ sizeof(buf)); ++ if (len < 4) ++ return 0x0; ++ ++ return buf[1]; /* First two bytes are len and descriptor type. */ ++} ++ ++static int is_language_supported(libusb_device_handle *dev, uint16_t lang) ++{ ++ uint16_t buf[32]; ++ int len; ++ int i; ++ ++ /* Get the string from libusb. */ ++ len = libusb_get_string_descriptor(dev, ++ 0x0, /* String ID */ ++ 0x0, /* Language */ ++ (unsigned char*)buf, ++ sizeof(buf)); ++ if (len < 4) ++ return 0x0; ++ ++ ++ len /= 2; /* language IDs are two-bytes each. */ ++ /* Start at index 1 because there are two bytes of protocol data. */ ++ for (i = 1; i < len; i++) { ++ if (buf[i] == lang) ++ return 1; ++ } ++ ++ return 0; ++} ++ ++ ++/* This function returns a newly allocated wide string containing the USB ++ device string numbered by the index. The returned string must be freed ++ by using free(). */ ++static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx) ++{ ++ char buf[512]; ++ int len; ++ wchar_t *str = NULL; ++ ++#ifndef __ANDROID__ /* we don't use iconv on Android */ ++ wchar_t wbuf[256]; ++ /* iconv variables */ ++ iconv_t ic; ++ size_t inbytes; ++ size_t outbytes; ++ size_t res; ++#ifdef __FreeBSD__ ++ const char *inptr; ++#else ++ char *inptr; ++#endif ++ char *outptr; ++#endif ++ ++ /* Determine which language to use. */ ++ uint16_t lang; ++ lang = get_usb_code_for_current_locale(); ++ if (!is_language_supported(dev, lang)) ++ lang = get_first_language(dev); ++ ++ /* Get the string from libusb. */ ++ len = libusb_get_string_descriptor(dev, ++ idx, ++ lang, ++ (unsigned char*)buf, ++ sizeof(buf)); ++ if (len < 0) ++ return NULL; ++ ++#ifdef __ANDROID__ ++ ++ /* Bionic does not have iconv support nor wcsdup() function, so it ++ has to be done manually. The following code will only work for ++ code points that can be represented as a single UTF-16 character, ++ and will incorrectly convert any code points which require more ++ than one UTF-16 character. ++ ++ Skip over the first character (2-bytes). */ ++ len -= 2; ++ str = malloc((len / 2 + 1) * sizeof(wchar_t)); ++ int i; ++ for (i = 0; i < len / 2; i++) { ++ str[i] = buf[i * 2 + 2] | (buf[i * 2 + 3] << 8); ++ } ++ str[len / 2] = 0x00000000; ++ ++#else ++ ++ /* buf does not need to be explicitly NULL-terminated because ++ it is only passed into iconv() which does not need it. */ ++ ++ /* Initialize iconv. */ ++ ic = iconv_open("WCHAR_T", "UTF-16LE"); ++ if (ic == (iconv_t)-1) { ++ LOG("iconv_open() failed\n"); ++ return NULL; ++ } ++ ++ /* Convert to native wchar_t (UTF-32 on glibc/BSD systems). ++ Skip the first character (2-bytes). */ ++ inptr = buf+2; ++ inbytes = len-2; ++ outptr = (char*) wbuf; ++ outbytes = sizeof(wbuf); ++ res = iconv(ic, &inptr, &inbytes, &outptr, &outbytes); ++ if (res == (size_t)-1) { ++ LOG("iconv() failed\n"); ++ goto err; ++ } ++ ++ /* Write the terminating NULL. */ ++ wbuf[sizeof(wbuf)/sizeof(wbuf[0])-1] = 0x00000000; ++ if (outbytes >= sizeof(wbuf[0])) ++ *((wchar_t*)outptr) = 0x00000000; ++ ++ /* Allocate and copy the string. */ ++ str = wcsdup(wbuf); ++ ++err: ++ iconv_close(ic); ++ ++#endif ++ ++ return str; ++} ++ ++static char *make_path(libusb_device *dev, int interface_number) ++{ ++ char str[64]; ++ snprintf(str, sizeof(str), "%04x:%04x:%02x", ++ libusb_get_bus_number(dev), ++ libusb_get_device_address(dev), ++ interface_number); ++ str[sizeof(str)-1] = '\0'; ++ ++ return strdup(str); ++} ++ ++ ++int HID_API_EXPORT hid_init(void) ++{ ++ if (!usb_context) { ++ const char *locale; ++ ++ /* Init Libusb */ ++ if (libusb_init(&usb_context)) ++ return -1; ++ ++ /* Set the locale if it's not set. */ ++ locale = setlocale(LC_CTYPE, NULL); ++ if (!locale) ++ setlocale(LC_CTYPE, ""); ++ } ++ ++ return 0; ++} ++ ++int HID_API_EXPORT hid_exit(void) ++{ ++ if (usb_context) { ++ libusb_exit(usb_context); ++ usb_context = NULL; ++ } ++ ++ return 0; ++} ++ ++struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) ++{ ++ libusb_device **devs; ++ libusb_device *dev; ++ libusb_device_handle *handle; ++ ssize_t num_devs; ++ int i = 0; ++ ++ struct hid_device_info *root = NULL; /* return object */ ++ struct hid_device_info *cur_dev = NULL; ++ ++ if(hid_init() < 0) ++ return NULL; ++ ++ num_devs = libusb_get_device_list(usb_context, &devs); ++ if (num_devs < 0) ++ return NULL; ++ while ((dev = devs[i++]) != NULL) { ++ struct libusb_device_descriptor desc; ++ struct libusb_config_descriptor *conf_desc = NULL; ++ int j, k; ++ int interface_num = 0; ++ ++ int res = libusb_get_device_descriptor(dev, &desc); ++ unsigned short dev_vid = desc.idVendor; ++ unsigned short dev_pid = desc.idProduct; ++ ++ res = libusb_get_active_config_descriptor(dev, &conf_desc); ++ if (res < 0) ++ libusb_get_config_descriptor(dev, 0, &conf_desc); ++ if (conf_desc) { ++ for (j = 0; j < conf_desc->bNumInterfaces; j++) { ++ const struct libusb_interface *intf = &conf_desc->interface[j]; ++ for (k = 0; k < intf->num_altsetting; k++) { ++ const struct libusb_interface_descriptor *intf_desc; ++ intf_desc = &intf->altsetting[k]; ++ if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) { ++ interface_num = intf_desc->bInterfaceNumber; ++ ++ /* Check the VID/PID against the arguments */ ++ if ((vendor_id == 0x0 || vendor_id == dev_vid) && ++ (product_id == 0x0 || product_id == dev_pid)) { ++ struct hid_device_info *tmp; ++ ++ /* VID/PID match. Create the record. */ ++ tmp = calloc(1, sizeof(struct hid_device_info)); ++ if (cur_dev) { ++ cur_dev->next = tmp; ++ } ++ else { ++ root = tmp; ++ } ++ cur_dev = tmp; ++ ++ /* Fill out the record */ ++ cur_dev->next = NULL; ++ cur_dev->path = make_path(dev, interface_num); ++ ++ res = libusb_open(dev, &handle); ++ ++ if (res >= 0) { ++ /* Serial Number */ ++ if (desc.iSerialNumber > 0) ++ cur_dev->serial_number = ++ get_usb_string(handle, desc.iSerialNumber); ++ ++ /* Manufacturer and Product strings */ ++ if (desc.iManufacturer > 0) ++ cur_dev->manufacturer_string = ++ get_usb_string(handle, desc.iManufacturer); ++ if (desc.iProduct > 0) ++ cur_dev->product_string = ++ get_usb_string(handle, desc.iProduct); ++ ++#ifdef INVASIVE_GET_USAGE ++{ ++ /* ++ This section is removed because it is too ++ invasive on the system. Getting a Usage Page ++ and Usage requires parsing the HID Report ++ descriptor. Getting a HID Report descriptor ++ involves claiming the interface. Claiming the ++ interface involves detaching the kernel driver. ++ Detaching the kernel driver is hard on the system ++ because it will unclaim interfaces (if another ++ app has them claimed) and the re-attachment of ++ the driver will sometimes change /dev entry names. ++ It is for these reasons that this section is ++ #if 0. For composite devices, use the interface ++ field in the hid_device_info struct to distinguish ++ between interfaces. */ ++ unsigned char data[256]; ++#ifdef DETACH_KERNEL_DRIVER ++ int detached = 0; ++ /* Usage Page and Usage */ ++ res = libusb_kernel_driver_active(handle, interface_num); ++ if (res == 1) { ++ res = libusb_detach_kernel_driver(handle, interface_num); ++ if (res < 0) ++ LOG("Couldn't detach kernel driver, even though a kernel driver was attached."); ++ else ++ detached = 1; ++ } ++#endif ++ res = libusb_claim_interface(handle, interface_num); ++ if (res >= 0) { ++ /* Get the HID Report Descriptor. */ ++ res = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_RECIPIENT_INTERFACE, LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_REPORT << 8)|interface_num, 0, data, sizeof(data), 5000); ++ if (res >= 0) { ++ unsigned short page=0, usage=0; ++ /* Parse the usage and usage page ++ out of the report descriptor. */ ++ get_usage(data, res, &page, &usage); ++ cur_dev->usage_page = page; ++ cur_dev->usage = usage; ++ } ++ else ++ LOG("libusb_control_transfer() for getting the HID report failed with %d\n", res); ++ ++ /* Release the interface */ ++ res = libusb_release_interface(handle, interface_num); ++ if (res < 0) ++ LOG("Can't release the interface.\n"); ++ } ++ else ++ LOG("Can't claim interface %d\n", res); ++#ifdef DETACH_KERNEL_DRIVER ++ /* Re-attach kernel driver if necessary. */ ++ if (detached) { ++ res = libusb_attach_kernel_driver(handle, interface_num); ++ if (res < 0) ++ LOG("Couldn't re-attach kernel driver.\n"); ++ } ++#endif ++} ++#endif /* INVASIVE_GET_USAGE */ ++ ++ libusb_close(handle); ++ } ++ /* VID/PID */ ++ cur_dev->vendor_id = dev_vid; ++ cur_dev->product_id = dev_pid; ++ ++ /* Release Number */ ++ cur_dev->release_number = desc.bcdDevice; ++ ++ /* Interface Number */ ++ cur_dev->interface_number = interface_num; ++ } ++ } ++ } /* altsettings */ ++ } /* interfaces */ ++ libusb_free_config_descriptor(conf_desc); ++ } ++ } ++ ++ libusb_free_device_list(devs, 1); ++ ++ return root; ++} ++ ++void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) ++{ ++ struct hid_device_info *d = devs; ++ while (d) { ++ struct hid_device_info *next = d->next; ++ free(d->path); ++ free(d->serial_number); ++ free(d->manufacturer_string); ++ free(d->product_string); ++ free(d); ++ d = next; ++ } ++} ++ ++hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) ++{ ++ struct hid_device_info *devs, *cur_dev; ++ const char *path_to_open = NULL; ++ hid_device *handle = NULL; ++ ++ devs = hid_enumerate(vendor_id, product_id); ++ cur_dev = devs; ++ while (cur_dev) { ++ if (cur_dev->vendor_id == vendor_id && ++ cur_dev->product_id == product_id) { ++ if (serial_number) { ++ if (cur_dev->serial_number && ++ wcscmp(serial_number, cur_dev->serial_number) == 0) { ++ path_to_open = cur_dev->path; ++ break; ++ } ++ } ++ else { ++ path_to_open = cur_dev->path; ++ break; ++ } ++ } ++ cur_dev = cur_dev->next; ++ } ++ ++ if (path_to_open) { ++ /* Open the device */ ++ handle = hid_open_path(path_to_open); ++ } ++ ++ hid_free_enumeration(devs); ++ ++ return handle; ++} ++ ++static void read_callback(struct libusb_transfer *transfer) ++{ ++ hid_device *dev = transfer->user_data; ++ int res; ++ ++ if (transfer->status == LIBUSB_TRANSFER_COMPLETED) { ++ ++ struct input_report *rpt = malloc(sizeof(*rpt)); ++ rpt->data = malloc(transfer->actual_length); ++ memcpy(rpt->data, transfer->buffer, transfer->actual_length); ++ rpt->len = transfer->actual_length; ++ rpt->next = NULL; ++ ++ pthread_mutex_lock(&dev->mutex); ++ ++ /* Attach the new report object to the end of the list. */ ++ if (dev->input_reports == NULL) { ++ /* The list is empty. Put it at the root. */ ++ dev->input_reports = rpt; ++ pthread_cond_signal(&dev->condition); ++ } ++ else { ++ /* Find the end of the list and attach. */ ++ struct input_report *cur = dev->input_reports; ++ int num_queued = 0; ++ while (cur->next != NULL) { ++ cur = cur->next; *** 2114 LINES SKIPPED ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202410281914.49SJE5Tl097587>