diff --git a/CMakeLists.txt b/CMakeLists.txt index 4165c4b..b74b42c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ include_directories(Middlewares/ST/STM32_USB_Device_Library/Class/HID/Inc) include_directories(Middlewares/ST/STM32_USB_Device_Library/Core/Inc) add_definitions(-DSTM32F103x6) -add_executable(${PROJECT_NAME}.elf ${USER_SOURCES} ${LINKER_SCRIPT} Inc/main.h) +add_executable(${PROJECT_NAME}.elf ${USER_SOURCES} ${LINKER_SCRIPT}) target_link_libraries(${PROJECT_NAME}.elf HAL CMSIS USBFS) diff --git a/Inc/circbuf.h b/Inc/circbuf.h new file mode 100644 index 0000000..9331628 --- /dev/null +++ b/Inc/circbuf.h @@ -0,0 +1,96 @@ +/** + * @file circbuf.h + * @author Ondřej Hruška, 2016 + * + * Circular buffer / queue / stack. + * Slots are pre-allocated, values are copied into the buffer. + * + * The buffer may be used as a stack, event queue or a simple buffer. + * + * ------------------------------------- + * + * NW LR + * append -> [][][][] -> pop + * <- push + * + * NW - next write pointer (stack base) + * LR - last read position (stack top) + * + * ------------------------------------- + * + * MIT license + */ + +#ifndef F103_USB_CIRCBUF_H +#define F103_USB_CIRCBUF_H + +#include +#include +#include + + +typedef struct circbuf_struct CircBuf; + + +/** + * @brief Initialize a circular buffer. The buffer is malloc'd. + * @param capacity : buffer capacity + * @param elem_size : size of one element + * @return pointer to the buffer instance + */ +CircBuf *cbuf_create(size_t capacity, size_t elem_size); + + +/** + * @brief Destroy a buffer, freeing used memory. + * + * @attention + * If the buffer items have malloc'd members, you have + * to free them manually to avoid a memory leak. + * + * @param cb : buffer + */ +void cbuf_destroy(CircBuf *cb); + + +/** Test for full buffer */ +bool cbuf_full(const CircBuf *cb); + + +/** Test for empty buffer */ +bool cbuf_empty(const CircBuf *cb); + + +/** + * @brief Append a value to the buffer (FIFO) + * @param cb : buffer + * @param source : pointer to a value (will be copied) + * @return success + */ +bool cbuf_append(CircBuf *cb, const void *source); + + +/** + * @brief Push a value into the circbuf (LIFO). + * + * @param cb : buffer + * @param source : pointer to a value (will be copied) + * @return success + */ +bool cbuf_push(CircBuf *cb, const void *source); + + +/** + * @brief Read a value from the buffer, return success. + * + * @param cb : buffer + * @param dest : read destionation. If NULL, value is discarded. + * @return success + */ +bool cbuf_pop(CircBuf *cb, void *dest); + + +/** @brief Remove all data from buffer */ +void cbuf_clear(CircBuf *cb); + +#endif // F103_USB_CIRCBUF_H diff --git a/Inc/keyboard.h b/Inc/keyboard.h new file mode 100644 index 0000000..31c7540 --- /dev/null +++ b/Inc/keyboard.h @@ -0,0 +1,339 @@ +// +// Created by MightyPork on 7.8.16. +// + +#ifndef F103_USB_KEYBOARD_H +#define F103_USB_KEYBOARD_H + +#include +#include + +/** Max nr of simultaneous keys pressed */ +#define KYBD_SLOTS 6 + +/** Struct that can be used for key buffers */ +typedef struct { + uint8_t key; + bool press; +} KeyEvent; + +/** + * Toggle key state + * + * @param key : key code + * @param press : key pressed / released + */ +bool kybd_key(uint8_t key, bool press); + +/** + * Toggle modifier + * + * @param mod : Modifier mask + * @param press : Modifier pressed / released + */ +void kybd_mod(uint8_t mod, bool press); + +/** + * Press a key + * + * @param key : key code + */ +bool kybd_press(uint8_t key); + +/** + * Release a key + * + * @param key : key code + */ +bool kybd_release(uint8_t key); + +/** + * Release all keys and cancel all modifiers + */ +void kybd_clear(); + +/** + * Get keyboard bytes for the USB HID report. + * + * @param arr : array long at least KYBD_SLOTS + 2 + */ +void kybd_get_bytes(uint8_t *arr); + +/* ----------------------------------------------------------- */ + +/** + * Modifier masks. Those may be used to directly set modifier status, + * as opposed to modifier Scan Codes 0xe0 - 0xe7, which do the same, + * but via the key press/release interface. + */ +#define MOD_LCTRL 0x01 +#define MOD_LSHIFT 0x02 +#define MOD_LALT 0x04 +#define MOD_LMETA 0x08 +#define MOD_RCTRL 0x10 +#define MOD_RSHIFT 0x20 +#define MOD_RALT 0x40 +#define MOD_RMETA 0x80 + +/** + * USB HID Keyboard scan codes as per USB spec 1.11 + * plus some additional codes + * + * Created by MightyPork, 2016 + * Public domain + * + * Adapted from: + * https://source.android.com/devices/input/keyboard-devices.html + */ +#define KEY_NONE 0x00 +#define KEY_ERR_OVF 0x01 // Keyboard Error Roll Over - used for all slots if too many keys are pressed ("Phantom key") +// 0x02 // Keyboard POST Fail +// 0x03 // Keyboard Error Undefined +#define KEY_A 0x04 // Keyboard a and A +#define KEY_B 0x05 // Keyboard b and B +#define KEY_C 0x06 // Keyboard c and C +#define KEY_D 0x07 // Keyboard d and D +#define KEY_E 0x08 // Keyboard e and E +#define KEY_F 0x09 // Keyboard f and F +#define KEY_G 0x0a // Keyboard g and G +#define KEY_H 0x0b // Keyboard h and H +#define KEY_I 0x0c // Keyboard i and I +#define KEY_J 0x0d // Keyboard j and J +#define KEY_K 0x0e // Keyboard k and K +#define KEY_L 0x0f // Keyboard l and L +#define KEY_M 0x10 // Keyboard m and M +#define KEY_N 0x11 // Keyboard n and N +#define KEY_O 0x12 // Keyboard o and O +#define KEY_P 0x13 // Keyboard p and P +#define KEY_Q 0x14 // Keyboard q and Q +#define KEY_R 0x15 // Keyboard r and R +#define KEY_S 0x16 // Keyboard s and S +#define KEY_T 0x17 // Keyboard t and T +#define KEY_U 0x18 // Keyboard u and U +#define KEY_V 0x19 // Keyboard v and V +#define KEY_W 0x1a // Keyboard w and W +#define KEY_X 0x1b // Keyboard x and X +#define KEY_Y 0x1c // Keyboard y and Y +#define KEY_Z 0x1d // Keyboard z and Z + +#define KEY_1 0x1e // Keyboard 1 and ! +#define KEY_2 0x1f // Keyboard 2 and @ +#define KEY_3 0x20 // Keyboard 3 and # +#define KEY_4 0x21 // Keyboard 4 and $ +#define KEY_5 0x22 // Keyboard 5 and % +#define KEY_6 0x23 // Keyboard 6 and ^ +#define KEY_7 0x24 // Keyboard 7 and & +#define KEY_8 0x25 // Keyboard 8 and * +#define KEY_9 0x26 // Keyboard 9 and ( +#define KEY_0 0x27 // Keyboard 0 and ) + +#define KEY_ENTER 0x28 // Keyboard Return (ENTER) +#define KEY_ESC 0x29 // Keyboard ESCAPE +#define KEY_BACKSPACE 0x2a // Keyboard DELETE (Backspace) +#define KEY_TAB 0x2b // Keyboard Tab +#define KEY_SPACE 0x2c // Keyboard Spacebar +#define KEY_MINUS 0x2d // Keyboard - and _ +#define KEY_EQUAL 0x2e // Keyboard = and + +#define KEY_LEFTBRACE 0x2f // Keyboard [ and { +#define KEY_RIGHTBRACE 0x30 // Keyboard ] and } +#define KEY_BACKSLASH 0x31 // Keyboard \ and | +#define KEY_HASHTILDE 0x32 // Keyboard Non-US # and ~ +#define KEY_SEMICOLON 0x33 // Keyboard ; and : +#define KEY_APOSTROPHE 0x34 // Keyboard ' and " +#define KEY_GRAVE 0x35 // Keyboard ` and ~ +#define KEY_COMMA 0x36 // Keyboard , and < +#define KEY_DOT 0x37 // Keyboard . and > +#define KEY_SLASH 0x38 // Keyboard / and ? +#define KEY_CAPSLOCK 0x39 // Keyboard Caps Lock + +#define KEY_F1 0x3a // Keyboard F1 +#define KEY_F2 0x3b // Keyboard F2 +#define KEY_F3 0x3c // Keyboard F3 +#define KEY_F4 0x3d // Keyboard F4 +#define KEY_F5 0x3e // Keyboard F5 +#define KEY_F6 0x3f // Keyboard F6 +#define KEY_F7 0x40 // Keyboard F7 +#define KEY_F8 0x41 // Keyboard F8 +#define KEY_F9 0x42 // Keyboard F9 +#define KEY_F10 0x43 // Keyboard F10 +#define KEY_F11 0x44 // Keyboard F11 +#define KEY_F12 0x45 // Keyboard F12 + +#define KEY_SYSRQ 0x46 // Keyboard Print Screen +#define KEY_SCROLLLOCK 0x47 // Keyboard Scroll Lock +#define KEY_PAUSE 0x48 // Keyboard Pause +#define KEY_INSERT 0x49 // Keyboard Insert +#define KEY_HOME 0x4a // Keyboard Home +#define KEY_PAGEUP 0x4b // Keyboard Page Up +#define KEY_DELETE 0x4c // Keyboard Delete Forward +#define KEY_END 0x4d // Keyboard End +#define KEY_PAGEDOWN 0x4e // Keyboard Page Down +#define KEY_RIGHT 0x4f // Keyboard Right Arrow +#define KEY_LEFT 0x50 // Keyboard Left Arrow +#define KEY_DOWN 0x51 // Keyboard Down Arrow +#define KEY_UP 0x52 // Keyboard Up Arrow + +#define KEY_NUMLOCK 0x53 // Keyboard Num Lock and Clear +#define KEY_KPSLASH 0x54 // Keypad / +#define KEY_KPASTERISK 0x55 // Keypad * +#define KEY_KPMINUS 0x56 // Keypad - +#define KEY_KPPLUS 0x57 // Keypad + +#define KEY_KPENTER 0x58 // Keypad ENTER +#define KEY_KP1 0x59 // Keypad 1 and End +#define KEY_KP2 0x5a // Keypad 2 and Down Arrow +#define KEY_KP3 0x5b // Keypad 3 and PageDn +#define KEY_KP4 0x5c // Keypad 4 and Left Arrow +#define KEY_KP5 0x5d // Keypad 5 +#define KEY_KP6 0x5e // Keypad 6 and Right Arrow +#define KEY_KP7 0x5f // Keypad 7 and Home +#define KEY_KP8 0x60 // Keypad 8 and Up Arrow +#define KEY_KP9 0x61 // Keypad 9 and Page Up +#define KEY_KP0 0x62 // Keypad 0 and Insert +#define KEY_KPDOT 0x63 // Keypad . and Delete + +#define KEY_102ND 0x64 // Keyboard Non-US \ and | +#define KEY_COMPOSE 0x65 // Keyboard Application +#define KEY_POWER 0x66 // Keyboard Power +#define KEY_KPEQUAL 0x67 // Keypad = + +#define KEY_F13 0x68 // Keyboard F13 +#define KEY_F14 0x69 // Keyboard F14 +#define KEY_F15 0x6a // Keyboard F15 +#define KEY_F16 0x6b // Keyboard F16 +#define KEY_F17 0x6c // Keyboard F17 +#define KEY_F18 0x6d // Keyboard F18 +#define KEY_F19 0x6e // Keyboard F19 +#define KEY_F20 0x6f // Keyboard F20 +#define KEY_F21 0x70 // Keyboard F21 +#define KEY_F22 0x71 // Keyboard F22 +#define KEY_F23 0x72 // Keyboard F23 +#define KEY_F24 0x73 // Keyboard F24 + +#define KEY_OPEN 0x74 // Keyboard Execute +#define KEY_HELP 0x75 // Keyboard Help +#define KEY_PROPS 0x76 // Keyboard Menu +#define KEY_FRONT 0x77 // Keyboard Select +#define KEY_STOP 0x78 // Keyboard Stop +#define KEY_AGAIN 0x79 // Keyboard Again +#define KEY_UNDO 0x7a // Keyboard Undo +#define KEY_CUT 0x7b // Keyboard Cut +#define KEY_COPY 0x7c // Keyboard Copy +#define KEY_PASTE 0x7d // Keyboard Paste +#define KEY_FIND 0x7e // Keyboard Find +#define KEY_MUTE 0x7f // Keyboard Mute +#define KEY_VOLUMEUP 0x80 // Keyboard Volume Up +#define KEY_VOLUMEDOWN 0x81 // Keyboard Volume Down +// 0x82 Keyboard Locking Caps Lock +// 0x83 Keyboard Locking Num Lock +// 0x84 Keyboard Locking Scroll Lock +#define KEY_KPCOMMA 0x85 // Keypad Comma +// 0x86 Keypad Equal Sign +#define KEY_RO 0x87 // Keyboard International1 +#define KEY_KATAKANAHIRAGANA 0x88 // Keyboard International2 +#define KEY_YEN 0x89 // Keyboard International3 +#define KEY_HENKAN 0x8a // Keyboard International4 +#define KEY_MUHENKAN 0x8b // Keyboard International5 +#define KEY_KPJPCOMMA 0x8c // Keyboard International6 +// 0x8d Keyboard International7 +// 0x8e Keyboard International8 +// 0x8f Keyboard International9 +#define KEY_HANGEUL 0x90 // Keyboard LANG1 +#define KEY_HANJA 0x91 // Keyboard LANG2 +#define KEY_KATAKANA 0x92 // Keyboard LANG3 +#define KEY_HIRAGANA 0x93 // Keyboard LANG4 +#define KEY_ZENKAKUHANKAKU 0x94 // Keyboard LANG5 +// 0x95 Keyboard LANG6 +// 0x96 Keyboard LANG7 +// 0x97 Keyboard LANG8 +// 0x98 Keyboard LANG9 +// 0x99 Keyboard Alternate Erase +// 0x9a Keyboard SysReq/Attention +// 0x9b Keyboard Cancel +// 0x9c Keyboard Clear +// 0x9d Keyboard Prior +// 0x9e Keyboard Return +// 0x9f Keyboard Separator +// 0xa0 Keyboard Out +// 0xa1 Keyboard Oper +// 0xa2 Keyboard Clear/Again +// 0xa3 Keyboard CrSel/Props +// 0xa4 Keyboard ExSel + +// 0xb0 Keypad 00 +// 0xb1 Keypad 000 +// 0xb2 Thousands Separator +// 0xb3 Decimal Separator +// 0xb4 Currency Unit +// 0xb5 Currency Sub-unit +#define KEY_KPLEFTPAREN 0xb6 // Keypad ( +#define KEY_KPRIGHTPAREN 0xb7 // Keypad ) +// 0xb8 Keypad { +// 0xb9 Keypad } +// 0xba Keypad Tab +// 0xbb Keypad Backspace +// 0xbc Keypad A +// 0xbd Keypad B +// 0xbe Keypad C +// 0xbf Keypad D +// 0xc0 Keypad E +// 0xc1 Keypad F +// 0xc2 Keypad XOR +// 0xc3 Keypad ^ +// 0xc4 Keypad % +// 0xc5 Keypad < +// 0xc6 Keypad > +// 0xc7 Keypad & +// 0xc8 Keypad && +// 0xc9 Keypad | +// 0xca Keypad || +// 0xcb Keypad : +// 0xcc Keypad # +// 0xcd Keypad Space +// 0xce Keypad @ +// 0xcf Keypad ! +// 0xd0 Keypad Memory Store +// 0xd1 Keypad Memory Recall +// 0xd2 Keypad Memory Clear +// 0xd3 Keypad Memory Add +// 0xd4 Keypad Memory Subtract +// 0xd5 Keypad Memory Multiply +// 0xd6 Keypad Memory Divide +// 0xd7 Keypad +/- +// 0xd8 Keypad Clear +// 0xd9 Keypad Clear Entry +// 0xda Keypad Binary +// 0xdb Keypad Octal +// 0xdc Keypad Decimal +// 0xdd Keypad Hexadecimal + +#define KEY_LEFTCTRL 0xe0 // Keyboard Left Control +#define KEY_LEFTSHIFT 0xe1 // Keyboard Left Shift +#define KEY_LEFTALT 0xe2 // Keyboard Left Alt +#define KEY_LEFTMETA 0xe3 // Keyboard Left GUI +#define KEY_RIGHTCTRL 0xe4 // Keyboard Right Control +#define KEY_RIGHTSHIFT 0xe5 // Keyboard Right Shift +#define KEY_RIGHTALT 0xe6 // Keyboard Right Alt +#define KEY_RIGHTMETA 0xe7 // Keyboard Right GUI + +#define KEY_MEDIA_PLAYPAUSE 0xe8 +#define KEY_MEDIA_STOPCD 0xe9 +#define KEY_MEDIA_PREVIOUSSONG 0xea +#define KEY_MEDIA_NEXTSONG 0xeb +#define KEY_MEDIA_EJECTCD 0xec +#define KEY_MEDIA_VOLUMEUP 0xed +#define KEY_MEDIA_VOLUMEDOWN 0xee +#define KEY_MEDIA_MUTE 0xef +#define KEY_MEDIA_WWW 0xf0 +#define KEY_MEDIA_BACK 0xf1 +#define KEY_MEDIA_FORWARD 0xf2 +#define KEY_MEDIA_STOP 0xf3 +#define KEY_MEDIA_FIND 0xf4 +#define KEY_MEDIA_SCROLLUP 0xf5 +#define KEY_MEDIA_SCROLLDOWN 0xf6 +#define KEY_MEDIA_EDIT 0xf7 +#define KEY_MEDIA_SLEEP 0xf8 +#define KEY_MEDIA_COFFEE 0xf9 +#define KEY_MEDIA_REFRESH 0xfa +#define KEY_MEDIA_CALC 0xfb + +#endif //F103_USB_KEYBOARD_H diff --git a/Inc/main.h b/Inc/main.h index e3a3633..4b26812 100644 --- a/Inc/main.h +++ b/Inc/main.h @@ -6,7 +6,10 @@ #define F103_USB_MAIN_H_H #include "stm32f1xx_hal.h" +#include "circbuf.h" extern void dbg(const char* msg); +extern CircBuf *key_cbuf; + #endif //F103_USB_MAIN_H_H diff --git a/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Inc/usbd_hid.h b/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Inc/usbd_hid.h index a46b8f3..14577a1 100644 --- a/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Inc/usbd_hid.h +++ b/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Inc/usbd_hid.h @@ -50,7 +50,8 @@ extern "C" { * @{ */ #define HID_EPIN_ADDR 0x81 -#define HID_EPIN_SIZE 0x04 +// CHANGED +#define HID_EPIN_SIZE 0x08 #define USB_HID_CONFIG_DESC_SIZ 34 #define USB_HID_DESC_SIZ 9 diff --git a/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Src/usbd_hid.c b/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Src/usbd_hid.c index 6f54f66..562dc7e 100644 --- a/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Src/usbd_hid.c +++ b/Middlewares/ST/STM32_USB_Device_Library/Class/HID/Src/usbd_hid.c @@ -166,7 +166,7 @@ __ALIGN_BEGIN static uint8_t USBD_HID_CfgDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_ 0x01, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/ 0x01, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse*//* CHANGED */ 0, /*iInterface: Index of string descriptor*/ - /******************** Descriptor of Joystick Mouse HID ********************/ + /******************** Descriptor of Keyboard HID ********************/ /* 18 */ 0x09, /*bLength: HID Descriptor size*/ HID_DESCRIPTOR_TYPE, /*bDescriptorType: HID*/ @@ -191,6 +191,7 @@ __ALIGN_BEGIN static uint8_t USBD_HID_CfgDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_ }; /* USB HID device Configuration Descriptor */ +/* SAME AS ABOVE! */ __ALIGN_BEGIN static uint8_t USBD_HID_Desc[USB_HID_DESC_SIZ] __ALIGN_END = { /* 18 */ @@ -225,7 +226,10 @@ __ALIGN_BEGIN static uint8_t HID_KEYBD_ReportDesc[HID_KEYBD_REPORT_DESC_SIZE] _ 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x06, // USAGE (Keyboard) 0xa1, 0x01, // COLLECTION (Application) + 0x05, 0x07, // USAGE_PAGE (Keyboard) + + // Modifier byte - 8 bits 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) 0x15, 0x00, // LOGICAL_MINIMUM (0) @@ -233,26 +237,34 @@ __ALIGN_BEGIN static uint8_t HID_KEYBD_ReportDesc[HID_KEYBD_REPORT_DESC_SIZE] _ 0x75, 0x01, // REPORT_SIZE (1) 0x95, 0x08, // REPORT_COUNT (8) 0x81, 0x02, // INPUT (Data,Var,Abs) + + // reserved byte - 8 bits 0x95, 0x01, // REPORT_COUNT (1) 0x75, 0x08, // REPORT_SIZE (8) 0x81, 0x03, // INPUT (Cnst,Var,Abs) + + // LEDs report - 5 bits 0x95, 0x05, // REPORT_COUNT (5) 0x75, 0x01, // REPORT_SIZE (1) 0x05, 0x08, // USAGE_PAGE (LEDs) 0x19, 0x01, // USAGE_MINIMUM (Num Lock) 0x29, 0x05, // USAGE_MAXIMUM (Kana) 0x91, 0x02, // OUTPUT (Data,Var,Abs) + // Unused padding - 3 bits 0x95, 0x01, // REPORT_COUNT (1) 0x75, 0x03, // REPORT_SIZE (3) - 0x91, 0x03, // OUTPUT (Cnst,Var,Abs) + 0x91, 0x03, // OUTPUT (Cnst,Var,Abs) - padding, unused + + // Key codes - 6 bytes 0x95, 0x06, // REPORT_COUNT (6) 0x75, 0x08, // REPORT_SIZE (8) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x65, // LOGICAL_MAXIMUM (101) 0x05, 0x07, // USAGE_PAGE (Keyboard) 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) - 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) + 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) - Key down 0x81, 0x00, // INPUT (Data,Ary,Abs) + 0xc0 // END_COLLECTION }; diff --git a/Src/circbuf.c b/Src/circbuf.c new file mode 100644 index 0000000..3c2a232 --- /dev/null +++ b/Src/circbuf.c @@ -0,0 +1,163 @@ +#include +#include +#include +#include +#include + +#include "circbuf.h" + +#define malloc_s malloc + +// --- Circbuf data structure ---- + +/** Offset in void* buffer */ +#define PV_OFFS(pvBuf, elem_size, index) ((uint8_t*)(pvBuf) + ((elem_size)*(index))) + + +// Instance structure +struct circbuf_struct { + void *buf; + size_t elem_size; + size_t cap; + size_t lr; // last read pos + size_t nw; // next write pos +}; + + +/** + * @brief Write data to a CircBuf slot + * @param cb : circbuf + * @param index : slot index + * @param source : data source + */ +static void write_buffer(CircBuf *cb, size_t index, const void *source) +{ + memcpy(PV_OFFS(cb->buf, cb->elem_size, index), source, cb->elem_size); +} + + +/** + * @brief Copy data from a CircBuf slot to a buffer + * @param cb : circbuf + * @param index : slot index + * @param dest : destination buffer + */ +static void read_buffer(const CircBuf *cb, size_t index, void *dest) +{ + memcpy(dest, PV_OFFS(cb->buf, cb->elem_size, index), cb->elem_size); +} + + +/** Create a cbuf */ +CircBuf *cbuf_create(size_t capacity, size_t elem_size) +{ + // add one, because one is always unused. + capacity++; + + // Allocate the structure + CircBuf *cb = malloc_s(sizeof(CircBuf)); + + // allocate the buffer + cb->buf = malloc_s(capacity * elem_size); + + // set capacity, clear state + cb->elem_size = elem_size; + cb->cap = capacity; + cbuf_clear(cb); + + return cb; +} + + +/** Release cbuf memory */ +void cbuf_destroy(CircBuf *cb) +{ + if (cb != NULL) { + if (cb->buf != NULL) { + free(cb->buf); + } + + free(cb); + } +} + + +/** Check if cbuf is full */ +bool cbuf_full(const CircBuf *cb) +{ + if (cb == NULL) return false; + + return (cb->lr == cb->nw); +} + + +/** Check if cbuf is empty */ +bool cbuf_empty(const CircBuf *cb) +{ + if (cb == NULL) return true; + + return ((cb->lr + 1) % cb->cap) == cb->nw; +} + + +/** Write a byte to the buffer, if space left */ +bool cbuf_append(CircBuf *cb, const void *source) +{ + if (cb == NULL) return false; + if (source == NULL) return false; + if (cbuf_full(cb)) return false; + + write_buffer(cb, cb->nw, source); + + // increment + cb->nw++; + if (cb->nw == cb->cap) cb->nw = 0; + + return true; +} + + +/** Push value to the end, like a stack. */ +bool cbuf_push(CircBuf *cb, const void *source) +{ + if (cb == NULL) return false; + if (source == NULL) return false; + if (cbuf_full(cb)) return false; + + write_buffer(cb, cb->lr, source); + + // move lr back + if (cb->lr == 0) { + cb->lr = cb->cap - 1; // wrap to the end + } else { + cb->lr--; + } + + return true; +} + + +/** Read one byte, if not empty. */ +bool cbuf_pop(CircBuf *cb, void *dest) +{ + if (cb == NULL || dest == NULL) return false; + if (cbuf_empty(cb)) return false; + + // increment + cb->lr++; + if (cb->lr == cb->cap) cb->lr = 0; + + read_buffer(cb, cb->lr, dest); + + return true; +} + + +/** Clear a cbuf */ +void cbuf_clear(CircBuf *cb) +{ + if (cb == NULL) return; + + cb->lr = cb->cap - 1; + cb->nw = 0; +} diff --git a/Src/keyboard.c b/Src/keyboard.c new file mode 100644 index 0000000..eda46a2 --- /dev/null +++ b/Src/keyboard.c @@ -0,0 +1,117 @@ +// +// Created by MightyPork on 7.8.16. +// + +#include +#include +#include +#include "keyboard.h" + +static uint8_t modifiers = 0x00; + +static uint8_t keys[KYBD_SLOTS] = {}; + +static uint8_t free_slot = 0; + +static bool err_ovf = false; + +/** Clear keys and mods */ +void kybd_clear() { + memset(keys, 0x00, KYBD_SLOTS); + modifiers = 0x00; + free_slot = 0; + err_ovf = false; +} + +/** Key down */ +bool kybd_press(uint8_t key) { + kybd_key(key, true); +} + +/** Key up */ +bool kybd_release(uint8_t key) { + kybd_key(key, false); +} + +/** Modifier press or release */ +void kybd_mod(uint8_t mod, bool press) { + if (press) { + modifiers |= mod; + } else { + modifiers &= ~mod; + } +} + +/** Key press or release */ +bool kybd_key(uint8_t key, bool press) { + if (key >= KEY_LEFTCTRL && key <= KEY_RIGHTMETA) { + // Modifier key + + // conveniently, the lower byte indicates the modifier position + uint8_t bitshift = (uint8_t) (key & 0x0F); + // obtain the modifier mask + uint8_t mod = (uint8_t) (1 << bitshift); + // apply modifier + kybd_mod(mod, press); + + goto suc; + } + + // Regular key + if (press) { + for (int i = 0; i < KYBD_SLOTS; i++) { + if (keys[i] == key) { + // key is already pressed + goto suc; + } + } + + if (free_slot < KYBD_SLOTS) { + // press the key + keys[free_slot++] = key; + goto suc; + } + + err_ovf = true; // set overflow flag + } + else { + // release + bool found = false; + for (int i = 0; i < KYBD_SLOTS; i++) { + if (found) { + keys[i - 1] = keys[i]; + if (i == KYBD_SLOTS - 1) { + keys[i] = 0x00; + } + } + else { + if (keys[i] == key) { + found = true; + } + } + } + if (found) { + err_ovf = false; // clear overflow flag + free_slot--; + goto suc; + } + } + + return false; +suc: + return true; +} + +/** Get HID report */ +void kybd_get_bytes(uint8_t *arr) { + arr[0] = modifiers; + arr[1] = 0x00; + + if (err_ovf) { + // all slots ERR_OVF + memset(arr + 2, KEY_ERR_OVF, KYBD_SLOTS); + } else { + // show keys + memcpy(arr + 2, keys, KYBD_SLOTS); + } +} diff --git a/Src/main.c b/Src/main.c index 378fbcc..d9f1d01 100644 --- a/Src/main.c +++ b/Src/main.c @@ -31,6 +31,10 @@ ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ +#include +#include +#include +#include #include "stm32f1xx_hal.h" #include "usart.h" #include "usb_device.h" @@ -59,27 +63,68 @@ void Error_Handler(void); /* USER CODE BEGIN 0 */ +CircBuf *key_cbuf; + + +void fkey_press(uint8_t key) { + KeyEvent ke = {key, true}; + cbuf_append(key_cbuf, &ke); +} + +void fkey_release(uint8_t key) { + KeyEvent ke = {key, false}; + cbuf_append(key_cbuf, &ke); +} + +void fkey_type(uint8_t key, bool shift) { + if(shift) fkey_press(KEY_LEFTSHIFT); + fkey_press(key); + fkey_release(key); + if(shift) fkey_release(KEY_LEFTSHIFT); +} + + /** Print a debug message */ -void dbg(const char *msg) -{ +void dbg(const char *msg) { HAL_UART_Transmit(&huart2, (char *) msg, (uint16_t) strlen(msg), 10); } -void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) -{ +void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { UNUSED(GPIO_Pin); + static uint32_t lasttick = 0; + dbg("EXTI!\r\n"); -} + if (HAL_GetTick() - lasttick < 1000) { + dbg("Discard, too soon\r\n"); + return; + } -/* USER CODE END 0 */ + dbg("HEYOOO\r\n"); + + fkey_type(KEY_H, true); + fkey_type(KEY_E, false); + fkey_type(KEY_L, false); + fkey_type(KEY_L, false); + fkey_type(KEY_O, false); + fkey_type(KEY_SPACE, false); + fkey_type(KEY_W, true); + fkey_type(KEY_O, false); + fkey_type(KEY_R, false); + fkey_type(KEY_L, false); + fkey_type(KEY_D, false); + fkey_type(KEY_ENTER, false); +} -int main(void) -{ +/* USER CODE END 0 */ +int main(void) { /* USER CODE BEGIN 1 */ + kybd_clear(); + + key_cbuf = cbuf_create(100, sizeof(KeyEvent)); /* USER CODE END 1 */ @@ -105,6 +150,8 @@ int main(void) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wmissing-noreturn" + dbg("-- READY! --\r\n\r\n"); + char msg[] = "A\r\n"; while (1) { @@ -132,8 +179,7 @@ int main(void) /** System Clock Configuration */ -void SystemClock_Config(void) -{ +void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct; RCC_ClkInitTypeDef RCC_ClkInitStruct; @@ -182,8 +228,7 @@ void SystemClock_Config(void) * @param None * @retval None */ -void Error_Handler(void) -{ +void Error_Handler(void) { /* USER CODE BEGIN Error_Handler */ /* User can add his own implementation to report the HAL error return state */ while (1) { diff --git a/Src/stm32f1xx_it.c b/Src/stm32f1xx_it.c index 841a92f..222a743 100644 --- a/Src/stm32f1xx_it.c +++ b/Src/stm32f1xx_it.c @@ -31,9 +31,14 @@ ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ +#include +#include +#include +#include #include "stm32f1xx_hal.h" #include "stm32f1xx.h" #include "stm32f1xx_it.h" +#include "circbuf.h" /* USER CODE BEGIN 0 */ @@ -43,138 +48,139 @@ extern PCD_HandleTypeDef hpcd_USB_FS; /******************************************************************************/ -/* Cortex-M3 Processor Interruption and Exception Handlers */ +/* Cortex-M3 Processor Interruption and Exception Handlers */ /******************************************************************************/ /** * @brief This function handles Non maskable interrupt. */ -void NMI_Handler(void) -{ - /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ +void NMI_Handler(void) { + /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ - /* USER CODE END NonMaskableInt_IRQn 0 */ - /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ + /* USER CODE END NonMaskableInt_IRQn 0 */ + /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ - /* USER CODE END NonMaskableInt_IRQn 1 */ + /* USER CODE END NonMaskableInt_IRQn 1 */ } /** * @brief This function handles Hard fault interrupt. */ -void HardFault_Handler(void) -{ - /* USER CODE BEGIN HardFault_IRQn 0 */ +void HardFault_Handler(void) { + /* USER CODE BEGIN HardFault_IRQn 0 */ - /* USER CODE END HardFault_IRQn 0 */ - while (1) - { - } - /* USER CODE BEGIN HardFault_IRQn 1 */ + /* USER CODE END HardFault_IRQn 0 */ + while (1) { + } + /* USER CODE BEGIN HardFault_IRQn 1 */ - /* USER CODE END HardFault_IRQn 1 */ + /* USER CODE END HardFault_IRQn 1 */ } /** * @brief This function handles Memory management fault. */ -void MemManage_Handler(void) -{ - /* USER CODE BEGIN MemoryManagement_IRQn 0 */ +void MemManage_Handler(void) { + /* USER CODE BEGIN MemoryManagement_IRQn 0 */ - /* USER CODE END MemoryManagement_IRQn 0 */ - while (1) - { - } - /* USER CODE BEGIN MemoryManagement_IRQn 1 */ + /* USER CODE END MemoryManagement_IRQn 0 */ + while (1) { + } + /* USER CODE BEGIN MemoryManagement_IRQn 1 */ - /* USER CODE END MemoryManagement_IRQn 1 */ + /* USER CODE END MemoryManagement_IRQn 1 */ } /** * @brief This function handles Prefetch fault, memory access fault. */ -void BusFault_Handler(void) -{ - /* USER CODE BEGIN BusFault_IRQn 0 */ +void BusFault_Handler(void) { + /* USER CODE BEGIN BusFault_IRQn 0 */ - /* USER CODE END BusFault_IRQn 0 */ - while (1) - { - } - /* USER CODE BEGIN BusFault_IRQn 1 */ + /* USER CODE END BusFault_IRQn 0 */ + while (1) { + } + /* USER CODE BEGIN BusFault_IRQn 1 */ - /* USER CODE END BusFault_IRQn 1 */ + /* USER CODE END BusFault_IRQn 1 */ } /** * @brief This function handles Undefined instruction or illegal state. */ -void UsageFault_Handler(void) -{ - /* USER CODE BEGIN UsageFault_IRQn 0 */ +void UsageFault_Handler(void) { + /* USER CODE BEGIN UsageFault_IRQn 0 */ - /* USER CODE END UsageFault_IRQn 0 */ - while (1) - { - } - /* USER CODE BEGIN UsageFault_IRQn 1 */ + /* USER CODE END UsageFault_IRQn 0 */ + while (1) { + } + /* USER CODE BEGIN UsageFault_IRQn 1 */ - /* USER CODE END UsageFault_IRQn 1 */ + /* USER CODE END UsageFault_IRQn 1 */ } /** * @brief This function handles System service call via SWI instruction. */ -void SVC_Handler(void) -{ - /* USER CODE BEGIN SVCall_IRQn 0 */ +void SVC_Handler(void) { + /* USER CODE BEGIN SVCall_IRQn 0 */ - /* USER CODE END SVCall_IRQn 0 */ - /* USER CODE BEGIN SVCall_IRQn 1 */ + /* USER CODE END SVCall_IRQn 0 */ + /* USER CODE BEGIN SVCall_IRQn 1 */ - /* USER CODE END SVCall_IRQn 1 */ + /* USER CODE END SVCall_IRQn 1 */ } /** * @brief This function handles Debug monitor. */ -void DebugMon_Handler(void) -{ - /* USER CODE BEGIN DebugMonitor_IRQn 0 */ +void DebugMon_Handler(void) { + /* USER CODE BEGIN DebugMonitor_IRQn 0 */ - /* USER CODE END DebugMonitor_IRQn 0 */ - /* USER CODE BEGIN DebugMonitor_IRQn 1 */ + /* USER CODE END DebugMonitor_IRQn 0 */ + /* USER CODE BEGIN DebugMonitor_IRQn 1 */ - /* USER CODE END DebugMonitor_IRQn 1 */ + /* USER CODE END DebugMonitor_IRQn 1 */ } /** * @brief This function handles Pendable request for system service. */ -void PendSV_Handler(void) -{ - /* USER CODE BEGIN PendSV_IRQn 0 */ +void PendSV_Handler(void) { + /* USER CODE BEGIN PendSV_IRQn 0 */ - /* USER CODE END PendSV_IRQn 0 */ - /* USER CODE BEGIN PendSV_IRQn 1 */ + /* USER CODE END PendSV_IRQn 0 */ + /* USER CODE BEGIN PendSV_IRQn 1 */ - /* USER CODE END PendSV_IRQn 1 */ + /* USER CODE END PendSV_IRQn 1 */ } /** * @brief This function handles System tick timer. */ -void SysTick_Handler(void) -{ - /* USER CODE BEGIN SysTick_IRQn 0 */ +void SysTick_Handler(void) { + /* USER CODE BEGIN SysTick_IRQn 0 */ + static uint8_t kreport[8]; - /* USER CODE END SysTick_IRQn 0 */ - HAL_IncTick(); - HAL_SYSTICK_IRQHandler(); - /* USER CODE BEGIN SysTick_IRQn 1 */ + /* USER CODE END SysTick_IRQn 0 */ + HAL_IncTick(); + HAL_SYSTICK_IRQHandler(); + /* USER CODE BEGIN SysTick_IRQn 1 */ - /* USER CODE END SysTick_IRQn 1 */ + if (((USBD_HID_HandleTypeDef *) hUsbDeviceFS.pClassData)->state == HID_IDLE) { + KeyEvent ke; + if (cbuf_pop(key_cbuf, &ke)) { + kybd_key(ke.key, ke.press); + + // Send report + dbg("key event\r\n"); + + kybd_get_bytes(kreport); + USBD_HID_SendReport(&hUsbDeviceFS, kreport, 8); + } + } + + /* USER CODE END SysTick_IRQn 1 */ } /******************************************************************************/ @@ -187,22 +193,20 @@ void SysTick_Handler(void) /** * @brief This function handles USB low priority or CAN RX0 interrupts. */ -void USB_LP_CAN1_RX0_IRQHandler(void) -{ - /* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 0 */ +void USB_LP_CAN1_RX0_IRQHandler(void) { + /* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 0 */ - /* USER CODE END USB_LP_CAN1_RX0_IRQn 0 */ - HAL_PCD_IRQHandler(&hpcd_USB_FS); - /* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 1 */ + /* USER CODE END USB_LP_CAN1_RX0_IRQn 0 */ + HAL_PCD_IRQHandler(&hpcd_USB_FS); + /* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 1 */ - /* USER CODE END USB_LP_CAN1_RX0_IRQn 1 */ + /* USER CODE END USB_LP_CAN1_RX0_IRQn 1 */ } /* USER CODE BEGIN 1 */ -void EXTI1_IRQHandler(void) -{ - HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1); +void EXTI1_IRQHandler(void) { + HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1); } /* USER CODE END 1 */ diff --git a/Src/syscalls.c b/Src/syscalls.c new file mode 100644 index 0000000..72cb6be --- /dev/null +++ b/Src/syscalls.c @@ -0,0 +1,32 @@ +#include +#include + +register char * stack_ptr asm("sp"); + +caddr_t _sbrk(int incr) +{ + extern char end __asm("end"); + static char *heap_end; + char *prev_heap_end; + + if (heap_end == 0) + heap_end = &end; + + prev_heap_end = heap_end; + if (heap_end + incr > stack_ptr) + { +// write(1, "Heap and stack collision\n", 25); +// abort(); + errno = ENOMEM; + return (caddr_t) -1; + } + + heap_end += incr; + + return (caddr_t) prev_heap_end; +} + + +// Other systcalls are defined in +// - com/com_fileio.c +// - hw_utils/reset.h