You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

hidapi

Package Overview
Dependencies
Maintainers
1
Versions
53
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

hidapi - cargo Package Compare versions

Comparing version
1.1.0
to
1.1.1
+27
.vscode/launch.json
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in library 'hidapi'",
"cargo": {
"args": [
"test",
"--no-run",
"--lib",
"--package=hidapi"
],
"filter": {
"name": "hidapi",
"kind": "lib"
}
},
"args": [],
"cwd": "${workspaceFolder}"
}
]
}
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Check",
"type": "shell",
"command": "echo Hello"
},
{
"type": "cargo",
"subcommand": "check",
"problemMatcher": [
"$rustc"
],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
os: Visual Studio 2015
environment:
matrix:
- BUILD_ENV: msbuild
arch: x64
- BUILD_ENV: msbuild
arch: Win32
- BUILD_ENV: cygwin
install:
- cmd: if %BUILD_ENV%==cygwin (
C:\cygwin64\setup-x86_64.exe --quiet-mode --no-shortcuts --upgrade-also --packages autoconf,automake )
build_script:
- cmd: if %BUILD_ENV%==msbuild (
msbuild .\windows\hidapi.sln /p:Configuration=Release /p:Platform=%arch% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" )
- cmd: if %BUILD_ENV%==cygwin (
C:\cygwin64\bin\bash -exlc "cd $APPVEYOR_BUILD_FOLDER; ./bootstrap; ./configure; make" )
artifacts:
# Win32 artifacts
- path: .\windows\Release\hidapi.dll
- path: .\windows\Release\hidapi.lib
- path: .\windows\Release\hidapi.pdb
- path: .\windows\Release\hidtest.exe
- path: .\windows\Release\hidtest.pdb
# x64 artifacts
- path: .\windows\x64\Release\hidapi.dll
- path: .\windows\x64\Release\hidapi.lib
- path: .\windows\x64\Release\hidapi.pdb
- path: .\windows\x64\Release\hidtest.exe
- path: .\windows\x64\Release\hidtest.pdb
image: alpine/edge
packages:
- autoconf
- automake
- libtool
- eudev-dev
- libusb-dev
- linux-headers
sources:
- https://github.com/libusb/hidapi
tasks:
- setup: |
cd hidapi
./bootstrap
./configure
- build: |
cd hidapi
make
make DESTDIR=$PWD/root install
make clean
- build-manual: |
cd hidapi/linux
make -f Makefile-manual
cd ../libusb
make -f Makefile-manual
image: archlinux
sources:
- https://github.com/libusb/hidapi
tasks:
- setup: |
cd hidapi
./bootstrap
./configure
- build: |
cd hidapi
make
make DESTDIR=$PWD/root install
make clean
- build-manual: |
cd hidapi/linux
make -f Makefile-manual
cd ../libusb
make -f Makefile-manual
image: fedora/latest
packages:
- autoconf
- automake
- libtool
- mingw64-gcc
- mingw64-gcc-c++
sources:
- https://github.com/libusb/hidapi
tasks:
- setup: |
cd hidapi
./bootstrap
mingw64-configure
- build: |
cd hidapi
make
make DESTDIR=$PWD/root install
make clean
- build-manual: |
cd hidapi/windows
make -f Makefile-manual OS=MINGW CC=x86_64-w64-mingw32-gcc
image: freebsd/latest
packages:
- autoconf
- automake
- gmake
- libiconv
- libtool
- pkgconf
sources:
- https://github.com/libusb/hidapi
tasks:
- setup: |
cd hidapi
./bootstrap
./configure
- build: |
cd hidapi
make
make DESTDIR=$PWD/root install
make clean
- build-manual: |
cd hidapi/libusb
gmake -f Makefile-manual
alpine_task:
container:
image: alpine:latest
install_script: apk add autoconf automake g++ gcc libusb-dev libtool linux-headers eudev-dev make musl-dev
script:
- ./bootstrap
- ./configure || { cat config.log; exit 1; }
- make
- make install
freebsd11_task:
freebsd_instance:
image: freebsd-11-2-release-amd64
install_script:
- pkg install -y
autoconf automake libiconv libtool pkgconf
script:
- ./bootstrap
- ./configure || { cat config.log; exit 1; }
- make
- make install
freebsd12_task:
freebsd_instance:
image: freebsd-12-1-release-amd64
install_script:
- pkg install -y
autoconf automake libiconv libtool pkgconf
script:
- ./bootstrap
- ./configure || { cat config.log; exit 1; }
- make
- make install
language: c
os: osx
osx_image: xcode10.2
script:
- ./bootstrap
- ./configure
- make
- make DESTDIR=$PWD/root install
- make clean
- cd mac
- make -f Makefile-manual

Sorry, the diff of this file is not supported yet

/*******************************************************
Windows HID simplification
Alan Ott
Signal 11 Software
8/22/2009
Copyright 2009
This contents of this file may be used by anyone
for any reason without any conditions and may be
used as a starting point for your own applications
which use HIDAPI.
********************************************************/
#include <stdio.h>
#include <wchar.h>
#include <string.h>
#include <stdlib.h>
#include "hidapi.h"
// Headers needed for sleeping.
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
int main(int argc, char* argv[])
{
int res;
unsigned char buf[256];
#define MAX_STR 255
wchar_t wstr[MAX_STR];
hid_device *handle;
int i;
#ifdef WIN32
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
#endif
struct hid_device_info *devs, *cur_dev;
if (hid_init())
return -1;
devs = hid_enumerate(0x0, 0x0);
cur_dev = devs;
while (cur_dev) {
printf("Device Found\n type: %04hx %04hx\n path: %s\n serial_number: %ls", cur_dev->vendor_id, cur_dev->product_id, cur_dev->path, cur_dev->serial_number);
printf("\n");
printf(" Manufacturer: %ls\n", cur_dev->manufacturer_string);
printf(" Product: %ls\n", cur_dev->product_string);
printf(" Release: %hx\n", cur_dev->release_number);
printf(" Interface: %d\n", cur_dev->interface_number);
printf(" Usage (page): 0x%hx (0x%hx)\n", cur_dev->usage, cur_dev->usage_page);
printf("\n");
cur_dev = cur_dev->next;
}
hid_free_enumeration(devs);
// Set up the command buffer.
memset(buf,0x00,sizeof(buf));
buf[0] = 0x01;
buf[1] = 0x81;
// Open the device using the VID, PID,
// and optionally the Serial number.
////handle = hid_open(0x4d8, 0x3f, L"12345");
handle = hid_open(0x4d8, 0x3f, NULL);
if (!handle) {
printf("unable to open device\n");
return 1;
}
// Read the Manufacturer String
wstr[0] = 0x0000;
res = hid_get_manufacturer_string(handle, wstr, MAX_STR);
if (res < 0)
printf("Unable to read manufacturer string\n");
printf("Manufacturer String: %ls\n", wstr);
// Read the Product String
wstr[0] = 0x0000;
res = hid_get_product_string(handle, wstr, MAX_STR);
if (res < 0)
printf("Unable to read product string\n");
printf("Product String: %ls\n", wstr);
// Read the Serial Number String
wstr[0] = 0x0000;
res = hid_get_serial_number_string(handle, wstr, MAX_STR);
if (res < 0)
printf("Unable to read serial number string\n");
printf("Serial Number String: (%d) %ls", wstr[0], wstr);
printf("\n");
// Read Indexed String 1
wstr[0] = 0x0000;
res = hid_get_indexed_string(handle, 1, wstr, MAX_STR);
if (res < 0)
printf("Unable to read indexed string 1\n");
printf("Indexed String 1: %ls\n", wstr);
// Set the hid_read() function to be non-blocking.
hid_set_nonblocking(handle, 1);
// Try to read from the device. There should be no
// data here, but execution should not block.
res = hid_read(handle, buf, 17);
// Send a Feature Report to the device
buf[0] = 0x2;
buf[1] = 0xa0;
buf[2] = 0x0a;
buf[3] = 0x00;
buf[4] = 0x00;
res = hid_send_feature_report(handle, buf, 17);
if (res < 0) {
printf("Unable to send a feature report.\n");
}
memset(buf,0,sizeof(buf));
// Read a Feature Report from the device
buf[0] = 0x2;
res = hid_get_feature_report(handle, buf, sizeof(buf));
if (res < 0) {
printf("Unable to get a feature report.\n");
printf("%ls", hid_error(handle));
}
else {
// Print out the returned buffer.
printf("Feature Report\n ");
for (i = 0; i < res; i++)
printf("%02hhx ", buf[i]);
printf("\n");
}
memset(buf,0,sizeof(buf));
// Toggle LED (cmd 0x80). The first byte is the report number (0x1).
buf[0] = 0x1;
buf[1] = 0x80;
res = hid_write(handle, buf, 17);
if (res < 0) {
printf("Unable to write()\n");
printf("Error: %ls\n", hid_error(handle));
}
// Request state (cmd 0x81). The first byte is the report number (0x1).
buf[0] = 0x1;
buf[1] = 0x81;
hid_write(handle, buf, 17);
if (res < 0)
printf("Unable to write() (2)\n");
// Read requested state. hid_read() has been set to be
// non-blocking by the call to hid_set_nonblocking() above.
// This loop demonstrates the non-blocking nature of hid_read().
res = 0;
while (res == 0) {
res = hid_read(handle, buf, sizeof(buf));
if (res == 0)
printf("waiting...\n");
if (res < 0)
printf("Unable to read()\n");
#ifdef WIN32
Sleep(500);
#else
usleep(500*1000);
#endif
}
printf("Data read:\n ");
// Print out the returned buffer.
for (i = 0; i < res; i++)
printf("%02hhx ", buf[i]);
printf("\n");
hid_close(handle);
/* Free static HIDAPI objects. */
hid_exit();
#ifdef WIN32
system("pause");
#endif
return 0;
}
## HIDAPI library for Windows, Linux, FreeBSD and macOS
| CI instance | Status |
|----------------------|--------|
| `macOS master` | [![Build Status](https://travis-ci.org/libusb/hidapi.svg?branch=master)](https://travis-ci.org/libusb/hidapi) |
| `Windows master` | [![Build status](https://ci.appveyor.com/api/projects/status/r482aevuigmi86rk/branch/master?svg=true)](https://ci.appveyor.com/project/Youw/hidapi/branch/master) |
| `Linux/BSD, last build (branch/PR)` | [![builds.sr.ht status](https://builds.sr.ht/~qbicz/hidapi.svg)](https://builds.sr.ht/~qbicz/hidapi?) |
HIDAPI is a multi-platform library which allows an application to interface
with USB and Bluetooth HID-Class devices on Windows, Linux, FreeBSD, and macOS.
HIDAPI can be either built as a shared library (`.so`, `.dll` or `.dylib`) or
can be embedded directly into a target application by adding a single source
file (per platform) and a single header.
HIDAPI library was originally developed by Alan Ott ([signal11](https://github.com/signal11)).
It was moved to [libusb/hidapi](https://github.com/libusb/hidapi) on June 4th, 2019, in order to merge important bugfixes and continue development of the library.
## Table of Contents
* [About](#about)
* [What Does the API Look Like?](#what-does-the-api-look-like)
* [License](#license)
* [Download](#download)
* [Build Instructions](#build-instructions)
* [Prerequisites](#prerequisites)
* [Linux](#linux)
* [FreeBSD](#freebsd)
* [Mac](#mac)
* [Windows](#windows)
* [Building HIDAPI into a shared library on Unix Platforms](#building-hidapi-into-a-shared-library-on-unix-platforms)
* [Building the manual way on Unix platforms](#building-the-manual-way-on-unix-platforms)
* [Building on Windows](#building-on-windows)
* [Cross Compiling](#cross-compiling)
* [Prerequisites](#prerequisites-1)
* [Building HIDAPI](#building-hidapi)
## About
HIDAPI has five back-ends:
* Windows (using `hid.dll`)
* Linux/hidraw (using the Kernel's hidraw driver)
* Linux/libusb (using libusb-1.0)
* FreeBSD (using libusb-1.0)
* Mac (using IOHidManager)
On Linux, either the hidraw or the libusb back-end can be used. There are
tradeoffs, and the functionality supported is slightly different.
__Linux/hidraw__ (`linux/hid.c`):
This back-end uses the hidraw interface in the Linux kernel, and supports
both USB and Bluetooth HID devices. It requires kernel version at least 2.6.39
to build. In addition, it will only communicate with devices which have hidraw
nodes associated with them.
Keyboards, mice, and some other devices which are blacklisted from having
hidraw nodes will not work. Fortunately, for nearly all the uses of hidraw,
this is not a problem.
__Linux/FreeBSD/libusb__ (`libusb/hid.c`):
This back-end uses libusb-1.0 to communicate directly to a USB device. This
back-end will of course not work with Bluetooth devices.
HIDAPI also comes with a Test GUI. The Test GUI is cross-platform and uses
Fox Toolkit <http://www.fox-toolkit.org>. It will build on every platform
which HIDAPI supports. Since it relies on a 3rd party library, building it
is optional but recommended because it is so useful when debugging hardware.
## What Does the API Look Like?
The API provides the most commonly used HID functions including sending
and receiving of input, output, and feature reports. The sample program,
which communicates with a heavily hacked up version of the Microchip USB
Generic HID sample looks like this (with error checking removed for
simplicity):
**Warning: Only run the code you understand, and only when it conforms to the
device spec. Writing data at random to your HID devices can break them.**
```c
#ifdef WIN32
#include <windows.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include "hidapi.h"
#define MAX_STR 255
int main(int argc, char* argv[])
{
int res;
unsigned char buf[65];
wchar_t wstr[MAX_STR];
hid_device *handle;
int i;
// Initialize the hidapi library
res = hid_init();
// Open the device using the VID, PID,
// and optionally the Serial number.
handle = hid_open(0x4d8, 0x3f, NULL);
// Read the Manufacturer String
res = hid_get_manufacturer_string(handle, wstr, MAX_STR);
wprintf(L"Manufacturer String: %s\n", wstr);
// Read the Product String
res = hid_get_product_string(handle, wstr, MAX_STR);
wprintf(L"Product String: %s\n", wstr);
// Read the Serial Number String
res = hid_get_serial_number_string(handle, wstr, MAX_STR);
wprintf(L"Serial Number String: (%d) %s\n", wstr[0], wstr);
// Read Indexed String 1
res = hid_get_indexed_string(handle, 1, wstr, MAX_STR);
wprintf(L"Indexed String 1: %s\n", wstr);
// Toggle LED (cmd 0x80). The first byte is the report number (0x0).
buf[0] = 0x0;
buf[1] = 0x80;
res = hid_write(handle, buf, 65);
// Request state (cmd 0x81). The first byte is the report number (0x0).
buf[0] = 0x0;
buf[1] = 0x81;
res = hid_write(handle, buf, 65);
// Read requested state
res = hid_read(handle, buf, 65);
// Print out the returned buffer.
for (i = 0; i < 4; i++)
printf("buf[%d]: %d\n", i, buf[i]);
// Close the device
hid_close(handle);
// Finalize the hidapi library
res = hid_exit();
return 0;
}
```
You can also use [hidtest/test.c](hidtest/test.c)
as a starting point for your applications.
## License
HIDAPI may be used by one of three licenses as outlined in [LICENSE.txt](LICENSE.txt).
## Download
HIDAPI can be downloaded from GitHub
```sh
git clone git://github.com/libusb/hidapi.git
```
## Build Instructions
This section is long. Don't be put off by this. It's not long because it's
complicated to build HIDAPI; it's quite the opposite. This section is long
because of the flexibility of HIDAPI and the large number of ways in which
it can be built and used. You will likely pick a single build method.
HIDAPI can be built in several different ways. If you elect to build a
shared library, you will need to build it from the HIDAPI source
distribution. If you choose instead to embed HIDAPI directly into your
application, you can skip the building and look at the provided platform
Makefiles for guidance. These platform Makefiles are located in `linux/`,
`libusb/`, `mac/` and `windows/` and are called `Makefile-manual`. In addition,
Visual Studio projects are provided. Even if you're going to embed HIDAPI
into your project, it is still beneficial to build the example programs.
### Prerequisites:
#### Linux:
On Linux, you will need to install development packages for libudev,
libusb and optionally Fox-toolkit (for the test GUI). On
Debian/Ubuntu systems these can be installed by running:
```sh
sudo apt-get install libudev-dev libusb-1.0-0-dev libfox-1.6-dev
```
If you downloaded the source directly from the git repository (using
git clone), you'll need Autotools:
```sh
sudo apt-get install autotools-dev autoconf automake libtool
```
#### FreeBSD:
On FreeBSD you will need to install GNU make, libiconv, and
optionally Fox-Toolkit (for the test GUI). This is done by running
the following:
```sh
pkg_add -r gmake libiconv fox16
```
If you downloaded the source directly from the git repository (using
git clone), you'll need Autotools:
```sh
pkg_add -r autotools
```
#### Mac:
On Mac, you will need to install Fox-Toolkit if you wish to build
the Test GUI. There are two ways to do this, and each has a slight
complication. Which method you use depends on your use case.
If you wish to build the Test GUI just for your own testing on your
own computer, then the easiest method is to install Fox-Toolkit
using ports:
```sh
sudo port install fox
```
If you wish to build the TestGUI app bundle to redistribute to
others, you will need to install Fox-toolkit from source. This is
because the version of fox that gets installed using ports uses the
ports X11 libraries which are not compatible with the Apple X11
libraries. If you install Fox with ports and then try to distribute
your built app bundle, it will simply fail to run on other systems.
To install Fox-Toolkit manually, download the source package from
<http://www.fox-toolkit.org>, extract it, and run the following from
within the extracted source:
```sh
./configure && make && make install
```
#### Windows:
On Windows, if you want to build the test GUI, you will need to get
the `hidapi-externals.zip` package from the download site. This
contains pre-built binaries for Fox-toolkit. Extract
`hidapi-externals.zip` just outside of hidapi, so that
hidapi-externals and hidapi are on the same level, as shown:
```
Parent_Folder
|
+hidapi
+hidapi-externals
```
Again, this step is not required if you do not wish to build the
test GUI.
### Building HIDAPI into a shared library on Unix Platforms:
On Unix-like systems such as Linux, FreeBSD, macOS, and even Windows, using
MinGW or Cygwin, the easiest way to build a standard system-installed shared
library is to use the GNU Autotools build system. If you checked out the
source from the git repository, run the following:
```sh
./bootstrap
./configure
make
make install # as root, or using sudo
```
If you downloaded a source package (i.e.: if you did not run git clone), you
can skip the `./bootstrap` step.
`./configure` can take several arguments which control the build. The two most
likely to be used are:
```sh
--enable-testgui
Enable build of the Test GUI. This requires Fox toolkit to
be installed. Instructions for installing Fox-Toolkit on
each platform are in the Prerequisites section above.
--prefix=/usr
Specify where you want the output headers and libraries to
be installed. The example above will put the headers in
/usr/include and the binaries in /usr/lib. The default is to
install into /usr/local which is fine on most systems.
```
### Building the manual way on Unix platforms:
Manual Makefiles are provided mostly to give the user and idea what it takes
to build a program which embeds HIDAPI directly inside of it. These should
really be used as examples only. If you want to build a system-wide shared
library, use the Autotools method described above.
To build HIDAPI using the manual Makefiles, change to the directory
of your platform and run make. For example, on Linux run:
```sh
cd linux/
make -f Makefile-manual
```
To build the Test GUI using the manual makefiles:
```sh
cd testgui/
make -f Makefile-manual
```
### Building on Windows:
To build the HIDAPI DLL on Windows using Visual Studio, build the `.sln` file
in the `windows/` directory.
To build the Test GUI on windows using Visual Studio, build the `.sln` file in
the `testgui/` directory.
To build HIDAPI using MinGW or Cygwin using Autotools, use the instructions
in the section [Building HIDAPI into a shared library on Unix Platforms](#building-hidapi-into-a-shared-library-on-unix-platforms)
above. Note that building the Test GUI with MinGW or Cygwin will
require the Windows procedure in the [Prerequisites](#prerequisites-1) section
above (i.e.: `hidapi-externals.zip`).
To build HIDAPI using MinGW using the Manual Makefiles, see the section
[Building the manual way on Unix platforms](#building-the-manual-way-on-unix-platforms)
above.
HIDAPI can also be built using the Windows DDK (now also called the Windows
Driver Kit or WDK). This method was originally required for the HIDAPI build
but not anymore. However, some users still prefer this method. It is not as
well supported anymore but should still work. Patches are welcome if it does
not. To build using the DDK:
1. Install the Windows Driver Kit (WDK) from Microsoft.
2. From the Start menu, in the Windows Driver Kits folder, select Build
Environments, then your operating system, then the x86 Free Build
Environment (or one that is appropriate for your system).
3. From the console, change directory to the `windows/ddk_build/` directory,
which is part of the HIDAPI distribution.
4. Type build.
5. You can find the output files (DLL and LIB) in a subdirectory created
by the build system which is appropriate for your environment. On
Windows XP, this directory is `objfre_wxp_x86/i386`.
## Cross Compiling
This section talks about cross compiling HIDAPI for Linux using Autotools.
This is useful for using HIDAPI on embedded Linux targets. These
instructions assume the most raw kind of embedded Linux build, where all
prerequisites will need to be built first. This process will of course vary
based on your embedded Linux build system if you are using one, such as
OpenEmbedded or Buildroot.
For the purpose of this section, it will be assumed that the following
environment variables are exported.
```sh
$ export STAGING=$HOME/out
$ export HOST=arm-linux
```
`STAGING` and `HOST` can be modified to suit your setup.
### Prerequisites
Note that the build of libudev is the very basic configuration.
Build libusb. From the libusb source directory, run:
```sh
./configure --host=$HOST --prefix=$STAGING
make
make install
```
Build libudev. From the libudev source directory, run:
```sh
./configure --disable-gudev --disable-introspection --disable-hwdb \
--host=$HOST --prefix=$STAGING
make
make install
```
### Building HIDAPI
Build HIDAPI:
```
PKG_CONFIG_DIR= \
PKG_CONFIG_LIBDIR=$STAGING/lib/pkgconfig:$STAGING/share/pkgconfig \
PKG_CONFIG_SYSROOT_DIR=$STAGING \
./configure --host=$HOST --prefix=$STAGING
```

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

+1
-1
[submodule "etc/hidapi"]
path = etc/hidapi
url = https://github.com/signal11/hidapi.git
url = https://github.com/libusb/hidapi.git

@@ -5,3 +5,3 @@ # This file is automatically @generated by Cargo.

name = "cc"
version = "1.0.47"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"

@@ -11,7 +11,7 @@

name = "hidapi"
version = "1.1.0"
version = "1.1.1"
dependencies = [
"cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
]

@@ -21,3 +21,3 @@

name = "libc"
version = "0.2.66"
version = "0.2.54"
source = "registry+https://github.com/rust-lang/crates.io-index"

@@ -27,8 +27,8 @@

name = "pkg-config"
version = "0.3.17"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)" = "aa87058dce70a3ff5621797f1506cb837edd02ac4c0ae642b4542dce802908b8"
"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
"checksum cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a0c56216487bb80eec9c4516337b2588a4f2a2290d72a1416d930e4dcdb0c90d"
"checksum libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "c6785aa7dd976f5fbf3b71cfd9cd49d7f783c1ff565a858d71031c6c313aa5c6"
"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"

@@ -15,3 +15,3 @@ # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO

name = "hidapi"
version = "1.1.0"
version = "1.1.1"
authors = ["Roland Ruckerbauer <roland.rucky@gmail.com>", "Osspial <osspial@gmail.com>", "Artyom Pavlov <newpavlov@gmail.com>", "mberndt123", "niklasad1"]

@@ -18,0 +18,0 @@ build = "build.rs"

@@ -5,5 +5,7 @@

aclocal.m4
ar-lib
autom4te.cache/
config.*
configure
compile
depcomp

@@ -10,0 +12,0 @@ install-sh

@@ -13,5 +13,7 @@

libusb/hidapi Team:
Development/maintainance since June 4th 2019
For a comprehensive list of contributions, see the commit list at github:
http://github.com/signal11/hidapi/commits/master
https://github.com/libusb/hidapi/commits/master

@@ -20,3 +20,3 @@ /*******************************************************

code repository located at:
http://github.com/signal11/hidapi .
https://github.com/libusb/hidapi .
********************************************************/

@@ -73,5 +73,9 @@

/** The USB interface which this logical device
represents. Valid on both Linux implementations
in all cases, and valid on the Windows implementation
only if the device contains more than one interface. */
represents.
* Valid on both Linux implementations in all cases.
* Valid on the Windows implementation only if the device
contains more than one interface.
* Valid on the Mac implementation if and only if the device
is a USB HID device. */
int interface_number;

@@ -130,3 +134,3 @@

This function returns a pointer to a linked list of type
struct #hid_device, containing information about the HID devices
struct #hid_device_info, containing information about the HID devices
attached to the system, or NULL in the case of failure. Free

@@ -153,2 +157,4 @@ this linked list by calling hid_free_enumeration().

This function sets the return value of hid_error().
@ingroup API

@@ -172,2 +178,4 @@ @param vendor_id The Vendor ID (VID) of the device to open.

This function sets the return value of hid_error().
@ingroup API

@@ -198,4 +206,6 @@ @param path The path name of the device to open

This function sets the return value of hid_error().
@ingroup API
@param device A device handle returned from hid_open().
@param dev A device handle returned from hid_open().
@param data The data to send, including the report number as

@@ -209,3 +219,3 @@ the first byte.

*/
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length);
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length);

@@ -218,4 +228,6 @@ /** @brief Read an Input report from a HID device with timeout.

This function sets the return value of hid_error().
@ingroup API
@param device A device handle returned from hid_open().
@param dev A device handle returned from hid_open().
@param data A buffer to put the read data into.

@@ -240,4 +252,6 @@ @param length The number of bytes to read. For devices with

This function sets the return value of hid_error().
@ingroup API
@param device A device handle returned from hid_open().
@param dev A device handle returned from hid_open().
@param data A buffer to put the read data into.

@@ -253,3 +267,3 @@ @param length The number of bytes to read. For devices with

*/
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length);
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length);

@@ -266,3 +280,3 @@ /** @brief Set the device handle to be non-blocking.

@ingroup API
@param device A device handle returned from hid_open().
@param dev A device handle returned from hid_open().
@param nonblock enable or not the nonblocking reads

@@ -275,3 +289,3 @@ - 1 to enable nonblocking

*/
int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock);
int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock);

@@ -293,4 +307,6 @@ /** @brief Send a Feature report to the device.

This function sets the return value of hid_error().
@ingroup API
@param device A device handle returned from hid_open().
@param dev A device handle returned from hid_open().
@param data The data to send, including the report number as

@@ -305,3 +321,3 @@ the first byte.

*/
int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length);
int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length);

@@ -316,3 +332,30 @@ /** @brief Get a feature report from a HID device.

This function sets the return value of hid_error().
@ingroup API
@param dev A device handle returned from hid_open().
@param data A buffer to put the read data into, including
the Report ID. Set the first byte of @p data[] to the
Report ID of the report to be read, or set it to zero
if your device does not use numbered reports.
@param length The number of bytes to read, including an
extra byte for the report ID. The buffer can be longer
than the actual report.
@returns
This function returns the number of bytes read plus
one for the report ID (which is still in the first
byte), or -1 on error.
*/
int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length);
/** @brief Get a input report from a HID device.
Set the first byte of @p data[] to the Report ID of the
report to be read. Make sure to allow space for this
extra byte in @p data[]. Upon return, the first byte will
still contain the Report ID, and the report data will
start in data[1].
@ingroup API
@param device A device handle returned from hid_open().

@@ -332,10 +375,12 @@ @param data A buffer to put the read data into, including

*/
int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length);
int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length);
/** @brief Close a HID device.
This function sets the return value of hid_error().
@ingroup API
@param device A device handle returned from hid_open().
@param dev A device handle returned from hid_open().
*/
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device);
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev);

@@ -345,3 +390,3 @@ /** @brief Get The Manufacturer String from a HID device.

@ingroup API
@param device A device handle returned from hid_open().
@param dev A device handle returned from hid_open().
@param string A wide string buffer to put the data into.

@@ -353,3 +398,3 @@ @param maxlen The length of the buffer in multiples of wchar_t.

*/
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen);
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen);

@@ -359,3 +404,3 @@ /** @brief Get The Product String from a HID device.

@ingroup API
@param device A device handle returned from hid_open().
@param dev A device handle returned from hid_open().
@param string A wide string buffer to put the data into.

@@ -367,3 +412,3 @@ @param maxlen The length of the buffer in multiples of wchar_t.

*/
int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen);
int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen);

@@ -373,3 +418,3 @@ /** @brief Get The Serial Number String from a HID device.

@ingroup API
@param device A device handle returned from hid_open().
@param dev A device handle returned from hid_open().
@param string A wide string buffer to put the data into.

@@ -381,3 +426,3 @@ @param maxlen The length of the buffer in multiples of wchar_t.

*/
int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen);
int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen);

@@ -387,3 +432,3 @@ /** @brief Get a string from a HID device, based on its string index.

@ingroup API
@param device A device handle returned from hid_open().
@param dev A device handle returned from hid_open().
@param string_index The index of the string to get.

@@ -396,8 +441,18 @@ @param string A wide string buffer to put the data into.

*/
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen);
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen);
/** @brief Get a string describing the last error which occurred.
Whether a function sets the last error is noted in its
documentation. These functions will reset the last error
to NULL before their execution.
Strings returned from hid_error() must not be freed by the user!
This function is thread-safe, and error messages are thread-local.
@ingroup API
@param device A device handle returned from hid_open().
@param dev A device handle returned from hid_open(),
or NULL to get the last non-device-specific error
(e.g. for errors in hid_open() itself).

@@ -408,3 +463,3 @@ @returns

*/
HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device);
HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *dev);

@@ -411,0 +466,0 @@ #ifdef __cplusplus

@@ -23,3 +23,3 @@ /*******************************************************

code repository located at:
http://github.com/signal11/hidapi .
https://github.com/libusb/hidapi .
********************************************************/

@@ -55,3 +55,3 @@

#ifdef __ANDROID__
#if defined(__ANDROID__) && __ANDROID_API__ < __ANDROID_API_N__

@@ -178,2 +178,7 @@ /* Barrier implementation because Android/Bionic don't have pthread_barrier.

struct input_report *input_reports;
/* Was kernel driver detached by libusb */
#ifdef DETACH_KERNEL_DRIVER
int is_driver_detached;
#endif
};

@@ -188,3 +193,3 @@

{
hid_device *dev = calloc(1, sizeof(hid_device));
hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device));
dev->blocking = 1;

@@ -211,4 +216,4 @@

#if 0
/*TODO: Implement this funciton on hidapi/libusb.. */
static void register_error(hid_device *device, const char *op)
/*TODO: Implement this function on hidapi/libusb.. */
static void register_error(hid_device *dev, const char *op)
{

@@ -405,7 +410,3 @@

size_t res;
#ifdef __FreeBSD__
const char *inptr;
#else
char *inptr;
#endif
char *outptr;

@@ -439,3 +440,3 @@ #endif

len -= 2;
str = malloc((len / 2 + 1) * sizeof(wchar_t));
str = (wchar_t*) malloc((len / 2 + 1) * sizeof(wchar_t));
int i;

@@ -573,3 +574,3 @@ for (i = 0; i < len / 2; i++) {

/* VID/PID match. Create the record. */
tmp = calloc(1, sizeof(struct hid_device_info));
tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info));
if (cur_dev) {

@@ -747,4 +748,4 @@ cur_dev->next = tmp;

struct input_report *rpt = malloc(sizeof(*rpt));
rpt->data = malloc(transfer->actual_length);
struct input_report *rpt = (struct input_report*) malloc(sizeof(*rpt));
rpt->data = (uint8_t*) malloc(transfer->actual_length);
memcpy(rpt->data, transfer->buffer, transfer->actual_length);

@@ -811,7 +812,7 @@ rpt->len = transfer->actual_length;

hid_device *dev = param;
unsigned char *buf;
uint8_t *buf;
const size_t length = dev->input_ep_max_packet_size;
/* Set up the transfer object. */
buf = malloc(length);
buf = (uint8_t*) malloc(length);
dev->transfer = libusb_alloc_transfer(0);

@@ -925,2 +926,3 @@ libusb_fill_interrupt_transfer(dev->transfer,

device is managed by the kernel */
dev->is_driver_detached = 0;
if (libusb_kernel_driver_active(dev->device_handle, intf_desc->bInterfaceNumber) == 1) {

@@ -935,2 +937,6 @@ res = libusb_detach_kernel_driver(dev->device_handle, intf_desc->bInterfaceNumber);

}
else {
dev->is_driver_detached = 1;
LOG("Driver successfully detached from kernel.\n");
}
}

@@ -1246,3 +1252,32 @@ #endif

int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length)
{
int res = -1;
int skipped_report_id = 0;
int report_number = data[0];
if (report_number == 0x0) {
/* Offset the return buffer by 1, so that the report ID
will remain in byte 0. */
data++;
length--;
skipped_report_id = 1;
}
res = libusb_control_transfer(dev->device_handle,
LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_IN,
0x01/*HID get_report*/,
(1/*HID Input*/ << 8) | report_number,
dev->interface,
(unsigned char *)data, length,
1000/*timeout millis*/);
if (res < 0)
return -1;
if (skipped_report_id)
res++;
return res;
}
void HID_API_EXPORT hid_close(hid_device *dev)

@@ -1267,2 +1302,11 @@ {

/* reattach the kernel driver if it was detached */
#ifdef DETACH_KERNEL_DRIVER
if (dev->is_driver_detached) {
int res = libusb_attach_kernel_driver(dev->device_handle, dev->interface);
if (res < 0)
LOG("Failed to reattach the driver to kernel.\n");
}
#endif
/* Close the handle */

@@ -1315,3 +1359,3 @@ libusb_close(dev->device_handle);

{
return NULL;
return L"hid_error is not implemented yet";
}

@@ -1370,3 +1414,3 @@

LANG("English - New Zealand", "en_nz", 0x1409),
LANG("English - Phillippines", "en_ph", 0x3409),
LANG("English - Philippines", "en_ph", 0x3409),
LANG("English - Southern Africa", "en_za", 0x1C09),

@@ -1373,0 +1417,0 @@ LANG("English - Trinidad", "en_tt", 0x2C09),

@@ -21,3 +21,3 @@ /*******************************************************

code repository located at:
http://github.com/signal11/hidapi .
https://github.com/libusb/hidapi .
********************************************************/

@@ -49,12 +49,3 @@

/* Definitions from linux/hidraw.h. Since these are new, some distros
may not have header files which contain them. */
#ifndef HIDIOCSFEATURE
#define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len)
#endif
#ifndef HIDIOCGFEATURE
#define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len)
#endif
/* USB HID device property names */

@@ -80,34 +71,16 @@ const char *device_string_names[] = {

int uses_numbered_reports;
wchar_t *last_error_str;
};
/* Global error message that is not specific to a device, e.g. for
hid_open(). It is thread-local like errno. */
__thread wchar_t *last_global_error_str = NULL;
static __u32 kernel_version = 0;
static __u32 detect_kernel_version(void)
{
struct utsname name;
int major, minor, release;
int ret;
uname(&name);
ret = sscanf(name.release, "%d.%d.%d", &major, &minor, &release);
if (ret == 3) {
return KERNEL_VERSION(major, minor, release);
}
ret = sscanf(name.release, "%d.%d", &major, &minor);
if (ret == 2) {
return KERNEL_VERSION(major, minor, 0);
}
printf("Couldn't determine kernel version from version string \"%s\"\n", name.release);
return 0;
}
static hid_device *new_hid_device(void)
{
hid_device *dev = calloc(1, sizeof(hid_device));
hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device));
dev->device_handle = -1;
dev->blocking = 1;
dev->uses_numbered_reports = 0;
dev->last_error_str = NULL;

@@ -128,3 +101,3 @@ return dev;

}
ret = calloc(wlen+1, sizeof(wchar_t));
ret = (wchar_t*) calloc(wlen+1, sizeof(wchar_t));
mbstowcs(ret, utf8, wlen+1);

@@ -137,2 +110,44 @@ ret[wlen] = 0x0000;

/* Set the last global error to be reported by hid_error(NULL).
* The given error message will be copied (and decoded according to the
* currently locale, so do not pass in string constants).
* The last stored global error message is freed.
* Use register_global_error(NULL) to indicate "no error". */
static void register_global_error(const char *msg)
{
if (last_global_error_str)
free(last_global_error_str);
last_global_error_str = utf8_to_wchar_t(msg);
}
/* Set the last error for a device to be reported by hid_error(device).
* The given error message will be copied (and decoded according to the
* currently locale, so do not pass in string constants).
* The last stored global error message is freed.
* Use register_device_error(device, NULL) to indicate "no error". */
static void register_device_error(hid_device *dev, const char *msg)
{
if (dev->last_error_str)
free(dev->last_error_str);
dev->last_error_str = utf8_to_wchar_t(msg);
}
/* See register_device_error, but you can pass a format string into this function. */
static void register_device_error_format(hid_device *dev, const char *format, ...)
{
va_list args;
va_start(args, format);
char msg[100];
vsnprintf(msg, sizeof(msg), format, args);
va_end(args);
register_device_error(dev, msg);
}
/* Get an attribute value from a udev_device and return it as a whar_t

@@ -277,3 +292,3 @@ string. The returned string must be freed with free() when done.*/

if (!udev) {
printf("Can't create udev\n");
register_global_error("Couldn't create udev context");
return -1;

@@ -377,4 +392,2 @@ }

kernel_version = detect_kernel_version();
return 0;

@@ -385,3 +398,5 @@ }

{
/* Nothing to do for this in the Linux/hidraw implementation. */
/* Free global error message */
register_global_error(NULL);
return 0;

@@ -406,3 +421,3 @@ }

if (!udev) {
printf("Can't create udev\n");
register_global_error("Couldn't create udev context");
return NULL;

@@ -473,3 +488,3 @@ }

/* VID/PID match. Create the record. */
tmp = malloc(sizeof(struct hid_device_info));
tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info));
if (cur_dev) {

@@ -597,2 +612,5 @@ cur_dev->next = tmp;

{
/* Set global error to none */
register_global_error(NULL);
struct hid_device_info *devs, *cur_dev;

@@ -624,2 +642,4 @@ const char *path_to_open = NULL;

handle = hid_open_path(path_to_open);
} else {
register_global_error("No such device");
}

@@ -634,2 +654,5 @@

{
/* Set global error to none */
register_global_error(NULL);
hid_device *dev = NULL;

@@ -646,2 +669,4 @@

if (dev->device_handle > 0) {
/* Set device error to none */
register_device_error(dev, NULL);

@@ -657,5 +682,4 @@ /* Get the report descriptor */

if (res < 0)
perror("HIDIOCGRDESCSIZE");
register_device_error_format(dev, "ioctl (GRDESCSIZE): %s", strerror(errno));
/* Get Report Descriptor */

@@ -665,3 +689,3 @@ rpt_desc.size = desc_size;

if (res < 0) {
perror("HIDIOCGRDESC");
register_device_error_format(dev, "ioctl (GRDESC): %s", strerror(errno));
} else {

@@ -678,2 +702,3 @@ /* Determine if this device uses numbered reports. */

/* Unable to open any devices. */
register_global_error(strerror(errno));
free(dev);

@@ -691,2 +716,4 @@ return NULL;

register_device_error(dev, (bytes_written == -1)? strerror(errno): NULL);
return bytes_written;

@@ -698,2 +725,5 @@ }

{
/* Set device error to none */
register_device_error(dev, NULL);
int bytes_read;

@@ -715,6 +745,11 @@

ret = poll(&fds, 1, milliseconds);
if (ret == -1 || ret == 0) {
/* Error or timeout */
if (ret == 0) {
/* Timeout */
return ret;
}
if (ret == -1) {
/* Error */
register_device_error(dev, strerror(errno));
return ret;
}
else {

@@ -724,2 +759,3 @@ /* Check for errors on the file descriptor. This will

if (fds.revents & (POLLERR | POLLHUP | POLLNVAL))
// We cannot use strerror() here as no -1 was returned from poll().
return -1;

@@ -730,12 +766,7 @@ }

bytes_read = read(dev->device_handle, data, length);
if (bytes_read < 0 && (errno == EAGAIN || errno == EINPROGRESS))
bytes_read = 0;
if (bytes_read >= 0 &&
kernel_version != 0 &&
kernel_version < KERNEL_VERSION(2,6,34) &&
dev->uses_numbered_reports) {
/* Work around a kernel bug. Chop off the first byte. */
memmove(data, data+1, bytes_read);
bytes_read--;
if (bytes_read < 0) {
if (errno == EAGAIN || errno == EINPROGRESS)
bytes_read = 0;
else
register_device_error(dev, strerror(errno));
}

@@ -768,3 +799,3 @@

if (res < 0)
perror("ioctl (SFEATURE)");
register_device_error_format(dev, "ioctl (SFEATURE): %s", strerror(errno));

@@ -780,8 +811,12 @@ return res;

if (res < 0)
perror("ioctl (GFEATURE)");
register_device_error_format(dev, "ioctl (GFEATURE): %s", strerror(errno));
return res;
}
// Not supported by Linux HidRaw yet
int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length)
{
return -1;
}

@@ -792,3 +827,10 @@ void HID_API_EXPORT hid_close(hid_device *dev)

return;
close(dev->device_handle);
int ret = close(dev->device_handle);
register_global_error((ret == -1)? strerror(errno): NULL);
/* Free the device error message */
register_device_error(dev, NULL);
free(dev);

@@ -819,5 +861,14 @@ }

/* Passing in NULL means asking for the last global error message. */
HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev)
{
return NULL;
if (dev) {
if (dev->last_error_str == NULL)
return L"Success";
return dev->last_error_str;
}
if (last_global_error_str == NULL)
return L"Success";
return last_global_error_str;
}

@@ -20,3 +20,3 @@ /*******************************************************

code repository located at:
http://github.com/signal11/hidapi .
https://github.com/libusb/hidapi .
********************************************************/

@@ -29,2 +29,3 @@

#include <IOKit/IOKitLib.h>
#include <IOKit/usb/USBSpec.h>
#include <CoreFoundation/CoreFoundation.h>

@@ -129,3 +130,3 @@ #include <wchar.h>

{
hid_device *dev = calloc(1, sizeof(hid_device));
hid_device *dev = (hid_device*) calloc(1, sizeof(hid_device));
dev->device_handle = NULL;

@@ -188,3 +189,3 @@ dev->blocking = 1;

#if 0
static void register_error(hid_device *device, const char *op)
static void register_error(hid_device *dev, const char *op)
{

@@ -195,2 +196,11 @@

static CFArrayRef get_array_property(IOHIDDeviceRef device, CFStringRef key)
{
CFTypeRef ref = IOHIDDeviceGetProperty(device, key);
if (ref != NULL && CFGetTypeID(ref) == CFArrayGetTypeID()) {
return (CFArrayRef)ref;
} else {
return NULL;
}
}

@@ -212,2 +222,7 @@ static int32_t get_int_property(IOHIDDeviceRef device, CFStringRef key)

static CFArrayRef get_usage_pairs(IOHIDDeviceRef device)
{
return get_array_property(device, CFSTR(kIOHIDDeviceUsagePairsKey));
}
static unsigned short get_vendor_id(IOHIDDeviceRef device)

@@ -235,3 +250,3 @@ {

str = IOHIDDeviceGetProperty(device, prop);
str = (CFStringRef) IOHIDDeviceGetProperty(device, prop);

@@ -249,7 +264,7 @@ buf[0] = 0;

range.location = 0;
range.length = ((size_t)str_len > len)? len: (size_t)str_len;
range.length = ((size_t) str_len > len)? len: (size_t) str_len;
chars_copied = CFStringGetBytes(str,
range,
kCFStringEncodingUTF32LE,
(char)'?',
(char) '?',
FALSE,

@@ -292,3 +307,3 @@ (UInt8*)buf,

size_t len = wcslen(s);
wchar_t *ret = malloc((len+1)*sizeof(wchar_t));
wchar_t *ret = (wchar_t*) malloc((len+1)*sizeof(wchar_t));
wcscpy(ret, s);

@@ -308,3 +323,4 @@

static void *iokit_framework = NULL;
static io_service_t (*dynamic_IOHIDDeviceGetService)(IOHIDDeviceRef device) = NULL;
typedef io_service_t (*dynamic_IOHIDDeviceGetService_t)(IOHIDDeviceRef device);
static dynamic_IOHIDDeviceGetService_t dynamic_IOHIDDeviceGetService = NULL;

@@ -316,6 +332,6 @@ /* Use dlopen()/dlsym() to get a pointer to IOHIDDeviceGetService() if it exists.

if (iokit_framework == NULL) {
iokit_framework = dlopen("/System/Library/IOKit.framework/IOKit", RTLD_LAZY);
iokit_framework = dlopen("/System/Library/Frameworks/IOKit.framework/IOKit", RTLD_LAZY);
if (iokit_framework != NULL)
dynamic_IOHIDDeviceGetService = dlsym(iokit_framework, "IOHIDDeviceGetService");
dynamic_IOHIDDeviceGetService = (dynamic_IOHIDDeviceGetService_t) dlsym(iokit_framework, "IOHIDDeviceGetService");
}

@@ -352,3 +368,3 @@

};
struct IOHIDDevice_internal *tmp = (struct IOHIDDevice_internal *)device;
struct IOHIDDevice_internal *tmp = (struct IOHIDDevice_internal *) device;

@@ -405,2 +421,121 @@ return tmp->service;

static struct hid_device_info *create_device_info_with_usage(IOHIDDeviceRef dev, int32_t usage_page, int32_t usage)
{
unsigned short dev_vid;
unsigned short dev_pid;
int BUF_LEN = 256;
wchar_t buf[BUF_LEN];
struct hid_device_info *cur_dev;
io_object_t iokit_dev;
kern_return_t res;
io_string_t path;
if (dev == NULL) {
return NULL;
}
cur_dev = (struct hid_device_info *)calloc(1, sizeof(struct hid_device_info));
if (cur_dev == NULL) {
return NULL;
}
dev_vid = get_vendor_id(dev);
dev_pid = get_product_id(dev);
cur_dev->usage_page = usage_page;
cur_dev->usage = usage;
/* Fill out the record */
cur_dev->next = NULL;
/* Fill in the path (IOService plane) */
iokit_dev = hidapi_IOHIDDeviceGetService(dev);
res = IORegistryEntryGetPath(iokit_dev, kIOServicePlane, path);
if (res == KERN_SUCCESS)
cur_dev->path = strdup(path);
else
cur_dev->path = strdup("");
/* Serial Number */
get_serial_number(dev, buf, BUF_LEN);
cur_dev->serial_number = dup_wcs(buf);
/* Manufacturer and Product strings */
get_manufacturer_string(dev, buf, BUF_LEN);
cur_dev->manufacturer_string = dup_wcs(buf);
get_product_string(dev, buf, BUF_LEN);
cur_dev->product_string = dup_wcs(buf);
/* VID/PID */
cur_dev->vendor_id = dev_vid;
cur_dev->product_id = dev_pid;
/* Release Number */
cur_dev->release_number = get_int_property(dev, CFSTR(kIOHIDVersionNumberKey));
/* Interface Number */
/* We can only retrieve the interface number for USB HID devices.
* IOKit always seems to return 0 when querying a standard USB device
* for its interface. */
bool is_usb_hid = get_int_property(dev, CFSTR(kUSBInterfaceClass)) == kUSBHIDClass;
if (is_usb_hid) {
/* Get the interface number */
cur_dev->interface_number = get_int_property(dev, CFSTR(kUSBInterfaceNumber));
} else {
cur_dev->interface_number = -1;
}
return cur_dev;
}
static struct hid_device_info *create_device_info(IOHIDDeviceRef device)
{
struct hid_device_info *root = NULL;
CFArrayRef usage_pairs = get_usage_pairs(device);
if (usage_pairs != NULL) {
struct hid_device_info *cur = NULL;
struct hid_device_info *next = NULL;
for (CFIndex i = 0; i < CFArrayGetCount(usage_pairs); i++) {
CFTypeRef dict = CFArrayGetValueAtIndex(usage_pairs, i);
if (CFGetTypeID(dict) != CFDictionaryGetTypeID()) {
continue;
}
CFTypeRef usage_page_ref, usage_ref;
int32_t usage_page, usage;
if (!CFDictionaryGetValueIfPresent((CFDictionaryRef)dict, CFSTR(kIOHIDDeviceUsagePageKey), &usage_page_ref) ||
!CFDictionaryGetValueIfPresent((CFDictionaryRef)dict, CFSTR(kIOHIDDeviceUsageKey), &usage_ref) ||
CFGetTypeID(usage_page_ref) != CFNumberGetTypeID() ||
CFGetTypeID(usage_ref) != CFNumberGetTypeID() ||
!CFNumberGetValue((CFNumberRef)usage_page_ref, kCFNumberSInt32Type, &usage_page) ||
!CFNumberGetValue((CFNumberRef)usage_ref, kCFNumberSInt32Type, &usage)) {
continue;
}
next = create_device_info_with_usage(device, usage_page, usage);
if (cur == NULL) {
root = next;
}
else {
cur->next = next;
}
if (next != NULL) {
cur = next;
}
}
}
if (root == NULL) {
/* error when generating or parsing usage pairs */
int32_t usage_page = get_int_property(device, CFSTR(kIOHIDPrimaryUsagePageKey));
int32_t usage = get_int_property(device, CFSTR(kIOHIDPrimaryUsageKey));
root = create_device_info_with_usage(device, usage_page, usage);
}
return root;
}
struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id)

@@ -421,3 +556,23 @@ {

/* Get a list of the Devices */
IOHIDManagerSetDeviceMatching(hid_mgr, NULL);
CFMutableDictionaryRef matching = NULL;
if (vendor_id != 0 || product_id != 0) {
matching = CFDictionaryCreateMutable(kCFAllocatorDefault, kIOHIDOptionsTypeNone, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
if (matching && vendor_id != 0) {
CFNumberRef v = CFNumberCreate(kCFAllocatorDefault, kCFNumberShortType, &vendor_id);
CFDictionarySetValue(matching, CFSTR(kIOHIDVendorIDKey), v);
CFRelease(v);
}
if (matching && product_id != 0) {
CFNumberRef p = CFNumberCreate(kCFAllocatorDefault, kCFNumberShortType, &product_id);
CFDictionarySetValue(matching, CFSTR(kIOHIDProductIDKey), p);
CFRelease(p);
}
}
IOHIDManagerSetDeviceMatching(hid_mgr, matching);
if (matching != NULL) {
CFRelease(matching);
}
CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr);

@@ -427,3 +582,3 @@

num_devices = CFSetGetCount(device_set);
IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef));
IOHIDDeviceRef *device_array = (IOHIDDeviceRef*) calloc(num_devices, sizeof(IOHIDDeviceRef));
CFSetGetValues(device_set, (const void **) device_array);

@@ -433,67 +588,24 @@

for (i = 0; i < num_devices; i++) {
unsigned short dev_vid;
unsigned short dev_pid;
#define BUF_LEN 256
wchar_t buf[BUF_LEN];
IOHIDDeviceRef dev = device_array[i];
if (!dev) {
continue;
}
if (!dev) {
continue;
}
dev_vid = get_vendor_id(dev);
dev_pid = get_product_id(dev);
struct hid_device_info *tmp = create_device_info(dev);
if (tmp == NULL) {
continue;
}
/* Check the VID/PID against the arguments */
if ((vendor_id == 0x0 || vendor_id == dev_vid) &&
(product_id == 0x0 || product_id == dev_pid)) {
struct hid_device_info *tmp;
io_object_t iokit_dev;
kern_return_t res;
io_string_t path;
if (cur_dev) {
cur_dev->next = tmp;
}
else {
root = tmp;
}
cur_dev = tmp;
/* VID/PID match. Create the record. */
tmp = malloc(sizeof(struct hid_device_info));
if (cur_dev) {
cur_dev->next = tmp;
}
else {
root = tmp;
}
cur_dev = tmp;
/* Get the Usage Page and Usage for this device. */
cur_dev->usage_page = get_int_property(dev, CFSTR(kIOHIDPrimaryUsagePageKey));
cur_dev->usage = get_int_property(dev, CFSTR(kIOHIDPrimaryUsageKey));
/* Fill out the record */
cur_dev->next = NULL;
/* Fill in the path (IOService plane) */
iokit_dev = hidapi_IOHIDDeviceGetService(dev);
res = IORegistryEntryGetPath(iokit_dev, kIOServicePlane, path);
if (res == KERN_SUCCESS)
cur_dev->path = strdup(path);
else
cur_dev->path = strdup("");
/* Serial Number */
get_serial_number(dev, buf, BUF_LEN);
cur_dev->serial_number = dup_wcs(buf);
/* Manufacturer and Product strings */
get_manufacturer_string(dev, buf, BUF_LEN);
cur_dev->manufacturer_string = dup_wcs(buf);
get_product_string(dev, buf, BUF_LEN);
cur_dev->product_string = dup_wcs(buf);
/* VID/PID */
cur_dev->vendor_id = dev_vid;
cur_dev->product_id = dev_pid;
/* Release Number */
cur_dev->release_number = get_int_property(dev, CFSTR(kIOHIDVersionNumberKey));
/* Interface Number (Unsupported on Mac)*/
cur_dev->interface_number = -1;
/* move the pointer to the tail of returnd list */
while (cur_dev->next != NULL) {
cur_dev = cur_dev->next;
}

@@ -563,3 +675,3 @@ }

/* Stop the Run Loop for this device. */
hid_device *d = context;
hid_device *d = (hid_device*) context;

@@ -578,7 +690,7 @@ d->disconnected = 1;

struct input_report *rpt;
hid_device *dev = context;
hid_device *dev = (hid_device*) context;
/* Make a new Input Report object */
rpt = calloc(1, sizeof(struct input_report));
rpt->data = calloc(1, report_length);
rpt = (struct input_report*) calloc(1, sizeof(struct input_report));
rpt->data = (uint8_t*) calloc(1, report_length);
memcpy(rpt->data, report, report_length);

@@ -626,3 +738,3 @@ rpt->len = report_length;

{
hid_device *dev = context;
hid_device *dev = (hid_device*) context;
CFRunLoopStop(dev->run_loop); /*TODO: CFRunLoopGetCurrent()*/

@@ -633,3 +745,3 @@ }

{
hid_device *dev = param;
hid_device *dev = (hid_device*) param;
SInt32 code;

@@ -705,9 +817,10 @@

io_registry_entry_t entry = MACH_PORT_NULL;
IOReturn ret = kIOReturnInvalid;
dev = new_hid_device();
/* Set up the HID Manager if it hasn't been done */
if (hid_init() < 0)
return NULL;
goto return_error;
dev = new_hid_device();
/* Get the IORegistry entry for the given path */

@@ -728,3 +841,3 @@ entry = IORegistryEntryFromPath(kIOMasterPortDefault, path);

/* Open the IOHIDDevice */
IOReturn ret = IOHIDDeviceOpen(dev->device_handle, kIOHIDOptionsTypeSeizeDevice);
ret = IOHIDDeviceOpen(dev->device_handle, kIOHIDOptionsTypeSeizeDevice);
if (ret == kIOReturnSuccess) {

@@ -735,3 +848,3 @@ char str[32];

dev->max_input_report_len = (CFIndex) get_max_report_length(dev->device_handle);
dev->input_report_buf = calloc(dev->max_input_report_len, sizeof(uint8_t));
dev->input_report_buf = (uint8_t*) calloc(dev->max_input_report_len, sizeof(uint8_t));

@@ -776,11 +889,8 @@ /* Create the Run Loop Mode for this device.

{
const unsigned char *data_to_send;
size_t length_to_send;
const unsigned char *data_to_send = data;
CFIndex length_to_send = length;
IOReturn res;
const unsigned char report_id = data[0];
/* Return if the device has been disconnected. */
if (dev->disconnected)
return -1;
if (data[0] == 0x0) {
if (report_id == 0x0) {
/* Not using numbered Reports.

@@ -791,20 +901,49 @@ Don't send the report number. */

}
else {
/* Using numbered Reports.
Send the Report Number */
data_to_send = data;
length_to_send = length;
/* Avoid crash if the device has been unplugged. */
if (dev->disconnected) {
return -1;
}
if (!dev->disconnected) {
res = IOHIDDeviceSetReport(dev->device_handle,
type,
data[0], /* Report ID*/
data_to_send, length_to_send);
res = IOHIDDeviceSetReport(dev->device_handle,
type,
report_id,
data_to_send, length_to_send);
if (res == kIOReturnSuccess) {
return length;
if (res == kIOReturnSuccess) {
return length;
}
return -1;
}
static int get_report(hid_device *dev, IOHIDReportType type, unsigned char *data, size_t length)
{
unsigned char *report = data;
CFIndex report_length = length;
IOReturn res = kIOReturnSuccess;
const unsigned char report_id = data[0];
if (report_id == 0x0) {
/* Not using numbered Reports.
Don't send the report number. */
report = data+1;
report_length = length-1;
}
/* Avoid crash if the device has been unplugged. */
if (dev->disconnected) {
return -1;
}
res = IOHIDDeviceGetReport(dev->device_handle,
type,
report_id,
report, &report_length);
if (res == kIOReturnSuccess) {
if (report_id == 0x0) { // 0 report number still present at the beginning
report_length++;
}
else
return -1;
return report_length;
}

@@ -842,3 +981,3 @@

/* A res of 0 means we may have been signaled or it may
be a spurious wakeup. Check to see that there's acutally
be a spurious wakeup. Check to see that there's actually
data in the queue before returning, and if not, go back

@@ -863,3 +1002,3 @@ to sleep. See the pthread_cond_timedwait() man page for

/* A res of 0 means we may have been signaled or it may
be a spurious wakeup. Check to see that there's acutally
be a spurious wakeup. Check to see that there's actually
data in the queue before returning, and if not, go back

@@ -971,20 +1110,10 @@ to sleep. See the pthread_cond_timedwait() man page for

{
CFIndex len = length;
IOReturn res;
return get_report(dev, kIOHIDReportTypeFeature, data, length);
}
/* Return if the device has been unplugged. */
if (dev->disconnected)
return -1;
res = IOHIDDeviceGetReport(dev->device_handle,
kIOHIDReportTypeFeature,
data[0], /* Report ID */
data, &len);
if (res == kIOReturnSuccess)
return len;
else
return -1;
int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length)
{
return get_report(dev, kIOHIDReportTypeInput, data, length);
}
void HID_API_EXPORT hid_close(hid_device *dev)

@@ -1063,3 +1192,3 @@ {

return NULL;
return L"hid_error is not implemented yet";
}

@@ -1066,0 +1195,0 @@

@@ -82,3 +82,3 @@ #!/bin/bash

# Copy the binary into the bundle. Use ../libtool to do this if it's
# available beacuse if $EXE_NAME was built with autotools, it will be
# available because if $EXE_NAME was built with autotools, it will be
# necessary. If ../libtool not available, just use cp to do the copy, but

@@ -85,0 +85,0 @@ # only if $EXE_NAME is a binary.

@@ -11,6 +11,15 @@ /*******************************

#ifndef MAC_OS_X_VERSION_10_12
#define MAC_OS_X_VERSION_10_12 101200
#endif
// macOS 10.12 deprecated NSAnyEventMask in favor of NSEventMaskAny
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12
#define NSEventMaskAny NSAnyEventMask
#endif
extern FXMainWindow *g_main_window;
@interface MyAppDelegate : NSObject
@interface MyAppDelegate : NSObject<NSApplicationDelegate>
{

@@ -81,3 +90,3 @@ }

while (1) {
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
untilDate:nil

@@ -84,0 +93,0 @@ inMode:NSDefaultRunLoopMode

Debug
Release
.vs/
*.exp

@@ -8,2 +9,3 @@ *.ilk

*.vcproj.*
*.vcxproj.*
*.ncb

@@ -10,0 +12,0 @@ *.suo

@@ -20,3 +20,3 @@ /*******************************************************

code repository located at:
http://github.com/signal11/hidapi .
https://github.com/libusb/hidapi .
********************************************************/

@@ -59,2 +59,3 @@

#define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100)
#define IOCTL_HID_GET_INPUT_REPORT HID_OUT_CTL_CODE(104)

@@ -114,2 +115,3 @@ #ifdef __cplusplus

typedef BOOLEAN (__stdcall *HidD_GetFeature_)(HANDLE handle, PVOID data, ULONG length);
typedef BOOLEAN (__stdcall *HidD_GetInputReport_)(HANDLE handle, PVOID data, ULONG length);
typedef BOOLEAN (__stdcall *HidD_GetIndexedString_)(HANDLE handle, ULONG string_index, PVOID buffer, ULONG buffer_len);

@@ -127,2 +129,3 @@ typedef BOOLEAN (__stdcall *HidD_GetPreparsedData_)(HANDLE handle, PHIDP_PREPARSED_DATA *preparsed_data);

static HidD_GetFeature_ HidD_GetFeature;
static HidD_GetInputReport_ HidD_GetInputReport;
static HidD_GetIndexedString_ HidD_GetIndexedString;

@@ -176,3 +179,3 @@ static HidD_GetPreparsedData_ HidD_GetPreparsedData;

static void register_error(hid_device *device, const char *op)
static void register_error(hid_device *dev, const char *op)
{

@@ -203,4 +206,4 @@ WCHAR *ptr, *msg;

the hid_error() function can pick it up. */
LocalFree(device->last_error_str);
device->last_error_str = msg;
LocalFree(dev->last_error_str);
dev->last_error_str = msg;
}

@@ -220,2 +223,3 @@

RESOLVE(HidD_GetFeature);
RESOLVE(HidD_GetInputReport);
RESOLVE(HidD_GetIndexedString);

@@ -235,6 +239,6 @@ RESOLVE(HidD_GetPreparsedData);

static HANDLE open_device(const char *path, BOOL enumerate)
static HANDLE open_device(const char *path, BOOL open_rw)
{
HANDLE handle;
DWORD desired_access = (enumerate)? 0: (GENERIC_WRITE | GENERIC_READ);
DWORD desired_access = (open_rw)? (GENERIC_WRITE | GENERIC_READ): 0;
DWORD share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;

@@ -369,3 +373,5 @@

if (strcmp(driver_name, "HIDClass") == 0) {
if ((strcmp(driver_name, "HIDClass") == 0) ||
(strcmp(driver_name, "Mouse") == 0) ||
(strcmp(driver_name, "Keyboard") == 0)) {
/* See if there's a driver bound. */

@@ -382,3 +388,3 @@ res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data,

/* Open a handle to the device */
write_handle = open_device(device_interface_detail_data->DevicePath, TRUE);
write_handle = open_device(device_interface_detail_data->DevicePath, FALSE);

@@ -448,2 +454,3 @@ /* Check validity of write_handle. */

/* Serial Number */
wstr[0]= 0x0000;
res = HidD_GetSerialNumberString(write_handle, wstr, sizeof(wstr));

@@ -456,2 +463,3 @@ wstr[WSTR_LEN-1] = 0x0000;

/* Manufacturer String */
wstr[0]= 0x0000;
res = HidD_GetManufacturerString(write_handle, wstr, sizeof(wstr));

@@ -464,2 +472,3 @@ wstr[WSTR_LEN-1] = 0x0000;

/* Product String */
wstr[0]= 0x0000;
res = HidD_GetProductString(write_handle, wstr, sizeof(wstr));

@@ -582,9 +591,19 @@ wstr[WSTR_LEN-1] = 0x0000;

/* Open a handle to the device */
dev->device_handle = open_device(path, FALSE);
dev->device_handle = open_device(path, TRUE);
/* Check validity of write_handle. */
if (dev->device_handle == INVALID_HANDLE_VALUE) {
/* Unable to open the device. */
register_error(dev, "CreateFile");
goto err;
/* System devices, such as keyboards and mice, cannot be opened in
read-write mode, because the system takes exclusive control over
them. This is to prevent keyloggers. However, feature reports
can still be sent and received. Retry opening the device, but
without read/write access. */
dev->device_handle = open_device(path, FALSE);
/* Check the validity of the limited device_handle. */
if (dev->device_handle == INVALID_HANDLE_VALUE) {
/* Unable to open the device, even without read-write mode. */
register_error(dev, "CreateFile");
goto err;
}
}

@@ -823,2 +842,51 @@

int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length)
{
#if 0
BOOL res;
res = HidD_GetInputReport(dev->device_handle, data, length);
if (!res) {
register_error(dev, "HidD_GetInputReport");
return -1;
}
return length;
#else
DWORD bytes_returned;
OVERLAPPED ol;
memset(&ol, 0, sizeof(ol));
BOOL res = DeviceIoControl(dev->device_handle,
IOCTL_HID_GET_INPUT_REPORT,
data, length,
data, length,
&bytes_returned, &ol);
if (!res) {
if (GetLastError() != ERROR_IO_PENDING) {
/* DeviceIoControl() failed. Return error. */
register_error(dev, "Send Input Report DeviceIoControl");
return -1;
}
}
/* Wait here until the write is done. This makes
hid_get_feature_report() synchronous. */
res = GetOverlappedResult(dev->device_handle, &ol, &bytes_returned, TRUE/*wait*/);
if (!res) {
/* The operation failed. */
register_error(dev, "Send Input Report GetOverLappedResult");
return -1;
}
/* bytes_returned does not include the first byte which contains the
report ID. The data buffer actually contains one more byte than
bytes_returned. */
bytes_returned++;
return bytes_returned;
#endif
}
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev)

@@ -887,3 +955,10 @@ {

{
return (wchar_t*)dev->last_error_str;
if (dev) {
if (dev->last_error_str == NULL)
return L"Success";
return (wchar_t*)dev->last_error_str;
}
// Global error messages are not (yet) implemented on Windows.
return L"hid_error for global errors is not implemented yet";
}

@@ -890,0 +965,0 @@


Microsoft Visual Studio Solution File, Format Version 10.00
# Visual C++ Express 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hidapi", "hidapi.vcproj", "{A107C21C-418A-4697-BB10-20C3AA60E2E4}"
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.136
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hidapi", "hidapi.vcxproj", "{A107C21C-418A-4697-BB10-20C3AA60E2E4}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hidtest", "hidtest.vcproj", "{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}"
ProjectSection(ProjectDependencies) = postProject
{A107C21C-418A-4697-BB10-20C3AA60E2E4} = {A107C21C-418A-4697-BB10-20C3AA60E2E4}
EndProjectSection
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hidtest", "hidtest.vcxproj", "{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}"
EndProject

@@ -14,3 +13,5 @@ Global

Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection

@@ -20,8 +21,16 @@ GlobalSection(ProjectConfigurationPlatforms) = postSolution

{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug|Win32.Build.0 = Debug|Win32
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug|x64.ActiveCfg = Debug|x64
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Debug|x64.Build.0 = Debug|x64
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|Win32.ActiveCfg = Release|Win32
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|Win32.Build.0 = Release|Win32
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|x64.ActiveCfg = Release|x64
{A107C21C-418A-4697-BB10-20C3AA60E2E4}.Release|x64.Build.0 = Release|x64
{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Debug|Win32.ActiveCfg = Debug|Win32
{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Debug|Win32.Build.0 = Debug|Win32
{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Debug|x64.ActiveCfg = Debug|x64
{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Debug|x64.Build.0 = Debug|x64
{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Release|Win32.ActiveCfg = Release|Win32
{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Release|Win32.Build.0 = Release|Win32
{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Release|x64.ActiveCfg = Release|x64
{23E9FF6A-49D1-4993-B2B5-BBB992C6C712}.Release|x64.Build.0 = Release|x64
EndGlobalSection

@@ -31,2 +40,5 @@ GlobalSection(SolutionProperties) = preSolution

EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8749E535-9C65-4A89-840E-78D7578C7866}
EndGlobalSection
EndGlobal
{
"git": {
"sha1": "8da2a18387b812bbdf138f0b67f277ea5b5d8efe"
}
}
/*******************************************************
Windows HID simplification
Alan Ott
Signal 11 Software
8/22/2009
Copyright 2009
This contents of this file may be used by anyone
for any reason without any conditions and may be
used as a starting point for your own applications
which use HIDAPI.
********************************************************/
#include <stdio.h>
#include <wchar.h>
#include <string.h>
#include <stdlib.h>
#include "hidapi.h"
// Headers needed for sleeping.
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
int main(int argc, char* argv[])
{
int res;
unsigned char buf[256];
#define MAX_STR 255
wchar_t wstr[MAX_STR];
hid_device *handle;
int i;
#ifdef WIN32
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
#endif
struct hid_device_info *devs, *cur_dev;
if (hid_init())
return -1;
devs = hid_enumerate(0x0, 0x0);
cur_dev = devs;
while (cur_dev) {
printf("Device Found\n type: %04hx %04hx\n path: %s\n serial_number: %ls", cur_dev->vendor_id, cur_dev->product_id, cur_dev->path, cur_dev->serial_number);
printf("\n");
printf(" Manufacturer: %ls\n", cur_dev->manufacturer_string);
printf(" Product: %ls\n", cur_dev->product_string);
printf(" Release: %hx\n", cur_dev->release_number);
printf(" Interface: %d\n", cur_dev->interface_number);
printf("\n");
cur_dev = cur_dev->next;
}
hid_free_enumeration(devs);
// Set up the command buffer.
memset(buf,0x00,sizeof(buf));
buf[0] = 0x01;
buf[1] = 0x81;
// Open the device using the VID, PID,
// and optionally the Serial number.
////handle = hid_open(0x4d8, 0x3f, L"12345");
handle = hid_open(0x4d8, 0x3f, NULL);
if (!handle) {
printf("unable to open device\n");
return 1;
}
// Read the Manufacturer String
wstr[0] = 0x0000;
res = hid_get_manufacturer_string(handle, wstr, MAX_STR);
if (res < 0)
printf("Unable to read manufacturer string\n");
printf("Manufacturer String: %ls\n", wstr);
// Read the Product String
wstr[0] = 0x0000;
res = hid_get_product_string(handle, wstr, MAX_STR);
if (res < 0)
printf("Unable to read product string\n");
printf("Product String: %ls\n", wstr);
// Read the Serial Number String
wstr[0] = 0x0000;
res = hid_get_serial_number_string(handle, wstr, MAX_STR);
if (res < 0)
printf("Unable to read serial number string\n");
printf("Serial Number String: (%d) %ls", wstr[0], wstr);
printf("\n");
// Read Indexed String 1
wstr[0] = 0x0000;
res = hid_get_indexed_string(handle, 1, wstr, MAX_STR);
if (res < 0)
printf("Unable to read indexed string 1\n");
printf("Indexed String 1: %ls\n", wstr);
// Set the hid_read() function to be non-blocking.
hid_set_nonblocking(handle, 1);
// Try to read from the device. There shoud be no
// data here, but execution should not block.
res = hid_read(handle, buf, 17);
// Send a Feature Report to the device
buf[0] = 0x2;
buf[1] = 0xa0;
buf[2] = 0x0a;
buf[3] = 0x00;
buf[4] = 0x00;
res = hid_send_feature_report(handle, buf, 17);
if (res < 0) {
printf("Unable to send a feature report.\n");
}
memset(buf,0,sizeof(buf));
// Read a Feature Report from the device
buf[0] = 0x2;
res = hid_get_feature_report(handle, buf, sizeof(buf));
if (res < 0) {
printf("Unable to get a feature report.\n");
printf("%ls", hid_error(handle));
}
else {
// Print out the returned buffer.
printf("Feature Report\n ");
for (i = 0; i < res; i++)
printf("%02hhx ", buf[i]);
printf("\n");
}
memset(buf,0,sizeof(buf));
// Toggle LED (cmd 0x80). The first byte is the report number (0x1).
buf[0] = 0x1;
buf[1] = 0x80;
res = hid_write(handle, buf, 17);
if (res < 0) {
printf("Unable to write()\n");
printf("Error: %ls\n", hid_error(handle));
}
// Request state (cmd 0x81). The first byte is the report number (0x1).
buf[0] = 0x1;
buf[1] = 0x81;
hid_write(handle, buf, 17);
if (res < 0)
printf("Unable to write() (2)\n");
// Read requested state. hid_read() has been set to be
// non-blocking by the call to hid_set_nonblocking() above.
// This loop demonstrates the non-blocking nature of hid_read().
res = 0;
while (res == 0) {
res = hid_read(handle, buf, sizeof(buf));
if (res == 0)
printf("waiting...\n");
if (res < 0)
printf("Unable to read()\n");
#ifdef WIN32
Sleep(500);
#else
usleep(500*1000);
#endif
}
printf("Data read:\n ");
// Print out the returned buffer.
for (i = 0; i < res; i++)
printf("%02hhx ", buf[i]);
printf("\n");
hid_close(handle);
/* Free static HIDAPI objects. */
hid_exit();
#ifdef WIN32
system("pause");
#endif
return 0;
}
There are two implementations of HIDAPI for Linux. One (linux/hid.c) uses the
Linux hidraw driver, and the other (libusb/hid.c) uses libusb. Which one you
use depends on your application. Complete functionality of the hidraw
version depends on patches to the Linux kernel which are not currently in
the mainline. These patches have to do with sending and receiving feature
reports. The libusb implementation uses libusb to talk directly to the
device, bypassing any Linux HID driver. The disadvantage of the libusb
version is that it will only work with USB devices, while the hidraw
implementation will work with Bluetooth devices as well.
To use HIDAPI, simply drop either linux/hid.c or libusb/hid.c into your
application and build using the build parameters in the Makefile.
Libusb Implementation notes
----------------------------
For the libusb implementation, libusb-1.0 must be installed. Libusb 1.0 is
different than the legacy libusb 0.1 which is installed on many systems. To
install libusb-1.0 on Ubuntu and other Debian-based systems, run:
sudo apt-get install libusb-1.0-0-dev
Hidraw Implementation notes
----------------------------
For the hidraw implementation, libudev headers and libraries are required to
build hidapi programs. To install libudev libraries on Ubuntu,
and other Debian-based systems, run:
sudo apt-get install libudev-dev
On Redhat-based systems, run the following as root:
yum install libudev-devel
Unfortunately, the hidraw driver, which the linux version of hidapi is based
on, contains bugs in kernel versions < 2.6.36, which the client application
should be aware of.
Bugs (hidraw implementation only):
-----------------------------------
On Kernel versions < 2.6.34, if your device uses numbered reports, an extra
byte will be returned at the beginning of all reports returned from read()
for hidraw devices. This is worked around in the libary. No action should be
necessary in the client library.
On Kernel versions < 2.6.35, reports will only be sent using a Set_Report
transfer on the CONTROL endpoint. No data will ever be sent on an Interrupt
Out endpoint if one exists. This is fixed in 2.6.35. In 2.6.35, OUTPUT
reports will be sent to the device on the first INTERRUPT OUT endpoint if it
exists; If it does not exist, OUTPUT reports will be sent on the CONTROL
endpoint.
On Kernel versions < 2.6.36, add an extra byte containing the report number
to sent reports if numbered reports are used, and the device does not
contain an INTERRPUT OUT endpoint for OUTPUT transfers. For example, if
your device uses numbered reports and wants to send {0x2 0xff 0xff 0xff} to
the device (0x2 is the report number), you must send {0x2 0x2 0xff 0xff
0xff}. If your device has the optional Interrupt OUT endpoint, this does not
apply (but really on 2.6.35 only, because 2.6.34 won't use the interrupt
out endpoint).
HIDAPI library for Windows, Linux, FreeBSD and Mac OS X
=========================================================
About
======
HIDAPI is a multi-platform library which allows an application to interface
with USB and Bluetooth HID-Class devices on Windows, Linux, FreeBSD, and Mac
OS X. HIDAPI can be either built as a shared library (.so or .dll) or
can be embedded directly into a target application by adding a single source
file (per platform) and a single header.
HIDAPI has four back-ends:
* Windows (using hid.dll)
* Linux/hidraw (using the Kernel's hidraw driver)
* Linux/libusb (using libusb-1.0)
* FreeBSD (using libusb-1.0)
* Mac (using IOHidManager)
On Linux, either the hidraw or the libusb back-end can be used. There are
tradeoffs, and the functionality supported is slightly different.
Linux/hidraw (linux/hid.c):
This back-end uses the hidraw interface in the Linux kernel. While this
back-end will support both USB and Bluetooth, it has some limitations on
kernels prior to 2.6.39, including the inability to send or receive feature
reports. In addition, it will only communicate with devices which have
hidraw nodes associated with them. Keyboards, mice, and some other devices
which are blacklisted from having hidraw nodes will not work. Fortunately,
for nearly all the uses of hidraw, this is not a problem.
Linux/FreeBSD/libusb (libusb/hid.c):
This back-end uses libusb-1.0 to communicate directly to a USB device. This
back-end will of course not work with Bluetooth devices.
HIDAPI also comes with a Test GUI. The Test GUI is cross-platform and uses
Fox Toolkit (http://www.fox-toolkit.org). It will build on every platform
which HIDAPI supports. Since it relies on a 3rd party library, building it
is optional but recommended because it is so useful when debugging hardware.
What Does the API Look Like?
=============================
The API provides the the most commonly used HID functions including sending
and receiving of input, output, and feature reports. The sample program,
which communicates with a heavily hacked up version of the Microchip USB
Generic HID sample looks like this (with error checking removed for
simplicity):
#ifdef WIN32
#include <windows.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include "hidapi.h"
#define MAX_STR 255
int main(int argc, char* argv[])
{
int res;
unsigned char buf[65];
wchar_t wstr[MAX_STR];
hid_device *handle;
int i;
// Initialize the hidapi library
res = hid_init();
// Open the device using the VID, PID,
// and optionally the Serial number.
handle = hid_open(0x4d8, 0x3f, NULL);
// Read the Manufacturer String
res = hid_get_manufacturer_string(handle, wstr, MAX_STR);
wprintf(L"Manufacturer String: %s\n", wstr);
// Read the Product String
res = hid_get_product_string(handle, wstr, MAX_STR);
wprintf(L"Product String: %s\n", wstr);
// Read the Serial Number String
res = hid_get_serial_number_string(handle, wstr, MAX_STR);
wprintf(L"Serial Number String: (%d) %s\n", wstr[0], wstr);
// Read Indexed String 1
res = hid_get_indexed_string(handle, 1, wstr, MAX_STR);
wprintf(L"Indexed String 1: %s\n", wstr);
// Toggle LED (cmd 0x80). The first byte is the report number (0x0).
buf[0] = 0x0;
buf[1] = 0x80;
res = hid_write(handle, buf, 65);
// Request state (cmd 0x81). The first byte is the report number (0x0).
buf[0] = 0x0;
buf[1] = 0x81;
res = hid_write(handle, buf, 65);
// Read requested state
res = hid_read(handle, buf, 65);
// Print out the returned buffer.
for (i = 0; i < 4; i++)
printf("buf[%d]: %d\n", i, buf[i]);
// Finalize the hidapi library
res = hid_exit();
return 0;
}
If you have your own simple test programs which communicate with standard
hardware development boards (such as those from Microchip, TI, Atmel,
FreeScale and others), please consider sending me something like the above
for inclusion into the HIDAPI source. This will help others who have the
same hardware as you do.
License
========
HIDAPI may be used by one of three licenses as outlined in LICENSE.txt.
Download
=========
HIDAPI can be downloaded from github
git clone git://github.com/signal11/hidapi.git
Build Instructions
===================
This section is long. Don't be put off by this. It's not long because it's
complicated to build HIDAPI; it's quite the opposite. This section is long
because of the flexibility of HIDAPI and the large number of ways in which
it can be built and used. You will likely pick a single build method.
HIDAPI can be built in several different ways. If you elect to build a
shared library, you will need to build it from the HIDAPI source
distribution. If you choose instead to embed HIDAPI directly into your
application, you can skip the building and look at the provided platform
Makefiles for guidance. These platform Makefiles are located in linux/
libusb/ mac/ and windows/ and are called Makefile-manual. In addition,
Visual Studio projects are provided. Even if you're going to embed HIDAPI
into your project, it is still beneficial to build the example programs.
Prerequisites:
---------------
Linux:
-------
On Linux, you will need to install development packages for libudev,
libusb and optionally Fox-toolkit (for the test GUI). On
Debian/Ubuntu systems these can be installed by running:
sudo apt-get install libudev-dev libusb-1.0-0-dev libfox-1.6-dev
If you downloaded the source directly from the git repository (using
git clone), you'll need Autotools:
sudo apt-get install autotools-dev autoconf automake libtool
FreeBSD:
---------
On FreeBSD you will need to install GNU make, libiconv, and
optionally Fox-Toolkit (for the test GUI). This is done by running
the following:
pkg_add -r gmake libiconv fox16
If you downloaded the source directly from the git repository (using
git clone), you'll need Autotools:
pkg_add -r autotools
Mac:
-----
On Mac, you will need to install Fox-Toolkit if you wish to build
the Test GUI. There are two ways to do this, and each has a slight
complication. Which method you use depends on your use case.
If you wish to build the Test GUI just for your own testing on your
own computer, then the easiest method is to install Fox-Toolkit
using ports:
sudo port install fox
If you wish to build the TestGUI app bundle to redistribute to
others, you will need to install Fox-toolkit from source. This is
because the version of fox that gets installed using ports uses the
ports X11 libraries which are not compatible with the Apple X11
libraries. If you install Fox with ports and then try to distribute
your built app bundle, it will simply fail to run on other systems.
To install Fox-Toolkit manually, download the source package from
http://www.fox-toolkit.org, extract it, and run the following from
within the extracted source:
./configure && make && make install
Windows:
---------
On Windows, if you want to build the test GUI, you will need to get
the hidapi-externals.zip package from the download site. This
contains pre-built binaries for Fox-toolkit. Extract
hidapi-externals.zip just outside of hidapi, so that
hidapi-externals and hidapi are on the same level, as shown:
Parent_Folder
|
+hidapi
+hidapi-externals
Again, this step is not required if you do not wish to build the
test GUI.
Building HIDAPI into a shared library on Unix Platforms:
---------------------------------------------------------
On Unix-like systems such as Linux, FreeBSD, Mac, and even Windows, using
Mingw or Cygwin, the easiest way to build a standard system-installed shared
library is to use the GNU Autotools build system. If you checked out the
source from the git repository, run the following:
./bootstrap
./configure
make
make install <----- as root, or using sudo
If you downloaded a source package (ie: if you did not run git clone), you
can skip the ./bootstrap step.
./configure can take several arguments which control the build. The two most
likely to be used are:
--enable-testgui
Enable build of the Test GUI. This requires Fox toolkit to
be installed. Instructions for installing Fox-Toolkit on
each platform are in the Prerequisites section above.
--prefix=/usr
Specify where you want the output headers and libraries to
be installed. The example above will put the headers in
/usr/include and the binaries in /usr/lib. The default is to
install into /usr/local which is fine on most systems.
Building the manual way on Unix platforms:
-------------------------------------------
Manual Makefiles are provided mostly to give the user and idea what it takes
to build a program which embeds HIDAPI directly inside of it. These should
really be used as examples only. If you want to build a system-wide shared
library, use the Autotools method described above.
To build HIDAPI using the manual makefiles, change to the directory
of your platform and run make. For example, on Linux run:
cd linux/
make -f Makefile-manual
To build the Test GUI using the manual makefiles:
cd testgui/
make -f Makefile-manual
Building on Windows:
---------------------
To build the HIDAPI DLL on Windows using Visual Studio, build the .sln file
in the windows/ directory.
To build the Test GUI on windows using Visual Studio, build the .sln file in
the testgui/ directory.
To build HIDAPI using MinGW or Cygwin using Autotools, use the instructions
in the section titled "Building HIDAPI into a shared library on Unix
Platforms" above. Note that building the Test GUI with MinGW or Cygwin will
require the Windows procedure in the Prerequisites section above (ie:
hidapi-externals.zip).
To build HIDAPI using MinGW using the Manual Makefiles, see the section
"Building the manual way on Unix platforms" above.
HIDAPI can also be built using the Windows DDK (now also called the Windows
Driver Kit or WDK). This method was originally required for the HIDAPI build
but not anymore. However, some users still prefer this method. It is not as
well supported anymore but should still work. Patches are welcome if it does
not. To build using the DDK:
1. Install the Windows Driver Kit (WDK) from Microsoft.
2. From the Start menu, in the Windows Driver Kits folder, select Build
Environments, then your operating system, then the x86 Free Build
Environment (or one that is appropriate for your system).
3. From the console, change directory to the windows/ddk_build/ directory,
which is part of the HIDAPI distribution.
4. Type build.
5. You can find the output files (DLL and LIB) in a subdirectory created
by the build system which is appropriate for your environment. On
Windows XP, this directory is objfre_wxp_x86/i386.
Cross Compiling
================
This section talks about cross compiling HIDAPI for Linux using autotools.
This is useful for using HIDAPI on embedded Linux targets. These
instructions assume the most raw kind of embedded Linux build, where all
prerequisites will need to be built first. This process will of course vary
based on your embedded Linux build system if you are using one, such as
OpenEmbedded or Buildroot.
For the purpose of this section, it will be assumed that the following
environment variables are exported.
$ export STAGING=$HOME/out
$ export HOST=arm-linux
STAGING and HOST can be modified to suit your setup.
Prerequisites
--------------
Note that the build of libudev is the very basic configuration.
Build Libusb. From the libusb source directory, run:
./configure --host=$HOST --prefix=$STAGING
make
make install
Build libudev. From the libudev source directory, run:
./configure --disable-gudev --disable-introspection --disable-hwdb \
--host=$HOST --prefix=$STAGING
make
make install
Building HIDAPI
----------------
Build HIDAPI:
PKG_CONFIG_DIR= \
PKG_CONFIG_LIBDIR=$STAGING/lib/pkgconfig:$STAGING/share/pkgconfig \
PKG_CONFIG_SYSROOT_DIR=$STAGING \
./configure --host=$HOST --prefix=$STAGING
Signal 11 Software - 2010-04-11
2010-07-28
2011-09-10
2012-05-01
2012-07-03
/*******************************
Mac support for HID Test GUI
Alan Ott
Signal 11 Software
Some of this code is from Apple Documentation, most notably
http://developer.apple.com/legacy/mac/library/documentation/AppleScript/Conceptual/AppleEvents/AppleEvents.pdf
*******************************/
#include <Carbon/Carbon.h>
#include <fx.h>
extern FXMainWindow *g_main_window;
static pascal OSErr HandleQuitMessage(const AppleEvent *theAppleEvent, AppleEvent
*reply, long handlerRefcon)
{
puts("Quitting\n");
FXApp::instance()->exit();
return 0;
}
static pascal OSErr HandleReopenMessage(const AppleEvent *theAppleEvent, AppleEvent
*reply, long handlerRefcon)
{
puts("Showing");
g_main_window->show();
return 0;
}
static pascal OSErr HandleWildCardMessage(const AppleEvent *theAppleEvent, AppleEvent
*reply, long handlerRefcon)
{
puts("WildCard\n");
return 0;
}
OSStatus AEHandler(EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon)
{
Boolean release = false;
EventRecord eventRecord;
OSErr ignoreErrForThisSample;
// Events of type kEventAppleEvent must be removed from the queue
// before being passed to AEProcessAppleEvent.
if (IsEventInQueue(GetMainEventQueue(), inEvent))
{
// RemoveEventFromQueue will release the event, which will
// destroy it if we don't retain it first.
RetainEvent(inEvent);
release = true;
RemoveEventFromQueue(GetMainEventQueue(), inEvent);
}
// Convert the event ref to the type AEProcessAppleEvent expects.
ConvertEventRefToEventRecord(inEvent, &eventRecord);
ignoreErrForThisSample = AEProcessAppleEvent(&eventRecord);
if (release)
ReleaseEvent(inEvent);
// This Carbon event has been handled, even if no AppleEvent handlers
// were installed for the Apple event.
return noErr;
}
static void HandleEvent(EventRecord *event)
{
//printf("What: %d message %x\n", event->what, event->message);
if (event->what == osEvt) {
if (((event->message >> 24) & 0xff) == suspendResumeMessage) {
if (event->message & resumeFlag) {
g_main_window->show();
}
}
}
#if 0
switch (event->what)
{
case mouseDown:
//HandleMouseDown(event);
break;
case keyDown:
case autoKey:
//HandleKeyPress(event);
break;
case kHighLevelEvent:
puts("Calling ProcessAppleEvent\n");
AEProcessAppleEvent(event);
break;
}
#endif
}
void
init_apple_message_system()
{
OSErr err;
static const EventTypeSpec appleEvents[] =
{
{ kEventClassAppleEvent, kEventAppleEvent }
};
/* Install the handler for Apple Events */
InstallApplicationEventHandler(NewEventHandlerUPP(AEHandler),
GetEventTypeCount(appleEvents), appleEvents, 0, NULL);
/* Install handlers for the individual Apple Events that come
from the Dock icon: the Reopen (click), and the Quit messages. */
err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
NewAEEventHandlerUPP(HandleQuitMessage), 0, false);
err = AEInstallEventHandler(kCoreEventClass, kAEReopenApplication,
NewAEEventHandlerUPP(HandleReopenMessage), 0, false);
#if 0
// Left as an example of a wild card match.
err = AEInstallEventHandler(kCoreEventClass, typeWildCard,
NewAEEventHandlerUPP(HandleWildMessage), 0, false);
#endif
}
void
check_apple_events()
{
RgnHandle cursorRgn = NULL;
Boolean gotEvent=TRUE;
EventRecord event;
while (gotEvent) {
gotEvent = WaitNextEvent(everyEvent, &event, 0L/*timeout*/, cursorRgn);
if (gotEvent) {
HandleEvent(&event);
}
}
}
#!/bin/bash
xterm -e /Users/alan/work/hidapi/testgui/TestGUI.app/Contents/MacOS/tg

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet