diff --git a/MAX/CMakeLists.txt b/MAX/CMakeLists.txt index 717feffc..4c005770 100644 --- a/MAX/CMakeLists.txt +++ b/MAX/CMakeLists.txt @@ -46,6 +46,24 @@ zephyr_include_directories( ${MSDK_PERIPH_INC_DIR} ) +if (CONFIG_UDC_MAX32) + zephyr_compile_definitions( + -DUSE_ZEPHYR_USB_STACK=1 + ) + + set(MSDK_MAXUSB_DIR ${MSDK_LIBRARY_DIR}/MAXUSB) + + zephyr_include_directories( + ${MSDK_MAXUSB_DIR}/include/core + ${MSDK_MAXUSB_DIR}/include/core/musbhsfc + ) + + zephyr_library_sources( + ${MSDK_MAXUSB_DIR}/src/core/usb_event.c + ${MSDK_MAXUSB_DIR}/src/core/musbhsfc/usb.c + ) +endif() + add_subdirectory_ifdef(CONFIG_SOC_MAX32520 Source/MAX32520) add_subdirectory_ifdef(CONFIG_SOC_MAX32570 Source/MAX32570) add_subdirectory_ifdef(CONFIG_SOC_MAX32572 Source/MAX32572) diff --git a/MAX/Libraries/MAXUSB/include/core/musbhsfc/usb_hwopt.h b/MAX/Libraries/MAXUSB/include/core/musbhsfc/usb_hwopt.h new file mode 100644 index 00000000..ec5ad5df --- /dev/null +++ b/MAX/Libraries/MAXUSB/include/core/musbhsfc/usb_hwopt.h @@ -0,0 +1,63 @@ +/****************************************************************************** + * + * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by + * Analog Devices, Inc.), + * Copyright (C) 2023-2024 Analog Devices, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#ifndef LIBRARIES_MAXUSB_INCLUDE_CORE_MUSBHSFC_USB_HWOPT_H_ +#define LIBRARIES_MAXUSB_INCLUDE_CORE_MUSBHSFC_USB_HWOPT_H_ + +#include "mxc_device.h" +#include "usbhs_regs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Configuration options for MUSBHSFC */ +typedef struct { + unsigned int enable_hs; /* 0 = full-speed only, otherwise high-speed if negotiated */ + void (*delay_us)(unsigned int usec); /* User-supplied function to delay usec micro-seconds */ + int (*init_callback)(void); /* User-supplied function for initializing the USB block */ + int (*shutdown_callback)(void); /* User-supplied function for shutting down the USB block */ +} maxusb_cfg_options_t; + +/** + * @brief Put the transceiver into a low power state. + */ +void MXC_USB_Sleep(void); + +/** + * @brief Power up the USB transceiver, must be called once the device wakes from sleep. + */ +void MXC_USB_Wakeup(void); + +/** + * @brief Send a remote wakeup signal to the host. + */ +void MXC_USB_RemoteWakeup(void); + +/* + * @brief USB internal DMA engine interrupt handler + */ +void MXC_USB_DmaIsr(void); + +#ifdef __cplusplus +} +#endif + +#endif //LIBRARIES_MAXUSB_INCLUDE_CORE_MUSBHSFC_USB_HWOPT_H_ diff --git a/MAX/Libraries/MAXUSB/include/core/usb.h b/MAX/Libraries/MAXUSB/include/core/usb.h new file mode 100644 index 00000000..93a76a55 --- /dev/null +++ b/MAX/Libraries/MAXUSB/include/core/usb.h @@ -0,0 +1,446 @@ +/****************************************************************************** + * + * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by + * Analog Devices, Inc.), + * Copyright (C) 2023-2024 Analog Devices, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#ifndef LIBRARIES_MAXUSB_INCLUDE_CORE_USB_H_ +#define LIBRARIES_MAXUSB_INCLUDE_CORE_USB_H_ + +#include +#include "usb_hwopt.h" +#include "usb_protocol.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file usb.h + * @brief Defines the API used to abstract USB hardware away from upper layers. + * + */ + +/******************************** Definitions *********************************/ + +/* + * Current status, as bit field, of physical layer. Note that some bits may + * not be available on hardware which lacks detection of that specific condition. + * + */ +#define MAXUSB_STATUS_VBUS_ON 0x1 +#define MAXUSB_STATUS_HIGH_SPEED 0x2 + +/* + * Endpoint types, additional types may be supported in the future. + * + * On non-configurable hardware, an error will be returned if the type selected + * disagrees with hardware capability on that endpoint (ie. can't make an IN + * into an OUT). + * + */ +typedef enum { + MAXUSB_EP_TYPE_DISABLED = 0, + MAXUSB_EP_TYPE_OUT = 1, + MAXUSB_EP_TYPE_IN = 2, + MAXUSB_EP_TYPE_CONTROL = 3 +} maxusb_ep_type_t; + +/* + * USB events. Register for callbacks with usb_register_callback(). + */ +typedef enum { + MAXUSB_EVENT_DPACT = 0, /* D+ Activity */ + MAXUSB_EVENT_RWUDN, /* Remote Wake-Up Signaling Done */ + MAXUSB_EVENT_BACT, /* Bus Active */ + MAXUSB_EVENT_BRST, /* Bus Reset */ + MAXUSB_EVENT_SUSP, /* Suspend */ + MAXUSB_EVENT_NOVBUS, /* No VBUS - VBUSDET signal makes 0 -> 1 transition i.e. VBUS not present */ + MAXUSB_EVENT_VBUS, /* VBUS present */ + MAXUSB_EVENT_BRSTDN, /* Bus Reset Done */ + MAXUSB_EVENT_SUDAV, /* Setup Data Available */ + MAXUSB_NUM_EVENTS +} maxusb_event_t; + +/* + * USB events flags. + */ +typedef struct { + /* Non-endpoint events */ + unsigned int dpact : 1; + unsigned int rwudn : 1; + unsigned int bact : 1; + unsigned int brst : 1; + unsigned int susp : 1; + unsigned int novbus : 1; + unsigned int vbus : 1; + unsigned int brstdn : 1; + unsigned int sudav : 1; +} maxusb_usbio_events_t; + +/* + * USB Request Type + */ +typedef enum { + MAXUSB_TYPE_TRANS = 0, + /* The request will complete once the requested amount + * of data has been received, or when a packet is + * received containing less than max packet. + */ + MAXUSB_TYPE_PKT + /* The request will complete each time a packet is + * received. The caller is responsible for zero-packet + * handling + */ +} maxusb_req_type_t; + +/* + * Object for requesting an endpoint read or write. The object is updated with + * the transaction status and can be observed when the callback is called. + */ +typedef struct { + unsigned int ep; + uint8_t *data; + unsigned int reqlen; // requested / max length + unsigned int actlen; // actual length transacted + int error_code; + void (*callback)(void *); + void *cbdata; + maxusb_req_type_t type; + void *driver_xtra; /* driver-specific data, do not modify */ +} MXC_USB_Req_t; + + +/**************************** Function Prototypes *****************************/ + +/** + * @brief Initialize the USB hardware to a non-connected, "ready" state + * + * @param options Hardware-specific options which are in each chip's MXC_USB_hwopt.h + * @return This function returns zero (0) for success, non-zero for failure + * + */ +int MXC_USB_Init(maxusb_cfg_options_t *options); + +#ifdef MAX32690 +// Clock setter mux APIs are currently only supported on the MAX32690. It does not exist +// on earlier hardware revisions such as the MAX32650 + +#ifndef mxc_usb_clock_t +#warning "mxc_usb_clock_t" not implemented. See note in usb.h on "MXC_USB_SetClockSource" +typedef enum { + MXC_USB_CLOCK_0 = 0, + MXC_USB_CLOCK_1 = 1, + MXC_USB_CLOCK_2 = 2 +} mxc_usb_clock_t; +#endif + +/** + * @brief Set the input clock source to the USB peripheral. + * + * @param clock_source Input clock source + * @note (Developers): "mxc_usb_clock_t" should be defined as a macro in the top-level "max32xxx.h" file + * so that the pre-processor can check for its existence. Ex: + * + * #define mxc_usb_clock_t _mxc_usb_clock_t + * + * where "_mxc_usb_clock_t" is the actual "typedef enum". + * See "max32690.h" for reference. + * + * @return This function returns zero (0) for success, non-zero for failure + * + */ +int MXC_USB_SetClockSource(mxc_usb_clock_t clock_source); + +/** + * @brief Lock the input clock source to the USB peripheral. + * + * @param lock Whether to lock the clock source. Set to true to lock, false to unlock. + * + * @return This function returns zero (0) for success, non-zero for failure + * + */ +int MXC_USB_LockClockSource(bool lock); + +#endif + +/** + * @brief Shut down the USB peripheral block + * + * This function will shut down the USB IP. Once called, you must call + * MXC_USB_init() to bring the block back into a working condition. No + * state persists after this call, including endpoint configuration, + * pending reads/writes, etc. All pending and outstanding events will be + * quashed at the driver layer. + * + * @return This function returns zero (0) for success, non-zero for failure + * + */ +int MXC_USB_Shutdown(void); + +/** + * @brief Connect to the USB bus + * @return This function returns zero (0) for success, non-zero for failure + * + */ +int MXC_USB_Connect(void); + +/** + * @brief Disconnect from the USB bus + * @return This function returns zero (0) for success, non-zero for failure + * + */ +int MXC_USB_Disconnect(void); + +/** + * @brief Get current USB status (VBUS, High Speed, etc.) + * @return This function returns a bit field of MAXUSB_STATUS_xxx + * + */ +unsigned int MXC_USB_GetStatus(void); + +/** + * @brief Endpoint configuration function + * + * Endpoints can be Disabled, CONTROL, BULK/INTERRUPT IN, or BULK/INTERRUPT OUT. + * No hardware support for ISOCHRONOUS exists currently, but may appear in the future. + * + * An endpoint has a configured size, which should match that advertised to the host in + * the Device Descriptor. + * + * @param ep endpoint number + * @param type endpoint type + * @param size endpoint size + * @return This function returns zero (0) for success, non-zero for failure + * + */ +int MXC_USB_ConfigEp(unsigned int ep, maxusb_ep_type_t type, unsigned int size); + +/** + * @brief Query the configuration status of the selected endpoint + * @param ep endpoint number + * @return This function returns 1 if the endpoint is configured, 0 if it is not, and < 0 for error + * + */ +int MXC_USB_IsConfigured(unsigned int ep); + +/** + * @brief Stall the selected endpoint + * + * If the endpoint is the CONTROL endpoint, then both the IN and OUT pipes are stalled. + * In this case, the hardware will also stall the Status stage of the transfer. + * + * @param ep endpoint number + * @return This function returns zero (0) for success, non-zero for failure + * + */ +int MXC_USB_Stall(unsigned int ep); + +/** + * @brief Unstall the selected endpoint + * + * If this endpoint is the CONTROL endpoint, the IN, OUT, and Status stage stall bits are cleared. + * This is not normally needed, as hardware should clear these bits upon reception of the + * next SETUP packet. + * + * @param ep endpoint number + * @return This function returns zero (0) for success, non-zero for failure + * + */ +int MXC_USB_Unstall(unsigned int ep); + +/** + * @brief Query the stalled/unstalled status of the selected endpoint + * @param ep endpoint number + * @return This function returns 0 if the endpoint is not stalled, 1 if it is, and < 0 for error + * + */ +int MXC_USB_IsStalled(unsigned int ep); + +/** + * @brief Reset state and clear the data toggle on the selected endpoint + * @param ep endpoint number + * @return This function returns zero (0) for success, non-zero for failure + * + */ +int MXC_USB_ResetEp(unsigned int ep); + +/** + * @brief Arm the hardware to ACK the Status stage of a SETUP transfer. Only valid for CONTROL endpoints. + * @param ep endpoint number + * @return This function returns zero (0) for success, non-zero for failure + * + */ +int MXC_USB_Ackstat(unsigned int ep); + +/** + * @brief Enable the specified event interrupt in hardware + * This function is called by the event layer through MXC_USB_event_enable() and + * should not be called directly from the application. + * @param event event number + * @return This function returns zero (0) for success, non-zero for failure + * + */ +int MXC_USB_IrqEnable(maxusb_event_t event); + +/** + * @brief Enable the specified event interrupt in hardware + * This function is called by the event layer through MXC_USB_EventDisable() and + * should not be called directly from the application. + * @param event event number + * @return This function returns zero (0) for success, non-zero for failure + * + */ +int MXC_USB_IrqDisable(maxusb_event_t event); + +/** + * @brief Clear the specified interrupt flag in hardware + * This function is called by the event layer through MXC_USB_EventClear() and + * should not be called directly from the application. + * @param event event number + * @return This function returns zero (0) for success, non-zero for failure + * + */ +int MXC_USB_IrqClear(maxusb_event_t event); + +/** + * @brief Interrupt handler. + * This function is called by the event layer through MXC_USB_EventHandler() and + * should not be called directly from the application. + * This function will read the interrupt flags, handle any outstanding + * I/O in a chip-specific way (DMA, Programmed I/O, Bus Master, etc.) + * The event structure is returned to the upper layer so that it may react to + * bus conditions. + * @param evt structure of event flags + */ +void MXC_USB_IrqHandler(maxusb_usbio_events_t *events); + +/** + * @brief Read the SETUP data from hardware + * @param setup_pkt Pointer to setup data structure + * @return This function returns zero (0) for success, non-zero for failure + * + */ +int MXC_USB_GetSetup(MXC_USB_SetupPkt *setup_pkt); + +/** + * @brief Change the function address, in response to a Host request + * @param addr The 7-bit address in the SET_ADDRESS request + * @return This function returns zero (0) for success, non-zero for failure + * @note Some hardware does this automatically; In that case, this function will always return 0. + * + */ +int MXC_USB_SetFuncAddr(unsigned int addr); + +/** + * @brief Returns a pointer to the request queued for the specified endpoint + * @param ep Endpoint which to query + * @return Pointer to request structure, or NULL if none queued + * + */ +MXC_USB_Req_t *MXC_USB_GetRequest(unsigned int ep); + +/** + * @brief Remove a queued endpoint request + * @param req Pointer to usb request (if not known, use MXC_USB_GetRequest(ep)) + * @return Zero if successful, non-zero otherwise + * @note Callback function on request, if any, will be called with a -1 error result + * + */ +int MXC_USB_RemoveRequest(MXC_USB_Req_t *req); + +/** + * @brief Send data to the host via the selected endpoint + * + * This asynchronous function allows the caller to specify a buffer for outgoing data. + * The buffer may have any length, and device-specific code will handle breaking the data + * into endpoint-sized chunks. The request object and data buffer passed to this function must + * remain "owned" by the USB stack until the callback function is called indicating completion. + * It will handle a zero-length length, as that is a valid message on the USB to indicate + * success during various phases of data transfer. + * + * Once called, the next IN transaction processed by hardware on the selected endpoint + * will cause the IN DATAx payload to be sent from the provided buffer. The driver will + * keep track of how many bytes have been sent and continue sending additional chunks of + * data until all data has been sent to the host. The driver will send a zero-length packet + * if the data to be sent is a whole multiple (no remainder after division) of the endpoint size. + * + * Upon completion of the request, the request object's error_code and actlen fields are + * updated to reflect the result of the transaction and the function specified in the request + * object is be called. + * + * Only one outstanding buffer is allowed to exist in the current implementation. This function + * will return an error to the caller if it finds that there is an outstanding buffer already + * configured. This will not affect the outstanding buffer. + * + * A special case exists for this call: If the data pointer is NULL, then any existing + * outstanding buffer is removed from the driver. This allows for a "disarming" mechanism + * without shutting down the entire stack and re-starting. + * + * @param req Initialized request object + * + * @return This function returns zero (0) for success, non-zero for failure + * + */ +int MXC_USB_WriteEndpoint(MXC_USB_Req_t *req); + +/** + * @brief Arm the selected endpoint to receive data from the host + * + * This asynchronous function allows the caller to specify a buffer for incoming data. + * The driver will read from the endpoint at most len bytes into the provided buffer. + * + * Once called, the next OUT transaction processed by hardware on the selected endpoint + * will cause the OUT DATAx payload to be loaded into the provided buffer. Additional OUT + * DATAx payloads will be concatenated to the buffer until 1) len bytes have been read, or + * 2) a DATAx payload of length less than the maximum endpoint size has been read. The + * latter case signifies the end of a USB transaction. If case #1 is reached before the end + * of the USB transfer, any additional data is thrown away by the driver layer. + * + * Upon completion of the request, the request object's error_code and actlen fields are + * updated to reflect the result of the transaction and the function specified in the request + * object is be called. + * + * Only one outstanding buffer is allowed to exist in the current implementation. This function + * will return an error to the caller if it finds that there is an outstanding buffer already + * configured. This will not affect the outstanding buffer. + * + * A special case exists for this call: If the data pointer is NULL, then any existing + * outstanding buffer is removed from the driver. This allows for a "disarming" mechanism + * without shutting down the entire stack and re-starting. + * + * @param req Initialized request object + * + * @return This function returns zero (0) for success, non-zero for failure + * + */ +int MXC_USB_ReadEndpoint(MXC_USB_Req_t *req); + +/** + * @brief Instruct hardware to transmit test mode pattern (USB 2.0 High Speed only) + * @detail See Universal Serial Bus Specification Revision 2.0 Section 7.1.20 for details + * @param value Test mode selector + * @return -1 if selected test mode is not supported, 0 otherwise + * + */ +int MXC_USB_TestMode(unsigned int value); + +#ifdef __cplusplus +} +#endif + +#endif //LIBRARIES_MAXUSB_INCLUDE_CORE_USB_H_ diff --git a/MAX/Libraries/MAXUSB/include/core/usb_event.h b/MAX/Libraries/MAXUSB/include/core/usb_event.h new file mode 100644 index 00000000..702deb53 --- /dev/null +++ b/MAX/Libraries/MAXUSB/include/core/usb_event.h @@ -0,0 +1,85 @@ +/****************************************************************************** + * + * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by + * Analog Devices, Inc.), + * Copyright (C) 2023-2024 Analog Devices, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +/* + * Low-layer API calls + * + * These do not change, and provide the basis by which usb.c acceses the + * hardware. All usbio.c drivers will provide these calls, or return an + * error if the function is not supported. + * + */ + +#ifndef LIBRARIES_MAXUSB_INCLUDE_CORE_USB_EVENT_H_ +#define LIBRARIES_MAXUSB_INCLUDE_CORE_USB_EVENT_H_ + +#include "usb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file MXC_USB_event.h + * @brief Defines the API used for USB event handling + * + */ + +/***** Definitions *****/ +typedef struct { + int (*func)(maxusb_event_t, void *); + void *cbdata; +} MXC_USB_event_callback_t; + +/** + * @brief Register a callback for and enable the specified event + * @param event event number + * @param func function to be called + * @param cbdata parameter to call callback function with + * @return This function returns zero (0) for success, non-zero for failure + */ +int MXC_USB_EventEnable(maxusb_event_t event, int (*callback)(maxusb_event_t, void *), void *cbdata); + +/** + * @brief Enable the specified event + * @param event event number + * @return This function returns zero (0) for success, non-zero for failure + */ +int MXC_USB_EventDisable(maxusb_event_t event); + +/** + * @brief Clear the specified event + * @param event event number + * @return This function returns zero (0) for success, non-zero for failure + */ +int MXC_USB_EventClear(maxusb_event_t event); + +/** + * @brief Processes USB events + * This function should be called from the USB interrupt vector or periodically + * from the application. + */ +void MXC_USB_EventHandler(void); + +#ifdef __cplusplus +} +#endif + +#endif //LIBRARIES_MAXUSB_INCLUDE_CORE_USB_EVENT_H_ diff --git a/MAX/Libraries/MAXUSB/include/core/usb_protocol.h b/MAX/Libraries/MAXUSB/include/core/usb_protocol.h new file mode 100644 index 00000000..d1533d26 --- /dev/null +++ b/MAX/Libraries/MAXUSB/include/core/usb_protocol.h @@ -0,0 +1,205 @@ +/****************************************************************************** + * + * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by + * Analog Devices, Inc.), + * Copyright (C) 2023-2024 Analog Devices, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#ifndef LIBRARIES_MAXUSB_INCLUDE_CORE_USB_PROTOCOL_H_ +#define LIBRARIES_MAXUSB_INCLUDE_CORE_USB_PROTOCOL_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* SETUP message byte offsets */ +#define SETUP_bmRequestType 0 +#define SETUP_bRequest 1 +#define SETUP_wValueL 2 +#define SETUP_wValueH 3 +#define SETUP_wIndexL 4 +#define SETUP_wIndexH 5 +#define SETUP_wLengthL 6 +#define SETUP_wLengthH 7 + +typedef struct { + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} MXC_USB_SetupPkt; + +/* Bitmasks for the bit-field bmRequestType */ +#define RT_DEV_TO_HOST 0x80 + +#define RT_TYPE_MASK 0x60 +#define RT_TYPE_STD 0x00 +#define RT_TYPE_CLASS 0x20 +#define RT_TYPE_VENDOR 0x40 + +#define RT_RECIP_MASK 0x1f +#define RT_RECIP_DEVICE 0x00 +#define RT_RECIP_IFACE 0x01 +#define RT_RECIP_ENDP 0x02 +#define RT_RECIP_OTHER 0x03 + +/* Standard Device Requests for bRequest */ +#define SDR_GET_STATUS 0x00 +#define SDR_CLEAR_FEATURE 0x01 +#define SDR_SET_FEATURE 0x03 +#define SDR_SET_ADDRESS 0x05 +#define SDR_GET_DESCRIPTOR 0x06 +#define SDR_SET_DESCRIPTOR 0x07 +#define SDR_GET_CONFIG 0x08 +#define SDR_SET_CONFIG 0x09 +#define SDR_GET_INTERFACE 0x0a +#define SDR_SET_INTERFACE 0x0b +#define SDR_SYNCH_FRAME 0x0c + +/* Descriptor types for *_DESCRIPTOR */ +#define DESC_DEVICE 1 +#define DESC_CONFIG 2 +#define DESC_STRING 3 +#define DESC_INTERFACE 4 +#define DESC_ENDPOINT 5 +#define DESC_DEVICE_QUAL 6 +#define DESC_OTHER_SPEED 7 +#define DESC_IFACE_PWR 8 + +/* Feature types for *_FEATURE */ +#define FEAT_ENDPOINT_HALT 0 +#define FEAT_REMOTE_WAKE 1 +#define FEAT_TEST_MODE 2 + +/* Get Status bit positions */ +#define STATUS_EP_HALT 0x1 +#define STATUS_DEV_SELF_POWERED 0x1 +#define STATUS_DEV_REMOTE_WAKE 0x2 + +/* bmAttributes bit positions */ +#define BMATT_REMOTE_WAKE 0x20 +#define BMATT_SELF_POWERED 0x40 + +#if defined(__GNUC__) +typedef struct __attribute__((packed)) { +#else +typedef __packed struct { +#endif + 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; +} MXC_USB_device_descriptor_t; + +#if defined(__GNUC__) +typedef struct __attribute__((packed)) { +#else +typedef __packed struct { +#endif + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumInterfaces; + uint8_t bConfigurationValue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t bMaxPower; +} MXC_USB_configuration_descriptor_t; + +#if defined(__GNUC__) +typedef struct __attribute__((packed)) { +#else +typedef __packed struct { +#endif + 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; +} MXC_USB_interface_descriptor_t; + +#define USB_EP_NUM_MASK 0x0F + +#ifndef USE_ZEPHYR_USB_STACK +#define USB_EP_DIR_MASK 0x80 +#endif + +#if defined(__GNUC__) +typedef struct __attribute__((packed)) { +#else +typedef __packed struct { +#endif + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint16_t wMaxPacketSize; + uint8_t bInterval; +} MXC_USB_endpoint_descriptor_t; + +#if defined(__GNUC__) +typedef struct __attribute__((packed)) { +#else +typedef __packed struct { +#endif + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize; + uint8_t bNumConfigurations; + uint8_t bReserved; +} MXC_USB_device_qualifier_descriptor_t; + +#if defined(__GNUC__) +typedef struct __attribute__((packed)) { +#else +typedef __packed struct { +#endif + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumInterfaces; + uint8_t bConfigurationValue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t bMaxPower; +} MXC_USB_other_speed_configuration_descriptor_t; + +#ifdef __cplusplus +} +#endif + +#endif //LIBRARIES_MAXUSB_INCLUDE_CORE_USB_PROTOCOL_H_ diff --git a/MAX/Libraries/MAXUSB/src/core/musbhsfc/usb.c b/MAX/Libraries/MAXUSB/src/core/musbhsfc/usb.c new file mode 100644 index 00000000..ef6b099b --- /dev/null +++ b/MAX/Libraries/MAXUSB/src/core/musbhsfc/usb.c @@ -0,0 +1,1196 @@ +/****************************************************************************** + * + * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by + * Analog Devices, Inc.), + * Copyright (C) 2023-2024 Analog Devices, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#include +#include +#include +#include "mxc_device.h" +#include "mxc_assert.h" +#include "mxc_errors.h" +#include "mxc_sys.h" +#include "usbhs_regs.h" +#include "usb.h" + +#ifdef MAX32690 +#include "fcr_regs.h" +static bool g_is_clock_locked = false; +#endif + +#define USBHS_M31_CLOCK_RECOVERY + +typedef enum { + SETUP_IDLE, + SETUP_NODATA, + SETUP_DATA_OUT, + SETUP_DATA_IN +} setup_phase_t; + +/* storage for active endpoint data request objects */ +static MXC_USB_Req_t *MXC_USB_Request[MXC_USBHS_NUM_EP]; +/* endpoint sizes */ +static unsigned int ep_size[MXC_USBHS_NUM_EP]; +/* MUSBHSFC does not track SETUP in hardware, so instantiate state variable */ +static setup_phase_t setup_phase = SETUP_IDLE; +/* Driver options passed in during MXC_USB_Init() */ +static maxusb_cfg_options_t driver_opts; + +static volatile uint8_t *get_fifo_ptr(unsigned int ep) +{ + volatile uint32_t *ptr; + + ptr = &MXC_USBHS->fifo0; + ptr += ep; /* Pointer math: multiplies ep by sizeof(uint32_t) */ + + return (volatile uint8_t *)ptr; +} + +static void load_fifo(volatile uint8_t *fifoptr, uint8_t *dataptr, unsigned int len) +{ + volatile uint32_t *fifoptr_32 = (uint32_t *)fifoptr; + uint32_t *dataptr_32 = (uint32_t *)dataptr; + unsigned int len_32; + + /* Calculate sizes to efficiently move data */ + len_32 = len >> 2; + len &= 0x3; + + /* Load word-sized chunks */ + while (len_32--) { + *fifoptr_32 = *dataptr_32++; + } + dataptr = (uint8_t *)dataptr_32; + /* Load remainder as bytes */ + while (len--) { + *fifoptr = *dataptr++; + } +} + +static void unload_fifo(uint8_t *dataptr, volatile uint8_t *fifoptr, unsigned int len) +{ + volatile uint32_t *fifoptr_32 = (uint32_t *)fifoptr; + uint32_t *dataptr_32 = (uint32_t *)dataptr; + unsigned int len_32; + + /* Calculate sizes to efficiently move data */ + len_32 = len >> 2; + len &= 0x3; + + while (len_32--) { + *dataptr_32++ = *fifoptr_32; + } + dataptr = (uint8_t *)dataptr_32; + while (len--) { + *dataptr++ = *fifoptr; + } +} + +int MXC_USB_Init(maxusb_cfg_options_t *options) +{ + int i; + + /* Save the init options */ + if (options) { + memcpy(&driver_opts, options, sizeof(maxusb_cfg_options_t)); + } else { + driver_opts.enable_hs = 0; + } + + /* Enable peripheral at the chip level */ + if (driver_opts.init_callback) { + if (driver_opts.init_callback() != E_NO_ERROR) { + return -1; + } + } + + /* Endpoint 0 is CONTROL, size fixed in hardware. Does not need configuration. */ + ep_size[0] = 64; + + /* Reset all other endpoints */ + for (i = 1; i < MXC_USBHS_NUM_EP; i++) { + MXC_USB_ResetEp(i); + } + + setup_phase = SETUP_IDLE; + + /* Start out disconnected */ + MXC_USBHS->power = 0; + + /* Disable all interrupts */ + MXC_USBHS->intrinen = 0; + MXC_USBHS->introuten = 0; + MXC_USBHS->intrusben = 0; + + /* Unsuspend the MAC */ + MXC_USBHS->mxm_suspend = 0; + + /* Configure PHY */ +#if 0 + MXC_USBHS->xcfgi0 = (0x1 << 3) | (0x1 << 11); + MXC_USBHS->xcfgi1 = 0; + MXC_USBHS->xcfgi2 = 0x1 << (72-64); + MXC_USBHS->xcfgi3 = 0; +#endif + MXC_USBHS->m31_phy_xcfgi_31_0 = (0x1 << 3) | (0x1 << 11); + MXC_USBHS->m31_phy_xcfgi_63_32 = 0; + MXC_USBHS->m31_phy_xcfgi_95_64 = 0x1 << (72-64); + MXC_USBHS->m31_phy_xcfgi_127_96 = 0; + + +#ifdef USBHS_M31_CLOCK_RECOVERY + MXC_USBHS->m31_phy_noncry_rstb = 1; + MXC_USBHS->m31_phy_noncry_en = 1; + MXC_USBHS->m31_phy_outclksel = 0; + MXC_USBHS->m31_phy_coreclkin = 0; + MXC_USBHS->m31_phy_xtlsel = 2; /* Select 25 MHz clock */ +#else + /* Use this option to feed the PHY a 30 MHz clock, which is them used as a PLL reference */ + /* As it depends on the system core clock, this should probably be done at the SYS level */ + MXC_USBHS->m31_phy_noncry_rstb = 0; + MXC_USBHS->m31_phy_noncry_en = 0; + MXC_USBHS->m31_phy_outclksel = 1; + MXC_USBHS->m31_phy_coreclkin = 1; + MXC_USBHS->m31_phy_xtlsel = 3; /* Select 30 MHz clock */ +#endif + MXC_USBHS->m31_phy_pll_en = 1; + MXC_USBHS->m31_phy_oscouten = 1; + + /* Reset PHY */ + MXC_USBHS->m31_phy_ponrst = 0; + MXC_USBHS->m31_phy_ponrst = 1; + + return 0; +} + +#ifdef MAX32690 + +int MXC_USB_LockClockSource(bool lock) +{ + g_is_clock_locked = lock; + return E_NO_ERROR; +} + +int MXC_USB_SetClockSource(mxc_usb_clock_t clock_source) +{ + if (g_is_clock_locked) { + return E_BAD_STATE; // Clock source must be unlocked to set it. + } + + // The USB peripheral's clock source is set in the FCR register bank. + // The actual clock source selected by each field value may vary between + // microcontrollers, so it is the responsibility of the implementer to define + // mxc_usb_clock_t correctly in the top-level "max32xxx.h" file. The enum values + // should match the field values when type-casted to an unsigned int. + if ((unsigned int)clock_source < 0 || (unsigned int)clock_source >= 3) { + return E_BAD_PARAM; + } + + mxc_sys_system_clock_t current_sys_clk = (mxc_sys_system_clock_t)(MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_SYSCLK_SEL); + if (current_sys_clk != MXC_SYS_CLOCK_IPO && clock_source == MXC_USB_CLOCK_SYS_DIV_10) { + return E_BAD_STATE; // System clock must be set to the IPO for the USB PHY to use the internal clock + } + + MXC_SETFIELD(MXC_FCR->fctrl0, MXC_F_FCR_FCTRL0_USBCLKSEL, ((unsigned int)clock_source) << MXC_F_FCR_FCTRL0_USBCLKSEL_POS); + + return E_NO_ERROR; +} + +#endif + +int MXC_USB_Shutdown(void) +{ + /* Disconnect and disable HS, too. */ + MXC_USBHS->power = 0; + + /* Disable all interrupts */ + MXC_USBHS->intrinen = 0; + MXC_USBHS->introuten = 0; + MXC_USBHS->intrusben = 0; + + /* Suspend the MAC */ + MXC_USBHS->mxm_suspend = 3; + + /* Shut down PHY */ + MXC_USBHS->m31_phy_ponrst = 0; + + /* Disable peripheral at chip level -- ignore failures */ + if (driver_opts.shutdown_callback) { + driver_opts.shutdown_callback(); + } + + return 0; +} + +int MXC_USB_Connect(void) +{ + /* Should high-speed negotiation be attempted? */ + if (driver_opts.enable_hs) { + MXC_USBHS->power |= MXC_F_USBHS_POWER_HS_ENABLE; + } else { + MXC_USBHS->power &= ~MXC_F_USBHS_POWER_HS_ENABLE; + } + + /* Connect to bus, if present */ + MXC_USBHS->power |= MXC_F_USBHS_POWER_SOFTCONN; + + setup_phase = SETUP_IDLE; + + return 0; +} + +int MXC_USB_Disconnect(void) +{ + /* Disconnect from bus */ + MXC_USBHS->power &= ~MXC_F_USBHS_POWER_SOFTCONN; + + setup_phase = SETUP_IDLE; + + return 0; +} + +unsigned int MXC_USB_GetStatus(void) +{ + int status = 0; + + /* VBUS */ + if (MXC_USBHS->mxm_reg_a4 & MXC_F_USBHS_MXM_REG_A4_VRST_VDDB_N_A) { + status |= MAXUSB_STATUS_VBUS_ON; + } + + /* High-speed state */ + if (MXC_USBHS->power & MXC_F_USBHS_POWER_HS_MODE) { + status |= MAXUSB_STATUS_HIGH_SPEED; + } + + return status; +} + +int MXC_USB_ConfigEp(unsigned int ep, maxusb_ep_type_t type, unsigned int size) +{ + if (!ep || (ep >= MXC_USBHS_NUM_EP) || (size > MXC_USBHS_MAX_PACKET)) { + /* Can't configure this endpoint, invalid endpoint, or size too big */ + return -1; + } + + /* Default to disabled */ + MXC_USB_ResetEp(ep); + + /* Interrupts must be disabled while banked registers are accessed */ + MXC_SYS_Crit_Enter(); + + /* Select register index for endpoint */ + MXC_USBHS->index = ep; + + switch (type) { + case MAXUSB_EP_TYPE_DISABLED: + break; + case MAXUSB_EP_TYPE_OUT: + MXC_USBHS->outcsrl = MXC_F_USBHS_OUTCSRL_CLRDATATOG; + MXC_USBHS->outcsru = MXC_F_USBHS_OUTCSRU_DPKTBUFDIS; + MXC_USBHS->outmaxp = size; + ep_size[ep] = size; + MXC_USBHS->introuten &= ~(1 << ep); + break; + case MAXUSB_EP_TYPE_IN: + MXC_USBHS->incsrl = MXC_F_USBHS_INCSRL_CLRDATATOG; + MXC_USBHS->incsru = MXC_F_USBHS_INCSRU_DPKTBUFDIS | MXC_F_USBHS_INCSRU_MODE; + MXC_USBHS->inmaxp = size; + ep_size[ep] = size; + MXC_USBHS->intrinen |= (1 << ep); + break; + default: + MXC_SYS_Crit_Exit(); + return -1; + } + + MXC_SYS_Crit_Exit(); + return 0; +} + +int MXC_USB_IsConfigured(unsigned int ep) +{ + return !!(ep_size[ep]); +} + +int MXC_USB_Stall(unsigned int ep) +{ + MXC_USB_Req_t *req; + + if (!MXC_USB_IsConfigured(ep)) { + /* Can't stall an unconfigured endpoint */ + return -1; + } + + /* Interrupts must be disabled while banked registers are accessed */ + MXC_SYS_Crit_Enter(); + + MXC_USBHS->index = ep; + + if (ep == 0) { + MXC_USBHS->csr0 |= MXC_F_USBHS_CSR0_SERV_OUTPKTRDY | MXC_F_USBHS_CSR0_SEND_STALL; + setup_phase = SETUP_IDLE; + } else { + if (MXC_USBHS->incsru & MXC_F_USBHS_INCSRU_MODE) { + /* IN endpoint */ + MXC_USBHS->incsrl |= MXC_F_USBHS_INCSRL_SENDSTALL; + } else { + /* Otherwise, must be OUT endpoint */ + MXC_USBHS->outcsrl |= MXC_F_USBHS_OUTCSRL_SENDSTALL; + } + } + + /* clear pending requests */ + req = MXC_USB_Request[ep]; + MXC_USB_Request[ep] = NULL; + + if (req) { + /* complete pending requests with error */ + req->error_code = -1; + if (req->callback) { + req->callback(req->cbdata); + } + } + + MXC_SYS_Crit_Exit(); + return 0; +} + +int MXC_USB_Unstall(unsigned int ep) +{ + if (!MXC_USB_IsConfigured(ep)) { + /* Can't unstall an unconfigured endpoint */ + return -1; + } + + /* Interrupts must be disabled while banked registers are accessed */ + MXC_SYS_Crit_Enter(); + + MXC_USBHS->index = ep; + + if (ep != 0) { + if (MXC_USBHS->incsru & MXC_F_USBHS_INCSRU_MODE) { + /* IN endpoint */ + if (MXC_USBHS->incsrl & MXC_F_USBHS_INCSRL_INPKTRDY) { + /* Per musbhsfc_pg, only flush FIFO if IN packet loaded */ + MXC_USBHS->incsrl = MXC_F_USBHS_INCSRL_CLRDATATOG | MXC_F_USBHS_INCSRL_FLUSHFIFO; + } else { + MXC_USBHS->incsrl = MXC_F_USBHS_INCSRL_CLRDATATOG; + } + } else { + /* Otherwise, must be OUT endpoint */ + if (MXC_USBHS->outcsrl & MXC_F_USBHS_OUTCSRL_OUTPKTRDY) { + /* Per musbhsfc_pg, only flush FIFO if OUT packet is ready */ + MXC_USBHS->outcsrl = MXC_F_USBHS_OUTCSRL_CLRDATATOG | MXC_F_USBHS_OUTCSRL_FLUSHFIFO; + } else { + MXC_USBHS->outcsrl = MXC_F_USBHS_OUTCSRL_CLRDATATOG; + } + } + } + + MXC_SYS_Crit_Exit(); + return 0; +} + +int MXC_USB_IsStalled(unsigned int ep) +{ + unsigned int stalled; + + MXC_USBHS->index = ep; + + if (ep) { + if (MXC_USBHS->incsru & MXC_F_USBHS_INCSRU_MODE) { + /* IN endpoint */ + stalled = !!(MXC_USBHS->incsrl & MXC_F_USBHS_INCSRL_SENDSTALL); + } else { + /* Otherwise, must be OUT endpoint */ + stalled = !!(MXC_USBHS->outcsrl & MXC_F_USBHS_OUTCSRL_SENDSTALL); + } + } else { + /* Control (EP 0) */ + stalled = !!(MXC_USBHS->csr0 & MXC_F_USBHS_CSR0_SEND_STALL); + } + + return stalled; +} + +int MXC_USB_ResetEp(unsigned int ep) +{ + MXC_USB_Req_t *req; + + if (ep >= MXC_USBHS_NUM_EP) { + return -1; + } + + /* Interrupts must be disabled while banked registers are accessed */ + MXC_SYS_Crit_Enter(); + + /* clear pending requests */ + req = MXC_USB_Request[ep]; + MXC_USB_Request[ep] = NULL; + + if (ep) { + ep_size[ep] = 0; + + /* Select register index for endpoint */ + MXC_USBHS->index = ep; + + /* Default to disabled */ + MXC_USBHS->intrinen &= ~(1 << ep); + MXC_USBHS->introuten &= ~(1 << ep); + + if (MXC_USBHS->incsrl & MXC_F_USBHS_INCSRL_INPKTRDY) { + /* Per musbhsfc_pg, only flush FIFO if IN packet loaded */ + MXC_USBHS->incsrl = MXC_F_USBHS_INCSRL_FLUSHFIFO; + } + MXC_USBHS->incsrl = MXC_F_USBHS_INCSRL_SENDSTALL; + + MXC_USBHS->incsru = MXC_F_USBHS_INCSRU_DPKTBUFDIS; + MXC_USBHS->inmaxp = 0; + + if (MXC_USBHS->outcsrl & MXC_F_USBHS_OUTCSRL_OUTPKTRDY) { + /* Per musbhsfc_pg, only flush FIFO if OUT packet is ready */ + MXC_USBHS->outcsrl = MXC_F_USBHS_OUTCSRL_FLUSHFIFO; + } + MXC_USBHS->outcsrl = MXC_F_USBHS_OUTCSRL_SENDSTALL; + + MXC_USBHS->outcsru = MXC_F_USBHS_OUTCSRU_DPKTBUFDIS; + MXC_USBHS->outmaxp = 0; + + MXC_SYS_Crit_Exit(); + + /* We specifically do not complete SETUP callbacks, as this causes undesired SETUP status-stage STALLs */ + if (req) { + /* complete pending requests with error */ + req->error_code = -1; + if (req->callback) { + req->callback(req->cbdata); + } + } + } else { + MXC_SYS_Crit_Exit(); + } + + return 0; +} + +int MXC_USB_Ackstat(unsigned int ep) +{ + uint32_t saved_index; + + if (ep) { + /* Only valid for endpoint 0 */ + return -1; + } + + /* Interrupts must be disabled while banked registers are accessed */ + MXC_SYS_Crit_Enter(); + + saved_index = MXC_USBHS->index; + MXC_USBHS->index = 0; + + /* On this hardware, only setup transactions with no data stage need to be explicitly ACKed */ + if (setup_phase == SETUP_NODATA) { + MXC_USBHS->csr0 |= MXC_F_USBHS_CSR0_SERV_OUTPKTRDY | MXC_F_USBHS_CSR0_DATA_END; + } + + setup_phase = SETUP_IDLE; + + MXC_USBHS->index = saved_index; + + MXC_SYS_Crit_Exit(); + + return 0; +} + +void MXC_USB_DmaIsr(void) +{ + /* Not implemented */ +} + +/* sent packet done handler*/ +static void event_in_data(uint32_t irqs) +{ + uint32_t ep, buffer_bit, data_left; + MXC_USB_Req_t *req; + unsigned int len; + + /* Loop for each data endpoint */ + for (ep = 0; ep < MXC_USBHS_NUM_EP; ep++) { + buffer_bit = (1 << ep); + if ((irqs & buffer_bit) == 0) { /* Not set, next Endpoint */ + continue; + } + + /* If an interrupt was received, but no request on this EP, ignore. */ + if (!MXC_USB_Request[ep]) { + continue; + } + + /* This function is called within interrupt context, so no need for a critical section */ + + MXC_USBHS->index = ep; + + req = MXC_USB_Request[ep]; + data_left = req->reqlen - req->actlen; + + /* Check for more data left to transmit */ + if (data_left) { + if (data_left >= ep_size[ep]) { + len = ep_size[ep]; + } else { + len = data_left; + } + + /* Fill FIFO with data */ + load_fifo(get_fifo_ptr(ep), (req->data + req->actlen), len); + req->actlen += len; + + if (!ep) { + if (MXC_USB_Request[ep]->actlen == MXC_USB_Request[ep]->reqlen) { + /* Implicit status-stage ACK, move state machine back to IDLE */ + setup_phase = SETUP_IDLE; + MXC_USBHS->csr0 |= MXC_F_USBHS_CSR0_INPKTRDY | MXC_F_USBHS_CSR0_DATA_END; + + /* free request */ + MXC_USB_Request[ep] = NULL; + + /* set done return value */ + if (req->callback) { + req->callback(req->cbdata); + } + } else { + MXC_USBHS->csr0 |= MXC_F_USBHS_CSR0_INPKTRDY; + } + } else { + /* Arm for transmit to host */ + MXC_USBHS->incsrl = MXC_F_USBHS_INCSRL_INPKTRDY; + } + + } else { + /* all done sending data */ + + /* free request */ + MXC_USB_Request[ep] = NULL; + + /* set done return value */ + if (req->callback) { + req->callback(req->cbdata); + } + } + } +} + +/* received packet */ +static void event_out_data(uint32_t irqs) +{ + uint32_t ep, buffer_bit, reqsize; + MXC_USB_Req_t *req; + + /* Loop for each data endpoint */ + for (ep = 0; ep < MXC_USBHS_NUM_EP; ep++) { + buffer_bit = (1 << ep); + if ((irqs & buffer_bit) == 0) { + continue; + } + /* If an interrupt was received, but no request on this EP, ignore. */ + if (!MXC_USB_Request[ep]) { + continue; + } + + req = MXC_USB_Request[ep]; + + /* This function is called within interrupt context, so no need for a critical section */ + + /* Select this endpoint for banked registers */ + MXC_USBHS->index = ep; + + if (!ep) { + if (!(MXC_USBHS->csr0 & MXC_F_USBHS_CSR0_OUTPKTRDY)) { + continue; + } + if (MXC_USBHS->count0 == 0) { + /* ZLP */ + MXC_USB_Request[ep] = NULL; + /* Let the callback do the status stage */ + /* call it done */ + if (req->callback) { + req->callback(req->cbdata); + } + continue; + } else { + /* Write as much as we can to the request buffer */ + reqsize = MXC_USBHS->count0; + if (reqsize > (req->reqlen - req->actlen)) { + reqsize = (req->reqlen - req->actlen); + } + } + } else { + if (!(MXC_USBHS->outcsrl & MXC_F_USBHS_OUTCSRL_OUTPKTRDY)) { + /* No packet on this endpoint? */ + continue; + } + if (MXC_USBHS->outcount == 0) { + /* ZLP */ + /* Clear out request */ + MXC_USB_Request[ep] = NULL; + + /* Signal to H/W that FIFO has been read */ + MXC_USBHS->outcsrl &= ~MXC_F_USBHS_OUTCSRL_OUTPKTRDY; + + /* Disable interrupt for this endpoint */ + MXC_USBHS->introuten &= ~(1 << ep); + + /* Complete request */ + if (req->callback) { + req->callback(req->cbdata); + } + continue; + + } else { + /* Write as much as we can to the request buffer */ + reqsize = MXC_USBHS->outcount; + if (reqsize > (req->reqlen - req->actlen)) { + reqsize = (req->reqlen - req->actlen); + } + } + } + + unload_fifo(&req->data[req->actlen], get_fifo_ptr(ep), reqsize); + + req->actlen += reqsize; + + if (!ep) { + if (req->actlen == req->reqlen) { + /* No more data */ + MXC_USBHS->csr0 |= MXC_F_USBHS_CSR0_SERV_OUTPKTRDY | MXC_F_USBHS_CSR0_DATA_END; + /* Done */ + MXC_USB_Request[ep] = NULL; + + if (req->callback) { + req->callback(req->cbdata); + } + } else { + /* More data */ + MXC_USBHS->csr0 |= MXC_F_USBHS_CSR0_SERV_OUTPKTRDY; + } + } else { + /* Signal to H/W that FIFO has been read */ + MXC_USBHS->outcsrl &= ~MXC_F_USBHS_OUTCSRL_OUTPKTRDY; + + if ((req->type == MAXUSB_TYPE_PKT) || (req->actlen == req->reqlen)) { + /* Done */ + MXC_USB_Request[ep] = NULL; + + /* Disable interrupt for this endpoint */ + MXC_USBHS->introuten &= ~(1 << ep); + + /* Complete request */ + if (req->callback) { + req->callback(req->cbdata); + } + } + } + } +} + +void MXC_USB_IrqHandler(maxusb_usbio_events_t *evt) +{ + uint32_t saved_index; + uint32_t in_flags, out_flags, MXC_USB_flags, MXC_USB_mxm_flags; + int i, aborted = 0; + uint32_t intrusb, intrusben, intrin, intrinen, introut, introuten, mxm_int, mxm_int_en; + + /* Save current index register */ + saved_index = MXC_USBHS->index; + + /* Note: Hardware clears these after read, so we must process them all or they are lost */ + /* Order of volatile accesses must be separated for IAR */ + intrusb = MXC_USBHS->intrusb; + intrusben = MXC_USBHS->intrusben; + MXC_USB_flags = intrusb & intrusben; + + intrin = MXC_USBHS->intrin; + intrinen = MXC_USBHS->intrinen; + in_flags = intrin & intrinen; + + introut = MXC_USBHS->introut; + introuten = MXC_USBHS->introuten; + out_flags = introut & introuten; + + /* These USB interrupt flags are W1C. */ + /* Order of volatile accesses must be separated for IAR */ + mxm_int = MXC_USBHS->mxm_int; + mxm_int_en = MXC_USBHS->mxm_int_en; + MXC_USB_mxm_flags = mxm_int & mxm_int_en; + MXC_USBHS->mxm_int = MXC_USB_mxm_flags; + + /* Map hardware-specific signals to generic stack events */ + evt->dpact = !!(MXC_USB_flags & MXC_F_USBHS_INTRUSB_SOF_INT); + evt->rwudn = 0; /* Not supported by this hardware */ + evt->bact = !!(MXC_USB_flags & MXC_F_USBHS_INTRUSB_SOF_INT); + evt->brst = !!(MXC_USB_flags & MXC_F_USBHS_INTRUSB_RESET_INT); + evt->susp = !!(MXC_USB_flags & MXC_F_USBHS_INTRUSB_SUSPEND_INT); + evt->novbus = !!(MXC_USB_mxm_flags & MXC_F_USBHS_MXM_INT_NOVBUS); + evt->vbus = !!(MXC_USB_mxm_flags & MXC_F_USBHS_MXM_INT_VBUS); + evt->brstdn = !!(MXC_USB_flags & MXC_F_USBHS_INTRUSB_RESET_INT); /* Hardware does not signal this, so simulate it */ + evt->sudav = 0; /* Overwritten, if necessary, below */ + + /* Handle control state machine */ + if (in_flags & MXC_F_USBHS_INTRIN_EP0_IN_INT) { + /* Select endpoint 0 */ + MXC_USBHS->index = 0; + /* Process all error conditions */ + if (MXC_USBHS->csr0 & MXC_F_USBHS_CSR0_SENT_STALL) { + /* Clear stall indication, go back to IDLE */ + MXC_USBHS->csr0 &= ~(MXC_F_USBHS_CSR0_SENT_STALL); + /* Remove this from the IN flags so that it is not erroneously processed as data */ + in_flags &= ~MXC_F_USBHS_INTRIN_EP0_IN_INT; + setup_phase = SETUP_IDLE; + aborted = 1; + } + if (MXC_USBHS->csr0 & MXC_F_USBHS_CSR0_SETUP_END) { + /* Abort pending requests, clear early end-of-control-transaction bit, go back to IDLE */ + MXC_USBHS->csr0 |= (MXC_F_USBHS_CSR0_SERV_SETUP_END); + setup_phase = SETUP_IDLE; + + /* Remove this from the IN flags so that it is not erroneously processed as data */ + in_flags &= ~MXC_F_USBHS_INTRIN_EP0_IN_INT; + MXC_USB_ResetEp(0); + aborted = 1; + } + /* Now, check for a SETUP packet */ + if (!aborted) { + if ((setup_phase == SETUP_IDLE) && (MXC_USBHS->csr0 & MXC_F_USBHS_CSR0_OUTPKTRDY)) { + /* Flag that we got a SETUP packet */ + evt->sudav = 1; + /* Remove this from the IN flags so that it is not erroneously processed as data */ + in_flags &= ~MXC_F_USBHS_INTRIN_EP0_IN_INT; + } else { + /* Otherwise, we are in endpoint 0 data IN/OUT */ + /* Fix interrupt flags so that OUTs are processed properly */ + if (setup_phase == SETUP_DATA_OUT) { + in_flags &= ~MXC_F_USBHS_INTRIN_EP0_IN_INT; + out_flags |= MXC_F_USBHS_INTRIN_EP0_IN_INT; + } + /* SETUP_NODATA is silently ignored by event_in_data() right now.. could fix this later */ + } + } + } + /* do cleanup in cases of bus reset */ + if (evt->brst) { + setup_phase = SETUP_IDLE; + /* kill any pending requests */ + for (i = 0; i < MXC_USBHS_NUM_EP; i++) { + MXC_USB_ResetEp(i); + } + /* no need to process events after reset */ + return; + } + + if (in_flags) { + event_in_data(in_flags); + } + + if (out_flags) { + event_out_data(out_flags); + } + + /* Restore register index before exiting ISR */ + MXC_USBHS->index = saved_index; +} + +int MXC_USB_IrqEnable(maxusb_event_t event) +{ + if (event >= MAXUSB_NUM_EVENTS) { + return -1; + } + + switch (event) { + case MAXUSB_EVENT_BACT: + /* Bus Active */ + MXC_USBHS->intrusben |= MXC_F_USBHS_INTRUSBEN_SOF_INT_EN; + break; + + case MAXUSB_EVENT_BRST: + /* Bus Reset */ + MXC_USBHS->intrusben |= MXC_F_USBHS_INTRUSBEN_RESET_INT_EN; + break; + + case MAXUSB_EVENT_SUSP: + /* Suspend */ + MXC_USBHS->power |= MXC_F_USBHS_POWER_EN_SUSPENDM; + MXC_USBHS->intrusben |= MXC_F_USBHS_INTRUSBEN_SUSPEND_INT_EN; + break; + + case MAXUSB_EVENT_SUDAV: + /* Setup Data Available */ + MXC_USBHS->intrinen |= MXC_F_USBHS_INTRINEN_EP0_INT_EN; + break; + + case MAXUSB_EVENT_VBUS: + /* VBUS Detect */ + MXC_USBHS->mxm_int_en |= MXC_F_USBHS_MXM_INT_EN_VBUS; + break; + + case MAXUSB_EVENT_NOVBUS: + /* NOVBUS Detect */ + MXC_USBHS->mxm_int_en |= MXC_F_USBHS_MXM_INT_EN_NOVBUS; + break; + + default: + /* Other events not supported by this hardware */ + break; + } + + return 0; +} + +int MXC_USB_IrqDisable(maxusb_event_t event) +{ + if (event >= MAXUSB_NUM_EVENTS) { + return -1; + } + + switch (event) { + case MAXUSB_EVENT_BACT: + /* Bus Active */ + MXC_USBHS->intrusben &= ~MXC_F_USBHS_INTRUSBEN_SOF_INT_EN; + break; + + case MAXUSB_EVENT_BRST: + /* Bus Reset */ + MXC_USBHS->intrusben &= ~MXC_F_USBHS_INTRUSBEN_RESET_INT_EN; + break; + + case MAXUSB_EVENT_SUSP: + /* Suspend */ + MXC_USBHS->intrusben &= ~MXC_F_USBHS_INTRUSBEN_SUSPEND_INT_EN; + MXC_USBHS->power &= ~MXC_F_USBHS_POWER_EN_SUSPENDM; + break; + + case MAXUSB_EVENT_SUDAV: + /* Setup Data Available */ + MXC_USBHS->intrinen &= ~MXC_F_USBHS_INTRINEN_EP0_INT_EN; + break; + + case MAXUSB_EVENT_VBUS: + /* VBUS Detect */ + MXC_USBHS->mxm_int_en &= ~MXC_F_USBHS_MXM_INT_EN_VBUS; + break; + + case MAXUSB_EVENT_NOVBUS: + /* NOVBUS Detect */ + MXC_USBHS->mxm_int_en &= ~MXC_F_USBHS_MXM_INT_EN_NOVBUS; + break; + + default: + /* Other events not supported by this hardware */ + break; + } + + return 0; +} + +int MXC_USB_IrqClear(maxusb_event_t event) +{ + /* No-op on this hardware, as reading the interrupt flag register clears it */ + + return 0; +} + +int MXC_USB_GetSetup(MXC_USB_SetupPkt *sud) +{ + volatile uint8_t *fifoptr = (uint8_t *)&MXC_USBHS->fifo0; + + /* Interrupts must be disabled while banked registers are accessed */ + MXC_SYS_Crit_Enter(); + + /* Select endpoint 0 */ + MXC_USBHS->index = 0; + + if ((sud == NULL) || !(MXC_USBHS->csr0 & MXC_F_USBHS_CSR0_OUTPKTRDY)) { + MXC_SYS_Crit_Exit(); + return -1; + } + + /* Pull SETUP packet out of FIFO */ + sud->bmRequestType = *fifoptr; + sud->bRequest = *fifoptr; + sud->wValue = *fifoptr; + sud->wValue += (*fifoptr) << 8; + sud->wIndex = *fifoptr; + sud->wIndex += (*fifoptr) << 8; + sud->wLength = *fifoptr; + sud->wLength += (*fifoptr) << 8; + + /* Check for follow-on data and advance state machine */ + if (sud->wLength > 0) { +#ifndef USE_ZEPHYR_USB_STACK + MXC_USBHS->csr0 |= MXC_F_USBHS_CSR0_SERV_OUTPKTRDY; +#endif + /* Determine if IN or OUT data follows */ + if (sud->bmRequestType & RT_DEV_TO_HOST) { + setup_phase = SETUP_DATA_IN; + } else { + setup_phase = SETUP_DATA_OUT; + } + } else { + /* SERV_OUTPKTRDY is set using MXC_USB_Ackstat() */ + setup_phase = SETUP_NODATA; + } + + MXC_SYS_Crit_Exit(); + return 0; +} + +int MXC_USB_SetFuncAddr(unsigned int addr) +{ + if (addr > 0x7f) { + return -1; + } + + MXC_USBHS->faddr = addr; + + return 0; +} + +MXC_USB_Req_t *MXC_USB_GetRequest(unsigned int ep) +{ + return MXC_USB_Request[ep]; +} + +int MXC_USB_RemoveRequest(MXC_USB_Req_t *req) +{ + if (req->ep >= MXC_USBHS_NUM_EP) { + return -1; + } + + if (MXC_USB_Request[req->ep] != req) { + return -1; + } + + /* Delete request */ + MXC_USB_Request[req->ep] = NULL; + + /* complete pending request with error */ + req->error_code = -1; + if (req->callback) { + req->callback(req->cbdata); + } + + return 0; +} + +int MXC_USB_WriteEndpoint(MXC_USB_Req_t *req) +{ + unsigned int ep = req->ep; + unsigned int len = req->reqlen; + unsigned int armed; + + if (ep >= MXC_USBHS_NUM_EP) { + return -1; + } + + /* EP must be enabled (configured) */ + if (!MXC_USB_IsConfigured(ep)) { + return -1; + } + + /* Interrupts must be disabled while banked registers are accessed */ + MXC_SYS_Crit_Enter(); + + MXC_USBHS->index = ep; + + /* if pending request; error */ + if (MXC_USB_Request[ep] || (MXC_USBHS->incsrl & MXC_F_USBHS_INCSRL_INPKTRDY)) { + MXC_SYS_Crit_Exit(); + return -1; + } + + /* assign req object */ + MXC_USB_Request[ep] = req; + + /* clear errors */ + req->error_code = 0; + + /* Determine if DMA can be used for this transmit */ + armed = 0; + + if (!armed) { + /* EP0 or no free DMA channel found, fall back to PIO */ + + /* Determine how many bytes to be sent */ + if (len > ep_size[ep]) { + len = ep_size[ep]; + } + MXC_USB_Request[ep]->actlen = len; + + load_fifo(get_fifo_ptr(ep), req->data, len); + + if (!ep) { + if (MXC_USB_Request[ep]->actlen == MXC_USB_Request[ep]->reqlen) { + /* Implicit status-stage ACK, move state machine back to IDLE */ + setup_phase = SETUP_IDLE; + MXC_USBHS->csr0 |= MXC_F_USBHS_CSR0_INPKTRDY | MXC_F_USBHS_CSR0_DATA_END; + } else { + MXC_USBHS->csr0 |= MXC_F_USBHS_CSR0_INPKTRDY; + } + } else { + /* Arm for transmit to host */ + MXC_USBHS->incsrl = MXC_F_USBHS_INCSRL_INPKTRDY; + } + } + + MXC_SYS_Crit_Exit(); + return 0; +} + +int MXC_USB_ReadEndpoint(MXC_USB_Req_t *req) +{ + unsigned int ep = req->ep; + uint32_t reqsize; + unsigned int armed; + + if (ep >= MXC_USBHS_NUM_EP) { + return -1; + } + + /* Interrupts must be disabled while banked registers are accessed */ + MXC_SYS_Crit_Enter(); + + /* EP must be enabled (configured) and not stalled */ + if (!MXC_USB_IsConfigured(ep)) { + MXC_SYS_Crit_Exit(); + return -1; + } + + if (MXC_USB_IsStalled(ep)) { + MXC_SYS_Crit_Exit(); + return -1; + } + + /* if pending request; error */ + if (MXC_USB_Request[ep]) { + MXC_SYS_Crit_Exit(); + return -1; + } + + /* clear errors */ + req->error_code = 0; + + /* reset length */ + req->actlen = 0; + + /* assign the req object */ + MXC_USB_Request[ep] = req; + + /* Select endpoint */ + MXC_USBHS->index = ep; + + /* Since the OUT interrupt for EP 0 doesn't really exist, only do this logic for other endpoints */ + if (ep) { + armed = 0; + + if (!armed) { + /* EP0 or no free DMA channel found, fall back to PIO */ + + /* See if data already in FIFO for this EP */ + if (MXC_USBHS->outcsrl & MXC_F_USBHS_OUTCSRL_OUTPKTRDY) { + reqsize = MXC_USBHS->outcount; + if (reqsize > (req->reqlen - req->actlen)) { + reqsize = (req->reqlen - req->actlen); + } + + unload_fifo(&req->data[req->actlen], get_fifo_ptr(ep), reqsize); + + req->actlen += reqsize; + + /* Signal to H/W that FIFO has been read */ + MXC_USBHS->outcsrl &= ~MXC_F_USBHS_OUTCSRL_OUTPKTRDY; + if ((req->type == MAXUSB_TYPE_PKT) || (req->actlen == req->reqlen)) { + /* Done with request, callback fires if configured */ + MXC_SYS_Crit_Exit(); + MXC_USB_Request[ep] = NULL; + + if (req->callback) { + req->callback(req->cbdata); + } + return 0; + } else { + /* Not done, more data requested */ + MXC_USBHS->introuten |= (1 << ep); + } + } else { + /* No data, will need an interrupt to service later */ + MXC_USBHS->introuten |= (1 << ep); + } + } + } + + MXC_SYS_Crit_Exit(); + return 0; +} + +void MXC_USB_RemoteWakeup(void) +{ + if (driver_opts.delay_us) { + MXC_USBHS->power |= MXC_F_USBHS_POWER_RESUME; + driver_opts.delay_us(10000); + MXC_USBHS->power &= ~MXC_F_USBHS_POWER_RESUME; + } +} + +int MXC_USB_TestMode(unsigned int value) +{ + const uint8_t test_packet[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, + 0xEE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xBF, 0xDF, + 0xEF, 0xF7, 0xFB, 0xFD, 0xFC, 0x7E, 0xBF, 0xDF, + 0xEF, 0xF7, 0xFB, 0xFD, 0x7E}; + + switch (value) { + case 0x01: + /* Test_J */ + MXC_USBHS->testmode = MXC_F_USBHS_TESTMODE_TEST_J; + break; + case 0x02: + /* Test_K */ + MXC_USBHS->testmode = MXC_F_USBHS_TESTMODE_TEST_K; + break; + case 0x03: + /* Test_SE0_NAK */ + MXC_USBHS->testmode = MXC_F_USBHS_TESTMODE_TEST_SE0_NAK; + break; + case 0x04: + /* Test_Packet */ + /* Load EP 0 with data provided by section 11.4 of musbhsfc_pg.pdf */ + /* sizeof() considered safe, since we use uint8_t explicitly */ + load_fifo(get_fifo_ptr(0), (uint8_t*)test_packet, sizeof(test_packet)); + MXC_USBHS->csr0 |= MXC_F_USBHS_CSR0_INPKTRDY; + MXC_USBHS->testmode = MXC_F_USBHS_TESTMODE_TEST_PKT; + break; + default: + /* Unsupported */ + return -1; + } + + return 0; +} diff --git a/MAX/Libraries/MAXUSB/src/core/musbhsfc/usbhs_reva.svd b/MAX/Libraries/MAXUSB/src/core/musbhsfc/usbhs_reva.svd new file mode 100644 index 00000000..44c0abc4 --- /dev/null +++ b/MAX/Libraries/MAXUSB/src/core/musbhsfc/usbhs_reva.svd @@ -0,0 +1,1687 @@ + + + + USBHS + USB 2.0 High-speed Controller. + 0x400B1000 + + 0 + 0x1000 + registers + + + USB + 2 + + + + FADDR + Function address register. + 0x00 + 8 + 0x00 + + + ADDR + Function address for this controller. + 0 + 7 + read-write + + + UPDATE + Set when ADDR is written, cleared when new address takes effect. + 7 + 1 + read-only + + + + + POWER + Power management register. + 0x01 + 8 + + + EN_SUSPENDM + Enable SUSPENDM signal. + 0 + 1 + read-write + + + SUSPEND + Suspend mode detected. + 1 + 1 + read-only + + + RESUME + Generate resume signaling. + 2 + 1 + read-write + + + RESET + Bus reset detected. + 3 + 1 + read-only + + + HS_MODE + High-speed mode detected. + 4 + 1 + read-only + + + HS_ENABLE + High-speed mode enable. + 5 + 1 + read-write + + + SOFTCONN + Softconn. + 6 + 1 + read-write + + + ISO_UPDATE + Wait for SOF during Isochronous xfers. + 7 + 1 + read-write + + + + + INTRIN + Interrupt register for EP0 and IN EP1-15. + 0x02 + 16 + + + EP15_IN_INT + Endpoint 15 interrupt. + 15 + 1 + read-only + + + EP14_IN_INT + Endpoint 14 interrupt. + 14 + 1 + read-only + + + EP13_IN_INT + Endpoint 13 interrupt. + 13 + 1 + read-only + + + EP12_IN_INT + Endpoint 12 interrupt. + 12 + 1 + read-only + + + EP11_IN_INT + Endpoint 11 interrupt. + 11 + 1 + read-only + + + EP10_IN_INT + Endpoint 10 interrupt. + 10 + 1 + read-only + + + EP9_IN_INT + Endpoint 9 interrupt. + 9 + 1 + read-only + + + EP8_IN_INT + Endpoint 8 interrupt. + 8 + 1 + read-only + + + EP7_IN_INT + Endpoint 7 interrupt. + 7 + 1 + read-only + + + EP6_IN_INT + Endpoint 6 interrupt. + 6 + 1 + read-only + + + EP5_IN_INT + Endpoint 5 interrupt. + 5 + 1 + read-only + + + EP4_IN_INT + Endpoint 4 interrupt. + 4 + 1 + read-only + + + EP3_IN_INT + Endpoint 3 interrupt. + 3 + 1 + read-only + + + EP2_IN_INT + Endpoint 2 interrupt. + 2 + 1 + read-only + + + EP1_IN_INT + Endpoint 1 interrupt. + 1 + 1 + read-only + + + EP0_IN_INT + Endpoint 0 interrupt. + 0 + 1 + read-only + + + + + INTROUT + Interrupt register for OUT EP 1-15. + 0x04 + 16 + + + EP15_OUT_INT + Endpoint 15 interrupt. + 15 + 1 + read-only + + + EP14_OUT_INT + Endpoint 14 interrupt. + 14 + 1 + read-only + + + EP13_OUT_INT + Endpoint 13 interrupt. + 13 + 1 + read-only + + + EP12_OUT_INT + Endpoint 12 interrupt. + 12 + 1 + read-only + + + EP11_OUT_INT + Endpoint 11 interrupt. + 11 + 1 + read-only + + + EP10_OUT_INT + Endpoint 10 interrupt. + 10 + 1 + read-only + + + EP9_OUT_INT + Endpoint 9 interrupt. + 9 + 1 + read-only + + + EP8_OUT_INT + Endpoint 8 interrupt. + 8 + 1 + read-only + + + EP7_OUT_INT + Endpoint 7 interrupt. + 7 + 1 + read-only + + + EP6_OUT_INT + Endpoint 6 interrupt. + 6 + 1 + read-only + + + EP5_OUT_INT + Endpoint 5 interrupt. + 5 + 1 + read-only + + + EP4_OUT_INT + Endpoint 4 interrupt. + 4 + 1 + read-only + + + EP3_OUT_INT + Endpoint 3 interrupt. + 3 + 1 + read-only + + + EP2_OUT_INT + Endpoint 2 interrupt. + 2 + 1 + read-only + + + EP1_OUT_INT + Endpoint 1 interrupt. + 1 + 1 + read-only + + + + + INTRINEN + Interrupt enable for EP 0 and IN EP 1-15. + 0x06 + 16 + + + EP15_IN_INT_EN + Endpoint 15 interrupt enable. + 15 + 1 + read-write + + + EP14_IN_INT_EN + Endpoint 14 interrupt enable. + 14 + 1 + read-write + + + EP13_IN_INT_EN + Endpoint 13 interrupt enable. + 13 + 1 + read-write + + + EP12_IN_INT_EN + Endpoint 12 interrupt enable. + 12 + 1 + read-write + + + EP11_IN_INT_EN + Endpoint 11 interrupt enable. + 11 + 1 + read-write + + + EP10_IN_INT_EN + Endpoint 10 interrupt enable. + 10 + 1 + read-write + + + EP9_IN_INT_EN + Endpoint 9 interrupt enable. + 9 + 1 + read-write + + + EP8_IN_INT_EN + Endpoint 8 interrupt enable. + 8 + 1 + read-write + + + EP7_IN_INT_EN + Endpoint 7 interrupt enable. + 7 + 1 + read-write + + + EP6_IN_INT_EN + Endpoint 6 interrupt enable. + 6 + 1 + read-write + + + EP5_IN_INT_EN + Endpoint 5 interrupt enable. + 5 + 1 + read-write + + + EP4_IN_INT_EN + Endpoint 4 interrupt enable. + 4 + 1 + read-write + + + EP3_IN_INT_EN + Endpoint 3 interrupt enable. + 3 + 1 + read-write + + + EP2_IN_INT_EN + Endpoint 2 interrupt enable. + 2 + 1 + read-write + + + EP1_IN_INT_EN + Endpoint 1 interrupt enable. + 1 + 1 + read-write + + + EP0_INT_EN + Endpoint 0 interrupt enable. + 0 + 1 + read-write + + + + + INTROUTEN + Interrupt enable for OUT EP 1-15. + 0x08 + 16 + + + EP15_OUT_INT_EN + Endpoint 15 interrupt. + 15 + 1 + read-write + + + EP14_OUT_INT_EN + Endpoint 14 interrupt. + 14 + 1 + read-write + + + EP13_OUT_INT_EN + Endpoint 13 interrupt. + 13 + 1 + read-write + + + EP12_OUT_INT_EN + Endpoint 12 interrupt. + 12 + 1 + read-write + + + EP11_OUT_INT_EN + Endpoint 11 interrupt. + 11 + 1 + read-write + + + EP10_OUT_INT_EN + Endpoint 10 interrupt. + 10 + 1 + read-write + + + EP9_OUT_INT_EN + Endpoint 9 interrupt. + 9 + 1 + read-write + + + EP8_OUT_INT_EN + Endpoint 8 interrupt. + 8 + 1 + read-write + + + EP7_OUT_INT_EN + Endpoint 7 interrupt. + 7 + 1 + read-write + + + EP6_OUT_INT_EN + Endpoint 6 interrupt. + 6 + 1 + read-write + + + EP5_OUT_INT_EN + Endpoint 5 interrupt. + 5 + 1 + read-write + + + EP4_OUT_INT_EN + Endpoint 4 interrupt. + 4 + 1 + read-write + + + EP3_OUT_INT_EN + Endpoint 3 interrupt. + 3 + 1 + read-write + + + EP2_OUT_INT_EN + Endpoint 2 interrupt. + 2 + 1 + read-write + + + EP1_OUT_INT_EN + Endpoint 1 interrupt. + 1 + 1 + read-write + + + + + INTRUSB + Interrupt register for common USB interrupts. + 0x0A + 8 + + + SOF_INT + Start of Frame. + 3 + 1 + read-only + + + RESET_INT + Bus reset detected. + 2 + 1 + read-only + + + RESUME_INT + Resume detected. + 1 + 1 + read-only + + + SUSPEND_INT + Suspend detected. + 0 + 1 + read-only + + + + + INTRUSBEN + Interrupt enable for common USB interrupts. + 0x0B + 8 + + + SOF_INT_EN + Start of Frame. + 3 + 1 + read-write + + + RESET_INT_EN + Bus reset detected. + 2 + 1 + read-write + + + RESUME_INT_EN + Resume detected. + 1 + 1 + read-write + + + SUSPEND_INT_EN + Suspend detected. + 0 + 1 + read-write + + + + + FRAME + Frame number. + 0x0C + 16 + + + FRAMENUM + Read the last received frame number, that is the 11-bit frame number received in the SOF packet. + 0 + 11 + read-only + + + + + INDEX + Index for banked registers. + 0x0E + 8 + + + INDEX + Index Register Access Selector. + 0 + 4 + read-write + + + + + TESTMODE + USB 2.0 test mode enable register. + 0x0F + 8 + + + FORCE_FS + Force USB to Full-speed after reset. + 5 + 1 + read-write + + + FORCE_HS + Force USB to High-speed after reset. + 4 + 1 + read-write + + + TEST_PKT + Transmit fixed test packet. + 3 + 1 + read-write + + + TEST_K + Force USB to continuous K state. + 2 + 1 + read-write + + + TEST_J + Force USB to continuous J state. + 1 + 1 + read-write + + + TEST_SE0_NAK + Respond to any valid IN token with NAK. + 0 + 1 + read-write + + + + + INMAXP + Maximum packet size for INx endpoint (x == INDEX). + 0x10 + 16 + + + MAXPACKETSIZE + Maximum Packet Size in a Single Transaction. That is the maximum packet size in bytes, that is transmitted for each microframe. The maximum value is 1024, subject to the limitations of the endpoint type set in USB 2.0 Specification, Chapter 9 + 0 + 11 + + + NUMPACKMINUS1 + Number of Split Packets - 1. Defines the maximum number of packets minus 1 that a USB payload can be split into. THis must be an exact multiple of maxpacketsize. Only applicable for HS High-Bandwidth isochronous endpoints and Bulk endpoints. Ignored in all other cases. + 11 + 5 + + + + + CSR0 + Control status register for EP 0 (when INDEX == 0). + 0x12 + 8 + + + SERV_SETUP_END + Clear EP0 Setup End Bit. Write a 1 to clear the setupend bit. Automatically cleared after being set + 7 + 1 + read-write + + + SERV_OUTPKTRDY + Clear EP0 Out Packet Ready Bit. Write a 1 to clear the outpktrdy bit. Automatically cleared after being set. + 6 + 1 + read-write + + + SEND_STALL + Send EP0 STALL Handshake. Write a 1 to this bit to terminate the current control transaction by sneding a STALL handshake. Automatically cleared after being set. + 5 + 1 + read-write + + + SETUP_END + Read Setup End Status. Automatically set when a contorl transaction ends before the dataend bit has been set by fimrware. An interrupt is generated when this bit is set. Write 1 to servicedsetupend to clear. + 4 + 1 + read-only + + + DATA_END + Control Transaction Data End. Write a 1 to this bit after firmware completes any of the following three transactions: 1. set inpktrdy = 1 for the last data packet. 2. Set inpktrdy =1 for a zero-length data packet. 3. Clear outpktrdy = 0 after unloading the last data packet. + 3 + 1 + read-write + + + SENT_STALL + Read EP0 STALL Handshake Sent Status Automatically set when a STALL handshake is transmitted. Write a 0 to clear. + 2 + 1 + read-write + + + INPKTRDY + EP0 IN Packet Ready 1: Write a 1 after writing a data packet to the IN FIFO. Automatically cleared when the data packet is transmitted. An interrupt is generated when this bit is cleared. + 1 + 1 + read-write + + + OUTPKTRDY + EP0 OUT Packet Ready Status Automatically set when a data packet is received in the OUT FIFO. An interrupt is generated when this bit is set. Write a 1 to the servicedoutpktrdy bit (above) to clear after the packet is unloaded from the OUT FIFO. + 0 + 1 + read-only + + + + + INCSRL + Control status lower register for INx endpoint (x == INDEX). + CSR0 + 0x12 + 8 + + + INCOMPTX + Read Incomplete Split Transfer Error Status High-bandwidth isochronous transfers: Automatically set when a payload is split into multiple packets but insufficient IN tokens were received to send all packets. The current packets is flushed from the IN FIFO. Write 0 to clear. + 7 + 1 + read-write + + + CLRDATATOG + Write 1 to clear IN endpoint data-toggle to 0. + 6 + 1 + read-write + + + SENTSTALL + Read STALL Handshake Sent Status Automatically set when a STALL handshake is transmitted, at which time the IN FIFO is flushed, and inpktrdy is cleared. Write 0 to clear. + 5 + 1 + read-write + + + SENDSTALL + Send STALL Handshake. + 4 + 1 + read-only + + + terminate + Terminate STALL handhsake + 0 + + + respond + Respond to an IN token with a STALL handshake + 1 + + + + + FLUSHFIFO + Flush Next Packet from IN FIFO. Write 1 to clear + 3 + 1 + read-write + + + UNDERRUN + Read IN FIFO Underrun Error Status Isochronous Mode: Automatically set if the IN FIFO is empty. Write 0 to clear + 2 + 1 + read-write + + + FIFONOTEMPTY + Read FIFO Not Empty Status. Automatically set when there is at least one packet in the IN FIFO. Write a 0 to clear. + 1 + 1 + read-write + + + INPKTRDY + IN Packet Ready. Write a 1 to clear + 0 + 1 + read-only + + + + + INCSRU + Control status upper register for INx endpoint (x == INDEX). + 0x13 + 8 + + + AUTOSET + Auto Set inpktrdy. + 7 + 1 + read-write + + + set + USBHS_INCSRL_inpktrdy must be set by firmware. + 0 + + + auto + USBHS_INCSRL_inpktrdy is automatically set. + 1 + + + + + ISO + Isochronous Transfer Enable + 6 + 1 + read-write + + + interrupt + Enable IN Bulk and IN interrupt transfers. + 0 + + + isochronous + Enable IN Isochronous transfers. + 1 + + + + + MODE + Endpoint Direction Mode. + 5 + 1 + read-write + + + out + Endpoint direction is OUT. + 0 + + + in + Endpoint direction is IN. + 1 + + + + + FRCDATATOG + Force In Data - Toggle + 3 + 1 + read-write + + + received + Toggle data-toglge only when an ACK is received. + 0 + + + dontcare + Toggle data-toggle regardless of ACK. + 1 + + + + + DPKTBUFDIS + Double Packet Buffering Disable + 1 + 1 + read-write + + + en + Enable Double packet buffering. + 0 + + + dis + Disable Double Packet Buffering. + 1 + + + + + + + OUTMAXP + Maximum packet size for OUTx endpoint (x == INDEX). + 0x14 + 16 + + + NUMPACKMINUS1 + Number of Split Packets -1. Defines the maximum number of packets - 1 that a usb payload is combined into. The value must be exact multiple of maxpacketsize. + 11 + 5 + + + MAXPACKETSIZE + Maximum Packet in a Single Transaction. This is the maximum packet size, in bytes, that is transmitted for each microframe. The maximum value is 1024, subject to the limitations for the endpoint type set in USB2.0 spesification, chapter 9. + 0 + 11 + + + + + OUTCSRL + Control status lower register for OUTx endpoint (x == INDEX). + 0x16 + 8 + + + CLRDATATOG + 7 + 1 + read-write + + + SENTSTALL + 6 + 1 + read-write + + + SENDSTALL + 5 + 1 + read-write + + + FLUSHFIFO + 4 + 1 + read-write + + + DATAERROR + 3 + 1 + read-only + + + OVERRUN + 2 + 1 + read-write + + + FIFOFULL + 1 + 1 + read-only + + + OUTPKTRDY + 0 + 1 + read-write + + + + + OUTCSRU + Control status upper register for OUTx endpoint (x == INDEX). + 0x17 + 8 + + + AUTOCLEAR + 7 + 1 + read-write + + + ISO + 6 + 1 + read-write + + + DISNYET + 4 + 1 + read-write + + + DPKTBUFDIS + 1 + 1 + read-write + + + INCOMPRX + 0 + 1 + read-only + + + + + COUNT0 + Number of received bytes in EP 0 FIFO (INDEX == 0). + 0x18 + 16 + + + COUNT0 + Read Number of Data Bytes in the Endpoint 0 FIFO. Returns the number of data bytes in the endpoint 0 FIFO. This value changes as contents of the FIFO change. The value is only valued when USBHS_OUTSCRL_outpktrdy = 1 + 0 + 7 + read-only + + + + + OUTCOUNT + Number of received bytes in OUT EPx FIFO (x == INDEX). + COUNT0 + 0x18 + 16 + + + OUTCOUNT + Read Number of Data Bytes in OUT FIFO. Returns the number of data bytes in the packet that are read next in the OUT FIFO. + 0 + 13 + read-only + + + + + FIFO0 + Read for OUT data FIFO, write for IN data FIFO. + 0x20 + + + USBHS_FIFO0 + USBHS Endpoint FIFO Read/Write Register. + 0 + 32 + + + + + FIFO1 + Read for OUT data FIFO, write for IN data FIFO. + 0x24 + + + USBHS_FIFO1 + USBHS Endpoint FIFO Read/Write Register. + 0 + 32 + + + + + FIFO2 + Read for OUT data FIFO, write for IN data FIFO. + 0x28 + + + USBHS_FIFO2 + USBHS Endpoint FIFO Read/Write Register. + 0 + 32 + + + + + FIFO3 + Read for OUT data FIFO, write for IN data FIFO. + 0x2c + + + USBHS_FIFO3 + USBHS Endpoint FIFO Read/Write Register. + 0 + 32 + + + + + FIFO4 + Read for OUT data FIFO, write for IN data FIFO. + 0x30 + + + USBHS_FIFO4 + USBHS Endpoint FIFO Read/Write Register. + 0 + 32 + + + + + FIFO5 + Read for OUT data FIFO, write for IN data FIFO. + 0x34 + + + USBHS_FIFO5 + USBHS Endpoint FIFO Read/Write Register. + 0 + 32 + + + + + FIFO6 + Read for OUT data FIFO, write for IN data FIFO. + 0x38 + + + USBHS_FIFO6 + USBHS Endpoint FIFO Read/Write Register. + 0 + 32 + + + + + FIFO7 + Read for OUT data FIFO, write for IN data FIFO. + 0x3c + + + USBHS_FIFO7 + USBHS Endpoint FIFO Read/Write Register. + 0 + 32 + + + + + FIFO8 + Read for OUT data FIFO, write for IN data FIFO. + 0x40 + + + USBHS_FIFO8 + USBHS Endpoint FIFO Read/Write Register. + 0 + 32 + + + + + FIFO9 + Read for OUT data FIFO, write for IN data FIFO. + 0x44 + + + USBHS_FIFO9 + USBHS Endpoint FIFO Read/Write Register. + 0 + 32 + + + + + FIFO10 + Read for OUT data FIFO, write for IN data FIFO. + 0x48 + + + USBHS_FIFO10 + USBHS Endpoint FIFO Read/Write Register. + 0 + 32 + + + + + FIFO11 + Read for OUT data FIFO, write for IN data FIFO. + 0x4c + + + USBHS_FIFO11 + USBHS Endpoint FIFO Read/Write Register. + 0 + 32 + + + + + FIFO12 + Read for OUT data FIFO, write for IN data FIFO. + 0x50 + + + USBHS_FIFO12 + USBHS Endpoint FIFO Read/Write Register. + 0 + 32 + + + + + FIFO13 + Read for OUT data FIFO, write for IN data FIFO. + 0x54 + + + USBHS_FIFO13 + USBHS Endpoint FIFO Read/Write Register. + 0 + 32 + + + + + FIFO14 + Read for OUT data FIFO, write for IN data FIFO. + 0x58 + + + USBHS_FIFO14 + USBHS Endpoint FIFO Read/Write Register. + 0 + 32 + + + + + FIFO15 + Read for OUT data FIFO, write for IN data FIFO. + 0x5c + + + USBHS_FIFO15 + USBHS Endpoint FIFO Read/Write Register. + 0 + 32 + + + + + HWVERS + HWVERS + 0x6c + 16 + + + USBHS_HWVERS + USBHS Register. + 0 + 16 + + + + + EPINFO + Endpoint hardware information. + 0x78 + 8 + + + OUTENDPOINTS + 4 + 4 + read-only + + + INTENDPOINTS + 0 + 4 + read-only + + + + + RAMINFO + RAM width information. + 0x79 + 8 + + + RAMBITS + 0 + 4 + read-only + + + + + SOFTRESET + Software reset register. + 0x7A + 8 + + + RSTXS + 1 + 1 + read-write + + + RSTS + 0 + 1 + read-write + + + + + CTUCH + Chirp timeout timer setting. + 0x80 + 16 + + + C_T_UCH + HS Chirp Timeout Clock Cycles. This configures the chirp timeout used by this device to negotiate a HS connection with a FS Host. + 0 + 16 + + + + + CTHSRTN + Sets delay between HS resume to UTM normal operating mode. + 0x82 + 16 + + + C_T_HSTRN + High Speed Resume Delay Clock Cycles. This configures the delay from when the RESUME state on the bus ends, the when the USBHS resumes normal operation. + 0 + 16 + + + + + MXM_USB_REG_00 + MXM_USB_REG_00 + 0x400 + + + M31_PHY_UTMI_RESET + M31_PHY_UTMI_RESET + 0x404 + + + M31_PHY_UTMI_VCONTROL + M31_PHY_UTMI_VCONTROL + 0x408 + + + M31_PHY_CLK_EN + M31_PHY_CLK_EN + 0x40C + + + M31_PHY_PONRST + M31_PHY_PONRST + 0x410 + + + M31_PHY_NONCRY_RSTB + M31_PHY_NONCRY_RSTB + 0x414 + + + M31_PHY_NONCRY_EN + M31_PHY_NONCRY_EN + 0x418 + + + M31_PHY_U2_COMPLIANCE_EN + M31_PHY_U2_COMPLIANCE_EN + 0x420 + + + M31_PHY_U2_COMPLIANCE_DAC_ADJ + M31_PHY_U2_COMPLIANCE_DAC_ADJ + 0x424 + + + M31_PHY_U2_COMPLIANCE_DAC_ADJ_EN + M31_PHY_U2_COMPLIANCE_DAC_ADJ_EN + 0x428 + + + M31_PHY_CLK_RDY + M31_PHY_CLK_RDY + 0x42C + + + M31_PHY_PLL_EN + M31_PHY_PLL_EN + 0x430 + + + M31_PHY_BIST_OK + M31_PHY_BIST_OK + 0x434 + + + M31_PHY_DATA_OE + M31_PHY_DATA_OE + 0x438 + + + M31_PHY_OSCOUTEN + M31_PHY_OSCOUTEN + 0x43C + + + M31_PHY_LPM_ALIVE + M31_PHY_LPM_ALIVE + 0x440 + + + M31_PHY_HS_BIST_MODE + M31_PHY_HS_BIST_MODE + 0x444 + + + M31_PHY_CORECLKIN + M31_PHY_CORECLKIN + 0x448 + + + M31_PHY_XTLSEL + M31_PHY_XTLSEL + 0x44C + + + M31_PHY_LS_EN + M31_PHY_LS_EN + 0x450 + + + M31_PHY_DEBUG_SEL + M31_PHY_DEBUG_SEL + 0x454 + + + M31_PHY_DEBUG_OUT + M31_PHY_DEBUG_OUT + 0x458 + + + M31_PHY_OUTCLKSEL + M31_PHY_OUTCLKSEL + 0x45C + + + M31_PHY_XCFGI_31_0 + M31_PHY_XCFGI_31_0 + 0x460 + + + M31_PHY_XCFGI_63_32 + M31_PHY_XCFGI_63_32 + 0x464 + + + M31_PHY_XCFGI_95_64 + M31_PHY_XCFGI_95_64 + 0x468 + + + M31_PHY_XCFGI_127_96 + M31_PHY_XCFGI_127_96 + 0x46C + + + M31_PHY_XCFGI_137_128 + M31_PHY_XCFGI_137_128 + 0x470 + + + M31_PHY_XCFG_HS_COARSE_TUNE_NUM + M31_PHY_XCFG_HS_COARSE_TUNE_NUM + 0x474 + + + M31_PHY_XCFG_HS_FINE_TUNE_NUM + M31_PHY_XCFG_HS_FINE_TUNE_NUM + 0x478 + + + M31_PHY_XCFG_FS_COARSE_TUNE_NUM + M31_PHY_XCFG_FS_COARSE_TUNE_NUM + 0x47C + + + M31_PHY_XCFG_FS_FINE_TUNE_NUM + M31_PHY_XCFG_FS_FINE_TUNE_NUM + 0x480 + + + M31_PHY_XCFG_LOCK_RANGE_MAX + M31_PHY_XCFG_LOCK_RANGE_MAX + 0x484 + + + M31_PHY_XCFGI_LOCK_RANGE_MIN + M31_PHY_XCFGI_LOCK_RANGE_MIN + 0x488 + + + M31_PHY_XCFG_OB_RSEL + M31_PHY_XCFG_OB_RSEL + 0x48C + + + M31_PHY_XCFG_OC_RSEL + M31_PHY_XCFG_OC_RSEL + 0x490 + + + M31_PHY_XCFGO + M31_PHY_XCFGO + 0x494 + + + MXM_INT + USB Added Maxim Interrupt Flag Register. + 0x498 + + + VBUS + VBUS + 0 + 1 + + + NOVBUS + NOVBUS + 1 + 1 + + + + + MXM_INT_EN + USB Added Maxim Interrupt Enable Register. + 0x49C + + + VBUS + VBUS + 0 + 1 + + + NOVBUS + NOVBUS + 1 + 1 + + + + + MXM_SUSPEND + USB Added Maxim Suspend Register. + 0x4A0 + + + SEL + Suspend register + 0 + 1 + + + + + MXM_REG_A4 + USB Added Maxim Power Status Register + 0x4A4 + + + VRST_VDDB_N_A + VRST_VDDB_N_A + 0 + 1 + + + + + + + \ No newline at end of file diff --git a/MAX/Libraries/MAXUSB/src/core/usb_event.c b/MAX/Libraries/MAXUSB/src/core/usb_event.c new file mode 100644 index 00000000..032aebb2 --- /dev/null +++ b/MAX/Libraries/MAXUSB/src/core/usb_event.c @@ -0,0 +1,119 @@ +/****************************************************************************** + * + * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. (now owned by + * Analog Devices, Inc.), + * Copyright (C) 2023-2024 Analog Devices, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#include +#include "usb.h" +#include "usb_event.h" + +/***** File Scope Data *****/ +static maxusb_usbio_events_t events; +static MXC_USB_event_callback_t callback[MAXUSB_NUM_EVENTS]; + +/******************************************************************************/ +int MXC_USB_EventEnable(maxusb_event_t event, int (*func)(maxusb_event_t, void *), void *cbdata) +{ + if ( (event >= MAXUSB_NUM_EVENTS) || (func == NULL) ) { + return -1; + } + + callback[event].func = func; + callback[event].cbdata = cbdata; + + return MXC_USB_IrqEnable(event); +} + +/******************************************************************************/ +int MXC_USB_EventDisable(maxusb_event_t event) +{ + int result = -1; + + if (event >= MAXUSB_NUM_EVENTS) { + return -1; + } + + result = MXC_USB_IrqDisable(event); + + callback[event].func = NULL; + callback[event].cbdata = NULL; + + return result; +} + +/******************************************************************************/ +int MXC_USB_EventClear(maxusb_event_t event) +{ + if (event >= MAXUSB_NUM_EVENTS) { + return -1; + } + + return MXC_USB_IrqClear(event); +} + +/******************************************************************************/ +void MXC_USB_EventHandler(void) +{ + MXC_USB_IrqHandler(&events); + + if (events.novbus && callback[MAXUSB_EVENT_NOVBUS].func) + { + callback[MAXUSB_EVENT_NOVBUS].func(MAXUSB_EVENT_NOVBUS, callback[MAXUSB_EVENT_NOVBUS].cbdata); + } + + if (events.vbus && callback[MAXUSB_EVENT_VBUS].func) + { + callback[MAXUSB_EVENT_VBUS].func(MAXUSB_EVENT_VBUS, callback[MAXUSB_EVENT_VBUS].cbdata); + } + + if (events.brst && callback[MAXUSB_EVENT_BRST].func) + { + callback[MAXUSB_EVENT_BRST].func(MAXUSB_EVENT_BRST, callback[MAXUSB_EVENT_BRST].cbdata); + } + + if (events.brstdn && callback[MAXUSB_EVENT_BRSTDN].func) + { + callback[MAXUSB_EVENT_BRSTDN].func(MAXUSB_EVENT_BRSTDN, callback[MAXUSB_EVENT_BRSTDN].cbdata); + } + + if (events.dpact && callback[MAXUSB_EVENT_DPACT].func) + { + callback[MAXUSB_EVENT_DPACT].func(MAXUSB_EVENT_DPACT, callback[MAXUSB_EVENT_DPACT].cbdata); + } + + if (events.rwudn && callback[MAXUSB_EVENT_RWUDN].func) + { + callback[MAXUSB_EVENT_RWUDN].func(MAXUSB_EVENT_RWUDN, callback[MAXUSB_EVENT_RWUDN].cbdata); + } + + if (events.bact && callback[MAXUSB_EVENT_BACT].func) + { + callback[MAXUSB_EVENT_BACT].func(MAXUSB_EVENT_BACT, callback[MAXUSB_EVENT_BACT].cbdata); + } + + if (events.susp && callback[MAXUSB_EVENT_SUSP].func) + { + callback[MAXUSB_EVENT_SUSP].func(MAXUSB_EVENT_SUSP, callback[MAXUSB_EVENT_SUSP].cbdata); + } + + if (events.sudav && callback[MAXUSB_EVENT_SUDAV].func) + { + callback[MAXUSB_EVENT_SUDAV].func(MAXUSB_EVENT_SUDAV, callback[MAXUSB_EVENT_SUDAV].cbdata); + } +} +/** */ diff --git a/MAX/msdk_sha b/MAX/msdk_sha index 420ddc26..f1914810 100644 --- a/MAX/msdk_sha +++ b/MAX/msdk_sha @@ -1 +1 @@ -1d174f0be31a18c3bbe829af7fa3d774495e7046 +1b95c3c0d3cedfa086518f2c628723007cac838d