diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..9c380ca --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,19 @@ +--- +name: Bug report +about: Create a report to help us improve + +--- + +**Environment:** + - OS: [e.g. Ubuntu 18.10 or Windows 10] + - Java version [e.g. Oracle Java 8] + - usb4java version [e.g. 1.3.0] + +**Bug description** +A clear and concise description of what the bug is. + +**Reproduction** +Java code example showing how to reproduce the error. + +**Expected behavior** +A clear and concise description of what you expected to happen. diff --git a/.gitignore b/.gitignore index 5a3ecc8..351afa7 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,6 @@ target .classpath .project .idea +.vscode *.iml hs_err_*.log diff --git a/LICENSE.md b/LICENSE.md index 7da529f..e7f8f8b 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,167 +1,20 @@ -GNU LESSER GENERAL PUBLIC LICENSE -================================= - -Version 3, 29 June 2007 - -Copyright (C) 2007 Free Software Foundation, Inc. - -Everyone is permitted to copy and distribute verbatim copies of this license -document, but changing it is not allowed. - -This version of the GNU Lesser General Public License incorporates the terms -and conditions of version 3 of the GNU General Public License, supplemented -by the additional permissions listed below. - - -### 0. Additional Definitions. - -As used herein, "this License" refers to version 3 of the GNU Lesser General -Public License, and the "GNU GPL" refers to version 3 of the GNU General -Public License. - -"The Library" refers to a covered work governed by this License, other than -an Application or a Combined Work as defined below. - -An "Application" is any work that makes use of an interface provided by the -Library, but which is not otherwise based on the Library. Defining a -subclass of a class defined by the Library is deemed a mode of using an -interface provided by the Library. - -A "Combined Work" is a work produced by combining or linking an Application -with the Library. The particular version of the Library with which the -Combined Work was made is also called the "Linked Version". - -The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code for -portions of the Combined Work that, considered in isolation, are based on -the Application, and not on the Linked Version. - -The "Corresponding Application Code" for a Combined Work means the object -code and/or source code for the Application, including any data and utility -programs needed for reproducing the Combined Work from the Application, but -excluding the System Libraries of the Combined Work. - - -### 1. Exception to Section 3 of the GNU GPL. - -You may convey a covered work under sections 3 and 4 of this License without -being bound by section 3 of the GNU GPL. - - -### 2. Conveying Modified Versions. - -If you modify a copy of the Library, and, in your modifications, a facility -refers to a function or data to be supplied by an Application that uses the -facility (other than as an argument passed when the facility is invoked), -then you may convey a copy of the modified version: - -* a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the function - or data, the facility still operates, and performs whatever part of its - purpose remains meaningful, or - -* b) under the GNU GPL, with none of the additional permissions of this - License applicable to that copy. - - -### 3. Object Code Incorporating Material from Library Header Files. - -The object code form of an Application may incorporate material from a -header file that is part of the Library. You may convey such object code -under terms of your choice, provided that, if the incorporated material is -not limited to numerical parameters, data structure layouts and accessors, -or small macros, inline functions and templates (ten or fewer lines in -length), you do both of the following: - -* a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are covered by - this License. - -* b) Accompany the object code with a copy of the GNU GPL and this license - document. - - -### 4. Combined Works. - -You may convey a Combined Work under terms of your choice that, taken -together, effectively do not restrict modification of the portions of the -Library contained in the Combined Work and reverse engineering for debugging -such modifications, if you also do each of the following: - -* a) Give prominent notice with each copy of the Combined Work that the - Library is used in it and that the Library and its use are covered by - this License. - -* b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - -* c) For a Combined Work that displays copyright notices during execution, - include the copyright notice for the Library among these notices, as - well as a reference directing the user to the copies of the GNU GPL and - this license document. - -* d) Do one of the following: - - * 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form suitable - for, and under terms that permit, the user to recombine or relink - the Application with a modified version of the Linked Version to - produce a modified Combined Work, in the manner specified by - section 6 of the GNU GPL for conveying Corresponding Source. - - * 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time a - copy of the Library already present on the user's computer system, - and (b) will operate properly with a modified version of the - Library that is interface-compatible with the Linked Version. - -* e) Provide Installation Information, but only if you would otherwise be - required to provide such information under section 6 of the GNU GPL, - and only to the extent that such information is necessary to install - and execute a modified version of the Combined Work produced by - recombining or relinking the Application with a modified version of the - Linked Version. (If you use option 4d0, the Installation Information - must accompany the Minimal Corresponding Source and Corresponding - Application Code. If you use option 4d1, you must provide the - Installation Information in the manner specified by section 6 of the - GNU GPL for conveying Corresponding Source.) - - -### 5. Combined Libraries. - -You may place library facilities that are a work based on the Library side -by side in a single library together with other library facilities that are -not Applications and are not covered by this License, and convey such a -combined library under terms of your choice, if you do both of the -following: - -* a) Accompany the combined library with a copy of the same work based on - the Library, uncombined with any other library facilities, conveyed - under the terms of this License. - -* b) Give prominent notice with the combined library that part of it is a - work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - -### 6. Revised Versions of the GNU Lesser General Public License. - -The Free Software Foundation may publish revised and/or new versions of the -GNU Lesser General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Library as you -received it specifies that a certain numbered version of the GNU Lesser -General Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that published -version or of any later version published by the Free Software Foundation. -If the Library as you received it does not specify a version number of the -GNU Lesser General Public License, you may choose any version of the GNU -Lesser General Public License ever published by the Free Software -Foundation. - -If the Library as you received it specifies that a proxy can decide whether -future versions of the GNU Lesser General Public License shall apply, that -proxy's public statement of acceptance of any version is permanent -authorization for you to choose that version for the Library. +Copyright (C) 2011 Klaus Reimer, k@ailis.de +Copyright (C) 2013 Luca Longinotti, l@longi.li + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 40dbba2..5636524 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ See LICENSE.md for licensing information. This library can be used to access USB devices in Java. It is based on the native libusb 1.0 shared library and reflects this API as complete as -possible. usb4java also implements the javax.usb (JSR80) API. So you can choose +possible. usb4java also implements the javax-usb (JSR80) API. So you can choose if you want to access the USB devices via the low-level libusb 1.0 API or -via the high level javax.usb API. +via the high level javax-usb API. The native libraries are included in pre-compiled form for Linux, Windows and Mac OS X in 32 and 64 bit versions. The libraries are automatically extracted @@ -21,5 +21,3 @@ and loaded so you don't need to care about them. For more detailed information please visit the [usb4java website](http://usb4java.org/). -[![Build Status](https://ci.ailis.de/job/usb4java/badge/icon)](https://ci.ailis.de/job/usb4java/) - diff --git a/pom.xml b/pom.xml index a3b38e2..3e169f6 100644 --- a/pom.xml +++ b/pom.xml @@ -1,30 +1,30 @@ 4.0.0 - + org.usb4java usb4java jar usb4java - 1.2.0 + 1.3.1-SNAPSHOT http://usb4java.org/ - USB library for Java based on libusb and implementing javax.usb (JSR-80). + USB library for Java based on libusb and implementing javax-usb (JSR-80). 2011 usb4java Team http://usb4java.org/ - + - LGPL + MIT LICENSE.md repo - + Discussions @@ -32,9 +32,9 @@ usb4java+unsubscribe@googlegroups.com usb4java@googlegroups.com http://groups.google.com/group/usb4java - - - + + + kayahr @@ -45,7 +45,7 @@ +1 http://www.ailis.de/~k/ - + llongi Luca Longinotti @@ -55,45 +55,36 @@ +1 http://l.longi.li/ - + UTF-8 - http://nexus.ailis.de/content/groups/public/org/usb4java - - ${repoBaseUrl}/${project.version}/${project.artifactId}-${project.version} - 1.2.0 - 1.2.0 + 1.3.1-SNAPSHOT - + scm:git:git://github.com/usb4java/${project.artifactId}.git scm:git:ssh://git@github.com/usb4java/${project.artifactId}.git http://github.com/usb4java/${project.artifactId} - usb4java-1.2.0 + HEAD - + GitHub https://github.com/usb4java/${project.artifactId}/issues - - - Jenkins - https://ci.ailis.de/job/${project.artifactId}/ - - + - 3.0 + 3.0.5 - + org.apache.maven.plugins maven-project-info-reports-plugin - 2.7 + 3.0.0 false false @@ -102,23 +93,25 @@ summary - project-team - mailing-list - issue-tracking + team + mailing-lists + issue-management scm - cim - license + licenses dependencies plugins plugin-management - - - + + + - + org.apache.maven.plugins maven-changes-plugin - 2.9 + 2.12.1 + + team.html + @@ -130,7 +123,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 2.9.1 + 3.0.1 @@ -139,39 +132,29 @@ - - - + + + - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.16 - - - - - + org.apache.maven.plugins maven-compiler-plugin - 3.1 + 3.8.0 1.6 1.6 ${project.build.sourceEncoding} - + org.apache.maven.plugins - maven-site-plugin - 3.3 + maven-site-plugin + 3.7.1 false en @@ -179,55 +162,79 @@ ${project.build.sourceEncoding} - - - - org.apache.maven.plugins - maven-jar-plugin - 2.4 - - - org.codehaus.plexus - plexus-archiver - 2.4.4 - - - + - + maven-assembly-plugin - 2.4 + 3.1.0 + false false src/main/assembly/tarball.xml src/main/assembly/zip.xml - - - 420 - 493 - 493 - package-assembly package - attached + single - + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.0 + + + org.apache.maven.plugins + maven-clean-plugin + 3.1.0 + + + org.apache.maven.plugins + maven-deploy-plugin + 3.0.0-M1 + + + org.apache.maven.plugins + maven-install-plugin + 3.0.0-M1 + + + org.apache.maven.plugins + maven-resources-plugin + 3.1.0 + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.0 + + + org.apache.maven.plugins + maven-source-plugin + 3.0.1 + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.0.1 + + + org.apache.maven.plugins + maven-release-plugin + 2.5.3 - - - - + - ailis - Ailis Maven Repository - http://nexus.ailis.de/content/groups/public/ + sonatype-releases + Sonatype Snapshot Repository + https://oss.sonatype.org/content/repositories/releases + true + false + + + sonatype-snapshots + Sonatype Snapshot Repository + https://oss.sonatype.org/content/repositories/snapshots + false + true @@ -271,7 +287,6 @@ project-website file://${project.basedir}/../${project.artifactId}-site/ - - - ailis-releases - Ailis Maven Releases - http://nexus.ailis.de/content/repositories/releases - - - ailis-snapshots - Ailis Maven Snapshots - http://nexus.ailis.de/content/repositories/snapshots - - + - + junit junit - 4.11 + 4.12 test @@ -308,48 +311,48 @@ libusb4java ${libusb4java.version} linux-x86 - + org.usb4java libusb4java ${libusb4java.version} - linux-x86_64 - + linux-x86-64 + org.usb4java libusb4java ${libusb4java.version} - linux-arm - + win32-x86 + org.usb4java libusb4java ${libusb4java.version} - windows-x86 - + win32-x86-64 + org.usb4java libusb4java ${libusb4java.version} - windows-x86_64 - + darwin-x86-64 + org.usb4java libusb4java ${libusb4java.version} - osx-x86 - + linux-arm + org.usb4java libusb4java ${libusb4java.version} - osx-x86_64 - + linux-aarch64 + org.apache.commons commons-lang3 - 3.2.1 + 3.8.1 - + diff --git a/src/changes/changes.xml b/src/changes/changes.xml index e4d2690..de229a9 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -1,36 +1,59 @@ - Changelog Klaus Reimer - + + + + Renamed os and architecture identifiers to the naming conventions of + the JNA project. So the platforms are now named: linux-x86, + linux-x86-64, linux-arm, linux-aarch64, darwin-x86-64, win32-x86 and + win32-x86-64. + + + Add missing SPEED_SUPER_PLUS constant. + + + Wrap new libusb functions: setOption, devMemAlloc, devMemFree, interruptEventHandler, getPollfds, freePollfds. + + + Updated to libusb 1.0.22. + + + Dropped support for 32 bit macOS because XCode no longer supports it. + + + Added support for 64 bit ARM platform. + + Split project into usb4java (Main library), usb4java-javax - (javax.usb extension) and libusb4java (Native code). + (javax-usb extension) and libusb4java (Native code). - Add hotplug support to low-level API. + Add hotplug support to low-level API. - Add asynchronous I/O support to low-level API. + Add asynchronous I/O support to low-level API. - Using reunited libusb/libusbx 1.0.16 as backend. + Using reunited libusb/libusbx 1.0.16 as backend. - Add new libusb constants: LOW_SPEED_OPERATION, FULL_SPEED_OPERATION, + Add new libusb constants: LOW_SPEED_OPERATION, FULL_SPEED_OPERATION, HIGH_SPEED_OPERATION, SUPER_SPEED_OPERATION, BM_LPM_SUPPORT, BM_LTM_SUPPORT, BT_WIRELESS_USB_DEVICE_CAPABILITY, BT_USB_2_0_EXTENSION, BT_SS_USB_DEVICE_CAPABILITY, BT_CONTAINER_ID, CAP_HAS_HOTPLUG, CAP_HAS_HID_ACCESS, CAP_SUPPORTS_DETACH_KERNEL_DRIVER, DT_BOS, - DT_DEVICE_CAPABILITY, DT_SS_ENDPOINT_COMPANION + DT_DEVICE_CAPABILITY, DT_SS_ENDPOINT_COMPANION Wrap new libusb methods: getPortNumbers, setAutoDetachKernelDriver, @@ -51,26 +74,26 @@ - Rewritten library to use libusb 1.0 as backend. + Rewritten library to use libusb 1.0 as backend. Made library loading more universal to support loading shared libraries - for platforms not officially supported by usb4java. + for platforms not officially supported by usb4java. - Add native library for linux-arm platform (Raspberry Pi). + Add native library for linux-arm platform (Raspberry Pi). Native libraries are no longer extracted to a temporary directory when they are not in a JAR file. - + - Improve error handling during native lib loading so javax.usb no + Improve error handling during native lib loading so javax-usb no longer hides the important exceptions. - + Fix logic error in AbstractIrpQueue#isBusy(). - + @@ -97,7 +120,7 @@ - Fixed library paths in dylibs so they can be placed in + Fixed library paths in dylibs so they can be placed in *.app/Contents/MacOS. @@ -130,7 +153,7 @@ libusb reports broken bus root devices when detaching USB devices and when user has no root permissions on linux. Fixed it by - only trusting root devices which are also in the device list of a bus. + only trusting root devices which are also in the device list of a bus. diff --git a/src/main/assembly/README.txt b/src/main/assembly/README.txt index 62f3f9b..e6b9c1c 100644 --- a/src/main/assembly/README.txt +++ b/src/main/assembly/README.txt @@ -11,6 +11,6 @@ libusb4java-*.jar (The native libraries for the various platforms) commons-lang3-*.jar (Apache Commons Lang library needed by usb4java) If you don't want usb4java to extract the native libraries into a temporary -directoy on each program start then you might want to distribute them in +directory on each program start then you might want to distribute them in extracted form with your application. Just make sure your classpath points to the directory where you extracted the JARs. diff --git a/src/main/assembly/tarball.xml b/src/main/assembly/tarball.xml index a37a02d..35bb930 100644 --- a/src/main/assembly/tarball.xml +++ b/src/main/assembly/tarball.xml @@ -4,12 +4,12 @@ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd"> tarball - tar.bz2 + tar.xz - / + LICENSE.md @@ -18,7 +18,7 @@ src/main/assembly - / + README.txt AUTHORS.txt @@ -30,9 +30,9 @@ - lib + lib false runtime - + diff --git a/src/main/assembly/zip.xml b/src/main/assembly/zip.xml index 7d043c1..5f37b66 100644 --- a/src/main/assembly/zip.xml +++ b/src/main/assembly/zip.xml @@ -9,7 +9,7 @@ - / + LICENSE.md @@ -18,7 +18,7 @@ src/main/assembly - / + README.txt AUTHORS.txt diff --git a/src/main/java/org/usb4java/ConfigDescriptor.java b/src/main/java/org/usb4java/ConfigDescriptor.java index b741391..60cb03c 100644 --- a/src/main/java/org/usb4java/ConfigDescriptor.java +++ b/src/main/java/org/usb4java/ConfigDescriptor.java @@ -107,9 +107,10 @@ public long getPointer() public native byte bmAttributes(); /** - * Returns the maximum power consumption of the USB device from this bus - * in this configuration when the device is fully operation. Expressed in - * units of 2 mA. + * Returns the maximum power consumption of the USB device from this bus + * configuration when the device is fully operation. Expressed in units + * of 2 mA when the device is operating in high-speed mode and in units + * of 8 mA when the device is operating in super-speed mode. * * @return The maximum power consumption. */ diff --git a/src/main/java/org/usb4java/DescriptorUtils.java b/src/main/java/org/usb4java/DescriptorUtils.java index a30d1b6..75f281f 100644 --- a/src/main/java/org/usb4java/DescriptorUtils.java +++ b/src/main/java/org/usb4java/DescriptorUtils.java @@ -17,7 +17,7 @@ public final class DescriptorUtils { /** Mapping from USB class id to USB class name. */ - private static final Map CLASS_NAMES = + private static final Map CLASS_NAMES = new HashMap(); static @@ -35,8 +35,7 @@ public final class DescriptorUtils CLASS_NAMES.put(LibUsb.CLASS_SMART_CARD, "Smart Card"); CLASS_NAMES.put(LibUsb.CLASS_CONTENT_SECURITY, "Content Security"); CLASS_NAMES.put(LibUsb.CLASS_VIDEO, "Video"); - CLASS_NAMES.put(LibUsb.CLASS_PERSONAL_HEALTHCARE, - "Personal Healthcare"); + CLASS_NAMES.put(LibUsb.CLASS_PERSONAL_HEALTHCARE, "Personal Healthcare"); CLASS_NAMES.put(LibUsb.CLASS_DIAGNOSTIC_DEVICE, "Diagnostic Device"); CLASS_NAMES.put(LibUsb.CLASS_WIRELESS, "Wireless"); CLASS_NAMES.put(LibUsb.CLASS_APPLICATION, "Application"); @@ -137,7 +136,7 @@ public static String dump(final DeviceDescriptor descriptor) * @param product * The product string or null if unknown. * @param serial - * The serial number strsing or null if unknown. + * The serial number string or null if unknown. * @return The descriptor dump. */ public static String dump(final DeviceDescriptor descriptor, @@ -348,7 +347,7 @@ public static String getUsageTypeName(final byte bmAttributes) return "Feedback"; case LibUsb.ISO_USAGE_TYPE_IMPLICIT: return "Implicit Feedback Data"; - case 3: + case 3: // b11 is considered "Reserved" according to USB 3.0 spec. return "Reserved"; default: diff --git a/src/main/java/org/usb4java/DeviceDescriptor.java b/src/main/java/org/usb4java/DeviceDescriptor.java index a79244d..81804f4 100644 --- a/src/main/java/org/usb4java/DeviceDescriptor.java +++ b/src/main/java/org/usb4java/DeviceDescriptor.java @@ -59,11 +59,11 @@ public long getPointer() { return this.deviceDescriptorPointer; } - + /** * Returns the Java byte buffer which contains the descriptor structure. * - * @return The descriptor structur buffer. + * @return The descriptor structure buffer. */ public ByteBuffer getBuffer() { @@ -72,15 +72,15 @@ public ByteBuffer getBuffer() /** * Returns the size of this descriptor (in bytes). - * - * @return The size of this descriptor (in bytes). + * + * @return The size of this descriptor (in bytes). */ public native byte bLength(); /** * Returns the descriptor type. Will have value {@link LibUsb#DT_DEVICE} - * in this context. - * + * in this context. + * * @return The descriptor type. */ public native byte bDescriptorType(); @@ -88,88 +88,88 @@ public ByteBuffer getBuffer() /** * Returns the USB specification release number in binary-coded decimal. * A value of 0x0200 indicates USB 2.0, 0x0110 indicates USB 1.1, etc. - * + * * @return The USB specification release number. - */ + */ public native short bcdUSB(); /** * Returns the USB-IF class code for the device. See LibUSB.CLASS_* * constants. - * + * * @return The USB-IF class code. */ public native byte bDeviceClass(); /** - * Returns the USB-IF subclass code for the device, qualified by the + * Returns the USB-IF subclass code for the device, qualified by the * bDeviceClass value. - * + * * @return The USB-IF subclass code. - */ + */ public native byte bDeviceSubClass(); /** - * Returns the USB-IF protocol code for the device, qualified by the + * Returns the USB-IF protocol code for the device, qualified by the * bDeviceClass and bDeviceSubClass values. - * + * * @return The USB-IF protocol code. */ public native byte bDeviceProtocol(); /** * Returns the maximum packet size for endpoint 0. - * + * * @return The maximum packet site for endpoint 0. */ public native byte bMaxPacketSize0(); /** * Returns the USB-IF vendor ID. - * + * * @return The vendor ID */ public native short idVendor(); /** * Returns the USB-IF product ID. - * + * * @return The product ID. */ public native short idProduct(); /** * Returns the device release number in binary-coded decimal. - * + * * @return The device release number. */ public native short bcdDevice(); /** * Returns the index of the string descriptor describing manufacturer. - * + * * @return The manufacturer string descriptor index. */ public native byte iManufacturer(); /** * Returns the index of the string descriptor describing product. - * + * * @return The product string descriptor index. */ public native byte iProduct(); /** - * Returns the index of the string descriptor containing device serial + * Returns the index of the string descriptor containing device serial * number. - * + * * @return The serial number string descriptor index. */ public native byte iSerialNumber(); /** * Returns the number of possible configurations. - * + * * @return The number of possible configurations. */ public native byte bNumConfigurations(); diff --git a/src/main/java/org/usb4java/LibUsb.java b/src/main/java/org/usb4java/LibUsb.java index d85dda1..6cebb61 100644 --- a/src/main/java/org/usb4java/LibUsb.java +++ b/src/main/java/org/usb4java/LibUsb.java @@ -59,6 +59,44 @@ public final class LibUsb */ public static final int LOG_LEVEL_DEBUG = 4; + + // Available option values for {@link #setOption()} + + /** + * Set the log message verbosity. + * + * The default level is {@link #LOG_LEVEL_NONE}, which means no messages are ever + * printed. If you choose to increase the message verbosity level, ensure + * that your application does not close the stderr file descriptor. + * + * You are advised to use level {@link #LOG_LEVEL_WARNING}. libusb is conservative + * with its message logging and most of the time, will only log messages that + * explain error conditions and other oddities. This will help you debug + * your software. + * + * If the LIBUSB_DEBUG environment variable was set when libusb was + * initialized, this function does nothing: the message verbosity is fixed + * to the value in the environment variable. + * + * If libusb was compiled without any message logging, this function does + * nothing: you'll never get any messages. + * + * If libusb was compiled with verbose debug message logging, this function + * does nothing: you'll always get messages from all levels. + */ + public static final int OPTION_LOG_LEVEL = 0; + + /** + * Use the UsbDk backend for a specific context, if available. + * + * This option should be set immediately after calling {@link #init(Context)}, otherwise + * unspecified behavior may occur. + * + * Only valid on Windows. + */ + public static final int OPTION_USE_USBDK = 1; + + // Error codes. Most libusb functions return 0 on success or one of these // codes on failure. You can call errorName() to retrieve a string // representation of an error code. @@ -125,6 +163,10 @@ public final class LibUsb /** The device is operating at super speed (5000MBit/s). */ public static final int SPEED_SUPER = 4; + /** The device is operating at super speed plus (10000MBit/s). */ + public static final int SPEED_SUPER_PLUS = 5; + + // Supported speeds (wSpeedSupported) bitfield. Indicates what speeds the // device supports. @@ -441,7 +483,7 @@ public final class LibUsb /** We unwrap the BOS => define its maximum size. */ public static final byte DT_BOS_MAX_SIZE = DT_BOS_SIZE - + BT_USB_2_0_EXTENSION_SIZE + BT_SS_USB_DEVICE_CAPABILITY_SIZE + + BT_USB_2_0_EXTENSION_SIZE + BT_SS_USB_DEVICE_CAPABILITY_SIZE + BT_CONTAINER_ID_SIZE; // Endpoint direction. Values for bit 7 of the endpoint address scheme. @@ -478,6 +520,9 @@ public final class LibUsb /** Interrupt endpoint. */ public static final byte TRANSFER_TYPE_INTERRUPT = 3; + /** Stream endpoint. */ + public static final byte TRANSFER_TYPE_BULK_STREAM = 4; + // Synchronization type for isochronous endpoints. // Values for bits 2:3 of the bmAttributes field in // EndpointDescriptor. @@ -519,7 +564,7 @@ public final class LibUsb /** * Automatically free transfer buffer during {@link #freeTransfer(Transfer)} - * + * * Please note that this flag (which is originally 2) is effectively a no-op * (set to zero) here in the Java wrapper, since the ByteBuffer that acts as * a buffer for transfers is allocated by the JVM and is subject to garbage @@ -594,6 +639,11 @@ public final class LibUsb // Flags for hotplug events + /** + * Default value when not using any flags. + */ + public static final int HOTPLUG_NO_FLAGS = 0; + /** * Arm the callback and fire it for all matching currently attached devices. */ @@ -624,14 +674,14 @@ public final class LibUsb /** * Hotplug callbacks (to correctly manage calls and additional data). */ - private static final ConcurrentMap> hotplugCallbacks = new ConcurrentHashMap>(); /** * Pollfd listeners (to support different listeners for different contexts). */ - private static final ConcurrentMap> pollfdListeners = new ConcurrentHashMap>(); @@ -712,9 +762,49 @@ private LibUsb() * context. * @param level * The log level to set. + * + * @deprecated Use {@link #setOption(Context, int, int)} instead using the {@link #OPTION_LOG_LEVEL} option. */ public static native void setDebug(final Context context, final int level); + /** + * Set an option in the library. + * + * Use this function to configure a specific option within the library. + * + * Some options require one or more arguments to be provided. Consult each option's documentation for specific + * requirements. + * + * @param context + * The {@link Context} on which to operate. + * @param option + * Which option to set. + * @return {@link #SUCCESS} on success, {@link #ERROR_INVALID_PARAM} if the option or arguments are invalid, + * {@link #ERROR_NOT_SUPPORTED} if the option is valid but not supported on this platform. + */ + public static int setOption(final Context context, final int option) { + return setOption(context, option, 0); + } + + /** + * Set an option in the library. + * + * Use this function to configure a specific option within the library. + * + * Some options require one or more arguments to be provided. Consult each option's documentation for specific + * requirements. + * + * @param context + * The {@link Context} on which to operate. + * @param option + * Which option to set. + * @param value + * Required argument for the specified option. + * @return {@link #SUCCESS} on success, {@link #ERROR_INVALID_PARAM} if the option or arguments are invalid, + * {@link #ERROR_NOT_SUPPORTED} if the option is valid but not supported on this platform. + */ + public static native int setOption(final Context context, final int option, final int value); + /** * Returns the version of the libusb runtime. * @@ -945,7 +1035,7 @@ public static native int getMaxIsoPacketSize(final Device device, * {@link #ERROR_NO_DEVICE} if the device has been disconnected, * another error on other failure */ - public static native int open(final Device device, + public static native int open(final Device device, final DeviceHandle handle); /** @@ -988,7 +1078,7 @@ public static native DeviceHandle openDeviceWithVidPid( */ public static native void close(final DeviceHandle handle); -/** + /** * Get the underlying device for a handle. * * Please note that the reference count of the returned device is not @@ -1187,6 +1277,82 @@ public static native int clearHalt(final DeviceHandle handle, */ public static native int resetDevice(final DeviceHandle handle); + /** + * Allocate up to numStreams USB bulk streams on the specified endpoints. + * This function takes an array of endpoints rather then a single endpoint + * because some protocols require that endpoints are setup with similar + * stream ids. All endpoints passed in must belong to the same interface. + * + * Note that this function may return less streams then requested. + * + * Stream id 0 is reserved, and should not be used to communicate with + * devices. If LibUsb.allocStreams() returns with a value of N, you may + * use stream ids 1 to N. + * + * @param handle + * a device handle + * @param numStreams + * number of streams to try to allocate + * @param endpoints + * array of endpoints to allocate streams on + * @return The number of streams allocated, or a LIBUSB_ERROR code + * on failure. + */ + public static native int allocStreams(final DeviceHandle handle, + final int numStreams, final byte[] endpoints); + + /** + * Free USB bulk streams allocated with LibUsb.allocStreams(). + * + * Note streams are automatically free-ed when releasing an interface. + * + * @param handle + * a device handle + * @param endpoints + * array of endpoints to allocate streams on + * @return 0 on success, or a LIBUSB_ERROR code on failure. + */ + public static native int freeStreams(final DeviceHandle handle, + final byte[] endpoints); + + + /** + * Attempts to allocate a block of persistent DMA memory suitable for transfers against the given device. + * + * If successful, will return a block of memory that is suitable for use as "buffer" in {@link Transfer} + * against this device. Using this memory instead of regular memory means that the host controller can use DMA + * directly into the buffer to increase performance, and also that transfers can no longer fail due to kernel + * memory fragmentation. + * + * Note that this means you should not modify this memory (or even data on the same cache lines) when a transfer + * is in progress, although it is legal to have several transfers going on within the same memory block. + * + * Will return NULL on failure. Many systems do not support such zerocopy and will always return NULL. Memory + * allocated with this function must be freed with {@link #devMemFree(DeviceHandle, ByteBuffer, int)}. + * Specifically, this means that the flag {@link #TRANSFER_FREE_BUFFER} cannot be used to free memory + * allocated with this function. + * + * @param handle + * A device handle. + * @param length + * Size of desired data buffer. + * @return The newly allocated memory, or NULL on failure. + */ + public static native ByteBuffer devMemAlloc(final DeviceHandle handle, final int length); + + /** + * Free device memory allocated with {@link #devMemAlloc(DeviceHandle, int)}. + * + * @param handle + * A device handle. + * @param buffer + * The previously allocated memory. + * @param size + * The size of the previously allocated memory. + * @return {@link #SUCCESS}, or a LIBUSB_ERROR code on failure. + */ + public static native int devMemFree(final DeviceHandle handle, final ByteBuffer buffer, final int size); + /** * Determine if a kernel driver is active on an interface. * @@ -1416,7 +1582,7 @@ public static native int getStringDescriptorAscii( * A simple wrapper around * {@link #getStringDescriptorAscii(DeviceHandle, byte, StringBuffer)}. * It simply returns the string (maximum length of 127) if possible. If not - * possible (NULL handle or 0-index specified or error occured) then null is + * possible (NULL handle or 0-index specified or error occurred) then null is * returned. * * This method is not part of libusb. @@ -1550,7 +1716,7 @@ public static native int getSsEndpointCompanionDescriptor( /** * Free a superspeed endpoint companion descriptor obtained from - * {@link #getSsEndpointCompanionDescriptor(Context, EndpointDescriptor, + * {@link #getSsEndpointCompanionDescriptor(Context, EndpointDescriptor, * SsEndpointCompanionDescriptor)}. * * It is safe to call this function with a NULL parameter, in which case the @@ -1611,7 +1777,7 @@ public static native int getUsb20ExtensionDescriptor(final Context context, /** * Free a USB 2.0 Extension descriptor obtained from - * {@link #getUsb20ExtensionDescriptor(Context, BosDevCapabilityDescriptor, + * {@link #getUsb20ExtensionDescriptor(Context, BosDevCapabilityDescriptor, * Usb20ExtensionDescriptor)}. * * It is safe to call this function with a NULL parameter, in which case @@ -1646,7 +1812,7 @@ public static native int getSsUsbDeviceCapabilityDescriptor( /** * Free a SuperSpeed USB Device Capability descriptor obtained from - * {@link #getSsUsbDeviceCapabilityDescriptor(Context, + * {@link #getSsUsbDeviceCapabilityDescriptor(Context, * BosDevCapabilityDescriptor, SsUsbDeviceCapabilityDescriptor)}. * * It is safe to call this function with a NULL parameter, @@ -1679,7 +1845,7 @@ public static native int getContainerIdDescriptor(final Context context, /** * Free a Container ID descriptor obtained from - * {@link #getContainerIdDescriptor(Context, BosDevCapabilityDescriptor, + * {@link #getContainerIdDescriptor(Context, BosDevCapabilityDescriptor, * ContainerIdDescriptor)}. * * It is safe to call this function with a NULL parameter, in which case @@ -1712,7 +1878,7 @@ public static int getDescriptor(final DeviceHandle handle, final byte type, final byte index, final ByteBuffer data) { return controlTransfer(handle, ENDPOINT_IN, REQUEST_GET_DESCRIPTOR, - (short) (((type & 0xff) << 8) | (index & 0xff)), (short) 0, + (short) (((type & 0xff) << 8) | (index & 0xff)), (short) 0, data, 1000); } @@ -1764,14 +1930,17 @@ public static int getStringDescriptor(final DeviceHandle handle, * A suitably-sized data buffer for either input or output * (depending on direction bits within bmRequestType). * @param timeout - * Timeout (in millseconds) that this function should wait before + * Timeout (in milliseconds) that this function should wait before * giving up due to no response being received. For an unlimited * timeout, use value 0. * @return on success the number of bytes actually transferred, * {@link #ERROR_TIMEOUT} if the transfer timed out, - * {@link #ERROR_PIPE} if the control request was not supported by - * the device, {@link #ERROR_NO_DEVICE} if the device has been - * disconnected, another ERROR code on other failures + * {@link #ERROR_PIPE} if the control request was not supported by the device, + * {@link #ERROR_NO_DEVICE} if the device has been disconnected, + * {@link #ERROR_BUSY} if called from event handling context, + * {@link #ERROR_INVALID_PARAM} if the transfer size is larger than the operating system and/or + * hardware can support. + * Another ERROR code on other failures */ public static native int controlTransfer(final DeviceHandle handle, final byte bmRequestType, final byte bRequest, final short wValue, @@ -1808,7 +1977,7 @@ public static native int controlTransfer(final DeviceHandle handle, * @param transferred * Output location for the number of bytes actually transferred. * @param timeout - * timeout (in millseconds) that this function should wait before + * timeout (in milliseconds) that this function should wait before * giving up due to no response being received. For an unlimited * timeout, use value 0. * @return 0 on success (and populates transferred), {@link #ERROR_TIMEOUT} @@ -1855,7 +2024,7 @@ public static native int bulkTransfer(final DeviceHandle handle, * @param transferred * Output location for the number of bytes actually transferred. * @param timeout - * Timeout (in millseconds) that this function should wait before + * Timeout (in milliseconds) that this function should wait before * giving up due to no response being received. For an unlimited * timeout, use value 0. * @return 0 on success (and populates transferred), {@link #ERROR_TIMEOUT} @@ -1960,6 +2129,17 @@ public static native int interruptTransfer(final DeviceHandle handle, */ public static native int eventHandlerActive(final Context context); + /** + * Interrupt any active thread that is handling events. + * + * This is mainly useful for interrupting a dedicated event handling thread when an application wishes to call + * {@link #exit(Context)}. + * + * @param context + * The context to operate on, or NULL for the default context. + */ + public static native void interruptEventHandler(final Context context); + /** * Acquire the event waiters lock. * @@ -1972,7 +2152,7 @@ public static native int interruptTransfer(final DeviceHandle handle, * * You only need to use this lock if you are developing an application which * calls poll() or select() on libusb's file descriptors directly, and may - * potentially be handling events from 2 threads simultaenously. If you + * potentially be handling events from 2 threads simultaneously. If you * stick to libusb's event handling loop functions (e.g. * {@link #handleEvents(Context)}) then you do not need to be concerned with * this locking. @@ -2059,17 +2239,17 @@ public static native int handleEventsTimeoutCompleted( /** * Handle any pending events. - * + * * Like {@link #handleEventsTimeoutCompleted(Context, long, IntBuffer)}, but * without the completed parameter, calling this function is equivalent to * calling {@link #handleEventsTimeoutCompleted(Context, long, IntBuffer)} * with a NULL completed parameter. - * + * * This function is kept primarily for backwards compatibility. All new code * should call {@link #handleEventsCompleted(Context, IntBuffer)} or * {@link #handleEventsTimeoutCompleted(Context, long, IntBuffer)} to avoid * race conditions. - * + * * @param context * The context to operate on, or NULL for the default context * @param timeout @@ -2121,17 +2301,17 @@ public static native int handleEventsCompleted(final Context context, /** * Handle any pending events by polling file descriptors, without checking * if any other threads are already doing so. - * + * * Must be called with the event lock held, see {@link #lockEvents(Context)} * . - * + * * This function is designed to be called under the situation where you have * taken the event lock and are calling poll()/select() directly on libusb's * file descriptors (as opposed to using {@link #handleEvents(Context)} or * similar). You detect events on libusb's descriptors, so you then call * this function with a zero timeout value (while still holding the event * lock). - * + * * @param context * The context to operate on, or NULL for the default context. * @param timeout @@ -2329,6 +2509,31 @@ static native void setPollfdNotifiersNative(final Context context, */ static native void unsetPollfdNotifiersNative(final Context context); + /** + * Retrieve a list of file descriptors that should be polled by your main loop as libusb event sources. + * + * The returned list should be freed with {@link #freePollfds(Pollfds)} when done. The actual list contents must not be + * touched. + * + * As file descriptors are a Unix-specific concept, this function is not available on Windows and will always + * return NULL. + * + * @param context + * The context to operate on, or NULL for the default context. + * @return A list of libusb_pollfd structures, NULL on error, NULL on platforms where the functionality is not + * available. + */ + public static native Pollfds getPollfds(final Context context); + + /** + * Free a list of {@link Pollfd} structures. + * + * This should be called for all pollfd lists allocated with {@link #getPollfds(Context)}. + * + * It is legal to call this function with a NULL pollfd list. In this case, the function will simply return safely. + */ + public static native void freePollfds(final Pollfds pollfds); + /** * Allocate a libusb transfer without support for isochronous transfers. * @@ -2588,6 +2793,37 @@ public static void fillBulkTransfer(final Transfer transfer, transfer.setCallback(callback); } + /** + * Helper function to populate the required {@link Transfer} fields + * for a bulk transfer using bulk streams. + * + * @param transfer + * The transfer to populate. + * @param handle + * Handle of the device that will handle the transfer. + * @param endpoint + * Address of the endpoint where this transfer will be sent. + * @param streamId + * Bulk stream id for this transfer. + * @param buffer + * Data buffer. + * @param callback + * Callback function to be invoked on transfer completion. + * @param userData + * User data to pass to callback function. + * @param timeout + * Timeout for the transfer in milliseconds. + */ + public static void fillBulkStreamTransfer(final Transfer transfer, + final DeviceHandle handle, final byte endpoint, final int streamId, + final ByteBuffer buffer, final TransferCallback callback, + final Object userData, final long timeout) + { + fillBulkTransfer(transfer, handle, endpoint, buffer, callback, userData, timeout); + transfer.setType(TRANSFER_TYPE_BULK_STREAM); + transfer.setStreamId(streamId); + } + /** * Helper function to populate the required {@link Transfer} fields for an * interrupt transfer. @@ -2844,7 +3080,7 @@ public static synchronized int hotplugRegisterCallback( : (vendorId & 0xFFFF), (productId == LibUsb.HOTPLUG_MATCH_ANY) ? (LibUsb.HOTPLUG_MATCH_ANY) : (productId & 0xFFFF), - (deviceClass == LibUsb.HOTPLUG_MATCH_ANY) ? + (deviceClass == LibUsb.HOTPLUG_MATCH_ANY) ? (LibUsb.HOTPLUG_MATCH_ANY) : (deviceClass & 0xFF), callbackHandle, globalHotplugId); diff --git a/src/main/java/org/usb4java/Loader.java b/src/main/java/org/usb4java/Loader.java index bbf6f0e..8d8339a 100644 --- a/src/main/java/org/usb4java/Loader.java +++ b/src/main/java/org/usb4java/Loader.java @@ -22,45 +22,6 @@ public final class Loader /** Buffer size used for copying data. */ private static final int BUFFER_SIZE = 8192; - /** Constant for OS X operating system. */ - private static final String OS_OSX = "osx"; - - /** Constant for OS X operating system. */ - private static final String OS_MACOSX = "macosx"; - - /** Constant for Linux operating system. */ - private static final String OS_LINUX = "linux"; - - /** Constant for Windows operating system. */ - private static final String OS_WINDOWS = "windows"; - - /** Constant for FreeBSD operating system. */ - private static final String OS_FREEBSD = "freebsd"; - - /** Constant for SunOS operating system. */ - private static final String OS_SUNOS = "sunos"; - - /** Constant for i386 architecture. */ - private static final String ARCH_I386 = "i386"; - - /** Constant for x86 architecture. */ - private static final String ARCH_X86 = "x86"; - - /** Constant for x86_64 architecture. */ - private static final String ARCH_X86_64 = "x86_64"; - - /** Constant for amd64 architecture. */ - private static final String ARCH_AMD64 = "amd64"; - - /** Constant for so file extension. */ - private static final String EXT_SO = "so"; - - /** Constant for dll file extension. */ - private static final String EXT_DLL = "dll"; - - /** Constant for dylib file extension. */ - private static final String EXT_DYLIB = "dylib"; - /** The temporary directory for native libraries. */ private static File tmp; @@ -77,7 +38,7 @@ private Loader() /** * Returns the operating system name. This could be "linux", "windows" or - * "osx" or (for any other non-supported platform) the value of the + * "macos" or (for any other non-supported platform) the value of the * "os.name" property converted to lower case and with removed space * characters. * @@ -87,13 +48,13 @@ private static String getOS() { final String os = System.getProperty("os.name").toLowerCase() .replace(" ", ""); - if (os.contains(OS_WINDOWS)) + if (os.contains("windows")) { - return OS_WINDOWS; + return "win32"; } - if (os.equals(OS_MACOSX)) + if (os.equals("macosx") || os.equals("macos")) { - return OS_OSX; + return "darwin"; } return os; } @@ -110,13 +71,21 @@ private static String getArch() { final String arch = System.getProperty("os.arch").toLowerCase() .replace(" ", ""); - if (arch.equals(ARCH_I386)) + if (arch.equals("i386")) { - return ARCH_X86; + return "x86"; } - if (arch.equals(ARCH_AMD64)) + if (arch.equals("amd64") || arch.equals("x86_64")) { - return ARCH_X86_64; + return "x86-64"; + } + if (arch.equals("arm64")) + { + return "aarch64"; + } + if (arch.equals("armhf") || arch.equals("aarch32") || arch.equals("armv7l")) + { + return "arm"; } return arch; } @@ -135,21 +104,21 @@ private static String getExt() { return ext; } - if (os.equals(OS_LINUX) || os.equals(OS_FREEBSD) || os.equals(OS_SUNOS)) + if (os.equals("linux") || os.equals("freebsd") || os.equals("sunos")) { - return EXT_SO; + return "so"; } - if (os.equals(OS_WINDOWS)) + if (os.equals("win32")) { - return EXT_DLL; + return "dll"; } - if (os.equals(OS_OSX)) + if (os.equals("darwin")) { - return EXT_DYLIB; + return "dylib"; } throw new LoaderException("Unable to determine the shared library " + "file extension for operating system '" + os - + "'. Please specify Java parameter -D" + key + + "'. Please specify Java parameter -D" + key + "="); } @@ -214,17 +183,13 @@ private static String getLibName() /** * Returns the name of the libusb native library. This could be * "libusb0.dll" for example or null if this library is not needed on the - * current platform (Because it is provided by the operating system). + * current platform (Because it is provided by the operating system or + * statically linked into the libusb4java library). * * @return The libusb native library name or null if not needed. */ private static String getExtraLibName() { - final String os = getOS(); - if (os.equals(OS_WINDOWS)) - { - return "libusb-1.0." + EXT_DLL; - } return null; } @@ -266,7 +231,7 @@ private static void copy(final InputStream input, final File output) * The library name to extract (For example "libusb0.dll") * @return The absolute path to the extracted library. */ - private static String extractLibrary(final String platform, + private static String extractLibrary(final String platform, final String lib) { // Extract the usb4java library @@ -335,6 +300,11 @@ private static String extractLibrary(final String platform, * times. Duplicate calls are ignored. This method is automatically called * when the {@link LibUsb} class is loaded. When you need to do it earlier * (To catch exceptions for example) then simply call this method manually. + *

+ * If the system property org.usb4java.LibraryName is defined, then + * instead of going through the classpath looking for the appropriate DLL, + * extracting it, etc., we simply call {@link System#loadLibrary}, passing + * in the value of the property. * * @throws LoaderException * When loading the native wrapper libraries failed. @@ -346,15 +316,23 @@ public static synchronized void load() { return; } - + loaded = true; - final String platform = getPlatform(); - final String lib = getLibName(); - final String extraLib = getExtraLibName(); - if (extraLib != null) + final String libraryName = System.getProperty("org.usb4java.LibraryName"); + if (libraryName != null) + { + System.loadLibrary(libraryName); + } + else { - System.load(extractLibrary(platform, extraLib)); + final String platform = getPlatform(); + final String lib = getLibName(); + final String extraLib = getExtraLibName(); + if (extraLib != null) + { + System.load(extractLibrary(platform, extraLib)); + } + System.load(extractLibrary(platform, lib)); } - System.load(extractLibrary(platform, lib)); } } diff --git a/src/main/java/org/usb4java/Pollfd.java b/src/main/java/org/usb4java/Pollfd.java new file mode 100644 index 0000000..38dd6e1 --- /dev/null +++ b/src/main/java/org/usb4java/Pollfd.java @@ -0,0 +1,111 @@ +/* + * Copyright 2018 Klaus Reimer + * See LICENSE.md for licensing information. + * + * Based on libusb : + * + * Copyright 2001 Johannes Erdfelt + * Copyright 2007-2009 Daniel Drake + * Copyright 2010-2012 Peter Stuge + * Copyright 2008-2013 Nathan Hjelm + * Copyright 2009-2013 Pete Batard + * Copyright 2009-2013 Ludovic Rousseau + * Copyright 2010-2012 Michael Plante + * Copyright 2011-2013 Hans de Goede + * Copyright 2012-2013 Martin Pieuchot + * Copyright 2012-2013 Toby Gray + */ + +package org.usb4java; + +/** + * File descriptor for polling. + * + * @author Klaus Reimer (k@ailis.de) + */ +public final class Pollfd +{ + /** There is data to read */ + public static final int POLLIN = 1; + + /** Writing now will not block. */ + public static final int POLLOUT = 4; + + /** The native pointer to the pollfd structure. */ + private long pollfdPointer; + + /** + * Package-private constructor to prevent manual instantiation. Structures are + * always created by JNI. + */ + Pollfd() + { + // Empty + } + + /** + * Returns the native pointer to the pollfd structure. + * + * @return The native pointer to the pollfd structure. + */ + public long getPointer() + { + return this.pollfdPointer; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = (prime * result) + + (int) (this.pollfdPointer ^ (this.pollfdPointer >>> 32)); + return result; + } + + @Override + public boolean equals(final Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (this.getClass() != obj.getClass()) + { + return false; + } + final Pollfd other = (Pollfd) obj; + if (this.pollfdPointer != other.pollfdPointer) + { + return false; + } + return true; + } + + @Override + public String toString() + { + return String.format("libusb pollfd 0x%x", this.pollfdPointer); + } + + /** + * Returns the numeric file descriptor. + * + * @return The numeric file descriptor. + */ + public native byte fd(); + + /** + * Returns the event flags to poll. + * + * {@link #POLLIN} indicates that you should monitor this file descriptor for becoming ready to read from, and + * {@link #POLLOUT} indicates that you should monitor this file descriptor for non-blocking write readiness. + * + * @return The event flags to poll. + */ + public native short events(); +} diff --git a/src/main/java/org/usb4java/Pollfds.java b/src/main/java/org/usb4java/Pollfds.java new file mode 100644 index 0000000..bb1906d --- /dev/null +++ b/src/main/java/org/usb4java/Pollfds.java @@ -0,0 +1,102 @@ +/* + * Copyright 2018 Klaus Reimer + * See LICENSE.md for licensing information. + */ + +package org.usb4java; + +import java.util.Iterator; + +/** + * List of poll file descriptors as returned by {@link LibUsb#getPollfds(Context)}. + * + * @author Klaus Reimer (k@ailis.de) + */ +public final class Pollfds implements Iterable +{ + /** The native pointer to the pollfd array. */ + private long pollfdsPointer; + + /** The number of file descriptors in the list. */ + private int size; + + /** + * Package-private constructor to prevent manual instantiation. Structures are + * always created by JNI. + */ + Pollfds() + { + // Empty + } + + /** + * Returns the native pointer. + * + * @return The native pointer. + */ + public long getPointer() + { + return this.pollfdsPointer; + } + + /** + * Returns the number of poll file descriptors in the list. + * + * @return The number of poll file descriptors in the list. + */ + public int getSize() + { + return this.size; + } + + /** + * Returns the poll file descriptor with the specified index. + * + * @param index + * The index. + * @return The poll file descriptor or null when index is out of bounds. + */ + public native Pollfd get(final int index); + + @Override + public Iterator iterator() + { + return new PollfdsIterator(this); + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = (prime * result) + + (int) (this.pollfdsPointer ^ (this.pollfdsPointer >>> 32)); + return result; + } + + @Override + public boolean equals(final Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (this.getClass() != obj.getClass()) + { + return false; + } + final Pollfds other = (Pollfds) obj; + return this.pollfdsPointer == other.pollfdsPointer; + } + + @Override + public String toString() + { + return String.format("libusb pollfd list 0x%x with size %d", + this.pollfdsPointer, this.size); + } +} diff --git a/src/main/java/org/usb4java/PollfdsIterator.java b/src/main/java/org/usb4java/PollfdsIterator.java new file mode 100644 index 0000000..41a7755 --- /dev/null +++ b/src/main/java/org/usb4java/PollfdsIterator.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2018 Klaus Reimer + * See LICENSE.md for licensing information. + */ + +package org.usb4java; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * Iterator for {@link Pollfds}. + * + * @author Klaus Reimer (k@ailis.de) + */ +final class PollfdsIterator implements Iterator +{ + /** The file descriptor list. */ + private final Pollfds pollfds; + + /** The current index. */ + private int nextIndex; + + /** + * Constructor. + * + * @param pollfds + * The file descriptor list list. + */ + PollfdsIterator(final Pollfds pollfds) + { + this.pollfds = pollfds; + } + + @Override + public boolean hasNext() + { + return this.nextIndex < this.pollfds.getSize(); + } + + @Override + public Pollfd next() + { + if (!hasNext()) throw new NoSuchElementException(); + return this.pollfds.get(this.nextIndex++); + } + + @Override + public void remove() + { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/org/usb4java/SsEndpointCompanionDescriptor.java b/src/main/java/org/usb4java/SsEndpointCompanionDescriptor.java index 9a63d3a..2093463 100644 --- a/src/main/java/org/usb4java/SsEndpointCompanionDescriptor.java +++ b/src/main/java/org/usb4java/SsEndpointCompanionDescriptor.java @@ -36,7 +36,7 @@ public final class SsEndpointCompanionDescriptor /** * Constructs a new descriptor which can be passed to the - * {@link LibUsb#getSsEndpointCompanionDescriptor(Context, + * {@link LibUsb#getSsEndpointCompanionDescriptor(Context, * EndpointDescriptor, SsEndpointCompanionDescriptor)} * method. */ @@ -144,7 +144,7 @@ public boolean equals(final Object obj) return false; } - final SsEndpointCompanionDescriptor other = + final SsEndpointCompanionDescriptor other = (SsEndpointCompanionDescriptor) obj; return new EqualsBuilder() diff --git a/src/main/java/org/usb4java/Transfer.java b/src/main/java/org/usb4java/Transfer.java index 50fc126..828975b 100644 --- a/src/main/java/org/usb4java/Transfer.java +++ b/src/main/java/org/usb4java/Transfer.java @@ -191,7 +191,7 @@ public void setLength(final int length) /** * Native method called internally to set the length of the data buffer. - * + * * @param length * The length to set. */ @@ -277,7 +277,7 @@ public void setBuffer(final ByteBuffer buffer) /** * Native method called internally to set the data buffer. - * + * * @param buffer * The data buffer to set. */ @@ -306,6 +306,24 @@ public void setBuffer(final ByteBuffer buffer) */ public native IsoPacketDescriptor[] isoPacketDesc(); + /** + * Get a transfer's bulk stream id. + * + * @return The stream id for the transfer. + */ + public native int streamId(); + + /** + * Set a transfer's bulk stream id. + * + * Note: users are advised to use LibUsb.fillBulkStreamTransfer() instead + * of calling this function directly. + * + * @param streamId + * The stream id to set. + */ + public native void setStreamId(final int streamId); + @Override public int hashCode() { diff --git a/src/site/apt/configuration.apt.vm b/src/site/apt/configuration.apt.vm index 7e2e317..7d6ef54 100644 --- a/src/site/apt/configuration.apt.vm +++ b/src/site/apt/configuration.apt.vm @@ -1,7 +1,7 @@ ----------------------------------------------------------------------------- Configuration ----------------------------------------------------------------------------- - + Configuration The configuration options explained here are only valid for the javax-usb @@ -11,25 +11,25 @@ Configuration * Selecting usb4java as javax-usb implementation - To tell the USB Host Manager of to use the + To tell the USB Host Manager of to use the implementation you have to put the following property into the file which must be located in the root of your classpath: - + +----+ javax.usb.services = org.usb4java.javax.Services -+----+ ++----+ can be configured by adding more properties to this file as described in the following sections. - + * Communication timeout The default USB communication timeout of is 2500 milliseconds. To change this to 250 milliseconds for example add this to the properties - file: - + file: + +----+ org.usb4java.javax.timeout = 250 +----+ @@ -47,9 +47,20 @@ org.usb4java.javax.scanInterval = 1000 When you set this interval to 0 then only scans once during application startup. If you want to trigger a manual device you can do it by calling the scan method on the USB services class (Must be casted - to the implementation, because this is not a javax.usb feature: + to the implementation, because this is not a javax-usb feature: +----+ ((org.usb4java.javax.Services) UsbHostManager.getUsbServices()).scan(); +----+ - \ No newline at end of file + + +* Use USBDK + + If you want to use {{{https://github.com/daynix/UsbDk}USBDK}} on Windows + then you have to enable the feature with the following entry: + ++----+ +org.usb4java.javax.useUSBDK = true ++----+ + + This setting is ignored on other platforms. diff --git a/src/site/apt/faq.apt.vm b/src/site/apt/faq.apt.vm index 1517e7b..620d3d7 100644 --- a/src/site/apt/faq.apt.vm +++ b/src/site/apt/faq.apt.vm @@ -1,15 +1,15 @@ ----------------------------------------------------------------------------- FAQ ----------------------------------------------------------------------------- - + Frequently asked questions If you have a question which is not answered here please ask the {{{mailto:usb4java@googlegroups.com}usb4java mailing list}} ({{{http://groups.google.com/group/usb4java}Google group}}). - You can subscribe to it via email by sending a mail to + You can subscribe to it via email by sending a mail to {{{mailto:usb4java+subscribe@googlegroups.com}usb4java+subscribe@googlegroups.com}}. - + * I can't open my USB device on Linux. Why? On Linux you need write permissions on the device file of the USB device @@ -17,52 +17,51 @@ Frequently asked questions running your program as root. If this works then it is recommended to configure to give your user write permissions when the device is attached. You can do this by creating a file like - with content like this: + with content like this: ---- - SUBSYSTEM=="usb",ATTR{idVendor}=="89ab",ATTR{idProduct}=="4567",MODE="0660",GROUP="wheel" + SUBSYSTEM=="usb",ATTR{idVendor}=="89ab",ATTR{idProduct}=="4567",MODE="0660",GROUP="plugdev" ---- This means that whenever a USB device with vendor id <0x89ab> and product id - <0x4567> is attached then the group is permitted to + <0x4567> is attached then the group is permitted to write to the device. So make sure your user is in that group (or use a different group). - + If your device uses a shared vendor/product id then you might want to filter for the manufacturer and product name. This can be done by checking - the ATTR properties and . - + the ATTR properties and . + To activate this new configuration you may need to re-attach the USB device or run the command <<>>. * I can't open my USB device on Windows. Why? On Windows you need to create a driver for your USB device. Read the - {{{https://github.com/libusb/libusb/wiki/Windows#wiki-How_to_use_libusb_on_Windows}How to use libusb on Windows}} + {{{https://github.com/libusb/libusb/wiki/Windows#wiki-How_to_use_libusb_on_Windows}How to use libusb on Windows}} article from the {{{http://libusb.info}libusb project}} for more information. * My program crashes. What can I do? - If the program crashes with a Java stack trace then it is most likely a - problem in your own program. If you can't find it you may find some help on - the {{{./mail-lists.html}mailinglist}}. - + If the program crashes with a Java stack trace then it is most likely a + problem in your own program. If you can't find it you may find some help on + the {{{./mail-lists.html}mailinglist}}. + If the JVM crashes the hard way because of a segfault in the native code then - it is more likely a problem of usb4java or libusb and you should file a + it is more likely a problem of usb4java or libusb and you should file a {{{./issue-tracking.html}bugreport}} with as much information as possible (Full stack trace, full crash log, example code how to reproduce the crash). - + If usb4java crashes on Windows then please first of all make sure you have created a proper device driver as explained in the previous FAQ entry. Also consider creating a new up-to-date device driver with the latest Zadig tool. - + If you have experience in C programming then it would be very helpful when you could try to reproduce the problem in C by directly using libusb. If - this works but the same USB communication doesn't work with usb4java then it - would be nice if you could give us your C source and Java source so we can + this works but the same USB communication doesn't work with usb4java then it + would be nice if you could give us your C source and Java source so we can track down the difference which causes the crash. If the C program also crashes then your problem is located in libusb and not in usb4java and you - should consult the libusb mailinglist or bug tracker instead. Never report a - problem in the libusb bug tracker or the libusb mailing list if you - can't reproduce the problem with a native C program! - \ No newline at end of file + should consult the libusb mailinglist or bug tracker instead. Never report a + problem in the libusb bug tracker or the libusb mailing list if you + can't reproduce the problem with a native C program! diff --git a/src/site/apt/nativelibs.apt.vm b/src/site/apt/nativelibs.apt.vm index d8399b3..862aa7c 100644 --- a/src/site/apt/nativelibs.apt.vm +++ b/src/site/apt/nativelibs.apt.vm @@ -1,41 +1,41 @@ ----------------------------------------------------------------------------- Native libraries ----------------------------------------------------------------------------- - + Library loading The native libraries for all supported platforms are provided as JAR files which you can simply reference in your classpath. usb4java automatically determines on startup which libraries are needed for the current platform - and extracts them to a temporary directory and loads them from there. - This makes it easy to use usb4java because you just need to put the JARs + and extracts them to a temporary directory and loads them from there. + This makes it easy to use usb4java because you just need to put the JARs into your classpath. No need to fiddle around with or environment variables like or . - + usb4java only extracts the files into a temporary directory when they are inside a JAR file. So if you prefer direct loading without extracting to a temporary directory then you may want to distribute the files in extracted form. Just make sure your classpath includes the directory where you have extracted the JARs. Here is an example application layout for this scenario: - + +-----------------------------------------------------------------------------+ natives/ org/usb4java/ - linux-x86/libusb4java.so - windows-x86/libusb4java.dll - osx-x86/libusb4java.dylib + linux-x86-64/libusb4java.so + win32-x86-64/libusb4java.dll + darwin-x86-64/libusb4java.dylib lib/ usb4java.jar commons-lang3.jar myapp.jar myapp.sh -+-----------------------------------------------------------------------------+ ++-----------------------------------------------------------------------------+ To make this work just make sure to put the folder into your - classpath. + classpath. + - Unsupported platforms When you use usb4java on a platform which is not directly supported by @@ -46,7 +46,7 @@ Native library not found in classpath: /org/usb4java/freebsd-x86/libusb4java.so +----+ +----+ -Unable to determine the shared library file extension for operating system +Unable to determine the shared library file extension for operating system 'strangeos'. Please specify Java parameter -Dusb4java.libext.strangeos= +----+ @@ -54,12 +54,12 @@ Unable to determine the shared library file extension for operating system is completely unknown to the usb4java authors and usb4java does not know the file extension of shared libraries on this platform. You can fix this by specifying a Java parameter like this (As explained in the exception): - + +----+ -Dusb4java.libext.strangeos=so +----+ - After this you will most likely get the other exception, which means that + After this you will most likely get the other exception, which means that there is no native JNI wrapper present for this platform. Your only chance here is to compile this wrapper yourself. I can't predict how this works on really strange platforms but chances are high that your platform is @@ -68,48 +68,53 @@ Unable to determine the shared library file extension for operating system 1. Install a Java JDK ({{{http://openjdk.java.net/}OpenJDK}} for example). Make sure the environment variable is pointing to the directory where you have installed the JDK. - + 2. Install the {{{http://libusb.info/}libusb}} development files. - + 3. Install {{{http://git-scm.com/}Git}}. - + 4. Clone the {{{https://github.com/usb4java/libusb4java/}libusb4java source code repository}} with Git: - + +---- $ git clone git://github.com/usb4java/libusb4java.git +---- 5. Enter the cloned libusb4java directory: - + +---- $ cd libusb4java +---- - 6. Compile the native library: - + 6. Create a build output directory and enter it: + ++--- +$ mkdir build +$ cd build ++--- + + 7. Compile the native library: + ++---- +$ cmake .. -DCMAKE_INSTALL_PREFIX="" +$ make install/strip DESTDIR=/tmp +---- -$ ./autogen.sh -$ ./configure --prefix=/ -$ make install-strip DESTDIR=/tmp -+---- - 8. When compilation was successful then the native library can be found in + 8. When compilation was successful then the native library can be found in the directory . The file name depends on your operating system. Make sure you rename it to (Or whatever file extension - your platform uses) and copy this file into the directory + your platform uses) and copy this file into the directory in your classpath where is the name of your operating system and is your CPU architecture (Both must match the names mentioned in the exception thrown by usb4java.) - - If you can't use the GNU compiler or the autotools then you are on your own. + + If you can't use the GNU compiler or cmake then you are on your own. If you have some experience with compiling JNI libraries then I guess this won't be hard for you. There are only a couple of source files in the sub folder. You could write a new simple Makefile or whatever is needed on your platform. - If you have problems then please consult the + If you have problems then please consult the {{{mailto:usb4java@googlegroups.com}usb4java mailing list}} ({{{http://groups.google.com/group/usb4java}Google group}}). You can subscribe to it via email by sending a mail to {{{mailto:usb4java+subscribe@googlegroups.com}usb4java+subscribe@googlegroups.com}}. - \ No newline at end of file diff --git a/src/site/apt/quickstart/index.apt b/src/site/apt/quickstart/index.apt index f6a36cc..302293a 100644 --- a/src/site/apt/quickstart/index.apt +++ b/src/site/apt/quickstart/index.apt @@ -7,14 +7,14 @@ Quick start * Choose an API usb4java provides two different APIs you can choose from: - + * {{{./libusb.html}The low-level (libusb) API}} - + * {{{./javax-usb.html}The high-level (javax-usb) API}} - + [] - - The low-level API closely follows the C API of the + + The low-level API closely follows the C API of the {{{http://libusb.info/}libusb}} project. This API has the advantage that it provides the same functionality as libusb does. And if you know the C API of libusb then you will most likely feel right at home when using this API @@ -22,16 +22,13 @@ Quick start Java. The disadvantage is that you will have a hard time changing your code when you later switch to a different Java USB library. And as a pure Java developer you may dislike the API because it is too low-level (For - example most methods return error codes instead of throwing exceptions). + example most methods return error codes instead of throwing exceptions). - The high-level API simply implements the + The high-level API simply implements the {{{http://javax-usb.sourceforge.net/}javax-usb (JSR80) API}}. One advantage of this API is that it is implementation-independent. So it is easy to switch to a different javax-usb implementation later without changing your code. Another advantage is that this API is object oriented and is much - easier to use for Java developers. The disadvantage is that the javax-usb - specification is pretty old and may lack support for some newer USB - techniques provided by the low-level API. - - - \ No newline at end of file + easier to use for Java developers. The disadvantage is that the javax-usb + specification is very old (maybe even abandoned) and may lack support for + some newer USB techniques provided by the low-level API. diff --git a/src/site/site.xml b/src/site/site.xml index 532dfd7..85b2e71 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -12,16 +12,16 @@ org.apache.maven.skins maven-fluido-skin - 1.3.0 + 1.7 - + ]]> - + diff --git a/src/site/xdoc/index.xml.vm b/src/site/xdoc/index.xml.vm index 2e77a26..a212c30 100644 --- a/src/site/xdoc/index.xml.vm +++ b/src/site/xdoc/index.xml.vm @@ -14,45 +14,31 @@ through the usb4java-javax extension.

- Supported platforms are Linux (x86 32/64 bit, ARM 32 bit), - OS X (x86 32/64 bit) and + Supported platforms are Linux (x86 32/64 bit, ARM 32/64 bit), + OS X (x86 64 bit) and Windows (x86 32/64 bit). But other platforms may work - as well (as long as they have at least Java 6 and are supported by + as well (as long as they have at least Java 6 and are supported by libusb) by compiling the JNI library manually.

- +
+
+ +

- When you are using Maven then you can add the necessary dependencies + When you are using Maven then you can add the necessary dependencies like this:

-
<repositories>
-  <repository>
-    <id>ailis</id>
-    <name>Ailis Maven Releases</name>
-    <url>http://nexus.ailis.de/content/groups/public/</url>
-  </repository>
-</repositories>
-
-<-- For using just usb4java without javax-usb -->
+      
<-- For using just usb4java without javax-usb -->
 <dependencies>
   <dependency>
     <groupId>${project.groupId}</groupId>
@@ -66,50 +52,63 @@
   <dependency>
     <groupId>${project.groupId}</groupId>
     <artifactId>${project.artifactId}-javax</artifactId>
-    <version>${usb4javaJavaxVersion}</version>
+    <version>${project.version}</version>
   </dependency>
 </dependencies>
- +

- This library is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. + Copyright (C) 2011 Klaus Reimer, k@ailis.de
+ Copyright (C) 2013 Luca Longinotti, l@longi.li +

+ +

+ Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: +

+

+ The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software.

- This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more - details. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE.

- +

- Read the quick start guide and the + Read the quick start guide and the FAQ. There are also some low-level (libusb) examples - and + and high-level (javax-usb) examples available.

- +

- For questions and discussions please use the - usb4java mailing list + For questions and discussions please use the + usb4java mailing list (Google group). - You can subscribe to it via email by sending a mail to + You can subscribe to it via email by sending a mail to usb4java+subscribe@googlegroups.com.

-

+

If you have found a bug in the software or this web site (even if it's just a typo) then please create - an issue on GitHub. + an issue on GitHub.

diff --git a/src/test/java/org/usb4java/DeviceListIteratorTest.java b/src/test/java/org/usb4java/DeviceListIteratorTest.java index a78f057..212735a 100644 --- a/src/test/java/org/usb4java/DeviceListIteratorTest.java +++ b/src/test/java/org/usb4java/DeviceListIteratorTest.java @@ -24,7 +24,7 @@ public class DeviceListIteratorTest { /** The test subject. */ private DeviceListIterator iterator; - + /** * Setup test. */ @@ -51,11 +51,11 @@ public void tearDown() LibUsb.exit(null); } } - + /** * Tests the {@link DeviceListIterator#hasNext()} method. It just checks * that this call doesn't crash because we can't assume that a device is - * connected at all. + * connected at all. */ @Test public void testHasNext() @@ -63,7 +63,7 @@ public void testHasNext() assumeUsbTestsEnabled(); this.iterator.hasNext(); } - + /** * Tests the {@link DeviceListIterator#next()} method. */ @@ -74,21 +74,23 @@ public void testNext() while (this.iterator.hasNext()) { assertNotNull(this.iterator.next()); - } + } } - + /** * Ensures that {@link DeviceListIterator#next()} method throws * a {@link NoSuchElementException} when accessing elements after the end */ @Test(expected = NoSuchElementException.class) - public void testNextAfterend() + public void testNextAfterEnd() { assumeUsbTestsEnabled(); - while (this.iterator.hasNext()) this.iterator.next(); + while (this.iterator.hasNext()) { + this.iterator.next(); + } this.iterator.next(); } - + /** * Ensures that {@link DeviceListIterator#remove()} throws an exception * because the list is read-only. @@ -96,6 +98,7 @@ public void testNextAfterend() @Test(expected = UnsupportedOperationException.class) public void testRemove() { + assumeUsbTestsEnabled(); this.iterator.remove(); } } diff --git a/src/test/java/org/usb4java/DeviceListTest.java b/src/test/java/org/usb4java/DeviceListTest.java index 090abdc..5a0bd1b 100644 --- a/src/test/java/org/usb4java/DeviceListTest.java +++ b/src/test/java/org/usb4java/DeviceListTest.java @@ -76,7 +76,7 @@ public void testEquals() LibUsb.freeDeviceList(b, true); } } - + /** * Tests the {@link DeviceList#hashCode()} method. */ @@ -95,7 +95,7 @@ public void testHashCode() LibUsb.freeDeviceList(list, true); } } - + /** * Tests the {@link DeviceList#toString()} method */ @@ -115,7 +115,7 @@ public void testToString() LibUsb.freeDeviceList(list, true); } } - + /** * Tests the {@link DeviceList#getPointer()} method */ diff --git a/src/test/java/org/usb4java/LibUsbDeviceTest.java b/src/test/java/org/usb4java/LibUsbDeviceTest.java index 85356bb..6253ee5 100644 --- a/src/test/java/org/usb4java/LibUsbDeviceTest.java +++ b/src/test/java/org/usb4java/LibUsbDeviceTest.java @@ -9,8 +9,11 @@ import static org.usb4java.test.UsbAssume.isUsbTestsEnabled; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.junit.Assume.assumeFalse; import static org.junit.Assume.assumeNotNull; import java.nio.ByteBuffer; @@ -38,7 +41,7 @@ */ public class LibUsbDeviceTest { - /** The libusb contxet. */ + /** The libusb context. */ private Context context; /** The device to run the tests on. */ @@ -120,7 +123,7 @@ private Device findTestDevice() { final InterfaceDescriptor ifaceDescriptor = iface .altsetting()[k]; - if (ifaceDescriptor.bNumEndpoints() > 1) + if (ifaceDescriptor.bNumEndpoints() > 0) { this.endpoint = ifaceDescriptor.endpoint()[0] .bEndpointAddress(); @@ -193,7 +196,7 @@ public void testGetPortNumbers() assumeNotNull(this.device); final ByteBuffer path = BufferUtils.allocateByteBuffer(8); final int result = LibUsb.getPortNumbers(this.device, path); - assertTrue(result > 0); + assertTrue(result >= 0); assertTrue(result <= path.capacity()); } @@ -208,7 +211,7 @@ public void testGetPortNumbersWithTooSmallBuffer() assumeNotNull(this.device); final ByteBuffer path = BufferUtils.allocateByteBuffer(0); final int result = LibUsb.getPortNumbers(this.device, path); - assertEquals(LibUsb.ERROR_OVERFLOW, result); + assertEquals(LibUsb.ERROR_INVALID_PARAM, result); } /** @@ -436,7 +439,7 @@ public void testUnrefDeviceWithoutDevice() * Tests the {@link LibUsb#open(Device, DeviceHandle)} method. This can't be * really tested in a simple unit test like this. Most likely the user has * no access to the device. So this test succeeds on SUCCESS and on - * ERROR_ACCESS. At least we have to make sure then open() method doesn't + * ERROR_ACCESS. At least we have to make sure that the open() method doesn't * crash. */ @Test @@ -785,7 +788,7 @@ private void validateInterfaceDescriptor(final InterfaceDescriptor desc) } /** - * Validates the specified endpoint desriptor. + * Validates the specified endpoint descriptor. * * @param desc * The endpoint descriptor to validate. @@ -1212,4 +1215,114 @@ public void testGetAndFreeDeviceListWithDefaultContext() LibUsb.exit(null); } } + + /** + * Tests the {@link LibUsb#getPollfds()} and {@link LibUsb#freePollfds()} methods. + */ + @Test + public void testGetAndFreePollfds() + { + assumeUsbTestsEnabled(); + + final Pollfds pollfds = LibUsb.getPollfds(this.context); + try { + if (System.getProperty("os.name").toLowerCase().contains("windows")) { + assertNull(pollfds); + } else { + assertNotNull(pollfds); + assertTrue("Size must be >= 0", pollfds.getSize() >= 0); + int i = 0; + for (Pollfd pollfd : pollfds) { + assertEquals(pollfds.get(i), pollfd); + assertTrue("File descriptor must be > 0", pollfd.fd() > 0); + assertTrue("Events must be > 0", pollfd.events() > 0); + i++; + } + } + } finally { + LibUsb.freePollfds(pollfds); + } + } + + /** + * Tests the {@link LibUsb#getPollfds()} and {@link LibUsb#freePollfds()} methods with the default context. + */ + @Test + public void testGetAndFreePollfdsWithDefaultContext() + { + assumeUsbTestsEnabled(); + + assertEquals(0, LibUsb.init(null)); + try + { + final Pollfds pollfds = LibUsb.getPollfds(null); + try { + if (System.getProperty("os.name").toLowerCase().contains("windows")) { + assertNull(pollfds); + } else { + assertNotNull(pollfds); + assertTrue("Size must be >= 0", pollfds.getSize() >= 0); + int i = 0; + for (Pollfd pollfd : pollfds) { + assertEquals(pollfds.get(i), pollfd); + assertTrue("File descriptor must be > 0", pollfd.fd() > 0); + assertTrue("Events must be > 0", pollfd.events() > 0); + i++; + } + } + } finally { + LibUsb.freePollfds(pollfds); + } + } + finally + { + LibUsb.exit(null); + } + } + + /** + * Ensures that {@link LibUsb#freePollfds()} doesn't throw an error when called with null argument. + */ + @Test + public void testFreePollfdsWithNullArgument() + { + LibUsb.freePollfds(null); + } + + /** + * Ensures that {@link LibUsb#freePollfds()} doesn't crash when called twice and throws an IllegalStateException + * instead. + */ + @Test(expected = IllegalStateException.class) + public void testDoubleFreePollfds() + { + assumeFalse(System.getProperty("os.name").toLowerCase().contains("windows")); + assumeUsbTestsEnabled(); + final Pollfds pollfds = LibUsb.getPollfds(this.context); + LibUsb.freePollfds(pollfds); + LibUsb.freePollfds(pollfds); + } + + /** + * Ensures that accessing Pollfds properties after calling {@link LibUsb#freePollfds()} doesn't crash and + * throws an IllegalStateException instead. + */ + @Test(expected = IllegalStateException.class) + public void testPollfdsAccessAfterFree() + { + assumeFalse(System.getProperty("os.name").toLowerCase().contains("windows")); + assumeUsbTestsEnabled(); + assertEquals(0, LibUsb.init(null)); + try + { + final Pollfds pollfds = LibUsb.getPollfds(null); + assertNotNull(pollfds); + LibUsb.freePollfds(pollfds); + assertNotNull(pollfds.get(0)); + } + finally + { + LibUsb.exit(null); + } + } } diff --git a/src/test/java/org/usb4java/LibUsbGlobalTest.java b/src/test/java/org/usb4java/LibUsbGlobalTest.java index 84c8ecd..10c74fd 100644 --- a/src/test/java/org/usb4java/LibUsbGlobalTest.java +++ b/src/test/java/org/usb4java/LibUsbGlobalTest.java @@ -27,7 +27,7 @@ */ public class LibUsbGlobalTest { - /** The libusb contxet. */ + /** The libusb context. */ private Context context; /** @@ -63,6 +63,7 @@ public void tearDown() * Tests the {@link LibUsb#setDebug(Context, int)} method. */ @Test + @Deprecated public void testSetDebug() { assumeUsbTestsEnabled(); diff --git a/src/test/java/org/usb4java/LibUsbHotplugTest.java b/src/test/java/org/usb4java/LibUsbHotplugTest.java index 1eaadfc..dafa218 100644 --- a/src/test/java/org/usb4java/LibUsbHotplugTest.java +++ b/src/test/java/org/usb4java/LibUsbHotplugTest.java @@ -18,12 +18,12 @@ /** * Tests the hotplug part of the {@link LibUsb} class. - * + * * @author Klaus Reimer (k@ailis.de) */ public class LibUsbHotplugTest { - /** The libusb contxet. */ + /** The libusb context. */ private Context context; /** @@ -95,7 +95,7 @@ public int processEvent(Context context, Device device, } /** - * Ensures that no hotplug event is fired when enumeration is deactived. + * Ensures that no hotplug event is fired when enumeration is deactivated. * When no devices are connected then this test is pretty much useless but * won't fail because of that. */ diff --git a/src/test/java/org/usb4java/LibUsbTest.java b/src/test/java/org/usb4java/LibUsbTest.java index 34cd154..a798a33 100644 --- a/src/test/java/org/usb4java/LibUsbTest.java +++ b/src/test/java/org/usb4java/LibUsbTest.java @@ -192,6 +192,54 @@ public void testGetApiVersion() assertTrue(LibUsb.getApiVersion() >= 0x1000102); } + /** + * Tests the {@link LibUsb#setOption(Context, int, int)} method with valid options and values. + */ + @Test + public void testSetOption() + { + assumeUsbTestsEnabled(); + final Context context = new Context(); + assertEquals(LibUsb.SUCCESS, LibUsb.init(context)); + try + { + if (System.getProperty("os.name").toLowerCase().contains("windows")) { + // On Windows this is either a success when USBDK is found or ERROR_NOT_FOUND when not + final int result = LibUsb.setOption(context, LibUsb.OPTION_USE_USBDK); + assertTrue(result == LibUsb.SUCCESS || result == LibUsb.ERROR_NOT_FOUND); + } else { + // On other operating systems it is always ERROR_NOT_SUPPORTED + assertEquals(LibUsb.ERROR_NOT_SUPPORTED, LibUsb.setOption(context, LibUsb.OPTION_USE_USBDK)); + } + assertEquals(LibUsb.SUCCESS, LibUsb.setOption(context, LibUsb.OPTION_LOG_LEVEL, LibUsb.LOG_LEVEL_NONE)); + assertEquals(LibUsb.SUCCESS, LibUsb.setOption(context, LibUsb.OPTION_LOG_LEVEL, LibUsb.LOG_LEVEL_DEBUG)); + } + finally + { + LibUsb.exit(context); + } + } + + /** + * Tests the {@link LibUsb#setOption(Context, int, int)} method with invalid options and values. + */ + @Test + public void testSetOptionWithInvalidParameters() + { + assumeUsbTestsEnabled(); + final Context context = new Context(); + assertEquals(LibUsb.SUCCESS, LibUsb.init(context)); + try + { + assertEquals(LibUsb.ERROR_INVALID_PARAM, LibUsb.setOption(context, LibUsb.OPTION_LOG_LEVEL, 234)); + assertEquals(LibUsb.ERROR_INVALID_PARAM, LibUsb.setOption(context, 123)); + } + finally + { + LibUsb.exit(context); + } + } + /** * Tests the initialization and deinitialization of libusb with default * context. @@ -254,6 +302,7 @@ public void testExitWithUninitializedContext() * context */ @Test(expected = IllegalStateException.class) + @Deprecated public void testSetDebugWithUninitializedContext() { assumeUsbTestsEnabled(); @@ -262,8 +311,60 @@ public void testSetDebugWithUninitializedContext() } /** - * Tests {@link LibUsb#getDeviceList(Context, DeviceList)} method with - * uninitialized USB context. + * Tests {@link LibUsb#setOption(Context, int, int)} method with uninitialized USB context. + */ + @Test(expected = IllegalStateException.class) + @Deprecated + public void testSetOptionWithUninitializedContext() + { + assumeUsbTestsEnabled(); + final Context context = new Context(); + LibUsb.setOption(context, 0); + } + + /** + * Tests {@link LibUsb#getDeviceList(Context, DeviceList)} method. + */ + @Test + public void testGetDeviceList() + { + assumeUsbTestsEnabled(); + final Context context = new Context(); + final DeviceList deviceList = new DeviceList(); + LibUsb.init(context); + try + { + assertTrue(LibUsb.getDeviceList(context, deviceList) >= 0); + LibUsb.freeDeviceList(deviceList, true); + } + finally + { + LibUsb.exit(context); + } + } + + /** + * Tests {@link LibUsb#getDeviceList(Context, DeviceList)} method with the default context. + */ + @Test + public void testGetDeviceListFromDefaultContext() + { + assumeUsbTestsEnabled(); + final DeviceList deviceList = new DeviceList(); + LibUsb.init(null); + try + { + assertTrue(LibUsb.getDeviceList(null, deviceList) >= 0); + LibUsb.freeDeviceList(deviceList, true); + } + finally + { + LibUsb.exit(null); + } + } + + /** + * Tests {@link LibUsb#getDeviceList(Context, DeviceList)} method with uninitialized USB context. */ @Test(expected = IllegalStateException.class) public void testGetDeviceListWithUninitializedContext() @@ -273,6 +374,16 @@ public void testGetDeviceListWithUninitializedContext() LibUsb.getDeviceList(context, new DeviceList()); } + /** + * Tests {@link LibUsb#getDeviceList(Context, DeviceList)} method with uninitialized default USB context. + */ + @Test(expected = IllegalStateException.class) + public void testGetDeviceListWithUninitializedDefaultContext() + { + assumeUsbTestsEnabled(); + LibUsb.getDeviceList(null, new DeviceList()); + } + /** * Tests {@link LibUsb#freeDeviceList(DeviceList, boolean)} method with * uninitialized list. @@ -1052,6 +1163,17 @@ public void testEventHandlerActiveWithUninitializedContext() LibUsb.eventHandlerActive(context); } + /** + * Tests {@link LibUsb#interruptEventHandler(Context)} with uninitialized USB context. + */ + @Test(expected = IllegalStateException.class) + public void testInterruptEventHandlerWithUninitializedContext() + { + assumeUsbTestsEnabled(); + final Context context = new Context(); + LibUsb.interruptEventHandler(context); + } + /** * Tests {@link LibUsb#lockEventWaiters(Context)} with uninitialized USB * context. @@ -1210,45 +1332,71 @@ public void testPollFdNotifiers() final PollfdListenerMock listener = new PollfdListenerMock(); final Context context = new Context(); LibUsb.init(context); - LibUsb.setPollfdNotifiers(context, listener, "test"); - - FileDescriptor fd = new FileDescriptor(); - LibUsb.triggerPollfdAdded(fd, 53, context.getPointer()); - assertEquals(53, listener.addedEvents); - assertSame(fd, listener.addedFd); - assertSame("test", listener.addedUserData); - assertNull(listener.removedFd); - assertNull(listener.removedUserData); - - listener.reset(); - - fd = new FileDescriptor(); - LibUsb.triggerPollfdRemoved(fd, context.getPointer()); - assertEquals(0, listener.addedEvents); - assertNull(listener.addedFd); - assertNull(listener.addedUserData); - assertSame(fd, listener.removedFd); - assertSame("test", listener.removedUserData); - - LibUsb.setPollfdNotifiers(context, null, null); - listener.reset(); - - fd = new FileDescriptor(); - LibUsb.triggerPollfdAdded(fd, 53, context.getPointer()); - assertEquals(0, listener.addedEvents); - assertNull(listener.addedFd); - assertNull(listener.addedUserData); - assertNull(listener.removedFd); - assertNull(listener.removedUserData); - - listener.reset(); - - fd = new FileDescriptor(); - LibUsb.triggerPollfdRemoved(fd, context.getPointer()); - assertEquals(0, listener.addedEvents); - assertNull(listener.addedFd); - assertNull(listener.addedUserData); - assertNull(listener.removedFd); - assertNull(listener.removedUserData); + try + { + LibUsb.setPollfdNotifiers(context, listener, "test"); + + FileDescriptor fd = new FileDescriptor(); + LibUsb.triggerPollfdAdded(fd, 53, context.getPointer()); + assertEquals(53, listener.addedEvents); + assertSame(fd, listener.addedFd); + assertSame("test", listener.addedUserData); + assertNull(listener.removedFd); + assertNull(listener.removedUserData); + + listener.reset(); + + fd = new FileDescriptor(); + LibUsb.triggerPollfdRemoved(fd, context.getPointer()); + assertEquals(0, listener.addedEvents); + assertNull(listener.addedFd); + assertNull(listener.addedUserData); + assertSame(fd, listener.removedFd); + assertSame("test", listener.removedUserData); + + LibUsb.setPollfdNotifiers(context, null, null); + listener.reset(); + + fd = new FileDescriptor(); + LibUsb.triggerPollfdAdded(fd, 53, context.getPointer()); + assertEquals(0, listener.addedEvents); + assertNull(listener.addedFd); + assertNull(listener.addedUserData); + assertNull(listener.removedFd); + assertNull(listener.removedUserData); + + listener.reset(); + + fd = new FileDescriptor(); + LibUsb.triggerPollfdRemoved(fd, context.getPointer()); + assertEquals(0, listener.addedEvents); + assertNull(listener.addedFd); + assertNull(listener.addedUserData); + assertNull(listener.removedFd); + assertNull(listener.removedUserData); + } + finally + { + LibUsb.exit(context); + } + } + + /** + * Tests the {@link LibUsb#interruptEventHandler(Context)} method. Must not crash. + */ + @Test + public void testInterruptEventHandler() + { + assumeUsbTestsEnabled(); + final Context context = new Context(); + assertEquals(LibUsb.SUCCESS, LibUsb.init(context)); + try + { + LibUsb.interruptEventHandler(context); + } + finally + { + LibUsb.exit(context); + } } } diff --git a/src/test/java/org/usb4java/TransferTest.java b/src/test/java/org/usb4java/TransferTest.java index facb0e8..c2d852e 100644 --- a/src/test/java/org/usb4java/TransferTest.java +++ b/src/test/java/org/usb4java/TransferTest.java @@ -30,7 +30,7 @@ */ public class TransferTest { - /** The libusb contxet. */ + /** The libusb context. */ private Context context; /** diff --git a/src/test/java/org/usb4java/test/UsbAssume.java b/src/test/java/org/usb4java/test/UsbAssume.java index 1b9f22f..7445ce8 100644 --- a/src/test/java/org/usb4java/test/UsbAssume.java +++ b/src/test/java/org/usb4java/test/UsbAssume.java @@ -15,7 +15,7 @@ /** * USB-related assumptions. - * + * * @author Klaus Reimer (k@ailis.de) */ public class UsbAssume @@ -25,16 +25,16 @@ public class UsbAssume /** If TCK tests are to be executed. */ private static Boolean tckTests; - + /** * Check if USB tests are enabled. - * + * * USB tests can be controlled with the system property USB_TESTS. When * set to true then USB tests are always run, if set to false then they * are never run. If this property is not set then the command-line tool * lsusb is called. If this tool returned at least two lines of text then * USB tests are enabled. In all other cases they are disabled. - * + * * @return True if USB tests are enabled, false if not. */ public static boolean isUsbTestsEnabled() @@ -86,7 +86,7 @@ public static boolean isUsbTestsEnabled() * Assume that USB tests are enabled. Call this in the first line of * tests method or preparation methods when you want to ignore the * tests when the system is not able to run the tests anyway. - * + * * USB tests can be controlled with the system property USB_TESTS. When * set to true then USB tests are always run, if set to false then they * are never run. If this property is not set then the command-line tool @@ -117,7 +117,7 @@ public static void assumeHotplugAvailable() * Assume that TCK tests are enabled. Call this in the first line of * tests method or preparation methods when you want to ignore the * tests when the system is not able to run the TCK tests anyway. - * + * * TCK tests can be controlled with the system property TCK_TESTS. When * set to true then TCK tests are always run, if set to false then they * are never run. If this property is not set then the command-line tool