Switch from libusb to hidapi

Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
This commit is contained in:
TheJackiMonster 2023-04-30 12:59:34 +02:00
parent 15c2a03944
commit 72feaa60b3
No known key found for this signature in database
GPG key ID: D850A5F772E880F9
6 changed files with 114 additions and 332 deletions

1
.gitignore vendored
View file

@ -1,4 +1,5 @@
.idea/ .idea/
.cache/
cmake-build-debug/ cmake-build-debug/
cmake-build-release/ cmake-build-release/

View file

@ -3,9 +3,7 @@ project(nrealAirLibrary C)
set(CMAKE_C_STANDARD 17) set(CMAKE_C_STANDARD 17)
find_package(PkgConfig REQUIRED) find_package(hidapi REQUIRED)
pkg_search_module(LIBUSB1 REQUIRED libusb-1.0)
find_package(json-c REQUIRED) find_package(json-c REQUIRED)
add_library( add_library(
@ -20,11 +18,11 @@ target_include_directories(nrealAirLibrary
) )
target_include_directories(nrealAirLibrary target_include_directories(nrealAirLibrary
SYSTEM BEFORE PRIVATE ${FUSION_INCLUDE_DIR} ${LIBUSB1_INCLUDE_DIRS} SYSTEM BEFORE PRIVATE ${FUSION_INCLUDE_DIR}
) )
target_link_libraries(nrealAirLibrary target_link_libraries(nrealAirLibrary
${LIBUSB1_LIBRARIES} json-c::json-c ${FUSION_LIBRARY} m hidapi::hidapi json-c::json-c ${FUSION_LIBRARY} m
) )
set(NRA_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE) set(NRA_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include PARENT_SCOPE)

View file

@ -101,20 +101,8 @@ struct device3_t {
uint16_t vendor_id; uint16_t vendor_id;
uint16_t product_id; uint16_t product_id;
void* context;
void* handle; void* handle;
uint8_t interface_number;
uint8_t endpoint_address_in;
uint8_t max_packet_size_in;
uint8_t endpoint_address_out;
uint8_t max_packet_size_out;
bool detached;
bool claimed;
uint32_t static_id; uint32_t static_id;
uint64_t last_timestamp; uint64_t last_timestamp;

View file

@ -84,21 +84,9 @@ struct device4_t {
uint16_t vendor_id; uint16_t vendor_id;
uint16_t product_id; uint16_t product_id;
void* context;
void* handle; void* handle;
uint8_t interface_number;
uint8_t endpoint_address_in;
uint8_t max_packet_size_in;
uint8_t endpoint_address_out;
uint8_t max_packet_size_out;
bool detached;
bool claimed;
bool active; bool active;
uint8_t brightness; uint8_t brightness;
device4_event_callback callback; device4_event_callback callback;

View file

@ -29,9 +29,10 @@
#include <string.h> #include <string.h>
#include <Fusion/Fusion.h> #include <Fusion/Fusion.h>
#include <libusb-1.0/libusb.h>
#include <json-c/json.h> #include <json-c/json.h>
#include <hidapi/hidapi.h>
#include "crc32.h" #include "crc32.h"
struct device3_calibration_t { struct device3_calibration_t {
@ -53,27 +54,17 @@ struct device3_calibration_t {
FusionQuaternion noises; FusionQuaternion noises;
}; };
static bool send_payload(device3_type* device, uint8_t size, uint8_t* payload) { #define MAX_PACKET_SIZE 64
if (!device->claimed) {
return false;
}
static bool send_payload(device3_type* device, uint8_t size, const uint8_t* payload) {
int payload_size = size; int payload_size = size;
if (payload_size > device->max_packet_size_out) { if (payload_size > MAX_PACKET_SIZE) {
payload_size = device->max_packet_size_out; payload_size = MAX_PACKET_SIZE;
} }
int transferred = 0; int transferred = hid_write(device->handle, payload, payload_size);
int error = libusb_bulk_transfer(
device->handle,
device->endpoint_address_out,
payload,
payload_size,
&transferred,
0
);
if ((0 != error) || (transferred != payload_size)) { if (transferred != payload_size) {
perror("ERROR: sending payload failed\n"); perror("ERROR: sending payload failed\n");
return false; return false;
} }
@ -82,34 +73,22 @@ static bool send_payload(device3_type* device, uint8_t size, uint8_t* payload) {
} }
static bool recv_payload(device3_type* device, uint8_t size, uint8_t* payload) { static bool recv_payload(device3_type* device, uint8_t size, uint8_t* payload) {
if (!device->claimed) {
return false;
}
int payload_size = size; int payload_size = size;
if (payload_size > device->max_packet_size_in) { if (payload_size > MAX_PACKET_SIZE) {
payload_size = device->max_packet_size_in; payload_size = MAX_PACKET_SIZE;
} }
int transferred = 0; int transferred = hid_read(device->handle, payload, payload_size);
int error = libusb_bulk_transfer(
device->handle,
device->endpoint_address_in,
payload,
device->max_packet_size_in,
&transferred,
0
);
if (transferred >= payload_size) { if (transferred >= payload_size) {
transferred = payload_size; transferred = payload_size;
} }
if (error == LIBUSB_ERROR_TIMEOUT) { /*if (transferred == 0) {
return false; return false;
} }*/
if ((0 != error) || (transferred != payload_size)) { if (transferred != payload_size) {
perror("ERROR: receiving payload failed\n"); perror("ERROR: receiving payload failed\n");
return false; return false;
} }
@ -193,7 +172,7 @@ static FusionVector json_object_get_vector(struct json_object* obj) {
static FusionQuaternion json_object_get_quaternion(struct json_object* obj) { static FusionQuaternion json_object_get_quaternion(struct json_object* obj) {
if ((!json_object_is_type(obj, json_type_array)) || if ((!json_object_is_type(obj, json_type_array)) ||
(json_object_array_length(obj) != 3)) { (json_object_array_length(obj) != 4)) {
return FUSION_IDENTITY_QUATERNION; return FUSION_IDENTITY_QUATERNION;
} }
@ -218,89 +197,33 @@ device3_type* device3_open(device3_event_callback callback) {
device->product_id = 0x0424; device->product_id = 0x0424;
device->callback = callback; device->callback = callback;
if (0 != libusb_init((libusb_context**) &(device->context))) { if (0 != hid_init()) {
perror("No context!\n"); perror("Not initialized!\n");
return device; return device;
} }
device->handle = libusb_open_device_with_vid_pid( struct hid_device_info* info = hid_enumerate(
device->context,
device->vendor_id, device->vendor_id,
device->product_id device->product_id
); );
struct hid_device_info* it = info;
while (it) {
if (it->interface_number == 3) {
device->handle = hid_open_path(it->path);
break;
}
it = it->next;
}
hid_free_enumeration(info);
if (!device->handle) { if (!device->handle) {
perror("No handle!\n"); perror("No handle!\n");
return device; return device;
} }
libusb_device* dev = libusb_get_device(device->handle);
if (!dev) {
perror("No dev!\n");
return device;
}
struct libusb_device_descriptor desc;
if (0 != libusb_get_device_descriptor(dev, &desc)) {
perror("No desc!\n");
return device;
}
struct libusb_config_descriptor* config;
for (uint8_t i = 0; i < desc.bNumConfigurations; i++) {
if (0 != libusb_get_config_descriptor(dev, i, &config)) {
continue;
}
const struct libusb_interface* interface;
for (uint8_t j = 0; j < config->bNumInterfaces; j++) {
interface = &(config->interface[j]);
const struct libusb_interface_descriptor* setting;
for (int k = 0; k < interface->num_altsetting; k++) {
setting = &(interface->altsetting[k]);
if (LIBUSB_CLASS_HID != setting->bInterfaceClass) {
continue;
}
if (3 != setting->bInterfaceNumber) {
continue;
}
device->interface_number = setting->bInterfaceNumber;
if (2 != setting->bNumEndpoints) {
continue;
}
device->endpoint_address_in = setting->endpoint[0].bEndpointAddress;
device->max_packet_size_in = setting->endpoint[0].wMaxPacketSize;
device->endpoint_address_out = setting->endpoint[1].bEndpointAddress;
device->max_packet_size_out = setting->endpoint[1].wMaxPacketSize;
}
}
}
if (3 != device->interface_number) {
perror("No interface!\n");
return device;
}
if (1 == libusb_kernel_driver_active(device->handle, device->interface_number)) {
if (0 == libusb_detach_kernel_driver(device->handle, device->interface_number)) {
device->detached = true;
} else {
perror("Not detached!\n");
return device;
}
}
if (0 == libusb_claim_interface(device->handle, device->interface_number)) {
device->claimed = true;
}
if (!send_payload_msg(device, DEVICE3_MSG_GET_STATIC_ID, 0, NULL)) { if (!send_payload_msg(device, DEVICE3_MSG_GET_STATIC_ID, 0, NULL)) {
return device; return device;
} }
@ -688,18 +611,13 @@ int device3_calibrate(device3_type* device, uint32_t iterations, bool gyro, bool
return -1; return -1;
} }
if (!device->claimed) { if (MAX_PACKET_SIZE != sizeof(device3_packet_type)) {
perror("Not claimed!\n"); perror("Not proper size!\n");
return -2; return -2;
} }
if (device->max_packet_size_in != sizeof(device3_packet_type)) {
perror("Not proper size!\n");
return -3;
}
device3_packet_type packet; device3_packet_type packet;
int transferred, error; int transferred;
bool initialized = false; bool initialized = false;
@ -712,23 +630,19 @@ int device3_calibrate(device3_type* device, uint32_t iterations, bool gyro, bool
while (iterations > 0) { while (iterations > 0) {
memset(&packet, 0, sizeof(device3_packet_type)); memset(&packet, 0, sizeof(device3_packet_type));
transferred = 0; transferred = hid_read(
error = libusb_bulk_transfer(
device->handle, device->handle,
device->endpoint_address_in,
(uint8_t*) &packet, (uint8_t*) &packet,
device->max_packet_size_in, MAX_PACKET_SIZE
&transferred,
0
); );
if (error == LIBUSB_ERROR_TIMEOUT) { /*if (transferred == 0) {
continue; continue;
} }*/
if ((0 != error) || (device->max_packet_size_in != transferred)) { if (MAX_PACKET_SIZE != transferred) {
perror("Not expected issue!\n"); perror("Not expected issue!\n");
return -4; return -3;
} }
if ((packet.signature[0] != 0x01) || (packet.signature[1] != 0x02)) { if ((packet.signature[0] != 0x01) || (packet.signature[1] != 0x02)) {
@ -808,36 +722,27 @@ int device3_read(device3_type* device, int timeout) {
return -1; return -1;
} }
if (!device->claimed) { if (MAX_PACKET_SIZE != sizeof(device3_packet_type)) {
perror("Not claimed!\n");
return -2;
}
if (device->max_packet_size_in != sizeof(device3_packet_type)) {
perror("Not proper size!\n"); perror("Not proper size!\n");
return -3; return -2;
} }
device3_packet_type packet; device3_packet_type packet;
memset(&packet, 0, sizeof(device3_packet_type)); memset(&packet, 0, sizeof(device3_packet_type));
int transferred = 0; int transferred = hid_read(
int error = libusb_bulk_transfer(
device->handle, device->handle,
device->endpoint_address_in,
(uint8_t*) &packet, (uint8_t*) &packet,
device->max_packet_size_in, MAX_PACKET_SIZE
&transferred,
timeout
); );
if (error == LIBUSB_ERROR_TIMEOUT) { /*if (transferred == 0) {
return 1; return 1;
} }*/
if ((0 != error) || (device->max_packet_size_in != transferred)) { if (MAX_PACKET_SIZE != transferred) {
perror("Not expected issue!\n"); perror("Not expected issue!\n");
return -4; return -3;
} }
const uint64_t timestamp = packet.timestamp; const uint64_t timestamp = packet.timestamp;
@ -849,7 +754,7 @@ int device3_read(device3_type* device, int timeout) {
if ((packet.signature[0] != 0x01) || (packet.signature[1] != 0x02)) { if ((packet.signature[0] != 0x01) || (packet.signature[1] != 0x02)) {
perror("Not matching signature!\n"); perror("Not matching signature!\n");
return -5; return -4;
} }
const uint64_t delta = timestamp - device->last_timestamp; const uint64_t delta = timestamp - device->last_timestamp;
@ -942,25 +847,10 @@ void device3_close(device3_type* device) {
free(device->offset); free(device->offset);
} }
if ((device->claimed) &&
(0 == libusb_release_interface(device->handle, device->interface_number))) {
device->claimed = false;
}
if ((device->detached) &&
(0 == libusb_attach_kernel_driver(device->handle, device->interface_number))) {
device->detached = false;
}
if (device->handle) { if (device->handle) {
libusb_close(device->handle); hid_close(device->handle);
device->handle = NULL; device->handle = NULL;
} }
if (device->context) {
libusb_exit(device->context);
device->context = NULL;
}
free(device); free(device);
} }

View file

@ -28,7 +28,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <libusb-1.0/libusb.h> #include <hidapi/hidapi.h>
#define MAX_PACKET_SIZE 64
device4_type* device4_open(device4_event_callback callback) { device4_type* device4_open(device4_event_callback callback) {
device4_type* device = (device4_type*) malloc(sizeof(device4_type)); device4_type* device = (device4_type*) malloc(sizeof(device4_type));
@ -43,90 +45,33 @@ device4_type* device4_open(device4_event_callback callback) {
device->product_id = 0x0424; device->product_id = 0x0424;
device->callback = callback; device->callback = callback;
if (0 != libusb_init((libusb_context**) &(device->context))) { if (0 != hid_init()) {
perror("No context!\n"); perror("Not initialized!\n");
return device; return device;
} }
device->handle = libusb_open_device_with_vid_pid( struct hid_device_info* info = hid_enumerate(
device->context,
device->vendor_id, device->vendor_id,
device->product_id device->product_id
); );
struct hid_device_info* it = info;
while (it) {
if (it->interface_number == 3) {
device->handle = hid_open_path(it->path);
break;
}
it = it->next;
}
hid_free_enumeration(info);
if (!device->handle) { if (!device->handle) {
perror("No handle!\n"); perror("No handle!\n");
return device; return device;
} }
libusb_device* dev = libusb_get_device(device->handle);
if (!dev) {
perror("No dev!\n");
return device;
}
struct libusb_device_descriptor desc;
if (0 != libusb_get_device_descriptor(dev, &desc)) {
perror("No desc!\n");
return device;
}
struct libusb_config_descriptor* config;
for (uint8_t i = 0; i < desc.bNumConfigurations; i++) {
if (0 != libusb_get_config_descriptor(dev, i, &config)) {
continue;
}
const struct libusb_interface* interface;
for (uint8_t j = 0; j < config->bNumInterfaces; j++) {
interface = &(config->interface[j]);
const struct libusb_interface_descriptor* setting;
for (int k = 0; k < interface->num_altsetting; k++) {
setting = &(interface->altsetting[k]);
if (LIBUSB_CLASS_HID != setting->bInterfaceClass) {
continue;
}
if (4 != setting->bInterfaceNumber) {
continue;
}
device->interface_number = setting->bInterfaceNumber;
if (2 != setting->bNumEndpoints) {
continue;
}
device->endpoint_address_in = setting->endpoint[0].bEndpointAddress;
device->max_packet_size_in = setting->endpoint[0].wMaxPacketSize;
device->endpoint_address_out = setting->endpoint[1].bEndpointAddress;
device->max_packet_size_out = setting->endpoint[1].wMaxPacketSize;
}
}
}
if (4 != device->interface_number) {
perror("No interface!\n");
return device;
}
if (1 == libusb_kernel_driver_active(device->handle, device->interface_number)) {
if (0 == libusb_detach_kernel_driver(device->handle, device->interface_number)) {
device->detached = true;
} else {
perror("Not detached!\n");
return device;
}
}
if (0 == libusb_claim_interface(device->handle, device->interface_number)) {
device->claimed = true;
}
if (device->claimed) {
uint8_t initial_brightness_payload [16] = { uint8_t initial_brightness_payload [16] = {
0xfd, 0x1e, 0xb9, 0xf0, 0xfd, 0x1e, 0xb9, 0xf0,
0x68, 0x11, 0x00, 0x00, 0x68, 0x11, 0x00, 0x00,
@ -134,26 +79,21 @@ device4_type* device4_open(device4_event_callback callback) {
0x00, 0x00, 0x00, 0x03 0x00, 0x00, 0x00, 0x03
}; };
int size = device->max_packet_size_out; int size = MAX_PACKET_SIZE;
if (sizeof(initial_brightness_payload) < size) { if (sizeof(initial_brightness_payload) < size) {
size = sizeof(initial_brightness_payload); size = sizeof(initial_brightness_payload);
} }
int transferred = 0; int transferred = hid_write(
int error = libusb_bulk_transfer(
device->handle, device->handle,
device->endpoint_address_out,
initial_brightness_payload, initial_brightness_payload,
size, size
&transferred,
0
); );
if ((0 != error) || (transferred != sizeof(initial_brightness_payload))) { if (transferred != sizeof(initial_brightness_payload)) {
perror("ERROR\n"); perror("ERROR\n");
return device; return device;
} }
}
return device; return device;
} }
@ -179,36 +119,28 @@ int device4_read(device4_type* device, int timeout) {
return -1; return -1;
} }
if (!device->claimed) { if (MAX_PACKET_SIZE != sizeof(device4_packet_type)) {
perror("Not claimed!\n");
return -2;
}
if (device->max_packet_size_in != sizeof(device4_packet_type)) {
perror("Not proper size!\n"); perror("Not proper size!\n");
return -3; return -2;
} }
device4_packet_type packet; device4_packet_type packet;
memset(&packet, 0, sizeof(device4_packet_type)); memset(&packet, 0, sizeof(device4_packet_type));
int transferred = 0; int transferred = hid_read_timeout(
int error = libusb_bulk_transfer(
device->handle, device->handle,
device->endpoint_address_in,
(uint8_t*) &packet, (uint8_t*) &packet,
device->max_packet_size_in, MAX_PACKET_SIZE,
&transferred,
timeout timeout
); );
if (error == LIBUSB_ERROR_TIMEOUT) { /*if (transferred == 0) {
return 1; return 1;
} }*/
if ((0 != error) || (device->max_packet_size_in != transferred)) { if (MAX_PACKET_SIZE != transferred) {
perror("Not expected issue!\n"); perror("Not expected issue!\n");
return -4; return -3;
} }
const uint32_t timestamp = packet.timestamp; const uint32_t timestamp = packet.timestamp;
@ -328,25 +260,10 @@ void device4_close(device4_type* device) {
return; return;
} }
if ((device->claimed) &&
(0 == libusb_release_interface(device->handle, device->interface_number))) {
device->claimed = false;
}
if ((device->detached) &&
(0 == libusb_attach_kernel_driver(device->handle, device->interface_number))) {
device->detached = false;
}
if (device->handle) { if (device->handle) {
libusb_close(device->handle); hid_close(device->handle);
device->handle = NULL; device->handle = NULL;
} }
if (device->context) {
libusb_exit(device->context);
device->context = NULL;
}
free(device); free(device);
} }