├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── INSTALL.md ├── LICENSE ├── Makefile ├── README.md ├── cat.png ├── digits.sprite.png ├── digits.sprite.small.png ├── digits.svg ├── draft-UI.pdf ├── ir.png ├── ir_small.png ├── main ├── CMakeLists.txt ├── Kconfig.projbuild ├── ble │ ├── ble.c │ ├── ble.h │ ├── ble_hack.c │ └── ble_hack.h ├── component.mk ├── doh.h ├── img │ ├── ble_icons.c │ ├── ble_icons.h │ ├── ble_icons_8bpp.c │ ├── ble_icons_big.c │ ├── ble_icons_big.h │ ├── ble_icons_big_8bpp.c │ ├── bluetooth_icon.h │ ├── bluetooth_icon_8bpp.h │ ├── digits.c │ ├── digits.h │ ├── digits_8bpp.c │ ├── digits_small.c │ ├── digits_small.h │ ├── digits_small_8bpp.c │ ├── ir_icon.h │ ├── ir_icon_8bpp.h │ ├── ir_small.h │ ├── ir_small_8bpp.h │ ├── settings_icon.h │ ├── settings_icon_8bpp.h │ ├── skull.h │ ├── ticks.c │ ├── ticks.h │ ├── ticks_8bpp.c │ ├── wifi_icon.h │ └── wifi_icon_8bpp.h ├── main.c ├── menu.c ├── menu.h ├── sound │ ├── inc │ │ └── sound.h │ └── src │ │ ├── .sound.c.swp │ │ └── sound.c ├── ui │ ├── battery.c │ ├── battery.h │ ├── dateset.c │ ├── dateset.h │ ├── tile-apinfo.c │ ├── tile-apinfo.h │ ├── tile-bleinfo.c │ ├── tile-bleinfo.h │ ├── tile-blescan.c │ ├── tile-blescan.h │ ├── tile-channels.c │ ├── tile-channels.h │ ├── tile-clock.c │ ├── tile-clock.h │ ├── tile-deauth.c │ ├── tile-deauth.h │ ├── tile-rogueap.c │ ├── tile-rogueap.h │ ├── tile-scanner.c │ ├── tile-scanner.h │ ├── tile-settings.c │ ├── tile-settings.h │ ├── tile-tvbgone.c │ ├── tile-tvbgone.h │ ├── timeset.c │ └── timeset.h └── wifi │ ├── dissect.c │ ├── dissect.h │ ├── wifi.c │ ├── wifi.h │ ├── wifi_aplist.c │ ├── wifi_aplist.h │ ├── wifiscan.c │ └── wifiscan.h ├── resources ├── apple.xcf ├── ble-icons-big.png ├── ble-icons.png ├── ble-icons.svg ├── ble-icons.xcf ├── ble.xcf ├── cat.png ├── digits.png ├── digits.sprite.png ├── digits.sprite.small.png ├── digits.svg ├── digits.xcf ├── fitbit.xcf ├── heart.xcf ├── icon-ir.svg ├── ir.png ├── ir_small.png ├── keyfob.xcf ├── music.xcf ├── triangle.png ├── unknown.xcf ├── watch.xcf └── wifi.png ├── sdkconfig ├── triangle.png └── wifi.png /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "components/twatch-lib"] 2 | path = components/twatch-lib 3 | url = https://github.com/virtualabs/twatch-lib.git 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following lines of boilerplate have to be in your project's 2 | # CMakeLists 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(hackwatch) 7 | -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | 2 | # Hackwatch Installation 3 | 4 | ## Development framework 5 | 6 | Install the Espressif SDK: 7 | * Get Espressif's ESP-IDF framework (version 4.4.2) and install it (following the instructions at https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/) 8 | * In the installation of ESP-IDF, make sure you specify `-b v4.4.2` when cloning 9 | ``` 10 | mkdir -p ~/esp 11 | cd ~/esp 12 | git clone --recursive -b v4.4.2 https://github.com/espressif/esp-idf.git 13 | cd esp-idf/ 14 | ./install.sh esp32 15 | . ./export.sh 16 | idf.py --version 17 | ``` 18 | * Verify the output, it should be 4.4.2 19 | 20 | ## Hackwatch projet 21 | 22 | Clone the hackwatch project from github: 23 | 24 | cd ~/esp/ 25 | git clone --recurse-submodules https://github.com/virtualabs/hackwatch 26 | cd hackwatch 27 | 28 | Customize feature and select T-Watch 2020 version: 29 | * `idf.py menuconfig` 30 | * To decide what feature (Wifi, BLE and/or IR): 31 | * Choose `HackWatch menu` 32 | * To select your T-Watch version: 33 | * Choose `Component config` 34 | * Go at the very bottom and pick `T-Watch Lib` 35 | * Select `Target T-Watch version` to choose between `T-Watch 2020 v1`, `v2` or `v3` 36 | * (S)ave and quit 37 | 38 | ## Compile 39 | 40 | To compile the project 41 | 42 | idf.py build 43 | 44 | ## Flash 45 | 46 | Start the watch then connect it in USB to the computer. 47 | 48 | To flash the code execute this command: 49 | 50 | idf.py -p flash 51 | 52 | ## Debugging the firmware (monitor mode) 53 | 54 | To monitor the execution: 55 | 56 | idf.py -p monitor 57 | 58 | 59 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2021, Damien "virtualabs" Cauquil 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files 4 | (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, 5 | publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do 6 | so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 9 | 10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 11 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 12 | FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 13 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | 15 | 16 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a 3 | # project subdirectory. 4 | # 5 | 6 | PROJECT_NAME := app-template 7 | 8 | include $(IDF_PATH)/make/project.mk 9 | 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | The HackWatch - a T-Watch 2020 firmware for WiFi and BLE hackers 2 | ================================================================ 3 | 4 | What about having a versatile WiFi/BLe hacking tool on your wrist ? Imagine this: you 5 | walk into a room/building/premise/whatever and use your watch to scan/detect nearby WiFi networks, 6 | BLE devices, and get information about them. Maybe you would also be able to try one or two 7 | attacks that may be implemented into this firmware :). 8 | 9 | What's this T-Watch 2020 ? 10 | -------------------------- 11 | 12 | The T-Watch 2020 is an ESP32-based smartwatch for developper by Lilygo. 13 | 14 | T-Watch 2020 v1 has: 15 | * a capacitive touch screen (240x240 pixels) 16 | * a 3-axis accelerometer 17 | * a speaker 18 | * a basic vibration motor 19 | * a battery (of course) 20 | * an IR LED (well, could be useful) 21 | * an embedded real-time clock (obviously, it's a watch !) 22 | 23 | T-Watch 2020 v2 is a bit diferent: 24 | * remove Max98357a I2S amplifier 25 | * add DVR2605L haptic vibration contoler 26 | * add L76K GPS 27 | * add TF Card Holder 28 | 29 | T-Watch 2020 v3 is very similar to v1 but add: 30 | * PDM microphone 31 | 32 | 33 | How to build this project 34 | ------------------------- 35 | 36 | See [INSTALL](INSTALL.md). 37 | 38 | 39 | How to use it 40 | ------------- 41 | 42 | Once flashed, the watch will restart and display the current time and date. Swipe left or right to browse the 43 | main categories, swipe up on a category screen to access the different tools/screens available. Basically, 44 | categories/tools navigation is done by swiping the screen :). 45 | 46 | Pressing the button on the right side of the watch will bring you back to the current category and then to 47 | the main screen. If this button is pressed when on the main screen (clock), the watch will go in deep sleep 48 | mode and can be wake up by pressing the button again. 49 | 50 | Provided tools 51 | -------------- 52 | 53 | ### WiFi 54 | 55 | This smartwatch provides a real-time WiFi network scanner, a WiFi channel scanner, a rogue AP generator and 56 | a WiFi deauth tool. 57 | 58 | The WiFi Scanner shows a list of available wireless access points, along with their RSSI levels and MAC 59 | addresses. Information about security and channel can be displayed when an access point is selected. 60 | 61 | The WiFi channel scanner simply loops on every possible channel and shows the *activity*. It could be useful 62 | to find less noisy channels when setting up a WiFi network. 63 | 64 | The WiFi Rogue AP generator provides a way to spoof a specific WiFi access point (previously selected) in 65 | order to force stations to connect to it instead of the legitimate access point. Security is set to open by 66 | default, and no IP will be provided on connection (no DHCP server started, and no web server). 67 | 68 | The WiFi Deauth tool allows you to automatically disconnect every connected station from a given WiFi 69 | network. This is quite similar to other projects like [ESP32 WiFi Penetration tool](https://github.com/risinek/esp32-wifi-penetration-tool) or [ESP32 Deauther](https://github.com/GANESH-ICMC/esp32-deauther). 70 | 71 | ### Bluetooth Low Energy 72 | 73 | The smartwatch includes a BLE scanner that performs fingerprinting of detected devices and classifying 74 | them in various categories (watch, health device, audio, etc.). It also provides a dedicated feature 75 | to retrieve the Bluetooth Low Energy baseband vendor and software version (using BLE LL_VERSION_IND PDU). 76 | 77 | ### Infrared 78 | 79 | A TV-B-Gone feature has been added to the watch. It can be started from the Infrared tool, and kept active 80 | while the watch still remains on its main screen (stealth mode :D). -------------------------------------------------------------------------------- /cat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/cat.png -------------------------------------------------------------------------------- /digits.sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/digits.sprite.png -------------------------------------------------------------------------------- /digits.sprite.small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/digits.sprite.small.png -------------------------------------------------------------------------------- /draft-UI.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/draft-UI.pdf -------------------------------------------------------------------------------- /ir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/ir.png -------------------------------------------------------------------------------- /ir_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/ir_small.png -------------------------------------------------------------------------------- /main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Edit following two lines to set component requirements (see docs) 2 | set(COMPONENT_REQUIRES twatch-lib) 3 | set(COMPONENT_PRIV_REQUIRES nvs_flash bt) 4 | 5 | set( 6 | COMPONENT_SRCS 7 | "main.c" 8 | "menu.c" 9 | "img/digits_8bpp.c" 10 | "img/digits_small_8bpp.c" 11 | "img/ticks_8bpp.c" 12 | "ui/tile-clock.c" 13 | "ui/tile-settings.c" 14 | "ui/timeset.c" 15 | "ui/dateset.c" 16 | "ui/battery.c" 17 | ) 18 | 19 | if (CONFIG_INCLUDE_IR) 20 | list(APPEND COMPONENT_SRCS 21 | "ui/tile-tvbgone.c" 22 | ) 23 | endif() 24 | 25 | if (CONFIG_INCLUDE_BLE) 26 | list(APPEND COMPONENT_SRCS 27 | "ble/ble.c" 28 | "ble/ble_hack.c" 29 | "img/ble_icons_8bpp.c" 30 | "img/ble_icons_big_8bpp.c" 31 | "ui/tile-blescan.c" 32 | "ui/tile-bleinfo.c" 33 | ) 34 | endif() 35 | 36 | if (CONFIG_INCLUDE_WIFI) 37 | list(APPEND COMPONENT_SRCS 38 | "wifi/wifi.c" 39 | "wifi/wifi_aplist.c" 40 | "wifi/wifiscan.c" 41 | "wifi/dissect.c" 42 | ) 43 | 44 | if (CONFIG_WIFI_SCANNER) 45 | list( APPEND COMPONENT_SRCS 46 | "ui/tile-scanner.c" 47 | "ui/tile-apinfo.c" 48 | ) 49 | endif() 50 | 51 | if (CONFIG_WIFI_CHANNELS) 52 | list( APPEND COMPONENT_SRCS "ui/tile-channels.c") 53 | endif() 54 | 55 | if (CONFIG_WIFI_ROGUEAP) 56 | list( APPEND COMPONENT_SRCS "ui/tile-rogueap.c") 57 | endif() 58 | 59 | if (CONFIG_WIFI_DEAUTH) 60 | list( APPEND COMPONENT_SRCS "ui/tile-deauth.c") 61 | endif() 62 | endif() 63 | 64 | 65 | register_component() 66 | -------------------------------------------------------------------------------- /main/Kconfig.projbuild: -------------------------------------------------------------------------------- 1 | menu "HackWatch" 2 | config INCLUDE_WIFI 3 | bool "Include WiFi tools" 4 | default y 5 | 6 | config WIFI_SCANNER 7 | depends on INCLUDE_WIFI 8 | bool "WiFi scanner" 9 | default y 10 | 11 | config WIFI_CHANNELS 12 | depends on INCLUDE_WIFI 13 | bool "WiFi channels scanner" 14 | default y 15 | 16 | config WIFI_ROGUEAP 17 | depends on INCLUDE_WIFI 18 | bool "Rogue AP generator" 19 | default y 20 | 21 | config WIFI_DEAUTH 22 | depends on INCLUDE_WIFI 23 | bool "Deauth" 24 | default y 25 | 26 | config INCLUDE_BLE 27 | bool "Include Bluetooth Low Energy tools" 28 | default y 29 | 30 | config BLE_SCANNER 31 | depends on INCLUDE_BLE 32 | bool "Bluetooth Low Energy scanner" 33 | default y 34 | 35 | config INCLUDE_IR 36 | bool "Infrared tools" 37 | default y 38 | endmenu 39 | -------------------------------------------------------------------------------- /main/ble/ble.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_BLE_H 2 | #define __INC_BLE_H 3 | 4 | #define BLESCAN_DEVICES_MAX 10 5 | 6 | #include "esp_log.h" 7 | #include "nvs_flash.h" 8 | 9 | /* BLE */ 10 | #include "esp_nimble_hci.h" 11 | #include "esp_event.h" 12 | #include "esp_err.h" 13 | #include "nimble/nimble_port.h" 14 | #include "nimble/nimble_port_freertos.h" 15 | #include "host/ble_hs.h" 16 | #include "host/util/util.h" 17 | #include "console/console.h" 18 | #include "services/gap/ble_svc_gap.h" 19 | 20 | 21 | #define BLE_DEVICE_NAME_MAXSIZE 32 22 | #define BLE_FRESHNESS_DEFAULT 50 23 | #define BLE_CTRL_EVENT "BLECTRL" 24 | #define BLE_DEVICE_FOUND 0x0000 25 | #define BLE_DEVICE_VERSION 0x0001 26 | #define BLE_DEVICE_DISCONNECTED 0x0002 27 | 28 | typedef struct { 29 | uint16_t id; 30 | char *psz_name; 31 | char *psz_short_name; 32 | } ble_company_id_t; 33 | 34 | typedef enum { 35 | BLE_OFF, 36 | BLE_IDLE, 37 | BLE_SCANNER, 38 | BLE_FINGERPRINT 39 | } ble_controller_mode_t; 40 | 41 | typedef enum { 42 | UNKNOWN, 43 | PHONE, 44 | APPLE, 45 | FITBIT, 46 | SMARTLOCK, 47 | KEYFOB, 48 | HEARTBEAT, 49 | SMARTWATCH, 50 | SOUND 51 | } ble_device_type_t; 52 | 53 | typedef struct { 54 | uint8_t record_type; 55 | uint8_t *pattern; 56 | uint8_t pattern_size; 57 | } ble_device_fp_pattern_t; 58 | 59 | typedef struct { 60 | ble_device_type_t device_type; 61 | ble_device_fp_pattern_t *patterns; 62 | } ble_device_fingerprint_t; 63 | 64 | typedef struct tBleDevice { 65 | 66 | /* Device type. */ 67 | ble_device_type_t device_type; 68 | 69 | /* Device Bluetooth address. */ 70 | ble_addr_t address; 71 | 72 | /* Device name. */ 73 | char psz_name[BLE_DEVICE_NAME_MAXSIZE]; 74 | 75 | /* Device rssi. */ 76 | uint8_t i8_rssi; 77 | 78 | /* Freshness. */ 79 | uint8_t freshness; 80 | 81 | } ble_device_t; 82 | 83 | typedef struct tBleDeviceVersion { 84 | uint8_t ble; 85 | uint16_t company; 86 | uint16_t software; 87 | } ble_device_version_t; 88 | 89 | typedef struct tBleController { 90 | 91 | /* Controller mode. */ 92 | ble_controller_mode_t mode; 93 | 94 | /* Custom event loop. */ 95 | bool evt_loop_initialized; 96 | esp_event_loop_args_t evt_loop_args; 97 | esp_event_loop_handle_t evt_loop_handle; 98 | 99 | /* Mutex */ 100 | SemaphoreHandle_t mutex; 101 | 102 | /* Connection control. */ 103 | uint16_t conn_handle; 104 | bool b_connected; 105 | 106 | /* Version info. */ 107 | uint8_t version_ble; 108 | uint16_t version_compid; 109 | uint16_t version_soft; 110 | 111 | } ble_controller_t; 112 | 113 | /* Helpers. */ 114 | char *ble_get_version_str(int version); 115 | ble_company_id_t *ble_get_company_info(uint16_t comp_id); 116 | 117 | /* Initialisation. */ 118 | void ble_ctrl_init(void); 119 | int ble_scan_start(void); 120 | int ble_scan_active(void); 121 | int ble_scan_stop(void); 122 | 123 | int ble_connect(ble_device_t *device); 124 | int ble_disconnect(void); 125 | 126 | int ble_get_devices_nb(void); 127 | ble_device_t *ble_get_device(int index); 128 | esp_err_t ble_ctrl_event_handler_register( 129 | int32_t event_id, 130 | esp_event_handler_t event_handler, 131 | void* event_handler_arg 132 | ); 133 | 134 | uint8_t ble_device_get_version(void); 135 | uint16_t ble_device_get_compid(void); 136 | uint16_t ble_device_get_soft(void); 137 | 138 | esp_err_t ble_enter_critical_section(void); 139 | void ble_leave_critical_section(void); 140 | 141 | #endif /* __INC_BLE_H */ -------------------------------------------------------------------------------- /main/ble/ble_hack.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_ESP32_BLE_HACK_H 2 | #define __INC_ESP32_BLE_HACK_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "freertos/FreeRTOS.h" 9 | #include "freertos/task.h" 10 | #include "esp_system.h" 11 | 12 | /* Enable this if you want more verbose messages. */ 13 | //#define BLE_HACK_DEBUG 0 14 | 15 | #define LLC_LLCP_SEND_ADDR (0x40043ed4) 16 | #define LLC_LLCP_TESTER_SEND_ADDR (0x400445e4) 17 | #define LLC_ENV_ADDR (0x3ffb96d0) 18 | #define IP_FUNCS_ARRAY_ADDR (0x3ffae70c) 19 | #define BLE_RX_BUFFER_ADDR (0x3ffb0000) 20 | #define BLE_RX_PKT_STATUS (0x3ffb094a) 21 | #define BLE_RX_PKT_HDR_ADDR (0x3ffb094c) 22 | #define BLE_RX_CUR_FIFO_ADDR (0x3ffb8d74) 23 | #define BLE_RX_DESC_ADDR (0x3ffb0950) 24 | 25 | #define HOOK_FORWARD 0x1 26 | #define HOOK_BLOCK 0x0 27 | 28 | /* ROM hooking helpers. */ 29 | #define HOOKTYPE(x) F_r_##x 30 | #define HOOKFUNCPTR(x) pfn_##x 31 | #define ROM_HOOK(func, args...) typedef int (*HOOKTYPE(func))(args); \ 32 | HOOKTYPE(func) pfn_##func = NULL; 33 | 34 | #define INSTALL_HOOK(id, func) HOOKFUNCPTR(func)=(void *)(((uint32_t *)g_ip_funcs_p)[id]); \ 35 | printf("Hooking function id %d, replacing 0x%08x by 0x%08x\r\n", id, ((uint32_t *)g_ip_funcs_p)[id], (uint32_t)_##func); \ 36 | ((uint32_t *)g_ip_funcs_p)[id]=(uint32_t)_##func; 37 | 38 | typedef enum { 39 | LL_CONNECTION_UPDATE_REQ, 40 | LL_CHANNEL_MAP_REQ, 41 | LL_TERMINATE_IND, 42 | LL_ENC_REQ, 43 | LL_ENC_RSP, 44 | LL_START_ENC_REQ, 45 | LL_START_ENC_RSP, 46 | LL_UNKNOWN_RSP, 47 | LL_FEATURE_REQ, 48 | LL_FEATURE_RSP, 49 | LL_PAUSE_ENC_REQ, 50 | LL_PAUSE_ENC_RSP, 51 | LL_VERSION_IND, 52 | LL_REJECT_IND, 53 | LL_SLAVE_FEATURE_REQ, 54 | LL_CONNECTION_PARAM_REQ, 55 | LL_CONNECTION_PARAM_RSP, 56 | LL_REJECT_IND_EXT, 57 | LL_PING_REQ, 58 | LL_PING_RSP, 59 | LL_LENGTH_REQ, 60 | LL_LENGTH_RSP, 61 | LL_TESTER_SEND=0xFF 62 | } llcp_pdu_type; 63 | 64 | /** 65 | * Common list header structure (required by co_list* functions). 66 | **/ 67 | 68 | struct co_list_hdr 69 | { 70 | /// Pointer to next co_list_hdr 71 | struct co_list_hdr *next; 72 | }; 73 | 74 | /** 75 | * Common list structure 76 | **/ 77 | 78 | struct co_list 79 | { 80 | /// pointer to first element of the list 81 | struct co_list_hdr *first; 82 | /// pointer to the last element 83 | struct co_list_hdr *last; 84 | 85 | /// number of element in the list 86 | uint32_t cnt; 87 | /// max number of element in the list 88 | uint32_t maxcnt; 89 | /// min number of element in the list 90 | uint32_t mincnt; 91 | }; 92 | 93 | /** 94 | * Event Arbiter Element 95 | **/ 96 | 97 | struct ea_elt_tag 98 | { 99 | /// List element for chaining in the Even Arbiter lists 100 | struct co_list_hdr hdr; 101 | 102 | /// Pointer on the next element linked to the current action 103 | struct ea_elt_tag *linked_element; 104 | 105 | /// Programming time in basetime (CLOCKN) absolute value 106 | uint32_t timestamp; 107 | 108 | /** 109 | * ASAP field contains the type and the limit 110 | * bit |31 30| 29 |28 27|26 ...................... 0| 111 | * def | TYPE | Parity | RFU | LIMIT (absolute time) | 112 | * 113 | * Type: 114 | * - 00: No ASAP 115 | * - 01: ASAP no limit 116 | * - 10: ASAP with limit 117 | * 118 | * Parity (only for ASAP requests): 119 | * - 0: even slots 120 | * - 1: odd slots 121 | * 122 | * Limit (only for ASAP LIMIT requests): 123 | * - Absolute value in slots 124 | * - The reservation can not cross over this limit 125 | */ 126 | uint32_t asap_field; 127 | 128 | /// Minimum duration of the event or frame (in slots) 129 | uint16_t duration_min; 130 | 131 | /// Current priority 132 | uint8_t current_prio; 133 | /// Threshold1 for prevent stop 134 | uint8_t prev_stop_thr1; 135 | /// Threshold2 for prevent stop 136 | uint8_t prev_stop_thr2; 137 | /// Threshold for prevent start 138 | uint8_t prev_start_thr; 139 | 140 | /************************************************************************************ 141 | * ISR CALLBACKS 142 | ************************************************************************************/ 143 | 144 | /// Start event or frame call back function 145 | void (*ea_cb_prevent_start)(struct ea_elt_tag*); 146 | /// Prevent stop call back function 147 | void (*ea_cb_prevent_stop)(struct ea_elt_tag*); 148 | /// event or frame canceling call back function 149 | void (*ea_cb_cancel)(struct ea_elt_tag*); 150 | 151 | /// BT/BLE Specific environment variable 152 | void *env; 153 | }; 154 | 155 | 156 | /** 157 | * Synchronization counters 158 | **/ 159 | 160 | struct lld_evt_anchor 161 | { 162 | /// Base time counter value of the latest found sync 163 | uint32_t basetime_cnt; 164 | /// Fine time counter value of the latest found sync 165 | uint16_t finetime_cnt; 166 | /// Event counter of the of the latest found sync 167 | uint16_t evt_cnt; 168 | }; 169 | 170 | /** 171 | * Non connected event information 172 | **/ 173 | 174 | struct lld_non_conn 175 | { 176 | /// Scan Window Size 177 | uint32_t window; 178 | /// Anchor timestamp 179 | uint32_t anchor; 180 | /// Event end time stamp 181 | uint32_t end_ts; 182 | /// use to know if it's an initiate procedure 183 | bool initiate; 184 | /// use to know if connect request has been sent 185 | bool connect_req_sent; 186 | }; 187 | 188 | /** 189 | * Connected event information 190 | **/ 191 | 192 | struct lld_conn 193 | { 194 | /// Synchronization Window Size (in us) 195 | uint32_t sync_win_size; 196 | /// SCA Drift (in us) 197 | uint32_t sca_drift; 198 | /// Instant of the next action (in events) 199 | uint16_t instant; 200 | /// Latency 201 | uint16_t latency; 202 | /// Event counter 203 | uint16_t counter; 204 | /// Number of connection events missed since last anchor point 205 | uint16_t missed_cnt; 206 | /// Minimum duration of the event or frame (in slots) 207 | uint16_t duration_dft; 208 | /// Update offset 209 | uint16_t update_offset; 210 | /// Effective maximum tx time 211 | uint16_t eff_max_tx_time; 212 | /// Effective maximum tx size 213 | uint16_t eff_max_tx_size; 214 | /// Update window size 215 | uint8_t update_size; 216 | /// Describe the action to be done when instant occurs 217 | uint8_t instant_action; 218 | /// Master sleep clock accuracy 219 | uint8_t mst_sca; 220 | /// value of the latest More Data bit received 221 | uint8_t last_md_rx; 222 | /// TX programmed packet counter 223 | uint8_t tx_prog_pkt_cnt; 224 | /// Default RX windows offset 225 | uint8_t rx_win_off_dft; 226 | /// Default RX windows path delay compensation 227 | uint8_t rx_win_pathdly_comp; 228 | #if (BLE_2MBPS) 229 | /// TX phy to be programmed 230 | uint8_t tx_phy; 231 | /// RX phy to be programmed 232 | uint8_t rx_phy; 233 | #endif // (BLE_2MBPS) 234 | /// Wait for a sync due to a connection update 235 | bool wait_con_up_sync; 236 | 237 | uint32_t win_size_backup; //us 238 | }; 239 | 240 | 241 | /** 242 | * Event Arbiter interval structure 243 | **/ 244 | 245 | struct ea_interval_tag 246 | { 247 | /// List element for chaining in the Interval list 248 | struct co_list_hdr hdr; 249 | /// Interval used 250 | uint16_t interval_used; 251 | /// Offset used 252 | uint16_t offset_used; 253 | /// Bandwidth used 254 | uint16_t bandwidth_used; 255 | /// Connection handle used 256 | uint16_t conhdl_used; 257 | /// Role used 258 | uint16_t role_used; 259 | /// Odd offset or even offset 260 | bool odd_offset; 261 | /// Link id 262 | uint16_t linkid; 263 | }; 264 | 265 | 266 | /** 267 | * Link-layer Controller PDU tag structure 268 | * 269 | * This structure is used to send Control PDU. 270 | **/ 271 | 272 | struct llcp_pdu_tag 273 | { 274 | /// List element for chaining 275 | struct co_list_hdr hdr; 276 | /// Node index 277 | uint32_t idx; 278 | /// Pointer on the pdu to send 279 | void *ptr; 280 | uint16_t pdu_length; 281 | /// opcode 282 | uint8_t opcode; 283 | }; 284 | 285 | /** 286 | * Link-layer Driver main structure (contains everything about LLD) 287 | **/ 288 | 289 | struct lld_evt_tag 290 | { 291 | /// Information about the latest found synchronization 292 | struct lld_evt_anchor anchor_point; 293 | 294 | /// List of TX Data descriptors ready for transmission (i.e. not yet chained with the CS) 295 | struct co_list tx_acl_rdy; 296 | /// List of TX Data descriptors ready to be freed (i.e. already chained in the CS) 297 | struct co_list tx_acl_tofree; 298 | /// List of TX LLCP descriptors ready for transmission (i.e. not yet chained with the CS) 299 | struct co_list tx_llcp_pdu_rdy; 300 | /// List of TX LLCP descriptors programmed for transmission (i.e. chained with the CS) 301 | struct co_list tx_prog; 302 | 303 | /// Interval element pointer linked to this event 304 | struct ea_interval_tag* interval_elt; 305 | 306 | /// event information for connected and non-connected activity 307 | union lld_evt_info 308 | { 309 | /// Non connected event information 310 | struct lld_non_conn non_conn; 311 | 312 | /// Connected event information 313 | struct lld_conn conn; 314 | } evt; 315 | 316 | /// Connection Handle 317 | uint16_t conhdl; 318 | /// Control structure pointer address 319 | uint16_t cs_ptr; 320 | /// Connection Interval 321 | uint16_t interval; 322 | /// Number of RX Descriptors already handled in the event 323 | uint8_t rx_cnt; 324 | /// Mode of the link (Master connect, slave connect, ...) 325 | uint8_t mode; 326 | /// TX Power 327 | uint8_t tx_pwr; 328 | /// Default priority 329 | uint8_t default_prio; 330 | 331 | /// Internal status 332 | uint8_t evt_flag; 333 | 334 | /// Flag delete on going 335 | bool delete_ongoing; 336 | }; 337 | 338 | 339 | /** 340 | * EM buffer node. 341 | * 342 | * Used for communication with ESP32 BLE peripheral (SoC). 343 | **/ 344 | 345 | struct em_buf_node 346 | { 347 | struct co_list_hdr hdr; 348 | /// Index of the buffer 349 | uint16_t idx; 350 | /// EM buffer pointer 351 | uint16_t buf_ptr; 352 | }; 353 | 354 | /** 355 | * HCI data TX PDU structure 356 | * 357 | * This structure is used by the BLE controller to send Data PDU. 358 | **/ 359 | 360 | struct hci_acl_data_tx 361 | { 362 | /// connection handle 363 | uint16_t conhdl; 364 | /// broadcast and packet boundary flag 365 | uint16_t pb_bc_flag; 366 | /// length of the data 367 | uint16_t length; 368 | struct em_buf_node *buf; 369 | }; 370 | 371 | /** 372 | * Internal structure used to store incoming packet info. 373 | **/ 374 | 375 | typedef struct { 376 | uint32_t header; 377 | uint32_t a; 378 | uint32_t b; 379 | } pkt_hdr_t; 380 | 381 | /** 382 | * EM TX node descriptor. 383 | * 384 | * This structure stores information about a TX PDU. 385 | **/ 386 | 387 | struct em_buf_tx_desc 388 | { 389 | /// tx pointer 390 | uint16_t txptr; 391 | /// tx header 392 | uint16_t txheader; 393 | /// tx data pointer 394 | uint16_t txdataptr; 395 | /// tx data length extension info 396 | uint16_t txdle; 397 | }; 398 | 399 | 400 | /** 401 | * EM descriptor node 402 | * 403 | * A descriptor stores information about a TX node (em_buf_node) and some metadata. 404 | **/ 405 | 406 | struct em_desc_node 407 | { 408 | struct co_list_hdr hdr; 409 | /// Index of the buffer 410 | uint16_t idx; 411 | /// EM Pointer of the buffer 412 | uint16_t buffer_idx; 413 | /// Buffer index 414 | uint16_t buffer_ptr; 415 | /// Logical Link Identifier 416 | uint8_t llid; 417 | /// Data length 418 | uint8_t length; 419 | }; 420 | 421 | /** 422 | * EM main structure. 423 | **/ 424 | 425 | struct em_buf_env_tag 426 | { 427 | /// List of free TX descriptors 428 | struct co_list tx_desc_free; 429 | /// List of free TX buffers 430 | struct co_list tx_buff_free; 431 | /// Array of TX descriptors (SW tag) 432 | struct em_desc_node tx_desc_node[0x71]; 433 | /// Array of TX buffer (SW tag) 434 | struct em_buf_node tx_buff_node[10]; 435 | /// Pointer to TX descriptors 436 | struct em_buf_tx_desc *tx_desc; 437 | /// Index of the current RX buffer 438 | uint8_t rx_current; 439 | }; 440 | 441 | 442 | /** 443 | * Link-layer control procedures PDU details. 444 | **/ 445 | 446 | typedef struct { 447 | llcp_pdu_type opcode; 448 | uint16_t conhdl; 449 | } llcp_opinfo; 450 | 451 | typedef struct { 452 | llcp_opinfo header; 453 | } llcp_version_params; 454 | 455 | typedef struct { 456 | llcp_opinfo header; 457 | } llcp_ch_map_update_params; 458 | 459 | typedef struct { 460 | llcp_opinfo header; 461 | } llcp_pause_enc_req_params; 462 | 463 | typedef struct { 464 | llcp_opinfo header; 465 | } llcp_pause_enc_rsp_params; 466 | 467 | typedef struct { 468 | llcp_opinfo header; 469 | uint16_t rej_opcode; 470 | uint8_t reason; 471 | } llcp_reject_params; 472 | 473 | typedef struct { 474 | llcp_opinfo header; 475 | struct hci_le_start_enc_cmd *param; 476 | } llcp_enc_req_params; 477 | 478 | typedef struct { 479 | llcp_opinfo header; 480 | struct llcp_enc_req *param; 481 | } llcp_enc_rsp_params; 482 | 483 | typedef struct { 484 | llcp_opinfo header; 485 | } llcp_start_enc_rsp_params; 486 | 487 | typedef struct { 488 | llcp_opinfo header; 489 | struct llcp_con_upd_ind *param; 490 | } llcp_con_update_params; 491 | 492 | typedef struct { 493 | llcp_opinfo header; 494 | struct llc_con_upd_req_ind *param; 495 | } llcp_con_param_req_params; 496 | 497 | typedef struct { 498 | llcp_opinfo header; 499 | struct llc_con_upd_req_ind *param; 500 | } llcp_con_param_rsp_params; 501 | 502 | typedef struct { 503 | llcp_opinfo header; 504 | } llcp_feats_req_params; 505 | 506 | typedef struct { 507 | llcp_opinfo header; 508 | } llcp_feats_rsp_params; 509 | 510 | typedef struct { 511 | llcp_opinfo header; 512 | } llcp_start_enc_params; 513 | 514 | typedef struct { 515 | llcp_opinfo header; 516 | uint8_t err_code; 517 | } llcp_terminate_params; 518 | 519 | typedef struct { 520 | llcp_opinfo header; 521 | uint8_t unk_type; 522 | } llcp_unknown_rsp_params; 523 | 524 | typedef struct { 525 | llcp_opinfo header; 526 | } llcp_ping_req_params; 527 | 528 | typedef struct { 529 | llcp_opinfo header; 530 | } llcp_ping_rsp_params; 531 | 532 | typedef struct { 533 | llcp_opinfo header; 534 | } llcp_length_req_params; 535 | 536 | typedef struct { 537 | llcp_opinfo header; 538 | } llcp_length_rsp_params; 539 | 540 | typedef struct { 541 | llcp_opinfo header; 542 | uint8_t length; 543 | uint8_t *data; 544 | } llcp_tester_send_params; 545 | 546 | typedef int (*FBLEHACK_IsrCallback)(uint16_t header, uint8_t *p_pdu, int length); 547 | typedef int (*FBLEHACK_CtlCallback)(llcp_opinfo *p_llcp_pdu); 548 | typedef int (*F_rom_llc_llcp_send)(int conhdl, uint8_t *p_pdu, uint8_t opcode); 549 | 550 | /* Printf() equivalent required to display debug info when in ISR (callbacks). */ 551 | int esp_rom_printf( const char *restrict format, ... ); 552 | 553 | /* Install hooks. */ 554 | void ble_hack_install_hooks(void); 555 | void disconnect_nimble(void); 556 | 557 | void ble_hack_rx_control_pdu_handler(FBLEHACK_IsrCallback pfn_control_callback); 558 | void ble_hack_rx_data_pdu_handler(FBLEHACK_IsrCallback pfn_data_callback); 559 | void ble_hack_tx_control_pdu_handler(FBLEHACK_CtlCallback pfn_control_callback); 560 | void ble_hack_tx_data_pdu_handler(FBLEHACK_IsrCallback pfn_data_callback); 561 | 562 | /* Send a data PDU. */ 563 | void send_data_pdu(int conhdl, void *p_pdu, int length); 564 | void send_raw_data_pdu(int conhdl, uint8_t llid, void *p_pdu, int length, bool can_be_freed); 565 | 566 | /* Send a control PDU. */ 567 | void send_control_pdu(int conhdl, uint8_t *p_pdu, int length); 568 | int rom_llc_llcp_send(int conhdl, uint8_t *p_pdu, uint8_t opcode); 569 | 570 | void _llc_llcp_version_ind_pdu_send(uint16_t conhdl); 571 | void _llc_llcp_terminate_ind_pdu_send(uint16_t conhdl, uint8_t err_code); 572 | 573 | #endif /* __INC_ESP32_BLE_HACK_H */ -------------------------------------------------------------------------------- /main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Main component makefile. 3 | # 4 | # This Makefile can be left empty. By default, it will take the sources in the 5 | # src/ directory, compile them and link them into lib(subdirectory_name).a 6 | # in the build directory. This behaviour is entirely configurable, 7 | # please read the ESP-IDF documents if you need to do this. 8 | # 9 | -------------------------------------------------------------------------------- /main/img/ble_icons.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_BLE_ICONS_H 2 | #define __INC_BLE_ICONS_H 3 | #include "twatch.h" 4 | 5 | __attribute__ ((aligned(4))) 6 | extern const uint8_t ble_icons[]; 7 | 8 | #endif /* __INC_BLE_ICONS_H */ 9 | 10 | -------------------------------------------------------------------------------- /main/img/ble_icons_8bpp.c: -------------------------------------------------------------------------------- 1 | #include "twatch.h" 2 | 3 | __attribute__ ((aligned(4))) 4 | const uint8_t ble_icons[]={ 5 | 144, 0, 16, 0, 1, 0, 6 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x31, 0x20, 0x10, 0x00, 0x00, 0x31, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x20, 0x00, 0x31, 0x00, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x00, 0x31, 0x31, 0x00, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x31, 0x31, 0x31, 0x20, 0x10, 0x31, 0x31, 0x31, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x20, 0x31, 0x00, 0x00, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x00, 0x31, 0x31, 0x00, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x00, 0x31, 0x31, 0x00, 0x31, 0x31, 0x00, 0x31, 0x31, 0x00, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x00, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x00, 0x31, 0x31, 0x00, 0x31, 0x31, 0x00, 0x31, 0x31, 0x00, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x10, 0x31, 0x00, 0x00, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x31, 0x31, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x31, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x00, 0x31, 0x31, 0x00, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x31, 0x31, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x20, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x00, 0x31, 0x31, 0x00, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x31, 0x31, 0x31, 0x31, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x20, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x31, 0x31, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x00, 0x31, 0x31, 0x31, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x31, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 7 | }; 8 | -------------------------------------------------------------------------------- /main/img/ble_icons_big.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_BLE_ICONS_BIG_H 2 | #define __INC_BLE_ICONS_BIG_H 3 | #include "twatch.h" 4 | 5 | __attribute__ ((aligned(4))) 6 | extern const uint8_t ble_icons_big[]; 7 | 8 | #endif /* __INC_BLE_ICONS_BIG_H */ 9 | 10 | -------------------------------------------------------------------------------- /main/img/digits.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_DIGITS_H 2 | #define __INC_DIGITS_H 3 | 4 | #include "twatch.h" 5 | 6 | __attribute__ ((aligned(4))) 7 | extern const uint8_t digits_img[]; 8 | 9 | #endif /* __INC_DIGITS_H */ -------------------------------------------------------------------------------- /main/img/digits_small.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_DIGITS_SMALL_H 2 | #define __INC_DIGITS_SMALL_H 3 | #include "twatch.h" 4 | 5 | __attribute__ ((aligned(4))) 6 | extern const uint8_t digits_small_img[]; 7 | 8 | #endif /* __INC_DIGITS_SMALL_H */ 9 | 10 | -------------------------------------------------------------------------------- /main/img/ir_small.h: -------------------------------------------------------------------------------- 1 | const uint16_t ir_icon_small[]={ 2 | 23, 18, 1, 3 | 0x0a36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0a36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0b36, 0x0c47, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0e48, 0x0a36, 0x0e48, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0311, 0x0000, 0x0000, 0x0825, 0x0f59, 0x0f59, 0x0f59, 0x0c47, 0x0000, 0x0000, 0x0000, 0x0d48, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0c47, 0x0000, 0x0000, 0x0000, 0x0201, 0x0f59, 0x0f59, 0x0f59, 0x0624, 0x0000, 0x0000, 0x0000, 0x0724, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0e48, 0x0000, 0x0000, 0x0000, 0x0412, 0x0f59, 0x0f59, 0x0f59, 0x0935, 0x0000, 0x0000, 0x0000, 0x0a36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0a36, 0x0312, 0x0513, 0x0e48, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0724, 0x0312, 0x0824, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0a36, 0x0513, 0x0311, 0x0201, 0x0312, 0x0623, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0825, 0x0100, 0x0100, 0x0623, 0x0825, 0x0935, 0x0825, 0x0513, 0x0000, 0x0101, 0x0935, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0d48, 0x0201, 0x0100, 0x0935, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0824, 0x0000, 0x0312, 0x0d48, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0312, 0x0412, 0x0e48, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0e48, 0x0412, 0x0312, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0835, 0x0e48, 0x0e48, 0x0e48, 0x0e48, 0x0e48, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0e48, 0x0e48, 0x0e48, 0x0e48, 0x0e48, 0x0825, 0x0000, 0x0000, 0x0000, 0x0000, 0x0724, 0x0d47, 0x0f59, 0x0d48, 0x0a36, 0x0824, 0x0623, 0x0513, 0x0623, 0x0724, 0x0a36, 0x0d48, 0x0f59, 0x0d48, 0x0724, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0623, 0x0d48, 0x0724, 0x0201, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0201, 0x0724, 0x0d48, 0x0623, 0x0000, 0x0000, 0x0000 4 | }; 5 | -------------------------------------------------------------------------------- /main/img/ir_small_8bpp.h: -------------------------------------------------------------------------------- 1 | const uint8_t ir_icon_small[]={ 2 | 23, 0, 18, 0, 1, 0, 3 | 0x21, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x35, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x21, 0x36, 0x36, 0x36, 0x35, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x35, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x11, 0x00, 0x00, 0x00, 0x11, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x10, 0x36, 0x36, 0x36, 0x21, 0x00, 0x00, 0x00, 0x21, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x00, 0x10, 0x36, 0x36, 0x36, 0x36, 0x36, 0x11, 0x00, 0x21, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x10, 0x00, 0x00, 0x00, 0x10, 0x21, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x00, 0x00, 0x10, 0x21, 0x21, 0x21, 0x10, 0x00, 0x00, 0x21, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x21, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x10, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x10, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x21, 0x00, 0x00, 0x00, 0x00, 0x11, 0x35, 0x36, 0x36, 0x21, 0x21, 0x10, 0x10, 0x10, 0x11, 0x21, 0x36, 0x36, 0x36, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x36, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x36, 0x10, 0x00, 0x00, 0x00 4 | }; -------------------------------------------------------------------------------- /main/img/skull.h: -------------------------------------------------------------------------------- 1 | const uint8_t skull_raw[]={ 2 | 120, 0, 120, 0, 0, 0, 3 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xc0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0xe0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x0f, 0x00, 0x00, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x1f, 0x00, 0x00, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x1f, 0x00, 0x00, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x1f, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x1f, 0x00, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00, 0xfc, 0xff, 0x3f, 0x00, 0x00, 0xe0, 0xff, 0x1f, 0x00, 0xc0, 0xff, 0xff, 0x03, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x03, 0x00, 0xe0, 0xff, 0x1f, 0x00, 0xe0, 0xff, 0xff, 0x03, 0x80, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xe0, 0xff, 0x1f, 0x00, 0xe0, 0xff, 0xff, 0x03, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xe0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x07, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x9f, 0xff, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0x1f, 0xe0, 0xff, 0xff, 0x0f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xe0, 0xff, 0xff, 0x0f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf1, 0xff, 0xff, 0x0f, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xf3, 0xff, 0xff, 0x0f, 0xc0, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x80, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x0f, 0x00, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0xfc, 0x1f, 0x00, 0xfc, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0xfc, 0x1f, 0x00, 0xfc, 0x03, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x1f, 0x00, 0xfe, 0x07, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0xfe, 0x07, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0xff, 0x07, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0xff, 0x07, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0xff, 0x07, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0xff, 0x07, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0xff, 0x07, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0xff, 0x03, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xf0, 0x3f, 0x80, 0xff, 0x03, 0x80, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xe0, 0x0f, 0x80, 0xff, 0x01, 0x80, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x80, 0x0f, 0x80, 0xff, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0xe0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0xe0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x01, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x03, 0x00, 0xe0, 0x07, 0x00, 0x80, 0xff, 0xff, 0xf8, 0x01, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x01, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0xe0, 0xff, 0xfb, 0xff, 0xff, 0x7f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0xe0, 0xff, 0xf0, 0xff, 0xff, 0x7f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xfc, 0x01, 0x00, 0x00, 0xe0, 0x3f, 0xc0, 0xff, 0xff, 0x7f, 0x00, 0xe0, 0xff, 0xff, 0x7f, 0xf8, 0x81, 0x8f, 0x1f, 0xfc, 0x1f, 0x00, 0xff, 0xff, 0x7f, 0x00, 0xf0, 0xff, 0xff, 0x3f, 0xf8, 0x81, 0x8f, 0x3f, 0xfc, 0x07, 0x00, 0xfc, 0xff, 0x7f, 0x00, 0xf0, 0xff, 0xff, 0x1f, 0xf8, 0x81, 0x9f, 0x3f, 0xfc, 0x00, 0x00, 0xf8, 0xff, 0x1f, 0x00, 0xf0, 0xff, 0xff, 0x1f, 0xf8, 0x81, 0x9f, 0x3f, 0xfc, 0x00, 0x00, 0xf0, 0xff, 0x03, 0x00, 0xf0, 0xff, 0xff, 0x07, 0xf8, 0x81, 0x9f, 0x3f, 0xfc, 0x00, 0x00, 0xf0, 0xff, 0x03, 0x00, 0xf0, 0xff, 0xff, 0x07, 0xf0, 0x81, 0x9f, 0x3f, 0xfc, 0x00, 0x00, 0xf0, 0xff, 0x03, 0x00, 0xf0, 0xff, 0xff, 0x03, 0xf0, 0x83, 0x1f, 0x7e, 0xfc, 0x00, 0x00, 0xf0, 0xff, 0x03, 0x00, 0xf0, 0xff, 0xff, 0x07, 0xf0, 0x03, 0x1f, 0x7e, 0xfc, 0x00, 0x00, 0xf0, 0xff, 0x03, 0x00, 0xe0, 0xff, 0xff, 0x07, 0xf0, 0x03, 0x3f, 0x7e, 0xfc, 0x01, 0x00, 0xe0, 0xff, 0x03, 0x00, 0xc0, 0xff, 0xff, 0x07, 0xf0, 0x03, 0x3f, 0x7e, 0xfc, 0x01, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x07, 0xf0, 0x03, 0x3f, 0x7e, 0xf8, 0x01, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x07, 0xe0, 0x03, 0x3f, 0x7c, 0xf8, 0x01, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x07, 0xe0, 0x07, 0x3f, 0x7c, 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x07, 0xe0, 0x07, 0x3f, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x03, 0xe0, 0x07, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0x07, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x01, 0xe0, 0x07, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7f, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0xc0, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xfe, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 4 | }; 5 | -------------------------------------------------------------------------------- /main/img/ticks.c: -------------------------------------------------------------------------------- 1 | #include "twatch.h" 2 | 3 | __attribute__ ((aligned(4))) 4 | const uint16_t ticks_img[]={ 5 | 26, 26, 1, 6 | 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0c37, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0c37, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0c37, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0c37, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0c37, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0c37, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0c37, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0c37, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0c37, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0c37, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0c37, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0c37, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0c37, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0b36, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0b36, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0b36, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0b36, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0b36, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0b36, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0b36, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0b36, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0b36, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0b36, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0f59, 0x0f59, 0x0b36, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0f59, 0x0f59, 0x0b36, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0b36, 0x0b36, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 7 | }; 8 | -------------------------------------------------------------------------------- /main/img/ticks.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_TICKS_H 2 | #define __INC_TICKS_H 3 | 4 | #include "twatch.h" 5 | 6 | __attribute__ ((aligned(4))) 7 | extern const uint8_t ticks_img[]; 8 | 9 | #endif /* __INC_TICKS_H */ -------------------------------------------------------------------------------- /main/img/ticks_8bpp.c: -------------------------------------------------------------------------------- 1 | #include "twatch.h" 2 | 3 | __attribute__ ((aligned(4))) 4 | const uint8_t ticks_img[]={ 5 | 26, 0, 26, 0, 1, 6 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 54, 54, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 54, 54, 54, 54, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 54, 54, 54, 54, 54, 54, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 54, 54, 54, 54, 54, 54, 54, 54, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 49, 0, 0, 0, 0, 0, 0, 0, 33, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 49, 0, 0, 0, 0, 0, 33, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 49, 0, 0, 0, 33, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 49, 0, 33, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 49, 33, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 33, 0, 33, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 33, 0, 0, 0, 33, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 33, 0, 0, 0, 0, 0, 33, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 33, 0, 0, 0, 0, 0, 0, 0, 33, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 54, 54, 54, 54, 54, 54, 54, 54, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 54, 54, 54, 54, 54, 54, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 54, 54, 54, 54, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 54, 54, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 7 | }; -------------------------------------------------------------------------------- /main/main.c: -------------------------------------------------------------------------------- 1 | #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG 2 | 3 | #include 4 | #include 5 | #include "freertos/FreeRTOS.h" 6 | #include "freertos/task.h" 7 | 8 | #include "menu.h" 9 | #include "twatch.h" 10 | #include "hal/hal.h" 11 | #include "ui/tile-scanner.h" 12 | #include "ui/tile-blescan.h" 13 | #include "ui/tile-apinfo.h" 14 | #include "ui/tile-clock.h" 15 | #include "ui/tile-settings.h" 16 | #include "ui/tile-channels.h" 17 | #include "ui/tile-rogueap.h" 18 | #include "ui/tile-deauth.h" 19 | #include "ui/tile-tvbgone.h" 20 | 21 | /* Include WiFi icon if needed. */ 22 | #ifdef CONFIG_INCLUDE_WIFI 23 | #include "img/wifi_icon_8bpp.h" 24 | #endif 25 | 26 | /* Include WiFi icon if needed. */ 27 | #ifdef CONFIG_INCLUDE_BLE 28 | #include "ble/ble.h" 29 | #include "img/bluetooth_icon_8bpp.h" 30 | #endif 31 | 32 | 33 | /* Include IR icon if needed. */ 34 | #ifdef CONFIG_INCLUDE_IR 35 | #include "img/ir_icon_8bpp.h" 36 | #endif 37 | 38 | #include "img/settings_icon_8bpp.h" 39 | 40 | 41 | void main_ui(void *parameter) 42 | { 43 | tile_t main_tile; 44 | tile_t settings_tile /*, bluetooth_tile*/; 45 | 46 | tile_t *p_tile_first, *p_tile_current; /* main menu */ 47 | tile_t *p_sub_first, *p_sub_current; /* submenu */ 48 | 49 | tile_t *p_settings_one_tile, *p_settings_two_tile, *p_settings_three_tile; 50 | image_t *settings; 51 | 52 | widget_image_t settings_img; 53 | widget_label_t settings_lbl; 54 | widget_label_t label_main; 55 | 56 | #ifdef CONFIG_INCLUDE_WIFI 57 | tile_t wifi_tile; 58 | image_t *wifi; 59 | widget_image_t wifi_img; 60 | widget_label_t wifi_lbl; 61 | #endif /* CONFIG_INCLUDE_WIFI */ 62 | 63 | #ifdef CONFIG_INCLUDE_BLE 64 | tile_t bluetooth_tile; 65 | image_t *bluetooth; 66 | widget_image_t bluetooth_img; 67 | widget_label_t bluetooth_lbl; 68 | #endif /* CONFIG_INCLUDE_BLE */ 69 | 70 | 71 | #ifdef CONFIG_INCLUDE_IR 72 | tile_t ir_tile; 73 | image_t *ir; 74 | widget_image_t ir_img; 75 | widget_label_t ir_lbl; 76 | #endif 77 | 78 | /* Main screen */ 79 | tile_init(&main_tile, NULL); 80 | widget_label_init(&label_main, &main_tile, 80, 110, 220, 45, "Main tile"); 81 | 82 | p_settings_one_tile = tile_settings_one_init(); 83 | p_settings_two_tile = tile_settings_two_init(); 84 | p_settings_three_tile = tile_settings_three_init(); 85 | 86 | /* Main circular "menu" */ 87 | p_tile_first = NULL; 88 | p_tile_current = NULL; 89 | 90 | /* Add clock tile (mandatory). */ 91 | p_tile_current = menu_add_menu(p_tile_current, tile_clock_init()); 92 | p_tile_first = p_tile_current; 93 | 94 | /* Add Bluetooth Low Energy screen (if enabled). */ 95 | #ifdef CONFIG_INCLUDE_BLE 96 | tile_init(&bluetooth_tile, NULL); 97 | bluetooth = load_image(bluetooth_icon); 98 | widget_image_init(&bluetooth_img, &bluetooth_tile, 80, (240-88)/2 - 20, 88, 88, bluetooth); 99 | widget_label_init(&bluetooth_lbl, &bluetooth_tile, 60, 150, 120, 50, "Bluetooth"); 100 | p_tile_current = menu_add_menu(p_tile_current, &bluetooth_tile); 101 | #endif /* CONFIG_INCLUDE_BLE */ 102 | 103 | /* Add WiFi menu (if enabled). */ 104 | #ifdef CONFIG_INCLUDE_WIFI 105 | /* WiFi screen */ 106 | tile_init(&wifi_tile, NULL); 107 | wifi = load_image(wifi_icon); 108 | widget_image_init(&wifi_img, &wifi_tile, 70, (240-88)/2 - 20, 100, 88, wifi); 109 | widget_label_init(&wifi_lbl, &wifi_tile, 90, 150, 120, 50, "WiFi"); 110 | p_tile_current = menu_add_menu(p_tile_current, &wifi_tile); 111 | #endif 112 | 113 | /* Add IR menu (if enabled). */ 114 | #ifdef CONFIG_INCLUDE_IR 115 | /* Add IR menu. */ 116 | tile_init(&ir_tile, NULL); 117 | ir = load_image(ir_icon); 118 | widget_image_init(&ir_img, &ir_tile, 70, (240-88)/2 - 20, 100, 88, ir); 119 | widget_label_init(&ir_lbl, &ir_tile, 100, 150, 120, 50, "IR"); 120 | p_tile_current = menu_add_menu(p_tile_current, &ir_tile); 121 | #endif 122 | 123 | /* Add Settings menu. */ 124 | tile_init(&settings_tile, NULL); 125 | settings = load_image(settings_icon); 126 | widget_image_init(&settings_img, &settings_tile, 80, (240-88)/2 - 20, 88, 88, settings); 127 | widget_label_init(&settings_lbl, &settings_tile, 70, 150, 120, 50, "Settings"); 128 | p_tile_current = menu_add_menu(p_tile_current, &settings_tile); 129 | 130 | /* Loop on first tile. */ 131 | tile_link_right(p_tile_current, p_tile_first); 132 | 133 | #ifdef CONFIG_INCLUDE_BLE 134 | /* BLE "submenu" */ 135 | p_sub_first = NULL; 136 | p_sub_current = NULL; 137 | 138 | p_sub_current = menu_add_tile(&bluetooth_tile, p_sub_current, tile_blescan_init); 139 | printf("created tile blescan: 0x%08x\n", (uint32_t)p_sub_current); 140 | printf("(ble)p_sub_current: 0x%08x\n", (uint32_t)p_sub_current); 141 | if (p_sub_first == NULL) 142 | p_sub_first = p_sub_current; 143 | printf("(ble)p_sub_first: 0x%08x\n", (uint32_t)p_sub_first); 144 | 145 | if (p_sub_current != p_sub_first) 146 | { 147 | tile_link_right(p_sub_current, p_sub_first); 148 | printf("(ble) link right: current=0x%08x right=0x%08x\n", (uint32_t)p_sub_current, (uint32_t)p_sub_first); 149 | } 150 | tile_link_bottom(&bluetooth_tile, p_sub_first); 151 | printf("(ble) link bottom: tile=0x%08x bottom=0x%08x\n", (uint32_t)&bluetooth_tile, (uint32_t)p_sub_first); 152 | #endif 153 | 154 | #ifdef CONFIG_INCLUDE_WIFI 155 | /* Wifi "submenu" */ 156 | p_sub_first = NULL; 157 | p_sub_current = NULL; 158 | 159 | #ifdef CONFIG_WIFI_SCANNER 160 | p_sub_current = menu_add_tile(&wifi_tile, p_sub_current, tile_scanner_init); 161 | if (p_sub_first == NULL) 162 | p_sub_first = p_sub_current; 163 | #endif 164 | 165 | #ifdef CONFIG_WIFI_CHANNELS 166 | p_sub_current = menu_add_tile(&wifi_tile, p_sub_current, tile_channels_init); 167 | if (p_sub_first == NULL) 168 | p_sub_first = p_sub_current; 169 | #endif 170 | 171 | #ifdef CONFIG_WIFI_ROGUEAP 172 | p_sub_current = menu_add_tile(&wifi_tile, p_sub_current, tile_rogueap_init); 173 | if (p_sub_first == NULL) 174 | p_sub_first = p_sub_current; 175 | #endif 176 | 177 | #ifdef CONFIG_WIFI_DEAUTH 178 | p_sub_current = menu_add_tile(&wifi_tile, p_sub_current, tile_deauth_init); 179 | if (p_sub_first == NULL) 180 | p_sub_first = p_sub_current; 181 | #endif 182 | 183 | if (p_sub_current != p_sub_first) 184 | tile_link_right(p_sub_current, p_sub_first); 185 | tile_link_bottom(&wifi_tile, p_sub_first); 186 | #endif 187 | 188 | 189 | #ifdef CONFIG_INCLUDE_IR 190 | /* IR "submenu" */ 191 | tile_link_bottom(&ir_tile, tile_tvbgone_init()); 192 | #endif 193 | 194 | /* Settings "submenu" */ 195 | tile_link_bottom(&settings_tile, p_settings_three_tile); 196 | tile_link_bottom(&settings_tile, p_settings_two_tile); 197 | tile_link_bottom(&settings_tile, p_settings_one_tile); 198 | tile_link_right(p_settings_one_tile, p_settings_two_tile); 199 | tile_link_right(p_settings_two_tile, p_settings_three_tile); 200 | tile_link_right(p_settings_three_tile, p_settings_one_tile); 201 | 202 | /* Select our main tile. */ 203 | ui_select_tile(p_tile_first); 204 | 205 | /* Introspect tile structure */ 206 | tile_t *p_top, *p_sec_top; 207 | tile_t *p_first_level; 208 | p_top = p_first_level = p_tile_first; 209 | tile_t *p_sec_level = NULL; 210 | while (p_first_level != NULL) 211 | { 212 | printf("Top menu tile: 0x%08x\n", (uint32_t)p_first_level); 213 | if (p_first_level->p_bottom != NULL) 214 | { 215 | p_sec_top = p_sec_level = p_first_level->p_bottom; 216 | while (p_sec_level != NULL) 217 | { 218 | printf(" - Sub menu tile: 0x%08x\n", (uint32_t)p_sec_level); 219 | /* Next tile */ 220 | p_sec_level = p_sec_level->p_right; 221 | if (p_sec_level == p_sec_top) 222 | break; 223 | } 224 | } 225 | 226 | /* Next tile */ 227 | p_first_level = p_first_level->p_right; 228 | if (p_first_level == p_top) 229 | break; 230 | } 231 | 232 | /* Enable eco mode. */ 233 | enable_ecomode(); 234 | 235 | while (1) 236 | { 237 | ui_process_events(); 238 | vTaskDelay(1); 239 | } 240 | } 241 | 242 | /** 243 | * HackWatch main application routine. 244 | **/ 245 | 246 | void app_main(void) 247 | { 248 | esp_log_level_set("*", ESP_LOG_DEBUG); 249 | 250 | /* Init HAL. */ 251 | twatch_hal_init(); 252 | 253 | ui_init(); 254 | 255 | #ifdef CONFIG_INCLUDE_WIFI 256 | /* Initialize WiFi controller. */ 257 | wifi_ctrl_init(); 258 | #endif 259 | 260 | #ifdef CONFIG_INCLUDE_BLE 261 | /* Initialize BLE controller. */ 262 | ble_ctrl_init(); 263 | #endif 264 | 265 | /* Start UI in a dedicated task. */ 266 | xTaskCreate(main_ui, "main_ui", 15000, NULL, 1, NULL); 267 | } 268 | -------------------------------------------------------------------------------- /main/menu.c: -------------------------------------------------------------------------------- 1 | #include "menu.h" 2 | 3 | tile_t *menu_add_menu(tile_t *p_tile_prev, tile_t *p_tile) 4 | { 5 | /* Link this tile to the previous one (if any). */ 6 | if (p_tile_prev != NULL) 7 | tile_link_right(p_tile_prev, p_tile); 8 | 9 | return p_tile; 10 | } 11 | 12 | tile_t *menu_add_tile(tile_t *p_menu_tile, tile_t *p_tile_prev, Ftile_init pfn_tile_init) 13 | { 14 | tile_t *p_tile = pfn_tile_init(); 15 | tile_link_bottom(p_menu_tile, p_tile); 16 | 17 | /* Link this tile to the previous one (if any). */ 18 | if (p_tile_prev != NULL) 19 | tile_link_right(p_tile_prev, p_tile); 20 | 21 | return p_tile; 22 | } 23 | -------------------------------------------------------------------------------- /main/menu.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_MENU_H 2 | #define __INC_MENU_H 3 | 4 | #include "twatch.h" 5 | 6 | typedef tile_t* (*Ftile_init)(void); 7 | 8 | tile_t *menu_add_menu(tile_t *p_tile_prev, tile_t *p_tile); 9 | tile_t *menu_add_tile(tile_t *p_menu_tile, tile_t *p_tile_prev, Ftile_init pfn_tile_init); 10 | 11 | #endif /* __INC_MENU_H */ -------------------------------------------------------------------------------- /main/sound/inc/sound.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_SOUND_H 2 | #define __INC_SOUND_H 3 | 4 | #include 5 | #include "freertos/FreeRTOS.h" 6 | #include "driver/i2s.h" 7 | #include "driver/gpio.h" 8 | #include "esp_system.h" 9 | 10 | 11 | #define SOUND_OK 1 12 | #define SOUND_ERR 0 13 | #define DEFAULT_I2S_PORT 0 14 | 15 | typedef struct t_sound_system { 16 | i2s_config_t ss_config; 17 | i2s_pin_config_t ss_pin_config; 18 | int sample_rate; 19 | int port; 20 | } sound_system_t; 21 | 22 | /* Initialize 16-bit sound system. */ 23 | int sound_init(sound_system_t *p_sound_system, int sample_rate); 24 | 25 | /* Send samples to sound system. */ 26 | int sound_send_samples(sound_system_t *p_sound_system, void *samples, size_t samples_size, size_t *p_bytes_written, TickType_t ticks_to_wait); 27 | 28 | /* Deinitialize 16-bit sound system. */ 29 | int sound_deinit(sound_system_t *p_sound_system); 30 | 31 | 32 | #endif /* __INC_SOUND_H */ 33 | -------------------------------------------------------------------------------- /main/sound/src/.sound.c.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/main/sound/src/.sound.c.swp -------------------------------------------------------------------------------- /main/sound/src/sound.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "freertos/FreeRTOS.h" 4 | #include "driver/i2s.h" 5 | #include "driver/gpio.h" 6 | #include "esp_system.h" 7 | #include "esp_log.h" 8 | 9 | #include "sound.h" 10 | 11 | int sound_init(sound_system_t *p_sound_system, int sample_rate) 12 | { 13 | esp_err_t err; 14 | 15 | /* Sanity check. */ 16 | if (p_sound_system == NULL) 17 | return SOUND_ERR; 18 | 19 | /* Reset sound system structure. */ 20 | memset(p_sound_system, 0, sizeof(sound_system_t)); 21 | 22 | /** 23 | * Initialize the sound system. 24 | **/ 25 | 26 | p_sound_system->port = DEFAULT_I2S_PORT; 27 | p_sound_system->sample_rate = sample_rate; 28 | 29 | /* Initialize ESP32 I2S config. */ 30 | p_sound_system->ss_config.mode = I2S_MODE_MASTER | I2S_MODE_TX; 31 | p_sound_system->ss_config.sample_rate = sample_rate; 32 | p_sound_system->ss_config.bits_per_sample = 16; 33 | p_sound_system->ss_config.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT; 34 | p_sound_system->ss_config.communication_format = I2S_COMM_FORMAT_STAND_MSB; 35 | 36 | /* Use ESP_INTR_FLAG_LEVEL2, as ESP_INTR_FLAG_LEVEL1 is already used. */ 37 | p_sound_system->ss_config.intr_alloc_flags = ESP_INTR_FLAG_LEVEL2; 38 | p_sound_system->ss_config.dma_buf_count = 6; 39 | p_sound_system->ss_config.dma_buf_len = 60; 40 | p_sound_system->ss_config.use_apll = false; 41 | 42 | /* Initialize ESP32 pin config. */ 43 | p_sound_system->ss_pin_config.bck_io_num = 26; 44 | p_sound_system->ss_pin_config.ws_io_num = 25; 45 | p_sound_system->ss_pin_config.data_out_num = 33; 46 | //p_sound_system->ss_pin_config.data_in_num = -1; 47 | 48 | /* Install I2S driver. */ 49 | err = i2s_driver_install( 50 | p_sound_system->port, 51 | &p_sound_system->ss_config, 52 | 0, 53 | NULL 54 | ); 55 | if (err != ESP_OK) 56 | { 57 | /* Error while installing I2S driver. */ 58 | ESP_LOGE("sound_system", "cannot install i2s driver: %d\r\n", err); 59 | return SOUND_ERR; 60 | } 61 | 62 | err = i2s_set_pin(p_sound_system->port, &p_sound_system->ss_pin_config); 63 | if (err != ESP_OK) 64 | { 65 | /* Error while setting pins. */ 66 | ESP_LOGE("sound_system", "setting i2s pins failed: %d\r\n", err); 67 | return SOUND_ERR; 68 | } 69 | 70 | /* Success. */ 71 | return SOUND_OK; 72 | } 73 | 74 | int sound_send_samples(sound_system_t *p_sound_system, void *samples, size_t samples_size, size_t *p_bytes_written, TickType_t ticks_to_wait) 75 | { 76 | esp_err_t err; 77 | err = i2s_write( 78 | p_sound_system->port, 79 | samples, 80 | samples_size, 81 | p_bytes_written, 82 | ticks_to_wait 83 | ); 84 | 85 | return (err == ESP_OK)?SOUND_OK:SOUND_ERR; 86 | } 87 | 88 | int sound_deinit(sound_system_t *p_sound_system) 89 | { 90 | esp_err_t err; 91 | 92 | if (p_sound_system != NULL) 93 | { 94 | err = i2s_driver_uninstall(p_sound_system->port); 95 | if (err != ESP_OK) 96 | { 97 | /* Error, cannot uninstall driver. */ 98 | ESP_LOGE("sound_system", "cannot uninstall driver: %d\r\n", err); 99 | return SOUND_ERR; 100 | } 101 | 102 | /* Success. */ 103 | return SOUND_OK; 104 | } 105 | else 106 | return SOUND_ERR; 107 | } 108 | -------------------------------------------------------------------------------- /main/ui/battery.c: -------------------------------------------------------------------------------- 1 | #include "battery.h" 2 | #include "hal/pmu.h" 3 | 4 | /** 5 | * widget_battery_drawfunc() 6 | * 7 | * @brief: render function for battery widget 8 | * @param p_widget: pointer to a `widget_t` structure 9 | **/ 10 | 11 | int widget_battery_drawfunc(widget_t *p_widget) 12 | { 13 | widget_batt_t *p_battery = (widget_batt_t *)p_widget->p_user_data; 14 | 15 | if (p_battery != NULL) 16 | { 17 | /* Read battery level each 50 iterations. */ 18 | if (p_battery->delay < 50) 19 | p_battery->delay++; 20 | else 21 | { 22 | p_battery->percentage = twatch_pmu_get_battery_level(); 23 | p_battery->delay = 0; 24 | } 25 | 26 | widget_draw_line( 27 | p_widget, 28 | 1, 0, BATTERY_WIDTH, 0, RGB(0xe, 0xe, 0xe) 29 | ); 30 | widget_draw_line( 31 | p_widget, 32 | 1, BATTERY_HEIGHT-1, BATTERY_WIDTH, BATTERY_HEIGHT-1, RGB(0xe, 0xe, 0xe) 33 | ); 34 | widget_draw_line( 35 | p_widget, 36 | 0, 1, 0, BATTERY_HEIGHT - 2, RGB(0xe, 0xe, 0xe) 37 | ); 38 | widget_draw_line( 39 | p_widget, 40 | BATTERY_WIDTH, 1, BATTERY_WIDTH, BATTERY_HEIGHT-2, RGB(0xe, 0xe, 0xe) 41 | ); 42 | widget_draw_line( 43 | p_widget, 44 | BATTERY_WIDTH+1, BATTERY_HEIGHT/2 - 2, BATTERY_WIDTH+1, BATTERY_HEIGHT/2+2, RGB(0xe, 0xe, 0xe) 45 | ); 46 | widget_draw_line( 47 | p_widget, 48 | BATTERY_WIDTH+2, BATTERY_HEIGHT/2 - 2, BATTERY_WIDTH+2, BATTERY_HEIGHT/2+2, RGB(0xe, 0xe, 0xe) 49 | ); 50 | widget_fill_region( 51 | p_widget, 52 | 1, 53 | 1, 54 | ((BATTERY_WIDTH-1)*p_battery->percentage)/100, 55 | BATTERY_HEIGHT-2, 56 | twatch_pmu_is_usb_plugged(false)?RGB(0x1, 0x2, 0x3):RGB(0xe,0xe,0xe) 57 | ); 58 | } 59 | return 0; 60 | } 61 | 62 | 63 | 64 | /** 65 | * widget_battery_init() 66 | * 67 | * @brief: Initialize a battery widget 68 | * @param p_battery: pointer to a `widget_batt_t` structure 69 | * @param p_tile: pointer to a `tile_t` structure 70 | * @param x: widget X coordinate 71 | * @param y: widget Y coordinate 72 | **/ 73 | 74 | void widget_battery_init(widget_batt_t *p_battery, tile_t *p_tile, int x, int y) 75 | { 76 | /* Initialize widget. */ 77 | widget_init(&p_battery->widget, p_tile, x, y, BATTERY_WIDTH+3, BATTERY_HEIGHT+2); 78 | 79 | /* Read battery level. */ 80 | p_battery->percentage = twatch_pmu_get_battery_level(); 81 | 82 | /* Check if we are charging. */ 83 | p_battery->b_usb_connected = twatch_pmu_is_usb_plugged(true); 84 | 85 | p_battery->delay = 0; 86 | 87 | /* Set user data. */ 88 | widget_set_userdata(&p_battery->widget, (void *)p_battery); 89 | 90 | /* Define our drawing function. */ 91 | widget_set_drawfunc(&p_battery->widget, (FDrawWidget)widget_battery_drawfunc); 92 | } -------------------------------------------------------------------------------- /main/ui/battery.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_BATTERY_H 2 | #define __INC_BATTERY_H 3 | 4 | #include "ui/ui.h" 5 | #include "ui/widget.h" 6 | 7 | #define BATTERY_WIDTH 30 8 | #define BATTERY_HEIGHT 18 9 | 10 | typedef struct { 11 | widget_t widget; 12 | 13 | /* Update delay. */ 14 | int delay; 15 | 16 | /* Battery percentage. */ 17 | int percentage; 18 | bool b_usb_connected; 19 | 20 | } widget_batt_t; 21 | 22 | void widget_battery_init(widget_batt_t *p_battery, tile_t *p_tile, int x, int y); 23 | 24 | #endif /* __INC_BATTERY_H */ -------------------------------------------------------------------------------- /main/ui/dateset.c: -------------------------------------------------------------------------------- 1 | #include "dateset.h" 2 | #include "../img/digits_small.h" 3 | #include "../img/ticks.h" 4 | 5 | #define DIGIT_WIDTH 28 6 | #define DIGIT_HEIGHT 45 7 | 8 | #define DAY_X 18 9 | #define DAY_Y 0 10 | #define MONTH_X (DIGIT_WIDTH*2 + 36) 11 | #define MONTH_Y 0 12 | #define YEAR_X (DIGIT_WIDTH*4 + 54) 13 | #define YEAR_Y 0 14 | 15 | static image_t *p_font; 16 | static image_t *p_ticks; 17 | 18 | /* Months (obviously). */ 19 | enum { 20 | JAN=1, 21 | FEB, 22 | MAR, 23 | APR, 24 | MAY, 25 | JUN, 26 | JUL, 27 | AUG, 28 | SEP, 29 | OCT, 30 | NOV, 31 | DEC 32 | }; 33 | 34 | 35 | /** 36 | * is_leap_year() 37 | * 38 | * @brief: determine if a given year is leap 39 | * @param year: year to test 40 | * @return: true if it is a leap year, false otherwise 41 | **/ 42 | 43 | bool is_leap_year(int year) 44 | { 45 | return ( 46 | ( ((year % 4) == 0) && (year % 100 != 0) ) || 47 | ( year % 400 == 0) 48 | ) && (year>0); 49 | } 50 | 51 | 52 | /** 53 | * nb_days_in_month() 54 | * 55 | * @brief: compute the number of days in a given month of a year 56 | * @param month: month number (starting from 1) 57 | * @param year: year 58 | * @return: number of days in the month 59 | **/ 60 | 61 | int nb_days_in_month(int month, int year) 62 | { 63 | if (month == FEB) 64 | { 65 | if (is_leap_year(year)) 66 | return 29; 67 | else 68 | return 28; 69 | } 70 | else 71 | { 72 | return ((((month-1)%7)%2)==0)?31:30; 73 | } 74 | } 75 | 76 | 77 | /** 78 | * nb_days_in_month() 79 | * 80 | * @brief: compute the number of days in a given month of a year 81 | * @param month: month number (starting from 1) 82 | * @param year: year 83 | * @return: number of days in the month 84 | **/ 85 | 86 | void dateset_fix(widget_dateset_t *p_dateset) 87 | { 88 | int days_in_month; 89 | 90 | /* Determine the number of days in the current month. */ 91 | days_in_month = nb_days_in_month(p_dateset->month, p_dateset->year); 92 | 93 | /* Limit day number depending on the month. */ 94 | if (p_dateset->day >= days_in_month) 95 | { 96 | p_dateset->day = days_in_month; 97 | } 98 | if (p_dateset->day <= 1) 99 | { 100 | p_dateset->day = 1; 101 | } 102 | 103 | /* Limit month. */ 104 | if (p_dateset->month < JAN) 105 | p_dateset->month = JAN; 106 | else if (p_dateset->month > DEC) 107 | p_dateset->month = DEC; 108 | } 109 | 110 | 111 | /** 112 | * _dateset_drawfunc() 113 | * 114 | * @brief: dateset widget drawing function 115 | * @param p_widget: pointer to a `widget_t` structure 116 | * @return: TE_PROCESSED 117 | **/ 118 | 119 | int _dateset_drawfunc(widget_t *p_widget) 120 | { 121 | int delta_y; 122 | 123 | widget_dateset_t *p_dateset = (widget_dateset_t *)p_widget->p_user_data; 124 | 125 | delta_y = (p_widget->box.height - 45)/2; 126 | 127 | /* Draw day digit 1. */ 128 | widget_bitblt( 129 | p_widget, 130 | p_font, 131 | (p_dateset->day/10)*DIGIT_WIDTH, 132 | 0, 133 | DIGIT_WIDTH, 134 | DIGIT_HEIGHT, 135 | DAY_X, 136 | delta_y + DAY_Y 137 | ); 138 | 139 | /* Draw day digit 2. */ 140 | widget_bitblt( 141 | p_widget, 142 | p_font, 143 | (p_dateset->day%10)*DIGIT_WIDTH, 144 | 0, 145 | DIGIT_WIDTH, 146 | DIGIT_HEIGHT, 147 | DAY_X + DIGIT_WIDTH, 148 | delta_y + DAY_Y 149 | ); 150 | 151 | /* Draw month digit 1. */ 152 | widget_bitblt( 153 | p_widget, 154 | p_font, 155 | (p_dateset->month/10)*DIGIT_WIDTH, 156 | 0, 157 | DIGIT_WIDTH, 158 | DIGIT_HEIGHT, 159 | MONTH_X, 160 | delta_y + MONTH_Y 161 | ); 162 | 163 | /* Draw month digit 2. */ 164 | widget_bitblt( 165 | p_widget, 166 | p_font, 167 | (p_dateset->month%10)*DIGIT_WIDTH, 168 | 0, 169 | DIGIT_WIDTH, 170 | DIGIT_HEIGHT, 171 | MONTH_X + DIGIT_WIDTH, 172 | delta_y + MONTH_Y 173 | ); 174 | 175 | /* Draw year digit 1. */ 176 | widget_bitblt( 177 | p_widget, 178 | p_font, 179 | ((p_dateset->year%100)/10)*DIGIT_WIDTH, 180 | 0, 181 | DIGIT_WIDTH, 182 | DIGIT_HEIGHT, 183 | YEAR_X, 184 | delta_y + YEAR_Y 185 | ); 186 | 187 | /* Draw year digit 2. */ 188 | widget_bitblt( 189 | p_widget, 190 | p_font, 191 | (p_dateset->year%10)*DIGIT_WIDTH, 192 | 0, 193 | DIGIT_WIDTH, 194 | DIGIT_HEIGHT, 195 | YEAR_X + DIGIT_WIDTH, 196 | delta_y + YEAR_Y 197 | ); 198 | 199 | 200 | /* Draw upper triangles. */ 201 | widget_bitblt( 202 | p_widget, 203 | p_ticks, 204 | 0, 205 | 0, 206 | 26, 207 | 13, 208 | DAY_X + DIGIT_WIDTH/2 + 1, 209 | delta_y - 18 210 | ); 211 | 212 | widget_bitblt( 213 | p_widget, 214 | p_ticks, 215 | 0, 216 | 0, 217 | 26, 218 | 13, 219 | MONTH_X + DIGIT_WIDTH/2 + 1, 220 | delta_y - 18 221 | ); 222 | 223 | widget_bitblt( 224 | p_widget, 225 | p_ticks, 226 | 0, 227 | 0, 228 | 26, 229 | 13, 230 | YEAR_X + DIGIT_WIDTH/2, 231 | delta_y - 18 232 | ); 233 | 234 | /* Draw lower triangles. */ 235 | widget_bitblt( 236 | p_widget, 237 | p_ticks, 238 | 0, 239 | 13, 240 | 26, 241 | 13, 242 | DAY_X + DIGIT_WIDTH/2 + 1, 243 | delta_y + DIGIT_HEIGHT + 5 244 | ); 245 | 246 | widget_bitblt( 247 | p_widget, 248 | p_ticks, 249 | 0, 250 | 13, 251 | 26, 252 | 13, 253 | MONTH_X + DIGIT_WIDTH/2 + 1, 254 | delta_y + DIGIT_HEIGHT + 5 255 | ); 256 | 257 | widget_bitblt( 258 | p_widget, 259 | p_ticks, 260 | 0, 261 | 13, 262 | 26, 263 | 13, 264 | YEAR_X + DIGIT_WIDTH/2 + 1, 265 | delta_y + DIGIT_HEIGHT + 5 266 | ); 267 | 268 | /* Draw day/month/year texts. */ 269 | widget_draw_text(p_widget, DAY_X + DIGIT_WIDTH - font_get_text_width("day")/2, 100, "day", RGB(0xc,0xc,0xc)); 270 | widget_draw_text(p_widget, MONTH_X + DIGIT_WIDTH - font_get_text_width("month")/2, 100, "month", RGB(0xc,0xc,0xc)); 271 | widget_draw_text(p_widget, YEAR_X + DIGIT_WIDTH - font_get_text_width("year")/2, 100, "year", RGB(0xc,0xc,0xc)); 272 | 273 | /* Success. */ 274 | return TE_PROCESSED; 275 | } 276 | 277 | 278 | /** 279 | * update_date() 280 | * 281 | * @brief: Update dateset date 282 | * @param p_widget: pointer to a `widget_t` structure 283 | * @param x: X coordinate of a press event 284 | * @param y: Y coordinate of a press event 285 | * @param longpress: true if event is a long press, false otherwise 286 | **/ 287 | 288 | void update_date(widget_t *p_widget, int x, int y, bool longpress) 289 | { 290 | widget_dateset_t *p_dateset = (widget_dateset_t *)p_widget->p_user_data; 291 | 292 | 293 | /* Is day pressed ? */ 294 | if ((x >= DAY_X) && (x <= (DAY_X + DIGIT_WIDTH*2))) 295 | { 296 | /* Update day value. */ 297 | if (y > (p_widget->box.height)/2) 298 | { 299 | p_dateset->day -= (longpress?2:1); 300 | } 301 | else 302 | { 303 | p_dateset->day += (longpress?2:1); 304 | } 305 | 306 | /* Fix value if needed. */ 307 | dateset_fix(p_dateset); 308 | } 309 | 310 | /* Is month pressed ? */ 311 | if ((x >= MONTH_X) && (x <= (MONTH_X + DIGIT_WIDTH*2))) 312 | { 313 | /* Update day value. */ 314 | if (y > (p_widget->box.height)/2) 315 | { 316 | p_dateset->month -= (longpress?2:1); 317 | } 318 | else 319 | { 320 | p_dateset->month += (longpress?2:1); 321 | } 322 | 323 | /* Fix value if needed. */ 324 | dateset_fix(p_dateset); 325 | } 326 | 327 | /* Is year pressed ? */ 328 | if ((x >= YEAR_X) && (x <= (YEAR_X + DIGIT_WIDTH*2))) 329 | { 330 | /* Update day value. */ 331 | if (y > (p_widget->box.height)/2) 332 | { 333 | p_dateset->year--; 334 | } 335 | else 336 | { 337 | p_dateset->year++; 338 | } 339 | 340 | /* Fix value if needed. */ 341 | dateset_fix(p_dateset); 342 | } 343 | } 344 | 345 | 346 | /** 347 | * _dateset_eventhandler() 348 | * 349 | * @brief: Dateset widget event handler 350 | * @param p_widget: pointer to a `widget_t` structure 351 | * @param event: event type 352 | * @param x: X coordinate of a press event 353 | * @param y: Y coordinate of a press event 354 | * @param velocity: speed of a swipe event 355 | * @return WE_PROCESSED if success. 356 | **/ 357 | 358 | int _dateset_eventhandler(widget_t *p_widget, widget_event_t p_event, int x, int y, int velocity) 359 | { 360 | bool b_event_processed = false; 361 | widget_dateset_t *p_dateset = (widget_dateset_t *)p_widget->p_user_data; 362 | 363 | switch(p_event) 364 | { 365 | case WE_PRESS: 366 | { 367 | p_dateset->last_x = x; 368 | p_dateset->last_y = y; 369 | 370 | p_dateset->press_cycles++; 371 | if (p_dateset->press_cycles > 20) 372 | { 373 | if (!p_dateset->longpress) 374 | { 375 | p_dateset->nb_cycles++; 376 | if (p_dateset->nb_cycles > 5) 377 | { 378 | p_dateset->longpress = true; 379 | } 380 | } 381 | 382 | /* Update time. */ 383 | update_date(p_widget, x, y, p_dateset->longpress); 384 | 385 | /* Reset cycles. */ 386 | p_dateset->press_cycles = 0; 387 | } 388 | } 389 | break; 390 | 391 | case WE_RELEASE: 392 | { 393 | if (p_dateset->press_cycles > 2) 394 | { 395 | /* Update time. */ 396 | update_date(p_widget, p_dateset->last_x, p_dateset->last_y, p_dateset->longpress); 397 | } 398 | 399 | /* Reset press cycles. */ 400 | p_dateset->press_cycles = 0; 401 | p_dateset->nb_cycles = 0; 402 | p_dateset->longpress = false; 403 | } 404 | break; 405 | 406 | default: 407 | break; 408 | } 409 | 410 | /* Return WE_PROCESSED if event has been processed. */ 411 | return (b_event_processed?WE_PROCESSED:WE_ERROR); 412 | } 413 | 414 | 415 | /** 416 | * dateset_set_date() 417 | * 418 | * @brief: Update dateset widget date 419 | * @param p_dateset: pointer to a `widget_dateset_t` structure 420 | * @param p_datetime: pointer to a `rtc_datetime_t` structure 421 | **/ 422 | 423 | void dateset_set_date(widget_dateset_t *p_dateset, rtc_datetime_t *p_datetime) 424 | { 425 | /* Set day, month and year. */ 426 | p_dateset->day = p_datetime->day; 427 | p_dateset->month = p_datetime->month; 428 | p_dateset->year = p_datetime->year; 429 | } 430 | 431 | 432 | /** 433 | * dateset_get_date() 434 | * 435 | * @brief: Retrieve dateset widget date 436 | * @param p_dateset: pointer to a `widget_dateset_t` structure 437 | * @param p_datetime: pointer to a `rtc_datetime_t` structure 438 | **/ 439 | 440 | void dateset_get_date(widget_dateset_t *p_dateset, rtc_datetime_t *p_datetime) 441 | { 442 | /* Copy day, month and year into p_datetime. */ 443 | p_datetime->day = p_dateset->day; 444 | p_datetime->month = p_dateset->month; 445 | p_datetime->year = p_dateset->year; 446 | } 447 | 448 | 449 | /** 450 | * dateset_init() 451 | * 452 | * @brief: Initialize a dateset widget 453 | * @param p_dateset: pointer to a `widget_dateset_t` structure 454 | * @param p_tile: pointer to a `tile_t` structure 455 | * @param x: widget X coordinate 456 | * @param y: widget Y coordinate 457 | * @param day: current day 458 | * @param month: current month 459 | * @param year: current year 460 | **/ 461 | 462 | void dateset_init(widget_dateset_t *p_dateset, tile_t *p_tile, int x, int y, int day, int month, int year) 463 | { 464 | /* Initialize our widget. */ 465 | widget_init(&p_dateset->base_widget, p_tile, x, y, DATESET_WIDTH, DATESET_HEIGHT); 466 | widget_set_drawfunc(&p_dateset->base_widget, _dateset_drawfunc); 467 | widget_set_eventhandler(&p_dateset->base_widget, _dateset_eventhandler); 468 | widget_set_userdata(&p_dateset->base_widget, (void *)p_dateset); 469 | 470 | /* Load our font. */ 471 | p_font = load_image(digits_small_img); 472 | 473 | /* Load our ticks. */ 474 | p_ticks = load_image(ticks_img); 475 | 476 | /* Set day, month and year. */ 477 | p_dateset->day = day; 478 | p_dateset->month = month; 479 | p_dateset->year = year; 480 | dateset_fix(p_dateset); 481 | 482 | p_dateset->nb_cycles = 0; 483 | p_dateset->longpress = false; 484 | } -------------------------------------------------------------------------------- /main/ui/dateset.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_WIDGET_DATESET_H 2 | #define __INC_WIDGET_DATESET_H 3 | 4 | #include "twatch.h" 5 | #include "ui/ui.h" 6 | #include "ui/widget.h" 7 | 8 | #define DATESET_WIDTH 240 9 | #define DATESET_HEIGHT 120 10 | 11 | typedef struct { 12 | /* Base widget. */ 13 | widget_t base_widget; 14 | 15 | /* Font. */ 16 | image_t *p_font; 17 | 18 | /* Day, month and year. */ 19 | int day; 20 | int month; 21 | int year; 22 | 23 | /* Press and longpress */ 24 | int last_x; 25 | int last_y; 26 | int press_cycles; 27 | int nb_cycles; 28 | bool longpress; 29 | 30 | } widget_dateset_t; 31 | 32 | void dateset_init(widget_dateset_t *p_dateset, tile_t *p_tile, int x, int y, int day, int month, int year); 33 | void dateset_set_date(widget_dateset_t *p_dateset, rtc_datetime_t *p_datetime); 34 | void dateset_get_date(widget_dateset_t *p_dateset, rtc_datetime_t *p_datetime); 35 | 36 | #endif /* __INC_WIDGET_DATESET_H */ -------------------------------------------------------------------------------- /main/ui/tile-apinfo.c: -------------------------------------------------------------------------------- 1 | #include "tile-apinfo.h" 2 | 3 | #define BLUE RGB(0x5,0x9,0xf) 4 | #define TAG "[tile::wifi::apinfo]" 5 | 6 | static modal_t apinfo_modal; 7 | static widget_label_t title_lbl, mac_lbl, channel_lbl, security_lbl, rssi_lbl; 8 | static widget_label_t mac_address, channel, security, rssi; 9 | static widget_frame_t frame; 10 | static wifi_ap_t ap_info; 11 | static widget_button_t close_btn; 12 | 13 | volatile char *psz_mac[18]; 14 | volatile char *psz_channel[4]; 15 | volatile char *psz_rssi[6]; 16 | 17 | char *auth_mode[] = { 18 | "OPEN", 19 | "WEP", 20 | "WPA_PSK", 21 | "WPA2_PSK", 22 | "WPA_WPA2_PSK", 23 | "WPA2_ENTERPRISE", 24 | "WPA3_PSK", 25 | "WPA2_WPA3_PSK", 26 | "WAPI_PSK" 27 | }; 28 | 29 | int close_handler(widget_t *p_widget) 30 | { 31 | ui_unset_modal(); 32 | return 0; 33 | } 34 | 35 | int apinfo_event_handler(tile_t *p_tile, tile_event_t event, int x, int y, int velocity) 36 | { 37 | switch (event) 38 | { 39 | case TE_EXIT: 40 | { 41 | } 42 | break; 43 | 44 | default: 45 | break; 46 | } 47 | return 0; 48 | } 49 | 50 | modal_t *modal_apinfo_init(void) 51 | { 52 | /* Initialize our wifi_ap_info. */ 53 | psz_mac[0] = '\0'; 54 | psz_channel[0] = '\0'; 55 | psz_rssi[0] = '\0'; 56 | 57 | /* Initialize our modal tile. */ 58 | modal_init(&apinfo_modal, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); 59 | modal_set_border_color(&apinfo_modal, RGB(0,0,0)); 60 | 61 | /* Set our own event handler. */ 62 | tile_set_event_handler(&apinfo_modal.tile, apinfo_event_handler); 63 | 64 | /* Add labels. */ 65 | widget_label_init(&title_lbl, &apinfo_modal.tile, 10, 5, 230, 45, ""); 66 | 67 | widget_label_init(&mac_lbl, &apinfo_modal.tile, 10, 50, 230, 45, "MAC"); 68 | widget_label_set_fontsize(&mac_lbl, LABEL_FONT_SMALL); 69 | widget_set_front_color((widget_t *)&mac_lbl, BLUE); 70 | 71 | widget_label_init(&mac_address, &apinfo_modal.tile, 70, 50, 160, 45, ""); 72 | widget_label_set_fontsize(&mac_address, LABEL_FONT_SMALL); 73 | 74 | widget_label_init(&channel_lbl, &apinfo_modal.tile, 10, 70, 230, 45, "Channel"); 75 | widget_label_set_fontsize(&channel_lbl, LABEL_FONT_SMALL); 76 | widget_set_front_color((widget_t *)&channel_lbl, BLUE); 77 | 78 | widget_label_init(&channel, &apinfo_modal.tile, 70, 70, 160, 45, ""); 79 | widget_label_set_fontsize(&channel, LABEL_FONT_SMALL); 80 | 81 | widget_label_init(&security_lbl, &apinfo_modal.tile, 10, 90, 230, 45, "Security"); 82 | widget_label_set_fontsize(&security_lbl, LABEL_FONT_SMALL); 83 | widget_set_front_color((widget_t *)&security_lbl, BLUE); 84 | 85 | widget_label_init(&security, &apinfo_modal.tile, 70, 90, 160, 45, ""); 86 | widget_label_set_fontsize(&security, LABEL_FONT_SMALL); 87 | 88 | widget_label_init(&rssi_lbl, &apinfo_modal.tile, 10, 110, 230, 45, "RSSI"); 89 | widget_label_set_fontsize(&rssi_lbl, LABEL_FONT_SMALL); 90 | widget_set_front_color((widget_t *)&rssi_lbl, BLUE); 91 | 92 | 93 | widget_label_init(&rssi, &apinfo_modal.tile, 70, 110, 160, 45, ""); 94 | widget_label_set_fontsize(&rssi, LABEL_FONT_SMALL); 95 | 96 | /* Add deauth button. */ 97 | widget_button_init(&close_btn, &apinfo_modal.tile, (240 - 120)/2, 175, 120, 50, "OK"); 98 | widget_set_bg_color(&close_btn.widget, RGB(0x1, 0x2, 0x3)); 99 | widget_set_border_color(&close_btn.widget, RGB(0x1, 0x2, 0x3)); 100 | widget_button_set_handler(&close_btn, close_handler); 101 | 102 | /* Add a frame. */ 103 | widget_frame_init(&frame, &apinfo_modal.tile, 5, 45, 230, 185); 104 | widget_set_border_color(&frame.widget, BLUE); 105 | 106 | /* Return our modal. */ 107 | return &apinfo_modal; 108 | } 109 | 110 | void modal_apinfo_set_ap(wifi_ap_t *p_wifi_ap) 111 | { 112 | /* Copy our AP info into our local structure (cache). */ 113 | memcpy(&ap_info, p_wifi_ap, sizeof(wifi_ap_t)); 114 | 115 | /* Copy ESSID. */ 116 | widget_label_set_text(&title_lbl, (char *)ap_info.essid); 117 | 118 | /* Format BSSID. */ 119 | snprintf( 120 | (char *)psz_mac, 121 | 18, 122 | "%02x:%02x:%02x:%02x:%02x:%02x", 123 | p_wifi_ap->bssid[0], 124 | p_wifi_ap->bssid[1], 125 | p_wifi_ap->bssid[2], 126 | p_wifi_ap->bssid[3], 127 | p_wifi_ap->bssid[4], 128 | p_wifi_ap->bssid[5] 129 | ); 130 | widget_label_set_text(&mac_address, (char *) psz_mac); 131 | 132 | /* Format channel. */ 133 | itoa(p_wifi_ap->channel, (char *)psz_channel, 10); 134 | widget_label_set_text(&channel, (char *)psz_channel); 135 | 136 | /* Display auth mode. */ 137 | widget_label_set_text(&security, auth_mode[p_wifi_ap->auth_mode]); 138 | 139 | /* Format RSSI. */ 140 | itoa(p_wifi_ap->rssi, (char *)psz_rssi, 10); 141 | widget_label_set_text(&rssi, (char *)psz_rssi); 142 | } 143 | -------------------------------------------------------------------------------- /main/ui/tile-apinfo.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_HACKWATCH_APINFO_H 2 | #define __INC_HACKWATCH_APINFO_H 3 | 4 | #include "twatch.h" 5 | #include "ui/ui.h" 6 | #include "ui/frame.h" 7 | #include "../wifi/wifi.h" 8 | 9 | modal_t *modal_apinfo_init(void); 10 | void modal_apinfo_set_ap(wifi_ap_t *p_wifi_ap); 11 | 12 | #endif /* __INC_HACKWATCH_APINFO_H */ -------------------------------------------------------------------------------- /main/ui/tile-bleinfo.c: -------------------------------------------------------------------------------- 1 | #include "tile-bleinfo.h" 2 | 3 | #define BLUE RGB(0x5,0x9,0xf) 4 | #define TAG "[tile::ble::bleinfo]" 5 | 6 | static modal_t bleinfo_modal; 7 | static widget_label_t title_lbl, ble_ver_lbl, ble_ver_value_lbl, ble_vendor_lbl; 8 | static widget_label_t ble_vendor_value_lbl; 9 | static widget_label_t ble_software_lbl, ble_software_value_lbl; 10 | static widget_spinner_t wait_spinner; 11 | static widget_button_t ok_btn; 12 | static widget_frame_t frame; 13 | static char software_version[8]; 14 | static char bd_address[18]; 15 | 16 | FDrawTile pfn_orig_draw_func = NULL; 17 | bool b_info_found = false; 18 | 19 | int close_modal(widget_t *p_widget) 20 | { 21 | int res; 22 | ESP_LOGI(TAG, "Disconnecting from device"); 23 | 24 | /* Reset state. */ 25 | b_info_found = false; 26 | 27 | /* Disconnect. */ 28 | res = ble_disconnect(); 29 | ESP_LOGI(TAG, "disconnect=%d", res); 30 | 31 | /* Close modal. */ 32 | ui_unset_modal(); 33 | 34 | return 0; 35 | } 36 | 37 | void bleinfo_poll_status(void) 38 | { 39 | uint8_t ble_version = 0; 40 | uint16_t ble_compid, ble_soft; 41 | 42 | ble_enter_critical_section(); 43 | ble_version = ble_device_get_version(); 44 | if (ble_version > 0) 45 | { 46 | ble_compid = ble_device_get_compid(); 47 | ble_soft = ble_device_get_soft(); 48 | b_info_found = true; 49 | modal_bleinfo_update(ble_version, ble_compid, ble_soft); 50 | } 51 | ble_leave_critical_section(); 52 | } 53 | 54 | int bleinfo_draw_func(tile_t *tile) 55 | { 56 | if (!b_info_found) 57 | bleinfo_poll_status(); 58 | return pfn_orig_draw_func(tile); 59 | } 60 | 61 | int bleinfo_event_handler(tile_t *p_tile, tile_event_t event, int x, int y, int velocity) 62 | { 63 | switch (event) 64 | { 65 | case TE_EXIT: 66 | { 67 | ESP_LOGI(TAG, "Disconnecting from device"); 68 | /* Disconnect. */ 69 | ble_disconnect(); 70 | } 71 | break; 72 | 73 | default: 74 | break; 75 | } 76 | return 0; 77 | } 78 | 79 | modal_t *modal_bleinfo_init(void) 80 | { 81 | /* Initialize our BLE device info. */ 82 | 83 | /* Initialize our modal tile. */ 84 | modal_init(&bleinfo_modal, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); 85 | modal_set_border_color(&bleinfo_modal, RGB(0,0,0)); 86 | 87 | /* Set our own event handler. */ 88 | tile_set_event_handler(&bleinfo_modal.tile, bleinfo_event_handler); 89 | 90 | /* Hook modal drawing function. */ 91 | pfn_orig_draw_func = ((tile_t *)&bleinfo_modal)->pfn_draw_tile; 92 | if (pfn_orig_draw_func != bleinfo_draw_func) 93 | { 94 | tile_set_drawfunc((tile_t *)&bleinfo_modal.tile, bleinfo_draw_func); 95 | } 96 | 97 | /* Add labels. */ 98 | widget_label_init(&title_lbl, &bleinfo_modal.tile, 10, 5, 230, 45, ""); 99 | 100 | /* Spinner (hidden by default). */ 101 | widget_spinner_init(&wait_spinner, &bleinfo_modal.tile, 10, 52, 220, 150); 102 | widget_set_visible(WIDGET(&wait_spinner), WIDGET_HIDDEN); 103 | 104 | /* First label: BLE version. */ 105 | widget_label_init(&ble_ver_lbl, &bleinfo_modal.tile, 10, 52, 80, 15, "BLE Ver.:"); 106 | widget_label_set_fontsize(&ble_ver_lbl, LABEL_FONT_SMALL); 107 | widget_set_front_color(&ble_ver_lbl.widget, RGB(0x1, 0x2, 0x3)); 108 | widget_label_init(&ble_ver_value_lbl, &bleinfo_modal.tile, 90, 52, 80, 20, ""); 109 | widget_label_set_fontsize(&ble_ver_value_lbl, LABEL_FONT_SMALL); 110 | 111 | /* Second label: Vendor name. */ 112 | widget_label_init(&ble_vendor_lbl, &bleinfo_modal.tile, 10, 72, 80, 15, "Vendor. :"); 113 | widget_label_set_fontsize(&ble_vendor_lbl, LABEL_FONT_SMALL); 114 | widget_set_front_color(&ble_vendor_lbl.widget, RGB(0x1, 0x2, 0x3)); 115 | widget_label_init(&ble_vendor_value_lbl, &bleinfo_modal.tile, 90, 72, 80, 20, ""); 116 | widget_label_set_fontsize(&ble_vendor_value_lbl, LABEL_FONT_SMALL); 117 | 118 | /* Third label: software version. */ 119 | widget_label_init(&ble_software_lbl, &bleinfo_modal.tile, 10, 92, 80, 15, "Softw. :"); 120 | widget_label_set_fontsize(&ble_software_lbl, LABEL_FONT_SMALL); 121 | widget_set_front_color(&ble_software_lbl.widget, RGB(0x1, 0x2, 0x3)); 122 | widget_label_init(&ble_software_value_lbl, &bleinfo_modal.tile, 90, 92, 80, 20, ""); 123 | widget_label_set_fontsize(&ble_software_value_lbl, LABEL_FONT_SMALL); 124 | 125 | 126 | /* Add OK button. */ 127 | widget_button_init(&ok_btn, &bleinfo_modal.tile, (240 - 120)/2, 175, 120, 50, "Ok"); 128 | widget_set_bg_color(&ok_btn.widget, RGB(0x1, 0x2, 0x3)); 129 | widget_set_border_color(&ok_btn.widget, RGB(0x1, 0x2, 0x3)); 130 | widget_button_set_handler(&ok_btn, close_modal); 131 | 132 | /* Add a frame. */ 133 | widget_frame_init(&frame, &bleinfo_modal.tile, 5, 45, 230, 185); 134 | widget_set_border_color(&frame.widget, BLUE); 135 | 136 | /* Return our modal. */ 137 | return &bleinfo_modal; 138 | } 139 | 140 | void modal_bleinfo_set_title(ble_device_t *p_device) 141 | { 142 | if (p_device->psz_name[0]) 143 | { 144 | widget_label_set_text(&title_lbl, p_device->psz_name); 145 | } 146 | else 147 | { 148 | snprintf( 149 | bd_address, 150 | 18, 151 | "%02x:%02x:%02x:%02x:%02x:%02x", 152 | p_device->address.val[5], 153 | p_device->address.val[4], 154 | p_device->address.val[3], 155 | p_device->address.val[2], 156 | p_device->address.val[1], 157 | p_device->address.val[0] 158 | ); 159 | widget_label_set_text(&title_lbl, bd_address); 160 | } 161 | 162 | } 163 | 164 | void modal_bleinfo_update(uint8_t ble_ver, uint16_t comp_id, uint16_t sw_ver) 165 | { 166 | ESP_LOGI(TAG, "ble_ver=%d, comp_id=%04x, sw_ver=%04x", ble_ver, comp_id, sw_ver); 167 | 168 | char *version = ble_get_version_str(ble_ver); 169 | ble_company_id_t *vendor = ble_get_company_info(comp_id); 170 | 171 | /* Hide spinner. */ 172 | widget_set_visible(WIDGET(&wait_spinner), WIDGET_HIDDEN); 173 | 174 | /* Show all labels, set spinner visible. */ 175 | widget_set_visible(WIDGET(&ble_ver_lbl), WIDGET_SHOW); 176 | widget_set_visible(WIDGET(&ble_ver_value_lbl), WIDGET_SHOW); 177 | widget_set_visible(WIDGET(&ble_vendor_lbl), WIDGET_SHOW); 178 | widget_set_visible(WIDGET(&ble_vendor_value_lbl), WIDGET_SHOW); 179 | widget_set_visible(WIDGET(&ble_software_lbl), WIDGET_SHOW); 180 | widget_set_visible(WIDGET(&ble_software_value_lbl), WIDGET_SHOW); 181 | 182 | if (version != NULL) 183 | { 184 | widget_label_set_text(&ble_ver_value_lbl, version); 185 | } 186 | 187 | if (vendor != NULL) 188 | { 189 | widget_label_set_text(&ble_vendor_value_lbl, vendor->psz_name); 190 | } 191 | 192 | snprintf(software_version, 8, "%d.%d", (sw_ver & 0xFF00)>>8, (sw_ver & 0xFF)); 193 | widget_label_set_text(&ble_software_value_lbl, software_version); 194 | 195 | } 196 | 197 | void modal_bleinfo_clear(void) 198 | { 199 | widget_label_set_text(&ble_ver_value_lbl, ""); 200 | widget_label_set_text(&ble_vendor_value_lbl, ""); 201 | widget_label_set_text(&ble_software_value_lbl, ""); 202 | } 203 | 204 | void modal_bleinfo_wait(void) 205 | { 206 | /* Reset polling state. */ 207 | b_info_found = false; 208 | 209 | /* Hide all labels, set spinner visible. */ 210 | widget_set_visible(WIDGET(&ble_ver_lbl), WIDGET_HIDDEN); 211 | widget_set_visible(WIDGET(&ble_ver_value_lbl), WIDGET_HIDDEN); 212 | widget_set_visible(WIDGET(&ble_vendor_lbl), WIDGET_HIDDEN); 213 | widget_set_visible(WIDGET(&ble_vendor_value_lbl), WIDGET_HIDDEN); 214 | widget_set_visible(WIDGET(&ble_software_lbl), WIDGET_HIDDEN); 215 | widget_set_visible(WIDGET(&ble_software_value_lbl), WIDGET_HIDDEN); 216 | 217 | /* Show spinner. */ 218 | widget_set_visible(WIDGET(&wait_spinner), WIDGET_SHOW); 219 | } -------------------------------------------------------------------------------- /main/ui/tile-bleinfo.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_HACKWATCH_BLEINFO_H 2 | #define __INC_HACKWATCH_BLEINFO_H 3 | 4 | #include "twatch.h" 5 | #include "ui/ui.h" 6 | #include "ui/frame.h" 7 | #include "../ble/ble.h" 8 | 9 | modal_t *modal_bleinfo_init(void); 10 | void modal_bleinfo_clear(void); 11 | void modal_bleinfo_set_title(ble_device_t *p_device); 12 | void modal_bleinfo_update(uint8_t ble_ver, uint16_t comp_id, uint16_t sw_ver); 13 | void modal_bleinfo_wait(void); 14 | 15 | #endif /* __INC_HACKWATCH_BLEINFO_H */ -------------------------------------------------------------------------------- /main/ui/tile-blescan.c: -------------------------------------------------------------------------------- 1 | #include "tile-blescan.h" 2 | 3 | #include "../img/ble_icons.h" 4 | #include "../img/ble_icons_big.h" 5 | 6 | #define BLESCAN_LISTITEM_HEIGHT 35 7 | #define BLESCAN_LISTITEM_OFFY 5 8 | #undef TAG 9 | #define TAG "[tile::ble::scanner]" 10 | 11 | /******************************************* 12 | * Globals 13 | ******************************************/ 14 | 15 | tile_t blescan_tile; 16 | blescan_widget_listitem_t g_devices_names[10]; 17 | char names[10][BLE_DEVICE_NAME_MAXSIZE]; 18 | widget_label_t ble_lbl_scanner; 19 | widget_listbox_t lb_devices; 20 | volatile int g_ble_devices_nb; 21 | FEventHandler pfn_lb_event_handler; 22 | modal_t *p_bleinfo_modal; 23 | image_t *icons, *icons_big; 24 | 25 | 26 | /******************************************* 27 | * BleDevice list item widget 28 | ******************************************/ 29 | 30 | /** 31 | * blescan_widget_listitem_event_handler() 32 | * 33 | * @brief: BLE scan widget listitem event handler. 34 | * @param event: UI event. 35 | * @param x: X screen coordinate 36 | * @param y: Y screen coordinate 37 | * @param velocity: swipe speed (not used). 38 | * @return: WE_PROCESSED if event has been processed, WE_ERROR otherwise. 39 | **/ 40 | 41 | int blescan_widget_listitem_event_handler(widget_t *p_widget, widget_event_t event, int x, int y, int velocity) 42 | { 43 | bool b_processed = false; 44 | blescan_widget_listitem_t *p_listitem = (blescan_widget_listitem_t *)p_widget->p_user_data; 45 | 46 | if (p_listitem != NULL) 47 | { 48 | switch (event) 49 | { 50 | 51 | case LB_ITEM_SELECTED: 52 | { 53 | /* Mark list item as selected. */ 54 | p_listitem->b_selected = true; 55 | b_processed = true; 56 | } 57 | break; 58 | 59 | case LB_ITEM_DESELECTED: 60 | { 61 | p_listitem->b_selected = false; 62 | b_processed = true; 63 | } 64 | break; 65 | 66 | default: 67 | break; 68 | } 69 | 70 | /* Event processed (or not) */ 71 | return b_processed; 72 | } 73 | 74 | /* Event not processed. */ 75 | return WE_ERROR; 76 | } 77 | 78 | 79 | /** 80 | * wscan_widget_listitem_drawfunc() 81 | * 82 | * @brief: Wifiscan listitem widget drawing function. 83 | * @param p_widget: pointer to a `widget_t` structure. 84 | **/ 85 | 86 | int blescan_widget_listitem_drawfunc(widget_t *p_widget) 87 | { 88 | char bdaddr[18]; 89 | 90 | blescan_widget_listitem_t *p_listitem = (blescan_widget_listitem_t *)p_widget->p_user_data; 91 | 92 | if (p_listitem != NULL) 93 | { 94 | if (p_listitem->p_device != NULL) 95 | { 96 | /* Draw background. */ 97 | widget_fill_region( 98 | p_widget, 99 | 1, 100 | 1 + BLESCAN_LISTITEM_OFFY, 101 | p_widget->box.width - 2, 102 | p_widget->box.height - 2 - BLESCAN_LISTITEM_OFFY, 103 | p_widget->style.background 104 | ); 105 | 106 | /* Draw BD address. */ 107 | if (!p_listitem->p_device->psz_name[0]) 108 | { 109 | snprintf( 110 | bdaddr, 111 | 18, 112 | "%02X:%02X:%02X:%02X:%02X:%02X", 113 | p_listitem->p_device->address.val[5], 114 | p_listitem->p_device->address.val[4], 115 | p_listitem->p_device->address.val[3], 116 | p_listitem->p_device->address.val[2], 117 | p_listitem->p_device->address.val[1], 118 | p_listitem->p_device->address.val[0] 119 | ); 120 | widget_draw_text( 121 | p_widget, 122 | 31, 123 | 5 + BLESCAN_LISTITEM_OFFY, 124 | (char *)bdaddr, 125 | p_widget->style.front 126 | ); 127 | } 128 | else 129 | { 130 | widget_draw_text( 131 | p_widget, 132 | 31, 133 | 5 + BLESCAN_LISTITEM_OFFY, 134 | (char *)p_listitem->p_device->psz_name, 135 | p_widget->style.front 136 | ); 137 | } 138 | 139 | /* Draw icon. */ 140 | if (p_listitem->b_selected) 141 | { 142 | widget_bitblt( 143 | p_widget, 144 | icons_big, 145 | 24*p_listitem->p_device->device_type, 146 | 0, 147 | 24, 148 | 24, 149 | 4, 150 | 1 + BLESCAN_LISTITEM_OFFY 151 | ); 152 | } 153 | else 154 | { 155 | widget_bitblt( 156 | p_widget, 157 | icons, 158 | 16*p_listitem->p_device->device_type, 159 | 0, 160 | 16, 161 | 16, 162 | 9, 163 | 5 + BLESCAN_LISTITEM_OFFY 164 | ); 165 | } 166 | 167 | /* Draw a frame when selected. */ 168 | if (p_listitem->b_selected) 169 | { 170 | widget_draw_line( 171 | p_widget, 172 | 1,0,p_widget->box.width-2,0,RGB(0x1, 0x2, 0x3) 173 | ); 174 | widget_draw_line( 175 | p_widget, 176 | 1,1,p_widget->box.width-2,1,RGB(0x1, 0x2, 0x3) 177 | ); 178 | 179 | widget_draw_line( 180 | p_widget, 181 | 1,p_widget->box.height-1,p_widget->box.width-2,p_widget->box.height-1,RGB(0x1, 0x2, 0x3) 182 | ); 183 | widget_draw_line( 184 | p_widget, 185 | 1,p_widget->box.height-2,p_widget->box.width-2,p_widget->box.height-2,RGB(0x1, 0x2, 0x3) 186 | ); 187 | 188 | 189 | widget_draw_line( 190 | p_widget, 191 | 0,1,0,p_widget->box.height-2,RGB(0x1, 0x2, 0x3) 192 | ); 193 | widget_draw_line( 194 | p_widget, 195 | 1,1,1,p_widget->box.height-2,RGB(0x1, 0x2, 0x3) 196 | ); 197 | 198 | widget_draw_line( 199 | p_widget, 200 | p_widget->box.width-1,1,p_widget->box.width-1,p_widget->box.height-2,RGB(0x1, 0x2, 0x3) 201 | ); 202 | widget_draw_line( 203 | p_widget, 204 | p_widget->box.width-2,1,p_widget->box.width-2,p_widget->box.height-2,RGB(0x1, 0x2, 0x3) 205 | ); 206 | 207 | } 208 | 209 | } 210 | } 211 | 212 | /* Success. */ 213 | return TE_PROCESSED; 214 | } 215 | 216 | 217 | /** 218 | * @brief Initialize our BLE scanner list item 219 | * @param p_listitem: pointer to a `blescan_widget_listitem_t` structure 220 | * @param p_device: pointer to a `ble_device_t` structure, referencing the BLE device associated with this item 221 | **/ 222 | 223 | void blescan_widget_listitem_init(blescan_widget_listitem_t *p_listitem, ble_device_t *p_device) 224 | { 225 | /* Initialize our widget. */ 226 | widget_init(&p_listitem->widget, NULL, 0, 0, 0, BLESCAN_LISTITEM_HEIGHT); 227 | 228 | /* Copy name and BD address. */ 229 | p_listitem->p_device = p_device; 230 | 231 | /* Set userdata. */ 232 | widget_set_userdata(&p_listitem->widget, (void *)p_listitem); 233 | 234 | /* Set drawing function. */ 235 | widget_set_drawfunc(&p_listitem->widget, blescan_widget_listitem_drawfunc); 236 | 237 | /* Set default event handler. */ 238 | widget_set_eventhandler(&p_listitem->widget, blescan_widget_listitem_event_handler); 239 | } 240 | 241 | 242 | /** 243 | * @brief Update widget list item BLE device structure. 244 | * @param p_listitem: pointer to a `blescan_widget_listitem_t` structure 245 | * @param p_device: pointer to a `ble_device_t` structure that will be associated with this item 246 | **/ 247 | 248 | void blescan_widget_listitem_update(blescan_widget_listitem_t *p_listitem, ble_device_t *p_device) 249 | { 250 | /* Update BLE device. */ 251 | p_listitem->p_device = p_device; 252 | } 253 | 254 | 255 | /** 256 | * @brief BLE scanner tile event handler 257 | * @param p_tile: pointer to a `tile_t` structure referencing the current tile 258 | * @param event: event type 259 | * @param x: x-coordinate of the event (if required) 260 | * @param y: y-coordinate of the event (if required) 261 | * @param velocity: swipe velocity (only set for user interaction event) 262 | * @return TE_PROCESSED if event has been processed, TE_ERROR otherwise. 263 | **/ 264 | 265 | int ble_scanner_tile_event_handler(tile_t *p_tile, tile_event_t event, int x, int y, int velocity) 266 | { 267 | switch (event) 268 | { 269 | case TE_ENTER: 270 | { 271 | /* Enable BLE scanner. */ 272 | ble_scan_start(); 273 | 274 | /* Disable eco mode. */ 275 | disable_ecomode(); 276 | } 277 | break; 278 | 279 | case TE_EXIT: 280 | { 281 | /* Stop scanner. */ 282 | ble_scan_stop(); 283 | 284 | /* Re-enable eco mode. */ 285 | enable_ecomode(); 286 | } 287 | break; 288 | 289 | default: 290 | break; 291 | } 292 | 293 | /* Success. */ 294 | return TE_PROCESSED; 295 | } 296 | 297 | 298 | /** 299 | * blescan_widget_list_event_handler() 300 | * 301 | * @brief: Wifi scan widget listitem event handler. 302 | * @param event: UI event. 303 | * @param x: X screen coordinate 304 | * @param y: Y screen coordinate 305 | * @param velocity: swipe speed (not used). 306 | * @return: WE_PROCESSED if event has been processed, WE_ERROR otherwise. 307 | **/ 308 | 309 | int blescan_widget_list_event_handler(widget_t *p_widget, widget_event_t event, int x, int y, int velocity) 310 | { 311 | bool b_processed = false; 312 | widget_listbox_t *p_listbox = (widget_listbox_t *)p_widget; 313 | blescan_widget_listitem_t *p_listitem; 314 | 315 | if (ble_enter_critical_section() == ESP_OK) 316 | { 317 | switch (event) 318 | { 319 | 320 | case LB_ITEM_SELECTED: 321 | { 322 | /* Retrieve selected item. */ 323 | p_listitem = (blescan_widget_listitem_t *)p_listbox->p_selected_item; 324 | if (p_listitem != NULL) 325 | { 326 | ESP_LOGI(TAG, "Item selected !"); 327 | 328 | /* Clear modal. */ 329 | modal_bleinfo_clear(); 330 | modal_bleinfo_wait(); 331 | 332 | /* Connect to the selected device. */ 333 | ble_connect(p_listitem->p_device); 334 | 335 | /* Set modal title. */ 336 | modal_bleinfo_set_title(p_listitem->p_device); 337 | 338 | /* Show modal. */ 339 | ui_set_modal(p_bleinfo_modal); 340 | } 341 | 342 | b_processed = true; 343 | } 344 | break; 345 | 346 | default: 347 | break; 348 | } 349 | 350 | /* Event processed (or not) */ 351 | ble_leave_critical_section(); 352 | } 353 | 354 | return b_processed?WE_PROCESSED:pfn_lb_event_handler(p_widget, event, x, y, velocity); 355 | } 356 | 357 | 358 | /** 359 | * @brief Event callback used to handle device events sent by the BLE controller 360 | * @param event_handler_arg: argument passed by the BLE controller 361 | * @param event_base: event category 362 | * @param event_id: event ID 363 | * @param event_data: pointer to data associated to the current event 364 | **/ 365 | 366 | void on_device_event(void *event_handler_arg, esp_event_base_t event_base, int32_t event_id, void *event_data) 367 | { 368 | int i; 369 | ble_device_t *peer; 370 | ble_device_version_t *p_version = NULL; 371 | 372 | switch (event_id) 373 | { 374 | case BLE_DEVICE_VERSION: 375 | { 376 | p_version = (ble_device_version_t *)(event_data); 377 | modal_bleinfo_update(p_version->ble, p_version->company, p_version->software); 378 | } 379 | break; 380 | 381 | case BLE_DEVICE_FOUND: 382 | { 383 | if (ble_enter_critical_section() == ESP_OK) 384 | { 385 | ui_enter_critical_section(); 386 | 387 | /* Empty list. */ 388 | for (i=0; i<10; i++) 389 | { 390 | widget_listbox_remove(&lb_devices, (widget_t *)&g_devices_names[i]); 391 | } 392 | 393 | g_ble_devices_nb = ble_get_devices_nb(); 394 | 395 | /* Add device. */ 396 | for (i=0; i= 0) 37 | avg = 0; 38 | 39 | return avg; 40 | } 41 | 42 | void channels_on_pkt_sniffed(wifi_promiscuous_pkt_t *p_wifi_pkt) 43 | { 44 | //printf("got packet on channel %d (%d)\r\n", g_channel, p_wifi_pkt->rx_ctrl.rssi); 45 | /* We received a packet. */ 46 | g_pkt_count++; 47 | 48 | /* Insert our RSSI. */ 49 | channels_add_measure(g_channel, p_wifi_pkt->rx_ctrl.rssi); 50 | } 51 | 52 | int channels_draw(tile_t *p_tile) 53 | { 54 | char *tableau[] = {"1","2","3","4","5","6","7","8","9","","11","","","14"}; 55 | int i, avg, height; 56 | 57 | /* Set drawing window. */ 58 | st7789_set_drawing_window( 59 | p_tile->offset_x, 60 | p_tile->offset_y, 61 | p_tile->offset_x + p_tile->width, 62 | p_tile->offset_y + p_tile->height 63 | ); 64 | 65 | /* Fill region with background color. */ 66 | st7789_fill_region( 67 | p_tile->offset_x, 68 | p_tile->offset_y, 69 | p_tile->width, 70 | p_tile->height, 71 | p_tile->background_color 72 | ); 73 | 74 | /* Draw title. */ 75 | tile_draw_text_x2(p_tile, 3, 3, "Channel scan", RGB(0xf,0xf,0xf)); 76 | 77 | /* Draw channel labels (source: rebelor49) */ 78 | for (i=0; i<14; i++) 79 | { 80 | if (tableau[i][0] != 0) 81 | { 82 | tile_draw_text(p_tile, (i>9)?(14 + i*16 - 2):(14 + i*16), 220, tableau[i], RGB(0xb,0xb,0xb)); 83 | } 84 | } 85 | 86 | /* Draw a frame */ 87 | tile_draw_line( 88 | p_tile, 89 | 3, 90 | 39, 91 | 240-6, 92 | 39, 93 | RGB(0x1, 0x2, 0x3) 94 | ); 95 | tile_draw_line( 96 | p_tile, 97 | 2, 98 | 40, 99 | 2, 100 | 210, 101 | RGB(0x1, 0x2, 0x3) 102 | ); 103 | tile_draw_line( 104 | p_tile, 105 | 3, 106 | 211, 107 | 240-6, 108 | 211, 109 | RGB(0x1, 0x2, 0x3) 110 | ); 111 | tile_draw_line( 112 | p_tile, 113 | 240-6, 114 | 40, 115 | 240-6, 116 | 210, 117 | RGB(0x1, 0x2, 0x3) 118 | ); 119 | 120 | /* Draw rules. */ 121 | for (i=0; i<100; i+=10) 122 | { 123 | tile_draw_line( 124 | p_tile, 125 | 3, 126 | CHANNELS_TABLE_Y + (CHANNELS_COLUMN_HEIGHT - (i*CHANNELS_COLUMN_HEIGHT)/100), 127 | 240-6, 128 | CHANNELS_TABLE_Y + (CHANNELS_COLUMN_HEIGHT - (i*CHANNELS_COLUMN_HEIGHT)/100), 129 | RGB(0x3,0x3,0x3) 130 | ); 131 | } 132 | 133 | /* Draw our measures. */ 134 | for (i=0; i 0) 148 | { 149 | tile_fill_region( 150 | p_tile, 151 | i*CHANNELS_COLUMN_WIDTH + CHANNELS_TABLE_X + 2, 152 | CHANNELS_TABLE_Y + (CHANNELS_COLUMN_HEIGHT - height), 153 | CHANNELS_COLUMN_WIDTH - 2, 154 | height, 155 | RGB(0xf,0xf,0xf) 156 | ); 157 | } 158 | } 159 | 160 | 161 | /* Increment ticks, update channel if required. */ 162 | g_ticks++; 163 | if (g_ticks > CHANNELS_SCAN_TIMEOUT_TICKS) 164 | { 165 | /* Display current measures for channel. */ 166 | printf("Measures chan %d: ", g_channel); 167 | for (int j=(g_channel-1)*CHANNELS_NB_MEASURES; j CHANNELS_MAX_CHANS) 184 | g_channel = 1; 185 | wifi_set_channel(g_channel); 186 | } 187 | 188 | /* Success. */ 189 | return 0; 190 | } 191 | 192 | int channels_tile_event_handler(tile_t *p_tile, tile_event_t event, int x, int y, int velocity) 193 | { 194 | switch (event) 195 | { 196 | case TE_ENTER: 197 | { 198 | /* Disable eco mode. */ 199 | disable_ecomode(); 200 | 201 | /* Enable scanner. */ 202 | wifi_set_mode(WIFI_SNIFFER); 203 | 204 | /* Set channel. */ 205 | g_channel = 1; 206 | wifi_set_channel(g_channel); 207 | 208 | /* Register our packet sniffer callback. */ 209 | wifi_set_sniffer_handler(channels_on_pkt_sniffed); 210 | 211 | g_ticks = 0; 212 | g_pkt_count = 0; 213 | } 214 | break; 215 | 216 | case TE_EXIT: 217 | { 218 | /* Stop scanner. */ 219 | wifi_set_mode(WIFI_OFF); 220 | 221 | /* Unregister our packet sniffer callback. */ 222 | wifi_set_sniffer_handler(NULL); 223 | 224 | /* Re-enable eco mode. */ 225 | enable_ecomode(); 226 | } 227 | break; 228 | 229 | default: 230 | break; 231 | } 232 | 233 | /* Success. */ 234 | return TE_PROCESSED; 235 | } 236 | 237 | tile_t *tile_channels_init(void) 238 | { 239 | int i; 240 | 241 | /* Initialize our tile. */ 242 | tile_init(&channels_tile, NULL); 243 | tile_set_drawfunc(&channels_tile, channels_draw); 244 | tile_set_event_handler(&channels_tile, channels_tile_event_handler); 245 | 246 | /* Initialize our measures. */ 247 | for (i=0; i<(CHANNELS_NB_MEASURES * CHANNELS_MAX_CHANS); i++) 248 | g_measures[i] = -100; 249 | 250 | /* Return our tile. */ 251 | return &channels_tile; 252 | } -------------------------------------------------------------------------------- /main/ui/tile-channels.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_HACKWATCH_CHANNELS_H 2 | #define __INC_HACKWATCH_CHANNELS_H 3 | 4 | #include "twatch.h" 5 | #include "ui/ui.h" 6 | #include "ui/button.h" 7 | #include "../wifi/wifi.h" 8 | 9 | #define CHANNELS_SCAN_TIMEOUT_TICKS 10 10 | #define CHANNELS_MAX_CHANS 14 11 | #define CHANNELS_NB_MEASURES 5 12 | 13 | #define CHANNELS_COLUMN_WIDTH 16 14 | #define CHANNELS_COLUMN_HEIGHT 180 15 | #define CHANNELS_TABLE_X 8 16 | #define CHANNELS_TABLE_Y 30 17 | 18 | tile_t *tile_channels_init(void); 19 | 20 | #endif /* __INC_HACKWATCH_CHANNELS_H */ -------------------------------------------------------------------------------- /main/ui/tile-clock.c: -------------------------------------------------------------------------------- 1 | #include "tile-clock.h" 2 | #include "../img/digits.h" 3 | #include "../img/ir_small_8bpp.h" 4 | 5 | #define HOURS_X 15 6 | #define HOURS_Y 10 7 | #define MINS_X 120 8 | #define MINS_Y (240-90-10) 9 | #define DIGIT_WIDTH 56 10 | #define DIGIT_HEIGHT 90 11 | 12 | #define BLUE RGB(0x5,0x9,0xf) 13 | 14 | #define TAG "[tile::clock]" 15 | 16 | 17 | static tile_t clock_tile; 18 | static image_t *clock_digits; 19 | #ifdef CONFIG_INCLUDE_IR 20 | static image_t *ir_tvbgone; 21 | #endif 22 | static widget_label_t date_lbl; 23 | static widget_batt_t batt; 24 | rtc_datetime_t datetime; 25 | int hours=12, mins=34; 26 | 27 | volatile char *psz_date[14]; 28 | 29 | int _tile_clock_draw(tile_t *p_tile) 30 | { 31 | /* Set drawing window. */ 32 | st7789_set_drawing_window( 33 | p_tile->offset_x, 34 | p_tile->offset_y, 35 | p_tile->offset_x + SCREEN_WIDTH, 36 | p_tile->offset_y + SCREEN_HEIGHT 37 | ); 38 | 39 | /* Fill region with background color. */ 40 | st7789_fill_region( 41 | p_tile->offset_x, 42 | p_tile->offset_y, 43 | SCREEN_WIDTH, 44 | SCREEN_HEIGHT, 45 | p_tile->background_color 46 | ); 47 | 48 | 49 | /* Draw digit. */ 50 | tile_bitblt( 51 | p_tile, 52 | clock_digits, 53 | (hours/10)*DIGIT_WIDTH, 54 | 0, 55 | DIGIT_WIDTH, 56 | DIGIT_HEIGHT, 57 | HOURS_X, 58 | HOURS_Y 59 | ); 60 | 61 | /* Draw digit. */ 62 | tile_bitblt( 63 | p_tile, 64 | clock_digits, 65 | (hours%10)*DIGIT_WIDTH, 66 | 0, 67 | DIGIT_WIDTH, 68 | DIGIT_HEIGHT, 69 | HOURS_X + DIGIT_WIDTH, 70 | HOURS_Y 71 | ); 72 | 73 | /* Draw digit. */ 74 | tile_bitblt( 75 | p_tile, 76 | clock_digits, 77 | (mins/10)*DIGIT_WIDTH, 78 | 0, 79 | DIGIT_WIDTH, 80 | DIGIT_HEIGHT, 81 | MINS_X, 82 | MINS_Y 83 | ); 84 | 85 | /* Draw digit. */ 86 | tile_bitblt( 87 | p_tile, 88 | clock_digits, 89 | (mins%10)*DIGIT_WIDTH, 90 | 0, 91 | DIGIT_WIDTH, 92 | DIGIT_HEIGHT, 93 | MINS_X + DIGIT_WIDTH, 94 | MINS_Y 95 | ); 96 | 97 | #ifdef CONFIG_INCLUDE_IR 98 | /* If TV-B-Gone is running, show a small icon. */ 99 | if (tvbgone_is_enabled()) 100 | { 101 | tile_bitblt( 102 | p_tile, 103 | ir_tvbgone, 104 | 0, 105 | 0, 106 | 23, 107 | 18, 108 | 191-28, 109 | 10 110 | ); 111 | } 112 | #endif /* CONFIG_INCLUDE_IR */ 113 | 114 | /* Draw widgets. */ 115 | tile_draw_widgets(p_tile); 116 | 117 | /* Success. */ 118 | return 0; 119 | } 120 | 121 | 122 | void clock_update(void *parameter) 123 | { 124 | while(true) 125 | { 126 | twatch_rtc_get_date_time(&datetime); 127 | hours = datetime.hour; 128 | mins = datetime.minute; 129 | 130 | snprintf( 131 | (char *)psz_date, 132 | 14, 133 | "%02d/%02d/%04d", 134 | datetime.day, 135 | datetime.month, 136 | datetime.year 137 | ); 138 | widget_label_set_text(&date_lbl, (char *)psz_date); 139 | 140 | vTaskDelay(300/portTICK_PERIOD_MS); 141 | } 142 | } 143 | 144 | 145 | tile_t *tile_clock_init(void) 146 | { 147 | /* Initialize date */ 148 | psz_date[0] = '\0'; 149 | 150 | /* Load digits into memory. */ 151 | clock_digits = load_image(digits_img); 152 | 153 | #ifdef CONFIG_INCLUDE_IR 154 | /* Load IR TV-B-Gone icon. */ 155 | ir_tvbgone = load_image(ir_icon_small); 156 | #endif /* CONFIG_INCLUDE_IR */ 157 | 158 | /* Initialize our tile. */ 159 | tile_init(&clock_tile, NULL); 160 | 161 | /* Add labels */ 162 | widget_label_init(&date_lbl, &clock_tile, (240-160)/2, 100, 160, 50, "01/01/1970"); 163 | widget_set_front_color((widget_t *)&date_lbl, BLUE); 164 | 165 | /* Add battery */ 166 | widget_battery_init(&batt, &clock_tile, 191, 10); 167 | 168 | /* Set tile drawing function. */ 169 | tile_set_drawfunc(&clock_tile, _tile_clock_draw); 170 | 171 | /* Create update task. */ 172 | xTaskCreate(clock_update, "clock_update", 10000, NULL, 1, NULL); 173 | 174 | /* Return our tile. */ 175 | return &clock_tile; 176 | } -------------------------------------------------------------------------------- /main/ui/tile-clock.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_HACKWATCH_CLOCK_H 2 | #define __INC_HACKWATCH_CLOCK_H 3 | 4 | #include "twatch.h" 5 | #include "ui/ui.h" 6 | #include "ui/frame.h" 7 | #include "battery.h" 8 | #include "tile-tvbgone.h" 9 | 10 | tile_t *tile_clock_init(void); 11 | 12 | #endif /* __INC_HACKWATCH_CLOCK_H */ -------------------------------------------------------------------------------- /main/ui/tile-deauth.c: -------------------------------------------------------------------------------- 1 | #include "tile-deauth.h" 2 | 3 | tile_t deauth_tile; 4 | widget_label_t deauth_title_lbl, deauth_target_lbl, deauth_essid_lbl, deauth_channel_lbl; 5 | widget_button_t deauth_select_btn, deauth_startstop_btn; 6 | 7 | /* AP selection. */ 8 | modal_t deauth_select_modal; 9 | wifiscan_t deauth_wifiscan; 10 | widget_button_t deauth_select_ok_btn; 11 | widget_frame_t deauth_frame; 12 | wifi_ap_t *deauth_target = NULL; 13 | char psz_deauth_target[64]; 14 | char psz_target_channel[64]; 15 | 16 | 17 | int deauth_tile_event_handler(tile_t *p_tile, tile_event_t event, int x, int y, int velocity) 18 | { 19 | switch (event) 20 | { 21 | case TE_ENTER: 22 | { 23 | /* Enable scanner. */ 24 | wifi_set_mode(WIFI_SCANNER); 25 | 26 | /* Disable eco mode. */ 27 | disable_ecomode(); 28 | } 29 | break; 30 | 31 | case TE_EXIT: 32 | { 33 | /* Stop scanner. */ 34 | wifi_set_mode(WIFI_OFF); 35 | 36 | /* Re-enable eco mode. */ 37 | enable_ecomode(); 38 | } 39 | break; 40 | 41 | default: 42 | break; 43 | } 44 | 45 | /* Success. */ 46 | return TE_PROCESSED; 47 | } 48 | 49 | int deauth_select_btn_onclick(widget_t *p_widget) 50 | { 51 | /* Activate AP selection dialog box (modal). */ 52 | ui_set_modal(&deauth_select_modal); 53 | 54 | /* Success. */ 55 | return TE_PROCESSED; 56 | } 57 | 58 | int deauth_start_btn_onclick(widget_t *p_widget) 59 | { 60 | if (wifi_get_mode() != WIFI_DEAUTH) 61 | { 62 | if (deauth_target != NULL) 63 | { 64 | printf("Starting Deauth for %s\r\n", deauth_target->essid); 65 | widget_button_set_text(&deauth_startstop_btn, "Stop"); 66 | wifi_deauth_target(deauth_target->bssid, deauth_target->channel); 67 | } 68 | else 69 | { 70 | printf("No target AP selected.\r\n"); 71 | } 72 | } 73 | else 74 | { 75 | /* Enable scanner. */ 76 | wifi_set_mode(WIFI_SCANNER); 77 | 78 | widget_button_set_text(&deauth_startstop_btn, "Start"); 79 | } 80 | /* Success. */ 81 | return TE_PROCESSED; 82 | } 83 | 84 | int deauth_select_modal_onclick(widget_t *p_widget) 85 | { 86 | /* Do we have a selected AP ? */ 87 | deauth_target = wifiscan_get_selected(&deauth_wifiscan); 88 | if (deauth_target != NULL) 89 | { 90 | /* Update target ap info. */ 91 | strncpy(psz_deauth_target, (char *)deauth_target->essid, 64); 92 | snprintf(psz_target_channel, 64, "Channel: %d", deauth_target->channel); 93 | } 94 | else 95 | { 96 | /* No AP selected. */ 97 | strncpy(psz_deauth_target, "", 64); 98 | strncpy(psz_target_channel, "Channel: -", 64); 99 | } 100 | 101 | /* Deactivate modal. */ 102 | ui_set_modal(NULL); 103 | 104 | /* Success. */ 105 | return TE_PROCESSED; 106 | } 107 | 108 | tile_t *tile_deauth_init(void) 109 | { 110 | /* Initialize our tile. */ 111 | tile_init(&deauth_tile, NULL); 112 | tile_set_event_handler(&deauth_tile, deauth_tile_event_handler); 113 | 114 | /* Add title. */ 115 | widget_label_init(&deauth_title_lbl, &deauth_tile, 3, 3, 200, 40, "Deauth"); 116 | widget_set_front_color((widget_t *)&deauth_title_lbl, RGB(0xf,0xf,0xf)); 117 | 118 | /* Add frame. */ 119 | widget_frame_init(&deauth_frame, &deauth_tile, 2, 39, 240-2, 240-39-2); 120 | widget_set_border_color((widget_t *)&deauth_frame, RGB(0x1, 0x2, 0x3)); 121 | 122 | /* No AP selected. */ 123 | psz_deauth_target[0] = '\0'; 124 | strncpy(psz_target_channel, "Channel: -", 64); 125 | widget_label_init(&deauth_target_lbl, &deauth_tile, 7, 46, 200, 40, "Target:"); 126 | widget_label_init(&deauth_essid_lbl, &deauth_tile, 7, 90, 200, 40, psz_deauth_target); 127 | widget_label_init(&deauth_channel_lbl, &deauth_tile, 7, 130, 200, 40, psz_target_channel); 128 | 129 | /* Add our buttons. */ 130 | widget_button_init( 131 | &deauth_select_btn, 132 | &deauth_tile, 133 | 7, 134 | 180, 135 | 110, 136 | 50, 137 | "Sel. AP" 138 | ); 139 | widget_set_border_color((widget_t *)&deauth_select_btn, RGB(0x1, 0x2, 0x3)); 140 | widget_set_bg_color((widget_t *)&deauth_select_btn, RGB(0x1, 0x2, 0x3)); 141 | widget_button_set_handler(&deauth_select_btn, deauth_select_btn_onclick); 142 | 143 | widget_button_init( 144 | &deauth_startstop_btn, 145 | &deauth_tile, 146 | 10 + (240-15)/2, 147 | 180, 148 | (240-15)/2, 149 | 50, 150 | "Start" 151 | ); 152 | widget_set_border_color((widget_t *)&deauth_startstop_btn, RGB(0x1, 0x2, 0x3)); 153 | widget_set_bg_color((widget_t *)&deauth_startstop_btn, RGB(0x1, 0x2, 0x3)); 154 | widget_button_set_handler(&deauth_startstop_btn, deauth_start_btn_onclick); 155 | 156 | /* Initialize our select AP dialog box. */ 157 | modal_init(&deauth_select_modal, 0, 0, 240, 238); 158 | widget_button_init( 159 | &deauth_select_ok_btn, 160 | &deauth_select_modal.tile, 161 | 60, 162 | 180, 163 | 120, 164 | 50, 165 | "OK" 166 | ); 167 | widget_set_border_color((widget_t *)&deauth_select_ok_btn, RGB(0x1, 0x2, 0x3)); 168 | widget_set_bg_color((widget_t *)&deauth_select_ok_btn, RGB(0x1, 0x2, 0x3)); 169 | widget_button_set_handler(&deauth_select_ok_btn, deauth_select_modal_onclick); 170 | wifiscan_init(&deauth_wifiscan, &deauth_select_modal.tile, 5, 5, 230, 168); 171 | 172 | /* Return our tile. */ 173 | return &deauth_tile; 174 | } -------------------------------------------------------------------------------- /main/ui/tile-deauth.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_HACKWATCH_DEAUTH_H 2 | #define __INC_HACKWATCH_DEAUTH_H 3 | 4 | #include "twatch.h" 5 | #include "ui/ui.h" 6 | #include "ui/button.h" 7 | #include "ui/frame.h" 8 | #include "../wifi/wifi.h" 9 | #include "../wifi/wifiscan.h" 10 | 11 | tile_t *tile_deauth_init(void); 12 | 13 | #endif /* __INC_HACKWATCH_DEAUTH_H */ -------------------------------------------------------------------------------- /main/ui/tile-rogueap.c: -------------------------------------------------------------------------------- 1 | #include "tile-rogueap.h" 2 | 3 | tile_t rogueap_tile; 4 | widget_label_t title_lbl, target_lbl, essid_lbl, channel_lbl; 5 | widget_button_t select_btn, startstop_btn; 6 | 7 | /* AP selection. */ 8 | modal_t ap_select_modal; 9 | wifiscan_t ap_wifiscan; 10 | widget_button_t ap_select_ok_btn; 11 | widget_frame_t ap_frame; 12 | wifi_ap_t *target_ap = NULL; 13 | char psz_target_ap[64]; 14 | char psz_target_channel[64]; 15 | 16 | 17 | int rogueap_tile_event_handler(tile_t *p_tile, tile_event_t event, int x, int y, int velocity) 18 | { 19 | switch (event) 20 | { 21 | case TE_ENTER: 22 | { 23 | /* Enable scanner. */ 24 | wifi_set_mode(WIFI_SCANNER); 25 | 26 | /* Disable eco mode. */ 27 | disable_ecomode(); 28 | } 29 | break; 30 | 31 | case TE_EXIT: 32 | { 33 | /* Stop scanner. */ 34 | wifi_set_mode(WIFI_OFF); 35 | 36 | /* Re-enable eco mode. */ 37 | enable_ecomode(); 38 | } 39 | break; 40 | 41 | default: 42 | break; 43 | } 44 | 45 | /* Success. */ 46 | return TE_PROCESSED; 47 | } 48 | 49 | int select_btn_onclick(widget_t *p_widget) 50 | { 51 | /* Activate AP selection dialog box (modal). */ 52 | ui_set_modal(&ap_select_modal); 53 | 54 | /* Success. */ 55 | return TE_PROCESSED; 56 | } 57 | 58 | int start_btn_onclick(widget_t *p_widget) 59 | { 60 | if (wifi_get_mode() != WIFI_ROGUEAP) 61 | { 62 | if (target_ap != NULL) 63 | { 64 | printf("Starting rogue AP for %s\r\n", target_ap->essid); 65 | widget_button_set_text(&startstop_btn, "Stop"); 66 | wifi_rogueap_set_target(target_ap); 67 | } 68 | else 69 | { 70 | printf("No target AP selected.\r\n"); 71 | } 72 | } 73 | else 74 | { 75 | /* Enable scanner. */ 76 | wifi_set_mode(WIFI_SCANNER); 77 | widget_button_set_text(&startstop_btn, "Start"); 78 | } 79 | /* Success. */ 80 | return TE_PROCESSED; 81 | } 82 | 83 | int ap_select_modal_onclick(widget_t *p_widget) 84 | { 85 | /* Do we have a selected AP ? */ 86 | target_ap = wifiscan_get_selected(&ap_wifiscan); 87 | if (target_ap != NULL) 88 | { 89 | /* Update target ap info. */ 90 | strncpy(psz_target_ap, (char *)target_ap->essid, 64); 91 | snprintf(psz_target_channel, 64, "Channel: %d", target_ap->channel); 92 | } 93 | else 94 | { 95 | /* No AP selected. */ 96 | strncpy(psz_target_ap, "", 64); 97 | strncpy(psz_target_channel, "Channel: -", 64); 98 | } 99 | 100 | /* Deactivate modal. */ 101 | ui_set_modal(NULL); 102 | 103 | /* Success. */ 104 | return TE_PROCESSED; 105 | } 106 | 107 | tile_t *tile_rogueap_init(void) 108 | { 109 | /* Initialize our tile. */ 110 | tile_init(&rogueap_tile, NULL); 111 | tile_set_event_handler(&rogueap_tile, rogueap_tile_event_handler); 112 | 113 | /* Add title. */ 114 | widget_label_init(&title_lbl, &rogueap_tile, 3, 3, 200, 40, "Rogue AP"); 115 | widget_set_front_color((widget_t *)&title_lbl, RGB(0xf,0xf,0xf)); 116 | 117 | /* Add frame. */ 118 | widget_frame_init(&ap_frame, &rogueap_tile, 2, 39, 240-2, 240-39-2); 119 | widget_set_border_color((widget_t *)&ap_frame, RGB(0x1, 0x2, 0x3)); 120 | 121 | /* No AP selected. */ 122 | psz_target_ap[0] = '\0'; 123 | strncpy(psz_target_channel, "Channel: -", 64); 124 | widget_label_init(&target_lbl, &rogueap_tile, 7, 46, 200, 40, "Target:"); 125 | widget_label_init(&essid_lbl, &rogueap_tile, 7, 90, 200, 40, psz_target_ap); 126 | widget_label_init(&channel_lbl, &rogueap_tile, 7, 130, 200, 40, psz_target_channel); 127 | 128 | /* Add our buttons. */ 129 | widget_button_init( 130 | &select_btn, 131 | &rogueap_tile, 132 | 7, 133 | 180, 134 | 110, 135 | 50, 136 | "Sel. AP" 137 | ); 138 | widget_set_border_color((widget_t *)&select_btn, RGB(0x1, 0x2, 0x3)); 139 | widget_set_bg_color((widget_t *)&select_btn, RGB(0x1, 0x2, 0x3)); 140 | widget_button_set_handler(&select_btn, select_btn_onclick); 141 | 142 | widget_button_init( 143 | &startstop_btn, 144 | &rogueap_tile, 145 | 10 + (240-15)/2, 146 | 180, 147 | (240-15)/2, 148 | 50, 149 | "Start" 150 | ); 151 | widget_set_border_color((widget_t *)&startstop_btn, RGB(0x1, 0x2, 0x3)); 152 | widget_set_bg_color((widget_t *)&startstop_btn, RGB(0x1, 0x2, 0x3)); 153 | widget_button_set_handler(&startstop_btn, start_btn_onclick); 154 | 155 | /* Initialize our select AP dialog box. */ 156 | modal_init(&ap_select_modal, 0, 0, 240, 238); 157 | widget_button_init( 158 | &ap_select_ok_btn, 159 | &ap_select_modal.tile, 160 | 60, 161 | 180, 162 | 120, 163 | 50, 164 | "OK" 165 | ); 166 | widget_set_border_color((widget_t *)&ap_select_ok_btn, RGB(0x1, 0x2, 0x3)); 167 | widget_set_bg_color((widget_t *)&ap_select_ok_btn, RGB(0x1, 0x2, 0x3)); 168 | widget_button_set_handler(&ap_select_ok_btn, ap_select_modal_onclick); 169 | wifiscan_init(&ap_wifiscan, &ap_select_modal.tile, 5, 5, 230, 168); 170 | 171 | /* Return our tile. */ 172 | return &rogueap_tile; 173 | } -------------------------------------------------------------------------------- /main/ui/tile-rogueap.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_HACKWATCH_ROGUEAP_H 2 | #define __INC_HACKWATCH_ROGUEAP_H 3 | 4 | #include "twatch.h" 5 | #include "ui/ui.h" 6 | #include "ui/button.h" 7 | #include "ui/frame.h" 8 | #include "../wifi/wifi.h" 9 | #include "../wifi/wifiscan.h" 10 | 11 | tile_t *tile_rogueap_init(void); 12 | 13 | #endif /* __INC_HACKWATCH_ROGUEAP_H */ -------------------------------------------------------------------------------- /main/ui/tile-scanner.c: -------------------------------------------------------------------------------- 1 | #include "tile-scanner.h" 2 | #include "tile-apinfo.h" 3 | 4 | tile_t scanner_tile; 5 | 6 | #undef TAG 7 | #define TAG "[tile::wifi::scanner]" 8 | 9 | wifiscan_t g_wifiscan; 10 | widget_label_t lbl_scanner; 11 | modal_t *p_apinfo_modal; 12 | 13 | 14 | void scanner_wifi_event_handler(wifiscan_event_t event) 15 | { 16 | wifi_ap_t *p_ap; 17 | 18 | if (event == WS_EVENT_SELECTED) 19 | { 20 | /* Process selected AP. */ 21 | p_ap = wifiscan_get_selected(&g_wifiscan); 22 | ESP_LOGI(TAG, "AP selected: %s", p_ap->essid); 23 | 24 | /* Display our modal. */ 25 | modal_apinfo_set_ap(p_ap); 26 | ui_set_modal(p_apinfo_modal); 27 | } 28 | } 29 | 30 | int scanner_tile_event_handler(tile_t *p_tile, tile_event_t event, int x, int y, int velocity) 31 | { 32 | switch (event) 33 | { 34 | case TE_ENTER: 35 | { 36 | /* Enable scanner. */ 37 | wifi_set_mode(WIFI_SCANNER); 38 | 39 | /* Disable eco mode. */ 40 | disable_ecomode(); 41 | } 42 | break; 43 | 44 | case TE_EXIT: 45 | { 46 | /* Stop scanner. */ 47 | wifi_set_mode(WIFI_OFF); 48 | 49 | /* Re-enable eco mode. */ 50 | enable_ecomode(); 51 | } 52 | break; 53 | 54 | default: 55 | break; 56 | } 57 | 58 | /* Success. */ 59 | return TE_PROCESSED; 60 | } 61 | 62 | 63 | tile_t *tile_scanner_init(void) 64 | { 65 | /* Initialize our modal box. */ 66 | p_apinfo_modal = modal_apinfo_init(); 67 | 68 | /* Initialize our tile. */ 69 | tile_init(&scanner_tile, NULL); 70 | tile_set_event_handler(&scanner_tile, scanner_tile_event_handler); 71 | 72 | /* Initialize our title label */ 73 | widget_label_init(&lbl_scanner, &scanner_tile, 3, 3, 237, 36, "WiFi Networks"); 74 | 75 | /* Add a wifiscan widget. */ 76 | wifiscan_init(&g_wifiscan, &scanner_tile, 5, 39, 230, 196); 77 | wifiscan_set_event_handler(&g_wifiscan, scanner_wifi_event_handler); 78 | 79 | /* Return our tile. */ 80 | return &scanner_tile; 81 | } -------------------------------------------------------------------------------- /main/ui/tile-scanner.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_HACKWATCH_WIFISCAN_H 2 | #define __INC_HACKWATCH_WIFISCAN_H 3 | 4 | #include "twatch.h" 5 | #include "ui/ui.h" 6 | #include "ui/button.h" 7 | #include "../wifi/wifiscan.h" 8 | #include "../ui/tile-apinfo.h" 9 | 10 | tile_t *tile_scanner_init(void); 11 | 12 | #endif /* __INC_HACKWATCH_WIFISCAN_H */ -------------------------------------------------------------------------------- /main/ui/tile-settings.c: -------------------------------------------------------------------------------- 1 | #include "tile-settings.h" 2 | 3 | static tile_t settings_one_tile, settings_two_tile, settings_three_tile; 4 | 5 | /* Time and date saved confirm modal */ 6 | static modal_t confirm, confirm_date; 7 | static widget_button_t confirm_btn, confirm_date_btn; 8 | static widget_label_t confirm_txt, confirm_date_txt; 9 | 10 | static rtc_datetime_t datetime; 11 | static widget_label_t lbl_one_title, lbl_two_title, lbl_three_title; 12 | static widget_button_t btn_orientation; 13 | static widget_button_t btn_save_clock, btn_save_date; 14 | static widget_timeset_t timeset; 15 | static widget_dateset_t dateset; 16 | static widget_slider_t sld_backlight; 17 | 18 | /** 19 | * _constrain() 20 | * 21 | * @brief: Constrain `value` between `min` and `max`. 22 | * @param min: min value 23 | * @param max: max value 24 | * @param value: value to constrain 25 | * @return: constrained value. 26 | **/ 27 | 28 | int _constrain(int min, int max, int value) 29 | { 30 | if (value < min) 31 | return max; 32 | else if (value > max) 33 | return min; 34 | return value; 35 | } 36 | 37 | 38 | /** 39 | * clock_save_onclick() 40 | * 41 | * @brief: time save button callback handler 42 | * @param p_widget: pointer to a `widget_t` structure 43 | **/ 44 | 45 | int clock_save_onclick(widget_t *p_widget) 46 | { 47 | twatch_rtc_get_date_time(&datetime); 48 | timeset_get_time(×et, &datetime); 49 | twatch_rtc_set_date_time(&datetime); 50 | 51 | ui_set_modal(&confirm); 52 | 53 | /* Success. */ 54 | return TE_PROCESSED; 55 | } 56 | 57 | 58 | /** 59 | * clock_save_confirm() 60 | * 61 | * @brief: time save confirm modal handler 62 | * @param p_widget: pointer to a `widget_t` structure 63 | **/ 64 | 65 | int clock_save_confirm(widget_t *p_widget) 66 | { 67 | ui_unset_modal(); 68 | 69 | /* Success. */ 70 | return TE_PROCESSED; 71 | } 72 | 73 | 74 | /** 75 | * date_save_onclick() 76 | * 77 | * @brief: Date save onclick handler. 78 | * @param p_widget: pointer to a `widget_t` structure 79 | **/ 80 | 81 | int date_save_onclick(widget_t *p_widget) 82 | { 83 | /* Set datetime. */ 84 | twatch_rtc_get_date_time(&datetime); 85 | dateset_get_date(&dateset, &datetime); 86 | twatch_rtc_set_date_time(&datetime); 87 | 88 | ui_set_modal(&confirm_date); 89 | 90 | /* Success. */ 91 | return TE_PROCESSED; 92 | } 93 | 94 | 95 | /** 96 | * date_save_confirm() 97 | * 98 | * @brief: date save confirm modal handler 99 | * @param p_widget: pointer to a `widget_t` structure 100 | **/ 101 | 102 | int date_save_confirm(widget_t *p_widget) 103 | { 104 | ui_unset_modal(); 105 | 106 | /* Success. */ 107 | return TE_PROCESSED; 108 | } 109 | 110 | 111 | /** 112 | * settings_invert_onclick() 113 | * 114 | * @brief: Screen rotation button onclick handler. 115 | * @param p_widget: pointer to a `widget_t` structure 116 | **/ 117 | 118 | int settings_invert_onclick(widget_t *p_widget) 119 | { 120 | if (twatch_screen_is_inverted()) 121 | { 122 | /* Disable inverted screen. */ 123 | twatch_screen_set_inverted(false); 124 | twatch_touch_set_inverted(false); 125 | } 126 | else 127 | { 128 | /* Enable inverted screen. */ 129 | twatch_screen_set_inverted(true); 130 | twatch_touch_set_inverted(true); 131 | } 132 | 133 | /* Success. */ 134 | return TE_PROCESSED; 135 | } 136 | 137 | 138 | /** 139 | * settings_one_tile_event_handler() 140 | * 141 | * @brief: First setting screen event handler 142 | * @param p_tile: pointer to a tile 143 | * @param event: tile event 144 | * @param x: x-coord for the event 145 | * @param y: y-coord for the event 146 | * @param velocity: swipe speed (if swipe event) 147 | **/ 148 | 149 | int settings_one_tile_event_handler(tile_t *p_tile, tile_event_t event, int x, int y, int velocity) 150 | { 151 | switch (event) 152 | { 153 | case TE_ENTER: 154 | { 155 | /* Get date and time. */ 156 | twatch_rtc_get_date_time(&datetime); 157 | 158 | /* Update time. */ 159 | timeset_set_time(×et, &datetime); 160 | 161 | //widget_value_select_set_value(&hours_select, datetime.hour); 162 | //widget_value_select_set_value(&mins_select, datetime.minute); 163 | } 164 | break; 165 | 166 | default: 167 | break; 168 | } 169 | 170 | /* Success. */ 171 | return TE_PROCESSED; 172 | } 173 | 174 | 175 | /** 176 | * settings_two_tile_event_handler() 177 | * 178 | * @brief: Second setting screen event handler 179 | * @param p_tile: pointer to a tile 180 | * @param event: tile event 181 | * @param x: x-coord for the event 182 | * @param y: y-coord for the event 183 | * @param velocity: swipe speed (if swipe event) 184 | **/ 185 | 186 | int settings_two_tile_event_handler(tile_t *p_tile, tile_event_t event, int x, int y, int velocity) 187 | { 188 | switch (event) 189 | { 190 | case TE_ENTER: 191 | { 192 | /* Get date and time. */ 193 | twatch_rtc_get_date_time(&datetime); 194 | dateset_set_date(&dateset, &datetime); 195 | } 196 | break; 197 | 198 | default: 199 | break; 200 | } 201 | 202 | /* Success. */ 203 | return TE_PROCESSED; 204 | } 205 | 206 | 207 | /** 208 | * tile_settings_one_init() 209 | * 210 | * @brief: Initialize our first setting screen (time) 211 | **/ 212 | 213 | tile_t *tile_settings_one_init(void) 214 | { 215 | /* Get date and time. */ 216 | twatch_rtc_get_date_time(&datetime); 217 | 218 | /* Initialize our tile. */ 219 | tile_init(&settings_one_tile, NULL); 220 | tile_set_event_handler(&settings_one_tile, settings_one_tile_event_handler); 221 | 222 | /* Initialize our title label. */ 223 | widget_label_init(&lbl_one_title, &settings_one_tile, 10, 5, 230, 45, "Time"); 224 | 225 | timeset_init(×et, &settings_one_tile, 0, 60, 0, 0); 226 | 227 | /* Get hours and minutes and set timeset. */ 228 | timeset_set_time(×et, &datetime); 229 | 230 | /* Initialize our modal box (confirm). */ 231 | modal_init(&confirm, 20, 50, 200, 120); 232 | confirm.tile.background_color = RGB(0x1, 0x2, 0x3); 233 | widget_button_init( 234 | &confirm_btn, 235 | &confirm.tile, 236 | 50, 237 | 80, 238 | 100, 239 | 30, 240 | "OK" 241 | ); 242 | widget_set_bg_color(&confirm_btn.widget, RGB(0x3, 0x3, 0x3)); 243 | widget_set_front_color(&confirm_btn.widget, RGB(0, 0, 0)); 244 | 245 | widget_button_set_handler(&confirm_btn, clock_save_confirm); 246 | widget_label_init( 247 | &confirm_txt, 248 | &confirm.tile, 249 | 10, 250 | 5, 251 | 180, 252 | 30, 253 | "Time saved !" 254 | ); 255 | widget_set_bg_color(&confirm_txt.widget, RGB(0x1, 0x2, 0x3)); 256 | widget_set_front_color(&confirm_txt.widget, RGB(0xf, 0xf, 0xf)); 257 | 258 | 259 | /* Initialize our buttons. */ 260 | widget_button_init(&btn_save_clock, &settings_one_tile, 15, 190, 210, 45, "Save"); 261 | widget_set_bg_color(&btn_save_clock.widget, RGB(0x1, 0x2, 0x3)); 262 | widget_set_border_color(&btn_save_clock.widget, RGB(0x1, 0x2, 0x3)); 263 | widget_button_set_handler(&btn_save_clock, clock_save_onclick); 264 | 265 | /* Return our tile. */ 266 | return &settings_one_tile; 267 | } 268 | 269 | 270 | /** 271 | * tile_settings_two_init() 272 | * 273 | * @brief: Initialize our second setting screen (date) 274 | **/ 275 | 276 | tile_t *tile_settings_two_init(void) 277 | { 278 | /* Get date and time. */ 279 | twatch_rtc_get_date_time(&datetime); 280 | 281 | /* Initialize our tile. */ 282 | tile_init(&settings_two_tile, NULL); 283 | tile_set_event_handler(&settings_two_tile, settings_two_tile_event_handler); 284 | 285 | /* Initialize our title label. */ 286 | widget_label_init(&lbl_two_title, &settings_two_tile, 10, 5, 230, 45, "Date"); 287 | 288 | dateset_init(&dateset, &settings_two_tile, 0, 50, datetime.day, datetime.month, datetime.year); 289 | 290 | /* Initialize our modal box (confirm_date). */ 291 | modal_init(&confirm_date, 20, 50, 200, 120); 292 | confirm_date.tile.background_color = RGB(0x1, 0x2, 0x3); 293 | widget_button_init( 294 | &confirm_date_btn, 295 | &confirm_date.tile, 296 | 50, 297 | 80, 298 | 100, 299 | 30, 300 | "OK" 301 | ); 302 | widget_set_bg_color(&confirm_date_btn.widget, RGB(0x3, 0x3, 0x3)); 303 | widget_set_front_color(&confirm_date_btn.widget, RGB(0, 0, 0)); 304 | 305 | widget_button_set_handler(&confirm_date_btn, date_save_confirm); 306 | widget_label_init( 307 | &confirm_date_txt, 308 | &confirm_date.tile, 309 | 10, 310 | 5, 311 | 180, 312 | 30, 313 | "Date saved !" 314 | ); 315 | widget_set_bg_color(&confirm_date_txt.widget, RGB(0x1, 0x2, 0x3)); 316 | widget_set_front_color(&confirm_date_txt.widget, RGB(0xf, 0xf, 0xf)); 317 | 318 | /* Initialize our buttons. */ 319 | widget_button_init(&btn_save_date, &settings_two_tile, 15, 190, 210, 45, "Save date"); 320 | widget_set_bg_color(&btn_save_date.widget, RGB(0x1, 0x2, 0x3)); 321 | widget_set_border_color(&btn_save_date.widget, RGB(0x1, 0x2, 0x3)); 322 | widget_button_set_handler(&btn_save_date, date_save_onclick); 323 | 324 | /* Return our tile. */ 325 | return &settings_two_tile; 326 | } 327 | 328 | /** 329 | * backlight_onchanged() 330 | * 331 | * @brief: Callback for backlight value changed 332 | * @param p_widget_slider: pointer to a `widget_t` structure 333 | * @return TE_PROCESSED if event has been processed. 334 | **/ 335 | 336 | int backlight_onchanged(widget_t *p_widget_slider) 337 | { 338 | int new_value = widget_slider_get_value((widget_slider_t *)p_widget_slider); 339 | int before = twatch_screen_get_backlight(); 340 | 341 | /* Update value if it has changed. */ 342 | if (before != new_value) { 343 | twatch_screen_set_default_backlight(new_value); 344 | twatch_screen_set_backlight(new_value); 345 | widget_slider_set_value((widget_slider_t *)p_widget_slider, new_value); 346 | } 347 | 348 | /* Success. */ 349 | return TE_PROCESSED; 350 | } 351 | 352 | 353 | /** 354 | * tile_settings_three_init() 355 | * 356 | * @brief: Initialize our thord setting screen (screen rotation) 357 | **/ 358 | 359 | tile_t *tile_settings_three_init(void) 360 | { 361 | /* Initialize our tile. */ 362 | tile_init(&settings_three_tile, NULL); 363 | 364 | /* Initialize our title label. */ 365 | widget_label_init(&lbl_three_title, &settings_three_tile, 10, 5, 230, 45, "Screen"); 366 | 367 | widget_button_init(&btn_orientation, &settings_three_tile, 15, (240-45)/2, 210, 45, "Rotate screen"); 368 | widget_set_bg_color(&btn_orientation.widget, RGB(0x1, 0x2, 0x3)); 369 | widget_set_border_color(&btn_orientation.widget, RGB(0x1, 0x2, 0x3)); 370 | widget_button_set_handler(&btn_orientation, settings_invert_onclick); 371 | 372 | /* Initialize our backlight slider */ 373 | widget_slider_init(&sld_backlight, &settings_three_tile, 2, 180, 240-4, 60); 374 | widget_slider_configure(&sld_backlight, 10, 5000, twatch_screen_get_default_backlight(), -1); 375 | widget_slider_set_handler(&sld_backlight, backlight_onchanged); 376 | 377 | /* Return our tile. */ 378 | return &settings_three_tile; 379 | } 380 | -------------------------------------------------------------------------------- /main/ui/tile-settings.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_HACKWATCH_SETTINGS_H 2 | #define __INC_HACKWATCH_SETTINGS_H 3 | 4 | #include "twatch.h" 5 | #include "hal/screen.h" 6 | #include "ui/ui.h" 7 | #include "ui/frame.h" 8 | #include "ui/slider.h" 9 | #include "timeset.h" 10 | #include "dateset.h" 11 | 12 | typedef struct { 13 | widget_label_t label; 14 | 15 | /* Properties. */ 16 | int min_value; 17 | int max_value; 18 | int current_value; 19 | 20 | /* Label text buffer. */ 21 | char psz_label_text[3]; 22 | 23 | } widget_value_select_t; 24 | 25 | void widget_value_select_init( 26 | widget_value_select_t *p_value_select, 27 | tile_t *p_tile, 28 | int x, 29 | int y, 30 | int width, 31 | int height, 32 | int min_value, 33 | int max_value, 34 | int current_value 35 | ); 36 | int widget_value_select_get_value(widget_value_select_t *p_value_select); 37 | void widget_value_select_set_value(widget_value_select_t *p_value_select, int value); 38 | 39 | tile_t *tile_settings_one_init(void); 40 | tile_t *tile_settings_two_init(void); 41 | tile_t *tile_settings_three_init(void); 42 | 43 | #endif /* __INC_HACKWATCH_SETTINGS_H */ -------------------------------------------------------------------------------- /main/ui/tile-tvbgone.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_HACKWATCH_TVBGONE_H 2 | #define __INC_HACKWATCH_TVBGONE_H 3 | 4 | #include "twatch.h" 5 | #include "ui/ui.h" 6 | #include "ui/frame.h" 7 | #include "ui/switch.h" 8 | #include "drivers/ir/esp32_rmt_remotes.h" 9 | 10 | tile_t *tile_tvbgone_init(void); 11 | bool tvbgone_is_enabled(void); 12 | 13 | #endif /* __INC_HACKWATCH_TVBGONE_H */ -------------------------------------------------------------------------------- /main/ui/timeset.c: -------------------------------------------------------------------------------- 1 | #include "timeset.h" 2 | #include "../img/digits_small.h" 3 | #include "../img/ticks.h" 4 | 5 | #define DIGIT_WIDTH 28 6 | #define DIGIT_HEIGHT 45 7 | #define HOURS_X 0 8 | #define HOURS_Y 0 9 | 10 | #define MINS_X (DIGIT_WIDTH*2 + 8) 11 | #define MINS_Y 0 12 | 13 | static image_t *p_font; 14 | static image_t *p_ticks; 15 | 16 | 17 | /** 18 | * _timeset_drawfunc() 19 | * 20 | * @brief: Timeset widget drawing function 21 | * @param p_widget: pointer to a `widget_t` structure 22 | * @return TE_PROCESSED if success. 23 | **/ 24 | 25 | int _timeset_drawfunc(widget_t *p_widget) 26 | { 27 | int delta_x, delta_y; 28 | 29 | widget_timeset_t *p_timeset = (widget_timeset_t *)p_widget->p_user_data; 30 | 31 | delta_x = (p_widget->box.width - 4*DIGIT_WIDTH - 8)/2; 32 | delta_y = (p_widget->box.height - 45)/2; 33 | 34 | /* Draw ':'. */ 35 | widget_bitblt( 36 | p_widget, 37 | p_font, 38 | 283, 39 | 0, 40 | 8, 41 | DIGIT_HEIGHT, 42 | delta_x + DIGIT_WIDTH*2, 43 | delta_y + 0 44 | ); 45 | 46 | 47 | /* Draw hours digit 1. */ 48 | widget_bitblt( 49 | p_widget, 50 | p_font, 51 | (p_timeset->hours/10)*DIGIT_WIDTH, 52 | 0, 53 | DIGIT_WIDTH, 54 | DIGIT_HEIGHT, 55 | delta_x + HOURS_X, 56 | delta_y + HOURS_Y 57 | ); 58 | 59 | /* Draw hours digit 2. */ 60 | widget_bitblt( 61 | p_widget, 62 | p_font, 63 | (p_timeset->hours%10)*DIGIT_WIDTH, 64 | 0, 65 | DIGIT_WIDTH, 66 | DIGIT_HEIGHT, 67 | delta_x + HOURS_X + DIGIT_WIDTH, 68 | delta_y + HOURS_Y 69 | ); 70 | 71 | /* Draw hours digit 1. */ 72 | widget_bitblt( 73 | p_widget, 74 | p_font, 75 | (p_timeset->minutes/10)*DIGIT_WIDTH, 76 | 0, 77 | DIGIT_WIDTH, 78 | DIGIT_HEIGHT, 79 | delta_x + MINS_X, 80 | delta_y + MINS_Y 81 | ); 82 | 83 | 84 | /* Draw hours digit 2. */ 85 | widget_bitblt( 86 | p_widget, 87 | p_font, 88 | (p_timeset->minutes%10)*DIGIT_WIDTH, 89 | 0, 90 | DIGIT_WIDTH, 91 | DIGIT_HEIGHT, 92 | delta_x + MINS_X + DIGIT_WIDTH, 93 | delta_y + MINS_Y 94 | ); 95 | 96 | /* Draw upper triangles. */ 97 | widget_bitblt( 98 | p_widget, 99 | p_ticks, 100 | 0, 101 | 0, 102 | 26, 103 | 13, 104 | delta_x + DIGIT_WIDTH/2 + 1, 105 | delta_y - 18 106 | ); 107 | 108 | widget_bitblt( 109 | p_widget, 110 | p_ticks, 111 | 0, 112 | 0, 113 | 26, 114 | 13, 115 | delta_x + DIGIT_WIDTH/2 + 1 + DIGIT_WIDTH*2 + 8, 116 | delta_y - 18 117 | ); 118 | 119 | /* Draw lower triangles. */ 120 | widget_bitblt( 121 | p_widget, 122 | p_ticks, 123 | 0, 124 | 13, 125 | 26, 126 | 13, 127 | delta_x + DIGIT_WIDTH/2 + 1, 128 | delta_y + DIGIT_HEIGHT + 5 129 | ); 130 | 131 | widget_bitblt( 132 | p_widget, 133 | p_ticks, 134 | 0, 135 | 13, 136 | 26, 137 | 13, 138 | delta_x + DIGIT_WIDTH/2 + 1 + DIGIT_WIDTH*2 + 8, 139 | delta_y + DIGIT_HEIGHT + 5 140 | ); 141 | 142 | /* Success. */ 143 | return TE_PROCESSED; 144 | } 145 | 146 | 147 | /** 148 | * update_time() 149 | * 150 | * @brief: Time update routine 151 | * @param p_widget: pointer to a `widget_t` structure 152 | * @param x: X coordinate of a press event 153 | * @param y: Y coordinate of a press event 154 | * @param longpress: true if event is a longpress, false otherwise 155 | * @return TE_PROCESSED if success. 156 | **/ 157 | 158 | void update_time(widget_t *p_widget, int x, int y, bool longpress) 159 | { 160 | widget_timeset_t *p_timeset = (widget_timeset_t *)p_widget->p_user_data; 161 | 162 | if (x > (p_widget->box.width/2)) 163 | { 164 | if (y > (p_widget->box.height)/2) 165 | { 166 | p_timeset->minutes -= (longpress?10:1); 167 | if (p_timeset->minutes < 0) 168 | p_timeset->minutes = 59; 169 | } 170 | else 171 | { 172 | p_timeset->minutes+= (longpress?10:1); 173 | if (p_timeset->minutes >= 60) 174 | p_timeset->minutes = 0; 175 | } 176 | } 177 | else 178 | { 179 | if (y > (p_widget->box.height)/2) 180 | { 181 | p_timeset->hours-=(longpress?2:1); 182 | if (p_timeset->hours < 0) 183 | p_timeset->hours = 23; 184 | } 185 | else 186 | { 187 | p_timeset->hours+=(longpress?2:1); 188 | if (p_timeset->hours >= 24) 189 | p_timeset->hours = 0; 190 | } 191 | } 192 | } 193 | 194 | 195 | /** 196 | * _timeset_eventhandler() 197 | * 198 | * @brief: Timeset widget event handler 199 | * @param p_widget: pointer to a `widget_t` structure 200 | * @param event: event type 201 | * @param x: X coordinate of a press event 202 | * @param y: Y coordinate of a press event 203 | * @param velocity: speed of a swipe event 204 | * @return WE_PROCESSED if success. 205 | **/ 206 | 207 | int _timeset_eventhandler(widget_t *p_widget, widget_event_t event, int x, int y, int velocity) 208 | { 209 | bool b_event_processed = false; 210 | widget_timeset_t *p_timeset = (widget_timeset_t *)p_widget->p_user_data; 211 | 212 | switch(event) 213 | { 214 | case WE_PRESS: 215 | { 216 | p_timeset->last_x = x; 217 | p_timeset->last_y = y; 218 | 219 | p_timeset->press_cycles++; 220 | if (p_timeset->press_cycles > 20) 221 | { 222 | if (!p_timeset->longpress) 223 | { 224 | p_timeset->nb_cycles++; 225 | if (p_timeset->nb_cycles > 5) 226 | { 227 | p_timeset->longpress = true; 228 | } 229 | } 230 | 231 | /* Update time. */ 232 | update_time(p_widget, x, y, p_timeset->longpress); 233 | 234 | /* Reset cycles. */ 235 | p_timeset->press_cycles = 0; 236 | } 237 | } 238 | break; 239 | 240 | case WE_RELEASE: 241 | { 242 | if (p_timeset->press_cycles > 2) 243 | { 244 | /* Update time. */ 245 | update_time(p_widget, p_timeset->last_x, p_timeset->last_y, p_timeset->longpress); 246 | } 247 | 248 | /* Reset press cycles. */ 249 | p_timeset->press_cycles = 0; 250 | p_timeset->nb_cycles = 0; 251 | p_timeset->longpress = false; 252 | } 253 | break; 254 | 255 | default: 256 | break; 257 | } 258 | 259 | /* Return WE_PROCESSED if event has been processed. */ 260 | return (b_event_processed?WE_PROCESSED:WE_ERROR); 261 | } 262 | 263 | 264 | /** 265 | * timeset_set_time() 266 | * 267 | * @brief: Set timeset widget time 268 | * @param p_timeset: pointer to a `widget_timeset_t` structure 269 | * @param p_datetime: pointer to a `rtc_datetime_t` structure 270 | **/ 271 | 272 | void timeset_set_time(widget_timeset_t *p_timeset, rtc_datetime_t *p_datetime) 273 | { 274 | /* Set hours and minutes. */ 275 | p_timeset->hours = p_datetime->hour; 276 | p_timeset->minutes = p_datetime->minute; 277 | } 278 | 279 | 280 | /** 281 | * timeset_get_time() 282 | * 283 | * @brief: Set timeset widget time 284 | * @param p_timeset: pointer to a `widget_timeset_t` structure 285 | * @param p_datetime: pointer to a `rtc_datetime_t` structure 286 | **/ 287 | 288 | void timeset_get_time(widget_timeset_t *p_timeset, rtc_datetime_t *p_datetime) 289 | { 290 | /* Copy hours and minutes into p_datetime. */ 291 | p_datetime->hour = p_timeset->hours; 292 | p_datetime->minute = p_timeset->minutes; 293 | } 294 | 295 | 296 | /** 297 | * timeset_init() 298 | * 299 | * @brief: Initialize a timeset widget 300 | * @param p_timeset: pointer to a `widget_timeset_t` structure 301 | * @param p_tile: pointer to a `tile_t` structure 302 | * @param x: X coordinate of the widget 303 | * @param y: Y coordinate of the widget 304 | * @param hours: current number of hours 305 | * @param minutes: current number of minutes 306 | **/ 307 | 308 | void timeset_init(widget_timeset_t *p_timeset, tile_t *p_tile, int x, int y, int hours, int minutes) 309 | { 310 | /* Initialize our widget. */ 311 | widget_init(&p_timeset->base_widget, p_tile, x, y, TIMESET_WIDTH, TIMESET_HEIGHT); 312 | widget_set_drawfunc(&p_timeset->base_widget, _timeset_drawfunc); 313 | widget_set_eventhandler(&p_timeset->base_widget, _timeset_eventhandler); 314 | widget_set_userdata(&p_timeset->base_widget, (void *)p_timeset); 315 | 316 | /* Load our font. */ 317 | p_font = load_image(digits_small_img); 318 | 319 | /* Load our ticks. */ 320 | p_ticks = load_image(ticks_img); 321 | 322 | /* Set hours and minutes. */ 323 | p_timeset->hours = 0; 324 | p_timeset->minutes = 0; 325 | p_timeset->press_cycles = 0; 326 | p_timeset->nb_cycles = 0; 327 | p_timeset->longpress = false; 328 | } -------------------------------------------------------------------------------- /main/ui/timeset.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_WIDGET_TIMESET_H 2 | #define __INC_WIDGET_TIMESET_H 3 | 4 | #include "twatch.h" 5 | #include "ui/ui.h" 6 | #include "ui/widget.h" 7 | 8 | #define TIMESET_WIDTH 240 9 | #define TIMESET_HEIGHT 120 10 | 11 | typedef struct { 12 | /* Base widget. */ 13 | widget_t base_widget; 14 | 15 | /* Font. */ 16 | image_t *p_font; 17 | 18 | /* Hours and minutes. */ 19 | int hours; 20 | int minutes; 21 | 22 | /* Press and longpress */ 23 | int last_x; 24 | int last_y; 25 | int press_cycles; 26 | int nb_cycles; 27 | bool longpress; 28 | 29 | } widget_timeset_t; 30 | 31 | void timeset_init(widget_timeset_t *p_timeset, tile_t *p_tile, int x, int y, int hours, int minutes); 32 | void timeset_set_time(widget_timeset_t *p_timeset, rtc_datetime_t *p_datetime); 33 | void timeset_get_time(widget_timeset_t *p_timeset, rtc_datetime_t *p_datetime); 34 | 35 | #endif /* __INC_WIDGET_TIMESET_H */ -------------------------------------------------------------------------------- /main/wifi/dissect.c: -------------------------------------------------------------------------------- 1 | #include "dissect.h" 2 | 3 | 4 | /** 5 | * tlv_parse() 6 | * 7 | * @brief: Parse TLV elements 8 | * @param buffer: pointer to a wifi packet as provided by ESP32 9 | * @param p_tlv_element: pointer to a `wifi_tlv_t` structure that will be filled by tlv_parse() 10 | * @return: Number of bytes parsed, <0 on error (not handled for now) 11 | **/ 12 | 13 | int tlv_parse(void *buffer, wifi_tlv_t *p_tlv_element) 14 | { 15 | wifi_tlv_t *p_item = (wifi_tlv_t *)buffer; 16 | 17 | /* Write element id in destination structure. */ 18 | p_tlv_element->element_id = p_item->element_id; 19 | 20 | /* TODO: ensure element_id exists. */ 21 | 22 | /* Write length in destination structure. */ 23 | p_tlv_element->length = p_item->length; 24 | 25 | /* Copy data into destination structure. */ 26 | p_tlv_element->p_data = (void *)((uint8_t *)buffer + 2); 27 | 28 | /* Succes, return number of bytes parsed. */ 29 | return (p_tlv_element->length + 2); 30 | } 31 | 32 | esp_err_t wifi_pkt_get_type(void *buffer, wifi_pkt_subtype_t *subtype) 33 | { 34 | uint8_t pkt_subtype, pkt_type; 35 | wifi_mac_header_t *p_mac_header = (wifi_mac_header_t *)buffer; 36 | 37 | /* Parse packet type and subtype. */ 38 | pkt_type = (p_mac_header->frame_ctrl >> 2) & 0x03; 39 | pkt_subtype = (p_mac_header->frame_ctrl >> 4) & 0x0F; 40 | 41 | if (pkt_type == PKT_TYPE_MANAGEMENT) 42 | { 43 | /* Return packet subtype. */ 44 | *subtype = (wifi_pkt_subtype_t) pkt_subtype; 45 | return ESP_OK; 46 | } 47 | else 48 | { 49 | /* Unable to dissect non-management frames. */ 50 | return ESP_FAIL; 51 | } 52 | } 53 | 54 | 55 | /** 56 | * wifi_pkt_parse_probe_req() 57 | * 58 | * @brief: Parse a probe request, extract the ESSID field. 59 | * @param buffer: pointer ot a wifi packet as provided by ESP32. 60 | * @param p_probe_req: pointer to a `wifi_probe_req` structure that will be filled by this function. 61 | * @return: ESP_OK on success, ESP_FAIL on error. 62 | **/ 63 | 64 | esp_err_t wifi_pkt_parse_probe_req(void *buffer, wifi_probe_req_t *p_probe_req) 65 | { 66 | wifi_tlv_t tlv_essid; 67 | wifi_pkt_subtype_t subtype; 68 | wifi_mac_header_t *p_mac_header = (wifi_mac_header_t *)buffer; 69 | 70 | if (wifi_pkt_get_type(buffer, &subtype) == ESP_OK) 71 | { 72 | /* Check subtype. */ 73 | if (subtype == PKT_PROBE_REQ) 74 | { 75 | /* Copy MAC header into our probe request structure. */ 76 | memcpy(p_probe_req, p_mac_header, sizeof(wifi_mac_header_t)); 77 | 78 | /* Extract ESSID */ 79 | if (tlv_parse((void *)((uint8_t *)p_mac_header + sizeof(wifi_mac_header_t)), &tlv_essid) > 0) 80 | { 81 | 82 | /* Ensure element ID == ESSID */ 83 | if (tlv_essid.element_id == TLV_ELEMENT_ESSID) 84 | { 85 | /* No more than 32 bytes. */ 86 | if (tlv_essid.length >= 32) 87 | tlv_essid.length = 31; 88 | 89 | /* Save ESSID to our structure. */ 90 | memcpy(p_probe_req->essid, tlv_essid.p_data, tlv_essid.length + 1); 91 | p_probe_req->essid[tlv_essid.length] = 0; 92 | 93 | /* Success. */ 94 | return ESP_OK; 95 | } 96 | else 97 | { 98 | /* Not an ESSID element. */ 99 | return ESP_FAIL; 100 | } 101 | } 102 | else 103 | { 104 | /* Failed parsing ESSID. */ 105 | return ESP_FAIL; 106 | } 107 | 108 | } 109 | else 110 | { 111 | /* Not a probe request. */ 112 | return ESP_FAIL; 113 | } 114 | 115 | } 116 | else 117 | { 118 | /* Not a valid packet. */ 119 | return ESP_FAIL; 120 | } 121 | } 122 | 123 | 124 | /** 125 | * wifi_pkt_parse_probe_rsp() 126 | * 127 | * @brief: Parse a probe response, extract the ESSID field. 128 | * @param buffer: pointer ot a wifi packet as provided by ESP32. 129 | * @param p_probe_req: pointer to a `wifi_probe_rsp` structure that will be filled by this function. 130 | * @return: ESP_OK on success, ESP_FAIL on error. 131 | **/ 132 | 133 | esp_err_t wifi_pkt_parse_probe_rsp(void *buffer, wifi_probe_rsp_t *p_probe_rsp) 134 | { 135 | wifi_tlv_t tlv_essid; 136 | wifi_pkt_subtype_t subtype; 137 | wifi_mac_header_t *p_mac_header = (wifi_mac_header_t *)buffer; 138 | 139 | if (wifi_pkt_get_type(buffer, &subtype) == ESP_OK) 140 | { 141 | /* Check subtype. */ 142 | if (subtype == PKT_PROBE_RSP) 143 | { 144 | /* Copy MAC header into our probe request structure. */ 145 | memcpy(p_probe_rsp, p_mac_header, sizeof(wifi_mac_header_t)); 146 | 147 | /* Extract ESSID */ 148 | if (tlv_parse((void *)((uint8_t *)p_mac_header + sizeof(wifi_mac_header_t) + 12), &tlv_essid) > 0) 149 | { 150 | 151 | /* Ensure element ID == ESSID */ 152 | if (tlv_essid.element_id == TLV_ELEMENT_ESSID) 153 | { 154 | /* No more than 32 bytes. */ 155 | if (tlv_essid.length >= 32) 156 | tlv_essid.length = 31; 157 | 158 | /* Save ESSID to our structure. */ 159 | memcpy(p_probe_rsp->essid, tlv_essid.p_data, tlv_essid.length + 1); 160 | p_probe_rsp->essid[tlv_essid.length] = 0; 161 | 162 | /* Success. */ 163 | return ESP_OK; 164 | } 165 | else 166 | { 167 | /* Not an ESSID element. */ 168 | return ESP_FAIL; 169 | } 170 | } 171 | else 172 | { 173 | /* Failed parsing ESSID. */ 174 | return ESP_FAIL; 175 | } 176 | 177 | } 178 | else 179 | { 180 | /* Not a probe response. */ 181 | return ESP_FAIL; 182 | } 183 | } 184 | else 185 | { 186 | /* Not a valid packet. */ 187 | return ESP_FAIL; 188 | } 189 | } -------------------------------------------------------------------------------- /main/wifi/dissect.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_WIFI_DISSECT_H 2 | #define __INC_WIFI_DISSECT_H 3 | 4 | #include 5 | #include "esp_err.h" 6 | 7 | #define PKT_TYPE_MANAGEMENT 0x00 8 | #define TLV_ELEMENT_ESSID 0x00 9 | 10 | /** 11 | * Enums 12 | **/ 13 | 14 | typedef enum { 15 | PKT_ASSOC_REQ = 0, 16 | PKT_ASSOC_RSP, 17 | PKT_REASSOC_REQ, 18 | PKT_REASSOC_RSP, 19 | PKT_PROBE_REQ, 20 | PKT_PROBE_RSP, 21 | PKT_BEACON = 8, 22 | PKT_ATIM, 23 | PKT_DISASSOC, 24 | PKT_AUTH, 25 | PKT_DEAUTH 26 | } wifi_pkt_subtype_t; 27 | 28 | /** 29 | * Structures 30 | **/ 31 | 32 | typedef struct { 33 | uint8_t element_id; 34 | uint8_t length; 35 | void *p_data; 36 | } wifi_tlv_t; 37 | 38 | typedef struct { 39 | unsigned frame_ctrl:16; 40 | unsigned duration_id:16; 41 | uint8_t addr1[6]; /* receiver address */ 42 | uint8_t addr2[6]; /* sender address */ 43 | uint8_t addr3[6]; /* filtering address */ 44 | unsigned sequence_ctrl:16; 45 | } wifi_mac_header_t; 46 | 47 | 48 | typedef struct { 49 | wifi_mac_header_t header; 50 | char essid[32]; 51 | } wifi_probe_req_t; 52 | 53 | typedef struct { 54 | wifi_mac_header_t header; 55 | char essid[32]; 56 | } wifi_probe_rsp_t; 57 | 58 | /* Exported functions. */ 59 | esp_err_t wifi_pkt_get_type(void *buffer, wifi_pkt_subtype_t *subtype); 60 | esp_err_t wifi_pkt_parse_probe_req(void *buffer, wifi_probe_req_t *p_probe_req); 61 | esp_err_t wifi_pkt_parse_probe_rsp(void *buffer, wifi_probe_rsp_t *p_probe_rsp); 62 | 63 | 64 | 65 | #endif /* __INC_WIFI_DISSECT_H */ -------------------------------------------------------------------------------- /main/wifi/wifi.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_WIFI_H 2 | #define __INC_WIFI_H 3 | 4 | #include "freertos/FreeRTOS.h" 5 | #include "freertos/task.h" 6 | #include "esp_wifi.h" 7 | #include "esp_wifi_types.h" 8 | #include "esp_event.h" 9 | #include "wifi_aplist.h" 10 | 11 | 12 | typedef struct { 13 | unsigned frame_ctrl:16; 14 | unsigned duration_id:16; 15 | uint8_t addr1[6]; /* receiver address */ 16 | uint8_t addr2[6]; /* sender address */ 17 | uint8_t addr3[6]; /* filtering address */ 18 | unsigned sequence_ctrl:16; 19 | uint8_t addr4[6]; /* optional */ 20 | } wifi_ieee80211_mac_hdr_t; 21 | 22 | typedef struct { 23 | 24 | } wifi_ieee80211_probe_resp_t; 25 | 26 | 27 | typedef void (*POSI_func)(void *p1); 28 | 29 | /* 802.11 raw packet feature. */ 30 | extern POSI_func *g_osi_funcs_p; 31 | extern void *g_wifi_global_lock; 32 | void *ic_ebuf_alloc( void *p1, int p2, void *p3); 33 | void *ieee80211_post_hmac_tx(void *param_1); 34 | esp_err_t esp_wifi_80211_tx(wifi_interface_t ifx, const void *buffer, int len, bool en_sys_seq); 35 | esp_err_t ieee80211_raw_frame_sanity_check(void *param_1,void *param_2,void *param_3,void *param_4); 36 | 37 | /* Callback types. */ 38 | typedef void (*FWifiPacketReceivedCb)(wifi_promiscuous_pkt_t *p_wifi_pkt); 39 | 40 | 41 | ESP_EVENT_DECLARE_BASE(WIFI_CTRL_EVENT); 42 | 43 | typedef enum { 44 | SCANNER_IDLE, 45 | SCANNER_RUNNING 46 | } scanner_state_t; 47 | 48 | typedef enum { 49 | WIFI_DRIVER_OFF, 50 | WIFI_DRIVER_STA, 51 | WIFI_DRIVER_AP, 52 | WIFI_DRIVER_APSTA 53 | } wifi_driver_mode_t; 54 | 55 | typedef enum { 56 | WIFI_OFF, 57 | WIFI_SNIFFER, 58 | WIFI_SCANNER, 59 | WIFI_DEAUTH, 60 | WIFI_FAKEAP, 61 | WIFI_ROGUEAP, 62 | WIFI_AP, 63 | WIFI_STA 64 | } wifi_controller_mode_t; 65 | 66 | typedef enum { 67 | WIFI_SCANNER_EVENT_SCAN_DONE = 0, 68 | WIFI_SCANNER_EVENT_APLIST_UPDATED 69 | } wifi_controller_event; 70 | 71 | typedef struct tWifiController { 72 | /* Wifi ESP32 */ 73 | wifi_driver_mode_t driver_mode; 74 | wifi_scan_config_t scan_config; 75 | bool b_enabled; 76 | 77 | /* WiFi controller mode. */ 78 | wifi_controller_mode_t mode; 79 | TaskHandle_t current_task_handle; 80 | 81 | /* WiFi controller AP list. */ 82 | wifi_aplist_t ap_list; 83 | scanner_state_t scan_state; 84 | 85 | /* WiFi deauth */ 86 | uint8_t deauth_target[6]; 87 | int deauth_channel; 88 | 89 | /* WiFi rogueAP */ 90 | wifi_ap_t *p_rogueap_target; 91 | 92 | /* WiFi callback. */ 93 | FWifiPacketReceivedCb pfn_on_packet_received; 94 | 95 | /* Custom event loop. */ 96 | bool evt_loop_initialized; 97 | esp_event_loop_args_t evt_loop_args; 98 | esp_event_loop_handle_t evt_loop_handle; 99 | 100 | } wifi_controller_t; 101 | 102 | /* Initialization. */ 103 | void wifi_ctrl_init(void); 104 | void wifi_set_mode(wifi_controller_mode_t mode); 105 | void wifi_set_channel(int channel); 106 | wifi_controller_mode_t wifi_get_mode(void); 107 | void wifi_deauth_target(uint8_t *p_bssid, int channel); 108 | void wifi_rogueap_set_target(wifi_ap_t *p_target); 109 | void wifi_set_sniffer_handler(FWifiPacketReceivedCb callback); 110 | 111 | /* Event handling. */ 112 | esp_err_t wifi_ctrl_event_handler_register( 113 | int32_t event_id, 114 | esp_event_handler_t event_handler, 115 | void* event_handler_arg 116 | ); 117 | 118 | 119 | 120 | #endif /* __INC_WIFI_H */ -------------------------------------------------------------------------------- /main/wifi/wifi_aplist.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "esp_log.h" 3 | #include "wifi_aplist.h" 4 | 5 | #define TAG "wifi_aplist" 6 | 7 | 8 | /** 9 | * wifi_aplist_init() 10 | * 11 | * @brief: Initialize a list of AP info 12 | * @param p_list: pointer to a `wifi_ap_t` structure 13 | **/ 14 | 15 | void wifi_aplist_init(wifi_aplist_t *p_list) 16 | { 17 | /* Initialize our list. */ 18 | p_list->count = 0; 19 | p_list->p_first = NULL; 20 | 21 | ESP_LOGD(TAG, "list initialized"); 22 | } 23 | 24 | 25 | /** 26 | * wifi_aplist_clean() 27 | **/ 28 | 29 | void wifi_aplist_clean(wifi_aplist_t *p_list) 30 | { 31 | wifi_ap_t *p_item; 32 | wifi_ap_t *p_previous; 33 | 34 | ESP_LOGI(TAG, "Clean list"); 35 | 36 | p_previous = NULL; 37 | p_item = p_list->p_first; 38 | while (p_item != NULL) 39 | { 40 | /* Decrease freshness. */ 41 | p_item->freshness--; 42 | if (p_item->freshness < WIFI_AP_FRESHNESS_OLD) 43 | { 44 | ESP_LOGD(TAG, "%s is not so fresh, removing it", p_item->essid); 45 | 46 | /* Remove item */ 47 | if (p_previous == NULL) 48 | { 49 | /* Update our pointer to the first item and free this item. */ 50 | p_list->p_first = p_item->p_next; 51 | free(p_item); 52 | 53 | /* Go on with the next item. */ 54 | p_item = p_list->p_first; 55 | } 56 | else 57 | { 58 | /* Skip the item to be removed. */ 59 | p_previous->p_next = p_item->p_next; 60 | 61 | /* Free the item (remove). */ 62 | free(p_item); 63 | 64 | /* Go on with next item. */ 65 | p_item = p_previous->p_next; 66 | } 67 | 68 | /* Decrease number of items. */ 69 | p_list->count--; 70 | } 71 | else 72 | { 73 | ESP_LOGD(TAG, "%s is fresh enough", p_item->essid); 74 | 75 | /* Keep previous up-to-date. */ 76 | p_previous = p_item; 77 | 78 | /* Go on with next item. */ 79 | p_item = p_item->p_next; 80 | } 81 | } 82 | } 83 | 84 | 85 | /** 86 | * wifi_aplist_alloc_item() 87 | * 88 | * @brief: Allocate and initialize a list item. 89 | * @param ap: pointer to a `wifi_ap_record` structure. 90 | * @return: pointer to the newly allocated item or NULL on error. 91 | **/ 92 | 93 | wifi_ap_t *wifi_aplist_alloc_item(wifi_ap_record_t *ap) 94 | { 95 | int i; 96 | wifi_ap_t *p_item; 97 | 98 | ESP_LOGD(TAG, "allocate wifi aplist item"); 99 | p_item = (wifi_ap_t *)malloc(sizeof(wifi_ap_t)); 100 | if (p_item != NULL) 101 | { 102 | ESP_LOGD(TAG, "wifi ap item allocated"); 103 | 104 | /* Initialize item. */ 105 | for (i=0; i<6; i++) 106 | p_item->bssid[i] = ap->bssid[i]; 107 | 108 | if (p_item->essid[0] == 0) 109 | { 110 | strncpy((char*)p_item->essid, "", 33); 111 | } 112 | else 113 | { 114 | strncpy((char*)p_item->essid, (char*)ap->ssid, 33); 115 | } 116 | 117 | p_item->rssi = ap->rssi; 118 | p_item->channel = ap->primary; 119 | p_item->auth_mode = ap->authmode; 120 | p_item->pw_cipher = ap->pairwise_cipher; 121 | p_item->gp_cipher = ap->group_cipher; 122 | p_item->freshness = WIFI_AP_FRESHNESS_MAX; 123 | 124 | /* No next item. */ 125 | p_item->p_next = NULL; 126 | 127 | /* Return item. */ 128 | return p_item; 129 | } 130 | else 131 | { 132 | ESP_LOGE(TAG, "memory error: could not allocate item"); 133 | 134 | /* Could not allocate, return NULL. */ 135 | return NULL; 136 | } 137 | } 138 | 139 | 140 | void wifi_aplist_add(wifi_aplist_t *p_list, wifi_ap_record_t *ap) 141 | { 142 | wifi_ap_t *p_item, *p_anchor; 143 | 144 | if (p_list->count == 0) 145 | { 146 | ESP_LOGD(TAG, "list is empty, allocating item"); 147 | p_item = wifi_aplist_alloc_item(ap); 148 | if (p_item != NULL) 149 | { 150 | ESP_LOGD(TAG, "saving item to list"); 151 | /* Save item. */ 152 | p_list->p_first = p_item; 153 | p_list->count++; 154 | } 155 | } 156 | else if (p_list->p_first != NULL) 157 | { 158 | ESP_LOGD(TAG, "list not empty, looking for an existing ap ..."); 159 | 160 | /* First, we walk the list to avoid a potential double. */ 161 | p_item = p_list->p_first; 162 | while (p_item != NULL) 163 | { 164 | /* Do we already know this AP ? */ 165 | if (!memcmp(p_item->bssid, ap->bssid, 6)) 166 | { 167 | ESP_LOGD(TAG, "found this ap, updating data ..."); 168 | 169 | /* Yep, update its info. */ 170 | memcpy(p_item->essid, ap->ssid, 33); 171 | 172 | p_item->rssi = ap->rssi; 173 | p_item->channel = ap->primary; 174 | p_item->auth_mode = ap->authmode; 175 | p_item->pw_cipher = ap->pairwise_cipher; 176 | p_item->gp_cipher = ap->group_cipher; 177 | p_item->freshness = WIFI_AP_FRESHNESS_MAX; 178 | 179 | /* Item added, exit. */ 180 | return; 181 | } 182 | else if (p_item->p_next == NULL) 183 | { 184 | break; 185 | } 186 | else 187 | /* Go to the next item. */ 188 | p_item = p_item->p_next; 189 | } 190 | 191 | ESP_LOGD(TAG, "ap not found, inserting info into our list"); 192 | 193 | /* Add AP if there is some space left. */ 194 | if (p_list->count < WIFI_APLIST_MAX_NUMBER) 195 | { 196 | /* Item is appended at the end of the list. */ 197 | p_anchor = p_item; 198 | p_item = wifi_aplist_alloc_item(ap); 199 | if (p_item != NULL) 200 | { 201 | /* Link item. */ 202 | p_anchor->p_next = p_item; 203 | p_list->count++; 204 | 205 | } 206 | } 207 | } 208 | } 209 | 210 | /** 211 | * wifi_aplist_enum_first() 212 | * 213 | * @brief: Retrieve the first item of an AP list. 214 | * @param p_list: pointer to a `wifi_aplist_t` structure 215 | * @return: a pointer to the first wifi_ap_t structure of the list, NULL otherwise 216 | **/ 217 | 218 | wifi_ap_t *wifi_aplist_enum_first(wifi_aplist_t *p_list) 219 | { 220 | if (p_list->p_first != NULL) 221 | return p_list->p_first; 222 | else 223 | return NULL; 224 | } 225 | 226 | 227 | /** 228 | * wifi_aplist_enum_next() 229 | * 230 | * @brief: Retrieve the next item of an AP list. 231 | * @param p_list: pointer to the previous `wifi_ap_t` structure 232 | * @return: a pointer to the first wifi_ap_t structure of the list, NULL otherwise 233 | **/ 234 | 235 | wifi_ap_t *wifi_aplist_enum_next(wifi_ap_t *ap) 236 | { 237 | if (ap->p_next != NULL) 238 | return ap->p_next; 239 | else 240 | return NULL; 241 | } -------------------------------------------------------------------------------- /main/wifi/wifi_aplist.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_WIFI_AP_H 2 | #define __INC_WIFI_AP_H 3 | 4 | #define WIFI_APLIST_MAX_NUMBER 30 5 | #define WIFI_AP_FRESHNESS_MAX 20 6 | #define WIFI_AP_FRESHNESS_OLD 5 7 | 8 | #include "esp_wifi.h" 9 | 10 | typedef struct t_wifi_ap { 11 | struct t_wifi_ap *p_next; 12 | uint8_t essid[33]; 13 | uint8_t bssid[6]; 14 | uint8_t channel; 15 | int8_t rssi; 16 | wifi_auth_mode_t auth_mode; 17 | wifi_auth_mode_t pw_cipher; 18 | wifi_cipher_type_t gp_cipher; 19 | uint8_t freshness; 20 | } wifi_ap_t; 21 | 22 | typedef struct { 23 | wifi_ap_t *p_first; 24 | int count; 25 | } wifi_aplist_t; 26 | 27 | void wifi_aplist_init(wifi_aplist_t *p_list); 28 | void wifi_aplist_add(wifi_aplist_t *p_list, wifi_ap_record_t *ap); 29 | void wifi_aplist_clean(wifi_aplist_t *p_list); 30 | wifi_ap_t *wifi_aplist_enum_first(wifi_aplist_t *p_list); 31 | wifi_ap_t *wifi_aplist_enum_next(wifi_ap_t *ap); 32 | 33 | 34 | #endif /* __INC_WIFI_AP_H */ -------------------------------------------------------------------------------- /main/wifi/wifiscan.c: -------------------------------------------------------------------------------- 1 | 2 | #define LOG_LOCAL_LEVEL ESP_LOG_INFO 3 | #include "esp_log.h" 4 | #include "wifiscan.h" 5 | 6 | 7 | /************************************** 8 | * AccessPoint ListItem widget 9 | *************************************/ 10 | 11 | uint16_t wscan_get_rssi_color(int rssi) 12 | { 13 | if (rssi <= WSCAN_RSSI_LOW) 14 | return WSCAN_RSSI_LOW_COLOR; 15 | 16 | if (rssi <= WSCAN_RSSI_MEDIUM) 17 | return WSCAN_RSSI_MEDIUM_COLOR; 18 | 19 | return WSCAN_RSSI_GOOD_COLOR; 20 | } 21 | 22 | 23 | /** 24 | * wscan_widget_listitem_event_handler() 25 | * 26 | * @brief: Wifi scan widget listitem event handler. 27 | * @param event: UI event. 28 | * @param x: X screen coordinate 29 | * @param y: Y screen coordinate 30 | * @param velocity: swipe speed (not used). 31 | * @return: WE_PROCESSED if event has been processed, WE_ERROR otherwise. 32 | **/ 33 | 34 | int wscan_widget_listitem_event_handler(widget_t *p_widget, widget_event_t event, int x, int y, int velocity) 35 | { 36 | bool b_processed = false; 37 | wifiscan_widget_listitem_t *p_listitem = (wifiscan_widget_listitem_t *)p_widget->p_user_data; 38 | 39 | if (p_listitem != NULL) 40 | { 41 | switch (event) 42 | { 43 | 44 | case LB_ITEM_SELECTED: 45 | { 46 | /* Mark list item as selected. */ 47 | p_listitem->b_selected = true; 48 | b_processed = true; 49 | } 50 | break; 51 | 52 | case LB_ITEM_DESELECTED: 53 | { 54 | p_listitem->b_selected = false; 55 | b_processed = true; 56 | } 57 | break; 58 | 59 | default: 60 | break; 61 | } 62 | 63 | /* Event processed (or not) */ 64 | return b_processed; 65 | } 66 | 67 | /* Event not processed. */ 68 | return WE_ERROR; 69 | } 70 | 71 | 72 | /** 73 | * wscan_widget_listitem_drawfunc() 74 | * 75 | * @brief: Wifiscan listitem widget drawing function. 76 | * @param p_widget: pointer to a `widget_t` structure. 77 | **/ 78 | 79 | int wscan_widget_listitem_drawfunc(widget_t *p_widget) 80 | { 81 | char bssid[18]; 82 | char channel[4]; 83 | 84 | wifiscan_widget_listitem_t *p_listitem = (wifiscan_widget_listitem_t *)p_widget->p_user_data; 85 | 86 | if (p_listitem != NULL) 87 | { 88 | if (p_listitem->p_ap != NULL) 89 | { 90 | 91 | /* Draw background. */ 92 | widget_fill_region( 93 | p_widget, 94 | 1, 95 | 1, 96 | p_widget->box.width - 2, 97 | p_widget->box.height - 2, 98 | (p_listitem->b_selected)?p_widget->style.front:p_widget->style.background 99 | ); 100 | 101 | /* Draw ESSID. */ 102 | widget_draw_text_x2( 103 | p_widget, 104 | 5, 105 | 5, 106 | (char *)p_listitem->p_ap->essid, 107 | wscan_get_rssi_color(p_listitem->p_ap->rssi) 108 | ); 109 | 110 | /* Draw BSSID. */ 111 | snprintf( 112 | bssid, 113 | 18, 114 | "%02X:%02X:%02X:%02X:%02X:%02X", 115 | p_listitem->p_ap->bssid[0], 116 | p_listitem->p_ap->bssid[1], 117 | p_listitem->p_ap->bssid[2], 118 | p_listitem->p_ap->bssid[3], 119 | p_listitem->p_ap->bssid[4], 120 | p_listitem->p_ap->bssid[5] 121 | ); 122 | widget_draw_text( 123 | p_widget, 124 | 5, 125 | 5 + 36, 126 | bssid, 127 | (p_listitem->b_selected)?p_widget->style.background:p_widget->style.front 128 | ); 129 | 130 | /* Draw BSSID. */ 131 | snprintf(channel, 4, "%d", p_listitem->p_ap->channel); 132 | widget_draw_text( 133 | p_widget, 134 | p_widget->box.width - 5 - 20, 135 | 5 + 36, 136 | channel, 137 | (p_listitem->b_selected)?p_widget->style.background:p_widget->style.front 138 | ); 139 | } 140 | } 141 | /* Success. */ 142 | return TE_PROCESSED; 143 | } 144 | 145 | 146 | /** 147 | * wscan_widget_listitem_init() 148 | * 149 | * @brief: Wifiscan listitem widget initialization. 150 | * @param p_listitem: pointer to a `wifiscan_widget_listitem_t` structure 151 | * @param p_ap: pointer to a `wifi_ap_t` structure. 152 | **/ 153 | 154 | void wscan_widget_listitem_init(wifiscan_widget_listitem_t *p_listitem, wifi_ap_t *p_ap) 155 | { 156 | /* Initialize our widget. */ 157 | widget_init(&p_listitem->widget, NULL, 0, 0, 0, WSCAN_LISTITEM_HEIGHT); 158 | 159 | /* Set parameters. */ 160 | p_listitem->p_ap = p_ap; 161 | p_listitem->b_selected = false; 162 | 163 | /* Set userdata. */ 164 | widget_set_userdata(&p_listitem->widget, (void *)p_listitem); 165 | 166 | /* Set drawing function. */ 167 | widget_set_drawfunc(&p_listitem->widget, wscan_widget_listitem_drawfunc); 168 | 169 | /* Set default event handler. */ 170 | widget_set_eventhandler(&p_listitem->widget, wscan_widget_listitem_event_handler); 171 | } 172 | 173 | 174 | /** 175 | * wscan_aplist_update_handler() 176 | * 177 | * @brief: Wifi scanner callback 178 | * @param arg: pointer to a `wifiscan_t` structure 179 | * @param event_base: ESP32 event base information 180 | * @param event_id: ESP32 event ID 181 | * @param event_data: pointer to an array of `wifi_aplist_t` structure 182 | **/ 183 | 184 | static void wscan_aplist_update_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) 185 | { 186 | int list_nb_aps, i; 187 | wifiscan_t *p_wifiscan = (wifiscan_t *)arg; 188 | wifi_aplist_t *p_list = (wifi_aplist_t *)event_data; 189 | wifi_ap_t *p_ap_record; 190 | 191 | 192 | /* Add all scanned access points. */ 193 | list_nb_aps = 0; 194 | p_ap_record = wifi_aplist_enum_first(p_list); 195 | if (p_ap_record != NULL) 196 | { 197 | do 198 | { 199 | ESP_LOGD( 200 | TAG, 201 | "AP: [%02x:%02x:%02x:%02x:%02x:%02x] %s (%d) frsh:%d", 202 | p_ap_record->bssid[0], 203 | p_ap_record->bssid[1], 204 | p_ap_record->bssid[2], 205 | p_ap_record->bssid[3], 206 | p_ap_record->bssid[4], 207 | p_ap_record->bssid[5], 208 | p_ap_record->essid, 209 | p_ap_record->rssi, 210 | p_ap_record->freshness 211 | ); 212 | 213 | list_nb_aps++; 214 | 215 | if ((list_nb_aps > p_wifiscan->nb_aps) && (p_wifiscan->nb_aps < WSCAN_MAX_APS)) 216 | { 217 | p_wifiscan->aps[list_nb_aps-1].p_ap = p_ap_record; 218 | widget_listbox_add(&p_wifiscan->listbox, (widget_t *)&p_wifiscan->aps[list_nb_aps-1]); 219 | p_wifiscan->nb_aps++; 220 | } 221 | else 222 | { 223 | p_wifiscan->aps[list_nb_aps-1].p_ap = p_ap_record; 224 | } 225 | } 226 | while ((p_ap_record = wifi_aplist_enum_next(p_ap_record)) != NULL); 227 | } 228 | 229 | /* Remove old access points (no more detected). */ 230 | if ((p_wifiscan->nb_aps > list_nb_aps) && (list_nb_aps > 0)) 231 | { 232 | for (i=list_nb_aps; inb_aps; i++) 233 | { 234 | ESP_LOGD(TAG, "Remove item %s", p_wifiscan->aps[i].p_ap->essid); 235 | widget_listbox_remove(&p_wifiscan->listbox, (widget_t *)&p_wifiscan->aps[i]); 236 | } 237 | 238 | /* Update number of aps. */ 239 | p_wifiscan->nb_aps = list_nb_aps; 240 | } 241 | } 242 | 243 | 244 | int wscan_listbox_event_hook(widget_t *p_widget, widget_event_t event, int x, int y, int velocity) 245 | { 246 | wifiscan_t *p_wifiscan = (wifiscan_t *)p_widget; 247 | 248 | /* Only capture the LB_ITEM_SELECTED event. */ 249 | if (event == LB_ITEM_SELECTED) 250 | { 251 | /* Forward to our custom event handler. */ 252 | if (p_wifiscan->pfn_event_handler != NULL) 253 | { 254 | p_wifiscan->pfn_event_handler(WS_EVENT_SELECTED); 255 | } 256 | } 257 | 258 | /* Forward event to our listbox. */ 259 | return p_wifiscan->pfn_event_hook(p_widget, event, x, y, velocity); 260 | } 261 | 262 | /** 263 | * wifiscan_init() 264 | * 265 | * @brief: Initialize a wifiscan widget 266 | * @param p_wifiscan: pointer to a `wifiscan_t` structure 267 | * @param p_tile: pointer to a `tile_t` structure (parent tile) 268 | * @param x: widget X coordinate 269 | * @param y: widget Y coordinate 270 | * @param width: widget width 271 | * @param height: widget height 272 | **/ 273 | 274 | void wifiscan_init(wifiscan_t *p_wifiscan, tile_t *p_tile, int x, int y, int width, int height) 275 | { 276 | int i; 277 | 278 | /* Add a listbox inside this tile. */ 279 | widget_listbox_init( 280 | (widget_listbox_t *)p_wifiscan, 281 | p_tile, 282 | x, 283 | y, 284 | width, 285 | height 286 | ); 287 | 288 | /* Set listbox border color. */ 289 | widget_set_border_color(&p_wifiscan->listbox.widget, RGB(0x1, 0x2, 0x3)); 290 | 291 | /* Set listbox's scrollbar border color. */ 292 | widget_set_border_color(&p_wifiscan->listbox.scrollbar.widget, RGB(0x1, 0x2, 0x3)); 293 | 294 | 295 | p_wifiscan->pfn_event_hook = widget_set_eventhandler((widget_t *)p_wifiscan, wscan_listbox_event_hook); 296 | 297 | /* Register a specific handler for scanning events. */ 298 | wifi_ctrl_event_handler_register( 299 | WIFI_SCANNER_EVENT_APLIST_UPDATED, 300 | wscan_aplist_update_handler, 301 | p_wifiscan 302 | ); 303 | 304 | /* Set parameters. */ 305 | p_wifiscan->nb_aps = 0; 306 | 307 | /* Initialize all of our labels. */ 308 | for (i=0; iaps[i], 312 | NULL 313 | ); 314 | } 315 | } 316 | 317 | 318 | /** 319 | * wifiscan_get_selected() 320 | * 321 | * @brief: Retrieve the selected AP. 322 | * @param p_wifiscan: pointer to a `wifiscan_t` structure 323 | * @return: pointer to a `wifi_ap_t` structure, or NULL if none has been selected. 324 | **/ 325 | 326 | wifi_ap_t *wifiscan_get_selected(wifiscan_t *p_wifiscan) 327 | { 328 | int i; 329 | 330 | for (i=0; inb_aps; i++) 331 | { 332 | if (p_wifiscan->aps[i].b_selected) 333 | { 334 | /* AP selected returned. */ 335 | return p_wifiscan->aps[i].p_ap; 336 | } 337 | } 338 | 339 | /* No AP selected. */ 340 | return NULL; 341 | } 342 | 343 | 344 | /** 345 | * wifiscan_set_event_handler() 346 | * 347 | * @brief: Set wifiscan event handler. 348 | * @param p_wifiscan: pointer to a `wifiscan_t` structure 349 | * @param pfn_event_handler: pointer to a FWifiscanEventHandler callback function. 350 | **/ 351 | 352 | void wifiscan_set_event_handler(wifiscan_t *p_wifiscan, FWifiscanEventHandler pfn_event_handler) 353 | { 354 | p_wifiscan->pfn_event_handler = pfn_event_handler; 355 | } -------------------------------------------------------------------------------- /main/wifi/wifiscan.h: -------------------------------------------------------------------------------- 1 | #ifndef __INC_WIFISCAN_H 2 | #define __INC_WIFISCAN_H 3 | 4 | #include "esp_log.h" 5 | 6 | #include "ui/ui.h" 7 | #include "ui/listbox.h" 8 | #include "ui/label.h" 9 | #include "wifi.h" 10 | 11 | #define TAG "[wifiscan]" 12 | 13 | #define WSCAN_LISTBOX_X 10 14 | #define WSCAN_LISTBOX_Y 10 15 | #define WSCAN_LISTBOX_W 220 16 | #define WSCAN_LISTBOX_H 220 17 | 18 | #define WSCAN_LISTITEM_HEIGHT 60 19 | 20 | #define WSCAN_RSSI_LOW -90 21 | #define WSCAN_RSSI_LOW_COLOR RGB(3, 0, 0) 22 | #define WSCAN_RSSI_MEDIUM -60 23 | #define WSCAN_RSSI_MEDIUM_COLOR RGB(3, 2, 0) 24 | #define WSCAN_RSSI_GOOD_COLOR RGB(0, 3, 0) 25 | 26 | 27 | #define WSCAN_MAX_APS WIFI_APLIST_MAX_NUMBER 28 | 29 | typedef enum { 30 | WS_EVENT_SELECTED 31 | } wifiscan_event_t; 32 | 33 | /* Event callback type. */ 34 | typedef void (*FWifiscanEventHandler)(wifiscan_event_t event); 35 | 36 | /* AccessPoint ListItem widget. */ 37 | typedef struct { 38 | 39 | /* Base widget. */ 40 | widget_t widget; 41 | 42 | /* AP infos */ 43 | wifi_ap_t *p_ap; 44 | 45 | /* Selected. */ 46 | bool b_selected; 47 | } wifiscan_widget_listitem_t; 48 | 49 | 50 | /* Wifiscan widget structure. */ 51 | typedef struct { 52 | widget_listbox_t listbox; 53 | 54 | tile_t tile_scanner; 55 | wifiscan_widget_listitem_t aps[WSCAN_MAX_APS]; 56 | int nb_aps; 57 | 58 | /* Listbox event hook. */ 59 | FEventHandler pfn_event_hook; 60 | 61 | /* Event callback. */ 62 | FWifiscanEventHandler pfn_event_handler; 63 | 64 | } wifiscan_t; 65 | 66 | void wifiscan_init(wifiscan_t *p_wifiscan, tile_t *p_tile, int x, int y, int width, int height); 67 | wifi_ap_t *wifiscan_get_selected(wifiscan_t *p_wifiscan); 68 | void wifiscan_set_event_handler(wifiscan_t *p_wifiscan, FWifiscanEventHandler pfn_event_handler); 69 | 70 | #endif /* __INC_WIFISCAN_H */ -------------------------------------------------------------------------------- /resources/apple.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/resources/apple.xcf -------------------------------------------------------------------------------- /resources/ble-icons-big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/resources/ble-icons-big.png -------------------------------------------------------------------------------- /resources/ble-icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/resources/ble-icons.png -------------------------------------------------------------------------------- /resources/ble-icons.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/resources/ble-icons.xcf -------------------------------------------------------------------------------- /resources/ble.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/resources/ble.xcf -------------------------------------------------------------------------------- /resources/cat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/resources/cat.png -------------------------------------------------------------------------------- /resources/digits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/resources/digits.png -------------------------------------------------------------------------------- /resources/digits.sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/resources/digits.sprite.png -------------------------------------------------------------------------------- /resources/digits.sprite.small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/resources/digits.sprite.small.png -------------------------------------------------------------------------------- /resources/digits.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/resources/digits.xcf -------------------------------------------------------------------------------- /resources/fitbit.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/resources/fitbit.xcf -------------------------------------------------------------------------------- /resources/heart.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/resources/heart.xcf -------------------------------------------------------------------------------- /resources/icon-ir.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 21 | 40 | 42 | 43 | 45 | image/svg+xml 46 | 48 | 49 | 50 | 51 | 52 | 56 | 59 | 61 | 66 | 74 | 75 | 78 | 83 | 87 | 93 | 99 | 100 | 101 | 102 | 111 | 116 | 119 | 128 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /resources/ir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/resources/ir.png -------------------------------------------------------------------------------- /resources/ir_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/resources/ir_small.png -------------------------------------------------------------------------------- /resources/keyfob.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/resources/keyfob.xcf -------------------------------------------------------------------------------- /resources/music.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/resources/music.xcf -------------------------------------------------------------------------------- /resources/triangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/resources/triangle.png -------------------------------------------------------------------------------- /resources/unknown.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/resources/unknown.xcf -------------------------------------------------------------------------------- /resources/watch.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/resources/watch.xcf -------------------------------------------------------------------------------- /resources/wifi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/resources/wifi.png -------------------------------------------------------------------------------- /triangle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/triangle.png -------------------------------------------------------------------------------- /wifi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/virtualabs/hackwatch/eab12300a60156222f9dc09f72db053875563b87/wifi.png --------------------------------------------------------------------------------