diff --git a/.gitignore b/.gitignore
index 9447032..7962d0a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -113,3 +113,4 @@ compile_commands.json
CTestTestfile.cmake
_deps
+c/build
\ No newline at end of file
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/P2FA.iml b/.idea/P2FA.iml
new file mode 100644
index 0000000..5e764c4
--- /dev/null
+++ b/.idea/P2FA.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/P2FA2.iml b/.idea/P2FA2.iml
new file mode 100644
index 0000000..f08604b
--- /dev/null
+++ b/.idea/P2FA2.iml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..2885ac9
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..7175db8
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 0297673..a6f4539 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,5 @@
# P2FA
+Hardware 2FA Manager
+
+https://www.adafruit.com/product/4282
\ No newline at end of file
diff --git a/c/CMakeLists.txt b/c/CMakeLists.txt
new file mode 100644
index 0000000..f02c6ca
--- /dev/null
+++ b/c/CMakeLists.txt
@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION 3.10)
+project(P2FA)
+
+set(CMAKE_C_STANDARD 99)
+set(CMAKE_CXX_STANDARD 11)
+
+add_library(p2fa SHARED p2fa.c
+ p2fa.h)
+
+set_target_properties(p2fa PROPERTIES
+ LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/build"
+ OUTPUT_NAME "p2fa"
+)
\ No newline at end of file
diff --git a/c/build.ps1 b/c/build.ps1
new file mode 100644
index 0000000..5e9c9c8
--- /dev/null
+++ b/c/build.ps1
@@ -0,0 +1,4 @@
+Get-ChildItem -Path build -Recurse | Remove-Item -force -recurse
+if (Test-Path -Path .\build) { Remove-Item -Path .\build -Recurse -Force }
+cmake -DCMAKE_BUILD_TYPE=Release -G "CodeBlocks - MinGW Makefiles" -S . -B .\build
+cmake --build .\build --target p2fa -- -j 14
\ No newline at end of file
diff --git a/c/libs/Config/DEV_Config.h b/c/libs/Config/DEV_Config.h
new file mode 100644
index 0000000..f22979a
--- /dev/null
+++ b/c/libs/Config/DEV_Config.h
@@ -0,0 +1,119 @@
+/*****************************************************************************
+* | File : DEV_Config.h
+* | Author : Waveshare team
+* | Function : Hardware underlying interface
+* | Info :
+* Used to shield the underlying layers of each master
+* and enhance portability
+*----------------
+* | This version: V2.0
+* | Date : 2018-10-30
+* | Info :
+* 1.add:
+* UBYTE\UWORD\UDOUBLE
+* 2.Change:
+* EPD_RST -> EPD_RST_PIN
+* EPD_DC -> EPD_DC_PIN
+* EPD_CS -> EPD_CS_PIN
+* EPD_BUSY -> EPD_BUSY_PIN
+* 3.Remote:
+* EPD_RST_1\EPD_RST_0
+* EPD_DC_1\EPD_DC_0
+* EPD_CS_1\EPD_CS_0
+* EPD_BUSY_1\EPD_BUSY_0
+* 3.add:
+* #define DEV_Digital_Write(_pin, _value) bcm2835_GPIOI_write(_pin, _value)
+* #define DEV_Digital_Read(_pin) bcm2835_GPIOI_lev(_pin)
+* #define DEV_SPI_WriteByte(__value) bcm2835_spi_transfer(__value)
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documnetation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+******************************************************************************/
+#ifndef _DEV_CONFIG_H_
+#define _DEV_CONFIG_H_
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "Debug.h"
+
+#ifdef RPI
+#ifdef USE_BCM2835_LIB
+ #include
+ #elif USE_WIRINGPI_LIB
+ #include
+ #include
+ #elif USE_LGPIO_LIB
+ #include
+ #define LFLAGS 0
+ #define NUM_MAXBUF 4
+ #elif USE_DEV_LIB
+ #include "RPI_gpiod.h"
+ #include "dev_hardware_SPI.h"
+ #endif
+#endif
+
+#ifdef JETSON
+#ifdef USE_DEV_LIB
+ #include "sysfs_gpio.h"
+ #include "sysfs_software_spi.h"
+ #elif USE_HARDWARE_LIB
+
+ #endif
+
+#endif
+
+/**
+ * data
+**/
+#define UBYTE uint8_t
+#define UWORD uint16_t
+#define UDOUBLE uint32_t
+
+/**
+ * GPIOI config
+**/
+extern int EPD_RST_PIN;
+extern int EPD_DC_PIN;
+extern int EPD_CS_PIN;
+extern int EPD_BUSY_PIN;
+extern int EPD_PWR_PIN;
+extern int EPD_MOSI_PIN;
+extern int EPD_SCLK_PIN;
+
+/*------------------------------------------------------------------------------------------------------*/
+void DEV_Digital_Write(UWORD Pin, UBYTE Value);
+UBYTE DEV_Digital_Read(UWORD Pin);
+
+void DEV_SPI_WriteByte(UBYTE Value);
+void DEV_SPI_Write_nByte(uint8_t *pData, uint32_t Len);
+void DEV_Delay_ms(UDOUBLE xms);
+
+void DEV_SPI_SendData(UBYTE Reg);
+void DEV_SPI_SendnData(UBYTE *Reg);
+UBYTE DEV_SPI_ReadData();
+
+UBYTE DEV_Module_Init(void);
+void DEV_Module_Exit(void);
+
+
+#endif
\ No newline at end of file
diff --git a/c/libs/Config/Debug.h b/c/libs/Config/Debug.h
new file mode 100644
index 0000000..f554726
--- /dev/null
+++ b/c/libs/Config/Debug.h
@@ -0,0 +1,46 @@
+/*****************************************************************************
+* | File : Debug.h
+* | Author : Waveshare team
+* | Function : debug with printf
+* | Info :
+* Image scanning
+* Please use progressive scanning to generate images or fonts
+*----------------
+* | This version: V2.0
+* | Date : 2018-10-30
+* | Info :
+* 1.USE_DEBUG -> DEBUG, If you need to see the debug information,
+* clear the execution: make DEBUG=-DDEBUG
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documnetation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+
+******************************************************************************/
+#ifndef __DEBUG_H
+#define __DEBUG_H
+
+#include
+
+#if DEBUG
+#define Debug(__info,...) printf("Debug: " __info,##__VA_ARGS__)
+#else
+#define Debug(__info,...)
+#endif
+
+#endif
\ No newline at end of file
diff --git a/c/libs/EPD_2in13_V4.h b/c/libs/EPD_2in13_V4.h
new file mode 100644
index 0000000..a700e7b
--- /dev/null
+++ b/c/libs/EPD_2in13_V4.h
@@ -0,0 +1,53 @@
+/*****************************************************************************
+* | File : EPD_2Iin13_V4.h
+* | Author : Waveshare team
+* | Function : 2.13inch e-paper V4
+* | Info :
+*----------------
+* | This version: V1.1
+* | Date : 2021-10-30
+* | Info :
+* -----------------------------------------------------------------------------
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documnetation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+******************************************************************************/
+#ifndef __EPD_2in13_V4_H_
+#define __EPD_2in13_V4_H_
+
+#include "Config/DEV_Config.h"
+
+
+// Display resolution
+#define EPD_2in13_V4_WIDTH 122
+#define EPD_2in13_V4_HEIGHT 250
+
+void EPD_2in13_V4_Init(void);
+void EPD_2in13_V4_Init_Fast(void);
+void EPD_2in13_V4_Init_GUI(void);
+void EPD_2in13_V4_Clear(void);
+void EPD_2in13_V4_Clear_Black(void);
+void EPD_2in13_V4_Display(UBYTE *Image);
+void EPD_2in13_V4_Display_Fast(UBYTE *Image);
+void EPD_2in13_V4_Display_Base(UBYTE *Image);
+void EPD_2in13_V4_Display_Partial(UBYTE *Image);
+void EPD_2in13_V4_Sleep(void);
+
+
+#endif
\ No newline at end of file
diff --git a/c/libs/Fonts/fonts.h b/c/libs/Fonts/fonts.h
new file mode 100644
index 0000000..bdd9f97
--- /dev/null
+++ b/c/libs/Fonts/fonts.h
@@ -0,0 +1,97 @@
+/**
+ ******************************************************************************
+ * @file fonts.h
+ * @author MCD Application Team
+ * @version V1.0.0
+ * @date 18-February-2014
+ * @brief Header for fonts.c file
+ ******************************************************************************
+ * @attention
+ *
+ * © COPYRIGHT(c) 2014 STMicroelectronics
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of STMicroelectronics nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __FONTS_H
+#define __FONTS_H
+
+/*最大字体微软雅黑24 (32x41) */
+#define MAX_HEIGHT_FONT 41
+#define MAX_WIDTH_FONT 32
+#define OFFSET_BITMAP
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include
+
+//ASCII
+typedef struct _tFont
+{
+ const uint8_t *table;
+ uint16_t Width;
+ uint16_t Height;
+
+} sFONT;
+
+
+//GB2312
+typedef struct // 汉字字模数据结构
+{
+ const char index[2]; // 汉字内码索引
+ const char matrix[MAX_HEIGHT_FONT*MAX_WIDTH_FONT/8+2]; // 点阵码数据
+}CH_CN;
+
+
+typedef struct
+{
+ const CH_CN *table;
+ uint16_t size;
+ uint16_t ASCII_Width;
+ uint16_t Width;
+ uint16_t Height;
+
+}cFONT;
+
+extern sFONT Font24;
+extern sFONT Font20;
+extern sFONT Font16;
+extern sFONT Font12;
+extern sFONT Font8;
+
+extern cFONT Font12CN;
+extern cFONT Font24CN;
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __FONTS_H */
+
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
\ No newline at end of file
diff --git a/c/libs/GUI/GUI_BMPfile.h b/c/libs/GUI/GUI_BMPfile.h
new file mode 100644
index 0000000..78e512c
--- /dev/null
+++ b/c/libs/GUI/GUI_BMPfile.h
@@ -0,0 +1,94 @@
+/*****************************************************************************
+* | File : GUI_BMPfile.h
+* | Author : Waveshare team
+* | Function : Hardware underlying interface
+* | Info :
+* Used to shield the underlying layers of each master
+* and enhance portability
+*----------------
+* | This version: V2.3
+* | Date : 2020-07-27
+* | Info :
+* -----------------------------------------------------------------------------
+* V2.3(2022-07-27):
+* 1.Add GUI_ReadBmp_RGB_4Color()
+* V2.2(2020-07-08):
+* 1.Add GUI_ReadBmp_RGB_7Color()
+* V2.1(2019-10-10):
+* 1.Add GUI_ReadBmp_4Gray()
+* V2.0(2018-11-12):
+* 1.Change file name: GUI_BMP.h -> GUI_BMPfile.h
+* 2.fix: GUI_ReadBmp()
+* Now Xstart and Xstart can control the position of the picture normally,
+* and support the display of images of any size. If it is larger than
+* the actual display range, it will not be displayed.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documnetation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+******************************************************************************/
+#ifndef __GUI_BMPFILE_H
+#define __GUI_BMPFILE_H
+
+#include
+#include
+#include
+#include
+
+#include "../Config/DEV_Config.h"
+
+/*Bitmap file header 14bit*/
+typedef struct BMP_FILE_HEADER {
+ UWORD bType; //File identifier
+ UDOUBLE bSize; //The size of the file
+ UWORD bReserved1; //Reserved value, must be set to 0
+ UWORD bReserved2; //Reserved value, must be set to 0
+ UDOUBLE bOffset; //The offset from the beginning of the file header to the beginning of the image data bit
+} __attribute__ ((packed)) BMPFILEHEADER; // 14bit
+
+/*Bitmap information header 40bit*/
+typedef struct BMP_INFO {
+ UDOUBLE biInfoSize; //The size of the header
+ UDOUBLE biWidth; //The width of the image
+ UDOUBLE biHeight; //The height of the image
+ UWORD biPlanes; //The number of planes in the image
+ UWORD biBitCount; //The number of bits per pixel
+ UDOUBLE biCompression; //Compression type
+ UDOUBLE bimpImageSize; //The size of the image, in bytes
+ UDOUBLE biXPelsPerMeter; //Horizontal resolution
+ UDOUBLE biYPelsPerMeter; //Vertical resolution
+ UDOUBLE biClrUsed; //The number of colors used
+ UDOUBLE biClrImportant; //The number of important colors
+} __attribute__ ((packed)) BMPINFOHEADER;
+
+/*Color table: palette */
+typedef struct RGB_QUAD {
+ UBYTE rgbBlue; //Blue intensity
+ UBYTE rgbGreen; //Green strength
+ UBYTE rgbRed; //Red intensity
+ UBYTE rgbReversed; //Reserved value
+} __attribute__ ((packed)) BMPRGBQUAD;
+/**************************************** end ***********************************************/
+
+UBYTE GUI_ReadBmp(const char *path, UWORD Xstart, UWORD Ystart);
+UBYTE GUI_ReadBmp_4Gray(const char *path, UWORD Xstart, UWORD Ystart);
+UBYTE GUI_ReadBmp_16Gray(const char *path, UWORD Xstart, UWORD Ystart);
+UBYTE GUI_ReadBmp_RGB_4Color(const char *path, UWORD Xstart, UWORD Ystart);
+UBYTE GUI_ReadBmp_RGB_6Color(const char *path, UWORD Xstart, UWORD Ystart);
+UBYTE GUI_ReadBmp_RGB_7Color(const char *path, UWORD Xstart, UWORD Ystart);
+#endif
\ No newline at end of file
diff --git a/c/libs/GUI/GUI_Paint.h b/c/libs/GUI/GUI_Paint.h
new file mode 100644
index 0000000..8bfbfe1
--- /dev/null
+++ b/c/libs/GUI/GUI_Paint.h
@@ -0,0 +1,212 @@
+/******************************************************************************
+* | File : GUI_Paint.h
+* | Author : Waveshare electronics
+* | Function : Achieve drawing: draw points, lines, boxes, circles and
+* their size, solid dotted line, solid rectangle hollow
+* rectangle, solid circle hollow circle.
+* | Info :
+* Achieve display characters: Display a single character, string, number
+* Achieve time display: adaptive size display time minutes and seconds
+*----------------
+* | This version: V3.1
+* | Date : 2019-10-10
+* | Info :
+* -----------------------------------------------------------------------------
+* V3.1(2019-10-10):
+* 1. Add gray level
+* PAINT Add Scale
+* 2. Add void Paint_SetScale(UBYTE scale);
+*
+* V3.0(2019-04-18):
+* 1.Change:
+* Paint_DrawPoint(..., DOT_STYLE DOT_STYLE)
+* => Paint_DrawPoint(..., DOT_STYLE Dot_Style)
+* Paint_DrawLine(..., LINE_STYLE Line_Style, DOT_PIXEL Dot_Pixel)
+* => Paint_DrawLine(..., DOT_PIXEL Line_width, LINE_STYLE Line_Style)
+* Paint_DrawRectangle(..., DRAW_FILL Filled, DOT_PIXEL Dot_Pixel)
+* => Paint_DrawRectangle(..., DOT_PIXEL Line_width, DRAW_FILL Draw_Fill)
+* Paint_DrawCircle(..., DRAW_FILL Draw_Fill, DOT_PIXEL Dot_Pixel)
+* => Paint_DrawCircle(..., DOT_PIXEL Line_width, DRAW_FILL Draw_Filll)
+*
+* -----------------------------------------------------------------------------
+* V2.0(2018-11-15):
+* 1.add: Paint_NewImage()
+* Create an image's properties
+* 2.add: Paint_SelectImage()
+* Select the picture to be drawn
+* 3.add: Paint_SetRotate()
+* Set the direction of the cache
+* 4.add: Paint_RotateImage()
+* Can flip the picture, Support 0-360 degrees,
+* but only 90.180.270 rotation is better
+* 4.add: Paint_SetMirroring()
+* Can Mirroring the picture, horizontal, vertical, origin
+* 5.add: Paint_DrawString_CN()
+* Can display Chinese(GB1312)
+*
+* -----------------------------------------------------------------------------
+* V1.0(2018-07-17):
+* Create library
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documnetation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+* THE SOFTWARE.
+*
+******************************************************************************/
+#ifndef __GUI_PAINT_H
+#define __GUI_PAINT_H
+
+#include "../Config/DEV_Config.h"
+#include "../Fonts/fonts.h"
+
+/**
+ * Image attributes
+**/
+typedef struct {
+ UBYTE *Image;
+ UWORD Width;
+ UWORD Height;
+ UWORD WidthMemory;
+ UWORD HeightMemory;
+ UWORD Color;
+ UWORD Rotate;
+ UWORD Mirror;
+ UWORD WidthByte;
+ UWORD HeightByte;
+ UWORD Scale;
+} PAINT;
+extern PAINT Paint;
+
+/**
+ * Display rotate
+**/
+#define ROTATE_0 0
+#define ROTATE_90 90
+#define ROTATE_180 180
+#define ROTATE_270 270
+
+/**
+ * Display Flip
+**/
+typedef enum {
+ MIRROR_NONE = 0x00,
+ MIRROR_HORIZONTAL = 0x01,
+ MIRROR_VERTICAL = 0x02,
+ MIRROR_ORIGIN = 0x03,
+} MIRROR_IMAGE;
+#define MIRROR_IMAGE_DFT MIRROR_NONE
+
+/**
+ * image color
+**/
+#define WHITE 0xFF
+#define BLACK 0x00
+#define RED BLACK
+
+#define IMAGE_BACKGROUND WHITE
+#define FONT_FOREGROUND BLACK
+#define FONT_BACKGROUND WHITE
+
+//4 Gray level
+#define GRAY1 0x03 //Blackest
+#define GRAY2 0x02
+#define GRAY3 0x01 //gray
+#define GRAY4 0x00 //white
+
+/**
+ * The size of the point
+**/
+typedef enum {
+ DOT_PIXEL_1X1 = 1, // 1 x 1
+ DOT_PIXEL_2X2 , // 2 X 2
+ DOT_PIXEL_3X3 , // 3 X 3
+ DOT_PIXEL_4X4 , // 4 X 4
+ DOT_PIXEL_5X5 , // 5 X 5
+ DOT_PIXEL_6X6 , // 6 X 6
+ DOT_PIXEL_7X7 , // 7 X 7
+ DOT_PIXEL_8X8 , // 8 X 8
+} DOT_PIXEL;
+#define DOT_PIXEL_DFT DOT_PIXEL_1X1 //Default dot pilex
+
+/**
+ * Point size fill style
+**/
+typedef enum {
+ DOT_FILL_AROUND = 1, // dot pixel 1 x 1
+ DOT_FILL_RIGHTUP , // dot pixel 2 X 2
+} DOT_STYLE;
+#define DOT_STYLE_DFT DOT_FILL_AROUND //Default dot pilex
+
+/**
+ * Line style, solid or dashed
+**/
+typedef enum {
+ LINE_STYLE_SOLID = 0,
+ LINE_STYLE_DOTTED,
+} LINE_STYLE;
+
+/**
+ * Whether the graphic is filled
+**/
+typedef enum {
+ DRAW_FILL_EMPTY = 0,
+ DRAW_FILL_FULL,
+} DRAW_FILL;
+
+/**
+ * Custom structure of a time attribute
+**/
+typedef struct {
+ UWORD Year; //0000
+ UBYTE Month; //1 - 12
+ UBYTE Day; //1 - 30
+ UBYTE Hour; //0 - 23
+ UBYTE Min; //0 - 59
+ UBYTE Sec; //0 - 59
+} PAINT_TIME;
+extern PAINT_TIME sPaint_time;
+
+//init and Clear
+void Paint_NewImage(UBYTE *image, UWORD Width, UWORD Height, UWORD Rotate, UWORD Color);
+void Paint_SelectImage(UBYTE *image);
+void Paint_SetRotate(UWORD Rotate);
+void Paint_SetMirroring(UBYTE mirror);
+void Paint_SetPixel(UWORD Xpoint, UWORD Ypoint, UWORD Color);
+void Paint_SetScale(UBYTE scale);
+
+void Paint_Clear(UWORD Color);
+void Paint_ClearWindows(UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend, UWORD Color);
+
+//Drawing
+void Paint_DrawPoint(UWORD Xpoint, UWORD Ypoint, UWORD Color, DOT_PIXEL Dot_Pixel, DOT_STYLE Dot_FillWay);
+void Paint_DrawLine(UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend, UWORD Color, DOT_PIXEL Line_width, LINE_STYLE Line_Style);
+void Paint_DrawRectangle(UWORD Xstart, UWORD Ystart, UWORD Xend, UWORD Yend, UWORD Color, DOT_PIXEL Line_width, DRAW_FILL Draw_Fill);
+void Paint_DrawCircle(UWORD X_Center, UWORD Y_Center, UWORD Radius, UWORD Color, DOT_PIXEL Line_width, DRAW_FILL Draw_Fill);
+
+//Display string
+void Paint_DrawChar(UWORD Xstart, UWORD Ystart, const char Acsii_Char, sFONT* Font, UWORD Color_Foreground, UWORD Color_Background);
+void Paint_DrawString_EN(UWORD Xstart, UWORD Ystart, const char * pString, sFONT* Font, UWORD Color_Foreground, UWORD Color_Background);
+void Paint_DrawString_CN(UWORD Xstart, UWORD Ystart, const char * pString, cFONT* font, UWORD Color_Foreground, UWORD Color_Background);
+void Paint_DrawNum(UWORD Xpoint, UWORD Ypoint, int32_t Nummber, sFONT* Font, UWORD Color_Foreground, UWORD Color_Background);
+void Paint_DrawNumDecimals(UWORD Xpoint, UWORD Ypoint, double Nummber, sFONT* Font, UWORD Digit, UWORD Color_Foreground, UWORD Color_Background); // Able to display decimals
+void Paint_DrawTime(UWORD Xstart, UWORD Ystart, PAINT_TIME *pTime, sFONT* Font, UWORD Color_Foreground, UWORD Color_Background);
+
+//pic
+void Paint_DrawBitMap(const unsigned char* image_buffer);
+
+
+#endif
\ No newline at end of file
diff --git a/c/p2fa.c b/c/p2fa.c
new file mode 100644
index 0000000..f4231d5
--- /dev/null
+++ b/c/p2fa.c
@@ -0,0 +1,155 @@
+//
+// Created by steven on 11/14/2024.
+//
+
+#include
+#include
+#include "libs/EPD_2in13_V4.h"
+#include "libs/GUI/GUI_Paint.h"
+#include "libs/GUI/GUI_BMPfile.h"
+
+__declspec(dllexport) int draw() {
+ srand(time(NULL));
+ return rand();
+}
+
+
+int EPD_2in13_V4_test(void) {
+
+ Debug("EPD_2in13_V4_test Demo\r\n");
+ if(DEV_Module_Init()!=0){
+ return -1;
+ }
+
+ Debug("e-Paper Init and Clear...\r\n");
+ EPD_2in13_V4_Init();
+
+
+ struct timespec start={0,0}, finish={0,0};
+ clock_gettime(CLOCK_REALTIME,&start);
+ EPD_2in13_V4_Clear();
+ clock_gettime(CLOCK_REALTIME,&finish);
+ Debug("%ld S\r\n",finish.tv_sec-start.tv_sec);
+
+ //Create a new image cache
+ UBYTE *BlackImage;
+ UWORD Imagesize = ((EPD_2in13_V4_WIDTH % 8 == 0)? (EPD_2in13_V4_WIDTH / 8 ): (EPD_2in13_V4_WIDTH / 8 + 1)) * EPD_2in13_V4_HEIGHT;
+ if((BlackImage = (UBYTE *)malloc(Imagesize)) == NULL) {
+ Debug("Failed to apply for black memory...\r\n");
+ return -1;
+ }
+ Debug("Paint_NewImage\r\n");
+ Paint_NewImage(BlackImage, EPD_2in13_V4_WIDTH, EPD_2in13_V4_HEIGHT, 90, WHITE);
+ Paint_Clear(WHITE);
+
+#if 1 // show bmp
+ Paint_NewImage(BlackImage, EPD_2in13_V4_WIDTH, EPD_2in13_V4_HEIGHT, 90, WHITE);
+ Debug("show window BMP-----------------\r\n");
+ Paint_SelectImage(BlackImage);
+ GUI_ReadBmp("./pic/100x100.bmp", 10, 10);
+ EPD_2in13_V4_Display(BlackImage);
+ DEV_Delay_ms(3000);
+
+ Debug("show bmp------------------------\r\n");
+ Paint_SelectImage(BlackImage);
+ GUI_ReadBmp("./pic/2in13_1.bmp", 0, 0);
+ EPD_2in13_V4_Display(BlackImage);
+ DEV_Delay_ms(3000);
+#endif
+
+#if 1 //show image for array
+ Debug("show image for array\r\n");
+ EPD_2in13_V4_Init_Fast();
+ Paint_SelectImage(BlackImage);
+ Paint_Clear(WHITE);
+ Paint_DrawBitMap(gImage_2in13_2);
+
+ EPD_2in13_V4_Display_Fast(BlackImage);
+ DEV_Delay_ms(2000);
+#endif
+
+#if 1 // Drawing on the image
+ Paint_NewImage(BlackImage, EPD_2in13_V4_WIDTH, EPD_2in13_V4_HEIGHT, 90, WHITE);
+ Debug("Drawing\r\n");
+ //1.Select Image
+ EPD_2in13_V4_Init();
+ Paint_SelectImage(BlackImage);
+ Paint_Clear(WHITE);
+
+ // 2.Drawing on the image
+ Paint_DrawPoint(5, 10, BLACK, DOT_PIXEL_1X1, DOT_STYLE_DFT);
+ Paint_DrawPoint(5, 25, BLACK, DOT_PIXEL_2X2, DOT_STYLE_DFT);
+ Paint_DrawPoint(5, 40, BLACK, DOT_PIXEL_3X3, DOT_STYLE_DFT);
+ Paint_DrawPoint(5, 55, BLACK, DOT_PIXEL_4X4, DOT_STYLE_DFT);
+
+ Paint_DrawLine(20, 10, 70, 60, BLACK, DOT_PIXEL_1X1, LINE_STYLE_SOLID);
+ Paint_DrawLine(70, 10, 20, 60, BLACK, DOT_PIXEL_1X1, LINE_STYLE_SOLID);
+ Paint_DrawRectangle(20, 10, 70, 60, BLACK, DOT_PIXEL_1X1, DRAW_FILL_EMPTY);
+ Paint_DrawRectangle(85, 10, 135, 60, BLACK, DOT_PIXEL_1X1, DRAW_FILL_FULL);
+
+ Paint_DrawLine(45, 15, 45, 55, BLACK, DOT_PIXEL_1X1, LINE_STYLE_DOTTED);
+ Paint_DrawLine(25, 35, 70, 35, BLACK, DOT_PIXEL_1X1, LINE_STYLE_DOTTED);
+ Paint_DrawCircle(45, 35, 20, BLACK, DOT_PIXEL_1X1, DRAW_FILL_EMPTY);
+ Paint_DrawCircle(110, 35, 20, WHITE, DOT_PIXEL_1X1, DRAW_FILL_FULL);
+
+ Paint_DrawString_EN(140, 15, "waveshare", &Font16, BLACK, WHITE);
+ Paint_DrawNum(140, 40, 123456789, &Font16, BLACK, WHITE);
+
+ Paint_DrawString_CN(140, 60, "ÄãºÃabc", &Font12CN, BLACK, WHITE);
+ Paint_DrawString_CN(5, 65, "΢ѩµç×Ó", &Font24CN, WHITE, BLACK);
+
+ EPD_2in13_V4_Display_Base(BlackImage);
+ DEV_Delay_ms(3000);
+#endif
+
+#if 1 //Partial refresh, example shows time
+ Paint_NewImage(BlackImage, EPD_2in13_V4_WIDTH, EPD_2in13_V4_HEIGHT, 90, WHITE);
+ Debug("Partial refresh\r\n");
+ Paint_SelectImage(BlackImage);
+
+ PAINT_TIME sPaint_time;
+ sPaint_time.Hour = 12;
+ sPaint_time.Min = 34;
+ sPaint_time.Sec = 56;
+ UBYTE num = 10;
+ for (;;) {
+ sPaint_time.Sec = sPaint_time.Sec + 1;
+ if (sPaint_time.Sec == 60) {
+ sPaint_time.Min = sPaint_time.Min + 1;
+ sPaint_time.Sec = 0;
+ if (sPaint_time.Min == 60) {
+ sPaint_time.Hour = sPaint_time.Hour + 1;
+ sPaint_time.Min = 0;
+ if (sPaint_time.Hour == 24) {
+ sPaint_time.Hour = 0;
+ sPaint_time.Min = 0;
+ sPaint_time.Sec = 0;
+ }
+ }
+ }
+ Paint_ClearWindows(150, 80, 150 + Font20.Width * 7, 80 + Font20.Height, WHITE);
+ Paint_DrawTime(150, 80, &sPaint_time, &Font20, WHITE, BLACK);
+
+ num = num - 1;
+ if(num == 0) {
+ break;
+ }
+ EPD_2in13_V4_Display_Partial(BlackImage);
+ DEV_Delay_ms(500);//Analog clock 1s
+ }
+#endif
+
+ Debug("Clear...\r\n");
+ EPD_2in13_V4_Init();
+ EPD_2in13_V4_Clear();
+
+ Debug("Goto Sleep...\r\n");
+ EPD_2in13_V4_Sleep();
+ free(BlackImage);
+ BlackImage = NULL;
+ DEV_Delay_ms(2000);//important, at least 2s
+ // close 5V
+ Debug("close 5V, Module enters 0 power consumption ...\r\n");
+ DEV_Module_Exit();
+ return 0;
+}
\ No newline at end of file
diff --git a/c/p2fa.h b/c/p2fa.h
new file mode 100644
index 0000000..1eea40a
--- /dev/null
+++ b/c/p2fa.h
@@ -0,0 +1,10 @@
+//
+// Created by steven on 11/14/2024.
+//
+
+#ifndef P2FA_P2FA_H
+#define P2FA_P2FA_H
+
+#endif //P2FA_P2FA_H
+
+__declspec(dllexport) int draw();
\ No newline at end of file
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..6cee1ea
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,5 @@
+module P2FA
+
+go 1.23.2
+
+require github.com/creachadair/otp v0.5.0
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..4957390
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,4 @@
+github.com/creachadair/mds v0.21.3 h1:RRgEAPIb52cU0q7UxGyN+13QlCVTZIL4slRr0cYYQfA=
+github.com/creachadair/mds v0.21.3/go.mod h1:1ltMWZd9yXhaHEoZwBialMaviWVUpRPvMwVP7saFAzM=
+github.com/creachadair/otp v0.5.0 h1:q3Th7CXm2zlmCdBjw5tEPFOj4oWJMnVL5HXlq0sNKS0=
+github.com/creachadair/otp v0.5.0/go.mod h1:0kceI87EnYFNYSTL121goJVAnk3eJhaed9H0nMuJUkA=
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..5e5ff46
--- /dev/null
+++ b/main.go
@@ -0,0 +1,162 @@
+package main
+
+/*
+#cgo CFLAGS: -I.
+#cgo LDFLAGS: -L. -llibp2fa
+
+#include "p2fa.h"
+*/
+import "C"
+
+import (
+ "crypto/hmac"
+ "crypto/sha1"
+ "crypto/sha256"
+ "crypto/sha512"
+ "fmt"
+ "github.com/creachadair/otp"
+ "hash"
+ "log"
+ "os"
+ "runtime"
+ "strconv"
+ "strings"
+ "time"
+)
+
+var token string
+
+var configs map[string]otp.Config
+
+func getSha1() func() hash.Hash { return sha1.New }
+
+func loadConfigs() {
+ var homeDir string
+
+ osVar := runtime.GOOS
+ if osVar == "windows" {
+ homeDir = os.Getenv("USERPROFILE")
+ } else {
+ homeDir = os.Getenv("HOME")
+ }
+
+ configs = make(map[string]otp.Config)
+
+ files, err := os.ReadDir(homeDir + "/.totp")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ for _, fileEntry := range files {
+ fileBytes, err := os.ReadFile(homeDir + "/.totp/" + fileEntry.Name())
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ fileStr := string(fileBytes)
+ lineSplt := strings.Split(fileStr, "\n")
+
+ var key string
+ var hashVar func() hash.Hash
+ var timeStep func() uint64
+ var counter uint64
+ var digits int
+ var format func(hash []byte, length int) string
+
+ for _, line := range lineSplt {
+ kv := strings.Split(line, ":")
+ if len(kv) < 2 {
+ continue
+ }
+ kv[1] = strings.TrimSpace(kv[1])
+
+ switch strings.ToLower(kv[0]) {
+ case "key":
+ key = kv[1]
+ case "hash":
+ {
+ switch kv[1] {
+ case "sha1":
+ hashVar = getSha1()
+ case "sha256":
+ hashVar = func() hash.Hash { return sha256.New() }
+ case "sha512":
+ hashVar = func() hash.Hash { return sha512.New() }
+ case "hmac":
+ {
+ keyBytes, err := otp.ParseKey(key)
+ if err != nil {
+ log.Fatal(err)
+ }
+ hashVar = func() hash.Hash { return hmac.New(getSha1(), keyBytes) } // Probably not proper implementation but who uses HMAC anyway
+ }
+ }
+ }
+ case "timestep":
+ {
+ ts, err := strconv.Atoi(kv[1])
+ if err != nil {
+ log.Fatal(err)
+ }
+ timeStep = otp.TimeWindow(ts)
+ }
+ case "counter":
+ {
+ cNum, err := strconv.ParseUint(kv[1], 10, 0)
+ if err != nil {
+ log.Fatal(err)
+ }
+ if cNum < 6 || cNum > 10 {
+ log.Fatal("Counter not in range 6-10")
+ }
+ counter = cNum
+ }
+ case "format":
+ {
+ } //TODO implement
+ }
+ }
+
+ config := otp.Config{
+ Key: key,
+ Hash: hashVar,
+ TimeStep: timeStep,
+ Counter: counter,
+ Digits: digits,
+ Format: format,
+ }
+
+ configs[fileEntry.Name()] = config
+ }
+}
+
+func refreshTokenVar() {
+ token, _ = otp.DefaultTOTP("alksjdfhalksjdbf")
+}
+
+func getTimeRemaining(n int) uint64 {
+ return uint64(n) - (uint64(time.Now().Unix()) % uint64(n))
+}
+
+func main() {
+ loadConfigs()
+
+ var rand C.int = C.draw()
+
+ fmt.Printf("Rand: %d\n", int(rand))
+
+ //refreshTokenVar()
+ //
+ //getTimeRemaining(30)
+ //
+ //for i := 0; i < 5; i++ {
+ // refreshTokenVar()
+ // fmt.Printf("TOTP: %s\n", token)
+ // for getTimeRemaining(30) > 1 {
+ // time.Sleep(1 * time.Second)
+ // fmt.Printf("\rTime Remaining: %ds", getTimeRemaining(30))
+ // }
+ // time.Sleep(1 * time.Second)
+ // fmt.Print("\n")
+ //}
+}
diff --git a/p2fa.h b/p2fa.h
new file mode 100644
index 0000000..1eea40a
--- /dev/null
+++ b/p2fa.h
@@ -0,0 +1,10 @@
+//
+// Created by steven on 11/14/2024.
+//
+
+#ifndef P2FA_P2FA_H
+#define P2FA_P2FA_H
+
+#endif //P2FA_P2FA_H
+
+__declspec(dllexport) int draw();
\ No newline at end of file