summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cad/PrusaSlicer/Makefile12
-rw-r--r--cad/PrusaSlicer/distinfo6
-rw-r--r--cad/PrusaSlicer/files/hid.c1514
-rw-r--r--cad/PrusaSlicer/files/patch-CMakeLists.txt57
-rw-r--r--cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_arduino.c2
-rw-r--r--cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_libavrdude.h2
-rw-r--r--cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_main.c2
-rw-r--r--cad/PrusaSlicer/files/patch-bundled__deps_hidapi_CMakeLists.txt2
-rw-r--r--cad/PrusaSlicer/files/patch-bundled__deps_hidapi_libusb_hid.c1517
-rw-r--r--cad/PrusaSlicer/files/patch-bundled__deps_hints_HintsToPot.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-cmake_modules_FindOpenVDB.cmake12
-rw-r--r--cad/PrusaSlicer/files/patch-src_CMakeLists.txt15
-rw-r--r--cad/PrusaSlicer/files/patch-src_hidapi_libusb_hid.c1517
-rw-r--r--cad/PrusaSlicer/files/patch-src_libslic3r_Arrange_Core_DataStoreTraits.hpp11
-rw-r--r--cad/PrusaSlicer/files/patch-src_libslic3r_Arrange_Core_NFP_NFPConcave__CGAL.cpp12
-rw-r--r--cad/PrusaSlicer/files/patch-src_libslic3r_CMakeLists.txt4
-rw-r--r--cad/PrusaSlicer/files/patch-src_libslic3r_CutSurface.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_libslic3r_Format_STEP.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_libslic3r_GCodeSender.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_libslic3r_Geometry_VoronoiUtilsCgal.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_libslic3r_MeshBoolean.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_libslic3r_Platform.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_libslic3r_Platform.hpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_libslic3r_SupportSpotsGenerator.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_libslic3r_Triangulation.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_libslic3r_Utils_DirectoriesUtils.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_occt__wrapper_CMakeLists.txt2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_CMakeLists.txt67
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_Config_Snapshot.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_Config_Version.cpp10
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_ConfigWizard.cpp14
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_ConfigWizard.hpp4
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_DesktopIntegrationDialog.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_DesktopIntegrationDialog.hpp4
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_EditGCodeDialog.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_ExtraRenderers.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_Field.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_FirmwareDialog.cpp20
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_GLCanvas3D.cpp16
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI.hpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI__App.cpp30
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI__Factories.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI__ObjectLayers.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI__Utils.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_HintNotification.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_InstanceCheck.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_InstanceCheck.hpp4
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_KBShortcutsDialog.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_Mouse3DController.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_OpenGLManager.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_OptionsGroup.cpp6
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_PhysicalPrinterDialog.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_Plater.cpp27
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_Preferences.cpp8
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_PresetComboBoxes.cpp4
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_PresetComboBoxes.hpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_PrintHostDialogs.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_RemovableDriveManager.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_Search.cpp11
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_Tab.cpp10
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_TopBar.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_UnsavedChangesDialog.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_UnsavedChangesDialog.hpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_UpdateDialogs.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_UserAccountCommunication.cpp4
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_WipeTowerDialog.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_wxExtensions.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_GUI_wxExtensions.hpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_Utils_AppUpdater.cpp4
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_Utils_Bonjour.cpp47
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_Utils_Bonjour.hpp61
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_Utils_FontConfigHelp.hpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_Utils_Serial.cpp30
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_Utils_Serial.hpp13
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_Utils_TCPConsole.cpp11
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_Utils_WifiScanner.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-src_slic3r_Utils_WxFontUtils.cpp2
-rw-r--r--cad/PrusaSlicer/files/patch-tests_fff__print_test__data.cpp6
-rw-r--r--cad/PrusaSlicer/files/patch-tests_libslic3r_test__emboss.cpp4
-rw-r--r--cad/PrusaSlicer/pkg-plist1088
81 files changed, 2965 insertions, 3305 deletions
diff --git a/cad/PrusaSlicer/Makefile b/cad/PrusaSlicer/Makefile
index eee97d4a0f6a..08352f6c206d 100644
--- a/cad/PrusaSlicer/Makefile
+++ b/cad/PrusaSlicer/Makefile
@@ -1,7 +1,6 @@
PORTNAME= PrusaSlicer
DISTVERSIONPREFIX=version_
-DISTVERSION= 2.8.1
-PORTREVISION= 7
+DISTVERSION= 2.9.0
CATEGORIES= cad
DIST_SUBDIR= PrusaSlicer
@@ -12,12 +11,13 @@ WWW= https://www.prusa3d.com/prusaslicer/
LICENSE= AGPLv3
LICENSE_FILE= ${WRKSRC}/LICENSE
-BROKEN= fails to build with Boost>=1.87
+#BROKEN= fails to build with Boost>=1.87
BUILD_DEPENDS= cereal>=1.3.0.10:devel/cereal \
cgal>=5.0.2:math/cgal \
opencascade>=7.7.0:cad/opencascade \
- libbgcode>=0.2.0_1:cad/libbgcode
+ libbgcode>=0.2.0_1:cad/libbgcode \
+ hidapi>=0.14.0:comms/hidapi
LIB_DEPENDS+= libbgcode_convert.so:cad/libbgcode \
libbgcode_binarize.so:cad/libbgcode \
@@ -64,5 +64,7 @@ CMAKE_ARGS+= -DwxWidgets_CONFIG_EXECUTABLE="${WX_CONFIG}" \
-DSLIC3R_BUILD_TESTS=OFF
PORTDATA= *
-
+post-patch:
+ ${MKDIR} ${WRKSRC}/bundled_deps/hidapi/libusb
+ ${CP} ${FILESDIR}/hid.c ${WRKSRC}/bundled_deps/hidapi/libusb/hid.c
.include <bsd.port.mk>
diff --git a/cad/PrusaSlicer/distinfo b/cad/PrusaSlicer/distinfo
index dc388786dc81..f0d226c67fee 100644
--- a/cad/PrusaSlicer/distinfo
+++ b/cad/PrusaSlicer/distinfo
@@ -1,3 +1,3 @@
-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
+TIMESTAMP = 1739556829
+SHA256 (PrusaSlicer/prusa3d-PrusaSlicer-version_2.9.0_GH0.tar.gz) = 515a41dea3bcd2fcadb713b22e4eccfd46fbb7a7ca8dad8440e7b5e29fbbc206
+SIZE (PrusaSlicer/prusa3d-PrusaSlicer-version_2.9.0_GH0.tar.gz) = 70604482
diff --git a/cad/PrusaSlicer/files/hid.c b/cad/PrusaSlicer/files/hid.c
new file mode 100644
index 000000000000..8cd5e3dca02e
--- /dev/null
+++ b/cad/PrusaSlicer/files/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;
+ num_queued++;
+ }
+ cur->next = rpt;
+
+ /* Pop one off if we've reached 30 in the queue. This
+ way we don't grow forever if the user never reads
+ anything from the device. */
+ if (num_queued > 30) {
+ return_data(dev, NULL, 0);
+ }
+ }
+ pthread_mutex_unlock(&dev->mutex);
+ }
+ else if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
+ dev->shutdown_thread = 1;
+ dev->cancelled = 1;
+ return;
+ }
+ else if (transfer->status == LIBUSB_TRANSFER_NO_DEVICE) {
+ dev->shutdown_thread = 1;
+ dev->cancelled = 1;
+ return;
+ }
+ else if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT) {
+ //LOG("Timeout (normal)\n");
+ }
+ else {
+ LOG("Unknown transfer code: %d\n", transfer->status);
+ }
+
+ /* Re-submit the transfer object. */
+ res = libusb_submit_transfer(transfer);
+ if (res != 0) {
+ LOG("Unable to submit URB. libusb error code: %d\n", res);
+ dev->shutdown_thread = 1;
+ dev->cancelled = 1;
+ }
+}
+
+
+static void *read_thread(void *param)
+{
+ hid_device *dev = param;
+ unsigned char *buf;
+ const size_t length = dev->input_ep_max_packet_size;
+
+ /* Set up the transfer object. */
+ buf = malloc(length);
+ dev->transfer = libusb_alloc_transfer(0);
+ libusb_fill_interrupt_transfer(dev->transfer,
+ dev->device_handle,
+ dev->input_endpoint,
+ buf,
+ length,
+ read_callback,
+ dev,
+ 5000/*timeout*/);
+
+ /* Make the first submission. Further submissions are made
+ from inside read_callback() */
+ libusb_submit_transfer(dev->transfer);
+
+ /* Notify the main thread that the read thread is up and running. */
+ pthread_barrier_wait(&dev->barrier);
+
+ /* Handle all the events. */
+ while (!dev->shutdown_thread) {
+ int res;
+ res = libusb_handle_events(usb_context);
+ if (res < 0) {
+ /* There was an error. */
+ LOG("read_thread(): libusb reports error # %d\n", res);
+
+ /* Break out of this loop only on fatal error.*/
+ if (res != LIBUSB_ERROR_BUSY &&
+ res != LIBUSB_ERROR_TIMEOUT &&
+ res != LIBUSB_ERROR_OVERFLOW &&
+ res != LIBUSB_ERROR_INTERRUPTED) {
+ break;
+ }
+ }
+ }
+
+ /* Cancel any transfer that may be pending. This call will fail
+ if no transfers are pending, but that's OK. */
+ libusb_cancel_transfer(dev->transfer);
+
+ while (!dev->cancelled)
+ libusb_handle_events_completed(usb_context, &dev->cancelled);
+
+ /* Now that the read thread is stopping, Wake any threads which are
+ waiting on data (in hid_read_timeout()). Do this under a mutex to
+ make sure that a thread which is about to go to sleep waiting on
+ the condition actually will go to sleep before the condition is
+ signaled. */
+ pthread_mutex_lock(&dev->mutex);
+ pthread_cond_broadcast(&dev->condition);
+ pthread_mutex_unlock(&dev->mutex);
+
+ /* The dev->transfer->buffer and dev->transfer objects are cleaned up
+ in hid_close(). They are not cleaned up here because this thread
+ could end either due to a disconnect or due to a user
+ call to hid_close(). In both cases the objects can be safely
+ cleaned up after the call to pthread_join() (in hid_close()), but
+ since hid_close() calls libusb_cancel_transfer(), on these objects,
+ they can not be cleaned up here. */
+
+ return NULL;
+}
+
+
+hid_device * HID_API_EXPORT hid_open_path(const char *path)
+{
+ hid_device *dev = NULL;
+
+ libusb_device **devs;
+ libusb_device *usb_dev;
+ int res;
+ int d = 0;
+ int good_open = 0;
+
+ if(hid_init() < 0)
+ return NULL;
+
+ dev = new_hid_device();
+
+ libusb_get_device_list(usb_context, &devs);
+ while ((usb_dev = devs[d++]) != NULL) {
+ struct libusb_device_descriptor desc;
+ struct libusb_config_descriptor *conf_desc = NULL;
+ int i,j,k;
+ libusb_get_device_descriptor(usb_dev, &desc);
+
+ if (libusb_get_active_config_descriptor(usb_dev, &conf_desc) < 0)
+ continue;
+ 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) {
+ char *dev_path = make_path(usb_dev, intf_desc->bInterfaceNumber);
+ if (!strcmp(dev_path, path)) {
+ /* Matched Paths. Open this device */
+
+ /* OPEN HERE */
+ res = libusb_open(usb_dev, &dev->device_handle);
+ if (res < 0) {
+ LOG("can't open device\n");
+ free(dev_path);
+ break;
+ }
+ good_open = 1;
+#ifdef DETACH_KERNEL_DRIVER
+ /* Detach the kernel driver, but only if the
+ device is managed by the kernel */
+ if (libusb_kernel_driver_active(dev->device_handle, intf_desc->bInterfaceNumber) == 1) {
+ res = libusb_detach_kernel_driver(dev->device_handle, intf_desc->bInterfaceNumber);
+ if (res < 0) {
+ libusb_close(dev->device_handle);
+ LOG("Unable to detach Kernel Driver\n");
+ free(dev_path);
+ good_open = 0;
+ break;
+ }
+ }
+#endif
+ res = libusb_claim_interface(dev->device_handle, intf_desc->bInterfaceNumber);
+ if (res < 0) {
+ LOG("can't claim interface %d: %d\n", intf_desc->bInterfaceNumber, res);
+ free(dev_path);
+ libusb_close(dev->device_handle);
+ good_open = 0;
+ break;
+ }
+
+ /* Store off the string descriptor indexes */
+ dev->manufacturer_index = desc.iManufacturer;
+ dev->product_index = desc.iProduct;
+ dev->serial_index = desc.iSerialNumber;
+
+ /* Store off the interface number */
+ dev->interface = intf_desc->bInterfaceNumber;
+
+ /* Find the INPUT and OUTPUT endpoints. An
+ OUTPUT endpoint is not required. */
+ for (i = 0; i < intf_desc->bNumEndpoints; i++) {
+ const struct libusb_endpoint_descriptor *ep
+ = &intf_desc->endpoint[i];
+
+ /* Determine the type and direction of this
+ endpoint. */
+ int is_interrupt =
+ (ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK)
+ == LIBUSB_TRANSFER_TYPE_INTERRUPT;
+ int is_output =
+ (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK)
+ == LIBUSB_ENDPOINT_OUT;
+ int is_input =
+ (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK)
+ == LIBUSB_ENDPOINT_IN;
+
+ /* Decide whether to use it for input or output. */
+ if (dev->input_endpoint == 0 &&
+ is_interrupt && is_input) {
+ /* Use this endpoint for INPUT */
+ dev->input_endpoint = ep->bEndpointAddress;
+ dev->input_ep_max_packet_size = ep->wMaxPacketSize;
+ }
+ if (dev->output_endpoint == 0 &&
+ is_interrupt && is_output) {
+ /* Use this endpoint for OUTPUT */
+ dev->output_endpoint = ep->bEndpointAddress;
+ }
+ }
+
+ pthread_create(&dev->thread, NULL, read_thread, dev);
+
+ /* Wait here for the read thread to be initialized. */
+ pthread_barrier_wait(&dev->barrier);
+
+ }
+ free(dev_path);
+ }
+ }
+ }
+ libusb_free_config_descriptor(conf_desc);
+
+ }
+
+ libusb_free_device_list(devs, 1);
+
+ /* If we have a good handle, return it. */
+ if (good_open) {
+ return dev;
+ }
+ else {
+ /* Unable to open any devices. */
+ free_hid_device(dev);
+ return NULL;
+ }
+}
+
+
+int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length)
+{
+ int res;
+ int report_number = data[0];
+ int skipped_report_id = 0;
+
+ if (report_number == 0x0) {
+ data++;
+ length--;
+ skipped_report_id = 1;
+ }
+
+
+ if (dev->output_endpoint <= 0) {
+ /* No interrupt out endpoint. Use the Control Endpoint */
+ res = libusb_control_transfer(dev->device_handle,
+ LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT,
+ 0x09/*HID Set_Report*/,
+ (2/*HID output*/ << 8) | report_number,
+ dev->interface,
+ (unsigned char *)data, length,
+ 1000/*timeout millis*/);
+
+ if (res < 0)
+ return -1;
+
+ if (skipped_report_id)
+ length++;
+
+ return length;
+ }
+ else {
+ /* Use the interrupt out endpoint */
+ int actual_length;
+ res = libusb_interrupt_transfer(dev->device_handle,
+ dev->output_endpoint,
+ (unsigned char*)data,
+ length,
+ &actual_length, 1000);
+
+ if (res < 0)
+ return -1;
+
+ if (skipped_report_id)
+ actual_length++;
+
+ return actual_length;
+ }
+}
+
+/* Helper function, to simplify hid_read().
+ This should be called with dev->mutex locked. */
+static int return_data(hid_device *dev, unsigned char *data, size_t length)
+{
+ /* Copy the data out of the linked list item (rpt) into the
+ return buffer (data), and delete the liked list item. */
+ struct input_report *rpt = dev->input_reports;
+ size_t len = (length < rpt->len)? length: rpt->len;
+ if (len > 0)
+ memcpy(data, rpt->data, len);
+ dev->input_reports = rpt->next;
+ free(rpt->data);
+ free(rpt);
+ return len;
+}
+
+static void cleanup_mutex(void *param)
+{
+ hid_device *dev = param;
+ pthread_mutex_unlock(&dev->mutex);
+}
+
+
+int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
+{
+ int bytes_read = -1;
+
+#if 0
+ int transferred;
+ int res = libusb_interrupt_transfer(dev->device_handle, dev->input_endpoint, data, length, &transferred, 5000);
+ LOG("transferred: %d\n", transferred);
+ return transferred;
+#endif
+
+ pthread_mutex_lock(&dev->mutex);
+ pthread_cleanup_push(&cleanup_mutex, dev);
+
+ /* There's an input report queued up. Return it. */
+ if (dev->input_reports) {
+ /* Return the first one */
+ bytes_read = return_data(dev, data, length);
+ goto ret;
+ }
+
+ if (dev->shutdown_thread) {
+ /* This means the device has been disconnected.
+ An error code of -1 should be returned. */
+ bytes_read = -1;
+ goto ret;
+ }
+
+ if (milliseconds == -1) {
+ /* Blocking */
+ while (!dev->input_reports && !dev->shutdown_thread) {
+ pthread_cond_wait(&dev->condition, &dev->mutex);
+ }
+ if (dev->input_reports) {
+ bytes_read = return_data(dev, data, length);
+ }
+ }
+ else if (milliseconds > 0) {
+ /* Non-blocking, but called with timeout. */
+ int res;
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ ts.tv_sec += milliseconds / 1000;
+ ts.tv_nsec += (milliseconds % 1000) * 1000000;
+ if (ts.tv_nsec >= 1000000000L) {
+ ts.tv_sec++;
+ ts.tv_nsec -= 1000000000L;
+ }
+
+ while (!dev->input_reports && !dev->shutdown_thread) {
+ res = pthread_cond_timedwait(&dev->condition, &dev->mutex, &ts);
+ if (res == 0) {
+ if (dev->input_reports) {
+ bytes_read = return_data(dev, data, length);
+ break;
+ }
+
+ /* If we're here, there was a spurious wake up
+ or the read thread was shutdown. Run the
+ loop again (ie: don't break). */
+ }
+ else if (res == ETIMEDOUT) {
+ /* Timed out. */
+ bytes_read = 0;
+ break;
+ }
+ else {
+ /* Error. */
+ bytes_read = -1;
+ break;
+ }
+ }
+ }
+ else {
+ /* Purely non-blocking */
+ bytes_read = 0;
+ }
+
+ret:
+ pthread_mutex_unlock(&dev->mutex);
+ pthread_cleanup_pop(0);
+
+ return bytes_read;
+}
+
+int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length)
+{
+ return hid_read_timeout(dev, data, length, dev->blocking ? -1 : 0);
+}
+
+int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
+{
+ dev->blocking = !nonblock;
+
+ return 0;
+}
+
+
+int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
+{
+ int res = -1;
+ int skipped_report_id = 0;
+ int report_number = data[0];
+
+ if (report_number == 0x0) {
+ data++;
+ length--;
+ skipped_report_id = 1;
+ }
+
+ res = libusb_control_transfer(dev->device_handle,
+ LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT,
+ 0x09/*HID set_report*/,
+ (3/*HID feature*/ << 8) | report_number,
+ dev->interface,
+ (unsigned char *)data, length,
+ 1000/*timeout millis*/);
+
+ if (res < 0)
+ return -1;
+
+ /* Account for the report ID */
+ if (skipped_report_id)
+ length++;
+
+ return length;
+}
+
+int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
+{
+ int res = -1;
+ int skipped_report_id = 0;
+ int report_number = data[0];
+
+ if (report_number == 0x0) {
+ /* Offset the return buffer by 1, so that the report ID
+ will remain in byte 0. */
+ data++;
+ length--;
+ skipped_report_id = 1;
+ }
+ res = libusb_control_transfer(dev->device_handle,
+ LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_IN,
+ 0x01/*HID get_report*/,
+ (3/*HID feature*/ << 8) | report_number,
+ dev->interface,
+ (unsigned char *)data, length,
+ 1000/*timeout millis*/);
+
+ if (res < 0)
+ return -1;
+
+ if (skipped_report_id)
+ res++;
+
+ return res;
+}
+
+
+void HID_API_EXPORT hid_close(hid_device *dev)
+{
+ if (!dev)
+ return;
+
+ /* Cause read_thread() to stop. */
+ dev->shutdown_thread = 1;
+ libusb_cancel_transfer(dev->transfer);
+
+ /* Wait for read_thread() to end. */
+ pthread_join(dev->thread, NULL);
+
+ /* Clean up the Transfer objects allocated in read_thread(). */
+ free(dev->transfer->buffer);
+ libusb_free_transfer(dev->transfer);
+
+ /* release the interface */
+ libusb_release_interface(dev->device_handle, dev->interface);
+
+ /* Close the handle */
+ libusb_close(dev->device_handle);
+
+ /* Clear out the queue of received reports. */
+ pthread_mutex_lock(&dev->mutex);
+ while (dev->input_reports) {
+ return_data(dev, NULL, 0);
+ }
+ pthread_mutex_unlock(&dev->mutex);
+
+ free_hid_device(dev);
+}
+
+
+int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
+{
+ return hid_get_indexed_string(dev, dev->manufacturer_index, string, maxlen);
+}
+
+int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
+{
+ return hid_get_indexed_string(dev, dev->product_index, string, maxlen);
+}
+
+int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
+{
+ return hid_get_indexed_string(dev, dev->serial_index, string, maxlen);
+}
+
+int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
+{
+ wchar_t *str;
+
+ str = get_usb_string(dev->device_handle, string_index);
+ if (str) {
+ wcsncpy(string, str, maxlen);
+ string[maxlen-1] = L'\0';
+ free(str);
+ return 0;
+ }
+ else
+ return -1;
+}
+
+
+HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
+{
+ return NULL;
+}
+
+
+struct lang_map_entry {
+ const char *name;
+ const char *string_code;
+ uint16_t usb_code;
+};
+
+#define LANG(name,code,usb_code) { name, code, usb_code }
+static struct lang_map_entry lang_map[] = {
+ LANG("Afrikaans", "af", 0x0436),
+ LANG("Albanian", "sq", 0x041C),
+ LANG("Arabic - United Arab Emirates", "ar_ae", 0x3801),
+ LANG("Arabic - Bahrain", "ar_bh", 0x3C01),
+ LANG("Arabic - Algeria", "ar_dz", 0x1401),
+ LANG("Arabic - Egypt", "ar_eg", 0x0C01),
+ LANG("Arabic - Iraq", "ar_iq", 0x0801),
+ LANG("Arabic - Jordan", "ar_jo", 0x2C01),
+ LANG("Arabic - Kuwait", "ar_kw", 0x3401),
+ LANG("Arabic - Lebanon", "ar_lb", 0x3001),
+ LANG("Arabic - Libya", "ar_ly", 0x1001),
+ LANG("Arabic - Morocco", "ar_ma", 0x1801),
+ LANG("Arabic - Oman", "ar_om", 0x2001),
+ LANG("Arabic - Qatar", "ar_qa", 0x4001),
+ LANG("Arabic - Saudi Arabia", "ar_sa", 0x0401),
+ LANG("Arabic - Syria", "ar_sy", 0x2801),
+ LANG("Arabic - Tunisia", "ar_tn", 0x1C01),
+ LANG("Arabic - Yemen", "ar_ye", 0x2401),
+ LANG("Armenian", "hy", 0x042B),
+ LANG("Azeri - Latin", "az_az", 0x042C),
+ LANG("Azeri - Cyrillic", "az_az", 0x082C),
+ LANG("Basque", "eu", 0x042D),
+ LANG("Belarusian", "be", 0x0423),
+ LANG("Bulgarian", "bg", 0x0402),
+ LANG("Catalan", "ca", 0x0403),
+ LANG("Chinese - China", "zh_cn", 0x0804),
+ LANG("Chinese - Hong Kong SAR", "zh_hk", 0x0C04),
+ LANG("Chinese - Macau SAR", "zh_mo", 0x1404),
+ LANG("Chinese - Singapore", "zh_sg", 0x1004),
+ LANG("Chinese - Taiwan", "zh_tw", 0x0404),
+ LANG("Croatian", "hr", 0x041A),
+ LANG("Czech", "cs", 0x0405),
+ LANG("Danish", "da", 0x0406),
+ LANG("Dutch - Netherlands", "nl_nl", 0x0413),
+ LANG("Dutch - Belgium", "nl_be", 0x0813),
+ LANG("English - Australia", "en_au", 0x0C09),
+ LANG("English - Belize", "en_bz", 0x2809),
+ LANG("English - Canada", "en_ca", 0x1009),
+ LANG("English - Caribbean", "en_cb", 0x2409),
+ LANG("English - Ireland", "en_ie", 0x1809),
+ LANG("English - Jamaica", "en_jm", 0x2009),
+ LANG("English - New Zealand", "en_nz", 0x1409),
+ LANG("English - Phillippines", "en_ph", 0x3409),
+ LANG("English - Southern Africa", "en_za", 0x1C09),
+ LANG("English - Trinidad", "en_tt", 0x2C09),
+ LANG("English - Great Britain", "en_gb", 0x0809),
+ LANG("English - United States", "en_us", 0x0409),
+ LANG("Estonian", "et", 0x0425),
+ LANG("Farsi", "fa", 0x0429),
+ LANG("Finnish", "fi", 0x040B),
+ LANG("Faroese", "fo", 0x0438),
+ LANG("French - France", "fr_fr", 0x040C),
+ LANG("French - Belgium", "fr_be", 0x080C),
+ LANG("French - Canada", "fr_ca", 0x0C0C),
+ LANG("French - Luxembourg", "fr_lu", 0x140C),
+ LANG("French - Switzerland", "fr_ch", 0x100C),
+ LANG("Gaelic - Ireland", "gd_ie", 0x083C),
+ LANG("Gaelic - Scotland", "gd", 0x043C),
+ LANG("German - Germany", "de_de", 0x0407),
+ LANG("German - Austria", "de_at", 0x0C07),
+ LANG("German - Liechtenstein", "de_li", 0x1407),
+ LANG("German - Luxembourg", "de_lu", 0x1007),
+ LANG("German - Switzerland", "de_ch", 0x0807),
+ LANG("Greek", "el", 0x0408),
+ LANG("Hebrew", "he", 0x040D),
+ LANG("Hindi", "hi", 0x0439),
+ LANG("Hungarian", "hu", 0x040E),
+ LANG("Icelandic", "is", 0x040F),
+ LANG("Indonesian", "id", 0x0421),
+ LANG("Italian - Italy", "it_it", 0x0410),
+ LANG("Italian - Switzerland", "it_ch", 0x0810),
+ LANG("Japanese", "ja", 0x0411),
+ LANG("Korean", "ko", 0x0412),
+ LANG("Latvian", "lv", 0x0426),
+ LANG("Lithuanian", "lt", 0x0427),
+ LANG("F.Y.R.O. Macedonia", "mk", 0x042F),
+ LANG("Malay - Malaysia", "ms_my", 0x043E),
+ LANG("Malay – Brunei", "ms_bn", 0x083E),
+ LANG("Maltese", "mt", 0x043A),
+ LANG("Marathi", "mr", 0x044E),
+ LANG("Norwegian - Bokml", "no_no", 0x0414),
+ LANG("Norwegian - Nynorsk", "no_no", 0x0814),
+ LANG("Polish", "pl", 0x0415),
+ LANG("Portuguese - Portugal", "pt_pt", 0x0816),
+ LANG("Portuguese - Brazil", "pt_br", 0x0416),
+ LANG("Raeto-Romance", "rm", 0x0417),
+ LANG("Romanian - Romania", "ro", 0x0418),
+ LANG("Romanian - Republic of Moldova", "ro_mo", 0x0818),
+ LANG("Russian", "ru", 0x0419),
+ LANG("Russian - Republic of Moldova", "ru_mo", 0x0819),
+ LANG("Sanskrit", "sa", 0x044F),
+ LANG("Serbian - Cyrillic", "sr_sp", 0x0C1A),
+ LANG("Serbian - Latin", "sr_sp", 0x081A),
+ LANG("Setsuana", "tn", 0x0432),
+ LANG("Slovenian", "sl", 0x0424),
+ LANG("Slovak", "sk", 0x041B),
+ LANG("Sorbian", "sb", 0x042E),
+ LANG("Spanish - Spain (Traditional)", "es_es", 0x040A),
+ LANG("Spanish - Argentina", "es_ar", 0x2C0A),
+ LANG("Spanish - Bolivia", "es_bo", 0x400A),
+ LANG("Spanish - Chile", "es_cl", 0x340A),
+ LANG("Spanish - Colombia", "es_co", 0x240A),
+ LANG("Spanish - Costa Rica", "es_cr", 0x140A),
+ LANG("Spanish - Dominican Republic", "es_do", 0x1C0A),
+ LANG("Spanish - Ecuador", "es_ec", 0x300A),
+ LANG("Spanish - Guatemala", "es_gt", 0x100A),
+ LANG("Spanish - Honduras", "es_hn", 0x480A),
+ LANG("Spanish - Mexico", "es_mx", 0x080A),
+ LANG("Spanish - Nicaragua", "es_ni", 0x4C0A),
+ LANG("Spanish - Panama", "es_pa", 0x180A),
+ LANG("Spanish - Peru", "es_pe", 0x280A),
+ LANG("Spanish - Puerto Rico", "es_pr", 0x500A),
+ LANG("Spanish - Paraguay", "es_py", 0x3C0A),
+ LANG("Spanish - El Salvador", "es_sv", 0x440A),
+ LANG("Spanish - Uruguay", "es_uy", 0x380A),
+ LANG("Spanish - Venezuela", "es_ve", 0x200A),
+ LANG("Southern Sotho", "st", 0x0430),
+ LANG("Swahili", "sw", 0x0441),
+ LANG("Swedish - Sweden", "sv_se", 0x041D),
+ LANG("Swedish - Finland", "sv_fi", 0x081D),
+ LANG("Tamil", "ta", 0x0449),
+ LANG("Tatar", "tt", 0X0444),
+ LANG("Thai", "th", 0x041E),
+ LANG("Turkish", "tr", 0x041F),
+ LANG("Tsonga", "ts", 0x0431),
+ LANG("Ukrainian", "uk", 0x0422),
+ LANG("Urdu", "ur", 0x0420),
+ LANG("Uzbek - Cyrillic", "uz_uz", 0x0843),
+ LANG("Uzbek – Latin", "uz_uz", 0x0443),
+ LANG("Vietnamese", "vi", 0x042A),
+ LANG("Xhosa", "xh", 0x0434),
+ LANG("Yiddish", "yi", 0x043D),
+ LANG("Zulu", "zu", 0x0435),
+ LANG(NULL, NULL, 0x0),
+};
+
+uint16_t get_usb_code_for_current_locale(void)
+{
+ char *locale;
+ char search_string[64];
+ char *ptr;
+ struct lang_map_entry *lang;
+
+ /* Get the current locale. */
+ locale = setlocale(0, NULL);
+ if (!locale)
+ return 0x0;
+
+ /* Make a copy of the current locale string. */
+ strncpy(search_string, locale, sizeof(search_string));
+ search_string[sizeof(search_string)-1] = '\0';
+
+ /* Chop off the encoding part, and make it lower case. */
+ ptr = search_string;
+ while (*ptr) {
+ *ptr = tolower(*ptr);
+ if (*ptr == '.') {
+ *ptr = '\0';
+ break;
+ }
+ ptr++;
+ }
+
+ /* Find the entry which matches the string code of our locale. */
+ lang = lang_map;
+ while (lang->string_code) {
+ if (!strcmp(lang->string_code, search_string)) {
+ return lang->usb_code;
+ }
+ lang++;
+ }
+
+ /* There was no match. Find with just the language only. */
+ /* Chop off the variant. Chop it off at the '_'. */
+ ptr = search_string;
+ while (*ptr) {
+ *ptr = tolower(*ptr);
+ if (*ptr == '_') {
+ *ptr = '\0';
+ break;
+ }
+ ptr++;
+ }
+
+#if 0 /* TODO: Do we need this? */
+ /* Find the entry which matches the string code of our language. */
+ lang = lang_map;
+ while (lang->string_code) {
+ if (!strcmp(lang->string_code, search_string)) {
+ return lang->usb_code;
+ }
+ lang++;
+ }
+#endif
+
+ /* Found nothing. */
+ return 0x0;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/cad/PrusaSlicer/files/patch-CMakeLists.txt b/cad/PrusaSlicer/files/patch-CMakeLists.txt
index 64eae04effc9..297a2a5d44b8 100644
--- a/cad/PrusaSlicer/files/patch-CMakeLists.txt
+++ b/cad/PrusaSlicer/files/patch-CMakeLists.txt
@@ -1,14 +1,6 @@
---- CMakeLists.txt.orig 2024-09-18 13:39:04 UTC
+--- CMakeLists.txt.orig 2025-02-14 18:17:10 UTC
+++ CMakeLists.txt
-@@ -14,6 +14,7 @@ include(CMakeDependentOption)
- include("version.inc")
- include(GNUInstallDirs)
- include(CMakeDependentOption)
-+add_compile_options(-DNDEBUG)
-
- set(SLIC3R_RESOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/resources")
- file(TO_NATIVE_PATH "${SLIC3R_RESOURCES_DIR}" SLIC3R_RESOURCES_DIR_WIN)
-@@ -234,7 +235,7 @@ endif ()
+@@ -233,7 +233,7 @@ endif ()
endif ()
endif ()
@@ -17,46 +9,29 @@
find_package(PkgConfig REQUIRED)
if (CMAKE_VERSION VERSION_LESS "3.1")
-@@ -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)
-
-+ add_compile_options(-Wno-enum-constexpr-conversion -Wno-implicit-const-int-float-conversion)
-+
- # 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)
-@@ -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)
+@@ -635,8 +635,14 @@ elseif (SLIC3R_FHS)
install(DIRECTORY ${SLIC3R_RESOURCES_DIR}/ DESTINATION ${SLIC3R_FHS_RESOURCES}
PATTERN "*/udev" EXCLUDE
)
-- install(FILES src/platform/unix/PrusaSlicer.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications)
-- install(FILES src/platform/unix/PrusaGcodeviewer.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications)
-+ install(FILES src/platform/unix/PrusaSlicer.desktop DESTINATION share/applications)
-+ install(FILES src/platform/unix/PrusaGcodeviewer.desktop DESTINATION share/applications)
++if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ install(FILES src/platform/unix/PrusaSlicer.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications)
+ install(FILES src/platform/unix/PrusaGcodeviewer.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications)
++endif()
++if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
++ install(FILES src/platform/unix/PrusaSlicer.desktop DESTINATION share/applications)
++ install(FILES src/platform/unix/PrusaGcodeviewer.desktop DESTINATION share/applications)
++endif()
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
-@@ -646,7 +649,8 @@ elseif (SLIC3R_FHS)
+@@ -645,7 +651,10 @@ elseif (SLIC3R_FHS)
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/${SIZE}x${SIZE}/apps RENAME PrusaSlicer-gcodeviewer.png
)
endforeach()
-- install(DIRECTORY ${SLIC3R_RESOURCES_DIR}/udev/ DESTINATION lib/udev/rules.d)
-+ #FreeBSD doesn't have a udev
-+ #install(DIRECTORY ${SLIC3R_RESOURCES_DIR}/udev/ DESTINATION lib/udev/rules.d)
++if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ install(DIRECTORY ${SLIC3R_RESOURCES_DIR}/udev/ DESTINATION lib/udev/rules.d)
++endif()
++
else ()
install(FILES src/platform/unix/PrusaSlicer.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/resources/applications)
install(FILES src/platform/unix/PrusaGcodeviewer.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/resources/applications)
diff --git a/cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_arduino.c b/cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_arduino.c
index 9aad1b125e9a..002561cba863 100644
--- a/cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_arduino.c
+++ b/cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_arduino.c
@@ -1,4 +1,4 @@
---- bundled_deps/avrdude/avrdude/arduino.c.orig 2024-09-18 13:39:04 UTC
+--- bundled_deps/avrdude/avrdude/arduino.c.orig 2024-12-20 11:54:34 UTC
+++ bundled_deps/avrdude/avrdude/arduino.c
@@ -28,6 +28,7 @@
#include "ac_cfg.h"
diff --git a/cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_libavrdude.h b/cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_libavrdude.h
index 6d03bb0bc90d..611e3d9d05e3 100644
--- a/cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_libavrdude.h
+++ b/cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_libavrdude.h
@@ -1,4 +1,4 @@
---- bundled_deps/avrdude/avrdude/libavrdude.h.orig 2024-09-18 13:39:04 UTC
+--- bundled_deps/avrdude/avrdude/libavrdude.h.orig 2024-12-20 11:54:34 UTC
+++ bundled_deps/avrdude/avrdude/libavrdude.h
@@ -950,6 +950,8 @@ int read_config_builtin();
// Header file for alloca()
diff --git a/cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_main.c b/cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_main.c
index a6912d0091ef..752545e0087b 100644
--- a/cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_main.c
+++ b/cad/PrusaSlicer/files/patch-bundled__deps_avrdude_avrdude_main.c
@@ -1,4 +1,4 @@
---- bundled_deps/avrdude/avrdude/main.c.orig 2024-09-18 13:39:04 UTC
+--- bundled_deps/avrdude/avrdude/main.c.orig 2024-12-20 11:54:34 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"
diff --git a/cad/PrusaSlicer/files/patch-bundled__deps_hidapi_CMakeLists.txt b/cad/PrusaSlicer/files/patch-bundled__deps_hidapi_CMakeLists.txt
index a8f856cd3cf2..b7cd9db381b3 100644
--- a/cad/PrusaSlicer/files/patch-bundled__deps_hidapi_CMakeLists.txt
+++ b/cad/PrusaSlicer/files/patch-bundled__deps_hidapi_CMakeLists.txt
@@ -1,4 +1,4 @@
---- bundled_deps/hidapi/CMakeLists.txt.orig 2024-09-18 13:39:04 UTC
+--- bundled_deps/hidapi/CMakeLists.txt.orig 2024-12-20 11:54:34 UTC
+++ bundled_deps/hidapi/CMakeLists.txt
@@ -1,8 +1,9 @@
-
diff --git a/cad/PrusaSlicer/files/patch-bundled__deps_hidapi_libusb_hid.c b/cad/PrusaSlicer/files/patch-bundled__deps_hidapi_libusb_hid.c
deleted file mode 100644
index df486242573f..000000000000
--- a/cad/PrusaSlicer/files/patch-bundled__deps_hidapi_libusb_hid.c
+++ /dev/null
@@ -1,1517 +0,0 @@
---- 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;
-+ num_queued++;
-+ }
-+ cur->next = rpt;
-+
-+ /* Pop one off if we've reached 30 in the queue. This
-+ way we don't grow forever if the user never reads
-+ anything from the device. */
-+ if (num_queued > 30) {
-+ return_data(dev, NULL, 0);
-+ }
-+ }
-+ pthread_mutex_unlock(&dev->mutex);
-+ }
-+ else if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
-+ dev->shutdown_thread = 1;
-+ dev->cancelled = 1;
-+ return;
-+ }
-+ else if (transfer->status == LIBUSB_TRANSFER_NO_DEVICE) {
-+ dev->shutdown_thread = 1;
-+ dev->cancelled = 1;
-+ return;
-+ }
-+ else if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT) {
-+ //LOG("Timeout (normal)\n");
-+ }
-+ else {
-+ LOG("Unknown transfer code: %d\n", transfer->status);
-+ }
-+
-+ /* Re-submit the transfer object. */
-+ res = libusb_submit_transfer(transfer);
-+ if (res != 0) {
-+ LOG("Unable to submit URB. libusb error code: %d\n", res);
-+ dev->shutdown_thread = 1;
-+ dev->cancelled = 1;
-+ }
-+}
-+
-+
-+static void *read_thread(void *param)
-+{
-+ hid_device *dev = param;
-+ unsigned char *buf;
-+ const size_t length = dev->input_ep_max_packet_size;
-+
-+ /* Set up the transfer object. */
-+ buf = malloc(length);
-+ dev->transfer = libusb_alloc_transfer(0);
-+ libusb_fill_interrupt_transfer(dev->transfer,
-+ dev->device_handle,
-+ dev->input_endpoint,
-+ buf,
-+ length,
-+ read_callback,
-+ dev,
-+ 5000/*timeout*/);
-+
-+ /* Make the first submission. Further submissions are made
-+ from inside read_callback() */
-+ libusb_submit_transfer(dev->transfer);
-+
-+ /* Notify the main thread that the read thread is up and running. */
-+ pthread_barrier_wait(&dev->barrier);
-+
-+ /* Handle all the events. */
-+ while (!dev->shutdown_thread) {
-+ int res;
-+ res = libusb_handle_events(usb_context);
-+ if (res < 0) {
-+ /* There was an error. */
-+ LOG("read_thread(): libusb reports error # %d\n", res);
-+
-+ /* Break out of this loop only on fatal error.*/
-+ if (res != LIBUSB_ERROR_BUSY &&
-+ res != LIBUSB_ERROR_TIMEOUT &&
-+ res != LIBUSB_ERROR_OVERFLOW &&
-+ res != LIBUSB_ERROR_INTERRUPTED) {
-+ break;
-+ }
-+ }
-+ }
-+
-+ /* Cancel any transfer that may be pending. This call will fail
-+ if no transfers are pending, but that's OK. */
-+ libusb_cancel_transfer(dev->transfer);
-+
-+ while (!dev->cancelled)
-+ libusb_handle_events_completed(usb_context, &dev->cancelled);
-+
-+ /* Now that the read thread is stopping, Wake any threads which are
-+ waiting on data (in hid_read_timeout()). Do this under a mutex to
-+ make sure that a thread which is about to go to sleep waiting on
-+ the condition actually will go to sleep before the condition is
-+ signaled. */
-+ pthread_mutex_lock(&dev->mutex);
-+ pthread_cond_broadcast(&dev->condition);
-+ pthread_mutex_unlock(&dev->mutex);
-+
-+ /* The dev->transfer->buffer and dev->transfer objects are cleaned up
-+ in hid_close(). They are not cleaned up here because this thread
-+ could end either due to a disconnect or due to a user
-+ call to hid_close(). In both cases the objects can be safely
-+ cleaned up after the call to pthread_join() (in hid_close()), but
-+ since hid_close() calls libusb_cancel_transfer(), on these objects,
-+ they can not be cleaned up here. */
-+
-+ return NULL;
-+}
-+
-+
-+hid_device * HID_API_EXPORT hid_open_path(const char *path)
-+{
-+ hid_device *dev = NULL;
-+
-+ libusb_device **devs;
-+ libusb_device *usb_dev;
-+ int res;
-+ int d = 0;
-+ int good_open = 0;
-+
-+ if(hid_init() < 0)
-+ return NULL;
-+
-+ dev = new_hid_device();
-+
-+ libusb_get_device_list(usb_context, &devs);
-+ while ((usb_dev = devs[d++]) != NULL) {
-+ struct libusb_device_descriptor desc;
-+ struct libusb_config_descriptor *conf_desc = NULL;
-+ int i,j,k;
-+ libusb_get_device_descriptor(usb_dev, &desc);
-+
-+ if (libusb_get_active_config_descriptor(usb_dev, &conf_desc) < 0)
-+ continue;
-+ 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) {
-+ char *dev_path = make_path(usb_dev, intf_desc->bInterfaceNumber);
-+ if (!strcmp(dev_path, path)) {
-+ /* Matched Paths. Open this device */
-+
-+ /* OPEN HERE */
-+ res = libusb_open(usb_dev, &dev->device_handle);
-+ if (res < 0) {
-+ LOG("can't open device\n");
-+ free(dev_path);
-+ break;
-+ }
-+ good_open = 1;
-+#ifdef DETACH_KERNEL_DRIVER
-+ /* Detach the kernel driver, but only if the
-+ device is managed by the kernel */
-+ if (libusb_kernel_driver_active(dev->device_handle, intf_desc->bInterfaceNumber) == 1) {
-+ res = libusb_detach_kernel_driver(dev->device_handle, intf_desc->bInterfaceNumber);
-+ if (res < 0) {
-+ libusb_close(dev->device_handle);
-+ LOG("Unable to detach Kernel Driver\n");
-+ free(dev_path);
-+ good_open = 0;
-+ break;
-+ }
-+ }
-+#endif
-+ res = libusb_claim_interface(dev->device_handle, intf_desc->bInterfaceNumber);
-+ if (res < 0) {
-+ LOG("can't claim interface %d: %d\n", intf_desc->bInterfaceNumber, res);
-+ free(dev_path);
-+ libusb_close(dev->device_handle);
-+ good_open = 0;
-+ break;
-+ }
-+
-+ /* Store off the string descriptor indexes */
-+ dev->manufacturer_index = desc.iManufacturer;
-+ dev->product_index = desc.iProduct;
-+ dev->serial_index = desc.iSerialNumber;
-+
-+ /* Store off the interface number */
-+ dev->interface = intf_desc->bInterfaceNumber;
-+
-+ /* Find the INPUT and OUTPUT endpoints. An
-+ OUTPUT endpoint is not required. */
-+ for (i = 0; i < intf_desc->bNumEndpoints; i++) {
-+ const struct libusb_endpoint_descriptor *ep
-+ = &intf_desc->endpoint[i];
-+
-+ /* Determine the type and direction of this
-+ endpoint. */
-+ int is_interrupt =
-+ (ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK)
-+ == LIBUSB_TRANSFER_TYPE_INTERRUPT;
-+ int is_output =
-+ (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK)
-+ == LIBUSB_ENDPOINT_OUT;
-+ int is_input =
-+ (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK)
-+ == LIBUSB_ENDPOINT_IN;
-+
-+ /* Decide whether to use it for input or output. */
-+ if (dev->input_endpoint == 0 &&
-+ is_interrupt && is_input) {
-+ /* Use this endpoint for INPUT */
-+ dev->input_endpoint = ep->bEndpointAddress;
-+ dev->input_ep_max_packet_size = ep->wMaxPacketSize;
-+ }
-+ if (dev->output_endpoint == 0 &&
-+ is_interrupt && is_output) {
-+ /* Use this endpoint for OUTPUT */
-+ dev->output_endpoint = ep->bEndpointAddress;
-+ }
-+ }
-+
-+ pthread_create(&dev->thread, NULL, read_thread, dev);
-+
-+ /* Wait here for the read thread to be initialized. */
-+ pthread_barrier_wait(&dev->barrier);
-+
-+ }
-+ free(dev_path);
-+ }
-+ }
-+ }
-+ libusb_free_config_descriptor(conf_desc);
-+
-+ }
-+
-+ libusb_free_device_list(devs, 1);
-+
-+ /* If we have a good handle, return it. */
-+ if (good_open) {
-+ return dev;
-+ }
-+ else {
-+ /* Unable to open any devices. */
-+ free_hid_device(dev);
-+ return NULL;
-+ }
-+}
-+
-+
-+int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length)
-+{
-+ int res;
-+ int report_number = data[0];
-+ int skipped_report_id = 0;
-+
-+ if (report_number == 0x0) {
-+ data++;
-+ length--;
-+ skipped_report_id = 1;
-+ }
-+
-+
-+ if (dev->output_endpoint <= 0) {
-+ /* No interrupt out endpoint. Use the Control Endpoint */
-+ res = libusb_control_transfer(dev->device_handle,
-+ LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT,
-+ 0x09/*HID Set_Report*/,
-+ (2/*HID output*/ << 8) | report_number,
-+ dev->interface,
-+ (unsigned char *)data, length,
-+ 1000/*timeout millis*/);
-+
-+ if (res < 0)
-+ return -1;
-+
-+ if (skipped_report_id)
-+ length++;
-+
-+ return length;
-+ }
-+ else {
-+ /* Use the interrupt out endpoint */
-+ int actual_length;
-+ res = libusb_interrupt_transfer(dev->device_handle,
-+ dev->output_endpoint,
-+ (unsigned char*)data,
-+ length,
-+ &actual_length, 1000);
-+
-+ if (res < 0)
-+ return -1;
-+
-+ if (skipped_report_id)
-+ actual_length++;
-+
-+ return actual_length;
-+ }
-+}
-+
-+/* Helper function, to simplify hid_read().
-+ This should be called with dev->mutex locked. */
-+static int return_data(hid_device *dev, unsigned char *data, size_t length)
-+{
-+ /* Copy the data out of the linked list item (rpt) into the
-+ return buffer (data), and delete the liked list item. */
-+ struct input_report *rpt = dev->input_reports;
-+ size_t len = (length < rpt->len)? length: rpt->len;
-+ if (len > 0)
-+ memcpy(data, rpt->data, len);
-+ dev->input_reports = rpt->next;
-+ free(rpt->data);
-+ free(rpt);
-+ return len;
-+}
-+
-+static void cleanup_mutex(void *param)
-+{
-+ hid_device *dev = param;
-+ pthread_mutex_unlock(&dev->mutex);
-+}
-+
-+
-+int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
-+{
-+ int bytes_read = -1;
-+
-+#if 0
-+ int transferred;
-+ int res = libusb_interrupt_transfer(dev->device_handle, dev->input_endpoint, data, length, &transferred, 5000);
-+ LOG("transferred: %d\n", transferred);
-+ return transferred;
-+#endif
-+
-+ pthread_mutex_lock(&dev->mutex);
-+ pthread_cleanup_push(&cleanup_mutex, dev);
-+
-+ /* There's an input report queued up. Return it. */
-+ if (dev->input_reports) {
-+ /* Return the first one */
-+ bytes_read = return_data(dev, data, length);
-+ goto ret;
-+ }
-+
-+ if (dev->shutdown_thread) {
-+ /* This means the device has been disconnected.
-+ An error code of -1 should be returned. */
-+ bytes_read = -1;
-+ goto ret;
-+ }
-+
-+ if (milliseconds == -1) {
-+ /* Blocking */
-+ while (!dev->input_reports && !dev->shutdown_thread) {
-+ pthread_cond_wait(&dev->condition, &dev->mutex);
-+ }
-+ if (dev->input_reports) {
-+ bytes_read = return_data(dev, data, length);
-+ }
-+ }
-+ else if (milliseconds > 0) {
-+ /* Non-blocking, but called with timeout. */
-+ int res;
-+ struct timespec ts;
-+ clock_gettime(CLOCK_REALTIME, &ts);
-+ ts.tv_sec += milliseconds / 1000;
-+ ts.tv_nsec += (milliseconds % 1000) * 1000000;
-+ if (ts.tv_nsec >= 1000000000L) {
-+ ts.tv_sec++;
-+ ts.tv_nsec -= 1000000000L;
-+ }
-+
-+ while (!dev->input_reports && !dev->shutdown_thread) {
-+ res = pthread_cond_timedwait(&dev->condition, &dev->mutex, &ts);
-+ if (res == 0) {
-+ if (dev->input_reports) {
-+ bytes_read = return_data(dev, data, length);
-+ break;
-+ }
-+
-+ /* If we're here, there was a spurious wake up
-+ or the read thread was shutdown. Run the
-+ loop again (ie: don't break). */
-+ }
-+ else if (res == ETIMEDOUT) {
-+ /* Timed out. */
-+ bytes_read = 0;
-+ break;
-+ }
-+ else {
-+ /* Error. */
-+ bytes_read = -1;
-+ break;
-+ }
-+ }
-+ }
-+ else {
-+ /* Purely non-blocking */
-+ bytes_read = 0;
-+ }
-+
-+ret:
-+ pthread_mutex_unlock(&dev->mutex);
-+ pthread_cleanup_pop(0);
-+
-+ return bytes_read;
-+}
-+
-+int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length)
-+{
-+ return hid_read_timeout(dev, data, length, dev->blocking ? -1 : 0);
-+}
-+
-+int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
-+{
-+ dev->blocking = !nonblock;
-+
-+ return 0;
-+}
-+
-+
-+int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
-+{
-+ int res = -1;
-+ int skipped_report_id = 0;
-+ int report_number = data[0];
-+
-+ if (report_number == 0x0) {
-+ data++;
-+ length--;
-+ skipped_report_id = 1;
-+ }
-+
-+ res = libusb_control_transfer(dev->device_handle,
-+ LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT,
-+ 0x09/*HID set_report*/,
-+ (3/*HID feature*/ << 8) | report_number,
-+ dev->interface,
-+ (unsigned char *)data, length,
-+ 1000/*timeout millis*/);
-+
-+ if (res < 0)
-+ return -1;
-+
-+ /* Account for the report ID */
-+ if (skipped_report_id)
-+ length++;
-+
-+ return length;
-+}
-+
-+int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
-+{
-+ int res = -1;
-+ int skipped_report_id = 0;
-+ int report_number = data[0];
-+
-+ if (report_number == 0x0) {
-+ /* Offset the return buffer by 1, so that the report ID
-+ will remain in byte 0. */
-+ data++;
-+ length--;
-+ skipped_report_id = 1;
-+ }
-+ res = libusb_control_transfer(dev->device_handle,
-+ LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_IN,
-+ 0x01/*HID get_report*/,
-+ (3/*HID feature*/ << 8) | report_number,
-+ dev->interface,
-+ (unsigned char *)data, length,
-+ 1000/*timeout millis*/);
-+
-+ if (res < 0)
-+ return -1;
-+
-+ if (skipped_report_id)
-+ res++;
-+
-+ return res;
-+}
-+
-+
-+void HID_API_EXPORT hid_close(hid_device *dev)
-+{
-+ if (!dev)
-+ return;
-+
-+ /* Cause read_thread() to stop. */
-+ dev->shutdown_thread = 1;
-+ libusb_cancel_transfer(dev->transfer);
-+
-+ /* Wait for read_thread() to end. */
-+ pthread_join(dev->thread, NULL);
-+
-+ /* Clean up the Transfer objects allocated in read_thread(). */
-+ free(dev->transfer->buffer);
-+ libusb_free_transfer(dev->transfer);
-+
-+ /* release the interface */
-+ libusb_release_interface(dev->device_handle, dev->interface);
-+
-+ /* Close the handle */
-+ libusb_close(dev->device_handle);
-+
-+ /* Clear out the queue of received reports. */
-+ pthread_mutex_lock(&dev->mutex);
-+ while (dev->input_reports) {
-+ return_data(dev, NULL, 0);
-+ }
-+ pthread_mutex_unlock(&dev->mutex);
-+
-+ free_hid_device(dev);
-+}
-+
-+
-+int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
-+{
-+ return hid_get_indexed_string(dev, dev->manufacturer_index, string, maxlen);
-+}
-+
-+int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
-+{
-+ return hid_get_indexed_string(dev, dev->product_index, string, maxlen);
-+}
-+
-+int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
-+{
-+ return hid_get_indexed_string(dev, dev->serial_index, string, maxlen);
-+}
-+
-+int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
-+{
-+ wchar_t *str;
-+
-+ str = get_usb_string(dev->device_handle, string_index);
-+ if (str) {
-+ wcsncpy(string, str, maxlen);
-+ string[maxlen-1] = L'\0';
-+ free(str);
-+ return 0;
-+ }
-+ else
-+ return -1;
-+}
-+
-+
-+HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
-+{
-+ return NULL;
-+}
-+
-+
-+struct lang_map_entry {
-+ const char *name;
-+ const char *string_code;
-+ uint16_t usb_code;
-+};
-+
-+#define LANG(name,code,usb_code) { name, code, usb_code }
-+static struct lang_map_entry lang_map[] = {
-+ LANG("Afrikaans", "af", 0x0436),
-+ LANG("Albanian", "sq", 0x041C),
-+ LANG("Arabic - United Arab Emirates", "ar_ae", 0x3801),
-+ LANG("Arabic - Bahrain", "ar_bh", 0x3C01),
-+ LANG("Arabic - Algeria", "ar_dz", 0x1401),
-+ LANG("Arabic - Egypt", "ar_eg", 0x0C01),
-+ LANG("Arabic - Iraq", "ar_iq", 0x0801),
-+ LANG("Arabic - Jordan", "ar_jo", 0x2C01),
-+ LANG("Arabic - Kuwait", "ar_kw", 0x3401),
-+ LANG("Arabic - Lebanon", "ar_lb", 0x3001),
-+ LANG("Arabic - Libya", "ar_ly", 0x1001),
-+ LANG("Arabic - Morocco", "ar_ma", 0x1801),
-+ LANG("Arabic - Oman", "ar_om", 0x2001),
-+ LANG("Arabic - Qatar", "ar_qa", 0x4001),
-+ LANG("Arabic - Saudi Arabia", "ar_sa", 0x0401),
-+ LANG("Arabic - Syria", "ar_sy", 0x2801),
-+ LANG("Arabic - Tunisia", "ar_tn", 0x1C01),
-+ LANG("Arabic - Yemen", "ar_ye", 0x2401),
-+ LANG("Armenian", "hy", 0x042B),
-+ LANG("Azeri - Latin", "az_az", 0x042C),
-+ LANG("Azeri - Cyrillic", "az_az", 0x082C),
-+ LANG("Basque", "eu", 0x042D),
-+ LANG("Belarusian", "be", 0x0423),
-+ LANG("Bulgarian", "bg", 0x0402),
-+ LANG("Catalan", "ca", 0x0403),
-+ LANG("Chinese - China", "zh_cn", 0x0804),
-+ LANG("Chinese - Hong Kong SAR", "zh_hk", 0x0C04),
-+ LANG("Chinese - Macau SAR", "zh_mo", 0x1404),
-+ LANG("Chinese - Singapore", "zh_sg", 0x1004),
-+ LANG("Chinese - Taiwan", "zh_tw", 0x0404),
-+ LANG("Croatian", "hr", 0x041A),
-+ LANG("Czech", "cs", 0x0405),
-+ LANG("Danish", "da", 0x0406),
-+ LANG("Dutch - Netherlands", "nl_nl", 0x0413),
-+ LANG("Dutch - Belgium", "nl_be", 0x0813),
-+ LANG("English - Australia", "en_au", 0x0C09),
-+ LANG("English - Belize", "en_bz", 0x2809),
-+ LANG("English - Canada", "en_ca", 0x1009),
-+ LANG("English - Caribbean", "en_cb", 0x2409),
-+ LANG("English - Ireland", "en_ie", 0x1809),
-+ LANG("English - Jamaica", "en_jm", 0x2009),
-+ LANG("English - New Zealand", "en_nz", 0x1409),
-+ LANG("English - Phillippines", "en_ph", 0x3409),
-+ LANG("English - Southern Africa", "en_za", 0x1C09),
-+ LANG("English - Trinidad", "en_tt", 0x2C09),
-+ LANG("English - Great Britain", "en_gb", 0x0809),
-+ LANG("English - United States", "en_us", 0x0409),
-+ LANG("Estonian", "et", 0x0425),
-+ LANG("Farsi", "fa", 0x0429),
-+ LANG("Finnish", "fi", 0x040B),
-+ LANG("Faroese", "fo", 0x0438),
-+ LANG("French - France", "fr_fr", 0x040C),
-+ LANG("French - Belgium", "fr_be", 0x080C),
-+ LANG("French - Canada", "fr_ca", 0x0C0C),
-+ LANG("French - Luxembourg", "fr_lu", 0x140C),
-+ LANG("French - Switzerland", "fr_ch", 0x100C),
-+ LANG("Gaelic - Ireland", "gd_ie", 0x083C),
-+ LANG("Gaelic - Scotland", "gd", 0x043C),
-+ LANG("German - Germany", "de_de", 0x0407),
-+ LANG("German - Austria", "de_at", 0x0C07),
-+ LANG("German - Liechtenstein", "de_li", 0x1407),
-+ LANG("German - Luxembourg", "de_lu", 0x1007),
-+ LANG("German - Switzerland", "de_ch", 0x0807),
-+ LANG("Greek", "el", 0x0408),
-+ LANG("Hebrew", "he", 0x040D),
-+ LANG("Hindi", "hi", 0x0439),
-+ LANG("Hungarian", "hu", 0x040E),
-+ LANG("Icelandic", "is", 0x040F),
-+ LANG("Indonesian", "id", 0x0421),
-+ LANG("Italian - Italy", "it_it", 0x0410),
-+ LANG("Italian - Switzerland", "it_ch", 0x0810),
-+ LANG("Japanese", "ja", 0x0411),
-+ LANG("Korean", "ko", 0x0412),
-+ LANG("Latvian", "lv", 0x0426),
-+ LANG("Lithuanian", "lt", 0x0427),
-+ LANG("F.Y.R.O. Macedonia", "mk", 0x042F),
-+ LANG("Malay - Malaysia", "ms_my", 0x043E),
-+ LANG("Malay – Brunei", "ms_bn", 0x083E),
-+ LANG("Maltese", "mt", 0x043A),
-+ LANG("Marathi", "mr", 0x044E),
-+ LANG("Norwegian - Bokml", "no_no", 0x0414),
-+ LANG("Norwegian - Nynorsk", "no_no", 0x0814),
-+ LANG("Polish", "pl", 0x0415),
-+ LANG("Portuguese - Portugal", "pt_pt", 0x0816),
-+ LANG("Portuguese - Brazil", "pt_br", 0x0416),
-+ LANG("Raeto-Romance", "rm", 0x0417),
-+ LANG("Romanian - Romania", "ro", 0x0418),
-+ LANG("Romanian - Republic of Moldova", "ro_mo", 0x0818),
-+ LANG("Russian", "ru", 0x0419),
-+ LANG("Russian - Republic of Moldova", "ru_mo", 0x0819),
-+ LANG("Sanskrit", "sa", 0x044F),
-+ LANG("Serbian - Cyrillic", "sr_sp", 0x0C1A),
-+ LANG("Serbian - Latin", "sr_sp", 0x081A),
-+ LANG("Setsuana", "tn", 0x0432),
-+ LANG("Slovenian", "sl", 0x0424),
-+ LANG("Slovak", "sk", 0x041B),
-+ LANG("Sorbian", "sb", 0x042E),
-+ LANG("Spanish - Spain (Traditional)", "es_es", 0x040A),
-+ LANG("Spanish - Argentina", "es_ar", 0x2C0A),
-+ LANG("Spanish - Bolivia", "es_bo", 0x400A),
-+ LANG("Spanish - Chile", "es_cl", 0x340A),
-+ LANG("Spanish - Colombia", "es_co", 0x240A),
-+ LANG("Spanish - Costa Rica", "es_cr", 0x140A),
-+ LANG("Spanish - Dominican Republic", "es_do", 0x1C0A),
-+ LANG("Spanish - Ecuador", "es_ec", 0x300A),
-+ LANG("Spanish - Guatemala", "es_gt", 0x100A),
-+ LANG("Spanish - Honduras", "es_hn", 0x480A),
-+ LANG("Spanish - Mexico", "es_mx", 0x080A),
-+ LANG("Spanish - Nicaragua", "es_ni", 0x4C0A),
-+ LANG("Spanish - Panama", "es_pa", 0x180A),
-+ LANG("Spanish - Peru", "es_pe", 0x280A),
-+ LANG("Spanish - Puerto Rico", "es_pr", 0x500A),
-+ LANG("Spanish - Paraguay", "es_py", 0x3C0A),
-+ LANG("Spanish - El Salvador", "es_sv", 0x440A),
-+ LANG("Spanish - Uruguay", "es_uy", 0x380A),
-+ LANG("Spanish - Venezuela", "es_ve", 0x200A),
-+ LANG("Southern Sotho", "st", 0x0430),
-+ LANG("Swahili", "sw", 0x0441),
-+ LANG("Swedish - Sweden", "sv_se", 0x041D),
-+ LANG("Swedish - Finland", "sv_fi", 0x081D),
-+ LANG("Tamil", "ta", 0x0449),
-+ LANG("Tatar", "tt", 0X0444),
-+ LANG("Thai", "th", 0x041E),
-+ LANG("Turkish", "tr", 0x041F),
-+ LANG("Tsonga", "ts", 0x0431),
-+ LANG("Ukrainian", "uk", 0x0422),
-+ LANG("Urdu", "ur", 0x0420),
-+ LANG("Uzbek - Cyrillic", "uz_uz", 0x0843),
-+ LANG("Uzbek – Latin", "uz_uz", 0x0443),
-+ LANG("Vietnamese", "vi", 0x042A),
-+ LANG("Xhosa", "xh", 0x0434),
-+ LANG("Yiddish", "yi", 0x043D),
-+ LANG("Zulu", "zu", 0x0435),
-+ LANG(NULL, NULL, 0x0),
-+};
-+
-+uint16_t get_usb_code_for_current_locale(void)
-+{
-+ char *locale;
-+ char search_string[64];
-+ char *ptr;
-+ struct lang_map_entry *lang;
-+
-+ /* Get the current locale. */
-+ locale = setlocale(0, NULL);
-+ if (!locale)
-+ return 0x0;
-+
-+ /* Make a copy of the current locale string. */
-+ strncpy(search_string, locale, sizeof(search_string));
-+ search_string[sizeof(search_string)-1] = '\0';
-+
-+ /* Chop off the encoding part, and make it lower case. */
-+ ptr = search_string;
-+ while (*ptr) {
-+ *ptr = tolower(*ptr);
-+ if (*ptr == '.') {
-+ *ptr = '\0';
-+ break;
-+ }
-+ ptr++;
-+ }
-+
-+ /* Find the entry which matches the string code of our locale. */
-+ lang = lang_map;
-+ while (lang->string_code) {
-+ if (!strcmp(lang->string_code, search_string)) {
-+ return lang->usb_code;
-+ }
-+ lang++;
-+ }
-+
-+ /* There was no match. Find with just the language only. */
-+ /* Chop off the variant. Chop it off at the '_'. */
-+ ptr = search_string;
-+ while (*ptr) {
-+ *ptr = tolower(*ptr);
-+ if (*ptr == '_') {
-+ *ptr = '\0';
-+ break;
-+ }
-+ ptr++;
-+ }
-+
-+#if 0 /* TODO: Do we need this? */
-+ /* Find the entry which matches the string code of our language. */
-+ lang = lang_map;
-+ while (lang->string_code) {
-+ if (!strcmp(lang->string_code, search_string)) {
-+ return lang->usb_code;
-+ }
-+ lang++;
-+ }
-+#endif
-+
-+ /* Found nothing. */
-+ return 0x0;
-+}
-+
-+#ifdef __cplusplus
-+}
-+#endif
diff --git a/cad/PrusaSlicer/files/patch-bundled__deps_hints_HintsToPot.cpp b/cad/PrusaSlicer/files/patch-bundled__deps_hints_HintsToPot.cpp
index 4c83f2707722..9a6563bf0682 100644
--- a/cad/PrusaSlicer/files/patch-bundled__deps_hints_HintsToPot.cpp
+++ b/cad/PrusaSlicer/files/patch-bundled__deps_hints_HintsToPot.cpp
@@ -1,4 +1,4 @@
---- bundled_deps/hints/HintsToPot.cpp.orig 2024-09-18 13:39:04 UTC
+--- bundled_deps/hints/HintsToPot.cpp.orig 2024-12-20 11:54:34 UTC
+++ bundled_deps/hints/HintsToPot.cpp
@@ -2,6 +2,7 @@
#include <vector>
diff --git a/cad/PrusaSlicer/files/patch-cmake_modules_FindOpenVDB.cmake b/cad/PrusaSlicer/files/patch-cmake_modules_FindOpenVDB.cmake
index 3a99d042e938..02a12d73302b 100644
--- a/cad/PrusaSlicer/files/patch-cmake_modules_FindOpenVDB.cmake
+++ b/cad/PrusaSlicer/files/patch-cmake_modules_FindOpenVDB.cmake
@@ -1,6 +1,6 @@
---- cmake/modules/FindOpenVDB.cmake.orig 2022-09-06 07:09:19 UTC
+--- cmake/modules/FindOpenVDB.cmake.orig 2025-02-14 18:26:40 UTC
+++ cmake/modules/FindOpenVDB.cmake
-@@ -347,24 +347,24 @@ macro(just_fail msg)
+@@ -347,24 +347,24 @@ endmacro()
return()
endmacro()
@@ -40,7 +40,7 @@
endif()
find_package(TBB ${_quiet} ${_required} COMPONENTS tbb)
find_package(ZLIB ${_quiet} ${_required})
-@@ -451,7 +451,7 @@ if(OpenVDB_USES_LOG4CPLUS)
+@@ -451,7 +451,7 @@ if(OpenVDB_USES_ILM)
endif()
if(OpenVDB_USES_ILM)
@@ -49,7 +49,7 @@
endif()
if(OpenVDB_USES_EXR)
-@@ -463,7 +463,7 @@ if(UNIX)
+@@ -463,7 +463,7 @@ endif()
endif()
# Set deps. Note that the order here is important. If we're building against
@@ -58,7 +58,7 @@
# users chosen namespaced headers are correctly prioritized. Otherwise other
# include paths from shared installs (including houdini) may pull in the wrong
# headers
-@@ -471,7 +471,7 @@ endif()
+@@ -471,7 +471,7 @@ set(_OPENVDB_VISIBLE_DEPENDENCIES
set(_OPENVDB_VISIBLE_DEPENDENCIES
Boost::iostreams
Boost::system
@@ -67,7 +67,7 @@
)
set(_OPENVDB_DEFINITIONS)
-@@ -481,10 +481,10 @@ endif()
+@@ -481,10 +481,10 @@ if(OpenVDB_USES_EXR)
if(OpenVDB_USES_EXR)
list(APPEND _OPENVDB_VISIBLE_DEPENDENCIES
diff --git a/cad/PrusaSlicer/files/patch-src_CMakeLists.txt b/cad/PrusaSlicer/files/patch-src_CMakeLists.txt
index 5e5d7da84a52..e9a16c47e89d 100644
--- a/cad/PrusaSlicer/files/patch-src_CMakeLists.txt
+++ b/cad/PrusaSlicer/files/patch-src_CMakeLists.txt
@@ -1,20 +1,11 @@
---- src/CMakeLists.txt.orig 2024-09-18 13:39:04 UTC
+--- src/CMakeLists.txt.orig 2025-02-14 18:46:38 UTC
+++ src/CMakeLists.txt
-@@ -46,7 +46,7 @@ if (SLIC3R_GUI)
+@@ -48,7 +48,7 @@ if (SLIC3R_GUI)
endif()
find_package(JPEG MODULE QUIET)
- find_package(NanoSVG REQUIRED)
-+ #find_package(NanoSVG REQUIRED)
++ #find_package(NanoSVG REQUIRED)
string(REGEX MATCH "wxpng" WX_PNG_BUILTIN ${wxWidgets_LIBRARIES})
if (PNG_FOUND AND NOT WX_PNG_BUILTIN)
-@@ -109,7 +109,7 @@ endif ()
- set_target_properties(PrusaSlicer PROPERTIES OUTPUT_NAME "prusa-slicer")
- endif ()
-
--target_link_libraries(PrusaSlicer libslic3r libcereal)
-+target_link_libraries(PrusaSlicer libslic3r)
-
- if (APPLE)
- # add_compile_options(-stdlib=libc++)
diff --git a/cad/PrusaSlicer/files/patch-src_hidapi_libusb_hid.c b/cad/PrusaSlicer/files/patch-src_hidapi_libusb_hid.c
deleted file mode 100644
index f5adfcade526..000000000000
--- a/cad/PrusaSlicer/files/patch-src_hidapi_libusb_hid.c
+++ /dev/null
@@ -1,1517 +0,0 @@
---- src/hidapi/libusb/hid.c.orig 2024-10-15 09:14:40 UTC
-+++ src/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;
-+ num_queued++;
-+ }
-+ cur->next = rpt;
-+
-+ /* Pop one off if we've reached 30 in the queue. This
-+ way we don't grow forever if the user never reads
-+ anything from the device. */
-+ if (num_queued > 30) {
-+ return_data(dev, NULL, 0);
-+ }
-+ }
-+ pthread_mutex_unlock(&dev->mutex);
-+ }
-+ else if (transfer->status == LIBUSB_TRANSFER_CANCELLED) {
-+ dev->shutdown_thread = 1;
-+ dev->cancelled = 1;
-+ return;
-+ }
-+ else if (transfer->status == LIBUSB_TRANSFER_NO_DEVICE) {
-+ dev->shutdown_thread = 1;
-+ dev->cancelled = 1;
-+ return;
-+ }
-+ else if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT) {
-+ //LOG("Timeout (normal)\n");
-+ }
-+ else {
-+ LOG("Unknown transfer code: %d\n", transfer->status);
-+ }
-+
-+ /* Re-submit the transfer object. */
-+ res = libusb_submit_transfer(transfer);
-+ if (res != 0) {
-+ LOG("Unable to submit URB. libusb error code: %d\n", res);
-+ dev->shutdown_thread = 1;
-+ dev->cancelled = 1;
-+ }
-+}
-+
-+
-+static void *read_thread(void *param)
-+{
-+ hid_device *dev = param;
-+ unsigned char *buf;
-+ const size_t length = dev->input_ep_max_packet_size;
-+
-+ /* Set up the transfer object. */
-+ buf = malloc(length);
-+ dev->transfer = libusb_alloc_transfer(0);
-+ libusb_fill_interrupt_transfer(dev->transfer,
-+ dev->device_handle,
-+ dev->input_endpoint,
-+ buf,
-+ length,
-+ read_callback,
-+ dev,
-+ 5000/*timeout*/);
-+
-+ /* Make the first submission. Further submissions are made
-+ from inside read_callback() */
-+ libusb_submit_transfer(dev->transfer);
-+
-+ /* Notify the main thread that the read thread is up and running. */
-+ pthread_barrier_wait(&dev->barrier);
-+
-+ /* Handle all the events. */
-+ while (!dev->shutdown_thread) {
-+ int res;
-+ res = libusb_handle_events(usb_context);
-+ if (res < 0) {
-+ /* There was an error. */
-+ LOG("read_thread(): libusb reports error # %d\n", res);
-+
-+ /* Break out of this loop only on fatal error.*/
-+ if (res != LIBUSB_ERROR_BUSY &&
-+ res != LIBUSB_ERROR_TIMEOUT &&
-+ res != LIBUSB_ERROR_OVERFLOW &&
-+ res != LIBUSB_ERROR_INTERRUPTED) {
-+ break;
-+ }
-+ }
-+ }
-+
-+ /* Cancel any transfer that may be pending. This call will fail
-+ if no transfers are pending, but that's OK. */
-+ libusb_cancel_transfer(dev->transfer);
-+
-+ while (!dev->cancelled)
-+ libusb_handle_events_completed(usb_context, &dev->cancelled);
-+
-+ /* Now that the read thread is stopping, Wake any threads which are
-+ waiting on data (in hid_read_timeout()). Do this under a mutex to
-+ make sure that a thread which is about to go to sleep waiting on
-+ the condition actually will go to sleep before the condition is
-+ signaled. */
-+ pthread_mutex_lock(&dev->mutex);
-+ pthread_cond_broadcast(&dev->condition);
-+ pthread_mutex_unlock(&dev->mutex);
-+
-+ /* The dev->transfer->buffer and dev->transfer objects are cleaned up
-+ in hid_close(). They are not cleaned up here because this thread
-+ could end either due to a disconnect or due to a user
-+ call to hid_close(). In both cases the objects can be safely
-+ cleaned up after the call to pthread_join() (in hid_close()), but
-+ since hid_close() calls libusb_cancel_transfer(), on these objects,
-+ they can not be cleaned up here. */
-+
-+ return NULL;
-+}
-+
-+
-+hid_device * HID_API_EXPORT hid_open_path(const char *path)
-+{
-+ hid_device *dev = NULL;
-+
-+ libusb_device **devs;
-+ libusb_device *usb_dev;
-+ int res;
-+ int d = 0;
-+ int good_open = 0;
-+
-+ if(hid_init() < 0)
-+ return NULL;
-+
-+ dev = new_hid_device();
-+
-+ libusb_get_device_list(usb_context, &devs);
-+ while ((usb_dev = devs[d++]) != NULL) {
-+ struct libusb_device_descriptor desc;
-+ struct libusb_config_descriptor *conf_desc = NULL;
-+ int i,j,k;
-+ libusb_get_device_descriptor(usb_dev, &desc);
-+
-+ if (libusb_get_active_config_descriptor(usb_dev, &conf_desc) < 0)
-+ continue;
-+ 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) {
-+ char *dev_path = make_path(usb_dev, intf_desc->bInterfaceNumber);
-+ if (!strcmp(dev_path, path)) {
-+ /* Matched Paths. Open this device */
-+
-+ /* OPEN HERE */
-+ res = libusb_open(usb_dev, &dev->device_handle);
-+ if (res < 0) {
-+ LOG("can't open device\n");
-+ free(dev_path);
-+ break;
-+ }
-+ good_open = 1;
-+#ifdef DETACH_KERNEL_DRIVER
-+ /* Detach the kernel driver, but only if the
-+ device is managed by the kernel */
-+ if (libusb_kernel_driver_active(dev->device_handle, intf_desc->bInterfaceNumber) == 1) {
-+ res = libusb_detach_kernel_driver(dev->device_handle, intf_desc->bInterfaceNumber);
-+ if (res < 0) {
-+ libusb_close(dev->device_handle);
-+ LOG("Unable to detach Kernel Driver\n");
-+ free(dev_path);
-+ good_open = 0;
-+ break;
-+ }
-+ }
-+#endif
-+ res = libusb_claim_interface(dev->device_handle, intf_desc->bInterfaceNumber);
-+ if (res < 0) {
-+ LOG("can't claim interface %d: %d\n", intf_desc->bInterfaceNumber, res);
-+ free(dev_path);
-+ libusb_close(dev->device_handle);
-+ good_open = 0;
-+ break;
-+ }
-+
-+ /* Store off the string descriptor indexes */
-+ dev->manufacturer_index = desc.iManufacturer;
-+ dev->product_index = desc.iProduct;
-+ dev->serial_index = desc.iSerialNumber;
-+
-+ /* Store off the interface number */
-+ dev->interface = intf_desc->bInterfaceNumber;
-+
-+ /* Find the INPUT and OUTPUT endpoints. An
-+ OUTPUT endpoint is not required. */
-+ for (i = 0; i < intf_desc->bNumEndpoints; i++) {
-+ const struct libusb_endpoint_descriptor *ep
-+ = &intf_desc->endpoint[i];
-+
-+ /* Determine the type and direction of this
-+ endpoint. */
-+ int is_interrupt =
-+ (ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK)
-+ == LIBUSB_TRANSFER_TYPE_INTERRUPT;
-+ int is_output =
-+ (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK)
-+ == LIBUSB_ENDPOINT_OUT;
-+ int is_input =
-+ (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK)
-+ == LIBUSB_ENDPOINT_IN;
-+
-+ /* Decide whether to use it for input or output. */
-+ if (dev->input_endpoint == 0 &&
-+ is_interrupt && is_input) {
-+ /* Use this endpoint for INPUT */
-+ dev->input_endpoint = ep->bEndpointAddress;
-+ dev->input_ep_max_packet_size = ep->wMaxPacketSize;
-+ }
-+ if (dev->output_endpoint == 0 &&
-+ is_interrupt && is_output) {
-+ /* Use this endpoint for OUTPUT */
-+ dev->output_endpoint = ep->bEndpointAddress;
-+ }
-+ }
-+
-+ pthread_create(&dev->thread, NULL, read_thread, dev);
-+
-+ /* Wait here for the read thread to be initialized. */
-+ pthread_barrier_wait(&dev->barrier);
-+
-+ }
-+ free(dev_path);
-+ }
-+ }
-+ }
-+ libusb_free_config_descriptor(conf_desc);
-+
-+ }
-+
-+ libusb_free_device_list(devs, 1);
-+
-+ /* If we have a good handle, return it. */
-+ if (good_open) {
-+ return dev;
-+ }
-+ else {
-+ /* Unable to open any devices. */
-+ free_hid_device(dev);
-+ return NULL;
-+ }
-+}
-+
-+
-+int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length)
-+{
-+ int res;
-+ int report_number = data[0];
-+ int skipped_report_id = 0;
-+
-+ if (report_number == 0x0) {
-+ data++;
-+ length--;
-+ skipped_report_id = 1;
-+ }
-+
-+
-+ if (dev->output_endpoint <= 0) {
-+ /* No interrupt out endpoint. Use the Control Endpoint */
-+ res = libusb_control_transfer(dev->device_handle,
-+ LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT,
-+ 0x09/*HID Set_Report*/,
-+ (2/*HID output*/ << 8) | report_number,
-+ dev->interface,
-+ (unsigned char *)data, length,
-+ 1000/*timeout millis*/);
-+
-+ if (res < 0)
-+ return -1;
-+
-+ if (skipped_report_id)
-+ length++;
-+
-+ return length;
-+ }
-+ else {
-+ /* Use the interrupt out endpoint */
-+ int actual_length;
-+ res = libusb_interrupt_transfer(dev->device_handle,
-+ dev->output_endpoint,
-+ (unsigned char*)data,
-+ length,
-+ &actual_length, 1000);
-+
-+ if (res < 0)
-+ return -1;
-+
-+ if (skipped_report_id)
-+ actual_length++;
-+
-+ return actual_length;
-+ }
-+}
-+
-+/* Helper function, to simplify hid_read().
-+ This should be called with dev->mutex locked. */
-+static int return_data(hid_device *dev, unsigned char *data, size_t length)
-+{
-+ /* Copy the data out of the linked list item (rpt) into the
-+ return buffer (data), and delete the liked list item. */
-+ struct input_report *rpt = dev->input_reports;
-+ size_t len = (length < rpt->len)? length: rpt->len;
-+ if (len > 0)
-+ memcpy(data, rpt->data, len);
-+ dev->input_reports = rpt->next;
-+ free(rpt->data);
-+ free(rpt);
-+ return len;
-+}
-+
-+static void cleanup_mutex(void *param)
-+{
-+ hid_device *dev = param;
-+ pthread_mutex_unlock(&dev->mutex);
-+}
-+
-+
-+int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds)
-+{
-+ int bytes_read = -1;
-+
-+#if 0
-+ int transferred;
-+ int res = libusb_interrupt_transfer(dev->device_handle, dev->input_endpoint, data, length, &transferred, 5000);
-+ LOG("transferred: %d\n", transferred);
-+ return transferred;
-+#endif
-+
-+ pthread_mutex_lock(&dev->mutex);
-+ pthread_cleanup_push(&cleanup_mutex, dev);
-+
-+ /* There's an input report queued up. Return it. */
-+ if (dev->input_reports) {
-+ /* Return the first one */
-+ bytes_read = return_data(dev, data, length);
-+ goto ret;
-+ }
-+
-+ if (dev->shutdown_thread) {
-+ /* This means the device has been disconnected.
-+ An error code of -1 should be returned. */
-+ bytes_read = -1;
-+ goto ret;
-+ }
-+
-+ if (milliseconds == -1) {
-+ /* Blocking */
-+ while (!dev->input_reports && !dev->shutdown_thread) {
-+ pthread_cond_wait(&dev->condition, &dev->mutex);
-+ }
-+ if (dev->input_reports) {
-+ bytes_read = return_data(dev, data, length);
-+ }
-+ }
-+ else if (milliseconds > 0) {
-+ /* Non-blocking, but called with timeout. */
-+ int res;
-+ struct timespec ts;
-+ clock_gettime(CLOCK_REALTIME, &ts);
-+ ts.tv_sec += milliseconds / 1000;
-+ ts.tv_nsec += (milliseconds % 1000) * 1000000;
-+ if (ts.tv_nsec >= 1000000000L) {
-+ ts.tv_sec++;
-+ ts.tv_nsec -= 1000000000L;
-+ }
-+
-+ while (!dev->input_reports && !dev->shutdown_thread) {
-+ res = pthread_cond_timedwait(&dev->condition, &dev->mutex, &ts);
-+ if (res == 0) {
-+ if (dev->input_reports) {
-+ bytes_read = return_data(dev, data, length);
-+ break;
-+ }
-+
-+ /* If we're here, there was a spurious wake up
-+ or the read thread was shutdown. Run the
-+ loop again (ie: don't break). */
-+ }
-+ else if (res == ETIMEDOUT) {
-+ /* Timed out. */
-+ bytes_read = 0;
-+ break;
-+ }
-+ else {
-+ /* Error. */
-+ bytes_read = -1;
-+ break;
-+ }
-+ }
-+ }
-+ else {
-+ /* Purely non-blocking */
-+ bytes_read = 0;
-+ }
-+
-+ret:
-+ pthread_mutex_unlock(&dev->mutex);
-+ pthread_cleanup_pop(0);
-+
-+ return bytes_read;
-+}
-+
-+int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length)
-+{
-+ return hid_read_timeout(dev, data, length, dev->blocking ? -1 : 0);
-+}
-+
-+int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock)
-+{
-+ dev->blocking = !nonblock;
-+
-+ return 0;
-+}
-+
-+
-+int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length)
-+{
-+ int res = -1;
-+ int skipped_report_id = 0;
-+ int report_number = data[0];
-+
-+ if (report_number == 0x0) {
-+ data++;
-+ length--;
-+ skipped_report_id = 1;
-+ }
-+
-+ res = libusb_control_transfer(dev->device_handle,
-+ LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT,
-+ 0x09/*HID set_report*/,
-+ (3/*HID feature*/ << 8) | report_number,
-+ dev->interface,
-+ (unsigned char *)data, length,
-+ 1000/*timeout millis*/);
-+
-+ if (res < 0)
-+ return -1;
-+
-+ /* Account for the report ID */
-+ if (skipped_report_id)
-+ length++;
-+
-+ return length;
-+}
-+
-+int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length)
-+{
-+ int res = -1;
-+ int skipped_report_id = 0;
-+ int report_number = data[0];
-+
-+ if (report_number == 0x0) {
-+ /* Offset the return buffer by 1, so that the report ID
-+ will remain in byte 0. */
-+ data++;
-+ length--;
-+ skipped_report_id = 1;
-+ }
-+ res = libusb_control_transfer(dev->device_handle,
-+ LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_IN,
-+ 0x01/*HID get_report*/,
-+ (3/*HID feature*/ << 8) | report_number,
-+ dev->interface,
-+ (unsigned char *)data, length,
-+ 1000/*timeout millis*/);
-+
-+ if (res < 0)
-+ return -1;
-+
-+ if (skipped_report_id)
-+ res++;
-+
-+ return res;
-+}
-+
-+
-+void HID_API_EXPORT hid_close(hid_device *dev)
-+{
-+ if (!dev)
-+ return;
-+
-+ /* Cause read_thread() to stop. */
-+ dev->shutdown_thread = 1;
-+ libusb_cancel_transfer(dev->transfer);
-+
-+ /* Wait for read_thread() to end. */
-+ pthread_join(dev->thread, NULL);
-+
-+ /* Clean up the Transfer objects allocated in read_thread(). */
-+ free(dev->transfer->buffer);
-+ libusb_free_transfer(dev->transfer);
-+
-+ /* release the interface */
-+ libusb_release_interface(dev->device_handle, dev->interface);
-+
-+ /* Close the handle */
-+ libusb_close(dev->device_handle);
-+
-+ /* Clear out the queue of received reports. */
-+ pthread_mutex_lock(&dev->mutex);
-+ while (dev->input_reports) {
-+ return_data(dev, NULL, 0);
-+ }
-+ pthread_mutex_unlock(&dev->mutex);
-+
-+ free_hid_device(dev);
-+}
-+
-+
-+int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen)
-+{
-+ return hid_get_indexed_string(dev, dev->manufacturer_index, string, maxlen);
-+}
-+
-+int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen)
-+{
-+ return hid_get_indexed_string(dev, dev->product_index, string, maxlen);
-+}
-+
-+int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen)
-+{
-+ return hid_get_indexed_string(dev, dev->serial_index, string, maxlen);
-+}
-+
-+int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen)
-+{
-+ wchar_t *str;
-+
-+ str = get_usb_string(dev->device_handle, string_index);
-+ if (str) {
-+ wcsncpy(string, str, maxlen);
-+ string[maxlen-1] = L'\0';
-+ free(str);
-+ return 0;
-+ }
-+ else
-+ return -1;
-+}
-+
-+
-+HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
-+{
-+ return NULL;
-+}
-+
-+
-+struct lang_map_entry {
-+ const char *name;
-+ const char *string_code;
-+ uint16_t usb_code;
-+};
-+
-+#define LANG(name,code,usb_code) { name, code, usb_code }
-+static struct lang_map_entry lang_map[] = {
-+ LANG("Afrikaans", "af", 0x0436),
-+ LANG("Albanian", "sq", 0x041C),
-+ LANG("Arabic - United Arab Emirates", "ar_ae", 0x3801),
-+ LANG("Arabic - Bahrain", "ar_bh", 0x3C01),
-+ LANG("Arabic - Algeria", "ar_dz", 0x1401),
-+ LANG("Arabic - Egypt", "ar_eg", 0x0C01),
-+ LANG("Arabic - Iraq", "ar_iq", 0x0801),
-+ LANG("Arabic - Jordan", "ar_jo", 0x2C01),
-+ LANG("Arabic - Kuwait", "ar_kw", 0x3401),
-+ LANG("Arabic - Lebanon", "ar_lb", 0x3001),
-+ LANG("Arabic - Libya", "ar_ly", 0x1001),
-+ LANG("Arabic - Morocco", "ar_ma", 0x1801),
-+ LANG("Arabic - Oman", "ar_om", 0x2001),
-+ LANG("Arabic - Qatar", "ar_qa", 0x4001),
-+ LANG("Arabic - Saudi Arabia", "ar_sa", 0x0401),
-+ LANG("Arabic - Syria", "ar_sy", 0x2801),
-+ LANG("Arabic - Tunisia", "ar_tn", 0x1C01),
-+ LANG("Arabic - Yemen", "ar_ye", 0x2401),
-+ LANG("Armenian", "hy", 0x042B),
-+ LANG("Azeri - Latin", "az_az", 0x042C),
-+ LANG("Azeri - Cyrillic", "az_az", 0x082C),
-+ LANG("Basque", "eu", 0x042D),
-+ LANG("Belarusian", "be", 0x0423),
-+ LANG("Bulgarian", "bg", 0x0402),
-+ LANG("Catalan", "ca", 0x0403),
-+ LANG("Chinese - China", "zh_cn", 0x0804),
-+ LANG("Chinese - Hong Kong SAR", "zh_hk", 0x0C04),
-+ LANG("Chinese - Macau SAR", "zh_mo", 0x1404),
-+ LANG("Chinese - Singapore", "zh_sg", 0x1004),
-+ LANG("Chinese - Taiwan", "zh_tw", 0x0404),
-+ LANG("Croatian", "hr", 0x041A),
-+ LANG("Czech", "cs", 0x0405),
-+ LANG("Danish", "da", 0x0406),
-+ LANG("Dutch - Netherlands", "nl_nl", 0x0413),
-+ LANG("Dutch - Belgium", "nl_be", 0x0813),
-+ LANG("English - Australia", "en_au", 0x0C09),
-+ LANG("English - Belize", "en_bz", 0x2809),
-+ LANG("English - Canada", "en_ca", 0x1009),
-+ LANG("English - Caribbean", "en_cb", 0x2409),
-+ LANG("English - Ireland", "en_ie", 0x1809),
-+ LANG("English - Jamaica", "en_jm", 0x2009),
-+ LANG("English - New Zealand", "en_nz", 0x1409),
-+ LANG("English - Phillippines", "en_ph", 0x3409),
-+ LANG("English - Southern Africa", "en_za", 0x1C09),
-+ LANG("English - Trinidad", "en_tt", 0x2C09),
-+ LANG("English - Great Britain", "en_gb", 0x0809),
-+ LANG("English - United States", "en_us", 0x0409),
-+ LANG("Estonian", "et", 0x0425),
-+ LANG("Farsi", "fa", 0x0429),
-+ LANG("Finnish", "fi", 0x040B),
-+ LANG("Faroese", "fo", 0x0438),
-+ LANG("French - France", "fr_fr", 0x040C),
-+ LANG("French - Belgium", "fr_be", 0x080C),
-+ LANG("French - Canada", "fr_ca", 0x0C0C),
-+ LANG("French - Luxembourg", "fr_lu", 0x140C),
-+ LANG("French - Switzerland", "fr_ch", 0x100C),
-+ LANG("Gaelic - Ireland", "gd_ie", 0x083C),
-+ LANG("Gaelic - Scotland", "gd", 0x043C),
-+ LANG("German - Germany", "de_de", 0x0407),
-+ LANG("German - Austria", "de_at", 0x0C07),
-+ LANG("German - Liechtenstein", "de_li", 0x1407),
-+ LANG("German - Luxembourg", "de_lu", 0x1007),
-+ LANG("German - Switzerland", "de_ch", 0x0807),
-+ LANG("Greek", "el", 0x0408),
-+ LANG("Hebrew", "he", 0x040D),
-+ LANG("Hindi", "hi", 0x0439),
-+ LANG("Hungarian", "hu", 0x040E),
-+ LANG("Icelandic", "is", 0x040F),
-+ LANG("Indonesian", "id", 0x0421),
-+ LANG("Italian - Italy", "it_it", 0x0410),
-+ LANG("Italian - Switzerland", "it_ch", 0x0810),
-+ LANG("Japanese", "ja", 0x0411),
-+ LANG("Korean", "ko", 0x0412),
-+ LANG("Latvian", "lv", 0x0426),
-+ LANG("Lithuanian", "lt", 0x0427),
-+ LANG("F.Y.R.O. Macedonia", "mk", 0x042F),
-+ LANG("Malay - Malaysia", "ms_my", 0x043E),
-+ LANG("Malay – Brunei", "ms_bn", 0x083E),
-+ LANG("Maltese", "mt", 0x043A),
-+ LANG("Marathi", "mr", 0x044E),
-+ LANG("Norwegian - Bokml", "no_no", 0x0414),
-+ LANG("Norwegian - Nynorsk", "no_no", 0x0814),
-+ LANG("Polish", "pl", 0x0415),
-+ LANG("Portuguese - Portugal", "pt_pt", 0x0816),
-+ LANG("Portuguese - Brazil", "pt_br", 0x0416),
-+ LANG("Raeto-Romance", "rm", 0x0417),
-+ LANG("Romanian - Romania", "ro", 0x0418),
-+ LANG("Romanian - Republic of Moldova", "ro_mo", 0x0818),
-+ LANG("Russian", "ru", 0x0419),
-+ LANG("Russian - Republic of Moldova", "ru_mo", 0x0819),
-+ LANG("Sanskrit", "sa", 0x044F),
-+ LANG("Serbian - Cyrillic", "sr_sp", 0x0C1A),
-+ LANG("Serbian - Latin", "sr_sp", 0x081A),
-+ LANG("Setsuana", "tn", 0x0432),
-+ LANG("Slovenian", "sl", 0x0424),
-+ LANG("Slovak", "sk", 0x041B),
-+ LANG("Sorbian", "sb", 0x042E),
-+ LANG("Spanish - Spain (Traditional)", "es_es", 0x040A),
-+ LANG("Spanish - Argentina", "es_ar", 0x2C0A),
-+ LANG("Spanish - Bolivia", "es_bo", 0x400A),
-+ LANG("Spanish - Chile", "es_cl", 0x340A),
-+ LANG("Spanish - Colombia", "es_co", 0x240A),
-+ LANG("Spanish - Costa Rica", "es_cr", 0x140A),
-+ LANG("Spanish - Dominican Republic", "es_do", 0x1C0A),
-+ LANG("Spanish - Ecuador", "es_ec", 0x300A),
-+ LANG("Spanish - Guatemala", "es_gt", 0x100A),
-+ LANG("Spanish - Honduras", "es_hn", 0x480A),
-+ LANG("Spanish - Mexico", "es_mx", 0x080A),
-+ LANG("Spanish - Nicaragua", "es_ni", 0x4C0A),
-+ LANG("Spanish - Panama", "es_pa", 0x180A),
-+ LANG("Spanish - Peru", "es_pe", 0x280A),
-+ LANG("Spanish - Puerto Rico", "es_pr", 0x500A),
-+ LANG("Spanish - Paraguay", "es_py", 0x3C0A),
-+ LANG("Spanish - El Salvador", "es_sv", 0x440A),
-+ LANG("Spanish - Uruguay", "es_uy", 0x380A),
-+ LANG("Spanish - Venezuela", "es_ve", 0x200A),
-+ LANG("Southern Sotho", "st", 0x0430),
-+ LANG("Swahili", "sw", 0x0441),
-+ LANG("Swedish - Sweden", "sv_se", 0x041D),
-+ LANG("Swedish - Finland", "sv_fi", 0x081D),
-+ LANG("Tamil", "ta", 0x0449),
-+ LANG("Tatar", "tt", 0X0444),
-+ LANG("Thai", "th", 0x041E),
-+ LANG("Turkish", "tr", 0x041F),
-+ LANG("Tsonga", "ts", 0x0431),
-+ LANG("Ukrainian", "uk", 0x0422),
-+ LANG("Urdu", "ur", 0x0420),
-+ LANG("Uzbek - Cyrillic", "uz_uz", 0x0843),
-+ LANG("Uzbek – Latin", "uz_uz", 0x0443),
-+ LANG("Vietnamese", "vi", 0x042A),
-+ LANG("Xhosa", "xh", 0x0434),
-+ LANG("Yiddish", "yi", 0x043D),
-+ LANG("Zulu", "zu", 0x0435),
-+ LANG(NULL, NULL, 0x0),
-+};
-+
-+uint16_t get_usb_code_for_current_locale(void)
-+{
-+ char *locale;
-+ char search_string[64];
-+ char *ptr;
-+ struct lang_map_entry *lang;
-+
-+ /* Get the current locale. */
-+ locale = setlocale(0, NULL);
-+ if (!locale)
-+ return 0x0;
-+
-+ /* Make a copy of the current locale string. */
-+ strncpy(search_string, locale, sizeof(search_string));
-+ search_string[sizeof(search_string)-1] = '\0';
-+
-+ /* Chop off the encoding part, and make it lower case. */
-+ ptr = search_string;
-+ while (*ptr) {
-+ *ptr = tolower(*ptr);
-+ if (*ptr == '.') {
-+ *ptr = '\0';
-+ break;
-+ }
-+ ptr++;
-+ }
-+
-+ /* Find the entry which matches the string code of our locale. */
-+ lang = lang_map;
-+ while (lang->string_code) {
-+ if (!strcmp(lang->string_code, search_string)) {
-+ return lang->usb_code;
-+ }
-+ lang++;
-+ }
-+
-+ /* There was no match. Find with just the language only. */
-+ /* Chop off the variant. Chop it off at the '_'. */
-+ ptr = search_string;
-+ while (*ptr) {
-+ *ptr = tolower(*ptr);
-+ if (*ptr == '_') {
-+ *ptr = '\0';
-+ break;
-+ }
-+ ptr++;
-+ }
-+
-+#if 0 /* TODO: Do we need this? */
-+ /* Find the entry which matches the string code of our language. */
-+ lang = lang_map;
-+ while (lang->string_code) {
-+ if (!strcmp(lang->string_code, search_string)) {
-+ return lang->usb_code;
-+ }
-+ lang++;
-+ }
-+#endif
-+
-+ /* Found nothing. */
-+ return 0x0;
-+}
-+
-+#ifdef __cplusplus
-+}
-+#endif
diff --git a/cad/PrusaSlicer/files/patch-src_libslic3r_Arrange_Core_DataStoreTraits.hpp b/cad/PrusaSlicer/files/patch-src_libslic3r_Arrange_Core_DataStoreTraits.hpp
deleted file mode 100644
index 0208ba7d3b33..000000000000
--- a/cad/PrusaSlicer/files/patch-src_libslic3r_Arrange_Core_DataStoreTraits.hpp
+++ /dev/null
@@ -1,11 +0,0 @@
---- src/libslic3r/Arrange/Core/DataStoreTraits.hpp.orig 2024-11-03 17:50:46 UTC
-+++ src/libslic3r/Arrange/Core/DataStoreTraits.hpp
-@@ -71,7 +71,7 @@ void set_data(ArrItem &itm, const std::string &key, T
- template<class T, class ArrItem>
- void set_data(ArrItem &itm, const std::string &key, T &&data)
- {
-- WritableDataStoreTraits<ArrItem>::template set(itm, key, std::forward<T>(data));
-+ WritableDataStoreTraits<ArrItem>::template set<T>(itm, key, std::forward<T>(data));
- }
-
- template<class T> constexpr bool IsReadWritableDataStore = IsDataStore<T> && IsWritableDataStore<T>;
diff --git a/cad/PrusaSlicer/files/patch-src_libslic3r_Arrange_Core_NFP_NFPConcave__CGAL.cpp b/cad/PrusaSlicer/files/patch-src_libslic3r_Arrange_Core_NFP_NFPConcave__CGAL.cpp
deleted file mode 100644
index b576e929a3a7..000000000000
--- a/cad/PrusaSlicer/files/patch-src_libslic3r_Arrange_Core_NFP_NFPConcave__CGAL.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
---- src/libslic3r/Arrange/Core/NFP/NFPConcave_CGAL.cpp.orig 2024-09-18 13:39:04 UTC
-+++ src/libslic3r/Arrange/Core/NFP/NFPConcave_CGAL.cpp
-@@ -2,6 +2,9 @@
- ///|/
- ///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
- ///|/
-+
-+#include <boost/next_prior.hpp>
-+
- #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
- #include <CGAL/partition_2.h>
- #include <CGAL/Partition_traits_2.h>
diff --git a/cad/PrusaSlicer/files/patch-src_libslic3r_CMakeLists.txt b/cad/PrusaSlicer/files/patch-src_libslic3r_CMakeLists.txt
index f98b32884c91..2e9c5dde9e4d 100644
--- a/cad/PrusaSlicer/files/patch-src_libslic3r_CMakeLists.txt
+++ b/cad/PrusaSlicer/files/patch-src_libslic3r_CMakeLists.txt
@@ -1,6 +1,6 @@
---- src/libslic3r/CMakeLists.txt.orig 2024-09-18 13:39:04 UTC
+--- src/libslic3r/CMakeLists.txt.orig 2024-12-20 11:54:34 UTC
+++ src/libslic3r/CMakeLists.txt
-@@ -611,7 +611,6 @@ target_link_libraries(libslic3r PRIVATE
+@@ -568,7 +568,6 @@ target_link_libraries(libslic3r PRIVATE
target_link_libraries(libslic3r PRIVATE
libnest2d
diff --git a/cad/PrusaSlicer/files/patch-src_libslic3r_CutSurface.cpp b/cad/PrusaSlicer/files/patch-src_libslic3r_CutSurface.cpp
index ef21b28fe2d0..0bba0fdeed85 100644
--- a/cad/PrusaSlicer/files/patch-src_libslic3r_CutSurface.cpp
+++ b/cad/PrusaSlicer/files/patch-src_libslic3r_CutSurface.cpp
@@ -1,4 +1,4 @@
---- src/libslic3r/CutSurface.cpp.orig 2024-09-18 13:39:04 UTC
+--- src/libslic3r/CutSurface.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/libslic3r/CutSurface.cpp
@@ -27,6 +27,8 @@ using namespace Slic3r;
//#define DEBUG_OUTPUT_DIR std::string("C:/data/temp/cutSurface/")
diff --git a/cad/PrusaSlicer/files/patch-src_libslic3r_Format_STEP.cpp b/cad/PrusaSlicer/files/patch-src_libslic3r_Format_STEP.cpp
index 062214443e84..20fef0dd1afc 100644
--- a/cad/PrusaSlicer/files/patch-src_libslic3r_Format_STEP.cpp
+++ b/cad/PrusaSlicer/files/patch-src_libslic3r_Format_STEP.cpp
@@ -1,4 +1,4 @@
---- src/libslic3r/Format/STEP.cpp.orig 2024-04-05 18:42:53 UTC
+--- src/libslic3r/Format/STEP.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/libslic3r/Format/STEP.cpp
@@ -39,7 +39,7 @@ LoadStepFn get_load_step_fn()
#endif
diff --git a/cad/PrusaSlicer/files/patch-src_libslic3r_GCodeSender.cpp b/cad/PrusaSlicer/files/patch-src_libslic3r_GCodeSender.cpp
index 2c326165f35a..3af1ce861020 100644
--- a/cad/PrusaSlicer/files/patch-src_libslic3r_GCodeSender.cpp
+++ b/cad/PrusaSlicer/files/patch-src_libslic3r_GCodeSender.cpp
@@ -1,4 +1,4 @@
---- src/libslic3r/GCodeSender.cpp.orig 2023-12-12 14:21:21 UTC
+--- src/libslic3r/GCodeSender.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/libslic3r/GCodeSender.cpp
@@ -14,7 +14,7 @@
#include <boost/date_time/posix_time/posix_time.hpp>
diff --git a/cad/PrusaSlicer/files/patch-src_libslic3r_Geometry_VoronoiUtilsCgal.cpp b/cad/PrusaSlicer/files/patch-src_libslic3r_Geometry_VoronoiUtilsCgal.cpp
index ed19dfea6089..b95c3f15eed0 100644
--- a/cad/PrusaSlicer/files/patch-src_libslic3r_Geometry_VoronoiUtilsCgal.cpp
+++ b/cad/PrusaSlicer/files/patch-src_libslic3r_Geometry_VoronoiUtilsCgal.cpp
@@ -1,4 +1,4 @@
---- src/libslic3r/Geometry/VoronoiUtilsCgal.cpp.orig 2024-09-18 13:39:04 UTC
+--- src/libslic3r/Geometry/VoronoiUtilsCgal.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/libslic3r/Geometry/VoronoiUtilsCgal.cpp
@@ -2,6 +2,7 @@
///|/
diff --git a/cad/PrusaSlicer/files/patch-src_libslic3r_MeshBoolean.cpp b/cad/PrusaSlicer/files/patch-src_libslic3r_MeshBoolean.cpp
index 70349ca87532..4e67b6351b61 100644
--- a/cad/PrusaSlicer/files/patch-src_libslic3r_MeshBoolean.cpp
+++ b/cad/PrusaSlicer/files/patch-src_libslic3r_MeshBoolean.cpp
@@ -1,4 +1,4 @@
---- src/libslic3r/MeshBoolean.cpp.orig 2024-09-18 13:39:04 UTC
+--- src/libslic3r/MeshBoolean.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/libslic3r/MeshBoolean.cpp
@@ -10,6 +10,8 @@
diff --git a/cad/PrusaSlicer/files/patch-src_libslic3r_Platform.cpp b/cad/PrusaSlicer/files/patch-src_libslic3r_Platform.cpp
index 5eaefd436470..90635161a87d 100644
--- a/cad/PrusaSlicer/files/patch-src_libslic3r_Platform.cpp
+++ b/cad/PrusaSlicer/files/patch-src_libslic3r_Platform.cpp
@@ -1,4 +1,4 @@
---- src/libslic3r/Platform.cpp.orig 2024-09-18 13:39:04 UTC
+--- src/libslic3r/Platform.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/libslic3r/Platform.cpp
@@ -90,6 +90,10 @@ void detect_platform()
BOOST_LOG_TRIVIAL(info) << "Platform: OpenBSD";
diff --git a/cad/PrusaSlicer/files/patch-src_libslic3r_Platform.hpp b/cad/PrusaSlicer/files/patch-src_libslic3r_Platform.hpp
index 1ee9a290c1e8..d6ff89d8d70b 100644
--- a/cad/PrusaSlicer/files/patch-src_libslic3r_Platform.hpp
+++ b/cad/PrusaSlicer/files/patch-src_libslic3r_Platform.hpp
@@ -1,4 +1,4 @@
---- src/libslic3r/Platform.hpp.orig 2023-12-12 14:21:21 UTC
+--- src/libslic3r/Platform.hpp.orig 2024-12-20 11:54:34 UTC
+++ src/libslic3r/Platform.hpp
@@ -29,6 +29,7 @@ enum class PlatformFlavor
WSL, // Microsoft's Windows on Linux (Linux kernel simulated on NTFS kernel)
diff --git a/cad/PrusaSlicer/files/patch-src_libslic3r_SupportSpotsGenerator.cpp b/cad/PrusaSlicer/files/patch-src_libslic3r_SupportSpotsGenerator.cpp
index 78d404572e88..51f9763ed1ea 100644
--- a/cad/PrusaSlicer/files/patch-src_libslic3r_SupportSpotsGenerator.cpp
+++ b/cad/PrusaSlicer/files/patch-src_libslic3r_SupportSpotsGenerator.cpp
@@ -1,4 +1,4 @@
---- src/libslic3r/SupportSpotsGenerator.cpp.orig 2024-09-18 13:39:04 UTC
+--- src/libslic3r/SupportSpotsGenerator.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/libslic3r/SupportSpotsGenerator.cpp
@@ -1062,7 +1062,7 @@ SliceMappings update_active_object_parts(const Layer
}
diff --git a/cad/PrusaSlicer/files/patch-src_libslic3r_Triangulation.cpp b/cad/PrusaSlicer/files/patch-src_libslic3r_Triangulation.cpp
index 832bb05f2ee4..df97343879c7 100644
--- a/cad/PrusaSlicer/files/patch-src_libslic3r_Triangulation.cpp
+++ b/cad/PrusaSlicer/files/patch-src_libslic3r_Triangulation.cpp
@@ -1,4 +1,4 @@
---- src/libslic3r/Triangulation.cpp.orig 2024-09-18 13:39:04 UTC
+--- src/libslic3r/Triangulation.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/libslic3r/Triangulation.cpp
@@ -2,6 +2,9 @@
///|/
diff --git a/cad/PrusaSlicer/files/patch-src_libslic3r_Utils_DirectoriesUtils.cpp b/cad/PrusaSlicer/files/patch-src_libslic3r_Utils_DirectoriesUtils.cpp
index bfe21a052f4d..523c46abb64e 100644
--- a/cad/PrusaSlicer/files/patch-src_libslic3r_Utils_DirectoriesUtils.cpp
+++ b/cad/PrusaSlicer/files/patch-src_libslic3r_Utils_DirectoriesUtils.cpp
@@ -1,4 +1,4 @@
---- src/libslic3r/Utils/DirectoriesUtils.cpp.orig 2024-07-03 10:13:37 UTC
+--- src/libslic3r/Utils/DirectoriesUtils.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/libslic3r/Utils/DirectoriesUtils.cpp
@@ -3,6 +3,7 @@
diff --git a/cad/PrusaSlicer/files/patch-src_occt__wrapper_CMakeLists.txt b/cad/PrusaSlicer/files/patch-src_occt__wrapper_CMakeLists.txt
index 55cd9289846e..f625e775f346 100644
--- a/cad/PrusaSlicer/files/patch-src_occt__wrapper_CMakeLists.txt
+++ b/cad/PrusaSlicer/files/patch-src_occt__wrapper_CMakeLists.txt
@@ -1,4 +1,4 @@
---- src/occt_wrapper/CMakeLists.txt.orig 2024-09-18 13:39:04 UTC
+--- src/occt_wrapper/CMakeLists.txt.orig 2024-12-20 11:54:34 UTC
+++ src/occt_wrapper/CMakeLists.txt
@@ -19,14 +19,13 @@ generate_export_header(OCCTWrapper)
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_CMakeLists.txt b/cad/PrusaSlicer/files/patch-src_slic3r_CMakeLists.txt
index 22fc6d300879..ac4231037482 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_CMakeLists.txt
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_CMakeLists.txt
@@ -1,45 +1,64 @@
---- src/slic3r/CMakeLists.txt.orig 2024-09-18 13:39:04 UTC
+--- src/slic3r/CMakeLists.txt.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/CMakeLists.txt
-@@ -382,7 +382,8 @@ set(SLIC3R_GUI_SOURCES
+@@ -392,11 +392,12 @@ set(SLIC3R_GUI_SOURCES
Utils/ServiceConfig.cpp
)
-find_package(NanoSVG REQUIRED)
-+#find_package(NanoSVG REQUIRED)
-+find_package(OpenSSL REQUIRED)
-
+ if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
++ find_package(NanoSVG REQUIRED)
++endif()
++if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
+ find_package(OpenSSL REQUIRED)
+ endif()
+-
if (APPLE)
list(APPEND SLIC3R_GUI_SOURCES
-@@ -426,7 +427,6 @@ target_link_libraries(
+ Utils/RetinaHelperImpl.mm
+@@ -433,14 +434,13 @@ encoding_check(libslic3r_gui)
+ endforeach()
+
+ encoding_check(libslic3r_gui)
+-
++if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ target_link_libraries(
+ libslic3r_gui
PUBLIC
libslic3r
+ slic3r-arrange-wrapper
avrdude
- libcereal
imgui
libvgcode
GLEW::GLEW
-@@ -434,19 +434,21 @@ target_link_libraries(
- hidapi
- libcurl
- ${wxWidgets_LIBRARIES}
-- NanoSVG::nanosvg
-- NanoSVG::nanosvgrast
- stb_dxt
+@@ -454,10 +454,29 @@ target_link_libraries(
fastfloat
-+ OpenSSL::SSL
-+ OpenSSL::Crypto
+ boost_headeronly
)
++elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
++target_link_libraries(
++ libslic3r_gui
++ PUBLIC
++ libslic3r
++ slic3r-arrange-wrapper
++ avrdude
++ imgui
++ libvgcode
++ GLEW::GLEW
++ OpenGL::GL
++ hidapi
++ libcurl
++ ${wxWidgets_LIBRARIES}
++ stb_dxt
++ fastfloat
++ boost_headeronly
++)
++endif()
if (MSVC)
target_link_libraries(libslic3r_gui PUBLIC Setupapi.lib)
-elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux")
+elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
- target_link_libraries(libslic3r_gui PUBLIC ${DBUS_LIBRARIES})
- elseif (APPLE)
- target_link_libraries(libslic3r_gui PUBLIC ${DISKARBITRATION_LIBRARY} ${COREWLAN_LIBRARY})
- endif()
-+
-+add_definitions(-DBOOST_LOG_DYN_LINK)
-
- #if (SLIC3R_STATIC)
- # FIXME: This was previously exported by wx-config but the wxWidgets
+ target_link_libraries(libslic3r_gui PUBLIC
+ ${DBus1_LIBRARIES}
+ OpenSSL::SSL
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_Config_Snapshot.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_Config_Snapshot.cpp
index 9f340e31fbf0..5a1e905be3a2 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_Config_Snapshot.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_Config_Snapshot.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/Config/Snapshot.cpp.orig 2024-04-05 09:25:31 UTC
+--- src/slic3r/Config/Snapshot.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/Config/Snapshot.cpp
@@ -12,6 +12,7 @@
#include <boost/property_tree/ini_parser.hpp>
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_Config_Version.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_Config_Version.cpp
deleted file mode 100644
index 2481d172a47e..000000000000
--- a/cad/PrusaSlicer/files/patch-src_slic3r_Config_Version.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
---- src/slic3r/Config/Version.cpp.orig 2024-04-05 09:25:31 UTC
-+++ src/slic3r/Config/Version.cpp
-@@ -7,6 +7,7 @@
- #include <cctype>
-
- #include <boost/filesystem/operations.hpp>
-+#include <boost/filesystem/directory.hpp>
- #include <boost/nowide/fstream.hpp>
-
- #include "libslic3r/libslic3r.h"
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_ConfigWizard.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_ConfigWizard.cpp
index 8912fc74fa5c..a065aa8c2a8e 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_ConfigWizard.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_ConfigWizard.cpp
@@ -1,6 +1,6 @@
---- src/slic3r/GUI/ConfigWizard.cpp.orig 2024-09-18 13:39:04 UTC
+--- src/slic3r/GUI/ConfigWizard.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/ConfigWizard.cpp
-@@ -638,7 +638,7 @@ void PageWelcome::set_run_reason(ConfigWizard::RunReas
+@@ -616,7 +616,7 @@ void PageWelcome::set_run_reason(ConfigWizard::RunReas
const bool data_empty = run_reason == ConfigWizard::RR_DATA_EMPTY;
welcome_text->Show(data_empty);
cbox_reset->Show(!data_empty);
@@ -9,7 +9,7 @@
if (!DesktopIntegrationDialog::is_integrated())
cbox_integrate->Show(true);
else
-@@ -1696,7 +1696,7 @@ PageDownloader::PageDownloader(ConfigWizard* parent)
+@@ -1674,7 +1674,7 @@ PageDownloader::PageDownloader(ConfigWizard* parent)
));
}
@@ -18,7 +18,7 @@
append_text(wxString::Format(_L(
"On Linux systems the process of registration also creates desktop integration files for this version of application."
)));
-@@ -1714,7 +1714,7 @@ bool PageDownloader::on_finish_downloader() const
+@@ -1692,7 +1692,7 @@ bool PageDownloader::on_finish_downloader() const
return m_downloader->on_finish();
}
@@ -27,7 +27,7 @@
bool DownloaderUtils::Worker::perform_registration_linux = false;
#endif // __linux__
-@@ -1763,10 +1763,10 @@ bool DownloaderUtils::Worker::perform_url_register()
+@@ -1741,10 +1741,10 @@ bool DownloaderUtils::Worker::perform_url_register()
}
//key_full = "\"C:\\Program Files\\Prusa3D\\PrusaSlicer\\prusa-slicer-console.exe\" \"%1\"";
key_full = key_string;
@@ -40,7 +40,7 @@
// the performation should be called later during desktop integration
perform_registration_linux = true;
#endif
-@@ -1782,9 +1782,9 @@ void DownloaderUtils::Worker::deregister()
+@@ -1760,9 +1760,9 @@ void DownloaderUtils::Worker::deregister()
return;
}
key_full = key_string;
@@ -52,7 +52,7 @@
BOOST_LOG_TRIVIAL(debug) << "DesktopIntegrationDialog::undo_downloader_registration";
DesktopIntegrationDialog::undo_downloader_registration();
perform_registration_linux = false;
-@@ -3421,7 +3421,7 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_c
+@@ -3405,7 +3405,7 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_c
if ((check_unsaved_preset_changes = install_bundles.size() > 0))
header = _L_PLURAL("A new vendor was installed and one of its printers will be activated", "New vendors were installed and one of theirs printers will be activated", install_bundles.size());
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_ConfigWizard.hpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_ConfigWizard.hpp
index 63af1840bafa..ca97e68ee8fa 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_ConfigWizard.hpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_ConfigWizard.hpp
@@ -1,6 +1,6 @@
---- src/slic3r/GUI/ConfigWizard.hpp.orig 2024-09-18 13:39:04 UTC
+--- src/slic3r/GUI/ConfigWizard.hpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/ConfigWizard.hpp
-@@ -54,7 +54,7 @@ namespace DownloaderUtils {
+@@ -50,7 +50,7 @@ namespace DownloaderUtils {
bool on_finish();
static bool perform_download_register(const std::string& path);
static bool perform_url_register();
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_DesktopIntegrationDialog.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_DesktopIntegrationDialog.cpp
index 8ad241e21ebb..ece2bb83f161 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_DesktopIntegrationDialog.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_DesktopIntegrationDialog.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/DesktopIntegrationDialog.cpp.orig 2023-12-12 14:21:21 UTC
+--- src/slic3r/GUI/DesktopIntegrationDialog.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/DesktopIntegrationDialog.cpp
@@ -3,7 +3,7 @@
///|/
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_DesktopIntegrationDialog.hpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_DesktopIntegrationDialog.hpp
index 0b3241780c71..d4af2a0e2023 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_DesktopIntegrationDialog.hpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_DesktopIntegrationDialog.hpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/DesktopIntegrationDialog.hpp.orig 2024-09-18 13:39:04 UTC
+--- src/slic3r/GUI/DesktopIntegrationDialog.hpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/DesktopIntegrationDialog.hpp
@@ -2,7 +2,7 @@
///|/
@@ -9,7 +9,7 @@
#ifndef slic3r_DesktopIntegrationDialog_hpp_
#define slic3r_DesktopIntegrationDialog_hpp_
-@@ -47,4 +47,4 @@ class DesktopIntegrationDialog : public wxDialog (priv
+@@ -49,4 +49,4 @@ class DesktopIntegrationDialog : public wxDialog (publ
} // namespace Slic3r
#endif // slic3r_DesktopIntegrationDialog_hpp_
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_EditGCodeDialog.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_EditGCodeDialog.cpp
index b85d7617c5f8..460db2f94833 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_EditGCodeDialog.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_EditGCodeDialog.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/EditGCodeDialog.cpp.orig 2024-10-15 09:06:23 UTC
+--- src/slic3r/GUI/EditGCodeDialog.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/EditGCodeDialog.cpp
@@ -566,7 +566,7 @@ void ParamsModel::GetValue(wxVariant& variant, const w
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_ExtraRenderers.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_ExtraRenderers.cpp
index f667949aee2e..7c2775c5646d 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_ExtraRenderers.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_ExtraRenderers.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/ExtraRenderers.cpp.orig 2023-12-12 14:21:21 UTC
+--- src/slic3r/GUI/ExtraRenderers.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/ExtraRenderers.cpp
@@ -343,7 +343,7 @@ wxWindow* BitmapChoiceRenderer::CreateEditorCtrl(wxWin
c_editor->SetSelection(atoi(data.GetText().c_str()));
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Field.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Field.cpp
index 5ba4452cf0ed..0a08dc2b0fc5 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Field.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Field.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/Field.cpp.orig 2024-09-18 13:39:04 UTC
+--- src/slic3r/GUI/Field.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/Field.cpp
@@ -222,7 +222,7 @@ static wxString na_value(bool for_spin_ctrl = false)
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_FirmwareDialog.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_FirmwareDialog.cpp
new file mode 100644
index 000000000000..11afaa98d3fb
--- /dev/null
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_FirmwareDialog.cpp
@@ -0,0 +1,20 @@
+--- src/slic3r/GUI/FirmwareDialog.cpp.orig 2025-02-14 23:34:27 UTC
++++ src/slic3r/GUI/FirmwareDialog.cpp
+@@ -365,7 +365,7 @@ bool FirmwareDialog::priv::check_model_id()
+ // return true;
+ // }
+
+- // asio::io_service io;
++ // asio::io_context io;
+ // Serial serial(io, port->port, 115200);
+ // serial.printer_setup();
+
+@@ -429,7 +429,7 @@ void FirmwareDialog::priv::avr109_reboot(const SerialP
+
+ void FirmwareDialog::priv::avr109_reboot(const SerialPortInfo &port)
+ {
+- asio::io_service io;
++ asio::io_context io;
+ Serial serial(io, port.port, 1200);
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
+ }
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GLCanvas3D.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GLCanvas3D.cpp
index 2a9da38ad3af..a08546fb6152 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GLCanvas3D.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GLCanvas3D.cpp
@@ -1,11 +1,11 @@
---- src/slic3r/GUI/GLCanvas3D.cpp.orig 2024-09-18 13:39:04 UTC
+--- src/slic3r/GUI/GLCanvas3D.cpp.orig 2025-02-20 18:44:48 UTC
+++ src/slic3r/GUI/GLCanvas3D.cpp
-@@ -107,7 +107,7 @@ float RetinaHelper::get_scale_factor() { return float(
- #endif // __WXGTK3__
+@@ -13,7 +13,7 @@
- // Fixed the collision between BuildVolume::Type::Convex and macro Convex defined inside /usr/include/X11/X.h that is included by WxWidgets 3.0.
--#if defined(__linux__) && defined(Convex)
-+#if (defined(__linux__) || defined(__FreeBSD__)) && defined(Convex)
- #undef Convex
- #endif
+ #include <igl/unproject.h> // IWYU pragma: keep
+ #include <LocalesUtils.hpp>
+-#include <nanosvgrast.h>
++#include <libnanosvg/nanosvgrast.h>
+ #include "libslic3r/BuildVolume.hpp"
+ #include "libslic3r/ClipperUtils.hpp"
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI.cpp
index 110e5c8a49be..b1589c5a6125 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/GUI.cpp.orig 2024-06-27 09:25:47 UTC
+--- src/slic3r/GUI/GUI.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/GUI.cpp
@@ -296,7 +296,7 @@ void desktop_open_folder(const boost::filesystem::path
const wxString widepath = path.wstring();
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI.hpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI.hpp
index e1da3491b81c..3864d60c17fc 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI.hpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI.hpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/GUI.hpp.orig 2024-06-27 09:25:47 UTC
+--- src/slic3r/GUI/GUI.hpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/GUI.hpp
@@ -74,7 +74,7 @@ void desktop_open_folder(const boost::filesystem::path
// Ask the destop to open the directory specified by path using the default file explorer.
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI__App.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI__App.cpp
index e760f2c122b4..b1d6ed311fab 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI__App.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI__App.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/GUI_App.cpp.orig 2024-09-18 13:39:04 UTC
+--- src/slic3r/GUI/GUI_App.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/GUI_App.cpp
@@ -412,7 +412,7 @@ class SplashScreen : public wxSplashScreen (private)
};
@@ -9,7 +9,7 @@
bool static check_old_linux_datadir(const wxString& app_name) {
// If we are on Linux and the datadir does not exist yet, look into the old
// location where the datadir was before version 2.3. If we find it there,
-@@ -1256,6 +1256,9 @@ bool GUI_App::on_init_inner()
+@@ -1344,6 +1344,9 @@ bool GUI_App::on_init_inner()
// Set initialization of image handlers before any UI actions - See GH issue #7469
wxInitAllImageHandlers();
@@ -19,7 +19,7 @@
// Set our own gui log as an active target
m_log_gui = new LogGui();
wxLog::SetActiveTarget(m_log_gui);
-@@ -1286,7 +1289,7 @@ bool GUI_App::on_init_inner()
+@@ -1374,7 +1377,7 @@ bool GUI_App::on_init_inner()
const wxString resources_dir = from_u8(Slic3r::resources_dir());
wxCHECK_MSG(wxDirExists(resources_dir), false, wxString::Format("Resources path does not exist or is not a directory: %s", resources_dir));
@@ -28,7 +28,7 @@
if (! check_old_linux_datadir(GetAppName())) {
std::cerr << "Quitting, user chose to move their data to new location." << std::endl;
return false;
-@@ -1391,7 +1394,7 @@ bool GUI_App::on_init_inner()
+@@ -1479,7 +1482,7 @@ bool GUI_App::on_init_inner()
if (!default_splashscreen_pos)
// revert "restore_win_position" value if application wasn't crashed
get_app_config()->set("restore_win_position", "1");
@@ -37,7 +37,7 @@
wxYield();
#endif
scrn->SetText(_L("Loading configuration")+ dots);
-@@ -1557,7 +1560,7 @@ bool GUI_App::on_init_inner()
+@@ -1649,7 +1652,7 @@ bool GUI_App::on_init_inner()
// and wxEVT_SET_FOCUS before GUI_App::post_init is called) wasn't called before GUI_App::post_init and OpenGL wasn't initialized.
// Since issue #9774 Where same problem occured on MacOS Ventura, we decided to have this check on MacOS as well.
@@ -46,7 +46,7 @@
if (!m_post_initialized && m_opengl_initialized) {
#else
if (!m_post_initialized) {
-@@ -2247,7 +2250,7 @@ bool GUI_App::switch_language()
+@@ -2339,7 +2342,7 @@ bool GUI_App::switch_language()
}
}
@@ -55,7 +55,7 @@
static const wxLanguageInfo* linux_get_existing_locale_language(const wxLanguageInfo* language,
const wxLanguageInfo* system_language)
{
-@@ -2449,7 +2452,7 @@ bool GUI_App::load_language(wxString language, bool in
+@@ -2541,7 +2544,7 @@ bool GUI_App::load_language(wxString language, bool in
m_language_info_best = wxLocale::FindLanguageInfo(best_language);
BOOST_LOG_TRIVIAL(trace) << boost::format("Best translation language detected (may be different from user locales): %1%") % m_language_info_best->CanonicalName.ToUTF8().data();
}
@@ -64,7 +64,7 @@
wxString lc_all;
if (wxGetEnv("LC_ALL", &lc_all) && ! lc_all.IsEmpty()) {
// Best language returned by wxWidgets on Linux apparently does not respect LC_ALL.
-@@ -2458,6 +2461,7 @@ bool GUI_App::load_language(wxString language, bool in
+@@ -2550,6 +2553,7 @@ bool GUI_App::load_language(wxString language, bool in
}
#endif
}
@@ -72,7 +72,7 @@
}
const wxLanguageInfo *language_info = language.empty() ? nullptr : wxLocale::FindLanguageInfo(language);
-@@ -2502,7 +2506,7 @@ bool GUI_App::load_language(wxString language, bool in
+@@ -2594,7 +2598,7 @@ bool GUI_App::load_language(wxString language, bool in
} else if (m_language_info_system != nullptr && language_info->CanonicalName.BeforeFirst('_') == m_language_info_system->CanonicalName.BeforeFirst('_'))
language_info = m_language_info_system;
@@ -81,7 +81,7 @@
// If we can't find this locale , try to use different one for the language
// instead of just reporting that it is impossible to switch.
if (! wxLocale::IsAvailable(language_info->Language)) {
-@@ -2623,7 +2627,7 @@ wxMenu* GUI_App::get_config_menu(MainFrame* main_frame
+@@ -2715,7 +2719,7 @@ wxMenu* GUI_App::get_config_menu(MainFrame* main_frame
local_menu->Append(config_id_base + ConfigMenuTakeSnapshot, _L("Take Configuration &Snapshot"), _L("Capture a configuration snapshot"));
local_menu->Append(config_id_base + ConfigMenuUpdateConf, _L("Check for Configuration Updates"), _L("Check for configuration updates"));
local_menu->Append(config_id_base + ConfigMenuUpdateApp, _L("Check for Application Updates"), _L("Check for new version of application"));
@@ -90,7 +90,7 @@
//if (DesktopIntegrationDialog::integration_possible())
local_menu->Append(config_id_base + ConfigMenuDesktopIntegration, _L("Desktop Integration"), _L("Desktop Integration"));
#endif //(__linux__) && defined(SLIC3R_DESKTOP_INTEGRATION)
-@@ -2657,7 +2661,7 @@ wxMenu* GUI_App::get_config_menu(MainFrame* main_frame
+@@ -2749,7 +2753,7 @@ wxMenu* GUI_App::get_config_menu(MainFrame* main_frame
case ConfigMenuUpdateApp:
app_version_check(true);
break;
@@ -98,8 +98,8 @@
+#if defined(__linux__) || defined(__FreeBSD__)
case ConfigMenuDesktopIntegration:
show_desktop_integration_dialog();
- break;
-@@ -3336,7 +3340,7 @@ void GUI_App::show_desktop_integration_dialog()
+ break;
+@@ -3393,7 +3397,7 @@ void GUI_App::show_desktop_integration_dialog()
void GUI_App::show_desktop_integration_dialog()
{
@@ -108,7 +108,7 @@
//wxCHECK_MSG(mainframe != nullptr, false, "Internal error: Main frame not created / null");
DesktopIntegrationDialog dialog(mainframe);
dialog.ShowModal();
-@@ -3356,7 +3360,7 @@ void GUI_App::show_downloader_registration_dialog()
+@@ -3413,7 +3417,7 @@ void GUI_App::show_downloader_registration_dialog()
if (msg.ShowModal() == wxID_YES) {
auto downloader_worker = new DownloaderUtils::Worker(nullptr);
downloader_worker->perform_download_register(app_config->get("url_downloader_dest"));
@@ -117,7 +117,7 @@
if (DownloaderUtils::Worker::perform_registration_linux)
DesktopIntegrationDialog::perform_downloader_desktop_integration();
#endif //(__linux__) && defined(SLIC3R_DESKTOP_INTEGRATION)
-@@ -3790,7 +3794,7 @@ void GUI_App::start_download(std::string url)
+@@ -3828,7 +3832,7 @@ void GUI_App::start_download(std::string url)
return;
}
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI__Factories.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI__Factories.cpp
index 154c16db480b..cbb831f8654e 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI__Factories.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI__Factories.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/GUI_Factories.cpp.orig 2024-06-27 09:25:47 UTC
+--- src/slic3r/GUI/GUI_Factories.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/GUI_Factories.cpp
@@ -1499,7 +1499,7 @@ void MenuFactory::sys_color_changed(wxMenuBar* menubar
for (size_t id = 0; id < menubar->GetMenuCount(); id++) {
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI__ObjectLayers.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI__ObjectLayers.cpp
index 3d3eb2c03a9e..ec31c5974dac 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI__ObjectLayers.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI__ObjectLayers.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/GUI_ObjectLayers.cpp.orig 2023-12-12 14:21:21 UTC
+--- src/slic3r/GUI/GUI_ObjectLayers.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/GUI_ObjectLayers.cpp
@@ -348,7 +348,7 @@ LayerRangeEditor::LayerRangeEditor( ObjectLayers* pare
m_enter_pressed = true;
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI__Utils.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI__Utils.cpp
index fce789370d3b..0ae859f3bd37 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI__Utils.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI__Utils.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/GUI_Utils.cpp.orig 2023-12-12 14:21:21 UTC
+--- src/slic3r/GUI/GUI_Utils.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/GUI_Utils.cpp
@@ -53,7 +53,7 @@ void on_window_geometry(wxTopLevelWindow *tlw, std::fu
// cf. https://groups.google.com/forum/#!topic/wx-users/c7ntMt6piRI
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_HintNotification.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_HintNotification.cpp
index 33bd3e4ca053..2b9c52d9b063 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_HintNotification.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_HintNotification.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/HintNotification.cpp.orig 2024-10-15 09:07:17 UTC
+--- src/slic3r/GUI/HintNotification.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/HintNotification.cpp
@@ -161,6 +161,13 @@ TagCheckResult tag_check_system(const std::string& tag
return TagCheckNegative;
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_InstanceCheck.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_InstanceCheck.cpp
index 9eb3e97d2088..d60906306662 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_InstanceCheck.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_InstanceCheck.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/InstanceCheck.cpp.orig 2024-09-18 13:39:04 UTC
+--- src/slic3r/GUI/InstanceCheck.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/InstanceCheck.cpp
@@ -27,7 +27,7 @@
#include <strsafe.h>
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_InstanceCheck.hpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_InstanceCheck.hpp
index 315ec2008339..ee54ff98e56c 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_InstanceCheck.hpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_InstanceCheck.hpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/InstanceCheck.hpp.orig 2023-12-12 14:21:21 UTC
+--- src/slic3r/GUI/InstanceCheck.hpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/InstanceCheck.hpp
@@ -15,7 +15,7 @@
@@ -9,7 +9,7 @@
#include <boost/thread.hpp>
#include <mutex>
#include <condition_variable>
-@@ -42,7 +42,7 @@ namespace GUI {
+@@ -42,7 +42,7 @@ class MainFrame;
class MainFrame;
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_KBShortcutsDialog.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_KBShortcutsDialog.cpp
index 81ba69658470..c8eae334bf0e 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_KBShortcutsDialog.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_KBShortcutsDialog.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/KBShortcutsDialog.cpp.orig 2023-12-12 14:21:21 UTC
+--- src/slic3r/GUI/KBShortcutsDialog.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/KBShortcutsDialog.cpp
@@ -59,7 +59,7 @@ KBShortcutsDialog::KBShortcutsDialog()
main_sizer->SetSizeHints(this);
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Mouse3DController.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Mouse3DController.cpp
index 976cfedd16b8..71f4376a09d4 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Mouse3DController.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Mouse3DController.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/Mouse3DController.cpp.orig 2023-12-12 14:21:21 UTC
+--- src/slic3r/GUI/Mouse3DController.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/Mouse3DController.cpp
@@ -890,7 +890,7 @@ bool Mouse3DController::connect_device()
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_OpenGLManager.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_OpenGLManager.cpp
index d83b04d46975..2eb9e4155ec1 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_OpenGLManager.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_OpenGLManager.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/OpenGLManager.cpp.orig 2024-06-27 09:25:47 UTC
+--- src/slic3r/GUI/OpenGLManager.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/OpenGLManager.cpp
@@ -346,7 +346,7 @@ bool OpenGLManager::init_gl()
if (!m_gl_initialized) {
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_OptionsGroup.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_OptionsGroup.cpp
index 658e4fde073b..5202d514dd53 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_OptionsGroup.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_OptionsGroup.cpp
@@ -1,6 +1,6 @@
---- src/slic3r/GUI/OptionsGroup.cpp.orig 2024-09-18 13:39:04 UTC
+--- src/slic3r/GUI/OptionsGroup.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/OptionsGroup.cpp
-@@ -1216,7 +1216,7 @@ void ogStaticText::SetPathEnd(const std::string& link)
+@@ -1234,7 +1234,7 @@ void ogStaticText::SetPathEnd(const std::string& link)
void ogStaticText::SetPathEnd(const std::string& link)
{
@@ -9,7 +9,7 @@
Bind(wxEVT_ENTER_WINDOW, [this, link](wxMouseEvent& event) {
SetToolTip(OptionsGroup::get_url(get_app_config()->get("suppress_hyperlinks") != "1" ? link : std::string()));
-@@ -1269,7 +1269,7 @@ void ogStaticText::FocusText(bool focus)
+@@ -1287,7 +1287,7 @@ void ogStaticText::FocusText(bool focus)
SetFont(focus ? Slic3r::GUI::wxGetApp().link_font() :
Slic3r::GUI::wxGetApp().normal_font());
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_PhysicalPrinterDialog.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_PhysicalPrinterDialog.cpp
index 2fc2ed86341d..9ad1afe5b965 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_PhysicalPrinterDialog.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_PhysicalPrinterDialog.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/PhysicalPrinterDialog.cpp.orig 2024-09-18 13:39:04 UTC
+--- src/slic3r/GUI/PhysicalPrinterDialog.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/PhysicalPrinterDialog.cpp
@@ -607,7 +607,7 @@ void PhysicalPrinterDialog::build_printhost_settings(C
// Always fill in the "printhost_port" combo box from the config and select it.
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Plater.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Plater.cpp
index cc0f5ef683c6..6afe5c8cc67b 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Plater.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Plater.cpp
@@ -1,6 +1,15 @@
---- src/slic3r/GUI/Plater.cpp.orig 2024-09-18 13:39:04 UTC
+--- src/slic3r/GUI/Plater.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/Plater.cpp
-@@ -894,7 +894,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
+@@ -24,7 +24,7 @@
+
+ #include <cstddef>
+ #include <algorithm>
+-#include <nanosvgrast.h>
++#include <libnanosvg/nanosvgrast.h>
+ #include <numeric>
+ #include <vector>
+ #include <string>
+@@ -912,7 +912,7 @@ void Plater::priv::init()
auto open_external_login = [this](wxCommandEvent& evt){
DownloaderUtils::Worker::perform_url_register();
@@ -9,7 +18,7 @@
// Remove all desktop files registering prusaslicer:// url done by previous versions.
DesktopIntegrationDialog::undo_downloader_registration_rigid();
#if defined(SLIC3R_DESKTOP_INTEGRATION)
-@@ -1201,7 +1201,7 @@ std::vector<size_t> Plater::priv::load_files(const std
+@@ -1228,7 +1228,7 @@ std::vector<size_t> Plater::priv::load_files(const std
// when loading a project file. However, creating the dialog on heap causes issues on macOS, where it does not
// appear at all. Therefore, we create the dialog on stack on Win and macOS, and on heap on Linux, which
// is the only system that needed the workarounds in the first place.
@@ -18,8 +27,8 @@
auto progress_dlg = new wxProgressDialog(loading, "", 100, find_toplevel_parent(q), wxPD_APP_MODAL | wxPD_AUTO_HIDE);
Slic3r::ScopeGuard([&progress_dlg](){ if (progress_dlg) progress_dlg->Destroy(); progress_dlg = nullptr; });
#else
-@@ -1256,7 +1256,7 @@ std::vector<size_t> Plater::priv::load_files(const std
- bool is_project_file = type_prusa;
+@@ -1285,7 +1285,7 @@ std::vector<size_t> Plater::priv::load_files(const std
+
try {
if (type_3mf || type_zip_amf) {
-#ifdef __linux__
@@ -27,7 +36,7 @@
// On Linux Constructor of the ProgressDialog calls DisableOtherWindows() function which causes a disabling of all children of the find_toplevel_parent(q)
// And a destructor of the ProgressDialog calls ReenableOtherWindows() function which revert previously disabled children.
// But if printer technology will be changes during project loading,
-@@ -3225,7 +3225,7 @@ void Plater::priv::on_right_click(RBtnEvent& evt)
+@@ -3552,7 +3552,7 @@ void Plater::priv::on_right_click(RBtnEvent& evt)
Vec2d mouse_position = evt.data.first;
wxPoint position(static_cast<int>(mouse_position.x()),
static_cast<int>(mouse_position.y()));
@@ -36,9 +45,9 @@
// For some reason on Linux the menu isn't displayed if position is
// specified (even though the position is sane).
position = wxDefaultPosition;
-@@ -4106,7 +4106,7 @@ void Plater::load_project(const wxString& filename)
-
- p->reset();
+@@ -4420,7 +4420,7 @@ void Plater::load_project(const wxString& filename)
+ s_multiple_beds.set_loading_project_flag(true);
+ ScopeGuard guard([](){ s_multiple_beds.set_loading_project_flag(false);});
- if (! load_files({ into_path(filename) }).empty()) {
+ if (! load_files((const std::vector<boost::filesystem::path>){ into_path(filename) }).empty()) {
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Preferences.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Preferences.cpp
index a7a651f300ff..4e6cb067029a 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Preferences.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Preferences.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/Preferences.cpp.orig 2024-09-18 13:39:04 UTC
+--- src/slic3r/GUI/Preferences.cpp.orig 2025-02-20 20:11:25 UTC
+++ src/slic3r/GUI/Preferences.cpp
@@ -29,7 +29,7 @@
#ifdef WIN32
@@ -14,11 +14,11 @@
#else
tabs = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_TOP | wxTAB_TRAVERSAL |wxNB_NOPAGETHEME | wxNB_DEFAULT );
-#ifdef __linux__
-+#if defined __linux__ || defined __FreeBSD__
++#if defined(__linux__) || defined(__FreeBSD__)
tabs->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED, [this](wxBookCtrlEvent& e) {
e.Skip();
CallAfter([this]() { tabs->GetCurrentPage()->Layout(); });
-@@ -755,7 +755,7 @@ void PreferencesDialog::accept(wxEvent&)
+@@ -750,7 +750,7 @@ void PreferencesDialog::accept(wxEvent&)
downloader->allow(it->second == "1");
if (!downloader->on_finish())
return;
@@ -27,7 +27,7 @@
if(DownloaderUtils::Worker::perform_registration_linux)
DesktopIntegrationDialog::perform_downloader_desktop_integration();
#endif //(__linux__) && defined(SLIC3R_DESKTOP_INTEGRATION)
-@@ -1113,7 +1113,7 @@ void PreferencesDialog::create_settings_font_widget()
+@@ -1108,7 +1108,7 @@ void PreferencesDialog::create_settings_font_widget()
font_example->SetFont(font);
m_values[opt_key] = format("%1%", val);
stb_sizer->Layout();
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_PresetComboBoxes.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_PresetComboBoxes.cpp
index df5098cb98f3..e739ce322321 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_PresetComboBoxes.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_PresetComboBoxes.cpp
@@ -1,6 +1,6 @@
---- src/slic3r/GUI/PresetComboBoxes.cpp.orig 2024-06-27 09:25:47 UTC
+--- src/slic3r/GUI/PresetComboBoxes.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/PresetComboBoxes.cpp
-@@ -882,7 +882,7 @@ void PlaterPresetComboBox::show_edit_menu()
+@@ -890,7 +890,7 @@ void PlaterPresetComboBox::show_edit_menu()
[this](wxCommandEvent&) { this->switch_to_tab(); }, "cog", menu, []() { return true; }, wxGetApp().plater());
if (m_type == Preset::TYPE_FILAMENT) {
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_PresetComboBoxes.hpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_PresetComboBoxes.hpp
index 073246d91eaf..2c88fdf406c4 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_PresetComboBoxes.hpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_PresetComboBoxes.hpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/PresetComboBoxes.hpp.orig 2024-06-27 09:25:47 UTC
+--- src/slic3r/GUI/PresetComboBoxes.hpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/PresetComboBoxes.hpp
@@ -129,7 +129,7 @@ class PresetComboBox : public BitmapComboBox (protecte
void validate_selection(bool predicate = false);
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_PrintHostDialogs.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_PrintHostDialogs.cpp
index 2e13ab05e8bc..8d3be7de2a9b 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_PrintHostDialogs.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_PrintHostDialogs.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/PrintHostDialogs.cpp.orig 2023-12-12 14:21:21 UTC
+--- src/slic3r/GUI/PrintHostDialogs.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/PrintHostDialogs.cpp
@@ -105,8 +105,8 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::pat
if (size_t extension_start = recent_path.find_last_of('.'); extension_start != std::string::npos)
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_RemovableDriveManager.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_RemovableDriveManager.cpp
index 6491a415a688..e22a92115ac8 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_RemovableDriveManager.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_RemovableDriveManager.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/RemovableDriveManager.cpp.orig 2024-06-27 09:25:47 UTC
+--- src/slic3r/GUI/RemovableDriveManager.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/RemovableDriveManager.cpp
@@ -743,7 +743,7 @@ namespace search_for_drives_internal
//confirms if the file is removable drive and adds it to vector
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Search.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Search.cpp
index 7ac7fddc2862..a6eea20183f1 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Search.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Search.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/Search.cpp.orig 2024-10-15 09:09:17 UTC
+--- src/slic3r/GUI/Search.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/Search.cpp
@@ -455,7 +455,7 @@ void OptionsSearcher::check_and_hide_dialog()
@@ -9,12 +9,3 @@
// Temporary linux specific workaround:
// has_focus(search_dialog) always returns false
// That's why search dialog will be hidden whole the time
-@@ -531,7 +531,7 @@ void OptionsSearcher::process_key_down_from_input(wxKe
- search_dialog->Hide();
- else if (search_dialog && (key == WXK_UP || key == WXK_DOWN || key == WXK_NUMPAD_ENTER || key == WXK_RETURN)) {
- search_dialog->KeyDown(e);
--#ifdef __linux__
-+#if defined(__linux__) || defined(__FreeBSD__)
- search_dialog->SetFocus();
- #endif // __linux__
- }
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Tab.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Tab.cpp
index da78c0abd491..8440ed1e9b42 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Tab.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_Tab.cpp
@@ -1,6 +1,6 @@
---- src/slic3r/GUI/Tab.cpp.orig 2024-09-18 13:39:04 UTC
+--- src/slic3r/GUI/Tab.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/Tab.cpp
-@@ -278,7 +278,7 @@ void Tab::create_preset_tab()
+@@ -279,7 +279,7 @@ void Tab::create_preset_tab()
m_treectrl = new wxTreeCtrl(panel, wxID_ANY, wxDefaultPosition, wxSize(20 * m_em_unit, -1),
wxTR_NO_BUTTONS | wxTR_HIDE_ROOT | wxTR_SINGLE | wxTR_NO_LINES | wxBORDER_SUNKEN | wxWANTS_CHARS);
m_treectrl->SetFont(wxGetApp().normal_font());
@@ -9,7 +9,7 @@
m_treectrl->SetBackgroundColour(m_parent->GetBackgroundColour());
#endif
m_left_sizer->Add(m_treectrl, 1, wxEXPAND);
-@@ -292,7 +292,7 @@ void Tab::create_preset_tab()
+@@ -293,7 +293,7 @@ void Tab::create_preset_tab()
// This helps to process all the cursor key events on Windows in the tree control,
// so that the cursor jumps to the last item.
m_treectrl->Bind(wxEVT_TREE_SEL_CHANGED, [this](wxTreeEvent&) {
@@ -18,7 +18,7 @@
// Events queue is opposite On Linux. wxEVT_SET_FOCUS invokes after wxEVT_TREE_SEL_CHANGED,
// and a result wxEVT_KILL_FOCUS doesn't invoke for the TextCtrls.
// see https://github.com/prusa3d/PrusaSlicer/issues/5720
-@@ -4143,7 +4143,7 @@ bool Tab::tree_sel_change_delayed()
+@@ -4158,7 +4158,7 @@ bool Tab::tree_sel_change_delayed()
// There is a bug related to Ubuntu overlay scrollbars, see https://github.com/prusa3d/PrusaSlicer/issues/898 and https://github.com/prusa3d/PrusaSlicer/issues/952.
// The issue apparently manifests when Show()ing a window with overlay scrollbars while the UI is frozen. For this reason,
// we will Thaw the UI prematurely on Linux. This means destroing the no_updates object prematurely.
@@ -27,7 +27,7 @@
std::unique_ptr<wxWindowUpdateLocker> no_updates(new wxWindowUpdateLocker(this));
#else
/* On Windows we use DoubleBuffering during rendering,
-@@ -4189,7 +4189,7 @@ bool Tab::tree_sel_change_delayed()
+@@ -4204,7 +4204,7 @@ bool Tab::tree_sel_change_delayed()
if (wxGetApp().mainframe!=nullptr && wxGetApp().mainframe->is_active_and_shown_tab(this))
activate_selected_page(throw_if_canceled);
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_TopBar.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_TopBar.cpp
index 966d656c0407..bcc5fe5fc1d8 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_TopBar.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_TopBar.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/TopBar.cpp.orig 2024-10-15 09:10:59 UTC
+--- src/slic3r/GUI/TopBar.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/TopBar.cpp
@@ -52,7 +52,7 @@ TopBarItemsCtrl::Button::Button(wxWindow* parent, cons
Bind(wxEVT_LEAVE_WINDOW, [this](wxMouseEvent& event) { set_hovered(false); event.Skip(); });
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_UnsavedChangesDialog.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_UnsavedChangesDialog.cpp
index ab6e0e643896..78271e53b23f 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_UnsavedChangesDialog.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_UnsavedChangesDialog.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/UnsavedChangesDialog.cpp.orig 2024-09-18 13:39:04 UTC
+--- src/slic3r/GUI/UnsavedChangesDialog.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/UnsavedChangesDialog.cpp
@@ -32,7 +32,7 @@ using boost::optional;
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_UnsavedChangesDialog.hpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_UnsavedChangesDialog.hpp
index 8d783eb5ed2d..f123e6d327d7 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_UnsavedChangesDialog.hpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_UnsavedChangesDialog.hpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/UnsavedChangesDialog.hpp.orig 2024-06-27 09:25:47 UTC
+--- src/slic3r/GUI/UnsavedChangesDialog.hpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/UnsavedChangesDialog.hpp
@@ -49,7 +49,7 @@ class ModelNode
wxString m_mod_color;
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_UpdateDialogs.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_UpdateDialogs.cpp
index d4f691292fa9..b663a0a38fc1 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_UpdateDialogs.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_UpdateDialogs.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/UpdateDialogs.cpp.orig 2024-09-18 13:39:04 UTC
+--- src/slic3r/GUI/UpdateDialogs.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/UpdateDialogs.cpp
@@ -153,7 +153,7 @@ AppUpdateDownloadDialog::AppUpdateDownloadDialog( cons
versions->Add(new wxStaticText(this, wxID_ANY, ver_online.to_string()));
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_UserAccountCommunication.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_UserAccountCommunication.cpp
index c2a79e267391..2ac1dfa7edf9 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_UserAccountCommunication.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_UserAccountCommunication.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/UserAccountCommunication.cpp.orig 2024-09-18 13:39:04 UTC
+--- src/slic3r/GUI/UserAccountCommunication.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/UserAccountCommunication.cpp
@@ -13,6 +13,7 @@
#include <boost/filesystem.hpp>
@@ -35,7 +35,7 @@
load_refresh_token_linux(refresh_token);
#endif
}
-@@ -254,7 +255,7 @@ void UserAccountCommunication::set_username(const std:
+@@ -252,7 +253,7 @@ void UserAccountCommunication::set_username(const std:
save_secret("tokens", m_session->get_shared_session_key(), tokens);
}
else {
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_WipeTowerDialog.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_WipeTowerDialog.cpp
index ffd72a02a351..7b91552d5e09 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_WipeTowerDialog.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_WipeTowerDialog.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/WipeTowerDialog.cpp.orig 2024-10-15 09:12:21 UTC
+--- src/slic3r/GUI/WipeTowerDialog.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/WipeTowerDialog.cpp
@@ -379,7 +379,7 @@ WipingPanel::WipingPanel(wxWindow* parent, const std::
int xpos = m_gridsizer_advanced->GetPosition().x;
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_wxExtensions.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_wxExtensions.cpp
index 218717d59eb6..1c500e9375d2 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_wxExtensions.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_wxExtensions.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/wxExtensions.cpp.orig 2024-06-27 09:25:47 UTC
+--- src/slic3r/GUI/wxExtensions.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/wxExtensions.cpp
@@ -28,7 +28,7 @@
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_wxExtensions.hpp b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_wxExtensions.hpp
index 9f5b292b875d..0e65f9e82281 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_GUI_wxExtensions.hpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_GUI_wxExtensions.hpp
@@ -1,4 +1,4 @@
---- src/slic3r/GUI/wxExtensions.hpp.orig 2024-06-27 09:25:47 UTC
+--- src/slic3r/GUI/wxExtensions.hpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/GUI/wxExtensions.hpp
@@ -21,7 +21,7 @@
#include <boost/filesystem.hpp>
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_Utils_AppUpdater.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_Utils_AppUpdater.cpp
index 6585ac8d34b4..57c327937627 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_Utils_AppUpdater.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_Utils_AppUpdater.cpp
@@ -1,6 +1,6 @@
---- src/slic3r/Utils/AppUpdater.cpp.orig 2024-10-15 09:13:05 UTC
+--- src/slic3r/Utils/AppUpdater.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/Utils/AppUpdater.cpp
-@@ -156,7 +156,7 @@ AppUpdater::priv::priv() :
+@@ -157,7 +157,7 @@ AppUpdater::priv::priv() :
AppUpdater::priv::priv() :
m_cancel (false)
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_Utils_Bonjour.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_Utils_Bonjour.cpp
new file mode 100644
index 000000000000..a2ff47c7adb7
--- /dev/null
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_Utils_Bonjour.cpp
@@ -0,0 +1,47 @@
+--- src/slic3r/Utils/Bonjour.cpp.orig 2025-02-14 23:36:08 UTC
++++ src/slic3r/Utils/Bonjour.cpp
+@@ -624,7 +624,7 @@ UdpSession::UdpSession(Bonjour::ReplyFn rfn) : replyfn
+ buffer.resize(DnsMessage::MAX_SIZE);
+ }
+
+-UdpSocket::UdpSocket( Bonjour::ReplyFn replyfn, const asio::ip::address& multicast_address, const asio::ip::address& interface_address, std::shared_ptr< boost::asio::io_service > io_service)
++UdpSocket::UdpSocket( Bonjour::ReplyFn replyfn, const asio::ip::address& multicast_address, const asio::ip::address& interface_address, std::shared_ptr< boost::asio::io_context > io_service)
+ : replyfn(replyfn)
+ , multicast_address(multicast_address)
+ , socket(*io_service)
+@@ -658,7 +658,7 @@ UdpSocket::UdpSocket( Bonjour::ReplyFn replyfn, const
+ }
+
+
+-UdpSocket::UdpSocket( Bonjour::ReplyFn replyfn, const asio::ip::address& multicast_address, std::shared_ptr< boost::asio::io_service > io_service)
++UdpSocket::UdpSocket( Bonjour::ReplyFn replyfn, const asio::ip::address& multicast_address, std::shared_ptr< boost::asio::io_context > io_service)
+ : replyfn(replyfn)
+ , multicast_address(multicast_address)
+ , socket(*io_service)
+@@ -714,7 +714,7 @@ void UdpSocket::receive_handler(SharedSession session,
+ // let io_service to handle the datagram on session
+ // from boost documentation io_service::post:
+ // The io_service guarantees that the handler will only be called in a thread in which the run(), run_one(), poll() or poll_one() member functions is currently being invoked.
+- io_service->post(boost::bind(&UdpSession::handle_receive, session, error, bytes));
++ io_service->get_executor().post(boost::bind(&UdpSession::handle_receive, session, error, bytes),std::allocator<void>());
+ // immediately accept new datagrams
+ async_receive();
+ }
+@@ -871,7 +871,7 @@ void Bonjour::priv::lookup_perform()
+ {
+ service_dn = (boost::format("_%1%._%2%.local") % service % protocol).str();
+
+- std::shared_ptr< boost::asio::io_service > io_service(new boost::asio::io_service);
++ std::shared_ptr< boost::asio::io_context > io_service(new boost::asio::io_context);
+
+ std::vector<LookupSocket*> sockets;
+
+@@ -966,7 +966,7 @@ void Bonjour::priv::resolve_perform()
+ rpls.push_back(reply);
+ };
+
+- std::shared_ptr< boost::asio::io_service > io_service(new boost::asio::io_service);
++ std::shared_ptr< boost::asio::io_context > io_service(new boost::asio::io_context);
+ std::vector<ResolveSocket*> sockets;
+
+ // resolve interfaces - from PR#6646
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_Utils_Bonjour.hpp b/cad/PrusaSlicer/files/patch-src_slic3r_Utils_Bonjour.hpp
new file mode 100644
index 000000000000..49901b22f613
--- /dev/null
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_Utils_Bonjour.hpp
@@ -0,0 +1,61 @@
+--- src/slic3r/Utils/Bonjour.hpp.orig 2024-12-20 11:54:34 UTC
++++ src/slic3r/Utils/Bonjour.hpp
+@@ -155,11 +155,11 @@ class UdpSocket (public)
+ UdpSocket(Bonjour::ReplyFn replyfn
+ , const boost::asio::ip::address& multicast_address
+ , const boost::asio::ip::address& interface_address
+- , std::shared_ptr< boost::asio::io_service > io_service);
++ , std::shared_ptr< boost::asio::io_context > io_service);
+
+ UdpSocket(Bonjour::ReplyFn replyfn
+ , const boost::asio::ip::address& multicast_address
+- , std::shared_ptr< boost::asio::io_service > io_service);
++ , std::shared_ptr< boost::asio::io_context > io_service);
+
+ void send();
+ void async_receive();
+@@ -172,7 +172,7 @@ class UdpSocket (public)
+ boost::asio::ip::address multicast_address;
+ boost::asio::ip::udp::socket socket;
+ boost::asio::ip::udp::endpoint mcast_endpoint;
+- std::shared_ptr< boost::asio::io_service > io_service;
++ std::shared_ptr< boost::asio::io_context > io_service;
+ std::vector<BonjourRequest> requests;
+ };
+
+@@ -186,7 +186,7 @@ class LookupSocket : public UdpSocket (public)
+ , Bonjour::ReplyFn replyfn
+ , const boost::asio::ip::address& multicast_address
+ , const boost::asio::ip::address& interface_address
+- , std::shared_ptr< boost::asio::io_service > io_service)
++ , std::shared_ptr< boost::asio::io_context > io_service)
+ : UdpSocket(replyfn, multicast_address, interface_address, io_service)
+ , txt_keys(txt_keys)
+ , service(service)
+@@ -203,7 +203,7 @@ class LookupSocket : public UdpSocket (public)
+ , std::string protocol
+ , Bonjour::ReplyFn replyfn
+ , const boost::asio::ip::address& multicast_address
+- , std::shared_ptr< boost::asio::io_service > io_service)
++ , std::shared_ptr< boost::asio::io_context > io_service)
+ : UdpSocket(replyfn, multicast_address, io_service)
+ , txt_keys(txt_keys)
+ , service(service)
+@@ -241,7 +241,7 @@ class ResolveSocket : public UdpSocket (public)
+ , Bonjour::ReplyFn replyfn
+ , const boost::asio::ip::address& multicast_address
+ , const boost::asio::ip::address& interface_address
+- , std::shared_ptr< boost::asio::io_service > io_service)
++ , std::shared_ptr< boost::asio::io_context > io_service)
+ : UdpSocket(replyfn, multicast_address, interface_address, io_service)
+ , hostname(hostname)
+
+@@ -253,7 +253,7 @@ class ResolveSocket : public UdpSocket (public)
+ ResolveSocket(const std::string& hostname
+ , Bonjour::ReplyFn replyfn
+ , const boost::asio::ip::address& multicast_address
+- , std::shared_ptr< boost::asio::io_service > io_service)
++ , std::shared_ptr< boost::asio::io_context > io_service)
+ : UdpSocket(replyfn, multicast_address, io_service)
+ , hostname(hostname)
+
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_Utils_FontConfigHelp.hpp b/cad/PrusaSlicer/files/patch-src_slic3r_Utils_FontConfigHelp.hpp
index 0f4eb01b49e3..4e33b74f261e 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_Utils_FontConfigHelp.hpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_Utils_FontConfigHelp.hpp
@@ -1,4 +1,4 @@
---- src/slic3r/Utils/FontConfigHelp.hpp.orig 2024-09-18 13:39:04 UTC
+--- src/slic3r/Utils/FontConfigHelp.hpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/Utils/FontConfigHelp.hpp
@@ -6,7 +6,7 @@
#define slic3r_FontConfigHelp_hpp_
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_Utils_Serial.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_Utils_Serial.cpp
index 18a9f1904436..71b6ef431f9b 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_Utils_Serial.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_Utils_Serial.cpp
@@ -1,20 +1,16 @@
---- src/slic3r/Utils/Serial.cpp.orig 2023-12-12 14:21:21 UTC
+--- src/slic3r/Utils/Serial.cpp.orig 2025-02-14 23:15:01 UTC
+++ src/slic3r/Utils/Serial.cpp
-@@ -53,7 +53,7 @@
- #include <sys/select.h>
- #endif
+@@ -282,11 +282,11 @@ using boost::system::error_code;
+ namespace asio = boost::asio;
+ using boost::system::error_code;
--#if defined(__APPLE__) || defined(__OpenBSD__)
-+#if defined(__APPLE__) || defined(__OpenBSD__) || defined(__FreeBSD__)
- #include <termios.h>
- #elif defined __linux__
- #include <fcntl.h>
-@@ -346,7 +346,7 @@ void Serial::set_baud_rate(unsigned baud_rate)
- ios.c_cc[VTIME] = 1;
- handle_errno(::ioctl(handle, TCSETS2, &ios));
+-Serial::Serial(asio::io_service& io_service) :
++Serial::Serial(asio::io_context &io_service) :
+ asio::serial_port(io_service)
+ {}
--#elif __OpenBSD__
-+#elif defined(__OpenBSD__) || defined(__FreeBSD__)
- struct termios ios;
- handle_errno(::tcgetattr(handle, &ios));
- handle_errno(::cfsetspeed(&ios, baud_rate));
+-Serial::Serial(asio::io_service& io_service, const std::string &name, unsigned baud_rate) :
++Serial::Serial(asio::io_context &io_service, const std::string &name, unsigned baud_rate) :
+ asio::serial_port(io_service, name)
+ {
+ set_baud_rate(baud_rate);
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_Utils_Serial.hpp b/cad/PrusaSlicer/files/patch-src_slic3r_Utils_Serial.hpp
new file mode 100644
index 000000000000..cd6f8950c00c
--- /dev/null
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_Utils_Serial.hpp
@@ -0,0 +1,13 @@
+--- src/slic3r/Utils/Serial.hpp.orig 2025-02-14 23:32:07 UTC
++++ src/slic3r/Utils/Serial.hpp
+@@ -43,8 +43,8 @@ class Serial : public boost::asio::serial_port (public
+ class Serial : public boost::asio::serial_port
+ {
+ public:
+- Serial(boost::asio::io_service &io_service);
+- Serial(boost::asio::io_service &io_service, const std::string &name, unsigned baud_rate);
++ Serial(boost::asio::io_context &io_service);
++ Serial(boost::asio::io_context &io_service, const std::string &name, unsigned baud_rate);
+ Serial(const Serial &) = delete;
+ Serial &operator=(const Serial &) = delete;
+ ~Serial();
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_Utils_TCPConsole.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_Utils_TCPConsole.cpp
new file mode 100644
index 000000000000..3b2d917b9704
--- /dev/null
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_Utils_TCPConsole.cpp
@@ -0,0 +1,11 @@
+--- src/slic3r/Utils/TCPConsole.cpp.orig 2025-02-14 23:42:57 UTC
++++ src/slic3r/Utils/TCPConsole.cpp
+@@ -161,7 +161,7 @@ bool TCPConsole::run_queue()
+
+ auto endpoints = m_resolver.resolve(m_host_name, m_port_name);
+
+- m_socket.async_connect(endpoints->endpoint(),
++ m_socket.async_connect(endpoints.begin()->endpoint(),
+ boost::bind(&TCPConsole::handle_connect, this, boost::placeholders::_1)
+ );
+
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_Utils_WifiScanner.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_Utils_WifiScanner.cpp
index c1ecd3afc5d1..0d5b53bf59c8 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_Utils_WifiScanner.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_Utils_WifiScanner.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/Utils/WifiScanner.cpp.orig 2024-06-27 09:25:47 UTC
+--- src/slic3r/Utils/WifiScanner.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/Utils/WifiScanner.cpp
@@ -16,7 +16,7 @@
#include "WifiScannerMac.h"
diff --git a/cad/PrusaSlicer/files/patch-src_slic3r_Utils_WxFontUtils.cpp b/cad/PrusaSlicer/files/patch-src_slic3r_Utils_WxFontUtils.cpp
index 5df7a478eadd..fa75da933a4a 100644
--- a/cad/PrusaSlicer/files/patch-src_slic3r_Utils_WxFontUtils.cpp
+++ b/cad/PrusaSlicer/files/patch-src_slic3r_Utils_WxFontUtils.cpp
@@ -1,4 +1,4 @@
---- src/slic3r/Utils/WxFontUtils.cpp.orig 2024-09-18 13:39:04 UTC
+--- src/slic3r/Utils/WxFontUtils.cpp.orig 2024-12-20 11:54:34 UTC
+++ src/slic3r/Utils/WxFontUtils.cpp
@@ -19,7 +19,7 @@
#include <wx/uri.h>
diff --git a/cad/PrusaSlicer/files/patch-tests_fff__print_test__data.cpp b/cad/PrusaSlicer/files/patch-tests_fff__print_test__data.cpp
index 7a3be2acbfdf..57c842839110 100644
--- a/cad/PrusaSlicer/files/patch-tests_fff__print_test__data.cpp
+++ b/cad/PrusaSlicer/files/patch-tests_fff__print_test__data.cpp
@@ -1,7 +1,7 @@
---- tests/fff_print/test_data.cpp.orig 2023-07-25 13:20:52 UTC
+--- tests/fff_print/test_data.cpp.orig 2024-12-20 11:54:34 UTC
+++ tests/fff_print/test_data.cpp
-@@ -8,6 +8,7 @@
- #include "libslic3r/Format/STL.hpp"
+@@ -10,6 +10,7 @@
+ #include <arrange-wrapper/ModelArrange.hpp>
#include <cstdlib>
+#include <fstream>
diff --git a/cad/PrusaSlicer/files/patch-tests_libslic3r_test__emboss.cpp b/cad/PrusaSlicer/files/patch-tests_libslic3r_test__emboss.cpp
index 5421f3b1f7c4..99ba4f0953a6 100644
--- a/cad/PrusaSlicer/files/patch-tests_libslic3r_test__emboss.cpp
+++ b/cad/PrusaSlicer/files/patch-tests_libslic3r_test__emboss.cpp
@@ -1,6 +1,6 @@
---- tests/libslic3r/test_emboss.cpp.orig 2024-09-18 13:39:04 UTC
+--- tests/libslic3r/test_emboss.cpp.orig 2024-12-20 11:54:34 UTC
+++ tests/libslic3r/test_emboss.cpp
-@@ -196,7 +196,7 @@ TEST_CASE("Visualize glyph from font", "[Emboss]")
+@@ -197,7 +197,7 @@ TEST_CASE("Visualize glyph from font", "[Emboss]")
#endif // VISUALIZE
#include "test_utils.hpp"
diff --git a/cad/PrusaSlicer/pkg-plist b/cad/PrusaSlicer/pkg-plist
index 4160841a7ea5..451394fa3823 100644
--- a/cad/PrusaSlicer/pkg-plist
+++ b/cad/PrusaSlicer/pkg-plist
@@ -1,11 +1,1089 @@
bin/prusa-gcodeviewer
bin/prusa-slicer
lib/OCCTWrapper.so
-share/applications/PrusaSlicer.desktop
+%%DATADIR%%/data/embossed_text.obj
+%%DATADIR%%/data/hints.ini
+%%DATADIR%%/fonts/NotoSans-Regular.ttf
+%%DATADIR%%/fonts/NotoSansCJK-Regular.ttc
+%%DATADIR%%/fonts/README.txt
+%%DATADIR%%/icons/Pmetal_001.png
+%%DATADIR%%/icons/PrusaSlicer-gcodeviewer-mac_128px.png
+%%DATADIR%%/icons/PrusaSlicer-gcodeviewer.ico
+%%DATADIR%%/icons/PrusaSlicer-gcodeviewer.svg
+%%DATADIR%%/icons/PrusaSlicer-gcodeviewer_128px.png
+%%DATADIR%%/icons/PrusaSlicer-gcodeviewer_192px.png
+%%DATADIR%%/icons/PrusaSlicer-gcodeviewer_32px.png
+%%DATADIR%%/icons/PrusaSlicer-mac_128px.png
+%%DATADIR%%/icons/PrusaSlicer.icns
+%%DATADIR%%/icons/PrusaSlicer.ico
+%%DATADIR%%/icons/PrusaSlicer.png
+%%DATADIR%%/icons/PrusaSlicer.svg
+%%DATADIR%%/icons/PrusaSlicer_128px.png
+%%DATADIR%%/icons/PrusaSlicer_192px.png
+%%DATADIR%%/icons/PrusaSlicer_192px_grayscale.png
+%%DATADIR%%/icons/PrusaSlicer_192px_transparent.png
+%%DATADIR%%/icons/PrusaSlicer_32px.png
+%%DATADIR%%/icons/add.svg
+%%DATADIR%%/icons/add_copies.svg
+%%DATADIR%%/icons/add_gcode.svg
+%%DATADIR%%/icons/add_modifier.svg
+%%DATADIR%%/icons/add_negative.svg
+%%DATADIR%%/icons/add_part.svg
+%%DATADIR%%/icons/add_text_modifier.svg
+%%DATADIR%%/icons/add_text_negative.svg
+%%DATADIR%%/icons/add_text_part.svg
+%%DATADIR%%/icons/advanced_plus.svg
+%%DATADIR%%/icons/align_horizontal_center.svg
+%%DATADIR%%/icons/align_horizontal_left.svg
+%%DATADIR%%/icons/align_horizontal_right.svg
+%%DATADIR%%/icons/align_vertical_bottom.svg
+%%DATADIR%%/icons/align_vertical_center.svg
+%%DATADIR%%/icons/align_vertical_top.svg
+%%DATADIR%%/icons/arrange.svg
+%%DATADIR%%/icons/arrange_current.svg
+%%DATADIR%%/icons/attention.svg
+%%DATADIR%%/icons/browse.svg
+%%DATADIR%%/icons/bullet_black.png
+%%DATADIR%%/icons/bullet_blue.png
+%%DATADIR%%/icons/bullet_white.png
+%%DATADIR%%/icons/burn.svg
+%%DATADIR%%/icons/change_extruder.svg
+%%DATADIR%%/icons/check_off.svg
+%%DATADIR%%/icons/check_off_disabled.svg
+%%DATADIR%%/icons/check_off_focused.svg
+%%DATADIR%%/icons/check_on.svg
+%%DATADIR%%/icons/check_on_disabled.svg
+%%DATADIR%%/icons/check_on_focused.svg
+%%DATADIR%%/icons/checked.svg
+%%DATADIR%%/icons/cog.svg
+%%DATADIR%%/icons/cog_.svg
+%%DATADIR%%/icons/cog_f.svg
+%%DATADIR%%/icons/cog_go.png
+%%DATADIR%%/icons/collapse.svg
+%%DATADIR%%/icons/collapse_btn.svg
+%%DATADIR%%/icons/colorchange_add.svg
+%%DATADIR%%/icons/colorchange_add_f.svg
+%%DATADIR%%/icons/colorchange_add_m.svg
+%%DATADIR%%/icons/colorchange_del.svg
+%%DATADIR%%/icons/colorchange_del_f.svg
+%%DATADIR%%/icons/compare.svg
+%%DATADIR%%/icons/connect_gcode.svg
+%%DATADIR%%/icons/connect_status.svg
+%%DATADIR%%/icons/convert_file.svg
+%%DATADIR%%/icons/cooling.svg
+%%DATADIR%%/icons/copy.svg
+%%DATADIR%%/icons/copy_menu.svg
+%%DATADIR%%/icons/cross.svg
+%%DATADIR%%/icons/cross_focus.svg
+%%DATADIR%%/icons/cross_focus_large.svg
+%%DATADIR%%/icons/custom-gcode_gcode.svg
+%%DATADIR%%/icons/custom-gcode_measure.svg
+%%DATADIR%%/icons/custom-gcode_object-info.svg
+%%DATADIR%%/icons/custom-gcode_single.svg
+%%DATADIR%%/icons/custom-gcode_slicing-state.svg
+%%DATADIR%%/icons/custom-gcode_slicing-state_global.svg
+%%DATADIR%%/icons/custom-gcode_stats.svg
+%%DATADIR%%/icons/custom-gcode_vector-index.svg
+%%DATADIR%%/icons/custom-gcode_vector.svg
+%%DATADIR%%/icons/cut.svg
+%%DATADIR%%/icons/cut_.svg
+%%DATADIR%%/icons/cut_connectors.svg
+%%DATADIR%%/icons/delete.svg
+%%DATADIR%%/icons/delete_all.svg
+%%DATADIR%%/icons/delete_all_menu.svg
+%%DATADIR%%/icons/dot.svg
+%%DATADIR%%/icons/dot_small.svg
+%%DATADIR%%/icons/dot_white.svg
+%%DATADIR%%/icons/dowel.svg
+%%DATADIR%%/icons/drop_down.svg
+%%DATADIR%%/icons/drop_to_bed.svg
+%%DATADIR%%/icons/edit.svg
+%%DATADIR%%/icons/edit_button.svg
+%%DATADIR%%/icons/edit_button_pressed.svg
+%%DATADIR%%/icons/edit_gcode.svg
+%%DATADIR%%/icons/edit_gcode_f.svg
+%%DATADIR%%/icons/edit_layers_all.svg
+%%DATADIR%%/icons/edit_layers_some.svg
+%%DATADIR%%/icons/edit_uni.svg
+%%DATADIR%%/icons/editor.svg
+%%DATADIR%%/icons/editor_menu.svg
+%%DATADIR%%/icons/eject_sd.svg
+%%DATADIR%%/icons/empty.svg
+%%DATADIR%%/icons/equal.svg
+%%DATADIR%%/icons/error_tick.svg
+%%DATADIR%%/icons/error_tick_f.svg
+%%DATADIR%%/icons/exclamation.svg
+%%DATADIR%%/icons/exclamation_manifold.svg
+%%DATADIR%%/icons/exit.svg
+%%DATADIR%%/icons/expand_btn.svg
+%%DATADIR%%/icons/export_config.svg
+%%DATADIR%%/icons/export_config_bundle.svg
+%%DATADIR%%/icons/export_gcode.svg
+%%DATADIR%%/icons/export_plater.svg
+%%DATADIR%%/icons/export_to_sd.svg
+%%DATADIR%%/icons/eye_closed.svg
+%%DATADIR%%/icons/eye_open.svg
+%%DATADIR%%/icons/fdm_supports.svg
+%%DATADIR%%/icons/fdm_supports_.svg
+%%DATADIR%%/icons/flag_green.svg
+%%DATADIR%%/icons/flag_red.svg
+%%DATADIR%%/icons/funnel.svg
+%%DATADIR%%/icons/fuzzy_skin.svg
+%%DATADIR%%/icons/fuzzy_skin_painting.svg
+%%DATADIR%%/icons/fuzzy_skin_painting_.svg
+%%DATADIR%%/icons/gcode.icns
+%%DATADIR%%/icons/hollow.svg
+%%DATADIR%%/icons/hollowing.svg
+%%DATADIR%%/icons/horizontal_hide.svg
+%%DATADIR%%/icons/horizontal_show.svg
+%%DATADIR%%/icons/import_config.svg
+%%DATADIR%%/icons/import_config_bundle.svg
+%%DATADIR%%/icons/import_plater.svg
+%%DATADIR%%/icons/infill.svg
+%%DATADIR%%/icons/info.svg
+%%DATADIR%%/icons/instance_add.svg
+%%DATADIR%%/icons/instance_remove.svg
+%%DATADIR%%/icons/ironing.svg
+%%DATADIR%%/icons/layers.svg
+%%DATADIR%%/icons/layers_white.svg
+%%DATADIR%%/icons/legend_cog.svg
+%%DATADIR%%/icons/legend_colorchanges.svg
+%%DATADIR%%/icons/legend_customgcodes.svg
+%%DATADIR%%/icons/legend_deretract.svg
+%%DATADIR%%/icons/legend_pauseprints.svg
+%%DATADIR%%/icons/legend_retract.svg
+%%DATADIR%%/icons/legend_seams.svg
+%%DATADIR%%/icons/legend_shells.svg
+%%DATADIR%%/icons/legend_toolchanges.svg
+%%DATADIR%%/icons/legend_toolmarker.svg
+%%DATADIR%%/icons/legend_travel.svg
+%%DATADIR%%/icons/legend_wipe.svg
+%%DATADIR%%/icons/lock.svg
+%%DATADIR%%/icons/lock_closed.svg
+%%DATADIR%%/icons/lock_closed_f.svg
+%%DATADIR%%/icons/lock_closed_white.svg
+%%DATADIR%%/icons/lock_open.svg
+%%DATADIR%%/icons/lock_open_f.svg
+%%DATADIR%%/icons/lock_open_sys.svg
+%%DATADIR%%/icons/login.svg
+%%DATADIR%%/icons/logout.svg
+%%DATADIR%%/icons/make_bold.svg
+%%DATADIR%%/icons/make_italic.svg
+%%DATADIR%%/icons/make_unbold.svg
+%%DATADIR%%/icons/make_unitalic.svg
+%%DATADIR%%/icons/mark_X.svg
+%%DATADIR%%/icons/mark_Y.svg
+%%DATADIR%%/icons/mark_Z.svg
+%%DATADIR%%/icons/measure.svg
+%%DATADIR%%/icons/mirroring_off.svg
+%%DATADIR%%/icons/mirroring_on.svg
+%%DATADIR%%/icons/mirroring_transparent.svg
+%%DATADIR%%/icons/mmu_segmentation.svg
+%%DATADIR%%/icons/mmu_segmentation_.svg
+%%DATADIR%%/icons/mode.svg
+%%DATADIR%%/icons/mode_advanced.svg
+%%DATADIR%%/icons/mode_expert.svg
+%%DATADIR%%/icons/mode_simple.svg
+%%DATADIR%%/icons/move.svg
+%%DATADIR%%/icons/not_equal.svg
+%%DATADIR%%/icons/note.svg
+%%DATADIR%%/icons/notification_cancel.svg
+%%DATADIR%%/icons/notification_cancel_hover.svg
+%%DATADIR%%/icons/notification_clippy.svg
+%%DATADIR%%/icons/notification_close.svg
+%%DATADIR%%/icons/notification_close_hover.svg
+%%DATADIR%%/icons/notification_documentation.svg
+%%DATADIR%%/icons/notification_documentation_hover.svg
+%%DATADIR%%/icons/notification_eject_sd.svg
+%%DATADIR%%/icons/notification_eject_sd_hover.svg
+%%DATADIR%%/icons/notification_error.svg
+%%DATADIR%%/icons/notification_info.svg
+%%DATADIR%%/icons/notification_minimalize.svg
+%%DATADIR%%/icons/notification_minimalize_hover.svg
+%%DATADIR%%/icons/notification_open.svg
+%%DATADIR%%/icons/notification_open_hover.svg
+%%DATADIR%%/icons/notification_pause.svg
+%%DATADIR%%/icons/notification_pause_hover.svg
+%%DATADIR%%/icons/notification_play.svg
+%%DATADIR%%/icons/notification_play_hover.svg
+%%DATADIR%%/icons/notification_preferences.svg
+%%DATADIR%%/icons/notification_preferences_hover.svg
+%%DATADIR%%/icons/notification_right.svg
+%%DATADIR%%/icons/notification_right_hover.svg
+%%DATADIR%%/icons/notification_warning.svg
+%%DATADIR%%/icons/notification_warning_grey.svg
+%%DATADIR%%/icons/number_of_copies.svg
+%%DATADIR%%/icons/numbers.png
+%%DATADIR%%/icons/objlist_info.svg
+%%DATADIR%%/icons/open.svg
+%%DATADIR%%/icons/open_browser.svg
+%%DATADIR%%/icons/output+page_white.svg
+%%DATADIR%%/icons/pad.svg
+%%DATADIR%%/icons/paste.svg
+%%DATADIR%%/icons/paste_menu.svg
+%%DATADIR%%/icons/pause_print.svg
+%%DATADIR%%/icons/pause_print_f.svg
+%%DATADIR%%/icons/place.svg
+%%DATADIR%%/icons/plater.svg
+%%DATADIR%%/icons/plug.svg
+%%DATADIR%%/icons/preview.svg
+%%DATADIR%%/icons/preview_menu.svg
+%%DATADIR%%/icons/print_finished.svg
+%%DATADIR%%/icons/print_idle.svg
+%%DATADIR%%/icons/print_running.svg
+%%DATADIR%%/icons/printer.svg
+%%DATADIR%%/icons/printer_available.svg
+%%DATADIR%%/icons/printer_busy.svg
+%%DATADIR%%/icons/printer_offline.svg
+%%DATADIR%%/icons/printer_placeholder.png
+%%DATADIR%%/icons/printer_white.svg
+%%DATADIR%%/icons/question.svg
+%%DATADIR%%/icons/re_slice.svg
+%%DATADIR%%/icons/redo.svg
+%%DATADIR%%/icons/redo_menu.svg
+%%DATADIR%%/icons/redo_toolbar.svg
+%%DATADIR%%/icons/reflection_x.svg
+%%DATADIR%%/icons/reflection_y.svg
+%%DATADIR%%/icons/refresh.svg
+%%DATADIR%%/icons/remove.svg
+%%DATADIR%%/icons/remove_copies.svg
+%%DATADIR%%/icons/remove_menu.svg
+%%DATADIR%%/icons/resin.svg
+%%DATADIR%%/icons/revert_all_.svg
+%%DATADIR%%/icons/rotate.svg
+%%DATADIR%%/icons/save.svg
+%%DATADIR%%/icons/scalar_param.svg
+%%DATADIR%%/icons/scale.svg
+%%DATADIR%%/icons/seam.svg
+%%DATADIR%%/icons/seam_.svg
+%%DATADIR%%/icons/search.svg
+%%DATADIR%%/icons/search_.svg
+%%DATADIR%%/icons/search_blink.svg
+%%DATADIR%%/icons/search_gray.svg
+%%DATADIR%%/icons/set_separate_obj.svg
+%%DATADIR%%/icons/settings.svg
+%%DATADIR%%/icons/shape_gallery.svg
+%%DATADIR%%/icons/sinking.svg
+%%DATADIR%%/icons/skirt+brim.svg
+%%DATADIR%%/icons/sla_printer.svg
+%%DATADIR%%/icons/sla_printer_available.svg
+%%DATADIR%%/icons/sla_printer_busy.svg
+%%DATADIR%%/icons/sla_printer_offline.svg
+%%DATADIR%%/icons/sla_supports.svg
+%%DATADIR%%/icons/sla_view_original.svg
+%%DATADIR%%/icons/sla_view_processed.svg
+%%DATADIR%%/icons/slice_all.svg
+%%DATADIR%%/icons/snap.svg
+%%DATADIR%%/icons/spin_dec.svg
+%%DATADIR%%/icons/spin_dec_act.svg
+%%DATADIR%%/icons/spin_inc.svg
+%%DATADIR%%/icons/spin_inc_act.svg
+%%DATADIR%%/icons/splashscreen-gcodepreview.jpg
+%%DATADIR%%/icons/splashscreen.jpg
+%%DATADIR%%/icons/split_object_SMALL.svg
+%%DATADIR%%/icons/split_objects.svg
+%%DATADIR%%/icons/split_parts.svg
+%%DATADIR%%/icons/split_parts_SMALL.svg
+%%DATADIR%%/icons/spool.svg
+%%DATADIR%%/icons/stl.icns
+%%DATADIR%%/icons/support.svg
+%%DATADIR%%/icons/support_blocker.svg
+%%DATADIR%%/icons/support_enforcer.svg
+%%DATADIR%%/icons/svg_modifier.svg
+%%DATADIR%%/icons/svg_negative.svg
+%%DATADIR%%/icons/svg_part.svg
+%%DATADIR%%/icons/switch_presets.svg
+%%DATADIR%%/icons/test.svg
+%%DATADIR%%/icons/thumb_down.svg
+%%DATADIR%%/icons/thumb_left.svg
+%%DATADIR%%/icons/thumb_right.svg
+%%DATADIR%%/icons/thumb_up.svg
+%%DATADIR%%/icons/tick_mark.svg
+%%DATADIR%%/icons/time.svg
+%%DATADIR%%/icons/timer_dot.svg
+%%DATADIR%%/icons/timer_dot_empty.svg
+%%DATADIR%%/icons/toggle_off.svg
+%%DATADIR%%/icons/toggle_on.svg
+%%DATADIR%%/icons/toolbar_arrow.svg
+%%DATADIR%%/icons/toolbar_arrow_2.svg
+%%DATADIR%%/icons/toolbar_background.png
+%%DATADIR%%/icons/undo.svg
+%%DATADIR%%/icons/undo_f.svg
+%%DATADIR%%/icons/undo_menu.svg
+%%DATADIR%%/icons/undo_toolbar.svg
+%%DATADIR%%/icons/upload_queue.svg
+%%DATADIR%%/icons/user.svg
+%%DATADIR%%/icons/user_mask.svg
+%%DATADIR%%/icons/vector_filament_param.svg
+%%DATADIR%%/icons/vector_param.svg
+%%DATADIR%%/icons/wrench.svg
+%%DATADIR%%/icons/wrench_white.svg
+%%DATADIR%%/localization/PrusaSlicer.pot
+%%DATADIR%%/localization/be/PrusaSlicer.mo
+%%DATADIR%%/localization/be/PrusaSlicer_be.po
+%%DATADIR%%/localization/ca/PrusaSlicer.mo
+%%DATADIR%%/localization/ca/PrusaSlicer_ca.po
+%%DATADIR%%/localization/cs/PrusaSlicer.mo
+%%DATADIR%%/localization/cs/PrusaSlicer_cs.po
+%%DATADIR%%/localization/de/PrusaSlicer.mo
+%%DATADIR%%/localization/de/PrusaSlicer_de.po
+%%DATADIR%%/localization/en/PrusaSlicer.mo
+%%DATADIR%%/localization/en/PrusaSlicer_en.po
+%%DATADIR%%/localization/es/PrusaSlicer.mo
+%%DATADIR%%/localization/es/PrusaSlicer_es.po
+%%DATADIR%%/localization/fi/PrusaSlicer.mo
+%%DATADIR%%/localization/fi/PrusaSlicer_fi.po
+%%DATADIR%%/localization/fr/PrusaSlicer.mo
+%%DATADIR%%/localization/fr/PrusaSlicer_fr.po
+%%DATADIR%%/localization/hu/PrusaSlicer.mo
+%%DATADIR%%/localization/hu/PrusaSlicer_hu.po
+%%DATADIR%%/localization/it/PrusaSlicer.mo
+%%DATADIR%%/localization/it/PrusaSlicer_it.po
+%%DATADIR%%/localization/ja/PrusaSlicer.mo
+%%DATADIR%%/localization/ja/PrusaSlicer_ja.po
+%%DATADIR%%/localization/ko/PrusaSlicer.mo
+%%DATADIR%%/localization/ko/PrusaSlicer_ko_KR.po
+%%DATADIR%%/localization/ko_KR/PrusaSlicer.mo
+%%DATADIR%%/localization/ko_KR/PrusaSlicer_ko.po
+%%DATADIR%%/localization/ko_KR/PrusaSlicer_ko_KR.mo
+%%DATADIR%%/localization/ko_KR/PrusaSlicer_ko_KR.po
+%%DATADIR%%/localization/list.txt
+%%DATADIR%%/localization/nl/PrusaSlicer.mo
+%%DATADIR%%/localization/nl/PrusaSlicer_nl.po
+%%DATADIR%%/localization/pl/PrusaSlicer.mo
+%%DATADIR%%/localization/pl/PrusaSlicer_pl.po
+%%DATADIR%%/localization/pt_BR/PrusaSlicer.mo
+%%DATADIR%%/localization/pt_BR/PrusaSlicer_pt_BR.po
+%%DATADIR%%/localization/ru/PrusaSlicer.mo
+%%DATADIR%%/localization/ru/PrusaSlicer_ru.po
+%%DATADIR%%/localization/sl/PrusaSlicer.mo
+%%DATADIR%%/localization/sl/PrusaSlicer.po
+%%DATADIR%%/localization/tr/PrusaSlicer.mo
+%%DATADIR%%/localization/tr/PrusaSlicer_tr.po
+%%DATADIR%%/localization/uk/PrusaSlicer.mo
+%%DATADIR%%/localization/uk/PrusaSlicer_uk.po
+%%DATADIR%%/localization/wx_locale/af.po
+%%DATADIR%%/localization/wx_locale/an.po
+%%DATADIR%%/localization/wx_locale/ar.po
+%%DATADIR%%/localization/wx_locale/be.po
+%%DATADIR%%/localization/wx_locale/ca.po
+%%DATADIR%%/localization/wx_locale/ca@valencia.po
+%%DATADIR%%/localization/wx_locale/cs.po
+%%DATADIR%%/localization/wx_locale/da.po
+%%DATADIR%%/localization/wx_locale/de.po
+%%DATADIR%%/localization/wx_locale/el.po
+%%DATADIR%%/localization/wx_locale/en.mo
+%%DATADIR%%/localization/wx_locale/en.po
+%%DATADIR%%/localization/wx_locale/es.po
+%%DATADIR%%/localization/wx_locale/eu.po
+%%DATADIR%%/localization/wx_locale/fa_IR.po
+%%DATADIR%%/localization/wx_locale/fi.po
+%%DATADIR%%/localization/wx_locale/fr.po
+%%DATADIR%%/localization/wx_locale/gl_ES.po
+%%DATADIR%%/localization/wx_locale/hi.po
+%%DATADIR%%/localization/wx_locale/hr.po
+%%DATADIR%%/localization/wx_locale/hu.po
+%%DATADIR%%/localization/wx_locale/id.po
+%%DATADIR%%/localization/wx_locale/it.po
+%%DATADIR%%/localization/wx_locale/ja.po
+%%DATADIR%%/localization/wx_locale/ko.po
+%%DATADIR%%/localization/wx_locale/ko_KR.po
+%%DATADIR%%/localization/wx_locale/lt.po
+%%DATADIR%%/localization/wx_locale/lv.po
+%%DATADIR%%/localization/wx_locale/ms.po
+%%DATADIR%%/localization/wx_locale/nb.po
+%%DATADIR%%/localization/wx_locale/ne.po
+%%DATADIR%%/localization/wx_locale/nl.po
+%%DATADIR%%/localization/wx_locale/pl.po
+%%DATADIR%%/localization/wx_locale/pt.po
+%%DATADIR%%/localization/wx_locale/pt_BR.po
+%%DATADIR%%/localization/wx_locale/ro.po
+%%DATADIR%%/localization/wx_locale/ru.po
+%%DATADIR%%/localization/wx_locale/sk.po
+%%DATADIR%%/localization/wx_locale/sl.po
+%%DATADIR%%/localization/wx_locale/sq.po
+%%DATADIR%%/localization/wx_locale/sv.po
+%%DATADIR%%/localization/wx_locale/ta.po
+%%DATADIR%%/localization/wx_locale/tr.po
+%%DATADIR%%/localization/wx_locale/uk.po
+%%DATADIR%%/localization/wx_locale/vi.po
+%%DATADIR%%/localization/wx_locale/zh_CN.po
+%%DATADIR%%/localization/wx_locale/zh_TW.po
+%%DATADIR%%/localization/zh_CN/PrusaSlicer.mo
+%%DATADIR%%/localization/zh_CN/PrusaSlicer_zh_CN.po
+%%DATADIR%%/localization/zh_TW/PrusaSlicer.mo
+%%DATADIR%%/localization/zh_TW/PrusaSlicer_zh_TW.po
+%%DATADIR%%/profiles/Anker.idx
+%%DATADIR%%/profiles/Anker.ini
+%%DATADIR%%/profiles/Anker/M5-bed.stl
+%%DATADIR%%/profiles/Anker/M5-texture.svg
+%%DATADIR%%/profiles/Anker/M5-texture_v2.svg
+%%DATADIR%%/profiles/Anker/M5C-bed.stl
+%%DATADIR%%/profiles/Anker/M5C-texture.svg
+%%DATADIR%%/profiles/Anker/M5C-texture_v2.svg
+%%DATADIR%%/profiles/Anker/M5C_thumbnail.png
+%%DATADIR%%/profiles/Anker/M5C_thumbnail_v2.png
+%%DATADIR%%/profiles/Anker/M5_thumbnail.png
+%%DATADIR%%/profiles/Anker/M5_thumbnail_v2.png
+%%DATADIR%%/profiles/Anycubic.idx
+%%DATADIR%%/profiles/Anycubic.ini
+%%DATADIR%%/profiles/Anycubic/4MAXPRO20_bed.stl
+%%DATADIR%%/profiles/Anycubic/4MAXPRO20_texture.svg
+%%DATADIR%%/profiles/Anycubic/4MAXPRO20_thumbnail.png
+%%DATADIR%%/profiles/Anycubic/AK.png
+%%DATADIR%%/profiles/Anycubic/AK.svg
+%%DATADIR%%/profiles/Anycubic/AKLP_Bed.stl
+%%DATADIR%%/profiles/Anycubic/AKLP_thumbnail.png
+%%DATADIR%%/profiles/Anycubic/AK_Bed.stl
+%%DATADIR%%/profiles/Anycubic/AK_thumbnail.png
+%%DATADIR%%/profiles/Anycubic/I3MEGAS_thumbnail.png
+%%DATADIR%%/profiles/Anycubic/I3MEGA_thumbnail.png
+%%DATADIR%%/profiles/Anycubic/MEGA0_thumbnail.png
+%%DATADIR%%/profiles/Anycubic/PHOTON MONO SE_thumbnail.png
+%%DATADIR%%/profiles/Anycubic/PHOTON MONO X 6K_thumbnail.png
+%%DATADIR%%/profiles/Anycubic/PHOTON MONO X_thumbnail.png
+%%DATADIR%%/profiles/Anycubic/PHOTON MONO_thumbnail.png
+%%DATADIR%%/profiles/Anycubic/PREDATOR_thumbnail.png
+%%DATADIR%%/profiles/Anycubic/i3megas.svg
+%%DATADIR%%/profiles/Anycubic/i3megas_bed.stl
+%%DATADIR%%/profiles/Anycubic/mega0.svg
+%%DATADIR%%/profiles/Anycubic/mega0_bed.stl
+%%DATADIR%%/profiles/AnycubicSLA.idx
+%%DATADIR%%/profiles/AnycubicSLA.ini
+%%DATADIR%%/profiles/AnycubicSLA/PHOTON MONO SE_thumbnail.png
+%%DATADIR%%/profiles/AnycubicSLA/PHOTON MONO X 6K_thumbnail.png
+%%DATADIR%%/profiles/AnycubicSLA/PHOTON MONO X_thumbnail.png
+%%DATADIR%%/profiles/AnycubicSLA/PHOTON MONO_thumbnail.png
+%%DATADIR%%/profiles/ArchiveRepositoryManifest.json
+%%DATADIR%%/profiles/Artillery.idx
+%%DATADIR%%/profiles/Artillery.ini
+%%DATADIR%%/profiles/Artillery/Genius_thumbnail.png
+%%DATADIR%%/profiles/Artillery/Hornet_thumbnail.png
+%%DATADIR%%/profiles/Artillery/X1_thumbnail.png
+%%DATADIR%%/profiles/Artillery/X3 Plus_thumbnail.png
+%%DATADIR%%/profiles/Artillery/X3 Pro_thumbnail.png
+%%DATADIR%%/profiles/Artillery/X4 Max_thumbnail.png
+%%DATADIR%%/profiles/Artillery/X4 Plus_thumbnail.png
+%%DATADIR%%/profiles/Artillery/X4 Pro_thumbnail.png
+%%DATADIR%%/profiles/Artillery/bed-genius.png
+%%DATADIR%%/profiles/Artillery/bed-genius.stl
+%%DATADIR%%/profiles/Artillery/bed-hornet.png
+%%DATADIR%%/profiles/Artillery/bed-hornet.stl
+%%DATADIR%%/profiles/Artillery/bed-x1.png
+%%DATADIR%%/profiles/Artillery/bed-x1.stl
+%%DATADIR%%/profiles/Artillery/bed-x3-plus.stl
+%%DATADIR%%/profiles/Artillery/bed-x3-pro.stl
+%%DATADIR%%/profiles/Artillery/bed-x4-max.stl
+%%DATADIR%%/profiles/Artillery/bed-x4-plus.stl
+%%DATADIR%%/profiles/Artillery/bed-x4-pro.stl
+%%DATADIR%%/profiles/BIBO.idx
+%%DATADIR%%/profiles/BIBO.ini
+%%DATADIR%%/profiles/BIBO/BIBO2.svg
+%%DATADIR%%/profiles/BIBO/BIBO2_bed.stl
+%%DATADIR%%/profiles/BIBO/BIBO2_thumbnail.png
+%%DATADIR%%/profiles/BIQU.idx
+%%DATADIR%%/profiles/BIQU.ini
+%%DATADIR%%/profiles/BIQU/BIQUBX_thumbnail.png
+%%DATADIR%%/profiles/BIQU/BX_Bed.stl
+%%DATADIR%%/profiles/BIQU/BX_Texture.png
+%%DATADIR%%/profiles/CocoaPress.idx
+%%DATADIR%%/profiles/CocoaPress.ini
+%%DATADIR%%/profiles/CocoaPress/CocoaPress_MiniChef.png
+%%DATADIR%%/profiles/CocoaPress/minichef_bed.stl
+%%DATADIR%%/profiles/CocoaPress/minichef_texture.svg
+%%DATADIR%%/profiles/Creality.idx
+%%DATADIR%%/profiles/Creality.ini
+%%DATADIR%%/profiles/Creality/CR10MAX_thumbnail.png
+%%DATADIR%%/profiles/Creality/CR10MINI_thumbnail.png
+%%DATADIR%%/profiles/Creality/CR10S4_thumbnail.png
+%%DATADIR%%/profiles/Creality/CR10S5_thumbnail.png
+%%DATADIR%%/profiles/Creality/CR10SMARTPRO_thumbnail.png
+%%DATADIR%%/profiles/Creality/CR10SMART_thumbnail.png
+%%DATADIR%%/profiles/Creality/CR10SPROV2_thumbnail.png
+%%DATADIR%%/profiles/Creality/CR10SPRO_thumbnail.png
+%%DATADIR%%/profiles/Creality/CR10S_thumbnail.png
+%%DATADIR%%/profiles/Creality/CR10V2_thumbnail.png
+%%DATADIR%%/profiles/Creality/CR10V3_thumbnail.png
+%%DATADIR%%/profiles/Creality/CR10_thumbnail.png
+%%DATADIR%%/profiles/Creality/CR200B_thumbnail.png
+%%DATADIR%%/profiles/Creality/CR20PRO_thumbnail.png
+%%DATADIR%%/profiles/Creality/CR20_thumbnail.png
+%%DATADIR%%/profiles/Creality/CR5PROH_thumbnail.png
+%%DATADIR%%/profiles/Creality/CR5PRO_thumbnail.png
+%%DATADIR%%/profiles/Creality/CR6MAX_thumbnail.png
+%%DATADIR%%/profiles/Creality/CR6SE_thumbnail.png
+%%DATADIR%%/profiles/Creality/CR8_thumbnail.png
+%%DATADIR%%/profiles/Creality/CRXPRO_thumbnail.png
+%%DATADIR%%/profiles/Creality/CRX_thumbnail.png
+%%DATADIR%%/profiles/Creality/ENDER2PRO_thumbnail.png
+%%DATADIR%%/profiles/Creality/ENDER2_thumbnail.png
+%%DATADIR%%/profiles/Creality/ENDER3BLTOUCH_thumbnail.png
+%%DATADIR%%/profiles/Creality/ENDER3MAXNEO_thumbnail.png
+%%DATADIR%%/profiles/Creality/ENDER3MAX_thumbnail.png
+%%DATADIR%%/profiles/Creality/ENDER3NEO_thumbnail.png
+%%DATADIR%%/profiles/Creality/ENDER3PRO_thumbnail.png
+%%DATADIR%%/profiles/Creality/ENDER3S1PLUS_thumbnail.png
+%%DATADIR%%/profiles/Creality/ENDER3S1PRO_thumbnail.png
+%%DATADIR%%/profiles/Creality/ENDER3S1_thumbnail.png
+%%DATADIR%%/profiles/Creality/ENDER3V2NEO_thumbnail.png
+%%DATADIR%%/profiles/Creality/ENDER3V2_thumbnail.png
+%%DATADIR%%/profiles/Creality/ENDER3_thumbnail.png
+%%DATADIR%%/profiles/Creality/ENDER4_thumbnail.png
+%%DATADIR%%/profiles/Creality/ENDER5PLUS_thumbnail.png
+%%DATADIR%%/profiles/Creality/ENDER5PRO_thumbnail.png
+%%DATADIR%%/profiles/Creality/ENDER5S1_thumbnail.png
+%%DATADIR%%/profiles/Creality/ENDER5_thumbnail.png
+%%DATADIR%%/profiles/Creality/ENDER6_thumbnail.png
+%%DATADIR%%/profiles/Creality/ENDER7_thumbnail.png
+%%DATADIR%%/profiles/Creality/SERMOOND1_thumbnail.png
+%%DATADIR%%/profiles/Creality/SERMOONV1PRO_thumbnail.png
+%%DATADIR%%/profiles/Creality/SERMOONV1_thumbnail.png
+%%DATADIR%%/profiles/Creality/cr10.svg
+%%DATADIR%%/profiles/Creality/cr10_bed.stl
+%%DATADIR%%/profiles/Creality/cr10max.svg
+%%DATADIR%%/profiles/Creality/cr10max_bed.stl
+%%DATADIR%%/profiles/Creality/cr10mini.svg
+%%DATADIR%%/profiles/Creality/cr10mini_bed.stl
+%%DATADIR%%/profiles/Creality/cr10s4.svg
+%%DATADIR%%/profiles/Creality/cr10s4_bed.stl
+%%DATADIR%%/profiles/Creality/cr10s5.svg
+%%DATADIR%%/profiles/Creality/cr10s5_bed.stl
+%%DATADIR%%/profiles/Creality/cr10spro.svg
+%%DATADIR%%/profiles/Creality/cr10v2_bed.stl
+%%DATADIR%%/profiles/Creality/cr20.svg
+%%DATADIR%%/profiles/Creality/cr200b.svg
+%%DATADIR%%/profiles/Creality/cr200b_bed.stl
+%%DATADIR%%/profiles/Creality/cr5pro.svg
+%%DATADIR%%/profiles/Creality/cr5pro_bed.stl
+%%DATADIR%%/profiles/Creality/cr6se.svg
+%%DATADIR%%/profiles/Creality/cr6se_bed.stl
+%%DATADIR%%/profiles/Creality/cr8.svg
+%%DATADIR%%/profiles/Creality/cr8_bed.stl
+%%DATADIR%%/profiles/Creality/ender2.svg
+%%DATADIR%%/profiles/Creality/ender2_bed.stl
+%%DATADIR%%/profiles/Creality/ender2pro.svg
+%%DATADIR%%/profiles/Creality/ender2pro_bed.stl
+%%DATADIR%%/profiles/Creality/ender3.svg
+%%DATADIR%%/profiles/Creality/ender3_bed.stl
+%%DATADIR%%/profiles/Creality/ender3v2.svg
+%%DATADIR%%/profiles/Creality/ender3v2_bed.stl
+%%DATADIR%%/profiles/Creality/ender5plus.svg
+%%DATADIR%%/profiles/Creality/ender5plus_bed.stl
+%%DATADIR%%/profiles/Creality/ender6.svg
+%%DATADIR%%/profiles/Creality/ender6_bed.stl
+%%DATADIR%%/profiles/Creality/ender7.svg
+%%DATADIR%%/profiles/Creality/ender7_bed.stl
+%%DATADIR%%/profiles/Creality/sermoond1.svg
+%%DATADIR%%/profiles/Creality/sermoond1_bed.stl
+%%DATADIR%%/profiles/Creality/sermoonv1.svg
+%%DATADIR%%/profiles/Creality/sermoonv1_bed.stl
+%%DATADIR%%/profiles/Elegoo.idx
+%%DATADIR%%/profiles/Elegoo.ini
+%%DATADIR%%/profiles/Elegoo/NEPTUNE1_thumbnail.png
+%%DATADIR%%/profiles/Elegoo/NEPTUNE2D_thumbnail.png
+%%DATADIR%%/profiles/Elegoo/NEPTUNE2S_thumbnail.png
+%%DATADIR%%/profiles/Elegoo/NEPTUNE2_thumbnail.png
+%%DATADIR%%/profiles/Elegoo/NEPTUNE3MAX_thumbnail.png
+%%DATADIR%%/profiles/Elegoo/NEPTUNE3PLUS_thumbnail.png
+%%DATADIR%%/profiles/Elegoo/NEPTUNE3PRO_thumbnail.png
+%%DATADIR%%/profiles/Elegoo/NEPTUNE3_thumbnail.png
+%%DATADIR%%/profiles/Elegoo/NEPTUNEX_thumbnail.png
+%%DATADIR%%/profiles/FLSun.idx
+%%DATADIR%%/profiles/FLSun.ini
+%%DATADIR%%/profiles/FLSun/Q5.svg
+%%DATADIR%%/profiles/FLSun/Q5_bed.stl
+%%DATADIR%%/profiles/FLSun/Q5_thumbnail.png
+%%DATADIR%%/profiles/FLSun/QQSP.svg
+%%DATADIR%%/profiles/FLSun/QQSP_bed.stl
+%%DATADIR%%/profiles/FLSun/QQSP_thumbnail.png
+%%DATADIR%%/profiles/Geeetech.idx
+%%DATADIR%%/profiles/Geeetech.ini
+%%DATADIR%%/profiles/Geeetech/105x105.stl
+%%DATADIR%%/profiles/Geeetech/105x105.svg
+%%DATADIR%%/profiles/Geeetech/125X130.stl
+%%DATADIR%%/profiles/Geeetech/125x130.svg
+%%DATADIR%%/profiles/Geeetech/150x150.stl
+%%DATADIR%%/profiles/Geeetech/150x150.svg
+%%DATADIR%%/profiles/Geeetech/160x160.stl
+%%DATADIR%%/profiles/Geeetech/160x160.svg
+%%DATADIR%%/profiles/Geeetech/180X150.stl
+%%DATADIR%%/profiles/Geeetech/180x150.svg
+%%DATADIR%%/profiles/Geeetech/200x200.stl
+%%DATADIR%%/profiles/Geeetech/200x200.svg
+%%DATADIR%%/profiles/Geeetech/220x220.stl
+%%DATADIR%%/profiles/Geeetech/220x220.svg
+%%DATADIR%%/profiles/Geeetech/250x250.stl
+%%DATADIR%%/profiles/Geeetech/250x250.svg
+%%DATADIR%%/profiles/Geeetech/255x255.stl
+%%DATADIR%%/profiles/Geeetech/255x255.svg
+%%DATADIR%%/profiles/Geeetech/300x180.stl
+%%DATADIR%%/profiles/Geeetech/300x180.svg
+%%DATADIR%%/profiles/Geeetech/320x320.stl
+%%DATADIR%%/profiles/Geeetech/320x320.svg
+%%DATADIR%%/profiles/Geeetech/A10M_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/A10Pro_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/A10T_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/A20M_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/A20T_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/A20_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/A30M_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/A30Pro_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/A30T_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/E180_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/GiantArmD200_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/I3ProB_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/I3ProC_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/I3ProW_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/M1.svg
+%%DATADIR%%/profiles/Geeetech/M1_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/MeCreator2_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/MeCreator_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/MeDucer_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/MizarM_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/MizarMax_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/MizarPro_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/MizarS_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/Mizar_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/ThunderPro_thumbnail.png
+%%DATADIR%%/profiles/Geeetech/Thunder_thumbnail.png
+%%DATADIR%%/profiles/HartSmartProducts.idx
+%%DATADIR%%/profiles/HartSmartProducts.ini
+%%DATADIR%%/profiles/HartSmartProducts/HSP1-I Duplicator Mode_thumbnail.png
+%%DATADIR%%/profiles/HartSmartProducts/HSP1-I_thumbnail.png
+%%DATADIR%%/profiles/HartSmartProducts/hsp1_i.svg
+%%DATADIR%%/profiles/HartSmartProducts/hsp1_i_bed.stl
+%%DATADIR%%/profiles/HartSmartProducts/hsp1_i_duplicator.svg
+%%DATADIR%%/profiles/HartSmartProducts/hsp1_i_duplicator_bed.stl
+%%DATADIR%%/profiles/INAT.idx
+%%DATADIR%%/profiles/INAT.ini
+%%DATADIR%%/profiles/INAT/PROTON_XE750_thumbnail.png
+%%DATADIR%%/profiles/INAT/PROTON_X_RAIL_thumbnail.png
+%%DATADIR%%/profiles/INAT/PROTON_X_ROD_thumbnail.png
+%%DATADIR%%/profiles/Infinity3D.idx
+%%DATADIR%%/profiles/Infinity3D.ini
+%%DATADIR%%/profiles/Infinity3D/DEV-200_thumbnail.png
+%%DATADIR%%/profiles/Infinity3D/DEV-350_thumbnail.png
+%%DATADIR%%/profiles/Infinity3D/DEV_200_bed.stl
+%%DATADIR%%/profiles/Infinity3D/DEV_200_texture.svg
+%%DATADIR%%/profiles/Infinity3D/DEV_350_bed.stl
+%%DATADIR%%/profiles/Infinity3D/DEV_350_texture.svg
+%%DATADIR%%/profiles/Jubilee.idx
+%%DATADIR%%/profiles/Jubilee.ini
+%%DATADIR%%/profiles/Jubilee/Jubilee_bed.stl
+%%DATADIR%%/profiles/Jubilee/Jubilee_texture.svg
+%%DATADIR%%/profiles/Jubilee/Jubilee_thumbnail.png
+%%DATADIR%%/profiles/LNL3D.idx
+%%DATADIR%%/profiles/LNL3D.ini
+%%DATADIR%%/profiles/LNL3D/LNL3D_D3_V2_bed.stl
+%%DATADIR%%/profiles/LNL3D/LNL3D_D3_V2_texture.svg
+%%DATADIR%%/profiles/LNL3D/LNL3D_D3_V2_thumbnail.png
+%%DATADIR%%/profiles/LNL3D/LNL3D_D3_VULCAN_bed.stl
+%%DATADIR%%/profiles/LNL3D/LNL3D_D3_VULCAN_texture.svg
+%%DATADIR%%/profiles/LNL3D/LNL3D_D3_VULCAN_thumbnail.png
+%%DATADIR%%/profiles/LNL3D/LNL3D_D3_bed.stl
+%%DATADIR%%/profiles/LNL3D/LNL3D_D3_texture.svg
+%%DATADIR%%/profiles/LNL3D/LNL3D_D3_thumbnail.png
+%%DATADIR%%/profiles/LNL3D/LNL3D_D5_bed.stl
+%%DATADIR%%/profiles/LNL3D/LNL3D_D5_texture.svg
+%%DATADIR%%/profiles/LNL3D/LNL3D_D5_thumbnail.png
+%%DATADIR%%/profiles/LNL3D/LNL3D_D6_bed.stl
+%%DATADIR%%/profiles/LNL3D/LNL3D_D6_texture.svg
+%%DATADIR%%/profiles/LNL3D/LNL3D_D6_thumbnail.png
+%%DATADIR%%/profiles/LulzBot.idx
+%%DATADIR%%/profiles/LulzBot.ini
+%%DATADIR%%/profiles/LulzBot/MINI_AERO_thumbnail.png
+%%DATADIR%%/profiles/LulzBot/TAZ6_AERO_thumbnail.png
+%%DATADIR%%/profiles/LulzBot/TAZ_WORKHORSE_thumbnail.png
+%%DATADIR%%/profiles/MakerGear.idx
+%%DATADIR%%/profiles/MakerGear.ini
+%%DATADIR%%/profiles/MakerGear/M2_M3.stl
+%%DATADIR%%/profiles/MakerGear/M2_M3.svg
+%%DATADIR%%/profiles/MakerGear/MAKERGEAR_M2_DUAL_thumbnail.png
+%%DATADIR%%/profiles/MakerGear/MAKERGEAR_M2_thumbnail.png
+%%DATADIR%%/profiles/MakerGear/MAKERGEAR_M3_DUPLICATION_thumbnail.png
+%%DATADIR%%/profiles/MakerGear/MAKERGEAR_M3_SE_thumbnail.png
+%%DATADIR%%/profiles/MakerGear/MAKERGEAR_M3_thumbnail.png
+%%DATADIR%%/profiles/MakerGear/MAKERGEAR_MICRO_thumbnail.png
+%%DATADIR%%/profiles/MakerGear/MAKERGEAR_U1_thumbnail.png
+%%DATADIR%%/profiles/PapapiuLab.idx
+%%DATADIR%%/profiles/PapapiuLab.ini
+%%DATADIR%%/profiles/PapapiuLab/Papapiu_N1S_Bed.stl
+%%DATADIR%%/profiles/PapapiuLab/Papapiu_N1S_thumbnail.png
+%%DATADIR%%/profiles/PapapiuLab/Papapiu_N1_Texture.png
+%%DATADIR%%/profiles/Print4Taste.idx
+%%DATADIR%%/profiles/Print4Taste.ini
+%%DATADIR%%/profiles/Print4Taste/MC2.0_bed.stl
+%%DATADIR%%/profiles/Print4Taste/MC2.0_texture.svg
+%%DATADIR%%/profiles/Print4Taste/MC2.0_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch.idx
+%%DATADIR%%/profiles/PrusaResearch.ini
+%%DATADIR%%/profiles/PrusaResearch/MINIIS_ALPHA_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MINIIS_BETA_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MINIIS_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MINI_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MK2.5MMU2_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MK2.5SMMU2S_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MK2.5S_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MK2.5_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MK2SMM_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MK2S_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MK3.5MMU3_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MK3.9MMU3_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MK35_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MK39IS_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MK39IS_thumbnail_v2.png
+%%DATADIR%%/profiles/PrusaResearch/MK39_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MK3MMU2_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MK3SMMU2S_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MK3SMMU3_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MK3S_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MK3_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MK4ISMMU3_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MK4IS_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MK4IS_thumbnail_v2.png
+%%DATADIR%%/profiles/PrusaResearch/MK4SMMU3_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MK4S_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/MK4_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/XL2IS_alpha_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/XL2IS_beta_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/XL2IS_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/XL2_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/XL5IS_alpha_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/XL5IS_beta_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/XL5IS_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/XL5_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/XLIS_alpha_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/XLIS_beta_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/XLIS_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/XL_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearch/mini.svg
+%%DATADIR%%/profiles/PrusaResearch/miniIS.svg
+%%DATADIR%%/profiles/PrusaResearch/miniISbeta.svg
+%%DATADIR%%/profiles/PrusaResearch/mini_bed.stl
+%%DATADIR%%/profiles/PrusaResearch/mk2.svg
+%%DATADIR%%/profiles/PrusaResearch/mk2_bed.stl
+%%DATADIR%%/profiles/PrusaResearch/mk3.svg
+%%DATADIR%%/profiles/PrusaResearch/mk35.svg
+%%DATADIR%%/profiles/PrusaResearch/mk39.svg
+%%DATADIR%%/profiles/PrusaResearch/mk39s.svg
+%%DATADIR%%/profiles/PrusaResearch/mk3_bed.stl
+%%DATADIR%%/profiles/PrusaResearch/mk4.svg
+%%DATADIR%%/profiles/PrusaResearch/mk4_bed.stl
+%%DATADIR%%/profiles/PrusaResearch/mk4is.svg
+%%DATADIR%%/profiles/PrusaResearch/mk4s.svg
+%%DATADIR%%/profiles/PrusaResearch/xl.svg
+%%DATADIR%%/profiles/PrusaResearch/xl_bed.stl
+%%DATADIR%%/profiles/PrusaResearch/xlis_alpha.svg
+%%DATADIR%%/profiles/PrusaResearch/xlis_beta.svg
+%%DATADIR%%/profiles/PrusaResearchSLA.idx
+%%DATADIR%%/profiles/PrusaResearchSLA.ini
+%%DATADIR%%/profiles/PrusaResearchSLA/SL1S_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearchSLA/SL1_thumbnail.png
+%%DATADIR%%/profiles/PrusaResearchSLA/sl1.svg
+%%DATADIR%%/profiles/PrusaResearchSLA/sl1_bed.stl
+%%DATADIR%%/profiles/PrusaResearchSLA/sl1s.svg
+%%DATADIR%%/profiles/PrusaResearchSLA/sl1s_bed.stl
+%%DATADIR%%/profiles/RatRig.idx
+%%DATADIR%%/profiles/RatRig.ini
+%%DATADIR%%/profiles/RatRig/VC3_300_thumbnail.png
+%%DATADIR%%/profiles/RatRig/VC3_400_thumbnail.png
+%%DATADIR%%/profiles/RatRig/VC3_500_thumbnail.png
+%%DATADIR%%/profiles/RatRig/VMINION_thumbnail.png
+%%DATADIR%%/profiles/RatRig/rr-vc-300.stl
+%%DATADIR%%/profiles/RatRig/rr-vc-300.svg
+%%DATADIR%%/profiles/RatRig/rr-vc-400.stl
+%%DATADIR%%/profiles/RatRig/rr-vc-400.svg
+%%DATADIR%%/profiles/RatRig/rr-vc-500.stl
+%%DATADIR%%/profiles/RatRig/rr-vc-500.svg
+%%DATADIR%%/profiles/RatRig/rr-vminion.stl
+%%DATADIR%%/profiles/RatRig/rr-vminion.svg
+%%DATADIR%%/profiles/RatRig/vc4-corexy.png
+%%DATADIR%%/profiles/RatRig/vc4-hybrid.png
+%%DATADIR%%/profiles/RatRig/vc4-idex.png
+%%DATADIR%%/profiles/Rigid3D.idx
+%%DATADIR%%/profiles/Rigid3D.ini
+%%DATADIR%%/profiles/Rigid3D/Mucit2_thumbnail.png
+%%DATADIR%%/profiles/Rigid3D/Mucit_thumbnail.png
+%%DATADIR%%/profiles/Rigid3D/Zero2_thumbnail.png
+%%DATADIR%%/profiles/Rigid3D/Zero3_thumbnail.png
+%%DATADIR%%/profiles/Rigid3D/mucit2_bed.png
+%%DATADIR%%/profiles/Rigid3D/mucit2_bed.stl
+%%DATADIR%%/profiles/Rigid3D/mucit_bed.png
+%%DATADIR%%/profiles/Rigid3D/mucit_bed.stl
+%%DATADIR%%/profiles/Rigid3D/zero2_bed.png
+%%DATADIR%%/profiles/Rigid3D/zero3_bed.png
+%%DATADIR%%/profiles/Rigid3D/zero_bed.stl
+%%DATADIR%%/profiles/Snapmaker.idx
+%%DATADIR%%/profiles/Snapmaker.ini
+%%DATADIR%%/profiles/Snapmaker/Snapmaker A250 Dual QSKit_cover.png
+%%DATADIR%%/profiles/Snapmaker/Snapmaker A250 Dual_cover.png
+%%DATADIR%%/profiles/Snapmaker/Snapmaker A250 QSKit_cover.png
+%%DATADIR%%/profiles/Snapmaker/Snapmaker A250 QSKit_texture.svg
+%%DATADIR%%/profiles/Snapmaker/Snapmaker A250_bed.stl
+%%DATADIR%%/profiles/Snapmaker/Snapmaker A250_cover.png
+%%DATADIR%%/profiles/Snapmaker/Snapmaker A250_texture.svg
+%%DATADIR%%/profiles/Snapmaker/Snapmaker A350 Dual QSKit_cover.png
+%%DATADIR%%/profiles/Snapmaker/Snapmaker A350 Dual_cover.png
+%%DATADIR%%/profiles/Snapmaker/Snapmaker A350 QSKit_cover.png
+%%DATADIR%%/profiles/Snapmaker/Snapmaker A350 QSKit_texture.svg
+%%DATADIR%%/profiles/Snapmaker/Snapmaker A350_bed.stl
+%%DATADIR%%/profiles/Snapmaker/Snapmaker A350_cover.png
+%%DATADIR%%/profiles/Snapmaker/Snapmaker A350_texture.svg
+%%DATADIR%%/profiles/Snapmaker/Snapmaker J1_bed.stl
+%%DATADIR%%/profiles/Snapmaker/Snapmaker J1_cover.png
+%%DATADIR%%/profiles/Snapmaker/Snapmaker J1_texture.svg
+%%DATADIR%%/profiles/Sovol.idx
+%%DATADIR%%/profiles/Sovol.ini
+%%DATADIR%%/profiles/Sovol/SV01 PRO_thumbnail.png
+%%DATADIR%%/profiles/Sovol/SV01_BLTouch_thumbnail.png
+%%DATADIR%%/profiles/Sovol/SV01_bed.stl
+%%DATADIR%%/profiles/Sovol/SV01_texture.svg
+%%DATADIR%%/profiles/Sovol/SV01_thumbnail.png
+%%DATADIR%%/profiles/Sovol/SV02_BLTouch_thumbnail.png
+%%DATADIR%%/profiles/Sovol/SV02_texture.svg
+%%DATADIR%%/profiles/Sovol/SV02_thumbnail.png
+%%DATADIR%%/profiles/Sovol/SV03_BLTouch_thumbnail.png
+%%DATADIR%%/profiles/Sovol/SV03_bed.stl
+%%DATADIR%%/profiles/Sovol/SV03_texture.svg
+%%DATADIR%%/profiles/Sovol/SV03_thumbnail.png
+%%DATADIR%%/profiles/Sovol/SV04 Copy Mode_thumbnail.png
+%%DATADIR%%/profiles/Sovol/SV04 Dual Mode_thumbnail.png
+%%DATADIR%%/profiles/Sovol/SV04 Mirror Mode_thumbnail.png
+%%DATADIR%%/profiles/Sovol/SV04 Single Mode 01_thumbnail.png
+%%DATADIR%%/profiles/Sovol/SV04 Single Mode 02_thumbnail.png
+%%DATADIR%%/profiles/Sovol/SV04_bed.stl
+%%DATADIR%%/profiles/Sovol/SV04_texture.svg
+%%DATADIR%%/profiles/Sovol/SV04_thumbnail.png
+%%DATADIR%%/profiles/Sovol/SV05_bed.stl
+%%DATADIR%%/profiles/Sovol/SV05_texture.svg
+%%DATADIR%%/profiles/Sovol/SV05_thumbnail.png
+%%DATADIR%%/profiles/Sovol/SV06 PLUS_thumbnail.png
+%%DATADIR%%/profiles/Sovol/SV06PLUS_bed.stl
+%%DATADIR%%/profiles/Sovol/SV06PLUS_texture.svg
+%%DATADIR%%/profiles/Sovol/SV06_bed.stl
+%%DATADIR%%/profiles/Sovol/SV06_texture.svg
+%%DATADIR%%/profiles/Sovol/SV06_thumbnail.png
+%%DATADIR%%/profiles/Sovol/Sovol.ini
+%%DATADIR%%/profiles/Templates.idx
+%%DATADIR%%/profiles/Templates.ini
+%%DATADIR%%/profiles/TriLAB.idx
+%%DATADIR%%/profiles/TriLAB.ini
+%%DATADIR%%/profiles/TriLAB/AQD_thumbnail.png
+%%DATADIR%%/profiles/TriLAB/AQI_thumbnail.png
+%%DATADIR%%/profiles/TriLAB/DQ2+FP2_thumbnail.png
+%%DATADIR%%/profiles/TriLAB/DQ2+FP_thumbnail.png
+%%DATADIR%%/profiles/TriLAB/DQ2P+FP2_thumbnail.png
+%%DATADIR%%/profiles/TriLAB/DQ2P+FP_thumbnail.png
+%%DATADIR%%/profiles/TriLAB/DQ2P_thumbnail.png
+%%DATADIR%%/profiles/TriLAB/DQ2_thumbnail.png
+%%DATADIR%%/profiles/TriLAB/DQL_thumbnail.png
+%%DATADIR%%/profiles/TriLAB/DQM_thumbnail.png
+%%DATADIR%%/profiles/TriLAB/DQXL_thumbnail.png
+%%DATADIR%%/profiles/TriLAB/aq_bed.stl
+%%DATADIR%%/profiles/TriLAB/aqp_bed.stl
+%%DATADIR%%/profiles/TriLAB/dq2_bed.stl
+%%DATADIR%%/profiles/Trimaker.idx
+%%DATADIR%%/profiles/Trimaker.ini
+%%DATADIR%%/profiles/Trimaker/CosmosII_bed.stl
+%%DATADIR%%/profiles/Trimaker/Cosmos_II_thumbnail.png
+%%DATADIR%%/profiles/Trimaker/NPC_thumbnail.png
+%%DATADIR%%/profiles/Trimaker/NebulaCloud.svg
+%%DATADIR%%/profiles/Trimaker/NebulaCloud_bed.stl
+%%DATADIR%%/profiles/Trimaker/Nebula_thumbnail.png
+%%DATADIR%%/profiles/Ultimaker.idx
+%%DATADIR%%/profiles/Ultimaker.ini
+%%DATADIR%%/profiles/Ultimaker/ULTIMAKER2_thumbnail.png
+%%DATADIR%%/profiles/Ultimaker/ULTIMAKER2_thumbnail_v2.png
+%%DATADIR%%/profiles/Ultimaker/ULTIMAKERSline_thumbnail.png
+%%DATADIR%%/profiles/Ultimaker/ultimaker2.svg
+%%DATADIR%%/profiles/Ultimaker/ultimaker2_bed.stl
+%%DATADIR%%/profiles/Voron.idx
+%%DATADIR%%/profiles/Voron.ini
+%%DATADIR%%/profiles/Voron/Voron_SW_thumbnail.png
+%%DATADIR%%/profiles/Voron/Voron_v0_120_thumbnail.png
+%%DATADIR%%/profiles/Voron/Voron_v1_250_afterburner_thumbnail.png
+%%DATADIR%%/profiles/Voron/Voron_v1_300_afterburner_thumbnail.png
+%%DATADIR%%/profiles/Voron/Voron_v1_350_afterburner_thumbnail.png
+%%DATADIR%%/profiles/Voron/Voron_v2_250_afterburner_thumbnail.png
+%%DATADIR%%/profiles/Voron/Voron_v2_250_thumbnail.png
+%%DATADIR%%/profiles/Voron/Voron_v2_300_afterburner_thumbnail.png
+%%DATADIR%%/profiles/Voron/Voron_v2_300_thumbnail.png
+%%DATADIR%%/profiles/Voron/Voron_v2_350_afterburner_thumbnail.png
+%%DATADIR%%/profiles/Voron/Voron_v2_350_thumbnail.png
+%%DATADIR%%/profiles/Voron/bedtexture-SW-250x210.png
+%%DATADIR%%/profiles/Voron/bedtexture-v0-120.png
+%%DATADIR%%/profiles/Voron/bedtexture-v1-250.png
+%%DATADIR%%/profiles/Voron/bedtexture-v1-300.png
+%%DATADIR%%/profiles/Voron/bedtexture-v2-250.png
+%%DATADIR%%/profiles/Voron/bedtexture-v2-300.png
+%%DATADIR%%/profiles/Voron/bedtexture-v2-350.png
+%%DATADIR%%/profiles/Voron/printbed-SW-MK52.stl
+%%DATADIR%%/profiles/Voron/printbed-v0-120.stl
+%%DATADIR%%/profiles/Voron/printbed-v1-250.stl
+%%DATADIR%%/profiles/Voron/printbed-v1-300.stl
+%%DATADIR%%/profiles/Voron/printbed-v1-350.stl
+%%DATADIR%%/profiles/Voron/printbed-v2-250.stl
+%%DATADIR%%/profiles/Voron/printbed-v2-300.stl
+%%DATADIR%%/profiles/Voron/printbed-v2-350.stl
+%%DATADIR%%/profiles/Zonestar.idx
+%%DATADIR%%/profiles/Zonestar.ini
+%%DATADIR%%/profiles/Zonestar/150_texture.svg
+%%DATADIR%%/profiles/Zonestar/220_texture.svg
+%%DATADIR%%/profiles/Zonestar/310_texture.svg
+%%DATADIR%%/profiles/Zonestar/Z5X_thumbnail.png
+%%DATADIR%%/profiles/Zonestar/Z5_thumbnail.png
+%%DATADIR%%/profiles/Zonestar/Z6_thumbnail.png
+%%DATADIR%%/profiles/Zonestar/Z8_thumbnail.png
+%%DATADIR%%/profiles/Zonestar/Z9_thumbnail.png
+%%DATADIR%%/profiles/Zonestar/bed_150.stl
+%%DATADIR%%/profiles/Zonestar/bed_220.stl
+%%DATADIR%%/profiles/Zonestar/bed_310.stl
+%%DATADIR%%/profiles/gCreate.idx
+%%DATADIR%%/profiles/gCreate.ini
+%%DATADIR%%/profiles/gCreate/GMAX15P_thumbnail.png
+%%DATADIR%%/profiles/gCreate/GMAX2DUAL2IN1_thumbnail.png
+%%DATADIR%%/profiles/gCreate/GMAX2DUAL_thumbnail.png
+%%DATADIR%%/profiles/gCreate/GMAX2PRO_thumbnail.png
+%%DATADIR%%/profiles/gCreate/GMAX2_thumbnail.png
+%%DATADIR%%/profiles/gCreate/gmax15p.svg
+%%DATADIR%%/profiles/gCreate/gmax15p_bed.stl
+%%DATADIR%%/profiles/gCreate/gmax2.svg
+%%DATADIR%%/profiles/gCreate/gmax2_bed.stl
+%%DATADIR%%/shaders/110/background.fs
+%%DATADIR%%/shaders/110/background.vs
+%%DATADIR%%/shaders/110/flat.fs
+%%DATADIR%%/shaders/110/flat.vs
+%%DATADIR%%/shaders/110/flat_clip.fs
+%%DATADIR%%/shaders/110/flat_clip.vs
+%%DATADIR%%/shaders/110/flat_texture.fs
+%%DATADIR%%/shaders/110/flat_texture.vs
+%%DATADIR%%/shaders/110/gouraud.fs
+%%DATADIR%%/shaders/110/gouraud.vs
+%%DATADIR%%/shaders/110/gouraud_light.fs
+%%DATADIR%%/shaders/110/gouraud_light.vs
+%%DATADIR%%/shaders/110/gouraud_light_clip.fs
+%%DATADIR%%/shaders/110/gouraud_light_clip.vs
+%%DATADIR%%/shaders/110/gouraud_light_instanced.fs
+%%DATADIR%%/shaders/110/gouraud_light_instanced.vs
+%%DATADIR%%/shaders/110/imgui.fs
+%%DATADIR%%/shaders/110/imgui.vs
+%%DATADIR%%/shaders/110/mm_contour.fs
+%%DATADIR%%/shaders/110/mm_contour.vs
+%%DATADIR%%/shaders/110/mm_gouraud.fs
+%%DATADIR%%/shaders/110/mm_gouraud.vs
+%%DATADIR%%/shaders/110/printbed.fs
+%%DATADIR%%/shaders/110/printbed.vs
+%%DATADIR%%/shaders/110/toolpaths_cog.fs
+%%DATADIR%%/shaders/110/toolpaths_cog.vs
+%%DATADIR%%/shaders/110/variable_layer_height.fs
+%%DATADIR%%/shaders/110/variable_layer_height.vs
+%%DATADIR%%/shaders/140/background.fs
+%%DATADIR%%/shaders/140/background.vs
+%%DATADIR%%/shaders/140/dashed_thick_lines.fs
+%%DATADIR%%/shaders/140/dashed_thick_lines.gs
+%%DATADIR%%/shaders/140/dashed_thick_lines.vs
+%%DATADIR%%/shaders/140/flat.fs
+%%DATADIR%%/shaders/140/flat.vs
+%%DATADIR%%/shaders/140/flat_clip.fs
+%%DATADIR%%/shaders/140/flat_clip.vs
+%%DATADIR%%/shaders/140/flat_texture.fs
+%%DATADIR%%/shaders/140/flat_texture.vs
+%%DATADIR%%/shaders/140/gouraud.fs
+%%DATADIR%%/shaders/140/gouraud.vs
+%%DATADIR%%/shaders/140/gouraud_light.fs
+%%DATADIR%%/shaders/140/gouraud_light.vs
+%%DATADIR%%/shaders/140/gouraud_light_clip.fs
+%%DATADIR%%/shaders/140/gouraud_light_clip.vs
+%%DATADIR%%/shaders/140/gouraud_light_instanced.fs
+%%DATADIR%%/shaders/140/gouraud_light_instanced.vs
+%%DATADIR%%/shaders/140/imgui.fs
+%%DATADIR%%/shaders/140/imgui.vs
+%%DATADIR%%/shaders/140/mm_contour.fs
+%%DATADIR%%/shaders/140/mm_contour.vs
+%%DATADIR%%/shaders/140/mm_gouraud.fs
+%%DATADIR%%/shaders/140/mm_gouraud.vs
+%%DATADIR%%/shaders/140/printbed.fs
+%%DATADIR%%/shaders/140/printbed.vs
+%%DATADIR%%/shaders/140/toolpaths_cog.fs
+%%DATADIR%%/shaders/140/toolpaths_cog.vs
+%%DATADIR%%/shaders/140/variable_layer_height.fs
+%%DATADIR%%/shaders/140/variable_layer_height.vs
+%%DATADIR%%/shaders/ES/background.fs
+%%DATADIR%%/shaders/ES/background.vs
+%%DATADIR%%/shaders/ES/dashed_lines.fs
+%%DATADIR%%/shaders/ES/dashed_lines.vs
+%%DATADIR%%/shaders/ES/flat.fs
+%%DATADIR%%/shaders/ES/flat.vs
+%%DATADIR%%/shaders/ES/flat_clip.fs
+%%DATADIR%%/shaders/ES/flat_clip.vs
+%%DATADIR%%/shaders/ES/flat_texture.fs
+%%DATADIR%%/shaders/ES/flat_texture.vs
+%%DATADIR%%/shaders/ES/gouraud.fs
+%%DATADIR%%/shaders/ES/gouraud.vs
+%%DATADIR%%/shaders/ES/gouraud_light.fs
+%%DATADIR%%/shaders/ES/gouraud_light.vs
+%%DATADIR%%/shaders/ES/gouraud_light_clip.fs
+%%DATADIR%%/shaders/ES/gouraud_light_clip.vs
+%%DATADIR%%/shaders/ES/gouraud_light_instanced.fs
+%%DATADIR%%/shaders/ES/gouraud_light_instanced.vs
+%%DATADIR%%/shaders/ES/imgui.fs
+%%DATADIR%%/shaders/ES/imgui.vs
+%%DATADIR%%/shaders/ES/mm_contour.fs
+%%DATADIR%%/shaders/ES/mm_contour.vs
+%%DATADIR%%/shaders/ES/mm_gouraud.fs
+%%DATADIR%%/shaders/ES/mm_gouraud.vs
+%%DATADIR%%/shaders/ES/printbed.fs
+%%DATADIR%%/shaders/ES/printbed.vs
+%%DATADIR%%/shaders/ES/toolpaths_cog.fs
+%%DATADIR%%/shaders/ES/toolpaths_cog.vs
+%%DATADIR%%/shaders/ES/variable_layer_height.fs
+%%DATADIR%%/shaders/ES/variable_layer_height.vs
+%%DATADIR%%/shaders/ES/wireframe.fs
+%%DATADIR%%/shaders/ES/wireframe.vs
+%%DATADIR%%/shapes/3DBenchy.png
+%%DATADIR%%/shapes/3DBenchy.stl
+%%DATADIR%%/shapes/M3_hex_nut.png
+%%DATADIR%%/shapes/M3_hex_nut.stl
+%%DATADIR%%/shapes/M3x10_screw.png
+%%DATADIR%%/shapes/M3x10_screw.stl
+%%DATADIR%%/shapes/OTHER_recycling_symbol.png
+%%DATADIR%%/shapes/OTHER_recycling_symbol.stl
+%%DATADIR%%/shapes/PETG_recycling_symbol.png
+%%DATADIR%%/shapes/PETG_recycling_symbol.stl
+%%DATADIR%%/shapes/PLA_recycling_symbol.png
+%%DATADIR%%/shapes/PLA_recycling_symbol.stl
+%%DATADIR%%/shapes/box.png
+%%DATADIR%%/shapes/box.stl
+%%DATADIR%%/shapes/bunny.png
+%%DATADIR%%/shapes/bunny.stl
+%%DATADIR%%/shapes/cone.png
+%%DATADIR%%/shapes/cone.stl
+%%DATADIR%%/shapes/cylinder.png
+%%DATADIR%%/shapes/cylinder.stl
+%%DATADIR%%/shapes/helper_disk.png
+%%DATADIR%%/shapes/helper_disk.stl
+%%DATADIR%%/shapes/pyramid.png
+%%DATADIR%%/shapes/pyramid.stl
+%%DATADIR%%/shapes/sign_base.png
+%%DATADIR%%/shapes/sign_base.stl
+%%DATADIR%%/shapes/sign_base_rounded.png
+%%DATADIR%%/shapes/sign_base_rounded.stl
+%%DATADIR%%/shapes/sphere.png
+%%DATADIR%%/shapes/sphere.stl
+%%DATADIR%%/shapes/torus.png
+%%DATADIR%%/shapes/torus.stl
+%%DATADIR%%/shapes/universal wall mount hole.png
+%%DATADIR%%/shapes/universal wall mount hole.stl
+%%DATADIR%%/web/connect_error.html
+%%DATADIR%%/web/connect_loading.html
+%%DATADIR%%/web/error_no_reload.html
+%%DATADIR%%/web/other_error.html
+%%DATADIR%%/web/other_loading.html
share/applications/PrusaGcodeviewer.desktop
-share/icons/hicolor/32x32/apps/PrusaSlicer.png
-share/icons/hicolor/32x32/apps/PrusaSlicer-gcodeviewer.png
-share/icons/hicolor/128x128/apps/PrusaSlicer.png
+share/applications/PrusaSlicer.desktop
share/icons/hicolor/128x128/apps/PrusaSlicer-gcodeviewer.png
-share/icons/hicolor/192x192/apps/PrusaSlicer.png
+share/icons/hicolor/128x128/apps/PrusaSlicer.png
share/icons/hicolor/192x192/apps/PrusaSlicer-gcodeviewer.png
+share/icons/hicolor/192x192/apps/PrusaSlicer.png
+share/icons/hicolor/32x32/apps/PrusaSlicer-gcodeviewer.png
+share/icons/hicolor/32x32/apps/PrusaSlicer.png