├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── components └── tinyusb │ ├── CMakeLists.txt │ ├── Kconfig │ ├── additions │ ├── include │ │ ├── tinyusb.h │ │ ├── tinyusb_types.h │ │ ├── tusb_cdc_acm.h │ │ ├── tusb_config.h │ │ ├── tusb_console.h │ │ ├── tusb_hid.h │ │ ├── tusb_msc.h │ │ ├── tusb_tasks.h │ │ └── vfs_tinyusb.h │ ├── include_private │ │ ├── cdc.h │ │ ├── descriptors_control.h │ │ └── usb_descriptors.h │ └── src │ │ ├── cdc.c │ │ ├── descriptors_control.c │ │ ├── tinyusb.c │ │ ├── tusb_cdc_acm.c │ │ ├── tusb_console.c │ │ ├── tusb_hid.c │ │ ├── tusb_msc.c │ │ ├── tusb_tasks.c │ │ ├── usb_descriptors.c │ │ └── vfs_tinyusb.c │ ├── idf_component.yml │ └── sdkconfig.rename ├── hardware ├── esp32_keyboard.pdf └── kicad_proj │ ├── esp32-keyboard-v0.1-gerber.zip │ ├── esp32_keyboard-v0.1.kicad_pcb │ ├── esp32_keyboard-v0.1.pro │ ├── esp32_keyboard-v0.1.sch │ ├── fp-lib-table │ ├── mylib.lib │ ├── mylib.pretty │ ├── ESP32-S3-WROOM-1.kicad_mod │ ├── Keyboard-32-36-40.kicad_mod │ ├── Keyboard-36.kicad_mod │ ├── Keyboard-40.kicad_mod │ ├── MSK22D14G2-SWITCH.kicad_mod │ ├── Trackpad-12p.kicad_mod │ ├── android-logo.kicad_mod │ ├── kicad-logo-small.kicad_mod │ ├── tux-logo.kicad_mod │ ├── ubuntu-logo.kicad_mod │ ├── windows-logo.kicad_mod │ └── x1c-tablet-keyboard-usb.kicad_mod │ └── sym-lib-table ├── imgs ├── e580.jpg ├── fpc-kb-tp.jpg ├── ps2-timing.jpg └── t470.jpg ├── main ├── CMakeLists.txt ├── ble_hidd_demo_main.c ├── esp_hidd_prf_api.c ├── esp_hidd_prf_api.h ├── hid_dev.c ├── hid_dev.h ├── hid_device_le_prf.c ├── hidd_le_prf_int.h ├── keyboard.c ├── keyboard_pm.c ├── keyboard_pm.h ├── keymap-e530.c ├── keymap-e580.c ├── keymap.c ├── keymap.h └── pin_cfg.h └── sdkconfig.defaults /.gitignore: -------------------------------------------------------------------------------- 1 | build/* 2 | sdkconfig 3 | sdkconfig.old 4 | dependencies.lock 5 | .vscode/* -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's CMakeLists 2 | # in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 6 | project(hidd_demos) 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Thinkpad USB/BLE keyboard based on ESP32S3 2 | 3 | This USB/BLE keyboard controller is built upon ESP32S3 (the ESP32S3-WROOM-1 module), which has hardware USB & BLE peripherals. It can support multiple Thinkpad laptop keyboards, if not limited to all sorts of matrix keyboards. The following functions are supported: 4 | 5 | - Keyboard & LED; 6 | - Mouse (trackpoint); 7 | - Fn consumer/multimedia keys; 8 | - USB & BLE connection; 9 | - "Low-power": around 6-day BLE connection on a 1500mAh battery; 10 | 11 | Tested on T440/T470/E430/E530/E580. 12 | 13 | - E580 keyboard with 3D printed case: 14 | ![E580](imgs/e580.jpg) 15 | 16 | - T470/T480 keyboard: 17 | ![T470](imgs/t470.jpg) 18 | 19 | The BLE and USB driver is mainly modified from: 20 | - [ble_hid_device_demo](https://github.com/espressif/esp-idf/tree/master/examples/bluetooth/bluedroid/ble/ble_hid_device_demo) in `esp-idf`; 21 | - [tinyusb hid](https://github.com/iot-components/tinyusb.git) component addon; 22 | 23 | ## Hardware 24 | 25 | The Thinkpad keyboard modules are similar. Usually it contains a 32-40 pins FPC cable for keyboard matrix and LEDs, and a 10-12 FPC cable for trackpoint, mouse buttons and backlight. The keyboard matrix comprises 24 or 26 pins, where 8 of them are sense ports and the remaining drive ports. The trackpoint contains 3 input ports for mouse buttons, and a PS2 interface for mouse report. The following pinout is extracted from the [E580](https://badcaps.net/forum/attachment.php?attachmentid=215193&d=1593808132) schematic. 26 | 27 | ![Keyboard & trackpoint pinout](imgs/fpc-kb-tp.jpg) 28 | 29 | Although ESP32 has no PS2 interface, we notice that the slave-to-host timing of PS2 DATA pin is identical to the UART (1 start bit, 8 data bit, 1 odd parity, 1 stop bit). While by contrast the host-to-slave timing is NOT compatible, this only happens during initialization. Thereby this step requires bit-banging. 30 | 31 | ![PS2 timing](imgs/ps2-timing.jpg) 32 | 33 | The ESP32S3-WROOM-1 module has 36 GPIOs, among which should reserve the USB port (IO19/20), and the 32.768kHz external oscillator for low-power modem sleep (IO15/16). To fully drive the keyboard matrix, LEDs and PS2 trackpoint mouse, a 74HC138 is used to expand the poor IOs... See the [schematic](hardware/esp32_keyboard.pdf) for detail. 34 | - Keyboard: 3 pins for column scanning with 74HC138, plus 18 pins for row sensing; 35 | - Trackpoint: 3 pins (RST, CLK, DATA); 36 | - LEDs: 4 pins (FnLock, CapLk, NumLk, F1, mux with the UART0), plus 1 pin for the keyboard backlight; 37 | - Hotkey/Fn: 1 pin; 38 | - 5V wake up: 1 pin; 39 | - Download Pin: IO0, connected to the middle button; 40 | 41 | ## Build & Run 42 | 43 | We build with the normal esp-idf project workflow on Linux: 44 | 45 | ```bash 46 | idf.py set-target esp32s3 47 | idf.py build 48 | ``` 49 | 50 | To update the firmware, we should first power off the board, hold the middle button, plug in the USB cable, and then we can release the button. The USB-CDC hardware in the ESP32S3 should launch a `/dev/ttyACMx` on your computer, which can be used to flash the firmware: 51 | 52 | ``` bash 53 | idf.py -p /dev/ttyACM0 flash 54 | ``` 55 | 56 | Finally, unplug the USB cable and power on the board. 57 | 58 | ## Power consumption 59 | 60 | The ESP32 is known to be power hungry... We use a 1500mAH battery for the keyboard, and the original `ble_hid_device_demo` would take over 100mA without midification, which means a poor 15-hour battery life. For lower-power design, we should adopt the [BLE modem sleep with external 32kHz crystal under light sleep](https://github.com/espressif/esp-idf/issues/947#issuecomment-500312453), which claims an average ~2mA current with ~1000ms BLE connection interval. However, 1000ms (1Hz) interval is too long for real-time keyboard response, and we have to decrease it to around 50ms (20Hz) for normal use. Moreover, the trackpoint/mouse requires a even shorter period, which we set to 12.5ms (80Hz). With this backdrop, we develop a multi-stage power management as follow. This can be configured in [keyboard_pm.c](main/keyboard_pm.c). 61 | 62 | | Charging | BLE Connect | Keyboard Scanning | Trackpoint | BLE Interval | Current | Duration | 63 | |--|--|--|--|--|--|--| 64 | | No | No | Slow | No | 1000ms | ~5mA | - | 65 | | No | Yes | Slow | No | 1000ms | ~8mA | - | 66 | | No | Yes | Slow | No | 400ms | 13mA | 120s | 67 | | No | Yes | Fast | No | 50ms | 30mA | 240s | 68 | | No | Yes | Fast | Yes (cannot sleep) | 12.5ms | 53mA | 120s | 69 | | Yes | - | - | - | - | -500mA | - | 70 | 71 | Note: 72 | - The ESP32 light sleep would force turning off all the peripherals, which means that we will never receive trackpoint message at sleep. So the trackpoint forces no sleep. 73 | - The USB 2.0 host could offer ~500mA current, which means that it takes 3 hours to charge the 1500mAh battery. This is quite a modest setting, and this is why we don't use a larger battery like 2500mAh. 74 | - Backlight takes an additional 50mA. 75 | 76 | Battery life estimation (1500mAh): 77 | - 12 days if no BLE connection; 78 | - ~6 days for normal use; 79 | 80 | ## TODO list 81 | 82 | - Online configuration; 83 | - `Fn` and `Left Ctrl` exchange; 84 | - Multiple BLE cnnection; 85 | - More keyboards, e.g. X220; 86 | - More OS support, e.g. Mac; 87 | 88 | ## Reference 89 | 90 | - [How to Make a USB Laptop Keyboard Controller](https://www.instructables.com/How-to-Make-a-USB-Laptop-Keyboard-Controller/) 91 | - [Laptop Touchpad/Trackpoint Conversion to USB](https://www.hackster.io/frank-adams/laptop-touchpad-trackpoint-conversion-to-usb-d70519) 92 | - [esp32 BLE bridge for mouse and keyboard](https://github.com/asterics/esp32_mouse_keyboard) 93 | - [HID scancodes](https://deskthority.net/wiki/Scancode#cite_ref-xmeta_13-0) 94 | - [Trackpoint hardware](https://deskthority.net/wiki/TrackPoint_Hardware) 95 | 96 | Thinkpad schematics: 97 | - [T440](https://drive.google.com/file/d/1L-NCRwoP0IHYmOoxbS2U5ZWHYhyHf4xC/view) 98 | - [T470](https://www.badcaps.net/forum/attachment.php?attachmentid=201515&d=1571565529) 99 | - [E430/E530](https://drive.google.com/file/d/0B6IqcVTk0jpYV0xfMUdOay1uWlE/view?resourcekey=0-oamnnXMgSrohielovUks4A) 100 | - [E580](https://badcaps.net/forum/attachment.php?attachmentid=215193&d=1593808132) 101 | -------------------------------------------------------------------------------- /components/tinyusb/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_build_get_property(target IDF_TARGET) 2 | 3 | set(srcs) 4 | set(includes_public) 5 | set(includes_private) 6 | set(compile_options) 7 | 8 | if(CONFIG_TINYUSB) 9 | if(target STREQUAL "esp32s3") 10 | set(tusb_mcu "OPT_MCU_ESP32S3") 11 | set(tusb_family "esp32sx") 12 | elseif(target STREQUAL "esp32s2") 13 | set(tusb_mcu "OPT_MCU_ESP32S2") 14 | set(tusb_family "esp32sx") 15 | else() 16 | # CONFIG_TINYUSB dependency has been garanteed by Kconfig logic, 17 | # So it's not possible that cmake goes here 18 | message(FATAL_ERROR "TinyUSB is not support on ${target}.") 19 | return() 20 | endif() 21 | 22 | list(APPEND compile_options 23 | "-DCFG_TUSB_MCU=${tusb_mcu}" 24 | "-DCFG_TUSB_DEBUG=${CONFIG_TINYUSB_DEBUG_LEVEL}" 25 | ) 26 | 27 | idf_component_get_property(freertos_component_dir freertos COMPONENT_DIR) 28 | 29 | list(APPEND includes_private 30 | "${IDF_PATH}/components/tinyusb/tinyusb/hw/bsp/" 31 | "${IDF_PATH}/components/tinyusb/tinyusb/src/" 32 | "${IDF_PATH}/components/tinyusb/tinyusb/src/device" 33 | #"additions/include_private" 34 | ) 35 | 36 | list(APPEND includes_public 37 | "${IDF_PATH}/components/tinyusb/tinyusb/src/" 38 | "additions/include" 39 | "additions/include_private" 40 | # The FreeRTOS API include convention in tinyusb is different from esp-idf 41 | "${freertos_component_dir}/FreeRTOS-Kernel/include/freertos" 42 | ) 43 | 44 | list(APPEND srcs 45 | "${IDF_PATH}/components/tinyusb/tinyusb/src/portable/espressif/${tusb_family}/dcd_${tusb_family}.c" 46 | "${IDF_PATH}/components/tinyusb/tinyusb/src/class/cdc/cdc_device.c" 47 | "${IDF_PATH}/components/tinyusb/tinyusb/src/class/hid/hid_device.c" 48 | "${IDF_PATH}/components/tinyusb/tinyusb/src/class/midi/midi_device.c" 49 | "${IDF_PATH}/components/tinyusb/tinyusb/src/class/msc/msc_device.c" 50 | "${IDF_PATH}/components/tinyusb/tinyusb/src/class/vendor/vendor_device.c" 51 | "${IDF_PATH}/components/tinyusb/tinyusb/src/common/tusb_fifo.c" 52 | "${IDF_PATH}/components/tinyusb/tinyusb/src/device/usbd_control.c" 53 | "${IDF_PATH}/components/tinyusb/tinyusb/src/device/usbd.c" 54 | "${IDF_PATH}/components/tinyusb/tinyusb/src/tusb.c" 55 | "additions/src/descriptors_control.c" 56 | "additions/src/tinyusb.c" 57 | "additions/src/tusb_tasks.c" 58 | "additions/src/usb_descriptors.c" 59 | ) 60 | 61 | # when no builtin class driver is enabled, an uint8_t data compared with `BUILTIN_DRIVER_COUNT` will always be false 62 | set_source_files_properties("tinyusb/src/device/usbd.c" PROPERTIES COMPILE_FLAGS "-Wno-type-limits") 63 | 64 | if(CONFIG_TINYUSB_CDC_ENABLED) 65 | list(APPEND srcs 66 | "additions/src/cdc.c" 67 | "additions/src/tusb_cdc_acm.c" 68 | "additions/src/tusb_console.c" 69 | "additions/src/vfs_tinyusb.c" 70 | ) 71 | endif() # CONFIG_TINYUSB_CDC_ENABLED 72 | 73 | if(CONFIG_TINYUSB_HID_ENABLED) 74 | list(APPEND srcs 75 | "additions/src/tusb_hid.c") 76 | endif() 77 | 78 | if(CONFIG_TINYUSB_MSC_ENABLED) 79 | list(APPEND srcs 80 | "additions/src/tusb_msc.c") 81 | endif() 82 | endif() # CONFIG_TINYUSB 83 | 84 | idf_component_register(SRCS ${srcs} 85 | INCLUDE_DIRS ${includes_public} 86 | PRIV_INCLUDE_DIRS ${includes_private} 87 | PRIV_REQUIRES "vfs" "fatfs" 88 | ) 89 | 90 | if(CONFIG_TINYUSB) 91 | target_compile_options(${COMPONENT_LIB} PRIVATE ${compile_options}) 92 | endif() 93 | -------------------------------------------------------------------------------- /components/tinyusb/Kconfig: -------------------------------------------------------------------------------- 1 | menu "TinyUSB Stack" 2 | visible if USB_OTG_SUPPORTED 3 | 4 | config TINYUSB 5 | bool "Use TinyUSB Stack" 6 | depends on USB_OTG_SUPPORTED 7 | default n 8 | help 9 | Enable TinyUSB stack support. 10 | Note that, esp-idf only uses the device stack provided by TinyUSB. 11 | 12 | if TINYUSB 13 | config TINYUSB_DEBUG_LEVEL 14 | int "TinyUSB log level (0-3)" 15 | default 0 16 | range 0 3 17 | help 18 | Specify verbosity of TinyUSB log output. 19 | 20 | menu "TinyUSB task configuration" 21 | config TINYUSB_NO_DEFAULT_TASK 22 | bool "Do not create a TinyUSB task" 23 | default n 24 | help 25 | This option allows to not create the FreeRTOS task during the driver initialization. 26 | User will have to handle TinyUSB events manually. 27 | 28 | config TINYUSB_TASK_PRIORITY 29 | int "TinyUSB task priority" 30 | default 5 31 | depends on !TINYUSB_NO_DEFAULT_TASK 32 | help 33 | Set the priority of the default TinyUSB main task. 34 | 35 | config TINYUSB_TASK_STACK_SIZE 36 | int "TinyUSB task stack size (bytes)" 37 | default 4096 38 | depends on !TINYUSB_NO_DEFAULT_TASK 39 | help 40 | Set the stack size of the default TinyUSB main task. 41 | endmenu 42 | 43 | menu "Descriptor configuration" 44 | config TINYUSB_DESC_USE_ESPRESSIF_VID 45 | bool "VID: Use Espressif's vendor ID" 46 | default y 47 | help 48 | Enable this option, USB device will use Espressif's vendor ID as its VID. 49 | This is helpful at product develop stage. 50 | 51 | config TINYUSB_DESC_CUSTOM_VID 52 | hex "VID: Custom vendor ID" 53 | default 0x1234 54 | depends on !TINYUSB_DESC_USE_ESPRESSIF_VID 55 | help 56 | Custom Vendor ID. 57 | 58 | config TINYUSB_DESC_USE_DEFAULT_PID 59 | bool "PID: Use a default PID assigned to TinyUSB" 60 | default y 61 | help 62 | Default TinyUSB PID assigning uses values 0x4000...0x4007. 63 | 64 | config TINYUSB_DESC_CUSTOM_PID 65 | hex "PID: Custom product ID" 66 | default 0x5678 67 | depends on !TINYUSB_DESC_USE_DEFAULT_PID 68 | help 69 | Custom Product ID. 70 | 71 | config TINYUSB_DESC_BCD_DEVICE 72 | hex "bcdDevice" 73 | default 0x0100 74 | help 75 | Version of the firmware of the USB device. 76 | 77 | config TINYUSB_DESC_MANUFACTURER_STRING 78 | string "Manufacturer name" 79 | default "Espressif Systems" 80 | help 81 | Name of the manufacturer of the USB device. 82 | 83 | config TINYUSB_DESC_PRODUCT_STRING 84 | string "Product name" 85 | default "Espressif Device" 86 | help 87 | Name of the USB device. 88 | 89 | config TINYUSB_DESC_SERIAL_STRING 90 | string "Serial string" 91 | default "123456" 92 | help 93 | Serial number of the USB device. 94 | 95 | config TINYUSB_DESC_CDC_STRING 96 | depends on TINYUSB_CDC_ENABLED 97 | string "CDC Device String" 98 | default "Espressif CDC Device" 99 | help 100 | Name of the CDC device. 101 | 102 | config TINYUSB_DESC_MSC_STRING 103 | depends on TINYUSB_MSC_ENABLED 104 | string "MSC Device String" 105 | default "Espressif MSC Device" 106 | help 107 | Name of the MSC device. 108 | 109 | config TINYUSB_DESC_HID_STRING 110 | depends on TINYUSB_HID_ENABLED 111 | string "HID Device String" 112 | default "Espressif HID Device" 113 | help 114 | Name of the HID device 115 | endmenu # "Descriptor configuration" 116 | 117 | menu "Massive Storage Class (MSC)" 118 | config TINYUSB_MSC_ENABLED 119 | bool "Enable TinyUSB MSC feature" 120 | default n 121 | help 122 | Enable TinyUSB MSC feature. 123 | 124 | config TINYUSB_MSC_BUFSIZE 125 | depends on TINYUSB_MSC_ENABLED 126 | int "MSC FIFO size" 127 | default 512 128 | help 129 | MSC FIFO size, in bytes. 130 | endmenu # "Massive Storage Class" 131 | 132 | menu "Communication Device Class (CDC)" 133 | config TINYUSB_CDC_ENABLED 134 | bool "Enable TinyUSB CDC feature" 135 | default n 136 | help 137 | Enable TinyUSB CDC feature. 138 | config TINYUSB_CDC_PORT_NUM 139 | depends on TINYUSB_CDC_ENABLED 140 | int "Number of Serial (CDC) Port" 141 | default 1 142 | range 1 2 143 | help 144 | Number of Serial (CDC) Port. 145 | config TINYUSB_CDC_RX_BUFSIZE 146 | depends on TINYUSB_CDC_ENABLED 147 | int "CDC FIFO size of RX channel" 148 | default 64 149 | help 150 | CDC FIFO size of RX channel. 151 | 152 | config TINYUSB_CDC_TX_BUFSIZE 153 | depends on TINYUSB_CDC_ENABLED 154 | int "CDC FIFO size of TX channel" 155 | default 64 156 | help 157 | CDC FIFO size of TX channel. 158 | endmenu # "Communication Device Class" 159 | 160 | menu "Human Interface Device Class (HID)" 161 | config TINYUSB_HID_ENABLED 162 | bool "Enable TinyUSB HID feature" 163 | default n 164 | help 165 | Enable TinyUSB HID feature. 166 | 167 | config TINYUSB_HID_BUFSIZE 168 | int "HID FIFO size" 169 | default 64 170 | depends on TINYUSB_HID_ENABLED 171 | help 172 | HID FIFO size 173 | endmenu # "Human Interface Device Class" 174 | endif # TINYUSB 175 | 176 | endmenu # "TinyUSB Stack" 177 | -------------------------------------------------------------------------------- /components/tinyusb/additions/include/tinyusb.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #include 18 | #include "tusb.h" 19 | #include "tusb_option.h" 20 | #include "tusb_config.h" 21 | #include "tinyusb_types.h" 22 | 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | 29 | /* tinyusb uses buffers with type of uint8_t[] but in our driver we are reading them as a 32-bit word */ 30 | #if (CFG_TUD_ENDPOINT0_SIZE < 4) 31 | # define CFG_TUD_ENDPOINT0_SIZE 4 32 | # warning "CFG_TUD_ENDPOINT0_SIZE was too low and was set to 4" 33 | #endif 34 | 35 | #if TUSB_OPT_DEVICE_ENABLED 36 | 37 | # if CFG_TUD_HID 38 | # if (CFG_TUD_HID_BUFSIZE < 4) 39 | # define CFG_TUD_HID_BUFSIZE 4 40 | # warning "CFG_TUD_HID_BUFSIZE was too low and was set to 4" 41 | # endif 42 | # endif 43 | 44 | # if CFG_TUD_CDC 45 | # if (CFG_TUD_CDC_EP_BUFSIZE < 4) 46 | # define CFG_TUD_CDC_EP_BUFSIZE 4 47 | # warning "CFG_TUD_CDC_EP_BUFSIZE was too low and was set to 4" 48 | # endif 49 | # endif 50 | 51 | # if CFG_TUD_MSC 52 | # if (CFG_TUD_MSC_BUFSIZE < 4) 53 | # define CFG_TUD_MSC_BUFSIZE 4 54 | # warning "CFG_TUD_MSC_BUFSIZE was too low and was set to 4" 55 | # endif 56 | # endif 57 | 58 | # if CFG_TUD_MIDI 59 | # if (CFG_TUD_MIDI_EPSIZE < 4) 60 | # define CFG_TUD_MIDI_EPSIZE 4 61 | # warning "CFG_TUD_MIDI_EPSIZE was too low and was set to 4" 62 | # endif 63 | # endif 64 | 65 | # if CFG_TUD_CUSTOM_CLASS 66 | # warning "Please check that the buffer is more then 4 bytes" 67 | # endif 68 | #endif 69 | 70 | /** 71 | * @brief Configuration structure of the tinyUSB core 72 | */ 73 | typedef struct { 74 | tusb_desc_device_t *descriptor; /*!< Pointer to a device descriptor */ 75 | const char **string_descriptor; /*!< Pointer to an array of string descriptors */ 76 | const uint8_t *config_descriptor; /*!< Pointer to config descriptors */ 77 | bool external_phy; /*!< Should USB use an external PHY */ 78 | } tinyusb_config_t; 79 | 80 | /** 81 | * @brief This is an all-in-one helper function, including: 82 | * 1. USB device driver initialization 83 | * 2. Descriptors preparation 84 | * 3. TinyUSB stack initialization 85 | * 4. Creates and start a task to handle usb events 86 | * 87 | * @note Don't change Custom descriptor, but if it has to be done, 88 | * Suggest to define as follows in order to match the Interface Association Descriptor (IAD): 89 | * bDeviceClass = TUSB_CLASS_MISC, 90 | * bDeviceSubClass = MISC_SUBCLASS_COMMON, 91 | * 92 | * @param config tinyusb stack specific configuration 93 | * @retval ESP_ERR_INVALID_ARG Install driver and tinyusb stack failed because of invalid argument 94 | * @retval ESP_FAIL Install driver and tinyusb stack failed because of internal error 95 | * @retval ESP_OK Install driver and tinyusb stack successfully 96 | */ 97 | esp_err_t tinyusb_driver_install(const tinyusb_config_t *config); 98 | 99 | // TODO esp_err_t tinyusb_driver_uninstall(void); (IDF-1474) 100 | 101 | #ifdef __cplusplus 102 | } 103 | #endif 104 | -------------------------------------------------------------------------------- /components/tinyusb/additions/include/tinyusb_types.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Espressif Systems (Shanghai) Co. Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #define USB_ESPRESSIF_VID 0x303A 22 | #define USB_STRING_DESCRIPTOR_ARRAY_SIZE 7 23 | 24 | typedef enum{ 25 | TINYUSB_USBDEV_0, 26 | } tinyusb_usbdev_t; 27 | 28 | typedef const char *tusb_desc_strarray_device_t[USB_STRING_DESCRIPTOR_ARRAY_SIZE]; 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | -------------------------------------------------------------------------------- /components/tinyusb/additions/include/tusb_cdc_acm.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Espressif Systems (Shanghai) Co. Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include 22 | #include "freertos/FreeRTOS.h" 23 | #include "freertos/ringbuf.h" 24 | #include "freertos/semphr.h" 25 | #include "freertos/timers.h" 26 | #include "tusb.h" 27 | #include "tinyusb.h" 28 | 29 | /** 30 | * @brief CDC ports available to setup 31 | */ 32 | typedef enum{ 33 | TINYUSB_CDC_ACM_0 = 0x0, 34 | TINYUSB_CDC_ACM_1, 35 | TINYUSB_CDC_TOTAL 36 | }tinyusb_cdcacm_itf_t; 37 | 38 | /* Callbacks and events 39 | ********************************************************************* */ 40 | 41 | /** 42 | * @brief Data provided to the input of the `callback_rx_wanted_char` callback 43 | */ 44 | typedef struct { 45 | char wanted_char; /*!< Wanted character */ 46 | } cdcacm_event_rx_wanted_char_data_t; 47 | 48 | /** 49 | * @brief Data provided to the input of the `callback_line_state_changed` callback 50 | */ 51 | typedef struct { 52 | bool dtr; /*!< Data Terminal Ready (DTR) line state */ 53 | bool rts; /*!< Request To Send (RTS) line state */ 54 | } cdcacm_event_line_state_changed_data_t; 55 | 56 | /** 57 | * @brief Data provided to the input of the `line_coding_changed` callback 58 | */ 59 | typedef struct { 60 | cdc_line_coding_t const *p_line_coding; /*!< New line coding value */ 61 | } cdcacm_event_line_coding_changed_data_t; 62 | 63 | /** 64 | * @brief Types of CDC ACM events 65 | */ 66 | typedef enum { 67 | CDC_EVENT_RX, 68 | CDC_EVENT_RX_WANTED_CHAR, 69 | CDC_EVENT_LINE_STATE_CHANGED, 70 | CDC_EVENT_LINE_CODING_CHANGED 71 | } cdcacm_event_type_t; 72 | 73 | /** 74 | * @brief Describes an event passing to the input of a callbacks 75 | */ 76 | typedef struct { 77 | cdcacm_event_type_t type; /*!< Event type */ 78 | union { 79 | cdcacm_event_rx_wanted_char_data_t rx_wanted_char_data; /*!< Data input of the `callback_rx_wanted_char` callback */ 80 | cdcacm_event_line_state_changed_data_t line_state_changed_data; /*!< Data input of the `callback_line_state_changed` callback */ 81 | cdcacm_event_line_coding_changed_data_t line_coding_changed_data; /*!< Data input of the `line_coding_changed` callback */ 82 | }; 83 | } cdcacm_event_t; 84 | 85 | /** 86 | * @brief CDC-ACM callback type 87 | */ 88 | typedef void(*tusb_cdcacm_callback_t)(int itf, cdcacm_event_t *event); 89 | 90 | /*********************************************************************** Callbacks and events*/ 91 | /* Other structs 92 | ********************************************************************* */ 93 | 94 | /** 95 | * @brief Configuration structure for CDC-ACM 96 | */ 97 | typedef struct { 98 | tinyusb_usbdev_t usb_dev; /*!< Usb device to set up */ 99 | tinyusb_cdcacm_itf_t cdc_port; /*!< CDC port */ 100 | size_t rx_unread_buf_sz; /*!< Amount of data that can be passed to the AMC at once */ 101 | tusb_cdcacm_callback_t callback_rx; /*!< Pointer to the function with the `tusb_cdcacm_callback_t` type that will be handled as a callback */ 102 | tusb_cdcacm_callback_t callback_rx_wanted_char; /*!< Pointer to the function with the `tusb_cdcacm_callback_t` type that will be handled as a callback */ 103 | tusb_cdcacm_callback_t callback_line_state_changed; /*!< Pointer to the function with the `tusb_cdcacm_callback_t` type that will be handled as a callback */ 104 | tusb_cdcacm_callback_t callback_line_coding_changed; /*!< Pointer to the function with the `tusb_cdcacm_callback_t` type that will be handled as a callback */ 105 | } tinyusb_config_cdcacm_t; 106 | 107 | /*********************************************************************** Other structs*/ 108 | /* Public functions 109 | ********************************************************************* */ 110 | /** 111 | * @brief Initialize CDC ACM. Initialization will be finished with 112 | * the `tud_cdc_line_state_cb` callback 113 | * 114 | * @param cfg - init configuration structure 115 | * @return esp_err_t 116 | */ 117 | esp_err_t tusb_cdc_acm_init(const tinyusb_config_cdcacm_t *cfg); 118 | 119 | 120 | /** 121 | * @brief Register a callback invoking on CDC event. If the callback had been 122 | * already registered, it will be overwritten 123 | * 124 | * @param itf - number of a CDC object 125 | * @param event_type - type of registered event for a callback 126 | * @param callback - callback function 127 | * @return esp_err_t - ESP_OK or ESP_ERR_INVALID_ARG 128 | */ 129 | esp_err_t tinyusb_cdcacm_register_callback(tinyusb_cdcacm_itf_t itf, 130 | cdcacm_event_type_t event_type, 131 | tusb_cdcacm_callback_t callback); 132 | 133 | 134 | /** 135 | * @brief Unregister a callback invoking on CDC event. 136 | * 137 | * @param itf - number of a CDC object 138 | * @param event_type - type of registered event for a callback 139 | * @return esp_err_t - ESP_OK or ESP_ERR_INVALID_ARG 140 | */ 141 | esp_err_t tinyusb_cdcacm_unregister_callback(tinyusb_cdcacm_itf_t itf, cdcacm_event_type_t event_type); 142 | 143 | 144 | /** 145 | * @brief Sent one character to a write buffer 146 | * 147 | * @param itf - number of a CDC object 148 | * @param ch - character to send 149 | * @return size_t - amount of queued bytes 150 | */ 151 | size_t tinyusb_cdcacm_write_queue_char(tinyusb_cdcacm_itf_t itf, char ch); 152 | 153 | 154 | /** 155 | * @brief Write data to write buffer from a byte array 156 | * 157 | * @param itf - number of a CDC object 158 | * @param in_buf - a source array 159 | * @param in_size - size to write from arr_src 160 | * @return size_t - amount of queued bytes 161 | */ 162 | size_t tinyusb_cdcacm_write_queue(tinyusb_cdcacm_itf_t itf, uint8_t *in_buf, size_t in_size); 163 | 164 | /** 165 | * @brief Send all data from a write buffer. Use `tinyusb_cdcacm_write_queue` to add data to the buffer. 166 | * 167 | * WARNING! TinyUSB can block output Endpoint for several RX callbacks, after will do additional flush 168 | * after the each trasfer. That can leads to the situation when you requested a flush, but it will fail until 169 | * ont of the next callbacks ends. 170 | * SO USING OF THE FLUSH WITH TIMEOUTS IN CALLBACKS IS NOT RECOMENDED - YOU CAN GET A LOCK FOR THE TIMEOUT 171 | * 172 | * @param itf - number of a CDC object 173 | * @param timeout_ticks - waiting until flush will be considered as failed 174 | * @return esp_err_t - ESP_OK if (timeout_ticks > 0) and and flush was successful, 175 | * ESP_ERR_TIMEOUT if timeout occurred3 or flush was successful with (timeout_ticks == 0) 176 | * ESP_FAIL if flush was unsuccessful 177 | */ 178 | esp_err_t tinyusb_cdcacm_write_flush(tinyusb_cdcacm_itf_t itf, uint32_t timeout_ticks); 179 | 180 | /** 181 | * @brief Read a content to the array, and defines it's size to the sz_store 182 | * 183 | * @param itf - number of a CDC object 184 | * @param out_buf - to this array will be stored the object from a CDC buffer 185 | * @param out_buf_sz - size of buffer for results 186 | * @param rx_data_size - to this address will be stored the object's size 187 | * @return esp_err_t ESP_OK, ESP_FAIL or ESP_ERR_INVALID_STATE 188 | */ 189 | esp_err_t tinyusb_cdcacm_read(tinyusb_cdcacm_itf_t itf, uint8_t *out_buf, size_t out_buf_sz, size_t *rx_data_size); 190 | 191 | 192 | /** 193 | * @brief Check if the ACM initialized 194 | * 195 | * @param itf - number of a CDC object 196 | * @return true or false 197 | */ 198 | bool tusb_cdc_acm_initialized(tinyusb_cdcacm_itf_t itf); 199 | 200 | /*********************************************************************** Public functions*/ 201 | 202 | #ifdef __cplusplus 203 | } 204 | #endif 205 | -------------------------------------------------------------------------------- /components/tinyusb/additions/include/tusb_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019 Ha Thach (tinyusb.org), 5 | * Additions Copyright (c) 2020, Espressif Systems (Shanghai) PTE LTD 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | * 25 | */ 26 | 27 | #pragma once 28 | 29 | #include "tusb_option.h" 30 | #include "sdkconfig.h" 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | #ifndef CONFIG_TINYUSB_CDC_ENABLED 37 | # define CONFIG_TINYUSB_CDC_ENABLED 0 38 | # define CONFIG_TINYUSB_CDC_PORT_NUM 0 39 | #endif 40 | 41 | #ifndef CONFIG_TINYUSB_MSC_ENABLED 42 | # define CONFIG_TINYUSB_MSC_ENABLED 0 43 | #endif 44 | 45 | #ifndef CONFIG_TINYUSB_HID_ENABLED 46 | # define CONFIG_TINYUSB_HID_ENABLED 0 47 | #endif 48 | 49 | #ifndef CONFIG_TINYUSB_MIDI_ENABLED 50 | # define CONFIG_TINYUSB_MIDI_ENABLED 0 51 | #endif 52 | 53 | #ifndef CONFIG_TINYUSB_CUSTOM_CLASS_ENABLED 54 | # define CONFIG_TINYUSB_CUSTOM_CLASS_ENABLED 0 55 | #endif 56 | 57 | #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE | OPT_MODE_FULL_SPEED 58 | #define CFG_TUSB_OS OPT_OS_FREERTOS 59 | 60 | /* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. 61 | * Tinyusb use follows macros to declare transferring memory so that they can be put 62 | * into those specific section. 63 | * e.g 64 | * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) 65 | * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) 66 | */ 67 | #ifndef CFG_TUSB_MEM_SECTION 68 | # define CFG_TUSB_MEM_SECTION 69 | #endif 70 | 71 | #ifndef CFG_TUSB_MEM_ALIGN 72 | # define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4) 73 | #endif 74 | 75 | #ifndef CFG_TUD_ENDPOINT0_SIZE 76 | #define CFG_TUD_ENDPOINT0_SIZE 64 77 | #endif 78 | 79 | // CDC FIFO size of TX and RX 80 | #define CFG_TUD_CDC_RX_BUFSIZE CONFIG_TINYUSB_CDC_RX_BUFSIZE 81 | #define CFG_TUD_CDC_TX_BUFSIZE CONFIG_TINYUSB_CDC_TX_BUFSIZE 82 | 83 | // MSC Buffer size of Device Mass storage 84 | #define CFG_TUD_MSC_BUFSIZE CONFIG_TINYUSB_MSC_BUFSIZE 85 | 86 | // HID buffer size Should be sufficient to hold ID (if any) + Data 87 | #define CFG_TUD_HID_BUFSIZE CONFIG_TINYUSB_HID_BUFSIZE 88 | 89 | // Enabled device class driver 90 | #define CFG_TUD_CDC CONFIG_TINYUSB_CDC_PORT_NUM 91 | #define CFG_TUD_MSC CONFIG_TINYUSB_MSC_ENABLED 92 | #define CFG_TUD_HID CONFIG_TINYUSB_HID_ENABLED 93 | #define CFG_TUD_MIDI CONFIG_TINYUSB_MIDI_ENABLED 94 | #define CFG_TUD_CUSTOM_CLASS CONFIG_TINYUSB_CUSTOM_CLASS_ENABLED 95 | 96 | #define CFG_TUD_HID_EP_BUFSIZE 9 97 | 98 | #ifdef __cplusplus 99 | } 100 | #endif 101 | -------------------------------------------------------------------------------- /components/tinyusb/additions/include/tusb_console.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Espressif Systems (Shanghai) Co. Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include "esp_err.h" 22 | 23 | /** 24 | * @brief Redirect output to the USB serial 25 | * @param cdc_intf - interface number of TinyUSB's CDC 26 | * 27 | * @return esp_err_t - ESP_OK, ESP_FAIL or an error code 28 | */ 29 | esp_err_t esp_tusb_init_console(int cdc_intf); 30 | 31 | /** 32 | * @brief Switch log to the default output 33 | * @param cdc_intf - interface number of TinyUSB's CDC 34 | * 35 | * @return esp_err_t 36 | */ 37 | esp_err_t esp_tusb_deinit_console(int cdc_intf); 38 | 39 | #ifdef __cplusplus 40 | } 41 | #endif 42 | -------------------------------------------------------------------------------- /components/tinyusb/additions/include/tusb_hid.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2021 Espressif Systems (Shanghai) Co. Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include 22 | #include "tusb.h" 23 | #include "tinyusb.h" 24 | 25 | 26 | /** 27 | * @brief Report mouse movement and buttons. 28 | * @param buttons hid mouse button bit mask 29 | * @param x Current delta x movement of the mouse 30 | * @param y Current delta y movement on the mouse 31 | * @param vertical Current delta wheel movement on the mouse 32 | * @param horizontal using AC Pan 33 | */ 34 | void tinyusb_hid_mouse_report( 35 | uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal); 36 | 37 | /** 38 | * @brief Report key press in the keyboard, using array here, contains six keys at most. 39 | * @param keycode hid keyboard code array 40 | */ 41 | void tinyusb_hid_keyboard_report(uint8_t *keycode); 42 | 43 | /** 44 | * @brief Report multimedia keys. 45 | * @param keycode 2-byte multimedia keycode 46 | */ 47 | void tinyusb_hid_consumer_report(uint16_t keycode); 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | -------------------------------------------------------------------------------- /components/tinyusb/additions/include/tusb_msc.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2021 Espressif Systems (Shanghai) Co. Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include 22 | #include "tusb.h" 23 | #include "tinyusb.h" 24 | 25 | typedef void(*tusb_msc_callback_t)(int pdrv, void *arg); 26 | 27 | /** 28 | * @brief Configuration structure for MSC 29 | */ 30 | typedef struct { 31 | uint8_t pdrv; /* Physical drive nmuber (0..) */ 32 | tusb_msc_callback_t cb_mount; 33 | tusb_msc_callback_t cb_unmount; 34 | } tinyusb_config_msc_t; 35 | 36 | /** 37 | * @brief Initialize MSC Device. 38 | * 39 | * @param cfg - init configuration structure 40 | * @return esp_err_t 41 | */ 42 | esp_err_t tusb_msc_init(const tinyusb_config_msc_t *cfg); 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | -------------------------------------------------------------------------------- /components/tinyusb/additions/include/tusb_tasks.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #include "esp_err.h" 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * @brief This helper function creates and starts a task which wraps `tud_task()`. 25 | * 26 | * The wrapper function basically wraps tud_task and some log. 27 | * Default parameters: stack size and priority as configured, argument = NULL, not pinned to any core. 28 | * If you have more requirements for this task, you can create your own task which calls tud_task as the last step. 29 | * 30 | * @retval ESP_OK run tinyusb main task successfully 31 | * @retval ESP_FAIL run tinyusb main task failed of internal error 32 | * @retval ESP_ERR_INVALID_STATE tinyusb main task has been created before 33 | */ 34 | esp_err_t tusb_run_task(void); 35 | 36 | /** 37 | * @brief This helper function stops and destroys the task created by `tusb_run_task()` 38 | * 39 | * @retval ESP_OK stop and destory tinyusb main task successfully 40 | * @retval ESP_ERR_INVALID_STATE tinyusb main task hasn't been created yet 41 | */ 42 | esp_err_t tusb_stop_task(void); 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | -------------------------------------------------------------------------------- /components/tinyusb/additions/include/vfs_tinyusb.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Espressif Systems (Shanghai) Co. Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #include "esp_err.h" 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | * @brief Register TinyUSB CDC at VFS with path 25 | * @param cdc_intf - interface number of TinyUSB's CDC 26 | * @param path - path where the CDC will be registered, `/dev/tusb_cdc` will be used if left NULL. 27 | * 28 | * @return esp_err_t ESP_OK or ESP_FAIL 29 | */ 30 | esp_err_t esp_vfs_tusb_cdc_register(int cdc_intf, char const *path); 31 | 32 | /** 33 | * @brief Unregister TinyUSB CDC from VFS 34 | * @param path - path where the CDC will be unregistered if NULL will be used `/dev/tusb_cdc` 35 | * 36 | * @return esp_err_t ESP_OK or ESP_FAIL 37 | */ 38 | esp_err_t esp_vfs_tusb_cdc_unregister(char const *path); 39 | 40 | #ifdef __cplusplus 41 | } 42 | #endif 43 | -------------------------------------------------------------------------------- /components/tinyusb/additions/include_private/cdc.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Espressif Systems (Shanghai) Co. Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include 22 | #include "freertos/FreeRTOS.h" 23 | #include "freertos/ringbuf.h" 24 | #include "freertos/semphr.h" 25 | #include "freertos/timers.h" 26 | #include "tusb.h" 27 | #include "tinyusb_types.h" 28 | 29 | /* CDC classification 30 | ********************************************************************* */ 31 | typedef enum { 32 | TINYUSB_CDC_DATA = 0x00, 33 | } cdc_data_sublcass_type_t; // CDC120 specification 34 | 35 | /* Note:other classification is represented in the file components\tinyusb\tinyusb\src\class\cdc\cdc.h */ 36 | 37 | /*********************************************************************** CDC classification*/ 38 | /* Structs 39 | ********************************************************************* */ 40 | typedef struct { 41 | tinyusb_usbdev_t usb_dev; /*!< USB device to set up */ 42 | tusb_class_code_t cdc_class; /*!< CDC device class : Communications or Data device */ 43 | union { 44 | cdc_comm_sublcass_type_t comm_subclass; /*!< Communications device subclasses: AMC, ECM, etc. */ 45 | cdc_data_sublcass_type_t data_subclass; /*!< Data device has only one subclass.*/ 46 | } cdc_subclass; /*!< CDC device subclass according to Class Definitions for Communications Devices the CDC v.1.20 */ 47 | } tinyusb_config_cdc_t; /*!< Main configuration structure of a CDC device */ 48 | 49 | typedef struct { 50 | tinyusb_usbdev_t usb_dev; /*!< USB device used for the instance */ 51 | tusb_class_code_t type; 52 | union { 53 | cdc_comm_sublcass_type_t comm_subclass; /*!< Communications device subclasses: AMC, ECM, etc. */ 54 | cdc_data_sublcass_type_t data_subclass; /*!< Data device has only one subclass.*/ 55 | } cdc_subclass; /*!< CDC device subclass according to Class Definitions for Communications Devices the CDC v.1.20 */ 56 | void *subclass_obj; /*!< Dynamically allocated subclass specific object */ 57 | } esp_tusb_cdc_t; 58 | /*********************************************************************** Structs*/ 59 | /* Functions 60 | ********************************************************************* */ 61 | /** 62 | * @brief Initializing CDC basic object 63 | * @param itf - number of a CDC object 64 | * @param cfg - CDC configuration structure 65 | * 66 | * @return esp_err_t ESP_OK or ESP_FAIL 67 | */ 68 | esp_err_t tinyusb_cdc_init(int itf, const tinyusb_config_cdc_t *cfg); 69 | 70 | 71 | /** 72 | * @brief De-initializing CDC. Clean its objects 73 | * @param itf - number of a CDC object 74 | * @return esp_err_t ESP_OK, ESP_ERR_INVALID_ARG, ESP_ERR_INVALID_STATE 75 | * 76 | */ 77 | esp_err_t tinyusb_cdc_deinit(int itf); 78 | 79 | 80 | /** 81 | * @brief Checks if the CDC initialized and ready to interaction 82 | * 83 | * @return true or false 84 | */ 85 | bool tinyusb_cdc_initialized(int itf); 86 | 87 | 88 | /** 89 | * @brief Return interface of a CDC device 90 | * 91 | * @param itf_num 92 | * @return esp_tusb_cdc_t* pointer to the interface or (NULL) on error 93 | */ 94 | esp_tusb_cdc_t *tinyusb_cdc_get_intf(int itf_num); 95 | /*********************************************************************** Functions*/ 96 | 97 | #ifdef __cplusplus 98 | } 99 | #endif 100 | -------------------------------------------------------------------------------- /components/tinyusb/additions/include_private/descriptors_control.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #include 18 | #include "usb_descriptors.h" 19 | 20 | 21 | /* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. 22 | * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. 23 | * 24 | * Auto ProductID layout's Bitmap: 25 | * [MSB] HID | MSC | CDC [LSB] 26 | */ 27 | #define EPNUM_MSC 0x03 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | //------------- HID Report Descriptor -------------// 33 | #if CFG_TUD_HID 34 | enum { 35 | REPORT_ID_KEYBOARD = 1, 36 | REPORT_ID_MOUSE, 37 | REPORT_ID_CONSUMER, 38 | }; 39 | #endif 40 | 41 | //------------- Configuration Descriptor -------------// 42 | enum { 43 | # if CFG_TUD_CDC 44 | ITF_NUM_CDC = 0, 45 | ITF_NUM_CDC_DATA, 46 | # endif 47 | 48 | # if CFG_TUD_MSC 49 | ITF_NUM_MSC, 50 | # endif 51 | 52 | # if CFG_TUD_HID 53 | ITF_NUM_HID, 54 | # endif 55 | 56 | ITF_NUM_TOTAL 57 | }; 58 | 59 | enum { 60 | TUSB_DESC_TOTAL_LEN = TUD_CONFIG_DESC_LEN + CFG_TUD_CDC * TUD_CDC_DESC_LEN + CFG_TUD_MSC * TUD_MSC_DESC_LEN + 61 | CFG_TUD_HID * TUD_HID_DESC_LEN 62 | }; 63 | 64 | void tusb_set_descriptor(tusb_desc_device_t *desc, const char **str_desc); 65 | void tusb_set_config_descriptor(const uint8_t *config_desc); 66 | tusb_desc_device_t *tusb_get_active_desc(void); 67 | char **tusb_get_active_str_desc(void); 68 | void tusb_clear_descriptor(void); 69 | 70 | #ifdef __cplusplus 71 | } 72 | #endif 73 | -------------------------------------------------------------------------------- /components/tinyusb/additions/include_private/usb_descriptors.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #pragma once 16 | 17 | #include "tusb.h" 18 | #include "tinyusb_types.h" 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | #define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) 25 | 26 | extern tusb_desc_device_t descriptor_tinyusb; 27 | extern tusb_desc_strarray_device_t descriptor_str_tinyusb; 28 | 29 | extern tusb_desc_device_t descriptor_kconfig; 30 | extern tusb_desc_strarray_device_t descriptor_str_kconfig; 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif 35 | -------------------------------------------------------------------------------- /components/tinyusb/additions/src/cdc.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Espressif Systems (Shanghai) Co. Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include "esp_check.h" 17 | #include "esp_err.h" 18 | #include "esp_log.h" 19 | #include "tusb.h" 20 | #include "cdc.h" 21 | #include "tusb_cdc_acm.h" 22 | #include "sdkconfig.h" 23 | 24 | static const char *TAG = "tusb_cdc"; 25 | 26 | #define CDC_INTF_NUM CFG_TUD_CDC // number of cdc blocks 27 | 28 | static esp_tusb_cdc_t *cdc_obj[CDC_INTF_NUM] = {}; 29 | 30 | /* Common CDC functions 31 | ********************************************************************* */ 32 | bool tinyusb_cdc_initialized(int itf) 33 | { 34 | return (cdc_obj[itf] != NULL); 35 | } 36 | 37 | static esp_err_t cdc_interface_check(int itf) 38 | { 39 | if (tinyusb_cdc_initialized(itf)) { 40 | return ESP_OK; 41 | } else { 42 | ESP_LOGE(TAG, "Interface %d is not initialized. Use `tinyusb_cdc_init` for initialization", itf); 43 | return ESP_ERR_INVALID_STATE; 44 | } 45 | } 46 | 47 | /** 48 | * @brief 49 | * 50 | * @param itf 51 | * @param expected_inited 52 | * @param expected_type use -1 if you don't care 53 | * @return esp_err_t 54 | */ 55 | static esp_err_t cdc_obj_check(int itf, bool expected_inited, tusb_class_code_t expected_type) 56 | { 57 | bool inited = (cdc_obj[itf] != NULL); 58 | if (expected_inited != inited) { 59 | ESP_LOGE(TAG, "Wrong state of the interface. Expected state: %s", 60 | expected_inited ? "initialized" : "not initialized"); 61 | return ESP_ERR_INVALID_STATE; 62 | } 63 | if (inited && (expected_type != -1) && !(cdc_obj[itf]->type == expected_type)) { 64 | ESP_LOGE(TAG, "Wrong type of the interface. Should be : 0x%x (tusb_class_code_t)", expected_type); 65 | return ESP_ERR_INVALID_ARG; 66 | } 67 | return ESP_OK; 68 | } 69 | 70 | esp_tusb_cdc_t *tinyusb_cdc_get_intf(int itf_num) 71 | { 72 | if (cdc_interface_check(itf_num) != ESP_OK) { 73 | return NULL; 74 | } 75 | return cdc_obj[itf_num]; 76 | } 77 | 78 | /*********************************************************************** Common CDC functions*/ 79 | /* CDC class funcs 80 | ********************************************************************* */ 81 | static esp_err_t tusb_cdc_comm_init(int itf) 82 | { 83 | ESP_RETURN_ON_ERROR(cdc_obj_check(itf, false, -1), TAG, "cdc_obj_check failed"); 84 | cdc_obj[itf] = calloc(1, sizeof(esp_tusb_cdc_t)); 85 | if (cdc_obj[itf] != NULL) { 86 | cdc_obj[itf]->type = TUSB_CLASS_CDC; 87 | ESP_LOGD(TAG, "CDC Comm class initialized"); 88 | return ESP_OK; 89 | } else { 90 | ESP_LOGE(TAG, "CDC Comm initialization error"); 91 | return ESP_FAIL; 92 | } 93 | } 94 | 95 | static esp_err_t tusb_cdc_deinit_comm(int itf) 96 | { 97 | ESP_RETURN_ON_ERROR(cdc_obj_check(itf, true, TUSB_CLASS_CDC), TAG, "cdc_obj_check failed"); 98 | free(cdc_obj[itf]); 99 | cdc_obj[itf] = NULL; 100 | return ESP_OK; 101 | } 102 | 103 | static esp_err_t tusb_cdc_data_init(int itf) 104 | { 105 | ESP_RETURN_ON_ERROR(cdc_obj_check(itf, false, TUSB_CLASS_CDC_DATA), TAG, "cdc_obj_check failed"); 106 | cdc_obj[itf] = calloc(1, sizeof(esp_tusb_cdc_t)); 107 | if (cdc_obj[itf] != NULL) { 108 | cdc_obj[itf]->type = TUSB_CLASS_CDC_DATA; 109 | ESP_LOGD(TAG, "CDC Data class initialized"); 110 | return ESP_OK; 111 | } else { 112 | ESP_LOGE(TAG, "CDC Data initialization error"); 113 | return ESP_FAIL; 114 | } 115 | } 116 | 117 | static esp_err_t tusb_cdc_deinit_data(int itf) 118 | { 119 | ESP_RETURN_ON_ERROR(cdc_obj_check(itf, true, TUSB_CLASS_CDC_DATA), TAG, "cdc_obj_check failed"); 120 | free(cdc_obj[itf]); 121 | cdc_obj[itf] = NULL; 122 | return ESP_OK; 123 | } 124 | /*********************************************************************** CDC class funcs*/ 125 | /* CDC initialization 126 | ********************************************************************* */ 127 | esp_err_t tinyusb_cdc_init(int itf, const tinyusb_config_cdc_t *cfg) 128 | { 129 | ESP_LOGD(TAG, "CDC initialization..."); 130 | if (itf >= TINYUSB_CDC_TOTAL) { 131 | ESP_LOGE(TAG, "There is not CDC no.%d", itf); 132 | return ESP_ERR_INVALID_ARG; 133 | } 134 | if (cfg->cdc_class == TUSB_CLASS_CDC) { 135 | ESP_RETURN_ON_ERROR(tusb_cdc_comm_init(itf), TAG, "tusb_cdc_comm_init failed"); 136 | cdc_obj[itf]->cdc_subclass.comm_subclass = cfg->cdc_subclass.comm_subclass; 137 | } else { 138 | ESP_RETURN_ON_ERROR(tusb_cdc_data_init(itf), TAG, "tusb_cdc_data_init failed"); 139 | cdc_obj[itf]->cdc_subclass.data_subclass = cfg->cdc_subclass.data_subclass; 140 | } 141 | cdc_obj[itf]->usb_dev = cfg->usb_dev; 142 | return ESP_OK; 143 | } 144 | 145 | 146 | esp_err_t tinyusb_cdc_deinit(int itf) 147 | { 148 | if (itf >= TINYUSB_CDC_TOTAL) { 149 | ESP_LOGE(TAG, "There is not CDC no.%d", itf); 150 | return ESP_ERR_INVALID_ARG; 151 | } 152 | if (cdc_obj[itf]->type == TUSB_CLASS_CDC) { 153 | ESP_RETURN_ON_ERROR(tusb_cdc_deinit_comm(itf), TAG, "tusb_cdc_deinit_comm failed"); 154 | } else if (cdc_obj[itf]->type == TUSB_CLASS_CDC_DATA) { 155 | ESP_RETURN_ON_ERROR(tusb_cdc_deinit_data(itf), TAG, "tusb_cdc_deinit_data failed"); 156 | } else { 157 | return ESP_ERR_INVALID_ARG; 158 | } 159 | ESP_LOGD(TAG, "De-initialized"); 160 | return ESP_OK; 161 | } 162 | /*********************************************************************** CDC initialization*/ 163 | -------------------------------------------------------------------------------- /components/tinyusb/additions/src/descriptors_control.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "esp_log.h" 16 | #include "descriptors_control.h" 17 | 18 | static const char *TAG = "tusb_desc"; 19 | static tusb_desc_device_t s_descriptor; 20 | static char *s_str_descriptor[USB_STRING_DESCRIPTOR_ARRAY_SIZE]; 21 | static uint8_t *s_config_descriptor = NULL; 22 | #define MAX_DESC_BUF_SIZE 32 23 | 24 | // Mouse Report Descriptor Template 25 | #define MY_HID_REPORT_DESC_MOUSE(...) \ 26 | HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ 27 | HID_USAGE ( HID_USAGE_DESKTOP_MOUSE ) ,\ 28 | HID_COLLECTION ( HID_COLLECTION_APPLICATION ) ,\ 29 | /* Report ID if any */\ 30 | __VA_ARGS__ \ 31 | HID_USAGE ( HID_USAGE_DESKTOP_POINTER ) ,\ 32 | HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) ,\ 33 | HID_USAGE_PAGE ( HID_USAGE_PAGE_BUTTON ) ,\ 34 | HID_USAGE_MIN ( 1 ) ,\ 35 | HID_USAGE_MAX ( 5 ) ,\ 36 | HID_LOGICAL_MIN ( 0 ) ,\ 37 | HID_LOGICAL_MAX ( 1 ) ,\ 38 | /* Left, Right, Middle, Backward, Forward buttons */ \ 39 | HID_REPORT_COUNT( 5 ) ,\ 40 | HID_REPORT_SIZE ( 1 ) ,\ 41 | HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ 42 | /* 3 bit padding */ \ 43 | HID_REPORT_COUNT( 1 ) ,\ 44 | HID_REPORT_SIZE ( 3 ) ,\ 45 | HID_INPUT ( HID_CONSTANT ) ,\ 46 | HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ 47 | /* X, Y position [-127, 127] */ \ 48 | HID_USAGE ( HID_USAGE_DESKTOP_X ) ,\ 49 | HID_USAGE ( HID_USAGE_DESKTOP_Y ) ,\ 50 | HID_LOGICAL_MIN ( 0x81 ) ,\ 51 | HID_LOGICAL_MAX ( 0x7f ) ,\ 52 | HID_REPORT_COUNT( 2 ) ,\ 53 | HID_REPORT_SIZE ( 8 ) ,\ 54 | HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\ 55 | HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ 56 | /* Verital wheel scroll [-127, 127] */ \ 57 | HID_USAGE ( HID_USAGE_DESKTOP_WHEEL ) ,\ 58 | HID_LOGICAL_MIN ( 0x81 ) ,\ 59 | HID_LOGICAL_MAX ( 0x7f ) ,\ 60 | HID_REPORT_COUNT( 1 ) ,\ 61 | HID_REPORT_SIZE ( 8 ) ,\ 62 | HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ) ,\ 63 | HID_USAGE_PAGE ( HID_USAGE_PAGE_CONSUMER ), \ 64 | /* Horizontal wheel scroll [-127, 127] */ \ 65 | HID_USAGE_N ( HID_USAGE_CONSUMER_AC_PAN, 2 ), \ 66 | HID_LOGICAL_MIN ( 0x81 ), \ 67 | HID_LOGICAL_MAX ( 0x7f ), \ 68 | HID_REPORT_COUNT( 1 ), \ 69 | HID_REPORT_SIZE ( 8 ), \ 70 | HID_INPUT ( HID_DATA | HID_VARIABLE | HID_RELATIVE ), \ 71 | HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ 72 | /* Resolution multipler for high-resolution mouse*/ \ 73 | HID_USAGE ( HID_USAGE_DESKTOP_RESOLUTION_MULTIPLIER) ,\ 74 | HID_LOGICAL_MIN ( 0 ) ,\ 75 | HID_LOGICAL_MAX ( 15 ) ,\ 76 | HID_PHYSICAL_MIN ( 1 ) ,\ 77 | HID_PHYSICAL_MAX ( 16 ) ,\ 78 | HID_REPORT_COUNT( 1 ) ,\ 79 | HID_REPORT_SIZE ( 8 ) ,\ 80 | HID_FEATURE ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ 81 | HID_COLLECTION_END , \ 82 | HID_COLLECTION_END \ 83 | 84 | #if CFG_TUD_HID //HID Report Descriptor 85 | uint8_t const desc_hid_report[] = { 86 | TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID_KEYBOARD)), 87 | MY_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(REPORT_ID_MOUSE)), 88 | TUD_HID_REPORT_DESC_CONSUMER(HID_REPORT_ID(REPORT_ID_CONSUMER)) 89 | }; 90 | #endif 91 | 92 | uint8_t const desc_configuration[] = { 93 | // interface count, string index, total length, attribute, power in mA 94 | TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, TUSB_DESC_TOTAL_LEN, 0, 100), 95 | 96 | # if CFG_TUD_CDC 97 | // Interface number, string index, EP notification address and size, EP data address (out, in) and size. 98 | TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, 0x02, 0x82, 64), 99 | # endif 100 | # if CFG_TUD_MSC 101 | // Interface number, string index, EP Out & EP In address, EP size 102 | TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC, 0x80 | EPNUM_MSC, 64), // highspeed 512 103 | # endif 104 | # if CFG_TUD_HID 105 | // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval 106 | TUD_HID_DESCRIPTOR(ITF_NUM_HID, 6, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), 0x84, 16, 10) 107 | # endif 108 | }; 109 | 110 | // ============================================================================= 111 | // CALLBACKS 112 | // ============================================================================= 113 | 114 | /** 115 | * @brief Invoked when received GET DEVICE DESCRIPTOR. 116 | * Application returns pointer to descriptor 117 | * 118 | * @return uint8_t const* 119 | */ 120 | uint8_t const *tud_descriptor_device_cb(void) 121 | { 122 | return (uint8_t const *)&s_descriptor; 123 | } 124 | 125 | /** 126 | * @brief Invoked when received GET CONFIGURATION DESCRIPTOR. 127 | * Descriptor contents must exist long enough for transfer to complete 128 | * 129 | * @param index 130 | * @return uint8_t const* Application return pointer to descriptor 131 | */ 132 | uint8_t const *tud_descriptor_configuration_cb(uint8_t index) 133 | { 134 | ESP_LOGD("TUSB", "%s(%u)", __func__, index); 135 | (void)index; // for multiple configurations 136 | return s_config_descriptor; 137 | } 138 | 139 | static uint16_t _desc_str[MAX_DESC_BUF_SIZE]; 140 | 141 | // Invoked when received GET STRING DESCRIPTOR request 142 | // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete 143 | uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) 144 | { 145 | (void) langid; 146 | ESP_LOGD("TUSB", "%s(%u, %u)", __func__, index, langid); 147 | 148 | uint8_t chr_count; 149 | 150 | if ( index == 0) { 151 | memcpy(&_desc_str[1], s_str_descriptor[0], 2); 152 | chr_count = 1; 153 | } else { 154 | // Convert ASCII string into UTF-16 155 | 156 | if ( index >= sizeof(s_str_descriptor) / sizeof(s_str_descriptor[0]) ) { 157 | return NULL; 158 | } 159 | 160 | const char *str = s_str_descriptor[index]; 161 | 162 | // Cap at max char 163 | chr_count = strlen(str); 164 | if ( chr_count > MAX_DESC_BUF_SIZE - 1 ) { 165 | chr_count = MAX_DESC_BUF_SIZE - 1; 166 | } 167 | 168 | for (uint8_t i = 0; i < chr_count; i++) { 169 | _desc_str[1 + i] = str[i]; 170 | } 171 | } 172 | 173 | // first byte is length (including header), second byte is string type 174 | _desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2 * chr_count + 2); 175 | 176 | return _desc_str; 177 | } 178 | 179 | /** 180 | * @brief Invoked when received GET HID REPORT DESCRIPTOR 181 | * Application returns pointer to descriptor. Descriptor contents must exist 182 | * long enough for transfer to complete 183 | * 184 | * @return uint8_t const* 185 | */ 186 | #if CFG_TUD_HID 187 | uint8_t const *tud_hid_descriptor_report_cb(uint8_t itf) 188 | { 189 | ESP_LOGD("TUSB", "%s(%u)", __func__, itf); 190 | (void)itf; 191 | return desc_hid_report; 192 | } 193 | #endif 194 | 195 | // ============================================================================= 196 | // Driver functions 197 | // ============================================================================= 198 | 199 | void tusb_set_descriptor(tusb_desc_device_t *dev_desc, const char **str_desc) 200 | { 201 | ESP_LOGI(TAG, "\n" 202 | "┌─────────────────────────────────┐\n" 203 | "│ USB Device Descriptor Summary │\n" 204 | "├───────────────────┬─────────────┤\n" 205 | "│bDeviceClass │ %-4u │\n" 206 | "├───────────────────┼─────────────┤\n" 207 | "│bDeviceSubClass │ %-4u │\n" 208 | "├───────────────────┼─────────────┤\n" 209 | "│bDeviceProtocol │ %-4u │\n" 210 | "├───────────────────┼─────────────┤\n" 211 | "│bMaxPacketSize0 │ %-4u │\n" 212 | "├───────────────────┼─────────────┤\n" 213 | "│idVendor │ %-#10x │\n" 214 | "├───────────────────┼─────────────┤\n" 215 | "│idProduct │ %-#10x │\n" 216 | "├───────────────────┼─────────────┤\n" 217 | "│bcdDevice │ %-#10x │\n" 218 | "├───────────────────┼─────────────┤\n" 219 | "│iManufacturer │ %-#10x │\n" 220 | "├───────────────────┼─────────────┤\n" 221 | "│iProduct │ %-#10x │\n" 222 | "├───────────────────┼─────────────┤\n" 223 | "│iSerialNumber │ %-#10x │\n" 224 | "├───────────────────┼─────────────┤\n" 225 | "│bNumConfigurations │ %-#10x │\n" 226 | "└───────────────────┴─────────────┘", 227 | dev_desc->bDeviceClass, dev_desc->bDeviceSubClass, 228 | dev_desc->bDeviceProtocol, dev_desc->bMaxPacketSize0, 229 | dev_desc->idVendor, dev_desc->idProduct, dev_desc->bcdDevice, 230 | dev_desc->iManufacturer, dev_desc->iProduct, dev_desc->iSerialNumber, 231 | dev_desc->bNumConfigurations); 232 | s_descriptor = *dev_desc; 233 | 234 | if (str_desc != NULL) { 235 | memcpy(s_str_descriptor, str_desc, 236 | sizeof(s_str_descriptor[0])*USB_STRING_DESCRIPTOR_ARRAY_SIZE); 237 | } 238 | } 239 | 240 | void tusb_set_config_descriptor(const uint8_t *config_desc) 241 | { 242 | size_t length = 0; 243 | const uint8_t *config_descriptor = NULL; 244 | if (config_desc == NULL) { 245 | config_descriptor = desc_configuration; 246 | ESP_LOGI(TAG, "using default config desc"); 247 | } else { 248 | config_descriptor = config_desc; 249 | ESP_LOGI(TAG, "using custom config desc"); 250 | } 251 | length = (config_descriptor[3]<<8) + config_descriptor[2]; 252 | ESP_LOGI(TAG, "config desc size=%d", length); 253 | s_config_descriptor = realloc(s_config_descriptor, length); 254 | memcpy(s_config_descriptor, config_descriptor, length); 255 | } 256 | 257 | tusb_desc_device_t *tusb_get_active_desc(void) 258 | { 259 | return &s_descriptor; 260 | } 261 | 262 | char **tusb_get_active_str_desc(void) 263 | { 264 | return s_str_descriptor; 265 | } 266 | 267 | void tusb_clear_descriptor(void) 268 | { 269 | memset(&s_descriptor, 0, sizeof(s_descriptor)); 270 | memset(&s_str_descriptor, 0, sizeof(s_str_descriptor)); 271 | free(s_config_descriptor); 272 | s_config_descriptor = NULL; 273 | } 274 | -------------------------------------------------------------------------------- /components/tinyusb/additions/src/tinyusb.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "sdkconfig.h" 16 | #include "rom/gpio.h" 17 | #include "driver/gpio.h" 18 | #include "driver/periph_ctrl.h" 19 | #include "esp_log.h" 20 | #include "esp_check.h" 21 | #include "esp_rom_gpio.h" 22 | #include "hal/gpio_ll.h" 23 | #include "hal/usb_hal.h" 24 | #include "soc/gpio_periph.h" 25 | #include "soc/usb_periph.h" 26 | #include "tinyusb.h" 27 | #include "descriptors_control.h" 28 | #include "tusb.h" 29 | #include "tusb_tasks.h" 30 | 31 | const static char *TAG = "TinyUSB"; 32 | 33 | static void configure_pins(usb_hal_context_t *usb) 34 | { 35 | /* usb_periph_iopins currently configures USB_OTG as USB Device. 36 | * Introduce additional parameters in usb_hal_context_t when adding support 37 | * for USB Host. 38 | */ 39 | for (const usb_iopin_dsc_t *iopin = usb_periph_iopins; iopin->pin != -1; ++iopin) { 40 | if ((usb->use_external_phy) || (iopin->ext_phy_only == 0)) { 41 | esp_rom_gpio_pad_select_gpio(iopin->pin); 42 | if (iopin->is_output) { 43 | esp_rom_gpio_connect_out_signal(iopin->pin, iopin->func, false, false); 44 | } else { 45 | esp_rom_gpio_connect_in_signal(iopin->pin, iopin->func, false); 46 | if ((iopin->pin != GPIO_FUNC_IN_LOW) && (iopin->pin != GPIO_FUNC_IN_HIGH)) { 47 | gpio_ll_input_enable(&GPIO, iopin->pin); 48 | } 49 | } 50 | esp_rom_gpio_pad_unhold(iopin->pin); 51 | } 52 | } 53 | if (!usb->use_external_phy) { 54 | gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3); 55 | gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3); 56 | } 57 | } 58 | 59 | esp_err_t tinyusb_driver_install(const tinyusb_config_t *config) 60 | { 61 | tusb_desc_device_t *dev_descriptor; 62 | const char **string_descriptor; 63 | ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); 64 | // Enable APB CLK to USB peripheral 65 | periph_module_enable(PERIPH_USB_MODULE); 66 | periph_module_reset(PERIPH_USB_MODULE); 67 | // Initialize HAL layer 68 | usb_hal_context_t hal = { 69 | .use_external_phy = config->external_phy 70 | }; 71 | usb_hal_init(&hal); 72 | configure_pins(&hal); 73 | 74 | dev_descriptor = config->descriptor ? config->descriptor : &descriptor_kconfig; 75 | string_descriptor = config->string_descriptor ? config->string_descriptor : descriptor_str_kconfig; 76 | 77 | tusb_set_config_descriptor(config->config_descriptor); //if NULL, using default descriptor config by menuconfig 78 | tusb_set_descriptor(dev_descriptor, string_descriptor); 79 | 80 | ESP_RETURN_ON_FALSE(tusb_init(), ESP_FAIL, TAG, "Init TinyUSB stack failed"); 81 | #if !CONFIG_TINYUSB_NO_DEFAULT_TASK 82 | ESP_RETURN_ON_ERROR(tusb_run_task(), TAG, "Run TinyUSB task failed"); 83 | #endif 84 | ESP_LOGI(TAG, "TinyUSB Driver installed"); 85 | return ESP_OK; 86 | } 87 | -------------------------------------------------------------------------------- /components/tinyusb/additions/src/tusb_console.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Espressif Systems (Shanghai) Co. Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | #include 17 | #include 18 | #include "esp_log.h" 19 | #include "cdc.h" 20 | #include "tusb_console.h" 21 | #include "tinyusb.h" 22 | #include "vfs_tinyusb.h" 23 | 24 | #define STRINGIFY(s) STRINGIFY2(s) 25 | #define STRINGIFY2(s) #s 26 | 27 | static const char *TAG = "tusb_console"; 28 | 29 | typedef struct { 30 | FILE *in; 31 | FILE *out; 32 | FILE *err; 33 | } console_handle_t; 34 | 35 | static console_handle_t con; 36 | 37 | 38 | /** 39 | * @brief Reopen standard streams using a new path 40 | * 41 | * @param f_in - pointer to a pointer holding a file for in or NULL to don't change stdin 42 | * @param f_out - pointer to a pointer holding a file for out or NULL to don't change stdout 43 | * @param f_err - pointer to a pointer holding a file for err or NULL to don't change stderr 44 | * @param path - mount point 45 | * @return esp_err_t ESP_FAIL or ESP_OK 46 | */ 47 | static esp_err_t redirect_std_streams_to(FILE **f_in, FILE **f_out, FILE **f_err, const char *path) 48 | { 49 | if (f_in) { 50 | *f_in = freopen(path, "r", stdin); 51 | if (*f_in == NULL) { 52 | ESP_LOGE(TAG, "Failed to reopen in!"); 53 | return ESP_FAIL; 54 | } 55 | } 56 | if (f_out) { 57 | *f_out = freopen(path, "w", stdout); 58 | if (*f_out == NULL) { 59 | ESP_LOGE(TAG, "Failed to reopen out!"); 60 | return ESP_FAIL; 61 | } 62 | } 63 | if (f_err) { 64 | *f_err = freopen(path, "w", stderr); 65 | if (*f_err == NULL) { 66 | ESP_LOGE(TAG, "Failed to reopen err!"); 67 | return ESP_FAIL; 68 | } 69 | } 70 | 71 | return ESP_OK; 72 | } 73 | 74 | /** 75 | * @brief Restore output to default 76 | * 77 | * @param f_in - pointer to a pointer of an in file updated with `redirect_std_streams_to` or NULL to don't change stdin 78 | * @param f_out - pointer to a pointer of an out file updated with `redirect_std_streams_to` or NULL to don't change stdout 79 | * @param f_err - pointer to a pointer of an err file updated with `redirect_std_streams_to` or NULL to don't change stderr 80 | * @return esp_err_t ESP_FAIL or ESP_OK 81 | */ 82 | static esp_err_t restore_std_streams(FILE **f_in, FILE **f_out, FILE **f_err) 83 | { 84 | const char *default_uart_dev = "/dev/uart/" STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM); 85 | if (f_in) { 86 | stdin = freopen(default_uart_dev, "r", *f_in); 87 | if (stdin == NULL) { 88 | ESP_LOGE(TAG, "Failed to reopen stdin!"); 89 | return ESP_FAIL; 90 | } 91 | } 92 | if (f_out) { 93 | stdout = freopen(default_uart_dev, "w", *f_out); 94 | if (stdout == NULL) { 95 | ESP_LOGE(TAG, "Failed to reopen stdout!"); 96 | return ESP_FAIL; 97 | } 98 | } 99 | if (f_err) { 100 | stderr = freopen(default_uart_dev, "w", *f_err); 101 | if (stderr == NULL) { 102 | ESP_LOGE(TAG, "Failed to reopen stderr!"); 103 | return ESP_FAIL; 104 | } 105 | } 106 | return ESP_OK; 107 | } 108 | 109 | esp_err_t esp_tusb_init_console(int cdc_intf) 110 | { 111 | if (!tinyusb_cdc_initialized(cdc_intf)) { 112 | ESP_LOGE(TAG, "Can't init the console because TinyUSB's CDC is not initialized!"); 113 | return ESP_ERR_INVALID_STATE; 114 | } 115 | /* Registering TUSB at VFS */ 116 | int res = esp_vfs_tusb_cdc_register(cdc_intf, NULL); 117 | if (res != ESP_OK) { 118 | return res; 119 | } 120 | 121 | res = redirect_std_streams_to(&con.in, &con.out, &con.err, "/dev/tusb_cdc"); 122 | if (res != ESP_OK) { 123 | return res; 124 | } 125 | 126 | return ESP_OK; 127 | } 128 | 129 | esp_err_t esp_tusb_deinit_console(int cdc_intf) 130 | { 131 | if (!tinyusb_cdc_initialized(cdc_intf)) { 132 | ESP_LOGE(TAG, "Can't deinit the console because TinyUSB's CDC is not initialized!"); 133 | return ESP_ERR_INVALID_STATE; 134 | } 135 | 136 | int res = restore_std_streams(&con.in, &con.out, &con.err); 137 | if (res != ESP_OK) { 138 | return res; 139 | } 140 | esp_vfs_tusb_cdc_unregister(NULL); 141 | return ESP_OK; 142 | } 143 | -------------------------------------------------------------------------------- /components/tinyusb/additions/src/tusb_hid.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2021 Espressif Systems (Shanghai) Co. Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | #include 17 | #include "esp_err.h" 18 | #include "sdkconfig.h" 19 | #include "esp_log.h" 20 | #include "tusb_hid.h" 21 | #include "descriptors_control.h" 22 | #include "esp_debug_helpers.h" 23 | 24 | static const char *TAG = "tusb_hid"; 25 | 26 | uint8_t curr_resolution_multiplier = 1; 27 | 28 | void tinyusb_hid_mouse_report( 29 | uint8_t buttons, int8_t x, int8_t y, int8_t vertical, int8_t horizontal) 30 | { 31 | ESP_LOGD(TAG, "buttons=%02x, x=%d, y=%d, vertical=%d, horizontal=%d", 32 | buttons, x, y, vertical, horizontal); 33 | 34 | // Remote wakeup 35 | if (tud_suspended()) { 36 | // Wake up host if we are in suspend mode 37 | // and REMOTE_WAKEUP feature is enabled by host 38 | tud_remote_wakeup(); 39 | } else { 40 | // Send the 1st of report chain, the rest will be sent by tud_hid_report_complete_cb() 41 | // skip if hid is not ready yet 42 | int i = 0; 43 | for (; i < 5 && !tud_hid_ready(); i++) { 44 | vTaskDelay(5); 45 | } 46 | if (i >= 5) { 47 | ESP_LOGW(__func__, "tinyusb not ready"); 48 | return; 49 | } 50 | 51 | tud_hid_mouse_report(REPORT_ID_MOUSE, buttons, x, y, vertical, horizontal); 52 | } 53 | } 54 | 55 | void tinyusb_hid_keyboard_report(uint8_t *keycode) 56 | { 57 | ESP_LOGD(TAG, "keycode: %02x %02x %02x %02x %02x %02x", 58 | keycode[0], keycode[1], keycode[2], keycode[3], keycode[4], keycode[5]); 59 | 60 | // Remote wakeup 61 | if (tud_suspended()) { 62 | // Wake up host if we are in suspend mode 63 | // and REMOTE_WAKEUP feature is enabled by host 64 | tud_remote_wakeup(); 65 | } else { 66 | // Send the 1st of report chain, the rest will be sent by tud_hid_report_complete_cb() 67 | // skip if hid is not ready yet 68 | int i = 0; 69 | for (; i < 5 && !tud_hid_ready(); i++) { 70 | vTaskDelay(5); 71 | } 72 | if (i >= 5) { 73 | ESP_LOGW(__func__, "tinyusb not ready"); 74 | return; 75 | } 76 | 77 | tud_hid_keyboard_report(REPORT_ID_KEYBOARD, keycode[0], &keycode[2]); 78 | } 79 | } 80 | 81 | void tinyusb_hid_consumer_report(uint16_t keycode) 82 | { 83 | ESP_LOGD(TAG, "consumer code: %04x", keycode); 84 | 85 | // Remote wakeup 86 | if (tud_suspended()) { 87 | // Wake up host if we are in suspend mode 88 | // and REMOTE_WAKEUP feature is enabled by host 89 | tud_remote_wakeup(); 90 | } else { 91 | // Send the 1st of report chain, the rest will be sent by tud_hid_report_complete_cb() 92 | // skip if hid is not ready yet 93 | int i = 0; 94 | for (; i < 5 && !tud_hid_ready(); i++) { 95 | vTaskDelay(5); 96 | } 97 | if (i >= 5) { 98 | ESP_LOGW(__func__, "tinyusb not ready"); 99 | return; 100 | } 101 | 102 | tud_hid_report(REPORT_ID_CONSUMER, &keycode, sizeof(keycode)); 103 | } 104 | } 105 | 106 | /************************************************** TinyUSB callbacks ***********************************************/ 107 | // Invoked when sent REPORT successfully to host 108 | // Application can use this to send the next report 109 | // Note: For composite reports, report[0] is report ID 110 | void tud_hid_report_complete_cb(uint8_t itf, uint8_t const *report, uint8_t len) 111 | { 112 | (void) itf; 113 | (void) report; 114 | (void) len; 115 | } 116 | 117 | // Invoked when received GET_REPORT control request 118 | // Application must fill buffer report's content and return its length. 119 | // Return zero will cause the stack to STALL request 120 | uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t *buffer, uint16_t reqlen) 121 | { 122 | (void) instance; 123 | // esp_backtrace_print(8); 124 | // ESP_LOGI(TAG, "get instance %d, report id %d, report type %d, len %d", 125 | // instance, report_id, report_type, reqlen); 126 | 127 | if (report_type == HID_REPORT_TYPE_FEATURE) { 128 | if (report_id == REPORT_ID_MOUSE && reqlen >= 1) { 129 | /** 130 | * Return the resolution multiplier for high-resolution pointer & wheel. 131 | * Windows may deliberately aquire for this parameter, whereas Linux may not... 132 | */ 133 | buffer[0] = curr_resolution_multiplier; 134 | return 1; 135 | } 136 | } 137 | 138 | return 0; 139 | } 140 | 141 | // My template LED callback 142 | void __attribute__((weak)) kb_led_cb(uint8_t kbd_leds) 143 | { 144 | ESP_LOGI(TAG, "LED: 0x%02x", kbd_leds); 145 | } 146 | 147 | // Invoked when received SET_REPORT control request or 148 | // received data on OUT endpoint ( Report ID = 0, Type = 0 ) 149 | void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) 150 | { 151 | (void) instance; 152 | ESP_LOGI(TAG, "set instance %d, report id %d, report type %d, len %d, buf[0] 0x%02x", 153 | instance, report_id, report_type, bufsize, buffer[0]); 154 | 155 | if (report_type == HID_REPORT_TYPE_OUTPUT) { 156 | // Set keyboard LED e.g Capslock, Numlock etc... 157 | if (report_id == REPORT_ID_KEYBOARD) { 158 | // bufsize should be (at least) 1 159 | if ( bufsize < 1 ) return; 160 | 161 | kb_led_cb(buffer[0]); 162 | } 163 | } else if (report_type == HID_REPORT_TYPE_FEATURE) { 164 | if (report_id == REPORT_ID_MOUSE) { 165 | /** 166 | * Set the resolution multiplier. 167 | * Windows should set it on connection. 168 | */ 169 | if (bufsize >= 1) { 170 | curr_resolution_multiplier = buffer[0]; 171 | } 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /components/tinyusb/additions/src/tusb_msc.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020-2021 Espressif Systems (Shanghai) Co. Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "esp_err.h" 16 | #include "esp_log.h" 17 | #include "ffconf.h" 18 | #include "ff.h" 19 | #include "diskio.h" 20 | #include "tusb_msc.h" 21 | #include "esp_attr.h" 22 | 23 | #define LOGICAL_DISK_NUM 1 24 | 25 | static uint8_t s_pdrv[LOGICAL_DISK_NUM] = {0}; 26 | static tusb_msc_callback_t cb_mount[LOGICAL_DISK_NUM] = {NULL}; 27 | static tusb_msc_callback_t cb_unmount[LOGICAL_DISK_NUM] = {NULL}; 28 | static int s_disk_block_size[LOGICAL_DISK_NUM] = {0}; 29 | static bool s_ejected[LOGICAL_DISK_NUM] = {true}; 30 | 31 | esp_err_t tusb_msc_init(const tinyusb_config_msc_t *cfg) 32 | { 33 | if (cfg == NULL) { 34 | return ESP_ERR_INVALID_ARG; 35 | } 36 | 37 | cb_mount[0] = cfg->cb_mount; 38 | cb_unmount[0] = cfg->cb_unmount; 39 | s_pdrv[0] = cfg->pdrv; 40 | //s_pdrv[1] = 1; 41 | return ESP_OK; 42 | } 43 | 44 | //--------------------------------------------------------------------+ 45 | // tinyusb callbacks 46 | //--------------------------------------------------------------------+ 47 | 48 | // Invoked when device is mounted 49 | void tud_mount_cb(void) 50 | { 51 | // Reset the ejection tracking every time we're plugged into USB. This allows for us to battery 52 | // power the device, eject, unplug and plug it back in to get the drive. 53 | for (uint8_t i = 0; i < LOGICAL_DISK_NUM; i++) { 54 | s_ejected[i] = false; 55 | } 56 | 57 | if (cb_mount[0]) 58 | { 59 | cb_mount[0](0, NULL); 60 | } 61 | 62 | ESP_LOGI(__func__, ""); 63 | } 64 | 65 | // Invoked when device is unmounted 66 | void tud_umount_cb(void) 67 | { 68 | if (cb_unmount[0]) 69 | { 70 | cb_unmount[0](0, NULL); 71 | } 72 | 73 | ESP_LOGW(__func__, ""); 74 | } 75 | 76 | // Invoked when usb bus is suspended 77 | // remote_wakeup_en : if host allows us to perform remote wakeup 78 | // USB Specs: Within 7ms, device must draw an average current less than 2.5 mA from bus 79 | void tud_suspend_cb(bool remote_wakeup_en) 80 | { 81 | if (cb_unmount[0]) 82 | { 83 | cb_unmount[0](0, NULL); 84 | } 85 | ESP_LOGW(__func__, ""); 86 | } 87 | 88 | // Invoked when usb bus is resumed 89 | void tud_resume_cb(void) 90 | { 91 | ESP_LOGW(__func__, ""); 92 | } 93 | 94 | // Invoked to determine max LUN 95 | uint8_t tud_msc_get_maxlun_cb(void) 96 | { 97 | return LOGICAL_DISK_NUM; // dual LUN 98 | } 99 | 100 | // Callback invoked when WRITE10 command is completed (status received and accepted by host). 101 | // used to flush any pending cache. 102 | void tud_msc_write10_complete_cb(uint8_t lun) 103 | { 104 | if (unlikely(lun >= LOGICAL_DISK_NUM)) { 105 | ESP_LOGE(__func__, "invalid lun number %u", lun); 106 | return; 107 | } 108 | 109 | // This write is complete, start the autoreload clock. 110 | ESP_LOGD(__func__, ""); 111 | } 112 | 113 | static bool _logical_disk_ejected(void) 114 | { 115 | bool all_ejected = true; 116 | 117 | for (uint8_t i = 0; i < LOGICAL_DISK_NUM; i++) { 118 | all_ejected &= s_ejected[i]; 119 | } 120 | 121 | return all_ejected; 122 | } 123 | 124 | // Invoked when received SCSI_CMD_INQUIRY 125 | // Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively 126 | void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) 127 | { 128 | ESP_LOGD(__func__, ""); 129 | 130 | if (unlikely(lun >= LOGICAL_DISK_NUM)) { 131 | ESP_LOGE(__func__, "invalid lun number %u", lun); 132 | return; 133 | } 134 | 135 | const char vid[] = "Espressif"; 136 | const char pid[] = "Mass Storage"; 137 | const char rev[] = "1.0"; 138 | 139 | memcpy(vendor_id, vid, strlen(vid)); 140 | memcpy(product_id, pid, strlen(pid)); 141 | memcpy(product_rev, rev, strlen(rev)); 142 | } 143 | 144 | // Invoked when received Test Unit Ready command. 145 | // return true allowing host to read/write this LUN e.g SD card inserted 146 | bool tud_msc_test_unit_ready_cb(uint8_t lun) 147 | { 148 | ESP_LOGD(__func__, ""); 149 | 150 | if (unlikely(lun >= LOGICAL_DISK_NUM)) { 151 | ESP_LOGE(__func__, "invalid lun number %u", lun); 152 | return false; 153 | } 154 | 155 | if (_logical_disk_ejected()) { 156 | // Set 0x3a for media not present. 157 | tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3A, 0x00); 158 | return false; 159 | } 160 | 161 | return true; 162 | } 163 | 164 | // Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size 165 | // Application update block count and block size 166 | void tud_msc_capacity_cb(uint8_t lun, uint32_t *block_count, uint16_t *block_size) 167 | { 168 | ESP_LOGD(__func__, ""); 169 | 170 | if (unlikely(lun >= LOGICAL_DISK_NUM)) { 171 | ESP_LOGE(__func__, "invalid lun number %u", lun); 172 | return; 173 | } 174 | 175 | disk_ioctl(s_pdrv[lun], GET_SECTOR_COUNT, block_count); 176 | disk_ioctl(s_pdrv[lun], GET_SECTOR_SIZE, block_size); 177 | s_disk_block_size[lun] = *block_size; 178 | ESP_LOGD(__func__, "lun = %u GET_SECTOR_COUNT = %d,GET_SECTOR_SIZE = %d",lun, *block_count, *block_size); 179 | } 180 | 181 | bool tud_msc_is_writable_cb(uint8_t lun) 182 | { 183 | ESP_LOGD(__func__, ""); 184 | 185 | if (unlikely(lun >= LOGICAL_DISK_NUM)) { 186 | ESP_LOGE(__func__, "invalid lun number %u", lun); 187 | return false; 188 | } 189 | 190 | return true; 191 | } 192 | 193 | // Invoked when received Start Stop Unit command 194 | // - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage 195 | // - Start = 1 : active mode, if load_eject = 1 : load disk storage 196 | bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) 197 | { 198 | ESP_LOGI(__func__, ""); 199 | (void) power_condition; 200 | 201 | if (unlikely(lun >= LOGICAL_DISK_NUM)) { 202 | ESP_LOGE(__func__, "invalid lun number %u", lun); 203 | return false; 204 | } 205 | 206 | if (load_eject) { 207 | if (!start) { 208 | // Eject but first flush. 209 | if (disk_ioctl(s_pdrv[lun], CTRL_SYNC, NULL) != RES_OK) { 210 | return false; 211 | } else { 212 | s_ejected[lun] = true; 213 | } 214 | } else { 215 | // We can only load if it hasn't been ejected. 216 | return !s_ejected[lun]; 217 | } 218 | } else { 219 | if (!start) { 220 | // Stop the unit but don't eject. 221 | if (disk_ioctl(s_pdrv[lun], CTRL_SYNC, NULL) != RES_OK) { 222 | return false; 223 | } 224 | } 225 | 226 | // Always start the unit, even if ejected. Whether media is present is a separate check. 227 | } 228 | 229 | return true; 230 | } 231 | 232 | // Callback invoked when received READ10 command. 233 | // Copy disk's data to buffer (up to bufsize) and return number of copied bytes. 234 | IRAM_ATTR int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buffer, uint32_t bufsize) 235 | { 236 | ESP_LOGD(__func__, ""); 237 | 238 | if (unlikely(lun >= LOGICAL_DISK_NUM)) { 239 | ESP_LOGE(__func__, "invalid lun number %u", lun); 240 | return 0; 241 | } 242 | 243 | const uint32_t block_count = bufsize / s_disk_block_size[lun]; 244 | disk_read(s_pdrv[lun], buffer, lba, block_count); 245 | return block_count * s_disk_block_size[lun]; 246 | } 247 | 248 | // Callback invoked when received WRITE10 command. 249 | // Process data in buffer to disk's storage and return number of written bytes 250 | IRAM_ATTR int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t *buffer, uint32_t bufsize) 251 | { 252 | ESP_LOGD(__func__, ""); 253 | (void) offset; 254 | 255 | if (unlikely(lun >= LOGICAL_DISK_NUM)) { 256 | ESP_LOGE(__func__, "invalid lun number %u", lun); 257 | return 0; 258 | } 259 | 260 | const uint32_t block_count = bufsize / s_disk_block_size[lun]; 261 | disk_write(s_pdrv[lun], buffer, lba, block_count); 262 | return block_count * s_disk_block_size[lun]; 263 | } 264 | 265 | // Callback invoked when received an SCSI command not in built-in list below 266 | // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE 267 | // - READ10 and WRITE10 has their own callbacks 268 | int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void *buffer, uint16_t bufsize) 269 | { 270 | // read10 & write10 has their own callback and MUST not be handled here 271 | ESP_LOGD(__func__, ""); 272 | 273 | if (unlikely(lun >= LOGICAL_DISK_NUM)) { 274 | ESP_LOGE(__func__, "invalid lun number %u", lun); 275 | return 0; 276 | } 277 | 278 | void const *response = NULL; 279 | uint16_t resplen = 0; 280 | 281 | // most scsi handled is input 282 | bool in_xfer = true; 283 | 284 | switch (scsi_cmd[0]) { 285 | case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: 286 | // Host is about to read/write etc ... better not to disconnect disk 287 | resplen = 0; 288 | break; 289 | 290 | case SCSI_CMD_START_STOP_UNIT: 291 | // Host try to eject/safe remove/poweroff us. We could safely disconnect with disk storage, or go into lower power 292 | /* scsi_start_stop_unit_t const * start_stop = (scsi_start_stop_unit_t const *) scsi_cmd; 293 | // Start bit = 0 : low power mode, if load_eject = 1 : unmount disk storage as well 294 | // Start bit = 1 : Ready mode, if load_eject = 1 : mount disk storage 295 | start_stop->start; 296 | start_stop->load_eject; 297 | */ 298 | resplen = 0; 299 | break; 300 | 301 | default: 302 | // Set Sense = Invalid Command Operation 303 | tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); 304 | 305 | // negative means error -> tinyusb could stall and/or response with failed status 306 | resplen = -1; 307 | break; 308 | } 309 | 310 | // return resplen must not larger than bufsize 311 | if (resplen > bufsize) { 312 | resplen = bufsize; 313 | } 314 | 315 | if (response && (resplen > 0)) { 316 | if (in_xfer) { 317 | memcpy(buffer, response, resplen); 318 | } else { 319 | // SCSI output 320 | } 321 | } 322 | 323 | return resplen; 324 | } 325 | -------------------------------------------------------------------------------- /components/tinyusb/additions/src/tusb_tasks.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "sdkconfig.h" 16 | #include "freertos/FreeRTOS.h" 17 | #include "freertos/task.h" 18 | #include "esp_log.h" 19 | #include "esp_check.h" 20 | #include "tinyusb.h" 21 | #include "tusb_tasks.h" 22 | 23 | const static char *TAG = "tusb_tsk"; 24 | static TaskHandle_t s_tusb_tskh; 25 | 26 | /** 27 | * @brief This top level thread processes all usb events and invokes callbacks 28 | */ 29 | static void tusb_device_task(void *arg) 30 | { 31 | ESP_LOGD(TAG, "tinyusb task started"); 32 | while (1) { // RTOS forever loop 33 | tud_task(); 34 | } 35 | } 36 | 37 | esp_err_t tusb_run_task(void) 38 | { 39 | // This function is not garanteed to be thread safe, if invoked multiple times without calling `tusb_stop_task`, will cause memory leak 40 | // doing a sanity check anyway 41 | ESP_RETURN_ON_FALSE(!s_tusb_tskh, ESP_ERR_INVALID_STATE, TAG, "TinyUSB main task already started"); 42 | // Create a task for tinyusb device stack: 43 | xTaskCreate(tusb_device_task, "TinyUSB", CONFIG_TINYUSB_TASK_STACK_SIZE, NULL, CONFIG_TINYUSB_TASK_PRIORITY, &s_tusb_tskh); 44 | ESP_RETURN_ON_FALSE(s_tusb_tskh, ESP_FAIL, TAG, "create TinyUSB main task failed"); 45 | return ESP_OK; 46 | } 47 | 48 | esp_err_t tusb_stop_task(void) 49 | { 50 | ESP_RETURN_ON_FALSE(s_tusb_tskh, ESP_ERR_INVALID_STATE, TAG, "TinyUSB main task not started yet"); 51 | vTaskDelete(s_tusb_tskh); 52 | s_tusb_tskh = NULL; 53 | return ESP_OK; 54 | } 55 | -------------------------------------------------------------------------------- /components/tinyusb/additions/src/usb_descriptors.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "usb_descriptors.h" 16 | #include "sdkconfig.h" 17 | 18 | #define USB_TUSB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | _PID_MAP(MIDI, 3)) 19 | 20 | /**** TinyUSB default ****/ 21 | tusb_desc_device_t descriptor_tinyusb = { 22 | .bLength = sizeof(descriptor_tinyusb), 23 | .bDescriptorType = TUSB_DESC_DEVICE, 24 | .bcdUSB = 0x0200, 25 | 26 | #if CFG_TUD_CDC 27 | // Use Interface Association Descriptor (IAD) for CDC 28 | // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) 29 | .bDeviceClass = TUSB_CLASS_MISC, 30 | .bDeviceSubClass = MISC_SUBCLASS_COMMON, 31 | .bDeviceProtocol = MISC_PROTOCOL_IAD, 32 | #else 33 | .bDeviceClass = 0x00, 34 | .bDeviceSubClass = 0x00, 35 | .bDeviceProtocol = 0x00, 36 | #endif 37 | 38 | .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, 39 | 40 | .idVendor = 0xCafe, 41 | .idProduct = USB_TUSB_PID, 42 | .bcdDevice = 0x0100, 43 | 44 | .iManufacturer = 0x01, 45 | .iProduct = 0x02, 46 | .iSerialNumber = 0x03, 47 | 48 | .bNumConfigurations = 0x01 49 | }; 50 | 51 | tusb_desc_strarray_device_t descriptor_str_tinyusb = { 52 | // array of pointer to string descriptors 53 | (char[]){0x09, 0x04}, // 0: is supported language is English (0x0409) 54 | "TinyUSB", // 1: Manufacturer 55 | "TinyUSB Device", // 2: Product 56 | "123456", // 3: Serials, should use chip ID 57 | "TinyUSB CDC", // 4: CDC Interface 58 | "TinyUSB MSC", // 5: MSC Interface 59 | "TinyUSB HID" // 6: HID 60 | }; 61 | /* End of TinyUSB default */ 62 | 63 | /**** Kconfig driven Descriptor ****/ 64 | tusb_desc_device_t descriptor_kconfig = { 65 | .bLength = sizeof(descriptor_kconfig), 66 | .bDescriptorType = TUSB_DESC_DEVICE, 67 | .bcdUSB = 0x0200, 68 | 69 | #if CFG_TUD_CDC 70 | // Use Interface Association Descriptor (IAD) for CDC 71 | // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) 72 | .bDeviceClass = TUSB_CLASS_MISC, 73 | .bDeviceSubClass = MISC_SUBCLASS_COMMON, 74 | .bDeviceProtocol = MISC_PROTOCOL_IAD, 75 | #else 76 | .bDeviceClass = 0x00, 77 | .bDeviceSubClass = 0x00, 78 | .bDeviceProtocol = 0x00, 79 | #endif 80 | 81 | .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, 82 | 83 | #if CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID 84 | .idVendor = USB_ESPRESSIF_VID, 85 | #else 86 | .idVendor = CONFIG_TINYUSB_DESC_CUSTOM_VID, 87 | #endif 88 | 89 | #if CONFIG_TINYUSB_DESC_USE_DEFAULT_PID 90 | .idProduct = USB_TUSB_PID, 91 | #else 92 | .idProduct = CONFIG_TINYUSB_DESC_CUSTOM_PID, 93 | #endif 94 | 95 | .bcdDevice = CONFIG_TINYUSB_DESC_BCD_DEVICE, 96 | 97 | .iManufacturer = 0x01, 98 | .iProduct = 0x02, 99 | .iSerialNumber = 0x03, 100 | 101 | .bNumConfigurations = 0x01 102 | }; 103 | 104 | tusb_desc_strarray_device_t descriptor_str_kconfig = { 105 | // array of pointer to string descriptors 106 | (char[]){0x09, 0x04}, // 0: is supported language is English (0x0409) 107 | CONFIG_TINYUSB_DESC_MANUFACTURER_STRING, // 1: Manufacturer 108 | CONFIG_TINYUSB_DESC_PRODUCT_STRING, // 2: Product 109 | CONFIG_TINYUSB_DESC_SERIAL_STRING, // 3: Serials, should use chip ID 110 | 111 | #if CONFIG_TINYUSB_CDC_ENABLED 112 | CONFIG_TINYUSB_DESC_CDC_STRING, // 4: CDC Interface 113 | #else 114 | "", 115 | #endif 116 | 117 | #if CONFIG_TINYUSB_MSC_ENABLED 118 | CONFIG_TINYUSB_DESC_MSC_STRING, // 5: MSC Interface 119 | #else 120 | "", 121 | #endif 122 | 123 | #if CONFIG_TINYUSB_HID_ENABLED 124 | CONFIG_TINYUSB_DESC_HID_STRING // 6: HIDs 125 | #else 126 | "", 127 | #endif 128 | 129 | }; 130 | /* End of Kconfig driven Descriptor */ 131 | -------------------------------------------------------------------------------- /components/tinyusb/additions/src/vfs_tinyusb.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Espressif Systems (Shanghai) Co. Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include "esp_attr.h" 25 | #include "esp_log.h" 26 | #include "esp_vfs.h" 27 | #include "esp_vfs_dev.h" 28 | #include "tinyusb.h" 29 | #include "tusb_cdc_acm.h" 30 | #include "vfs_tinyusb.h" 31 | #include "sdkconfig.h" 32 | 33 | const static char *TAG = "tusb_vfs"; 34 | #define VFS_TUSB_MAX_PATH 16 35 | #define VFS_TUSB_PATH_DEFAULT "/dev/tusb_cdc" 36 | 37 | // Token signifying that no character is available 38 | #define NONE -1 39 | 40 | #define FD_CHECK(fd, ret_val) do { \ 41 | if ((fd) != 0) { \ 42 | errno = EBADF; \ 43 | return (ret_val); \ 44 | } \ 45 | } while (0) 46 | 47 | 48 | 49 | #if CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF 50 | # define DEFAULT_TX_MODE ESP_LINE_ENDINGS_CRLF 51 | #elif CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR 52 | # define DEFAULT_TX_MODE ESP_LINE_ENDINGS_CR 53 | #else 54 | # define DEFAULT_TX_MODE ESP_LINE_ENDINGS_LF 55 | #endif 56 | 57 | #if CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF 58 | # define DEFAULT_RX_MODE ESP_LINE_ENDINGS_CRLF 59 | #elif CONFIG_NEWLIB_STDIN_LINE_ENDING_CR 60 | # define DEFAULT_RX_MODE ESP_LINE_ENDINGS_CR 61 | #else 62 | # define DEFAULT_RX_MODE ESP_LINE_ENDINGS_LF 63 | #endif 64 | 65 | typedef struct { 66 | _lock_t write_lock; 67 | _lock_t read_lock; 68 | esp_line_endings_t tx_mode; // Newline conversion mode when transmitting 69 | esp_line_endings_t rx_mode; // Newline conversion mode when receiving 70 | uint32_t flags; 71 | char vfs_path[VFS_TUSB_MAX_PATH]; 72 | int cdc_intf; 73 | } vfs_tinyusb_t; 74 | 75 | static vfs_tinyusb_t s_vfstusb; 76 | 77 | 78 | static esp_err_t apply_path(char const *path) 79 | { 80 | if (path != NULL) { 81 | size_t path_len = strlen(path) + 1; 82 | if (path_len > VFS_TUSB_MAX_PATH) { 83 | ESP_LOGE(TAG, "The path is too long; maximum is %d characters", VFS_TUSB_MAX_PATH); 84 | return ESP_ERR_INVALID_ARG; 85 | } 86 | strncpy(s_vfstusb.vfs_path, path, (VFS_TUSB_MAX_PATH - 1)); 87 | } else { 88 | strncpy(s_vfstusb.vfs_path, 89 | VFS_TUSB_PATH_DEFAULT, 90 | (VFS_TUSB_MAX_PATH - 1)); 91 | } 92 | ESP_LOGV(TAG, "Path is set to `%s`", s_vfstusb.vfs_path); 93 | return ESP_OK; 94 | } 95 | 96 | /** 97 | * @brief Fill s_vfstusb 98 | * 99 | * @param cdc_intf - interface of tusb for registration 100 | * @param path - a path where the CDC will be registered 101 | * @return esp_err_t ESP_OK or ESP_ERR_INVALID_ARG 102 | */ 103 | static esp_err_t vfstusb_init(int cdc_intf, char const *path) 104 | { 105 | s_vfstusb.cdc_intf = cdc_intf; 106 | s_vfstusb.tx_mode = DEFAULT_TX_MODE; 107 | s_vfstusb.rx_mode = DEFAULT_RX_MODE; 108 | 109 | return apply_path(path); 110 | } 111 | 112 | /** 113 | * @brief Clear s_vfstusb to default values 114 | */ 115 | static void vfstusb_deinit(void) 116 | { 117 | memset(&s_vfstusb, 0, sizeof(s_vfstusb)); 118 | } 119 | 120 | 121 | static int tusb_open(const char *path, int flags, int mode) 122 | { 123 | (void) mode; 124 | (void) path; 125 | s_vfstusb.flags = flags | O_NONBLOCK; // for now only non-blocking mode is implemented 126 | return 0; 127 | } 128 | 129 | static ssize_t tusb_write(int fd, const void *data, size_t size) 130 | { 131 | FD_CHECK(fd, -1); 132 | size_t written_sz = 0; 133 | const char *data_c = (const char *)data; 134 | _lock_acquire(&(s_vfstusb.write_lock)); 135 | for (size_t i = 0; i < size; i++) { 136 | int c = data_c[i]; 137 | /* handling the EOL */ 138 | if (c == '\n' && s_vfstusb.tx_mode != ESP_LINE_ENDINGS_LF) { 139 | if (tinyusb_cdcacm_write_queue_char(s_vfstusb.cdc_intf, '\r')) { 140 | written_sz++; 141 | } else { 142 | break; // can't write anymore 143 | } 144 | if (s_vfstusb.tx_mode == ESP_LINE_ENDINGS_CR) { 145 | continue; 146 | } 147 | } 148 | /* write a char */ 149 | if (tinyusb_cdcacm_write_queue_char(s_vfstusb.cdc_intf, c)) { 150 | written_sz++; 151 | } else { 152 | break; // can't write anymore 153 | } 154 | 155 | } 156 | tud_cdc_n_write_flush(s_vfstusb.cdc_intf); 157 | _lock_release(&(s_vfstusb.write_lock)); 158 | return written_sz; 159 | } 160 | 161 | static int tusb_close(int fd) 162 | { 163 | FD_CHECK(fd, -1); 164 | return 0; 165 | } 166 | 167 | static ssize_t tusb_read(int fd, void *data, size_t size) 168 | { 169 | FD_CHECK(fd, -1); 170 | char *data_c = (char *) data; 171 | size_t received = 0; 172 | _lock_acquire(&(s_vfstusb.read_lock)); 173 | int cm1 = NONE; 174 | int c = NONE; 175 | 176 | while (received < size) { 177 | cm1 = c; // store the old char 178 | int c = tud_cdc_n_read_char(0); // get a new one 179 | if (s_vfstusb.rx_mode == ESP_LINE_ENDINGS_CR) { 180 | if (c == '\r') { 181 | c = '\n'; 182 | } 183 | } else if (s_vfstusb.rx_mode == ESP_LINE_ENDINGS_CR) { 184 | if ((c == '\n') & (cm1 == '\r')) { 185 | --received; // step back 186 | c = '\n'; 187 | } 188 | } 189 | if ( c == NONE) { // if data ends 190 | break; 191 | } 192 | data_c[received] = (char) c; 193 | ++received; 194 | if (c == '\n') { 195 | break; 196 | } 197 | } 198 | _lock_release(&(s_vfstusb.read_lock)); 199 | if (received > 0) { 200 | return received; 201 | } 202 | errno = EWOULDBLOCK; 203 | return -1; 204 | } 205 | 206 | 207 | static int tusb_fstat(int fd, struct stat *st) 208 | { 209 | FD_CHECK(fd, -1); 210 | memset(st, 0, sizeof(*st)); 211 | st->st_mode = S_IFCHR; 212 | return 0; 213 | } 214 | 215 | static int tusb_fcntl(int fd, int cmd, int arg) 216 | { 217 | FD_CHECK(fd, -1); 218 | int result = 0; 219 | switch (cmd) { 220 | case F_GETFL: 221 | result = s_vfstusb.flags; 222 | break; 223 | case F_SETFL: 224 | s_vfstusb.flags = arg; 225 | break; 226 | default: 227 | result = -1; 228 | errno = ENOSYS; 229 | break; 230 | } 231 | return result; 232 | } 233 | 234 | esp_err_t esp_vfs_tusb_cdc_unregister(char const *path) 235 | { 236 | ESP_LOGD(TAG, "Unregistering TinyUSB driver"); 237 | int res; 238 | 239 | if (path == NULL) { // NULL means using the default path for unregistering: VFS_TUSB_PATH_DEFAULT 240 | res = strcmp(s_vfstusb.vfs_path, VFS_TUSB_PATH_DEFAULT); 241 | } else { 242 | res = strcmp(s_vfstusb.vfs_path, path); 243 | } 244 | 245 | if (res) { 246 | res = ESP_ERR_INVALID_ARG; 247 | ESP_LOGE(TAG, "There is no TinyUSB driver registerred to the path '%s' (err: 0x%x)", s_vfstusb.vfs_path, res); 248 | return res; 249 | } 250 | 251 | 252 | 253 | res = esp_vfs_unregister(s_vfstusb.vfs_path); 254 | if (res != ESP_OK) { 255 | ESP_LOGE(TAG, "Can't unregister TinyUSB driver from '%s' (err: 0x%x)", s_vfstusb.vfs_path, res); 256 | } else { 257 | ESP_LOGD(TAG, "Unregistered TinyUSB driver"); 258 | vfstusb_deinit(); 259 | } 260 | return res; 261 | } 262 | 263 | 264 | 265 | 266 | esp_err_t esp_vfs_tusb_cdc_register(int cdc_intf, char const *path) 267 | { 268 | ESP_LOGD(TAG, "Registering TinyUSB CDC driver"); 269 | int res; 270 | if (!tusb_cdc_acm_initialized(cdc_intf)) { 271 | ESP_LOGE(TAG, "TinyUSB CDC#%d is not initialized", cdc_intf); 272 | return ESP_ERR_INVALID_STATE; 273 | } 274 | 275 | res = vfstusb_init(cdc_intf, path); 276 | if (res != ESP_OK) { 277 | return res; 278 | } 279 | 280 | esp_vfs_t vfs = { 281 | .flags = ESP_VFS_FLAG_DEFAULT, 282 | .close = &tusb_close, 283 | .fcntl = &tusb_fcntl, 284 | .fstat = &tusb_fstat, 285 | .open = &tusb_open, 286 | .read = &tusb_read, 287 | .write = &tusb_write, 288 | }; 289 | 290 | res = esp_vfs_register(s_vfstusb.vfs_path, &vfs, NULL); 291 | if (res != ESP_OK) { 292 | ESP_LOGE(TAG, "Can't register TinyUSB driver (err: %x)", res); 293 | } else { 294 | ESP_LOGD(TAG, "TinyUSB CDC registered (%s)", s_vfstusb.vfs_path); 295 | } 296 | return res; 297 | } 298 | -------------------------------------------------------------------------------- /components/tinyusb/idf_component.yml: -------------------------------------------------------------------------------- 1 | version: "1.1.0" # Component version, required only for components pushed to the service 2 | targets: # List of supported targets (optional, if missing all targets are considered to be supported) 3 | - esp32s2 4 | - esp32s3 5 | description: ESP32-S2 TinyUSB Addtions # Description (optional) 6 | url: https://github.com/iot-components/tinyusb # Original repository (optional) 7 | dependencies: 8 | # Required IDF version 9 | idf: 10 | version: ">=4.4" 11 | -------------------------------------------------------------------------------- /components/tinyusb/sdkconfig.rename: -------------------------------------------------------------------------------- 1 | # sdkconfig replacement configurations for deprecated options formatted as 2 | # CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION 3 | CONFIG_USB_ENABLED CONFIG_TINYUSB 4 | CONFIG_USB_DO_NOT_CREATE_TASK CONFIG_TINYUSB_NO_DEFAULT_TASK 5 | CONFIG_USB_TASK_PRIORITY CONFIG_TINYUSB_TASK_PRIORITY 6 | CONFIG_USB_DESC_USE_ESPRESSIF_VID CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID 7 | CONFIG_USB_DESC_CUSTOM_VID CONFIG_TINYUSB_DESC_CUSTOM_VID 8 | CONFIG_USB_DESC_USE_DEFAULT_PID CONFIG_TINYUSB_DESC_USE_DEFAULT_PID 9 | CONFIG_USB_DESC_CUSTOM_PID CONFIG_TINYUSB_DESC_CUSTOM_PID 10 | CONFIG_USB_DESC_BCDDEVICE CONFIG_TINYUSB_DESC_BCD_DEVICE 11 | CONFIG_USB_DESC_MANUFACTURER_STRING CONFIG_TINYUSB_DESC_MANUFACTURER_STRING 12 | CONFIG_USB_DESC_PRODUCT_STRING CONFIG_TINYUSB_DESC_PRODUCT_STRING 13 | CONFIG_USB_DESC_SERIAL_STRING CONFIG_TINYUSB_DESC_SERIAL_STRING 14 | CONFIG_USB_DESC_CDC_STRING CONFIG_TINYUSB_DESC_CDC_STRING 15 | CONFIG_USB_DESC_MSC_STRING CONFIG_TINYUSB_DESC_MSC_STRING 16 | CONFIG_USB_DESC_HID_STRING CONFIG_TINYUSB_DESC_HID_STRING 17 | CONFIG_USB_MSC_ENABLED CONFIG_TINYUSB_MSC_ENABLED 18 | CONFIG_USB_MSC_BUFSIZE CONFIG_TINYUSB_MSC_BUFSIZE 19 | CONFIG_USB_CDC_ENABLED CONFIG_TINYUSB_CDC_ENABLED 20 | CONFIG_USB_CDC_RX_BUFSIZE CONFIG_TINYUSB_CDC_RX_BUFSIZE 21 | CONFIG_USB_CDC_TX_BUFSIZE CONFIG_TINYUSB_CDC_TX_BUFSIZE 22 | CONFIG_USB_DEBUG_LEVEL CONFIG_TINYUSB_DEBUG_LEVEL 23 | -------------------------------------------------------------------------------- /hardware/esp32_keyboard.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hhuysqt/esp32s3-keyboard/f6a5c573fb7a1ffcf0233ad4d05a9c2e8053f316/hardware/esp32_keyboard.pdf -------------------------------------------------------------------------------- /hardware/kicad_proj/esp32-keyboard-v0.1-gerber.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hhuysqt/esp32s3-keyboard/f6a5c573fb7a1ffcf0233ad4d05a9c2e8053f316/hardware/kicad_proj/esp32-keyboard-v0.1-gerber.zip -------------------------------------------------------------------------------- /hardware/kicad_proj/esp32_keyboard-v0.1.pro: -------------------------------------------------------------------------------- 1 | update=2021年12月05日 星期日 15时08分39秒 2 | version=1 3 | last_client=pcbnew 4 | [general] 5 | version=1 6 | RootSch= 7 | BoardNm= 8 | [cvpcb] 9 | version=1 10 | NetIExt=net 11 | [eeschema] 12 | version=1 13 | LibDir= 14 | [eeschema/libraries] 15 | [pcbnew] 16 | version=1 17 | PageLayoutDescrFile= 18 | LastNetListRead=esp32_keyboard.net 19 | CopperLayerCount=2 20 | BoardThickness=1.6 21 | AllowMicroVias=0 22 | AllowBlindVias=0 23 | RequireCourtyardDefinitions=0 24 | ProhibitOverlappingCourtyards=1 25 | MinTrackWidth=0.2 26 | MinViaDiameter=0.4 27 | MinViaDrill=0.3 28 | MinMicroViaDiameter=0.2 29 | MinMicroViaDrill=0.09999999999999999 30 | MinHoleToHole=0.25 31 | TrackWidth1=0.25 32 | TrackWidth2=0.2 33 | TrackWidth3=0.3 34 | TrackWidth4=0.4 35 | TrackWidth5=0.5 36 | TrackWidth6=0.6 37 | ViaDiameter1=0.8 38 | ViaDrill1=0.4 39 | ViaDiameter2=0.6 40 | ViaDrill2=0.3 41 | ViaDiameter3=0.7 42 | ViaDrill3=0.4 43 | dPairWidth1=0.2 44 | dPairGap1=0.25 45 | dPairViaGap1=0.25 46 | SilkLineWidth=0.12 47 | SilkTextSizeV=1 48 | SilkTextSizeH=1 49 | SilkTextSizeThickness=0.15 50 | SilkTextItalic=0 51 | SilkTextUpright=1 52 | CopperLineWidth=0.2 53 | CopperTextSizeV=1.5 54 | CopperTextSizeH=1.5 55 | CopperTextThickness=0.3 56 | CopperTextItalic=0 57 | CopperTextUpright=1 58 | EdgeCutLineWidth=0.05 59 | CourtyardLineWidth=0.05 60 | OthersLineWidth=0.15 61 | OthersTextSizeV=1 62 | OthersTextSizeH=1 63 | OthersTextSizeThickness=0.15 64 | OthersTextItalic=0 65 | OthersTextUpright=1 66 | SolderMaskClearance=0 67 | SolderMaskMinWidth=0 68 | SolderPasteClearance=0 69 | SolderPasteRatio=0 70 | [pcbnew/Layer.F.Cu] 71 | Name=F.Cu 72 | Type=0 73 | Enabled=1 74 | [pcbnew/Layer.In1.Cu] 75 | Name=In1.Cu 76 | Type=0 77 | Enabled=0 78 | [pcbnew/Layer.In2.Cu] 79 | Name=In2.Cu 80 | Type=0 81 | Enabled=0 82 | [pcbnew/Layer.In3.Cu] 83 | Name=In3.Cu 84 | Type=0 85 | Enabled=0 86 | [pcbnew/Layer.In4.Cu] 87 | Name=In4.Cu 88 | Type=0 89 | Enabled=0 90 | [pcbnew/Layer.In5.Cu] 91 | Name=In5.Cu 92 | Type=0 93 | Enabled=0 94 | [pcbnew/Layer.In6.Cu] 95 | Name=In6.Cu 96 | Type=0 97 | Enabled=0 98 | [pcbnew/Layer.In7.Cu] 99 | Name=In7.Cu 100 | Type=0 101 | Enabled=0 102 | [pcbnew/Layer.In8.Cu] 103 | Name=In8.Cu 104 | Type=0 105 | Enabled=0 106 | [pcbnew/Layer.In9.Cu] 107 | Name=In9.Cu 108 | Type=0 109 | Enabled=0 110 | [pcbnew/Layer.In10.Cu] 111 | Name=In10.Cu 112 | Type=0 113 | Enabled=0 114 | [pcbnew/Layer.In11.Cu] 115 | Name=In11.Cu 116 | Type=0 117 | Enabled=0 118 | [pcbnew/Layer.In12.Cu] 119 | Name=In12.Cu 120 | Type=0 121 | Enabled=0 122 | [pcbnew/Layer.In13.Cu] 123 | Name=In13.Cu 124 | Type=0 125 | Enabled=0 126 | [pcbnew/Layer.In14.Cu] 127 | Name=In14.Cu 128 | Type=0 129 | Enabled=0 130 | [pcbnew/Layer.In15.Cu] 131 | Name=In15.Cu 132 | Type=0 133 | Enabled=0 134 | [pcbnew/Layer.In16.Cu] 135 | Name=In16.Cu 136 | Type=0 137 | Enabled=0 138 | [pcbnew/Layer.In17.Cu] 139 | Name=In17.Cu 140 | Type=0 141 | Enabled=0 142 | [pcbnew/Layer.In18.Cu] 143 | Name=In18.Cu 144 | Type=0 145 | Enabled=0 146 | [pcbnew/Layer.In19.Cu] 147 | Name=In19.Cu 148 | Type=0 149 | Enabled=0 150 | [pcbnew/Layer.In20.Cu] 151 | Name=In20.Cu 152 | Type=0 153 | Enabled=0 154 | [pcbnew/Layer.In21.Cu] 155 | Name=In21.Cu 156 | Type=0 157 | Enabled=0 158 | [pcbnew/Layer.In22.Cu] 159 | Name=In22.Cu 160 | Type=0 161 | Enabled=0 162 | [pcbnew/Layer.In23.Cu] 163 | Name=In23.Cu 164 | Type=0 165 | Enabled=0 166 | [pcbnew/Layer.In24.Cu] 167 | Name=In24.Cu 168 | Type=0 169 | Enabled=0 170 | [pcbnew/Layer.In25.Cu] 171 | Name=In25.Cu 172 | Type=0 173 | Enabled=0 174 | [pcbnew/Layer.In26.Cu] 175 | Name=In26.Cu 176 | Type=0 177 | Enabled=0 178 | [pcbnew/Layer.In27.Cu] 179 | Name=In27.Cu 180 | Type=0 181 | Enabled=0 182 | [pcbnew/Layer.In28.Cu] 183 | Name=In28.Cu 184 | Type=0 185 | Enabled=0 186 | [pcbnew/Layer.In29.Cu] 187 | Name=In29.Cu 188 | Type=0 189 | Enabled=0 190 | [pcbnew/Layer.In30.Cu] 191 | Name=In30.Cu 192 | Type=0 193 | Enabled=0 194 | [pcbnew/Layer.B.Cu] 195 | Name=B.Cu 196 | Type=0 197 | Enabled=1 198 | [pcbnew/Layer.B.Adhes] 199 | Enabled=1 200 | [pcbnew/Layer.F.Adhes] 201 | Enabled=1 202 | [pcbnew/Layer.B.Paste] 203 | Enabled=1 204 | [pcbnew/Layer.F.Paste] 205 | Enabled=1 206 | [pcbnew/Layer.B.SilkS] 207 | Enabled=1 208 | [pcbnew/Layer.F.SilkS] 209 | Enabled=1 210 | [pcbnew/Layer.B.Mask] 211 | Enabled=1 212 | [pcbnew/Layer.F.Mask] 213 | Enabled=1 214 | [pcbnew/Layer.Dwgs.User] 215 | Enabled=1 216 | [pcbnew/Layer.Cmts.User] 217 | Enabled=1 218 | [pcbnew/Layer.Eco1.User] 219 | Enabled=1 220 | [pcbnew/Layer.Eco2.User] 221 | Enabled=1 222 | [pcbnew/Layer.Edge.Cuts] 223 | Enabled=1 224 | [pcbnew/Layer.Margin] 225 | Enabled=1 226 | [pcbnew/Layer.B.CrtYd] 227 | Enabled=1 228 | [pcbnew/Layer.F.CrtYd] 229 | Enabled=1 230 | [pcbnew/Layer.B.Fab] 231 | Enabled=1 232 | [pcbnew/Layer.F.Fab] 233 | Enabled=1 234 | [pcbnew/Layer.Rescue] 235 | Enabled=0 236 | [pcbnew/Netclasses] 237 | [pcbnew/Netclasses/Default] 238 | Name=Default 239 | Clearance=0.2 240 | TrackWidth=0.25 241 | ViaDiameter=0.8 242 | ViaDrill=0.4 243 | uViaDiameter=0.3 244 | uViaDrill=0.1 245 | dPairWidth=0.2 246 | dPairGap=0.25 247 | dPairViaGap=0.25 248 | -------------------------------------------------------------------------------- /hardware/kicad_proj/fp-lib-table: -------------------------------------------------------------------------------- 1 | (fp_lib_table 2 | (lib (name mylib)(type KiCad)(uri ${KIPRJMOD}/mylib.pretty)(options "")(descr "")) 3 | ) 4 | -------------------------------------------------------------------------------- /hardware/kicad_proj/mylib.lib: -------------------------------------------------------------------------------- 1 | EESchema-LIBRARY Version 2.4 2 | #encoding utf-8 3 | # 4 | # ESP32-S3-WROOM-1 5 | # 6 | DEF ESP32-S3-WROOM-1 U 0 20 Y Y 1 F N 7 | F0 "U" -800 1150 50 H V L CNN 8 | F1 "ESP32-S3-WROOM-1" -400 1150 50 H V L CNN 9 | F2 "mylib:ESP32-S3-WROOM-1" 0 700 50 H I C CNN 10 | F3 "" -700 50 50 H I C CNN 11 | $FPLIST 12 | ESP32?WROOM?32* 13 | $ENDFPLIST 14 | DRAW 15 | S -800 1100 800 -650 0 1 10 f 16 | X GND 1 -1000 900 200 R 50 50 1 1 W 17 | X IO17 10 -1000 0 200 R 50 50 1 1 B 18 | X IO18 11 -1000 -100 200 R 50 50 1 1 B 19 | X IO8 12 -1000 -200 200 R 50 50 1 1 B 20 | X IO19 13 -1000 -300 200 R 50 50 1 1 B 21 | X IO20 14 -1000 -400 200 R 50 50 1 1 B 22 | X IO3 15 -550 -850 200 U 50 50 1 1 B 23 | X IO46 16 -450 -850 200 U 50 50 1 1 B 24 | X IO9 17 -350 -850 200 U 50 50 1 1 B 25 | X IO10 18 -250 -850 200 U 50 50 1 1 B 26 | X IO11 19 -150 -850 200 U 50 50 1 1 B 27 | X 3V3 2 -1000 800 200 R 50 50 1 1 W 28 | X IO12 20 -50 -850 200 U 50 50 1 1 B 29 | X IO13 21 50 -850 200 U 50 50 1 1 B 30 | X IO14 22 150 -850 200 U 50 50 1 1 B 31 | X IO21 23 250 -850 200 U 50 50 1 1 B 32 | X IO47 24 350 -850 200 U 50 50 1 1 B 33 | X IO48 25 450 -850 200 U 50 50 1 1 B 34 | X IO45 26 550 -850 200 U 50 50 1 1 B 35 | X IO0 27 1000 -400 200 L 50 50 1 1 B 36 | X IO35 28 1000 -300 200 L 50 50 1 1 B 37 | X IO36 29 1000 -200 200 L 50 50 1 1 B 38 | X EN 3 -1000 700 200 R 50 50 1 1 I 39 | X IO37 30 1000 -100 200 L 50 50 1 1 B 40 | X IO38 31 1000 0 200 L 50 50 1 1 B 41 | X IO39 32 1000 100 200 L 50 50 1 1 B 42 | X IO40 33 1000 200 200 L 50 50 1 1 B 43 | X IO41 34 1000 300 200 L 50 50 1 1 B 44 | X IO42 35 1000 400 200 L 50 50 1 1 B 45 | X IO44/RXD0 36 1000 500 200 L 50 50 1 1 B 46 | X IO43/TXD0 37 1000 600 200 L 50 50 1 1 B 47 | X IO2 38 1000 700 200 L 50 50 1 1 B 48 | X IO1 39 1000 800 200 L 50 50 1 1 B 49 | X IO4 4 -1000 600 200 R 50 50 1 1 B 50 | X GND 40 1000 900 200 L 50 50 1 1 B 51 | X GND 41 1000 1000 200 L 50 50 1 1 B 52 | X IO5 5 -1000 500 200 R 50 50 1 1 B 53 | X IO6 6 -1000 400 200 R 50 50 1 1 B 54 | X IO7 7 -1000 300 200 R 50 50 1 1 B 55 | X IO15 8 -1000 200 200 R 50 50 1 1 B 56 | X IO16 9 -1000 100 200 R 50 50 1 1 B 57 | ENDDRAW 58 | ENDDEF 59 | # 60 | # Keyboard-30p 61 | # 62 | DEF Keyboard-30p U 0 40 Y Y 1 F N 63 | F0 "U" -900 900 50 H V C CNN 64 | F1 "Keyboard-30p" -400 900 50 H V C CNN 65 | F2 "Connector_FFC-FPC:TE_3-84952-0_1x30-1MP_P1.0mm_Horizontal" 100 0 50 H I C CNN 66 | F3 "" 100 0 50 H I C CNN 67 | DRAW 68 | S -250 -2250 -900 850 0 1 0 f 69 | X SENSE3 1 -50 750 200 L 50 50 1 1 B 70 | X DRV4 10 -50 -150 200 L 50 50 1 1 B 71 | X DRV2 11 -50 -250 200 L 50 50 1 1 B 72 | X SENSE5 12 -50 -350 200 L 50 50 1 1 B 73 | X DRV1 13 -50 -450 200 L 50 50 1 1 B 74 | X DRV3 14 -50 -550 200 L 50 50 1 1 B 75 | X DRV6 15 -50 -650 200 L 50 50 1 1 B 76 | X DRV7 16 -50 -750 200 L 50 50 1 1 B 77 | X DRV5 17 -50 -850 200 L 50 50 1 1 B 78 | X DRV15 18 -50 -950 200 L 50 50 1 1 B 79 | X DRV13 19 -50 -1050 200 L 50 50 1 1 B 80 | X SENSE7 2 -50 650 200 L 50 50 1 1 B 81 | X DRV9 20 -50 -1150 200 L 50 50 1 1 B 82 | X DRV12 21 -50 -1250 200 L 50 50 1 1 B 83 | X DRV10 22 -50 -1350 200 L 50 50 1 1 B 84 | X DRV8 23 -50 -1450 200 L 50 50 1 1 B 85 | X DRV11 24 -50 -1550 200 L 50 50 1 1 B 86 | X TP_GND 25 -50 -1650 200 L 50 50 1 1 W 87 | X TP_LEFT 26 -50 -1750 200 L 50 50 1 1 P 88 | X TP_MIDDLE 27 -50 -1850 200 L 50 50 1 1 P 89 | X TP_RIGHT 28 -50 -1950 200 L 50 50 1 1 P 90 | X DRV16 29 -50 -2050 200 L 50 50 1 1 B 91 | X SENSE6 3 -50 550 200 L 50 50 1 1 B 92 | X DRV17 30 -50 -2150 200 L 50 50 1 1 B 93 | X DRV14 4 -50 450 200 L 50 50 1 1 B 94 | X SENSE4 5 -50 350 200 L 50 50 1 1 B 95 | X SENSE1 6 -50 250 200 L 50 50 1 1 B 96 | X DRV0 7 -50 150 200 L 50 50 1 1 B 97 | X SENSE2 8 -50 50 200 L 50 50 1 1 B 98 | X SENSE0 9 -50 -50 200 L 50 50 1 1 B 99 | X NC MP -1000 -2150 100 R 50 50 1 1 N 100 | X NC MP -1000 -2050 100 R 50 50 1 1 N 101 | ENDDRAW 102 | ENDDEF 103 | # 104 | # Keyboard-36p 105 | # 106 | DEF Keyboard-36p U 0 40 Y Y 1 F N 107 | F0 "U" -900 900 50 H V C CNN 108 | F1 "Keyboard-36p" -500 900 50 H V C CNN 109 | F2 "Connector_FFC-FPC:TE_4-1734839-0_1x40-1MP_P0.5mm_Horizontal" 100 0 50 H I C CNN 110 | F3 "" 100 0 50 H I C CNN 111 | DRAW 112 | S -250 -2850 -900 850 0 1 0 f 113 | X TP_LEFT 33 -50 -2450 200 L 50 50 0 1 P 114 | X SENSE3 1 -50 750 200 L 50 50 1 1 B 115 | X DRV4 10 -50 -150 200 L 50 50 1 1 B 116 | X DRV2 11 -50 -250 200 L 50 50 1 1 B 117 | X SENSE5 12 -50 -350 200 L 50 50 1 1 B 118 | X DRV1 13 -50 -450 200 L 50 50 1 1 B 119 | X DRV3 14 -50 -550 200 L 50 50 1 1 B 120 | X DRV6 15 -50 -650 200 L 50 50 1 1 B 121 | X DRV7 16 -50 -750 200 L 50 50 1 1 B 122 | X DRV5 17 -50 -850 200 L 50 50 1 1 B 123 | X DRV15 18 -50 -950 200 L 50 50 1 1 B 124 | X DRV13 19 -50 -1050 200 L 50 50 1 1 B 125 | X SENSE7 2 -50 650 200 L 50 50 1 1 B 126 | X DRV9 20 -50 -1150 200 L 50 50 1 1 B 127 | X DRV12 21 -50 -1250 200 L 50 50 1 1 B 128 | X DRV10 22 -50 -1350 200 L 50 50 1 1 B 129 | X DRV8 23 -50 -1450 200 L 50 50 1 1 B 130 | X DRV11 24 -50 -1550 200 L 50 50 1 1 B 131 | X VCC 25 -50 -1650 200 L 50 50 1 1 W 132 | X LED1_FnLk 26 -50 -1750 200 L 50 50 1 1 I 133 | X LED2_F1 27 -50 -1850 200 L 50 50 1 1 I 134 | X LED3_F4 28 -50 -1950 200 L 50 50 1 1 I 135 | X Fn/HOTKEY 29 -50 -2050 200 L 50 50 1 1 P 136 | X SENSE6 3 -50 550 200 L 50 50 1 1 B 137 | X GND 30 -50 -2150 200 L 50 50 1 1 W 138 | X LED4_CapLk 31 -50 -2250 200 L 50 50 1 1 I 139 | X TP_GND 32 -50 -2350 200 L 50 50 1 1 W 140 | X TP_RIGHT 34 -50 -2550 200 L 50 50 1 1 P 141 | X TP_MIDDLE 35 -50 -2650 200 L 50 50 1 1 P 142 | X KB_ID 36 -50 -2750 200 L 50 50 1 1 B 143 | X DRV14 4 -50 450 200 L 50 50 1 1 B 144 | X SENSE4 5 -50 350 200 L 50 50 1 1 B 145 | X SENSE1 6 -50 250 200 L 50 50 1 1 B 146 | X DRV0 7 -50 150 200 L 50 50 1 1 B 147 | X SENSE2 8 -50 50 200 L 50 50 1 1 B 148 | X SENSE0 9 -50 -50 200 L 50 50 1 1 B 149 | X NC MP -1000 -2750 100 R 50 50 1 1 N 150 | X NC MP -1000 -2650 100 R 50 50 1 1 N 151 | ENDDRAW 152 | ENDDEF 153 | # 154 | # Keyboard-40p 155 | # 156 | DEF Keyboard-40p U 0 40 Y Y 1 F N 157 | F0 "U" -900 900 50 H V C CNN 158 | F1 "Keyboard-40p" -500 900 50 H V C CNN 159 | F2 "Connector_FFC-FPC:TE_4-1734839-0_1x40-1MP_P0.5mm_Horizontal" 100 0 50 H I C CNN 160 | F3 "" 100 0 50 H I C CNN 161 | DRAW 162 | S -250 -3250 -900 850 0 1 0 f 163 | X NC 39 -50 -3050 200 L 50 50 1 0 N 164 | X TP_LEFT 33 -50 -2450 200 L 50 50 0 1 P 165 | X NC 40 -50 -3150 200 L 50 50 0 1 N 166 | X SENSE3 1 -50 750 200 L 50 50 1 1 B 167 | X DRV4 10 -50 -150 200 L 50 50 1 1 B 168 | X DRV2 11 -50 -250 200 L 50 50 1 1 B 169 | X SENSE5 12 -50 -350 200 L 50 50 1 1 B 170 | X DRV1 13 -50 -450 200 L 50 50 1 1 B 171 | X DRV3 14 -50 -550 200 L 50 50 1 1 B 172 | X DRV6 15 -50 -650 200 L 50 50 1 1 B 173 | X DRV7 16 -50 -750 200 L 50 50 1 1 B 174 | X DRV5 17 -50 -850 200 L 50 50 1 1 B 175 | X DRV15 18 -50 -950 200 L 50 50 1 1 B 176 | X DRV13 19 -50 -1050 200 L 50 50 1 1 B 177 | X SENSE7 2 -50 650 200 L 50 50 1 1 B 178 | X DRV9 20 -50 -1150 200 L 50 50 1 1 B 179 | X DRV12 21 -50 -1250 200 L 50 50 1 1 B 180 | X DRV10 22 -50 -1350 200 L 50 50 1 1 B 181 | X DRV8 23 -50 -1450 200 L 50 50 1 1 B 182 | X DRV11 24 -50 -1550 200 L 50 50 1 1 B 183 | X VCC 25 -50 -1650 200 L 50 50 1 1 W 184 | X LED1_FnLk 26 -50 -1750 200 L 50 50 1 1 I 185 | X LED2_F1 27 -50 -1850 200 L 50 50 1 1 I 186 | X LED3_F4 28 -50 -1950 200 L 50 50 1 1 I 187 | X Fn/HOTKEY 29 -50 -2050 200 L 50 50 1 1 P 188 | X SENSE6 3 -50 550 200 L 50 50 1 1 B 189 | X GND 30 -50 -2150 200 L 50 50 1 1 W 190 | X LED4_CapLk 31 -50 -2250 200 L 50 50 1 1 I 191 | X TP_GND 32 -50 -2350 200 L 50 50 1 1 W 192 | X TP_RIGHT 34 -50 -2550 200 L 50 50 1 1 P 193 | X TP_MIDDLE 35 -50 -2650 200 L 50 50 1 1 P 194 | X DRV16 36 -50 -2750 200 L 50 50 1 1 B 195 | X DRV17 37 -50 -2850 200 L 50 50 1 1 B 196 | X LED5_NumLk 38 -50 -2950 200 L 50 50 1 1 I 197 | X DRV14 4 -50 450 200 L 50 50 1 1 B 198 | X SENSE4 5 -50 350 200 L 50 50 1 1 B 199 | X SENSE1 6 -50 250 200 L 50 50 1 1 B 200 | X DRV0 7 -50 150 200 L 50 50 1 1 B 201 | X SENSE2 8 -50 50 200 L 50 50 1 1 B 202 | X SENSE0 9 -50 -50 200 L 50 50 1 1 B 203 | X NC MP -1000 -3150 100 R 50 50 1 1 N 204 | X NC MP -1000 -3050 100 R 50 50 1 1 N 205 | ENDDRAW 206 | ENDDEF 207 | # 208 | # TP4056 209 | # 210 | DEF TP4056 U 0 40 Y Y 1 F N 211 | F0 "U" -350 350 50 H V C CNN 212 | F1 "TP4056" 250 350 50 H V C CNN 213 | F2 "Package_SO:SOP-8_3.9x4.9mm_P1.27mm" 0 0 50 H I C CNN 214 | F3 "" 0 0 50 H I C CNN 215 | DRAW 216 | S -400 300 400 -350 0 1 0 f 217 | X TEMP 1 500 0 100 L 50 50 1 1 I 218 | X PROG 2 500 -200 100 L 50 50 1 1 I 219 | X GND 3 0 -450 100 U 50 50 1 1 W 220 | X VCC 4 -500 200 100 R 50 50 1 1 W 221 | X BAT 5 500 200 100 L 50 50 1 1 w 222 | X /STDBY 6 -500 -200 100 R 50 50 1 1 O 223 | X /CHRG 7 -500 -100 100 R 50 50 1 1 O 224 | X CE 8 -500 100 100 R 50 50 1 1 I 225 | ENDDRAW 226 | ENDDEF 227 | # 228 | # Trackpoint-10p 229 | # 230 | DEF Trackpoint-10p U 0 40 Y Y 1 F N 231 | F0 "U" -250 650 50 H V C CNN 232 | F1 "Trackpoint-10p" 0 550 50 H V C CNN 233 | F2 "Connector_FFC-FPC:TE_1-84952-0_1x10-1MP_P1.0mm_Horizontal" -200 550 50 H I C CNN 234 | F3 "" -200 550 50 H I C CNN 235 | DRAW 236 | S -300 500 350 -600 0 1 0 f 237 | X TP_DATA 1 -500 400 200 R 50 50 1 1 B 238 | X NC 10 -500 -500 200 R 50 50 1 1 N 239 | X TP_RESET 2 -500 300 200 R 50 50 1 1 B 240 | X TP_MIDDLE/NC 3 -500 200 200 R 50 50 1 1 P 241 | X TP_RIGHT/NC 4 -500 100 200 R 50 50 1 1 P 242 | X TP_LEFT/NC 5 -500 0 200 R 50 50 1 1 P 243 | X TP_CLK 6 -500 -100 200 R 50 50 1 1 B 244 | X GND 7 -500 -200 200 R 50 50 1 1 W 245 | X VCC 8 -500 -300 200 R 50 50 1 1 W 246 | X NC 9 -500 -400 200 R 50 50 1 1 N 247 | X NC MP 450 -500 100 L 50 50 1 1 N 248 | X NC MP 450 -400 100 L 50 50 1 1 N 249 | ENDDRAW 250 | ENDDEF 251 | # 252 | # Trackpoint-12p 253 | # 254 | DEF Trackpoint-12p U 0 40 Y Y 1 F N 255 | F0 "U" -250 850 50 H V C CNN 256 | F1 "Trackpoint-12p" 0 750 50 H V C CNN 257 | F2 "Connector_FFC-FPC:TE_1-84952-2_1x12-1MP_P1.0mm_Horizontal" 50 750 50 H I C CNN 258 | F3 "" 50 750 50 H I C CNN 259 | DRAW 260 | S -300 700 400 -600 0 1 0 f 261 | X VCC 1 -500 600 200 R 50 50 1 1 W 262 | X LED_PWM 10 -500 -300 200 R 50 50 1 1 I 263 | X LED_DETECT 11 -500 -400 200 R 50 50 1 1 O 264 | X LED_GND 12 -500 -500 200 R 50 50 1 1 W 265 | X IPD_DATA 2 -500 500 200 R 50 50 1 1 B 266 | X IPD_RST 3 -500 400 200 R 50 50 1 1 I 267 | X TP_MIDDLE/NC 4 -500 300 200 R 50 50 1 1 P 268 | X TP_RIGHT/NC 5 -500 200 200 R 50 50 1 1 P 269 | X TP_LEFT/NC 6 -500 100 200 R 50 50 1 1 P 270 | X IPD_GND 7 -500 0 200 R 50 50 1 1 W 271 | X IPD_CLK 8 -500 -100 200 R 50 50 1 1 B 272 | X LED_VCC 9 -500 -200 200 R 50 50 1 1 W 273 | X NC MP 500 -500 100 L 50 50 1 1 N 274 | X NC MP 500 -400 100 L 50 50 1 1 N 275 | ENDDRAW 276 | ENDDEF 277 | # 278 | # tp-x1c-keyboard-usb 279 | # 280 | DEF tp-x1c-keyboard-usb U 0 40 Y Y 1 F N 281 | F0 "U" 50 -650 50 H V C CNN 282 | F1 "tp-x1c-keyboard-usb" -50 150 50 H V C CNN 283 | F2 "" 0 0 50 H I C CNN 284 | F3 "" 0 0 50 H I C CNN 285 | DRAW 286 | S 0 100 350 -600 0 1 0 f 287 | X USB- 1 -100 0 100 R 50 50 1 1 B 288 | X VCC 2 -100 -100 100 R 50 50 1 1 W 289 | X NC 3 -100 -200 100 R 50 50 1 1 N 290 | X GND 4 -100 -300 100 R 50 50 1 1 W 291 | X USB+ 5 -100 -400 100 R 50 50 1 1 B 292 | X NC 6 -100 -500 100 R 50 50 1 1 N 293 | ENDDRAW 294 | ENDDEF 295 | # 296 | #End Library 297 | -------------------------------------------------------------------------------- /hardware/kicad_proj/mylib.pretty/ESP32-S3-WROOM-1.kicad_mod: -------------------------------------------------------------------------------- 1 | (module ESP32-S3-WROOM-1 (layer F.Cu) (tedit 61A4E6D3) 2 | (descr "Single 2.4 GHz Wi-Fi and Bluetooth combo chip https://www.espressif.com/sites/default/files/documentation/esp32-s3-wroom-1_wroom-1u_datasheet_cn.pdf") 3 | (tags "Single 2.4 GHz Wi-Fi and Bluetooth combo chip") 4 | (attr smd) 5 | (fp_text reference REF** (at -10.61 8.43 90) (layer F.SilkS) 6 | (effects (font (size 1 1) (thickness 0.15))) 7 | ) 8 | (fp_text value ESP32-S3-WROOM-1 (at 0 11.5) (layer F.Fab) 9 | (effects (font (size 1 1) (thickness 0.15))) 10 | ) 11 | (fp_line (start -14 -9.97) (end -14 -20.75) (layer Dwgs.User) (width 0.1)) 12 | (fp_line (start 9 9.76) (end 9 -15.745) (layer F.Fab) (width 0.1)) 13 | (fp_line (start -9 9.76) (end 9 9.76) (layer F.Fab) (width 0.1)) 14 | (fp_line (start -9 -15.745) (end -9 -10.02) (layer F.Fab) (width 0.1)) 15 | (fp_line (start -9 -15.745) (end 9 -15.745) (layer F.Fab) (width 0.1)) 16 | (fp_line (start -9.75 10.5) (end -9.75 -9.72) (layer F.CrtYd) (width 0.05)) 17 | (fp_line (start -9.75 10.5) (end 9.75 10.5) (layer F.CrtYd) (width 0.05)) 18 | (fp_line (start 9.75 -9.72) (end 9.75 10.5) (layer F.CrtYd) (width 0.05)) 19 | (fp_line (start -14.25 -21) (end 14.25 -21) (layer F.CrtYd) (width 0.05)) 20 | (fp_line (start -9 -9.02) (end -9 9.76) (layer F.Fab) (width 0.1)) 21 | (fp_line (start -8.5 -9.52) (end -9 -10.02) (layer F.Fab) (width 0.1)) 22 | (fp_line (start -9 -9.02) (end -8.5 -9.52) (layer F.Fab) (width 0.1)) 23 | (fp_line (start 14 -9.97) (end -14 -9.97) (layer Dwgs.User) (width 0.1)) 24 | (fp_line (start 14 -9.97) (end 14 -20.75) (layer Dwgs.User) (width 0.1)) 25 | (fp_line (start 14 -20.75) (end -14 -20.75) (layer Dwgs.User) (width 0.1)) 26 | (fp_line (start -14.25 -21) (end -14.25 -9.72) (layer F.CrtYd) (width 0.05)) 27 | (fp_line (start 14.25 -21) (end 14.25 -9.72) (layer F.CrtYd) (width 0.05)) 28 | (fp_line (start -14.25 -9.72) (end -9.75 -9.72) (layer F.CrtYd) (width 0.05)) 29 | (fp_line (start 9.75 -9.72) (end 14.25 -9.72) (layer F.CrtYd) (width 0.05)) 30 | (fp_line (start -12.525 -20.75) (end -14 -19.66) (layer Dwgs.User) (width 0.1)) 31 | (fp_line (start -10.525 -20.75) (end -14 -18.045) (layer Dwgs.User) (width 0.1)) 32 | (fp_line (start -8.525 -20.75) (end -14 -16.43) (layer Dwgs.User) (width 0.1)) 33 | (fp_line (start -6.525 -20.75) (end -14 -14.815) (layer Dwgs.User) (width 0.1)) 34 | (fp_line (start -4.525 -20.75) (end -14 -13.2) (layer Dwgs.User) (width 0.1)) 35 | (fp_line (start -2.525 -20.75) (end -14 -11.585) (layer Dwgs.User) (width 0.1)) 36 | (fp_line (start -0.525 -20.75) (end -14 -9.97) (layer Dwgs.User) (width 0.1)) 37 | (fp_line (start 1.475 -20.75) (end -12 -9.97) (layer Dwgs.User) (width 0.1)) 38 | (fp_line (start 3.475 -20.75) (end -10 -9.97) (layer Dwgs.User) (width 0.1)) 39 | (fp_line (start -8 -9.97) (end 5.475 -20.75) (layer Dwgs.User) (width 0.1)) 40 | (fp_line (start 7.475 -20.75) (end -6 -9.97) (layer Dwgs.User) (width 0.1)) 41 | (fp_line (start 9.475 -20.75) (end -4 -9.97) (layer Dwgs.User) (width 0.1)) 42 | (fp_line (start 11.475 -20.75) (end -2 -9.97) (layer Dwgs.User) (width 0.1)) 43 | (fp_line (start 13.475 -20.75) (end 0 -9.97) (layer Dwgs.User) (width 0.1)) 44 | (fp_line (start 14 -19.66) (end 2 -9.97) (layer Dwgs.User) (width 0.1)) 45 | (fp_line (start 14 -18.045) (end 4 -9.97) (layer Dwgs.User) (width 0.1)) 46 | (fp_line (start 14 -16.43) (end 6 -9.97) (layer Dwgs.User) (width 0.1)) 47 | (fp_line (start 14 -14.815) (end 8 -9.97) (layer Dwgs.User) (width 0.1)) 48 | (fp_line (start 14 -13.2) (end 10 -9.97) (layer Dwgs.User) (width 0.1)) 49 | (fp_line (start 14 -11.585) (end 12 -9.97) (layer Dwgs.User) (width 0.1)) 50 | (fp_line (start 9.2 -13.875) (end 13.8 -13.875) (layer Cmts.User) (width 0.1)) 51 | (fp_line (start 13.8 -13.875) (end 13.6 -14.075) (layer Cmts.User) (width 0.1)) 52 | (fp_line (start 13.8 -13.875) (end 13.6 -13.675) (layer Cmts.User) (width 0.1)) 53 | (fp_line (start 9.2 -13.875) (end 9.4 -14.075) (layer Cmts.User) (width 0.1)) 54 | (fp_line (start 9.2 -13.875) (end 9.4 -13.675) (layer Cmts.User) (width 0.1)) 55 | (fp_line (start -13.8 -13.875) (end -13.6 -14.075) (layer Cmts.User) (width 0.1)) 56 | (fp_line (start -13.8 -13.875) (end -13.6 -13.675) (layer Cmts.User) (width 0.1)) 57 | (fp_line (start -9.2 -13.875) (end -9.4 -13.675) (layer Cmts.User) (width 0.1)) 58 | (fp_line (start -13.8 -13.875) (end -9.2 -13.875) (layer Cmts.User) (width 0.1)) 59 | (fp_line (start -9.2 -13.875) (end -9.4 -14.075) (layer Cmts.User) (width 0.1)) 60 | (fp_line (start 8.4 -16) (end 8.2 -16.2) (layer Cmts.User) (width 0.1)) 61 | (fp_line (start 8.4 -16) (end 8.6 -16.2) (layer Cmts.User) (width 0.1)) 62 | (fp_line (start 8.4 -20.6) (end 8.6 -20.4) (layer Cmts.User) (width 0.1)) 63 | (fp_line (start 8.4 -16) (end 8.4 -20.6) (layer Cmts.User) (width 0.1)) 64 | (fp_line (start 8.4 -20.6) (end 8.2 -20.4) (layer Cmts.User) (width 0.1)) 65 | (fp_line (start -9.12 9.1) (end -9.12 9.88) (layer F.SilkS) (width 0.12)) 66 | (fp_line (start -9.12 9.88) (end -8.12 9.88) (layer F.SilkS) (width 0.12)) 67 | (fp_line (start 9.12 9.1) (end 9.12 9.88) (layer F.SilkS) (width 0.12)) 68 | (fp_line (start 9.12 9.88) (end 8.12 9.88) (layer F.SilkS) (width 0.12)) 69 | (fp_line (start -9.12 -15.865) (end 9.12 -15.865) (layer F.SilkS) (width 0.12)) 70 | (fp_line (start 9.12 -15.865) (end 9.12 -9.445) (layer F.SilkS) (width 0.12)) 71 | (fp_line (start -9.12 -15.865) (end -9.12 -9.445) (layer F.SilkS) (width 0.12)) 72 | (fp_line (start -9.12 -9.445) (end -9.5 -9.445) (layer F.SilkS) (width 0.12)) 73 | (fp_text user "5 mm" (at 7.8 -19.075 90) (layer Cmts.User) 74 | (effects (font (size 0.5 0.5) (thickness 0.1))) 75 | ) 76 | (fp_text user "5 mm" (at -11.2 -14.375) (layer Cmts.User) 77 | (effects (font (size 0.5 0.5) (thickness 0.1))) 78 | ) 79 | (fp_text user "5 mm" (at 11.8 -14.375) (layer Cmts.User) 80 | (effects (font (size 0.5 0.5) (thickness 0.1))) 81 | ) 82 | (fp_text user Antenna (at 0 -13) (layer Cmts.User) 83 | (effects (font (size 1 1) (thickness 0.15))) 84 | ) 85 | (fp_text user "KEEP-OUT ZONE" (at 0 -19) (layer Cmts.User) 86 | (effects (font (size 1 1) (thickness 0.15))) 87 | ) 88 | (fp_text user %R (at 0 0) (layer F.Fab) 89 | (effects (font (size 1 1) (thickness 0.15))) 90 | ) 91 | (pad 38 smd rect (at 8.8 -5.715) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 92 | (pad 37 smd rect (at 8.8 -4.445) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 93 | (pad 36 smd rect (at 8.8 -3.175) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 94 | (pad 35 smd rect (at 8.8 -1.905) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 95 | (pad 34 smd rect (at 8.8 -0.635) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 96 | (pad 33 smd rect (at 8.8 0.635) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 97 | (pad 32 smd rect (at 8.8 1.905) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 98 | (pad 31 smd rect (at 8.8 3.175) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 99 | (pad 30 smd rect (at 8.8 4.445) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 100 | (pad 29 smd rect (at 8.8 5.715) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 101 | (pad 28 smd rect (at 8.8 6.985) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 102 | (pad 27 smd rect (at 8.8 8.255) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 103 | (pad 26 smd rect (at 6.985 9.555 270) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 104 | (pad 25 smd rect (at 5.715 9.555 270) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 105 | (pad 24 smd rect (at 4.445 9.555 90) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 106 | (pad 23 smd rect (at 3.175 9.555 90) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 107 | (pad 22 smd rect (at 1.905 9.555 90) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 108 | (pad 21 smd rect (at 0.635 9.555 90) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 109 | (pad 20 smd rect (at -0.635 9.555 90) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 110 | (pad 19 smd rect (at -1.905 9.555 90) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 111 | (pad 18 smd rect (at -3.175 9.555 90) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 112 | (pad 17 smd rect (at -4.445 9.555 90) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 113 | (pad 16 smd rect (at -5.715 9.555 90) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 114 | (pad 15 smd rect (at -6.985 9.555 90) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 115 | (pad 14 smd rect (at -8.8 8.255) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 116 | (pad 13 smd rect (at -8.8 6.985) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 117 | (pad 12 smd rect (at -8.8 5.715) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 118 | (pad 11 smd rect (at -8.8 4.445) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 119 | (pad 10 smd rect (at -8.8 3.175) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 120 | (pad 9 smd rect (at -8.8 1.905) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 121 | (pad 8 smd rect (at -8.8 0.635) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 122 | (pad 7 smd rect (at -8.8 -0.635) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 123 | (pad 6 smd rect (at -8.8 -1.905) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 124 | (pad 5 smd rect (at -8.8 -3.175) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 125 | (pad 4 smd rect (at -8.8 -4.445) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 126 | (pad 3 smd rect (at -8.8 -5.715) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 127 | (pad 2 smd rect (at -8.8 -6.985) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 128 | (pad 1 smd rect (at -8.8 -8.255) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 129 | (pad 41 smd rect (at -1.5 -0.55) (size 5 5) (layers F.Cu F.Paste F.Mask)) 130 | (pad 39 smd rect (at 8.8 -6.985) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 131 | (pad 40 smd rect (at 8.8 -8.255) (size 1.5 0.9) (layers F.Cu F.Paste F.Mask)) 132 | (model ${KISYS3DMOD}/RF_Module.3dshapes/ESP32-WROOM-32.wrl 133 | (at (xyz 0 0 0)) 134 | (scale (xyz 1 1 1)) 135 | (rotate (xyz 0 0 0)) 136 | ) 137 | ) 138 | -------------------------------------------------------------------------------- /hardware/kicad_proj/mylib.pretty/Keyboard-32-36-40.kicad_mod: -------------------------------------------------------------------------------- 1 | (module Keyboard-32-36-40 (layer F.Cu) (tedit 61A0D7ED) 2 | (fp_text reference REF** (at -3.7 -0.6) (layer F.SilkS) 3 | (effects (font (size 1 1) (thickness 0.15))) 4 | ) 5 | (fp_text value Keyboard-32-36-40 (at 7.6 2.8) (layer F.Fab) 6 | (effects (font (size 1 1) (thickness 0.15))) 7 | ) 8 | (fp_line (start -2.6 0.4) (end -1.4 0.4) (layer F.SilkS) (width 0.12)) 9 | (fp_line (start -2.65 4) (end -2.65 0.4) (layer F.SilkS) (width 0.12)) 10 | (fp_line (start -1 -0.8) (end -1 0.5) (layer F.SilkS) (width 0.3)) 11 | (fp_line (start -0.5 -0.8) (end -0.5 0.5) (layer F.SilkS) (width 0.3)) 12 | (fp_line (start 20.2 0.4) (end 22.15 0.4) (layer F.SilkS) (width 0.12)) 13 | (fp_line (start 22.15 0.4) (end 22.15 4) (layer F.SilkS) (width 0.12)) 14 | (fp_line (start -1 6.4) (end 20.4 6.4) (layer F.SilkS) (width 0.12)) 15 | (fp_line (start -3.5 4) (end -3.5 0.8) (layer F.SilkS) (width 0.24)) 16 | (fp_line (start 21 4) (end 21 1.6) (layer F.SilkS) (width 0.12)) 17 | (fp_line (start 19 4) (end 19 1.6) (layer F.SilkS) (width 0.12)) 18 | (fp_line (start 19 4) (end 18.2 4.8) (layer F.SilkS) (width 0.12)) 19 | (fp_line (start 21 4) (end 20.2 4.8) (layer F.SilkS) (width 0.12)) 20 | (fp_line (start 18.6 1) (end 20.4 1) (layer F.SilkS) (width 0.12)) 21 | (fp_line (start 20.4 1) (end 21 1.6) (layer F.SilkS) (width 0.12)) 22 | (fp_line (start 18.6 1) (end 18.5 0.9) (layer F.SilkS) (width 0.12)) 23 | (fp_line (start 17.5 0.9) (end 17.9 1.3) (layer F.SilkS) (width 0.12)) 24 | (fp_line (start 17.9 1.3) (end 18.7 1.3) (layer F.SilkS) (width 0.12)) 25 | (fp_line (start 18.7 1.3) (end 19 1.6) (layer F.SilkS) (width 0.12)) 26 | (pad MP smd rect (at 19.2 2.6) (size 4 1.5) (layers F.Cu F.Paste F.Mask)) 27 | (pad MP smd rect (at -2.7 2.6) (size 2 1.5) (layers F.Cu F.Paste F.Mask)) 28 | (pad MP smd rect (at 21.65 5.65) (size 1.8 2.2) (layers F.Cu F.Paste F.Mask)) 29 | (pad MP smd rect (at -2.25 5.65) (size 1.8 2.2) (layers F.Cu F.Paste F.Mask)) 30 | (pad 40 smd rect (at 19.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 31 | (pad 39 smd rect (at 19 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 32 | (pad 38 smd rect (at 18.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 33 | (pad 37 smd rect (at 18 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 34 | (pad 36 smd rect (at 17.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 35 | (pad 35 smd rect (at 17 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 36 | (pad 34 smd rect (at 16.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 37 | (pad 33 smd rect (at 16 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 38 | (pad 32 smd rect (at 15.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 39 | (pad 31 smd rect (at 15 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 40 | (pad 30 smd rect (at 14.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 41 | (pad 29 smd rect (at 14 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 42 | (pad 28 smd rect (at 13.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 43 | (pad 27 smd rect (at 13 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 44 | (pad 26 smd rect (at 12.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 45 | (pad 25 smd rect (at 12 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 46 | (pad 24 smd rect (at 11.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 47 | (pad 23 smd rect (at 11 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 48 | (pad 22 smd rect (at 10.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 49 | (pad 21 smd rect (at 10 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 50 | (pad 20 smd rect (at 9.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 51 | (pad 19 smd rect (at 9 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 52 | (pad 18 smd rect (at 8.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 53 | (pad 17 smd rect (at 8 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 54 | (pad 16 smd rect (at 7.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 55 | (pad 15 smd rect (at 7 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 56 | (pad 14 smd rect (at 6.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 57 | (pad 13 smd rect (at 6 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 58 | (pad 12 smd rect (at 5.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 59 | (pad 11 smd rect (at 5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 60 | (pad 10 smd rect (at 4.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 61 | (pad 9 smd rect (at 4 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 62 | (pad 8 smd rect (at 3.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 63 | (pad 7 smd rect (at 3 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 64 | (pad 6 smd rect (at 2.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 65 | (pad 5 smd rect (at 2 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 66 | (pad 4 smd rect (at 1.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 67 | (pad 3 smd rect (at 1 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 68 | (pad 2 smd rect (at 0.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 69 | (pad 1 smd rect (at 0 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 70 | ) 71 | -------------------------------------------------------------------------------- /hardware/kicad_proj/mylib.pretty/Keyboard-36.kicad_mod: -------------------------------------------------------------------------------- 1 | (module Keyboard-36 (layer F.Cu) (tedit 61A9C611) 2 | (fp_text reference REF** (at -3.7 -0.6) (layer F.SilkS) 3 | (effects (font (size 1 1) (thickness 0.15))) 4 | ) 5 | (fp_text value Keyboard-36 (at 7.6 2.8) (layer F.Fab) 6 | (effects (font (size 1 1) (thickness 0.15))) 7 | ) 8 | (fp_line (start 18.5 -0.8) (end 18.5 0.5) (layer F.SilkS) (width 0.3)) 9 | (fp_line (start 18 -0.8) (end 18 0.5) (layer F.SilkS) (width 0.3)) 10 | (fp_line (start -3.5 0.4) (end -1.4 0.4) (layer F.SilkS) (width 0.12)) 11 | (fp_line (start -1 -0.8) (end -1 0.5) (layer F.SilkS) (width 0.3)) 12 | (fp_line (start -0.5 -0.8) (end -0.5 0.5) (layer F.SilkS) (width 0.3)) 13 | (fp_line (start 19.05 0.4) (end 21 0.4) (layer F.SilkS) (width 0.12)) 14 | (fp_line (start -3.5 5.4) (end 21 5.4) (layer F.SilkS) (width 0.12)) 15 | (fp_line (start -3.5 5.4) (end -3.5 0.4) (layer F.SilkS) (width 0.12)) 16 | (fp_line (start 21 5.4) (end 21 0.4) (layer F.SilkS) (width 0.12)) 17 | (pad 1 smd rect (at 0 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 18 | (pad 2 smd rect (at 0.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 19 | (pad 3 smd rect (at 1 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 20 | (pad 4 smd rect (at 1.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 21 | (pad 5 smd rect (at 2 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 22 | (pad 6 smd rect (at 2.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 23 | (pad 7 smd rect (at 3 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 24 | (pad 8 smd rect (at 3.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 25 | (pad 9 smd rect (at 4 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 26 | (pad 10 smd rect (at 4.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 27 | (pad 11 smd rect (at 5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 28 | (pad 12 smd rect (at 5.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 29 | (pad 13 smd rect (at 6 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 30 | (pad 14 smd rect (at 6.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 31 | (pad 15 smd rect (at 7 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 32 | (pad 16 smd rect (at 7.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 33 | (pad 17 smd rect (at 8 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 34 | (pad 18 smd rect (at 8.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 35 | (pad 19 smd rect (at 9 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 36 | (pad 20 smd rect (at 9.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 37 | (pad 21 smd rect (at 10 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 38 | (pad 22 smd rect (at 10.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 39 | (pad 23 smd rect (at 11 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 40 | (pad 24 smd rect (at 11.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 41 | (pad 25 smd rect (at 12 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 42 | (pad 26 smd rect (at 12.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 43 | (pad 27 smd rect (at 13 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 44 | (pad 28 smd rect (at 13.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 45 | (pad 29 smd rect (at 14 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 46 | (pad 30 smd rect (at 14.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 47 | (pad 31 smd rect (at 15 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 48 | (pad 32 smd rect (at 15.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 49 | (pad 33 smd rect (at 16 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 50 | (pad 34 smd rect (at 16.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 51 | (pad 35 smd rect (at 17 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 52 | (pad 36 smd rect (at 17.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 53 | (pad MP0 smd rect (at -3 2.6) (size 2.6 1.5) (layers F.Cu F.Paste F.Mask)) 54 | (pad MP1 smd rect (at 20.5 2.6) (size 2.6 1.5) (layers F.Cu F.Paste F.Mask)) 55 | ) 56 | -------------------------------------------------------------------------------- /hardware/kicad_proj/mylib.pretty/Keyboard-40.kicad_mod: -------------------------------------------------------------------------------- 1 | (module Keyboard-40 (layer F.Cu) (tedit 61A48F8A) 2 | (fp_text reference REF** (at -3.7 -0.6) (layer F.SilkS) 3 | (effects (font (size 1 1) (thickness 0.15))) 4 | ) 5 | (fp_text value Keyboard-40 (at 7.6 2.8) (layer F.Fab) 6 | (effects (font (size 1 1) (thickness 0.15))) 7 | ) 8 | (fp_line (start -0.7 -0.7) (end -1.8 0.4) (layer F.SilkS) (width 0.12)) 9 | (fp_line (start -0.7 0.4) (end -0.7 -0.7) (layer F.SilkS) (width 0.12)) 10 | (fp_line (start -2.6 0.4) (end -0.7 0.4) (layer F.SilkS) (width 0.12)) 11 | (fp_line (start -2.65 4) (end -2.65 0.4) (layer F.SilkS) (width 0.12)) 12 | (fp_line (start 20.2 0.4) (end 22.15 0.4) (layer F.SilkS) (width 0.12)) 13 | (fp_line (start 22.15 0.4) (end 22.15 4) (layer F.SilkS) (width 0.12)) 14 | (fp_line (start -1 6.4) (end 20.4 6.4) (layer F.SilkS) (width 0.12)) 15 | (pad 1 smd rect (at 0 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 16 | (pad 2 smd rect (at 0.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 17 | (pad 3 smd rect (at 1 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 18 | (pad 4 smd rect (at 1.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 19 | (pad 5 smd rect (at 2 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 20 | (pad 6 smd rect (at 2.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 21 | (pad 7 smd rect (at 3 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 22 | (pad 8 smd rect (at 3.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 23 | (pad 9 smd rect (at 4 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 24 | (pad 10 smd rect (at 4.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 25 | (pad 11 smd rect (at 5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 26 | (pad 12 smd rect (at 5.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 27 | (pad 13 smd rect (at 6 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 28 | (pad 14 smd rect (at 6.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 29 | (pad 15 smd rect (at 7 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 30 | (pad 16 smd rect (at 7.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 31 | (pad 17 smd rect (at 8 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 32 | (pad 18 smd rect (at 8.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 33 | (pad 19 smd rect (at 9 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 34 | (pad 20 smd rect (at 9.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 35 | (pad 21 smd rect (at 10 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 36 | (pad 22 smd rect (at 10.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 37 | (pad 23 smd rect (at 11 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 38 | (pad 24 smd rect (at 11.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 39 | (pad 25 smd rect (at 12 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 40 | (pad 26 smd rect (at 12.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 41 | (pad 27 smd rect (at 13 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 42 | (pad 28 smd rect (at 13.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 43 | (pad 29 smd rect (at 14 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 44 | (pad 30 smd rect (at 14.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 45 | (pad 31 smd rect (at 15 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 46 | (pad 32 smd rect (at 15.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 47 | (pad 33 smd rect (at 16 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 48 | (pad 34 smd rect (at 16.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 49 | (pad 35 smd rect (at 17 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 50 | (pad 36 smd rect (at 17.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 51 | (pad 37 smd rect (at 18 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 52 | (pad 38 smd rect (at 18.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 53 | (pad 39 smd rect (at 19 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 54 | (pad 40 smd rect (at 19.5 -0.1) (size 0.3 1.5) (layers F.Cu F.Paste F.Mask)) 55 | (pad MP0 smd rect (at -2.25 5.65) (size 1.8 2.2) (layers F.Cu F.Paste F.Mask)) 56 | (pad MP1 smd rect (at 21.65 5.65) (size 1.8 2.2) (layers F.Cu F.Paste F.Mask)) 57 | ) 58 | -------------------------------------------------------------------------------- /hardware/kicad_proj/mylib.pretty/MSK22D14G2-SWITCH.kicad_mod: -------------------------------------------------------------------------------- 1 | (module MSK22D14G2-SWITCH (layer F.Cu) (tedit 61A0E001) 2 | (fp_text reference REF** (at 0.3 -4.2) (layer F.SilkS) 3 | (effects (font (size 1 1) (thickness 0.15))) 4 | ) 5 | (fp_text value MSK22D14G2-SWITCH (at 0.2 -2.9) (layer F.Fab) 6 | (effects (font (size 1 1) (thickness 0.15))) 7 | ) 8 | (fp_line (start -4.55 -1.75) (end -4.55 1.75) (layer F.SilkS) (width 0.12)) 9 | (fp_line (start -4.55 -1.75) (end 4.55 -1.75) (layer F.SilkS) (width 0.12)) 10 | (fp_line (start 4.55 -1.75) (end 4.55 1.75) (layer F.SilkS) (width 0.12)) 11 | (pad 1 smd rect (at -2.5 3.2) (size 1.2 2.7) (layers F.Cu F.Paste F.Mask)) 12 | (pad 2 smd rect (at 0 3.2) (size 1.2 2.7) (layers F.Cu F.Paste F.Mask)) 13 | (pad 3 smd rect (at 2.5 3.2) (size 1.2 2.7) (layers F.Cu F.Paste F.Mask)) 14 | (pad "" np_thru_hole circle (at -3.4 0) (size 0.9 0.9) (drill 0.9) (layers *.Cu *.Mask)) 15 | (pad "" np_thru_hole circle (at 3.4 0) (size 0.9 0.9) (drill 0.9) (layers *.Cu *.Mask)) 16 | ) 17 | -------------------------------------------------------------------------------- /hardware/kicad_proj/mylib.pretty/Trackpad-12p.kicad_mod: -------------------------------------------------------------------------------- 1 | (module Trackpad-12p (layer F.Cu) (tedit 61A9C64E) 2 | (fp_text reference REF** (at -0.6 -1.9) (layer F.SilkS) 3 | (effects (font (size 1 1) (thickness 0.15))) 4 | ) 5 | (fp_text value Trackpad-12p (at 5.5 3.3) (layer F.Fab) 6 | (effects (font (size 1 1) (thickness 0.15))) 7 | ) 8 | (fp_line (start -0.5 -0.6) (end -1.6 0.5) (layer F.SilkS) (width 0.12)) 9 | (fp_line (start -0.5 0.5) (end -0.5 -0.6) (layer F.SilkS) (width 0.12)) 10 | (fp_line (start -1.4 4.8) (end 12.4 4.8) (layer F.SilkS) (width 0.12)) 11 | (fp_line (start 13.25 3.1) (end 13.25 0.5) (layer F.SilkS) (width 0.12)) 12 | (fp_line (start 11.5 0.5) (end 13.25 0.5) (layer F.SilkS) (width 0.12)) 13 | (fp_line (start -2.25 0.5) (end -0.5 0.5) (layer F.SilkS) (width 0.12)) 14 | (fp_line (start -2.25 3.1) (end -2.25 0.5) (layer F.SilkS) (width 0.12)) 15 | (pad 1 smd rect (at 0 0) (size 0.5 1.5) (layers F.Cu F.Paste F.Mask)) 16 | (pad 2 smd rect (at 1 0) (size 0.5 1.5) (layers F.Cu F.Paste F.Mask)) 17 | (pad 3 smd rect (at 2 0) (size 0.5 1.5) (layers F.Cu F.Paste F.Mask)) 18 | (pad 4 smd rect (at 3 0) (size 0.5 1.5) (layers F.Cu F.Paste F.Mask)) 19 | (pad 5 smd rect (at 4 0) (size 0.5 1.5) (layers F.Cu F.Paste F.Mask)) 20 | (pad 6 smd rect (at 5 0) (size 0.5 1.5) (layers F.Cu F.Paste F.Mask)) 21 | (pad 7 smd rect (at 6 0) (size 0.5 1.5) (layers F.Cu F.Paste F.Mask)) 22 | (pad 8 smd rect (at 7 0) (size 0.5 1.5) (layers F.Cu F.Paste F.Mask)) 23 | (pad 9 smd rect (at 8 0) (size 0.5 1.5) (layers F.Cu F.Paste F.Mask)) 24 | (pad 10 smd rect (at 9 0) (size 0.5 1.5) (layers F.Cu F.Paste F.Mask)) 25 | (pad 11 smd rect (at 10 0) (size 0.5 1.5) (layers F.Cu F.Paste F.Mask)) 26 | (pad 12 smd rect (at 11 0) (size 0.5 1.5) (layers F.Cu F.Paste F.Mask)) 27 | (pad MP0 smd rect (at -2.5 4.15) (size 1.5 1.5) (layers F.Cu F.Paste F.Mask)) 28 | (pad MP1 smd rect (at 13.5 4.15) (size 1.5 1.5) (layers F.Cu F.Paste F.Mask)) 29 | (pad "" np_thru_hole circle (at -1.05 3.85) (size 0.8 0.8) (drill 0.8) (layers *.Cu *.Mask)) 30 | (pad "" np_thru_hole circle (at 12.05 3.85) (size 0.8 0.8) (drill 0.8) (layers *.Cu *.Mask)) 31 | ) 32 | -------------------------------------------------------------------------------- /hardware/kicad_proj/mylib.pretty/android-logo.kicad_mod: -------------------------------------------------------------------------------- 1 | (module LOGO (layer F.Cu) 2 | (at 0 0) 3 | (fp_text reference "G***" (at 0 0) (layer F.SilkS) hide 4 | (effects (font (thickness 0.3))) 5 | ) 6 | (fp_text value "LOGO" (at 0.75 0) (layer F.SilkS) hide 7 | (effects (font (thickness 0.3))) 8 | ) 9 | (fp_poly (pts (xy -1.389737 -1.259539) (xy -1.362233 -1.234939) (xy -1.327069 -1.189185) (xy -1.280768 -1.117821) (xy -1.219853 -1.016394) (xy -1.152032 -0.899834) (xy -0.964920 -0.575859) (xy -0.791479 -0.637235) 10 | (xy -0.560052 -0.708028) (xy -0.337481 -0.751012) (xy -0.103445 -0.769674) (xy -0.010957 -0.771110) (xy 0.190208 -0.766423) (xy 0.364550 -0.750231) (xy 0.528144 -0.720028) (xy 0.697062 -0.673307) 11 | (xy 0.769898 -0.649372) (xy 0.980951 -0.577469) (xy 1.178444 -0.918803) (xy 1.251906 -1.044249) (xy 1.308032 -1.135890) (xy 1.350277 -1.198507) (xy 1.382099 -1.236882) (xy 1.406953 -1.255794) 12 | (xy 1.425226 -1.260138) (xy 1.466200 -1.256118) (xy 1.490453 -1.241196) (xy 1.496858 -1.211073) (xy 1.484289 -1.161451) (xy 1.451617 -1.088034) (xy 1.397717 -0.986523) (xy 1.321461 -0.852622) 13 | (xy 1.315789 -0.842842) (xy 1.250992 -0.728608) (xy 1.198156 -0.630311) (xy 1.160031 -0.553470) (xy 1.139366 -0.503600) (xy 1.138029 -0.486317) (xy 1.194925 -0.457873) (xy 1.274468 -0.405433) 14 | (xy 1.367976 -0.335658) (xy 1.466769 -0.255205) (xy 1.562165 -0.170733) (xy 1.613327 -0.121721) (xy 1.822140 0.115114) (xy 1.994239 0.373974) (xy 2.127709 0.651811) (xy 2.167237 0.759758) 15 | (xy 2.190480 0.838134) (xy 2.213740 0.932151) (xy 2.235065 1.031542) (xy 2.252506 1.126040) (xy 2.264113 1.205378) (xy 2.267935 1.259289) (xy 2.265279 1.275901) (xy 2.242368 1.278256) 16 | (xy 2.178535 1.280514) (xy 2.076688 1.282655) (xy 1.939737 1.284656) (xy 1.770588 1.286496) (xy 1.572152 1.288152) (xy 1.347337 1.289602) (xy 1.099051 1.290825) (xy 0.830203 1.291799) 17 | (xy 0.543702 1.292501) (xy 0.242455 1.292910) (xy -0.003350 1.293012) (xy -2.261404 1.293012) (xy -2.246497 1.177956) (xy -2.187326 0.885711) (xy -2.087746 0.599132) (xy -1.999461 0.423197) 18 | (xy -1.223028 0.423197) (xy -1.218894 0.466582) (xy -1.185535 0.547277) (xy -1.127608 0.603155) (xy -1.055488 0.630367) (xy -0.979546 0.625064) (xy -0.910156 0.583397) (xy -0.908495 0.581756) 19 | (xy -0.864790 0.512232) (xy -0.859550 0.469603) (xy 0.868232 0.469603) (xy 0.892636 0.542181) (xy 0.928246 0.583600) (xy 1.006810 0.627486) (xy 1.087356 0.630537) (xy 1.161506 0.592816) 20 | (xy 1.173473 0.581756) (xy 1.216683 0.512829) (xy 1.226243 0.436086) (xy 1.206225 0.362404) (xy 1.160700 0.302663) (xy 1.093741 0.267741) (xy 1.054160 0.262986) (xy 0.973373 0.281137) 21 | (xy 0.912714 0.328606) (xy 0.876296 0.394920) (xy 0.868232 0.469603) (xy -0.859550 0.469603) (xy -0.855328 0.435261) (xy -0.875972 0.361634) (xy -0.922587 0.302138) (xy -0.991034 0.267563) 22 | (xy -1.030715 0.262986) (xy -1.103863 0.281782) (xy -1.165768 0.329610) (xy -1.208625 0.379623) (xy -1.223028 0.423197) (xy -1.999461 0.423197) (xy -1.951084 0.326793) (xy -1.862535 0.187943) 23 | (xy -1.765224 0.062336) (xy -1.643892 -0.071373) (xy -1.510264 -0.201737) (xy -1.376063 -0.317308) (xy -1.254851 -0.405461) (xy -1.188714 -0.450006) (xy -1.140099 -0.486886) (xy -1.118271 -0.508993) 24 | (xy -1.117879 -0.510532) (xy -1.128266 -0.534358) (xy -1.157178 -0.589504) (xy -1.201039 -0.669437) (xy -1.256277 -0.767623) (xy -1.306469 -0.855293) (xy -1.380106 -0.985219) (xy -1.431837 -1.083167) 25 | (xy -1.463254 -1.154160) (xy -1.475948 -1.203220) (xy -1.471511 -1.235371) (xy -1.451533 -1.255636) (xy -1.435679 -1.263086) (xy -1.413060 -1.267437) (xy -1.389737 -1.259539) )(layer F.SilkS) (width 0.010000) 26 | ) 27 | ) 28 | -------------------------------------------------------------------------------- /hardware/kicad_proj/mylib.pretty/windows-logo.kicad_mod: -------------------------------------------------------------------------------- 1 | (module LOGO (layer F.Cu) 2 | (at 0 0) 3 | (fp_text reference "G***" (at 0 0) (layer F.SilkS) hide 4 | (effects (font (thickness 0.3))) 5 | ) 6 | (fp_text value "LOGO" (at 0.75 0) (layer F.SilkS) hide 7 | (effects (font (thickness 0.3))) 8 | ) 9 | (fp_poly (pts (xy 2.016221 1.084814) (xy 2.015856 1.284346) (xy 2.014813 1.469588) (xy 2.013167 1.636110) (xy 2.010997 1.779478) (xy 2.008377 1.895262) (xy 2.005386 1.979029) (xy 2.002099 2.026348) 10 | (xy 1.999785 2.035456) (xy 1.975346 2.031956) (xy 1.911907 2.023000) (xy 1.813873 2.009206) (xy 1.685653 1.991193) (xy 1.531653 1.969581) (xy 1.356280 1.944987) (xy 1.163941 1.918031) 11 | (xy 0.997153 1.894669) (xy 0.790818 1.865753) (xy 0.595019 1.838276) (xy 0.414626 1.812924) (xy 0.254510 1.790382) (xy 0.119542 1.771337) (xy 0.014591 1.756475) (xy -0.055472 1.746482) 12 | (xy -0.082183 1.742597) (xy -0.175323 1.728634) (xy -0.175323 0.131492) (xy 2.016221 0.131492) (xy 2.016221 1.084814) )(layer F.SilkS) (width 0.010000) 13 | ) 14 | (fp_poly (pts (xy -1.199870 0.131492) (xy -0.372562 0.131492) (xy -0.372562 0.920448) (xy -0.373002 1.101355) (xy -0.374251 1.267510) (xy -0.376210 1.414048) (xy -0.378776 1.536098) (xy -0.381848 1.628795) 15 | (xy -0.385323 1.687271) (xy -0.388999 1.706689) (xy -0.413727 1.703146) (xy -0.476969 1.694244) (xy -0.573823 1.680667) (xy -0.699393 1.663101) (xy -0.848777 1.642231) (xy -1.017077 1.618742) 16 | (xy -1.199393 1.593321) (xy -1.211503 1.591633) (xy -2.017571 1.479292) (xy -2.022374 0.805392) (xy -2.027178 0.131491) (xy -1.199870 0.131492) )(layer F.SilkS) (width 0.010000) 17 | ) 18 | (fp_poly (pts (xy -0.372562 -0.087662) (xy -1.199870 -0.087662) (xy -2.027178 -0.087661) (xy -2.022378 -0.772519) (xy -2.017577 -1.457377) (xy -1.288210 -1.557949) (xy -1.110019 -1.582506) (xy -0.941956 -1.605643) 19 | (xy -0.789925 -1.626549) (xy -0.659832 -1.644412) (xy -0.557580 -1.658421) (xy -0.489073 -1.667766) (xy -0.465703 -1.670919) (xy -0.372562 -1.683319) (xy -0.372562 -0.087662) )(layer F.SilkS) (width 0.010000) 20 | ) 21 | (fp_poly (pts (xy 2.016221 -0.087662) (xy -0.175323 -0.087662) (xy -0.175323 -1.707419) (xy -0.104098 -1.719712) (xy -0.067875 -1.725176) (xy 0.006982 -1.735842) (xy 0.115667 -1.751047) (xy 0.253377 -1.770126) 22 | (xy 0.415308 -1.792416) (xy 0.596657 -1.817252) (xy 0.792620 -1.843971) (xy 0.931407 -1.862827) (xy 1.134051 -1.890375) (xy 1.324925 -1.916433) (xy 1.499294 -1.940344) (xy 1.652424 -1.961455) 23 | (xy 1.779579 -1.979113) (xy 1.876025 -1.992661) (xy 1.937027 -2.001448) (xy 1.955954 -2.004387) (xy 2.016221 -2.015126) (xy 2.016221 -0.087662) )(layer F.SilkS) (width 0.010000) 24 | ) 25 | ) 26 | -------------------------------------------------------------------------------- /hardware/kicad_proj/mylib.pretty/x1c-tablet-keyboard-usb.kicad_mod: -------------------------------------------------------------------------------- 1 | (module x1c-tablet-keyboard-usb (layer F.Cu) (tedit 6221C644) 2 | (fp_text reference REF** (at 10.4 0.1) (layer F.SilkS) 3 | (effects (font (size 1 1) (thickness 0.15))) 4 | ) 5 | (fp_text value x1c-tablet-keyboard-usb (at 3.9 -2.9) (layer F.Fab) 6 | (effects (font (size 1 1) (thickness 0.15))) 7 | ) 8 | (fp_line (start -11.3 -1.3) (end -7.5 -1.3) (layer F.SilkS) (width 0.12)) 9 | (fp_line (start -7.5 -1.3) (end -7.5 1.3) (layer F.SilkS) (width 0.12)) 10 | (fp_line (start -7.5 1.3) (end -11.3 1.3) (layer F.SilkS) (width 0.12)) 11 | (fp_line (start -11.3 1.3) (end -11.3 -1.3) (layer F.SilkS) (width 0.12)) 12 | (fp_line (start 23.2 1.3) (end 19.4 1.3) (layer F.SilkS) (width 0.12)) 13 | (fp_line (start 19.4 1.3) (end 19.4 -1.3) (layer F.SilkS) (width 0.12)) 14 | (fp_line (start 19.4 -1.3) (end 23.2 -1.3) (layer F.SilkS) (width 0.12)) 15 | (fp_line (start 23.2 -1.3) (end 23.2 1.3) (layer F.SilkS) (width 0.12)) 16 | (fp_line (start -6.8 4.1691) (end 18.4 4.1691) (layer F.SilkS) (width 0.12)) 17 | (fp_line (start 18.4 -1.8309) (end -6.8 -1.8309) (layer F.SilkS) (width 0.12)) 18 | (fp_line (start -6.8 -1.8309) (end -6.8 4.1691) (layer F.SilkS) (width 0.12)) 19 | (fp_line (start 18.4 -1.8309) (end 18.4 4.1691) (layer F.SilkS) (width 0.12)) 20 | (pad 1 thru_hole circle (at 0 0) (size 1.3 1.3) (drill 0.8) (layers *.Cu *.Mask)) 21 | (pad 2 thru_hole circle (at 2.7 0) (size 1.3 1.3) (drill 0.8) (layers *.Cu *.Mask)) 22 | (pad 3 thru_hole circle (at 5.4 0) (size 1.3 1.3) (drill 0.8) (layers *.Cu *.Mask)) 23 | (pad 5 thru_hole circle (at 1.35 2.3382) (size 1.3 1.3) (drill 0.8) (layers *.Cu *.Mask)) 24 | (pad 6 thru_hole circle (at 4.05 2.3382) (size 1.3 1.3) (drill 0.8) (layers *.Cu *.Mask)) 25 | (pad 4 thru_hole circle (at -1.35 2.3382) (size 1.3 1.3) (drill 0.8) (layers *.Cu *.Mask)) 26 | ) 27 | -------------------------------------------------------------------------------- /hardware/kicad_proj/sym-lib-table: -------------------------------------------------------------------------------- 1 | (sym_lib_table 2 | (lib (name mylib)(type Legacy)(uri ${KIPRJMOD}/mylib.lib)(options "")(descr "")) 3 | ) 4 | -------------------------------------------------------------------------------- /imgs/e580.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hhuysqt/esp32s3-keyboard/f6a5c573fb7a1ffcf0233ad4d05a9c2e8053f316/imgs/e580.jpg -------------------------------------------------------------------------------- /imgs/fpc-kb-tp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hhuysqt/esp32s3-keyboard/f6a5c573fb7a1ffcf0233ad4d05a9c2e8053f316/imgs/fpc-kb-tp.jpg -------------------------------------------------------------------------------- /imgs/ps2-timing.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hhuysqt/esp32s3-keyboard/f6a5c573fb7a1ffcf0233ad4d05a9c2e8053f316/imgs/ps2-timing.jpg -------------------------------------------------------------------------------- /imgs/t470.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hhuysqt/esp32s3-keyboard/f6a5c573fb7a1ffcf0233ad4d05a9c2e8053f316/imgs/t470.jpg -------------------------------------------------------------------------------- /main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register(SRCS "ble_hidd_demo_main.c" 2 | "esp_hidd_prf_api.c" 3 | "hid_dev.c" 4 | "hid_device_le_prf.c" 5 | "keyboard.c" 6 | "keyboard_pm.c" 7 | "keymap.c" 8 | INCLUDE_DIRS ".") 9 | 10 | target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-unused-const-variable) 11 | -------------------------------------------------------------------------------- /main/ble_hidd_demo_main.c: -------------------------------------------------------------------------------- 1 | /* This example code is in the Public Domain (or CC0 licensed, at your option.) 2 | Unless required by applicable law or agreed to in writing, this software is 3 | distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 4 | CONDITIONS OF ANY KIND, either express or implied. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include "freertos/FreeRTOS.h" 11 | #include "freertos/task.h" 12 | #include "freertos/event_groups.h" 13 | #include "esp_system.h" 14 | #include "esp_wifi.h" 15 | #include "esp_event.h" 16 | #include "esp_log.h" 17 | #include "nvs_flash.h" 18 | #include "esp_bt.h" 19 | 20 | #include "esp_hidd_prf_api.h" 21 | #include "esp_bt_defs.h" 22 | #include "esp_gap_ble_api.h" 23 | #include "esp_gatts_api.h" 24 | #include "esp_gatt_defs.h" 25 | #include "esp_bt_main.h" 26 | #include "esp_bt_device.h" 27 | #include "driver/gpio.h" 28 | #include "driver/uart.h" 29 | #include "hid_dev.h" 30 | 31 | #include "esp_err.h" 32 | #include "esp_pm.h" 33 | #include "esp_sleep.h" 34 | 35 | #include "keyboard_pm.h" 36 | 37 | /** 38 | * Brief: 39 | * This example Implemented BLE HID device profile related functions, in which the HID device 40 | * has 4 Reports (1 is mouse, 2 is keyboard and LED, 3 is Consumer Devices, 4 is Vendor devices). 41 | * Users can choose different reports according to their own application scenarios. 42 | * BLE HID profile inheritance and USB HID class. 43 | */ 44 | 45 | /** 46 | * Note: 47 | * 1. Win10 does not support vendor report , So SUPPORT_REPORT_VENDOR is always set to FALSE, it defines in hidd_le_prf_int.h 48 | * 2. Update connection parameters are not allowed during iPhone HID encryption, slave turns 49 | * off the ability to automatically update connection parameters during encryption. 50 | * 3. After our HID device is connected, the iPhones write 1 to the Report Characteristic Configuration Descriptor, 51 | * even if the HID encryption is not completed. This should actually be written 1 after the HID encryption is completed. 52 | * we modify the permissions of the Report Characteristic Configuration Descriptor to `ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE_ENCRYPTED`. 53 | * if you got `GATT_INSUF_ENCRYPTION` error, please ignore. 54 | */ 55 | 56 | #define HID_DEMO_TAG "HID_DEMO" 57 | 58 | bool is_ble_connected = false; 59 | esp_ble_conn_update_params_t ble_conn_param; 60 | uint16_t hid_conn_id = 0; 61 | 62 | static void hidd_event_callback(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param); 63 | 64 | #define HIDD_DEVICE_NAME "ESP32S3-KB" 65 | static uint8_t hidd_service_uuid128[] = { 66 | /* LSB <--------------------------------------------------------------------------------> MSB */ 67 | //first uuid, 16bit, [12],[13] is the value 68 | 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x12, 0x18, 0x00, 0x00, 69 | }; 70 | 71 | static esp_ble_adv_data_t hidd_adv_data = { 72 | .set_scan_rsp = false, 73 | .include_name = true, 74 | .include_txpower = true, 75 | .min_interval = 0x0006, //slave connection min interval, Time = min_interval * 1.25 msec 76 | .max_interval = 0x0010, //slave connection max interval, Time = max_interval * 1.25 msec 77 | .appearance = 0x03c0, //HID Generic, 78 | .manufacturer_len = 0, 79 | .p_manufacturer_data = NULL, 80 | .service_data_len = 0, 81 | .p_service_data = NULL, 82 | .service_uuid_len = sizeof(hidd_service_uuid128), 83 | .p_service_uuid = hidd_service_uuid128, 84 | .flag = 0x6, 85 | }; 86 | 87 | static esp_ble_adv_params_t hidd_adv_params = { 88 | .adv_int_min = 1000, 89 | .adv_int_max = 1600, 90 | .adv_type = ADV_TYPE_IND, 91 | .own_addr_type = BLE_ADDR_TYPE_PUBLIC, 92 | //.peer_addr = 93 | //.peer_addr_type = 94 | .channel_map = ADV_CHNL_ALL, 95 | .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, 96 | }; 97 | 98 | 99 | static void hidd_event_callback(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param) 100 | { 101 | switch(event) { 102 | case ESP_HIDD_EVENT_REG_FINISH: { 103 | if (param->init_finish.state == ESP_HIDD_INIT_OK) { 104 | //esp_bd_addr_t rand_addr = {0x04,0x11,0x11,0x11,0x11,0x05}; 105 | esp_ble_gap_set_device_name(HIDD_DEVICE_NAME); 106 | esp_ble_gap_config_adv_data(&hidd_adv_data); 107 | 108 | } 109 | break; 110 | } 111 | case ESP_BAT_EVENT_REG: { 112 | break; 113 | } 114 | case ESP_HIDD_EVENT_DEINIT_FINISH: 115 | break; 116 | case ESP_HIDD_EVENT_BLE_CONNECT: { 117 | hid_conn_id = param->connect.conn_id; 118 | ESP_LOGI(HID_DEMO_TAG, "ESP_HIDD_EVENT_BLE_CONNECT, id = %d", hid_conn_id); 119 | 120 | memcpy(ble_conn_param.bda, param->connect.remote_bda, sizeof(esp_bd_addr_t)); 121 | ble_conn_param.min_int = 160; // x 1.25ms 122 | ble_conn_param.max_int = 160; // x 1.25ms 123 | ble_conn_param.latency = 0; 124 | ble_conn_param.timeout = 500; // x 6.25ms for disconnection timeout 125 | // esp_ble_gap_update_conn_params(&ble_conn_param); 126 | is_ble_connected = true; 127 | flush_power_state(PM_KB_TP_ACTIVE); 128 | 129 | break; 130 | } 131 | case ESP_HIDD_EVENT_BLE_DISCONNECT: { 132 | is_ble_connected = false; 133 | ESP_LOGI(HID_DEMO_TAG, "ESP_HIDD_EVENT_BLE_DISCONNECT"); 134 | esp_ble_gap_start_advertising(&hidd_adv_params); 135 | break; 136 | } 137 | case ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT: { 138 | ESP_LOGI(HID_DEMO_TAG, "%s, ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT", __func__); 139 | ESP_LOG_BUFFER_HEX(HID_DEMO_TAG, param->vendor_write.data, param->vendor_write.length); 140 | break; 141 | } 142 | case ESP_HIDD_EVENT_BLE_LED_OUT_WRITE_EVT: { 143 | void kb_led_cb(uint8_t kbd_leds); 144 | kb_led_cb(param->vendor_write.data[0]); 145 | break; 146 | } 147 | default: 148 | break; 149 | } 150 | return; 151 | } 152 | 153 | static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) 154 | { 155 | switch (event) { 156 | case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: 157 | esp_ble_gap_start_advertising(&hidd_adv_params); 158 | break; 159 | case ESP_GAP_BLE_SEC_REQ_EVT: 160 | for(int i = 0; i < ESP_BD_ADDR_LEN; i++) { 161 | ESP_LOGD(HID_DEMO_TAG, "%x:",param->ble_security.ble_req.bd_addr[i]); 162 | } 163 | esp_ble_gap_security_rsp(param->ble_security.ble_req.bd_addr, true); 164 | break; 165 | case ESP_GAP_BLE_AUTH_CMPL_EVT: { 166 | esp_bd_addr_t bd_addr; 167 | memcpy(bd_addr, param->ble_security.auth_cmpl.bd_addr, sizeof(esp_bd_addr_t)); 168 | ESP_LOGI(HID_DEMO_TAG, "remote BD_ADDR: %08x%04x", 169 | (bd_addr[0] << 24) + (bd_addr[1] << 16) + (bd_addr[2] << 8) + bd_addr[3], 170 | (bd_addr[4] << 8) + bd_addr[5]); 171 | ESP_LOGI(HID_DEMO_TAG, "address type = %d", param->ble_security.auth_cmpl.addr_type); 172 | ESP_LOGI(HID_DEMO_TAG, "pair status = %s",param->ble_security.auth_cmpl.success ? "success" : "fail"); 173 | if(!param->ble_security.auth_cmpl.success) { 174 | ESP_LOGE(HID_DEMO_TAG, "fail reason = 0x%x",param->ble_security.auth_cmpl.fail_reason); 175 | is_ble_connected = false; 176 | } 177 | break; 178 | } 179 | default: 180 | break; 181 | } 182 | } 183 | 184 | void app_main(void) 185 | { 186 | esp_err_t ret; 187 | 188 | // Initialize NVS. 189 | ret = nvs_flash_init(); 190 | if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { 191 | ESP_ERROR_CHECK(nvs_flash_erase()); 192 | ret = nvs_flash_init(); 193 | } 194 | ESP_ERROR_CHECK( ret ); 195 | 196 | ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT)); 197 | 198 | esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); 199 | ret = esp_bt_controller_init(&bt_cfg); 200 | if (ret) { 201 | ESP_LOGE(HID_DEMO_TAG, "%s initialize controller failed\n", __func__); 202 | return; 203 | } 204 | 205 | ret = esp_bt_controller_enable(ESP_BT_MODE_BLE); 206 | if (ret) { 207 | ESP_LOGE(HID_DEMO_TAG, "%s enable controller failed\n", __func__); 208 | return; 209 | } 210 | 211 | ret = esp_bluedroid_init(); 212 | if (ret) { 213 | ESP_LOGE(HID_DEMO_TAG, "%s init bluedroid failed\n", __func__); 214 | return; 215 | } 216 | 217 | ret = esp_bluedroid_enable(); 218 | if (ret) { 219 | ESP_LOGE(HID_DEMO_TAG, "%s init bluedroid failed\n", __func__); 220 | return; 221 | } 222 | 223 | if((ret = esp_hidd_profile_init()) != ESP_OK) { 224 | ESP_LOGE(HID_DEMO_TAG, "%s init bluedroid failed\n", __func__); 225 | } 226 | 227 | ///register the callback function to the gap module 228 | esp_ble_gap_register_callback(gap_event_handler); 229 | esp_hidd_register_callbacks(hidd_event_callback); 230 | 231 | /* set the security iocap & auth_req & key size & init key response key parameters to the stack*/ 232 | esp_ble_auth_req_t auth_req = ESP_LE_AUTH_BOND; //bonding with peer device after authentication 233 | esp_ble_io_cap_t iocap = ESP_IO_CAP_NONE; //set the IO capability to No output No input 234 | uint8_t key_size = 16; //the key size should be 7~16 bytes 235 | uint8_t init_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK; 236 | uint8_t rsp_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK; 237 | esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &auth_req, sizeof(uint8_t)); 238 | esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &iocap, sizeof(uint8_t)); 239 | esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &key_size, sizeof(uint8_t)); 240 | /* If your BLE device act as a Slave, the init_key means you hope which types of key of the master should distribute to you, 241 | and the response key means which key you can distribute to the Master; 242 | If your BLE device act as a master, the response key means you hope which types of key of the slave should distribute to you, 243 | and the init key means which key you can distribute to the slave. */ 244 | esp_ble_gap_set_security_param(ESP_BLE_SM_SET_INIT_KEY, &init_key, sizeof(uint8_t)); 245 | esp_ble_gap_set_security_param(ESP_BLE_SM_SET_RSP_KEY, &rsp_key, sizeof(uint8_t)); 246 | 247 | void keyboard_task(void *arg); 248 | xTaskCreate(&keyboard_task, "kb_task", 4096, NULL, configMAX_PRIORITIES, NULL); 249 | } 250 | -------------------------------------------------------------------------------- /main/esp_hidd_prf_api.c: -------------------------------------------------------------------------------- 1 | // Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "esp_hidd_prf_api.h" 16 | #include "hidd_le_prf_int.h" 17 | #include "hid_dev.h" 18 | #include 19 | #include 20 | #include "esp_log.h" 21 | 22 | // HID keyboard input report length 23 | #define HID_KEYBOARD_IN_RPT_LEN 8 24 | 25 | // HID LED output report length 26 | #define HID_LED_OUT_RPT_LEN 1 27 | 28 | // HID mouse input report length 29 | #define HID_MOUSE_IN_RPT_LEN 5 30 | 31 | // HID consumer control input report length 32 | #define HID_CC_IN_RPT_LEN 2 33 | 34 | extern uint16_t hid_conn_id; 35 | extern bool is_ble_connected; 36 | 37 | esp_err_t esp_hidd_register_callbacks(esp_hidd_event_cb_t callbacks) 38 | { 39 | esp_err_t hidd_status; 40 | 41 | if(callbacks != NULL) { 42 | hidd_le_env.hidd_cb = callbacks; 43 | } else { 44 | return ESP_FAIL; 45 | } 46 | 47 | if((hidd_status = hidd_register_cb()) != ESP_OK) { 48 | return hidd_status; 49 | } 50 | 51 | esp_ble_gatts_app_register(BATTRAY_APP_ID); 52 | 53 | if((hidd_status = esp_ble_gatts_app_register(HIDD_APP_ID)) != ESP_OK) { 54 | return hidd_status; 55 | } 56 | 57 | return hidd_status; 58 | } 59 | 60 | esp_err_t esp_hidd_profile_init(void) 61 | { 62 | if (hidd_le_env.enabled) { 63 | ESP_LOGE(HID_LE_PRF_TAG, "HID device profile already initialized"); 64 | return ESP_FAIL; 65 | } 66 | // Reset the hid device target environment 67 | memset(&hidd_le_env, 0, sizeof(hidd_le_env_t)); 68 | hidd_le_env.enabled = true; 69 | return ESP_OK; 70 | } 71 | 72 | esp_err_t esp_hidd_profile_deinit(void) 73 | { 74 | uint16_t hidd_svc_hdl = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_SVC]; 75 | if (!hidd_le_env.enabled) { 76 | ESP_LOGE(HID_LE_PRF_TAG, "HID device profile already initialized"); 77 | return ESP_OK; 78 | } 79 | 80 | if(hidd_svc_hdl != 0) { 81 | esp_ble_gatts_stop_service(hidd_svc_hdl); 82 | esp_ble_gatts_delete_service(hidd_svc_hdl); 83 | } else { 84 | return ESP_FAIL; 85 | } 86 | 87 | /* register the HID device profile to the BTA_GATTS module*/ 88 | esp_ble_gatts_app_unregister(hidd_le_env.gatt_if); 89 | 90 | return ESP_OK; 91 | } 92 | 93 | uint16_t esp_hidd_get_version(void) 94 | { 95 | return HIDD_VERSION; 96 | } 97 | 98 | void esp_hidd_send_consumer_value(uint16_t key) 99 | { 100 | ESP_LOGD(HID_LE_PRF_TAG, "key = %04x", key); 101 | hid_dev_send_report(hidd_le_env.gatt_if, hid_conn_id, 102 | HID_RPT_ID_CC_IN, HID_REPORT_TYPE_INPUT, HID_CC_IN_RPT_LEN, (uint8_t*)&key); 103 | return; 104 | } 105 | 106 | void esp_hidd_send_keyboard_value(uint8_t *buffer) 107 | { 108 | if (!is_ble_connected) { 109 | return; 110 | } 111 | 112 | ESP_LOGD(HID_LE_PRF_TAG, "the key vaule = %d,%d,%d,%d,%d,%d,%d,%d", 113 | buffer[0], buffer[1], buffer[2], buffer[3], 114 | buffer[4], buffer[5], buffer[6], buffer[7]); 115 | hid_dev_send_report(hidd_le_env.gatt_if, hid_conn_id, 116 | HID_RPT_ID_KEY_IN, HID_REPORT_TYPE_INPUT, HID_KEYBOARD_IN_RPT_LEN, buffer); 117 | return; 118 | } 119 | 120 | void esp_hidd_send_mouse_value(uint8_t buttons, 121 | int8_t dx, int8_t dy, int8_t vertical, int8_t horizontal) 122 | { 123 | if (!is_ble_connected) { 124 | return; 125 | } 126 | 127 | uint8_t buffer[HID_MOUSE_IN_RPT_LEN]; 128 | buffer[0] = buttons; // Buttons 129 | buffer[1] = dx; // X 130 | buffer[2] = dy; // Y 131 | buffer[3] = vertical; // Wheel 132 | buffer[4] = horizontal; // AC Pan 133 | 134 | hid_dev_send_report(hidd_le_env.gatt_if, hid_conn_id, 135 | HID_RPT_ID_MOUSE_IN, HID_REPORT_TYPE_INPUT, HID_MOUSE_IN_RPT_LEN, buffer); 136 | return; 137 | } 138 | -------------------------------------------------------------------------------- /main/esp_hidd_prf_api.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef __ESP_HIDD_API_H__ 16 | #define __ESP_HIDD_API_H__ 17 | 18 | #include "esp_bt_defs.h" 19 | #include "esp_gatt_defs.h" 20 | #include "esp_err.h" 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | typedef enum { 27 | ESP_HIDD_EVENT_REG_FINISH = 0, 28 | ESP_BAT_EVENT_REG, 29 | ESP_HIDD_EVENT_DEINIT_FINISH, 30 | ESP_HIDD_EVENT_BLE_CONNECT, 31 | ESP_HIDD_EVENT_BLE_DISCONNECT, 32 | ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT, 33 | ESP_HIDD_EVENT_BLE_LED_OUT_WRITE_EVT, 34 | } esp_hidd_cb_event_t; 35 | 36 | /// HID config status 37 | typedef enum { 38 | ESP_HIDD_STA_CONN_SUCCESS = 0x00, 39 | ESP_HIDD_STA_CONN_FAIL = 0x01, 40 | } esp_hidd_sta_conn_state_t; 41 | 42 | /// HID init status 43 | typedef enum { 44 | ESP_HIDD_INIT_OK = 0, 45 | ESP_HIDD_INIT_FAILED = 1, 46 | } esp_hidd_init_state_t; 47 | 48 | /// HID deinit status 49 | typedef enum { 50 | ESP_HIDD_DEINIT_OK = 0, 51 | ESP_HIDD_DEINIT_FAILED = 0, 52 | } esp_hidd_deinit_state_t; 53 | 54 | #define LEFT_CONTROL_KEY_MASK (1 << 0) 55 | #define LEFT_SHIFT_KEY_MASK (1 << 1) 56 | #define LEFT_ALT_KEY_MASK (1 << 2) 57 | #define LEFT_GUI_KEY_MASK (1 << 3) 58 | #define RIGHT_CONTROL_KEY_MASK (1 << 4) 59 | #define RIGHT_SHIFT_KEY_MASK (1 << 5) 60 | #define RIGHT_ALT_KEY_MASK (1 << 6) 61 | #define RIGHT_GUI_KEY_MASK (1 << 7) 62 | 63 | typedef uint8_t key_mask_t; 64 | /** 65 | * @brief HIDD callback parameters union 66 | */ 67 | typedef union { 68 | /** 69 | * @brief ESP_HIDD_EVENT_INIT_FINISH 70 | */ 71 | struct hidd_init_finish_evt_param { 72 | esp_hidd_init_state_t state; /*!< Initial status */ 73 | esp_gatt_if_t gatts_if; 74 | } init_finish; /*!< HID callback param of ESP_HIDD_EVENT_INIT_FINISH */ 75 | 76 | /** 77 | * @brief ESP_HIDD_EVENT_DEINIT_FINISH 78 | */ 79 | struct hidd_deinit_finish_evt_param { 80 | esp_hidd_deinit_state_t state; /*!< De-initial status */ 81 | } deinit_finish; /*!< HID callback param of ESP_HIDD_EVENT_DEINIT_FINISH */ 82 | 83 | /** 84 | * @brief ESP_HIDD_EVENT_CONNECT 85 | */ 86 | struct hidd_connect_evt_param { 87 | uint16_t conn_id; 88 | esp_bd_addr_t remote_bda; /*!< HID Remote bluetooth connection index */ 89 | } connect; /*!< HID callback param of ESP_HIDD_EVENT_CONNECT */ 90 | 91 | /** 92 | * @brief ESP_HIDD_EVENT_DISCONNECT 93 | */ 94 | struct hidd_disconnect_evt_param { 95 | esp_bd_addr_t remote_bda; /*!< HID Remote bluetooth device address */ 96 | } disconnect; /*!< HID callback param of ESP_HIDD_EVENT_DISCONNECT */ 97 | 98 | /** 99 | * @brief ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT 100 | */ 101 | struct hidd_vendor_write_evt_param { 102 | uint16_t conn_id; /*!< HID connection index */ 103 | uint16_t report_id; /*!< HID report index */ 104 | uint16_t length; /*!< data length */ 105 | uint8_t *data; /*!< The pointer to the data */ 106 | } vendor_write; /*!< HID callback param of ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT */ 107 | 108 | } esp_hidd_cb_param_t; 109 | 110 | 111 | /** 112 | * @brief HID device event callback function type 113 | * @param event : Event type 114 | * @param param : Point to callback parameter, currently is union type 115 | */ 116 | typedef void (*esp_hidd_event_cb_t) (esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param); 117 | 118 | 119 | 120 | /** 121 | * 122 | * @brief This function is called to receive hid device callback event 123 | * 124 | * @param[in] callbacks: callback functions 125 | * 126 | * @return ESP_OK - success, other - failed 127 | * 128 | */ 129 | esp_err_t esp_hidd_register_callbacks(esp_hidd_event_cb_t callbacks); 130 | 131 | /** 132 | * 133 | * @brief This function is called to initialize hid device profile 134 | * 135 | * @return ESP_OK - success, other - failed 136 | * 137 | */ 138 | esp_err_t esp_hidd_profile_init(void); 139 | 140 | /** 141 | * 142 | * @brief This function is called to de-initialize hid device profile 143 | * 144 | * @return ESP_OK - success, other - failed 145 | * 146 | */ 147 | esp_err_t esp_hidd_profile_deinit(void); 148 | 149 | /** 150 | * 151 | * @brief Get hidd profile version 152 | * 153 | * @return Most 8bit significant is Great version, Least 8bit is Sub version 154 | * 155 | */ 156 | uint16_t esp_hidd_get_version(void); 157 | 158 | void esp_hidd_send_consumer_value(uint16_t key); 159 | 160 | void esp_hidd_send_keyboard_value(uint8_t *buffer); 161 | 162 | void esp_hidd_send_mouse_value(uint8_t buttons, 163 | int8_t dx, int8_t dy, int8_t vertical, int8_t horizontal); 164 | 165 | #ifdef __cplusplus 166 | } 167 | #endif 168 | 169 | #endif /* __ESP_HIDD_API_H__ */ 170 | -------------------------------------------------------------------------------- /main/hid_dev.c: -------------------------------------------------------------------------------- 1 | // Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "hid_dev.h" 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include "esp_log.h" 21 | 22 | static hid_report_map_t *hid_dev_rpt_tbl; 23 | static uint8_t hid_dev_rpt_tbl_Len; 24 | 25 | static hid_report_map_t *hid_dev_rpt_by_id(uint8_t id, uint8_t type) 26 | { 27 | hid_report_map_t *rpt = hid_dev_rpt_tbl; 28 | 29 | for (uint8_t i = hid_dev_rpt_tbl_Len; i > 0; i--, rpt++) { 30 | if (rpt->id == id && rpt->type == type && rpt->mode == hidProtocolMode) { 31 | return rpt; 32 | } 33 | } 34 | 35 | return NULL; 36 | } 37 | 38 | void hid_dev_register_reports(uint8_t num_reports, hid_report_map_t *p_report) 39 | { 40 | hid_dev_rpt_tbl = p_report; 41 | hid_dev_rpt_tbl_Len = num_reports; 42 | return; 43 | } 44 | 45 | void hid_dev_send_report(esp_gatt_if_t gatts_if, uint16_t conn_id, 46 | uint8_t id, uint8_t type, uint8_t length, uint8_t *data) 47 | { 48 | hid_report_map_t *p_rpt; 49 | 50 | // get att handle for report 51 | if ((p_rpt = hid_dev_rpt_by_id(id, type)) != NULL) { 52 | // if notifications are enabled 53 | ESP_LOGD(HID_LE_PRF_TAG, "%s(), send the report, handle = %d", __func__, p_rpt->handle); 54 | esp_ble_gatts_send_indicate(gatts_if, conn_id, p_rpt->handle, length, data, false); 55 | } 56 | 57 | return; 58 | } 59 | 60 | void hid_consumer_build_report(uint8_t *buffer, consumer_cmd_t cmd) 61 | { 62 | if (!buffer) { 63 | ESP_LOGE(HID_LE_PRF_TAG, "%s(), the buffer is NULL, hid build report failed.", __func__); 64 | return; 65 | } 66 | 67 | switch (cmd) { 68 | case HID_CONSUMER_CHANNEL_UP: 69 | HID_CC_RPT_SET_CHANNEL(buffer, HID_CC_RPT_CHANNEL_UP); 70 | break; 71 | 72 | case HID_CONSUMER_CHANNEL_DOWN: 73 | HID_CC_RPT_SET_CHANNEL(buffer, HID_CC_RPT_CHANNEL_DOWN); 74 | break; 75 | 76 | case HID_CONSUMER_VOLUME_UP: 77 | HID_CC_RPT_SET_VOLUME_UP(buffer); 78 | break; 79 | 80 | case HID_CONSUMER_VOLUME_DOWN: 81 | HID_CC_RPT_SET_VOLUME_DOWN(buffer); 82 | break; 83 | 84 | case HID_CONSUMER_MUTE: 85 | HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_MUTE); 86 | break; 87 | 88 | case HID_CONSUMER_POWER: 89 | HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_POWER); 90 | break; 91 | 92 | case HID_CONSUMER_RECALL_LAST: 93 | HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_LAST); 94 | break; 95 | 96 | case HID_CONSUMER_ASSIGN_SEL: 97 | HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_ASSIGN_SEL); 98 | break; 99 | 100 | case HID_CONSUMER_PLAY: 101 | HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_PLAY); 102 | break; 103 | 104 | case HID_CONSUMER_PAUSE: 105 | HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_PAUSE); 106 | break; 107 | 108 | case HID_CONSUMER_RECORD: 109 | HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_RECORD); 110 | break; 111 | 112 | case HID_CONSUMER_FAST_FORWARD: 113 | HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_FAST_FWD); 114 | break; 115 | 116 | case HID_CONSUMER_REWIND: 117 | HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_REWIND); 118 | break; 119 | 120 | case HID_CONSUMER_SCAN_NEXT_TRK: 121 | HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_SCAN_NEXT_TRK); 122 | break; 123 | 124 | case HID_CONSUMER_SCAN_PREV_TRK: 125 | HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_SCAN_PREV_TRK); 126 | break; 127 | 128 | case HID_CONSUMER_STOP: 129 | HID_CC_RPT_SET_BUTTON(buffer, HID_CC_RPT_STOP); 130 | break; 131 | 132 | default: 133 | break; 134 | } 135 | 136 | return; 137 | } 138 | -------------------------------------------------------------------------------- /main/hidd_le_prf_int.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | 16 | 17 | #ifndef __HID_DEVICE_LE_PRF__ 18 | #define __HID_DEVICE_LE_PRF__ 19 | #include 20 | #include "esp_gatts_api.h" 21 | #include "esp_gatt_defs.h" 22 | #include "esp_hidd_prf_api.h" 23 | #include "esp_gap_ble_api.h" 24 | #include "hid_dev.h" 25 | 26 | #define SUPPORT_REPORT_VENDOR false 27 | //HID BLE profile log tag 28 | #define HID_LE_PRF_TAG "HID_LE_PRF" 29 | 30 | /// Maximal number of HIDS that can be added in the DB 31 | #ifndef USE_ONE_HIDS_INSTANCE 32 | #define HIDD_LE_NB_HIDS_INST_MAX (2) 33 | #else 34 | #define HIDD_LE_NB_HIDS_INST_MAX (1) 35 | #endif 36 | 37 | #define HIDD_GREAT_VER 0x01 //Version + Subversion 38 | #define HIDD_SUB_VER 0x00 //Version + Subversion 39 | #define HIDD_VERSION ((HIDD_GREAT_VER<<8)|HIDD_SUB_VER) //Version + Subversion 40 | 41 | #define HID_MAX_APPS 1 42 | 43 | // Number of HID reports defined in the service 44 | #define HID_NUM_REPORTS 9 45 | 46 | // HID Report IDs for the service 47 | #define HID_RPT_ID_MOUSE_IN 1 // Mouse input report ID 48 | #define HID_RPT_ID_KEY_IN 2 // Keyboard input report ID 49 | #define HID_RPT_ID_CC_IN 3 //Consumer Control input report ID 50 | #define HID_RPT_ID_VENDOR_OUT 4 // Vendor output report ID 51 | #define HID_RPT_ID_LED_OUT 2 // LED output report ID 52 | #define HID_RPT_ID_FEATURE 0 // Feature report ID 53 | 54 | #define HIDD_APP_ID 0x1812//ATT_SVC_HID 55 | 56 | #define BATTRAY_APP_ID 0x180f 57 | 58 | 59 | #define ATT_SVC_HID 0x1812 60 | 61 | /// Maximal number of Report Char. that can be added in the DB for one HIDS - Up to 11 62 | #define HIDD_LE_NB_REPORT_INST_MAX (5) 63 | 64 | /// Maximal length of Report Char. Value 65 | #define HIDD_LE_REPORT_MAX_LEN (255) 66 | /// Maximal length of Report Map Char. Value 67 | #define HIDD_LE_REPORT_MAP_MAX_LEN (512) 68 | 69 | /// Length of Boot Report Char. Value Maximal Length 70 | #define HIDD_LE_BOOT_REPORT_MAX_LEN (8) 71 | 72 | /// Boot KB Input Report Notification Configuration Bit Mask 73 | #define HIDD_LE_BOOT_KB_IN_NTF_CFG_MASK (0x40) 74 | /// Boot KB Input Report Notification Configuration Bit Mask 75 | #define HIDD_LE_BOOT_MOUSE_IN_NTF_CFG_MASK (0x80) 76 | /// Boot Report Notification Configuration Bit Mask 77 | #define HIDD_LE_REPORT_NTF_CFG_MASK (0x20) 78 | 79 | 80 | /* HID information flags */ 81 | #define HID_FLAGS_REMOTE_WAKE 0x01 // RemoteWake 82 | #define HID_FLAGS_NORMALLY_CONNECTABLE 0x02 // NormallyConnectable 83 | 84 | /* Control point commands */ 85 | #define HID_CMD_SUSPEND 0x00 // Suspend 86 | #define HID_CMD_EXIT_SUSPEND 0x01 // Exit Suspend 87 | 88 | /* HID protocol mode values */ 89 | #define HID_PROTOCOL_MODE_BOOT 0x00 // Boot Protocol Mode 90 | #define HID_PROTOCOL_MODE_REPORT 0x01 // Report Protocol Mode 91 | 92 | /* Attribute value lengths */ 93 | #define HID_PROTOCOL_MODE_LEN 1 // HID Protocol Mode 94 | #define HID_INFORMATION_LEN 4 // HID Information 95 | #define HID_REPORT_REF_LEN 2 // HID Report Reference Descriptor 96 | #define HID_EXT_REPORT_REF_LEN 2 // External Report Reference Descriptor 97 | 98 | // HID feature flags 99 | #define HID_KBD_FLAGS HID_FLAGS_REMOTE_WAKE 100 | 101 | /* HID Report type */ 102 | #define HID_REPORT_TYPE_INPUT 1 103 | #define HID_REPORT_TYPE_OUTPUT 2 104 | #define HID_REPORT_TYPE_FEATURE 3 105 | 106 | 107 | /// HID Service Attributes Indexes 108 | enum { 109 | HIDD_LE_IDX_SVC, 110 | 111 | // Included Service 112 | HIDD_LE_IDX_INCL_SVC, 113 | 114 | // HID Information 115 | HIDD_LE_IDX_HID_INFO_CHAR, 116 | HIDD_LE_IDX_HID_INFO_VAL, 117 | 118 | // HID Control Point 119 | HIDD_LE_IDX_HID_CTNL_PT_CHAR, 120 | HIDD_LE_IDX_HID_CTNL_PT_VAL, 121 | 122 | // Report Map 123 | HIDD_LE_IDX_REPORT_MAP_CHAR, 124 | HIDD_LE_IDX_REPORT_MAP_VAL, 125 | HIDD_LE_IDX_REPORT_MAP_EXT_REP_REF, 126 | 127 | // Protocol Mode 128 | HIDD_LE_IDX_PROTO_MODE_CHAR, 129 | HIDD_LE_IDX_PROTO_MODE_VAL, 130 | 131 | // Report mouse input 132 | HIDD_LE_IDX_REPORT_MOUSE_IN_CHAR, 133 | HIDD_LE_IDX_REPORT_MOUSE_IN_VAL, 134 | HIDD_LE_IDX_REPORT_MOUSE_IN_CCC, 135 | HIDD_LE_IDX_REPORT_MOUSE_REP_REF, 136 | //Report Key input 137 | HIDD_LE_IDX_REPORT_KEY_IN_CHAR, 138 | HIDD_LE_IDX_REPORT_KEY_IN_VAL, 139 | HIDD_LE_IDX_REPORT_KEY_IN_CCC, 140 | HIDD_LE_IDX_REPORT_KEY_IN_REP_REF, 141 | ///Report Led output 142 | HIDD_LE_IDX_REPORT_LED_OUT_CHAR, 143 | HIDD_LE_IDX_REPORT_LED_OUT_VAL, 144 | HIDD_LE_IDX_REPORT_LED_OUT_REP_REF, 145 | 146 | #if (SUPPORT_REPORT_VENDOR == true) 147 | /// Report Vendor 148 | HIDD_LE_IDX_REPORT_VENDOR_OUT_CHAR, 149 | HIDD_LE_IDX_REPORT_VENDOR_OUT_VAL, 150 | HIDD_LE_IDX_REPORT_VENDOR_OUT_REP_REF, 151 | #endif 152 | HIDD_LE_IDX_REPORT_CC_IN_CHAR, 153 | HIDD_LE_IDX_REPORT_CC_IN_VAL, 154 | HIDD_LE_IDX_REPORT_CC_IN_CCC, 155 | HIDD_LE_IDX_REPORT_CC_IN_REP_REF, 156 | 157 | // Boot Keyboard Input Report 158 | HIDD_LE_IDX_BOOT_KB_IN_REPORT_CHAR, 159 | HIDD_LE_IDX_BOOT_KB_IN_REPORT_VAL, 160 | HIDD_LE_IDX_BOOT_KB_IN_REPORT_NTF_CFG, 161 | 162 | // Boot Keyboard Output Report 163 | HIDD_LE_IDX_BOOT_KB_OUT_REPORT_CHAR, 164 | HIDD_LE_IDX_BOOT_KB_OUT_REPORT_VAL, 165 | 166 | // Boot Mouse Input Report 167 | HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_CHAR, 168 | HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_VAL, 169 | HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_NTF_CFG, 170 | 171 | // Report 172 | HIDD_LE_IDX_REPORT_CHAR, 173 | HIDD_LE_IDX_REPORT_VAL, 174 | HIDD_LE_IDX_REPORT_REP_REF, 175 | //HIDD_LE_IDX_REPORT_NTF_CFG, 176 | 177 | HIDD_LE_IDX_NB, 178 | }; 179 | 180 | 181 | /// Attribute Table Indexes 182 | enum { 183 | HIDD_LE_INFO_CHAR, 184 | HIDD_LE_CTNL_PT_CHAR, 185 | HIDD_LE_REPORT_MAP_CHAR, 186 | HIDD_LE_REPORT_CHAR, 187 | HIDD_LE_PROTO_MODE_CHAR, 188 | HIDD_LE_BOOT_KB_IN_REPORT_CHAR, 189 | HIDD_LE_BOOT_KB_OUT_REPORT_CHAR, 190 | HIDD_LE_BOOT_MOUSE_IN_REPORT_CHAR, 191 | HIDD_LE_CHAR_MAX //= HIDD_LE_REPORT_CHAR + HIDD_LE_NB_REPORT_INST_MAX, 192 | }; 193 | 194 | ///att read event table Indexs 195 | enum { 196 | HIDD_LE_READ_INFO_EVT, 197 | HIDD_LE_READ_CTNL_PT_EVT, 198 | HIDD_LE_READ_REPORT_MAP_EVT, 199 | HIDD_LE_READ_REPORT_EVT, 200 | HIDD_LE_READ_PROTO_MODE_EVT, 201 | HIDD_LE_BOOT_KB_IN_REPORT_EVT, 202 | HIDD_LE_BOOT_KB_OUT_REPORT_EVT, 203 | HIDD_LE_BOOT_MOUSE_IN_REPORT_EVT, 204 | 205 | HID_LE_EVT_MAX 206 | }; 207 | 208 | /// Client Characteristic Configuration Codes 209 | enum { 210 | HIDD_LE_DESC_MASK = 0x10, 211 | 212 | HIDD_LE_BOOT_KB_IN_REPORT_CFG = HIDD_LE_BOOT_KB_IN_REPORT_CHAR | HIDD_LE_DESC_MASK, 213 | HIDD_LE_BOOT_MOUSE_IN_REPORT_CFG = HIDD_LE_BOOT_MOUSE_IN_REPORT_CHAR | HIDD_LE_DESC_MASK, 214 | HIDD_LE_REPORT_CFG = HIDD_LE_REPORT_CHAR | HIDD_LE_DESC_MASK, 215 | }; 216 | 217 | /// Features Flag Values 218 | enum { 219 | HIDD_LE_CFG_KEYBOARD = 0x01, 220 | HIDD_LE_CFG_MOUSE = 0x02, 221 | HIDD_LE_CFG_PROTO_MODE = 0x04, 222 | HIDD_LE_CFG_MAP_EXT_REF = 0x08, 223 | HIDD_LE_CFG_BOOT_KB_WR = 0x10, 224 | HIDD_LE_CFG_BOOT_MOUSE_WR = 0x20, 225 | }; 226 | 227 | /// Report Char. Configuration Flag Values 228 | enum { 229 | HIDD_LE_CFG_REPORT_IN = 0x01, 230 | HIDD_LE_CFG_REPORT_OUT = 0x02, 231 | //HOGPD_CFG_REPORT_FEAT can be used as a mask to check Report type 232 | HIDD_LE_CFG_REPORT_FEAT = 0x03, 233 | HIDD_LE_CFG_REPORT_WR = 0x10, 234 | }; 235 | 236 | /// Pointer to the connection clean-up function 237 | #define HIDD_LE_CLEANUP_FNCT (NULL) 238 | 239 | /* 240 | * TYPE DEFINITIONS 241 | **************************************************************************************** 242 | */ 243 | 244 | /// HIDD Features structure 245 | typedef struct { 246 | /// Service Features 247 | uint8_t svc_features; 248 | /// Number of Report Char. instances to add in the database 249 | uint8_t report_nb; 250 | /// Report Char. Configuration 251 | uint8_t report_char_cfg[HIDD_LE_NB_REPORT_INST_MAX]; 252 | } hidd_feature_t; 253 | 254 | 255 | typedef struct { 256 | bool in_use; 257 | bool congest; 258 | uint16_t conn_id; 259 | bool connected; 260 | esp_bd_addr_t remote_bda; 261 | uint32_t trans_id; 262 | uint8_t cur_srvc_id; 263 | 264 | } hidd_clcb_t; 265 | 266 | // HID report mapping table 267 | typedef struct { 268 | uint16_t handle; // Handle of report characteristic 269 | uint16_t cccdHandle; // Handle of CCCD for report characteristic 270 | uint8_t id; // Report ID 271 | uint8_t type; // Report type 272 | uint8_t mode; // Protocol mode (report or boot) 273 | } hidRptMap_t; 274 | 275 | 276 | typedef struct { 277 | /// hidd profile id 278 | uint8_t app_id; 279 | /// Notified handle 280 | uint16_t ntf_handle; 281 | ///Attribute handle Table 282 | uint16_t att_tbl[HIDD_LE_IDX_NB]; 283 | /// Supported Features 284 | hidd_feature_t hidd_feature[HIDD_LE_NB_HIDS_INST_MAX]; 285 | /// Current Protocol Mode 286 | uint8_t proto_mode[HIDD_LE_NB_HIDS_INST_MAX]; 287 | /// Number of HIDS added in the database 288 | uint8_t hids_nb; 289 | uint8_t pending_evt; 290 | uint16_t pending_hal; 291 | } hidd_inst_t; 292 | 293 | /// Report Reference structure 294 | typedef struct 295 | { 296 | ///Report ID 297 | uint8_t report_id; 298 | ///Report Type 299 | uint8_t report_type; 300 | }hids_report_ref_t; 301 | 302 | /// HID Information structure 303 | typedef struct 304 | { 305 | /// bcdHID 306 | uint16_t bcdHID; 307 | /// bCountryCode 308 | uint8_t bCountryCode; 309 | /// Flags 310 | uint8_t flags; 311 | }hids_hid_info_t; 312 | 313 | 314 | /* service engine control block */ 315 | typedef struct { 316 | hidd_clcb_t hidd_clcb[HID_MAX_APPS]; /* connection link*/ 317 | esp_gatt_if_t gatt_if; 318 | bool enabled; 319 | bool is_take; 320 | bool is_primery; 321 | hidd_inst_t hidd_inst; 322 | esp_hidd_event_cb_t hidd_cb; 323 | uint8_t inst_id; 324 | } hidd_le_env_t; 325 | 326 | extern hidd_le_env_t hidd_le_env; 327 | extern uint8_t hidProtocolMode; 328 | 329 | 330 | void hidd_clcb_alloc (uint16_t conn_id, esp_bd_addr_t bda); 331 | 332 | bool hidd_clcb_dealloc (uint16_t conn_id); 333 | 334 | void hidd_le_create_service(esp_gatt_if_t gatts_if); 335 | 336 | void hidd_set_attr_value(uint16_t handle, uint16_t val_len, const uint8_t *value); 337 | 338 | void hidd_get_attr_value(uint16_t handle, uint16_t *length, uint8_t **value); 339 | 340 | esp_err_t hidd_register_cb(void); 341 | 342 | 343 | #endif ///__HID_DEVICE_LE_PRF__ 344 | -------------------------------------------------------------------------------- /main/keyboard_pm.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of esp32s3-keyboard. 3 | * 4 | * Copyright (C) 2020-2021 Yuquan He 5 | * (Institute of Computing Technology, Chinese Academy of Sciences) 6 | * 7 | * esp32s3-keyboard is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * esp32s3-keyboard is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with esp32s3-keyboard. If not, see . 19 | */ 20 | 21 | #include "keyboard_pm.h" 22 | #include "pin_cfg.h" 23 | 24 | #include "esp_hidd_prf_api.h" 25 | #include "esp_gap_ble_api.h" 26 | #include "esp_err.h" 27 | #include "esp_pm.h" 28 | #include "esp_sleep.h" 29 | #include "esp_timer.h" 30 | #include "esp_log.h" 31 | 32 | #include "driver/uart.h" 33 | 34 | #include "freertos/FreeRTOS.h" 35 | #include "freertos/task.h" 36 | #include "esp_debug_helpers.h" 37 | 38 | /**************************************************************** 39 | * 40 | * Private Varibles 41 | * 42 | ****************************************************************/ 43 | 44 | // power management state configuration 45 | static kb_pm_state_t pm_cfg[] = { 46 | // keyboard idle for a long time. 5mA without BLE, 10ma with BLE 47 | [PM_IDLE_LONG_TIME] = { 48 | .kb_int_us = 25000, // *8 = 160ms per scan 49 | .ble_int_cnt = 800, // *1.25 = 1000ms BLE connection interval 50 | .duration_us = -1, 51 | .is_sleep = true 52 | }, 53 | // keyboard idle for a short time. 26mA with BLE 54 | [PM_IDLE_SHORT_TIME] = { 55 | .kb_int_us = 5000, // *8 = 40ms per scan 56 | .ble_int_cnt = 32, // *1.25 = 40ms BLE connection interval 57 | .duration_us = 2*60*1000000, 58 | .is_sleep = true 59 | }, 60 | // keyboard active but trackpoint inactive. 30mA with BLE 61 | [PM_KB_ACTIVE] = { 62 | .kb_int_us = 5000, // *8 = 40ms per scan 63 | .ble_int_cnt = 20, // *1.25 = 25ms BLE connection interval 64 | .duration_us = 10*60*1000000, 65 | .is_sleep = true 66 | }, 67 | // trackpoint active. 50mA with BLE 68 | [PM_KB_TP_ACTIVE] = { 69 | .kb_int_us = 5000, // *8 = 40ms per scan 70 | .ble_int_cnt = 10, // *1.25 = 12.5ms BLE connection interval 71 | .duration_us = 5*60*1000000, 72 | .is_sleep = false 73 | }, 74 | // charging, ~500mA 75 | [PM_CHARGING] = { 76 | .kb_int_us = 2000, // *8 = 16ms per scan 77 | .ble_int_cnt = 10, // *1.25 = 12.5ms BLE connection interval 78 | .duration_us = 60000000, 79 | .is_sleep = false 80 | }, 81 | }; 82 | 83 | static const int nr_pm_states = sizeof(pm_cfg) / sizeof(kb_pm_state_t); 84 | static kb_pm_t curr_pm_state = PM_IDLE_LONG_TIME; 85 | static volatile uint last_pm_timestamp = 0; 86 | 87 | static SemaphoreHandle_t pm_lock; 88 | 89 | // charging pin event queue 90 | static QueueHandle_t gpio_evt_queue = NULL; 91 | 92 | static const char *TAG = "kb-pm"; 93 | 94 | static bool is_pm_increase_rapid = false; 95 | 96 | /**************************************************************** 97 | * 98 | * Public varibles 99 | * 100 | ****************************************************************/ 101 | 102 | // power management in esp-idf library 103 | esp_pm_config_esp32s3_t esp_idf_pm_cfg = { 104 | .max_freq_mhz = 80, // e.g. 80, 160, 240 105 | .min_freq_mhz = 80, // e.g. 40 106 | .light_sleep_enable = false, // not enable at boot time 107 | }; 108 | 109 | extern volatile bool is_usb_connected; 110 | extern volatile bool is_ble_connected; 111 | extern esp_ble_conn_update_params_t ble_conn_param; 112 | 113 | /**************************************************************** 114 | * 115 | * Private Functions 116 | * 117 | ****************************************************************/ 118 | 119 | /** 120 | * Charging pin detection handler 121 | */ 122 | static void IRAM_ATTR gpio_isr_handler(void* arg) 123 | { 124 | uint32_t gpio_num = (uint32_t) arg; 125 | xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); 126 | } 127 | 128 | static void charging_detection_task(void* arg) 129 | { 130 | uint32_t io_num; 131 | for(;;) { 132 | if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) { 133 | // Hang FreeRTOS light sleep for a while... 134 | vTaskDelay(1); 135 | vTaskDelay(1); 136 | vTaskDelay(1); 137 | if (CHARGING_STATE != 0) { 138 | ESP_LOGI(TAG, "Charging. Turn off power saving."); 139 | flush_power_state(PM_CHARGING); 140 | } 141 | } 142 | } 143 | } 144 | 145 | /** 146 | * Update the BLE connection interval and power management settings 147 | * @param new_pm_state The state index 148 | */ 149 | static void update_ble_and_pm(kb_pm_t new_pm_state) 150 | { 151 | // if (new_pm_state == PM_KB_TP_ACTIVE) { 152 | // esp_backtrace_print(5); 153 | // } 154 | ESP_LOGI(TAG, "State %d, keyboard %d, BLE %d", new_pm_state, 155 | pm_cfg[new_pm_state].kb_int_us, pm_cfg[new_pm_state].ble_int_cnt); 156 | if (is_ble_connected 157 | && pm_cfg[new_pm_state].ble_int_cnt != ble_conn_param.min_int) 158 | { 159 | int lastint = ble_conn_param.min_int; 160 | ble_conn_param.min_int = 161 | ble_conn_param.max_int = pm_cfg[new_pm_state].ble_int_cnt; 162 | if (esp_ble_gap_update_conn_params(&ble_conn_param) != ESP_OK) { 163 | // restore last parameter and wait for next trial 164 | ble_conn_param.min_int = 165 | ble_conn_param.max_int = lastint; 166 | } 167 | } 168 | 169 | if (esp_idf_pm_cfg.light_sleep_enable != pm_cfg[new_pm_state].is_sleep) { 170 | esp_idf_pm_cfg.light_sleep_enable = pm_cfg[new_pm_state].is_sleep; 171 | esp_pm_configure(&esp_idf_pm_cfg); 172 | } 173 | } 174 | 175 | /**************************************************************** 176 | * 177 | * Public interface 178 | * 179 | ****************************************************************/ 180 | 181 | void init_pm(void) 182 | { 183 | // Charging detection 184 | GPIO_INIT_IN_FLOATING(CHARGING_PIN); 185 | 186 | esp_sleep_config_gpio_isolate(); 187 | 188 | gpio_wakeup_enable(CHARGING_PIN, GPIO_INTR_HIGH_LEVEL); 189 | esp_sleep_enable_gpio_wakeup(); 190 | 191 | gpio_sleep_set_direction(CHARGING_PIN, GPIO_MODE_INPUT); 192 | gpio_sleep_set_pull_mode(CHARGING_PIN, GPIO_FLOATING); 193 | 194 | // LEDs 195 | gpio_sleep_set_direction(BACKLIGHT_PWM, GPIO_MODE_OUTPUT); 196 | gpio_sleep_set_pull_mode(BACKLIGHT_PWM, GPIO_PULLDOWN_ONLY); 197 | gpio_sleep_set_direction(LED_F1, GPIO_MODE_OUTPUT); 198 | gpio_sleep_set_pull_mode(LED_F1, GPIO_PULLUP_ONLY); 199 | gpio_sleep_set_direction(LED_CAPLK, GPIO_MODE_OUTPUT); 200 | gpio_sleep_set_pull_mode(LED_CAPLK, GPIO_PULLUP_ONLY); 201 | 202 | // PS2 pins 203 | gpio_sleep_set_direction(PS2_DATA_PIN, GPIO_MODE_INPUT); 204 | gpio_sleep_set_pull_mode(PS2_DATA_PIN, GPIO_PULLUP_ONLY); 205 | gpio_sleep_set_direction(PS2_CLK_PIN, GPIO_MODE_INPUT); 206 | gpio_sleep_set_pull_mode(PS2_CLK_PIN, GPIO_PULLUP_ONLY); 207 | gpio_sleep_set_direction(PS2_RESET_PIN, GPIO_MODE_OUTPUT); 208 | gpio_sleep_set_pull_mode(PS2_RESET_PIN, GPIO_PULLDOWN_ONLY); 209 | 210 | // USB pins 211 | gpio_sleep_set_pull_mode(19, GPIO_PULLDOWN_ONLY); 212 | gpio_sleep_set_pull_mode(20, GPIO_PULLDOWN_ONLY); 213 | 214 | // charging task 215 | gpio_evt_queue = xQueueCreate(4, sizeof(uint32_t)); 216 | xTaskCreate(charging_detection_task, "charging_detection_task", 2048, NULL, 10, NULL); 217 | 218 | gpio_set_intr_type(CHARGING_PIN, GPIO_INTR_NEGEDGE); 219 | gpio_install_isr_service(0); 220 | gpio_isr_handler_add(CHARGING_PIN, gpio_isr_handler, (void*)CHARGING_PIN); 221 | 222 | ESP_ERROR_CHECK( uart_set_wakeup_threshold(UART_NUM_1, 3) ); 223 | ESP_ERROR_CHECK( esp_sleep_enable_uart_wakeup(UART_NUM_1) ); 224 | 225 | pm_lock = xSemaphoreCreateMutex(); 226 | if (CHARGING_STATE == 0) { 227 | curr_pm_state = PM_IDLE_LONG_TIME; 228 | esp_idf_pm_cfg.light_sleep_enable = true; 229 | esp_pm_configure(&esp_idf_pm_cfg); 230 | } else { 231 | curr_pm_state = PM_CHARGING; 232 | esp_idf_pm_cfg.light_sleep_enable = false; 233 | esp_pm_configure(&esp_idf_pm_cfg); 234 | } 235 | last_pm_timestamp = esp_timer_get_time(); 236 | } 237 | 238 | void flush_power_state(kb_pm_t new_pm_state) 239 | { 240 | if (xSemaphoreTake(pm_lock, 100) != pdTRUE) { 241 | ESP_LOGE(TAG, "Mutex wait too long..."); 242 | return; 243 | } 244 | 245 | uint currtime = esp_timer_get_time(); 246 | 247 | if (CHARGING_STATE != 0) { 248 | // force high power when charging 249 | new_pm_state = PM_CHARGING; 250 | last_pm_timestamp = currtime; 251 | } else if (new_pm_state < curr_pm_state) { 252 | // gradual decrement 253 | new_pm_state = curr_pm_state-1; 254 | } else { 255 | last_pm_timestamp = currtime; 256 | } 257 | 258 | // sleep for a while in case the BLE cannot response in time. 259 | is_pm_increase_rapid = 260 | (CHARGING_STATE == 0) 261 | && ((curr_pm_state == PM_IDLE_SHORT_TIME && new_pm_state == PM_KB_TP_ACTIVE) 262 | || (curr_pm_state == PM_IDLE_LONG_TIME && new_pm_state >= PM_KB_ACTIVE) 263 | ); 264 | 265 | uint diff_time = currtime - last_pm_timestamp; 266 | if (new_pm_state > curr_pm_state // increase power immediately 267 | || diff_time > pm_cfg[curr_pm_state].duration_us) 268 | { 269 | update_ble_and_pm(new_pm_state); 270 | curr_pm_state = new_pm_state; 271 | last_pm_timestamp = currtime; 272 | // } else { 273 | // update_ble_and_pm(curr_pm_state); 274 | } 275 | 276 | xSemaphoreGive(pm_lock); 277 | } 278 | 279 | unsigned get_kb_scan_interval_us(void) 280 | { 281 | return pm_cfg[curr_pm_state].kb_int_us * 5 / 6; 282 | } 283 | 284 | bool pm_should_wait(void) 285 | { 286 | return is_pm_increase_rapid; 287 | } 288 | -------------------------------------------------------------------------------- /main/keyboard_pm.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of esp32s3-keyboard. 3 | * 4 | * Copyright (C) 2020-2021 Yuquan He 5 | * (Institute of Computing Technology, Chinese Academy of Sciences) 6 | * 7 | * esp32s3-keyboard is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * esp32s3-keyboard is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with esp32s3-keyboard. If not, see . 19 | */ 20 | 21 | #ifndef _MY_KB_PM_H 22 | #define _MY_KB_PM_H 23 | 24 | #include 25 | #include 26 | 27 | /**************************************************************** 28 | * 29 | * Typedefs 30 | * 31 | ****************************************************************/ 32 | 33 | /** 34 | * Power state type 35 | */ 36 | typedef struct { 37 | uint32_t kb_int_us; // 1/8 of keyboard scan interval 38 | uint32_t ble_int_cnt; // 4/5 of BLE connection interval 39 | uint32_t duration_us; // Time in microsecond of this state 40 | bool is_sleep; // Enable auto light-sleep in esp-idf 41 | } kb_pm_state_t; 42 | 43 | /** 44 | * Power states 45 | */ 46 | typedef enum { 47 | PM_IDLE_LONG_TIME, 48 | PM_IDLE_SHORT_TIME, 49 | PM_KB_ACTIVE, 50 | PM_KB_TP_ACTIVE, 51 | PM_CHARGING 52 | } kb_pm_t; 53 | 54 | /**************************************************************** 55 | * 56 | * Public interface 57 | * 58 | ****************************************************************/ 59 | 60 | /** 61 | * Initializa the keyboard power management 62 | */ 63 | void init_pm(void); 64 | 65 | /** 66 | * Update power management 67 | * @param new_pm_state New PM state when duration expires 68 | */ 69 | void flush_power_state(kb_pm_t new_pm_state); 70 | 71 | /** 72 | * Get the keyboard scanning interval 73 | * @return scan interval in milliseconds 74 | */ 75 | unsigned get_kb_scan_interval_us(void); 76 | 77 | /** 78 | * Wait for a while ifr the BLE connection interval decreases rapidly. 79 | */ 80 | bool pm_should_wait(void); 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /main/keymap-e530.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of esp32s3-keyboard. 3 | * 4 | * Copyright (C) 2020-2021 Yuquan He 5 | * (Institute of Computing Technology, Chinese Academy of Sciences) 6 | * 7 | * esp32s3-keyboard is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * esp32s3-keyboard is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with esp32s3-keyboard. If not, see . 19 | */ 20 | 21 | /** 22 | * Keymap for Thinkpad E430/E530 etc. 23 | */ 24 | 25 | #include "keymap.h" 26 | 27 | keytable_t kbtbl[] = { 28 | // TODO 29 | }; 30 | 31 | fn_keytable_t fntbl[] = { 32 | // TODO 33 | }; 34 | -------------------------------------------------------------------------------- /main/keymap-e580.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of esp32s3-keyboard. 3 | * 4 | * Copyright (C) 2020-2021 Yuquan He 5 | * (Institute of Computing Technology, Chinese Academy of Sciences) 6 | * 7 | * esp32s3-keyboard is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * esp32s3-keyboard is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with esp32s3-keyboard. If not, see . 19 | */ 20 | 21 | /** 22 | * Keymap for Thinkpad E580/T470 etc. 23 | */ 24 | 25 | #include "keymap.h" 26 | 27 | keytable_t kbtbl[] = { 28 | { 0, 1, 0, KEY_ESC }, 29 | { 7, 4, 0, KEY_F1 }, 30 | { 7, 3, 0, KEY_F2 }, 31 | { 1, 3, 0, KEY_F3 }, 32 | { 0, 3, 0, KEY_F4 }, 33 | { 0, 14, 0, KEY_F5 }, 34 | { 0, 8, 0, KEY_F6 }, 35 | { 1, 6, 0, KEY_F7 }, 36 | { 7, 6, 0, KEY_F8 }, 37 | { 7, 14, 0, KEY_F9 }, 38 | { 5, 14, 0, KEY_F10 }, 39 | { 5, 13, 0, KEY_F11 }, 40 | { 5, 11, 0, KEY_F12 }, 41 | { 7, 12, 0, KEY_HOME }, 42 | { 5, 12, 0, KEY_END }, 43 | { 7, 11, 0, KEY_INSERT }, 44 | { 7, 13, 0, KEY_DELETE }, 45 | 46 | { 7, 1, '~', KEY_GRAVE }, 47 | { 5, 1, '1', KEY_1 }, 48 | { 5, 4, '2', KEY_2 }, 49 | { 5, 3, '3', KEY_3 }, 50 | { 5, 5, '4', KEY_4 }, 51 | { 7, 5, '5', KEY_5 }, 52 | { 7, 2, '6', KEY_6 }, 53 | { 5, 2, '7', KEY_7 }, 54 | { 5, 8, '8', KEY_8 }, 55 | { 5, 6, '9', KEY_9 }, 56 | { 5, 7, '0', KEY_0 }, 57 | { 7, 7, '-', KEY_MINUS }, 58 | { 7, 8, '=', KEY_EQUAL }, 59 | { 1, 14, 0, KEY_BACKSPACE }, 60 | 61 | { 1, 1, 0, KEY_TAB }, 62 | { 6, 1, 'q', KEY_Q }, 63 | { 6, 4, 'w', KEY_W }, 64 | { 6, 3, 'e', KEY_E }, 65 | { 6, 5, 'r', KEY_R }, 66 | { 1, 5, 't', KEY_T }, 67 | { 1, 2, 'y', KEY_Y }, 68 | { 6, 2, 'u', KEY_U }, 69 | { 6, 8, 'i', KEY_I }, 70 | { 6, 6, 'o', KEY_O }, 71 | { 6, 7, 'p', KEY_P }, 72 | { 1, 7, '[', KEY_LEFTBRACE }, 73 | { 1, 8, ']', KEY_RIGHTBRACE }, 74 | { 4, 14, '\\', KEY_BACKSLASH }, 75 | 76 | { 1, 4, 0, KEY_CAPSLOCK }, 77 | { 4, 1, 'a', KEY_A }, 78 | { 4, 4, 's', KEY_S }, 79 | { 4, 3, 'd', KEY_D }, 80 | { 4, 5, 'f', KEY_F }, 81 | { 0, 5, 'g', KEY_G }, 82 | { 0, 2, 'h', KEY_H }, 83 | { 4, 2, 'j', KEY_J }, 84 | { 4, 8, 'k', KEY_K }, 85 | { 4, 6, 'l', KEY_L }, 86 | { 4, 7, ';', KEY_SEMICOLON }, 87 | { 0, 7, '\'', KEY_APOSTROPHE }, 88 | { 3, 14, 0, KEY_ENTER }, 89 | 90 | { 1, 0, 0, KEY_LEFTSHIFT }, 91 | { 3, 1, 'z', KEY_Z }, 92 | { 3, 4, 'x', KEY_X }, 93 | { 3, 3, 'c', KEY_C }, 94 | { 3, 5, 'v', KEY_V }, 95 | { 2, 5, 'b', KEY_B }, 96 | { 2, 2, 'n', KEY_N }, 97 | { 3, 2, 'm', KEY_M }, 98 | { 3, 8, ',', KEY_COMMA }, 99 | { 3, 6, '.', KEY_DOT }, 100 | { 2, 7, '/', KEY_SLASH }, 101 | { 3, 0, 0, KEY_RIGHTSHIFT }, 102 | 103 | // { 23, 24, 0, 0 }, // Fn key 104 | { 7, 9, 0, KEY_LEFTCTRL }, 105 | { 1, 11, 0, KEY_LEFTMETA }, // win key 106 | { 0, 10, 0, KEY_LEFTALT }, 107 | { 2, 14, ' ', KEY_SPACE }, 108 | { 2, 10, 0, KEY_RIGHTALT }, 109 | { 5, 10, 0, KEY_PRTSC }, 110 | { 3, 9, 0, KEY_RIGHTCTRL }, 111 | { 7, 15, 0, KEY_PAGEUP }, 112 | { 0, 12, 0, KEY_UP }, 113 | { 5, 15, 0, KEY_PAGEDOWN }, 114 | 115 | { 2, 12, 0, KEY_LEFT }, 116 | { 2, 13, 0, KEY_DOWN }, 117 | { 2, 11, 0, KEY_RIGHT }, 118 | 119 | { 1, 12, 0, KEY_MEDIA_CALC }, 120 | { 6, 12, '(', KEY_KPLEFTPAREN }, 121 | { 1, 15, ')', KEY_KPRIGHTPAREN }, 122 | { 6, 15, 0, KEY_BACKSPACE }, 123 | { 0, 16, 0, KEY_NUMLOCK }, 124 | { 1, 16, '/', KEY_KPSLASH }, 125 | { 6, 16, '*', KEY_KPASTERISK }, 126 | { 7, 16, '-', KEY_KPMINUS }, 127 | { 4, 16, '7', KEY_KP7 }, 128 | { 5, 16, '8', KEY_KP8 }, 129 | { 3, 16, '9', KEY_KP9 }, 130 | { 2, 16, '+', KEY_KPPLUS }, 131 | { 0, 17, '4', KEY_KP4 }, 132 | { 1, 17, '5', KEY_KP5 }, 133 | { 6, 17, '6', KEY_KP6 }, 134 | { 7, 17, '1', KEY_KP1 }, 135 | { 4, 17, '2', KEY_KP2 }, 136 | { 5, 17, '3', KEY_KP3 }, 137 | { 3, 17, 0, KEY_KPENTER }, 138 | { 2, 17, '0', KEY_KP0 }, 139 | { 6, 11, '.', KEY_KPDOT }, 140 | }; 141 | 142 | fn_keytable_t fntbl[] = { 143 | { 0, 1, 0, FN_FNLOCK }, 144 | { 7, 4, KEY_CONSUMER_MUTE, FN_NOP }, 145 | { 7, 3, KEY_CONSUMER_VOLUME_DECREMENT, FN_NOP }, 146 | { 1, 3, KEY_CONSUMER_VOLUME_INCREMENT, FN_NOP }, 147 | // { 0, 3, , 0 }, 148 | { 0, 14, KEY_CONSUMER_BRIGHTNESS_DECREMENT, FN_NOP }, 149 | { 0, 8, KEY_CONSUMER_BRIGHTNESS_INCREMENT, FN_NOP }, 150 | // { 1, 6, , 0 }, 151 | // { 7, 6, , 0 }, 152 | // { 7, 14, , 0 }, 153 | // { 5, 14, , 0 }, 154 | // { 5, 13, , 0 }, 155 | // { 5, 11, , 0 }, 156 | { 2, 14, 0, FN_BACKLIGHT }, 157 | }; 158 | -------------------------------------------------------------------------------- /main/keymap.c: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of esp32s3-keyboard. 3 | * 4 | * Copyright (C) 2020-2021 Yuquan He 5 | * (Institute of Computing Technology, Chinese Academy of Sciences) 6 | * 7 | * esp32s3-keyboard is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * esp32s3-keyboard is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with esp32s3-keyboard. If not, see . 19 | */ 20 | 21 | /** 22 | * Common part of keymap 23 | */ 24 | 25 | #include "keymap.h" 26 | 27 | #ifdef USE_KEYMAP_E530 28 | #include "keymap-e530.c" 29 | #elif defined (USE_KEYMAP_E580) 30 | #include "keymap-e580.c" 31 | #else 32 | #include "keymap-e580.c" 33 | #endif 34 | 35 | static const int nr_keys = sizeof(kbtbl) / sizeof(keytable_t); 36 | static const int nr_fn_keys = sizeof(fntbl) / sizeof(fn_keytable_t); 37 | 38 | int search_hid_key(unsigned scan1, unsigned scan2) 39 | { 40 | uint16_t cmbcode = scan1 | (scan2 << 8); 41 | int i; 42 | for (i = 0; i < nr_keys; i++) { 43 | uint16_t item = *(uint16_t*)(&kbtbl[i].scan1); 44 | if (item == cmbcode) { 45 | break; 46 | } 47 | } 48 | return i < nr_keys ? kbtbl[i].hidcode : -1; 49 | } 50 | 51 | fn_keytable_t* search_fn(unsigned scan1, unsigned scan2) 52 | { 53 | uint16_t cmbcode = scan1 | (scan2 << 8); 54 | int i; 55 | for (i = 0; i < nr_fn_keys; i++) { 56 | uint16_t item = *(uint16_t*)(&fntbl[i].scan1); 57 | if (item == cmbcode) { 58 | break; 59 | } 60 | } 61 | return i < nr_fn_keys ? &fntbl[i] : 0; 62 | } 63 | -------------------------------------------------------------------------------- /main/pin_cfg.h: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of esp32s3-keyboard. 3 | * 4 | * Copyright (C) 2020-2021 Yuquan He 5 | * (Institute of Computing Technology, Chinese Academy of Sciences) 6 | * 7 | * esp32s3-keyboard is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * esp32s3-keyboard is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with esp32s3-keyboard. If not, see . 19 | */ 20 | 21 | /** 22 | * Keyboard pin configuration 23 | */ 24 | #ifndef MY_PIN_CFG_H 25 | #define MY_PIN_CFG_H 26 | 27 | #include "sdkconfig.h" 28 | #include "driver/gpio.h" 29 | 30 | 31 | /**************************************************************** 32 | * 33 | * GPIO allocation 34 | * 35 | ****************************************************************/ 36 | 37 | // 8 column scan with 74HC138 38 | #define KB_COLSEL_0 4 39 | #define KB_COLSEL_1 5 40 | #define KB_COLSEL_2 6 41 | 42 | // 18 row scan 43 | #define KB_ROW_0 35 44 | #define KB_ROW_1 41 45 | #define KB_ROW_2 48 46 | #define KB_ROW_3 47 47 | #define KB_ROW_4 21 48 | #define KB_ROW_5 14 49 | #define KB_ROW_6 13 50 | #define KB_ROW_7 12 51 | #define KB_ROW_8 11 52 | #define KB_ROW_9 10 53 | #define KB_ROW_10 9 54 | #define KB_ROW_11 42 55 | #define KB_ROW_12 3 56 | #define KB_ROW_13 8 57 | #define KB_ROW_14 18 58 | #define KB_ROW_15 17 59 | #define KB_ROW_16 7 60 | #define KB_ROW_17 46 61 | 62 | // Buttons 63 | #define BUTTON_MIDDLE 0 64 | #define BUTTON_FN 36 65 | 66 | // LED 67 | #define LED_CAPLK 45 68 | #define LED_FNLK 43 69 | #define LED_F1 1 70 | #define LED_NUMLK 44 71 | #define BACKLIGHT_PWM 40 72 | // #define LED_F4 7 73 | 74 | // Trackpad GPIO 75 | #define PS2_CLK_PIN 39 76 | #define PS2_DATA_PIN 38 77 | #define PS2_RESET_PIN 37 78 | 79 | // USB charging detection 80 | #define CHARGING_PIN 2 81 | 82 | #define BUTTON_MIDDLE_STATE gpio_get_level(BUTTON_MIDDLE) 83 | #define BUTTON_FN_STATE gpio_get_level(BUTTON_FN) 84 | 85 | #define LED_CAPLK_ON gpio_set_level(LED_CAPLK, 0) 86 | #define LED_CAPLK_OFF gpio_set_level(LED_CAPLK, 1) 87 | #define LED_FNLK_ON gpio_set_level(LED_FNLK, 0) 88 | #define LED_FNLK_OFF gpio_set_level(LED_FNLK, 1) 89 | #define LED_F1_ON gpio_set_level(LED_F1, 0) 90 | #define LED_F1_OFF gpio_set_level(LED_F1, 1) 91 | #define LED_NUMLK_ON gpio_set_level(LED_NUMLK, 0) 92 | #define LED_NUMLK_OFF gpio_set_level(LED_NUMLK, 1) 93 | #define BACKLIGHT_ON gpio_set_level(BACKLIGHT_PWM, 1) 94 | #define BACKLIGHT_OFF gpio_set_level(BACKLIGHT_PWM, 0) 95 | // #define LED_F4_ON gpio_set_level(LED_F4, 0) 96 | // #define LED_F4_OFF gpio_set_level(LED_F4, 1) 97 | 98 | #define PS2_CLK_STATE gpio_get_level(PS2_CLK_PIN) 99 | #define PS2_CLK_OUTPUT gpio_set_direction(PS2_CLK_PIN, GPIO_MODE_OUTPUT) 100 | #define PS2_CLK_INPUT gpio_set_direction(PS2_CLK_PIN, GPIO_MODE_INPUT) 101 | #define PS2_CLK_LOW gpio_set_level(PS2_CLK_PIN, 0) 102 | #define PS2_CLK_HIGH gpio_set_level(PS2_CLK_PIN, 1) 103 | #define PS2_DATA_STATE gpio_get_level(PS2_DATA_PIN) 104 | #define PS2_DATA_OUTPUT gpio_set_direction(PS2_DATA_PIN, GPIO_MODE_OUTPUT) 105 | #define PS2_DATA_INPUT gpio_set_direction(PS2_DATA_PIN, GPIO_MODE_INPUT) 106 | #define PS2_DATA_LOW gpio_set_level(PS2_DATA_PIN, 0) 107 | #define PS2_DATA_HIGH gpio_set_level(PS2_DATA_PIN, 1) 108 | 109 | #define CHARGING_STATE gpio_get_level(CHARGING_PIN) 110 | 111 | /**************************************************************** 112 | * 113 | * Handy GPIO helpers 114 | * 115 | ****************************************************************/ 116 | 117 | #define GPIO_INIT_IN_FLOATING(pinnum) \ 118 | do { \ 119 | gpio_reset_pin(pinnum); \ 120 | gpio_set_direction(pinnum, GPIO_MODE_INPUT); \ 121 | gpio_pullup_dis(pinnum); \ 122 | gpio_pulldown_dis(pinnum); \ 123 | } while(0) 124 | 125 | #define GPIO_INIT_IN_PULLUP(pinnum) \ 126 | do { \ 127 | gpio_reset_pin(pinnum); \ 128 | gpio_set_direction(pinnum, GPIO_MODE_INPUT); \ 129 | gpio_pullup_en(pinnum); \ 130 | gpio_pulldown_dis(pinnum); \ 131 | } while(0) 132 | 133 | #define GPIO_INIT_IN_PULLDOWN(pinnum) \ 134 | do { \ 135 | gpio_reset_pin(pinnum); \ 136 | gpio_set_direction(pinnum, GPIO_MODE_INPUT); \ 137 | gpio_pullup_dis(pinnum); \ 138 | gpio_pulldown_en(pinnum); \ 139 | } while(0) 140 | 141 | #define GPIO_SET_PULLUP(pinnum) \ 142 | do { \ 143 | gpio_pullup_en(pinnum); \ 144 | gpio_pulldown_dis(pinnum); \ 145 | } while(0) 146 | 147 | #define GPIO_SET_PULLDOWN(pinnum) \ 148 | do { \ 149 | gpio_pullup_dis(pinnum); \ 150 | gpio_pulldown_en(pinnum); \ 151 | } while(0) 152 | 153 | #define GPIO_INIT_OUT_PULLUP(pinnum) \ 154 | do { \ 155 | gpio_reset_pin(pinnum); \ 156 | gpio_set_direction(pinnum, GPIO_MODE_OUTPUT); \ 157 | gpio_pullup_en(pinnum); \ 158 | } while(0) 159 | 160 | #define GPIO_INIT_OUT_PULLDOWN(pinnum) \ 161 | do { \ 162 | gpio_reset_pin(pinnum); \ 163 | gpio_set_direction(pinnum, GPIO_MODE_OUTPUT); \ 164 | gpio_pulldown_en(pinnum); \ 165 | } while(0) 166 | 167 | #endif 168 | -------------------------------------------------------------------------------- /sdkconfig.defaults: -------------------------------------------------------------------------------- 1 | CONFIG_BT_ENABLED=y 2 | CONFIG_BT_CTRL_MODEM_SLEEP=y 3 | CONFIG_BT_CTRL_LPCLK_SEL_EXT_32K_XTAL=y 4 | # CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set 5 | CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y 6 | CONFIG_ESP32S3_DEFAULT_CPU_FREQ_80=y 7 | CONFIG_ESP32S3_RTC_CLK_SRC_EXT_CRYS=y 8 | CONFIG_ESP32S3_RTC_CLK_CAL_CYCLES=576 9 | CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH=y 10 | CONFIG_PM_ENABLE=y 11 | # CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP is not set 12 | # CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP is not set 13 | CONFIG_FMB_TIMER_PORT_ENABLED=y 14 | CONFIG_FREERTOS_UNICORE=y 15 | CONFIG_FREERTOS_HZ=1000 16 | CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=2304 17 | CONFIG_FREERTOS_USE_TICKLESS_IDLE=y 18 | CONFIG_FREERTOS_IDLE_TIME_BEFORE_SLEEP=2 19 | # CONFIG_MBEDTLS_HARDWARE_AES is not set 20 | # CONFIG_MBEDTLS_HARDWARE_MPI is not set 21 | # CONFIG_MBEDTLS_HARDWARE_SHA is not set 22 | CONFIG_TINYUSB=y 23 | # CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID is not set 24 | CONFIG_TINYUSB_DESC_CUSTOM_VID=0x303a 25 | # CONFIG_TINYUSB_DESC_USE_DEFAULT_PID is not set 26 | CONFIG_TINYUSB_DESC_CUSTOM_PID=0xbeef 27 | CONFIG_TINYUSB_HID_ENABLED=y 28 | --------------------------------------------------------------------------------