├── usb ├── Xpd │ ├── xpd_rcc_pc.h │ ├── xpd_syscfg.h │ ├── xpd_utils.h │ ├── xpd_rcc.h │ ├── xpd_usb_wrapper.h │ ├── usbd_pd_if.h │ ├── usbd_pd_def.h │ ├── xpd_common.h │ └── xpd_usb.h ├── .gitignore ├── Include │ ├── usb_types.h │ ├── usbd_cdc.h │ ├── usbd_utils.h │ ├── usbd.h │ ├── private │ │ ├── usbd_msc_private.h │ │ ├── usbd_private.h │ │ └── usbd_internal.h │ ├── usbd_ncm.h │ └── usbd_hid.h ├── Device │ ├── usbd_utils.c │ ├── usbd_if.c │ ├── usbd_ep.c │ └── usbd_ctrl.c ├── Templates │ ├── usbd_config.h │ └── console_if.c └── README.md ├── .gitignore ├── lib ├── cortexM │ ├── PSR.h │ ├── switch.h │ ├── armcpu.c │ ├── armcpu.h │ ├── switch.c │ ├── core_cmFunc.h │ └── core_cmInstr.h ├── stdlib.h ├── stdio.h ├── stdlib.c └── stdio.c ├── hal ├── stm32f1xx.h ├── stm32f103xb.h ├── system_stm32f1xx.h ├── stm32f1xx_hal_pcd_ex.h ├── stm32f1xx_hal_gpio_ex.c └── stm32f1xx_hal_msp.c ├── brd ├── hal_gpio.h ├── hal_timer.h ├── timer.c ├── hal_uart.h ├── hal_interrupt.h ├── memory_map.h ├── interrupt.c ├── gpio.c ├── stm32f1xx_it.h ├── main.c ├── uart.c └── stm32f1xx_it.c ├── app ├── hid_rawkvm.h ├── usb_device.h ├── common_kvm.h ├── hid_pikvm.h ├── hid_rawkvm.c ├── cli_task.c ├── common_kvm.c └── usbd_config.h ├── include ├── memio.h ├── stdarg.h └── stdbool.h ├── kernel ├── synch.h ├── event.c ├── task.h ├── msg.h ├── kernel.h ├── synch.c ├── msg.c ├── event.h ├── task.c └── kernel.c ├── README.md ├── Makefile ├── script └── hid_test.py ├── ram.ld └── flash.ld /usb/Xpd/xpd_rcc_pc.h: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /usb/Xpd/xpd_syscfg.h: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /usb/.gitignore: -------------------------------------------------------------------------------- 1 | /docs/html/ 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | misc 2 | out 3 | Build.cmd 4 | -------------------------------------------------------------------------------- /lib/cortexM/PSR.h: -------------------------------------------------------------------------------- 1 | #define PSR_INIT 0x21000000 2 | -------------------------------------------------------------------------------- /hal/stm32f1xx.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microxblue/pikvm_hid/HEAD/hal/stm32f1xx.h -------------------------------------------------------------------------------- /hal/stm32f103xb.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microxblue/pikvm_hid/HEAD/hal/stm32f103xb.h -------------------------------------------------------------------------------- /usb/Include/usb_types.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microxblue/pikvm_hid/HEAD/usb/Include/usb_types.h -------------------------------------------------------------------------------- /usb/Include/usbd_cdc.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microxblue/pikvm_hid/HEAD/usb/Include/usbd_cdc.h -------------------------------------------------------------------------------- /brd/hal_gpio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * HalGpio.h 3 | * 4 | * Created on: Jan 31, 2019 5 | * Author: maanu 6 | */ 7 | 8 | #ifndef HAL_HALGPIO_H_ 9 | #define HAL_HALGPIO_H_ 10 | 11 | void Hal_gpio_init(void); 12 | 13 | #endif /* HAL_HALGPIO_H_ */ 14 | -------------------------------------------------------------------------------- /app/hid_rawkvm.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | SPDX-License-Identifier: BSD-2-Clause-Patent 4 | 5 | **/ 6 | 7 | #ifndef _HID_RAW_KVM_H_ 8 | #define _HID_RAW_KVM_H_ 9 | 10 | #include "common_kvm.h" 11 | 12 | void handle_rawkvm_command (uint8_t *cmd_buf, uint8_t cmd_len); 13 | 14 | #endif 15 | 16 | -------------------------------------------------------------------------------- /include/memio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * memio.h 3 | * 4 | * Created on: Sep 21, 2018 5 | * Author: maanu 6 | */ 7 | 8 | #ifndef INCLUDE_MEMIO_H_ 9 | #define INCLUDE_MEMIO_H_ 10 | 11 | #define SET_BIT(p,n) ((p) |= (1 << (n))) 12 | #define CLR_BIT(p,n) ((p) &= ~(1 << (n))) 13 | 14 | #endif /* INCLUDE_MEMIO_H_ */ 15 | -------------------------------------------------------------------------------- /brd/hal_timer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * HalTimer.h 3 | * 4 | * Created on: Sep 27, 2018 5 | * Author: yiman 6 | */ 7 | 8 | #ifndef HAL_HALTIMER_H_ 9 | #define HAL_HALTIMER_H_ 10 | 11 | void Hal_timer_init(void); 12 | uint32_t Hal_timer_get_1ms_counter(void); 13 | 14 | 15 | #endif /* HAL_HALTIMER_H_ */ 16 | -------------------------------------------------------------------------------- /lib/cortexM/switch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * switch.h 3 | * 4 | * Created on: Jan 29, 2019 5 | * Author: maanu 6 | */ 7 | 8 | #ifndef LIB_CORTEXM_SWITCH_H_ 9 | #define LIB_CORTEXM_SWITCH_H_ 10 | 11 | void Arch_start(void); 12 | void Arch_context_switching(void); 13 | void Arch_Restore_context(void); 14 | 15 | #endif /* LIB_CORTEXM_SWITCH_H_ */ 16 | -------------------------------------------------------------------------------- /lib/cortexM/armcpu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * armcpu.c 3 | * 4 | * Created on: Sep 22, 2018 5 | * Author: maanu 6 | */ 7 | 8 | #include "armcpu.h" 9 | 10 | void enable_irq(void) 11 | { 12 | __asm__ ("cpsie i"); 13 | } 14 | 15 | void enable_fiq(void) 16 | { 17 | 18 | } 19 | 20 | void disable_irq(void) 21 | { 22 | __asm__ ("cpsid i"); 23 | } 24 | 25 | void disable_fiq(void) 26 | { 27 | 28 | } 29 | 30 | -------------------------------------------------------------------------------- /include/stdarg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * stdarg.h 3 | * 4 | * Created on: Sep 19, 2018 5 | * Author: maanu 6 | */ 7 | 8 | #ifndef INCLUDE_STDARG_H_ 9 | #define INCLUDE_STDARG_H_ 10 | 11 | typedef __builtin_va_list va_list; 12 | 13 | #define va_start(v,l) __builtin_va_start(v,l) 14 | #define va_end(v) __builtin_va_end(v) 15 | #define va_arg(v,l) __builtin_va_arg(v,l) 16 | 17 | #endif /* INCLUDE_STDARG_H_ */ 18 | -------------------------------------------------------------------------------- /brd/timer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Timer.c 3 | * 4 | * Created on: Sep 27, 2018 5 | * Author: yiman 6 | */ 7 | 8 | #include "stdint.h" 9 | #include "stdio.h" 10 | 11 | #include "hal_timer.h" 12 | 13 | 14 | static uint32_t sInternal_1ms_counter; 15 | 16 | void Hal_timer_init (void) 17 | { 18 | } 19 | 20 | uint32_t Hal_timer_get_1ms_counter (void) 21 | { 22 | return sInternal_1ms_counter; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /brd/hal_uart.h: -------------------------------------------------------------------------------- 1 | /* 2 | * HalUart.h 3 | * 4 | * Created on: Sep 8, 2018 5 | * Author: maanu 6 | */ 7 | 8 | #ifndef HAL_HALUART_H_ 9 | #define HAL_HALUART_H_ 10 | 11 | #define UART_RX_BUF_LEN 32 12 | 13 | void Hal_uart_init(void); 14 | void Hal_uart_put_char(uint8_t ch); 15 | uint8_t Hal_uart_get_char(void); 16 | 17 | uint8_t Hal_uart_fast_rx (uint8_t idx); 18 | void Hal_uart_fast_tx (uint8_t idx, uint8_t ch); 19 | 20 | #endif /* HAL_HALUART_H_ */ 21 | -------------------------------------------------------------------------------- /lib/cortexM/armcpu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * armcpu.h 3 | * 4 | * Created on: Sep 22, 2018 5 | * Author: maanu 6 | */ 7 | 8 | #ifndef LIB_ARMCPU_H_ 9 | #define LIB_ARMCPU_H_ 10 | 11 | #include "stdint.h" 12 | 13 | #define __CLZ __builtin_clz 14 | 15 | void enable_irq(void); 16 | void enable_fiq(void); 17 | void disable_irq(void); 18 | void disable_fiq(void); 19 | 20 | __inline void set_CONTROL(uint32_t control) 21 | { 22 | __asm__ ("MSR control, %0" : : "r" (control) : "memory"); 23 | } 24 | 25 | #endif /* LIB_ARMCPU_H_ */ 26 | -------------------------------------------------------------------------------- /kernel/synch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * synch.h 3 | * 4 | * Created on: Nov 8, 2018 5 | * Author: maanu 6 | */ 7 | 8 | #ifndef KERNEL_SYNCH_H_ 9 | #define KERNEL_SYNCH_H_ 10 | 11 | typedef struct KernelMutext_t 12 | { 13 | uint32_t owner; 14 | bool lock; 15 | } KernelMutext_t; 16 | 17 | void Kernel_sem_init(int32_t max); 18 | bool Kernel_sem_test(void); 19 | void Kernel_sem_release(void); 20 | 21 | void Kernel_mutex_init(void); 22 | bool Kernel_mutex_lock(uint32_t owner); 23 | bool Kernel_mutex_unlock(uint32_t owner); 24 | 25 | #endif /* KERNEL_SYNCH_H_ */ 26 | -------------------------------------------------------------------------------- /brd/hal_interrupt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * HalInterrupt.h 3 | * 4 | * Created on: Sep 21, 2018 5 | * Author: maanu 6 | */ 7 | 8 | #ifndef HAL_HALINTERRUPT_H_ 9 | #define HAL_HALINTERRUPT_H_ 10 | 11 | #define INTERRUPT_HANDLER_NUM 255 12 | 13 | typedef void (*InterHdlr_fptr)(void); 14 | 15 | void Hal_interrupt_init(void); 16 | void Hal_interrupt_enable(uint32_t interrupt_num); 17 | void Hal_interrupt_disable(uint32_t interrupt_num); 18 | void Hal_interrupt_register_handler(InterHdlr_fptr handler, uint32_t interrupt_num); 19 | void Hal_interrupt_run_handler(void); 20 | 21 | #endif /* HAL_HALINTERRUPT_H_ */ 22 | -------------------------------------------------------------------------------- /lib/stdlib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * stdlib.h 3 | * 4 | * Created on: Sep 27, 2018 5 | * Author: yiman 6 | */ 7 | 8 | #ifndef LIB_STDLIB_H_ 9 | #define LIB_STDLIB_H_ 10 | 11 | #include "stdint.h" 12 | #include "stdbool.h" 13 | 14 | void delay(uint32_t ms); 15 | void memclr(void* dst, uint32_t count); 16 | uint32_t memfind(uint8_t* src, uint8_t byte, uint32_t count); 17 | bool memncmp(uint8_t* m1, uint8_t* m2, uint32_t count); 18 | void memncpy(uint8_t* dst, uint8_t* src, uint32_t count); 19 | uint32_t htou(char* ascii, uint32_t count); 20 | 21 | void halt(char* filename, uint32_t line); 22 | 23 | #define HALT() halt(__FILE__, __LINE__); 24 | 25 | #endif /* LIB_STDLIB_H_ */ 26 | -------------------------------------------------------------------------------- /kernel/event.c: -------------------------------------------------------------------------------- 1 | /* 2 | * event.c 3 | * 4 | * Created on: Nov 2, 2018 5 | * Author: maanu 6 | */ 7 | 8 | #include "stdint.h" 9 | #include "stdbool.h" 10 | 11 | #include "event.h" 12 | 13 | static uint32_t sEventFlag; 14 | 15 | void Kernel_event_flag_init(void) 16 | { 17 | sEventFlag = 0; 18 | } 19 | 20 | void Kernel_event_flag_set(KernelEventFlag_t event) 21 | { 22 | sEventFlag |= (uint32_t)event; 23 | } 24 | 25 | void Kernel_event_flag_clear(KernelEventFlag_t event) 26 | { 27 | sEventFlag &= ~((uint32_t)event); 28 | } 29 | 30 | bool Kernel_event_flag_check(KernelEventFlag_t event) 31 | { 32 | if (sEventFlag & (uint32_t)event) 33 | { 34 | Kernel_event_flag_clear(event); 35 | return true; 36 | } 37 | return false; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /app/usb_device.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | SPDX-License-Identifier: BSD-2-Clause-Patent 4 | 5 | **/ 6 | 7 | #ifndef _USB_DEVICE_H_ 8 | #define _USB_DEVICE_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "usbd.h" 15 | 16 | #define ABSOLUTE_MOUSE_MODE 1 17 | 18 | #define HID_KB_MS_COMB 0 19 | 20 | #define HID_KB_REPORT_RAW_BYTE 8 21 | 22 | #if HID_KB_MS_COMB 23 | #define HID_KB_REPORT_BYTE (HID_KB_REPORT_RAW_BYTE + 1) 24 | #define HID_COMB_REPORT_BYTE HID_KB_REPORT_BYTE 25 | #else 26 | #define HID_KB_REPORT_BYTE HID_KB_REPORT_RAW_BYTE 27 | #endif 28 | 29 | #if ABSOLUTE_MOUSE_MODE 30 | #define HID_MS_REPORT_BYTE (HID_KB_REPORT_BYTE - 2) 31 | #else 32 | #define HID_MS_REPORT_BYTE (HID_KB_REPORT_BYTE - 4) 33 | #endif 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /kernel/task.h: -------------------------------------------------------------------------------- 1 | /* 2 | * task.h 3 | * 4 | * Created on: Oct 22, 2018 5 | * Author: maanu 6 | */ 7 | 8 | #ifndef KERNEL_TASK_H_ 9 | #define KERNEL_TASK_H_ 10 | 11 | #define NOT_ENOUGH_TASK_NUM 0xFFFFFFFF 12 | 13 | typedef struct KernelTaskContext_t 14 | { 15 | uint32_t spsr; 16 | uint32_t r0_r12[13]; 17 | uint32_t pc; 18 | } KernelTaskContext_t; 19 | 20 | typedef struct KernelTcb_t 21 | { 22 | uint32_t sp; 23 | uint8_t* stack_base; 24 | } KernelTcb_t; 25 | 26 | typedef void (*KernelTaskFunc_t)(void); 27 | 28 | void Kernel_task_init(void); 29 | void Kernel_task_start(void); 30 | uint32_t Kernel_task_create(KernelTaskFunc_t startFunc); 31 | void Kernel_task_scheduler(void); 32 | uint32_t Kernel_task_get_current_task_id(void); 33 | 34 | #endif /* KERNEL_TASK_H_ */ 35 | -------------------------------------------------------------------------------- /kernel/msg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * message.h 3 | * 4 | * Created on: Nov 6, 2018 5 | * Author: maanu 6 | */ 7 | 8 | #ifndef KERNEL_MSG_H_ 9 | #define KERNEL_MSG_H_ 10 | 11 | #define MSG_Q_SIZE_BYTE 512 12 | 13 | typedef enum KernelMsgQ_t 14 | { 15 | KernelMsgQ_D2hData, 16 | KernelMsgQ_DebugCmd, 17 | KernelMsgQ_Task2, 18 | 19 | KernelMsgQ_Num 20 | } KernelMsgQ_t; 21 | 22 | typedef struct KernelCirQ_t 23 | { 24 | uint32_t front; 25 | uint32_t rear; 26 | uint8_t Queue[MSG_Q_SIZE_BYTE]; 27 | } KernelCirQ_t; 28 | 29 | void Kernel_msgQ_init(void); 30 | bool Kernel_msgQ_is_empty(KernelMsgQ_t Qname); 31 | bool Kernel_msgQ_is_full(KernelMsgQ_t Qname); 32 | bool Kernel_msgQ_enqueue(KernelMsgQ_t Qname, uint8_t data); 33 | bool Kernel_msgQ_dequeue(KernelMsgQ_t Qname, uint8_t* out_data); 34 | 35 | #endif /* KERNEL_MSG_H_ */ 36 | -------------------------------------------------------------------------------- /lib/stdio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * stdio.h 3 | * 4 | * Created on: Sep 17, 2018 5 | * Author: maanu 6 | */ 7 | 8 | #ifndef LIB_STDIO_H_ 9 | #define LIB_STDIO_H_ 10 | 11 | #include "stdint.h" 12 | #include "stdarg.h" 13 | 14 | typedef enum utoa_t 15 | { 16 | utoa_dec = 10, 17 | utoa_hex = 16, 18 | } utoa_t; 19 | 20 | // PiKVM has around 10ms polling interval, 21 | // Should limit UART debug message level to avoid CMD timeout 22 | #ifndef DEBUG_LEVEL 23 | #define DEBUG_LEVEL 3 24 | #endif 25 | 26 | #define dprintf dbg_printf 27 | 28 | uint32_t puts(const char* s); 29 | uint32_t dbg_printf(uint8_t level, const char* format, ...); 30 | uint32_t snprintf(char* buf, int n, const char* format, ...); 31 | uint32_t utoa(char* buf, uint32_t val, utoa_t base); 32 | int printf(const char *format, ...); 33 | 34 | #endif /* LIB_STDIO_H_ */ 35 | -------------------------------------------------------------------------------- /usb/Xpd/xpd_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef __XPD_UTILS_H_ 2 | #define __XPD_UTILS_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" 6 | { 7 | #endif 8 | 9 | #include 10 | 11 | #if defined(USE_HAL_DRIVER) 12 | __STATIC_INLINE void XPD_vDelay_ms(uint32_t ulMilliseconds) 13 | { 14 | HAL_Delay(ulMilliseconds); 15 | } 16 | 17 | __STATIC_INLINE XPD_ReturnType XPD_eWaitForDiff(volatile uint32_t * pulVarAddress, uint32_t ulBitSelector, 18 | uint32_t ulMatch, uint32_t * pulTimeout) 19 | { 20 | uint32_t tickstart = HAL_GetTick(); 21 | 22 | while ((*pulVarAddress & ulBitSelector) == ulMatch) 23 | { 24 | if ((HAL_GetTick() - tickstart) > *pulTimeout) 25 | { 26 | return XPD_TIMEOUT; 27 | } 28 | } 29 | *pulTimeout -= HAL_GetTick() - tickstart; 30 | return XPD_OK; 31 | } 32 | #endif 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif /* __XPD_UTILS_H_ */ 39 | -------------------------------------------------------------------------------- /kernel/kernel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Kernel.h 3 | * 4 | * Created on: Oct 28, 2018 5 | * Author: maanu 6 | */ 7 | 8 | #ifndef KERNEL_KERNEL_H_ 9 | #define KERNEL_KERNEL_H_ 10 | 11 | #include "stdint.h" 12 | #include "stdbool.h" 13 | #include "task.h" 14 | #include "event.h" 15 | #include "msg.h" 16 | #include "synch.h" 17 | 18 | void Kernel_start(void); 19 | void Kernel_yield(void); 20 | void Kernel_send_events(uint32_t event_list); 21 | KernelEventFlag_t Kernel_wait_events(uint32_t waiting_list); 22 | bool Kernel_send_msg(KernelMsgQ_t Qname, void* data, uint32_t count); 23 | uint32_t Kernel_recv_msg(KernelMsgQ_t Qname, void* out_data, uint32_t count); 24 | void Kernel_flush_msg(KernelMsgQ_t Qname); 25 | void Kernel_lock_sem(void); 26 | void Kernel_unlock_sem(void); 27 | void Kernel_lock_mutex(void); 28 | void Kernel_unlock_mutex(void); 29 | 30 | #endif /* KERNEL_KERNEL_H_ */ 31 | -------------------------------------------------------------------------------- /brd/memory_map.h: -------------------------------------------------------------------------------- 1 | #ifndef _HAL_MEMORYMAP_H_ 2 | #define _HAL_MEMORYMAP_H_ 3 | 4 | /* 5 | * eFlash 6 | * 7 | * 0 ~ 19 page (20KB) : Loader -> 0x08000000 ~ 0x08004FFF 8 | * 20 ~ 62 page (43KB) : Main FW -> 0x08005000 ~ 0x0800FBFF 9 | * 63 page (1KB) : Keymap -> 0x0800FC00 10 | */ 11 | 12 | extern uint32_t __bss_end__; 13 | 14 | #define TASK_STACK_START ((uint32_t)&__bss_end__) 15 | #define USR_TASK_STACK_SIZE (2 * 1024) 16 | #define TASK_STACK_SIZE (USR_TASK_STACK_SIZE * 3) 17 | 18 | #define EFLASH_TOTALNUM 64 19 | #define EFLASH_START 0x08000000 20 | #define EFLASH_PAGESIZE 0x400 21 | #define EFLASH_BADDR(X) (EFLASH_START + EFLASH_PAGESIZE * (X)) 22 | 23 | #define MAIN_FW_PAGENUM 20 24 | #define MAIN_FW_FLASH_SIZE 43 25 | #define MAIN_FW_ENTRY_OFFSET (MAIN_FW_PAGENUM * EFLASH_PAGESIZE) 26 | #define MAIN_FW_BADDR EFLASH_BADDR(MAIN_FW_PAGENUM) 27 | 28 | #define KEYMAP_PAGENUM (EFLASH_TOTALNUM - 1) /* last page of eFlash */ 29 | #define KEYMAP_BADDR EFLASH_BADDR(KEYMAP_PAGENUM) 30 | 31 | #endif /*_HAL_MEMORYMAP_H_ */ 32 | -------------------------------------------------------------------------------- /brd/interrupt.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Interrupt.c 3 | * 4 | * Created on: Sep 21, 2018 5 | * Author: maanu 6 | */ 7 | 8 | #include "stdint.h" 9 | #include "memio.h" 10 | #include "hal_interrupt.h" 11 | #include "armcpu.h" 12 | 13 | static InterHdlr_fptr sHandlers[INTERRUPT_HANDLER_NUM]; 14 | 15 | static uint32_t GetInterruptNum(void); 16 | static void ClearInterruptNum(uint32_t n); 17 | 18 | void Hal_interrupt_init(void) 19 | { 20 | enable_irq(); 21 | } 22 | 23 | void Hal_interrupt_enable(uint32_t interrupt_num) 24 | { 25 | 26 | } 27 | 28 | void Hal_interrupt_disable(uint32_t interrupt_num) 29 | { 30 | 31 | } 32 | 33 | void Hal_interrupt_register_handler(InterHdlr_fptr handler, uint32_t interrupt_num) 34 | { 35 | sHandlers[interrupt_num] = handler; 36 | } 37 | 38 | void Hal_interrupt_run_handler(void) 39 | { 40 | uint32_t interrupt_num = GetInterruptNum(); 41 | 42 | if (sHandlers[interrupt_num] != NULL) 43 | { 44 | sHandlers[interrupt_num](); 45 | } 46 | 47 | ClearInterruptNum(interrupt_num); 48 | } 49 | 50 | static uint32_t GetInterruptNum(void) 51 | { 52 | return 0; 53 | } 54 | 55 | static void ClearInterruptNum(uint32_t n) 56 | { 57 | } 58 | -------------------------------------------------------------------------------- /app/common_kvm.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | SPDX-License-Identifier: BSD-2-Clause-Patent 4 | 5 | **/ 6 | 7 | #ifndef _COMMON_KVM_H_ 8 | #define _COMMON_KVM_H_ 9 | 10 | #include "stdio.h" 11 | #include "stdlib.h" 12 | #include "string.h" 13 | #include "stm32f1xx_hal.h" 14 | #include "hal_uart.h" 15 | #include "usb_device.h" 16 | 17 | #define RegBase (0x40005C00L) 18 | #define FNR ((__IO unsigned *)(RegBase + 0x48)) 19 | #define _GetFNR() ((uint16_t) *FNR) 20 | 21 | #define MAX_CMD_LEN 20 22 | #define MAX_RPT_LEN 9 23 | 24 | #define HID_DEV_KEYBOARD 1 25 | #define HID_DEV_MOUSE 2 26 | #define HID_DEV_ALL 0xFF 27 | 28 | #if HID_KB_MS_COMB 29 | extern USBD_HID_IfHandleType *const hid_comb_if; 30 | #define hid_kb_if hid_comb_if 31 | #define hid_ms_if hid_comb_if 32 | #else 33 | extern USBD_HID_IfHandleType *const hid_kb_if; 34 | extern USBD_HID_IfHandleType *const hid_ms_if; 35 | #endif 36 | 37 | void hex_dump (uint8_t *buf, int len, uint8_t lvl); 38 | uint8_t get_hid_state (uint8_t device); 39 | void set_hid_state (uint8_t device, uint8_t state); 40 | uint8_t send_hid_report (USBD_HID_IfHandleType *itf, void *data, uint16_t length, int8_t retry, uint8_t interval); 41 | void send_uart_raw (uint8_t *buf, int len); 42 | 43 | #endif -------------------------------------------------------------------------------- /usb/Include/usbd_utils.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file usbd_utils.h 4 | * @author Benedek Kupper 5 | * @version 0.1 6 | * @date 2018-01-31 7 | * @brief Universal Serial Bus Device Driver 8 | * 9 | * Copyright (c) 2018 Benedek Kupper 10 | * 11 | * Licensed under the Apache License, Version 2.0 (the "License"); 12 | * you may not use this file except in compliance with the License. 13 | * You may obtain a copy of the License at 14 | * 15 | * http://www.apache.org/licenses/LICENSE-2.0 16 | * 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | */ 23 | #ifndef __USBD_UTILS_H_ 24 | #define __USBD_UTILS_H_ 25 | 26 | #ifdef __cplusplus 27 | extern "C" 28 | { 29 | #endif 30 | 31 | #include 32 | 33 | extern void Uint2Unicode(const uint8_t *data, uint8_t *unicode, uint16_t len); 34 | 35 | #ifdef __cplusplus 36 | } 37 | #endif 38 | 39 | #endif /* __USBD_UTILS_H_ */ 40 | -------------------------------------------------------------------------------- /app/hid_pikvm.h: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | SPDX-License-Identifier: BSD-2-Clause-Patent 4 | 5 | **/ 6 | 7 | #ifndef _HID_PI_KVM_H_ 8 | #define _HID_PI_KVM_H_ 9 | 10 | #include "common_kvm.h" 11 | 12 | #define MAGIC 0x33 13 | #define MAGIC_RESP 0x34 14 | #define RESP_NONE 0x24 15 | #define RESP_CRC_ERROR 0x40 16 | #define RESP_INVALID_ERROR 0x45 17 | #define RESP_TIMEOUT_ERROR 0x48 18 | #define CMD_PING 0x01 19 | #define CMD_REPEAT 0x02 20 | #define CMD_SET_KEYBOARD 0x03 21 | #define CMD_SET_MOUSE 0x04 22 | #define CMD_CLEAR_HID 0x10 23 | #define CMD_KEY 0x11 24 | #define CMD_MOVE 0x12 25 | #define CMD_BUTTON 0x13 26 | #define CMD_WHEEL 0x14 27 | #define CMD_RELATIVE 0x15 28 | #define PONG_OK 0x80 29 | #define PONG_CAPS 0x01 30 | #define PONG_SCROLL 0x02 31 | #define PONG_NUM 0x04 32 | #define PONG_KEYBOARD_OFFLINE 0x08 33 | #define PONG_MOUSE_OFFLINE 0x10 34 | #define PONG_RESET_REQUIRED 0x40 35 | 36 | #define OUTPUTS_KEYBOARD_USB 0x01 37 | #define OUTPUTS_MOUSE_USB_ABS 0x08 38 | #define FEATURES_HAS_USB 0x01 39 | 40 | void handle_pikvm_command (uint8_t *cmd_buf, uint8_t cmd_len); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /kernel/synch.c: -------------------------------------------------------------------------------- 1 | /* 2 | * synch.c 3 | * 4 | * Created on: Nov 8, 2018 5 | * Author: maanu 6 | */ 7 | 8 | #include "stdint.h" 9 | #include "stdbool.h" 10 | 11 | #include "synch.h" 12 | 13 | #define DEF_SEM_MAX 8 14 | 15 | static int32_t sSemMax; 16 | static int32_t sSem; 17 | 18 | KernelMutext_t sMutex; 19 | 20 | void Kernel_sem_init(int32_t max) 21 | { 22 | sSemMax = (max <= 0) ? DEF_SEM_MAX : max; 23 | sSemMax = (max >= DEF_SEM_MAX) ? DEF_SEM_MAX : max; 24 | 25 | sSem = sSemMax; 26 | } 27 | 28 | bool Kernel_sem_test(void) 29 | { 30 | if (sSem <= 0) 31 | { 32 | return false; 33 | } 34 | 35 | sSem--; 36 | 37 | return true; 38 | } 39 | 40 | void Kernel_sem_release(void) 41 | { 42 | sSem++; 43 | 44 | if (sSem >= sSemMax) 45 | { 46 | sSem = sSemMax; 47 | } 48 | } 49 | 50 | void Kernel_mutex_init(void) 51 | { 52 | sMutex.owner = 0; 53 | sMutex.lock = false; 54 | } 55 | 56 | bool Kernel_mutex_lock(uint32_t owner) 57 | { 58 | if (sMutex.lock) 59 | { 60 | return false; 61 | } 62 | 63 | sMutex.owner = owner; 64 | sMutex.lock = true; 65 | return true; 66 | } 67 | 68 | bool Kernel_mutex_unlock(uint32_t owner) 69 | { 70 | if (owner == sMutex.owner) 71 | { 72 | sMutex.lock = false; 73 | return true; 74 | } 75 | return false; 76 | } 77 | 78 | -------------------------------------------------------------------------------- /app/hid_rawkvm.c: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | SPDX-License-Identifier: BSD-2-Clause-Patent 4 | 5 | **/ 6 | 7 | #include "hid_rawkvm.h" 8 | #include "kernel.h" 9 | 10 | void handle_rawkvm_command (uint8_t *cmd_buf, uint8_t cmd_len) 11 | { 12 | uint8_t resp[8]; 13 | uint8_t hid_rpt[MAX_RPT_LEN]; 14 | uint8_t rpt_len; 15 | uint8_t rpt_id; 16 | uint8_t error; 17 | uint8_t sent; 18 | 19 | error = 0; 20 | 21 | if (cmd_len == 0) { 22 | error = 1; 23 | } 24 | 25 | if (cmd_buf[0] == '@') { 26 | // KB 27 | rpt_len = HID_KB_REPORT_BYTE; 28 | rpt_id = 1; 29 | } else if (cmd_buf[0] == '#') { 30 | // MS 31 | rpt_len = HID_MS_REPORT_BYTE; 32 | rpt_id = 2; 33 | } else { 34 | error = 2; 35 | } 36 | 37 | if (error == 0) { 38 | cmd_buf++; 39 | cmd_len--; 40 | if (cmd_len > rpt_len) { 41 | cmd_len = rpt_len; 42 | } 43 | 44 | memset (hid_rpt, 0, sizeof (hid_rpt)); 45 | hid_rpt[0] = rpt_id; 46 | memcpy (hid_rpt + 1, cmd_buf, cmd_len); 47 | 48 | hex_dump (hid_rpt + (1 - HID_KB_MS_COMB), rpt_len, 6); 49 | sent = send_hid_report ( (rpt_id == 1) ? hid_kb_if : hid_ms_if, hid_rpt + (1 - HID_KB_MS_COMB), rpt_len, 3, 10); 50 | if (sent != rpt_len) { 51 | error = 3; 52 | } 53 | } 54 | 55 | if (error == 0) { 56 | memcpy (resp, "$OK\n", 4); 57 | send_uart_raw (resp, 4); 58 | } else { 59 | memcpy (resp, "$ERR0\n", 6); 60 | resp[3] = '0' + error; 61 | send_uart_raw (resp, 6); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /brd/gpio.c: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | SPDX-License-Identifier: BSD-2-Clause-Patent 4 | 5 | **/ 6 | 7 | #include "stm32f1xx_hal.h" 8 | 9 | void usb_disconnect (void) 10 | { 11 | GPIO_InitTypeDef GPIO_InitStruct; 12 | 13 | /* Disconnect USB */ 14 | HAL_GPIO_WritePin (HAL_USB_DISCONNECT, HAL_USB_DISCONNECT_PIN, GPIO_PIN_SET); 15 | 16 | // Workaround for Blue-Pill (No USB disconnect control pin) 17 | GPIO_InitStruct.Pin = GPIO_PIN_12; 18 | GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 19 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; 20 | HAL_GPIO_Init (GPIOA, &GPIO_InitStruct); 21 | HAL_GPIO_WritePin (GPIOA, GPIO_PIN_12, GPIO_PIN_RESET); 22 | 23 | } 24 | 25 | void usb_connect (int ms) 26 | { 27 | GPIO_InitTypeDef GPIO_InitStruct; 28 | 29 | HAL_Delay (ms); 30 | 31 | GPIO_InitStruct.Pin = GPIO_PIN_12; 32 | GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 33 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; 34 | HAL_GPIO_Init (GPIOA, &GPIO_InitStruct); 35 | } 36 | 37 | void Hal_gpio_init (void) 38 | { 39 | GPIO_InitTypeDef GPIO_InitStruct; 40 | 41 | /* GPIO Ports Clock Enable */ 42 | __HAL_RCC_GPIOA_CLK_ENABLE(); 43 | __HAL_RCC_GPIOB_CLK_ENABLE(); 44 | __HAL_RCC_GPIOC_CLK_ENABLE(); 45 | __HAL_RCC_GPIOD_CLK_ENABLE(); 46 | 47 | /* USB connect pin */ 48 | GPIO_InitStruct.Pin = GPIO_PIN_2; 49 | GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 50 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; 51 | HAL_GPIO_Init (GPIOD, &GPIO_InitStruct); 52 | 53 | // Disconnect USB 54 | usb_disconnect (); 55 | } 56 | -------------------------------------------------------------------------------- /include/stdbool.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1998-2014 Free Software Foundation, Inc. 2 | 3 | This file is part of GCC. 4 | 5 | GCC is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; either version 3, or (at your option) 8 | any later version. 9 | 10 | GCC is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | Under Section 7 of GPL version 3, you are granted additional 16 | permissions described in the GCC Runtime Library Exception, version 17 | 3.1, as published by the Free Software Foundation. 18 | 19 | You should have received a copy of the GNU General Public License and 20 | a copy of the GCC Runtime Library Exception along with this program; 21 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 22 | . */ 23 | 24 | /* 25 | * ISO C Standard: 7.16 Boolean type and values 26 | */ 27 | 28 | #ifndef _STDBOOL_H 29 | #define _STDBOOL_H 30 | 31 | #ifndef __cplusplus 32 | 33 | #define bool _Bool 34 | #define true 1 35 | #define false 0 36 | 37 | #else /* __cplusplus */ 38 | 39 | /* Supporting in C++ is a GCC extension. */ 40 | #define _Bool bool 41 | #define bool bool 42 | #define false false 43 | #define true true 44 | 45 | #endif /* __cplusplus */ 46 | 47 | /* Signal that all the definitions are present. */ 48 | #define __bool_true_false_are_defined 1 49 | 50 | #endif /* stdbool.h */ 51 | -------------------------------------------------------------------------------- /lib/cortexM/switch.c: -------------------------------------------------------------------------------- 1 | #include "stdint.h" 2 | #include "stdbool.h" 3 | #include "armcpu.h" 4 | #include "switch.h" 5 | #include "task.h" 6 | 7 | extern KernelTcb_t* gCurrent_tcb; 8 | extern KernelTcb_t* gNext_tcb; 9 | 10 | __attribute__ ((naked)) void Arch_start(void) 11 | { 12 | __asm__ volatile ("MOV r0, #2"); 13 | __asm__ volatile ("MSR control, r0"); 14 | __asm__ volatile ("B Arch_Restore_context"); 15 | } 16 | 17 | __attribute__ ((naked)) void Arch_context_switching(void) 18 | { 19 | __asm__ volatile ("B Arch_Save_context"); 20 | __asm__ volatile ("B Arch_Restore_context"); 21 | } 22 | 23 | __attribute__ ((naked)) void Arch_Save_context(void) 24 | { 25 | // save current task context into the current task stack 26 | __asm__ ("PUSH {lr}"); 27 | __asm__ ("PUSH {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12}"); 28 | __asm__ ("MRS r0, PSR"); 29 | __asm__ ("PUSH {r0}"); 30 | // save current task stack pointer into the current TCB 31 | __asm__ ("LDR r0, =gCurrent_tcb"); 32 | __asm__ ("LDR r0, [r0]"); 33 | __asm__ ("MRS r1, PSP"); 34 | __asm__ ("STMIA r0!,{r1}"); 35 | } 36 | 37 | __attribute__ ((naked)) void Arch_Restore_context(void) 38 | { 39 | // restore next task stack pointer from the next TCB 40 | __asm__ ("LDR r0, =gNext_tcb"); 41 | __asm__ ("LDR r0, [r0]"); 42 | __asm__ ("LDMIA r0!,{r1}"); 43 | __asm__ ("MSR PSP,r1"); 44 | // restore next task context from the next task stack 45 | __asm__ ("POP {r0}"); 46 | __asm__ ("MSR PSR_nzcvq, r0"); 47 | __asm__ ("POP {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12}"); 48 | __asm__ ("POP {pc}"); 49 | } 50 | -------------------------------------------------------------------------------- /app/cli_task.c: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | SPDX-License-Identifier: BSD-2-Clause-Patent 4 | 5 | **/ 6 | 7 | #include "stdio.h" 8 | #include "kernel.h" 9 | #include "hid_pikvm.h" 10 | #include "hid_rawkvm.h" 11 | 12 | static 13 | void handle_command () 14 | { 15 | static uint16_t last_fnr = 0; 16 | uint8_t cmd_buf[MAX_CMD_LEN]; 17 | bool valid; 18 | uint16_t fnr; 19 | uint32_t tick; 20 | uint8_t ch; 21 | uint8_t i; 22 | 23 | valid = false; 24 | for (i = 0 ; i < MAX_CMD_LEN; i++) { 25 | if (Kernel_recv_msg (KernelMsgQ_DebugCmd, &ch, 1) == 0) { 26 | valid = true; 27 | cmd_buf[i] = 0; 28 | break; 29 | } else if (((cmd_buf[0] != MAGIC)) && ((ch == '\r') || (ch == '\n'))) { 30 | valid = true; 31 | cmd_buf[i] = 0; 32 | break; 33 | } else { 34 | cmd_buf[i] = ch; 35 | } 36 | } 37 | 38 | if (valid) { 39 | fnr = _GetFNR(); 40 | if (!(fnr & USB_FNR_LCK)) { 41 | set_hid_state (HID_DEV_ALL, 0); 42 | } else if (!(last_fnr & USB_FNR_LCK)) { 43 | set_hid_state (HID_DEV_ALL, 1); 44 | } 45 | last_fnr = fnr; 46 | 47 | tick = HAL_GetTick(); 48 | dprintf (4, "CMD RX: (%8d)\n", tick); 49 | hex_dump (cmd_buf, i, 4); 50 | 51 | if (cmd_buf[0] == MAGIC) { 52 | handle_pikvm_command (cmd_buf, i); 53 | } else { 54 | handle_rawkvm_command (cmd_buf, i); 55 | } 56 | 57 | fnr = _GetFNR(); 58 | dprintf (4, "DNE --: (%8d)\n\n", HAL_GetTick() - tick); 59 | } 60 | } 61 | 62 | void cli_task (void) 63 | { 64 | KernelEventFlag_t handle_event; 65 | 66 | dprintf (1, "Ready\n"); 67 | while (true) { 68 | handle_event = Kernel_wait_events (KernelEventFlag_CmdIn); 69 | if (handle_event == KernelEventFlag_CmdIn) { 70 | handle_command (); 71 | } 72 | Kernel_yield(); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /usb/Xpd/xpd_rcc.h: -------------------------------------------------------------------------------- 1 | #ifndef __XPD_RCC_H_ 2 | #define __XPD_RCC_H_ 3 | 4 | #include 5 | 6 | #if defined(USE_HAL_DRIVER) 7 | #define RCC_POS_USB_EN __HAL_RCC_USB_CLK_ENABLE 8 | #define RCC_POS_USB_DIS __HAL_RCC_USB_CLK_DISABLE 9 | #define RCC_POS_OTG_FS_EN __HAL_RCC_USB_OTG_FS_CLK_ENABLE 10 | #define RCC_POS_OTG_FS_DIS __HAL_RCC_USB_OTG_FS_CLK_DISABLE 11 | #define RCC_POS_OTG_HS_EN __HAL_RCC_USB_OTG_HS_CLK_ENABLE 12 | #define RCC_POS_OTG_HS_DIS __HAL_RCC_USB_OTG_HS_CLK_DISABLE 13 | #define RCC_POS_USBPHYC_EN __HAL_RCC_OTGPHYC_CLK_ENABLE 14 | #define RCC_POS_USBPHYC_DIS __HAL_RCC_OTGPHYC_CLK_DISABLE 15 | #define RCC_POS_OTG_HS_ULPI_EN __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE 16 | #define RCC_POS_OTG_HS_ULPI_DIS __HAL_RCC_USB_OTG_HS_ULPI_CLK_DISABLE 17 | 18 | #define RCC_vClockEnable(A) A##_EN() 19 | #define RCC_vClockDisable(A) A##_DIS() 20 | #define RCC_CLKFREQ_HZ_HCLK HAL_RCC_GetHCLKFreq 21 | 22 | #elif defined(USE_STDPERIPH_DRIVER) 23 | #if defined(STM32F4XX) 24 | #define RCC_POS_OTG_FS_FN(CMD) RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS, CMD) 25 | #define RCC_POS_OTG_HS_FN(CMD) RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_OTG_HS, CMD) 26 | #define RCC_POS_OTG_HS_ULPI_FN(CMD) RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_OTG_HS_ULPI, CMD) 27 | #endif 28 | 29 | #define RCC_vClockEnable(A) A##_FN(ENABLE) 30 | #define RCC_vClockDisable(A) A##_FN(DISABLE) 31 | 32 | __STATIC_INLINE uint32_t RCC_CLKFREQ_HZ_HCLK(void) 33 | { 34 | RCC_ClocksTypeDef RCC_Clocks; 35 | RCC_GetClocksFreq(&RCC_Clocks); 36 | return RCC_Clocks.HCLK_Frequency; 37 | } 38 | #endif 39 | 40 | #define RCC_CLKFREQ_HZ_HSE HSE_VALUE 41 | #define RCC_ulClockFreq_Hz(A) RCC_CLKFREQ_HZ_##A() 42 | 43 | #endif /* __XPD_RCC_H_ */ 44 | -------------------------------------------------------------------------------- /app/common_kvm.c: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | SPDX-License-Identifier: BSD-2-Clause-Patent 4 | 5 | **/ 6 | 7 | #include "common_kvm.h" 8 | 9 | static uint8_t hid_state = 0xff; 10 | 11 | void hex_dump (uint8_t *buf, int len, uint8_t lvl) 12 | { 13 | int i; 14 | int off; 15 | 16 | off = 0; 17 | for (i = 0; i < len; i++) { 18 | if ((i & 0xf) == 0x00) { 19 | dprintf (lvl, " %04X: ", off); 20 | } 21 | dprintf (lvl, "%02X ", buf[i]); 22 | if ((i & 0xf) == 0x0f) { 23 | dprintf (lvl, "\n"); 24 | off += 16; 25 | } 26 | } 27 | if (i & 0xf) { 28 | dprintf (lvl, "\n"); 29 | } 30 | } 31 | 32 | void set_hid_state (uint8_t device, uint8_t state) 33 | { 34 | if (device == HID_DEV_ALL) { 35 | hid_state = state ? 0xff : 00; 36 | return; 37 | } 38 | 39 | if ((device != HID_DEV_KEYBOARD) && (device != HID_DEV_MOUSE)) { 40 | return; 41 | } 42 | 43 | if (state) { 44 | hid_state |= (1 << device); 45 | } else { 46 | hid_state &= ~(1 << device); 47 | } 48 | } 49 | 50 | uint8_t get_hid_state (uint8_t device) 51 | { 52 | if ((device != HID_DEV_KEYBOARD) && (device != HID_DEV_MOUSE)) { 53 | return 0; 54 | } 55 | return (hid_state & (1 << device)) ? 1 : 0; 56 | } 57 | 58 | uint8_t send_hid_report (USBD_HID_IfHandleType *itf, void *data, uint16_t length, int8_t retry, uint8_t interval) 59 | { 60 | USBD_ReturnType ret; 61 | 62 | do { 63 | ret = USBD_HID_ReportIn (itf, data, length); 64 | if (ret == USBD_E_OK) { 65 | break; 66 | } 67 | HAL_Delay (interval); 68 | } while (retry-- > 0); 69 | 70 | if (ret == USBD_E_OK) { 71 | return length; 72 | } else { 73 | return 0; 74 | } 75 | } 76 | 77 | void send_uart_raw (uint8_t *buf, int len) 78 | { 79 | for (int i = 0; i < len; i++) { 80 | Hal_uart_fast_tx (3, buf[i]); 81 | } 82 | } 83 | 84 | 85 | -------------------------------------------------------------------------------- /usb/Include/usbd.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file usbd.h 4 | * @author Benedek Kupper 5 | * @version 0.1 6 | * @date 2018-01-31 7 | * @brief Universal Serial Bus Device Driver 8 | * Public functions header 9 | * 10 | * Copyright (c) 2018 Benedek Kupper 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the "License"); 13 | * you may not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * http://www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an "AS IS" BASIS, 20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | #ifndef __USBD_H_ 25 | #define __USBD_H_ 26 | 27 | #ifdef __cplusplus 28 | extern "C" 29 | { 30 | #endif 31 | 32 | #include 33 | 34 | /** @ingroup USBD 35 | * @addtogroup USBD_Exported_Functions 36 | * @{ */ 37 | void USBD_Init (USBD_HandleType *dev, 38 | const USBD_DescriptionType *desc); 39 | void USBD_Deinit (USBD_HandleType *dev); 40 | void USBD_UnmountInterfaces (USBD_HandleType *dev); 41 | 42 | void USBD_Connect (USBD_HandleType *dev); 43 | void USBD_Disconnect (USBD_HandleType *dev); 44 | 45 | USBD_ReturnType USBD_SetRemoteWakeup (USBD_HandleType *dev); 46 | USBD_ReturnType USBD_ClearRemoteWakeup (USBD_HandleType *dev); 47 | /** @} */ 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | #endif /* __USBD_H_ */ 54 | -------------------------------------------------------------------------------- /lib/stdlib.c: -------------------------------------------------------------------------------- 1 | /* 2 | * stdlib.c 3 | * 4 | * Created on: Sep 27, 2018 5 | * Author: yiman 6 | */ 7 | 8 | #include "stdint.h" 9 | #include "stdbool.h" 10 | #include "stdio.h" 11 | 12 | #include "hal_timer.h" 13 | 14 | 15 | void delay(uint32_t ms) 16 | { 17 | uint32_t goal = Hal_timer_get_1ms_counter() + ms; 18 | 19 | while(goal != Hal_timer_get_1ms_counter()); 20 | } 21 | 22 | void memclr(void* dst, uint32_t count) 23 | { 24 | uint8_t* d = (uint8_t*)dst; 25 | 26 | while(count--) 27 | { 28 | *d++ = 0; 29 | } 30 | } 31 | 32 | uint32_t memfind(uint8_t* src, uint8_t byte, uint32_t count) 33 | { 34 | for(uint32_t i = 0 ; i < count ; i++) 35 | { 36 | if (*src++ == byte) 37 | { 38 | return i; 39 | } 40 | } 41 | return (count + 1); 42 | } 43 | 44 | bool memncmp(uint8_t* m1, uint8_t* m2, uint32_t count) 45 | { 46 | while(count--) 47 | { 48 | if (*m1++ != *m2++) 49 | { 50 | return false; 51 | } 52 | } 53 | 54 | return true; 55 | } 56 | 57 | void memncpy(uint8_t* dst, uint8_t* src, uint32_t count) 58 | { 59 | while(count--) 60 | { 61 | *dst++ = *src++; 62 | } 63 | } 64 | 65 | uint32_t htou(char* ascii, uint32_t count) 66 | { 67 | uint32_t ret = 0; 68 | while(count--) 69 | { 70 | uint32_t digit = 0; 71 | if ('0' <= *ascii && *ascii <= '9') 72 | { 73 | digit = *ascii - '0'; 74 | } 75 | else if ('a' <= *ascii && *ascii <= 'f') 76 | { 77 | digit = *ascii - 'a' + 10; 78 | } 79 | else if ('A' <= *ascii && *ascii <= 'F') 80 | { 81 | digit = *ascii - 'A' + 10; 82 | } 83 | else 84 | { 85 | return 0; 86 | } 87 | ascii++; 88 | ret += digit * (1 << (count*4)); 89 | } 90 | 91 | return ret; 92 | } 93 | 94 | void halt(char* filename, uint32_t line) 95 | { 96 | dprintf(1, "HALT [%s] at (%u)\n", filename, line); 97 | while(1); 98 | } 99 | -------------------------------------------------------------------------------- /kernel/msg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * msg.c 3 | * 4 | * Created on: Nov 6, 2018 5 | * Author: maanu 6 | */ 7 | 8 | #include "stdint.h" 9 | #include "stdbool.h" 10 | #include "stdlib.h" 11 | 12 | #include "msg.h" 13 | 14 | static KernelCirQ_t sMsgQ[KernelMsgQ_Num]; 15 | 16 | void Kernel_msgQ_init(void) 17 | { 18 | for (uint32_t i = 0 ; i < KernelMsgQ_Num ; i++) 19 | { 20 | sMsgQ[i].front = 0; 21 | sMsgQ[i].rear = 0; 22 | memclr(sMsgQ[i].Queue, MSG_Q_SIZE_BYTE); 23 | } 24 | } 25 | 26 | bool Kernel_msgQ_is_empty(KernelMsgQ_t Qname) 27 | { 28 | if (Qname >= KernelMsgQ_Num) 29 | { 30 | return false; 31 | } 32 | 33 | if (sMsgQ[Qname].front == sMsgQ[Qname].rear) 34 | { 35 | return true; 36 | } 37 | 38 | return false; 39 | } 40 | 41 | bool Kernel_msgQ_is_full(KernelMsgQ_t Qname) 42 | { 43 | if (Qname >= KernelMsgQ_Num) 44 | { 45 | return false; 46 | } 47 | 48 | if (((sMsgQ[Qname].rear + 1) % MSG_Q_SIZE_BYTE) == sMsgQ[Qname].front) 49 | { 50 | return true; 51 | } 52 | 53 | return false; 54 | } 55 | 56 | bool Kernel_msgQ_enqueue(KernelMsgQ_t Qname, uint8_t data) 57 | { 58 | if (Qname >= KernelMsgQ_Num) 59 | { 60 | return false; 61 | } 62 | 63 | if (Kernel_msgQ_is_full(Qname)) 64 | { 65 | return false; 66 | } 67 | sMsgQ[Qname].rear++; 68 | sMsgQ[Qname].rear %= MSG_Q_SIZE_BYTE; 69 | 70 | uint32_t idx = sMsgQ[Qname].rear; 71 | sMsgQ[Qname].Queue[idx] = data; 72 | 73 | return true; 74 | } 75 | 76 | bool Kernel_msgQ_dequeue(KernelMsgQ_t Qname, uint8_t* out_data) 77 | { 78 | if (Qname >= KernelMsgQ_Num) 79 | { 80 | return false; 81 | } 82 | 83 | if (Kernel_msgQ_is_empty(Qname)) 84 | { 85 | return false; 86 | } 87 | 88 | sMsgQ[Qname].front++; 89 | sMsgQ[Qname].front %= MSG_Q_SIZE_BYTE; 90 | 91 | uint32_t idx = sMsgQ[Qname].front; 92 | *out_data = sMsgQ[Qname].Queue[idx]; 93 | 94 | sMsgQ[Qname].Queue[idx] = 0; // clear 95 | 96 | return true; 97 | } 98 | -------------------------------------------------------------------------------- /kernel/event.h: -------------------------------------------------------------------------------- 1 | /* 2 | * event.h 3 | * 4 | * Created on: Nov 2, 2018 5 | * Author: maanu 6 | */ 7 | 8 | #ifndef KERNEL_EVENT_H_ 9 | #define KERNEL_EVENT_H_ 10 | 11 | typedef enum KernelEventFlag_t 12 | { 13 | KernelEventFlag_CmdIn = 0x00000001, 14 | KernelEventFlag_SendD2H = 0x00000002, 15 | KernelEventFlag_Reserved02 = 0x00000004, 16 | KernelEventFlag_Reserved03 = 0x00000008, 17 | KernelEventFlag_Reserved04 = 0x00000010, 18 | KernelEventFlag_Reserved05 = 0x00000020, 19 | KernelEventFlag_Reserved06 = 0x00000040, 20 | KernelEventFlag_Reserved07 = 0x00000080, 21 | KernelEventFlag_Reserved08 = 0x00000100, 22 | KernelEventFlag_Reserved09 = 0x00000200, 23 | KernelEventFlag_Reserved10 = 0x00000400, 24 | KernelEventFlag_Reserved11 = 0x00000800, 25 | KernelEventFlag_Reserved12 = 0x00001000, 26 | KernelEventFlag_Reserved13 = 0x00002000, 27 | KernelEventFlag_Reserved14 = 0x00004000, 28 | KernelEventFlag_Reserved15 = 0x00008000, 29 | KernelEventFlag_Reserved16 = 0x00010000, 30 | KernelEventFlag_Reserved17 = 0x00020000, 31 | KernelEventFlag_Reserved18 = 0x00040000, 32 | KernelEventFlag_Reserved19 = 0x00080000, 33 | KernelEventFlag_Reserved20 = 0x00100000, 34 | KernelEventFlag_Reserved21 = 0x00200000, 35 | KernelEventFlag_Reserved22 = 0x00400000, 36 | KernelEventFlag_Reserved23 = 0x00800000, 37 | KernelEventFlag_Reserved24 = 0x01000000, 38 | KernelEventFlag_Reserved25 = 0x02000000, 39 | KernelEventFlag_Reserved26 = 0x04000000, 40 | KernelEventFlag_Reserved27 = 0x08000000, 41 | KernelEventFlag_Reserved28 = 0x10000000, 42 | KernelEventFlag_Reserved29 = 0x20000000, 43 | KernelEventFlag_Reserved30 = 0x40000000, 44 | KernelEventFlag_Reserved31 = 0x80000000, 45 | 46 | KernelEventFlag_Empty = 0x00000000, 47 | } KernelEventFlag_t; 48 | 49 | void Kernel_event_flag_init(void); 50 | void Kernel_event_flag_set(KernelEventFlag_t event); 51 | void Kernel_event_flag_clear(KernelEventFlag_t event); 52 | bool Kernel_event_flag_check(KernelEventFlag_t event); 53 | 54 | #endif /* KERNEL_EVENT_H_ */ 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### Introduction 2 | [Pi-KVM](http://pikvm.org "Pi-KVM") is a Raspberry Pi based open source KVM implementation. It can support USB keyboard and mouse emulation through USB HID. It currently uses AVR-based HID implementation. However, I only have STM32F103 [BluePill](https://stm32-base.org/boards/STM32F103C8T6-Blue-Pill.html "BluePill") board available. So I decided to do a simlar implementation using cheap BluePill. This repo contains the HID emulation source code for my implementation on STM32F103. It has been tested on Pi-KVM, and it worked well for me. 3 | 4 | ### Build Instrucitons 5 | Comping Pi-KVM HID emulator has been tested with Ubuntu 20.04 distribution. Please make sure you have arm-non-eabi-gcc toolchain installed. 6 | To compile: 7 | ```c 8 | make clean 9 | make 10 | ``` 11 | The final generated image will be located at ./out/pikvm_hid.bin. This image needs to be flashed to STM32F103 flash address 0x8000000. 12 | 13 | ### Program BluePill 14 | - Enable boot mode to boot from ROM 15 | - Set jumper BOOT0 to position 1 (3.3v) 16 | - Connect USB UART adaptor to Blue Pill UART1 17 | - Host TXD to STM32F103 RXD (PA10) 18 | - Host RXD to STM32F103 TXD (PA9) 19 | - Host GND to STM32F103 GND 20 | - Flash binary to BluePill. Run following command: 21 | - sudo python ./script/stmloader.py -p /dev/ttyUSB0 -f F1 -e -w -v ./out/pikvm_hid.bin 22 | - Enable boot mode to normal mode 23 | - Set jumper BOOT0 to position 0 (GND) 24 | 25 | ### Connect to PiPVM 26 | Pi-KVM communicate with HID emulator through primary UART. It is GPIO 14 (TX, Pin 8) and GPIO 15 (RX, Pin 10) on Raspberry Pi 40-pin connector. For BluePill HID emulator, it uses STM32F103 UART3 (TX PB10 and RX PB11) for Pi-KVM communication. So they need to be connected as below: 27 | - RPI TX (Pin 8) <=> BluePill RX PB11 28 | - RPI RX (Pin 10) <=> BluePill TX PB10 29 | - RPI GND (Pin 6) <=> BluePill GND 30 | 31 | ### References 32 | This project reused some souce code from: 33 | - https://github.com/STMicroelectronics/STM32CubeF1 34 | - https://github.com/IntergatedCircuits/USBDevice 35 | - https://github.com/navilera/Navilos 36 | -------------------------------------------------------------------------------- /usb/Device/usbd_utils.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file usbd_utils.c 4 | * @author Benedek Kupper 5 | * @version 0.1 6 | * @date 2018-01-31 7 | * @brief Universal Serial Bus Device Driver 8 | * Utilities for descriptor conversion 9 | * 10 | * Copyright (c) 2018 Benedek Kupper 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the "License"); 13 | * you may not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * http://www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an "AS IS" BASIS, 20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | #include 25 | #include 26 | 27 | /** 28 | * @ingroup USBD 29 | * @addtogroup USBD_Utils USBD Utility functions 30 | * @{ */ 31 | 32 | /** 33 | * @brief Convert raw integers into Unicode string 34 | * @param data: address of raw data 35 | * @param unicode: Unicode string output 36 | * @param len: number of hexadecimal digits to output 37 | */ 38 | __attribute__((weak)) void Uint2Unicode(const uint8_t *data, uint8_t *unicode, uint16_t len) 39 | { 40 | uint8_t i = 0; 41 | 42 | len *= 2; 43 | while (i < len) 44 | { 45 | uint8_t val; 46 | 47 | if ((i & 2) == 0) 48 | { 49 | val = *data >> 4; 50 | } 51 | else 52 | { 53 | val = *data & 0xF; 54 | data++; 55 | } 56 | 57 | if (val < 0xA) 58 | { 59 | unicode[i] = '0' + val; 60 | } 61 | else 62 | { 63 | unicode[i] = 'A' - 10 + val; 64 | } 65 | i++; 66 | unicode[i] = 0x00; 67 | i++; 68 | } 69 | 70 | /* Null termination not used by USB string descriptors */ 71 | unicode[i++] = '\0'; 72 | unicode[i] = 0x00; 73 | } 74 | 75 | /** @} */ 76 | -------------------------------------------------------------------------------- /kernel/task.c: -------------------------------------------------------------------------------- 1 | /* 2 | * task.c 3 | * 4 | * Created on: Oct 22, 2018 5 | * Author: maanu 6 | */ 7 | 8 | 9 | #include "stdint.h" 10 | #include "stdbool.h" 11 | 12 | #include "PSR.h" 13 | #include "switch.h" 14 | 15 | #include "task.h" 16 | 17 | #include "memory_map.h" 18 | 19 | #define MAX_TASK_NUM (TASK_STACK_SIZE / USR_TASK_STACK_SIZE) 20 | 21 | KernelTcb_t* gCurrent_tcb; 22 | KernelTcb_t* gNext_tcb; 23 | 24 | static KernelTcb_t sTask_list[MAX_TASK_NUM]; 25 | static uint32_t sAllocated_tcb_index; 26 | static uint32_t sCurrent_tcb_index; 27 | 28 | static KernelTcb_t* Scheduler_round_robin_algorithm(void); 29 | 30 | void Kernel_task_init(void) 31 | { 32 | sAllocated_tcb_index = 0; 33 | sCurrent_tcb_index = 0; 34 | 35 | for(uint32_t i = 0 ; i < MAX_TASK_NUM ; i++) 36 | { 37 | sTask_list[i].stack_base = (uint8_t*)(TASK_STACK_START + (i * USR_TASK_STACK_SIZE)); 38 | sTask_list[i].sp = (uint32_t)sTask_list[i].stack_base + USR_TASK_STACK_SIZE - 4; 39 | 40 | sTask_list[i].sp -= sizeof(KernelTaskContext_t); 41 | KernelTaskContext_t* ctx = (KernelTaskContext_t*)sTask_list[i].sp; 42 | 43 | ctx->pc = 0; 44 | ctx->spsr = PSR_INIT; 45 | } 46 | } 47 | 48 | void Kernel_task_start(void) 49 | { 50 | gNext_tcb = &sTask_list[sCurrent_tcb_index]; 51 | Arch_start(); 52 | } 53 | 54 | uint32_t Kernel_task_create(KernelTaskFunc_t startFunc) 55 | { 56 | KernelTcb_t* new_tcb = &sTask_list[sAllocated_tcb_index++]; 57 | 58 | if (sAllocated_tcb_index > MAX_TASK_NUM) 59 | { 60 | return NOT_ENOUGH_TASK_NUM; 61 | } 62 | 63 | KernelTaskContext_t* ctx = (KernelTaskContext_t*)new_tcb->sp; 64 | ctx->pc = (uint32_t)startFunc; 65 | 66 | return (sAllocated_tcb_index - 1); 67 | } 68 | 69 | uint32_t Kernel_task_get_current_task_id(void) 70 | { 71 | return sCurrent_tcb_index; 72 | } 73 | 74 | void Kernel_task_scheduler(void) 75 | { 76 | gCurrent_tcb = &sTask_list[sCurrent_tcb_index]; 77 | gNext_tcb = Scheduler_round_robin_algorithm(); 78 | 79 | Arch_context_switching(); 80 | } 81 | 82 | static KernelTcb_t* Scheduler_round_robin_algorithm(void) 83 | { 84 | sCurrent_tcb_index++; 85 | sCurrent_tcb_index %= sAllocated_tcb_index; 86 | 87 | return &sTask_list[sCurrent_tcb_index]; 88 | } 89 | -------------------------------------------------------------------------------- /usb/Xpd/xpd_usb_wrapper.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file xpd_usb_wrapper.h 4 | * @author Benedek Kupper 5 | * @version 0.1 6 | * @date 2018-01-31 7 | * @brief STM32 eXtensible Peripheral Drivers Universal Serial Bus Module 8 | * 9 | * Copyright (c) 2018 Benedek Kupper 10 | * 11 | * Licensed under the Apache License, Version 2.0 (the "License"); 12 | * you may not use this file except in compliance with the License. 13 | * You may obtain a copy of the License at 14 | * 15 | * http://www.apache.org/licenses/LICENSE-2.0 16 | * 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | */ 23 | #ifndef __XPD_USB_WRAPPER_H_ 24 | #define __XPD_USB_WRAPPER_H_ 25 | 26 | #ifdef __cplusplus 27 | extern "C" 28 | { 29 | #endif 30 | 31 | #include 32 | 33 | /** @addtogroup USB 34 | * @{ */ 35 | 36 | /** @addtogroup USB_Imported_Types 37 | * @{ */ 38 | 39 | typedef USBD_HandleType USB_HandleType; 40 | typedef USBD_EpHandleType USB_EndPointHandleType; 41 | typedef USBD_ConfigurationType USB_InitType; 42 | 43 | /** @} */ 44 | 45 | #ifndef USB_vResetCallback 46 | #define USB_vResetCallback USBD_ResetCallback 47 | #endif 48 | #ifndef USB_vSetupCallback 49 | #define USB_vSetupCallback USBD_SetupCallback 50 | #endif 51 | #ifndef USB_vDataInCallback 52 | #define USB_vDataInCallback USBD_EpInCallback 53 | #endif 54 | #ifndef USB_vDataOutCallback 55 | #define USB_vDataOutCallback USBD_EpOutCallback 56 | #endif 57 | 58 | /* usbd <- PD */ 59 | void USB_vResetCallback (USBD_HandleType *dev, 60 | USB_SpeedType speed); 61 | 62 | /* usbd_ctrl <- PD */ 63 | void USB_vSetupCallback (USBD_HandleType *dev); 64 | 65 | /* usbd_ep <- PD */ 66 | void USB_vDataInCallback (USBD_HandleType *dev, 67 | USBD_EpHandleType *ep); 68 | void USB_vDataOutCallback (USBD_HandleType *dev, 69 | USBD_EpHandleType *ep); 70 | 71 | /** @} */ 72 | 73 | #ifdef __cplusplus 74 | } 75 | #endif 76 | 77 | #endif /* __XPD_USB_WRAPPER_H_ */ 78 | -------------------------------------------------------------------------------- /brd/stm32f1xx_it.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32f1xx_it.h 4 | * @brief This file contains the headers of the interrupt handlers. 5 | ****************************************************************************** 6 | * 7 | * COPYRIGHT(c) 2017 STMicroelectronics 8 | * 9 | * Redistribution and use in source and binary forms, with or without modification, 10 | * are permitted provided that the following conditions are met: 11 | * 1. Redistributions of source code must retain the above copyright notice, 12 | * this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 3. Neither the name of STMicroelectronics nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | ****************************************************************************** 32 | */ 33 | 34 | /* Define to prevent recursive inclusion -------------------------------------*/ 35 | #ifndef __STM32F1xx_IT_H 36 | #define __STM32F1xx_IT_H 37 | 38 | #ifdef __cplusplus 39 | extern "C" { 40 | #endif 41 | 42 | /* Includes ------------------------------------------------------------------*/ 43 | /* Exported types ------------------------------------------------------------*/ 44 | /* Exported constants --------------------------------------------------------*/ 45 | /* Exported macro ------------------------------------------------------------*/ 46 | /* Exported functions ------------------------------------------------------- */ 47 | 48 | void NMI_Handler(void); 49 | void HardFault_Handler(void); 50 | void MemManage_Handler(void); 51 | void BusFault_Handler(void); 52 | void UsageFault_Handler(void); 53 | void SVC_Handler(void); 54 | void DebugMon_Handler(void); 55 | void PendSV_Handler(void); 56 | void SysTick_Handler(void); 57 | void USB_LP_CAN1_RX0_IRQHandler(void); 58 | void USART1_IRQHandler(void); 59 | 60 | #ifdef __cplusplus 61 | } 62 | #endif 63 | 64 | #endif /* __STM32F1xx_IT_H */ 65 | 66 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 67 | -------------------------------------------------------------------------------- /brd/main.c: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | SPDX-License-Identifier: BSD-2-Clause-Patent 4 | 5 | **/ 6 | 7 | #include "stdbool.h" 8 | #include "stdint.h" 9 | #include "stdio.h" 10 | #include "stdlib.h" 11 | 12 | #include "stm32f1xx_hal.h" 13 | #include "hal_interrupt.h" 14 | 15 | #include "hal_gpio.h" 16 | #include "hal_uart.h" 17 | 18 | #include "kernel.h" 19 | #include "memory_map.h" 20 | 21 | #include "usbd.h" 22 | 23 | #define SYSTEM_US_TICKS (SystemCoreClock / 1000000) // cycles per microsecond 24 | 25 | extern void usb_device_init (void); 26 | extern void usb_connect (int ms); 27 | 28 | /** System Clock Configuration 29 | */ 30 | static void SystemClock_Config (void) 31 | { 32 | RCC_OscInitTypeDef RCC_OscInitStruct; 33 | RCC_ClkInitTypeDef RCC_ClkInitStruct; 34 | RCC_PeriphCLKInitTypeDef PeriphClkInit; 35 | 36 | /**Initializes the CPU, AHB and APB busses clocks 37 | */ 38 | RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; 39 | RCC_OscInitStruct.HSEState = RCC_HSE_ON; 40 | RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; 41 | RCC_OscInitStruct.HSIState = RCC_HSI_ON; 42 | RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; 43 | RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; 44 | RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL6; 45 | if (HAL_RCC_OscConfig (&RCC_OscInitStruct) != HAL_OK) { 46 | halt (__FILE__, __LINE__); 47 | } 48 | 49 | /**Initializes the CPU, AHB and APB busses clocks 50 | */ 51 | RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK 52 | | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; 53 | RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; 54 | RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; 55 | RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; 56 | RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV4; 57 | 58 | if (HAL_RCC_ClockConfig (&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) { 59 | halt (__FILE__, __LINE__); 60 | } 61 | 62 | PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB; 63 | PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL; 64 | if (HAL_RCCEx_PeriphCLKConfig (&PeriphClkInit) != HAL_OK) { 65 | halt (__FILE__, __LINE__); 66 | } 67 | 68 | /**Configure the Systick interrupt time 69 | */ 70 | HAL_SYSTICK_Config (HAL_RCC_GetHCLKFreq() / 1000); 71 | 72 | /**Configure the Systick 73 | */ 74 | HAL_SYSTICK_CLKSourceConfig (SYSTICK_CLKSOURCE_HCLK); 75 | 76 | /* SysTick_IRQn interrupt configuration */ 77 | HAL_NVIC_SetPriority (SysTick_IRQn, 0, 0); 78 | } 79 | 80 | static void Kernel_Init (void) 81 | { 82 | extern void cli_task(); 83 | 84 | uint32_t taskId; 85 | 86 | Kernel_task_init(); 87 | 88 | taskId = Kernel_task_create (cli_task); 89 | if (NOT_ENOUGH_TASK_NUM == taskId) { 90 | dprintf (1, "Failed to create task: cli_task\n"); 91 | } 92 | } 93 | 94 | int main (void) 95 | { 96 | HAL_Init(); 97 | 98 | SystemClock_Config(); 99 | 100 | Hal_interrupt_init (); 101 | 102 | Hal_gpio_init(); 103 | 104 | Hal_uart_init(); 105 | 106 | dprintf (1, "BootLoader\n"); 107 | 108 | usb_connect (10); 109 | 110 | usb_device_init (); 111 | 112 | Kernel_Init(); 113 | 114 | Kernel_start(); 115 | 116 | while (1) { } 117 | } 118 | -------------------------------------------------------------------------------- /usb/Templates/usbd_config.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file usbd_config.h 4 | * @author Benedek Kupper 5 | * @version 0.1 6 | * @date 2018-01-31 7 | * @brief Universal Serial Bus Device Driver 8 | * 9 | * Copyright (c) 2018 Benedek Kupper 10 | * 11 | * Licensed under the Apache License, Version 2.0 (the "License"); 12 | * you may not use this file except in compliance with the License. 13 | * You may obtain a copy of the License at 14 | * 15 | * http://www.apache.org/licenses/LICENSE-2.0 16 | * 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | */ 23 | #ifndef __USBD_CONFIG_H_ 24 | #define __USBD_CONFIG_H_ 25 | 26 | /** @addtogroup USBD_Exported_Macros 27 | * @{ */ 28 | 29 | /** @brief Must be set according to the highest number of interfaces for a given USB Device. */ 30 | #define USBD_MAX_IF_COUNT 2 31 | 32 | /** @brief Must be set higher than: 33 | * @arg the length of the entire USB device configuration descriptor 34 | * @arg the longest USB string (as Unicode string descriptor) 35 | * @arg the length of the longest class-specific control request */ 36 | #define USBD_EP0_BUFFER_SIZE 256 37 | 38 | /** @brief Set to 1 if peripheral support and application demand 39 | * for High-Speed operation both exist. */ 40 | #define USBD_HS_SUPPORT 0 41 | 42 | /** @brief When set to 0, no SerialNumber is readable by the host. 43 | * Otherwise the SerialNumber will be converted from USBD_SERIAL_BCD_SIZE / 2 44 | * amount of raw bytes to string BCD format and sent to the host. */ 45 | #define USBD_SERIAL_BCD_SIZE 0 46 | 47 | 48 | 49 | /** @brief Set to 1 if notifications are sent by a CDC-ACM interface. 50 | * In this case notification EP will be allocated and opened if its address is valid. */ 51 | #define USBD_CDC_NOTEP_USED 1 52 | 53 | /** @brief Set to 1 if SET_CONTROL_LINE_STATE request is used by a CDC-ACM interface. */ 54 | #define USBD_CDC_CONTROL_LINE_USED 0 55 | 56 | /** @brief Set to 1 if SEND_BREAK request is used by a CDC-ACM interface. */ 57 | #define USBD_CDC_BREAK_SUPPORT 0 58 | 59 | 60 | 61 | /** @brief Set to 1 if a DFU interface holds more than one applications as alternate settings. */ 62 | #define USBD_DFU_ALTSETTINGS 0 63 | 64 | /** @brief Set to 1 if DFU STMicroelectronics Extension 65 | * protocol (v1.1A) shall be used instead of the standard DFU (v1.1). */ 66 | #define USBD_DFU_ST_EXTENSION 0 67 | 68 | 69 | 70 | /** @brief Set to 1 if a HID interface holds more than one applications as alternate settings. */ 71 | #define USBD_HID_ALTSETTINGS 0 72 | 73 | /** @brief Set to 1 if a HID interface uses an OUT endpoint. */ 74 | #define USBD_HID_OUT_SUPPORT 0 75 | 76 | /** @brief Set to 1 if a HID interface defines strings in its report descriptor. */ 77 | #define USBD_HID_REPORT_STRINGS 0 78 | 79 | /** @} */ 80 | 81 | #endif /* __USBD_CONFIG_H_ */ 82 | -------------------------------------------------------------------------------- /kernel/kernel.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Kernel.c 3 | * 4 | * Created on: Oct 28, 2018 5 | * Author: maanu 6 | */ 7 | 8 | 9 | #include "stdint.h" 10 | #include "stdbool.h" 11 | 12 | #include "armcpu.h" 13 | #include "memio.h" 14 | #include "kernel.h" 15 | 16 | void Kernel_start(void) 17 | { 18 | enable_irq(); 19 | Kernel_task_start(); 20 | } 21 | 22 | void Kernel_yield(void) 23 | { 24 | Kernel_task_scheduler(); 25 | } 26 | 27 | void Kernel_send_events(uint32_t event_list) 28 | { 29 | KernelEventFlag_t sending_event = KernelEventFlag_Empty; 30 | 31 | for (uint32_t i = 0 ; i < 32 ; i++) 32 | { 33 | if ((event_list >> i) & 1) 34 | { 35 | SET_BIT(sending_event, i); 36 | Kernel_event_flag_set(sending_event); 37 | } 38 | } 39 | } 40 | 41 | KernelEventFlag_t Kernel_wait_events(uint32_t waiting_list) 42 | { 43 | KernelEventFlag_t waiting_event = KernelEventFlag_Empty; 44 | 45 | for (uint32_t i = 0 ; i < 32 ; i++) 46 | { 47 | if ((waiting_list >> i) & 1) 48 | { 49 | SET_BIT(waiting_event, i); 50 | 51 | if (Kernel_event_flag_check(waiting_event)) 52 | { 53 | return waiting_event; 54 | } 55 | } 56 | } 57 | 58 | return KernelEventFlag_Empty; 59 | } 60 | 61 | bool Kernel_send_msg(KernelMsgQ_t Qname, void* data, uint32_t count) 62 | { 63 | uint8_t* d = (uint8_t*)data; 64 | 65 | for (uint32_t i = 0 ; i < count ; i++) 66 | { 67 | if (false == Kernel_msgQ_enqueue(Qname, *d)) 68 | { 69 | for (uint32_t j = 0 ; j < i ; j++) 70 | { 71 | uint8_t rollback; 72 | Kernel_msgQ_dequeue(Qname, &rollback); 73 | } 74 | return false; 75 | } 76 | d++; 77 | } 78 | 79 | return true; 80 | } 81 | 82 | uint32_t Kernel_recv_msg(KernelMsgQ_t Qname, void* out_data, uint32_t count) 83 | { 84 | uint8_t* d = (uint8_t*)out_data; 85 | 86 | for (uint32_t i = 0 ; i < count ; i++) 87 | { 88 | if (false == Kernel_msgQ_dequeue(Qname, d)) 89 | { 90 | return i; 91 | } 92 | d++; 93 | } 94 | 95 | return count; 96 | } 97 | 98 | void Kernel_flush_msg(KernelMsgQ_t Qname) 99 | { 100 | uint8_t d = 0; 101 | 102 | while(true) 103 | { 104 | if (false == Kernel_msgQ_dequeue(Qname, &d)) 105 | { 106 | break; 107 | } 108 | } 109 | } 110 | 111 | void Kernel_lock_sem(void) 112 | { 113 | while(false == Kernel_sem_test()) 114 | { 115 | Kernel_yield(); 116 | } 117 | } 118 | 119 | void Kernel_unlock_sem(void) 120 | { 121 | Kernel_sem_release(); 122 | } 123 | 124 | void Kernel_lock_mutex(void) 125 | { 126 | while(true) 127 | { 128 | uint32_t current_task_id = Kernel_task_get_current_task_id(); 129 | if (false == Kernel_mutex_lock(current_task_id)) 130 | { 131 | Kernel_yield(); 132 | } 133 | else 134 | { 135 | break; 136 | } 137 | } 138 | } 139 | 140 | void Kernel_unlock_mutex(void) 141 | { 142 | uint32_t current_task_id = Kernel_task_get_current_task_id(); 143 | if (false == Kernel_mutex_unlock(current_task_id)) 144 | { 145 | Kernel_yield(); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /usb/Xpd/usbd_pd_if.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file usbd_pd_if.h 4 | * @author Benedek Kupper 5 | * @version 0.1 6 | * @date 2018-01-31 7 | * @brief Universal Serial Bus Device Driver 8 | * Peripheral Driver-specific interface function definitions 9 | * 10 | * Copyright (c) 2018 Benedek Kupper 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the "License"); 13 | * you may not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * http://www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an "AS IS" BASIS, 20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | #ifndef __USBD_PD_IF_H_ 25 | #define __USBD_PD_IF_H_ 26 | 27 | #ifdef __cplusplus 28 | extern "C" 29 | { 30 | #endif 31 | 32 | #include 33 | 34 | #if defined(USB) 35 | #include 36 | 37 | /** @addtogroup USBD_Exported_Macros 38 | * @{ */ 39 | 40 | #define USBD_PD_Init USB_vInit 41 | #define USBD_PD_Deinit USB_vDeinit 42 | #define USBD_PD_Start USB_vStart_IT 43 | #define USBD_PD_Stop USB_vStop_IT 44 | #define USBD_PD_SetRemoteWakeup USB_vSetRemoteWakeup 45 | #define USBD_PD_ClearRemoteWakeup USB_vClearRemoteWakeup 46 | #define USBD_PD_SetAddress USB_vSetAddress 47 | #define USBD_PD_CtrlEpOpen USB_vCtrlEpOpen 48 | #define USBD_PD_EpOpen USB_vEpOpen 49 | #define USBD_PD_EpClose USB_vEpClose 50 | #define USBD_PD_EpSend USB_vEpSend 51 | #define USBD_PD_EpReceive USB_vEpReceive 52 | #define USBD_PD_EpSetStall USB_vEpSetStall 53 | #define USBD_PD_EpClearStall USB_vEpClearStall 54 | #define USBD_PD_EpFlush(HANDLE,EPNUM) ((void)0) 55 | 56 | /** @} */ 57 | 58 | #elif defined(USB_OTG_FS) 59 | #include 60 | 61 | /** @addtogroup USBD_Exported_Macros 62 | * @{ */ 63 | 64 | #define USBD_PD_Init USB_vDevInit 65 | #define USBD_PD_Deinit USB_vDevDeinit 66 | #define USBD_PD_Start USB_vDevStart_IT 67 | #define USBD_PD_Stop USB_vDevStop_IT 68 | #define USBD_PD_SetRemoteWakeup USB_vSetRemoteWakeup 69 | #define USBD_PD_ClearRemoteWakeup USB_vClearRemoteWakeup 70 | #define USBD_PD_SetAddress USB_vSetAddress 71 | #define USBD_PD_CtrlEpOpen USB_vCtrlEpOpen 72 | #define USBD_PD_EpOpen USB_vEpOpen 73 | #define USBD_PD_EpClose USB_vEpClose 74 | #define USBD_PD_EpSend USB_vEpSend 75 | #define USBD_PD_EpReceive USB_vEpReceive 76 | #define USBD_PD_EpSetStall USB_vEpSetStall 77 | #define USBD_PD_EpClearStall USB_vEpClearStall 78 | #define USBD_PD_EpFlush USB_vEpFlush 79 | 80 | #ifndef __htonl 81 | #define __htonl(_x) ((uint32_t)__REV(_x)) 82 | #endif 83 | #ifndef __htons 84 | #define __htons(_x) ((uint16_t)__REVSH(_x)) 85 | #endif 86 | 87 | /** @} */ 88 | 89 | #endif 90 | 91 | #ifdef __cplusplus 92 | } 93 | #endif 94 | 95 | #endif /* __USBD_PD_IF_H_ */ 96 | -------------------------------------------------------------------------------- /app/usbd_config.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file usbd_config.h 4 | * @author Benedek Kupper 5 | * @version 0.1 6 | * @date 2018-01-31 7 | * @brief Universal Serial Bus Device Driver 8 | * 9 | * Copyright (c) 2018 Benedek Kupper 10 | * 11 | * Licensed under the Apache License, Version 2.0 (the "License"); 12 | * you may not use this file except in compliance with the License. 13 | * You may obtain a copy of the License at 14 | * 15 | * http://www.apache.org/licenses/LICENSE-2.0 16 | * 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | */ 23 | #ifndef __USBD_CONFIG_H_ 24 | #define __USBD_CONFIG_H_ 25 | 26 | /** @addtogroup USBD_Exported_Macros 27 | * @{ */ 28 | 29 | /** @brief Must be set according to the highest number of interfaces for a given USB Device. */ 30 | #define USBD_MAX_IF_COUNT 4 31 | 32 | /** @brief Must be set higher than: 33 | * @arg the length of the entire USB device configuration descriptor 34 | * @arg the longest USB string (as Unicode string descriptor) 35 | * @arg the length of the longest class-specific control request */ 36 | #define USBD_EP0_BUFFER_SIZE 64 37 | 38 | /** @brief Set to 1 if peripheral support and application demand 39 | * for High-Speed operation both exist. */ 40 | #define USBD_HS_SUPPORT 0 41 | 42 | /** @brief When set to 0, no SerialNumber is readable by the host. 43 | * Otherwise the SerialNumber will be converted from USBD_SERIAL_BCD_SIZE / 2 44 | * amount of raw bytes to string BCD format and sent to the host. */ 45 | #define USBD_SERIAL_BCD_SIZE 0 46 | 47 | /** @brief Selects which Microsoft OS descriptor specification should be used (if any). 48 | * Supported values are: 0, 1, 2 49 | * @note Microsoft OS 2.0 descriptors are supported by Windows 8.1 and higher. 50 | * Unless the device is required to operate on earlier Windows OS versions, use version 2. */ 51 | #define USBD_MS_OS_DESC_VERSION 0 52 | 53 | 54 | /** @brief Set to 1 if notifications are sent by a CDC-ACM interface. 55 | * In this case notification EP will be allocated and opened if its address is valid. */ 56 | #define USBD_CDC_NOTEP_USED 1 57 | 58 | /** @brief Set to 1 if SET_CONTROL_LINE_STATE request is used by a CDC-ACM interface. */ 59 | #define USBD_CDC_CONTROL_LINE_USED 0 60 | 61 | /** @brief Set to 1 if SEND_BREAK request is used by a CDC-ACM interface. */ 62 | #define USBD_CDC_BREAK_SUPPORT 0 63 | 64 | 65 | 66 | /** @brief Set to 1 if a DFU interface holds more than one applications as alternate settings. */ 67 | #define USBD_DFU_ALTSETTINGS 0 68 | 69 | /** @brief Set to 1 if DFU STMicroelectronics Extension 70 | * protocol (v1.1A) shall be used instead of the standard DFU (v1.1). */ 71 | #define USBD_DFU_ST_EXTENSION 0 72 | 73 | 74 | 75 | /** @brief Set to 1 if a HID interface holds more than one applications as alternate settings. */ 76 | #define USBD_HID_ALTSETTINGS 0 77 | 78 | /** @brief Set to 1 if a HID interface uses an OUT endpoint. */ 79 | #define USBD_HID_OUT_SUPPORT 0 80 | 81 | /** @brief Set to 1 if a HID interface defines strings in its report descriptor. */ 82 | #define USBD_HID_REPORT_STRINGS 0 83 | 84 | 85 | /** @} */ 86 | 87 | #endif /* __USBD_CONFIG_H_ */ 88 | -------------------------------------------------------------------------------- /brd/uart.c: -------------------------------------------------------------------------------- 1 | /** @file 2 | 3 | SPDX-License-Identifier: BSD-2-Clause-Patent 4 | 5 | **/ 6 | 7 | #include "stdint.h" 8 | #include "stdbool.h" 9 | #include "stm32f1xx_hal.h" 10 | #include "hal_uart.h" 11 | #include "kernel.h" 12 | 13 | UART_HandleTypeDef huart1; 14 | UART_HandleTypeDef huart3; 15 | 16 | void Hal_uart_init (void) 17 | { 18 | huart3.Instance = USART3; 19 | huart3.Init.BaudRate = 115200; 20 | huart3.Init.WordLength = UART_WORDLENGTH_8B; 21 | huart3.Init.StopBits = UART_STOPBITS_1; 22 | huart3.Init.Parity = UART_PARITY_NONE; 23 | huart3.Init.Mode = UART_MODE_TX_RX; 24 | huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE; 25 | huart3.Init.OverSampling = UART_OVERSAMPLING_16; 26 | huart3.gState = HAL_UART_STATE_RESET; 27 | HAL_UART_Init (&huart3); 28 | 29 | __HAL_UART_ENABLE_IT (&huart3, UART_IT_RXNE); 30 | 31 | HAL_NVIC_SetPriority (USART3_IRQn, 0, 1); 32 | HAL_NVIC_EnableIRQ (USART3_IRQn); 33 | 34 | huart1.Instance = USART1; 35 | huart1.Init.BaudRate = 115200; 36 | huart1.Init.WordLength = UART_WORDLENGTH_8B; 37 | huart1.Init.StopBits = UART_STOPBITS_1; 38 | huart1.Init.Parity = UART_PARITY_NONE; 39 | huart1.Init.Mode = UART_MODE_TX_RX; 40 | huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; 41 | huart1.Init.OverSampling = UART_OVERSAMPLING_16; 42 | huart1.gState = HAL_UART_STATE_RESET; 43 | HAL_UART_Init (&huart1); 44 | } 45 | 46 | void Hal_uart_put_char (uint8_t ch) 47 | { 48 | HAL_UART_Transmit (&huart1, &ch, 1, 1000); 49 | } 50 | 51 | uint8_t Hal_uart_get_char (void) 52 | { 53 | uint8_t ch; 54 | if (HAL_UART_Receive (&huart1, &ch, 1, 1000) == HAL_OK) { 55 | return ch; 56 | } else { 57 | return 0; 58 | } 59 | } 60 | 61 | uint8_t Hal_uart_fast_rx (uint8_t idx) 62 | { 63 | UART_HandleTypeDef *huart; 64 | if (idx == 1) { 65 | huart = &huart1; 66 | } else if (idx == 3) { 67 | huart = &huart3; 68 | } else { 69 | huart = NULL; 70 | } 71 | if (huart) { 72 | return (huart->Instance->DR & 0xff); 73 | } else { 74 | return 0; 75 | } 76 | } 77 | 78 | void Hal_uart_fast_tx (uint8_t idx, uint8_t ch) 79 | { 80 | UART_HandleTypeDef *huart; 81 | if (idx == 1) { 82 | huart = &huart1; 83 | } else if (idx == 3) { 84 | huart = &huart3; 85 | } else { 86 | huart = NULL; 87 | } 88 | if (huart) { 89 | while (!(huart->Instance->SR & UART_FLAG_TXE)); 90 | huart->Instance->DR = ch; 91 | } 92 | } 93 | 94 | void Hal_uart_isr (void) 95 | { 96 | static uint32_t last_tick = 0; 97 | static uint8_t cmd_cnt = 0; 98 | static uint8_t cmd_buf[UART_RX_BUF_LEN]; 99 | uint8_t ch; 100 | bool send_frame; 101 | uint32_t curr_tick; 102 | 103 | ch = Hal_uart_fast_rx (3); 104 | 105 | curr_tick = HAL_GetTick(); 106 | if (curr_tick >= last_tick) { 107 | curr_tick -= last_tick; 108 | } else { 109 | curr_tick = curr_tick - last_tick + 0xffffffff; 110 | } 111 | 112 | if (curr_tick > 50) { 113 | cmd_cnt = 0; 114 | } 115 | 116 | if (cmd_cnt >= UART_RX_BUF_LEN) { 117 | cmd_cnt = 0; 118 | } 119 | 120 | cmd_buf[cmd_cnt++] = ch; 121 | 122 | send_frame = false; 123 | if ((cmd_buf[0] == '@') || (cmd_buf[0] == '#')) { 124 | if ((ch == '\r') || (ch == '\n')) { 125 | send_frame = true; 126 | } 127 | } else if (cmd_buf[0] == '3') { 128 | if (cmd_cnt == 8) { 129 | send_frame = true; 130 | } 131 | } 132 | 133 | if (send_frame) { 134 | if (Kernel_send_msg (KernelMsgQ_DebugCmd, cmd_buf, cmd_cnt)) { 135 | Kernel_send_events (KernelEventFlag_CmdIn); 136 | } else { 137 | Kernel_flush_msg (KernelEventFlag_CmdIn); 138 | } 139 | cmd_cnt = 0; 140 | } 141 | 142 | last_tick = HAL_GetTick (); 143 | } 144 | 145 | -------------------------------------------------------------------------------- /hal/system_stm32f1xx.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file system_stm32f10x.h 4 | * @author MCD Application Team 5 | * @version V4.2.0 6 | * @date 31-March-2017 7 | * @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Header File. 8 | ****************************************************************************** 9 | * @attention 10 | * 11 | *

