Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 5 Apr 2020 11:46:17 +0000 (UTC)
From:      Michael Reifenberger <mr@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org
Subject:   svn commit: r530770 - in head/cad/PrusaSlicer: . files
Message-ID:  <202004051146.035BkHhx004377@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mr
Date: Sun Apr  5 11:46:17 2020
New Revision: 530770
URL: https://svnweb.freebsd.org/changeset/ports/530770

Log:
  Update to 2.2.0
  
  PR:		245247
  Submitted by:	teodorsigaev@gmail.com

Added:
  head/cad/PrusaSlicer/files/patch-CMakeLists.txt   (contents, props changed)
  head/cad/PrusaSlicer/files/patch-src_avrdude_libavrdude.h   (contents, props changed)
  head/cad/PrusaSlicer/files/patch-src_hidapi_CMakeLists.txt   (contents, props changed)
  head/cad/PrusaSlicer/files/patch-src_hidapi_libusb_hid.c   (contents, props changed)
Deleted:
  head/cad/PrusaSlicer/files/patch-src-avrdude-libavrdude.h
  head/cad/PrusaSlicer/files/patch-src-slic3r-GUI-GUI_App.cpp
  head/cad/PrusaSlicer/files/patch-src-slic3r-GUI-GUI_Utils.cpp
  head/cad/PrusaSlicer/files/patch-src-slic3r-GUI-GUI_Utils.hpp
Modified:
  head/cad/PrusaSlicer/Makefile
  head/cad/PrusaSlicer/distinfo
  head/cad/PrusaSlicer/pkg-plist

Modified: head/cad/PrusaSlicer/Makefile
==============================================================================
--- head/cad/PrusaSlicer/Makefile	Sun Apr  5 11:26:52 2020	(r530769)
+++ head/cad/PrusaSlicer/Makefile	Sun Apr  5 11:46:17 2020	(r530770)
@@ -2,9 +2,10 @@
 
 PORTNAME=		PrusaSlicer
 DISTVERSIONPREFIX=	version_
-DISTVERSION=		2.1.1
-PORTREVISION=		1
+DISTVERSION=		2.2.0
 CATEGORIES=		cad
+MASTER_SITES=https://github.com/CGAL/cgal/archive/releases/:cgal
+DISTFILES=CGAL-5.0.2.tar.gz:cgal
 
 MAINTAINER=	teodor@sigaev.ru
 COMMENT=	Slicing application for 3D printers
@@ -23,7 +24,10 @@ BUILD_DEPENDS=	cereal>=1.2.2:devel/cereal \
 		boost-libs>=1.64:devel/boost-libs \
 		wx31-gtk3>=3.1:x11-toolkits/wxgtk31 \
 		cmake>=3.2:devel/cmake \
-		ninja>=1.8.2:devel/ninja
+		ninja>=1.8.2:devel/ninja \
+		openvdb>=6.1.0:misc/openvdb \
+		gmp>=6.1.2:math/gmp \
+		mpfr>=4.0.2:math/mpfr
 
 USES=		cmake gettext
 
@@ -33,5 +37,19 @@ CMAKE_INSTALL_PREFIX=	${PREFIX}/${PORTNAME}
 USE_GITHUB=	yes
 USE_GL=		glew
 GH_ACCOUNT=	prusa3d
+
+post-patch:
+	${REINPLACE_CMD} -e 's,%%WRKSRC%%,${WRKSRC},' \
+		${WRKSRC}/CMakeLists.txt
+
+pre-build:
+	cd ${WRKDIR}/cgal-releases-CGAL-5.0.2 && \
+	${CMAKE_BIN} -E remove CGALConfig-installation-dirs.cmake && \
+	${MKDIR} build && cd build && \
+	${CMAKE_BIN} -DCMAKE_INSTALL_PREFIX=${WRKSRC}/CGAL \
+		-DCMAKE_PREFIX_PATH=${WRKSRC}/CGAL \
+		-DCMAKE_MODULE_PATH=${WRKSRC}/cmake/modules \
+		-DCMAKE_BUILD_TYPE=Release .. && \
+	${BSDMAKE} all install
 
 .include <bsd.port.mk>

