/** * @file usb.h * @brief USB (usb:*) service IPC wrapper. * @author SciresM, yellows8 * @copyright libnx Authors */ #pragma once #include "../types.h" #include "../services/sm.h" #include "../kernel/event.h" /// usb:ds Switch-as-device<>host USB comms, see also here: https://switchbrew.org/wiki/USB_services /// Names starting with "libusb" were changed to "usb" to avoid collision with actual libusb if it's ever used. #define USBDS_DEFAULT_InterfaceNumber 0x4 ///Value for usb_interface_descriptor bInterfaceNumber for automatically allocating the actual bInterfaceNumber. /// Imported from libusb with changed names. /* Descriptor sizes per descriptor type */ #define USB_DT_INTERFACE_SIZE 9 #define USB_DT_ENDPOINT_SIZE 7 #define USB_DT_DEVICE_SIZE 0x12 #define USB_DT_SS_ENDPOINT_COMPANION_SIZE 6 /// Imported from libusb, with some adjustments. struct usb_endpoint_descriptor { uint8_t bLength; uint8_t bDescriptorType; ///< Must match USB_DT_ENDPOINT. uint8_t bEndpointAddress; ///< Should be one of the usb_endpoint_direction values, the endpoint-number is automatically allocated. uint8_t bmAttributes; uint16_t wMaxPacketSize; uint8_t bInterval; }; /// Imported from libusb, with some adjustments. struct usb_interface_descriptor { uint8_t bLength; uint8_t bDescriptorType; ///< Must match USB_DT_INTERFACE. uint8_t bInterfaceNumber; ///< See also USBDS_DEFAULT_InterfaceNumber. uint8_t bAlternateSetting; ///< Must match 0. uint8_t bNumEndpoints; uint8_t bInterfaceClass; uint8_t bInterfaceSubClass; uint8_t bInterfaceProtocol; uint8_t iInterface; ///< Ignored. }; /// Imported from libusb, with some adjustments. struct usb_device_descriptor { uint8_t bLength; uint8_t bDescriptorType; ///< Must match USB_DT_Device. uint16_t bcdUSB; uint8_t bDeviceClass; uint8_t bDeviceSubClass; uint8_t bDeviceProtocol; uint8_t bMaxPacketSize0; uint16_t idVendor; uint16_t idProduct; uint16_t bcdDevice; uint8_t iManufacturer; uint8_t iProduct; uint8_t iSerialNumber; uint8_t bNumConfigurations; }; /// Imported from libusb, with some adjustments. struct usb_ss_endpoint_companion_descriptor { uint8_t bLength; uint8_t bDescriptorType; ///< Must match USB_DT_SS_ENDPOINT_COMPANION. uint8_t bMaxBurst; uint8_t bmAttributes; uint16_t wBytesPerInterval; }; /// Imported from libusb, with some adjustments. struct usb_string_descriptor { uint8_t bLength; uint8_t bDescriptorType; ///< Must match USB_DT_STRING. uint16_t wData[0x40]; }; typedef struct { u16 idVendor; ///< VID u16 idProduct; ///< PID u16 bcdDevice; char Manufacturer[0x20]; char Product[0x20]; char SerialNumber[0x20]; } UsbDsDeviceInfo; typedef struct { u32 id; ///< urbId from post-buffer cmds u32 requestedSize; u32 transferredSize; u32 urb_status; } UsbDsReportEntry; typedef struct { UsbDsReportEntry report[8]; u32 report_count; } UsbDsReportData; typedef struct { bool initialized; u32 interface_index; Service h; Event SetupEvent; Event CtrlInCompletionEvent; Event CtrlOutCompletionEvent; } UsbDsInterface; typedef struct { bool initialized; Service h; Event CompletionEvent; } UsbDsEndpoint; typedef enum { UsbComplexId_Default = 0x2 } UsbComplexId; typedef enum { UsbDeviceSpeed_Full = 0x2, ///< USB 1.1 Full Speed UsbDeviceSpeed_High = 0x3, ///< USB 2.0 High Speed UsbDeviceSpeed_Super = 0x4, ///< USB 3.0 Super Speed } UsbDeviceSpeed; /// Imported from libusb, with changed names. enum usb_class_code { USB_CLASS_PER_INTERFACE = 0, USB_CLASS_AUDIO = 1, USB_CLASS_COMM = 2, USB_CLASS_HID = 3, USB_CLASS_PHYSICAL = 5, USB_CLASS_PRINTER = 7, USB_CLASS_PTP = 6, /* legacy name from libusb-0.1 usb.h */ USB_CLASS_IMAGE = 6, USB_CLASS_MASS_STORAGE = 8, USB_CLASS_HUB = 9, USB_CLASS_DATA = 10, USB_CLASS_SMART_CARD = 0x0b, USB_CLASS_CONTENT_SECURITY = 0x0d, USB_CLASS_VIDEO = 0x0e, USB_CLASS_PERSONAL_HEALTHCARE = 0x0f, USB_CLASS_DIAGNOSTIC_DEVICE = 0xdc, USB_CLASS_WIRELESS = 0xe0, USB_CLASS_APPLICATION = 0xfe, USB_CLASS_VENDOR_SPEC = 0xff }; /// Imported from libusb, with changed names. enum usb_descriptor_type { USB_DT_DEVICE = 0x01, USB_DT_CONFIG = 0x02, USB_DT_STRING = 0x03, USB_DT_INTERFACE = 0x04, USB_DT_ENDPOINT = 0x05, USB_DT_BOS = 0x0f, USB_DT_DEVICE_CAPABILITY = 0x10, USB_DT_HID = 0x21, USB_DT_REPORT = 0x22, USB_DT_PHYSICAL = 0x23, USB_DT_HUB = 0x29, USB_DT_SUPERSPEED_HUB = 0x2a, USB_DT_SS_ENDPOINT_COMPANION = 0x30 }; /// Imported from libusb, with changed names. enum usb_endpoint_direction { USB_ENDPOINT_IN = 0x80, USB_ENDPOINT_OUT = 0x00 }; /// Imported from libusb, with changed names. enum usb_transfer_type { USB_TRANSFER_TYPE_CONTROL = 0, USB_TRANSFER_TYPE_ISOCHRONOUS = 1, USB_TRANSFER_TYPE_BULK = 2, USB_TRANSFER_TYPE_INTERRUPT = 3, USB_TRANSFER_TYPE_BULK_STREAM = 4, }; /// Imported from libusb, with changed names. enum usb_iso_sync_type { USB_ISO_SYNC_TYPE_NONE = 0, USB_ISO_SYNC_TYPE_ASYNC = 1, USB_ISO_SYNC_TYPE_ADAPTIVE = 2, USB_ISO_SYNC_TYPE_SYNC = 3 }; /// Imported from libusb, with changed names. enum usb_iso_usage_type { USB_ISO_USAGE_TYPE_DATA = 0, USB_ISO_USAGE_TYPE_FEEDBACK = 1, USB_ISO_USAGE_TYPE_IMPLICIT = 2, }; /// Opens a session with usb:ds. Result usbDsInitialize(void); /// Closes the usb:ds session. Any interfaces/endpoints which are left open are automatically closed, since otherwise usb-sysmodule won't fully reset usb:ds to defaults. void usbDsExit(void); /// Helpers Result usbDsWaitReady(u64 timeout); Result usbDsParseReportData(UsbDsReportData *reportdata, u32 urbId, u32 *requestedSize, u32 *transferredSize); /// IDsService Event* usbDsGetStateChangeEvent(void); Result usbDsGetState(u32* out); /// Removed in 5.0.0 Result usbDsGetDsInterface(UsbDsInterface** out, struct usb_interface_descriptor* descriptor, const char* interface_name); Result usbDsSetVidPidBcd(const UsbDsDeviceInfo* deviceinfo); /// Added in 5.0.0 Result usbDsRegisterInterface(UsbDsInterface** out); Result usbDsRegisterInterfaceEx(UsbDsInterface** out, u32 intf_num); Result usbDsClearDeviceData(void); Result usbDsAddUsbStringDescriptor(u8* out_index, const char* string); Result usbDsAddUsbLanguageStringDescriptor(u8* out_index, const u16* lang_ids, u16 num_langs); Result usbDsDeleteUsbStringDescriptor(u8 index); Result usbDsSetUsbDeviceDescriptor(UsbDeviceSpeed speed, struct usb_device_descriptor* descriptor); Result usbDsSetBinaryObjectStore(void* bos, size_t bos_size); Result usbDsEnable(void); Result usbDsDisable(void); /// IDsInterface void usbDsInterface_Close(UsbDsInterface* interface); Result usbDsInterface_GetSetupPacket(UsbDsInterface* interface, void* buffer, size_t size); Result usbDsInterface_EnableInterface(UsbDsInterface* interface); Result usbDsInterface_DisableInterface(UsbDsInterface* interface); Result usbDsInterface_CtrlInPostBufferAsync(UsbDsInterface* interface, void* buffer, size_t size, u32* urbId); Result usbDsInterface_CtrlOutPostBufferAsync(UsbDsInterface* interface, void* buffer, size_t size, u32* urbId); Result usbDsInterface_GetCtrlInReportData(UsbDsInterface* interface, UsbDsReportData* out); Result usbDsInterface_GetCtrlOutReportData(UsbDsInterface* interface, UsbDsReportData* out); Result usbDsInterface_StallCtrl(UsbDsInterface* interface); /// Removed in 5.0.0 Result usbDsInterface_GetDsEndpoint(UsbDsInterface* interface, UsbDsEndpoint** endpoint, struct usb_endpoint_descriptor* descriptor); /// Added in 5.0.0 Result usbDsInterface_RegisterEndpoint(UsbDsInterface* interface, UsbDsEndpoint** endpoint, u8 endpoint_address); Result usbDsInterface_AppendConfigurationData(UsbDsInterface* interface, UsbDeviceSpeed speed, void* buffer, size_t size); /// IDsEndpoint void usbDsEndpoint_Close(UsbDsEndpoint* endpoint); Result usbDsEndpoint_Cancel(UsbDsEndpoint* endpoint); Result usbDsEndpoint_PostBufferAsync(UsbDsEndpoint* endpoint, void* buffer, size_t size, u32* urbId); Result usbDsEndpoint_GetReportData(UsbDsEndpoint* endpoint, UsbDsReportData* out); Result usbDsEndpoint_StallCtrl(UsbDsEndpoint* endpoint); Result usbDsEndpoint_SetZlt(UsbDsEndpoint* endpoint, bool zlt); // Sets Zero Length Termination for endpoint