mirror of
https://github.com/Lorenzooone/cc3dsfs.git
synced 2026-03-22 02:06:22 -05:00
Some checks failed
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:linux32 flags:32 name:Linux GCC 32 os:ubuntu-latest]) (push) Has been cancelled
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:linux64 flags:64 name:Linux GCC x64 os:ubuntu-latest]) (push) Has been cancelled
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:linuxarm32 flags:arm32 name:Linux GCC ARM 32 os:ubuntu-latest]) (push) Has been cancelled
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:linuxarm64 flags:arm64 name:Linux GCC ARM 64 os:ubuntu-latest]) (push) Has been cancelled
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:macos name:macOS Apple Silicon os:macos-14]) (push) Has been cancelled
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:win32 flags:-A Win32 name:Windows VS2022 Win32 os:windows-2022]) (push) Has been cancelled
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:win64 flags:-A x64 name:Windows VS2022 x64 os:windows-2022]) (push) Has been cancelled
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:winarm64 flags:-A ARM64 name:Windows VS2022 ARM os:windows-2022]) (push) Has been cancelled
CD / Create Pi Mono Setup (push) Has been cancelled
CD / Publishing (push) Has been cancelled
446 lines
16 KiB
C++
446 lines
16 KiB
C++
#include "dscapture_ftd2_libusb_comms.hpp"
|
|
#include "dscapture_ftd2_general.hpp"
|
|
#include "dscapture_ftd2_compatibility.hpp"
|
|
#include "devicecapture.hpp"
|
|
#include "usb_generic.hpp"
|
|
|
|
#include <cstring>
|
|
#include <thread>
|
|
#include <chrono>
|
|
#include <iostream>
|
|
|
|
#define MANUFACTURER_SIZE 128
|
|
#define DESCRIPTION_SIZE 128
|
|
#define SERIAL_NUMBER_SIZE 128
|
|
|
|
#define FTDI_VID 0x0403
|
|
#define FT232H_PID 0x6014
|
|
|
|
#define DEFAULT_INTERFACE 0
|
|
#define DEFAULT_CONFIGURATION 1
|
|
|
|
#define DEFAULT_EP_IN 2
|
|
#define DEFAULT_EP_OUT 0x81
|
|
|
|
struct ftd2_libusb_handle_data {
|
|
libusb_device_handle *usb_handle = NULL;
|
|
int timeout_r_ms = 500;
|
|
int timeout_w_ms = 500;
|
|
int ep_in = 0x81;
|
|
int ep_out = 2;
|
|
int chip_index = 1;
|
|
};
|
|
|
|
struct vid_pid_descriptor {
|
|
int vid;
|
|
int pid;
|
|
};
|
|
|
|
static const vid_pid_descriptor base_device = {
|
|
.vid = FTDI_VID, .pid = FT232H_PID
|
|
};
|
|
|
|
static const vid_pid_descriptor* accepted_devices[] = {
|
|
&base_device,
|
|
};
|
|
|
|
static const vid_pid_descriptor* get_device_descriptor(int vid, int pid) {
|
|
for(size_t i = 0; i < sizeof(accepted_devices) / sizeof(*accepted_devices); i++)
|
|
if((vid == accepted_devices[i]->vid) && (pid == accepted_devices[i]->pid))
|
|
return accepted_devices[i];
|
|
return NULL;
|
|
}
|
|
|
|
void ftd2_libusb_init() {
|
|
return usb_init();
|
|
}
|
|
|
|
void ftd2_libusb_end() {
|
|
usb_close();
|
|
}
|
|
|
|
static int read_strings(libusb_device_handle *handle, libusb_device_descriptor *usb_descriptor, char* manufacturer, char* description, char* serial) {
|
|
manufacturer[0] = 0;
|
|
description[0] = 0;
|
|
serial[0] = 0;
|
|
int result = libusb_get_string_descriptor_ascii(handle, usb_descriptor->iManufacturer, (uint8_t*)manufacturer, MANUFACTURER_SIZE);
|
|
if(result < 0)
|
|
return result;
|
|
result = libusb_get_string_descriptor_ascii(handle, usb_descriptor->iProduct, (uint8_t*)description, DESCRIPTION_SIZE);
|
|
if(result < 0)
|
|
return result;
|
|
result = libusb_get_string_descriptor_ascii(handle, usb_descriptor->iSerialNumber, (uint8_t*)serial, SERIAL_NUMBER_SIZE);
|
|
if(result < 0)
|
|
return result;
|
|
manufacturer[MANUFACTURER_SIZE - 1] = 0;
|
|
description[DESCRIPTION_SIZE - 1] = 0;
|
|
serial[SERIAL_NUMBER_SIZE - 1] = 0;
|
|
return 0;
|
|
}
|
|
|
|
static void close_handle_ftd2_libusb(libusb_device_handle *dev_handle, bool claimed) {
|
|
if(dev_handle == NULL)
|
|
return;
|
|
if(claimed)
|
|
libusb_release_interface(dev_handle, DEFAULT_INTERFACE);
|
|
libusb_close(dev_handle);
|
|
}
|
|
|
|
static int init_handle_and_populate_device_info_ftd2_libusb(libusb_device_handle **dev_handle, libusb_device* dev, char* description, char* SerialNumber, const vid_pid_descriptor** curr_descriptor) {
|
|
char manufacturer[MANUFACTURER_SIZE];
|
|
libusb_device_descriptor desc = {0};
|
|
int retval = libusb_get_device_descriptor(dev, &desc);
|
|
if(retval < 0)
|
|
return retval;
|
|
*curr_descriptor = NULL;
|
|
*curr_descriptor = get_device_descriptor(desc.idVendor, desc.idProduct);
|
|
if((desc.bcdUSB < 0x0200) || ((*curr_descriptor) == NULL))
|
|
return LIBUSB_ERROR_OTHER;
|
|
|
|
retval = libusb_open(dev, dev_handle);
|
|
if(retval || ((*dev_handle) == NULL))
|
|
return retval;
|
|
retval = read_strings(*dev_handle, &desc, manufacturer, description, SerialNumber);
|
|
if(retval < 0) {
|
|
close_handle_ftd2_libusb(*dev_handle, false);
|
|
return retval;
|
|
}
|
|
libusb_check_and_detach_kernel_driver(*dev_handle, DEFAULT_INTERFACE);
|
|
retval = libusb_check_and_set_configuration(*dev_handle, DEFAULT_CONFIGURATION);
|
|
if(retval != LIBUSB_SUCCESS)
|
|
return retval;
|
|
libusb_check_and_detach_kernel_driver(*dev_handle, DEFAULT_INTERFACE);
|
|
retval = libusb_claim_interface(*dev_handle, DEFAULT_INTERFACE);
|
|
if(retval != LIBUSB_SUCCESS) {
|
|
close_handle_ftd2_libusb(*dev_handle, false);
|
|
return retval;
|
|
}
|
|
return LIBUSB_SUCCESS;
|
|
}
|
|
|
|
static int check_single_device_valid_ftd2_libusb(libusb_device* dev, char* description, char* SerialNumber, const vid_pid_descriptor** curr_descriptor) {
|
|
libusb_device_handle *dev_handle = NULL;
|
|
int retval = init_handle_and_populate_device_info_ftd2_libusb(&dev_handle, dev, description, SerialNumber, curr_descriptor);
|
|
if(retval != LIBUSB_SUCCESS)
|
|
return retval;
|
|
close_handle_ftd2_libusb(dev_handle, true);
|
|
return retval;
|
|
}
|
|
|
|
void list_devices_ftd2_libusb(std::vector<CaptureDevice> &devices_list, std::vector<no_access_recap_data> &no_access_list) {
|
|
if(!usb_is_initialized())
|
|
return;
|
|
libusb_device **usb_devices;
|
|
ssize_t num_devices = libusb_get_device_list(get_usb_ctx(), &usb_devices);
|
|
char description[DESCRIPTION_SIZE], SerialNumber[SERIAL_NUMBER_SIZE];
|
|
int debug_multiplier = 1;
|
|
bool insert_anyway = false;
|
|
bool perm_error = false;
|
|
const vid_pid_descriptor* curr_descriptor;
|
|
|
|
for(ssize_t i = 0; i < num_devices; i++) {
|
|
int retval = check_single_device_valid_ftd2_libusb(usb_devices[i], description, SerialNumber, &curr_descriptor);
|
|
if(retval < 0) {
|
|
if(retval == LIBUSB_ERROR_ACCESS)
|
|
perm_error = true;
|
|
continue;
|
|
}
|
|
std::string serial_number = std::string(SerialNumber);
|
|
bool is_already_inserted = false;
|
|
for(size_t j = 0; j < devices_list.size(); j++) {
|
|
if((devices_list[j].cc_type == CAPTURE_CONN_FTD2) && (devices_list[j].serial_number == serial_number)) {
|
|
is_already_inserted = true;
|
|
break;
|
|
}
|
|
}
|
|
if(is_already_inserted && (!insert_anyway))
|
|
continue;
|
|
insert_device_ftd2_shared(devices_list, description, debug_multiplier, serial_number, (void*)curr_descriptor, std::string(description), "l");
|
|
}
|
|
if(perm_error)
|
|
no_access_list.emplace_back("ftd2_libusb");
|
|
|
|
if(num_devices >= 0)
|
|
libusb_free_device_list(usb_devices, 1);
|
|
}
|
|
|
|
static int ftd2_libusb_ctrl_out(ftd2_libusb_handle_data* handle, uint8_t request, uint16_t value, uint16_t index, const uint8_t* data, size_t size) {
|
|
if(handle == NULL)
|
|
return -1;
|
|
if(handle->usb_handle == NULL)
|
|
return -1;
|
|
return libusb_control_transfer(handle->usb_handle, 0x40, request, value, index, (uint8_t*)data, (uint16_t)size, handle->timeout_w_ms);
|
|
}
|
|
|
|
static int ftd2_libusb_ctrl_in(ftd2_libusb_handle_data* handle, uint8_t request, uint16_t value, uint16_t index, uint8_t* data, size_t size) {
|
|
if(handle == NULL)
|
|
return -1;
|
|
if(handle->usb_handle == NULL)
|
|
return -1;
|
|
return libusb_control_transfer(handle->usb_handle, 0xC0, request, value, index, data, (uint16_t)size, handle->timeout_r_ms);
|
|
}
|
|
|
|
static int ftd2_libusb_ctrl_out_with_index(ftd2_libusb_handle_data* handle, uint8_t request, uint16_t value, uint16_t index, uint8_t* data, size_t size) {
|
|
if(handle == NULL)
|
|
return -1;
|
|
return ftd2_libusb_ctrl_out(handle, request, value, index | handle->chip_index, data, size);
|
|
}
|
|
|
|
static int ftd2_libusb_bulk_out(ftd2_libusb_handle_data* handle, const uint8_t* data, size_t size, int* transferred) {
|
|
if(handle == NULL)
|
|
return -1;
|
|
if(handle->usb_handle == NULL)
|
|
return -1;
|
|
return libusb_bulk_transfer(handle->usb_handle, handle->ep_out, (uint8_t*)data, (int)size, transferred, handle->timeout_w_ms);
|
|
}
|
|
|
|
static int ftd2_libusb_bulk_in(ftd2_libusb_handle_data* handle, uint8_t* data, size_t size, int* transferred) {
|
|
if(handle == NULL)
|
|
return -1;
|
|
if(handle->usb_handle == NULL)
|
|
return -1;
|
|
return libusb_bulk_transfer(handle->usb_handle, handle->ep_in, data, (int)size, transferred, handle->timeout_r_ms);
|
|
}
|
|
|
|
int ftd2_libusb_async_bulk_in_prepare_and_submit(void* handle, void* transfer_in, uint8_t* buffer_raw, size_t size, void* cb_fn, void* cb_data, int timeout_multiplier) {
|
|
ftd2_libusb_handle_data* in_handle = (ftd2_libusb_handle_data*)handle;
|
|
if(in_handle == NULL)
|
|
return -1;
|
|
if(in_handle->usb_handle == NULL)
|
|
return -1;
|
|
if(!transfer_in)
|
|
return -1;
|
|
libusb_transfer* transfer = (libusb_transfer*)transfer_in;
|
|
libusb_fill_bulk_transfer(transfer, in_handle->usb_handle, in_handle->ep_in, buffer_raw, (int)size, (libusb_transfer_cb_fn)cb_fn, cb_data, in_handle->timeout_r_ms * timeout_multiplier);
|
|
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
|
|
libusb_submit_transfer(transfer);
|
|
return 0;
|
|
}
|
|
|
|
int ftd2_libusb_reset(void* handle) {
|
|
return ftd2_libusb_ctrl_out_with_index((ftd2_libusb_handle_data*)handle, 0, 0, 0, NULL, 0);
|
|
}
|
|
|
|
int ftd2_libusb_set_latency_timer(void* handle, unsigned char latency) {
|
|
return ftd2_libusb_ctrl_out_with_index((ftd2_libusb_handle_data*)handle, 9, latency, 0, NULL, 0);
|
|
}
|
|
|
|
int ftd2_libusb_setflowctrl(void* handle, int flowctrl, unsigned char xon, unsigned char xoff) {
|
|
uint16_t value = 0;
|
|
if(flowctrl == FTD2_SIO_XON_XOFF_HS)
|
|
value = xon | (xoff << 8);
|
|
return ftd2_libusb_ctrl_out_with_index((ftd2_libusb_handle_data*)handle, 2, value, flowctrl, NULL, 0);
|
|
}
|
|
|
|
int ftd2_libusb_set_bitmode(void* handle, unsigned char bitmask, unsigned char mode) {
|
|
uint16_t value = bitmask | (mode << 8);
|
|
return ftd2_libusb_ctrl_out_with_index((ftd2_libusb_handle_data*)handle, 0xB, value, 0, NULL, 0);
|
|
}
|
|
|
|
int ftd2_libusb_purge(void* handle, bool do_read, bool do_write) {
|
|
int result = 0;
|
|
if(do_write)
|
|
result = ftd2_libusb_ctrl_out_with_index((ftd2_libusb_handle_data*)handle, 0, 1, 0, NULL, 0);
|
|
if(result < 0)
|
|
return result;
|
|
if(do_read)
|
|
result = ftd2_libusb_ctrl_out_with_index((ftd2_libusb_handle_data*)handle, 0, 2, 0, NULL, 0);
|
|
if(result < 0)
|
|
return result;
|
|
return 0;
|
|
}
|
|
|
|
int ftd2_libusb_read_eeprom(void* handle, int eeprom_addr, int *eeprom_val) {
|
|
uint8_t val[sizeof(uint16_t)];
|
|
int ret = ftd2_libusb_ctrl_in((ftd2_libusb_handle_data*)handle, 0x90, 0, eeprom_addr, val, sizeof(val));
|
|
*eeprom_val = read_le16(val, 0);
|
|
return ret;
|
|
}
|
|
|
|
int ftd2_libusb_set_chars(void* handle, unsigned char eventch, unsigned char event_enable, unsigned char errorch, unsigned char error_enable) {
|
|
if(event_enable)
|
|
event_enable = 1;
|
|
uint16_t value = eventch | (event_enable << 8);
|
|
int ret = ftd2_libusb_ctrl_out_with_index((ftd2_libusb_handle_data*)handle, 6, value, 0, NULL, 0);
|
|
if(ret < 0)
|
|
return ret;
|
|
if(error_enable)
|
|
error_enable = 1;
|
|
value = errorch | (error_enable << 8);
|
|
return ftd2_libusb_ctrl_out_with_index((ftd2_libusb_handle_data*)handle, 7, value, 0, NULL, 0);
|
|
}
|
|
|
|
int ftd2_libusb_set_usb_chunksizes(void* handle, unsigned int chunksize_in, unsigned int chunksize_out) {
|
|
return 0;
|
|
}
|
|
|
|
void ftd2_libusb_set_timeouts(void* handle, int timeout_in_ms, int timeout_out_ms) {
|
|
if(handle == NULL)
|
|
return;
|
|
ftd2_libusb_handle_data* in_handle = (ftd2_libusb_handle_data*)handle;
|
|
in_handle->timeout_r_ms = timeout_in_ms;
|
|
in_handle->timeout_w_ms = timeout_out_ms;
|
|
}
|
|
|
|
int ftd2_libusb_write(void* handle, const uint8_t* data, size_t size, size_t* bytesOut) {
|
|
int transferred = 0;
|
|
int result = ftd2_libusb_bulk_out((ftd2_libusb_handle_data*)handle, data, size, &transferred);
|
|
*bytesOut = transferred;
|
|
return result;
|
|
}
|
|
|
|
size_t ftd2_libusb_get_expanded_length(const int max_packet_size, size_t length, size_t header_packet_size) {
|
|
// Add the small headers every 512 bytes...
|
|
if(length == 0)
|
|
return header_packet_size;
|
|
return length + ((length + (max_packet_size - header_packet_size) - 1) / (max_packet_size - header_packet_size)) * header_packet_size;
|
|
}
|
|
|
|
size_t ftd2_libusb_get_expanded_length(size_t length) {
|
|
return ftd2_libusb_get_expanded_length(MAX_PACKET_SIZE_USB2, length, FTD2_INTRA_PACKET_HEADER_SIZE);
|
|
}
|
|
|
|
size_t ftd2_libusb_get_actual_length(const int max_packet_size, size_t length, size_t header_packet_size) {
|
|
// Remove the small headers every 512 bytes...
|
|
// The "- header_packet_size" instead of "-1" covers for partial header transfers...
|
|
int num_iters = (int)((length + max_packet_size - header_packet_size) / max_packet_size);
|
|
if(num_iters > 0)
|
|
length -= (num_iters * header_packet_size);
|
|
else
|
|
length = 0;
|
|
return length;
|
|
}
|
|
|
|
size_t ftd2_libusb_get_actual_length(size_t length) {
|
|
return ftd2_libusb_get_actual_length(MAX_PACKET_SIZE_USB2, length, FTD2_INTRA_PACKET_HEADER_SIZE);
|
|
}
|
|
|
|
void ftd2_libusb_copy_buffer_to_target(uint8_t* buffer_written, uint8_t* buffer_target, const int max_packet_size, size_t length, size_t header_packet_size) {
|
|
// Remove the small headers every 512 bytes...
|
|
// The "- header_packet_size" instead of "-1" covers for partial header transfers...
|
|
int num_iters = (int)((length + max_packet_size - header_packet_size) / max_packet_size);
|
|
if(num_iters <= 0)
|
|
return;
|
|
|
|
length -= (num_iters * header_packet_size);
|
|
const int real_packet_size = (int)(max_packet_size - header_packet_size);
|
|
for(int i = 0; i < num_iters; i++) {
|
|
int rem_size = (int)(length - (real_packet_size * i));
|
|
if(rem_size > real_packet_size)
|
|
rem_size = real_packet_size;
|
|
if(rem_size <= 0)
|
|
break;
|
|
memcpy(buffer_target + ((max_packet_size - header_packet_size) * i), buffer_written + header_packet_size + (max_packet_size * i), rem_size);
|
|
}
|
|
}
|
|
|
|
void ftd2_libusb_copy_buffer_to_target(uint8_t* buffer_written, uint8_t* buffer_target, size_t length) {
|
|
return ftd2_libusb_copy_buffer_to_target(buffer_written, buffer_target, MAX_PACKET_SIZE_USB2, length, FTD2_INTRA_PACKET_HEADER_SIZE);
|
|
}
|
|
|
|
// Read from bulk
|
|
static int ftd2_libusb_direct_read(void* handle, uint8_t* buffer_raw, uint8_t* buffer_normal, size_t length, size_t* transferred) {
|
|
length = ftd2_libusb_get_expanded_length(length);
|
|
int transferred_internal = 0;
|
|
int retval = ftd2_libusb_bulk_in((ftd2_libusb_handle_data*)handle, buffer_raw, length, &transferred_internal);
|
|
if(retval < 0)
|
|
return retval;
|
|
ftd2_libusb_copy_buffer_to_target(buffer_raw, buffer_normal, transferred_internal);
|
|
*transferred = ftd2_libusb_get_actual_length(transferred_internal);
|
|
return LIBUSB_SUCCESS;
|
|
}
|
|
|
|
int ftd2_libusb_read(void* handle, uint8_t* data, size_t size, size_t* bytesIn) {
|
|
size_t new_size = ftd2_libusb_get_expanded_length(size);
|
|
uint8_t* buffer_raw = new uint8_t[new_size];
|
|
int result = ftd2_libusb_direct_read(handle, buffer_raw, data, size, bytesIn);
|
|
delete []buffer_raw;
|
|
return result;
|
|
}
|
|
|
|
int ftd2_libusb_force_read_with_timeout(void* handle, uint8_t* buffer_raw, uint8_t* buffer_normal, size_t length, double timeout) {
|
|
size_t total_transferred = 0;
|
|
const auto start_time = std::chrono::high_resolution_clock::now();
|
|
while(total_transferred < length) {
|
|
size_t received = 0;
|
|
int retval = ftd2_libusb_direct_read(handle, buffer_raw, buffer_normal, length - total_transferred, &received);
|
|
if(ftd2_is_error(retval, true))
|
|
return retval;
|
|
total_transferred += received;
|
|
if(received == 0)
|
|
break;
|
|
const auto curr_time = std::chrono::high_resolution_clock::now();
|
|
const std::chrono::duration<double> diff = curr_time - start_time;
|
|
if(diff.count() > timeout)
|
|
return LIBUSB_ERROR_TIMEOUT;
|
|
}
|
|
return LIBUSB_SUCCESS;
|
|
}
|
|
|
|
int get_ftd2_libusb_read_queue_size(void* handle, size_t* bytesIn) {
|
|
uint8_t buffer[64];
|
|
*bytesIn = 0;
|
|
ftd2_libusb_handle_data* in_handle = (ftd2_libusb_handle_data*)handle;
|
|
int timeout_in_ms = in_handle->timeout_r_ms;
|
|
in_handle->timeout_r_ms = 0;
|
|
size_t curr_bytes_in = 0;
|
|
bool done = false;
|
|
int retval = 0;
|
|
while(!done) {
|
|
retval = ftd2_libusb_read(handle, buffer, 64, &curr_bytes_in);
|
|
if(retval <= 0)
|
|
done = true;
|
|
else
|
|
*bytesIn += curr_bytes_in;
|
|
}
|
|
in_handle->timeout_r_ms = timeout_in_ms;
|
|
return LIBUSB_SUCCESS;
|
|
}
|
|
|
|
int ftd2_libusb_open_serial(CaptureDevice* device, void** handle) {
|
|
if(!usb_is_initialized())
|
|
return LIBUSB_ERROR_OTHER;
|
|
|
|
*handle = NULL;
|
|
libusb_device **usb_devices;
|
|
ssize_t num_devices = libusb_get_device_list(get_usb_ctx(), &usb_devices);
|
|
char description[DESCRIPTION_SIZE], SerialNumber[SERIAL_NUMBER_SIZE];
|
|
const vid_pid_descriptor* curr_descriptor;
|
|
int ret = LIBUSB_ERROR_OTHER;
|
|
|
|
for(ssize_t i = 0; i < num_devices; i++) {
|
|
ftd2_libusb_handle_data out_handle;
|
|
int retval = init_handle_and_populate_device_info_ftd2_libusb(&out_handle.usb_handle, usb_devices[i], description, SerialNumber, &curr_descriptor);
|
|
if(retval != LIBUSB_SUCCESS)
|
|
continue;
|
|
if(curr_descriptor != ((const vid_pid_descriptor*)device->descriptor)) {
|
|
close_handle_ftd2_libusb(out_handle.usb_handle, true);
|
|
continue;
|
|
}
|
|
std::string serial_number = std::string(SerialNumber);
|
|
std::string desc = std::string(description);
|
|
if((serial_number != device->serial_number) || (desc != device->path)) {
|
|
close_handle_ftd2_libusb(out_handle.usb_handle, true);
|
|
continue;
|
|
}
|
|
ftd2_libusb_handle_data* final_handle = new ftd2_libusb_handle_data;
|
|
*final_handle = out_handle;
|
|
*handle = final_handle;
|
|
ret = LIBUSB_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
if(num_devices >= 0)
|
|
libusb_free_device_list(usb_devices, 1);
|
|
return ret;
|
|
}
|
|
|
|
int ftd2_libusb_close(void* handle) {
|
|
if(handle == NULL)
|
|
return LIBUSB_SUCCESS;
|
|
ftd2_libusb_handle_data* in_handle = (ftd2_libusb_handle_data*)handle;
|
|
close_handle_ftd2_libusb(in_handle->usb_handle, true);
|
|
delete in_handle;
|
|
return LIBUSB_SUCCESS;
|
|
}
|