diff --git a/include/nsysuhs/nsysuhs.dox b/include/nsysuhs/nsysuhs.dox new file mode 100644 index 0000000..358d8f2 --- /dev/null +++ b/include/nsysuhs/nsysuhs.dox @@ -0,0 +1,4 @@ +/** + * \defgroup nsysuhs nsysuhs + * + */ diff --git a/include/nsysuhs/uhs.h b/include/nsysuhs/uhs.h new file mode 100644 index 0000000..6530fd2 --- /dev/null +++ b/include/nsysuhs/uhs.h @@ -0,0 +1,245 @@ +#pragma once +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "uhs_usbspec.h" + +typedef struct UhsInterfaceFilter UhsInterfaceFilter; +typedef struct UhsInterfaceProfile UhsInterfaceProfile; +typedef struct UhsEndpointDescriptor UhsEndpointDescriptor; +typedef struct UhsHandle UhsHandle; +typedef struct UhsConfig UhsConfig; + +/* Determines which interface parameters to check */ +#define MATCH_ANY 0x000 +#define MATCH_DEV_VID 0x001 +#define MATCH_DEV_PID 0x002 +#define MATCH_DEV_CLASS 0x010 +#define MATCH_DEV_SUBCLASS 0x020 +#define MATCH_DEV_PROTOCOL 0x040 +#define MATCH_IF_CLASS 0x080 +#define MATCH_IF_SUBCLASS 0x100 +#define MATCH_IF_PROTOCOL 0x200 + +typedef enum UHSStatus +{ + UHS_STATUS_OK = 0, + UHS_STATUS_HANDLE_INVALID_ARGS = 0xffdefffd, + UHS_STATUS_HANDLE_INVALID_STATE = 0xffdefffc, +} UHSStatus; + +typedef enum UHSHandleState +{ + UHS_HANDLE_STATE_INIT = 0x00, + UHS_HANDLE_STATE_OPENING = 0x01, + UHS_HANDLE_STATE_OPENED = 0x02, + UHS_HANDLE_STATE_CLOSING = 0x03, + UHS_HANDLE_STATE_CLOSED = 0x04, + UHS_HANDLE_STATE_ERROR = 0x05, +} UHSHandleState; + +struct WUT_PACKED UhsConfig +{ + uint32_t controller_num; + void* buffer; + uint32_t buffer_size; +}; +WUT_CHECK_OFFSET(UhsConfig, 0x00, controller_num); +WUT_CHECK_OFFSET(UhsConfig, 0x04, buffer); +WUT_CHECK_OFFSET(UhsConfig, 0x08, buffer_size); +WUT_CHECK_SIZE(UhsConfig, 0x0C); + +struct WUT_PACKED UhsHandle +{ + UHSHandleState state; + void* ipc_buffer; + WUT_UNKNOWN_BYTES(4); /* always 0xFFFFFFFF after init */ + uint32_t handle; + UhsConfig * config; + WUT_UNKNOWN_BYTES(4); +}; +WUT_CHECK_OFFSET(UhsHandle, 0x00, state); +WUT_CHECK_OFFSET(UhsHandle, 0x04, ipc_buffer); +WUT_CHECK_OFFSET(UhsHandle, 0x0C, handle); +WUT_CHECK_OFFSET(UhsHandle, 0x10, config); +WUT_CHECK_SIZE(UhsHandle, 0x18); + +/* Endpoint transfer directions */ +#define ENDPOINT_TRANSFER_OUT 1 +#define ENDPOINT_TRANSFER_IN 2 + +/* Special timeout values */ +#define TIMEOUT_NONE -1 + +/* Interface filter */ +struct WUT_PACKED UhsInterfaceFilter +{ + uint16_t match_params; /* Bitmask of above flags */ + uint16_t vid; /* Vendor ID */ + uint16_t pid; /* Product ID */ + WUT_UNKNOWN_BYTES(4); + uint8_t dev_class; /* Device class */ + uint8_t dev_subclass; /* Device subclass */ + uint8_t dev_protocol; /* Device protocol */ + uint8_t if_class; /* Interface class */ + uint8_t if_subclass; /* Interface subclass */ + uint8_t if_protocol; /* Interface protocol */ +}; +WUT_CHECK_OFFSET(UhsInterfaceFilter, 0x00, match_params); +WUT_CHECK_OFFSET(UhsInterfaceFilter, 0x02, vid); +WUT_CHECK_OFFSET(UhsInterfaceFilter, 0x04, pid); +WUT_CHECK_OFFSET(UhsInterfaceFilter, 0x0A, dev_class); +WUT_CHECK_OFFSET(UhsInterfaceFilter, 0x0B, dev_subclass); +WUT_CHECK_OFFSET(UhsInterfaceFilter, 0x0C, dev_protocol); +WUT_CHECK_OFFSET(UhsInterfaceFilter, 0x0D, if_class); +WUT_CHECK_OFFSET(UhsInterfaceFilter, 0x0E, if_subclass); +WUT_CHECK_OFFSET(UhsInterfaceFilter, 0x0F, if_protocol); +WUT_CHECK_SIZE(UhsInterfaceFilter, 0x10); + + +/* Interface profile */ +struct WUT_PACKED UhsEndpointDescriptor +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint16_t wMaxPacketSize; + uint8_t bInterval; + WUT_UNKNOWN_BYTES(0x2); +}; +WUT_CHECK_OFFSET(UhsEndpointDescriptor, 0x00, bLength); +WUT_CHECK_OFFSET(UhsEndpointDescriptor, 0x01, bDescriptorType); +WUT_CHECK_OFFSET(UhsEndpointDescriptor, 0x02, bEndpointAddress); +WUT_CHECK_OFFSET(UhsEndpointDescriptor, 0x03, bmAttributes); +WUT_CHECK_OFFSET(UhsEndpointDescriptor, 0x04, wMaxPacketSize); +WUT_CHECK_OFFSET(UhsEndpointDescriptor, 0x06, bInterval); +WUT_CHECK_SIZE(UhsEndpointDescriptor, 0x09); + +/* Interface profile */ +struct WUT_PACKED UhsInterfaceProfile +{ + uint32_t if_handle; + WUT_UNKNOWN_BYTES(0x24); + UhsDeviceDescriptor dev_desc; + UhsConfigDescriptor cfg_desc; + UhsInterfaceDescriptor if_desc; + UhsEndpointDescriptor in_endpoints[16]; + UhsEndpointDescriptor out_endpoints[16]; +}; +WUT_CHECK_OFFSET(UhsInterfaceProfile, 0x00, if_handle); +WUT_CHECK_OFFSET(UhsInterfaceProfile, 0x28, dev_desc); +WUT_CHECK_OFFSET(UhsInterfaceProfile, 0x3A, cfg_desc); +WUT_CHECK_OFFSET(UhsInterfaceProfile, 0x43, if_desc); +WUT_CHECK_OFFSET(UhsInterfaceProfile, 0x4c, in_endpoints); +WUT_CHECK_OFFSET(UhsInterfaceProfile, 0xdc, out_endpoints); +WUT_CHECK_SIZE(UhsInterfaceProfile, 0x16C); + +/* Open a specific controller under /dev/uhs */ +UHSStatus UhsClientOpen(UhsHandle* handle, + UhsConfig* config); + +UHSStatus UhsClientClose(UhsHandle* handle); + +typedef void(*UHSDrvRegCallback)(void * context, UhsInterfaceProfile * profile); + +/* Register a USB class driver */ +UHSStatus +UhsClassDrvReg(UhsHandle* handle, + UhsInterfaceFilter *filter, + void *context, + UHSDrvRegCallback callback); + +UHSStatus UhsGetFullConfigDescriptor(UhsHandle* handle, + uint32_t if_handle, + void* data, + uint32_t size); + +/* Determine which USB device interfaces are plugged in and available */ +UHSStatus +UhsQueryInterfaces(UhsHandle* handle, + UhsInterfaceFilter *filter, + UhsInterfaceProfile *profiles, + int32_t max_profiles); + + +typedef void(*UhsAcquireInterfaceCallback)(void * context, int32_t arg1, int32_t arg2); + +/* Acquire a USB device interface for use */ +UHSStatus +UhsAcquireInterface(UhsHandle* handle, + uint32_t if_handle, + void * context, + UhsAcquireInterfaceCallback callback); + +/* Release a currently-held USB device interface */ +UHSStatus +UhsReleaseInterface(UhsHandle* handle, + uint32_t if_handle, + bool no_reacquire); + +/* Administer a USB device */ +UHSStatus +UhsAdministerDevice(UhsHandle* handle, + uint32_t if_handle, + int32_t arg2, + int32_t arg3); + +/* Submit a control request to endpoint 0 */ +UHSStatus +UhsSubmitControlRequest(UhsHandle* handle, + uint32_t if_handle, + void *buffer, + uint8_t bRequest, + uint8_t bmRequestType, + uint16_t wValue, + uint16_t wIndex, + uint16_t wLength, + int32_t timeout); + +/* Submit a bulk request to an endpoint */ +UHSStatus +UhsSubmitBulkRequest(UhsHandle* handle, + uint32_t if_handle, + uint8_t endpoint, + int32_t direction, + void *buffer, + int32_t length, + int32_t timeout); + +UHSStatus +UhsAdministerEndpoint(UhsHandle* handle, + uint32_t if_handle, + uint32_t u1, + uint32_t endpointMask, + int32_t u2, + uint32_t u3); + +static inline uint32_t UHSEndpointDirIsIn(UhsEndpointDescriptor * endpoint_descriptor){ + return ((endpoint_descriptor->bEndpointAddress & 0x80) == 0x80); +} + +static inline uint32_t UHSEndpointGetNum(UhsEndpointDescriptor * endpoint_descriptor){ + return (endpoint_descriptor->bEndpointAddress & 0x0F); +} + +static inline uint32_t UHSEndpointGetMask(UhsEndpointDescriptor * endpoint_descriptor){ + uint32_t endpoint_mask; + + if (UHSEndpointDirIsIn(endpoint_descriptor)) { + endpoint_mask = (1 << (UHSEndpointGetNum(endpoint_descriptor) + 16)); + } else { + endpoint_mask = (1 << UHSEndpointGetNum(endpoint_descriptor)); + } + return endpoint_mask; +} + +#ifdef __cplusplus +} +#endif + +/** @} */ \ No newline at end of file diff --git a/include/nsysuhs/uhs_usbspec.h b/include/nsysuhs/uhs_usbspec.h new file mode 100644 index 0000000..e149775 --- /dev/null +++ b/include/nsysuhs/uhs_usbspec.h @@ -0,0 +1,117 @@ +#pragma once +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* USB class codes */ +#define USBCLASS_DEVICE 0x00 +#define USBCLASS_AUDIO 0x01 +#define USBCLASS_HID 0x03 +#define USBCLASS_STORAGE 0x08 + +typedef struct UhsDeviceDescriptor UhsDeviceDescriptor; +typedef struct UhsConfigDescriptor UhsConfigDescriptor; +typedef struct UhsInterfaceDescriptor UhsInterfaceDescriptor; +typedef struct UhsSetupPacket UhsSetupPacket; + +/* USB device descriptor */ +struct WUT_PACKED UhsDeviceDescriptor +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdUsb; + uint8_t bDeviceClass; + uint8_t bDeviceSubclass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize; + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; + uint8_t bNumConfigurations; +}; +WUT_CHECK_OFFSET(UhsDeviceDescriptor, 0x00, bLength); +WUT_CHECK_OFFSET(UhsDeviceDescriptor, 0x01, bDescriptorType); +WUT_CHECK_OFFSET(UhsDeviceDescriptor, 0x02, bcdUsb); +WUT_CHECK_OFFSET(UhsDeviceDescriptor, 0x04, bDeviceClass); +WUT_CHECK_OFFSET(UhsDeviceDescriptor, 0x05, bDeviceSubclass); +WUT_CHECK_OFFSET(UhsDeviceDescriptor, 0x06, bDeviceProtocol); +WUT_CHECK_OFFSET(UhsDeviceDescriptor, 0x07, bMaxPacketSize); +WUT_CHECK_OFFSET(UhsDeviceDescriptor, 0x08, idVendor); +WUT_CHECK_OFFSET(UhsDeviceDescriptor, 0x0A, idProduct); +WUT_CHECK_OFFSET(UhsDeviceDescriptor, 0x0C, bcdDevice); +WUT_CHECK_OFFSET(UhsDeviceDescriptor, 0x0E, iManufacturer); +WUT_CHECK_OFFSET(UhsDeviceDescriptor, 0x0F, iProduct); +WUT_CHECK_OFFSET(UhsDeviceDescriptor, 0x10, iSerialNumber); +WUT_CHECK_OFFSET(UhsDeviceDescriptor, 0x11, bNumConfigurations); +WUT_CHECK_SIZE(UhsDeviceDescriptor, 0x12); + +/* USB configuration descriptor */ +struct WUT_PACKED UhsConfigDescriptor +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumInterfaces; + uint8_t bConfigurationValue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t bMaxPower; +}; +WUT_CHECK_OFFSET(UhsConfigDescriptor, 0x00, bLength); +WUT_CHECK_OFFSET(UhsConfigDescriptor, 0x01, bDescriptorType); +WUT_CHECK_OFFSET(UhsConfigDescriptor, 0x02, wTotalLength); +WUT_CHECK_OFFSET(UhsConfigDescriptor, 0x04, bNumInterfaces); +WUT_CHECK_OFFSET(UhsConfigDescriptor, 0x05, bConfigurationValue); +WUT_CHECK_OFFSET(UhsConfigDescriptor, 0x06, iConfiguration); +WUT_CHECK_OFFSET(UhsConfigDescriptor, 0x07, bmAttributes); +WUT_CHECK_OFFSET(UhsConfigDescriptor, 0x08, bMaxPower); +WUT_CHECK_SIZE(UhsConfigDescriptor, 0x09); + +/* USB interface descriptor */ +struct WUT_PACKED UhsInterfaceDescriptor +{ + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t bNumEndpoints; + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t iInterface; +}; +WUT_CHECK_OFFSET(UhsInterfaceDescriptor, 0x00, bLength); +WUT_CHECK_OFFSET(UhsInterfaceDescriptor, 0x01, bDescriptorType); +WUT_CHECK_OFFSET(UhsInterfaceDescriptor, 0x02, bInterfaceNumber); +WUT_CHECK_OFFSET(UhsInterfaceDescriptor, 0x03, bAlternateSetting); +WUT_CHECK_OFFSET(UhsInterfaceDescriptor, 0x04, bNumEndpoints); +WUT_CHECK_OFFSET(UhsInterfaceDescriptor, 0x05, bInterfaceClass); +WUT_CHECK_OFFSET(UhsInterfaceDescriptor, 0x06, bInterfaceSubClass); +WUT_CHECK_OFFSET(UhsInterfaceDescriptor, 0x07, bInterfaceProtocol); +WUT_CHECK_OFFSET(UhsInterfaceDescriptor, 0x08, iInterface); +WUT_CHECK_SIZE(UhsInterfaceDescriptor, 0x09); + +/* USB setup packet */ +struct WUT_PACKED UhsSetupPacket +{ + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +}; +WUT_CHECK_OFFSET(UhsSetupPacket, 0x00, bmRequestType); +WUT_CHECK_OFFSET(UhsSetupPacket, 0x01, bRequest); +WUT_CHECK_OFFSET(UhsSetupPacket, 0x02, wValue); +WUT_CHECK_OFFSET(UhsSetupPacket, 0x04, wIndex); +WUT_CHECK_OFFSET(UhsSetupPacket, 0x06, wLength); +WUT_CHECK_SIZE(UhsSetupPacket, 0x08); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/tests/test_compile_headers_common/test_compile_headers_list.h b/tests/test_compile_headers_common/test_compile_headers_list.h index 61391db..c3459e3 100644 --- a/tests/test_compile_headers_common/test_compile_headers_list.h +++ b/tests/test_compile_headers_common/test_compile_headers_list.h @@ -96,6 +96,7 @@ #include #include #include +#include #include #include #include