svn commit: r530770 - in head/cad/PrusaSlicer: . files
Michael Reifenberger
mr at FreeBSD.org
Sun Apr 5 11:55:56 UTC 2020
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 at 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 at 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 ***
More information about the svn-ports-all
mailing list