Modified: head/cad/PrusaSlicer/distinfo
==============================================================================
--- head/cad/PrusaSlicer/distinfo	Sun Apr  5 11:26:52 2020	(r530769)
+++ head/cad/PrusaSlicer/distinfo	Sun Apr  5 11:46:17 2020	(r530770)
@@ -1,3 +1,5 @@
-TIMESTAMP = 1579717070
-SHA256 (prusa3d-PrusaSlicer-version_2.1.1_GH0.tar.gz) = 79d0681fbf3f4158cac25595522dcea330e0fa960934053ac929a15fa13c1072
-SIZE (prusa3d-PrusaSlicer-version_2.1.1_GH0.tar.gz) = 27551136
+TIMESTAMP = 1585766317
+SHA256 (prusa3d-PrusaSlicer-version_2.2.0_GH0.tar.gz) = e6e0c83bf92e448ec058fd3063b84caca69f58b8b419e48eace6e8ce534937c0
+SIZE (prusa3d-PrusaSlicer-version_2.2.0_GH0.tar.gz) = 30811929
+SHA256 (CGAL-5.0.2.tar.gz) = 7d824efce318fe901fd9d6f233a1f27e2d956d787602621df035a759b587c40c
+SIZE (CGAL-5.0.2.tar.gz) = 146441795

Added: head/cad/PrusaSlicer/files/patch-CMakeLists.txt
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/cad/PrusaSlicer/files/patch-CMakeLists.txt	Sun Apr  5 11:46:17 2020	(r530770)
@@ -0,0 +1,11 @@
+--- CMakeLists.txt.orig	2020-03-21 10:55:51 UTC
++++ CMakeLists.txt
+@@ -3,6 +3,8 @@ project(PrusaSlicer)
+ 
+ include("version.inc")
+ include(GNUInstallDirs)
++include_directories(BEFORE SYSTEM "%%WRKSRC%%/CGAL/include")
++add_compile_options(-DNDEBUG)
+ 
+ set(SLIC3R_RESOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/resources")
+ file(TO_NATIVE_PATH "${SLIC3R_RESOURCES_DIR}" SLIC3R_RESOURCES_DIR_WIN)

Added: head/cad/PrusaSlicer/files/patch-src_avrdude_libavrdude.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/cad/PrusaSlicer/files/patch-src_avrdude_libavrdude.h	Sun Apr  5 11:46:17 2020	(r530770)
@@ -0,0 +1,11 @@
+--- src/avrdude/libavrdude.h.orig	2020-03-21 10:55:51 UTC
++++ src/avrdude/libavrdude.h
+@@ -950,6 +950,8 @@ int read_config_builtin();
+ // Header file for alloca()
+ #if defined(WIN32NATIVE)
+ #  include <malloc.h>
++#elif defined __FreeBSD__
++#  include <stdlib.h>
+ #else
+ #  include <alloca.h>
+ #endif

Added: head/cad/PrusaSlicer/files/patch-src_hidapi_CMakeLists.txt
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/cad/PrusaSlicer/files/patch-src_hidapi_CMakeLists.txt	Sun Apr  5 11:46:17 2020	(r530770)
@@ -0,0 +1,20 @@
+--- src/hidapi/CMakeLists.txt.orig	2020-03-21 10:55:51 UTC
++++ src/hidapi/CMakeLists.txt
+@@ -1,8 +1,9 @@
+-
+ if (WIN32)
+     set(HIDAPI_IMPL win/hid.c)
+ elseif (APPLE)
+     set(HIDAPI_IMPL mac/hid.c)
++elseif (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
++	set(HIDAPI_IMPL libusb/hid.c)
+ else ()
+     # Assume Linux or Unix other than Mac OS
+     set(HIDAPI_IMPL linux/hid.c)
+@@ -16,4 +17,6 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ 	# Don't link the udev library, as there are two versions out there (libudev.so.0, libudev.so.1), so they are linked explicitely.
+ #	target_link_libraries(hidapi udev)
+ 	target_link_libraries(hidapi dl)
++elseif (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
++	target_link_libraries(hidapi usb iconv)
+ endif()

Added: head/cad/PrusaSlicer/files/patch-src_hidapi_libusb_hid.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/cad/PrusaSlicer/files/patch-src_hidapi_libusb_hid.c	Sun Apr  5 11:46:17 2020	(r530770)
@@ -0,0 +1,1517 @@
+--- src/hidapi/libusb/hid.c.orig	2020-03-31 19:30:48 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);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202004051146.035BkHhx004377>