© COPYRIGHT(c) 2017 STMicroelectronics

12 | * 13 | * Redistribution and use in source and binary forms, with or without modification, 14 | * are permitted provided that the following conditions are met: 15 | * 1. Redistributions of source code must retain the above copyright notice, 16 | * this list of conditions and the following disclaimer. 17 | * 2. Redistributions in binary form must reproduce the above copyright notice, 18 | * this list of conditions and the following disclaimer in the documentation 19 | * and/or other materials provided with the distribution. 20 | * 3. Neither the name of STMicroelectronics nor the names of its contributors 21 | * may be used to endorse or promote products derived from this software 22 | * without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | * 35 | ****************************************************************************** 36 | */ 37 | 38 | /** @addtogroup CMSIS 39 | * @{ 40 | */ 41 | 42 | /** @addtogroup stm32f10x_system 43 | * @{ 44 | */ 45 | 46 | /** 47 | * @brief Define to prevent recursive inclusion 48 | */ 49 | #ifndef __SYSTEM_STM32F10X_H 50 | #define __SYSTEM_STM32F10X_H 51 | 52 | #ifdef __cplusplus 53 | extern "C" { 54 | #endif 55 | 56 | /** @addtogroup STM32F10x_System_Includes 57 | * @{ 58 | */ 59 | 60 | /** 61 | * @} 62 | */ 63 | 64 | 65 | /** @addtogroup STM32F10x_System_Exported_types 66 | * @{ 67 | */ 68 | 69 | extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ 70 | extern const uint8_t AHBPrescTable[16U]; /*!< AHB prescalers table values */ 71 | extern const uint8_t APBPrescTable[8U]; /*!< APB prescalers table values */ 72 | 73 | /** 74 | * @} 75 | */ 76 | 77 | /** @addtogroup STM32F10x_System_Exported_Constants 78 | * @{ 79 | */ 80 | 81 | /** 82 | * @} 83 | */ 84 | 85 | /** @addtogroup STM32F10x_System_Exported_Macros 86 | * @{ 87 | */ 88 | 89 | /** 90 | * @} 91 | */ 92 | 93 | /** @addtogroup STM32F10x_System_Exported_Functions 94 | * @{ 95 | */ 96 | 97 | extern void SystemInit(void); 98 | extern void SystemCoreClockUpdate(void); 99 | /** 100 | * @} 101 | */ 102 | 103 | #ifdef __cplusplus 104 | } 105 | #endif 106 | 107 | #endif /*__SYSTEM_STM32F10X_H */ 108 | 109 | /** 110 | * @} 111 | */ 112 | 113 | /** 114 | * @} 115 | */ 116 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 117 | -------------------------------------------------------------------------------- /lib/cortexM/core_cmFunc.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file core_cmFunc.h 3 | * @brief CMSIS Cortex-M Core Function Access Header File 4 | * @version V4.30 5 | * @date 20. October 2015 6 | ******************************************************************************/ 7 | /* Copyright (c) 2009 - 2015 ARM LIMITED 8 | 9 | All rights reserved. 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | - Redistributions of source code must retain the above copyright 13 | notice, this list of conditions and the following disclaimer. 14 | - Redistributions in binary form must reproduce the above copyright 15 | notice, this list of conditions and the following disclaimer in the 16 | documentation and/or other materials provided with the distribution. 17 | - Neither the name of ARM nor the names of its contributors may be used 18 | to endorse or promote products derived from this software without 19 | specific prior written permission. 20 | * 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE 25 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. 32 | ---------------------------------------------------------------------------*/ 33 | 34 | 35 | #if defined ( __ICCARM__ ) 36 | #pragma system_include /* treat file as system include file for MISRA check */ 37 | #elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) 38 | #pragma clang system_header /* treat file as system include file */ 39 | #endif 40 | 41 | #ifndef __CORE_CMFUNC_H 42 | #define __CORE_CMFUNC_H 43 | 44 | 45 | /* ########################### Core Function Access ########################### */ 46 | /** \ingroup CMSIS_Core_FunctionInterface 47 | \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions 48 | @{ 49 | */ 50 | 51 | /*------------------ RealView Compiler -----------------*/ 52 | #if defined ( __CC_ARM ) 53 | #include "cmsis_armcc.h" 54 | 55 | /*------------------ ARM Compiler V6 -------------------*/ 56 | #elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) 57 | #include "cmsis_armcc_V6.h" 58 | 59 | /*------------------ GNU Compiler ----------------------*/ 60 | #elif defined ( __GNUC__ ) 61 | #include "cmsis_gcc.h" 62 | 63 | /*------------------ ICC Compiler ----------------------*/ 64 | #elif defined ( __ICCARM__ ) 65 | #include 66 | 67 | /*------------------ TI CCS Compiler -------------------*/ 68 | #elif defined ( __TMS470__ ) 69 | #include 70 | 71 | /*------------------ TASKING Compiler ------------------*/ 72 | #elif defined ( __TASKING__ ) 73 | /* 74 | * The CMSIS functions have been implemented as intrinsics in the compiler. 75 | * Please use "carm -?i" to get an up to date list of all intrinsics, 76 | * Including the CMSIS ones. 77 | */ 78 | 79 | /*------------------ COSMIC Compiler -------------------*/ 80 | #elif defined ( __CSMC__ ) 81 | #include 82 | 83 | #endif 84 | 85 | /*@} end of CMSIS_Core_RegAccFunctions */ 86 | 87 | #endif /* __CORE_CMFUNC_H */ 88 | -------------------------------------------------------------------------------- /lib/cortexM/core_cmInstr.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file core_cmInstr.h 3 | * @brief CMSIS Cortex-M Core Instruction Access Header File 4 | * @version V4.30 5 | * @date 20. October 2015 6 | ******************************************************************************/ 7 | /* Copyright (c) 2009 - 2015 ARM LIMITED 8 | 9 | All rights reserved. 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | - Redistributions of source code must retain the above copyright 13 | notice, this list of conditions and the following disclaimer. 14 | - Redistributions in binary form must reproduce the above copyright 15 | notice, this list of conditions and the following disclaimer in the 16 | documentation and/or other materials provided with the distribution. 17 | - Neither the name of ARM nor the names of its contributors may be used 18 | to endorse or promote products derived from this software without 19 | specific prior written permission. 20 | * 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE 25 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. 32 | ---------------------------------------------------------------------------*/ 33 | 34 | 35 | #if defined ( __ICCARM__ ) 36 | #pragma system_include /* treat file as system include file for MISRA check */ 37 | #elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) 38 | #pragma clang system_header /* treat file as system include file */ 39 | #endif 40 | 41 | #ifndef __CORE_CMINSTR_H 42 | #define __CORE_CMINSTR_H 43 | 44 | 45 | /* ########################## Core Instruction Access ######################### */ 46 | /** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface 47 | Access to dedicated instructions 48 | @{ 49 | */ 50 | 51 | /*------------------ RealView Compiler -----------------*/ 52 | #if defined ( __CC_ARM ) 53 | #include "cmsis_armcc.h" 54 | 55 | /*------------------ ARM Compiler V6 -------------------*/ 56 | #elif defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) 57 | #include "cmsis_armcc_V6.h" 58 | 59 | /*------------------ GNU Compiler ----------------------*/ 60 | #elif defined ( __GNUC__ ) 61 | #include "cmsis_gcc.h" 62 | 63 | /*------------------ ICC Compiler ----------------------*/ 64 | #elif defined ( __ICCARM__ ) 65 | #include 66 | 67 | /*------------------ TI CCS Compiler -------------------*/ 68 | #elif defined ( __TMS470__ ) 69 | #include 70 | 71 | /*------------------ TASKING Compiler ------------------*/ 72 | #elif defined ( __TASKING__ ) 73 | /* 74 | * The CMSIS functions have been implemented as intrinsics in the compiler. 75 | * Please use "carm -?i" to get an up to date list of all intrinsics, 76 | * Including the CMSIS ones. 77 | */ 78 | 79 | /*------------------ COSMIC Compiler -------------------*/ 80 | #elif defined ( __CSMC__ ) 81 | #include 82 | 83 | #endif 84 | 85 | /*@}*/ /* end of group CMSIS_Core_InstructionInterface */ 86 | 87 | #endif /* __CORE_CMINSTR_H */ 88 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | OUTNAME = pikvm_hid 2 | 3 | IN_FLASH ?= 1 4 | DEBUG_LEVEL = 3 5 | 6 | PROJROOT = . 7 | PREFIX = arm-none-eabi- 8 | CC = $(PREFIX)gcc 9 | LD = $(PREFIX)ld 10 | AS = $(PREFIX)gcc -x assembler-with-cpp 11 | AR = $(PREFIX)ar 12 | GDB = $(PREFIX)gdb 13 | OC = $(PREFIX)objcopy 14 | OD = $(PREFIX)objdump 15 | ELFSIZE = $(PREFIX)size 16 | 17 | ifeq ($(IN_FLASH), 1) 18 | VECT_TAB_BASE = 0x08000000 19 | LINKER_SCRIPT = $(PRJ_HOME)/flash.ld 20 | else 21 | VECT_TAB_BASE = 0x20005000 22 | LINKER_SCRIPT = $(PRJ_HOME)/ram.ld 23 | endif 24 | 25 | MCPU = cortex-m3 26 | ARMTHMODE = thumb 27 | ARM_ARCH = cortexM 28 | 29 | SOC = stm32f10c8 30 | 31 | USR_DEFINE = -DSTM32F103xB 32 | 33 | 34 | PRJ_HOME = . 35 | OUT_DIR = out 36 | OUTPUT_DIR = $(PRJ_HOME)/$(OUT_DIR) 37 | 38 | MAP_FILE = $(OUTPUT_DIR)/$(OUTNAME).map 39 | SYM_FILE = $(OUTPUT_DIR)/$(OUTNAME).sym 40 | 41 | VPATH = hal \ 42 | lib \ 43 | lib/$(ARM_ARCH) \ 44 | usb/Device \ 45 | usb/Class/CDC \ 46 | usb/Class/HID \ 47 | usb/Xpd \ 48 | kernel \ 49 | app \ 50 | brd \ 51 | 52 | 53 | ASM_SRCS = $(wildcard $(PRJ_HOME)/brd/*.S) 54 | ASM_OBJS = $(patsubst $(PRJ_HOME)/brd/%.S, $(OUTPUT_DIR)/%.os, $(ASM_SRCS)) 55 | 56 | # NOTE: Keep board at the beginning 57 | C_SRCS = $(notdir $(wildcard $(PRJ_HOME)/brd/*.c)) 58 | C_SRCS += $(notdir $(wildcard $(PRJ_HOME)/hal/*.c)) 59 | C_SRCS += $(notdir $(wildcard $(PRJ_HOME)/lib/*.c)) 60 | C_SRCS += $(notdir $(wildcard $(PRJ_HOME)/lib/$(ARM_ARCH)/*.c)) 61 | C_SRCS += $(notdir $(wildcard $(PRJ_HOME)/usb/Device/*.c)) 62 | C_SRCS += $(notdir $(wildcard $(PRJ_HOME)/usb/Class/CDC/*.c)) 63 | C_SRCS += $(notdir $(wildcard $(PRJ_HOME)/usb/Class/HID/*.c)) 64 | C_SRCS += $(notdir $(wildcard $(PRJ_HOME)/usb/Xpd/*.c)) 65 | C_SRCS += $(notdir $(wildcard $(PRJ_HOME)/kernel/*.c)) 66 | C_SRCS += $(notdir $(wildcard $(PRJ_HOME)/app/*.c)) 67 | 68 | C_OBJS = $(patsubst %.c, $(OUTPUT_DIR)/%.o, $(C_SRCS)) 69 | 70 | INC_DIRS = -I include \ 71 | -I hal \ 72 | -I lib \ 73 | -I lib/$(ARM_ARCH) \ 74 | -I kernel \ 75 | -I usb/Include \ 76 | -I usb/Xpd \ 77 | -I brd \ 78 | -I app \ 79 | -I . \ 80 | 81 | 82 | COMMON_FLG = -mcpu=$(MCPU) -m$(ARMTHMODE) 83 | 84 | CCFLAGS = -g 85 | CCFLAGS += -Os -Wall -fdata-sections -ffunction-sections 86 | CCFLAGS += $(USR_DEFINE) $(INC_DIRS) 87 | CCFLAGS += $(COMMON_FLG) 88 | 89 | CFLAGS = -MMD -MP -c -g -std=c11 90 | CFLAGS += -Os -Wall -fdata-sections -ffunction-sections -nostdlib -nostartfiles 91 | CFLAGS += $(USR_DEFINE) $(INC_DIRS) 92 | CFLAGS += $(COMMON_FLG) 93 | CFLAGS += -DVECT_TAB_BASE=$(VECT_TAB_BASE) -DDEBUG_LEVEL=$(DEBUG_LEVEL) 94 | 95 | LDFLAGS = $(COMMON_FLG) -Wl,--cref,--gc-sections 96 | 97 | navilos_base = $(OUTPUT_DIR)/$(OUTNAME) 98 | navilos = $(navilos_base).axf 99 | navilos_bin = $(navilos_base).bin 100 | 101 | .PHONY: all clean run prebuild 102 | 103 | all: prebuild $(navilos) 104 | 105 | prebuild: 106 | @echo Create outout direcotry.. 107 | @[ -d $(OUT_DIR) ] || mkdir $(OUT_DIR) 108 | 109 | clean: 110 | @echo Clean.. 111 | @rm $(OUT_DIR) -Rf 112 | 113 | $(navilos): $(ASM_OBJS) $(CC_OBJS) $(C_OBJS) Makefile 114 | @echo Linking.. 115 | @echo Generate binary.. $(navilos_bin) 116 | @$(CC) $(COMMON_FLG) $(ASM_OBJS) $(CC_OBJS) $(C_OBJS) -o $(navilos) -n -T $(LINKER_SCRIPT) -Wl,-Map=$(MAP_FILE) $(LDFLAGS) 117 | @$(OD) -h -S -C -r $(navilos) > $(navilos_base).s 118 | @$(OC) -O binary $(navilos) $(navilos_bin) 119 | @$(ELFSIZE) -B $(navilos) 120 | 121 | $(OUTPUT_DIR)/%.os: %.S 122 | @echo Compile $< 123 | @$(CC) $(CFLAGS) -o $@ $< 124 | 125 | $(OUTPUT_DIR)/%.o: %.c 126 | @echo Compile $< 127 | @$(CC) $(CFLAGS) -o $@ $< 128 | 129 | -include $(patsubst %.c,$(OUTPUT_DIR)/%.d,$(C_SRCS)) 130 | 131 | -------------------------------------------------------------------------------- /lib/stdio.c: -------------------------------------------------------------------------------- 1 | /* 2 | * stdio.c 3 | * 4 | * Created on: Sep 17, 2018 5 | * Author: maanu 6 | */ 7 | 8 | #include "stdint.h" 9 | #include "stdio.h" 10 | 11 | #include "armcpu.h" 12 | #include "hal_uart.h" 13 | 14 | #define PRINTF_BUF_LEN 64 15 | 16 | #define out(c) *bf++ = c 17 | 18 | static 19 | void putch ( 20 | char *ptr, 21 | char ch 22 | ) 23 | { 24 | if (ptr) { 25 | *ptr = ch; 26 | } else { 27 | Hal_uart_fast_tx(1, ch); 28 | } 29 | } 30 | 31 | uint32_t putstr(const char* s) 32 | { 33 | uint32_t c = 0; 34 | while(*s) 35 | { 36 | Hal_uart_fast_tx(1, *s++); 37 | c++; 38 | } 39 | return c; 40 | } 41 | 42 | static 43 | int buf_printf ( char *s, int n, const char * fmt, va_list va) 44 | { 45 | char ch; 46 | unsigned int mask; 47 | unsigned int num; 48 | char buf[12]; 49 | char* bf; 50 | char* p; 51 | char* sh; 52 | char* st; 53 | char uc; 54 | char zs; 55 | 56 | sh = s; 57 | st = s + n; 58 | if (sh == 0) st = 0; 59 | 60 | while ((ch=*(fmt++))) { 61 | if (ch!='%') { 62 | putch((sh < st) ? sh++ : 0, ch); 63 | } 64 | else { 65 | char lz=0; 66 | char w =1; 67 | char hx=0; 68 | unsigned char dgt; 69 | ch=*(fmt++); 70 | if (ch=='0') { 71 | ch=*(fmt++); 72 | lz=1; 73 | } 74 | if (ch>='0' && ch<='9') { 75 | w=0; 76 | while (ch>='0' && ch<='9') { 77 | w=(((w<<2)+w)<<1)+ch-'0'; 78 | ch=*fmt++; 79 | } 80 | } 81 | bf=buf; 82 | p=bf; 83 | zs=0; 84 | switch (ch) { 85 | case 0: 86 | goto abort; 87 | 88 | case 'x': 89 | case 'X' : 90 | hx = 1; 91 | case 'u': 92 | case 'd' : 93 | num = va_arg(va, unsigned int); 94 | uc = (ch=='X') ? 'A' : 'a'; 95 | if (ch=='d' && (int)num<0) { 96 | num = -(int)num; 97 | out('-'); 98 | } 99 | if (hx) 100 | mask = 0x10000000; 101 | else 102 | mask = 1000000000; 103 | while (mask) { 104 | dgt = 0; 105 | while (num >= mask) { 106 | num -= mask; 107 | dgt++; 108 | } 109 | if (zs || dgt>0) { 110 | out(dgt+(dgt<10 ? '0' : uc-10)); 111 | zs=1; 112 | } 113 | mask = hx ? mask >> 4 : mask / 10; 114 | } 115 | if (zs == 0) out('0'); 116 | break; 117 | case 'c' : 118 | out((char)(va_arg(va, int))); 119 | break; 120 | case 's' : 121 | p=va_arg(va, char*); 122 | break; 123 | case '%' : 124 | out('%'); 125 | default: 126 | break; 127 | } 128 | *bf=0; 129 | bf=p; 130 | while (*bf++ && w > 0) 131 | w--; 132 | while (w-- > 0) 133 | putch((sh < st) ? sh++ : 0, lz ? '0' : ' '); 134 | while ((ch= *p++)) 135 | putch((sh < st) ? sh++ : 0, ch); 136 | } 137 | } 138 | if (sh < st) { 139 | *sh = 0; 140 | } 141 | 142 | abort:; 143 | 144 | return sh - s; 145 | } 146 | 147 | uint32_t snprintf(char* buf, int n, const char* format, ...) 148 | { 149 | uint32_t ret; 150 | va_list args; 151 | va_start (args, format); 152 | ret = buf_printf (buf, n, format, args); 153 | va_end (args); 154 | return ret; 155 | } 156 | 157 | uint32_t dbg_printf(uint8_t level, const char* format, ...) 158 | { 159 | char printf_buf[PRINTF_BUF_LEN] = {0}; 160 | 161 | if (level > DEBUG_LEVEL) { 162 | return 0; 163 | } 164 | 165 | va_list args; 166 | va_start (args, format); 167 | buf_printf (printf_buf, PRINTF_BUF_LEN, format, args); 168 | va_end (args); 169 | 170 | return putstr (printf_buf); 171 | } 172 | 173 | uint32_t utoa(char* buf, uint32_t val, utoa_t base) 174 | { 175 | uint32_t c = 0; 176 | int32_t idx = 0; 177 | char tmp[11]; // It is big enough for store 32 bit int 178 | 179 | do { 180 | uint32_t t = val % (uint32_t)base; 181 | if (t >= 10) 182 | { 183 | t += 'A' - '0' - 10; 184 | } 185 | tmp[idx] = (t + '0'); 186 | val /= base; 187 | idx++; 188 | } while(val); 189 | 190 | // reverse 191 | idx--; 192 | while (idx >= 0) 193 | { 194 | buf[c++] = tmp[idx]; 195 | idx--; 196 | } 197 | 198 | return c; 199 | } 200 | -------------------------------------------------------------------------------- /hal/stm32f1xx_hal_pcd_ex.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32f1xx_hal_pcd_ex.h 4 | * @author MCD Application Team 5 | * @version V1.1.1 6 | * @date 12-May-2017 7 | * @brief Header file of Extended PCD HAL module. 8 | ****************************************************************************** 9 | * @attention 10 | * 11 | *

