- basic docs added
- doxygen styling added - CDC -> ACM refactor - type refactoring - examples categorized - flatUSB_config.h examples added
This commit is contained in:
		
							parent
							
								
									685fa77bda
								
							
						
					
					
						commit
						2a69c57225
					
				
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					docs/html/
 | 
				
			||||||
@ -10,8 +10,8 @@ endif()
 | 
				
			|||||||
set(FLATUSB_CLASSES_SRC "")
 | 
					set(FLATUSB_CLASSES_SRC "")
 | 
				
			||||||
if ("CDC_ACM" IN_LIST FLATUSB_CLASSES)
 | 
					if ("CDC_ACM" IN_LIST FLATUSB_CLASSES)
 | 
				
			||||||
    list(APPEND FLATUSB_CLASSES_SRC
 | 
					    list(APPEND FLATUSB_CLASSES_SRC
 | 
				
			||||||
        class/cdc.c
 | 
					        class/acm.c
 | 
				
			||||||
        class/cdc.h
 | 
					        class/acm.h
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -73,3 +73,9 @@ if (FLATUSB_DESC_JSON AND FLATUSB_DESC_DIR)
 | 
				
			|||||||
        WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
 | 
					        WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_custom_target(
 | 
				
			||||||
 | 
					    flatUSB-docs
 | 
				
			||||||
 | 
					    COMMAND doxygen
 | 
				
			||||||
 | 
					    WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										158
									
								
								class/acm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								class/acm.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,158 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 ******************************************************************************
 | 
				
			||||||
 | 
					 * @file    cdc.c
 | 
				
			||||||
 | 
					 * @copyright András Wiesner, 2024-\showdate "%Y"
 | 
				
			||||||
 | 
					 * @brief   CDC ACM implementation module for the flatUSB project.
 | 
				
			||||||
 | 
					 ******************************************************************************
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "acm.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <memory.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../usb.h"
 | 
				
			||||||
 | 
					#include "../usb_device_types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <blocking_io/blocking_fifo.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// -------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static Usb_AcmState acms = {0};                 ///< ACM module state
 | 
				
			||||||
 | 
					static uint8_t tx_buffer[USB_ACM_PCKT_BUFSIZE]; ///< Transmit buffer
 | 
				
			||||||
 | 
					static uint8_t fifo_mem[USB_ACM_FIFO_MEM_SIZE]; ///< Memory assigned to the TX BFifo
 | 
				
			||||||
 | 
					static BFifo fifo;                              ///< TX Blocking FIFO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// -------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_acm_read_callback(const uint8_t *data, uint32_t size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_acm_init(const Usb_Acm_EpAssignments *as) {
 | 
				
			||||||
 | 
					    // clear the structure
 | 
				
			||||||
 | 
					    memset(&acms, 0, sizeof(Usb_AcmState));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // set Control Line State to something invalid
 | 
				
			||||||
 | 
					    acms.control_line_state.D = USB_ACM_INVALID_CONTROL_LINE_STATE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // fill-in assigments
 | 
				
			||||||
 | 
					    acms.ep_assignments = *as;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // initialize buffer
 | 
				
			||||||
 | 
					    bfifo_create(&fifo, fifo_mem, USB_ACM_FIFO_MEM_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // initialize an all-0 interrupt
 | 
				
			||||||
 | 
					    acms.interrupt_data = 0;
 | 
				
			||||||
 | 
					    acms.interrupt_pending = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // communication parameters have not been set
 | 
				
			||||||
 | 
					    acms.commInit = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // from now on CDC module is considered initialized
 | 
				
			||||||
 | 
					    acms.moduleInit = true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void usb_cdc_review_comm_init() {
 | 
				
			||||||
 | 
					    // check if line coding was initialized
 | 
				
			||||||
 | 
					    Usb_Acm_LineCodingStruct *lc = &acms.line_coding;
 | 
				
			||||||
 | 
					    bool lcOk = (lc->dwDTERate != 0) && (lc->bDataBits != 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // check if control line state was initialized
 | 
				
			||||||
 | 
					    bool clsOk = acms.control_line_state.D != USB_ACM_INVALID_CONTROL_LINE_STATE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // combine the above criteria
 | 
				
			||||||
 | 
					    acms.commInit = lcOk && clsOk;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int usb_acm_process_and_return(Usb_CallbackEvent *cbevt) {
 | 
				
			||||||
 | 
					    int ret = -1;
 | 
				
			||||||
 | 
					    switch (cbevt->type) {
 | 
				
			||||||
 | 
					    case USB_CBEVT_UNKNOWN_REQ: {
 | 
				
			||||||
 | 
					        // initialize reply
 | 
				
			||||||
 | 
					        cbevt->reply_data = NULL;
 | 
				
			||||||
 | 
					        cbevt->reply_size = 0;
 | 
				
			||||||
 | 
					        cbevt->reply_valid = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        switch (cbevt->setup_request->bRequest) {
 | 
				
			||||||
 | 
					        case USB_ACM_SET_LINE_CODING: // set line coding
 | 
				
			||||||
 | 
					            memcpy(&acms.line_coding, cbevt->data, sizeof(Usb_Acm_LineCodingStruct));
 | 
				
			||||||
 | 
					            usb_cdc_review_comm_init(); // review the communcation initialization state
 | 
				
			||||||
 | 
					            ret = 0;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case USB_ACM_GET_LINE_CODING:                               // get line coding
 | 
				
			||||||
 | 
					            cbevt->reply_data = (const uint8_t *)&acms.line_coding; // expert move: pass the pointer, no copying
 | 
				
			||||||
 | 
					            cbevt->reply_size = sizeof(Usb_Acm_LineCodingStruct);
 | 
				
			||||||
 | 
					            ret = 0;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case USB_ACM_SEND_BREAK: // send break
 | 
				
			||||||
 | 
					            // do nothing
 | 
				
			||||||
 | 
					            ret = 0;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        case USB_ACM_SET_CONTROL_LINE_STATE:                          // set control line state
 | 
				
			||||||
 | 
					            acms.control_line_state.D = cbevt->setup_request->wValue; // control line state is carried in wValue of the SETUP request
 | 
				
			||||||
 | 
					            usb_cdc_review_comm_init();                               // review the communcation initialization state
 | 
				
			||||||
 | 
					            ret = 0;
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            cbevt->reply_valid = false; // this event is not processed by or not related to the CDC ACM module
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case USB_CBEVT_OUT: {
 | 
				
			||||||
 | 
					        if (cbevt->ep == acms.ep_assignments.data_ep) {
 | 
				
			||||||
 | 
					            ret = 0;
 | 
				
			||||||
 | 
					            usb_acm_read_callback(cbevt->data, cbevt->size);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case USB_CBEVT_IN: {
 | 
				
			||||||
 | 
					        if (cbevt->ep == acms.ep_assignments.control_ep) { // if notification feeding is requested
 | 
				
			||||||
 | 
					            if (acms.interrupt_pending) {
 | 
				
			||||||
 | 
					                usbcore_schedule_transmission(acms.ep_assignments.control_ep, (const uint8_t *)&(acms.interrupt_data), sizeof(uint16_t)); // send ZLP
 | 
				
			||||||
 | 
					                acms.interrupt_pending = false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            ret = 0;
 | 
				
			||||||
 | 
					        } else if (cbevt->ep == acms.ep_assignments.data_ep) { // if data are requested
 | 
				
			||||||
 | 
					            ret = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // read from the fifo
 | 
				
			||||||
 | 
					            if (acms.commInit) {
 | 
				
			||||||
 | 
					                uint32_t readSize = bfifo_read(&fifo, tx_buffer, USB_ACM_PCKT_BUFSIZE);
 | 
				
			||||||
 | 
					                if (readSize > 0) {
 | 
				
			||||||
 | 
					                    uint32_t writeSize = usbcore_schedule_transmission(acms.ep_assignments.data_ep, tx_buffer, readSize); // write data acquired from the buffer
 | 
				
			||||||
 | 
					                    bfifo_pop(&fifo, writeSize, 0);                                                                       // pop with no blocking
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_acm_write(const uint8_t *data, uint32_t size) {
 | 
				
			||||||
 | 
					    if (acms.moduleInit) {
 | 
				
			||||||
 | 
					        bfifo_push_all(&fifo, data, size);
 | 
				
			||||||
 | 
					        usbcore_wake_up_endpoint(acms.ep_assignments.data_ep, USB_IN);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @fn void usb_acm_read_callback(const uint8_t *data, uint32_t size)
 | 
				
			||||||
 | 
					 * Callback function prototype for data reception. This function is
 | 
				
			||||||
 | 
					 * expected to be overridden by the application.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @param data ingress data
 | 
				
			||||||
 | 
					 * @param size length of the data
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					__attribute__((weak)) void usb_acm_read_callback(const uint8_t *data, uint32_t size) {
 | 
				
			||||||
 | 
					    (void)data;
 | 
				
			||||||
 | 
					    (void)size;
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										129
									
								
								class/acm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								class/acm.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,129 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 ******************************************************************************
 | 
				
			||||||
 | 
					 * @file    cdc.h
 | 
				
			||||||
 | 
					 * @brief   This is the USB Communication Device Class, Abstract Control Model
 | 
				
			||||||
 | 
					 * implementation module for the flatUSB project. The following standard
 | 
				
			||||||
 | 
					 * requestes are implemented: `SetLineCoding`, `GetLineCoding`,
 | 
				
			||||||
 | 
					 * `SetControlLineState` and `SendBreak`. Data transmission is performed by
 | 
				
			||||||
 | 
					 * calling `usb_acm_write()`. Ingress data is passed to the application through
 | 
				
			||||||
 | 
					 * the `usb_acm_read_callback()` function. A weak prototype is provided which
 | 
				
			||||||
 | 
					 * is expected to be overridden by the application. Supplying a BlockingFifo
 | 
				
			||||||
 | 
					 * is mandatory!
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * If necessary, `USB_CDC_FIFO_MEM_SIZE` and `USB_CDC_PCKT_BUFSIZE` can be freely
 | 
				
			||||||
 | 
					 * overridden in the flatUSB configuration file.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * For more information about the USB CDC ACM class refer to the
 | 
				
			||||||
 | 
					 * <a href="https://www.usb.org/document-library/class-definitions-communication-devices-12" target="_blank">
 | 
				
			||||||
 | 
					 * USB CDC PSTN subclass</a>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright András Wiesner, 2024-\showdate "%Y"
 | 
				
			||||||
 | 
					 ******************************************************************************
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef CORE_USB_CLASS_CDC
 | 
				
			||||||
 | 
					#define CORE_USB_CLASS_CDC
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../usb_callback_event.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * CDC request codes
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef enum {
 | 
				
			||||||
 | 
					    USB_ACM_SET_COMM_FEATURE = 0x2,        ///< SetCommFeature
 | 
				
			||||||
 | 
					    USB_ACM_GET_COMM_FEATURE = 0x3,        ///< GetCommFeature
 | 
				
			||||||
 | 
					    USB_ACM_CLEAR_COMM_FEATURE = 0x4,      ///< ClearCommFeature
 | 
				
			||||||
 | 
					    USB_ACM_SET_AUX_LINE_STATE = 0x10,     ///< SetAuxLineState
 | 
				
			||||||
 | 
					    USB_ACM_SET_HOOK_STATE = 0x11,         ///< SetHookState
 | 
				
			||||||
 | 
					    USB_ACM_PULSE_SETUP = 0x12,            ///< PulseSetup
 | 
				
			||||||
 | 
					    USB_ACM_SEND_PULSE = 0x13,             ///< SendPulse
 | 
				
			||||||
 | 
					    USB_ACM_SET_PULSE_TIME = 0x14,         ///< SetPulseTime
 | 
				
			||||||
 | 
					    USB_ACM_RING_AUX_JACK = 0x15,          ///< RingAuxJack
 | 
				
			||||||
 | 
					    USB_ACM_SET_LINE_CODING = 0x20,        ///< SetLineCoding
 | 
				
			||||||
 | 
					    USB_ACM_GET_LINE_CODING = 0x21,        ///< GetLineCoding
 | 
				
			||||||
 | 
					    USB_ACM_SET_CONTROL_LINE_STATE = 0x22, ///< SetControlLineState
 | 
				
			||||||
 | 
					    USB_ACM_SEND_BREAK = 0x23,             ///< SendBreak
 | 
				
			||||||
 | 
					    USB_ACM_SET_RINGER_PARMS = 0x30,       ///< SetRingerParms
 | 
				
			||||||
 | 
					    USB_ACM_GET_RINGER_PARMS = 0x31,       ///< GetRingerParms
 | 
				
			||||||
 | 
					    USB_ACM_SET_OPERATION_PARMS = 0x32,    ///< SetOperationParms
 | 
				
			||||||
 | 
					    USB_ACM_GET_OPERATION_PARMS = 0x33,    ///< GetOperationParms
 | 
				
			||||||
 | 
					    USB_ACM_SET_LINE_PARMS = 0x34,         ///< GetLineParms
 | 
				
			||||||
 | 
					} Usb_Acm_RequestCodes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * ACM line coding structure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    uint32_t dwDTERate;  ///< data terminal rate, bits per second
 | 
				
			||||||
 | 
					    uint8_t bCharFormat; ///< character format
 | 
				
			||||||
 | 
					    uint8_t bParityType; ///< parity type
 | 
				
			||||||
 | 
					    uint8_t bDataBits;   ///< data bits
 | 
				
			||||||
 | 
					} Usb_Acm_LineCodingStruct;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * CDC control line state struct
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    uint16_t D; ///< settings word
 | 
				
			||||||
 | 
					} Usb_Acm_ControlLineStateStruct;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Endpoint assignments
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    uint8_t control_ep : 4; ///< Control endpoint
 | 
				
			||||||
 | 
					    uint8_t data_ep : 4;    ///< Data endpoint
 | 
				
			||||||
 | 
					} Usb_Acm_EpAssignments;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    Usb_Acm_EpAssignments ep_assignments;              ///< Endpoint assignments
 | 
				
			||||||
 | 
					    Usb_Acm_LineCodingStruct line_coding;              ///< Line Coding
 | 
				
			||||||
 | 
					    Usb_Acm_ControlLineStateStruct control_line_state; ///< Control Line State
 | 
				
			||||||
 | 
					    uint16_t interrupt_data;                           ///< Data sent though the next transfer on the notification element
 | 
				
			||||||
 | 
					    bool interrupt_pending;                            ///< Interrupt data is valid and should be send in the next cycle
 | 
				
			||||||
 | 
					    bool moduleInit;                                   ///< CDC module is initialized
 | 
				
			||||||
 | 
					    bool commInit;                                     ///< Communication protocol is initialized
 | 
				
			||||||
 | 
					} Usb_AcmState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_ACM_INVALID_CONTROL_LINE_STATE (0xFFFF) ///< Invalid Control Line State
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef USB_ACM_FIFO_MEM_SIZE
 | 
				
			||||||
 | 
					#define USB_ACM_FIFO_MEM_SIZE (3072) ///< CDC ACM FIFO memory size
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef USB_ACM_PCKT_BUFSIZE
 | 
				
			||||||
 | 
					#define USB_ACM_PCKT_BUFSIZE (128) ///< Buffer size assigned to the data transfer endpoint
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Initialize CDC ACM module.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param as pointer to filled endpoint assignments object
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void usb_acm_init(const Usb_Acm_EpAssignments *as);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Regular USB class process and return function.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param cbevt pointer to callback event emitted by the USB core
 | 
				
			||||||
 | 
					 * @return request is unprocessed if < 0
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int usb_acm_process_and_return(Usb_CallbackEvent *cbevt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Write to CDC ACM interface.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param data data to be sent through the interface
 | 
				
			||||||
 | 
					 * @param size length of the data
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void usb_acm_write(const uint8_t *data, uint32_t size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* CORE_USB_CLASS_CDC */
 | 
				
			||||||
							
								
								
									
										180
									
								
								class/cdc.c
									
									
									
									
									
								
							
							
						
						
									
										180
									
								
								class/cdc.c
									
									
									
									
									
								
							@ -1,180 +0,0 @@
 | 
				
			|||||||
#include "cdc.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <memory.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "../usb_device_types.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "../usb.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <blocking_io/blocking_fifo.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <cmsis_gcc.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// state
 | 
					 | 
				
			||||||
static USB_CdcState cdcs = {0};
 | 
					 | 
				
			||||||
static uint8_t tx_buffer[USB_CDC_PCKT_BUFSIZE];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define USB_CDC_FIFO_MEM_SIZE (3072) // FIXME: ez vagy a blocking FIFO bugos
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static uint8_t fifo_mem[USB_CDC_FIFO_MEM_SIZE];
 | 
					 | 
				
			||||||
static BFifo fifo;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void usb_cdc_read_callback(const uint8_t *data, uint32_t size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void usb_cdc_init(const USB_CdcAssignments *as) {
 | 
					 | 
				
			||||||
    // clear the structure
 | 
					 | 
				
			||||||
    memset(&cdcs, 0, sizeof(USB_CdcState));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // set Control Line State to something invalid
 | 
					 | 
				
			||||||
    cdcs.control_line_state.D = USB_CDC_INVALID_CONTROL_LINE_STATE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // fill-in default values
 | 
					 | 
				
			||||||
    // USB_Cdc_LineCodingStruct *lc = &cdcs.line_coding;
 | 
					 | 
				
			||||||
    // lc->dwDTERate = USB_CDC_DEFAULT_BITRATE;
 | 
					 | 
				
			||||||
    // lc->bCharFormat = USB_CDC_DEFAULT_CHAR_FORMAT;
 | 
					 | 
				
			||||||
    // lc->bParityType = USB_CDC_DEFAULT_PARITY_TYPE;
 | 
					 | 
				
			||||||
    // lc->bDataBits = USB_CDC_DEFAULT_DATA_BITS;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // fill-in assigments
 | 
					 | 
				
			||||||
    cdcs.ep_assignments = *as;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // initialize buffer
 | 
					 | 
				
			||||||
    bfifo_create(&fifo, fifo_mem, USB_CDC_FIFO_MEM_SIZE);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // initialize an all-0 interrupt
 | 
					 | 
				
			||||||
    cdcs.interrupt_data = 0;
 | 
					 | 
				
			||||||
    cdcs.interrupt_pending = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // communication parameters have not been set
 | 
					 | 
				
			||||||
    cdcs.commInit = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // from now on CDC module is considered initialized
 | 
					 | 
				
			||||||
    cdcs.moduleInit = true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// static uint8_t replyBuf[sizeof(USB_Cdc_LineCodingStruct)];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// static void usbcore_setup_cplt_cb(uint8_t in) {
 | 
					 | 
				
			||||||
//     usbcore_wake_up_endpoint(cdcs.ep_assignments.data_ep, USB_IN);
 | 
					 | 
				
			||||||
// }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void usb_cdc_review_comm_init() {
 | 
					 | 
				
			||||||
    // check if line coding was initialized
 | 
					 | 
				
			||||||
    USB_Cdc_LineCodingStruct *lc = &cdcs.line_coding;
 | 
					 | 
				
			||||||
    bool lcOk = (lc->dwDTERate != 0) && (lc->bDataBits != 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // check if control line state was initialized
 | 
					 | 
				
			||||||
    bool clsOk = cdcs.control_line_state.D != USB_CDC_INVALID_CONTROL_LINE_STATE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // combine the above criteria
 | 
					 | 
				
			||||||
    cdcs.commInit = lcOk && clsOk;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // // wake up endpoint if initialized
 | 
					 | 
				
			||||||
    // if (cdcs.commInit) {
 | 
					 | 
				
			||||||
    //     usbcore_register_IN_callback(0, usbcore_setup_cplt_cb);   
 | 
					 | 
				
			||||||
    // }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int usb_cdc_process_and_return(USB_CallbackEvent *cbevt) {
 | 
					 | 
				
			||||||
    int ret = -1;
 | 
					 | 
				
			||||||
    switch (cbevt->type) {
 | 
					 | 
				
			||||||
    case USB_CBEVT_UNKNOWN_REQ: {
 | 
					 | 
				
			||||||
        // initialize reply
 | 
					 | 
				
			||||||
        cbevt->reply_data = NULL;
 | 
					 | 
				
			||||||
        cbevt->reply_size = 0;
 | 
					 | 
				
			||||||
        cbevt->reply_valid = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        switch (cbevt->setup_request->bRequest) {
 | 
					 | 
				
			||||||
        case USB_CDC_SET_LINE_CODING: // set line coding
 | 
					 | 
				
			||||||
            memcpy(&cdcs.line_coding, cbevt->data, sizeof(USB_Cdc_LineCodingStruct));
 | 
					 | 
				
			||||||
            usb_cdc_review_comm_init(); // review the communcation initialization state
 | 
					 | 
				
			||||||
            // MSG("%u\n", cdcs.line_coding.dwDTERate);
 | 
					 | 
				
			||||||
            ret = 0;
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case USB_CDC_GET_LINE_CODING:                               // get line coding
 | 
					 | 
				
			||||||
            cbevt->reply_data = (const uint8_t *)&cdcs.line_coding; // expert move: pass the pointer, no copying
 | 
					 | 
				
			||||||
            cbevt->reply_size = sizeof(USB_Cdc_LineCodingStruct);
 | 
					 | 
				
			||||||
            ret = 0;
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case USB_CDC_SEND_BREAK: // send break
 | 
					 | 
				
			||||||
            // do nothing
 | 
					 | 
				
			||||||
            ret = 0;
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case USB_CDC_SET_CONTROL_LINE_STATE:                          // set control line state
 | 
					 | 
				
			||||||
            cdcs.control_line_state.D = cbevt->setup_request->wValue; // control line state is carried in wValue of the SETUP request
 | 
					 | 
				
			||||||
            usb_cdc_review_comm_init(); // review the communcation initialization state
 | 
					 | 
				
			||||||
            // MSG("%u\n", cdcs.control_line_state.D);
 | 
					 | 
				
			||||||
            ret = 0;
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        default:
 | 
					 | 
				
			||||||
            cbevt->reply_valid = false; // this event is not processed by or not related to the CDC ACM module
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // send a ZLP reply
 | 
					 | 
				
			||||||
        if (ret != -1) {
 | 
					 | 
				
			||||||
            cbevt->reply_data = NULL;
 | 
					 | 
				
			||||||
            cbevt->reply_size = 0;
 | 
					 | 
				
			||||||
            cbevt->reply_valid = true;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case USB_CBEVT_OUT: {
 | 
					 | 
				
			||||||
        if (cbevt->ep == cdcs.ep_assignments.data_ep) {
 | 
					 | 
				
			||||||
            // MSG("%c\n", cbevt->data[0]);
 | 
					 | 
				
			||||||
            ret = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            usb_cdc_read_callback(cbevt->data, cbevt->size);
 | 
					 | 
				
			||||||
            // usbcore_schedule_transmission(cdcs.ep_assignments.data_ep, cbevt->data, cbevt->size); // echo
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    case USB_CBEVT_IN: {
 | 
					 | 
				
			||||||
        if (cbevt->ep == cdcs.ep_assignments.control_ep) { // if notification feeding is requested
 | 
					 | 
				
			||||||
            if (cdcs.interrupt_pending) {
 | 
					 | 
				
			||||||
                usbcore_schedule_transmission(cdcs.ep_assignments.control_ep, (const uint8_t *)&(cdcs.interrupt_data), sizeof(uint16_t)); // send ZLP
 | 
					 | 
				
			||||||
                cdcs.interrupt_pending = false;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            ret = 0;
 | 
					 | 
				
			||||||
        } else if (cbevt->ep == cdcs.ep_assignments.data_ep) { // if data are requested
 | 
					 | 
				
			||||||
            // usbcore_schedule_transmission(cdcs.ep_assignments.data_ep, NULL, 0); // send ZLP
 | 
					 | 
				
			||||||
            ret = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // read from the fifo
 | 
					 | 
				
			||||||
            if (cdcs.commInit) {
 | 
					 | 
				
			||||||
                uint32_t readSize = bfifo_read(&fifo, tx_buffer, USB_CDC_PCKT_BUFSIZE);
 | 
					 | 
				
			||||||
                if (readSize > 0) {
 | 
					 | 
				
			||||||
                    uint32_t writeSize = usbcore_schedule_transmission(cdcs.ep_assignments.data_ep, tx_buffer, readSize); // write data acquired from the buffer
 | 
					 | 
				
			||||||
                    bfifo_pop(&fifo, writeSize, 0);                                                                       // pop with no blocking
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    default:
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// void usb_event_callback(USB_CallbackEvent *cbevt) {
 | 
					 | 
				
			||||||
//    usb_cdc_process_and_return(cbevt);
 | 
					 | 
				
			||||||
// }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void usb_cdc_write(const uint8_t *data, uint32_t size) {
 | 
					 | 
				
			||||||
    if (cdcs.moduleInit) {
 | 
					 | 
				
			||||||
        bfifo_push_all(&fifo, data, size);
 | 
					 | 
				
			||||||
        usbcore_wake_up_endpoint(cdcs.ep_assignments.data_ep, USB_IN);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
__attribute__((weak)) void usb_cdc_read_callback(const uint8_t *data, uint32_t size) {
 | 
					 | 
				
			||||||
    (void)data;
 | 
					 | 
				
			||||||
    (void)size;
 | 
					 | 
				
			||||||
    return;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										78
									
								
								class/cdc.h
									
									
									
									
									
								
							
							
						
						
									
										78
									
								
								class/cdc.h
									
									
									
									
									
								
							@ -1,78 +0,0 @@
 | 
				
			|||||||
#ifndef CORE_USB_CLASS_CDC
 | 
					 | 
				
			||||||
#define CORE_USB_CLASS_CDC
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "../usb_callback_event.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// CDC request codes
 | 
					 | 
				
			||||||
typedef enum {
 | 
					 | 
				
			||||||
    USB_CDC_SET_COMM_FEATURE = 0x2,
 | 
					 | 
				
			||||||
    USB_CDC_GET_COMM_FEATURE = 0x3,
 | 
					 | 
				
			||||||
    USB_CDC_CLEAR_COMM_FEATURE = 0x4,
 | 
					 | 
				
			||||||
    USB_CDC_SET_AUX_LINE_STATE = 0x10,
 | 
					 | 
				
			||||||
    USB_CDC_SET_HOOK_STATE = 0x11,
 | 
					 | 
				
			||||||
    USB_CDC_PULSE_SETUP = 0x12,
 | 
					 | 
				
			||||||
    USB_CDC_SEND_PULSE = 0x13,
 | 
					 | 
				
			||||||
    USB_CDC_SET_PULSE_TIME = 0x14,
 | 
					 | 
				
			||||||
    USB_CDC_RING_AUX_JACK = 0x15,
 | 
					 | 
				
			||||||
    USB_CDC_SET_LINE_CODING = 0x20,
 | 
					 | 
				
			||||||
    USB_CDC_GET_LINE_CODING = 0x21,
 | 
					 | 
				
			||||||
    USB_CDC_SET_CONTROL_LINE_STATE = 0x22,
 | 
					 | 
				
			||||||
    USB_CDC_SEND_BREAK = 0x23,
 | 
					 | 
				
			||||||
    USB_CDC_SET_RINGER_PARMS = 0x30,
 | 
					 | 
				
			||||||
    USB_CDC_GET_RINGER_PARMS = 0x31,
 | 
					 | 
				
			||||||
    USB_CDC_SET_OPERATION_PARMS = 0x32,
 | 
					 | 
				
			||||||
    USB_CDC_GET_OPERATION_PARMS = 0x33,
 | 
					 | 
				
			||||||
    USB_CDC_SET_LINE_PARMS = 0x34,
 | 
					 | 
				
			||||||
} USB_Cdc_RequestCodes;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// CDC line coding structure
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
    uint32_t dwDTERate;  // data terminal rate, bits per second
 | 
					 | 
				
			||||||
    uint8_t bCharFormat; // character format
 | 
					 | 
				
			||||||
    uint8_t bParityType; // parity type
 | 
					 | 
				
			||||||
    uint8_t bDataBits;   // data bits
 | 
					 | 
				
			||||||
} USB_Cdc_LineCodingStruct;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// CDC control line state struct
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
    uint16_t D; // settings word
 | 
					 | 
				
			||||||
} USB_Cdc_ControlLineStateStruct;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// endpoint assignments
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
    uint8_t control_ep : 4; // control endpoint
 | 
					 | 
				
			||||||
    uint8_t data_ep : 4;    // data endpoint
 | 
					 | 
				
			||||||
} USB_CdcAssignments;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
    USB_CdcAssignments ep_assignments;                 // endpoint assignments
 | 
					 | 
				
			||||||
    USB_Cdc_LineCodingStruct line_coding;              // line coding
 | 
					 | 
				
			||||||
    USB_Cdc_ControlLineStateStruct control_line_state; // control line state
 | 
					 | 
				
			||||||
    uint16_t interrupt_data;                           // data sent though the next transfer on the notification element
 | 
					 | 
				
			||||||
    bool interrupt_pending;                            // interrupt data is valid and should be send in the next cycle
 | 
					 | 
				
			||||||
    bool moduleInit;                                   // CDC module is initialized
 | 
					 | 
				
			||||||
    bool commInit;                                     // communication is initialized
 | 
					 | 
				
			||||||
} USB_CdcState;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define USB_CDC_INVALID_CONTROL_LINE_STATE (0xFFFF)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define USB_CDC_DEFAULT_BITRATE (115200)
 | 
					 | 
				
			||||||
#define USB_CDC_DEFAULT_DATA_BITS (8)
 | 
					 | 
				
			||||||
#define USB_CDC_DEFAULT_PARITY_TYPE (0)
 | 
					 | 
				
			||||||
#define USB_CDC_DEFAULT_CHAR_FORMAT (0)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define USB_CDC_PCKT_BUFSIZE (300)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void usb_cdc_init(const USB_CdcAssignments *as);
 | 
					 | 
				
			||||||
int usb_cdc_process_and_return(USB_CallbackEvent *cbevt);
 | 
					 | 
				
			||||||
void usb_cdc_write(const uint8_t *data, uint32_t size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif /* CORE_USB_CLASS_CDC */
 | 
					 | 
				
			||||||
@ -73,7 +73,7 @@ USB_EemEvent usb_eem_pop_event() {
 | 
				
			|||||||
    return evt;
 | 
					    return evt;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int usb_eem_process_and_return(USB_CallbackEvent *cbevt) {
 | 
					int usb_eem_process_and_return(Usb_CallbackEvent *cbevt) {
 | 
				
			||||||
    switch (cbevt->type) {
 | 
					    switch (cbevt->type) {
 | 
				
			||||||
    case USB_CBEVT_UNKNOWN_REQ:
 | 
					    case USB_CBEVT_UNKNOWN_REQ:
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
				
			|||||||
@ -24,7 +24,6 @@ usb_target_dir = argv[2]
 | 
				
			|||||||
print("Input JSON: ", usb_config_file_name)
 | 
					print("Input JSON: ", usb_config_file_name)
 | 
				
			||||||
print("Target directory: ", usb_target_dir)
 | 
					print("Target directory: ", usb_target_dir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#usb_config_file_name = "/home/epagris/VCSDEV/usbt1/stws/USB-T1/Modules/flatUSB/desc/usb_config_cdc.json"
 | 
					 | 
				
			||||||
with open(usb_config_file_name, 'r') as usb_config_file:
 | 
					with open(usb_config_file_name, 'r') as usb_config_file:
 | 
				
			||||||
    usb_config_data = usb_config_file.read()
 | 
					    usb_config_data = usb_config_file.read()
 | 
				
			||||||
usb_config = json.loads(usb_config_data)
 | 
					usb_config = json.loads(usb_config_data)
 | 
				
			||||||
@ -42,29 +41,5 @@ if "misc" in usb_config:
 | 
				
			|||||||
cfggen = ConfigGenerator(usb_config)
 | 
					cfggen = ConfigGenerator(usb_config)
 | 
				
			||||||
cfggen.generate(usb_target_dir)
 | 
					cfggen.generate(usb_target_dir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# devDesc = desc.DeviceDescriptor(usb_config)
 | 
					 | 
				
			||||||
# print(devDesc.print_assigment())
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# strDesc = desc.StringDescriptor("Testdevice", "StrDevice")
 | 
					 | 
				
			||||||
# print(strDesc.print_assigment())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#intrec = sg.RecordFactory.create("num", "u32", 127)
 | 
					 | 
				
			||||||
#print(intrec.print_typedef("INT"))
 | 
					 | 
				
			||||||
# intrec = sg.RecordFactory.create([ "num", "u32", 127, ])
 | 
					 | 
				
			||||||
# print(intrec.print_typedef("INTINT"))
 | 
					 | 
				
			||||||
# #
 | 
					 | 
				
			||||||
# strrec = sg.RecordFactory.create("some_string", "str", "Some string")
 | 
					 | 
				
			||||||
# print(strrec.print_typedef("STR"))
 | 
					 | 
				
			||||||
#print(strrec.print_content())
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# recs = [ intrec, strrec ]
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# struct1 = sg.StructRecord("struct1", "struct struct 1", recs)
 | 
					 | 
				
			||||||
# struct2 = sg.StructRecord("struct2", "struct struct2", recs)
 | 
					 | 
				
			||||||
# print(struct2.print_typedef("struct2"))
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# structrec = sg.StructRecord("object", "struct compound", [ struct1, struct2, *recs ])
 | 
					 | 
				
			||||||
# print(structrec.print_content())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# print complete message
 | 
					# print complete message
 | 
				
			||||||
print("Descriptor generation complete!")
 | 
					print("Descriptor generation complete!")
 | 
				
			||||||
							
								
								
									
										21
									
								
								docs/LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								docs/LICENSE
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					MIT License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright (c) 2021 - 2023 jothepro
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The above copyright notice and this permission notice shall be included in all
 | 
				
			||||||
 | 
					copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
				
			||||||
 | 
					SOFTWARE.
 | 
				
			||||||
							
								
								
									
										157
									
								
								docs/doxygen-awesome-darkmode-toggle.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								docs/doxygen-awesome-darkmode-toggle.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,157 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Doxygen Awesome
 | 
				
			||||||
 | 
					https://github.com/jothepro/doxygen-awesome-css
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MIT License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright (c) 2021 - 2023 jothepro
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The above copyright notice and this permission notice shall be included in all
 | 
				
			||||||
 | 
					copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
				
			||||||
 | 
					SOFTWARE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DoxygenAwesomeDarkModeToggle extends HTMLElement {
 | 
				
			||||||
 | 
					    // SVG icons from https://fonts.google.com/icons
 | 
				
			||||||
 | 
					    // Licensed under the Apache 2.0 license:
 | 
				
			||||||
 | 
					    // https://www.apache.org/licenses/LICENSE-2.0.html
 | 
				
			||||||
 | 
					    static lightModeIcon = `<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#FCBF00"><rect fill="none" height="24" width="24"/><circle cx="12" cy="12" opacity=".3" r="3"/><path d="M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"/></svg>`
 | 
				
			||||||
 | 
					    static darkModeIcon = `<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#FE9700"><rect fill="none" height="24" width="24"/><path d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27 C17.45,17.19,14.93,19,12,19c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z" opacity=".3"/><path d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"/></svg>`
 | 
				
			||||||
 | 
					    static title = "Toggle Light/Dark Mode"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static prefersLightModeInDarkModeKey = "prefers-light-mode-in-dark-mode"
 | 
				
			||||||
 | 
					    static prefersDarkModeInLightModeKey = "prefers-dark-mode-in-light-mode"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static _staticConstructor = function() {
 | 
				
			||||||
 | 
					        DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.userPreference)
 | 
				
			||||||
 | 
					        // Update the color scheme when the browsers preference changes
 | 
				
			||||||
 | 
					        // without user interaction on the website.
 | 
				
			||||||
 | 
					        window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
 | 
				
			||||||
 | 
					            DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged()
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        // Update the color scheme when the tab is made visible again.
 | 
				
			||||||
 | 
					        // It is possible that the appearance was changed in another tab 
 | 
				
			||||||
 | 
					        // while this tab was in the background.
 | 
				
			||||||
 | 
					        document.addEventListener("visibilitychange", visibilityState => {
 | 
				
			||||||
 | 
					            if (document.visibilityState === 'visible') {
 | 
				
			||||||
 | 
					                DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged()
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static init() {
 | 
				
			||||||
 | 
					        $(function() {
 | 
				
			||||||
 | 
					            $(document).ready(function() {
 | 
				
			||||||
 | 
					                const toggleButton = document.createElement('doxygen-awesome-dark-mode-toggle')
 | 
				
			||||||
 | 
					                toggleButton.title = DoxygenAwesomeDarkModeToggle.title
 | 
				
			||||||
 | 
					                toggleButton.updateIcon()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
 | 
				
			||||||
 | 
					                    toggleButton.updateIcon()
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                document.addEventListener("visibilitychange", visibilityState => {
 | 
				
			||||||
 | 
					                    if (document.visibilityState === 'visible') {
 | 
				
			||||||
 | 
					                        toggleButton.updateIcon()
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                $(document).ready(function(){
 | 
				
			||||||
 | 
					                    document.getElementById("MSearchBox").parentNode.appendChild(toggleButton)
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                $(window).resize(function(){
 | 
				
			||||||
 | 
					                    document.getElementById("MSearchBox").parentNode.appendChild(toggleButton)
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor() {
 | 
				
			||||||
 | 
					        super();
 | 
				
			||||||
 | 
					        this.onclick=this.toggleDarkMode
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @returns `true` for dark-mode, `false` for light-mode system preference
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    static get systemPreference() {
 | 
				
			||||||
 | 
					        return window.matchMedia('(prefers-color-scheme: dark)').matches
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @returns `true` for dark-mode, `false` for light-mode user preference
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    static get userPreference() {
 | 
				
			||||||
 | 
					        return (!DoxygenAwesomeDarkModeToggle.systemPreference && localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey)) || 
 | 
				
			||||||
 | 
					        (DoxygenAwesomeDarkModeToggle.systemPreference && !localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static set userPreference(userPreference) {
 | 
				
			||||||
 | 
					        DoxygenAwesomeDarkModeToggle.darkModeEnabled = userPreference
 | 
				
			||||||
 | 
					        if(!userPreference) {
 | 
				
			||||||
 | 
					            if(DoxygenAwesomeDarkModeToggle.systemPreference) {
 | 
				
			||||||
 | 
					                localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey, true)
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            if(!DoxygenAwesomeDarkModeToggle.systemPreference) {
 | 
				
			||||||
 | 
					                localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey, true)
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        DoxygenAwesomeDarkModeToggle.onUserPreferenceChanged()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static enableDarkMode(enable) {
 | 
				
			||||||
 | 
					        if(enable) {
 | 
				
			||||||
 | 
					            DoxygenAwesomeDarkModeToggle.darkModeEnabled = true
 | 
				
			||||||
 | 
					            document.documentElement.classList.add("dark-mode")
 | 
				
			||||||
 | 
					            document.documentElement.classList.remove("light-mode")
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            DoxygenAwesomeDarkModeToggle.darkModeEnabled = false
 | 
				
			||||||
 | 
					            document.documentElement.classList.remove("dark-mode")
 | 
				
			||||||
 | 
					            document.documentElement.classList.add("light-mode")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static onSystemPreferenceChanged() {
 | 
				
			||||||
 | 
					        DoxygenAwesomeDarkModeToggle.darkModeEnabled = DoxygenAwesomeDarkModeToggle.userPreference
 | 
				
			||||||
 | 
					        DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static onUserPreferenceChanged() {
 | 
				
			||||||
 | 
					        DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    toggleDarkMode() {
 | 
				
			||||||
 | 
					        DoxygenAwesomeDarkModeToggle.userPreference = !DoxygenAwesomeDarkModeToggle.userPreference
 | 
				
			||||||
 | 
					        this.updateIcon()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    updateIcon() {
 | 
				
			||||||
 | 
					        if(DoxygenAwesomeDarkModeToggle.darkModeEnabled) {
 | 
				
			||||||
 | 
					            this.innerHTML = DoxygenAwesomeDarkModeToggle.darkModeIcon
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            this.innerHTML = DoxygenAwesomeDarkModeToggle.lightModeIcon
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					customElements.define("doxygen-awesome-dark-mode-toggle", DoxygenAwesomeDarkModeToggle);
 | 
				
			||||||
							
								
								
									
										85
									
								
								docs/doxygen-awesome-fragment-copy-button.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								docs/doxygen-awesome-fragment-copy-button.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,85 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Doxygen Awesome
 | 
				
			||||||
 | 
					https://github.com/jothepro/doxygen-awesome-css
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MIT License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright (c) 2022 - 2023 jothepro
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The above copyright notice and this permission notice shall be included in all
 | 
				
			||||||
 | 
					copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
				
			||||||
 | 
					SOFTWARE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DoxygenAwesomeFragmentCopyButton extends HTMLElement {
 | 
				
			||||||
 | 
					    constructor() {
 | 
				
			||||||
 | 
					        super();
 | 
				
			||||||
 | 
					        this.onclick=this.copyContent
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    static title = "Copy to clipboard"
 | 
				
			||||||
 | 
					    static copyIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg>`
 | 
				
			||||||
 | 
					    static successIcon = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z"/></svg>`
 | 
				
			||||||
 | 
					    static successDuration = 980
 | 
				
			||||||
 | 
					    static init() {
 | 
				
			||||||
 | 
					        $(function() {
 | 
				
			||||||
 | 
					            $(document).ready(function() {
 | 
				
			||||||
 | 
					                if(navigator.clipboard) {
 | 
				
			||||||
 | 
					                    const fragments = document.getElementsByClassName("fragment")
 | 
				
			||||||
 | 
					                    for(const fragment of fragments) {
 | 
				
			||||||
 | 
					                        const fragmentWrapper = document.createElement("div")
 | 
				
			||||||
 | 
					                        fragmentWrapper.className = "doxygen-awesome-fragment-wrapper"
 | 
				
			||||||
 | 
					                        const fragmentCopyButton = document.createElement("doxygen-awesome-fragment-copy-button")
 | 
				
			||||||
 | 
					                        fragmentCopyButton.innerHTML = DoxygenAwesomeFragmentCopyButton.copyIcon
 | 
				
			||||||
 | 
					                        fragmentCopyButton.title = DoxygenAwesomeFragmentCopyButton.title
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                        fragment.parentNode.replaceChild(fragmentWrapper, fragment)
 | 
				
			||||||
 | 
					                        fragmentWrapper.appendChild(fragment)
 | 
				
			||||||
 | 
					                        fragmentWrapper.appendChild(fragmentCopyButton)
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    copyContent() {
 | 
				
			||||||
 | 
					        const content = this.previousSibling.cloneNode(true)
 | 
				
			||||||
 | 
					        // filter out line number from file listings
 | 
				
			||||||
 | 
					        content.querySelectorAll(".lineno, .ttc").forEach((node) => {
 | 
				
			||||||
 | 
					            node.remove()
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        let textContent = content.textContent
 | 
				
			||||||
 | 
					        // remove trailing newlines that appear in file listings
 | 
				
			||||||
 | 
					        let numberOfTrailingNewlines = 0
 | 
				
			||||||
 | 
					        while(textContent.charAt(textContent.length - (numberOfTrailingNewlines + 1)) == '\n') {
 | 
				
			||||||
 | 
					            numberOfTrailingNewlines++;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        textContent = textContent.substring(0, textContent.length - numberOfTrailingNewlines)
 | 
				
			||||||
 | 
					        navigator.clipboard.writeText(textContent);
 | 
				
			||||||
 | 
					        this.classList.add("success")
 | 
				
			||||||
 | 
					        this.innerHTML = DoxygenAwesomeFragmentCopyButton.successIcon
 | 
				
			||||||
 | 
					        window.setTimeout(() => {
 | 
				
			||||||
 | 
					            this.classList.remove("success")
 | 
				
			||||||
 | 
					            this.innerHTML = DoxygenAwesomeFragmentCopyButton.copyIcon
 | 
				
			||||||
 | 
					        }, DoxygenAwesomeFragmentCopyButton.successDuration);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					customElements.define("doxygen-awesome-fragment-copy-button", DoxygenAwesomeFragmentCopyButton)
 | 
				
			||||||
							
								
								
									
										91
									
								
								docs/doxygen-awesome-interactive-toc.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								docs/doxygen-awesome-interactive-toc.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,91 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Doxygen Awesome
 | 
				
			||||||
 | 
					https://github.com/jothepro/doxygen-awesome-css
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MIT License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright (c) 2022 - 2023 jothepro
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The above copyright notice and this permission notice shall be included in all
 | 
				
			||||||
 | 
					copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
				
			||||||
 | 
					SOFTWARE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DoxygenAwesomeInteractiveToc {
 | 
				
			||||||
 | 
					    static topOffset = 38
 | 
				
			||||||
 | 
					    static hideMobileMenu = true
 | 
				
			||||||
 | 
					    static headers = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static init() {
 | 
				
			||||||
 | 
					        window.addEventListener("load", () => {
 | 
				
			||||||
 | 
					            let toc = document.querySelector(".contents > .toc")
 | 
				
			||||||
 | 
					            if(toc) {
 | 
				
			||||||
 | 
					                toc.classList.add("interactive")
 | 
				
			||||||
 | 
					                if(!DoxygenAwesomeInteractiveToc.hideMobileMenu) {
 | 
				
			||||||
 | 
					                    toc.classList.add("open")
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                document.querySelector(".contents > .toc > h3")?.addEventListener("click", () => {
 | 
				
			||||||
 | 
					                    if(toc.classList.contains("open")) {
 | 
				
			||||||
 | 
					                        toc.classList.remove("open")
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        toc.classList.add("open")
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                document.querySelectorAll(".contents > .toc > ul a").forEach((node) => {
 | 
				
			||||||
 | 
					                    let id = node.getAttribute("href").substring(1)
 | 
				
			||||||
 | 
					                    DoxygenAwesomeInteractiveToc.headers.push({
 | 
				
			||||||
 | 
					                        node: node,
 | 
				
			||||||
 | 
					                        headerNode: document.getElementById(id)
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    document.getElementById("doc-content")?.addEventListener("scroll",this.throttle(DoxygenAwesomeInteractiveToc.update, 100))
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                DoxygenAwesomeInteractiveToc.update()
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static update() {
 | 
				
			||||||
 | 
					        let active = DoxygenAwesomeInteractiveToc.headers[0]?.node
 | 
				
			||||||
 | 
					        DoxygenAwesomeInteractiveToc.headers.forEach((header) => {
 | 
				
			||||||
 | 
					            let position = header.headerNode.getBoundingClientRect().top
 | 
				
			||||||
 | 
					            header.node.classList.remove("active")
 | 
				
			||||||
 | 
					            header.node.classList.remove("aboveActive")
 | 
				
			||||||
 | 
					            if(position < DoxygenAwesomeInteractiveToc.topOffset) {
 | 
				
			||||||
 | 
					                active = header.node
 | 
				
			||||||
 | 
					                active?.classList.add("aboveActive")
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        active?.classList.add("active")
 | 
				
			||||||
 | 
					        active?.classList.remove("aboveActive")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static throttle(func, delay) {
 | 
				
			||||||
 | 
					        let lastCall = 0;
 | 
				
			||||||
 | 
					        return function (...args) {
 | 
				
			||||||
 | 
					            const now = new Date().getTime();
 | 
				
			||||||
 | 
					            if (now - lastCall < delay) {
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            lastCall = now;
 | 
				
			||||||
 | 
					            return setTimeout(() => {func(...args)}, delay);
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										40
									
								
								docs/doxygen-awesome-sidebar-only-darkmode-toggle.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								docs/doxygen-awesome-sidebar-only-darkmode-toggle.css
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Doxygen Awesome
 | 
				
			||||||
 | 
					https://github.com/jothepro/doxygen-awesome-css
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MIT License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright (c) 2021 - 2023 jothepro
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The above copyright notice and this permission notice shall be included in all
 | 
				
			||||||
 | 
					copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
				
			||||||
 | 
					SOFTWARE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@media screen and (min-width: 768px) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #MSearchBox {
 | 
				
			||||||
 | 
					        width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - var(--searchbar-height) - 1px);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #MSearchField {
 | 
				
			||||||
 | 
					        width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - 66px - var(--searchbar-height));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										116
									
								
								docs/doxygen-awesome-sidebar-only.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								docs/doxygen-awesome-sidebar-only.css
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,116 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Doxygen Awesome
 | 
				
			||||||
 | 
					https://github.com/jothepro/doxygen-awesome-css
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MIT License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright (c) 2021 - 2023 jothepro
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The above copyright notice and this permission notice shall be included in all
 | 
				
			||||||
 | 
					copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
				
			||||||
 | 
					SOFTWARE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					html {
 | 
				
			||||||
 | 
					    /* side nav width. MUST be = `TREEVIEW_WIDTH`.
 | 
				
			||||||
 | 
					     * Make sure it is wide enough to contain the page title (logo + title + version)
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    --side-nav-fixed-width: 335px;
 | 
				
			||||||
 | 
					    --menu-display: none;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    --top-height: 120px;
 | 
				
			||||||
 | 
					    --toc-sticky-top: -25px;
 | 
				
			||||||
 | 
					    --toc-max-height: calc(100vh - 2 * var(--spacing-medium) - 25px);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#projectname {
 | 
				
			||||||
 | 
					    white-space: nowrap;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@media screen and (min-width: 768px) {
 | 
				
			||||||
 | 
					    html {
 | 
				
			||||||
 | 
					        --searchbar-background: var(--page-background-color);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #side-nav {
 | 
				
			||||||
 | 
					        min-width: var(--side-nav-fixed-width);
 | 
				
			||||||
 | 
					        max-width: var(--side-nav-fixed-width);
 | 
				
			||||||
 | 
					        top: var(--top-height);
 | 
				
			||||||
 | 
					        overflow: visible;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #nav-tree, #side-nav {
 | 
				
			||||||
 | 
					        height: calc(100vh - var(--top-height)) !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #nav-tree {
 | 
				
			||||||
 | 
					        padding: 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #top {
 | 
				
			||||||
 | 
					        display: block;
 | 
				
			||||||
 | 
					        border-bottom: none;
 | 
				
			||||||
 | 
					        height: var(--top-height);
 | 
				
			||||||
 | 
					        margin-bottom: calc(0px - var(--top-height));
 | 
				
			||||||
 | 
					        max-width: var(--side-nav-fixed-width);
 | 
				
			||||||
 | 
					        overflow: hidden;
 | 
				
			||||||
 | 
					        background: var(--side-nav-background);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    #main-nav {
 | 
				
			||||||
 | 
					        float: left;
 | 
				
			||||||
 | 
					        padding-right: 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .ui-resizable-handle {
 | 
				
			||||||
 | 
					        cursor: default;
 | 
				
			||||||
 | 
					        width: 1px !important;
 | 
				
			||||||
 | 
					        background: var(--separator-color);
 | 
				
			||||||
 | 
					        box-shadow: 0 calc(-2 * var(--top-height)) 0 0 var(--separator-color);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #nav-path {
 | 
				
			||||||
 | 
					        position: fixed;
 | 
				
			||||||
 | 
					        right: 0;
 | 
				
			||||||
 | 
					        left: var(--side-nav-fixed-width);
 | 
				
			||||||
 | 
					        bottom: 0;
 | 
				
			||||||
 | 
					        width: auto;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #doc-content {
 | 
				
			||||||
 | 
					        height: calc(100vh - 31px) !important;
 | 
				
			||||||
 | 
					        padding-bottom: calc(3 * var(--spacing-large));
 | 
				
			||||||
 | 
					        padding-top: calc(var(--top-height) - 80px);
 | 
				
			||||||
 | 
					        box-sizing: border-box;
 | 
				
			||||||
 | 
					        margin-left: var(--side-nav-fixed-width) !important;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #MSearchBox {
 | 
				
			||||||
 | 
					        width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #MSearchField {
 | 
				
			||||||
 | 
					        width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - 65px);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #MSearchResultsWindow {
 | 
				
			||||||
 | 
					        left: var(--spacing-medium) !important;
 | 
				
			||||||
 | 
					        right: auto;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										90
									
								
								docs/doxygen-awesome-tabs.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								docs/doxygen-awesome-tabs.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,90 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Doxygen Awesome
 | 
				
			||||||
 | 
					https://github.com/jothepro/doxygen-awesome-css
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MIT License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright (c) 2023 jothepro
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The above copyright notice and this permission notice shall be included in all
 | 
				
			||||||
 | 
					copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
				
			||||||
 | 
					SOFTWARE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DoxygenAwesomeTabs {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static init() {
 | 
				
			||||||
 | 
					        window.addEventListener("load", () => {
 | 
				
			||||||
 | 
					            document.querySelectorAll(".tabbed:not(:empty)").forEach((tabbed, tabbedIndex) => {
 | 
				
			||||||
 | 
					                let tabLinkList = []           
 | 
				
			||||||
 | 
					                tabbed.querySelectorAll(":scope > ul > li").forEach((tab, tabIndex) => {
 | 
				
			||||||
 | 
					                    tab.id = "tab_" + tabbedIndex + "_" + tabIndex
 | 
				
			||||||
 | 
					                    let header = tab.querySelector(".tab-title")
 | 
				
			||||||
 | 
					                    let tabLink = document.createElement("button")
 | 
				
			||||||
 | 
					                    tabLink.classList.add("tab-button")
 | 
				
			||||||
 | 
					                    tabLink.appendChild(header)
 | 
				
			||||||
 | 
					                    header.title = header.textContent
 | 
				
			||||||
 | 
					                    tabLink.addEventListener("click", () => {
 | 
				
			||||||
 | 
					                        tabbed.querySelectorAll(":scope > ul > li").forEach((tab) => {
 | 
				
			||||||
 | 
					                            tab.classList.remove("selected")
 | 
				
			||||||
 | 
					                        })
 | 
				
			||||||
 | 
					                        tabLinkList.forEach((tabLink) => {
 | 
				
			||||||
 | 
					                            tabLink.classList.remove("active")
 | 
				
			||||||
 | 
					                        })
 | 
				
			||||||
 | 
					                        tab.classList.add("selected")
 | 
				
			||||||
 | 
					                        tabLink.classList.add("active")
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                    tabLinkList.push(tabLink)
 | 
				
			||||||
 | 
					                    if(tabIndex == 0) {
 | 
				
			||||||
 | 
					                        tab.classList.add("selected")
 | 
				
			||||||
 | 
					                        tabLink.classList.add("active")
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                let tabsOverview = document.createElement("div")
 | 
				
			||||||
 | 
					                tabsOverview.classList.add("tabs-overview")
 | 
				
			||||||
 | 
					                let tabsOverviewContainer = document.createElement("div")
 | 
				
			||||||
 | 
					                tabsOverviewContainer.classList.add("tabs-overview-container")
 | 
				
			||||||
 | 
					                tabLinkList.forEach((tabLink) => {
 | 
				
			||||||
 | 
					                    tabsOverview.appendChild(tabLink)
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                tabsOverviewContainer.appendChild(tabsOverview)
 | 
				
			||||||
 | 
					                tabbed.before(tabsOverviewContainer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                function resize() {
 | 
				
			||||||
 | 
					                    let maxTabHeight = 0
 | 
				
			||||||
 | 
					                    tabbed.querySelectorAll(":scope > ul > li").forEach((tab, tabIndex) => {
 | 
				
			||||||
 | 
					                        let visibility = tab.style.display
 | 
				
			||||||
 | 
					                        tab.style.display = "block"
 | 
				
			||||||
 | 
					                        maxTabHeight = Math.max(tab.offsetHeight, maxTabHeight)
 | 
				
			||||||
 | 
					                        tab.style.display = visibility
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                    tabbed.style.height = `${maxTabHeight + 10}px`
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                resize()
 | 
				
			||||||
 | 
					                new ResizeObserver(resize).observe(tabbed)
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static resize(tabbed) {
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										2681
									
								
								docs/doxygen-awesome.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2681
									
								
								docs/doxygen-awesome.css
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										86
									
								
								docs/header.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								docs/header.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,86 @@
 | 
				
			|||||||
 | 
					<!-- HTML header for doxygen 1.9.8-->
 | 
				
			||||||
 | 
					<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 | 
				
			||||||
 | 
					<html xmlns="http://www.w3.org/1999/xhtml" lang="$langISO">
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
 | 
				
			||||||
 | 
					<meta http-equiv="X-UA-Compatible" content="IE=11"/>
 | 
				
			||||||
 | 
					<meta name="generator" content="Doxygen $doxygenversion"/>
 | 
				
			||||||
 | 
					<meta name="viewport" content="width=device-width, initial-scale=1"/>
 | 
				
			||||||
 | 
					<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
 | 
				
			||||||
 | 
					<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
 | 
				
			||||||
 | 
					<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
 | 
				
			||||||
 | 
					<!--BEGIN DISABLE_INDEX-->
 | 
				
			||||||
 | 
					  <!--BEGIN FULL_SIDEBAR-->
 | 
				
			||||||
 | 
					<script type="text/javascript">var page_layout=1;</script>
 | 
				
			||||||
 | 
					  <!--END FULL_SIDEBAR-->
 | 
				
			||||||
 | 
					<!--END DISABLE_INDEX-->
 | 
				
			||||||
 | 
					<script type="text/javascript" src="$relpath^jquery.js"></script>
 | 
				
			||||||
 | 
					<script type="text/javascript" src="$relpath^dynsections.js"></script>
 | 
				
			||||||
 | 
					$treeview
 | 
				
			||||||
 | 
					$search
 | 
				
			||||||
 | 
					$mathjax
 | 
				
			||||||
 | 
					$darkmode
 | 
				
			||||||
 | 
					<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
 | 
				
			||||||
 | 
					$extrastylesheet
 | 
				
			||||||
 | 
					<script type="text/javascript" src="$relpath^doxygen-awesome-fragment-copy-button.js"></script>
 | 
				
			||||||
 | 
					<script type="text/javascript">
 | 
				
			||||||
 | 
					    DoxygenAwesomeFragmentCopyButton.init()
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					<script type="text/javascript" src="$relpath^doxygen-awesome-interactive-toc.js"></script>
 | 
				
			||||||
 | 
					<script type="text/javascript">
 | 
				
			||||||
 | 
					    DoxygenAwesomeInteractiveToc.init()
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					<script type="text/javascript" src="$relpath^doxygen-awesome-darkmode-toggle.js"></script>
 | 
				
			||||||
 | 
					<script type="text/javascript">
 | 
				
			||||||
 | 
					    DoxygenAwesomeDarkModeToggle.init()
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
					<!--BEGIN DISABLE_INDEX-->
 | 
				
			||||||
 | 
					  <!--BEGIN FULL_SIDEBAR-->
 | 
				
			||||||
 | 
					<div id="side-nav" class="ui-resizable side-nav-resizable"><!-- do not remove this div, it is closed by doxygen! -->
 | 
				
			||||||
 | 
					  <!--END FULL_SIDEBAR-->
 | 
				
			||||||
 | 
					<!--END DISABLE_INDEX-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--BEGIN TITLEAREA-->
 | 
				
			||||||
 | 
					<div id="titlearea">
 | 
				
			||||||
 | 
					<table cellspacing="0" cellpadding="0">
 | 
				
			||||||
 | 
					 <tbody>
 | 
				
			||||||
 | 
					 <tr id="projectrow">
 | 
				
			||||||
 | 
					  <!--BEGIN PROJECT_LOGO-->
 | 
				
			||||||
 | 
					  <td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></td>
 | 
				
			||||||
 | 
					  <!--END PROJECT_LOGO-->
 | 
				
			||||||
 | 
					  <!--BEGIN PROJECT_NAME-->
 | 
				
			||||||
 | 
					  <td id="projectalign">
 | 
				
			||||||
 | 
					   <div id="projectname">$projectname<!--BEGIN PROJECT_NUMBER--><span id="projectnumber"> $projectnumber</span><!--END PROJECT_NUMBER-->
 | 
				
			||||||
 | 
					   </div>
 | 
				
			||||||
 | 
					   <!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
 | 
				
			||||||
 | 
					  </td>
 | 
				
			||||||
 | 
					  <!--END PROJECT_NAME-->
 | 
				
			||||||
 | 
					  <!--BEGIN !PROJECT_NAME-->
 | 
				
			||||||
 | 
					   <!--BEGIN PROJECT_BRIEF-->
 | 
				
			||||||
 | 
					    <td>
 | 
				
			||||||
 | 
					    <div id="projectbrief">$projectbrief</div>
 | 
				
			||||||
 | 
					    </td>
 | 
				
			||||||
 | 
					   <!--END PROJECT_BRIEF-->
 | 
				
			||||||
 | 
					  <!--END !PROJECT_NAME-->
 | 
				
			||||||
 | 
					  <!--BEGIN DISABLE_INDEX-->
 | 
				
			||||||
 | 
					   <!--BEGIN SEARCHENGINE-->
 | 
				
			||||||
 | 
					     <!--BEGIN !FULL_SIDEBAR-->
 | 
				
			||||||
 | 
					    <td>$searchbox</td>
 | 
				
			||||||
 | 
					     <!--END !FULL_SIDEBAR-->
 | 
				
			||||||
 | 
					   <!--END SEARCHENGINE-->
 | 
				
			||||||
 | 
					  <!--END DISABLE_INDEX-->
 | 
				
			||||||
 | 
					 </tr>
 | 
				
			||||||
 | 
					  <!--BEGIN SEARCHENGINE-->
 | 
				
			||||||
 | 
					   <!--BEGIN FULL_SIDEBAR-->
 | 
				
			||||||
 | 
					   <tr><td colspan="2">$searchbox</td></tr>
 | 
				
			||||||
 | 
					   <!--END FULL_SIDEBAR-->
 | 
				
			||||||
 | 
					  <!--END SEARCHENGINE-->
 | 
				
			||||||
 | 
					 </tbody>
 | 
				
			||||||
 | 
					</table>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					<!--END TITLEAREA-->
 | 
				
			||||||
 | 
					<!-- end header part -->
 | 
				
			||||||
							
								
								
									
										3
									
								
								docs/large-top-height.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								docs/large-top-height.css
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					body {
 | 
				
			||||||
 | 
					    --top-height: 160px
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,16 +0,0 @@
 | 
				
			|||||||
#ifndef CORE_USB_USB_CORE_TYPES
 | 
					 | 
				
			||||||
#define CORE_USB_USB_CORE_TYPES
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// #include "usb_common_types.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// /* USB linespeed */
 | 
					 | 
				
			||||||
// typedef enum { USB_SPD_UNKNOWN = 0b00, USB_SPD_LOW = 0b01, USB_SPD_FULL = 0b11 } USB_Speed;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// /* USB core state */
 | 
					 | 
				
			||||||
// typedef struct
 | 
					 | 
				
			||||||
// {
 | 
					 | 
				
			||||||
//     uint8_t linespeed; // USB linespeed
 | 
					 | 
				
			||||||
// } USB_CoreState;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif /* CORE_USB_USB_CORE_TYPES */
 | 
					 | 
				
			||||||
@ -15,14 +15,16 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// ------------------------
 | 
					// ------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define USB_RX_BUF_SIZE (512)
 | 
					#define USB_RX_BUF_SIZE (512) ///< Receive buffer size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static USBDRV_GlobalState gs;                       // global USB state
 | 
					static USBDRV_GlobalState gs;                       ///< Blobal USB state
 | 
				
			||||||
static uint8_t rx_buf[USB_RX_BUF_SIZE] DWORD_ALIGN; // receive buffer
 | 
					static uint8_t rx_buf[USB_RX_BUF_SIZE] DWORD_ALIGN; ///< Receive buffer
 | 
				
			||||||
static USBDRV_IN_cb cbs[USB_NUM_OF_ENDPOINTS];      // callbacks for IN completion
 | 
					static UsbDrv_IN_cb cbs[USB_NUM_OF_ENDPOINTS];      ///< Callbacks for IN completion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** \cond false */
 | 
				
			||||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
 | 
					#define MAX(a, b) (((a) > (b)) ? (a) : (b))
 | 
				
			||||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
 | 
					#define MIN(a, b) (((a) < (b)) ? (a) : (b))
 | 
				
			||||||
 | 
					/** \endcond */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ------------------------
 | 
					// ------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -46,13 +48,13 @@ __weak void usbdrv_ulpi_init() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// ------------------------
 | 
					// ------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void usbdrv_register_IN_complete_cb(uint8_t ep, USBDRV_IN_cb cb) {
 | 
					void usbdrv_register_IN_complete_cb(uint8_t ep, UsbDrv_IN_cb cb) {
 | 
				
			||||||
    cbs[ep] = cb;
 | 
					    cbs[ep] = cb;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ------------------------
 | 
					// ------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static USB_DrvIntf drvIntf;
 | 
					static UsbDrv_DrvIntf drvIntf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void usbdrv_init_intf() {
 | 
					void usbdrv_init_intf() {
 | 
				
			||||||
    drvIntf.init = usbdrv_init;
 | 
					    drvIntf.init = usbdrv_init;
 | 
				
			||||||
@ -67,7 +69,7 @@ void usbdrv_init_intf() {
 | 
				
			|||||||
    drvIntf.reg_IN_cb = usbdrv_register_IN_complete_cb;
 | 
					    drvIntf.reg_IN_cb = usbdrv_register_IN_complete_cb;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
USB_DrvIntf *usbdrv_get_intf() {
 | 
					UsbDrv_DrvIntf *usbdrv_get_intf() {
 | 
				
			||||||
    return &drvIntf;
 | 
					    return &drvIntf;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -185,7 +187,7 @@ void usbdrv_init_global_state() {
 | 
				
			|||||||
    memset(&gs, 0, sizeof(USBDRV_GlobalState));
 | 
					    memset(&gs, 0, sizeof(USBDRV_GlobalState));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // clear IN complete callbacks
 | 
					    // clear IN complete callbacks
 | 
				
			||||||
    memset(&cbs, 0, sizeof(USBDRV_IN_cb) * USB_NUM_OF_ENDPOINTS);
 | 
					    memset(&cbs, 0, sizeof(UsbDrv_IN_cb) * USB_NUM_OF_ENDPOINTS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // initialize receive buffer
 | 
					    // initialize receive buffer
 | 
				
			||||||
    gs.rx_buf = rx_buf;
 | 
					    gs.rx_buf = rx_buf;
 | 
				
			||||||
@ -734,12 +736,26 @@ void usbdrv_process_rx_fifo_top(USBDRV_EventData *evt_data) {
 | 
				
			|||||||
    USBMSG("%s [%u] %u\n", FIFO_STATUS_STR[pckt_status - 1], ep_num, byte_count);
 | 
					    USBMSG("%s [%u] %u\n", FIFO_STATUS_STR[pckt_status - 1], ep_num, byte_count);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// always pass ALIGNED data!
 | 
					/**
 | 
				
			||||||
 | 
					 * Function prototype for processing SETUP packets. This function is expected to be
 | 
				
			||||||
 | 
					 * overridden by the application.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @param data pointer to the SETUP packet
 | 
				
			||||||
 | 
					 * @param size size of the packet
 | 
				
			||||||
 | 
					 * @param stage stage of the SETUP transaction
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
__weak void usbcore_process_setup_pckt(const uint8_t *data, uint16_t size, uint8_t stage) {
 | 
					__weak void usbcore_process_setup_pckt(const uint8_t *data, uint16_t size, uint8_t stage) {
 | 
				
			||||||
 | 
					    // always pass ALIGNED data!
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__weak void usbcore_process_nonsetup_event(USBDRV_CallbackCompound *cbcpd) {
 | 
					/**
 | 
				
			||||||
 | 
					 * Function prototype for processing non-SETUP packets. This function is expected to be
 | 
				
			||||||
 | 
					 * overridden by the application.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @param cbcpd pointer to callback compound
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					__weak void usbcore_process_nonsetup_event(UsbDrv_CallbackCompound *cbcpd) {
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -815,7 +831,7 @@ void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data) {
 | 
				
			|||||||
                // SET_BIT(USBG->GINTMSK, USB_OTG_GINTMSK_RXFLVLM); // unmask interrupt
 | 
					                // SET_BIT(USBG->GINTMSK, USB_OTG_GINTMSK_RXFLVLM); // unmask interrupt
 | 
				
			||||||
            } else { // not EP0
 | 
					            } else { // not EP0
 | 
				
			||||||
                if (evt_data.rx.pckt_status == USB_PCKT_STATUS_OUT_DATA_RECV) {
 | 
					                if (evt_data.rx.pckt_status == USB_PCKT_STATUS_OUT_DATA_RECV) {
 | 
				
			||||||
                    USBDRV_CallbackCompound cbcpd;
 | 
					                    UsbDrv_CallbackCompound cbcpd;
 | 
				
			||||||
                    cbcpd.ep = evt_data.rx.ep_num;
 | 
					                    cbcpd.ep = evt_data.rx.ep_num;
 | 
				
			||||||
                    cbcpd.dir = USB_OUT;
 | 
					                    cbcpd.dir = USB_OUT;
 | 
				
			||||||
                    cbcpd.code = USB_CBC_OUT;
 | 
					                    cbcpd.code = USB_CBC_OUT;
 | 
				
			||||||
@ -852,7 +868,7 @@ void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data) {
 | 
				
			|||||||
        case USB_EVT_IN_DONE: { // some IN operations have finished
 | 
					        case USB_EVT_IN_DONE: { // some IN operations have finished
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // callback compound
 | 
					            // callback compound
 | 
				
			||||||
            USBDRV_CallbackCompound cbcpd;
 | 
					            UsbDrv_CallbackCompound cbcpd;
 | 
				
			||||||
            cbcpd.dir = USB_IN;
 | 
					            cbcpd.dir = USB_IN;
 | 
				
			||||||
            cbcpd.data = NULL;
 | 
					            cbcpd.data = NULL;
 | 
				
			||||||
            cbcpd.size = 0;
 | 
					            cbcpd.size = 0;
 | 
				
			||||||
@ -887,7 +903,7 @@ void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                            // invoke callback if registered
 | 
					                            // invoke callback if registered
 | 
				
			||||||
                            if (cbs[ep] != NULL) {
 | 
					                            if (cbs[ep] != NULL) {
 | 
				
			||||||
                                USBDRV_IN_cb cb = cbs[ep]; // fetch function pointer
 | 
					                                UsbDrv_IN_cb cb = cbs[ep]; // fetch function pointer
 | 
				
			||||||
                                cbs[ep] = NULL;            // clear callback
 | 
					                                cbs[ep] = NULL;            // clear callback
 | 
				
			||||||
                                cb(ep);                    // invoke the callback
 | 
					                                cb(ep);                    // invoke the callback
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
 | 
				
			|||||||
@ -118,6 +118,11 @@ void usbdrv_init();
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
void usbdrv_reset();
 | 
					void usbdrv_reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Init driver's global state.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void usbdrv_init_global_state();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Initialize driver interface.
 | 
					 * Initialize driver interface.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@ -138,7 +143,7 @@ void usbdrv_periph_init(bool reset);
 | 
				
			|||||||
void usbdrv_flush_tx_fifo(uint8_t n);
 | 
					void usbdrv_flush_tx_fifo(uint8_t n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Flush specific RX FIFO.
 | 
					 * Flush all RX FIFOs.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void usbdrv_flush_rx_fifo();
 | 
					void usbdrv_flush_rx_fifo();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -231,8 +236,6 @@ void usbdrv_autoarm_OUT_endpoint(uint8_t ep);
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
void usbdrv_enable_endpoint_interrupt(uint8_t ep, uint8_t dir, bool en);
 | 
					void usbdrv_enable_endpoint_interrupt(uint8_t ep, uint8_t dir, bool en);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Set the shared FIFO size for all receptions.
 | 
					 * Set the shared FIFO size for all receptions.
 | 
				
			||||||
 * (Shared among all OUT endpoints.)
 | 
					 * (Shared among all OUT endpoints.)
 | 
				
			||||||
@ -259,7 +262,6 @@ void usbdrv_preload_endpoint_config(uint8_t ep, uint8_t dir, const USBDRV_EpConf
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
void usbdrv_clear_endpoint_config();
 | 
					void usbdrv_clear_endpoint_config();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Apply preloaded Endpoint configuration, write
 | 
					 * Apply preloaded Endpoint configuration, write
 | 
				
			||||||
 * Endpoint config to the hardware.
 | 
					 * Endpoint config to the hardware.
 | 
				
			||||||
@ -296,7 +298,7 @@ void usbdrv_set_address(uint8_t addr);
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 * @return pointer to the driver interface
 | 
					 * @return pointer to the driver interface
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
USB_DrvIntf * usbdrv_get_intf();
 | 
					UsbDrv_DrvIntf *usbdrv_get_intf();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Register callback for IN transaction complete.
 | 
					 * Register callback for IN transaction complete.
 | 
				
			||||||
@ -304,6 +306,29 @@ USB_DrvIntf * usbdrv_get_intf();
 | 
				
			|||||||
 * @param ep index of the Endpoint
 | 
					 * @param ep index of the Endpoint
 | 
				
			||||||
 * @param cb pointer to the callback function
 | 
					 * @param cb pointer to the callback function
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void usbdrv_register_IN_complete_cb(uint8_t ep, USBDRV_IN_cb cb);
 | 
					void usbdrv_register_IN_complete_cb(uint8_t ep, UsbDrv_IN_cb cb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Get Endpoint interrupt flag.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param ep index of the Endpoint
 | 
				
			||||||
 | 
					 * @param dir direction of the Endpoint
 | 
				
			||||||
 | 
					 * @return flag was set
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					bool usbdrv_get_endpoint_interrupt_flag(uint8_t ep, uint8_t dir);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Process data on the RX FIFO top.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param evt_data pointer to event data target area
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void usbdrv_process_rx_fifo_top(USBDRV_EventData *evt_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Get the address table.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @return immutable pointer to the address table
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const char *usbdrv_get_fifo_addr_table();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* STM32_USB_DRV */
 | 
					#endif /* STM32_USB_DRV */
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										46
									
								
								examples/configs/flatUSB_config_stm32f4_internal.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								examples/configs/flatUSB_config_stm32f4_internal.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,46 @@
 | 
				
			|||||||
 | 
					#ifndef SRC_FLATUSB_CONFIG
 | 
				
			||||||
 | 
					#define SRC_FLATUSB_CONFIG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stm32f4xx_hal.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_VBUSSENSE (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void usbdrv_gpio_init() {
 | 
				
			||||||
 | 
					    __HAL_RCC_GPIOA_CLK_ENABLE(); // turn ON GPIOA clocks
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    GPIO_InitTypeDef gpio_init;
 | 
				
			||||||
 | 
					    gpio_init.Mode = GPIO_MODE_AF_PP;
 | 
				
			||||||
 | 
					    gpio_init.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 | 
				
			||||||
 | 
					    gpio_init.Pull = GPIO_NOPULL;
 | 
				
			||||||
 | 
					    gpio_init.Alternate = GPIO_AF10_OTG_FS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gpio_init.Pin = GPIO_PIN_11 | GPIO_PIN_12;
 | 
				
			||||||
 | 
					    HAL_GPIO_Init(GPIOA, &gpio_init); // USB D-, D+
 | 
				
			||||||
 | 
					#if USB_VBUSSENSE
 | 
				
			||||||
 | 
					    // FIXME
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_IRQ_N OTG_FS_IRQn
 | 
				
			||||||
 | 
					#define USB_IRQ_HANDLER OTG_FS_IRQHandler
 | 
				
			||||||
 | 
					#define USB_IRQ_PRIORITY (8)
 | 
				
			||||||
 | 
					#define USB_IRQ_SET_PRIORITY(irq, priority) HAL_NVIC_SetPriority((irq),(priority),0)
 | 
				
			||||||
 | 
					#define USB_IRQ_ENABLE(irq) HAL_NVIC_EnableIRQ((irq))
 | 
				
			||||||
 | 
					#define USB_IRQ_DISABLE(irq) HAL_NVIC_DisableIRQ((irq))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// define USBG
 | 
				
			||||||
 | 
					#define USBG (USB_OTG_FS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_CLOCK_ENABLE() __HAL_RCC_USB_OTG_FS_CLK_ENABLE()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_INTERNAL (1)
 | 
				
			||||||
 | 
					#define USB_UPLI (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "embfmt/embformat.h"
 | 
				
			||||||
 | 
					#define SNPRINTF(str, n, fmt, ...) embfmt(str, n, fmt, __VA_ARGS__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef USBDBGMSG
 | 
				
			||||||
 | 
					#define USBMSG(...) MSG(__VA_ARGS__)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* SRC_FLATUSB_CONFIG */
 | 
				
			||||||
							
								
								
									
										58
									
								
								examples/configs/flatUSB_config_stm32f4_ulpi.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								examples/configs/flatUSB_config_stm32f4_ulpi.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					#ifndef SRC_FLATUSB_CONFIG
 | 
				
			||||||
 | 
					#define SRC_FLATUSB_CONFIG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stm32f4xx_hal.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_VBUSSENSE (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void usbdrv_gpio_init() {
 | 
				
			||||||
 | 
					    // turn on GPIO clocks
 | 
				
			||||||
 | 
					    __HAL_RCC_GPIOA_CLK_ENABLE();
 | 
				
			||||||
 | 
					    __HAL_RCC_GPIOB_CLK_ENABLE();
 | 
				
			||||||
 | 
					    __HAL_RCC_GPIOC_CLK_ENABLE();
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    // initialize pins
 | 
				
			||||||
 | 
					    GPIO_InitTypeDef gpio_init;
 | 
				
			||||||
 | 
					    gpio_init.Mode = GPIO_MODE_AF_PP;
 | 
				
			||||||
 | 
					    gpio_init.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 | 
				
			||||||
 | 
					    gpio_init.Pull = GPIO_NOPULL;
 | 
				
			||||||
 | 
					    gpio_init.Alternate = GPIO_AF10_OTG_HS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gpio_init.Pin = GPIO_PIN_3 | GPIO_PIN_5; // D0, CK
 | 
				
			||||||
 | 
					    HAL_GPIO_Init(GPIOA, &gpio_init);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // D1, D2, D7, D3, D4, D5, D6
 | 
				
			||||||
 | 
					    gpio_init.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_5 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
 | 
				
			||||||
 | 
					    HAL_GPIO_Init(GPIOB, &gpio_init);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // STP, DIR, NXT
 | 
				
			||||||
 | 
					    gpio_init.Pin = GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3;
 | 
				
			||||||
 | 
					    HAL_GPIO_Init(GPIOC, &gpio_init);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if USB_VBUSSENSE
 | 
				
			||||||
 | 
					    // FIXME
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_IRQ_N OTG_HS_IRQn
 | 
				
			||||||
 | 
					#define USB_IRQ_HANDLER OTG_HS_IRQHandler
 | 
				
			||||||
 | 
					#define USB_IRQ_PRIORITY (8)
 | 
				
			||||||
 | 
					#define USB_IRQ_SET_PRIORITY(irq, priority) HAL_NVIC_SetPriority((irq),(priority),0)
 | 
				
			||||||
 | 
					#define USB_IRQ_ENABLE(irq) HAL_NVIC_EnableIRQ((irq))
 | 
				
			||||||
 | 
					#define USB_IRQ_DISABLE(irq) HAL_NVIC_DisableIRQ((irq))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USBG (USB_OTG_HS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_CLOCK_ENABLE() __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_INTERNAL (0)
 | 
				
			||||||
 | 
					#define USB_UPLI (1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "embfmt/embformat.h"
 | 
				
			||||||
 | 
					#define SNPRINTF(str, n, fmt, ...) embfmt(str, n, fmt, __VA_ARGS__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef USBDBGMSG
 | 
				
			||||||
 | 
					#define USBMSG(...) MSG(__VA_ARGS__)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* SRC_FLATUSB_CONFIG */
 | 
				
			||||||
							
								
								
									
										82
									
								
								examples/configs/flatUSB_config_stm32h7_internal.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								examples/configs/flatUSB_config_stm32h7_internal.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,82 @@
 | 
				
			|||||||
 | 
					#ifndef SRC_FLATUSB_CONFIG
 | 
				
			||||||
 | 
					#define SRC_FLATUSB_CONFIG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stm32h7xx_hal.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_VBUSSENSE (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// H723
 | 
				
			||||||
 | 
					#if 1
 | 
				
			||||||
 | 
					static inline void usbdrv_gpio_init() {
 | 
				
			||||||
 | 
					    __HAL_RCC_GPIOA_CLK_ENABLE();
 | 
				
			||||||
 | 
					#if USB_VBUSSENSE
 | 
				
			||||||
 | 
					    // FIXME
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// H743
 | 
				
			||||||
 | 
					#elif 1
 | 
				
			||||||
 | 
					static inline void usbdrv_gpio_init() {
 | 
				
			||||||
 | 
					    __HAL_RCC_GPIOA_CLK_ENABLE(); // turn ON GPIOA clocks
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    GPIO_InitTypeDef gpio_init;
 | 
				
			||||||
 | 
					    gpio_init.Mode = GPIO_MODE_AF_PP;
 | 
				
			||||||
 | 
					    gpio_init.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 | 
				
			||||||
 | 
					    gpio_init.Pull = GPIO_NOPULL;
 | 
				
			||||||
 | 
					    gpio_init.Alternate = GPIO_AF10_OTG_FS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    gpio_init.Pin = GPIO_PIN_11 | GPIO_PIN_12;
 | 
				
			||||||
 | 
					    HAL_GPIO_Init(GPIOA, &gpio_init); // USB D-, D+
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if USB_VBUSSENSE
 | 
				
			||||||
 | 
					    // FIXME
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// H723
 | 
				
			||||||
 | 
					#if 1
 | 
				
			||||||
 | 
					#define USB_IRQ_N OTG_HS_IRQn
 | 
				
			||||||
 | 
					#define USB_IRQ_HANDLER OTG_HS_IRQHandler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// H743
 | 
				
			||||||
 | 
					#elif 1
 | 
				
			||||||
 | 
					#define USB_IRQ_N OTG_FS_IRQn
 | 
				
			||||||
 | 
					#define USB_IRQ_HANDLER OTG_FS_IRQHandler
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_IRQ_PRIORITY (8)
 | 
				
			||||||
 | 
					#define USB_IRQ_SET_PRIORITY(irq, priority) HAL_NVIC_SetPriority((irq),(priority),0)
 | 
				
			||||||
 | 
					#define USB_IRQ_ENABLE(irq) HAL_NVIC_EnableIRQ((irq))
 | 
				
			||||||
 | 
					#define USB_IRQ_DISABLE(irq) HAL_NVIC_DisableIRQ((irq))
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					// H723
 | 
				
			||||||
 | 
					#if 1
 | 
				
			||||||
 | 
					#define USBG (USB_OTG_HS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// H743
 | 
				
			||||||
 | 
					#elif 1 
 | 
				
			||||||
 | 
					#define USBG (USB_OTG_FS)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_STM32H7_ENABLE_USB_VOLTAGE_DETECTOR()  HAL_PWREx_EnableUSBVoltageDetector(); WAIT_FOR_nBIT_DELAY(PWR->CR3, PWR_CR3_USB33RDY, 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// STM32H723
 | 
				
			||||||
 | 
					#if 1
 | 
				
			||||||
 | 
					#define USB_CLOCK_ENABLE() USB_STM32H7_ENABLE_USB_VOLTAGE_DETECTOR(); __HAL_RCC_USB1_OTG_HS_CLK_ENABLE()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// STM32H743
 | 
				
			||||||
 | 
					#elif 1
 | 
				
			||||||
 | 
					#define USB_CLOCK_ENABLE() USB_STM32H7_ENABLE_USB_VOLTAGE_DETECTOR(); __HAL_RCC_USB2_OTG_FS_CLK_ENABLE()
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_INTERNAL (1)
 | 
				
			||||||
 | 
					#define USB_UPLI (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "embfmt/embformat.h"
 | 
				
			||||||
 | 
					#define SNPRINTF(str, n, fmt, ...) embfmt(str, n, fmt, __VA_ARGS__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef USBDBGMSG
 | 
				
			||||||
 | 
					#define USBMSG(...) MSG(__VA_ARGS__)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* SRC_FLATUSB_CONFIG */
 | 
				
			||||||
							
								
								
									
										38
									
								
								examples/configs/flatUSB_config_stm32h7_ulpi.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								examples/configs/flatUSB_config_stm32h7_ulpi.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					#ifndef SRC_FLATUSB_CONFIG
 | 
				
			||||||
 | 
					#define SRC_FLATUSB_CONFIG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stm32h7xx_hal.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_VBUSSENSE (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void usbdrv_gpio_init() {
 | 
				
			||||||
 | 
					    // FIXME
 | 
				
			||||||
 | 
					#if USB_VBUSSENSE
 | 
				
			||||||
 | 
					    // FIXME
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_IRQ_N OTG_HS_IRQn
 | 
				
			||||||
 | 
					#define USB_IRQ_HANDLER OTG_HS_IRQHandler
 | 
				
			||||||
 | 
					#define USB_IRQ_PRIORITY (8)
 | 
				
			||||||
 | 
					#define USB_IRQ_SET_PRIORITY(irq, priority) HAL_NVIC_SetPriority((irq),(priority),0)
 | 
				
			||||||
 | 
					#define USB_IRQ_ENABLE(irq) HAL_NVIC_EnableIRQ((irq))
 | 
				
			||||||
 | 
					#define USB_IRQ_DISABLE(irq) HAL_NVIC_DisableIRQ((irq))
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					#define USBG (USB_OTG_HS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_STM32H7_ENABLE_USB_VOLTAGE_DETECTOR() // FIXME
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_CLOCK_ENABLE() // FIXME
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_INTERNAL (0)
 | 
				
			||||||
 | 
					#define USB_UPLI (1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "embfmt/embformat.h"
 | 
				
			||||||
 | 
					#define SNPRINTF(str, n, fmt, ...) embfmt(str, n, fmt, __VA_ARGS__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef USBDBGMSG
 | 
				
			||||||
 | 
					#define USBMSG(...) MSG(__VA_ARGS__)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* SRC_FLATUSB_CONFIG */
 | 
				
			||||||
							
								
								
									
										89
									
								
								usb.c
									
									
									
									
									
								
							
							
						
						
									
										89
									
								
								usb.c
									
									
									
									
									
								
							@ -6,72 +6,52 @@
 | 
				
			|||||||
#include "usb_common.h"
 | 
					#include "usb_common.h"
 | 
				
			||||||
#include "usb_driver_common.h"
 | 
					#include "usb_driver_common.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// #include "utils/gen_queue.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include FLATUSB_DESCRIPTOR_HEADER
 | 
					#include FLATUSB_DESCRIPTOR_HEADER
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ---------------
 | 
					// ---------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** \cond false */
 | 
				
			||||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
 | 
					#define MAX(a, b) (((a) > (b)) ? (a) : (b))
 | 
				
			||||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
 | 
					#define MIN(a, b) (((a) < (b)) ? (a) : (b))
 | 
				
			||||||
 | 
					/** \endcond */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USBDRV_ARM_IN_ZLP(ep) drv->arm_IN((ep), NULL, 0) ///< Arm a ZLP IN message
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ---------------
 | 
					// ---------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define USBDRV_ARM_IN_ZLP(ep) drv->arm_IN((ep), NULL, 0)
 | 
					static uint8_t tx_assembly_buf[USB_RX_BUF_SIZE] DWORD_ALIGN; ///< Buffer for assembling packets
 | 
				
			||||||
 | 
					static Usb_SetupTransferState stups; ///< Setup transfer state.
 | 
				
			||||||
#define USB_RX_BUF_SIZE (512)                                // FIXME
 | 
					static UsbDrv_DrvIntf *drv; ///< Mutable pointer to the driver interface
 | 
				
			||||||
static uint8_t tx_assembly_buf[USB_RX_BUF_SIZE] DWORD_ALIGN; // buffer for assembling packets
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ---------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// // state of changeing address
 | 
					 | 
				
			||||||
// typedef enum {
 | 
					 | 
				
			||||||
//     USB_ADDRCHG_IDLE = 0, // idle state
 | 
					 | 
				
			||||||
//     USB_ADDRCHG_NEW_ADDR_RECVD, // new address received
 | 
					 | 
				
			||||||
// } USB_AddressChangeState;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ----------------
 | 
					// ----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__attribute__((weak)) void usb_event_callback(USB_CallbackEvent *cbevt) {
 | 
					/**
 | 
				
			||||||
 | 
					 * @fn void usb_event_callback(USB_CallbackEvent *cbevt)
 | 
				
			||||||
 | 
					 * Prototype for the USB event callback.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @param cbevt pointer to the event data
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					__attribute__((weak)) void usb_event_callback(Usb_CallbackEvent *cbevt) {
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ----------------
 | 
					// ----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// prepare descriptor for transmission, return with final transmission size
 | 
					/**
 | 
				
			||||||
// static uint8_t usb_prepare_descriptor(const uint8_t *desc, uint8_t desc_size, uint8_t req_size) {
 | 
					 * Callback function for bus issued Reset is done notification.
 | 
				
			||||||
//     uint8_t sz = (uint8_t)(MIN(req_size, desc_size));     // determine transmission size
 | 
					 */
 | 
				
			||||||
//     memcpy(gs.tx_assembly_buf, desc, sz);                 // copy that portion to the assembly buffer
 | 
					 | 
				
			||||||
//     USB_DescHdr *hdr = (USB_DescHdr *)gs.tx_assembly_buf; // obtain header
 | 
					 | 
				
			||||||
//     hdr->bLength = MIN(sz, hdr->bLength);                 // write transmit size
 | 
					 | 
				
			||||||
//     return sz;
 | 
					 | 
				
			||||||
// }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// #define USB_SETUP_STREAM_BUFFER (72)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
    USB_SetupRequest setup_req; // setup request
 | 
					 | 
				
			||||||
    uint8_t next_stage;         // next expected stage
 | 
					 | 
				
			||||||
    bool out_complete;          // signals if transfer's OUT direction is complete, no later data reception is expected
 | 
					 | 
				
			||||||
} USB_SetupTransferState;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static USB_SetupTransferState stups;
 | 
					 | 
				
			||||||
static USB_DrvIntf *drv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void usbcore_reset() {
 | 
					 | 
				
			||||||
    // init state
 | 
					 | 
				
			||||||
    memset(&stups, 0, sizeof(USB_SetupTransferState));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void usbcore_rst_notify() {
 | 
					static void usbcore_rst_notify() {
 | 
				
			||||||
    usbcore_reset();
 | 
					    usbcore_reset();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Callback for Enumeration Done notification.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
static void usbcore_enum_notify(uint8_t spd) {
 | 
					static void usbcore_enum_notify(uint8_t spd) {
 | 
				
			||||||
    (void)spd;
 | 
					    (void)spd;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void usbcore_init(USB_DrvIntf *drvIntf) {
 | 
					void usbcore_init(UsbDrv_DrvIntf *drvIntf) {
 | 
				
			||||||
    usbcore_reset(); // reset USB Core
 | 
					    usbcore_reset(); // reset USB Core
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    drv = drvIntf;                          // store USB driver interface assignments
 | 
					    drv = drvIntf;                          // store USB driver interface assignments
 | 
				
			||||||
@ -79,6 +59,18 @@ void usbcore_init(USB_DrvIntf *drvIntf) {
 | 
				
			|||||||
    drv->enum_notify = usbcore_enum_notify; // assign Enumeration Done callback
 | 
					    drv->enum_notify = usbcore_enum_notify; // assign Enumeration Done callback
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usbcore_reset() {
 | 
				
			||||||
 | 
					    // init state
 | 
				
			||||||
 | 
					    memset(&stups, 0, sizeof(Usb_SetupTransferState));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Process SETUP packets.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @param data pointer to the SETUP packet
 | 
				
			||||||
 | 
					 * @param size size of the packet
 | 
				
			||||||
 | 
					 * @param stage stage of the SETUP transaction
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
void usbcore_process_setup_pckt(const uint8_t *data, uint16_t size, uint8_t stage) {
 | 
					void usbcore_process_setup_pckt(const uint8_t *data, uint16_t size, uint8_t stage) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // MSG("STUP: %u, %s\n", size, stage == UST_SETUP ? "SETUP" : "DATA");
 | 
					    // MSG("STUP: %u, %s\n", size, stage == UST_SETUP ? "SETUP" : "DATA");
 | 
				
			||||||
@ -186,12 +178,12 @@ void usbcore_process_setup_pckt(const uint8_t *data, uint16_t size, uint8_t stag
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    case UREQ_SetInterface: // SET INTERFACE
 | 
					    case UREQ_SetInterface: // SET INTERFACE
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // TODO: set configuration
 | 
					        // TODO: set interface
 | 
				
			||||||
        USBDRV_ARM_IN_ZLP(0);
 | 
					        USBDRV_ARM_IN_ZLP(0);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    default: { // UNKNOWN REQUEST, pass processing to user application
 | 
					    default: { // UNKNOWN REQUEST, pass processing to user application
 | 
				
			||||||
        USB_CallbackEvent cbevt = {0};
 | 
					        Usb_CallbackEvent cbevt = {0};
 | 
				
			||||||
        cbevt.type = USB_CBEVT_UNKNOWN_REQ;
 | 
					        cbevt.type = USB_CBEVT_UNKNOWN_REQ;
 | 
				
			||||||
        cbevt.setup_request = &stups.setup_req;
 | 
					        cbevt.setup_request = &stups.setup_req;
 | 
				
			||||||
        cbevt.data = (const uint8_t *)data;
 | 
					        cbevt.data = (const uint8_t *)data;
 | 
				
			||||||
@ -211,8 +203,13 @@ void usbcore_process_setup_pckt(const uint8_t *data, uint16_t size, uint8_t stag
 | 
				
			|||||||
    stups.out_complete = false;
 | 
					    stups.out_complete = false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void usbcore_process_nonsetup_event(USBDRV_CallbackCompound *cbcpd) {
 | 
					/**
 | 
				
			||||||
    USB_CallbackEvent cbevt = {0}; // allocate and clear structure...
 | 
					 * Process the non-SETUP packets.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @param cbcpd pointer to callback compound
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void usbcore_process_nonsetup_event(UsbDrv_CallbackCompound *cbcpd) {
 | 
				
			||||||
 | 
					    Usb_CallbackEvent cbevt = {0}; // allocate and clear structure...
 | 
				
			||||||
    cbevt.ep = cbcpd->ep;          // later only fill nonzero fields
 | 
					    cbevt.ep = cbcpd->ep;          // later only fill nonzero fields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool discard_event = false; // only discard if event does not fit any category above
 | 
					    bool discard_event = false; // only discard if event does not fit any category above
 | 
				
			||||||
@ -257,7 +254,7 @@ void usbcore_wake_up_endpoint(uint8_t ep, uint8_t dir) {
 | 
				
			|||||||
    drv->en_ep_irq(ep, dir, true);
 | 
					    drv->en_ep_irq(ep, dir, true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void usbcore_register_IN_callback(uint8_t ep, USBDRV_IN_cb cb) {
 | 
					void usbcore_register_IN_callback(uint8_t ep, UsbDrv_IN_cb cb) {
 | 
				
			||||||
    drv->reg_IN_cb(ep, cb);
 | 
					    drv->reg_IN_cb(ep, cb);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										73
									
								
								usb.h
									
									
									
									
									
								
							
							
						
						
									
										73
									
								
								usb.h
									
									
									
									
									
								
							@ -3,12 +3,75 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "usb_device_types.h"
 | 
				
			||||||
#include "usb_driver_common.h"
 | 
					#include "usb_driver_common.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void usbcore_init(USB_DrvIntf *drvIntf);                                                // initialize USB core
 | 
					// --------------
 | 
				
			||||||
uint32_t usbcore_schedule_transmission(uint8_t ep, const uint8_t *data, uint16_t size); // write data to endpoint, return with number of bytes actually written
 | 
					
 | 
				
			||||||
uint32_t usbcore_schedule_reception(uint8_t ep, uint16_t size);                         // expect data coming from the endpoint
 | 
					/**
 | 
				
			||||||
void usbcore_wake_up_endpoint(uint8_t ep, uint8_t dir);                                 // wake up endpoint
 | 
					 * Setup transfer state.
 | 
				
			||||||
void usbcore_register_IN_callback(uint8_t ep, USBDRV_IN_cb cb);                         // register IN complete callback
 | 
					 */
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    USB_SetupRequest setup_req; ///< Setup request
 | 
				
			||||||
 | 
					    uint8_t next_stage;         ///< Next expected stage
 | 
				
			||||||
 | 
					    bool out_complete;          ///< Signals if transfer's OUT direction is complete, no later data reception is expected
 | 
				
			||||||
 | 
					} Usb_SetupTransferState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// --------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** \cond 0 */
 | 
				
			||||||
 | 
					#ifndef USB_RX_BUF_SIZE
 | 
				
			||||||
 | 
					#define USB_RX_BUF_SIZE (512) ///< Receive buffer size FIXME
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					/** \endcond */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// --------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Initialize USB core.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param drvIntf pointer to a mutable driver interface object
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void usbcore_init(UsbDrv_DrvIntf *drvIntf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Reset USB core.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void usbcore_reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Write data to an IN Endpoint.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param ep index of the Endpoint
 | 
				
			||||||
 | 
					 * @param data pointer to data to be written
 | 
				
			||||||
 | 
					 * @param size data length
 | 
				
			||||||
 | 
					 * @return number of bytes written
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					uint32_t usbcore_schedule_transmission(uint8_t ep, const uint8_t *data, uint16_t size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Expect ingress data on an Endpoint.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param ep index of the Endpoint
 | 
				
			||||||
 | 
					 * @param size expected reception length
 | 
				
			||||||
 | 
					 * @return message length that the endpoint can support during next reception
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					uint32_t usbcore_schedule_reception(uint8_t ep, uint16_t size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Wake up an Endpoint.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param ep index of the Endpoint
 | 
				
			||||||
 | 
					 * @param dir direction of the Endpoint
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void usbcore_wake_up_endpoint(uint8_t ep, uint8_t dir);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Register a callback for IN transmission completion.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param ep index of the Endpoint
 | 
				
			||||||
 | 
					 * @param cb callback function
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void usbcore_register_IN_callback(uint8_t ep, UsbDrv_IN_cb cb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* CORE_USB_USB */
 | 
					#endif /* CORE_USB_USB */
 | 
				
			||||||
 | 
				
			|||||||
@ -5,30 +5,39 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "usb_device_types.h"
 | 
					#include "usb_device_types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Callback event type. 
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    USB_CBEVT_OUT, // OUT event
 | 
					    USB_CBEVT_OUT,        ///< OUT event
 | 
				
			||||||
    USB_CBEVT_IN, // IN event
 | 
					    USB_CBEVT_IN,         ///< IN event
 | 
				
			||||||
    USB_CBEVT_UNKNOWN_REQ // unknown request on a control endpoint
 | 
					    USB_CBEVT_UNKNOWN_REQ ///< unknown request on a control endpoint
 | 
				
			||||||
} USB_CallbackEventType;
 | 
					} Usb_CallbackEventType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Callback event subtype.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    USB_CBEVST_IN_NONE = 0, // no subtype
 | 
					    USB_CBEVST_IN_NONE = 0, ///< No subtype
 | 
				
			||||||
    USB_CBEVST_IN_REQ // IN request was received but could not be responded
 | 
					    USB_CBEVST_IN_REQ       ///< IN request was received but could not be responded
 | 
				
			||||||
} USB_CallbackEventSubType;
 | 
					} Usb_CallbackEventSubType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * USB callback event.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    uint8_t type : 4; // event type
 | 
					    uint8_t type : 4;                      ///< Event type
 | 
				
			||||||
    uint8_t subtype : 4; // event subtype
 | 
					    uint8_t subtype : 4;                   ///< Event subtype
 | 
				
			||||||
    uint8_t ep;   // endpoint number
 | 
					    uint8_t ep;                            ///< Endpoint number
 | 
				
			||||||
    uint8_t dir;  // endpoint direction
 | 
					    uint8_t dir;                           ///< Endpoint direction
 | 
				
			||||||
    uint8_t size; // size of accompaining data
 | 
					    uint8_t size;                          ///< Size of accompaining data
 | 
				
			||||||
    const uint8_t * data; // event data
 | 
					    const uint8_t *data;                   ///< Event data
 | 
				
			||||||
    const USB_SetupRequest * setup_request; // corresponding setup request (if exists)
 | 
					    const USB_SetupRequest *setup_request; ///< Corresponding setup request (if exists)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool reply_valid; // reply message is valid
 | 
					    bool reply_valid;          ///< Reply message is valid
 | 
				
			||||||
    const uint8_t * reply_data; // reply data
 | 
					    const uint8_t *reply_data; ///< Reply data
 | 
				
			||||||
    uint8_t reply_size; // reply size
 | 
					    uint8_t reply_size;        ///< Reply size
 | 
				
			||||||
    bool arm_out_endpoint; // automatically arm OUT endpoint at the end of the current transmission
 | 
					    bool arm_out_endpoint;     ///< Automatically arm OUT endpoint at the end of the current transmission
 | 
				
			||||||
} USB_CallbackEvent;
 | 
					} Usb_CallbackEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* CORE_USB_USB_CALLBACK_EVENT */
 | 
					#endif /* CORE_USB_USB_CALLBACK_EVENT */
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										20
									
								
								usb_common.h
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								usb_common.h
									
									
									
									
									
								
							@ -4,18 +4,18 @@
 | 
				
			|||||||
#include "usb_common_types.h"
 | 
					#include "usb_common_types.h"
 | 
				
			||||||
#include "usb_device_types.h"
 | 
					#include "usb_device_types.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define USB_DELAY(t) for (uint64_t i = 0; i < (t) * 10000; i++) { asm("nop"); }
 | 
					#define USB_DELAY(t) for (uint64_t i = 0; i < (t) * 10000; i++) { asm("nop"); } ///< Create a delay that does not relay on the processor ticks.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define READ_FIELD(r,f) (((r) & (f##_Msk)) >> (f##_Pos))
 | 
					#define READ_FIELD(r,f) (((r) & (f##_Msk)) >> (f##_Pos)) ///< Read a named field of a register
 | 
				
			||||||
#define WRITE_FIELD(r,f,v) ((r) = ((r) & ~(f##_Msk)) | (v << (f##_Pos)))
 | 
					#define WRITE_FIELD(r,f,v) ((r) = ((r) & ~(f##_Msk)) | (v << (f##_Pos))) ///< Write a name field of a register
 | 
				
			||||||
#define WAIT_FOR_BIT(r,b) while ((r) & (b)) {}
 | 
					#define WAIT_FOR_BIT(r,b) while ((r) & (b)) {} ///< Wait for a bit to clear
 | 
				
			||||||
#define WAIT_FOR_BIT_DELAY(r,b,d) while ((r) & (b)) { USB_DELAY((d)); }
 | 
					#define WAIT_FOR_BIT_DELAY(r,b,d) while ((r) & (b)) { USB_DELAY((d)); } ///< Wait for a bit to clear with injected delay
 | 
				
			||||||
#define WAIT_FOR_nBIT(r,b) while (!((r) & (b))) {}
 | 
					#define WAIT_FOR_nBIT(r,b) while (!((r) & (b))) {} ///< Wait for a bit to set
 | 
				
			||||||
#define WAIT_FOR_nBIT_DELAY(r,b,d) while (!((r) & (b))) { USB_DELAY((d)); }
 | 
					#define WAIT_FOR_nBIT_DELAY(r,b,d) while (!((r) & (b))) { USB_DELAY((d)); } ///< Wait for a bit to set with injected delay
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DWORD_ALIGN __attribute__((aligned(4)))
 | 
					#define DWORD_ALIGN __attribute__((aligned(4))) ///< Declare a 32-bit aligned memory area
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CEILDIV4(x) (((x) + 3) >> 2)
 | 
					#define CEILDIV4(x) (((x) + 3) >> 2) ///< Integer division by four after rounding up to the nearest multiple of 4
 | 
				
			||||||
#define CEIL4(x) (((x) + 3) & (~0b11))
 | 
					#define CEIL4(x) (((x) + 3) & (~0b11)) ///< Round up to the closest multiple of 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* CORE_USB_USB_COMMON */
 | 
					#endif /* CORE_USB_USB_COMMON */
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,9 @@
 | 
				
			|||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <stdbool.h>
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * A byte-sized boolean.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef uint8_t bool8_t;
 | 
					typedef uint8_t bool8_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* CORE_USB_USB_COMMON_TYPES */
 | 
					#endif /* CORE_USB_USB_COMMON_TYPES */
 | 
				
			||||||
 | 
				
			|||||||
@ -9,109 +9,120 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* ------ USB DESCRIPTORS ------- */
 | 
					/* ------ USB DESCRIPTORS ------- */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// USB Descriptor type codes
 | 
					/**
 | 
				
			||||||
 | 
					 * USB Descriptor type codes.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    UD_Device = 1,
 | 
					    UD_Device = 1,                 ///< Device Descriptor
 | 
				
			||||||
    UD_Configuration = 2,
 | 
					    UD_Configuration = 2,          ///< Configuration Descriptor
 | 
				
			||||||
    UD_String = 3,
 | 
					    UD_String = 3,                 ///< String Descriptor
 | 
				
			||||||
    UD_Interface = 4,
 | 
					    UD_Interface = 4,              ///< Interface Descriptor
 | 
				
			||||||
    UD_Endpoint = 5,
 | 
					    UD_Endpoint = 5,               ///< Endpoint Descriptor
 | 
				
			||||||
    UD_DeviceQualifier = 6,
 | 
					    UD_DeviceQualifier = 6,        ///< DeviceQualifier Descriptor
 | 
				
			||||||
    UD_OtherSpeedConfiguration = 7
 | 
					    UD_OtherSpeedConfiguration = 7 ///< OtherSpeedConfiguration Descriptor
 | 
				
			||||||
    // NOT FULL!
 | 
					    // NOT FULL!
 | 
				
			||||||
} USB_DescType;
 | 
					} USB_DescType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// USB descriptor header
 | 
					/**
 | 
				
			||||||
 | 
					 * USB descriptor header
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
#define USB_DESC_HEADER                            \
 | 
					#define USB_DESC_HEADER                            \
 | 
				
			||||||
    uint8_t bLength;         /* length in bytes */ \
 | 
					    uint8_t bLength;         /* length in bytes */ \
 | 
				
			||||||
    uint8_t bDescriptorType; /* descriptor type */
 | 
					    uint8_t bDescriptorType; /* descriptor type */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define USB_DESC_HEADER_SIZE (2) // USB descriptor header size
 | 
					#define USB_DESC_HEADER_SIZE (2) ///< USB descriptor header size
 | 
				
			||||||
 | 
					 | 
				
			||||||
// USB Descriptor header
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * USB Descriptor header
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    USB_DESC_HEADER
 | 
					    USB_DESC_HEADER
 | 
				
			||||||
} USB_DescHdr;
 | 
					} USB_DescHdr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// USB Device descriptor
 | 
					/**
 | 
				
			||||||
 | 
					 * USB Device descriptor
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    USB_DESC_HEADER
 | 
					    USB_DESC_HEADER
 | 
				
			||||||
    uint16_t bcdUSB;           // USB specification release number (BCD)
 | 
					    uint16_t bcdUSB;           ///< USB specification release number (BCD)
 | 
				
			||||||
    uint8_t bDeviceClass;      // Class code
 | 
					    uint8_t bDeviceClass;      ///< Class code
 | 
				
			||||||
    uint8_t bDeviceSubclass;   // Subclass code
 | 
					    uint8_t bDeviceSubclass;   ///< Subclass code
 | 
				
			||||||
    uint8_t bDeviceProtocol;   // Protocol code
 | 
					    uint8_t bDeviceProtocol;   ///< Protocol code
 | 
				
			||||||
    uint8_t bMaxPacketSize0;   // Maximum packet size for endpoint 0
 | 
					    uint8_t bMaxPacketSize0;   ///< Maximum packet size for endpoint 0
 | 
				
			||||||
    uint16_t idVendor;         // Vendor ID
 | 
					    uint16_t idVendor;         ///< Vendor ID
 | 
				
			||||||
    uint16_t idProduct;        // Product ID
 | 
					    uint16_t idProduct;        ///< Product ID
 | 
				
			||||||
    uint16_t bcdDevice;        // Device release number (BCD)
 | 
					    uint16_t bcdDevice;        ///< Device release number (BCD)
 | 
				
			||||||
    uint8_t iManufacturer;     // Index of string descriptor for manufacturer
 | 
					    uint8_t iManufacturer;     ///< Index of string descriptor for manufacturer
 | 
				
			||||||
    uint8_t iProduct;          // Index of string descriptor for the product
 | 
					    uint8_t iProduct;          ///< Index of string descriptor for the product
 | 
				
			||||||
    uint8_t iSerialNumber;     // Index of string descriptor for the serial number
 | 
					    uint8_t iSerialNumber;     ///< Index of string descriptor for the serial number
 | 
				
			||||||
    uint8_t bNumConfiguration; // Number of possible configurations
 | 
					    uint8_t bNumConfiguration; ///< Number of possible configurations
 | 
				
			||||||
} USB_DeviceDesc;
 | 
					} USB_DeviceDesc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// USB Device Qualifier descriptor
 | 
					/**
 | 
				
			||||||
 | 
					 * USB Device Qualifier descriptor
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    USB_DESC_HEADER
 | 
					    USB_DESC_HEADER
 | 
				
			||||||
    uint16_t bcdUSB;           // USB specification release number (BCD)
 | 
					    uint16_t bcdUSB;           ///< USB specification release number (BCD)
 | 
				
			||||||
    uint8_t bDeviceClass;      // Class code
 | 
					    uint8_t bDeviceClass;      ///< Class code
 | 
				
			||||||
    uint8_t bDeviceSubclass;   // Subclass code
 | 
					    uint8_t bDeviceSubclass;   ///< Subclass code
 | 
				
			||||||
    uint8_t bDeviceProtocol;   // Protocol code
 | 
					    uint8_t bDeviceProtocol;   ///< Protocol code
 | 
				
			||||||
    uint8_t bMaxPacketSize0;   // Maximum packet size for endpoint 0
 | 
					    uint8_t bMaxPacketSize0;   ///< Maximum packet size for endpoint 0
 | 
				
			||||||
    uint8_t bNumConfiguration; // Number of possible configurations
 | 
					    uint8_t bNumConfiguration; ///< Number of possible configurations
 | 
				
			||||||
} __attribute__((packed)) USB_DeviceQualifierDesc;
 | 
					} __attribute__((packed)) USB_DeviceQualifierDesc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define USB_CONFIG_ATTR_SELF_POWERED (1 << 6)
 | 
					#define USB_CONFIG_ATTR_SELF_POWERED (1 << 6) ///< Device is self-powered
 | 
				
			||||||
#define USB_CONFIG_ATTR_REMOTE_WKUP (1 << 5)
 | 
					#define USB_CONFIG_ATTR_REMOTE_WKUP (1 << 5)  ///< Device is intended to wake up the host
 | 
				
			||||||
#define USB_CONFIG_ATTR_USB1_1_FLAG (1 << 7)
 | 
					#define USB_CONFIG_ATTR_USB1_1_FLAG (1 << 7)  ///< It's a USB 1.1 or newer device
 | 
				
			||||||
 | 
					 | 
				
			||||||
// USB Configuration descriptor
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * USB Configuration descriptor
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    USB_DESC_HEADER
 | 
					    USB_DESC_HEADER
 | 
				
			||||||
    uint16_t wTotalLength;      // The number of bytes in the configuration descriptor and all of its subordinate descriptors
 | 
					    uint16_t wTotalLength;      ///< The number of bytes in the configuration descriptor and all of its subordinate descriptors
 | 
				
			||||||
    uint8_t bNumInterfaces;     // Number of interfaces in the configuration
 | 
					    uint8_t bNumInterfaces;     ///< Number of interfaces in the configuration
 | 
				
			||||||
    uint8_t bConfigrationValue; // Identifier for Set Configuration and Get Configuration Requests
 | 
					    uint8_t bConfigrationValue; ///< Identifier for Set Configuration and Get Configuration Requests
 | 
				
			||||||
    uint8_t iConfiguration;     // Index of string descriptor for the configuration
 | 
					    uint8_t iConfiguration;     ///< Index of string descriptor for the configuration
 | 
				
			||||||
    uint8_t bmAttributes;       // Self/bus power and remote wakeup settings
 | 
					    uint8_t bmAttributes;       ///< Self/bus power and remote wakeup settings
 | 
				
			||||||
    uint8_t bMaxPower;          // Bus power required in units of 2 mA
 | 
					    uint8_t bMaxPower;          ///< Bus power required in units of 2 mA
 | 
				
			||||||
} __attribute__((packed)) USB_ConfigurationDesc;
 | 
					} __attribute__((packed)) USB_ConfigurationDesc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// USB Interface descriptor
 | 
					/**
 | 
				
			||||||
 | 
					 * USB Interface descriptor
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    USB_DESC_HEADER
 | 
					    USB_DESC_HEADER
 | 
				
			||||||
    uint8_t bInterfaceNumber;   // Number identifying this interface
 | 
					    uint8_t bInterfaceNumber;   ///< Number identifying this interface
 | 
				
			||||||
    uint8_t bAlternateSetting;  // A number that identifies a descriptor with alternate settings for this bInterfaceNumber
 | 
					    uint8_t bAlternateSetting;  ///< A number that identifies a descriptor with alternate settings for this bInterfaceNumber
 | 
				
			||||||
    uint8_t bNumEndpoints;      // Number of endpoints supported not counting endpoint zero
 | 
					    uint8_t bNumEndpoints;      ///< Number of endpoints supported not counting endpoint zero
 | 
				
			||||||
    uint8_t bInterfaceClass;    // Class code
 | 
					    uint8_t bInterfaceClass;    ///< Class code
 | 
				
			||||||
    uint8_t bInterfaceSubclass; // Subclass code
 | 
					    uint8_t bInterfaceSubclass; ///< Subclass code
 | 
				
			||||||
    uint8_t bInterfaceProtocol; // Protocol code
 | 
					    uint8_t bInterfaceProtocol; ///< Protocol code
 | 
				
			||||||
    uint8_t iInterface;         // Index of string descriptor for the interface
 | 
					    uint8_t iInterface;         ///< Index of string descriptor for the interface
 | 
				
			||||||
} __attribute__((packed)) USB_InterfaceDesc;
 | 
					} __attribute__((packed)) USB_InterfaceDesc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// USB Transfer type
 | 
					/**
 | 
				
			||||||
 | 
					 * USB Transfer type
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    UT_Control = 0b00,
 | 
					    UT_Control = 0b00,     ///< Control
 | 
				
			||||||
    UT_Isochronous = 0b01,
 | 
					    UT_Isochronous = 0b01, ///< Isochronous
 | 
				
			||||||
    UT_Bulk = 0b10,
 | 
					    UT_Bulk = 0b10,        ///< Bulk
 | 
				
			||||||
    UT_Interrupt = 0b11
 | 
					    UT_Interrupt = 0b11    ///< Interrupt
 | 
				
			||||||
} USB_TransferType;
 | 
					} USB_TransferType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// USB Endpoint descriptor
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * USB Endpoint descriptor
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    USB_DESC_HEADER
 | 
					    USB_DESC_HEADER
 | 
				
			||||||
    uint8_t bEndpointAddress; // Endpoint number and direction
 | 
					    uint8_t bEndpointAddress; ///< Endpoint number and direction
 | 
				
			||||||
    uint8_t bmAttributes;    // Transfer type and supplementary information
 | 
					    uint8_t bmAttributes;     ///< Transfer type and supplementary information
 | 
				
			||||||
    uint16_t wMaxPacketSize; // Maximum packet size supported
 | 
					    uint16_t wMaxPacketSize;  ///< Maximum packet size supported
 | 
				
			||||||
    uint8_t bInterval;       // Service interval or NAK rate
 | 
					    uint8_t bInterval;        ///< Service interval or NAK rate
 | 
				
			||||||
} __attribute__((packed)) USB_EndpointDesc;
 | 
					} __attribute__((packed)) USB_EndpointDesc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*  struct {
 | 
					/*  struct {
 | 
				
			||||||
@ -119,21 +130,25 @@ typedef struct {
 | 
				
			|||||||
        uint8_t dir;         // direction
 | 
					        uint8_t dir;         // direction
 | 
				
			||||||
    } bEndpointAddress;      // Endpoint number and direction*/
 | 
					    } bEndpointAddress;      // Endpoint number and direction*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// USB String descriptor
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 
 | 
				
			||||||
 | 
					 * USB String descriptor
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    USB_DESC_HEADER
 | 
					    USB_DESC_HEADER
 | 
				
			||||||
} USB_StringDesc;
 | 
					} USB_StringDesc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// USB endpoint direction
 | 
					/**
 | 
				
			||||||
 | 
					 * USB endpoint direction
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    USB_OUT = 0,
 | 
					    USB_OUT = 0, ///< OUT
 | 
				
			||||||
    USB_IN = 1
 | 
					    USB_IN = 1 ///< IN
 | 
				
			||||||
} USB_EndpointDir;
 | 
					} USB_EndpointDir;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// USB PIDs
 | 
					/**
 | 
				
			||||||
 | 
					 * USB PIDs
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    PID_EXT = 0,
 | 
					    PID_EXT = 0,
 | 
				
			||||||
    PID_OUT = 1,
 | 
					    PID_OUT = 1,
 | 
				
			||||||
@ -153,16 +168,18 @@ typedef enum {
 | 
				
			|||||||
    PID_MDATA = 15,
 | 
					    PID_MDATA = 15,
 | 
				
			||||||
} USB_PID;
 | 
					} USB_PID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// USB Request types
 | 
					/**
 | 
				
			||||||
 | 
					 * USB Request types
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    UR_Standard = 0,
 | 
					    UR_Standard = 0,
 | 
				
			||||||
    UR_VendorSpec = 1,
 | 
					    UR_VendorSpec = 1,
 | 
				
			||||||
    UR_ReqDefVendorSpec = 2
 | 
					    UR_ReqDefVendorSpec = 2
 | 
				
			||||||
} USB_RequestType;
 | 
					} USB_RequestType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// USB Recipients
 | 
					/**
 | 
				
			||||||
 | 
					 * USB Recipients
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    UREC_Device = 0,
 | 
					    UREC_Device = 0,
 | 
				
			||||||
    UREC_SpecificInterface = 1,
 | 
					    UREC_SpecificInterface = 1,
 | 
				
			||||||
@ -170,8 +187,9 @@ typedef enum {
 | 
				
			|||||||
    UREC_OtherElement = 3
 | 
					    UREC_OtherElement = 3
 | 
				
			||||||
} USB_Recipient;
 | 
					} USB_Recipient;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// USB Request types
 | 
					/**
 | 
				
			||||||
 | 
					 * USB Request types
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    UREQ_GetStatus = 0x00,
 | 
					    UREQ_GetStatus = 0x00,
 | 
				
			||||||
    UREQ_ClearFeature = 0x01,
 | 
					    UREQ_ClearFeature = 0x01,
 | 
				
			||||||
@ -188,23 +206,24 @@ typedef enum {
 | 
				
			|||||||
    UREQ_SetIsochronousDelay = 0x31
 | 
					    UREQ_SetIsochronousDelay = 0x31
 | 
				
			||||||
} USB_RequestCode;
 | 
					} USB_RequestCode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// setup request structure
 | 
					/**
 | 
				
			||||||
 | 
					 * Setup request structure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    union {
 | 
					    union {
 | 
				
			||||||
        uint8_t bmRequestType;
 | 
					        uint8_t bmRequestType; ///< Request type
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        struct {
 | 
					        struct {
 | 
				
			||||||
            uint8_t recipient : 5;
 | 
					            uint8_t recipient : 5; ///< Recipient
 | 
				
			||||||
            uint8_t type : 2;
 | 
					            uint8_t type : 2; ///< Type
 | 
				
			||||||
            uint8_t dir : 1;
 | 
					            uint8_t dir : 1; ///< Direction
 | 
				
			||||||
        } fields;
 | 
					        } fields;
 | 
				
			||||||
    } bmRequestType;  // request type
 | 
					    } bmRequestType;  ///< Request type
 | 
				
			||||||
    uint8_t bRequest; // request
 | 
					    uint8_t bRequest; ///< Request
 | 
				
			||||||
    uint16_t wValue;  // ...
 | 
					    uint16_t wValue;  ///< Value
 | 
				
			||||||
    uint16_t wIndex;  // ...
 | 
					    uint16_t wIndex;  ///< Index
 | 
				
			||||||
    uint16_t wLength; // number of bytes in the data stage
 | 
					    uint16_t wLength; ///< Number of bytes in the data stage
 | 
				
			||||||
} USB_SetupRequest;
 | 
					} USB_SetupRequest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* CORE_USB_USB_DEVICE_TYPES */
 | 
					#endif /* CORE_USB_USB_DEVICE_TYPES */
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1113
									
								
								usb_driver.c
									
									
									
									
									
								
							
							
						
						
									
										1113
									
								
								usb_driver.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										170
									
								
								usb_driver.h
									
									
									
									
									
								
							
							
						
						
									
										170
									
								
								usb_driver.h
									
									
									
									
									
								
							@ -1,170 +0,0 @@
 | 
				
			|||||||
#ifndef CORE_USB_USB_DRIVER
 | 
					 | 
				
			||||||
#define CORE_USB_USB_DRIVER
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// #include "utils/gen_queue.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "usb_common_types.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// #define USBDBGMSG
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define USB_NUM_OF_ENDPOINTS (4) // FIXME: this is module-dependend
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// non isochronous transfers
 | 
					 | 
				
			||||||
#define USB_MAX_FS_PCKT_SIZE_NON_ISOCHRONOUS (64)
 | 
					 | 
				
			||||||
#define USB_MAX_HS_PCKT_SIZE_NON_ISOCHRONOUS (512)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// isochronous transfers
 | 
					 | 
				
			||||||
#define USB_MAX_FS_PCKT_SIZE_ISOCHRONOUS (1023)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define USB_MIN_EP_FIFO_SIZE (64)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Unfortunately this cannot be enabled, since the USB controller
 | 
					 | 
				
			||||||
// generates such enormous amounts of interrupts, so that no other
 | 
					 | 
				
			||||||
// task can run along the USB processing.
 | 
					 | 
				
			||||||
#define USB_EVENT_PROCESSING_IN_OS_THREAD (0)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if USB_EVENT_PROCESSING_IN_OS_THREAD
 | 
					 | 
				
			||||||
#include <cmsis_os2.h>
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// endpoint configuration structure
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
    uint16_t max_packet_size; // maximum packet size
 | 
					 | 
				
			||||||
    bool8_t responding_NAK;   // indicates if endpoint responds with NAK
 | 
					 | 
				
			||||||
    uint8_t type;             // endpoint type
 | 
					 | 
				
			||||||
    uint8_t service_interval; // service interval
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // calculated values
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    uint8_t is_configured; // the endpoint is in use
 | 
					 | 
				
			||||||
    uint16_t fifo_address; // address in the FIFO
 | 
					 | 
				
			||||||
    uint16_t fifo_size;    // FIFO size
 | 
					 | 
				
			||||||
    bool8_t zlp_next;      // indicates, that ZLP should be transmitted at the end of the current transfer (for IN endpoints)
 | 
					 | 
				
			||||||
    bool8_t autoarm;       // automatically arm endpoint (for OUT endpoints)
 | 
					 | 
				
			||||||
} USBDRV_EpConfig;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef enum {
 | 
					 | 
				
			||||||
    USB_FSM_INITIAL_WAIT_SPEEDNEG = 0, // initial state, right after reset, wait for speed negotiation, must be ZERO!
 | 
					 | 
				
			||||||
    USB_FSM_SETUP_OPERATE,             // ready to perform setup operations
 | 
					 | 
				
			||||||
} USBDRV_FsmState;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef enum {
 | 
					 | 
				
			||||||
    USB_EVT_USB_RESET,      // bus reset received
 | 
					 | 
				
			||||||
    USB_EVT_SPEEDNEG_DONE,  // linespeed negotiation (ST calls "enumeration") done
 | 
					 | 
				
			||||||
    USB_EVT_RECEPTION_DONE, // received packet is waiting to be fetched from the Rx FIFO
 | 
					 | 
				
			||||||
    USB_EVT_OUT_DONE,       // something has happened on an OUT endpoint
 | 
					 | 
				
			||||||
    USB_EVT_IN_DONE,        // previously armed IN endpoint has finished packet transmission
 | 
					 | 
				
			||||||
} USBDRV_EventCode;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// endpoint event
 | 
					 | 
				
			||||||
typedef enum {
 | 
					 | 
				
			||||||
    USB_EPEVT_IDLE = 0x00, // endpoint is IDLE
 | 
					 | 
				
			||||||
    USB_EPEVT_ARMED,       // endpoint is armed for transmission
 | 
					 | 
				
			||||||
    USB_EPEVT_STALLED,     // endpoint is stalled
 | 
					 | 
				
			||||||
    USB_EPEVT_NAK          // endpoint responds NAK regardless of FIFO level
 | 
					 | 
				
			||||||
} USBDRV_EndpointEvent;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// USB device state
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
    USBDRV_EpConfig ep_OUT[USB_NUM_OF_ENDPOINTS]; // OUT endpoint configs
 | 
					 | 
				
			||||||
    USBDRV_EpConfig ep_IN[USB_NUM_OF_ENDPOINTS];  // IN endpoint configs
 | 
					 | 
				
			||||||
    uint16_t rx_fifo_size;                        // Rx FIFO size in bytes
 | 
					 | 
				
			||||||
    uint16_t state;                               // FSM state
 | 
					 | 
				
			||||||
    uint8_t *rx_buf;                              // pointer to the receive buffer (this way declaration can be separated)
 | 
					 | 
				
			||||||
    uint16_t rx_buf_level;                        // fill level of the rx buffer
 | 
					 | 
				
			||||||
    uint8_t address;                              // device address
 | 
					 | 
				
			||||||
#if USB_EVENT_PROCESSING_IN_OS_THREAD
 | 
					 | 
				
			||||||
    osMessageQueueId_t event_queue; // event queue
 | 
					 | 
				
			||||||
    osThreadId_t th;                // event processing thread
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
} USBDRV_GlobalState;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// USB received packet status
 | 
					 | 
				
			||||||
typedef enum { USB_PCKT_STATUS_GLOBAL_OUT_NAK = 0b0001,
 | 
					 | 
				
			||||||
               USB_PCKT_STATUS_OUT_DATA_RECV = 0b0010,
 | 
					 | 
				
			||||||
               USB_PCKT_STATUS_OUT_TRANSFER_CPLT = 0b0011,
 | 
					 | 
				
			||||||
               USB_PCKT_STATUS_SETUP_CPLT = 0b0100,
 | 
					 | 
				
			||||||
               USB_PCKT_STATUS_SETUP_DATA_RECV = 0b0110,
 | 
					 | 
				
			||||||
} USBDRV_PcktStatus;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define USB_FLUSH_TX_FIFO_ALL (0b10000)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// event data
 | 
					 | 
				
			||||||
typedef union {
 | 
					 | 
				
			||||||
    struct {
 | 
					 | 
				
			||||||
        uint8_t pckt_status; // read packet status
 | 
					 | 
				
			||||||
        uint8_t data_pid;    // data PID
 | 
					 | 
				
			||||||
        uint8_t byte_count;  // byte count
 | 
					 | 
				
			||||||
        uint8_t ep_num;      // read endpoint number
 | 
					 | 
				
			||||||
    } rx;                    // receive event data
 | 
					 | 
				
			||||||
} USBDRV_EventData;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// event compound for queueing
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
    uint32_t code;         // event code
 | 
					 | 
				
			||||||
    USBDRV_EventData data; // accompaining event data
 | 
					 | 
				
			||||||
} USBDRV_EventCompound;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// callback codes
 | 
					 | 
				
			||||||
typedef enum {
 | 
					 | 
				
			||||||
    USB_CBC_OUT,          // OUT done!
 | 
					 | 
				
			||||||
    USB_CBC_IN_DONE,      // IN done!
 | 
					 | 
				
			||||||
    USB_CBC_IN_FIFOEMPTY, // could not serve IN request, since Tx FIFO was empty
 | 
					 | 
				
			||||||
} USBDRV_CallbackCode;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// callback compound
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
    uint8_t ep : 4;      // endpoint number
 | 
					 | 
				
			||||||
    uint8_t dir : 1;     // direction
 | 
					 | 
				
			||||||
    uint8_t code : 3;    // event code
 | 
					 | 
				
			||||||
    uint16_t size;       // data size
 | 
					 | 
				
			||||||
    const uint8_t *data; // data
 | 
					 | 
				
			||||||
} USBDRV_CallbackCompound;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef enum { UST_SETUP,
 | 
					 | 
				
			||||||
               UST_DATA } USBDRV_ControlTfStage;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ------------
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void usbdrv_gpio_init();                // USB pin low level, early peripheral initialization
 | 
					 | 
				
			||||||
void usbdrv_init_global_state();        // initialize global state
 | 
					 | 
				
			||||||
void usbdrv_periph_init();              // initialize USB peripheral
 | 
					 | 
				
			||||||
void usbdrv_initial_ep0_setup();        // create an initial setup for EP0 in both directions
 | 
					 | 
				
			||||||
void usbdrv_power_and_connect(bool en); // connect to or disconnect from the bus
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void usbdrv_init();  // initialize USB subsystem
 | 
					 | 
				
			||||||
void usbdrv_reset(); // reset USB subsystem
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void usbdrv_preload_endpoint_config(uint8_t ep, uint8_t dir, const USBDRV_EpConfig *cfg); // preload usb endpoint config
 | 
					 | 
				
			||||||
void usbdrv_clear_endpoint_config();                                                      // clear endpoint config
 | 
					 | 
				
			||||||
void usbdrv_apply_endpoint_config();                                                      // apply preloaded endpoint configuration
 | 
					 | 
				
			||||||
void usbdrv_build_fifo();                                                                 // build FIFO (compute addresses)
 | 
					 | 
				
			||||||
const char *usbdrv_get_fifo_addr_table();                                                 // get FIFO address table
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void usbdrv_fetch_endpoint_configuration(uint8_t config_index);                      // fetch endpoint configuration from descriptor dump
 | 
					 | 
				
			||||||
void usbdrv_configure_endpoint(uint8_t ep, uint8_t dir, const USBDRV_EpConfig *cfg); // configure USB endpoint
 | 
					 | 
				
			||||||
void usbdrv_deconfigure_endpoint(uint8_t ep, uint8_t dir);                           // deconfigure USB endpoint
 | 
					 | 
				
			||||||
void usbdrv_stall_endpoint(uint8_t ep, uint8_t dir, bool stall);                     // stall endpoint
 | 
					 | 
				
			||||||
void usbdrv_set_global_NAK(uint8_t dir, bool en);                                    // set global NAK
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void usbdrv_flush_tx_fifo(uint8_t n);        // flush specific or all Tx FIFOs
 | 
					 | 
				
			||||||
void usbdrv_flush_rx_fifo();                 // flush the Rx FIFO
 | 
					 | 
				
			||||||
void usbdrv_set_rx_fifo_size(uint16_t size); // set Rx FIFO size
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void usbdrv_fetch_received_data(uint8_t ep, uint16_t len);   // fetch received data from RX FIFO to receive buffer
 | 
					 | 
				
			||||||
void usbdrv_process_rx_fifo_top(USBDRV_EventData *evt_data); // see what's on top of Rx FIFO
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
uint32_t usbdrv_arm_IN_endpoint(uint8_t ep, const uint8_t *data, uint16_t len); // write data to specific endpoint FIFO
 | 
					 | 
				
			||||||
#define USBDRV_ARM_IN_ZLP(ep) usbdrv_arm_IN_endpoint((ep), NULL, 0)
 | 
					 | 
				
			||||||
uint32_t usbdrv_arm_OUT_endpoint(uint8_t ep, uint8_t size);              // arm OUT endpoint, returned with the actual armed size (capped by the max packet size on that endpoint)
 | 
					 | 
				
			||||||
void usbdrv_autoarm_OUT_endpoint(uint8_t ep);                            // automatically re-arm OUT endpoint at the and of the current OUT transfer
 | 
					 | 
				
			||||||
void usbdrv_enable_endpoint_interrupt(uint8_t ep, uint8_t dir, bool en); // enable/disable endpoint interrupt signaling
 | 
					 | 
				
			||||||
bool usbdrv_get_endpoint_interrupt_flag(uint8_t ep, uint8_t dir);        // get endpoint interrupt flag
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void usbdrv_set_address(uint8_t addr); // set device address
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void usbdrv_process_event(uint8_t evt_code, USBDRV_EventData *evt_data); // process USB event
 | 
					 | 
				
			||||||
void usbdrv_push_event(uint32_t evt_code, USBDRV_EventData *evt_data);   // push event onto the event queue
 | 
					 | 
				
			||||||
void usbdrv_periodic_processing();                                       // call this to process incoming events
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif /* CORE_USB_USB_DRIVER */
 | 
					 | 
				
			||||||
@ -9,49 +9,60 @@ typedef enum {
 | 
				
			|||||||
    USB_SPD_LOW = 1,
 | 
					    USB_SPD_LOW = 1,
 | 
				
			||||||
    USB_SPD_FULL = 2,
 | 
					    USB_SPD_FULL = 2,
 | 
				
			||||||
    USB_SPD_HIGH = 3
 | 
					    USB_SPD_HIGH = 3
 | 
				
			||||||
} USBDRV_LineSpeed;
 | 
					} UsbDrv_LineSpeed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef void (*USBDRV_IN_cb)(uint8_t ep);
 | 
					typedef void (*UsbDrv_IN_cb)(uint8_t ep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * USB Driver interface.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    // USB CORE -> USB DRIVER
 | 
					    // USB CORE -> USB DRIVER
 | 
				
			||||||
    void (*init)();                                                    // initialize USB driver
 | 
					    void (*init)();                                                    ///< Initialize USB driver
 | 
				
			||||||
    void (*reset)();                                                   // reset USB driver
 | 
					    void (*reset)();                                                   ///< Reset USB driver
 | 
				
			||||||
    void (*stall)(uint8_t ep, uint8_t dir, bool stall);                // stall the endpoint
 | 
					    void (*stall)(uint8_t ep, uint8_t dir, bool stall);                ///< Stall the endpoint
 | 
				
			||||||
    uint32_t (*arm_IN)(uint8_t ep, const uint8_t *data, uint16_t len); // arm IN endpoint
 | 
					    uint32_t (*arm_IN)(uint8_t ep, const uint8_t *data, uint16_t len); ///< Arm IN endpoint
 | 
				
			||||||
    uint32_t (*arm_OUT)(uint8_t ep, uint16_t len);                     // arm OUT endpoint
 | 
					    uint32_t (*arm_OUT)(uint8_t ep, uint16_t len);                     ///< Arm OUT endpoint
 | 
				
			||||||
    void (*set_address)(uint8_t addr);                                 // set device address
 | 
					    void (*set_address)(uint8_t addr);                                 ///< Set device address
 | 
				
			||||||
    void (*set_config)(uint8_t ci);                                    // make the chosen setting operational
 | 
					    void (*set_config)(uint8_t ci);                                    ///< Make the chosen setting operational
 | 
				
			||||||
    void (*autoarm)(uint8_t ep);                                       // enable OUT autoarm
 | 
					    void (*autoarm)(uint8_t ep);                                       ///< Enable OUT autoarm
 | 
				
			||||||
    void (*en_ep_irq)(uint8_t ep, uint8_t dir, bool en);               // enable endpoint interrupt
 | 
					    void (*en_ep_irq)(uint8_t ep, uint8_t dir, bool en);               ///< Enable endpoint interrupt
 | 
				
			||||||
    void (*reg_IN_cb)(uint8_t ep, USBDRV_IN_cb cb);                    // register a callback for IN transaction complete
 | 
					    void (*reg_IN_cb)(uint8_t ep, UsbDrv_IN_cb cb);                    ///< Register a callback for IN transaction complete
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // USB DRIVER -> USB CORE
 | 
					    // USB DRIVER -> USB CORE
 | 
				
			||||||
    void (*rst_notify)();             // notify USB core of a bus issued reset
 | 
					    void (*rst_notify)();             ///< Notify USB core of a bus issued reset
 | 
				
			||||||
    void (*enum_notify)(uint8_t spd); // notify the USB core that speed negotiation has concluded
 | 
					    void (*enum_notify)(uint8_t spd); ///< Notify the USB core that speed negotiation has concluded
 | 
				
			||||||
} USB_DrvIntf;
 | 
					} UsbDrv_DrvIntf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef USBDBGMSG
 | 
					#ifndef USBDBGMSG
 | 
				
			||||||
#define USBMSG(...)
 | 
					#define USBMSG(...)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// callback codes
 | 
					/**
 | 
				
			||||||
 | 
					 * Callback codes.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
    USB_CBC_OUT,          // OUT done!
 | 
					    USB_CBC_OUT,          ///< OUT done!
 | 
				
			||||||
    USB_CBC_IN_DONE,      // IN done!
 | 
					    USB_CBC_IN_DONE,      ///< IN done!
 | 
				
			||||||
    USB_CBC_IN_FIFOEMPTY, // could not serve IN request, since Tx FIFO was empty
 | 
					    USB_CBC_IN_FIFOEMPTY, ///< Could not serve IN request, since Tx FIFO was empty
 | 
				
			||||||
} USBDRV_CallbackCode;
 | 
					} UsbDrv_CallbackCode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// callback compound
 | 
					/**
 | 
				
			||||||
 | 
					 * Callback compound.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    uint8_t ep : 4;      // endpoint number
 | 
					    uint8_t ep : 4;      ///< Endpoint number
 | 
				
			||||||
    uint8_t dir : 1;     // direction
 | 
					    uint8_t dir : 1;     ///< Direction
 | 
				
			||||||
    uint8_t code : 3;    // event code
 | 
					    uint8_t code : 3;    ///< Event code
 | 
				
			||||||
    uint16_t size;       // data size
 | 
					    uint16_t size;       ///< Data size
 | 
				
			||||||
    const uint8_t *data; // data
 | 
					    const uint8_t *data; ///< Data
 | 
				
			||||||
} USBDRV_CallbackCompound;
 | 
					} UsbDrv_CallbackCompound;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum { UST_SETUP,
 | 
					/**
 | 
				
			||||||
               UST_DATA } USBDRV_ControlTfStage;
 | 
					 * Control transfer stages.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef enum { UST_SETUP, ///< Setup stage
 | 
				
			||||||
 | 
					               UST_DATA   ///< Data stage
 | 
				
			||||||
 | 
					} UsbDrv_ControlTfStage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* FLATUSB_USB_DRIVER_INTERFACE */
 | 
					#endif /* FLATUSB_USB_DRIVER_INTERFACE */
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user