Files
fluxengine/dep/libusbp/include/libusbp.h
2024-10-01 20:36:53 +02:00

713 lines
31 KiB
C

// Copyright (C) Pololu Corporation. See www.pololu.com for details.
/*! \file libusbp.h
*
* This header file provides the C API for libusbp.
*/
#pragma once
/*! The major component of libusbp's version number. In accordance with
* semantic versioning, this gets incremented every time there is a breaking
* change. */
#define LIBUSBP_VERSION_MAJOR 1
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef _WIN32
#include <wtypesbase.h>
#endif
#ifdef _WIN32
#define LIBUSBP_DLL_EXPORT __declspec(dllexport)
#define LIBUSBP_DLL_IMPORT __declspec(dllimport)
#else
#define LIBUSBP_DLL_IMPORT __attribute__((visibility("default")))
#define LIBUSBP_DLL_EXPORT __attribute__((visibility("default")))
#endif
#ifdef _MSC_VER
#define LIBUSBP_WARN_UNUSED _Check_return_
#else
#define LIBUSBP_WARN_UNUSED __attribute__((warn_unused_result))
#endif
#ifdef LIBUSBP_STATIC
#define LIBUSBP_API
#else
#ifdef LIBUSBP_EXPORTS
#define LIBUSBP_API LIBUSBP_DLL_EXPORT
#else
#define LIBUSBP_API LIBUSBP_DLL_IMPORT
#endif
#endif
/*! Some functions in this library return strings to the caller via a char
* ** argument. If the function call was successful, it is the caller's
* responsibility to free those strings by passing them to this function.
* Passing the NULL pointer to this function is OK. Do not pass any strings
* to this function unless they were previously returned by a call to this
* library. Do not free the same non-NULL string twice. */
LIBUSBP_API
void libusbp_string_free(char*);
/** libusbp_error
* **************************************************************/
/*! A libusbp_error object represents an error that occurred in the library.
* Many functions return a libusbp_error pointer as a return value. The
* convention is that a NULL pointer indicates success. If the pointer is
* not NULL, the caller needs to free it at some point by calling
* libusbp_error_free().
*
* NULL is a valid value for a libusbp_error pointer, and can be passed to
* any function in this library that takes a libusbp_error pointer. */
typedef struct libusbp_error libusbp_error;
/*! Each ::libusbp_error can have 0 or more error codes that give additional
* information about the error that might help the caller take the right
* action when the error occurs. This enum defines which error codes are
* possible. */
enum libusbp_error_code
{
/*! There were problems allocating memory. A memory shortage might be
* the root cause of the error, or there might be another error that is
* masked by the memory problems. */
LIBUSBP_ERROR_MEMORY = 1,
/*! It is possible that the error was caused by a temporary condition,
* such as the operating system taking some time to initialize drivers.
* Any function that could return this error will say so explicitly in
* its documentation so you do not have to worry about handling it in
* too many places. */
LIBUSBP_ERROR_NOT_READY = 2,
/*! Access was denied. A common cause of this error on Windows is that
* another application has a handle open to the same device. */
LIBUSBP_ERROR_ACCESS_DENIED = 3,
/*! The device does not have a serial number. */
LIBUSBP_ERROR_NO_SERIAL_NUMBER = 4,
/*! The device took too long to respond to a request or transfer data.
*/
LIBUSBP_ERROR_TIMEOUT = 5,
/*! The error might have been caused by the device being disconnected,
* but it is possible it was caused by something else. */
LIBUSBP_ERROR_DEVICE_DISCONNECTED = 6,
/*! The error might have been caused by the host receiving a STALL
* packet from the device, but it is possible it was caused by something
* else. */
LIBUSBP_ERROR_STALL = 7,
/*! The error might have been caused by the transfer getting cancelled
* from the host side. Some data might have been transferred anyway. */
LIBUSBP_ERROR_CANCELLED = 8,
};
/*! Attempts to copy an error. If you copy a NULL ::libusbp_error
* pointer, the result will also be NULL. If you copy a non-NULL
* ::libusbp_error pointer, the result will be non-NULL, but if there are
* issues allocating memory, then the copied error might have different
* properties than the original error, and it will have the
* ::LIBUSBP_ERROR_MEMORY code.
*
* It is the caller's responsibility to free the copied error. */
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error* libusbp_error_copy(
const libusbp_error*);
/*! Frees a returned error object. Passing the NULL pointer to this
* function is OK. Do not free the same non-NULL error twice. */
LIBUSBP_API
void libusbp_error_free(libusbp_error*);
/*! Returns true if the error has specified error code. The error codes are
* listed in the ::libusbp_error_code enum. */
LIBUSBP_API bool libusbp_error_has_code(
const libusbp_error*, uint32_t code);
/*! Returns an English-language ASCII-encoded string describing the error.
* The message consists of one or more sentences. If there are multiple
* sentences, the earlier ones will typically explain the context that the
* error happened in.
*
* The returned pointer will be valid until the error is freed, at which
* point it might become invalid. Do not pass the returned pointer to
* libusbp_string_free(). */
LIBUSBP_API const char* libusbp_error_get_message(const libusbp_error*);
/** libusbp_async_in_pipe
* ******************************************************/
/*! A libusbp_async_in_pipe is an object that holds the memory and other
* data structures for a set of asynchronous USB requests to read data from
* a non-zero endpoint. It can be used to read data from a bulk or IN
* endpoint with high throughput. */
typedef struct libusbp_async_in_pipe libusbp_async_in_pipe;
/*! Closes the pipe immediately. Note that if the pipe has any
* pending transfers, then it is possible that they cannot be freed
* by this function. Freeing a pipe with pending transfers could
* cause a memory leak, but is otherwise safe. */
LIBUSBP_API
void libusbp_async_in_pipe_close(libusbp_async_in_pipe*);
/*! Allocates buffers and other data structures for performing multiple
* concurrent transfers on the pipe.
*
* The @a transfer_count parameter specifies how many transfers to allocate.
* You can also think of this as the maximum number of concurrent transfers
* that can be active at the same time.
*
* The @a transfer_size parameter specifies how large each transfer's buffer
* should be, and is also the number of bytes that will be requested from
* the operating system when the transfer is submitted.
*
* It is best to set the transfer size to a multiple of the maximum packet
* size of the endpoint. Otherwise, you might get an error when the device
* sends more data than can fit in the transfer's buffer. This type of
* error is called an overflow.
*
* If you want to be reading the pipe every millisecond without gaps, you
* should set the transfer count high enough so that it would take about 100
* ms to 250 ms to finish all the transfers. As long as the operating
* system runs your process that often, you should be able to keep the USB
* host controller busy permanently. (Though we have observed gaps in the
* transfers when trying to do this inside a VirtualBox machine.)
*
* You should not set the transfer count too high, or else it might end up
* taking a long time to cancel the transfers when you are closing the pipe.
*/
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error*
libusbp_async_in_pipe_allocate_transfers(
libusbp_async_in_pipe*, size_t transfer_count, size_t transfer_size);
/*! Starts reading data from the pipe. */
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error*
libusbp_async_in_pipe_start_endless_transfers(libusbp_async_in_pipe*);
/*! Checks for new events, such as a transfer completing. This
* function and libusbp_async_in_pipe_handle_finished_transfer() should
* be called regularly in order to get data from the pipe. */
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error*
libusbp_async_in_pipe_handle_events(libusbp_async_in_pipe*);
/*! Retrieves a boolean saying whether there are any pending
* transfers. A pending transfer is a transfer that was submitted to
* the operating system, and it may have been completed, but it has
* not been passed to the caller yet via
* libusbp_async_in_pipe_handle_finished_transfer(). */
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error*
libusbp_async_in_pipe_has_pending_transfers(
libusbp_async_in_pipe*, bool* result);
/*! Checks to see if there is a finished transfer that can be handled.
* If there is one, then this function retrieves the data from the
* transfer, the number of bytes transferred, and any error that might
* have occurred related to the transfer.
*
* @param finished An optional output pointer used to return a pointer that
* indicates whether a transfer was finished. If the returned value is
* false, then no transfer was finished, and there is no transfer_error or
* data to handle.
*
* @param buffer An optional output pointer used to return the data
* from the transfer. The buffer must be at least as large as the
* transfer size specifed when
* libusbp_async_in_pipe_allocate_transfers was called.
*
* @param transferred An optional output pointer used to return the
* number of bytes transferred.
*
* @param transfer_error An optional pointer used to return an error
* related to the transfer, such as a timeout or a cancellation. If
* this pointer is provided, and a non-NULL error is returned via it,
* then the error must later be freed with libusbp_error_free(). There
* will never be a non-NULL transfer error if there is a regular error
* returned as the return value of this function. */
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error*
libusbp_async_in_pipe_handle_finished_transfer(libusbp_async_in_pipe*,
bool* finished,
void* buffer,
size_t* transferred,
libusbp_error** transfer_error);
/*! Cancels all the transfers for this pipe. The cancellation is
* asynchronous, so it won't have an immediate effect. If you want
* to actually make sure that all the transfers get cancelled, you
* will need to call libusbp_async_in_pipe_handle_events() and
* libusbp_async_in_pipe_handle_finished_transfer() repeatedly until
* libusbp_async_in_pipe_has_pending_transfers() indicates there are
* no pending transfers left. */
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error*
libusbp_async_in_pipe_cancel_transfers(libusbp_async_in_pipe*);
/** libusbp_device
* *************************************************************/
/*! Represents a single USB device. A composite device with multiple
* functions is represented by a single libusbp_device object.
*
* A NULL libusbp_device pointer is valid and can be passed to any function
* in this library that takes such pointers. */
typedef struct libusbp_device libusbp_device;
/*! Finds all the USB devices connected to the computer and returns a list
* of them.
*
* The optional @a device_count parameter is used to return the number of
* devices in the list. The list is actually one element larger because it
* ends with a NULL pointer.
*
* If this function is successful (the returned error pointer is NULL), then
* you must later free each device by calling libusbp_device_free() and free
* the list by calling libusbp_list_free(). The order in which the
* retrieved objects are freed does not matter. */
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error*
libusbp_list_connected_devices(
libusbp_device*** device_list, size_t* device_count);
/*! Frees a device list returned by libusbp_list_connected_device(). */
LIBUSBP_API
void libusbp_list_free(libusbp_device** list);
/*! Finds a device with the specified vendor ID and product ID and returns a
* pointer to it. If no device can be found, returns a NULL pointer. If
* the retrieved device pointer is not NULL, you must free it later by
* calling libusbp_device_free(). The retrieved device pointer will always
* be NULL if an error is returned. */
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error*
libusbp_find_device_with_vid_pid(
uint16_t vendor_id, uint16_t product_id, libusbp_device** device);
/*! Makes a copy of a device object. If this function is successful, you
* will need to free the copy by calling libusbp_device_free() at some
* point. */
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error* libusbp_device_copy(
const libusbp_device* source, libusbp_device** dest);
/*! Frees a device object. Passing a NULL pointer to this function is OK.
* Do not free the same non-NULL device twice. */
LIBUSBP_API void libusbp_device_free(libusbp_device*);
/*! Gets the USB vendor ID of the device (idVendor). */
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error* libusbp_device_get_vendor_id(
const libusbp_device*, uint16_t* vendor_id);
/*! Gets the USB product ID of the device (idProduct). */
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error*
libusbp_device_get_product_id(const libusbp_device*, uint16_t* product_id);
/*! Gets the USB revision code of the device (bcdDevice). */
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error* libusbp_device_get_revision(
const libusbp_device*, uint16_t* revision);
/*! Gets the serial number of the device as an ASCII-encoded string.
*
* On Windows, this just returns the segment of the Device Instance ID after
* the last slash. If the device does not have a serial number, it will
* return some other type of identifier that contains andpersands (&).
* Windows ignores serial numbers with invalid characters in them. For more
* information, see:
*
* https://msdn.microsoft.com/en-us/library/windows/hardware/dn423379#usbsn
*
* On other systems, if the device does not have a serial number, then this
* function returns an error with the code ::LIBUSBP_ERROR_NO_SERIAL_NUMBER.
*
* (Most applications should only call this function on specific USB devices
* that are already known to have serial numbers, in which case the lack of
* a serial number really does indicate a failure.)
*
* You should free the returned string by calling libusbp_string_free(). */
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error*
libusbp_device_get_serial_number(
const libusbp_device*, char** serial_number);
/*! Gets an operating system-specific string that identifies the device.
*
* Note that the level of specificity provided by the ID depends on the
* system you are on, and whether your device has a USB serial number. As
* long as the device remains connected to the bus, this ID is not expected
* to change and there should be no other devices that have the same ID.
* However, if the device gets disconnected from the bus, it may be possible
* for the ID to be reused by another device.
*
* @b Windows: This will be a device instance ID, and it will look something
* like this:
*
* <pre>
* USB\\VID_1FFB&PID_DA01\6&11A23516&18&0000
* </pre>
*
* If your device has a serial number, the part after the slash will be the
* serial number. Otherwise, it will be a string with andpersands in it.
*
* @b Linux: This will be a sysfs path, and it will look like something like
* this:
*
* <pre>
* /sys/devices/pci0000:00/0000:00:06.0/usb1/1-2
* </pre>
*
* <b>macOS:</b> This will be an integer from
* IORegistryEntryGetRegistryEntryID, formatted as a lower-case hex number
* with no leading zeros. It will look something like this:
*
* <pre>
* 10000021a
* </pre>
*/
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error* libusbp_device_get_os_id(
const libusbp_device*, char** id);
/** libusbp_generic_interface
* **************************************************/
/*! Represents a generic or vendor-defined interface of a USB device. A
* null libusbp_generic_interface pointer is valid and can be passed to any
* function in this library that takes such pointers. */
typedef struct libusbp_generic_interface libusbp_generic_interface;
/*! Creates a generic interface object for a specified interface of the
* specified USB device. This function does as many checks as possible to
* make sure that a handle to the interface could be opened, without
* actually opening it yet.
*
* On all platforms, if a record of the interface cannot be found, then an
* error is returned with the code LIBUSBP_ERROR_NOT_READY, because this
* could just be a temporary condition that happens right after the device
* is plugged in.
*
* On Windows, the generic interface must use the WinUSB driver, or this
* function will fail. If it is using no driver, that could be a temporary
* condition, and the error returned will use the LIBUSBP_ERROR_NOT_READY
* error code.
*
* On Linux, if the corresponding devnode file does not exist, an error with
* code LIBUSBP_ERROR_NOT_READY is returned. If the interface is assigned
* to a driver that is not "usbfs", an error is returned.
*
* On macOS, we do not have any additional checks beyond just making sure
* that an entry for the interface is found. For non-composite devices,
* that check is deferred until a handle is opened.
*
* @param interface_number The lowest @a bInterfaceNumber for the interfaces
* in the USB function you want to use.
*
* @param composite Should be true if the device is composite, and false
* otherwise.
*
* The returned object must be freed with libusbp_generic_interface_free().
*/
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error*
libusbp_generic_interface_create(const libusbp_device*,
uint8_t interface_number,
bool composite,
libusbp_generic_interface**);
/*! Frees the specified generic interface object. Passing the NULL pointer
* to this function is OK. Do not free the same non-NULL pointer twice. */
LIBUSBP_API void libusbp_generic_interface_free(libusbp_generic_interface*);
/*! Makes a copy of the generic interface object. The copy must be freed
* with libusbp_generic_interface_free(). */
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error*
libusbp_generic_interface_copy(const libusbp_generic_interface* source,
libusbp_generic_interface** dest);
/*! Returns an operating system-specific string that can be used to uniquely
* identify this generic interface.
*
* <b>Windows:</b> This will be a device instance ID specific to this
* interface, and it will look something like this:
*
* <pre>
* USB\\VID_1FFB&PID_DA01&MI_00\6&11A23516&18&0000
* </pre>
*
* <b>Linux:</b> This will be a sysfs path specific to this interface, and
* it will look like something like this:
*
* <pre>
* /sys/devices/pci0000:00/0000:00:06.0/usb1/1-2/1-2:1.0
* </pre>
*
* <b>macOS:</b> This will be an integer from
* IORegistryEntryGetRegistryEntryID, formatted as a lower-case hex number
* with no leading zeros. It will look something like this:
*
* <pre>
* 10000021a
* </pre>
*/
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error*
libusbp_generic_interface_get_os_id(
const libusbp_generic_interface*, char** id);
/*! Returns an operating system-specific filename corresponding to this
* interface.
*
* <b>Windows:</b> This will be the name of a file you can use with
* CreateFile to access the device, and it will look something like this:
*
* <pre>
* \\\\?\\usb#vid_1ffb&pid_da01&mi_00#6&11a23516&18&0000#{99c4bbb0-e925-4397-afee-981cd0702163}
* </pre>
*
* <b>Linux:</b> this will return a device node file name that represents
* the overall USB device. It will look something like:
*
* <pre>
* /dev/bus/usb/001/007
* </pre>
*
* <b>macOS:</b> This will be an integer from
* IORegistryEntryGetRegistryEntryID, formatted as a lower-case hex number
* with no leading zeros. It will look something like this:
*
* <pre>
* 10000021a
* </pre>
*/
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error*
libusbp_generic_interface_get_os_filename(
const libusbp_generic_interface*, char** filename);
/** libusbp_generic_handle
* *****************************************************/
/*! Represents a generic handle to a USB device. This handle can be used to
* perform operations such as control transfers and reading and writing data
* from non-zero endpoints.
*
* NULL is a valid value for a libusbp_generic_handle pointer, and can be
* passed in any functions of this library that take a
* libusbp_generic_handle pointer. */
typedef struct libusbp_generic_handle libusbp_generic_handle;
/*! Opens a generic handle to the specified interface of a USB device which
* can be used to perform USB I/O operations.
*
* The handle must later be closed with libusbp_generic_handle_close().
*
* On Windows, for devices using WinUSB, if another application has a handle
* open already when this function is called, then this function will fail
* and the returned error will have code ::LIBUSBP_ERROR_ACCESS_DENIED.
*
* On macOS, this function will set the device's configuration to 1 as a
* side effect in case it is not already configured. */
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error* libusbp_generic_handle_open(
const libusbp_generic_interface*, libusbp_generic_handle**);
/*! Closes and frees the specified generic handle. It is OK to pass NULL to
* this function. Do not close the same non-NULL handle twice. All
* ::libusbp_async_in_pipe objects created by the handle must be closed
* before closing the handle. */
LIBUSBP_API
void libusbp_generic_handle_close(libusbp_generic_handle*);
/*! Creates a new asynchronous pipe object for reading data in from the
* device on one of its bulk or interrupt IN endpoints.
*
* The behavior of this library is unspecified if you use both an
* asynchronous IN pipe and synchronous reads with libusbp_read_pipe() on
* the same pipe of the same generic handle. One reason for that is because
* for WinUSB devices, this function enables RAW_IO for the pipe, and it
* does not turn off RAW_IO again after the pipe is closed. So the behavior
* of libusbp_read_pipe() could change depending on whether an asynchronous
* IN pipe has been used. */
LIBUSBP_API
libusbp_error* libusbp_generic_handle_open_async_in_pipe(
libusbp_generic_handle*,
uint8_t pipe_id,
libusbp_async_in_pipe** async_in_pipe);
/*! Sets a timeout for a particular pipe on the USB device.
*
* The @a pipe_id should either be 0 to specify control transfers on
* endpoint 0, or should be a bEndpointAddress value from one of the
* device's endpoint descriptors. Specifying an invalid pipe might result
* in an error.
*
* The timeout value is specified in milliseconds, and a value of 0 means no
* timeout (wait forever). If this function is not called, the default
* behavior of the handle is to have no timeout.
*
* The behavior of this function is unspecified if there is any data being
* transferred on the pipe while this function is running.
*
* It is unspecified whether this timeout has an effect on asynchronous
* transfers. */
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error*
libusbp_generic_handle_set_timeout(
libusbp_generic_handle*, uint8_t pipe_id, uint32_t timeout);
/*! Performs a synchronous (blocking) control transfer on endpoint 0.
*
* Under Linux, this blocking transfer unfortunately cannot be interrupted
* with Ctrl+C.
*
* The @a buffer parameter should point to a buffer that is at least @a
* wLength bytes long.
*
* The @a transferred pointer is optional, and is used to return the number
* of bytes that were actually transferred.
*
* The direction of the transfer is determined by the @a bmRequestType
* parameter.
*/
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error* libusbp_control_transfer(
libusbp_generic_handle*,
uint8_t bmRequestType,
uint8_t bRequest,
uint16_t wValue,
uint16_t wIndex,
void* buffer,
uint16_t wLength,
size_t* transferred);
/*! Performs a synchronous (blocking) write of data to a bulk or interrupt
* endpoint.
*
* Under Linux, this blocking transfer unfortunately cannot be interrupted
* with Ctrl+C.
*
* The @a pipe_id parameter specifies which endpoint to use. This argument
* should be bEndpointAddress value from one of the device's IN endpoint
* descriptors. (Its most significant bit must be 0.)
*
* The @a transferred parameter is an optional pointer to a variable that
* will receive the number of bytes transferred. */
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error* libusbp_write_pipe(
libusbp_generic_handle*,
uint8_t pipe_id,
const void* buffer,
size_t size,
size_t* transferred);
/*! Performs a synchronous (blocking) read of data from a bulk or interrupt
* endpoint.
*
* It is best to set the buffer size to a multiple of the maximum
* packet size of the endpoint. Otherwise, this function might return
* an error when the device sends more data than can fit in the
* buffer. This type of error is called an overflow.
*
* Under Linux, this blocking transfer unfortunately cannot be interrupted
* with Ctrl+C.
*
* The @a pipe_id parameter specifies which endpoint to use. This argument
* should be bEndpointAddress value from one of the device's IN endpoint
* descriptors. (Its most significant bit must be 1.)
*
* The @a transferred parameter is an optional pointer to a variable that
* will receive the number of bytes transferred. */
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error* libusbp_read_pipe(
libusbp_generic_handle*,
uint8_t pipe_id,
void* buffer,
size_t size,
size_t* transferred);
#ifdef __linux__
/*! Gets the underlying file descriptor of the generic handle. This
* function is only available on Linux, and is intended for advanced users.
* The returned file descriptor will remain open and valid as long as the
* handle is open and has not been closed. */
LIBUSBP_API
int libusbp_generic_handle_get_fd(libusbp_generic_handle*);
#endif
#ifdef _WIN32
/*! Gets the underlying WinUSB handle for the generic handle. This function
* is only available on Windows, and is intended for advanced users. The
* returned WinUSB handle will remain open and valid as long as the generic
* handle is open and has not been closed. */
LIBUSBP_API
HANDLE libusbp_generic_handle_get_winusb_handle(libusbp_generic_handle*);
#endif
#ifdef __APPLE__
/*! Gets the underlying IOCFPlugInInterface object representing the
* interface. You can cast the returned pointer to a `IOCFPlugInInterface
* **` and then use `QueryInterface` to get the corresponding
* `IOUSBInterfaceInterface **`. There is an example of this in
* generic_handle_test.cpp. */
LIBUSBP_API
void** libusbp_generic_handle_get_cf_plug_in(libusbp_generic_handle*);
#endif
/** libusbp_serial_port
* ********************************************************/
/*! Represents a serial port. A null libusbp_serial_port pointer is valid
* and can be passed to any function in this library that takes such
* pointers. */
typedef struct libusbp_serial_port libusbp_serial_port;
/*! Creates a serial port object for a specified interface of the
* specified USB device.
*
* On all platforms, if a record of the interface cannot be found, then an
* error is returned with the code LIBUSBP_ERROR_NOT_READY, because this
* could just be a temporary condition that happens right after the device
* is plugged in.
*
* On macOS, it is assumed that the interface with a @a bInterfaceNumber one
* greater than @a interface_number is the interface that the
* IOSerialBSDClient will attach to. This should be true if the device
* implements the USB CDC ACM class and has ordered its interfaces so that
* the control interface is right before the data interface.
*
* @param interface_number The lowest @a bInterfaceNumber for the USB
* interfaces that comprise the serial port.
*
* @param composite Should be true if the device is composite, and false
* otherwise.
*
* The returned object must be freed with libusbp_generic_interface_free().
*/
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error* libusbp_serial_port_create(
const libusbp_device*,
uint8_t interface_number,
bool composite,
libusbp_serial_port**);
/*! Frees the specified serial port object. Passing the NULL pointer to
* this function is OK. Do not free the same non-NULL pointer twice. */
LIBUSBP_API void libusbp_serial_port_free(libusbp_serial_port*);
/*! Makes a copy of the generic interface object. The copy must be freed
* with libusbp_generic_interface_free(). */
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error* libusbp_serial_port_copy(
const libusbp_serial_port* source, libusbp_serial_port** dest);
/*! Gets the user-friendly name of the COM port
* that could be used to open a handle.
*
* On Windows, this will be something like "COM12".
*
* On Linux, it will be something like "/dev/ttyACM0".
*
* On macOS, it will be something like "/dev/cu.usbmodem012345".
* Specifically, it will be a call-out device, not a dial-in device.
*
* You should free the returned string by calling libusbp_string_free().
*/
LIBUSBP_API LIBUSBP_WARN_UNUSED libusbp_error* libusbp_serial_port_get_name(
const libusbp_serial_port*, char** name);
#ifdef __cplusplus
}
#endif