© COPYRIGHT(c) 2016 STMicroelectronics

12 | * 13 | * Redistribution and use in source and binary forms, with or without modification, 14 | * are permitted provided that the following conditions are met: 15 | * 1. Redistributions of source code must retain the above copyright notice, 16 | * this list of conditions and the following disclaimer. 17 | * 2. Redistributions in binary form must reproduce the above copyright notice, 18 | * this list of conditions and the following disclaimer in the documentation 19 | * and/or other materials provided with the distribution. 20 | * 3. Neither the name of STMicroelectronics nor the names of its contributors 21 | * may be used to endorse or promote products derived from this software 22 | * without specific prior written permission. 23 | * 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 27 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 33 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | * 35 | ****************************************************************************** 36 | */ 37 | 38 | /* Define to prevent recursive inclusion -------------------------------------*/ 39 | #ifndef __STM32F1xx_HAL_PCD_EX_H 40 | #define __STM32F1xx_HAL_PCD_EX_H 41 | 42 | #ifdef __cplusplus 43 | extern "C" { 44 | #endif 45 | 46 | #if defined(STM32F102x6) || defined(STM32F102xB) || \ 47 | defined(STM32F103x6) || defined(STM32F103xB) || \ 48 | defined(STM32F103xE) || defined(STM32F103xG) || \ 49 | defined(STM32F105xC) || defined(STM32F107xC) 50 | 51 | /* Includes ------------------------------------------------------------------*/ 52 | #include "stm32f1xx_hal_def.h" 53 | 54 | /** @addtogroup STM32F1xx_HAL_Driver 55 | * @{ 56 | */ 57 | 58 | /** @addtogroup PCDEx 59 | * @{ 60 | */ 61 | 62 | /* Exported types ------------------------------------------------------------*/ 63 | /* Exported constants --------------------------------------------------------*/ 64 | /* Exported macros -----------------------------------------------------------*/ 65 | /* Exported functions --------------------------------------------------------*/ 66 | /** @addtogroup PCDEx_Exported_Functions PCDEx Exported Functions 67 | * @{ 68 | */ 69 | /** @addtogroup PCDEx_Exported_Functions_Group1 Peripheral Control functions 70 | * @{ 71 | */ 72 | #if defined (USB_OTG_FS) 73 | HAL_StatusTypeDef HAL_PCDEx_SetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo, uint16_t size); 74 | HAL_StatusTypeDef HAL_PCDEx_SetRxFiFo(PCD_HandleTypeDef *hpcd, uint16_t size); 75 | #endif /* USB_OTG_FS */ 76 | 77 | #if defined (USB) 78 | HAL_StatusTypeDef HAL_PCDEx_PMAConfig(PCD_HandleTypeDef *hpcd, 79 | uint16_t ep_addr, 80 | uint16_t ep_kind, 81 | uint32_t pmaadress); 82 | #endif /* USB */ 83 | /** 84 | * @} 85 | */ 86 | 87 | /** @addtogroup PCDEx_Exported_Functions_Group2 Peripheral State functions 88 | * @{ 89 | */ 90 | void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state); 91 | /** 92 | * @} 93 | */ 94 | /** 95 | * @} 96 | */ 97 | /** 98 | * @} 99 | */ 100 | 101 | /** 102 | * @} 103 | */ 104 | #endif /* STM32F102x6 || STM32F102xB || */ 105 | /* STM32F103x6 || STM32F103xB || */ 106 | /* STM32F103xE || STM32F103xG || */ 107 | /* STM32F105xC || STM32F107xC */ 108 | 109 | #ifdef __cplusplus 110 | } 111 | #endif 112 | 113 | 114 | #endif /* __STM32F1xx_HAL_PCD_EX_H */ 115 | 116 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 117 | -------------------------------------------------------------------------------- /script/hid_test.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import serial 3 | import time 4 | from ctypes import * 5 | 6 | class MS_HID_PKT (Structure): 7 | _pack_ = 1 8 | _fields_ = [ 9 | ('btn', c_uint8), 10 | ('x', c_uint16), 11 | ('y', c_uint16), 12 | ('s', c_uint16), 13 | ] 14 | 15 | kb_sym_key_map = { 16 | '!': 0x11E, 17 | '@': 0x11F, 18 | '#': 0x120, 19 | '$': 0x121, 20 | '%': 0x122, 21 | '^': 0x123, 22 | '&': 0x124, 23 | '*': 0x125, 24 | '(': 0x126, 25 | ')': 0x127, 26 | '0': 0x27, 27 | '\n': 0x28, 28 | '\r': 0x28, 29 | '\b': 0x2A, 30 | '\t': 0x2B, 31 | ' ': 0x2C, 32 | '_': 0x12D, 33 | '-': 0x2D, 34 | '+': 0x12E, 35 | '=': 0x2E, 36 | '{': 0x12F, 37 | '[': 0x2F, 38 | '}': 0x130, 39 | ']': 0x30, 40 | '|': 0x131, 41 | '\\': 0x31, 42 | ':': 0x133, 43 | ';': 0x33, 44 | '"': 0x134, 45 | '\'': 0x34, 46 | '~': 0x135, 47 | '`': 0x35, 48 | '<': 0x136, 49 | ',': 0x36, 50 | '>': 0x137, 51 | '.': 0x37, 52 | '?': 0x138, 53 | '/': 0x38, 54 | } 55 | 56 | def ascii_to_hid(ch): 57 | shift = 0 58 | c = ch.encode()[0] 59 | if (c >= ord('A')) and (c <= ord('Z')): 60 | c = ord('a') + (c - ord('A')) 61 | shift = 0x100 62 | 63 | if (c >= ord('a')) and (c <= ord('z')): 64 | c = c - ord('a') 65 | return (c + 4) | shift 66 | 67 | if (c >= ord('1')) and (c <= ord('9')): 68 | c = c - ord('0') 69 | return c + 0x1d 70 | return kb_sym_key_map[chr(c)] 71 | 72 | def str_to_kb_hid(keystr): 73 | grp_list = [] 74 | 75 | keys = bytearray() 76 | shift = 0 77 | sep = False 78 | for ch in keystr + '\x00': 79 | shift_next = shift 80 | if ch == '\x00': 81 | sep = True 82 | else: 83 | key = ascii_to_hid(ch) 84 | if (key & 0x100) != shift: 85 | shift_next = key & 0x100 86 | sep = True 87 | if len(keys) >= 6: 88 | sep = True 89 | if sep: 90 | grp_list.append((b'\x02' if shift else b'\x00') + b'\x00' + bytearray(keys)) 91 | keys = bytearray() 92 | sep = False 93 | keys.append (key & 0xff) 94 | shift = shift_next 95 | return grp_list 96 | 97 | 98 | def swap16(x): 99 | return ((x & 0xff) << 8) + ((x >> 8) & 0xff) 100 | 101 | 102 | class KVM_HID: 103 | def __init__(self, comport): 104 | self.ser = serial.Serial(comport, 115200, timeout=0) 105 | 106 | def wait_rsp(self): 107 | data_str = '' 108 | loop = 0 109 | while loop < 100: 110 | if (self.ser.inWaiting() > 0): 111 | data_str += self.ser.read(self.ser.inWaiting()).decode('ascii') 112 | if '\r' in data_str or '\n' in data_str: 113 | break 114 | time.sleep(0.01) 115 | loop += 1 116 | return data_str 117 | 118 | 119 | def send_hid_kb_pkt (self, keystr): 120 | self.ser.write(b'@%s\r' % keystr) 121 | rsp1 = self.wait_rsp() 122 | self.ser.write(b'@\x00\x00\r') 123 | rsp2 = self.wait_rsp() 124 | if '$OK' in rsp1 and '$OK' in rsp2: 125 | return 0 126 | else: 127 | return 1 128 | 129 | def send_hid_ms_pkt (self, data): 130 | self.ser.write(b'#%s\r' % bytearray(data)) 131 | rsp = self.wait_rsp() 132 | if '$OK' in rsp: 133 | return 0 134 | else: 135 | return 1 136 | 137 | def main (): 138 | if len(sys.argv) < 2: 139 | print ('Usage:\n python %s serial_device\n' % sys.argv[0]) 140 | return 1 141 | 142 | cont = True 143 | comport = sys.argv[1] 144 | hid = KVM_HID (comport) 145 | 146 | time.sleep(0.1) 147 | 148 | # send "dir" keys to keyboard 149 | if 1: 150 | key_str = 'dir\n' 151 | key_list = str_to_kb_hid(key_str) 152 | for keys in key_list: 153 | if hid.send_hid_kb_pkt (keys): 154 | raise Exception ('Failed to send keyboard HID packet !') 155 | 156 | # move mouse 157 | ms_hid = MS_HID_PKT() 158 | ms_hid.btn = 0 159 | ms_hid.x = 1 160 | ms_hid.y = 1 161 | ms_hid.s = 0 162 | for i in range(4): 163 | ms_hid.x = 1000 + (i & 1) * 4000 164 | ms_hid.y = 1000 + (i >> 1) * 4000 165 | if hid.send_hid_ms_pkt (ms_hid): 166 | raise Exception ('Failed to send mouse HID packet !') 167 | time.sleep (.5) 168 | 169 | if __name__ == '__main__': 170 | sys.exit(main()) 171 | -------------------------------------------------------------------------------- /usb/Include/private/usbd_msc_private.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file usbd_msc_private.h 4 | * @author Benedek Kupper 5 | * @version 0.1 6 | * @date 2018-03-25 7 | * @brief Universal Serial Bus Mass Storage Class 8 | * Private cross-domain functions header 9 | * 10 | * Copyright (c) 2018 Benedek Kupper 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the "License"); 13 | * you may not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * http://www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an "AS IS" BASIS, 20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | #ifndef __USBD_MSC_PRIVATE_H_ 25 | #define __USBD_MSC_PRIVATE_H_ 26 | 27 | #ifdef __cplusplus 28 | extern "C" 29 | { 30 | #endif 31 | 32 | #include 33 | 34 | /** @ingroup USBD_MSC 35 | * @defgroup USBD_MSC_Private_Types MSC Private Types 36 | * @{ */ 37 | 38 | /** @brief SCSI/UFI commands */ 39 | typedef enum 40 | { 41 | SCSI_FORMAT_UNIT = 0x04, 42 | SCSI_INQUIRY = 0x12, 43 | SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL = 0x1E, 44 | SCSI_REQUEST_SENSE = 0x03, 45 | SCSI_START_STOP_UNIT = 0x1B, 46 | SCSI_TEST_UNIT_READY = 0x00, 47 | SCSI_SEND_DIAGNOSTIC = 0x1D, 48 | SCSI_READ_FORMAT_CAPACITIES = 0x23, 49 | 50 | SCSI_READ_CAPACITY10 = 0x25, 51 | SCSI_READ_CAPACITY16 = 0x9E, 52 | 53 | SCSI_MODE_SELECT6 = 0x15, 54 | SCSI_MODE_SELECT10 = 0x55, 55 | 56 | SCSI_MODE_SENSE6 = 0x1A, 57 | SCSI_MODE_SENSE10 = 0x5A, 58 | 59 | SCSI_READ6 = 0x08, 60 | SCSI_READ10 = 0x28, 61 | SCSI_READ12 = 0xA8, 62 | SCSI_READ16 = 0x88, 63 | 64 | SCSI_WRITE6 = 0x0A, 65 | SCSI_WRITE10 = 0x2A, 66 | SCSI_WRITE12 = 0xAA, 67 | SCSI_WRITE16 = 0x8A, 68 | 69 | SCSI_VERIFY10 = 0x2F, 70 | SCSI_VERIFY12 = 0xAF, 71 | SCSI_VERIFY16 = 0x8F, 72 | }USBD_SCSI_OperationCodeType; 73 | 74 | /** @brief SCSI Sense Keys */ 75 | typedef enum 76 | { 77 | SCSI_SKEY_NO_SENSE = 0, 78 | SCSI_SKEY_RECOVERED_ERROR = 1, 79 | SCSI_SKEY_NOT_READY = 2, 80 | SCSI_SKEY_MEDIUM_ERROR = 3, 81 | SCSI_SKEY_HARDWARE_ERROR = 4, 82 | SCSI_SKEY_ILLEGAL_REQUEST = 5, 83 | SCSI_SKEY_UNIT_ATTENTION = 6, 84 | SCSI_SKEY_DATA_PROTECT = 7, 85 | SCSI_SKEY_BLANK_CHECK = 8, 86 | SCSI_SKEY_VENDOR_SPECIFIC = 9, 87 | SCSI_SKEY_COPY_ABORTED = 10, 88 | SCSI_SKEY_ABORTED_COMMAND = 11, 89 | SCSI_SKEY_VOLUME_OVERFLOW = 13, 90 | SCSI_SKEY_MISCOMPARE = 14, 91 | }USBD_SCSI_SenseKeyType; 92 | 93 | /** @brief SCSI Additional Sense Codes */ 94 | typedef enum 95 | { 96 | SCSI_ASC_INVALID_CDB = 0x20, 97 | SCSI_ASC_INVALID_FIELD_IN_COMMAND = 0x24, 98 | SCSI_ASC_PARAMETER_LIST_LENGTH_ERROR = 0x1A, 99 | SCSI_ASC_ADDRESS_OUT_OF_RANGE = 0x21, 100 | SCSI_ASC_MEDIUM_NOT_PRESENT = 0x3A, 101 | SCSI_ASC_MEDIUM_HAVE_CHANGED = 0x28, 102 | SCSI_ASC_WRITE_PROTECTED = 0x27, 103 | SCSI_ASC_UNRECOVERED_READ_ERROR = 0x11, 104 | SCSI_ASC_WRITE_FAULT = 0x03, 105 | }USBD_SCSI_AddSenseCodeType; 106 | 107 | /** @} */ 108 | 109 | const USBD_MSC_LUType* MSC_GetLU (USBD_MSC_IfHandleType *itf, 110 | uint8_t lunIndex); 111 | 112 | void SCSI_ProcessCommand (USBD_MSC_IfHandleType *itf); 113 | USBD_ReturnType SCSI_ProcessRead (USBD_MSC_IfHandleType *itf); 114 | USBD_ReturnType SCSI_ProcessWrite (USBD_MSC_IfHandleType *itf); 115 | 116 | void SCSI_PutSenseCode (USBD_MSC_IfHandleType *itf, 117 | USBD_SCSI_SenseKeyType skey, 118 | USBD_SCSI_AddSenseCodeType asc); 119 | 120 | 121 | #ifdef __cplusplus 122 | } 123 | #endif 124 | 125 | #endif /* __USBD_MSC_PRIVATE_H_ */ 126 | -------------------------------------------------------------------------------- /usb/Include/usbd_ncm.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file usbd_ncm.h 4 | * @author Benedek Kupper 5 | * @version 0.1 6 | * @date 2018-06-02 7 | * @brief USB CDC Network Control Model 8 | * 9 | * Copyright (c) 2018 Benedek Kupper 10 | * 11 | * Licensed under the Apache License, Version 2.0 (the "License"); 12 | * you may not use this file except in compliance with the License. 13 | * You may obtain a copy of the License at 14 | * 15 | * http://www.apache.org/licenses/LICENSE-2.0 16 | * 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | */ 23 | #ifndef __USBD_NCM_H 24 | #define __USBD_NCM_H 25 | 26 | #ifdef __cplusplus 27 | extern "C" 28 | { 29 | #endif 30 | 31 | #include 32 | #include 33 | 34 | /** @ingroup USBD 35 | * @addtogroup USBD_Class USBD Classes 36 | * @{ */ 37 | 38 | /** @defgroup USBD_NCM Network Control Model (NCM) 39 | * @{ */ 40 | 41 | /** @defgroup USBD_NCM_Exported_Macros NCM Exported Macros 42 | * @{ */ 43 | 44 | #ifndef USBD_NCM_MAX_OUT_SIZE 45 | #define USBD_NCM_MAX_OUT_SIZE 2048 46 | #endif 47 | #ifndef USBD_NCM_MAX_IN_SIZE 48 | #define USBD_NCM_MAX_IN_SIZE 2048 49 | #endif 50 | 51 | /** @} */ 52 | 53 | /** @defgroup USBD_NCM_Exported_Types NCM Exported Types 54 | * @{ */ 55 | 56 | 57 | /** @brief Network (MAC) address type */ 58 | typedef uint8_t USBD_NCM_NetAddressType[6]; 59 | 60 | 61 | /** @brief CDC application structure */ 62 | typedef struct 63 | { 64 | const char* Name; /*!< String description of the application */ 65 | 66 | const USBD_NCM_NetAddressType* NetAddress; /*!< Fixed MAC address */ 67 | 68 | void (*Init) (void* itf);/*!< Initialization request */ 69 | 70 | void (*Deinit) (void* itf);/*!< Shutdown request */ 71 | 72 | void (*Received) (void* itf);/*!< Received datagrams available */ 73 | 74 | }USBD_NCM_AppType; 75 | 76 | 77 | /** @brief NCM interface configuration */ 78 | typedef struct 79 | { 80 | uint8_t OutEpNum; /*!< OUT endpoint address */ 81 | uint8_t InEpNum; /*!< IN endpoint address */ 82 | uint8_t NotEpNum; /*!< Notification endpoint address */ 83 | }USBD_NCM_ConfigType; 84 | 85 | 86 | /** @brief NCM class interface structure */ 87 | typedef struct 88 | { 89 | USBD_IfHandleType Base; /*!< Class-independent interface base */ 90 | const USBD_NCM_AppType* App; /*!< NCM application reference */ 91 | USBD_NCM_ConfigType Config; /*!< NCM interface configuration */ 92 | USBD_PADDING_1(); 93 | 94 | /* NCM class internal context */ 95 | struct { 96 | USBD_CDC_NotifyHeaderType SpeedChange; 97 | USBD_CDC_SpeedChangeType SpeedData; 98 | USBD_CDC_NotifyHeaderType Connection; 99 | }Notify; /*!< NCM message buffer for notifications */ 100 | 101 | struct { 102 | uint32_t Data[2][USBD_NCM_MAX_OUT_SIZE / sizeof(uint32_t)]; 103 | void* PT; 104 | uint8_t Page; 105 | uint8_t Dx; 106 | volatile uint8_t State[2]; 107 | }Out; /*!< Received NTB status and double buffer */ 108 | 109 | struct { 110 | uint32_t Data[2][USBD_NCM_MAX_IN_SIZE / sizeof(uint32_t)]; 111 | uint32_t MaxSize; 112 | uint32_t RemSize; 113 | uint16_t Index; 114 | uint8_t Page; 115 | uint8_t DgCount; 116 | volatile uint8_t SendState; 117 | volatile uint8_t FillState; 118 | }In; /*!< Transmit NTB status and double buffer */ 119 | }USBD_NCM_IfHandleType; 120 | 121 | /** @} */ 122 | 123 | /** @addtogroup USBD_NCM_Exported_Functions 124 | * @{ */ 125 | USBD_ReturnType USBD_NCM_MountInterface (USBD_NCM_IfHandleType *itf, 126 | USBD_HandleType *dev); 127 | 128 | USBD_ReturnType USBD_NCM_Connect (USBD_NCM_IfHandleType *itf, 129 | uint32_t bitrate); 130 | 131 | USBD_ReturnType USBD_NCM_Disconnect (USBD_NCM_IfHandleType *itf); 132 | 133 | uint8_t* USBD_NCM_GetDatagram (USBD_NCM_IfHandleType *itf, 134 | uint16_t *length); 135 | 136 | uint8_t* USBD_NCM_AllocDatagram (USBD_NCM_IfHandleType *itf, 137 | uint16_t length); 138 | USBD_ReturnType USBD_NCM_SetDatagram (USBD_NCM_IfHandleType *itf); 139 | 140 | USBD_ReturnType USBD_NCM_PutDatagram (USBD_NCM_IfHandleType *itf, 141 | uint8_t *data, 142 | uint16_t length); 143 | /** @} */ 144 | 145 | /** @} */ 146 | 147 | /** @} */ 148 | 149 | #ifdef __cplusplus 150 | } 151 | #endif 152 | 153 | #endif /* __USBD_NCM_H */ 154 | -------------------------------------------------------------------------------- /usb/Device/usbd_if.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file usbd_if.c 4 | * @author Benedek Kupper 5 | * @version 0.1 6 | * @date 2018-01-31 7 | * @brief Universal Serial Bus Device Driver 8 | * Device interface management 9 | * 10 | * Copyright (c) 2018 Benedek Kupper 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the "License"); 13 | * you may not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * http://www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an "AS IS" BASIS, 20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | #include 25 | 26 | /** @ingroup USBD_Private 27 | * @defgroup USBD_Private_Functions_If USBD Interface Management 28 | * @{ */ 29 | 30 | /** 31 | * @brief This function changes the active device configuration. 32 | * @param dev: USB Device handle reference 33 | * @param cfgNum: New configuration selector index 34 | */ 35 | void USBD_IfConfig(USBD_HandleType *dev, uint8_t cfgNum) 36 | { 37 | if (dev->ConfigSelector != cfgNum) 38 | { 39 | uint8_t ifNum; 40 | 41 | /* Clear any previously selected config */ 42 | if (dev->ConfigSelector != 0) 43 | { 44 | for (ifNum = 0; ifNum < dev->IfCount; ifNum++) 45 | { 46 | USBD_IfClass_Deinit(dev->IF[ifNum]); 47 | dev->IF[ifNum]->AltSelector = 0; 48 | } 49 | } 50 | 51 | /* Update configuration index */ 52 | dev->ConfigSelector = cfgNum; 53 | 54 | /* Set the new selected valid config */ 55 | if (dev->ConfigSelector != 0) 56 | { 57 | for (ifNum = 0; ifNum < dev->IfCount; ifNum++) 58 | { 59 | USBD_IfClass_Init(dev->IF[ifNum]); 60 | } 61 | } 62 | } 63 | } 64 | 65 | /** @} */ 66 | 67 | /** @addtogroup USBD_Private_Functions_Desc 68 | * @{ */ 69 | 70 | /** 71 | * @brief This function provides the string of the interface 72 | * which is selected by the setup request. 73 | * @param dev: USB Device handle reference 74 | * @return Reference to the interface's string, or NULL if not available 75 | */ 76 | const char* USBD_IfString(USBD_HandleType *dev) 77 | { 78 | uint8_t ifNum = ((uint8_t)dev->Setup.Value & 0xF) - USBD_ISTR_INTERFACES; 79 | uint8_t intNum = ((uint8_t)dev->Setup.Value >> 4); 80 | USBD_IfHandleType *itf = dev->IF[ifNum]; 81 | const char* str = NULL; 82 | 83 | if (ifNum < dev->IfCount) 84 | { 85 | str = USBD_IfClass_GetString(itf, intNum); 86 | } 87 | 88 | return str; 89 | } 90 | 91 | /** @} */ 92 | 93 | /** @addtogroup USBD_Private_Functions_Ctrl 94 | * @{ */ 95 | 96 | /** 97 | * @brief Processes the interface request. 98 | * @param dev: USB Device handle reference 99 | * @return OK if the request is processed, INVALID if not supported 100 | */ 101 | USBD_ReturnType USBD_IfRequest(USBD_HandleType *dev) 102 | { 103 | USBD_ReturnType retval = USBD_E_INVALID; 104 | uint8_t ifNum = (uint8_t)dev->Setup.Index; 105 | USBD_IfHandleType *itf = dev->IF[ifNum]; 106 | 107 | if ((dev->ConfigSelector == 0) || (ifNum >= dev->IfCount)) 108 | { 109 | /* Configured and valid indexed interfaces only */ 110 | } 111 | else if (dev->Setup.RequestType.Type == USB_REQ_TYPE_STANDARD) 112 | { 113 | switch (dev->Setup.Request) 114 | { 115 | /* Current alternate setting of the IF */ 116 | case USB_REQ_GET_INTERFACE: 117 | { 118 | retval = USBD_CtrlSendData(dev, 119 | &itf->AltSelector, sizeof(itf->AltSelector)); 120 | break; 121 | } 122 | 123 | /* Set alternate setting of the IF */ 124 | case USB_REQ_SET_INTERFACE: 125 | { 126 | uint8_t altSel = (uint8_t)dev->Setup.Value; 127 | 128 | /* Check validity */ 129 | if (itf->AltCount > altSel) 130 | { 131 | /* Deinit previous AS */ 132 | USBD_IfClass_Deinit(itf); 133 | 134 | itf->AltSelector = altSel; 135 | 136 | /* Init with new AS */ 137 | USBD_IfClass_Init(itf); 138 | 139 | retval = USBD_E_OK; 140 | } 141 | break; 142 | } 143 | 144 | default: 145 | { 146 | /* forward the request to the IF */ 147 | retval = USBD_IfClass_SetupStage(itf); 148 | break; 149 | } 150 | } 151 | } 152 | else 153 | { 154 | /* forward the request to the IF */ 155 | retval = USBD_IfClass_SetupStage(itf); 156 | } 157 | 158 | return retval; 159 | } 160 | 161 | /** @} */ 162 | -------------------------------------------------------------------------------- /usb/README.md: -------------------------------------------------------------------------------- 1 | # Composite USB Device library 2 | 3 | This project implements a platform-independent, highly flexible USB Device software framework, 4 | which allows you to create a full-feature USB 2.0 device firmware 5 | with multiple independent interfaces. 6 | 7 | ## Features 8 | 9 | * Effective compliance to USB 2.0 specification 10 | * Interfaces are independent of the device and can be added or removed in runtime 11 | * Interface classes support multiple instantiation 12 | * All USB descriptors are created internally (no need for user definition) 13 | * Code size optimized for resource-constrained systems 14 | * Platform-independent stack 15 | * A console interface template provides zero-effort implementation for standard I/O through a CDC serial port 16 | 17 | ### Supported device classes 18 | 19 | * Communications Device Class (**CDC** - ACM) specification version 1.10 20 | * Network Control Model (CDC - **NCM**) specification version 1.0 21 | * Human Interface Device Class (**HID**) specification version 1.11 - with helper macros for report definition 22 | * Mass Storage Class Bulk-Only Transport (**MSC** - BOT) revision 1.0 with transparent SCSI command set 23 | * Device Firmware Upgrade Class (**DFU**) specification version 1.1 24 | (or DFU STMicroelectronics Extension [(DFUSE)][DFUSE] 1.1A 25 | using `USBD_DFU_ST_EXTENSION` compile switch) 26 | 27 | ## Contents 28 | 29 | The project consists of the followings: 30 | * The USB 2.0 device framework is located in the **Device** folder. 31 | * Common USB classes are implemented as part of the project, under the **Class** folder. 32 | * The *Templates* folder contains `usbd_config.h` configuration file and various example files. 33 | * The *Doc* folder contains a prepared *doxyfile* for Doxygen documentation generation. 34 | 35 | ## Platform support 36 | 37 | Currently the following hardware platforms are supported: 38 | - STMicroelectronics [STM32][STM32] using the [STM32_XPD][STM32_XPD] peripheral drivers 39 | or the STM32CubeMX package with [this wrapper project][USBDevice4Cube] 40 | 41 | ## Basis of operation 42 | 43 | The interface implementations are completely separated from the USB device control. 44 | Each of them should use its class-specific API from `usbd_.h`. 45 | There are only two steps to mount an interface to a device: 46 | 47 | 1. Setting the interface's endpoint addresses; 48 | 2. Cross-referencing the interface and the device with a `USBD__MountInterface()` call. 49 | 50 | The interfaces are added to the device configuration in the order of the mount calls. 51 | It is possible to change the active interfaces during runtime by unmounting all and mounting the new ones. 52 | The only requirement is that the device has to be logically disconnected from the host when it is done. 53 | 54 | The device control of the library is limited to the global state management 55 | using the public API in *usbd.h*. The bulk of the device operation is servicing 56 | the device peripheral events: 57 | - USB Reset signal on bus -> `USBD_ResetCallback()` 58 | - USB control pipe setup request received -> `USBD_SetupCallback()` 59 | - USB endpoint data transfer completed -> `USBD_EpInCallback()` or `USBD_EpOutCallback()` 60 | 61 | The USBD handles are used as a shared management structure for both this stack 62 | and the peripheral driver. Any additional fields that the peripheral driver requires 63 | can be defined in the driver-specific *usbd_pd_def.h* header, while the *usbd_types.h* shall 64 | be included by the driver. 65 | 66 | ## Example Projects 67 | 68 | ### [IP over USB][IPoverUSB] 69 | 70 | A virtual network with a single lwIP server (DNS, DHCP, HTTP) is presented by the device 71 | (as a network adapter). Composite USB device demonstrating the CDC-NCM function usage 72 | and a reduced DFU interface to enter ROM bootloader. 73 | 74 | ### [DfuBootloader][DfuBootloader] 75 | 76 | A generic USB device bootloader firmware for STM32 controllers. 77 | USB device with a single DFU interface 78 | which is mountable on both the bootloader's and the application's device stack. 79 | 80 | ### [DebugDongle][DebugDongle] 81 | 82 | A debug serial port with selectable output power and battery charging. 83 | Composite USB device with one CDC (serial port), 84 | two HID interfaces (onboard sensors and power management) 85 | and the bootloader's DFU interface. 86 | 87 | ### [CanDybug][CanDybug] 88 | 89 | A CAN bus gateway which uses a custom protocol over a USB serial port emulation. 90 | Composite USB device with CDC-ACM function and the bootloader's DFU interface. 91 | 92 | ## How to contribute 93 | 94 | This project is free to use for everyone as long as the license terms are met. 95 | Any found defects or suggestions should be reported as a GitHub issue. 96 | Improvements in the form of pull requests are also welcome. 97 | 98 | ## Authors 99 | 100 | * **Benedek Kupper** - [IntergatedCircuits](https://github.com/IntergatedCircuits) 101 | 102 | [CanDybug]: https://github.com/IntergatedCircuits/CanDybugFW 103 | [DebugDongle]: https://github.com/IntergatedCircuits/DebugDongleFW 104 | [DfuBootloader]: https://github.com/IntergatedCircuits/DfuBootloader 105 | [DFUSE]: http://www.st.com/resource/en/application_note/cd00264379.pdf 106 | [IPoverUSB]: https://github.com/IntergatedCircuits/IPoverUSB 107 | [STM32]: http://www.st.com/en/microcontrollers/stm32-32-bit-arm-cortex-mcus.html 108 | [STM32_XPD]: https://github.com/IntergatedCircuits/STM32_XPD 109 | [USBDevice4Cube]: https://github.com/IntergatedCircuits/USBDevice4Cube 110 | -------------------------------------------------------------------------------- /usb/Include/private/usbd_private.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file usbd_private.h 4 | * @author Benedek Kupper 5 | * @version 0.1 6 | * @date 2018-01-31 7 | * @brief Universal Serial Bus Device Driver 8 | * Private cross-domain functions header 9 | * 10 | * Copyright (c) 2018 Benedek Kupper 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the "License"); 13 | * you may not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * http://www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an "AS IS" BASIS, 20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | #ifndef __USBD_PRIVATE_H_ 25 | #define __USBD_PRIVATE_H_ 26 | 27 | #ifdef __cplusplus 28 | extern "C" 29 | { 30 | #endif 31 | 32 | #include 33 | 34 | /* {function definition} <- {call site} */ 35 | 36 | /* usbd <- usbd_ctrl */ 37 | USBD_ReturnType USBD_DevRequest (USBD_HandleType *dev); 38 | 39 | /* usbd_ctrl <- usbd_ep */ 40 | void USBD_CtrlInCallback (USBD_HandleType *dev); 41 | void USBD_CtrlOutCallback (USBD_HandleType *dev); 42 | 43 | /* usbd_if <- usbd_ctrl */ 44 | USBD_ReturnType USBD_IfRequest (USBD_HandleType *dev); 45 | 46 | /* usbd_if <- usbd */ 47 | void USBD_IfConfig (USBD_HandleType *dev, 48 | uint8_t cfgNum); 49 | 50 | /* usbd_if <- usbd_desc */ 51 | const char* USBD_IfString (USBD_HandleType *dev); 52 | 53 | /* usbd_ep <- usbd_ctrl */ 54 | USBD_ReturnType USBD_EpRequest (USBD_HandleType *dev); 55 | 56 | /* usbd_desc <- usbd */ 57 | USBD_ReturnType USBD_GetDescriptor (USBD_HandleType *dev); 58 | 59 | /** @ingroup USBD 60 | * @defgroup USBD_Private_Functions_IfClass USBD Class-specific Interface Callouts 61 | * @brief These functions simply call the class-specific function pointer 62 | * @{ */ 63 | 64 | /** 65 | * @brief Calls the interface's class specific 66 | * @ref USBD_ClassType::GetDescriptor function. 67 | * @param itf: reference of the interface 68 | * @param ifNum: the interface index in the device 69 | * @param dest: destination buffer pointer 70 | * @return Length of the descriptor 71 | */ 72 | static inline uint16_t USBD_IfClass_GetDesc( 73 | USBD_IfHandleType *itf, uint8_t ifNum, uint8_t *dest) 74 | { 75 | if (itf->Class->GetDescriptor != NULL) 76 | { return itf->Class->GetDescriptor(itf, ifNum, dest); } 77 | else 78 | { return 0; } 79 | } 80 | 81 | /** 82 | * @brief Calls the interface's class specific 83 | * @ref USBD_ClassType::GetString function. 84 | * @param itf: reference of the interface 85 | * @param intNum: the interface-internal string index 86 | * @return String reference 87 | */ 88 | static inline const char* USBD_IfClass_GetString( 89 | USBD_IfHandleType *itf, uint8_t intNum) 90 | { 91 | if (itf->Class->GetString == NULL) 92 | { return (const char*)NULL; } 93 | else 94 | { return itf->Class->GetString(itf, intNum); } 95 | } 96 | 97 | /** 98 | * @brief Calls the interface's class specific 99 | * @ref USBD_ClassType::Init function. 100 | * @param itf: reference of the interface 101 | */ 102 | static inline void USBD_IfClass_Init( 103 | USBD_IfHandleType *itf) 104 | { 105 | USBD_SAFE_CALLBACK(itf->Class->Init, itf); 106 | } 107 | 108 | /** 109 | * @brief Calls the interface's class specific 110 | * @ref USBD_ClassType::Deinit function. 111 | * @param itf: reference of the interface 112 | */ 113 | static inline void USBD_IfClass_Deinit( 114 | USBD_IfHandleType *itf) 115 | { 116 | USBD_SAFE_CALLBACK(itf->Class->Deinit, itf); 117 | } 118 | 119 | /** 120 | * @brief Calls the interface's class specific 121 | * @ref USBD_ClassType::SetupStage function. 122 | * @param itf: reference of the interface 123 | * @return Return value of the function call 124 | */ 125 | static inline USBD_ReturnType USBD_IfClass_SetupStage( 126 | USBD_IfHandleType *itf) 127 | { 128 | if (itf->Class->SetupStage == NULL) 129 | { return USBD_E_INVALID; } 130 | else 131 | { return itf->Class->SetupStage(itf); } 132 | } 133 | 134 | /** 135 | * @brief Calls the interface's class specific 136 | * @ref USBD_ClassType::DataStage function. 137 | * @param itf: reference of the interface 138 | */ 139 | static inline void USBD_IfClass_DataStage( 140 | USBD_IfHandleType *itf) 141 | { 142 | USBD_SAFE_CALLBACK(itf->Class->DataStage, itf); 143 | } 144 | 145 | /** 146 | * @brief Calls the interface's class specific 147 | * @ref USBD_ClassType::InData function. 148 | * @param itf: reference of the interface 149 | * @param ep: reference of the endpoint 150 | */ 151 | static inline void USBD_IfClass_InData( 152 | USBD_IfHandleType *itf, USBD_EpHandleType *ep) 153 | { 154 | USBD_SAFE_CALLBACK(itf->Class->InData, itf, ep); 155 | } 156 | 157 | /** 158 | * @brief Calls the interface's class specific 159 | * @ref USBD_ClassType::OutData function. 160 | * @param itf: reference of the interface 161 | * @param ep: reference of the endpoint 162 | */ 163 | static inline void USBD_IfClass_OutData( 164 | USBD_IfHandleType *itf, USBD_EpHandleType *ep) 165 | { 166 | USBD_SAFE_CALLBACK(itf->Class->OutData, itf, ep); 167 | } 168 | 169 | /** @} */ 170 | 171 | #ifdef __cplusplus 172 | } 173 | #endif 174 | 175 | #endif /* __USBD_PRIVATE_H_ */ 176 | -------------------------------------------------------------------------------- /usb/Xpd/usbd_pd_def.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file usbd_pd_def.h 4 | * @author Benedek Kupper 5 | * @version 0.1 6 | * @date 2018-01-31 7 | * @brief Universal Serial Bus Device Driver 8 | * Peripheral Driver-specific constant and type definitions 9 | * 10 | * Copyright (c) 2018 Benedek Kupper 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the "License"); 13 | * you may not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * http://www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an "AS IS" BASIS, 20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | #ifndef __USBD_PD_DEF_H_ 25 | #define __USBD_PD_DEF_H_ 26 | 27 | #ifdef __cplusplus 28 | extern "C" 29 | { 30 | #endif 31 | 32 | #include 33 | #include 34 | 35 | /** @addtogroup USBD_Exported_Macros 36 | * @{ */ 37 | 38 | #if defined(USBD_HS_SUPPORT) && !defined(USB_OTG_HS) 39 | /* High speed support is only needed 40 | * if the HS core is intended for HS operation */ 41 | #undef USBD_HS_SUPPORT 42 | #define USBD_HS_SUPPORT 0 43 | #endif 44 | 45 | /* Link Power Management support by peripheral */ 46 | #define USBD_LPM_SUPPORT \ 47 | (defined(USB_OTG_GLPMCFG_LPMEN) || defined(USB_LPMCSR_LPMEN)) 48 | 49 | /* USB cores set the address after the SetAddress request is completed, 50 | * while USB_OTG cores need the new address as soon as available */ 51 | #define USBD_SET_ADDRESS_IMMEDIATE \ 52 | (defined(USB_OTG_FS)) 53 | 54 | /* The maximal number of available endpoints differs for all USB cores */ 55 | #if defined(USB) 56 | #define USBD_MAX_EP_COUNT 8 /* Theoretical maximum */ 57 | #elif defined(USB_OTG_HS) 58 | #define USBD_MAX_EP_COUNT USB_OTG_HS_MAX_IN_ENDPOINTS 59 | #elif defined(USB_OTG_FS) && defined(USB_OTG_FS_MAX_IN_ENDPOINTS) 60 | #define USBD_MAX_EP_COUNT USB_OTG_FS_MAX_IN_ENDPOINTS 61 | #elif defined(USB_OTG_FS) 62 | #define USBD_MAX_EP_COUNT 6 63 | #endif 64 | 65 | /* Peripheral Driver extension fields */ 66 | #if defined(USB) 67 | #define USBD_PD_EP_FIELDS \ 68 | uint8_t RegId; /*!< Endpoint register ID */ 69 | 70 | #if defined(USB_BCDR_DPPU) 71 | #define USBD_PD_DEV_FIELDS \ 72 | struct { \ 73 | XPD_HandleCallbackType DepInit; /*!< Initialize module dependencies */\ 74 | XPD_HandleCallbackType DepDeinit; /*!< Restore module dependencies */\ 75 | XPD_HandleCallbackType Suspend; /*!< Suspend request */ \ 76 | XPD_HandleCallbackType Resume; /*!< Resume request */ \ 77 | XPD_HandleCallbackType SOF; /*!< Start Of Frame */ \ 78 | }Callbacks; /* Handle Callbacks */ 79 | #else 80 | #define USBD_PD_DEV_FIELDS \ 81 | struct { \ 82 | XPD_HandleCallbackType DepInit; /*!< Initialize module dependencies */\ 83 | XPD_HandleCallbackType DepDeinit; /*!< Restore module dependencies */\ 84 | XPD_CtrlCallbackType ConnectCtrl; /*!< Callback to set USB device bus line connection state */\ 85 | XPD_HandleCallbackType Suspend; /*!< Suspend request */ \ 86 | XPD_HandleCallbackType Resume; /*!< Resume request */ \ 87 | XPD_HandleCallbackType SOF; /*!< Start Of Frame */ \ 88 | }Callbacks; /* Handle Callbacks */ 89 | #endif /* USB_BCDR_DPPU */ 90 | 91 | /* Packet memory is 16 bit wide */ 92 | #define USBD_DATA_ALIGNMENT 2 93 | 94 | #elif defined(USB_OTG_FS) 95 | 96 | /** @brief USB peripheral PHYsical layer selection */ 97 | typedef enum { 98 | USB_PHY_EMBEDDED_FS = 0, /*!< Full-Speed PHY embedded in chip */ 99 | USB_PHY_ULPI = 1, /*!< ULPI interface to external High-Speed PHY */ 100 | USB_PHY_EMBEDDED_HS = 2, /*!< High-Speed PHY embedded in chip */ 101 | }USB_PHYType; 102 | 103 | #if defined(USB_OTG_HS) 104 | 105 | #define USBD_PD_CONFIG_FIELDS \ 106 | USB_PHYType PHY; /*!< USB PHYsical layer selection */ \ 107 | FunctionalState DMA; /*!< DMA activation */ 108 | 109 | /* DMA requires word aligned data */ 110 | #define USBD_DATA_ALIGNMENT 4 111 | 112 | #else 113 | 114 | #define USBD_PD_CONFIG_FIELDS \ 115 | USB_PHYType PHY; /*!< USB PHYsical layer selection */ 116 | 117 | #define USBD_DATA_ALIGNMENT 1 118 | 119 | #endif /* USB_OTG_HS */ 120 | 121 | #define USBD_PD_DEV_FIELDS \ 122 | USB_OTG_TypeDef * Inst; /*!< The address of the peripheral */ \ 123 | struct { \ 124 | XPD_HandleCallbackType DepInit; /*!< Initialize module dependencies */\ 125 | XPD_HandleCallbackType DepDeinit; /*!< Restore module dependencies */\ 126 | XPD_HandleCallbackType Suspend; /*!< Suspend request */ \ 127 | XPD_HandleCallbackType Resume; /*!< Resume request */ \ 128 | XPD_HandleCallbackType SOF; /*!< Start Of Frame */ \ 129 | }Callbacks; /* Handle Callbacks */ 130 | 131 | #endif 132 | 133 | /** @} */ 134 | 135 | #ifdef __cplusplus 136 | } 137 | #endif 138 | 139 | #endif /* __USBD_PD_DEF_H_ */ 140 | -------------------------------------------------------------------------------- /hal/stm32f1xx_hal_gpio_ex.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32f1xx_hal_gpio_ex.c 4 | * @author MCD Application Team 5 | * @version V1.1.1 6 | * @date 12-May-2017 7 | * @brief GPIO Extension HAL module driver. 8 | * This file provides firmware functions to manage the following 9 | * functionalities of the General Purpose Input/Output (GPIO) extension peripheral. 10 | * + Extended features functions 11 | * 12 | @verbatim 13 | ============================================================================== 14 | ##### GPIO Peripheral extension features ##### 15 | ============================================================================== 16 | [..] GPIO module on STM32F1 family, manage also the AFIO register: 17 | (+) Possibility to use the EVENTOUT Cortex feature 18 | 19 | ##### How to use this driver ##### 20 | ============================================================================== 21 | [..] This driver provides functions to use EVENTOUT Cortex feature 22 | (#) Configure EVENTOUT Cortex feature using the function HAL_GPIOEx_ConfigEventout() 23 | (#) Activate EVENTOUT Cortex feature using the HAL_GPIOEx_EnableEventout() 24 | (#) Deactivate EVENTOUT Cortex feature using the HAL_GPIOEx_DisableEventout() 25 | 26 | @endverbatim 27 | ****************************************************************************** 28 | * @attention 29 | * 30 | *

