X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fdrv%2Fusb.h;h=4016864f0e9966f83d6ca5d36c428e76ce4bffd4;hb=933e092273b03ff625e037ff37b68f8ebea9aa79;hp=68af01362dd2d20c8d0dc1e2b8058963cfdf57dc;hpb=ea55bf87b5e954a4939dece9aec37e364da15b93;p=bertos.git diff --git a/bertos/drv/usb.h b/bertos/drv/usb.h index 68af0136..4016864f 100644 --- a/bertos/drv/usb.h +++ b/bertos/drv/usb.h @@ -37,6 +37,8 @@ * This file holds USB constants and structures that are needed for USB device * APIs, as defined in the USB 2.0 specification. * + * \attention The API is work in progress and may change in future versions. + * * $WIZ$ module_name = "usb" * $WIZ$ module_configuration = "bertos/cfg/cfg_usb.h" * $WIZ$ module_supports = "stm32" @@ -47,27 +49,10 @@ #include -/* - * Handle CPU endianess - * - * TODO: consider to move this stuff in compiler.h - */ -#define usb_bswap16(x) (((x & 0xff) << 8) | (x >> 8)) -#define usb_bswap32(x) ((usb_bswap16(x & 0xffff) << 16) | usb_bswap16(x >> 16)) - -#if CPU_BYTE_ORDER == CPU_LITTLE_ENDIAN -#define usb_cpu_to_le16(x) (x) -#define usb_le16_to_cpu(x) (x) -#define usb_cpu_to_le32(x) (x) -#define usb_le32_to_cpu(x) (x) -#elif CPU_BYTE_ORDER == CPU_BIG_ENDIAN -#define usb_cpu_to_le16(x) usb_bswap16(x) -#define usb_le16_to_cpu(x) usb_bswap16(x) -#define usb_cpu_to_le32(x) usb_bswap32(x) -#define usb_le32_to_cpu(x) usb_bswap32(x) -#else -#error "unrecognized CPU endianness" -#endif +#define usb_cpu_to_le16(x) cpu_to_le16(x) +#define usb_le16_to_cpu(x) le16_to_cpu(x) +#define usb_cpu_to_le32(x) cpu_to_le32(x) +#define usb_le32_to_cpu(x) le32_to_cpu(x) /* State of a USB device */ enum usb_device_state { @@ -89,6 +74,7 @@ enum usb_device_state { */ #define USB_DIR_OUT 0 /* to device */ #define USB_DIR_IN 0x80 /* to host */ +#define USB_DIR_MASK 0x80 /* * USB types, the second of three bRequestType fields @@ -146,29 +132,41 @@ enum usb_device_state { #define USB_DT_CS_INTERFACE (USB_TYPE_CLASS | USB_DT_INTERFACE) #define USB_DT_CS_ENDPOINT (USB_TYPE_CLASS | USB_DT_ENDPOINT) -/* +/** + * + * USB Control Request descriptor + * * This structure is used to send control requests to a USB device. * - * It matches the different fields of the USB 2.0 spec. section 9.3, table 9-2. + * It matches the different fields of the USB 2.0 specification (section 9.3, + * table 9-2). */ -typedef struct usb_ctrlrequest +typedef struct UsbCtrlRequest { uint8_t mRequestType; uint8_t bRequest; uint16_t wValue; uint16_t wIndex; uint16_t wLength; -} PACKED usb_ctrlrequest_t; +} PACKED UsbCtrlRequest; -/* All standard descriptors have these 2 fields at the beginning */ -typedef struct usb_descriptor_header +/** + * USB common descriptor header. + * + * \note All the USB standard descriptors have these 2 fields at the beginning. + */ +typedef struct UsbDescHeader { uint8_t bLength; uint8_t bDescriptorType; -} PACKED usb_descriptor_header_t; +} PACKED UsbDescHeader; -/* Device descriptor */ -typedef struct usb_device_descriptor +/** + * USB Device descriptor + * + * \note See USB 2.0 specification. + */ +typedef struct UsbDeviceDesc { uint8_t bLength; uint8_t bDescriptorType; @@ -184,21 +182,20 @@ typedef struct usb_device_descriptor uint8_t iProduct; uint8_t iSerialNumber; uint8_t bNumConfigurations; -} PACKED usb_device_descriptor_t; +} PACKED UsbDeviceDesc; -/* USB string descriptor */ -typedef struct usb_string_descriptor +/** + * USB string descriptor. + * + * \note See USB 2.0 specification. + */ +typedef struct UsbStringDesc { uint8_t bLength; uint8_t bDescriptorType; uint8_t data[0]; -} PACKED usb_string_descriptor_t; +} PACKED UsbStringDesc; -/* - * Macros to define USB strings - * - * TODO: add comment. - */ #define USB_STRING_1(__a, ...) __a "\x00" #define USB_STRING_2(__a, ...) __a "\x00" USB_STRING_1(__VA_ARGS__) #define USB_STRING_3(__a, ...) __a "\x00" USB_STRING_2(__VA_ARGS__) @@ -216,18 +213,35 @@ typedef struct usb_string_descriptor #define USB_STRING_15(__a, ...) __a "\x00" USB_STRING_14(__VA_ARGS__) #define USB_STRING_16(__a, ...) __a "\x00" USB_STRING_15(__VA_ARGS__) +/** + * Pack a list with a variable number of elements into a UTF-16LE USB string. + * + * \note The macro is recursively defined according the number of elements + * passed as argument. At the moment we support strings with up to 16 + * characters. + */ #define USB_STRING(...) PP_CAT(USB_STRING_, PP_COUNT(__VA_ARGS__))(__VA_ARGS__) -#define DEFINE_USB_STRING(__name, __text) \ - struct { \ - usb_descriptor_header_t __header; \ - uint8_t __body[sizeof(__text)]; \ - } PACKED __name = { \ - .__header = { \ - .bLength = sizeof(__name), \ - .bDescriptorType = USB_DT_STRING, \ - }, \ - .__body = {__text}, \ +/** + * Define and initialize an USB string descriptor. + * + * This macro is reuquired to properly declare and initialize a constant USB + * string in UTF-16LE format. + * + * The structure must contain the standard common USB header (UsbDescHeader) + * and the UTF-16LE string all packed in a contiguous memory region. + */ +#define DEFINE_USB_STRING(__name, __text) \ + struct { \ + UsbDescHeader __header; \ + uint8_t __body[sizeof(__text)]; \ + } PACKED __name = { \ + .__header = { \ + .bLength = \ + cpu_to_le16((uint16_t)sizeof(__name)), \ + .bDescriptorType = USB_DT_STRING, \ + }, \ + .__body = {__text}, \ } /* @@ -262,8 +276,12 @@ typedef struct usb_string_descriptor #define USB_CDC_SUBCLASS_EEM 0x0c #define USB_CDC_SUBCLASS_NCM 0x0d -/* Device configuration descriptor */ -typedef struct usb_config_descriptor +/** + * Device configuration descriptor + * + * \note See USB 2.0 specification. + */ +typedef struct UsbConfigDesc { uint8_t bLength; uint8_t bDescriptorType; @@ -273,7 +291,7 @@ typedef struct usb_config_descriptor uint8_t iConfiguration; uint8_t bmAttributes; uint8_t bMaxPower; -} PACKED usb_config_descriptor_t; +} PACKED UsbConfigDesc; /* from config descriptor bmAttributes */ #define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */ @@ -281,8 +299,12 @@ typedef struct usb_config_descriptor #define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */ #define USB_CONFIG_ATT_BATTERY (1 << 4) /* battery powered */ -/* Device interface descriptor */ -typedef struct usb_interface_descriptor +/** + * Device interface descriptor + * + * \note See USB 2.0 specification. + */ +typedef struct UsbInterfaceDesc { uint8_t bLength; uint8_t bDescriptorType; @@ -293,10 +315,14 @@ typedef struct usb_interface_descriptor uint8_t bInterfaceSubClass; uint8_t bInterfaceProtocol; uint8_t iInterface; -} PACKED usb_interface_descriptor_t; +} PACKED UsbInterfaceDesc; -/* Endpoint descriptor */ -typedef struct usb_endpoint_descriptor +/** + * Endpoint descriptor + * + * \note See USB 2.0 specification. + */ +typedef struct UsbEndpointDesc { uint8_t bLength; uint8_t bDescriptorType; @@ -304,13 +330,13 @@ typedef struct usb_endpoint_descriptor uint8_t bmAttributes; uint16_t wMaxPacketSize; uint8_t bInterval; -} PACKED usb_endpoint_descriptor_t; +} PACKED UsbEndpointDesc; /* * Endpoints */ #define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */ -#define USB_ENDPOINT_DIR_MASK 0x80 +#define USB_ENDPOINT_DIR_MASK USB_DIR_MASK #define USB_ENDPOINT_SYNCTYPE 0x0c #define USB_ENDPOINT_SYNC_NONE (0 << 2) @@ -325,145 +351,157 @@ typedef struct usb_endpoint_descriptor #define USB_ENDPOINT_XFER_INT 3 #define USB_ENDPOINT_MAX_ADJUSTABLE 0x80 -/* USB: generic device descriptor */ -struct usb_device +/** + * USB: generic device descriptor + */ +typedef struct UsbDevice { - usb_device_descriptor_t *device; - usb_descriptor_header_t **config; - usb_string_descriptor_t **strings; + UsbDeviceDesc *device; ///< USB 2.0 device descriptor + const UsbDescHeader **config; ///< USB 2.0 configuration descriptors + const UsbStringDesc **strings; ///< USB strings + + /* Callbacks */ + void (*event_cb)(UsbCtrlRequest *); ///< Called to handle control requests. + /* Private data */ - bool configured; -}; + bool configured; ///< True when the device has been correctly initialized. +} UsbDevice; -/* - * usb_endpoint_num - get the endpoint's number +/** + * Get the endpoint's address number of \a epd. */ -INLINE int usb_endpoint_num(const usb_endpoint_descriptor_t *epd) +INLINE int usb_endpointNum(const UsbEndpointDesc *epd) { return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; } -/* - * usb_endpoint_type - get the endpoint's transfer type +/** + * Get the transfer type of the endpoint \a epd. */ -INLINE int usb_endpoint_type(const struct usb_endpoint_descriptor *epd) +INLINE int usb_endpointType(const struct UsbEndpointDesc *epd) { return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; } -/* - * usb_endpoint_dir_in - check if the endpoint has IN direction +/** + * Check if the endpoint \a epd has IN direction. */ -INLINE int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd) +INLINE int usb_endpointDirIn(const struct UsbEndpointDesc *epd) { return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN); } -/* - * usb_endpoint_dir_out - check if the endpoint has OUT direction +/** + * Check if the endpoint \a epd has OUT direction. */ -INLINE int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd) +INLINE int usb_endpointDirOut(const struct UsbEndpointDesc *epd) { return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); } -/* - * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type +/** + * Check if the endpoint \a epd has bulk transfer type. */ -INLINE int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd) +INLINE int usb_endpointXferBulk(const struct UsbEndpointDesc *epd) { return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK); } -/* - * usb_endpoint_xfer_control - check if the endpoint has control transfer type +/** + * Check if the endpoint \a epd has control transfer type. */ -INLINE int usb_endpoint_xfer_control(const struct usb_endpoint_descriptor *epd) +INLINE int usb_endpointXferControl(const struct UsbEndpointDesc *epd) { return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_CONTROL); } -/* - * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type +/** + * Check if the endpoint \a epd has interrupt transfer type. */ -INLINE int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd) +INLINE int usb_endpointXferInt(const struct UsbEndpointDesc *epd) { return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT); } -/* - * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type +/** + * Check if the endpoint \a epd has isochronous transfer type. */ -INLINE int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd) +INLINE int usb_endpointXferIsoc(const struct UsbEndpointDesc *epd) { return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_ISOC); } -/* - * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN +/** + * Check if the endpoint \a epd is bulk IN. */ -INLINE int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd) +INLINE int usb_endpointIsBulkIn(const struct UsbEndpointDesc *epd) { - return usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd); + return usb_endpointXferBulk(epd) && usb_endpointDirIn(epd); } -/* - * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT +/** + * Check if the endpoint \a epd is bulk OUT. */ -INLINE int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd) +INLINE int usb_endpointIsBulkOut(const struct UsbEndpointDesc *epd) { - return usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd); + return usb_endpointXferBulk(epd) && usb_endpointDirOut(epd); } -/* - * usb_endpoint_is_int_in - check if the endpoint is interrupt IN +/** + * Check if the endpoint \a epd is interrupt IN. */ -INLINE int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd) +INLINE int usb_endpointIsIntIn(const struct UsbEndpointDesc *epd) { - return usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd); + return usb_endpointXferInt(epd) && usb_endpointDirIn(epd); } -/* - * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT +/** + * Check if the endpoint \a epd is interrupt OUT. */ -INLINE int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd) +INLINE int usb_endpointIsIntOut(const struct UsbEndpointDesc *epd) { - return usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd); + return usb_endpointXferInt(epd) && usb_endpointDirOut(epd); } -/* - * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN +/** + * Check if the endpoint \a epd is isochronous IN. */ -INLINE int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd) +INLINE int usb_endpointIsIsocIn(const struct UsbEndpointDesc *epd) { - return usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd); + return usb_endpointXferIsoc(epd) && usb_endpointDirIn(epd); } -/* - * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT +/** + * Check if the endpoint \a epd is isochronous OUT. */ -INLINE int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd) +INLINE int usb_endpointIsIsocOut(const struct UsbEndpointDesc *epd) { - return usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd); + return usb_endpointXferIsoc(epd) && usb_endpointDirOut(epd); } -/* - * usb_ep_read - configure endponint and perform the read operation +/** + * Read up to \a size bytes from the USB endpoint identified by the address + * \a ep and store them in \a buffer. + * + * \return number of bytes actually read. */ -ssize_t usb_ep_read(int ep, void *buffer, ssize_t size); +ssize_t usb_endpointRead(int ep, void *buffer, ssize_t size); -/* - * usb_ep_write - configure endponint and perform the write operation +/** + * Write up to \a size bytes from the buffer pointed \a buffer to the USB + * endpoint identified by the address \a ep. + * + * \return number of bytes actually wrote. */ -ssize_t usb_ep_write(int ep, const void *buffer, ssize_t size); +ssize_t usb_endpointWrite(int ep, const void *buffer, ssize_t size); -/* - * usb_device_register - register a generic USB device driver +/** + * Register a generic USB device driver \a dev in the USB controller. */ -int usb_device_register(struct usb_device *dev); +int usb_deviceRegister(UsbDevice *dev); #endif /* USB_H */