© COPYRIGHT(c) 2016 STMicroelectronics

31 | * 32 | * Redistribution and use in source and binary forms, with or without modification, 33 | * are permitted provided that the following conditions are met: 34 | * 1. Redistributions of source code must retain the above copyright notice, 35 | * this list of conditions and the following disclaimer. 36 | * 2. Redistributions in binary form must reproduce the above copyright notice, 37 | * this list of conditions and the following disclaimer in the documentation 38 | * and/or other materials provided with the distribution. 39 | * 3. Neither the name of STMicroelectronics nor the names of its contributors 40 | * may be used to endorse or promote products derived from this software 41 | * without specific prior written permission. 42 | * 43 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 44 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 45 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 46 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 47 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 48 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 49 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 50 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 51 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 52 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 53 | * 54 | ****************************************************************************** 55 | */ 56 | 57 | /* Includes ------------------------------------------------------------------*/ 58 | #include "stm32f1xx_hal.h" 59 | 60 | /** @addtogroup STM32F1xx_HAL_Driver 61 | * @{ 62 | */ 63 | 64 | /** @defgroup GPIOEx GPIOEx 65 | * @brief GPIO HAL module driver 66 | * @{ 67 | */ 68 | 69 | #ifdef HAL_GPIO_MODULE_ENABLED 70 | 71 | /** @defgroup GPIOEx_Exported_Functions GPIOEx Exported Functions 72 | * @{ 73 | */ 74 | 75 | /** @defgroup GPIOEx_Exported_Functions_Group1 Extended features functions 76 | * @brief Extended features functions 77 | * 78 | @verbatim 79 | ============================================================================== 80 | ##### Extended features functions ##### 81 | ============================================================================== 82 | [..] This section provides functions allowing to: 83 | (+) Configure EVENTOUT Cortex feature using the function HAL_GPIOEx_ConfigEventout() 84 | (+) Activate EVENTOUT Cortex feature using the HAL_GPIOEx_EnableEventout() 85 | (+) Deactivate EVENTOUT Cortex feature using the HAL_GPIOEx_DisableEventout() 86 | 87 | @endverbatim 88 | * @{ 89 | */ 90 | 91 | /** 92 | * @brief Configures the port and pin on which the EVENTOUT Cortex signal will be connected. 93 | * @param GPIO_PortSource Select the port used to output the Cortex EVENTOUT signal. 94 | * This parameter can be a value of @ref GPIOEx_EVENTOUT_PORT. 95 | * @param GPIO_PinSource Select the pin used to output the Cortex EVENTOUT signal. 96 | * This parameter can be a value of @ref GPIOEx_EVENTOUT_PIN. 97 | * @retval None 98 | */ 99 | void HAL_GPIOEx_ConfigEventout(uint32_t GPIO_PortSource, uint32_t GPIO_PinSource) 100 | { 101 | /* Verify the parameters */ 102 | assert_param(IS_AFIO_EVENTOUT_PORT(GPIO_PortSource)); 103 | assert_param(IS_AFIO_EVENTOUT_PIN(GPIO_PinSource)); 104 | 105 | /* Apply the new configuration */ 106 | MODIFY_REG(AFIO->EVCR, (AFIO_EVCR_PORT)|(AFIO_EVCR_PIN), (GPIO_PortSource)|(GPIO_PinSource)); 107 | } 108 | 109 | /** 110 | * @brief Enables the Event Output. 111 | * @retval None 112 | */ 113 | void HAL_GPIOEx_EnableEventout(void) 114 | { 115 | SET_BIT(AFIO->EVCR, AFIO_EVCR_EVOE); 116 | } 117 | 118 | /** 119 | * @brief Disables the Event Output. 120 | * @retval None 121 | */ 122 | void HAL_GPIOEx_DisableEventout(void) 123 | { 124 | CLEAR_BIT(AFIO->EVCR, AFIO_EVCR_EVOE); 125 | } 126 | 127 | /** 128 | * @} 129 | */ 130 | 131 | /** 132 | * @} 133 | */ 134 | 135 | #endif /* HAL_GPIO_MODULE_ENABLED */ 136 | 137 | /** 138 | * @} 139 | */ 140 | 141 | /** 142 | * @} 143 | */ 144 | 145 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 146 | -------------------------------------------------------------------------------- /ram.ld: -------------------------------------------------------------------------------- 1 | /* 2 | ***************************************************************************** 3 | ** 4 | 5 | ** File : LinkerScript.ld 6 | ** 7 | ** Abstract : Linker script for STM32F103C8Tx Device with 8 | ** 64KByte FLASH, 20KByte RAM 9 | ** 10 | ** Set heap size, stack size and stack location according 11 | ** to application requirements. 12 | ** 13 | ** Set memory bank area and size if external memory is used. 14 | ** 15 | ** Target : STMicroelectronics STM32 16 | ** 17 | ** 18 | ** Distribution: The file is distributed as is, without any warranty 19 | ** of any kind. 20 | ** 21 | ***************************************************************************** 22 | ** @attention 23 | ** 24 | **

© COPYRIGHT(c) 2014 Ac6

25 | ** 26 | ** Redistribution and use in source and binary forms, with or without modification, 27 | ** are permitted provided that the following conditions are met: 28 | ** 1. Redistributions of source code must retain the above copyright notice, 29 | ** this list of conditions and the following disclaimer. 30 | ** 2. Redistributions in binary form must reproduce the above copyright notice, 31 | ** this list of conditions and the following disclaimer in the documentation 32 | ** and/or other materials provided with the distribution. 33 | ** 3. Neither the name of Ac6 nor the names of its contributors 34 | ** may be used to endorse or promote products derived from this software 35 | ** without specific prior written permission. 36 | ** 37 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 38 | ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 39 | ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 40 | ** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 41 | ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 42 | ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 43 | ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 44 | ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 45 | ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 46 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 47 | ** 48 | ***************************************************************************** 49 | */ 50 | 51 | /* Entry Point */ 52 | ENTRY(Reset_Handler) 53 | 54 | /* Highest address of the user mode stack */ 55 | _estack = 0x20005000; /* end of RAM */ 56 | /* Generate a link error if heap and stack don't fit into RAM */ 57 | _Min_Heap_Size = 0x200; /* required amount of heap */ 58 | _Min_Stack_Size = 0x400; /* required amount of stack */ 59 | 60 | /* Specify the memory areas */ 61 | MEMORY 62 | { 63 | RAM (xrw) : ORIGIN = 0x20001000, LENGTH = 16K 64 | FLASH (rx) : ORIGIN = 0x20005000, LENGTH = 76K 65 | } 66 | 67 | /* Define output sections */ 68 | SECTIONS 69 | { 70 | /* The startup code goes first into FLASH */ 71 | .isr_vector : 72 | { 73 | . = ALIGN(4); 74 | KEEP(*(.isr_vector)) /* Startup code */ 75 | . = ALIGN(4); 76 | } >FLASH 77 | 78 | /* The program code and other data goes into FLASH */ 79 | .text : 80 | { 81 | . = ALIGN(4); 82 | *(.text) /* .text sections (code) */ 83 | *(.text*) /* .text* sections (code) */ 84 | *(.glue_7) /* glue arm to thumb code */ 85 | *(.glue_7t) /* glue thumb to arm code */ 86 | *(.eh_frame) 87 | 88 | KEEP (*(.init)) 89 | KEEP (*(.fini)) 90 | 91 | . = ALIGN(4); 92 | _etext = .; /* define a global symbols at end of code */ 93 | } >FLASH 94 | 95 | /* Constant data goes into FLASH */ 96 | .rodata : 97 | { 98 | . = ALIGN(4); 99 | *(.rodata) /* .rodata sections (constants, strings, etc.) */ 100 | *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ 101 | . = ALIGN(4); 102 | } >FLASH 103 | 104 | .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH 105 | .ARM : { 106 | __exidx_start = .; 107 | *(.ARM.exidx*) 108 | __exidx_end = .; 109 | } >FLASH 110 | 111 | .preinit_array : 112 | { 113 | PROVIDE_HIDDEN (__preinit_array_start = .); 114 | KEEP (*(.preinit_array*)) 115 | PROVIDE_HIDDEN (__preinit_array_end = .); 116 | } >FLASH 117 | .init_array : 118 | { 119 | PROVIDE_HIDDEN (__init_array_start = .); 120 | KEEP (*(SORT(.init_array.*))) 121 | KEEP (*(.init_array*)) 122 | PROVIDE_HIDDEN (__init_array_end = .); 123 | } >FLASH 124 | .fini_array : 125 | { 126 | PROVIDE_HIDDEN (__fini_array_start = .); 127 | KEEP (*(SORT(.fini_array.*))) 128 | KEEP (*(.fini_array*)) 129 | PROVIDE_HIDDEN (__fini_array_end = .); 130 | } >FLASH 131 | 132 | /* used by the startup to initialize data */ 133 | _sidata = LOADADDR(.data); 134 | 135 | /* Initialized data sections goes into RAM, load LMA copy after code */ 136 | .data : 137 | { 138 | . = ALIGN(4); 139 | _sdata = .; /* create a global symbol at data start */ 140 | *(.data) /* .data sections */ 141 | *(.data*) /* .data* sections */ 142 | 143 | . = ALIGN(4); 144 | _edata = .; /* define a global symbol at data end */ 145 | } >RAM AT> FLASH 146 | 147 | 148 | /* Uninitialized data section */ 149 | . = ALIGN(4); 150 | .bss : 151 | { 152 | /* This is used by the startup in order to initialize the .bss secion */ 153 | _sbss = .; /* define a global symbol at bss start */ 154 | __bss_start__ = _sbss; 155 | *(.bss) 156 | *(.bss*) 157 | *(COMMON) 158 | 159 | . = ALIGN(4); 160 | _ebss = .; /* define a global symbol at bss end */ 161 | __bss_end__ = _ebss; 162 | } >RAM 163 | 164 | /* User_heap_stack section, used to check that there is enough RAM left */ 165 | ._user_heap_stack : 166 | { 167 | . = ALIGN(8); 168 | PROVIDE ( end = . ); 169 | PROVIDE ( _end = . ); 170 | . = . + _Min_Heap_Size; 171 | . = . + _Min_Stack_Size; 172 | . = ALIGN(8); 173 | } >RAM 174 | 175 | 176 | 177 | /* Remove information from the standard libraries */ 178 | /DISCARD/ : 179 | { 180 | libc.a ( * ) 181 | libm.a ( * ) 182 | libgcc.a ( * ) 183 | } 184 | 185 | .ARM.attributes 0 : { *(.ARM.attributes) } 186 | } 187 | 188 | 189 | -------------------------------------------------------------------------------- /flash.ld: -------------------------------------------------------------------------------- 1 | /* 2 | ***************************************************************************** 3 | ** 4 | 5 | ** File : LinkerScript.ld 6 | ** 7 | ** Abstract : Linker script for STM32F103C8Tx Device with 8 | ** 64KByte FLASH, 20KByte RAM 9 | ** 10 | ** Set heap size, stack size and stack location according 11 | ** to application requirements. 12 | ** 13 | ** Set memory bank area and size if external memory is used. 14 | ** 15 | ** Target : STMicroelectronics STM32 16 | ** 17 | ** 18 | ** Distribution: The file is distributed as is, without any warranty 19 | ** of any kind. 20 | ** 21 | ***************************************************************************** 22 | ** @attention 23 | ** 24 | **

© COPYRIGHT(c) 2014 Ac6

25 | ** 26 | ** Redistribution and use in source and binary forms, with or without modification, 27 | ** are permitted provided that the following conditions are met: 28 | ** 1. Redistributions of source code must retain the above copyright notice, 29 | ** this list of conditions and the following disclaimer. 30 | ** 2. Redistributions in binary form must reproduce the above copyright notice, 31 | ** this list of conditions and the following disclaimer in the documentation 32 | ** and/or other materials provided with the distribution. 33 | ** 3. Neither the name of Ac6 nor the names of its contributors 34 | ** may be used to endorse or promote products derived from this software 35 | ** without specific prior written permission. 36 | ** 37 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 38 | ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 39 | ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 40 | ** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 41 | ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 42 | ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 43 | ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 44 | ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 45 | ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 46 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 47 | ** 48 | ***************************************************************************** 49 | */ 50 | 51 | /* Entry Point */ 52 | ENTRY(Reset_Handler) 53 | 54 | /* Highest address of the user mode stack */ 55 | _estack = 0x20005000; /* end of RAM */ 56 | /* Generate a link error if heap and stack don't fit into RAM */ 57 | _Min_Heap_Size = 0x200; /* required amount of heap */ 58 | _Min_Stack_Size = 0x400; /* required amount of stack */ 59 | 60 | /* Specify the memory areas */ 61 | MEMORY 62 | { 63 | RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K 64 | FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K 65 | } 66 | 67 | /* Define output sections */ 68 | SECTIONS 69 | { 70 | /* The startup code goes first into FLASH */ 71 | .isr_vector : 72 | { 73 | . = ALIGN(4); 74 | KEEP(*(.isr_vector)) /* Startup code */ 75 | . = ALIGN(4); 76 | } >FLASH 77 | 78 | /* The program code and other data goes into FLASH */ 79 | .text : 80 | { 81 | . = ALIGN(4); 82 | *(.text) /* .text sections (code) */ 83 | *(.text*) /* .text* sections (code) */ 84 | *(.glue_7) /* glue arm to thumb code */ 85 | *(.glue_7t) /* glue thumb to arm code */ 86 | *(.eh_frame) 87 | 88 | KEEP (*(.init)) 89 | KEEP (*(.fini)) 90 | 91 | . = ALIGN(4); 92 | _etext = .; /* define a global symbols at end of code */ 93 | } >FLASH 94 | 95 | /* Constant data goes into FLASH */ 96 | .rodata : 97 | { 98 | . = ALIGN(4); 99 | *(.rodata) /* .rodata sections (constants, strings, etc.) */ 100 | *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ 101 | . = ALIGN(4); 102 | } >FLASH 103 | 104 | .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH 105 | .ARM : { 106 | __exidx_start = .; 107 | *(.ARM.exidx*) 108 | __exidx_end = .; 109 | } >FLASH 110 | 111 | .preinit_array : 112 | { 113 | PROVIDE_HIDDEN (__preinit_array_start = .); 114 | KEEP (*(.preinit_array*)) 115 | PROVIDE_HIDDEN (__preinit_array_end = .); 116 | } >FLASH 117 | .init_array : 118 | { 119 | PROVIDE_HIDDEN (__init_array_start = .); 120 | KEEP (*(SORT(.init_array.*))) 121 | KEEP (*(.init_array*)) 122 | PROVIDE_HIDDEN (__init_array_end = .); 123 | } >FLASH 124 | .fini_array : 125 | { 126 | PROVIDE_HIDDEN (__fini_array_start = .); 127 | KEEP (*(SORT(.fini_array.*))) 128 | KEEP (*(.fini_array*)) 129 | PROVIDE_HIDDEN (__fini_array_end = .); 130 | } >FLASH 131 | 132 | /* used by the startup to initialize data */ 133 | _sidata = LOADADDR(.data); 134 | 135 | /* Initialized data sections goes into RAM, load LMA copy after code */ 136 | .data : 137 | { 138 | . = ALIGN(4); 139 | _sdata = .; /* create a global symbol at data start */ 140 | *(.data) /* .data sections */ 141 | *(.data*) /* .data* sections */ 142 | 143 | . = ALIGN(4); 144 | _edata = .; /* define a global symbol at data end */ 145 | } >RAM AT> FLASH 146 | 147 | 148 | /* Uninitialized data section */ 149 | . = ALIGN(4); 150 | .bss : 151 | { 152 | /* This is used by the startup in order to initialize the .bss secion */ 153 | _sbss = .; /* define a global symbol at bss start */ 154 | __bss_start__ = _sbss; 155 | *(.bss) 156 | *(.bss*) 157 | *(COMMON) 158 | 159 | . = ALIGN(4); 160 | _ebss = .; /* define a global symbol at bss end */ 161 | __bss_end__ = _ebss; 162 | } >RAM 163 | 164 | /* User_heap_stack section, used to check that there is enough RAM left */ 165 | ._user_heap_stack : 166 | { 167 | . = ALIGN(8); 168 | PROVIDE ( end = . ); 169 | PROVIDE ( _end = . ); 170 | . = . + _Min_Heap_Size; 171 | . = . + _Min_Stack_Size; 172 | . = ALIGN(8); 173 | } >RAM 174 | 175 | 176 | 177 | /* Remove information from the standard libraries */ 178 | /DISCARD/ : 179 | { 180 | libc.a ( * ) 181 | libm.a ( * ) 182 | libgcc.a ( * ) 183 | } 184 | 185 | .ARM.attributes 0 : { *(.ARM.attributes) } 186 | } 187 | 188 | 189 | -------------------------------------------------------------------------------- /brd/stm32f1xx_it.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32f1xx_it.c 4 | * @brief Interrupt Service Routines. 5 | ****************************************************************************** 6 | * 7 | * COPYRIGHT(c) 2017 STMicroelectronics 8 | * 9 | * Redistribution and use in source and binary forms, with or without modification, 10 | * are permitted provided that the following conditions are met: 11 | * 1. Redistributions of source code must retain the above copyright notice, 12 | * this list of conditions and the following disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 3. Neither the name of STMicroelectronics nor the names of its contributors 17 | * may be used to endorse or promote products derived from this software 18 | * without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | ****************************************************************************** 32 | */ 33 | /* Includes ------------------------------------------------------------------*/ 34 | #include "stm32f1xx_hal.h" 35 | #include "stm32f1xx.h" 36 | #include "stm32f1xx_it.h" 37 | 38 | /* USER CODE BEGIN 0 */ 39 | 40 | /* USER CODE END 0 */ 41 | 42 | /* External variables --------------------------------------------------------*/ 43 | extern PCD_HandleTypeDef hpcd_USB_FS; 44 | 45 | /******************************************************************************/ 46 | /* Cortex-M3 Processor Interruption and Exception Handlers */ 47 | /******************************************************************************/ 48 | 49 | /** 50 | * @brief This function handles Non maskable interrupt. 51 | */ 52 | void NMI_Handler(void) 53 | { 54 | /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ 55 | 56 | /* USER CODE END NonMaskableInt_IRQn 0 */ 57 | /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ 58 | 59 | /* USER CODE END NonMaskableInt_IRQn 1 */ 60 | } 61 | 62 | /** 63 | * @brief This function handles Hard fault interrupt. 64 | */ 65 | void HardFault_Handler(void) 66 | { 67 | /* USER CODE BEGIN HardFault_IRQn 0 */ 68 | 69 | /* USER CODE END HardFault_IRQn 0 */ 70 | while (1) 71 | { 72 | } 73 | /* USER CODE BEGIN HardFault_IRQn 1 */ 74 | 75 | /* USER CODE END HardFault_IRQn 1 */ 76 | } 77 | 78 | /** 79 | * @brief This function handles Memory management fault. 80 | */ 81 | void MemManage_Handler(void) 82 | { 83 | /* USER CODE BEGIN MemoryManagement_IRQn 0 */ 84 | 85 | /* USER CODE END MemoryManagement_IRQn 0 */ 86 | while (1) 87 | { 88 | } 89 | /* USER CODE BEGIN MemoryManagement_IRQn 1 */ 90 | 91 | /* USER CODE END MemoryManagement_IRQn 1 */ 92 | } 93 | 94 | /** 95 | * @brief This function handles Prefetch fault, memory access fault. 96 | */ 97 | void BusFault_Handler(void) 98 | { 99 | /* USER CODE BEGIN BusFault_IRQn 0 */ 100 | 101 | /* USER CODE END BusFault_IRQn 0 */ 102 | while (1) 103 | { 104 | } 105 | /* USER CODE BEGIN BusFault_IRQn 1 */ 106 | 107 | /* USER CODE END BusFault_IRQn 1 */ 108 | } 109 | 110 | /** 111 | * @brief This function handles Undefined instruction or illegal state. 112 | */ 113 | void UsageFault_Handler(void) 114 | { 115 | /* USER CODE BEGIN UsageFault_IRQn 0 */ 116 | 117 | /* USER CODE END UsageFault_IRQn 0 */ 118 | while (1) 119 | { 120 | } 121 | /* USER CODE BEGIN UsageFault_IRQn 1 */ 122 | 123 | /* USER CODE END UsageFault_IRQn 1 */ 124 | } 125 | 126 | /** 127 | * @brief This function handles System service call via SWI instruction. 128 | */ 129 | void SVC_Handler(void) 130 | { 131 | /* USER CODE BEGIN SVCall_IRQn 0 */ 132 | 133 | /* USER CODE END SVCall_IRQn 0 */ 134 | /* USER CODE BEGIN SVCall_IRQn 1 */ 135 | 136 | /* USER CODE END SVCall_IRQn 1 */ 137 | } 138 | 139 | /** 140 | * @brief This function handles Debug monitor. 141 | */ 142 | void DebugMon_Handler(void) 143 | { 144 | /* USER CODE BEGIN DebugMonitor_IRQn 0 */ 145 | 146 | /* USER CODE END DebugMonitor_IRQn 0 */ 147 | /* USER CODE BEGIN DebugMonitor_IRQn 1 */ 148 | 149 | /* USER CODE END DebugMonitor_IRQn 1 */ 150 | } 151 | 152 | /** 153 | * @brief This function handles Pendable request for system service. 154 | */ 155 | void PendSV_Handler(void) 156 | { 157 | /* USER CODE BEGIN PendSV_IRQn 0 */ 158 | 159 | /* USER CODE END PendSV_IRQn 0 */ 160 | /* USER CODE BEGIN PendSV_IRQn 1 */ 161 | 162 | /* USER CODE END PendSV_IRQn 1 */ 163 | } 164 | 165 | /** 166 | * @brief This function handles System tick timer. 167 | */ 168 | void SysTick_Handler(void) 169 | { 170 | /* USER CODE BEGIN SysTick_IRQn 0 */ 171 | 172 | /* USER CODE END SysTick_IRQn 0 */ 173 | HAL_IncTick(); 174 | HAL_SYSTICK_IRQHandler(); 175 | /* USER CODE BEGIN SysTick_IRQn 1 */ 176 | 177 | /* USER CODE END SysTick_IRQn 1 */ 178 | } 179 | 180 | /******************************************************************************/ 181 | /* STM32F1xx Peripheral Interrupt Handlers */ 182 | /* Add here the Interrupt Handlers for the used peripherals. */ 183 | /* For the available peripheral interrupt handler names, */ 184 | /* please refer to the startup file (startup_stm32f1xx.s). */ 185 | /******************************************************************************/ 186 | 187 | /** 188 | * @brief This function handles USB low priority or CAN RX0 interrupts. 189 | */ 190 | void USB_LP_CAN1_RX0_IRQHandler(void) 191 | { 192 | extern void USB_vISR (void); 193 | /* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 0 */ 194 | /* USER CODE END USB_LP_CAN1_RX0_IRQn 0 */ 195 | USB_vISR (); 196 | /* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 1 */ 197 | 198 | /* USER CODE END USB_LP_CAN1_RX0_IRQn 1 */ 199 | } 200 | 201 | void USART3_IRQHandler(void) 202 | { 203 | extern void Hal_uart_isr(void); 204 | Hal_uart_isr(); 205 | } 206 | -------------------------------------------------------------------------------- /usb/Xpd/xpd_common.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file xpd_common.h 4 | * @author Benedek Kupper 5 | * @version 0.2 6 | * @date 2018-01-28 7 | * @brief STM32 eXtensible Peripheral Drivers Common Module 8 | * 9 | * Copyright (c) 2018 Benedek Kupper 10 | * 11 | * Licensed under the Apache License, Version 2.0 (the "License"); 12 | * you may not use this file except in compliance with the License. 13 | * You may obtain a copy of the License at 14 | * 15 | * http://www.apache.org/licenses/LICENSE-2.0 16 | * 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | */ 23 | #ifndef __XPD_COMMON_H_ 24 | #define __XPD_COMMON_H_ 25 | 26 | #ifdef __cplusplus 27 | extern "C" 28 | { 29 | #endif 30 | 31 | #include 32 | 33 | /** @defgroup Common 34 | * @{ */ 35 | 36 | /** @defgroup Common_Exported_Types Common Exported Types 37 | * @{ */ 38 | 39 | /** @brief Boolean type */ 40 | typedef uint8_t boolean_t; 41 | 42 | /** @brief XPD functions return type */ 43 | typedef enum 44 | { 45 | XPD_OK = 0, /*!< Operation finished successfully */ 46 | XPD_ERROR = 1, /*!< Operation encountered an error */ 47 | XPD_BUSY = 2, /*!< Operation exited because it was already in progress */ 48 | XPD_TIMEOUT = 3 /*!< Operation timed out */ 49 | }XPD_ReturnType; 50 | 51 | /** @brief Occurrence reaction type */ 52 | typedef enum 53 | { 54 | REACTION_NONE = 0, /*!< No reaction */ 55 | REACTION_IT = 1, /*!< Interrupt generation reaction */ 56 | REACTION_EVENT = 2 /*!< Event generation reaction */ 57 | }ReactionType; 58 | 59 | /** @brief Signal active level type */ 60 | typedef enum 61 | { 62 | ACTIVE_LOW = 1, /*!< Signal is active low */ 63 | ACTIVE_HIGH = 0 /*!< Signal is active high */ 64 | }ActiveLevelType; 65 | 66 | /** @brief General level type */ 67 | typedef enum 68 | { 69 | LOW = 0, /*!< Low level is selected */ 70 | MEDIUM = 1, /*!< Medium level is selected */ 71 | HIGH = 2, /*!< High level is selected */ 72 | VERY_HIGH = 3 /*!< Very high level is selected */ 73 | }LevelType; 74 | 75 | /** @brief Signal edge type */ 76 | typedef enum 77 | { 78 | EDGE_NONE = 0, /*!< No edge is selected */ 79 | EDGE_RISING = 1, /*!< Rising edge is selected */ 80 | EDGE_FALLING = 2, /*!< Falling edge is selected */ 81 | EDGE_RISING_FALLING = 3 /*!< Rising and falling edges are selected */ 82 | }EdgeType; 83 | 84 | /** @brief Clock division type */ 85 | typedef enum 86 | { 87 | CLK_DIV1 = 0, /*!< Clock is not divided */ 88 | CLK_DIV2 = 1, /*!< Clock is divided by 2 */ 89 | CLK_DIV4 = 2, /*!< Clock is divided by 4 */ 90 | CLK_DIV8 = 3, /*!< Clock is divided by 8 */ 91 | CLK_DIV16 = 4, /*!< Clock is divided by 16 */ 92 | CLK_DIV32 = 5, /*!< Clock is divided by 32 */ 93 | CLK_DIV64 = 6, /*!< Clock is divided by 64 */ 94 | CLK_DIV128 = 7, /*!< Clock is divided by 128 */ 95 | CLK_DIV256 = 8, /*!< Clock is divided by 256 */ 96 | CLK_DIV512 = 9 /*!< Clock is divided by 512 */ 97 | }ClockDividerType; 98 | 99 | /** @brief Clock sampling phase type */ 100 | typedef enum 101 | { 102 | CLOCK_PHASE_1EDGE = 0, /*!< Data sampling begins at the first clock phase switch */ 103 | CLOCK_PHASE_2EDGE = 1 /*!< Data sampling begins at the second clock phase switch */ 104 | }ClockPhaseType; 105 | 106 | /** @brief Data transfer stream type */ 107 | typedef struct 108 | { 109 | void * buffer; /*!< Pointer to the initial data element */ 110 | uint16_t length; /*!< Length of the data stream */ 111 | uint16_t size; /*!< Size of a data element */ 112 | }DataStreamType; 113 | 114 | /** 115 | * @brief Function pointer type for binary control function reference 116 | * @param NewState: the state to set 117 | */ 118 | typedef void ( *XPD_CtrlCallbackType ) ( int NewState ); 119 | 120 | /** 121 | * @brief Callback function pointer type with no parameters 122 | */ 123 | typedef void ( *XPD_SimpleCallbackType ) ( void ); 124 | 125 | /** 126 | * @brief Callback function pointer type with numeric parameter 127 | * @param Value: provided data for the callback 128 | */ 129 | typedef void ( *XPD_ValueCallbackType ) ( uint32_t Value ); 130 | 131 | /** 132 | * @brief Callback function pointer type with handle pointer parameter 133 | * @param Handle: pointer of the callback sender handle 134 | */ 135 | typedef void ( *XPD_HandleCallbackType ) ( void * Handle ); 136 | 137 | /** @} */ 138 | 139 | /** @defgroup Common_Exported_Macros Common Exported Macros 140 | * @{ */ 141 | 142 | #ifndef NULL 143 | #define NULL ((void *)0) 144 | #endif 145 | 146 | #ifndef FALSE 147 | #define FALSE 0 148 | #endif 149 | #ifndef TRUE 150 | #define TRUE (!FALSE) 151 | #endif 152 | 153 | /** 154 | * @brief Safe function pointer caller that checks it against NULL and calls it with parameters. 155 | * @param CALLBACK: the function pointer 156 | * @param PARAMETERS: the required parameters of the function 157 | */ 158 | #define XPD_SAFE_CALLBACK(CALLBACK, ...) \ 159 | do{ if ((CALLBACK) != NULL) (void) CALLBACK(__VA_ARGS__); }while(0) 160 | 161 | /** @} */ 162 | 163 | /** @} */ 164 | 165 | /* Inherited macros */ 166 | 167 | #define SET_BIT(REG, BIT) ((REG) |= (BIT)) 168 | 169 | #define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT)) 170 | 171 | #undef MODIFY_REG 172 | #define MODIFY_REG(REG, CLEARMASK, SETMASK) \ 173 | ((REG) = (((REG) & (~(CLEARMASK))) | ((SETMASK) & (CLEARMASK)))) 174 | 175 | #define POSITION_VAL(VAL) (__CLZ(__RBIT(VAL))) 176 | 177 | #if defined ( __GNUC__ ) 178 | #ifndef __weak 179 | #define __weak __attribute__((weak)) 180 | #endif /* __weak */ 181 | #ifndef __packed 182 | #define __packed __attribute__((__packed__)) 183 | #endif /* __packed */ 184 | #endif /* __GNUC__ */ 185 | 186 | /* Macro to get variable aligned on 4-bytes, 187 | * for __ICCARM__ the directive "#pragma data_alignment=4" must be used instead */ 188 | #if defined (__GNUC__) /* GNU Compiler */ 189 | #ifndef __ALIGN_END 190 | #define __ALIGN_END __attribute__ ((aligned (4))) 191 | #endif /* __ALIGN_END */ 192 | #ifndef __ALIGN_BEGIN 193 | #define __ALIGN_BEGIN 194 | #endif /* __ALIGN_BEGIN */ 195 | #else 196 | #ifndef __ALIGN_END 197 | #define __ALIGN_END 198 | #endif /* __ALIGN_END */ 199 | #ifndef __ALIGN_BEGIN 200 | #if defined (__CC_ARM) /* ARM Compiler */ 201 | #define __ALIGN_BEGIN __align(4) 202 | #elif defined (__ICCARM__) /* IAR Compiler */ 203 | #define __ALIGN_BEGIN 204 | #endif /* __CC_ARM */ 205 | #endif /* __ALIGN_BEGIN */ 206 | #endif /* __GNUC__ */ 207 | 208 | #include 209 | 210 | #ifdef __cplusplus 211 | } 212 | #endif 213 | 214 | #endif /* __XPD_COMMON_H_ */ 215 | -------------------------------------------------------------------------------- /usb/Include/private/usbd_internal.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file usbd_internal.h 4 | * @author Benedek Kupper 5 | * @version 0.1 6 | * @date 2018-01-31 7 | * @brief Universal Serial Bus Device Driver 8 | * Services accessible by (class) interfaces 9 | * 10 | * Copyright (c) 2018 Benedek Kupper 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the "License"); 13 | * you may not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * http://www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an "AS IS" BASIS, 20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | #ifndef __USBD_INTERNAL_H_ 25 | #define __USBD_INTERNAL_H_ 26 | 27 | #ifdef __cplusplus 28 | extern "C" 29 | { 30 | #endif 31 | 32 | #include 33 | #include 34 | 35 | /* strlen(), memcpy() */ 36 | #include 37 | 38 | /** @ingroup USBD 39 | * @addtogroup USBD_Internal_Functions 40 | * @{ */ 41 | 42 | USBD_ReturnType USBD_CtrlSendData (USBD_HandleType *dev, 43 | void *data, 44 | uint16_t len); 45 | 46 | USBD_ReturnType USBD_CtrlReceiveData (USBD_HandleType *dev, 47 | void *data); 48 | 49 | uint16_t USBD_EpDesc (USBD_HandleType *dev, 50 | uint8_t epAddr, 51 | uint8_t *data); 52 | 53 | uint8_t USBD_EpHsInterval (uint32_t interval_ms); 54 | 55 | USBD_ReturnType USBD_EpSend (USBD_HandleType *dev, 56 | uint8_t epAddr, 57 | void *data, 58 | uint16_t len); 59 | 60 | USBD_ReturnType USBD_EpReceive (USBD_HandleType *dev, 61 | uint8_t epAddr, 62 | void *data, 63 | uint16_t len); 64 | 65 | /** 66 | * @brief Converts the USBD endpoint address to its reference. 67 | * @param dev: USB Device handle reference 68 | * @param epAddr: endpoint address 69 | * @return The endpoint's reference 70 | */ 71 | static inline 72 | USBD_EpHandleType* USBD_EpAddr2Ref (USBD_HandleType *dev, 73 | uint8_t epAddr) 74 | { 75 | return (epAddr > 0x7F) ? &dev->EP.IN[epAddr & 0xF] : &dev->EP.OUT[epAddr]; 76 | } 77 | 78 | /** 79 | * @brief Converts the USBD endpoint reference to its address. 80 | * @param dev: USB Device handle reference 81 | * @param ep: USB endpoint handle reference 82 | * @return The endpoint's address 83 | */ 84 | static inline uint8_t USBD_EpRef2Addr (USBD_HandleType *dev, 85 | USBD_EpHandleType *ep) 86 | { 87 | uint8_t epAddr = (((uint32_t)ep - (uint32_t)&dev->EP.IN[0]) 88 | / sizeof(USBD_EpHandleType)); 89 | return (epAddr < USBD_MAX_EP_COUNT) ? 90 | (0x80 | epAddr) : /* IN endpoint */ 91 | (epAddr - USBD_MAX_EP_COUNT); /* OUT endpoint */ 92 | } 93 | 94 | /** 95 | * @brief Opens the device endpoint. 96 | * @param dev: USB Device handle reference 97 | * @param epAddr: endpoint address 98 | * @param type: endpoint type 99 | * @param mps: endpoint maximal packet size 100 | */ 101 | static inline void USBD_EpOpen (USBD_HandleType *dev, 102 | uint8_t epAddr, 103 | USB_EndPointType type, 104 | uint16_t mps) 105 | { 106 | USBD_PD_EpOpen(dev, epAddr, type, mps); 107 | USBD_EpAddr2Ref(dev, epAddr)->State = USB_EP_STATE_IDLE; 108 | } 109 | 110 | /** 111 | * @brief Closes the device endpoint. 112 | * @param dev: USB Device handle reference 113 | * @param epAddr: endpoint address 114 | */ 115 | static inline void USBD_EpClose (USBD_HandleType *dev, 116 | uint8_t epAddr) 117 | { 118 | USBD_PD_EpClose(dev, epAddr); 119 | USBD_EpAddr2Ref(dev, epAddr)->State = USB_EP_STATE_CLOSED; 120 | } 121 | 122 | /** 123 | * @brief Flushes the buffered data from the endpoint. 124 | * @param dev: USB Device handle reference 125 | * @param epAddr: endpoint address 126 | */ 127 | static inline void USBD_EpFlush (USBD_HandleType *dev, 128 | uint8_t epAddr) 129 | { 130 | USBD_PD_EpFlush(dev, epAddr); 131 | USBD_EpAddr2Ref(dev, epAddr)->State = USB_EP_STATE_IDLE; 132 | } 133 | 134 | /** 135 | * @brief Sets the stall (NAK) status on the endpoint. 136 | * @param dev: USB Device handle reference 137 | * @param epAddr: endpoint address 138 | */ 139 | static inline void USBD_EpSetStall (USBD_HandleType *dev, 140 | uint8_t epAddr) 141 | { 142 | USBD_PD_EpSetStall(dev, epAddr); 143 | USBD_EpAddr2Ref(dev, epAddr)->State = USB_EP_STATE_STALL; 144 | } 145 | 146 | /** 147 | * @brief Clears the stall (NAK) status on the endpoint. 148 | * @param dev: USB Device handle reference 149 | * @param epAddr: endpoint address 150 | */ 151 | static inline void USBD_EpClearStall (USBD_HandleType *dev, 152 | uint8_t epAddr) 153 | { 154 | USBD_PD_EpClearStall(dev, epAddr); 155 | USBD_EpAddr2Ref(dev, epAddr)->State = USB_EP_STATE_IDLE; 156 | } 157 | 158 | /** @} */ 159 | 160 | /** 161 | * @brief Safe function pointer caller that 162 | * checks it against NULL and calls it with parameters. 163 | * @param CALLBACK: the function pointer 164 | * @param ...: the required parameters of the function 165 | */ 166 | #define USBD_SAFE_CALLBACK(CALLBACK, ...) \ 167 | do{ if ((CALLBACK) != NULL) (void) CALLBACK(__VA_ARGS__); }while(0) 168 | 169 | 170 | /** @brief Reserved string descriptor index */ 171 | #define USBD_IIF_INVALID 0 172 | 173 | /** 174 | * @brief Returns an interface string index based on the interface index 175 | * and an internal index. 176 | * @param IFNUM: the interface index in the device 177 | * @param INTNUM: the internal index 178 | */ 179 | #define USBD_IIF_INDEX(IFNUM, INTNUM) \ 180 | (USBD_ISTR_INTERFACES + (IFNUM) + ((INTNUM) << 4)) 181 | 182 | 183 | #ifdef __htonl 184 | #define htonl(_x) __htonl(_x) 185 | #endif 186 | #ifdef __htons 187 | #define htons(_x) __htons(_x) 188 | #endif 189 | #define ntohl(_x) htonl(_x) 190 | #define ntohs(_x) htons(_x) 191 | 192 | 193 | #ifdef __cplusplus 194 | } 195 | #endif 196 | 197 | #endif /* __USBD_INTERNAL_H_ */ 198 | -------------------------------------------------------------------------------- /usb/Device/usbd_ep.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file usbd_ep.c 4 | * @author Benedek Kupper 5 | * @version 0.1 6 | * @date 2018-01-31 7 | * @brief Universal Serial Bus Device Driver 8 | * Endpoint control functions 9 | * 10 | * Copyright (c) 2018 Benedek Kupper 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the "License"); 13 | * you may not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * http://www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an "AS IS" BASIS, 20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | #include 25 | 26 | /** @ingroup USBD 27 | * @defgroup USBD_Internal_Functions USB Device Internal Functions 28 | * @brief This group is used by the Device and the Classes. 29 | * @{ */ 30 | 31 | /** 32 | * @brief This function sends data through the selected IN endpoint. 33 | * @param dev: USB Device handle reference 34 | * @param epAddr: endpoint address 35 | * @param data: pointer to the data to send 36 | * @param len: length of the data 37 | * @return BUSY if the endpoint isn't idle, OK if successful 38 | */ 39 | USBD_ReturnType USBD_EpSend(USBD_HandleType *dev, uint8_t epAddr, 40 | void *data, uint16_t len) 41 | { 42 | USBD_ReturnType retval = USBD_E_BUSY; 43 | USBD_EpHandleType *ep = &dev->EP.IN[epAddr & 0xF]; 44 | 45 | if ((ep->State == USB_EP_STATE_IDLE) || 46 | (ep->Type == USB_EP_TYPE_ISOCHRONOUS)) 47 | { 48 | /* Set EP transfer data */ 49 | ep->State = USB_EP_STATE_DATA; 50 | USBD_PD_EpSend(dev, epAddr, (const uint8_t*)data, len); 51 | 52 | retval = USBD_E_OK; 53 | } 54 | 55 | return retval; 56 | } 57 | 58 | /** 59 | * @brief This function prepares data reception through the selected OUT endpoint. 60 | * @param dev: USB Device handle reference 61 | * @param epAddr: endpoint address 62 | * @param data: pointer to the target buffer to receive to 63 | * @param len: maximum length of the data 64 | * @return BUSY if the endpoint isn't idle, OK if successful 65 | */ 66 | USBD_ReturnType USBD_EpReceive(USBD_HandleType *dev, uint8_t epAddr, 67 | void *data, uint16_t len) 68 | { 69 | USBD_ReturnType retval = USBD_E_BUSY; 70 | USBD_EpHandleType *ep = &dev->EP.OUT[epAddr]; 71 | 72 | if ((ep->State == USB_EP_STATE_IDLE) || 73 | (ep->Type == USB_EP_TYPE_ISOCHRONOUS)) 74 | { 75 | /* Set EP transfer data */ 76 | ep->State = USB_EP_STATE_DATA; 77 | USBD_PD_EpReceive(dev, epAddr, (uint8_t*)data, len); 78 | 79 | retval = USBD_E_OK; 80 | } 81 | 82 | return retval; 83 | } 84 | 85 | /** @} */ 86 | 87 | /** @addtogroup USBD_Exported_Functions 88 | * @{ */ 89 | 90 | /** 91 | * @brief This function notifies the appropriate higher layer 92 | * of the completion of an IN endpoint transfer. 93 | * @param dev: USB Device handle reference 94 | * @param ep: USB IN endpoint handle reference 95 | */ 96 | void USBD_EpInCallback(USBD_HandleType *dev, USBD_EpHandleType *ep) 97 | { 98 | if (ep == &dev->EP.IN[0]) 99 | { 100 | USBD_CtrlInCallback(dev); 101 | } 102 | else 103 | { 104 | ep->State = USB_EP_STATE_IDLE; 105 | USBD_IfClass_InData(dev->IF[ep->IfNum], ep); 106 | } 107 | } 108 | 109 | /** 110 | * @brief This function notifies the appropriate higher layer 111 | * of the completion of an OUT endpoint transfer. 112 | * @param dev: USB Device handle reference 113 | * @param ep: USB OUT endpoint handle reference 114 | */ 115 | void USBD_EpOutCallback(USBD_HandleType *dev, USBD_EpHandleType *ep) 116 | { 117 | ep->State = USB_EP_STATE_IDLE; 118 | 119 | if (ep == &dev->EP.OUT[0]) 120 | { 121 | USBD_CtrlOutCallback(dev); 122 | } 123 | else 124 | { 125 | USBD_IfClass_OutData(dev->IF[ep->IfNum], ep); 126 | } 127 | } 128 | 129 | /** @} */ 130 | 131 | /** @addtogroup USBD_Private_Functions_Ctrl 132 | * @{ */ 133 | 134 | /** 135 | * @brief This function handles standard endpoint requests. 136 | * @param dev: USB Device handle reference 137 | * @return OK if the request is processed, INVALID if not supported 138 | */ 139 | USBD_ReturnType USBD_EpRequest(USBD_HandleType *dev) 140 | { 141 | USBD_ReturnType retval = USBD_E_INVALID; 142 | uint8_t epAddr = (uint8_t)dev->Setup.Index, epNum = epAddr & 0xF; 143 | 144 | if ((epNum >= USBD_MAX_EP_COUNT) || 145 | (epNum == 0) || 146 | (dev->ConfigSelector == 0)) 147 | { 148 | } 149 | else if (dev->Setup.RequestType.Type == USB_REQ_TYPE_STANDARD) 150 | { 151 | USBD_EpHandleType *ep = USBD_EpAddr2Ref(dev, epAddr); 152 | 153 | switch (dev->Setup.Request) 154 | { 155 | /* EP halt is the only standard feature */ 156 | case USB_REQ_SET_FEATURE: 157 | { 158 | if (dev->Setup.Value == USB_FEATURE_EP_HALT) 159 | { 160 | retval = USBD_E_OK; 161 | 162 | if (ep->State != USB_EP_STATE_STALL) 163 | { 164 | USBD_PD_EpSetStall(dev, epAddr); 165 | ep->State = USB_EP_STATE_STALL; 166 | } 167 | } 168 | break; 169 | } 170 | 171 | case USB_REQ_CLEAR_FEATURE: 172 | { 173 | if (dev->Setup.Value == USB_FEATURE_EP_HALT) 174 | { 175 | retval = USBD_E_OK; 176 | 177 | if (ep->State == USB_EP_STATE_STALL) 178 | { 179 | USBD_PD_EpClearStall(dev, epAddr); 180 | ep->State = USB_EP_STATE_IDLE; 181 | 182 | ep->Transfer.Length = 0; 183 | /* Workaround: notify interface of ready endpoint 184 | * by completion callback with 0 length */ 185 | if (epAddr != epNum) 186 | { 187 | USBD_IfClass_InData(dev->IF[ep->IfNum], ep); 188 | } 189 | else 190 | { 191 | USBD_IfClass_OutData(dev->IF[ep->IfNum], ep); 192 | } 193 | } 194 | } 195 | break; 196 | } 197 | 198 | /* Report the halt (stall) status of the EP */ 199 | case USB_REQ_GET_STATUS: 200 | { 201 | uint16_t *epStatus = (uint16_t*)dev->CtrlData; 202 | 203 | *epStatus = (ep->State == USB_EP_STATE_STALL) ? 204 | 1 << USB_FEATURE_EP_HALT : 0; 205 | 206 | retval = USBD_CtrlSendData(dev, epStatus, sizeof(*epStatus)); 207 | break; 208 | } 209 | 210 | default: 211 | break; 212 | } 213 | } 214 | else 215 | { 216 | /* Callouts for class or vendor specific 217 | * EP request processing not implemented 218 | * Interface level requests are promoted (and supported) instead */ 219 | } 220 | 221 | return retval; 222 | } 223 | 224 | /** @} */ 225 | -------------------------------------------------------------------------------- /hal/stm32f1xx_hal_msp.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * File Name : stm32f1xx_hal_msp.c 4 | * Description : This file provides code for the MSP Initialization 5 | * and de-Initialization codes. 6 | ****************************************************************************** 7 | * This notice applies to any and all portions of this file 8 | * that are not between comment pairs USER CODE BEGIN and 9 | * USER CODE END. Other portions of this file, whether 10 | * inserted by the user or by software development tools 11 | * are owned by their respective copyright owners. 12 | * 13 | * Copyright (c) 2017 STMicroelectronics International N.V. 14 | * All rights reserved. 15 | * 16 | * Redistribution and use in source and binary forms, with or without 17 | * modification, are permitted, provided that the following conditions are met: 18 | * 19 | * 1. Redistribution of source code must retain the above copyright notice, 20 | * this list of conditions and the following disclaimer. 21 | * 2. Redistributions in binary form must reproduce the above copyright notice, 22 | * this list of conditions and the following disclaimer in the documentation 23 | * and/or other materials provided with the distribution. 24 | * 3. Neither the name of STMicroelectronics nor the names of other 25 | * contributors to this software may be used to endorse or promote products 26 | * derived from this software without specific written permission. 27 | * 4. This software, including modifications and/or derivative works of this 28 | * software, must execute solely and exclusively on microcontroller or 29 | * microprocessor devices manufactured by or for STMicroelectronics. 30 | * 5. Redistribution and use of this software other than as permitted under 31 | * this license is void and will automatically terminate your rights under 32 | * this license. 33 | * 34 | * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" 35 | * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT 36 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 37 | * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY 38 | * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT 39 | * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 40 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 41 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 42 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 43 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 44 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 45 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 46 | * 47 | ****************************************************************************** 48 | */ 49 | /* Includes ------------------------------------------------------------------*/ 50 | #include "stm32f1xx_hal.h" 51 | 52 | extern void _Error_Handler(char *, int); 53 | /* USER CODE BEGIN 0 */ 54 | 55 | /* USER CODE END 0 */ 56 | /** 57 | * Initializes the Global MSP. 58 | */ 59 | void HAL_MspInit(void) 60 | { 61 | /* USER CODE BEGIN MspInit 0 */ 62 | 63 | /* USER CODE END MspInit 0 */ 64 | 65 | __HAL_RCC_AFIO_CLK_ENABLE(); 66 | 67 | HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4); 68 | 69 | /* System interrupt init*/ 70 | /* MemoryManagement_IRQn interrupt configuration */ 71 | HAL_NVIC_SetPriority(MemoryManagement_IRQn, 0, 0); 72 | /* BusFault_IRQn interrupt configuration */ 73 | HAL_NVIC_SetPriority(BusFault_IRQn, 0, 0); 74 | /* UsageFault_IRQn interrupt configuration */ 75 | HAL_NVIC_SetPriority(UsageFault_IRQn, 0, 0); 76 | /* SVCall_IRQn interrupt configuration */ 77 | HAL_NVIC_SetPriority(SVCall_IRQn, 0, 0); 78 | /* DebugMonitor_IRQn interrupt configuration */ 79 | HAL_NVIC_SetPriority(DebugMonitor_IRQn, 0, 0); 80 | /* PendSV_IRQn interrupt configuration */ 81 | HAL_NVIC_SetPriority(PendSV_IRQn, 0, 0); 82 | /* SysTick_IRQn interrupt configuration */ 83 | HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); 84 | 85 | /**NOJTAG: JTAG-DP Disabled and SW-DP Enabled 86 | */ 87 | __HAL_AFIO_REMAP_SWJ_NOJTAG(); 88 | 89 | /* USER CODE BEGIN MspInit 1 */ 90 | 91 | /* USER CODE END MspInit 1 */ 92 | } 93 | 94 | void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base) 95 | { 96 | 97 | if(htim_base->Instance==TIM1) 98 | { 99 | /* USER CODE BEGIN TIM1_MspInit 0 */ 100 | 101 | /* USER CODE END TIM1_MspInit 0 */ 102 | /* Peripheral clock enable */ 103 | __HAL_RCC_TIM1_CLK_ENABLE(); 104 | /* USER CODE BEGIN TIM1_MspInit 1 */ 105 | 106 | /* USER CODE END TIM1_MspInit 1 */ 107 | } 108 | 109 | } 110 | 111 | void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base) 112 | { 113 | 114 | if(htim_base->Instance==TIM1) 115 | { 116 | /* USER CODE BEGIN TIM1_MspDeInit 0 */ 117 | 118 | /* USER CODE END TIM1_MspDeInit 0 */ 119 | /* Peripheral clock disable */ 120 | __HAL_RCC_TIM1_CLK_DISABLE(); 121 | /* USER CODE BEGIN TIM1_MspDeInit 1 */ 122 | 123 | /* USER CODE END TIM1_MspDeInit 1 */ 124 | } 125 | 126 | } 127 | 128 | void HAL_UART_MspInit(UART_HandleTypeDef* huart) 129 | { 130 | 131 | GPIO_InitTypeDef GPIO_InitStruct; 132 | if(huart->Instance==USART1) 133 | { 134 | /* USER CODE BEGIN USART1_MspInit 0 */ 135 | 136 | /* USER CODE END USART1_MspInit 0 */ 137 | /* Peripheral clock enable */ 138 | __HAL_RCC_USART1_CLK_ENABLE(); 139 | 140 | /**USART1 GPIO Configuration 141 | PA9 ------> USART1_TX 142 | PA10 ------> USART1_RX 143 | */ 144 | GPIO_InitStruct.Pin = GPIO_PIN_9; 145 | GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 146 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; 147 | HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 148 | 149 | GPIO_InitStruct.Pin = GPIO_PIN_10; 150 | GPIO_InitStruct.Mode = GPIO_MODE_INPUT; 151 | GPIO_InitStruct.Pull = GPIO_NOPULL; 152 | HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 153 | 154 | /* USER CODE BEGIN USART1_MspInit 1 */ 155 | 156 | /* USER CODE END USART1_MspInit 1 */ 157 | } 158 | 159 | if(huart->Instance==USART3) 160 | { 161 | /* USER CODE BEGIN USART1_MspInit 0 */ 162 | 163 | /* USER CODE END USART1_MspInit 0 */ 164 | /* Peripheral clock enable */ 165 | __HAL_RCC_USART3_CLK_ENABLE(); 166 | 167 | /* Configure USART3 Tx (PB10) as alternate function push-pull */ 168 | GPIO_InitStruct.Pin = GPIO_PIN_10; 169 | GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 170 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; 171 | HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 172 | 173 | /* Configure USART3 Rx (PB11) as input floating */ 174 | GPIO_InitStruct.Pin = GPIO_PIN_11; 175 | GPIO_InitStruct.Mode = GPIO_MODE_INPUT; 176 | GPIO_InitStruct.Pull = GPIO_NOPULL; 177 | HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 178 | } 179 | 180 | } 181 | 182 | void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) 183 | { 184 | 185 | if(huart->Instance==USART1) 186 | { 187 | /* USER CODE BEGIN USART1_MspDeInit 0 */ 188 | 189 | /* USER CODE END USART1_MspDeInit 0 */ 190 | /* Peripheral clock disable */ 191 | __HAL_RCC_USART1_CLK_DISABLE(); 192 | 193 | /**USART1 GPIO Configuration 194 | PA9 ------> USART1_TX 195 | PA10 ------> USART1_RX 196 | */ 197 | HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); 198 | 199 | /* USER CODE BEGIN USART1_MspDeInit 1 */ 200 | 201 | /* USER CODE END USART1_MspDeInit 1 */ 202 | } 203 | 204 | } 205 | 206 | /* USER CODE BEGIN 1 */ 207 | 208 | /* USER CODE END 1 */ 209 | 210 | /** 211 | * @} 212 | */ 213 | 214 | /** 215 | * @} 216 | */ 217 | 218 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 219 | -------------------------------------------------------------------------------- /usb/Include/usbd_hid.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file usbd_hid.h 4 | * @author Benedek Kupper 5 | * @version 0.1 6 | * @date 2018-01-31 7 | * @brief USB Human Interface Device Class 8 | * 9 | * Copyright (c) 2018 Benedek Kupper 10 | * 11 | * Licensed under the Apache License, Version 2.0 (the "License"); 12 | * you may not use this file except in compliance with the License. 13 | * You may obtain a copy of the License at 14 | * 15 | * http://www.apache.org/licenses/LICENSE-2.0 16 | * 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | */ 23 | #ifndef __USBD_HID_H 24 | #define __USBD_HID_H 25 | 26 | #ifdef __cplusplus 27 | extern "C" 28 | { 29 | #endif 30 | 31 | #include 32 | 33 | /** @ingroup USBD 34 | * @addtogroup USBD_Class USBD Classes 35 | * @{ */ 36 | 37 | /** @defgroup USBD_HID Human Interface Device Class (HID) 38 | * @{ */ 39 | 40 | /** @defgroup USBD_HID_Exported_Macros HID Exported Macros 41 | * @{ */ 42 | 43 | #define HID_IDLE_RATE_INDEFINITE 0xFFFF 44 | 45 | /** @} */ 46 | 47 | /** @defgroup USBD_HID_Exported_Types HID Exported Types 48 | * @{ */ 49 | 50 | /** @brief Standard HID control requests */ 51 | typedef enum 52 | { 53 | HID_REQ_SET_REPORT = 0x09, /*!< Send a report to the device, setting the state of 54 | input, output, or feature controls. 55 | wValue.upper = @ref USBD_HID_ReportType 56 | wValue.lower = Report ID */ 57 | HID_REQ_GET_REPORT = 0x01, /*!< Receive a report via the Control pipe. 58 | wValue.upper = @ref USBD_HID_ReportType 59 | wValue.lower = Report ID */ 60 | HID_REQ_SET_IDLE = 0x0A, /*!< Silence an Input report until the data changes 61 | or (wValue.upper * 4) ms elapses (0 => infinite). 62 | wValue.lower = Report ID (0 applies to all reports) */ 63 | HID_REQ_GET_IDLE = 0x02, /*!< Read the current idle rate for an Input report. 64 | wValue.lower = Report ID (0 applies to all reports) */ 65 | 66 | /* Required for Boot subclass devices only */ 67 | HID_REQ_SET_PROTOCOL = 0x0B, /*!< Sets the new protocol. 68 | wValue = @ref USBD_HID_ProtocolType */ 69 | HID_REQ_GET_PROTOCOL = 0x03, /*!< Read which @ref USBD_HID_ProtocolType is currently active. */ 70 | }HID_RequestType, USBD_HID_RequestType; 71 | 72 | 73 | /** @brief HID standard descriptor types */ 74 | typedef enum 75 | { 76 | HID_DESC_TYPE_HID = 0x21, /*!< HID class descriptor */ 77 | HID_DESC_TYPE_REPORT = 0x22, /*!< HID report descriptor */ 78 | HID_DESC_TYPE_PHYSICAL = 0x23, /*!< HID physical descriptor */ 79 | }HID_DescriptorType, USBD_HID_DescriptorType; 80 | 81 | 82 | /** @brief HID report types */ 83 | typedef enum 84 | { 85 | HID_REPORT_INPUT = 0x01, /*!< Report sent by the device */ 86 | HID_REPORT_OUTPUT = 0x02, /*!< Report sent to the device */ 87 | HID_REPORT_FEATURE = 0x03, /*!< Bidirectional configuration report */ 88 | }HID_ReportType, USBD_HID_ReportType; 89 | 90 | 91 | /** @brief HID protocol types */ 92 | typedef enum 93 | { 94 | HID_PROTOCOL_REPORT = 0x01, /*!< Default HID protocol */ 95 | HID_PROTOCOL_BOOT = 0x00, /*!< BOOT protocol */ 96 | }HID_ProtocolType, USBD_HID_ProtocolType; 97 | 98 | 99 | /** @brief HID report configuration structure */ 100 | typedef struct { 101 | const uint8_t* Desc; /*!< Pointer to the report descriptor */ 102 | uint16_t DescLength; /*!< Byte size of the report descriptor */ 103 | uint8_t MaxId; /*!< Largest used report ID (0 if report IDs aren't used) */ 104 | uint8_t DevType; /*!< 0: Def 1:Keyboard 2: Mouse */ 105 | struct { 106 | uint8_t Interval_ms;/*!< Input frame interval in ms */ 107 | uint16_t MaxSize; /*!< Maximal input report size */ 108 | }Input; 109 | struct { 110 | uint16_t MaxSize; /*!< Maximal feature report size */ 111 | }Feature; 112 | struct { 113 | uint8_t Interval_ms;/*!< Output frame interval in ms */ 114 | uint16_t MaxSize; /*!< Maximal output report size */ 115 | }Output; 116 | }HID_ReportConfigType, USBD_HID_ReportConfigType; 117 | 118 | 119 | /** @brief HID application structure */ 120 | typedef struct 121 | { 122 | const char* Name; /*!< String description of the application */ 123 | 124 | const HID_ReportConfigType* Report; /*!< Report configuration */ 125 | 126 | void (*Init) (void* itf); /*!< Initialization request */ 127 | 128 | void (*Deinit) (void* itf); /*!< Shutdown request */ 129 | 130 | void (*SetReport) (void* itf, 131 | USBD_HID_ReportType type, 132 | uint8_t * data, 133 | uint16_t length); /*!< Process a received report */ 134 | 135 | void (*GetReport) (void* itf, 136 | USBD_HID_ReportType type, 137 | uint8_t reportId); /*!< A report transmission is requested */ 138 | 139 | void (*SetIdle) (void* itf, 140 | uint16_t idleRate_ms, 141 | uint8_t reportId); /*!< Limit the IN reporting frequency */ 142 | 143 | #if (USBD_HID_REPORT_STRINGS != 0) 144 | const char* (*GetString)(void* itf, 145 | uint8_t intNum); /*!< Return a string from the report description */ 146 | 147 | #endif 148 | }HID_AppType, USBD_HID_AppType; 149 | 150 | 151 | /** @brief HID interface configuration */ 152 | typedef struct 153 | { 154 | uint8_t InEpNum; /*!< IN endpoint address */ 155 | #if (USBD_HID_OUT_SUPPORT == 1) 156 | uint8_t OutEpNum; /*!< OUT endpoint address */ 157 | #endif 158 | }USBD_HID_ConfigType; 159 | 160 | 161 | /** @brief HID class interface structure */ 162 | typedef struct 163 | { 164 | USBD_IfHandleType Base; /*!< Class-independent interface base */ 165 | const USBD_HID_AppType* App; /*!< HID application reference */ 166 | USBD_HID_ConfigType Config; /*!< HID interface configuration */ 167 | 168 | uint8_t IdleRate; /*!< Contains the current idle rate 169 | @note Report ID separate idle rates are 170 | not readable with the current API. */ 171 | volatile uint8_t Request; /*!< Holds the @ref USBD_HID_ReportType during 172 | control report transfers, otherwise it is 0 */ 173 | }USBD_HID_IfHandleType; 174 | 175 | /** @} */ 176 | 177 | /** @addtogroup USBD_HID_Exported_Functions 178 | * @{ */ 179 | USBD_ReturnType USBD_HID_MountInterface (USBD_HID_IfHandleType *itf, 180 | USBD_HandleType *dev); 181 | 182 | USBD_ReturnType USBD_HID_ReportIn (USBD_HID_IfHandleType *itf, 183 | void *data, 184 | uint16_t length); 185 | 186 | #if (USBD_HID_OUT_SUPPORT == 1) 187 | USBD_ReturnType USBD_HID_ReportOut (USBD_HID_IfHandleType *itf, 188 | void *data, 189 | uint16_t length); 190 | #endif 191 | /** @} */ 192 | 193 | /** @} */ 194 | 195 | /** @} */ 196 | 197 | #ifdef __cplusplus 198 | } 199 | #endif 200 | 201 | #endif /* __USBD_HID_H */ 202 | -------------------------------------------------------------------------------- /usb/Device/usbd_ctrl.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file usbd_ctrl.c 4 | * @author Benedek Kupper 5 | * @version 0.1 6 | * @date 2018-01-31 7 | * @brief Universal Serial Bus Device Driver 8 | * Control transfer management 9 | * 10 | * Copyright (c) 2018 Benedek Kupper 11 | * 12 | * Licensed under the Apache License, Version 2.0 (the "License"); 13 | * you may not use this file except in compliance with the License. 14 | * You may obtain a copy of the License at 15 | * 16 | * http://www.apache.org/licenses/LICENSE-2.0 17 | * 18 | * Unless required by applicable law or agreed to in writing, software 19 | * distributed under the License is distributed on an "AS IS" BASIS, 20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | * See the License for the specific language governing permissions and 22 | * limitations under the License. 23 | */ 24 | #include 25 | 26 | /** @ingroup USBD_Private 27 | * @defgroup USBD_Private_Functions_Ctrl USBD Control Request Handling 28 | * @{ */ 29 | 30 | /** 31 | * @brief This function indicates a failed control request by stalling EP0. 32 | * @param dev: USB Device handle reference 33 | */ 34 | static void USBD_CtrlSendError(USBD_HandleType *dev) 35 | { 36 | USBD_PD_EpSetStall(dev, 0x80); 37 | dev->EP.IN [0].State = USB_EP_STATE_STALL; 38 | USBD_PD_EpSetStall(dev, 0x00); 39 | dev->EP.OUT[0].State = USB_EP_STATE_STALL; 40 | } 41 | 42 | /** 43 | * @brief This function indicates a successful control data OUT stage by sending ZLP on EP0. 44 | * @param dev: USB Device handle reference 45 | */ 46 | static void USBD_CtrlSendStatus(USBD_HandleType *dev) 47 | { 48 | dev->EP.IN[0].State = USB_EP_STATE_STATUS; 49 | USBD_PD_EpSend(dev, 0x80, NULL, 0); 50 | } 51 | 52 | /** 53 | * @brief This function indicates a successful control data IN stage by receiving ZLP on EP0. 54 | * @param dev: USB Device handle reference 55 | */ 56 | static void USBD_CtrlReceiveStatus(USBD_HandleType *dev) 57 | { 58 | dev->EP.OUT[0].State = USB_EP_STATE_STATUS; 59 | USBD_PD_EpReceive(dev, 0x00, NULL, 0); 60 | } 61 | 62 | /** 63 | * @brief This function manages the end of a control IN endpoint transfer: 64 | * - Send Zero Length Packet if the end of the transfer is ambiguous 65 | * - Provide completion callback and OUT status stage if it was a data stage 66 | * - Set device address if it was requested 67 | * @param dev: USB Device handle reference 68 | */ 69 | void USBD_CtrlInCallback(USBD_HandleType *dev) 70 | { 71 | /* Last packet is MPS multiple, so send ZLP packet */ 72 | if (( dev->EP.IN[0].Transfer.Length < dev->Setup.Length) && 73 | ( dev->EP.IN[0].Transfer.Length >= dev->EP.IN[0].MaxPacketSize) && 74 | ((dev->EP.IN[0].Transfer.Length & (dev->EP.IN[0].MaxPacketSize - 1)) == 0)) 75 | { 76 | USBD_PD_EpSend(dev, 0x80, NULL, 0); 77 | } 78 | else 79 | { 80 | dev->EP.IN[0].State = USB_EP_STATE_IDLE; 81 | 82 | /* If the callback is from a Data stage */ 83 | if (dev->Setup.RequestType.Direction == USB_DIRECTION_IN) 84 | { 85 | /* Only call back if the IF was serving the request */ 86 | if ((dev->ConfigSelector != 0) && 87 | (dev->Setup.RequestType.Recipient == USB_REQ_RECIPIENT_INTERFACE)) 88 | { 89 | /* If callback for transmitted EP0 data */ 90 | USBD_IfClass_DataStage(dev->IF[(uint8_t)dev->Setup.Index]); 91 | } 92 | 93 | /* Proceed to Status stage */ 94 | USBD_CtrlReceiveStatus(dev); 95 | } 96 | #if (USBD_SET_ADDRESS_IMMEDIATE != 1) 97 | /* If the address was set by the last request, apply it now */ 98 | else if ((dev->Setup.RequestType.b == 0x00) && 99 | (dev->Setup.Request == USB_REQ_SET_ADDRESS)) 100 | { 101 | USBD_PD_SetAddress(dev, dev->Setup.Value & 0x7F); 102 | } 103 | #endif 104 | } 105 | } 106 | 107 | /** 108 | * @brief This function manages the end of a control OUT endpoint transfer: 109 | * - Provide completion callback and IN status stage if it was a data stage 110 | * @param dev: USB Device handle reference 111 | */ 112 | void USBD_CtrlOutCallback(USBD_HandleType *dev) 113 | { 114 | /* If the callback is from a Data stage */ 115 | if ((dev->Setup.Length > 0) && 116 | (dev->Setup.RequestType.Direction == USB_DIRECTION_OUT)) 117 | { 118 | /* Standard requests have no OUT direction data stage -> must be IF related */ 119 | if (dev->ConfigSelector != 0) 120 | { 121 | /* If callback for received EP0 data */ 122 | USBD_IfClass_DataStage(dev->IF[(uint8_t)dev->Setup.Index]); 123 | } 124 | 125 | /* Proceed to Status stage */ 126 | USBD_CtrlSendStatus(dev); 127 | } 128 | } 129 | 130 | /** @} */ 131 | 132 | /** @addtogroup USBD_Internal_Functions 133 | * @{ */ 134 | 135 | /** 136 | * @brief This function sends data through the control endpoint in response to a setup request. 137 | * @param dev: USB Device handle reference 138 | * @param data: pointer to the data to send 139 | * @param len: length of the data 140 | * @return OK if called from the right context, ERROR otherwise 141 | */ 142 | USBD_ReturnType USBD_CtrlSendData(USBD_HandleType *dev, void *data, uint16_t len) 143 | { 144 | USBD_ReturnType retval = USBD_E_ERROR; 145 | 146 | /* Sanity check */ 147 | if (dev->EP.OUT[0].State == USB_EP_STATE_SETUP) 148 | { 149 | /* Don't send more bytes than requested */ 150 | if (dev->Setup.Length < len) 151 | { 152 | len = dev->Setup.Length; 153 | } 154 | 155 | dev->EP.IN[0].State = USB_EP_STATE_DATA; 156 | USBD_PD_EpSend(dev, 0x80, (const uint8_t*)data, len); 157 | 158 | retval = USBD_E_OK; 159 | } 160 | return retval; 161 | } 162 | 163 | /** 164 | * @brief This function receives control data according to the setup request. 165 | * @param dev: USB Device handle reference 166 | * @param data: pointer to the target buffer to receive to 167 | * @return OK if called from the right context, ERROR otherwise 168 | */ 169 | USBD_ReturnType USBD_CtrlReceiveData(USBD_HandleType *dev, void *data) 170 | { 171 | USBD_ReturnType retval = USBD_E_ERROR; 172 | 173 | /* Sanity check */ 174 | if (dev->EP.OUT[0].State == USB_EP_STATE_SETUP) 175 | { 176 | uint16_t len = dev->Setup.Length; 177 | 178 | dev->EP.OUT[0].State = USB_EP_STATE_DATA; 179 | USBD_PD_EpReceive(dev, 0x00, (uint8_t*)data, len); 180 | 181 | retval = USBD_E_OK; 182 | } 183 | return retval; 184 | } 185 | 186 | /** @} */ 187 | 188 | /** @addtogroup USBD_Exported_Functions 189 | * @{ */ 190 | 191 | /** 192 | * @brief This function routes the setup request depending on the recipient 193 | * and performs the endpoint's status stage if no data stage is requested 194 | * or the request wasn't accepted. 195 | * @param dev: USB Device handle reference 196 | */ 197 | void USBD_SetupCallback(USBD_HandleType *dev) 198 | { 199 | USBD_ReturnType retval = USBD_E_INVALID; 200 | 201 | dev->EP.OUT[0].State = USB_EP_STATE_SETUP; 202 | 203 | /* Route the request to the recipient */ 204 | switch (dev->Setup.RequestType.Recipient) 205 | { 206 | case USB_REQ_RECIPIENT_DEVICE: 207 | retval = USBD_DevRequest(dev); 208 | break; 209 | 210 | case USB_REQ_RECIPIENT_INTERFACE: 211 | retval = USBD_IfRequest(dev); 212 | break; 213 | 214 | case USB_REQ_RECIPIENT_ENDPOINT: 215 | retval = USBD_EpRequest(dev); 216 | break; 217 | 218 | default: 219 | break; 220 | } 221 | 222 | /* If the request was rejected, send Request Error (EP0 STALL) */ 223 | if (retval != USBD_E_OK) 224 | { 225 | USBD_CtrlSendError(dev); 226 | } 227 | /* If the wLength is 0, there is no Data stage, 228 | * send positive status (EP0 ZLP) */ 229 | else if (dev->Setup.Length == 0) 230 | { 231 | USBD_CtrlSendStatus(dev); 232 | } 233 | else 234 | { 235 | /* Data stage starts in the requested direction */ 236 | } 237 | } 238 | 239 | /** @} */ 240 | -------------------------------------------------------------------------------- /usb/Xpd/xpd_usb.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file xpd_usb.h 4 | * @author Benedek Kupper 5 | * @version 0.3 6 | * @date 2018-01-28 7 | * @brief STM32 eXtensible Peripheral Drivers Universal Serial Bus Module 8 | * 9 | * Copyright (c) 2018 Benedek Kupper 10 | * 11 | * Licensed under the Apache License, Version 2.0 (the "License"); 12 | * you may not use this file except in compliance with the License. 13 | * You may obtain a copy of the License at 14 | * 15 | * http://www.apache.org/licenses/LICENSE-2.0 16 | * 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, 19 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | */ 23 | #ifndef __XPD_USB_H_ 24 | #define __XPD_USB_H_ 25 | 26 | #ifdef __cplusplus 27 | extern "C" 28 | { 29 | #endif 30 | 31 | #include 32 | 33 | #if defined(USB_OTG_FS) 34 | #include 35 | 36 | #define USB_vInit USB_vDevInit 37 | #define USB_vDeinit USB_vDevDeinit 38 | #define USB_vStart_IT USB_vDevStart_IT 39 | #define USB_vStop_IT USB_vDevStop_IT 40 | #define USB_vIRQHandler USB_vDevIRQHandler 41 | 42 | #elif defined(USB) 43 | #include 44 | 45 | /** @defgroup USB 46 | * @{ */ 47 | 48 | /** @defgroup USB_Exported_Types USB Exported Types 49 | * @{ */ 50 | 51 | /** @brief USB Power Source types */ 52 | typedef enum 53 | { 54 | USB_BCD_NO_DATA_CONTACT = 0, /*!< Data lines are floating on the device side */ 55 | USB_BCD_STANDARD_DOWNSTREAM_PORT = 1, /*!< Standard Downstream Port */ 56 | USB_BCD_CHARGING_DOWNSTREAM_PORT = 2, /*!< Charging Downstream Port detected */ 57 | USB_BCD_DEDICATED_CHARGING_PORT = 3, /*!< Dedicated Charging Port detected */ 58 | USB_BCD_PS2_PROPRIETARY_PORT = 4, /*!< PS2 or proprietary charging port detected */ 59 | USB_BCD_NOT_SUPPORTED = 0xFF /*!< Battery Charge Detection is not supported on the device */ 60 | }USB_ChargerType; 61 | 62 | /** @defgroup USB_Exported_Macros USB Exported Macros 63 | * @{ */ 64 | 65 | /** 66 | * @brief USB Instance to handle binder macro 67 | * @param HANDLE: specifies the peripheral handle. 68 | * @param INSTANCE: specifies the USB peripheral instance. 69 | */ 70 | #define USB_INST2HANDLE(HANDLE,INSTANCE) ((void)INSTANCE) 71 | 72 | #ifdef USB_BB 73 | /** 74 | * @brief USB register bit accessing macro 75 | * @param HANDLE: specifies the peripheral handle. 76 | * @param REG_NAME: specifies the register name. 77 | * @param BIT_NAME: specifies the register bit name. 78 | */ 79 | #define USB_REG_BIT(HANDLE, REG_NAME, BIT_NAME) \ 80 | (USB_BB->REG_NAME.BIT_NAME) 81 | 82 | #else 83 | /** 84 | * @brief USB register bit accessing macro 85 | * @param HANDLE: specifies the peripheral handle. 86 | * @param REG_NAME: specifies the register name. 87 | * @param BIT_NAME: specifies the register bit name. 88 | */ 89 | #define USB_REG_BIT(HANDLE, REG_NAME, BIT_NAME) \ 90 | (USB->REG_NAME.b.BIT_NAME) 91 | 92 | #endif /* USB_BB */ 93 | 94 | /** 95 | * @brief Enable the specified USB interrupt. 96 | * @param HANDLE: specifies the USB Handle. 97 | * @param IT_NAME: specifies the interrupt to enable. 98 | * This parameter can be one of the following values: 99 | * @arg ESOF: Expected start of frame 100 | * @arg SOF: Start of frame 101 | * @arg RESET: Reset 102 | * @arg SUSP: Suspend 103 | * @arg WKUP: Wake up 104 | * @arg L1REQ: L1 sleep mode request 105 | * @arg ERR: Error 106 | * @arg PMAOVR: Packet memory overrun 107 | * @arg CTR: Correct transfer 108 | */ 109 | #define USB_IT_ENABLE( HANDLE, IT_NAME) \ 110 | (USB_REG_BIT(HANDLE,CNTR,IT_NAME##M) = 1) 111 | 112 | /** 113 | * @brief Disable the specified USB interrupt. 114 | * @param HANDLE: specifies the USB Handle. 115 | * @param IT_NAME: specifies the interrupt to disable. 116 | * This parameter can be one of the following values: 117 | * @arg ESOF: Expected start of frame 118 | * @arg SOF: Start of frame 119 | * @arg RESET: Reset 120 | * @arg SUSP: Suspend 121 | * @arg WKUP: Wake up 122 | * @arg L1REQ: L1 sleep mode request 123 | * @arg ERR: Error 124 | * @arg PMAOVR: Packet memory overrun 125 | * @arg CTR: Correct transfer 126 | */ 127 | #define USB_IT_DISABLE( HANDLE, IT_NAME) \ 128 | (USB_REG_BIT(HANDLE,CNTR,IT_NAME##M) = 0) 129 | 130 | /** 131 | * @brief Get the specified USB flag. 132 | * @param HANDLE: specifies the USB Handle. 133 | * @param FLAG_NAME: specifies the flag to return. 134 | * This parameter can be one of the following values: 135 | * @arg ESOF: Expected start of frame 136 | * @arg SOF: Start of frame 137 | * @arg RESET: Reset 138 | * @arg SUSP: Suspend 139 | * @arg WKUP: Wake up 140 | * @arg L1REQ: L1 sleep mode request 141 | * @arg ERR: Error 142 | * @arg PMAOVR: Packet memory overrun 143 | * @arg CTR: Correct transfer 144 | */ 145 | #define USB_FLAG_STATUS( HANDLE, FLAG_NAME) \ 146 | (USB_REG_BIT(HANDLE,ISTR,FLAG_NAME)) 147 | 148 | /** 149 | * @brief Clear the specified USB flag. 150 | * @param HANDLE: specifies the USB Handle. 151 | * @param FLAG_NAME: specifies the flag to clear. 152 | * This parameter can be one of the following values: 153 | * @arg ESOF: Expected start of frame 154 | * @arg SOF: Start of frame 155 | * @arg RESET: Reset 156 | * @arg SUSP: Suspend 157 | * @arg WKUP: Wake up 158 | * @arg ERR: Error 159 | * @arg PMAOVR: Packet memory overrun 160 | * @arg CTR: Correct transfer 161 | */ 162 | #define USB_FLAG_CLEAR(HANDLE, FLAG_NAME) \ 163 | (USB_REG_BIT(HANDLE,ISTR,FLAG_NAME) = 0) 164 | 165 | /** @} */ 166 | 167 | /** @addtogroup USB_Exported_Functions 168 | * @{ */ 169 | void USB_vInit (USB_HandleType * pxUSB, const USB_InitType * pxConfig); 170 | void USB_vDeinit (USB_HandleType * pxUSB); 171 | 172 | void USB_vStart_IT (USB_HandleType * pxUSB); 173 | void USB_vStop_IT (USB_HandleType * pxUSB); 174 | 175 | void USB_vSetAddress (USB_HandleType * pxUSB, uint8_t ucAddress); 176 | void USB_vCtrlEpOpen (USB_HandleType * pxUSB); 177 | 178 | void USB_vEpOpen (USB_HandleType * pxUSB, uint8_t ucEpAddress, 179 | USB_EndPointType eType, uint16_t usMaxPacketSize); 180 | void USB_vEpClose (USB_HandleType * pxUSB, uint8_t ucEpAddress); 181 | void USB_vEpSetStall (USB_HandleType * pxUSB, uint8_t ucEpAddress); 182 | void USB_vEpClearStall (USB_HandleType * pxUSB, uint8_t ucEpAddress); 183 | 184 | void USB_vEpSend (USB_HandleType * pxUSB, uint8_t ucEpAddress, 185 | const uint8_t * pucData, uint16_t usLength); 186 | void USB_vEpReceive (USB_HandleType * pxUSB, uint8_t ucEpAddress, 187 | uint8_t * pucData, uint16_t usLength); 188 | 189 | void USB_vSetRemoteWakeup (USB_HandleType * pxUSB); 190 | void USB_vClearRemoteWakeup (USB_HandleType * pxUSB); 191 | 192 | void USB_vIRQHandler (USB_HandleType * pxUSB); 193 | 194 | USB_ChargerType USB_eChargerDetect (USB_HandleType * pxUSB); 195 | 196 | /* Used internally, has a weak definition */ 197 | void USB_vAllocateEPs (USB_HandleType * pxUSB); 198 | /** @} */ 199 | 200 | /** @} */ 201 | 202 | #define XPD_USB_API 203 | #include 204 | #include 205 | #undef XPD_USB_API 206 | 207 | #endif /* defined(USB) */ 208 | 209 | #ifdef __cplusplus 210 | } 211 | #endif 212 | 213 | #endif /* __XPD_USB_H_ */ 214 | -------------------------------------------------------------------------------- /usb/Templates/console_if.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file console_if.c 4 | * @author Benedek Kupper 5 | * @version 0.2 6 | * @date 2018-12-16 7 | * @brief USB serial console interface 8 | * 9 | * @details 10 | * This CDC interface can be used to channel standard I/O operations through 11 | * a virtual serial port: 12 | * @code 13 | * #include 14 | * extern USBD_CDC_IfHandleType *const console_if; 15 | * @endcode 16 | * After configuring it's endpoint numbers it can be mounted on a USB device. 17 | * Define STDOUT_BUFFER_SIZE with an appropriate buffer size to enable output, 18 | * STDIN_BUFFER_SIZE to enable input functionality. (Twice the max packet size 19 | * is recommended.) 20 | * The interface becomes operational after the serial port's line coding is set 21 | * (with any standard baudrate value). 22 | * 23 | * 24 | * Copyright (c) 2018 Benedek Kupper 25 | * 26 | * Licensed under the Apache License, Version 2.0 (the "License"); 27 | * you may not use this file except in compliance with the License. 28 | * You may obtain a copy of the License at 29 | * 30 | * http://www.apache.org/licenses/LICENSE-2.0 31 | * 32 | * Unless required by applicable law or agreed to in writing, software 33 | * distributed under the License is distributed on an "AS IS" BASIS, 34 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 35 | * See the License for the specific language governing permissions and 36 | * limitations under the License. 37 | */ 38 | #include 39 | 40 | #include 41 | #include 42 | #include 43 | 44 | #undef errno 45 | extern int32_t errno; 46 | 47 | /** @defgroup Templates */ 48 | 49 | /** @ingroup Templates 50 | * @defgroup console_if USB serial console interface 51 | * @{ */ 52 | 53 | static void console_if_open (void* itf, USBD_CDC_LineCodingType * lc); 54 | 55 | #if (STDOUT_BUFFER_SIZE > 0) 56 | 57 | static const uint16_t console_in_size = STDOUT_BUFFER_SIZE; 58 | 59 | static struct { 60 | uint16_t head; 61 | uint16_t tail; 62 | uint8_t buffer[STDOUT_BUFFER_SIZE + 1]; 63 | }console_if_IN; 64 | 65 | static void console_if_in_cmplt (void* itf, uint8_t * pbuf, uint16_t length); 66 | static void console_if_send (void); 67 | #endif 68 | 69 | #if (STDIN_BUFFER_SIZE > 0) 70 | 71 | static const uint16_t console_out_size = STDIN_BUFFER_SIZE; 72 | 73 | static struct { 74 | uint16_t head; 75 | uint16_t tail; 76 | uint8_t buffer[STDIN_BUFFER_SIZE + 1]; 77 | }console_if_OUT; 78 | 79 | static void console_if_out_cmplt (void* itf, uint8_t * pbuf, uint16_t length); 80 | static void console_if_recv (void); 81 | #endif 82 | 83 | static const USBD_CDC_AppType console_app = 84 | { 85 | .Name = "Serial port as standard I/O", 86 | .Open = console_if_open, 87 | #if (STDIN_BUFFER_SIZE > 0) 88 | .Received = console_if_out_cmplt, 89 | #endif 90 | #if (STDOUT_BUFFER_SIZE > 0) 91 | .Transmitted = console_if_in_cmplt, 92 | #endif 93 | }; 94 | 95 | USBD_CDC_IfHandleType _console_if = { 96 | .App = &console_app, 97 | .Base.AltCount = 1, 98 | }, *const console_if = &_console_if; 99 | 100 | static void console_if_open(void* itf, USBD_CDC_LineCodingType * lc) 101 | { 102 | #if (STDOUT_BUFFER_SIZE > 0) 103 | console_if_IN.head = console_if_IN.tail = 0; 104 | #endif 105 | #if (STDIN_BUFFER_SIZE > 0) 106 | console_if_OUT.head = console_if_OUT.tail = 0; 107 | console_if_recv(); 108 | #endif 109 | } 110 | 111 | #if (STDOUT_BUFFER_SIZE > 0) 112 | static void console_if_in_cmplt(void* itf, uint8_t * pbuf, uint16_t length) 113 | { 114 | if (console_if_IN.tail < console_in_size) 115 | console_if_IN.tail += length; 116 | else 117 | console_if_IN.tail = length - 1; 118 | console_if_send(); 119 | } 120 | 121 | static void console_if_send(void) 122 | { 123 | uint16_t head = console_if_IN.head, tail = console_if_IN.tail; 124 | uint16_t start = tail + 1, length; 125 | 126 | if (tail <= head) 127 | { 128 | length = head - tail; 129 | } 130 | else if (tail < console_in_size) 131 | { 132 | length = console_in_size - tail; 133 | } 134 | else 135 | { 136 | length = head + 1; 137 | start = 0; 138 | } 139 | 140 | if (length > 0) 141 | { 142 | USBD_CDC_Transmit(console_if, 143 | &console_if_IN.buffer[start], length); 144 | } 145 | } 146 | 147 | int _write(int32_t file, uint8_t *ptr, int32_t len) 148 | { 149 | int retval = -1; 150 | uint16_t head = console_if_IN.head, tail = console_if_IN.tail; 151 | 152 | if (console_if->LineCoding.DataBits == 0) 153 | { 154 | errno = -EIO; 155 | } 156 | else if (((tail > head) ? 157 | (tail - head - 1) : (console_in_size - (head - tail))) < len) 158 | { 159 | errno = -ENOMEM; 160 | } 161 | else 162 | { 163 | uint16_t len1, len2 = 0; 164 | 165 | if (tail > head) 166 | { 167 | /* continuous */ 168 | len1 = tail - head - 1; 169 | if (len < len1) 170 | len1 = len; 171 | } 172 | else 173 | { 174 | /* two chunks */ 175 | len1 = console_in_size - head; 176 | 177 | if (len <= len1) 178 | len1 = len; 179 | else if (len < (len1 + tail)) 180 | len2 = len - len1; 181 | else 182 | len2 = tail; 183 | } 184 | 185 | /* first chunk is copied starting from current head */ 186 | memcpy(&console_if_IN.buffer[head + 1], ptr, len1); 187 | console_if_IN.head += len1; 188 | ptr += len1; 189 | 190 | /* the remaining chunk is copied from the buffer start */ 191 | if (len2 > 0) 192 | { 193 | memcpy(&console_if_IN.buffer[0], ptr, len2); 194 | console_if_IN.head = len2 - 1; 195 | } 196 | 197 | retval = len1 + len2; 198 | console_if_send(); 199 | } 200 | return retval; 201 | } 202 | #endif 203 | 204 | #if (STDIN_BUFFER_SIZE > 0) 205 | static void console_if_out_cmplt(void* itf, uint8_t * pbuf, uint16_t length) 206 | { 207 | if (console_if_OUT.head < console_out_size) 208 | console_if_OUT.head += length; 209 | else 210 | console_if_OUT.head = length - 1; 211 | console_if_recv(); 212 | } 213 | 214 | static void console_if_recv(void) 215 | { 216 | uint16_t tail = console_if_OUT.tail, head = console_if_OUT.head; 217 | uint16_t start = head + 1, length; 218 | 219 | if (tail > head) 220 | { 221 | length = tail - head - 1; 222 | } 223 | else if (head < console_out_size) 224 | { 225 | length = console_out_size - head; 226 | } 227 | else 228 | { 229 | length = tail; 230 | start = 0; 231 | } 232 | 233 | if (length > 0) 234 | { 235 | USBD_CDC_Receive(console_if, 236 | &console_if_OUT.buffer[start], length); 237 | } 238 | } 239 | 240 | int _read(int32_t file, uint8_t *ptr, int32_t len) 241 | { 242 | int retval = -1; 243 | uint16_t tail = console_if_OUT.tail, head = console_if_OUT.head; 244 | 245 | if (console_if->LineCoding.DataBits == 0) 246 | { 247 | errno = -EIO; 248 | } 249 | else 250 | { 251 | uint16_t len1, len2 = 0; 252 | 253 | if (tail <= head) 254 | { 255 | /* continuous */ 256 | len1 = head - tail; 257 | if (len < len1) 258 | len1 = len; 259 | } 260 | else 261 | { 262 | /* two chunks */ 263 | len1 = console_out_size - tail; 264 | 265 | if (len <= len1) 266 | len1 = len; 267 | else if (len < (len1 + head + 1)) 268 | len2 = len - len1; 269 | else 270 | len2 = head + 1; 271 | } 272 | 273 | /* first chunk is copied starting from current tail */ 274 | memcpy(ptr, &console_if_OUT.buffer[tail + 1], len1); 275 | console_if_OUT.tail += len1; 276 | ptr += len1; 277 | 278 | /* the remaining chunk is copied from the buffer start */ 279 | if (len2 > 0) 280 | { 281 | memcpy(ptr, &console_if_OUT.buffer[0], len2); 282 | console_if_OUT.tail = len2 - 1; 283 | } 284 | 285 | retval = len1 + len2; 286 | if (retval > 0) 287 | console_if_recv(); 288 | } 289 | return retval; 290 | } 291 | #endif 292 | 293 | /** @} */ 294 | --------------------------------------------------------------------------------