diff --git a/kvm_system/.DS_Store b/kvm_system/.DS_Store new file mode 100755 index 0000000..bfe1b51 Binary files /dev/null and b/kvm_system/.DS_Store differ diff --git a/kvm_system/README.md b/kvm_system/README.md new file mode 100644 index 0000000..e69de29 diff --git a/kvm_system/main/CMakeLists.txt b/kvm_system/main/CMakeLists.txt new file mode 100644 index 0000000..939403d --- /dev/null +++ b/kvm_system/main/CMakeLists.txt @@ -0,0 +1,28 @@ + +list(APPEND ADD_INCLUDE + "include" + "lib/libqr" + "lib/system_ctrl" + "lib/system_state" + "lib/system_init" + "lib/oled_ctrl" + "lib/oled_ui" + "lib/hdmi" + ) + +list(APPEND ADD_PRIVATE_INCLUDE "") + +append_srcs_dir(ADD_SRCS + "src" + "lib/libqr" + "lib/system_ctrl" + "lib/system_state" + "lib/system_init" + "lib/oled_ctrl" + "lib/oled_ui" + "lib/hdmi" + ) # append source file in src dir to var ADD_SRCS + +list(APPEND ADD_REQUIREMENTS basic peripheral) + +register_component() diff --git a/kvm_system/main/Kconfig b/kvm_system/main/Kconfig new file mode 100644 index 0000000..e69de29 diff --git a/kvm_system/main/include/config.h b/kvm_system/main/include/config.h new file mode 100644 index 0000000..528c86d --- /dev/null +++ b/kvm_system/main/include/config.h @@ -0,0 +1,100 @@ +#ifndef CONFIG_H_ +#define CONFIG_H_ + +#include "maix_basic.hpp" +#include "maix_time.hpp" +#include "maix_gpio.hpp" +#include "maix_pinmap.hpp" +#include "maix_i2c.hpp" +#include "maix_uart.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qr.h" +#include "system_ctrl.h" +#include "system_state.h" +#include "system_init.h" +#include "oled_ctrl.h" +#include "oled_ui.h" +#include "hdmi.h" + +#define IP_Change_time 5000 +#define QR_Change_time 5000 +#define STATE_DELAY 1000 +#define OLED_DELAY 1000 +#define KEY_DELAY 100 +#define KEY_LONG_PRESS 1500 +#define KEY_LONGLONG_PRESS 9000 +#define WIFI_CONNECTION_DELAY 5000 +#define OLED_SLEEP_DELAY_MIN 10 +#define OLED_SLEEP_DELAY_DEFAULT 30 + +typedef struct { + int8_t page = 0; + int8_t sub_page = 0; + uint8_t eth_route[16] = {0}; // route ip + uint8_t wifi_route[16] = {0}; // route ip + uint8_t eth_addr[16] = {0}; // ETH ip + uint8_t wifi_addr[16] = {0}; // WiFi ip + uint8_t tail_addr[16] = {0}; // Tailscale ip + uint8_t rndis_addr[16] = {0}; // RNDIS ip + int8_t eth_state = -1; // cat /sys/class/net/eth0/carrier + int8_t wifi_state = -1; // cat /sys/class/net/wlan0/carrier + int8_t tail_state = -1; // ifconfig tailscale0 | grep 'inet addr' | awk '{print $2}' + int8_t hdmi_state = -1; // cat /proc/cvitek/vi_dbg | grep VIFPS | awk '{print $3}' (1s) + int8_t usb_state = -1; // cat /sys/class/udc/4340000.usb/state + int8_t hid_state = -1; // (exist?) /sys/kernel/config/usb_gadget/g0/configs/c.1/hid.GSn(n=012) + int8_t rndis_state = -1; // (exist?) /sys/kernel/config/usb_gadget/g0/configs/c.1/rndis.usb0 + int8_t udisk_state = -1; // (exist?) /sys/kernel/config/usb_gadget/g0/configs/c.1/mass_storage.disk0 + int8_t host_pwr_state = -1; // cat /sys/class/gpio/gpio504/value + int16_t hdmi_width = 0; // cat /kvmapp/kvm/width + int16_t hdmi_height = 0; // cat /kvmapp/kvm/height + int8_t type = 0; // cat /kvmapp/kvm/type + int8_t now_fps = 0; // cat /kvmapp/kvm/now_fps + int16_t qlty = 0; // cat /kvmapp/kvm/qlty + int8_t oled_thread_running = 0; + int8_t key_thread_running = 0; + int8_t sys_thread_running = 0; + int8_t wifi_config_process = -1; // 1:QR;2:Test;3:IP; + char wifi_ap_pass[9] = {0}; + uint8_t oled_sleep_state = 0; // 0:wakeup; 1:sleep; + int8_t reconvery_update = 0; // 0:Undetected; 1:Needs Update; 2:Update finish; -1:not need to update +} kvm_sys_state_t; + +typedef struct { + int8_t page = -1; + int8_t sub_page = -1; + uint8_t eth_route[16] = {0}; // route ip + uint8_t wifi_route[16] = {0}; // route ip + uint8_t eth_addr[16] = {0}; // ETH ip + uint8_t wifi_addr[16] = {0}; // WiFi ip + uint8_t tail_addr[16] = {0}; // Tailscale ip + uint8_t rndis_addr[16] = {0}; // RNDIS ip + int8_t eth_state = -1; // cat /sys/class/net/eth0/carrier + int8_t wifi_state = -1; // cat /sys/class/net/wlan0/carrier + int8_t tail_state = -1; // ifconfig tailscale0 | grep inet\ addr | awk '{print $2}' + int8_t hdmi_state = -1; // cat /proc/cvitek/vi_dbg | grep VIFPS | awk '{print $3}' (1s) + int8_t usb_state = -1; // cat /sys/class/udc/4340000.usb/state + int8_t hid_state = -1; // (exist?) /sys/kernel/config/usb_gadget/g0/configs/c.1/hid.GSn(n=012) + int8_t rndis_state = -1; // (exist?) /sys/kernel/config/usb_gadget/g0/configs/c.1/rndis.usb0 + int8_t udisk_state = -1; // (exist?) /sys/kernel/config/usb_gadget/g0/configs/c.1/mass_storage.disk0 + int8_t host_pwr_state = -1; // cat /sys/class/gpio/gpio504/value + int16_t hdmi_width = -1; // cat /kvmapp/kvm/width + int16_t hdmi_height = -1; // cat /kvmapp/kvm/height + int8_t type = -1; // cat /kvmapp/kvm/type + int8_t now_fps = -1; // cat /kvmapp/kvm/now_fps + int16_t qlty = -1; // cat /kvmapp/kvm/qlty + uint8_t oled_sleep_param = 0; + uint8_t oled_sleep_state = 0; // 0:wakeup; 1:sleep; + uint64_t oled_sleep_start = 0; +} kvm_oled_state_t; + +#endif // CONFIG_H_ diff --git a/kvm_system/main/lib/hdmi/hdmi.cpp b/kvm_system/main/lib/hdmi/hdmi.cpp new file mode 100644 index 0000000..fd10587 --- /dev/null +++ b/kvm_system/main/lib/hdmi/hdmi.cpp @@ -0,0 +1,238 @@ +#include "hdmi.h" + +using namespace maix; +using namespace maix::sys; +using namespace maix::peripheral; +i2c::I2C LT6911_i2c(4, i2c::Mode::MASTER); + +void lt6911_enable() +{ + uint8_t buf[2]; + buf[0] = 0xff; + buf[1] = 0x80; + LT6911_i2c.writeto(LT6911_ADDR, buf, 2); + + buf[0] = 0xee; + buf[1] = 0x01; + LT6911_i2c.writeto(LT6911_ADDR, buf, 2); +} + +void lt6911_disable() +{ + uint8_t buf[2]; + buf[0] = 0xff; + buf[1] = 0x80; + LT6911_i2c.writeto(LT6911_ADDR, buf, 2); + + buf[0] = 0xee; + buf[1] = 0x00; + LT6911_i2c.writeto(LT6911_ADDR, buf, 2); +} + +void lt6911_start() +{ + uint8_t buf[2]; + + buf[0] = 0xff; + buf[1] = 0x80; + LT6911_i2c.writeto(LT6911_ADDR, buf, 2); + + buf[0] = 0x5A; + buf[1] = 0x80; + LT6911_i2c.writeto(LT6911_ADDR, buf, 2); +} + +void lt6911_stop() +{ + uint8_t buf[2]; + + buf[0] = 0xff; + buf[1] = 0x80; + LT6911_i2c.writeto(LT6911_ADDR, buf, 2); + + buf[0] = 0x5A; + buf[1] = 0x88; + LT6911_i2c.writeto(LT6911_ADDR, buf, 2); +} + +void lt6911_reset() +{ + lt6911_stop(); + time::sleep_ms(1); + lt6911_start(); +} + +void lt6911_get_hdmi_errer() +{ + uint8_t buf[6]; + + buf[0] = 0xff; + buf[1] = 0xC0; + LT6911_i2c.writeto(LT6911_ADDR, buf, 2); + + buf[0] = 0x20; + buf[1] = 0x01; + LT6911_i2c.writeto(LT6911_ADDR, buf, 2); + + time::sleep_ms(100); + + buf[0] = 0x24; + LT6911_i2c.writeto(LT6911_ADDR, buf, 1); + + maix::Bytes *dat = LT6911_i2c.readfrom(LT6911_ADDR, 6); + + buf[0] = 0x20; + buf[1] = 0x07; + LT6911_i2c.writeto(LT6911_ADDR, buf, 2); + + for(int i = 0; i < 6; i++){ + buf[i] = (uint8_t)dat->data[i]; + } + delete dat; + + printf("hdmi_errer_code = %x, %x, %x, %x, %x, %x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); +} + +uint8_t lt6911_get_hdmi_res() +{ + uint8_t buf[2]; + uint8_t revbuf[4]; + uint16_t Vactive; + uint16_t Hactive; + + buf[0] = 0xff; + buf[1] = 0xd2; + LT6911_i2c.writeto(LT6911_ADDR, buf, 2); + + buf[0] = 0x83; + buf[1] = 0x11; + LT6911_i2c.writeto(LT6911_ADDR, buf, 2); + + time::sleep_ms(100); + + // Vactive + buf[0] = 0x96; + LT6911_i2c.writeto(LT6911_ADDR, buf, 1); + maix::Bytes *dat0 = LT6911_i2c.readfrom(LT6911_ADDR, 2); + + // Hactive + buf[0] = 0x8b; + LT6911_i2c.writeto(LT6911_ADDR, buf, 1); + maix::Bytes *dat1 = LT6911_i2c.readfrom(LT6911_ADDR, 2); + + revbuf[0] = (uint8_t)dat0->data[0]; + revbuf[1] = (uint8_t)dat0->data[1]; + revbuf[2] = (uint8_t)dat1->data[0]; + revbuf[3] = (uint8_t)dat1->data[1]; + + Vactive = (revbuf[0] << 8)|revbuf[1]; + Hactive = (revbuf[2] << 8)|revbuf[3]; + Hactive *= 2; + + printf("HDMI res modification event\n"); + printf("new res: %d * %d\n", Hactive, Vactive); + + delete dat0; + delete dat1; + + if (Vactive != 0 && Hactive != 0){ + return 1; + } else { + return 0; + } +} + +void lt6911_get_hdmi_clk() +{ + uint8_t buf[2]; + uint8_t revbuf[3]; + uint32_t clk; + + buf[0] = 0xff; + buf[1] = 0xa0; + LT6911_i2c.writeto(LT6911_ADDR, buf, 2); + + buf[0] = 0x34; + buf[1] = 0x0b; + LT6911_i2c.writeto(LT6911_ADDR, buf, 2); + + time::sleep_ms(50); + + // clk + buf[0] = 0xff; + buf[1] = 0xb8; + LT6911_i2c.writeto(LT6911_ADDR, buf, 2); + + buf[0] = 0xb1; + LT6911_i2c.writeto(LT6911_ADDR, buf, 1); + maix::Bytes *dat0 = LT6911_i2c.readfrom(LT6911_ADDR, 3); + + revbuf[0] = (uint8_t)dat0->data[0]; + revbuf[1] = (uint8_t)dat0->data[1]; + revbuf[2] = (uint8_t)dat0->data[2]; + revbuf[0] &= 0x07; + + clk = revbuf[0]; + clk <<= 8; + clk |= revbuf[1]; + clk <<= 8; + clk |= revbuf[2]; + + printf("HDMI CLK = %d\n", clk); + + delete dat0; +} + +uint8_t lt6911_get_csi_res() +{ + uint8_t ret = 0; + uint8_t buf[2]; + uint8_t revbuf[4]; + static uint16_t old_Vactive; + static uint16_t old_Hactive; + uint16_t Vactive; + uint16_t Hactive; + char Cmd[100]={0}; + + buf[0] = 0xff; + buf[1] = 0xc2; + LT6911_i2c.writeto(LT6911_ADDR, buf, 2); + + // Vactive + buf[0] = 0x06; + LT6911_i2c.writeto(LT6911_ADDR, buf, 1); + maix::Bytes *dat0 = LT6911_i2c.readfrom(LT6911_ADDR, 2); + + // Hactive + buf[0] = 0x38; + LT6911_i2c.writeto(LT6911_ADDR, buf, 1); + maix::Bytes *dat1 = LT6911_i2c.readfrom(LT6911_ADDR, 2); + + revbuf[0] = (uint8_t)dat0->data[0]; + revbuf[1] = (uint8_t)dat0->data[1]; + revbuf[2] = (uint8_t)dat1->data[0]; + revbuf[3] = (uint8_t)dat1->data[1]; + + Vactive = (revbuf[0] << 8)|revbuf[1]; + Hactive = (revbuf[2] << 8)|revbuf[3]; + + if(old_Hactive != Hactive || old_Vactive != Vactive){ + old_Hactive = Hactive; + old_Vactive = Vactive; + ret = 1; + } + + printf("CSI res: %d * %d\n", Hactive, Vactive); + // setenv("KVM_CSI_HEIGHT", to_string(Hactive).c_str(), 1); + // setenv("KVM_CSI_WIDTH", to_string(Vactive).c_str(), 1); + + sprintf(Cmd, "echo %d > /kvmapp/kvm/width", Hactive); + system(Cmd); + sprintf(Cmd, "echo %d > /kvmapp/kvm/height", Vactive); + system(Cmd); + + delete dat0; + delete dat1; + + return ret; +} \ No newline at end of file diff --git a/kvm_system/main/lib/hdmi/hdmi.h b/kvm_system/main/lib/hdmi/hdmi.h new file mode 100644 index 0000000..cddb660 --- /dev/null +++ b/kvm_system/main/lib/hdmi/hdmi.h @@ -0,0 +1,29 @@ +#ifndef HDMI_H_ +#define HDMI_H_ + +#include "maix_basic.hpp" +#include "maix_time.hpp" +#include "maix_gpio.hpp" +#include "maix_pinmap.hpp" +#include "maix_i2c.hpp" +#include +#include +#include +#include +#include + +#define LT6911_ADDR 0x2B +#define LT6911_READ 0xFF +#define LT6911_WRITE 0x00 + +void lt6911_enable(); +void lt6911_disable(); +void lt6911_start(); +void lt6911_stop(); +void lt6911_reset(); +void lt6911_get_hdmi_errer(); +uint8_t lt6911_get_hdmi_res(); +void lt6911_get_hdmi_clk(); +uint8_t lt6911_get_csi_res(); + +#endif // HDMI_H_ \ No newline at end of file diff --git a/kvm_system/main/lib/libqr/CMakeLists.txt b/kvm_system/main/lib/libqr/CMakeLists.txt new file mode 100644 index 0000000..b60d6fa --- /dev/null +++ b/kvm_system/main/lib/libqr/CMakeLists.txt @@ -0,0 +1,59 @@ +project(qr) +cmake_minimum_required(VERSION 2.6.0) + +set(QR_VERSION "1.0.0") +set(QR_SOVERSION "1") + +set(QR_COMMAND_SOURCES qrcmd.c) +set(QR_LIBRARY_SOURCES + qr.c qrcnv.c qrcnv_bmp.c qrcnv_png.c qrcnv_svg.c qrcnv_tiff.c +) +set(QR_PUBLIC_HEADERS qr.h) + +set(bindir bin) +set(incdir include) +set(libdir lib) + +set(CMAKE_SKIP_BUILD_RPATH OFF) +set(CMAKE_BUILD_WITH_INSTALL_RPATH OFF) +set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${libdir}") +set(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${libdir}") + +find_package(ZLIB) + +add_definitions(-Wall -Wextra) + +include_directories(${ZLIB_INCLUDE_DIRS}) + +add_executable(qrcmd ${QR_COMMAND_SOURCES}) +add_executable(qrcmd_multi ${QR_COMMAND_SOURCES}) + +add_library(libqr_shared SHARED ${QR_LIBRARY_SOURCES}) +add_library(libqr_static STATIC ${QR_LIBRARY_SOURCES}) + +target_link_libraries(qrcmd libqr_shared) +target_link_libraries(qrcmd_multi libqr_shared) +target_link_libraries(libqr_shared m ${ZLIB_LIBRARIES}) + +set_target_properties(qrcmd PROPERTIES + OUTPUT_NAME qr +) +set_target_properties(qrcmd_multi PROPERTIES + OUTPUT_NAME qrs + COMPILE_FLAGS -DQRCMD_STRUCTURED_APPEND +) +set_target_properties(libqr_shared PROPERTIES + OUTPUT_NAME qr + VERSION ${QR_VERSION} + SOVERSION ${QR_SOVERSION} +) +set_target_properties(libqr_static PROPERTIES + OUTPUT_NAME qr +) + +install(TARGETS qrcmd qrcmd_multi libqr_shared libqr_static + RUNTIME DESTINATION ${bindir} + LIBRARY DESTINATION ${libdir} + ARCHIVE DESTINATION ${libdir} +) +install(FILES ${QR_PUBLIC_HEADERS} DESTINATION ${incdir}) diff --git a/kvm_system/main/lib/libqr/LICENSE b/kvm_system/main/lib/libqr/LICENSE new file mode 100644 index 0000000..85a58e3 --- /dev/null +++ b/kvm_system/main/lib/libqr/LICENSE @@ -0,0 +1,19 @@ +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation 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 furnished 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 FOR 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. diff --git a/kvm_system/main/lib/libqr/README b/kvm_system/main/lib/libqr/README new file mode 100644 index 0000000..17700bc --- /dev/null +++ b/kvm_system/main/lib/libqr/README @@ -0,0 +1 @@ +This is a C library and a command line tool to make a QR Code. diff --git a/kvm_system/main/lib/libqr/TODO b/kvm_system/main/lib/libqr/TODO new file mode 100644 index 0000000..c649aa2 --- /dev/null +++ b/kvm_system/main/lib/libqr/TODO @@ -0,0 +1,8 @@ +TODO: +- test on Win32 +- test on Cygwin (if I could) +- write tests +- write manpage of qr(1), qrs(1) and libqr(3) +- localization support by ICU4C +- pkg-config (.pc file) support +- rcfile support for command line tool diff --git a/kvm_system/main/lib/libqr/crc.h b/kvm_system/main/lib/libqr/crc.h new file mode 100644 index 0000000..e1983b7 --- /dev/null +++ b/kvm_system/main/lib/libqr/crc.h @@ -0,0 +1,63 @@ +/* + * This code is taken from: + * PNG (Portable Network Graphics) Specification, Version 1.1 + * 15. Appendix: Sample CRC Code + * http://www.libpng.org/pub/png/spec/1.1/PNG-CRCAppendix.html + */ + +#ifdef uint32_t +typedef uint32_t crc_t; +#else +typedef unsigned long crc_t; +#endif + +/* Table of CRCs of all 8-bit messages. */ +static crc_t crc_table[256]; + +/* Flag: has the table been computed? Initially false. */ +static int crc_table_computed = 0; + +/* Make the table for a fast CRC. */ +static void make_crc_table(void) +{ + crc_t c; + int n, k; + + for (n = 0; n < 256; n++) { + c = (crc_t) n; + for (k = 0; k < 8; k++) { + if (c & 1) { + c = 0xedb88320L ^ (c >> 1); + } else { + c = c >> 1; + } + } + crc_table[n] = c; + } + crc_table_computed = 1; +} + +/* Update a running CRC with the bytes buf[0..len-1]--the CRC + should be initialized to all 1's, and the transmitted value + is the 1's complement of the final running CRC (see the + crc() routine below)). */ + +static crc_t update_crc(crc_t crc, const unsigned char *buf, int len) +{ + crc_t c = crc; + int n; + + if (!crc_table_computed) { + make_crc_table(); + } + for (n = 0; n < len; n++) { + c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); + } + return c; +} + +/* Return the CRC of the bytes buf[0..len-1]. */ +static crc_t crc(const unsigned char *buf, int len) +{ + return update_crc(0xffffffffL, buf, len) ^ 0xffffffffL; +} diff --git a/kvm_system/main/lib/libqr/qr.c b/kvm_system/main/lib/libqr/qr.c new file mode 100644 index 0000000..07ca444 --- /dev/null +++ b/kvm_system/main/lib/libqr/qr.c @@ -0,0 +1,2611 @@ +/* + * QR Code Generator Library + * + * Core routines were originally written by Junn Ohta. + * Based on qr.c Version 0.1: 2004/4/3 (Public Domain) + * + * @package libqr + * @author Ryusuke SEKIYAMA + * @copyright 2006-2013 Ryusuke SEKIYAMA + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "qr.h" +#include "qr_util.h" +#include "qr_private.h" +#include "qr_dwtable.h" + +#define qrIsData(qr, i, j) (((qr)->symbol[i][j] & QR_MM_DATA) != 0) +#define qrIsFunc(qr, i, j) (((qr)->symbol[i][j] & QR_MM_FUNC) != 0) + +QR_API const char *(*qrGetCurrentFunctionName)(void) = NULL; + +/* + * ライブラリのバージョンを返す + */ +QR_API const char * +qrVersion(void) +{ + return LIBQR_VERSION; +} + +/* + * QRCodeオブジェクトを生成する + */ +QR_API QRCode * +qrInit(int version, int mode, int eclevel, int masktype, int *errcode) +{ + QRCode *qr = NULL; + + /* + * メモリを確保する + */ + qr = (QRCode *)calloc(1, sizeof(QRCode)); + if (qr == NULL) { + *errcode = QR_ERR_MEMORY_EXHAUSTED; + return NULL; + } + qr->dataword = (qr_byte_t *)calloc(1, QR_DWD_MAX); + qr->ecword = (qr_byte_t *)calloc(1, QR_ECW_MAX); + qr->codeword = (qr_byte_t *)calloc(1, QR_CWD_MAX); + if (qr->dataword == NULL || qr->ecword == NULL || qr->codeword == NULL) { + *errcode = QR_ERR_MEMORY_EXHAUSTED; + qrDestroy(qr); + return NULL; + } + + /* + * 内部状態を初期化する + */ + qr->_symbol = NULL; + qr->symbol = NULL; + qr->source = NULL; + qr->srcmax = 0; + qr->srclen = 0; + qr->enclen = 0; + qr->delta1 = 0; + qr->delta2 = 0; + qr->errcode = QR_ERR_NONE; + qr->state = QR_STATE_BEGIN; + + /* + * 型番を設定する + */ + if (version == -1 || (version >= 1 && version <= QR_VER_MAX)) { + qr->param.version = version; + } else { + *errcode = QR_ERR_INVALID_VERSION; + qrDestroy(qr); + return NULL; + } + + /* + * 符号化モードを設定する + */ + if (mode == QR_EM_AUTO || (mode >= QR_EM_NUMERIC && mode < QR_EM_COUNT)) { + qr->param.mode = mode; + } else { + *errcode = QR_ERR_INVALID_MODE; + qrDestroy(qr); + return NULL; + } + + /* + * 誤り訂正レベルを設定する + */ + if (eclevel >= QR_ECL_L && eclevel < QR_EM_COUNT) { + qr->param.eclevel = eclevel; + } else { + *errcode = QR_ERR_INVALID_ECL; + qrDestroy(qr); + return NULL; + } + + /* + * マスクパターンを設定する + */ + if (masktype == -1 || (masktype >= 0 && masktype < QR_MPT_MAX)) { + qr->param.masktype = masktype; + } else { + *errcode = QR_ERR_INVALID_MPT; + qrDestroy(qr); + return NULL; + } + + return qr; +} + +/* + * QRStructuredオブジェクトを生成する + */ +QR_API QRStructured * +qrsInit(int version, int mode, int eclevel, int masktype, int maxnum, int *errcode) +{ + QRStructured *st = NULL; + + /* + * メモリを確保する + */ + st = (QRStructured *)calloc(1, sizeof(QRStructured)); + if (st == NULL) { + *errcode = QR_ERR_MEMORY_EXHAUSTED; + return NULL; + } + + /* + * 内部状態を初期化する + */ + st->parity = 0; + st->state = QR_STATE_BEGIN; + + /* + * 最大シンボル数を設定する + */ + if (maxnum >= 2 && masktype <= QR_STA_MAX) { + st->max = maxnum; + } else { + *errcode = QR_ERR_INVALID_MAXNUM; + qrsDestroy(st); + return NULL; + } + + /* + * 型番を設定する + */ + if (version >= 1 && version <= QR_VER_MAX) { + st->param.version = version; + } else { + *errcode = QR_ERR_INVALID_VERSION; + qrsDestroy(st); + return NULL; + } + + /* + * 符号化モードを設定する + */ + if (mode == QR_EM_AUTO || (mode >= QR_EM_NUMERIC && mode < QR_EM_COUNT)) { + st->param.mode = mode; + } else { + *errcode = QR_ERR_INVALID_MODE; + qrsDestroy(st); + return NULL; + } + + /* + * 誤り訂正レベルを設定する + */ + if (eclevel >= QR_ECL_L && eclevel < QR_EM_COUNT) { + st->param.eclevel = eclevel; + } else { + *errcode = QR_ERR_INVALID_ECL; + qrsDestroy(st); + return NULL; + } + + /* + * マスクパターンを設定する + */ + if (masktype == -1 || (masktype >= 0 && masktype < QR_MPT_MAX)) { + st->param.masktype = masktype; + } else { + *errcode = QR_ERR_INVALID_MPT; + qrsDestroy(st); + return NULL; + } + + /* + * 一つめのQRコードオブジェクトを初期化する + */ + st->qrs[0] = qrInit(st->param.version, st->param.mode, + st->param.eclevel, st->param.masktype, errcode); + if (st->qrs[0] == NULL) { + qrsDestroy(st); + return NULL; + } + st->cur = st->qrs[0]; + st->num = 1; + + return st; +} + +/* + * QRCodeオブジェクトを複製する + */ +QR_API QRCode * +qrClone(const QRCode *qr, int *errcode) +{ + QRCode *cp = NULL; + + /* + * QRCodeオブジェクト用のメモリを確保し、複製する + */ + cp = (QRCode *)malloc(sizeof(QRCode)); + if (cp == NULL) { + *errcode = QR_ERR_MEMORY_EXHAUSTED; + return NULL; + } + memcpy(cp, qr, sizeof(QRCode)); + + /* + * 動的に確保されるメンバをいったんNULLにする + */ + cp->dataword = NULL; + cp->ecword = NULL; + cp->codeword = NULL; + cp->_symbol = NULL; + cp->symbol = NULL; + cp->source = NULL; + + /* + * ファイナライズ後ならシンボル、ファイナライズ前なら計算用領域を複製 + */ + if (cp->state == QR_STATE_FINAL) { + int i, dim; + + dim = qr_vertable[cp->param.version].dimension; + + cp->_symbol = (qr_byte_t *)calloc((size_t)dim, (size_t)dim); + if (cp->_symbol == NULL) { + *errcode = QR_ERR_MEMORY_EXHAUSTED; + qrDestroy(cp); + return NULL; + } + memcpy(cp->_symbol, qr->_symbol, (size_t)(dim * dim)); + + cp->symbol = (qr_byte_t **)malloc(sizeof(qr_byte_t *) * (size_t)dim); + if (cp->symbol == NULL) { + *errcode = QR_ERR_MEMORY_EXHAUSTED; + qrDestroy(cp); + return NULL; + } + for (i = 0; i < dim; i++) { + cp->symbol[i] = cp->_symbol + dim * i; + } + } else { + cp->dataword = (qr_byte_t *)malloc(QR_DWD_MAX); + cp->ecword = (qr_byte_t *)malloc(QR_ECW_MAX); + cp->codeword = (qr_byte_t *)malloc(QR_CWD_MAX); + if (cp->dataword == NULL || cp->ecword == NULL || cp->codeword == NULL) { + *errcode = QR_ERR_MEMORY_EXHAUSTED; + qrDestroy(cp); + return NULL; + } + memcpy(cp->dataword, qr->dataword, QR_DWD_MAX); + memcpy(cp->ecword , qr->ecword , QR_ECW_MAX); + memcpy(cp->codeword, qr->codeword, QR_CWD_MAX); + } + + /* + * 入力データを複製 + */ + if (cp->srcmax > 0 && qr->source != NULL) { + cp->source = (qr_byte_t *)malloc(cp->srcmax); + if (cp->source == NULL) { + *errcode = QR_ERR_MEMORY_EXHAUSTED; + qrDestroy(cp); + return NULL; + } + memcpy(cp->source, qr->source, cp->srclen); + } + + return cp; +} + +/* + * QRStructuredオブジェクトを複製する + */ +QR_API QRStructured * +qrsClone(const QRStructured *st, int *errcode) +{ + QRStructured *cps = NULL; + int i = 0; + + /* + * QRStructuredオブジェクト用のメモリを確保し、複製する + */ + cps = (QRStructured *)malloc(sizeof(QRStructured)); + if (cps == NULL) { + *errcode = QR_ERR_MEMORY_EXHAUSTED; + return NULL; + } + memcpy(cps, st, sizeof(QRStructured)); + + /* + * 保持しているQRCodeオブジェクトを複製する + */ + while (i < cps->num) { + QRCode *cp = qrClone(st->qrs[i], errcode); + if (cp == NULL) { + while (i > 0) { + qrDestroy(cps->qrs[--i]); + free(cps); + } + return NULL; + } + cps->qrs[i++] = cp; + } + while (i < QR_STA_MAX) { + cps->qrs[i++] = NULL; + } + cps->cur = cps->qrs[0] + (st->cur - st->qrs[0]); + + return cps; +} + +/* + * QRCodeオブジェクトを開放する + */ +QR_API void +qrDestroy(QRCode *qr) +{ + if (qr == NULL) { + return; + } + qrFree(qr->source); + qrFree(qr->dataword); + qrFree(qr->ecword); + qrFree(qr->codeword); + qrFree(qr->symbol); + qrFree(qr->_symbol); + free(qr); +} + +/* + * QRStructuredオブジェクトを開放する + */ +QR_API void +qrsDestroy(QRStructured *st) +{ + int i; + if (st == NULL) { + return; + } + for (i = 0; i < st->num; i++) { + qrDestroy(st->qrs[i]); + } + free(st); +} + +/* + * 出力形式に対応するMIMEタイプを返す + */ +QR_API const char * +qrMimeType(int format) +{ + switch (format) { + case QR_FMT_PNG: return "image/png"; + case QR_FMT_BMP: return "image/bmp"; + case QR_FMT_TIFF: return "image/tiff"; + case QR_FMT_PBM: return "image/x-portable-bitmap"; + case QR_FMT_SVG: return "image/svg+xml"; + case QR_FMT_JSON: return "application/json"; + case QR_FMT_DIGIT: return "text/plain"; + case QR_FMT_ASCII: return "text/plain"; + default: return NULL; + } +} + +/* + * 出力形式に対応する拡張子 (ピリオドなし) を返す + */ +QR_API const char * +qrExtension(int format) +{ + switch (format) { + case QR_FMT_PNG: return "png"; + case QR_FMT_BMP: return "bmp"; + case QR_FMT_TIFF: return "tiff"; + case QR_FMT_PBM: return "pbm"; + case QR_FMT_SVG: return "svg"; + case QR_FMT_JSON: return "json"; + case QR_FMT_DIGIT: return "txt"; + case QR_FMT_ASCII: return "txt"; + default: return NULL; + } +} + +/* + * QRコードオブジェクトに登録されているエラー番号を返す + */ +QR_API int +qrGetErrorCode(QRCode *qr) +{ + return qr->errcode; +} + +/* + * QRコードオブジェクトに登録されているエラー情報を返す + */ +QR_API char * +qrGetErrorInfo(QRCode *qr) +{ + return &(qr->errinfo[0]); +} + +/* + * 構造的連接の最後のQRコードオブジェクトに登録されているエラー番号を返す + */ +QR_API int +qrsGetErrorCode(QRStructured *st) +{ + return st->cur->errcode; +} + +/* + * 構造的連接の最後のQRコードオブジェクトに登録されているエラー情報を返す + */ +QR_API char * +qrsGetErrorInfo(QRStructured *st) +{ + return &(st->cur->errinfo[0]); +} + +/* + * エラー番号に対応したエラー情報を返す + */ +QR_API const char * +qrStrError(int errcode) +{ + switch (errcode) { + /* wide use errors */ + case QR_ERR_NONE: + case QR_ERR_USAGE: + return ""; + + case QR_ERR_SEE_ERRNO: + return "For more information, check for errno"; + + case QR_ERR_NOT_IMPL: + return "Not yet implemented"; + + case QR_ERR_STATE: + return "Not allowed in the current state"; + + case QR_ERR_FOPEN: + return "Failed to open file"; + + case QR_ERR_FREAD: + return "Failed to read data"; + + case QR_ERR_FWRITE: + return "Failed to write data"; + + case QR_ERR_MEMORY_EXHAUSTED: + return "Memory exhausted"; + + /* invalid parameter errors */ + case QR_ERR_INVALID_ARG: + return "Invalid argument"; + + case QR_ERR_INVALID_VERSION: + return "Invalid version number"; + + case QR_ERR_INVALID_MODE: + return "Invalid encoding mode"; + + case QR_ERR_INVALID_ECL: + return "Invalid error correction level"; + + case QR_ERR_INVALID_MPT: + return "Invalid mask pattern type"; + + case QR_ERR_INVALID_MAG: + return "Invalid pixel magnifying ratio"; + + case QR_ERR_INVALID_SEP: + return "Invalid separator width"; + + case QR_ERR_INVALID_SIZE: + return "Invalid output size"; + + case QR_ERR_INVALID_FMT: + return "Invalid output format"; + + case QR_ERR_INVALID_OUT: + return "Invalid output pathname"; + + case QR_ERR_INVALID_MAXNUM: + return "Invalid maximum symbol number"; + + case QR_ERR_UNSUPPORTED_FMT: + return "Unsupported output format"; + + case QR_ERR_EMPTY_PARAM: + return "Parameter required"; + + /* input data size/type errors */ + case QR_ERR_EMPTY_SRC: + return "Input data is empty"; + + case QR_ERR_LARGE_SRC: + return "Input data too large"; + + case QR_ERR_NOT_NUMERIC: + return "Non decimal characters found"; + + case QR_ERR_NOT_ALNUM: + return "Non alphanumeric characters found"; + + case QR_ERR_NOT_KANJI: + return "Non JIS X 0208 kanji sequence found"; + + /* imaging related errors */ + case QR_ERR_IMAGE_TOO_LARGE: + return "Output image size too large"; + + case QR_ERR_WIDTH_TOO_LARGE: + return "Output image width too large"; + + case QR_ERR_HEIGHT_TOO_LARGE: + return "Output image height too large"; + + case QR_ERR_IMAGECREATE: + return "Failed to create image"; + + case QR_ERR_IMAGEFORMAT: + return "Failed to convert image"; + + case QR_ERR_IMAGEFRAME: + return "Failed to create frame"; + + /* zlib related errors */ + case QR_ERR_DEFLATE: + return "Failed to deflate"; + + /* unknown error(s) */ + case QR_ERR_UNKNOWN: + default: + return "Unknown error"; + } +} + +/* + * libqrのエラー番号からエラー情報を設定する + */ +QR_API void +qrSetErrorInfo(QRCode *qr, int errnum, const char *param) +{ + qr->errcode = errnum; + if (param != NULL) { + snprintf(&(qr->errinfo[0]), QR_ERR_MAX, "%s: %s", param, qrStrError(errnum)); + } else { + snprintf(&(qr->errinfo[0]), QR_ERR_MAX, "%s", qrStrError(errnum)); + } +} + +/* + * システム標準のエラー番号からエラー情報を設定する + */ +QR_API void +qrSetErrorInfo2(QRCode *qr, int errnum, const char *param) +{ + char *info; + int size = 0; + info = &(qr->errinfo[0]); + qr->errcode = QR_ERR_SEE_ERRNO; + if (param != NULL) { + size = snprintf(info, QR_ERR_MAX, "%s: ", param); + if (size < 0 || size >= QR_ERR_MAX) { + return; + } + info += size; + } +#ifdef WIN32 + snprintf(info, (size_t)(QR_ERR_MAX - size), "%s", strerror(errnum)); +#else + strerror_r(errnum, info, (size_t)(QR_ERR_MAX - size)); +#endif +} + +/* + * libqrのエラー番号と可変長パラメータからエラー情報を設定する + */ +QR_API void +qrSetErrorInfo3(QRCode *qr, int errnum, const char *fmt, ...) +{ + char info[QR_ERR_MAX]; + va_list ap; + + qr->errcode = errnum; + va_start(ap, fmt); + vsnprintf(&(info[0]), QR_ERR_MAX, fmt, ap); + va_end(ap); + snprintf(&(qr->errinfo[0]), QR_ERR_MAX, "%s%s", qrStrError(errnum), info); +} + +/* + * 最適な符号化方法を調べる + */ +QR_API int +qrDetectDataType(const qr_byte_t *source, int size) +{ + if (qrStrPosNotNumeric(source, size) == -1) { + return QR_EM_NUMERIC; + } + if (qrStrPosNotAlnum(source, size) == -1) { + return QR_EM_ALNUM; + } + if (qrStrPosNotKanji(source, size) == -1) { + return QR_EM_KANJI; + } + return QR_EM_8BIT; +} + +/* + * 数字以外のデータが現れる位置を調べる + */ +QR_API int +qrStrPosNotNumeric(const qr_byte_t *source, int size) +{ + int p = 0; + + while (p < size) { + if (source[p] < '0' || source[p] > '9') { + return p; + } + p++; + } + return -1; +} + +/* + * 英数字以外のデータが現れる位置を調べる + */ +QR_API int +qrStrPosNotAlnum(const qr_byte_t *source, int size) +{ + int p = 0; + + while (p < size) { + if (qr_alnumtable[source[p]] == -1) { + return p; + } + p++; + } + return -1; +} + +/* + * JIS X 0208漢字以外のデータが現れる位置を調べる + */ +QR_API int +qrStrPosNotKanji(const qr_byte_t *source, int size) +{ + qr_byte_t x, y; + int p = 0; + + while (p < size - 1) { + x = source[p++]; + if (x >= 0x81 && x <= 0x9f) { + x -= 0x81; + } else if (x >= 0xe0 && x <= 0xea) { + x -= 0xc1; + } else { + /* JIS X 0208漢字の1バイトめでない */ + return p - 1; + } + y = source[p++]; + if (y >= 0x40 && y <= 0xfc) { + y -= 0x40; + } else { + /* JIS X 0208漢字の2バイトめでない */ + return p - 1; + } + if (qr_dwtable_kanji[x][y] == -1) { + /* JIS X 0208漢字の未定義領域 */ + return p - 2; + } + } + if (p < size) { + return p; + } + return -1; +} + +/* + * 英数字もしくはJIS X 0208漢字のデータが現れる位置を調べる + */ +QR_API int +qrStrPosNot8bit(const qr_byte_t *source, int size) +{ + qr_byte_t x, y; + int p = 0; + + while (p < size) { + x = source[p++]; + if (qr_alnumtable[x] != -1) { + return p - 1; + } + if (p < size && ((x >= 0x81 && x <= 0x9f) || (x >= 0xe0 && x <= 0xea))) { + if (x < 0xa0) { + x -= 0x81; + } else { + x -= 0xc1; + } + y = source[p]; + if (y >= 0x40 && y <= 0xfc && qr_dwtable_kanji[x][y - 0x40] != -1) { + return p - 1; + } + } + } + return -1; +} + +/* + * デフォルトの符号化モードでsizeバイト符号化したときのビット長を返す + */ +QR_API int +qrGetEncodedLength(QRCode *qr, int size) +{ + return qrGetEncodedLength2(qr, size, qr->param.mode); +} + +/* + * 特定の符号化モードでsizeバイト符号化したときのビット長を返す + */ +QR_API int +qrGetEncodedLength2(QRCode *qr, int size, int mode) +{ + int n, v; + + /* + * モード指示子と文字数指示子のサイズ + */ + v = (qr->param.version == -1) ? QR_VER_MAX : qr->param.version; + n = 4 + qr_vertable[v].nlen[mode]; + + /* + * 符号化モードごとのデータサイズ + */ + switch (mode) { + case QR_EM_NUMERIC: + /* + * 数字モード: 3桁ごとに10ビット + * (余りは1桁なら4ビット, 2桁なら7ビット) + */ + n += (size / 3) * 10; + switch (size % 3) { + case 1: + n += 4; + break; + case 2: + n += 7; + break; + } + break; + case QR_EM_ALNUM: + /* + * 英数字モード: 2桁ごとに11ビット + * (余りは1桁につき6ビット) + */ + n += (size / 2) * 11; + if (size % 2 == 1) { + n += 6; + } + break; + case QR_EM_8BIT: + /* + * 8ビットバイトモード: 1桁ごとに8ビット + */ + n += size * 8; + break; + case QR_EM_KANJI: + /* + * 漢字モード: 1文字(2バイト)ごとに13ビット + */ + n += (size / 2) * 13; + break; + default: + qrSetErrorInfo(qr, QR_ERR_INVALID_MODE, NULL); + return -1; + } + + return n; +} + +/* + * デフォルトの符号化モードでsizeビットを上限として符号化可能な最大のバイト長を返す + */ +QR_API int +qrGetEncodableLength(QRCode *qr, int size) +{ + return qrGetEncodableLength2(qr, size, qr->param.mode); +} + +/* + * 特定の符号化モードでsizeビットを上限として符号化可能な最大のバイト長を返す + */ +QR_API int +qrGetEncodableLength2(QRCode *qr, int size, int mode) +{ + int l, m, n, v; + + /* + * モード指示子と文字数指示子のサイズ + */ + v = (qr->param.version == -1) ? QR_VER_MAX : qr->param.version; + n = size - 4 - qr_vertable[v].nlen[mode]; + if (n <= 0) { + return 0; + } + + /* + * 符号化モードごとのデータサイズ + */ + switch (mode) { + case QR_EM_NUMERIC: + /* + * 数字モード: 3桁ごとに10ビット + * (余りは1桁なら4ビット, 2桁なら7ビット) + */ + l = (n / 10) * 3; + m = n % 10; + if (m >= 7) { + l += 2; + } else if (m >= 4) { + l += 1; + } + break; + case QR_EM_ALNUM: + /* + * 英数字モード: 2桁ごとに11ビット + * (余りは1桁につき6ビット) + */ + l = (n / 11) * 2; + m = n % 11; + if (m >= 6) { + l += 1; + } + break; + case QR_EM_8BIT: + /* + * 8ビットバイトモード: 1桁ごとに8ビット + */ + l = n / 8; + break; + case QR_EM_KANJI: + /* + * 漢字モード: 1文字(2バイト)ごとに13ビット + */ + l = (n / 13) * 2; + break; + default: + qrSetErrorInfo(qr, QR_ERR_INVALID_MODE, NULL); + return -1; + } + + return l; +} + +/* + * データを追加する + */ +QR_API int +qrAddData(QRCode *qr, const qr_byte_t *source, int size) +{ + if (qr->state == QR_STATE_FINAL) { + qrSetErrorInfo(qr, QR_ERR_STATE, _QR_FUNCTION); + return FALSE; + } + return qrAddData2(qr, source, size, qr->param.mode); +} + +/* + * 符号化モードを指定してデータを追加する + */ +QR_API int +qrAddData2(QRCode *qr, const qr_byte_t *source, int size, int mode) +{ + int enclen, maxlen; + int version; + int pos, err; + + if (qr->state == QR_STATE_FINAL) { + qrSetErrorInfo(qr, QR_ERR_STATE, _QR_FUNCTION); + return FALSE; + } + + if (size <= 0) { + qrSetErrorInfo(qr, QR_ERR_EMPTY_SRC, NULL); + return FALSE; + } + + /* + * 入力データに最適な符号化モードを選ぶ + */ + if (mode == QR_EM_AUTO) { + mode = qrDetectDataType(source, size); + } else if (mode < QR_EM_NUMERIC || mode >= QR_EM_COUNT) { + qrSetErrorInfo(qr, QR_ERR_INVALID_MODE, NULL); + return FALSE; + } + + + /* + * 符号化後のデータ長を計算する + */ + enclen = qrGetEncodedLength2(qr, size, mode); + if (enclen == -1) { + return FALSE; + } + version = (qr->param.version == -1) ? QR_VER_MAX : qr->param.version; + maxlen = 8 * qr_vertable[version].ecl[qr->param.eclevel].datawords; + if (qr->enclen + enclen > maxlen) { + qrSetErrorInfo3(qr, QR_ERR_LARGE_SRC, ", %d total encoded bits" + " (max %d bits on version=%d, ecl=%s)", + qr->enclen + enclen, maxlen, version, qr_eclname[qr->param.eclevel]); + return FALSE; + } + if (qr->param.version == -1) { + qr->delta1 += qr_vertable[QR_VER_MAX].nlen[mode] - qr_vertable[VERPOINT1].nlen[mode]; + qr->delta2 += qr_vertable[QR_VER_MAX].nlen[mode] - qr_vertable[VERPOINT2].nlen[mode]; + } + + /* + * 型番が指定されていれば、入力データをバッファリングせず直接エンコードする + */ + if (qr->param.version != -1) { + qr->enclen += enclen; + if (!qrHasData(qr)) { + qrInitDataWord(qr); + } + if (qrEncodeDataWord(qr, source, size, mode) == TRUE) { + qr->state = QR_STATE_SET; + return TRUE; + } + return FALSE; + } + + /* + * 入力データを検証する + */ + pos = -1; + err = QR_ERR_NONE; + switch (mode) { + case QR_EM_NUMERIC: + pos = qrStrPosNotNumeric(source, size); + err = QR_ERR_NOT_NUMERIC; + break; + case QR_EM_ALNUM: + pos = qrStrPosNotAlnum(source, size); + err = QR_ERR_NOT_ALNUM; + break; + case QR_EM_KANJI: + pos = qrStrPosNotKanji(source, size); + err = QR_ERR_NOT_KANJI; + break; + } + if (pos != -1) { + qrSetErrorInfo3(qr, err, " at offset %d", pos); + return FALSE; + } + qr->enclen += enclen; + + /* + * バッファの容量が足りないときは追加で確保する + */ + while (qr->srcmax < qr->srclen + size + 6) { + qr->srcmax += QR_SRC_MAX; + qr->source = (qr_byte_t *)realloc(qr->source, qr->srcmax); + if (qr->source == NULL) { + qr->srcmax = 0; + qrSetErrorInfo2(qr, QR_ERR_MEMORY_EXHAUSTED, _QR_FUNCTION); + return FALSE; + } + } + + /* + * バッファにデータを保存する + */ + qr->source[qr->srclen++] = (qr_byte_t)(mode | 0x80); + qr->source[qr->srclen++] = (qr_byte_t)((size >> 24) & 0x7F); + qr->source[qr->srclen++] = (qr_byte_t)((size >> 16) & 0xFF); + qr->source[qr->srclen++] = (qr_byte_t)((size >> 8) & 0xFF); + qr->source[qr->srclen++] = (qr_byte_t)(size & 0xFF); + memcpy(&(qr->source[qr->srclen]), source, (size_t)size); + qr->srclen += size; + qr->source[qr->srclen] = '\0'; + + qr->state = QR_STATE_SET; + return TRUE; +} + +/* + * 構造的連接の最後のQRコードオブジェクトにデータを追加する + */ +QR_API int +qrsAddData(QRStructured *st, const qr_byte_t *source, int size) +{ + if (st->state == QR_STATE_FINAL) { + qrSetErrorInfo(st->cur, QR_ERR_STATE, _QR_FUNCTION); + return FALSE; + } + return qrsAddData2(st, source, size, st->param.mode); +} + +/* + * 構造的連接の最後のQRコードオブジェクトに符号化モードを指定してデータを追加する + */ +QR_API int +qrsAddData2(QRStructured *st, const qr_byte_t *source, int size, int mode) +{ + int enclen, maxlen, limit, remain; + int sizes[QR_STA_MAX] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + int i, j; + int p; + + if (st->state == QR_STATE_FINAL) { + qrSetErrorInfo(st->cur, QR_ERR_STATE, _QR_FUNCTION); + return FALSE; + } + + if (size <= 0) { + qrSetErrorInfo(st->cur, QR_ERR_EMPTY_SRC, NULL); + return FALSE; + } + + /* + * 入力データに最適な符号化モードを選ぶ + */ + if (mode == QR_EM_AUTO) { + mode = qrDetectDataType(source, size); + } + + /* + * 残りデータ容量を計算する + */ + maxlen = 8 * qr_vertable[st->param.version].ecl[st->param.eclevel].datawords; + limit = maxlen - QR_STA_LEN; + if (!qrHasData(st->cur)) { + remain = limit; + } else { + remain = qrRemainedDataBits(st->cur); + } + + /* + * 符号化後のデータ長を計算する + */ + enclen = qrGetEncodedLength2(st->cur, size, mode); + if (enclen == -1) { + return FALSE; + } + j = 0; + if (enclen > remain) { + int l, r, s; + r = remain; + s = size; + for (i = 0; i <= st->max - st->num; i++) { + j++; + l = qrGetEncodableLength2(st->cur, r, mode); + if (s <= l) { + sizes[i] = s; + s = 0; + break; + } else { + sizes[i] = l; + s -= l; + r = limit; + } + } + if (s > 0) { + int snum, reqlen; + snum = (enclen + maxlen - 1) / maxlen - (st->num - 1); + reqlen = maxlen * (st->num - 1); + reqlen += maxlen - remain; + reqlen += enclen; + reqlen += qr_vertable[st->param.version].nlen[mode] * (snum - 1) + QR_STA_LEN * snum; + qrSetErrorInfo3(st->cur, QR_ERR_LARGE_SRC, ", %d total encoded bits" + " (max %d bits on version=%d, ecl=%s, num=%d)", + reqlen, maxlen * st->max, + st->param.version, qr_eclname[st->param.eclevel], st->max); + return FALSE; + } + } else { + j = 1; + sizes[0] = size; + } + + /* + * 入力データをエンコードする + */ + p = 0; + i = 0; + while (i < j) { + if (sizes[i] == 0 && i != 0) { + break; + } + if (!qrHasData(st->cur)) { + /* + * データコード語を初期化し、仮の構造的連接ヘッダを追加する + */ + qrInitDataWord(st->cur); + qrAddDataBits(st->cur, 4, 0); + qrAddDataBits(st->cur, 4, 0); + qrAddDataBits(st->cur, 4, 0); + qrAddDataBits(st->cur, 8, 0); + } + if (sizes[i] != 0) { + st->cur->enclen += qrGetEncodedLength2(st->cur, sizes[i], mode); + if (qrEncodeDataWord(st->cur, source + p, sizes[i], mode) == TRUE) { + st->cur->state = QR_STATE_SET; + st->state = QR_STATE_SET; + } else { + return FALSE; + } + p += sizes[i]; + } + i++; + if (i < j && sizes[i] > 0) { + /* + * 次のQRコードオブジェクトを初期化する + */ + int errcode; + st->qrs[st->num] = qrInit(st->param.version, st->param.mode, + st->param.eclevel, st->param.masktype, &errcode); + if (st->qrs[st->num] == NULL) { + qrSetErrorInfo(st->cur, errcode, NULL); + return FALSE; + } + st->cur = st->qrs[st->num]; + st->num++; + } + } + + /* + * パリティを計算する + */ + p = 0; + while (p < size) { + st->parity ^= source[p++]; + } + + return TRUE; +} + +/* + * データコード語を初期化する + */ +static int +qrInitDataWord(QRCode *qr) +{ + /* + * データコード語領域をゼロクリアする + */ + memset(qr->dataword, '\0', QR_DWD_MAX); + + /* + * 追加位置をバイト0の最上位ビットにする + */ + qr->dwpos = 0; + qr->dwbit = 7; + + return TRUE; +} + +/* + * データコード語をエンコードする + */ +static int +qrEncodeDataWord(QRCode *qr, const qr_byte_t *source, int size, int mode) +{ + int p = 0; + int e = QR_ERR_NONE; + int n = 0; + int word = 0; + int dwpos = qr->dwbit; + int dwbit = qr->dwpos; + + if (mode < QR_EM_NUMERIC || mode >= QR_EM_COUNT) { + e = QR_ERR_INVALID_MODE; + goto err; + } + + /* + * モード指示子(4ビット)を追加する + */ + qrAddDataBits(qr, 4, qr_modeid[mode]); + + /* + * 文字数指示子(8〜16ビット)を追加する + * ビット数は型番とモードによって異なる + */ + if (mode == QR_EM_KANJI) { + qrAddDataBits(qr, qr_vertable[qr->param.version].nlen[mode], size / 2); + } else { + qrAddDataBits(qr, qr_vertable[qr->param.version].nlen[mode], size); + } + + /* + * 入力データを符号化する + */ + switch (mode) { + case QR_EM_NUMERIC: + /* + * 数字モード + * 3桁ずつ10ビットの2進数に変換する + * 余りは1桁なら4ビット、2桁なら7ビットにする + */ + while (p < size) { + qr_byte_t q = source[p]; + if (q < '0' || q > '9') { + /* 数字でない */ + e = QR_ERR_NOT_NUMERIC; + goto err; + } + word = word * 10 + (q - '0'); + /* + * 3桁たまったら10ビットで追加する + */ + if (++n >= 3) { + qrAddDataBits(qr, 10, word); + n = 0; + word = 0; + } + p++; + } + /* + * 余りの桁を追加する + */ + if (n == 1) { + qrAddDataBits(qr, 4, word); + } else if (n == 2) { + qrAddDataBits(qr, 7, word); + } + break; + + case QR_EM_ALNUM: + /* + * 英数字モード + * 2桁ずつ11ビットの2進数に変換する + * 余りは6ビットとして変換する + */ + while (p < size) { + signed char q = qr_alnumtable[source[p]]; + if (q == -1) { + /* 符号化可能な英数字でない */ + e = QR_ERR_NOT_ALNUM; + goto err; + } + word = word * 45 + (int)q; + /* + * 2桁たまったら11ビットで追加する + */ + if (++n >= 2) { + qrAddDataBits(qr, 11, word); + n = 0; + word = 0; + } + p++; + } + /* + * 余りの桁を追加する + */ + if (n == 1) { + qrAddDataBits(qr, 6, word); + } + break; + + case QR_EM_8BIT: + /* + * 8ビットバイトモード + * 各バイトを直接8ビット値として追加する + */ + while (p < size) { + qrAddDataBits(qr, 8, (int)source[p++]); + } + break; + + case QR_EM_KANJI: + /* + * 漢字モード + * 2バイトを13ビットに変換して追加する + */ + while (p < size - 1) { + qr_byte_t x, y; + /* + * 第1バイトの処理 + * 0x81-0x9fなら0x81を引く + * 0xe0,0xeaなら0xc1を引く + */ + x = source[p++]; + if (x >= 0x81 && x <= 0x9f) { + x -= 0x81; + } else if (x >= 0xe0 && x <= 0xea) { + x -= 0xc1; + } else { + /* JIS X 0208漢字の1バイトめでない */ + p -= 1; + e = QR_ERR_NOT_KANJI; + goto err; + } + /* + * 第2バイトの処理 + * 0x40を引く + */ + y = source[p++]; + if (y >= 0x40 && y <= 0xfc) { + y -= 0x40; + } else { + /* JIS X 0208漢字の2バイトめでない */ + p -= 1; + e = QR_ERR_NOT_KANJI; + goto err; + } + /* + * 結果を13ビットの値として追加する + */ + word = (int)qr_dwtable_kanji[x][y]; + if (word == -1) { + /* JIS X 0208漢字の未定義領域 */ + p -= 2; + e = QR_ERR_NOT_KANJI; + goto err; + } + qrAddDataBits(qr, 13, word); + } + if (p < size) { + /* + * 末尾に余分なバイトがある + */ + e = QR_ERR_NOT_KANJI; + goto err; + } + break; + + default: + e = QR_ERR_INVALID_MODE; + goto err; + } + + return TRUE; + + err: + qr->dwpos = dwpos; + qr->dwbit = dwbit; + if (e == QR_ERR_INVALID_MODE) { + qrSetErrorInfo(qr, e, NULL); + } else { + qrSetErrorInfo3(qr, e, " at offset %d", p); + } + return FALSE; +} + +/* + * データコード語の余りを埋める + */ +static int +qrFinalizeDataWord(QRCode *qr) +{ + int n, m; + int word; + + /* + * 終端パターンを追加する(最大4ビットの0) + */ + n = qrRemainedDataBits(qr); + if (n < 4) { + qrAddDataBits(qr, n, 0); + n = 0; + } else { + qrAddDataBits(qr, 4, 0); + n -= 4; + } + /* + * 末尾のデータコード語の全ビットが埋まっていなければ + * 余りを埋め草ビット(0)で埋める + */ + m = n % 8; + if (m > 0) { + qrAddDataBits(qr, m, 0); + n -= m; + } + + /* + * 残りのデータコード語に埋め草コード語1,2を交互に埋める + */ + word = PADWORD1; + while (n >= 8) { + qrAddDataBits(qr, 8, word); + if (word == PADWORD1) { + word = PADWORD2; + } else { + word = PADWORD1; + } + n -= 8; + } + + return TRUE; +} + +/* + * データコード語にビット列を追加する + */ +static void +qrAddDataBits(QRCode *qr, int n, int word) +{ + /* + * 上位ビットから順に処理(ビット単位で処理するので遅い) + */ + while (n-- > 0) { + /* + * ビット追加位置にデータの下位からnビットめをORする + */ + qr->dataword[qr->dwpos] |= ((word >> n) & 1) << qr->dwbit; + /* + * 次のビット追加位置に進む + */ + if (--qr->dwbit < 0) { + qr->dwpos++; + qr->dwbit = 7; + } + } +} + +/* + * データコード語の残りビット数を返す + */ +QR_API int +qrRemainedDataBits(QRCode *qr) +{ + int version; + version = (qr->param.version == -1) ? QR_VER_MAX : qr->param.version; + return (qr_vertable[version].ecl[qr->param.eclevel].datawords - qr->dwpos) * 8 - (7 - qr->dwbit); +} + +/* + * RSブロックごとに誤り訂正コード語を計算する + */ +static int +qrComputeECWord(QRCode *qr) +{ + int i, j, k, m; + int ecwtop, dwtop, nrsb, rsbnum; + qr_byte_t rswork[QR_RSD_MAX]; + + /* + * データコード語をRSブロックごとに読み出し、 + * それぞれについて誤り訂正コード語を計算する + * RSブロックは長さによってnrsb種類に分かれ、 + * それぞれの長さについてrsbnum個のブロックがある + */ + dwtop = 0; + ecwtop = 0; + nrsb = qr_vertable[qr->param.version].ecl[qr->param.eclevel].nrsb; +#define rsb qr_vertable[qr->param.version].ecl[qr->param.eclevel].rsb +#define gfvector qr_gftable[ecwlen] + for (i = 0; i < nrsb; i++) { + int dwlen, ecwlen; + /*unsigned char *gfvector;*/ + /*qr_rsblock_t *rsbp;*/ + /* + * この長さのRSブロックの個数(rsbnum)と + * RSブロック内のデータコード語の長さ(dwlen)、 + * 誤り訂正コード語の長さ(ecwlen)を求める + * また誤り訂正コード語の長さから、使われる + * 誤り訂正生成多項式(gfvector)を選ぶ + */ + /*rsbp = &(qr_vertable[qr->param.version].ecl[qr->param.eclevel].rsb[i]); + rsbnum = rsbp->rsbnum; + dwlen = rsbp->datawords; + ecwlen = rsbp->totalwords - rsbp->datawords;*/ + rsbnum = rsb[i].rsbnum; + dwlen = rsb[i].datawords; + ecwlen = rsb[i].totalwords - rsb[i].datawords; + /*gfvector = qr_gftable[ecwlen];*/ + /* + * それぞれのRSブロックについてデータコード語を + * 誤り訂正生成多項式で除算し、結果を誤り訂正 + * コード語とする + */ + for (j = 0; j < rsbnum; j++) { + /* + * RS符号計算用作業領域をクリアし、 + * 当該RSブロックのデータコード語を + * 多項式係数とみなして作業領域に入れる + * (作業領域の大きさはRSブロックの + * データコード語と誤り訂正コード語の + * いずれか長いほうと同じだけ必要) + */ + memset(&(rswork[0]), '\0', QR_RSD_MAX); + memcpy(&(rswork[0]), &(qr->dataword[dwtop]), (size_t)dwlen); + /* + * 多項式の除算を行う + * (各次数についてデータコード語の初項係数から + * 誤り訂正生成多項式への乗数を求め、多項式 + * どうしの減算により剰余を求めることをくり返す) + */ + for (k = 0; k < dwlen; k++) { + int e; + if (rswork[0] == 0) { + /* + * 初項係数がゼロなので、各項係数を + * 左にシフトして次の次数に進む + */ + for (m = 0; m < QR_RSD_MAX-1; m++) { + rswork[m] = rswork[m+1]; + } + rswork[QR_RSD_MAX-1] = 0; + continue; + } + /* + * データコード語の初項係数(整数表現)から + * 誤り訂正生成多項式への乗数(べき表現)を求め、 + * 残りの各項について剰余を求めるために + * データコード語の各項係数を左にシフトする + */ + e = qr_fac2exp[rswork[0]]; + for (m = 0; m < QR_RSD_MAX-1; m++) { + rswork[m] = rswork[m+1]; + } + rswork[QR_RSD_MAX-1] = 0; + /* + * 誤り訂正生成多項式の各項係数に上で求めた + * 乗数を掛け(べき表現の加算により求める)、 + * データコード語の各項から引いて(整数表現の + * 排他的論理和により求める)、剰余を求める + */ + for (m = 0; m < ecwlen; m++) { + rswork[m] ^= qr_exp2fac[(gfvector[m] + e) % 255]; + } + } + /* + * 多項式除算の剰余を当該RSブロックの + * 誤り訂正コードとする + */ + memcpy(&(qr->ecword[ecwtop]), &(rswork[0]), (size_t)ecwlen); + /* + * データコード語の読み出し位置と + * 誤り訂正コード語の書き込み位置を + * 次のRSブロック開始位置に移動する + */ + dwtop += dwlen; + ecwtop += ecwlen; + } + } +#undef rsb +#undef gfvector + return TRUE; +} + +/* + * データコード語と誤り訂正コード語から最終的なコード語を作る + */ +static int +qrMakeCodeWord(QRCode *qr) +{ + int i, j, k, cwtop, pos; + int dwlenmax, ecwlenmax; + int dwlen, ecwlen, nrsb; + /*qr_rsblock_t *rsb;*/ + + /* + * RSブロックのサイズ種類数(nrsb)および + * 最大RSブロックのデータコード語数(dwlenmax)、 + * 誤り訂正コード語数(ecwlenmax)を得る + */ + nrsb = qr_vertable[qr->param.version].ecl[qr->param.eclevel].nrsb; + /*rsb = qr_vertable[qr->param.version].ecl[qr->param.eclevel].rsb;*/ +#define rsb qr_vertable[qr->param.version].ecl[qr->param.eclevel].rsb + dwlenmax = rsb[nrsb-1].datawords; + ecwlenmax = rsb[nrsb-1].totalwords - rsb[nrsb-1].datawords; + /* + * 各RSブロックから順にデータコード語を取り出し + * コード語領域(qr->codeword)に追加する + */ + cwtop = 0; + for (i = 0; i < dwlenmax; i++) { + pos = i; + /* + * RSブロックのサイズごとに処理を行う + */ + for (j = 0; j < nrsb; j++) { + dwlen = rsb[j].datawords; + /* + * 同じサイズのRSブロックは順に処理する + */ + for (k = 0; k < rsb[j].rsbnum; k++) { + /* + * 各RSブロックのiバイトめのデータ + * コード語をコード語領域に追加する + * (すでにすべてのデータコード語を + * 取り出したRSブロックは飛ばす) + */ + if (i < dwlen) { + qr->codeword[cwtop++] = qr->dataword[pos]; + } + /* + * 次のRSブロックのiバイトめに進む + */ + pos += dwlen; + } + } + } + /* + * 各RSブロックから順に誤り訂正コード語を取り出し + * コード語領域(qr->codeword)に追加する + */ + for (i = 0; i < ecwlenmax; i++) { + pos = i; + /* + * RSブロックのサイズごとに処理を行う + */ + for (j = 0; j < nrsb; j++) { + ecwlen = rsb[j].totalwords - rsb[j].datawords; + /* + * 同じサイズのRSブロックは順に処理する + */ + for (k = 0; k < rsb[j].rsbnum; k++) { + /* + * 各RSブロックのiバイトめの誤り訂正 + * コード語をコード語領域に追加する + * (すでにすべての誤り訂正コード語を + * 取り出したRSブロックは飛ばす) + */ + if (i < ecwlen) { + qr->codeword[cwtop++] = qr->ecword[pos]; + } + /* + * 次のRSブロックのiバイトめに進む + */ + pos += ecwlen; + } + } + } +#undef rsb +#undef nrsb + return TRUE; +} + +/* + * シンボルを初期化し、機能パターンを配置する + */ +static int +qrFillFunctionPattern(QRCode *qr) +{ + int i, j, n, dim, xpos, ypos; + + /* + * シンボルの1辺の長さを求める + */ + dim = qr_vertable[qr->param.version].dimension; + /* + * シンボル全体をクリアする + */ + qrFree(qr->symbol); + qrFree(qr->_symbol); + qr->_symbol = (qr_byte_t *)calloc((size_t)dim, (size_t)dim); + if (qr->_symbol == NULL) { + return FALSE; + } + qr->symbol = (qr_byte_t **)malloc(sizeof(qr_byte_t *) * (size_t)dim); + if (qr->symbol == NULL) { + free(qr->_symbol); + return FALSE; + } + for (i = 0; i < dim; i++) { + qr->symbol[i] = qr->_symbol + dim * i; + } + /* + * 左上、右上、左下の隅に位置検出パターンを配置する + */ + for (i = 0; i < QR_DIM_FINDER; i++) { + for (j = 0; j < QR_DIM_FINDER; j++) { + qr->symbol[i][j] = qr_finderpattern[i][j]; + qr->symbol[i][dim-1-j] = qr_finderpattern[i][j]; + qr->symbol[dim-1-i][j] = qr_finderpattern[i][j]; + } + } + /* + * 位置検出パターンの分離パターンを配置する + */ + for (i = 0; i < QR_DIM_FINDER+1; i++) { + qr->symbol[i][QR_DIM_FINDER] = QR_MM_FUNC; + qr->symbol[QR_DIM_FINDER][i] = QR_MM_FUNC; + qr->symbol[i][dim-1-QR_DIM_FINDER] = QR_MM_FUNC; + qr->symbol[dim-1-QR_DIM_FINDER][i] = QR_MM_FUNC; + qr->symbol[dim-1-i][QR_DIM_FINDER] = QR_MM_FUNC; + qr->symbol[QR_DIM_FINDER][dim-1-i] = QR_MM_FUNC; + } + /* + * 位置合わせパターンを配置する + */ + n = qr_vertable[qr->param.version].aplnum; + for (i = 0; i < n; i++) { + for (j = 0; j < n; j++) { + int x, y, x0, y0, xcenter, ycenter; + /* + * 位置合わせパターンの中心と左上の座標を求める + */ + ycenter = qr_vertable[qr->param.version].aploc[i]; + xcenter = qr_vertable[qr->param.version].aploc[j]; + y0 = ycenter - QR_DIM_ALIGN / 2; + x0 = xcenter - QR_DIM_ALIGN / 2; + if (qrIsFunc(qr, ycenter, xcenter)) { + /* + * 位置検出パターンと重なるときは配置しない + */ + continue; + } + for (y = 0; y < QR_DIM_ALIGN; y++) { + for (x = 0; x < QR_DIM_ALIGN; x++) { + qr->symbol[y0+y][x0+x] = qr_alignpattern[y][x]; + } + } + } + } + /* + * タイミングパターンを配置する + */ + for (i = QR_DIM_FINDER; i < dim-1-QR_DIM_FINDER; i++) { + qr->symbol[i][QR_DIM_TIMING] = QR_MM_FUNC; + qr->symbol[QR_DIM_TIMING][i] = QR_MM_FUNC; + if ((i & 1) == 0) { + qr->symbol[i][QR_DIM_TIMING] |= QR_MM_BLACK; + qr->symbol[QR_DIM_TIMING][i] |= QR_MM_BLACK; + } + } + /* + * 形式情報の領域を予約する + */ + for (i = 0; i < 2; i++) { + for (j = 0; j < QR_FIN_MAX; j++) { + xpos = (qr_fmtinfopos[i][j].xpos + dim) % dim; + ypos = (qr_fmtinfopos[i][j].ypos + dim) % dim; + qr->symbol[ypos][xpos] |= QR_MM_FUNC; + } + } + xpos = (qr_fmtblackpos.xpos + dim) % dim; + ypos = (qr_fmtblackpos.ypos + dim) % dim; + qr->symbol[ypos][xpos] |= QR_MM_FUNC; + /* + * 型番情報が有効(型番7以上)なら + * 型番情報の領域を予約する + */ + if (qr_verinfo[qr->param.version] != -1L) { + for (i = 0; i < 2; i++) { + for (j = 0; j < QR_VIN_MAX; j++) { + xpos = (qr_verinfopos[i][j].xpos + dim) % dim; + ypos = (qr_verinfopos[i][j].ypos + dim) % dim; + qr->symbol[ypos][xpos] |= QR_MM_FUNC; + } + } + } + + return TRUE; +} + +/* + * シンボルに符号化されたコード語を配置する + */ +static int +qrFillCodeWord(QRCode *qr) +{ + int i, j; + + /* + * シンボル右下隅から開始する + */ + qrInitPosition(qr); + /* + * コード語領域のすべてのバイトについて... + */ + for (i = 0; i < qr_vertable[qr->param.version].totalwords; i++) { + /* + * 最上位ビットから順に各ビットを調べ... + */ + for (j = 7; j >= 0; j--) { + /* + * そのビットが1なら黒モジュールを置く + */ + if ((qr->codeword[i] & (1 << j)) != 0) { + qr->symbol[qr->ypos][qr->xpos] |= QR_MM_DATA; + } + /* + * 次のモジュール配置位置に移動する + */ + qrNextPosition(qr); + } + } + + return TRUE; +} + +/* + * モジュール配置の初期位置と配置方向を決める + */ +static void +qrInitPosition(QRCode *qr) +{ + /* + * シンボルの右下隅から配置を始める + */ + qr->xpos = qr->ypos = qr_vertable[qr->param.version].dimension - 1; + /* + * 最初の移動方向は左向き、次に上向き + */ + qr->xdir = -1; + qr->ydir = -1; +} + +/* + * 次のモジュール配置位置を決める + */ +static void +qrNextPosition(QRCode *qr) +{ + do { + /* + * qr->xdir方向に1モジュール移動して + * qr->xdirの向きを逆にする + * 右に移動したときはqr->ydir方向にも + * 1モジュール移動する + */ + qr->xpos += qr->xdir; + if (qr->xdir > 0) { + qr->ypos += qr->ydir; + } + qr->xdir = -qr->xdir; + /* + * y方向にシンボルをはみ出すようなら + * y方向ではなくx方向に2モジュール左に移動し、 + * かつqr->ydirの向きを逆にする + * qr->xposが縦のタイミングパターン上なら + * さらに1モジュール左に移動する + */ + if (qr->ypos < 0 || qr->ypos >= qr_vertable[qr->param.version].dimension) { + qr->ypos -= qr->ydir; + qr->ydir = -qr->ydir; + qr->xpos -= 2; + if (qr->xpos == QR_DIM_TIMING) { + qr->xpos--; + } + } + /* + * 新しい位置が機能パターン上なら + * それをよけて次の候補位置を探す + */ + } while (qrIsFunc(qr, qr->ypos, qr->xpos)); +} + +/* + * シンボルを最適なマスクパターンでマスクする + */ +static int +qrSelectMaskPattern(QRCode *qr) +{ + int type; + long penalty, xpenalty; + + if (qr->param.masktype >= 0) { + /* + * マスクパターンが引数で指定されていたので + * そのパターンでマスクして終了 + */ + return qrApplyMaskPattern(qr); + } + /* + * すべてのマスクパターンを評価する + */ + xpenalty = -1L; + for (type = 0; type < QR_MPT_MAX; type++) { + /* + * 当該マスクパターンでマスクして評価する + */ + qrApplyMaskPattern2(qr, type); + penalty = qrEvaluateMaskPattern(qr); + /* + * 失点がこれまでより低かったら記録する + */ + if (xpenalty == -1L || penalty < xpenalty) { + qr->param.masktype = type; + xpenalty = penalty; + } + } + /* + * 失点が最低のパターンでマスクする + */ + return qrApplyMaskPattern(qr); +} + +/* + * 設定済みの参照子のマスクパターンでシンボルをマスクする + */ +static int +qrApplyMaskPattern(QRCode *qr) +{ + return qrApplyMaskPattern2(qr, qr->param.masktype); +} + +/* + * 指定した参照子のマスクパターンでシンボルをマスクする + */ +static int +qrApplyMaskPattern2(QRCode *qr, int type) +{ + + int i, j, dim; + + if (type < 0 || type >= QR_MPT_MAX) { + qrSetErrorInfo3(qr, QR_ERR_INVALID_MPT, "%d", type); + return FALSE; + } + + dim = qr_vertable[qr->param.version].dimension; + /* + * 以前のマスクパターンをクリアし、 + * 符号化済みデータを初期パターンとする + */ + for (i = 0; i < dim; i++) { + for (j = 0; j < dim; j++) { + /* + * 機能パターン領域の印字黒モジュールは残す + */ + if (qrIsFunc(qr, i, j)) { + continue; + } + /* + * 符号化データ領域は符号化データの + * 黒モジュールを印字黒モジュールにする + */ + if (qrIsData(qr, i, j)) { + qr->symbol[i][j] |= QR_MM_BLACK; + } else { + qr->symbol[i][j] &= ~QR_MM_BLACK; + } + } + } + /* + * i行j列のモジュールについて... + */ + for (i = 0; i < dim; i++) { + for (j = 0; j < dim; j++) { + if (qrIsFunc(qr, i, j)) { + /* + * 機能パターン領域(および形式情報、 + * 型番情報)はマスク対象から除外する + */ + continue; + } + /* + * 指定された条件を満たすモジュールを反転する + */ + if ((type == 0 && (i + j) % 2 == 0) || + (type == 1 && i % 2 == 0) || + (type == 2 && j % 3 == 0) || + (type == 3 && (i + j) % 3 == 0) || + (type == 4 && ((i / 2) + (j / 3)) % 2 == 0) || + (type == 5 && (i * j) % 2 + (i * j) % 3 == 0) || + (type == 6 && ((i * j) % 2 + (i * j) % 3) % 2 == 0) || + (type == 7 && ((i * j) % 3 + (i + j) % 2) % 2 == 0)) + { + qr->symbol[i][j] ^= QR_MM_BLACK; + } + } + } + + return TRUE; +} + +/* + * マスクパターンを評価し評価値を返す + */ +static long +qrEvaluateMaskPattern(QRCode *qr) +{ + int i, j, m, n, dim; + long penalty; + + /* + * 評価値をpenaltyに積算する + * マスクは符号化領域に対してのみ行うが + * 評価はシンボル全体について行われる + */ + penalty = 0L; + dim = qr_vertable[qr->param.version].dimension; + /* + * 特徴: 同色の行/列の隣接モジュール + * 評価条件: モジュール数 = (5+i) + * 失点: 3+i + */ + for (i = 0; i < dim; i++) { + n = 0; + for (j = 0; j < dim; j++) { + if (j > 0 && qrIsBlack(qr, i, j) == qrIsBlack(qr, i, j-1)) { + /* + * すぐ左と同色のモジュール + * 同色列の長さを1増やす + */ + n++; + } else { + /* + * 色が変わった + * 直前で終わった同色列の長さを評価する + */ + if (n >= 5) { + penalty += (long)(3 + (n - 5)); + } + n = 1; + } + } + /* + * 列が尽きた + * 直前で終わった同色列の長さを評価する + */ + if (n >= 5) { + penalty += (long)(3 + (n - 5)); + } + } + for (i = 0; i < dim; i++) { + n = 0; + for (j = 0; j < dim; j++) { + if (j > 0 && qrIsBlack(qr, j, i) == qrIsBlack(qr, j-1, i)) { + /* + * すぐ上と同色のモジュール + * 同色列の長さを1増やす + */ + n++; + } else { + /* + * 色が変わった + * 直前で終わった同色列の長さを評価する + */ + if (n >= 5) { + penalty += (long)(3 + (n - 5)); + } + n = 1; + } + } + /* + * 列が尽きた + * 直前で終わった同色列の長さを評価する + */ + if (n >= 5) { + penalty += (long)(3 + (n - 5)); + } + } + /* + * 特徴: 同色のモジュールブロック + * 評価条件: ブロックサイズ = 2×2 + * 失点: 3 + */ + for (i = 0; i < dim - 1; i++) { + for (j = 0; j < dim - 1; j++) { + if (qrIsBlack(qr, i, j) == qrIsBlack(qr, i, j+1) && + qrIsBlack(qr, i, j) == qrIsBlack(qr, i+1, j) && + qrIsBlack(qr, i, j) == qrIsBlack(qr, i+1, j+1)) + { + /* + * 2×2の同色のブロックがあった + */ + penalty += 3L; + } + } + } + /* + * 特徴: 行/列における1:1:3:1:1比率(暗:明:暗:明:暗)のパターン + * に続いて比率4の幅以上の明パターン + * 失点: 40 + * 前後はシンボル境界外か明モジュールである必要がある + * 2:2:6:2:2のようなパターンにも失点を与えるべきかは + * JIS規格からは読み取れない。ここでは与えていない + */ + for (i = 0; i < dim; i++) { + for (j = 0; j < dim - 6; j++) { + if ((j == 0 || !qrIsBlack(qr, i, j-1)) && + qrIsBlack(qr, i, j+0) && + !qrIsBlack(qr, i, j+1) && + qrIsBlack(qr, i, j+2) && + qrIsBlack(qr, i, j+3) && + qrIsBlack(qr, i, j+4) && + !qrIsBlack(qr, i, j+5) && + qrIsBlack(qr, i, j+6)) + { + int k, l; + l = 1; + for (k = 0; k < dim - j - 7 && k < 4; k++) { + if (qrIsBlack(qr, i, j + k + 7)) { + l = 0; + break; + } + } + /* + * パターンがあった + */ + if (l) { + penalty += 40L; + } + } + } + } + for (i = 0; i < dim; i++) { + for (j = 0; j < dim - 6; j++) { + if ((j == 0 || !qrIsBlack(qr, j-1, i)) && + qrIsBlack(qr, j+0, i) && + !qrIsBlack(qr, j+1, i) && + qrIsBlack(qr, j+2, i) && + qrIsBlack(qr, j+3, i) && + qrIsBlack(qr, j+4, i) && + !qrIsBlack(qr, j+5, i) && + qrIsBlack(qr, j+6, i) && + (j == dim-7 || !qrIsBlack(qr, j+7, i))) + { + int k, l; + l = 1; + for (k = 0; k < dim - j - 7 && k < 4; k++) { + if (qrIsBlack(qr, j + k + 7, i)) { + l = 0; + break; + } + } + /* + * パターンがあった + */ + if (l) { + penalty += 40L; + } + } + } + } + /* + * 特徴: 全体に対する暗モジュールの占める割合 + * 評価条件: 50±(5×k)%〜50±(5×(k+1))% + * 失点: 10×k + */ + m = 0; + n = 0; + for (i = 0; i < dim; i++) { + for (j = 0; j < dim; j++) { + m++; + if (qrIsBlack(qr, i, j)) { + n++; + } + } + } + penalty += (long)(abs((n * 100 / m) - 50) / 5 * 10); + return penalty; +} + +/* + * シンボルに形式情報と型番情報を配置する + */ +static int +qrFillFormatInfo(QRCode *qr) +{ + int i, j, dim, fmt, modulo, xpos, ypos; + long v; + + dim = qr_vertable[qr->param.version].dimension; + /* + * 形式情報を計算する + * 誤り訂正レベル2ビット(L:01, M:00, Q:11, H:10)と + * マスクパターン参照子3ビットからなる計5ビットに + * Bose-Chaudhuri-Hocquenghem(15,5)符号による + * 誤り訂正ビット10ビットを付加して15ビットとする + * (5ビットをxの次数14〜10の多項式係数とみなして + * 多項式x^10+x^8+x^5+x^4+x^2+x+1(係数10100110111) + * で除算した剰余10ビットを誤り訂正ビットとする) + * さらにすべてのビットがゼロにならないように + * 101010000010010(0x5412)とXORをとる + */ + fmt = ((qr->param.eclevel ^ 1) << 3) | qr->param.masktype; + modulo = fmt << 10; + for (i = 14; i >= 10; i--) { + if ((modulo & (1 << i)) == 0) { + continue; + } + modulo ^= 0x537 << (i - 10); + } + fmt = ((fmt << 10) + modulo) ^ 0x5412; + /* + * 形式情報をシンボルに配置する + */ + for (i = 0; i < 2; i++) { + for (j = 0; j < QR_FIN_MAX; j++) { + if ((fmt & (1 << j)) == 0) { + continue; + } + xpos = (qr_fmtinfopos[i][j].xpos + dim) % dim; + ypos = (qr_fmtinfopos[i][j].ypos + dim) % dim; + qr->symbol[ypos][xpos] |= QR_MM_BLACK; + } + } + xpos = (qr_fmtblackpos.xpos + dim) % dim; + ypos = (qr_fmtblackpos.ypos + dim) % dim; + qr->symbol[ypos][xpos] |= QR_MM_BLACK; + /* + * 型番情報が有効(型番7以上)なら + * 型番情報をシンボルに配置する + */ + v = qr_verinfo[qr->param.version]; + if (v != -1L) { + for (i = 0; i < 2; i++) { + for (j = 0; j < QR_VIN_MAX; j++) { + if ((v & (1L << j)) == 0L) { + continue; + } + xpos = (qr_verinfopos[i][j].xpos + dim) % dim; + ypos = (qr_verinfopos[i][j].ypos + dim) % dim; + qr->symbol[ypos][xpos] |= QR_MM_BLACK; + } + } + } + + return TRUE; +} + +/* + * データコード語の余剰ビットを埋める処理から + * シンボルに形式情報と型番情報を配置する処理までを + * 一括で実行する + */ +QR_API int +qrFinalize(QRCode *qr) +{ + static qr_funcs funcs[] = { + qrFinalizeDataWord, + qrComputeECWord, + qrMakeCodeWord, + qrFillFunctionPattern, + qrFillCodeWord, + qrSelectMaskPattern, + qrFillFormatInfo, + NULL + }; + int i = 0; + int ret = TRUE; + + if (qrIsFinalized(qr)) { + return TRUE; + } + + /* + * 型番自動選択 + */ + if (qr->param.version == -1) { + int maxlen, delta; + int version = 0; + while (++version <= QR_VER_MAX) { + if (version <= VERPOINT1) { + delta = qr->delta1; + } else if (version <= VERPOINT2) { + delta = qr->delta2; + } else { + delta = 0; + } + maxlen = 8 * qr_vertable[version].ecl[qr->param.eclevel].datawords; + if (maxlen >= qr->enclen - delta) { + break; + } + } + if (version > QR_VER_MAX) { + maxlen = 8 * qr_vertable[QR_VER_MAX].ecl[qr->param.eclevel].datawords; + qrSetErrorInfo3(qr, QR_ERR_LARGE_SRC, ", %d total encoded bits" + " (max %d bits on version=%d, ecl=%s)", + qr->enclen, maxlen, QR_VER_MAX, qr_eclname[qr->param.eclevel]); + return FALSE; + } + qr->param.version = version; + } + + /* + * データコード語に入力データを登録する + */ + if (qr->source != NULL) { + qr_byte_t *source; + int mode, size; + + qrInitDataWord(qr); + source = qr->source; + while ((mode = (int)(*source++)) != '\0') { + mode ^= 0x80; + size = ((int)*source++) << 24; + size |= ((int)*source++) << 16; + size |= ((int)*source++) << 8; + size |= (int)*source++; + if (qrEncodeDataWord(qr, source, size, mode) == FALSE) { + return FALSE; + } + source += size; + } + + qrFree(qr->source); + } + + /* + * シンボルを生成する + */ + while (funcs[i] && ret == TRUE) { + ret = funcs[i++](qr); + } + + if (ret == TRUE) { + qrFree(qr->dataword); + qrFree(qr->ecword); + qrFree(qr->codeword); + qr->state = QR_STATE_FINAL; + } + return ret; +} + +/* + * Finalze済か判定する + */ +QR_API int +qrIsFinalized(const QRCode *qr) +{ + if (qr->state == QR_STATE_FINAL) { + return TRUE; + } + return FALSE; +} + +/* + * データをセット済か判定する + */ +QR_API int qrHasData(const QRCode *qr) +{ + if (qr->state == QR_STATE_BEGIN) { + return FALSE; + } + return TRUE; +} + +/* + * 構造的連接の最後のQRコードオブジェクトの + * 仮構造的連接ヘッダを正しい情報で上書きし、Finalizeする + */ +QR_API int +qrsFinalize(QRStructured *st) +{ + int m, n, r; + + if (!qrsHasData(st)) { + qrSetErrorInfo(st->cur, QR_ERR_STATE, _QR_FUNCTION); + return FALSE; + } else if (qrsIsFinalized(st)) { + return TRUE; + } + + m = 0; + n = st->num - 1; + r = TRUE; + while (m <= n && r == TRUE) { + int dwpos, dwbit; + dwpos = st->qrs[m]->dwpos; + dwbit = st->qrs[m]->dwbit; + st->qrs[m]->dwpos = 0; + st->qrs[m]->dwbit = 7; + qrAddDataBits(st->qrs[m], 4, 3); + qrAddDataBits(st->qrs[m], 4, m); + qrAddDataBits(st->qrs[m], 4, n); + qrAddDataBits(st->qrs[m], 8, st->parity); + st->qrs[m]->dwpos = dwpos; + st->qrs[m]->dwbit = dwbit; + r = qrFinalize(st->qrs[m]); + m++; + } + + if (r == TRUE) { + st->state = QR_STATE_FINAL; + } + return r; +} + +/* + * Finalze済か判定する + */ +QR_API int +qrsIsFinalized(const QRStructured *st) +{ + if (st->state == QR_STATE_FINAL) { + return TRUE; + } + return FALSE; +} + +/* + * データをセット済か判定する + */ +QR_API int qrsHasData(const QRStructured *st) +{ + if (st->state == QR_STATE_BEGIN) { + return FALSE; + } + return TRUE; +} + +/* + * 生成されたQRコードシンボルを fmt で指定した形式に変換する + */ +QR_API qr_byte_t * +qrGetSymbol(QRCode *qr, int fmt, int sep, int mag, int *size) +{ + qr_byte_t *buf; + int _size; + + static const QRConverter cnv[QR_FMT_COUNT] = { + qrSymbolToBMP, + qrSymbolToPBM, + qrSymbolToJSON, + qrSymbolToDigit, + qrSymbolToASCII + }; + + if (fmt < 0 || fmt >= QR_FMT_COUNT) { + qrSetErrorInfo(qr, QR_ERR_INVALID_FMT, NULL); + return NULL; + } + + if (cnv[fmt] == NULL) { + qrSetErrorInfo(qr, QR_ERR_UNSUPPORTED_FMT, NULL); + return NULL; + } + + buf = cnv[fmt](qr, sep, mag, &_size); + if (buf == NULL) { + return NULL; + } + + if (size) { + *size = _size; + } + return buf; +} + +/* + * 生成されたQRコードシンボルをストリーム fp に書き込む + */ +QR_API int +qrOutputSymbol(QRCode *qr, FILE *fp, int fmt, int sep, int mag) +{ + qr_byte_t *buf; + int size; + + buf = qrGetSymbol(qr, fmt, sep, mag, &size); + if (buf == NULL) { + return -1; + } + + if (fp == NULL) { + fp = stdout; + } + + if (!fwrite(buf, (size_t)size, 1, fp)) { + qrSetErrorInfo2(qr, QR_ERR_FWRITE, NULL); + free(buf); + return -1; + } + if (ferror(fp)) { + qrSetErrorInfo(qr, QR_ERR_FWRITE, NULL); + free(buf); + return -1; + } + + free(buf); + + return size; +} + +/* + * 生成されたQRコードシンボルをファイル pathname に書き込む + */ +QR_API int +qrOutputSymbol2(QRCode *qr, const char *pathname, int fmt, int sep, int mag) +{ + FILE *fp; + int size; + + if (pathname == NULL || pathname[0] == '\0') { + qrSetErrorInfo(qr, QR_ERR_EMPTY_PARAM, "(empty pathname)"); + return -1; + } + + fp = fopen(pathname, "wb"); + if (fp == NULL) { + qrSetErrorInfo2(qr, QR_ERR_FOPEN, pathname); + return -1; + } + + size = qrOutputSymbol(qr, fp, fmt, sep, mag); + fclose(fp); + + return size; +} + +/* + * 生成されたQRコードシンボルすべてを fmt で指定した形式に変換する + */ +QR_API qr_byte_t * +qrsGetSymbols(QRStructured *st, int fmt, int sep, int mag, int order, int *size) +{ + qr_byte_t *buf; + int _size; + + static QRsConverter cnv[QR_FMT_COUNT] = { + qrsSymbolsToPBM, + qrsSymbolsToJSON, + qrsSymbolsToDigit, + qrsSymbolsToASCII + }; + + if (fmt < 0 || fmt >= QR_FMT_COUNT) { + qrSetErrorInfo(st->cur, QR_ERR_INVALID_FMT, NULL); + return NULL; + } + + buf = cnv[fmt](st, sep, mag, order, &_size); + if (buf == NULL) { + return NULL; + } + + if (size) { + *size = _size; + } + + return buf; +} + +/* + * 生成されたQRコードシンボルすべてをストリーム fp に書き込む + */ +QR_API int +qrsOutputSymbols(QRStructured *st, FILE *fp, int fmt, int sep, int mag, int order) +{ + qr_byte_t *buf; + int size; + + + buf = qrsGetSymbols(st, fmt, sep, mag, order, &size); + if (buf == NULL) { + return -1; + } + + if (fp == NULL) { + fp = stdout; + } + + if (!fwrite(buf, (size_t)size, 1, fp)) { + qrSetErrorInfo2(st->cur, QR_ERR_FWRITE, NULL); + free(buf); + return -1; + } + if (ferror(fp)) { + qrSetErrorInfo(st->cur, QR_ERR_FWRITE, NULL); + free(buf); + return -1; + } + + free(buf); + + return size; +} + +/* + * 生成されたQRコードシンボルすべてをファイル pathname に書き込む + */ +QR_API int +qrsOutputSymbols2(QRStructured *st, const char *pathname, int fmt, int sep, int mag, int order) +{ + FILE *fp; + int size; + + if (pathname == NULL || pathname[0] == '\0') { + qrSetErrorInfo(st->cur, QR_ERR_EMPTY_PARAM, "(empty pathname)"); + return -1; + } + + fp = fopen(pathname, "wb"); + if (fp == NULL) { + qrSetErrorInfo2(st->cur, QR_ERR_FOPEN, pathname); + return -1; + } + + size = qrsOutputSymbols(st, fp, fmt, sep, mag, order); + fclose(fp); + + return size; +} diff --git a/kvm_system/main/lib/libqr/qr.h b/kvm_system/main/lib/libqr/qr.h new file mode 100644 index 0000000..657ad09 --- /dev/null +++ b/kvm_system/main/lib/libqr/qr.h @@ -0,0 +1,341 @@ +/* + * QR Code Generator Library: Basic Header + * + * Core routines were originally written by Junn Ohta. + * Based on qr.c Version 0.1: 2004/4/3 (Public Domain) + * + * @package libqr + * @author Ryusuke SEKIYAMA + * @copyright 2006-2013 Ryusuke SEKIYAMA + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +#ifndef _QR_H_ +#define _QR_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#if defined(WIN32) && !defined(QR_STATIC_BUILD) +#ifdef QR_DLL_BUILD +#define QR_API __declspec(dllexport) +#else +#define QR_API __declspec(dllimport) +#endif +#else +#define QR_API +#endif + +/* + * ライブラリのバージョン + */ +#define LIBQR_VERSION "0.3.1" + +/* + * エラーコード + */ +typedef enum { + /* 汎用エラーコード */ + QR_ERR_NONE = 0, + QR_ERR_USAGE = 0x68, + QR_ERR_NOT_IMPL = 0x69, + QR_ERR_SEE_ERRNO = 0x6e, + QR_ERR_FOPEN = 0x6f, + QR_ERR_FREAD = 0x72, + QR_ERR_STATE = 0x73, + QR_ERR_UNKNOWN = 0x75, + QR_ERR_FWRITE = 0x77, + QR_ERR_MEMORY_EXHAUSTED = 0x78, + + /* パラメータ用エラーコード */ + QR_ERR_INVALID_ARG = 0x01, + QR_ERR_INVALID_VERSION = 0x02, + QR_ERR_INVALID_MODE = 0x03, + QR_ERR_INVALID_ECL = 0x04, + QR_ERR_INVALID_MPT = 0x05, + QR_ERR_INVALID_MAG = 0x06, + QR_ERR_INVALID_SEP = 0x07, + QR_ERR_INVALID_SIZE = 0x08, + QR_ERR_INVALID_FMT = 0x09, + QR_ERR_INVALID_OUT = 0x0a, + QR_ERR_INVALID_MAXNUM = 0x0b, + QR_ERR_UNSUPPORTED_FMT = 0x0c, + QR_ERR_EMPTY_PARAM = 0x0f, + + /* 入力データ用エラーコード */ + QR_ERR_EMPTY_SRC = 0x10, + QR_ERR_LARGE_SRC = 0x11, + QR_ERR_NOT_NUMERIC = 0x12, + QR_ERR_NOT_ALNUM = 0x13, + QR_ERR_NOT_KANJI = 0x14, + + /* 画像処理用エラーコード */ + QR_ERR_IMAGE_TOO_LARGE = 0x30, + QR_ERR_WIDTH_TOO_LARGE = 0x31, + QR_ERR_HEIGHT_TOO_LARGE = 0x32, + QR_ERR_IMAGECREATE = 0x33, + QR_ERR_IMAGEFORMAT = 0x34, + QR_ERR_IMAGEFRAME = 0x35, + + /* zlib用エラーコード */ + QR_ERR_DEFLATE = 0x40 +} qr_err_t; + +/* + * 内部状態 + */ +#define QR_STATE_BEGIN 0 +#define QR_STATE_SET 1 +#define QR_STATE_FINAL 2 + +/* + * 符号化モード + */ +typedef enum { + QR_EM_AUTO = -1, /* 自動選択 */ + QR_EM_NUMERIC = 0, /* 数字 */ + QR_EM_ALNUM = 1, /* 英数字: 0-9 A-Z SP $%*+-./: */ + QR_EM_8BIT = 2, /* 8ビットバイト */ + QR_EM_KANJI = 3 /* 漢字 */ +} qr_em_t; + +/* モード総数 */ +#define QR_EM_COUNT 4 + +/* + * 誤り訂正レベル + */ +typedef enum { + QR_ECL_L = 0, /* レベルL */ + QR_ECL_M = 1, /* レベルM */ + QR_ECL_Q = 2, /* レベルQ */ + QR_ECL_H = 3 /* レベルH */ +} qr_ecl_t; + +/* レベル総数 */ +#define QR_ECL_COUNT 4 + +/* + * 出力形式 + */ +typedef enum { + QR_FMT_PNG = 0, /* PNG */ + QR_FMT_BMP = 1, /* BMP */ + QR_FMT_TIFF = 2, /* TIFF */ + QR_FMT_PBM = 3, /* PBM */ + QR_FMT_SVG = 4, /* SVG */ + QR_FMT_JSON = 5, /* JSON */ + QR_FMT_DIGIT = 6, /* 文字列 */ + QR_FMT_ASCII = 7, /* アスキーアート */ + QR_FMT_UNAVAILABLE = -1 /* 利用不可 */ +} qr_format_t; + +/* 出力形式総数 */ +#define QR_FMT_COUNT 8 + +/* + * モジュール値のマスク + */ +#define QR_MM_DATA 0x01 /* 符号化データの黒モジュール */ +#define QR_MM_BLACK 0x02 /* 印字される黒モジュール */ +#define QR_MM_FUNC 0x04 /* 機能パターン領域(形式/型番情報を含む) */ + +/* + * 機能パターンの定数 + */ +#define QR_DIM_SEP 4 /* 分離パターンの幅 */ +#define QR_DIM_FINDER 7 /* 位置検出パターンの1辺の長さ */ +#define QR_DIM_ALIGN 5 /* 位置合わせパターンの1辺の長さ */ +#define QR_DIM_TIMING 6 /* タイミングパターンのオフセット位置 */ + +/* + * サイズ定数 + */ +#define QR_SRC_MAX 7089 /* 入力データの最大長 */ +#define QR_DIM_MAX 177 /* 1辺のモジュール数の最大値 */ +#define QR_VER_MAX 40 /* 型番の最大値 */ +#define QR_DWD_MAX 2956 /* データコード語の最大長(型番40/レベルL) */ +#define QR_ECW_MAX 2430 /* 誤り訂正コード語の最大長(型番40/レベルH) */ +#define QR_CWD_MAX 3706 /* コード語の最大長(型番40) */ +#define QR_RSD_MAX 123 /* RSブロックデータコード語の最大長 */ +#define QR_RSW_MAX 68 /* RSブロック誤り訂正コード語の最大長 */ +#define QR_RSB_MAX 2 /* RSブロック種別の最大数 */ +#define QR_MPT_MAX 8 /* マスクパターン種別総数 */ +#define QR_APL_MAX 7 /* 位置合わせパターン座標の最大数 */ +#define QR_FIN_MAX 15 /* 形式情報のビット数 */ +#define QR_VIN_MAX 18 /* 型番情報のビット数 */ +#define QR_MAG_MAX 16 /* ピクセル表示倍率の最大値 */ +#define QR_SEP_MAX 16 /* 分離パターン幅の最大値 */ +#define QR_ERR_MAX 1024 /* エラー情報の最大長 */ +#define QR_STA_MAX 16 /* 構造的連接(分割/連結)の最大数 */ +#define QR_STA_LEN 20 /* 構造的連接ヘッダのビット数 */ + +/* + * その他の定数 + */ +#define NAV 0 /* 不使用(not available) */ +#define PADWORD1 0xec /* 埋め草コード語1: 11101100 */ +#define PADWORD2 0x11 /* 埋め草コード語2: 00010001 */ +#define VERPOINT1 9 /* 文字数指示子のビット数が変わる直前の型番1 */ +#define VERPOINT2 26 /* 文字数指示子のビット数が変わる直前の型番2 */ + +/* + * 8bitバイナリデータ型 + */ +typedef unsigned char qr_byte_t; + +/* + * RSブロックごとの情報 + */ +typedef struct qr_rsblock_t { + int rsbnum; /* RSブロック数 */ + int totalwords; /* RSブロック総コード語数 */ + int datawords; /* RSブロックデータコード語数 */ + int ecnum; /* RSブロック誤り訂正数(不使用) */ +} qr_rsblock_t; + +/* + * 誤り訂正レベルごとの情報 + */ +typedef struct qr_eclevel_t { + int datawords; /* データコード語数(全RSブロック) */ + int capacity[QR_EM_COUNT]; /* 符号化モードごとのデータ容量 */ + int nrsb; /* RSブロックの種類(1または2) */ + qr_rsblock_t rsb[QR_RSB_MAX]; /* RSブロックごとの情報 */ +} qr_eclevel_t; + +/* + * 型番ごとの情報 + */ +typedef struct qr_vertable_t { + int version; /* 型番 */ + int dimension; /* 1辺のモジュール数 */ + int totalwords; /* 総コード語数 */ + int remainedbits; /* 剰余ビット数 */ + int nlen[QR_EM_COUNT]; /* 文字数指示子のビット数 */ + qr_eclevel_t ecl[QR_ECL_COUNT]; /* 誤り訂正レベルごとの情報 */ + int aplnum; /* 位置合わせパターン中心座標数 */ + int aploc[QR_APL_MAX]; /* 位置合わせパターン中心座標 */ +} qr_vertable_t; + +/* + * 座標データ型 + */ +typedef struct qr_coord_t { int ypos, xpos; } qr_coord_t; + +/* + * パラメータ構造体 + */ +typedef struct qr_param_t { + int version; /* 型番 */ + int mode; /* 符号化モード */ + int eclevel; /* 誤り訂正レベル */ + int masktype; /* マスクパターン種別 */ +} qr_param_t; + +/* + * QRコードオブジェクト + */ +typedef struct qrcode_t { + qr_byte_t *dataword; /* データコード語領域のアドレス */ + qr_byte_t *ecword; /* 誤り訂正コード語領域のアドレス */ + qr_byte_t *codeword; /* シンボル配置用コード語領域のアドレス */ + qr_byte_t *_symbol; /* シンボルデータ領域のアドレス */ + qr_byte_t **symbol; /* シンボルデータの各行頭のアドレスのポインタ */ + qr_byte_t *source; /* 入力データ領域のアドレス */ + size_t srcmax; /* 入力データ領域の最大容量 */ + size_t srclen; /* 入力データ領域の使用容量 */ + int enclen; /* データコード語の総ビット長 */ + int delta1, delta2; /* 型番自動選択の補助に使われるビット長差分 */ + int dwpos; /* データコード語の追加バイト位置 */ + int dwbit; /* データコード語の追加ビット位置 */ + int xpos, ypos; /* モジュールを配置する座標位置 */ + int xdir, ydir; /* モジュール配置の移動方向 */ + int state; /* 処理の進行状況 */ + int errcode; /* 最後に起こったエラーの番号 */ + char errinfo[QR_ERR_MAX]; /* 最後に起こったエラーの詳細 */ + qr_param_t param; /* 出力パラメータ */ +} QRCode; + +/* + * 構造的連接QRコードオブジェクト + */ +typedef struct qrcode_sa_t { + QRCode *qrs[QR_STA_MAX]; /* QRコードオブジェクトのポインタ配列 */ + QRCode *cur; /* 値を入力する対象のQRコードオブジェクト */ + int num; /* シンボル数 */ + int max; /* 最大シンボル数 */ + int parity; /* パリティ */ + int state; /* 処理の進行状況 */ + qr_param_t param; /* 出力パラメータ */ +} QRStructured; + +/* + * QRコード出力関数型 + */ +typedef qr_byte_t *(*QRConverter)(QRCode *, int, int, int *); +typedef qr_byte_t *(*QRsConverter)(QRStructured *, int, int, int, int *); + +#define qrIsBlacke(qr, i, j) (((qr)->symbol[(i)][(j)] & QR_MM_BLACK) != 0) + +/* + * 基本関数のプロトタイプ + */ +QR_API QRCode *qrInit(int version, int mode, int eclevel, int masktype, int *errcode); +QR_API void qrDestroy(QRCode *qr); +QR_API int qrGetErrorCode(QRCode *qr); +QR_API char *qrGetErrorInfo(QRCode *qr); +QR_API int qrAddData(QRCode *qr, const qr_byte_t *source, int size); +QR_API int qrAddData2(QRCode *qr, const qr_byte_t *source, int size, int mode); +QR_API int qrFinalize(QRCode *qr); +QR_API int qrIsFinalized(const QRCode *qr); +QR_API int qrHasData(const QRCode *qr); +QR_API QRCode *qrClone(const QRCode *qr, int *errcode); + +/* + * 構造的連接操作用関数のプロトタイプ + */ +QR_API QRStructured *qrsInit(int version, int mode, int eclevel, int masktype, int maxnum, int *errcode); +QR_API void qrsDestroy(QRStructured *st); +QR_API int qrsGetErrorCode(QRStructured *st); +QR_API char *qrsGetErrorInfo(QRStructured *st); +QR_API int qrsAddData(QRStructured *st, const qr_byte_t *source, int size); +QR_API int qrsAddData2(QRStructured *st, const qr_byte_t *source, int size, int mode); +QR_API int qrsFinalize(QRStructured *st); +QR_API int qrsIsFinalized(const QRStructured *st); +QR_API int qrsHasData(const QRStructured *st); +QR_API QRStructured *qrsClone(const QRStructured *st, int *errcode); + +/* + * 出力用関数のプロトタイプ + */ +QR_API int qrOutputSymbol(QRCode *qr, FILE *fp, int fmt, int sep, int mag); +QR_API int qrOutputSymbol2(QRCode *qr, const char *pathname, int fmt, int sep, int mag); +QR_API qr_byte_t *qrGetSymbol(QRCode *qr, int fmt, int sep, int mag, int *size); +QR_API qr_byte_t *qrSymbolToDigit(QRCode *qr, int sep, int mag, int *size); +QR_API qr_byte_t *qrSymbolToASCII(QRCode *qr, int sep, int mag, int *size); +QR_API qr_byte_t *qrSymbolToJSON(QRCode *qr, int sep, int mag, int *size); +QR_API qr_byte_t *qrSymbolToPBM(QRCode *qr, int sep, int mag, int *size); +QR_API qr_byte_t *qrSymbolToBMP(QRCode *qr, int sep, int mag, int *size); + +/* + * 構造的連接出力用関数のプロトタイプ + */ +QR_API int qrsOutputSymbols(QRStructured *st, FILE *fp, int fmt, int sep, int mag, int order); +QR_API int qrsOutputSymbols2(QRStructured *st, const char *pathname, int fmt, int sep, int mag, int order); +QR_API qr_byte_t *qrsGetSymbols(QRStructured *st, int fmt, int sep, int mag, int order, int *size); +QR_API qr_byte_t *qrsSymbolsToDigit(QRStructured *st, int sep, int mag, int order, int *size); +QR_API qr_byte_t *qrsSymbolsToASCII(QRStructured *st, int sep, int mag, int order, int *size); +QR_API qr_byte_t *qrsSymbolsToJSON(QRStructured *st, int sep, int mag, int order, int *size); +QR_API qr_byte_t *qrsSymbolsToPBM(QRStructured *st, int sep, int mag, int order, int *size); +QR_API qr_byte_t *qrsSymbolsToBMP(QRStructured *st, int sep, int mag, int order, int *size); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* _QR_H_ */ diff --git a/kvm_system/main/lib/libqr/qr_dwtable.h b/kvm_system/main/lib/libqr/qr_dwtable.h new file mode 100644 index 0000000..3289b23 --- /dev/null +++ b/kvm_system/main/lib/libqr/qr_dwtable.h @@ -0,0 +1,48 @@ +static const short qr_dwtable_kanji[42][189] = { +{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,-1,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,120,121,122,123,124,125,126,127,-1,-1,-1,-1,-1,-1,-1,-1,136,137,138,139,140,141,142,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,-1,-1,-1,-1,-1,-1,-1,176,177,178,179,180,181,182,183,-1,-1,-1,-1,188}, +{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,207,208,209,210,211,212,213,214,215,216,-1,-1,-1,-1,-1,-1,-1,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,-1,-1,-1,-1,-1,-1,-1,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,-1,-1,-1,-1,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, +{384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,-1,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,-1,-1,-1,-1,-1,-1,-1,-1,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,-1,-1,-1,-1,-1,-1,-1,-1,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, +{576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,-1,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, +{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, +{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, +#ifdef QR_DISABLE_CP932_CHARACTER +{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, +#else +{1152,1153,1154,1155,1156,1157,1158,1159,1160,1161,1162,1163,1164,1165,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,1180,1181,-1,1183,1184,1185,1186,1187,1188,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204,1205,-1,-1,-1,-1,-1,-1,-1,-1,1214,-1,1216,1217,1218,1219,1220,1221,1222,1223,1224,1225,1226,1227,1228,1229,1230,1231,1232,1233,1234,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, +#endif +{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532}, +{1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,-1,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,1724}, +{1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,-1,1792,1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916}, +{1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,-1,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108}, +{2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,2174,-1,2176,2177,2178,2179,2180,2181,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300}, +{2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2323,2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,2334,2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,2365,2366,-1,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,2379,2380,2381,2382,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2394,2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,2410,2411,2412,2413,2414,2415,2416,2417,2418,2419,2420,2421,2422,2423,2424,2425,2426,2427,2428,2429,2430,2431,2432,2433,2434,2435,2436,2437,2438,2439,2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,2454,2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,2470,2471,2472,2473,2474,2475,2476,2477,2478,2479,2480,2481,2482,2483,2484,2485,2486,2487,2488,2489,2490,2491,2492}, +{2496,2497,2498,2499,2500,2501,2502,2503,2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,2514,2515,2516,2517,2518,2519,2520,2521,2522,2523,2524,2525,2526,2527,2528,2529,2530,2531,2532,2533,2534,2535,2536,2537,2538,2539,2540,2541,2542,2543,2544,2545,2546,2547,2548,2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,-1,2560,2561,2562,2563,2564,2565,2566,2567,2568,2569,2570,2571,2572,2573,2574,2575,2576,2577,2578,2579,2580,2581,2582,2583,2584,2585,2586,2587,2588,2589,2590,2591,2592,2593,2594,2595,2596,2597,2598,2599,2600,2601,2602,2603,2604,2605,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,2619,2620,2621,2622,2623,2624,2625,2626,2627,2628,2629,2630,2631,2632,2633,2634,2635,2636,2637,2638,2639,2640,2641,2642,2643,2644,2645,2646,2647,2648,2649,2650,2651,2652,2653,2654,2655,2656,2657,2658,2659,2660,2661,2662,2663,2664,2665,2666,2667,2668,2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,2679,2680,2681,2682,2683,2684}, +{2688,2689,2690,2691,2692,2693,2694,2695,2696,2697,2698,2699,2700,2701,2702,2703,2704,2705,2706,2707,2708,2709,2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,2724,2725,2726,2727,2728,2729,2730,2731,2732,2733,2734,2735,2736,2737,2738,2739,2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750,-1,2752,2753,2754,2755,2756,2757,2758,2759,2760,2761,2762,2763,2764,2765,2766,2767,2768,2769,2770,2771,2772,2773,2774,2775,2776,2777,2778,2779,2780,2781,2782,2783,2784,2785,2786,2787,2788,2789,2790,2791,2792,2793,2794,2795,2796,2797,2798,2799,2800,2801,2802,2803,2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,2814,2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,2829,2830,2831,2832,2833,2834,2835,2836,2837,2838,2839,2840,2841,2842,2843,2844,2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,2859,2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,2874,2875,2876}, +{2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,2890,2891,2892,2893,2894,2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915,2916,2917,2918,2919,2920,2921,2922,2923,2924,2925,2926,2927,2928,2929,2930,2931,2932,2933,2934,2935,2936,2937,2938,2939,2940,2941,2942,-1,2944,2945,2946,2947,2948,2949,2950,2951,2952,2953,2954,2955,2956,2957,2958,2959,2960,2961,2962,2963,2964,2965,2966,2967,2968,2969,2970,2971,2972,2973,2974,2975,2976,2977,2978,2979,2980,2981,2982,2983,2984,2985,2986,2987,2988,2989,2990,2991,2992,2993,2994,2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,3005,3006,3007,3008,3009,3010,3011,3012,3013,3014,3015,3016,3017,3018,3019,3020,3021,3022,3023,3024,3025,3026,3027,3028,3029,3030,3031,3032,3033,3034,3035,3036,3037,3038,3039,3040,3041,3042,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,3054,3055,3056,3057,3058,3059,3060,3061,3062,3063,3064,3065,3066,3067,3068}, +{3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,3084,3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3112,3113,3114,3115,3116,3117,3118,3119,3120,3121,3122,3123,3124,3125,3126,3127,3128,3129,3130,3131,3132,3133,3134,-1,3136,3137,3138,3139,3140,3141,3142,3143,3144,3145,3146,3147,3148,3149,3150,3151,3152,3153,3154,3155,3156,3157,3158,3159,3160,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,3174,3175,3176,3177,3178,3179,3180,3181,3182,3183,3184,3185,3186,3187,3188,3189,3190,3191,3192,3193,3194,3195,3196,3197,3198,3199,3200,3201,3202,3203,3204,3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3216,3217,3218,3219,3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,3234,3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245,3246,3247,3248,3249,3250,3251,3252,3253,3254,3255,3256,3257,3258,3259,3260}, +{3264,3265,3266,3267,3268,3269,3270,3271,3272,3273,3274,3275,3276,3277,3278,3279,3280,3281,3282,3283,3284,3285,3286,3287,3288,3289,3290,3291,3292,3293,3294,3295,3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,3310,3311,3312,3313,3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,3324,3325,3326,-1,3328,3329,3330,3331,3332,3333,3334,3335,3336,3337,3338,3339,3340,3341,3342,3343,3344,3345,3346,3347,3348,3349,3350,3351,3352,3353,3354,3355,3356,3357,3358,3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,3369,3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,3385,3386,3387,3388,3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,3399,3400,3401,3402,3403,3404,3405,3406,3407,3408,3409,3410,3411,3412,3413,3414,3415,3416,3417,3418,3419,3420,3421,3422,3423,3424,3425,3426,3427,3428,3429,3430,3431,3432,3433,3434,3435,3436,3437,3438,3439,3440,3441,3442,3443,3444,3445,3446,3447,3448,3449,3450,3451,3452}, +{3456,3457,3458,3459,3460,3461,3462,3463,3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,3474,3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,3485,3486,3487,3488,3489,3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,3504,3505,3506,3507,3508,3509,3510,3511,3512,3513,3514,3515,3516,3517,3518,-1,3520,3521,3522,3523,3524,3525,3526,3527,3528,3529,3530,3531,3532,3533,3534,3535,3536,3537,3538,3539,3540,3541,3542,3543,3544,3545,3546,3547,3548,3549,3550,3551,3552,3553,3554,3555,3556,3557,3558,3559,3560,3561,3562,3563,3564,3565,3566,3567,3568,3569,3570,3571,3572,3573,3574,3575,3576,3577,3578,3579,3580,3581,3582,3583,3584,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,3643,3644}, +{3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3674,3675,3676,3677,3678,3679,3680,3681,3682,3683,3684,3685,3686,3687,3688,3689,3690,3691,3692,3693,3694,3695,3696,3697,3698,3699,3700,3701,3702,3703,3704,3705,3706,3707,3708,3709,3710,-1,3712,3713,3714,3715,3716,3717,3718,3719,3720,3721,3722,3723,3724,3725,3726,3727,3728,3729,3730,3731,3732,3733,3734,3735,3736,3737,3738,3739,3740,3741,3742,3743,3744,3745,3746,3747,3748,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,3759,3760,3761,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,3774,3775,3776,3777,3778,3779,3780,3781,3782,3783,3784,3785,3786,3787,3788,3789,3790,3791,3792,3793,3794,3795,3796,3797,3798,3799,3800,3801,3802,3803,3804,3805,3806,3807,3808,3809,3810,3811,3812,3813,3814,3815,3816,3817,3818,3819,3820,3821,3822,3823,3824,3825,3826,3827,3828,3829,3830,3831,3832,3833,3834,3835,3836}, +{3840,3841,3842,3843,3844,3845,3846,3847,3848,3849,3850,3851,3852,3853,3854,3855,3856,3857,3858,3859,3860,3861,3862,3863,3864,3865,3866,3867,3868,3869,3870,3871,3872,3873,3874,3875,3876,3877,3878,3879,3880,3881,3882,3883,3884,3885,3886,3887,3888,3889,3890,3891,3892,3893,3894,3895,3896,3897,3898,3899,3900,3901,3902,-1,3904,3905,3906,3907,3908,3909,3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,3924,3925,3926,3927,3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939,3940,3941,3942,3943,3944,3945,3946,3947,3948,3949,3950,3951,3952,3953,3954,3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,3970,3971,3972,3973,3974,3975,3976,3977,3978,3979,3980,3981,3982,3983,3984,3985,3986,3987,3988,3989,3990,3991,3992,3993,3994,3995,3996,3997,3998,3999,4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028}, +{4032,4033,4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,4044,4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055,4056,4057,4058,4059,4060,4061,4062,4063,4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,4074,4075,4076,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,4089,4090,4091,4092,4093,4094,-1,4096,4097,4098,4099,4100,4101,4102,4103,4104,4105,4106,4107,4108,4109,4110,4111,4112,4113,4114,4115,4116,4117,4118,4119,4120,4121,4122,4123,4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,4134,4135,4136,4137,4138,4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,4149,4150,4151,4152,4153,4154,4155,4156,4157,4158,4159,4160,4161,4162,4163,4164,4165,4166,4167,4168,4169,4170,4171,4172,4173,4174,4175,4176,4177,4178,4179,4180,4181,4182,4183,4184,4185,4186,4187,4188,4189,4190,4191,4192,4193,4194,4195,4196,4197,4198,4199,4200,4201,4202,4203,4204,4205,4206,4207,4208,4209,4210,4211,4212,4213,4214,4215,4216,4217,4218,4219,4220}, +{4224,4225,4226,4227,4228,4229,4230,4231,4232,4233,4234,4235,4236,4237,4238,4239,4240,4241,4242,4243,4244,4245,4246,4247,4248,4249,4250,4251,4252,4253,4254,4255,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,-1,4288,4289,4290,4291,4292,4293,4294,4295,4296,4297,4298,4299,4300,4301,4302,4303,4304,4305,4306,4307,4308,4309,4310,4311,4312,4313,4314,4315,4316,4317,4318,4319,4320,4321,4322,4323,4324,4325,4326,4327,4328,4329,4330,4331,4332,4333,4334,4335,4336,4337,4338,4339,4340,4341,4342,4343,4344,4345,4346,4347,4348,4349,4350,4351,4352,4353,4354,4355,4356,4357,4358,4359,4360,4361,4362,4363,4364,4365,4366,4367,4368,4369,4370,4371,4372,4373,4374,4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386,4387,4388,4389,4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401,4402,4403,4404,4405,4406,4407,4408,4409,4410,4411,4412}, +{4416,4417,4418,4419,4420,4421,4422,4423,4424,4425,4426,4427,4428,4429,4430,4431,4432,4433,4434,4435,4436,4437,4438,4439,4440,4441,4442,4443,4444,4445,4446,4447,4448,4449,4450,4451,4452,4453,4454,4455,4456,4457,4458,4459,4460,4461,4462,4463,4464,4465,4466,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4511,4512,4513,4514,4515,4516,4517,4518,4519,4520,4521,4522,4523,4524,4525,4526,4527,4528,4529,4530,4531,4532,4533,4534,4535,4536,4537,4538,4539,4540,4541,4542,4543,4544,4545,4546,4547,4548,4549,4550,4551,4552,4553,4554,4555,4556,4557,4558,4559,4560,4561,4562,4563,4564,4565,4566,4567,4568,4569,4570,4571,4572,4573,4574,4575,4576,4577,4578,4579,4580,4581,4582,4583,4584,4585,4586,4587,4588,4589,4590,4591,4592,4593,4594,4595,4596,4597,4598,4599,4600,4601,4602,4603,4604}, +{4608,4609,4610,4611,4612,4613,4614,4615,4616,4617,4618,4619,4620,4621,4622,4623,4624,4625,4626,4627,4628,4629,4630,4631,4632,4633,4634,4635,4636,4637,4638,4639,4640,4641,4642,4643,4644,4645,4646,4647,4648,4649,4650,4651,4652,4653,4654,4655,4656,4657,4658,4659,4660,4661,4662,4663,4664,4665,4666,4667,4668,4669,4670,-1,4672,4673,4674,4675,4676,4677,4678,4679,4680,4681,4682,4683,4684,4685,4686,4687,4688,4689,4690,4691,4692,4693,4694,4695,4696,4697,4698,4699,4700,4701,4702,4703,4704,4705,4706,4707,4708,4709,4710,4711,4712,4713,4714,4715,4716,4717,4718,4719,4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731,4732,4733,4734,4735,4736,4737,4738,4739,4740,4741,4742,4743,4744,4745,4746,4747,4748,4749,4750,4751,4752,4753,4754,4755,4756,4757,4758,4759,4760,4761,4762,4763,4764,4765,4766,4767,4768,4769,4770,4771,4772,4773,4774,4775,4776,4777,4778,4779,4780,4781,4782,4783,4784,4785,4786,4787,4788,4789,4790,4791,4792,4793,4794,4795,4796}, +{4800,4801,4802,4803,4804,4805,4806,4807,4808,4809,4810,4811,4812,4813,4814,4815,4816,4817,4818,4819,4820,4821,4822,4823,4824,4825,4826,4827,4828,4829,4830,4831,4832,4833,4834,4835,4836,4837,4838,4839,4840,4841,4842,4843,4844,4845,4846,4847,4848,4849,4850,4851,4852,4853,4854,4855,4856,4857,4858,4859,4860,4861,4862,-1,4864,4865,4866,4867,4868,4869,4870,4871,4872,4873,4874,4875,4876,4877,4878,4879,4880,4881,4882,4883,4884,4885,4886,4887,4888,4889,4890,4891,4892,4893,4894,4895,4896,4897,4898,4899,4900,4901,4902,4903,4904,4905,4906,4907,4908,4909,4910,4911,4912,4913,4914,4915,4916,4917,4918,4919,4920,4921,4922,4923,4924,4925,4926,4927,4928,4929,4930,4931,4932,4933,4934,4935,4936,4937,4938,4939,4940,4941,4942,4943,4944,4945,4946,4947,4948,4949,4950,4951,4952,4953,4954,4955,4956,4957,4958,4959,4960,4961,4962,4963,4964,4965,4966,4967,4968,4969,4970,4971,4972,4973,4974,4975,4976,4977,4978,4979,4980,4981,4982,4983,4984,4985,4986,4987,4988}, +{4992,4993,4994,4995,4996,4997,4998,4999,5000,5001,5002,5003,5004,5005,5006,5007,5008,5009,5010,5011,5012,5013,5014,5015,5016,5017,5018,5019,5020,5021,5022,5023,5024,5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039,5040,5041,5042,5043,5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,5054,-1,5056,5057,5058,5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,5084,5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102,5103,5104,5105,5106,5107,5108,5109,5110,5111,5112,5113,5114,5115,5116,5117,5118,5119,5120,5121,5122,5123,5124,5125,5126,5127,5128,5129,5130,5131,5132,5133,5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149,5150,5151,5152,5153,5154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164,5165,5166,5167,5168,5169,5170,5171,5172,5173,5174,5175,5176,5177,5178,5179,5180}, +{5184,5185,5186,5187,5188,5189,5190,5191,5192,5193,5194,5195,5196,5197,5198,5199,5200,5201,5202,5203,5204,5205,5206,5207,5208,5209,5210,5211,5212,5213,5214,5215,5216,5217,5218,5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,5234,5235,5236,5237,5238,5239,5240,5241,5242,5243,5244,5245,5246,-1,5248,5249,5250,5251,5252,5253,5254,5255,5256,5257,5258,5259,5260,5261,5262,5263,5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278,5279,5280,5281,5282,5283,5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,5334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347,5348,5349,5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363,5364,5365,5366,5367,5368,5369,5370,5371,5372}, +{5376,5377,5378,5379,5380,5381,5382,5383,5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424,5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,-1,5440,5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456,5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472,5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,5485,5486,5487,5488,5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,5504,5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,5519,5520,5521,5522,5523,5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,5534,5535,5536,5537,5538,5539,5540,5541,5542,5543,5544,5545,5546,5547,5548,5549,5550,5551,5552,5553,5554,5555,5556,5557,5558,5559,5560,5561,5562,5563,5564}, +{5568,5569,5570,5571,5572,5573,5574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584,5585,5586,5587,5588,5589,5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600,5601,5602,5603,5604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616,5617,5618,5619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,-1,5632,5633,5634,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648,5649,5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,5664,5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,5680,5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,5695,5696,5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,5710,5711,5712,5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,5725,5726,5727,5728,5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,5740,5741,5742,5743,5744,5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,5755,5756}, +{5760,5761,5762,5763,5764,5765,5766,5767,5768,5769,5770,5771,5772,5773,5774,5775,5776,5777,5778,5779,5780,5781,5782,5783,5784,5785,5786,5787,5788,5789,5790,5791,5792,5793,5794,5795,5796,5797,5798,5799,5800,5801,5802,5803,5804,5805,5806,5807,5808,5809,5810,5811,5812,5813,5814,5815,5816,5817,5818,5819,5820,5821,5822,-1,5824,5825,5826,5827,5828,5829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,5844,5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856,5857,5858,5859,5860,5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872,5873,5874,5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888,5889,5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904,5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,5920,5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,5936,5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948}, +{5952,5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,5965,5966,5967,5968,5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979,5980,5981,5982,5983,5984,5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,5995,5996,5997,5998,5999,6000,6001,6002,6003,6004,6005,6006,6007,6008,6009,6010,6011,6012,6013,6014,-1,6016,6017,6018,6019,6020,6021,6022,6023,6024,6025,6026,6027,6028,6029,6030,6031,6032,6033,6034,6035,6036,6037,6038,6039,6040,6041,6042,6043,6044,6045,6046,6047,6048,6049,6050,6051,6052,6053,6054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064,6065,6066,6067,6068,6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,6084,6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,6099,6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,6114,6115,6116,6117,6118,6119,6120,6121,6122,6123,6124,6125,6126,6127,6128,6129,6130,6131,6132,6133,6134,6135,6136,6137,6138,6139,6140}, +{6144,6145,6146,6147,6148,6149,6150,6151,6152,6153,6154,6155,6156,6157,6158,6159,6160,6161,6162,6163,6164,6165,6166,6167,6168,6169,6170,6171,6172,6173,6174,6175,6176,6177,6178,6179,6180,6181,6182,6183,6184,6185,6186,6187,6188,6189,6190,6191,6192,6193,6194,6195,6196,6197,6198,6199,6200,6201,6202,6203,6204,6205,6206,-1,6208,6209,6210,6211,6212,6213,6214,6215,6216,6217,6218,6219,6220,6221,6222,6223,6224,6225,6226,6227,6228,6229,6230,6231,6232,6233,6234,6235,6236,6237,6238,6239,6240,6241,6242,6243,6244,6245,6246,6247,6248,6249,6250,6251,6252,6253,6254,6255,6256,6257,6258,6259,6260,6261,6262,6263,6264,6265,6266,6267,6268,6269,6270,6271,6272,6273,6274,6275,6276,6277,6278,6279,6280,6281,6282,6283,6284,6285,6286,6287,6288,6289,6290,6291,6292,6293,6294,6295,6296,6297,6298,6299,6300,6301,6302,6303,6304,6305,6306,6307,6308,6309,6310,6311,6312,6313,6314,6315,6316,6317,6318,6319,6320,6321,6322,6323,6324,6325,6326,6327,6328,6329,6330,6331,6332}, +{6336,6337,6338,6339,6340,6341,6342,6343,6344,6345,6346,6347,6348,6349,6350,6351,6352,6353,6354,6355,6356,6357,6358,6359,6360,6361,6362,6363,6364,6365,6366,6367,6368,6369,6370,6371,6372,6373,6374,6375,6376,6377,6378,6379,6380,6381,6382,6383,6384,6385,6386,6387,6388,6389,6390,6391,6392,6393,6394,6395,6396,6397,6398,-1,6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,6411,6412,6413,6414,6415,6416,6417,6418,6419,6420,6421,6422,6423,6424,6425,6426,6427,6428,6429,6430,6431,6432,6433,6434,6435,6436,6437,6438,6439,6440,6441,6442,6443,6444,6445,6446,6447,6448,6449,6450,6451,6452,6453,6454,6455,6456,6457,6458,6459,6460,6461,6462,6463,6464,6465,6466,6467,6468,6469,6470,6471,6472,6473,6474,6475,6476,6477,6478,6479,6480,6481,6482,6483,6484,6485,6486,6487,6488,6489,6490,6491,6492,6493,6494,6495,6496,6497,6498,6499,6500,6501,6502,6503,6504,6505,6506,6507,6508,6509,6510,6511,6512,6513,6514,6515,6516,6517,6518,6519,6520,6521,6522,6523,6524}, +{6528,6529,6530,6531,6532,6533,6534,6535,6536,6537,6538,6539,6540,6541,6542,6543,6544,6545,6546,6547,6548,6549,6550,6551,6552,6553,6554,6555,6556,6557,6558,6559,6560,6561,6562,6563,6564,6565,6566,6567,6568,6569,6570,6571,6572,6573,6574,6575,6576,6577,6578,6579,6580,6581,6582,6583,6584,6585,6586,6587,6588,6589,6590,-1,6592,6593,6594,6595,6596,6597,6598,6599,6600,6601,6602,6603,6604,6605,6606,6607,6608,6609,6610,6611,6612,6613,6614,6615,6616,6617,6618,6619,6620,6621,6622,6623,6624,6625,6626,6627,6628,6629,6630,6631,6632,6633,6634,6635,6636,6637,6638,6639,6640,6641,6642,6643,6644,6645,6646,6647,6648,6649,6650,6651,6652,6653,6654,6655,6656,6657,6658,6659,6660,6661,6662,6663,6664,6665,6666,6667,6668,6669,6670,6671,6672,6673,6674,6675,6676,6677,6678,6679,6680,6681,6682,6683,6684,6685,6686,6687,6688,6689,6690,6691,6692,6693,6694,6695,6696,6697,6698,6699,6700,6701,6702,6703,6704,6705,6706,6707,6708,6709,6710,6711,6712,6713,6714,6715,6716}, +{6720,6721,6722,6723,6724,6725,6726,6727,6728,6729,6730,6731,6732,6733,6734,6735,6736,6737,6738,6739,6740,6741,6742,6743,6744,6745,6746,6747,6748,6749,6750,6751,6752,6753,6754,6755,6756,6757,6758,6759,6760,6761,6762,6763,6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,6774,6775,6776,6777,6778,6779,6780,6781,6782,-1,6784,6785,6786,6787,6788,6789,6790,6791,6792,6793,6794,6795,6796,6797,6798,6799,6800,6801,6802,6803,6804,6805,6806,6807,6808,6809,6810,6811,6812,6813,6814,6815,6816,6817,6818,6819,6820,6821,6822,6823,6824,6825,6826,6827,6828,6829,6830,6831,6832,6833,6834,6835,6836,6837,6838,6839,6840,6841,6842,6843,6844,6845,6846,6847,6848,6849,6850,6851,6852,6853,6854,6855,6856,6857,6858,6859,6860,6861,6862,6863,6864,6865,6866,6867,6868,6869,6870,6871,6872,6873,6874,6875,6876,6877,6878,6879,6880,6881,6882,6883,6884,6885,6886,6887,6888,6889,6890,6891,6892,6893,6894,6895,6896,6897,6898,6899,6900,6901,6902,6903,6904,6905,6906,6907,6908}, +{6912,6913,6914,6915,6916,6917,6918,6919,6920,6921,6922,6923,6924,6925,6926,6927,6928,6929,6930,6931,6932,6933,6934,6935,6936,6937,6938,6939,6940,6941,6942,6943,6944,6945,6946,6947,6948,6949,6950,6951,6952,6953,6954,6955,6956,6957,6958,6959,6960,6961,6962,6963,6964,6965,6966,6967,6968,6969,6970,6971,6972,6973,6974,-1,6976,6977,6978,6979,6980,6981,6982,6983,6984,6985,6986,6987,6988,6989,6990,6991,6992,6993,6994,6995,6996,6997,6998,6999,7000,7001,7002,7003,7004,7005,7006,7007,7008,7009,7010,7011,7012,7013,7014,7015,7016,7017,7018,7019,7020,7021,7022,7023,7024,7025,7026,7027,7028,7029,7030,7031,7032,7033,7034,7035,7036,7037,7038,7039,7040,7041,7042,7043,7044,7045,7046,7047,7048,7049,7050,7051,7052,7053,7054,7055,7056,7057,7058,7059,7060,7061,7062,7063,7064,7065,7066,7067,7068,7069,7070,7071,7072,7073,7074,7075,7076,7077,7078,7079,7080,7081,7082,7083,7084,7085,7086,7087,7088,7089,7090,7091,7092,7093,7094,7095,7096,7097,7098,7099,7100}, +{7104,7105,7106,7107,7108,7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,7119,7120,7121,7122,7123,7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,7134,7135,7136,7137,7138,7139,7140,7141,7142,7143,7144,7145,7146,7147,7148,7149,7150,7151,7152,7153,7154,7155,7156,7157,7158,7159,7160,7161,7162,7163,7164,7165,7166,-1,7168,7169,7170,7171,7172,7173,7174,7175,7176,7177,7178,7179,7180,7181,7182,7183,7184,7185,7186,7187,7188,7189,7190,7191,7192,7193,7194,7195,7196,7197,7198,7199,7200,7201,7202,7203,7204,7205,7206,7207,7208,7209,7210,7211,7212,7213,7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,7224,7225,7226,7227,7228,7229,7230,7231,7232,7233,7234,7235,7236,7237,7238,7239,7240,7241,7242,7243,7244,7245,7246,7247,7248,7249,7250,7251,7252,7253,7254,7255,7256,7257,7258,7259,7260,7261,7262,7263,7264,7265,7266,7267,7268,7269,7270,7271,7272,7273,7274,7275,7276,7277,7278,7279,7280,7281,7282,7283,7284,7285,7286,7287,7288,7289,7290,7291,7292}, +{7296,7297,7298,7299,7300,7301,7302,7303,7304,7305,7306,7307,7308,7309,7310,7311,7312,7313,7314,7315,7316,7317,7318,7319,7320,7321,7322,7323,7324,7325,7326,7327,7328,7329,7330,7331,7332,7333,7334,7335,7336,7337,7338,7339,7340,7341,7342,7343,7344,7345,7346,7347,7348,7349,7350,7351,7352,7353,7354,7355,7356,7357,7358,-1,7360,7361,7362,7363,7364,7365,7366,7367,7368,7369,7370,7371,7372,7373,7374,7375,7376,7377,7378,7379,7380,7381,7382,7383,7384,7385,7386,7387,7388,7389,7390,7391,7392,7393,7394,7395,7396,7397,7398,7399,7400,7401,7402,7403,7404,7405,7406,7407,7408,7409,7410,7411,7412,7413,7414,7415,7416,7417,7418,7419,7420,7421,7422,7423,7424,7425,7426,7427,7428,7429,7430,7431,7432,7433,7434,7435,7436,7437,7438,7439,7440,7441,7442,7443,7444,7445,7446,7447,7448,7449,7450,7451,7452,7453,7454,7455,7456,7457,7458,7459,7460,7461,7462,7463,7464,7465,7466,7467,7468,7469,7470,7471,7472,7473,7474,7475,7476,7477,7478,7479,7480,7481,7482,7483,7484}, +{7488,7489,7490,7491,7492,7493,7494,7495,7496,7497,7498,7499,7500,7501,7502,7503,7504,7505,7506,7507,7508,7509,7510,7511,7512,7513,7514,7515,7516,7517,7518,7519,7520,7521,7522,7523,7524,7525,7526,7527,7528,7529,7530,7531,7532,7533,7534,7535,7536,7537,7538,7539,7540,7541,7542,7543,7544,7545,7546,7547,7548,7549,7550,-1,7552,7553,7554,7555,7556,7557,7558,7559,7560,7561,7562,7563,7564,7565,7566,7567,7568,7569,7570,7571,7572,7573,7574,7575,7576,7577,7578,7579,7580,7581,7582,7583,7584,7585,7586,7587,7588,7589,7590,7591,7592,7593,7594,7595,7596,7597,7598,7599,7600,7601,7602,7603,7604,7605,7606,7607,7608,7609,7610,7611,7612,7613,7614,7615,7616,7617,7618,7619,7620,7621,7622,7623,7624,7625,7626,7627,7628,7629,7630,7631,7632,7633,7634,7635,7636,7637,7638,7639,7640,7641,7642,7643,7644,7645,7646,7647,7648,7649,7650,7651,7652,7653,7654,7655,7656,7657,7658,7659,7660,7661,7662,7663,7664,7665,7666,7667,7668,7669,7670,7671,7672,7673,7674,7675,7676}, +{7680,7681,7682,7683,7684,7685,7686,7687,7688,7689,7690,7691,7692,7693,7694,7695,7696,7697,7698,7699,7700,7701,7702,7703,7704,7705,7706,7707,7708,7709,7710,7711,7712,7713,7714,7715,7716,7717,7718,7719,7720,7721,7722,7723,7724,7725,7726,7727,7728,7729,7730,7731,7732,7733,7734,7735,7736,7737,7738,7739,7740,7741,7742,-1,7744,7745,7746,7747,7748,7749,7750,7751,7752,7753,7754,7755,7756,7757,7758,7759,7760,7761,7762,7763,7764,7765,7766,7767,7768,7769,7770,7771,7772,7773,7774,7775,7776,7777,7778,7779,7780,7781,7782,7783,7784,7785,7786,7787,7788,7789,7790,7791,7792,7793,7794,7795,7796,7797,7798,7799,7800,7801,7802,7803,7804,7805,7806,7807,7808,7809,7810,7811,7812,7813,7814,7815,7816,7817,7818,7819,7820,7821,7822,7823,7824,7825,7826,7827,7828,7829,7830,7831,7832,7833,7834,7835,7836,7837,7838,7839,7840,7841,7842,7843,7844,7845,7846,7847,7848,7849,7850,7851,7852,7853,7854,7855,7856,7857,7858,7859,7860,7861,7862,7863,7864,7865,7866,7867,7868}, +{7872,7873,7874,7875,7876,7877,7878,7879,7880,7881,7882,7883,7884,7885,7886,7887,7888,7889,7890,7891,7892,7893,7894,7895,7896,7897,7898,7899,7900,7901,7902,7903,7904,7905,7906,7907,7908,7909,7910,7911,7912,7913,7914,7915,7916,7917,7918,7919,7920,7921,7922,7923,7924,7925,7926,7927,7928,7929,7930,7931,7932,7933,7934,-1,7936,7937,7938,7939,7940,7941,7942,7943,7944,7945,7946,7947,7948,7949,7950,7951,7952,7953,7954,7955,7956,7957,7958,7959,7960,7961,7962,7963,7964,7965,7966,7967,7968,7969,7970,7971,7972,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1} +}; diff --git a/kvm_system/main/lib/libqr/qr_private.h b/kvm_system/main/lib/libqr/qr_private.h new file mode 100644 index 0000000..ce38775 --- /dev/null +++ b/kvm_system/main/lib/libqr/qr_private.h @@ -0,0 +1,512 @@ +/* + * QR Code Generator Library: Private Definitions + * + * Core routines were originally written by Junn Ohta. + * Based on qr.c Version 0.1: 2004/4/3 (Public Domain) + * + * @package libqr + * @author Ryusuke SEKIYAMA + * @copyright 2006-2013 Ryusuke SEKIYAMA + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +#ifndef _QR_PRIVATE_H_ +#define _QR_PRIVATE_H_ + +#include "qr.h" +#include +#include + +/* + * Booblean + */ +#ifdef TRUE +#undef TRUE +#endif +#ifdef FALSE +#undef FALSE +#endif +#define TRUE 1 +#define FALSE 0 + +/* + * 型番データ表 + */ +const qr_vertable_t qr_vertable[QR_VER_MAX+1] = { + { NAV, NAV, NAV, NAV, { 0, 0, 0, 0 }, + {{ NAV, { 0, 0, 0, 0 }, NAV, {{ 0, 0, 0, 0 }}}, + { NAV, { 0, 0, 0, 0 }, NAV, {{ 0, 0, 0, 0 }}}, + { NAV, { 0, 0, 0, 0 }, NAV, {{ 0, 0, 0, 0 }}}, + { NAV, { 0, 0, 0, 0 }, NAV, {{ 0, 0, 0, 0 }}}}, + NAV, { NAV, NAV }}, + { 1, 21, 26, 0, { 10, 9, 8, 8 }, + {{ 19, { 41, 25, 17, 10 }, 1, {{ 1, 26, 19, 2 }}}, + { 16, { 34, 20, 14, 8 }, 1, {{ 1, 26, 16, 4 }}}, + { 13, { 27, 16, 11, 7 }, 1, {{ 1, 26, 13, 6 }}}, + { 9, { 17, 10, 7, 4 }, 1, {{ 1, 26, 9, 8 }}}}, + 0, { NAV, NAV }}, + { 2, 25, 44, 7, { 10, 9, 8, 8 }, + {{ 34, { 77, 47, 32, 20 }, 1, {{ 1, 44, 34, 4 }}}, + { 28, { 63, 38, 26, 16 }, 1, {{ 1, 44, 28, 8 }}}, + { 22, { 48, 29, 20, 12 }, 1, {{ 1, 44, 22, 11 }}}, + { 16, { 34, 20, 14, 8 }, 1, {{ 1, 44, 16, 14 }}}}, + 2, { 6, 18 }}, + { 3, 29, 70, 7, { 10, 9, 8, 8 }, + {{ 55, { 127, 77, 53, 32 }, 1, {{ 1, 70, 55, 7 }}}, + { 44, { 101, 61, 42, 26 }, 1, {{ 1, 70, 44, 13 }}}, + { 34, { 77, 47, 32, 20 }, 1, {{ 2, 35, 17, 9 }}}, + { 26, { 58, 35, 24, 15 }, 1, {{ 2, 35, 13, 11 }}}}, + 2, { 6, 22 }}, + { 4, 33, 100, 7, { 10, 9, 8, 8 }, + {{ 80, { 187, 114, 78, 48 }, 1, {{ 1, 100, 80, 10 }}}, + { 64, { 149, 90, 62, 38 }, 1, {{ 2, 50, 32, 9 }}}, + { 48, { 111, 67, 46, 28 }, 1, {{ 2, 50, 24, 13 }}}, + { 36, { 82, 50, 34, 21 }, 1, {{ 4, 25, 9, 8 }}}}, + 2, { 6, 26 }}, + { 5, 37, 134, 7, { 10, 9, 8, 8 }, + {{ 108, { 255, 154, 106, 65 }, 1, {{ 1, 134, 108, 13 }}}, + { 86, { 202, 122, 84, 52 }, 1, {{ 2, 67, 43, 12 }}}, + { 62, { 144, 87, 60, 37 }, 2, {{ 2, 33, 15, 9 }, { 2, 34, 16, 9 }}}, + { 46, { 106, 64, 44, 27 }, 2, {{ 2, 33, 11, 11 }, { 2, 34, 12, 11 }}}}, + 2, { 6, 30 }}, + { 6, 41, 172, 7, { 10, 9, 8, 8 }, + {{ 136, { 322, 195, 134, 82 }, 1, {{ 2, 86, 68, 9 }}}, + { 108, { 255, 154, 106, 65 }, 1, {{ 4, 43, 27, 8 }}}, + { 76, { 178, 108, 74, 45 }, 1, {{ 4, 43, 19, 12 }}}, + { 60, { 139, 84, 58, 36 }, 1, {{ 4, 43, 15, 14 }}}}, + 2, { 6, 34 }}, + { 7, 45, 196, 0, { 10, 9, 8, 8 }, + {{ 156, { 370, 224, 154, 95 }, 1, {{ 2, 98, 78, 10 }}}, + { 124, { 293, 178, 122, 75 }, 1, {{ 4, 49, 31, 9 }}}, + { 88, { 207, 125, 86, 53 }, 2, {{ 2, 32, 14, 9 }, { 4, 33, 15, 9 }}}, + { 66, { 154, 93, 64, 39 }, 2, {{ 4, 39, 13, 13 }, { 1, 40, 14, 13 }}}}, + 3, { 6, 22, 38 }}, + { 8, 49, 242, 0, { 10, 9, 8, 8 }, + {{ 194, { 461, 279, 192, 118 }, 1, {{ 2, 121, 97, 12 }}}, + { 154, { 365, 221, 152, 93 }, 2, {{ 2, 60, 38, 11 }, { 2, 61, 39, 11 }}}, + { 110, { 259, 157, 108, 66 }, 2, {{ 4, 40, 18, 11 }, { 2, 41, 19, 11 }}}, + { 86, { 202, 122, 84, 52 }, 2, {{ 4, 40, 14, 13 }, { 2, 41, 15, 13 }}}}, + 3, { 6, 24, 42 }}, + { 9, 53, 292, 0, { 10, 9, 8, 8 }, + {{ 232, { 552, 335, 230, 141 }, 1, {{ 2, 146, 116, 15 }}}, + { 182, { 432, 262, 180, 111 }, 2, {{ 3, 58, 36, 11 }, { 2, 59, 37, 11 }}}, + { 132, { 312, 189, 130, 80 }, 2, {{ 4, 36, 16, 10 }, { 4, 37, 17, 10 }}}, + { 100, { 235, 143, 98, 60 }, 2, {{ 4, 36, 12, 12 }, { 4, 37, 13, 12 }}}}, + 3, { 6, 26, 46 }}, + { 10, 57, 346, 0, { 12, 11, 16, 10 }, + {{ 274, { 652, 395, 271, 167 }, 2, {{ 2, 86, 68, 9 }, { 2, 87, 69, 9 }}}, + { 216, { 513, 311, 213, 131 }, 2, {{ 4, 69, 43, 13 }, { 1, 70, 44, 13 }}}, + { 154, { 364, 221, 151, 93 }, 2, {{ 6, 43, 19, 12 }, { 2, 44, 20, 12 }}}, + { 122, { 288, 174, 119, 74 }, 2, {{ 6, 43, 15, 14 }, { 2, 44, 16, 14 }}}}, + 3, { 6, 28, 50 }}, + { 11, 61, 404, 0, { 12, 11, 16, 10 }, + {{ 324, { 772, 468, 321, 198 }, 1, {{ 4, 101, 81, 10 }}}, + { 254, { 604, 366, 251, 155 }, 2, {{ 1, 80, 50, 15 }, { 4, 81, 51, 15 }}}, + { 180, { 427, 259, 177, 109 }, 2, {{ 4, 50, 22, 14 }, { 4, 51, 23, 14 }}}, + { 140, { 331, 200, 137, 85 }, 2, {{ 3, 36, 12, 12 }, { 8, 37, 13, 12 }}}}, + 3, { 6, 30, 54 }}, + { 12, 65, 466, 0, { 12, 11, 16, 10 }, + {{ 370, { 883, 535, 367, 226 }, 2, {{ 2, 116, 92, 12 }, { 2, 117, 93, 12 }}}, + { 290, { 691, 419, 287, 177 }, 2, {{ 6, 58, 36, 11 }, { 2, 59, 37, 11 }}}, + { 206, { 489, 296, 203, 125 }, 2, {{ 4, 46, 20, 13 }, { 6, 47, 21, 13 }}}, + { 158, { 374, 227, 155, 96 }, 2, {{ 7, 42, 14, 14 }, { 4, 43, 15, 14 }}}}, + 3, { 6, 32, 58 }}, + { 13, 69, 532, 0, { 12, 11, 16, 10 }, + {{ 428, { 1022, 619, 425, 262 }, 1, {{ 4, 133, 107, 13 }}}, + { 334, { 796, 483, 331, 204 }, 2, {{ 8, 59, 37, 11 }, { 1, 60, 38, 11 }}}, + { 244, { 580, 352, 241, 149 }, 2, {{ 8, 44, 20, 12 }, { 4, 45, 21, 12 }}}, + { 180, { 427, 259, 177, 109 }, 2, {{ 12, 33, 11, 11 }, { 4, 34, 12, 11 }}}}, + 3, { 6, 34, 62 }}, + { 14, 73, 581, 3, { 12, 11, 16, 10 }, + {{ 461, { 1101, 667, 458, 282 }, 2, {{ 3, 145, 115, 15 }, { 1, 146, 116, 15 }}}, + { 365, { 871, 528, 362, 223 }, 2, {{ 4, 64, 40, 12 }, { 5, 65, 41, 12 }}}, + { 261, { 621, 376, 258, 159 }, 2, {{ 11, 36, 16, 10 }, { 5, 37, 17, 10 }}}, + { 197, { 468, 283, 194, 120 }, 2, {{ 11, 36, 12, 12 }, { 5, 37, 13, 12 }}}}, + 4, { 6, 26, 46, 66 }}, + { 15, 77, 655, 3, { 12, 11, 16, 10 }, + {{ 523, { 1250, 758, 520, 320 }, 2, {{ 5, 109, 87, 11 }, { 1, 110, 88, 11 }}}, + { 415, { 991, 600, 412, 254 }, 2, {{ 5, 65, 41, 12 }, { 5, 66, 42, 12 }}}, + { 295, { 703, 426, 292, 180 }, 2, {{ 5, 54, 24, 15 }, { 7, 55, 25, 15 }}}, + { 223, { 530, 321, 220, 136 }, 2, {{ 11, 36, 12, 12 }, { 7, 37, 13, 12 }}}}, + 4, { 6, 26, 48, 70 }}, + { 16, 81, 733, 3, { 12, 11, 16, 10 }, + {{ 589, { 1408, 854, 586, 361 }, 2, {{ 5, 122, 98, 12 }, { 1, 123, 99, 12 }}}, + { 453, { 1082, 656, 450, 277 }, 2, {{ 7, 73, 45, 14 }, { 3, 74, 46, 14 }}}, + { 325, { 775, 470, 322, 198 }, 2, {{ 15, 43, 19, 12 }, { 2, 44, 20, 12 }}}, + { 253, { 602, 365, 250, 154 }, 2, {{ 3, 45, 15, 15 }, { 13, 46, 16, 15 }}}}, + 4, { 6, 26, 50, 74 }}, + { 17, 85, 815, 3, { 12, 11, 16, 10 }, + {{ 647, { 1548, 938, 644, 397 }, 2, {{ 1, 135, 107, 14 }, { 5, 136, 108, 14 }}}, + { 507, { 1212, 734, 504, 310 }, 2, {{ 10, 74, 46, 14 }, { 1, 75, 47, 14 }}}, + { 367, { 876, 531, 364, 224 }, 2, {{ 1, 50, 22, 14 }, { 15, 51, 23, 14 }}}, + { 283, { 674, 408, 280, 173 }, 2, {{ 2, 42, 14, 14 }, { 17, 43, 15, 14 }}}}, + 4, { 6, 30, 54, 78 }}, + { 18, 89, 901, 3, { 12, 11, 16, 10 }, + {{ 721, { 1725, 1046, 718, 442 }, 2, {{ 5, 150, 120, 15 }, { 1, 151, 121, 15 }}}, + { 563, { 1346, 816, 560, 345 }, 2, {{ 9, 69, 43, 13 }, { 4, 70, 44, 13 }}}, + { 397, { 948, 574, 394, 243 }, 2, {{ 17, 50, 22, 14 }, { 1, 51, 23, 14 }}}, + { 313, { 746, 452, 310, 191 }, 2, {{ 2, 42, 14, 14 }, { 19, 43, 15, 14 }}}}, + 4, { 6, 30, 56, 82 }}, + { 19, 93, 991, 3, { 12, 11, 16, 10 }, + {{ 795, { 1903, 1153, 792, 488 }, 2, {{ 3, 141, 113, 14 }, { 4, 142, 114, 14 }}}, + { 627, { 1500, 909, 624, 384 }, 2, {{ 3, 70, 44, 13 }, { 11, 71, 45, 13 }}}, + { 445, { 1063, 644, 442, 272 }, 2, {{ 17, 47, 21, 13 }, { 4, 48, 22, 13 }}}, + { 341, { 813, 493, 338, 208 }, 2, {{ 9, 39, 13, 13 }, { 16, 40, 14, 13 }}}}, + 4, { 6, 30, 58, 86 }}, + { 20, 97, 1085, 3, { 12, 11, 16, 10 }, + {{ 861, { 2061, 1249, 858, 528 }, 2, {{ 3, 135, 107, 14 }, { 5, 136, 108, 14 }}}, + { 669, { 1600, 970, 666, 410 }, 2, {{ 3, 67, 41, 13 }, { 13, 68, 42, 13 }}}, + { 485, { 1159, 702, 482, 297 }, 2, {{ 15, 54, 24, 15 }, { 5, 55, 25, 15 }}}, + { 385, { 919, 557, 382, 235 }, 2, {{ 15, 43, 15, 14 }, { 10, 44, 16, 14 }}}}, + 4, { 6, 34, 62, 90 }}, + { 21, 101, 1156, 4, { 12, 11, 16, 10 }, + {{ 932, { 2232, 1352, 929, 572 }, 2, {{ 4, 144, 116, 14 }, { 4, 145, 117, 14 }}}, + { 714, { 1708, 1035, 711, 438 }, 1, {{ 17, 68, 42, 13 }}}, + { 512, { 1224, 742, 509, 314 }, 2, {{ 17, 50, 22, 14 }, { 6, 51, 23, 14 }}}, + { 406, { 969, 587, 403, 248 }, 2, {{ 19, 46, 16, 15 }, { 6, 47, 17, 15 }}}}, + 5, { 6, 28, 50, 72, 94 }}, + { 22, 105, 1258, 4, { 12, 11, 16, 10 }, + {{ 1006, { 2409, 1460, 1003, 618 }, 2, {{ 2, 139, 111, 14 }, { 7, 140, 112, 14 }}}, + { 782, { 1872, 1134, 779, 480 }, 1, {{ 17, 74, 46, 14 }}}, + { 568, { 1358, 823, 565, 348 }, 2, {{ 7, 54, 24, 15 }, { 16, 55, 25, 15 }}}, + { 442, { 1056, 640, 439, 270 }, 1, {{ 34, 37, 13, 13 }}}}, + 5, { 6, 26, 50, 74, 98 }}, + { 23, 109, 1364, 4, { 12, 11, 16, 10 }, + {{ 1094, { 2620, 1588, 1091, 672 }, 2, {{ 4, 151, 121, 15 }, { 5, 152, 122, 15 }}}, + { 860, { 2059, 1248, 857, 528 }, 2, {{ 4, 75, 47, 14 }, { 14, 76, 48, 14 }}}, + { 614, { 1468, 890, 611, 376 }, 2, {{ 11, 54, 24, 15 }, { 14, 55, 25, 15 }}}, + { 464, { 1108, 672, 461, 284 }, 2, {{ 16, 45, 15, 15 }, { 14, 46, 16, 15 }}}}, + 5, { 6, 30, 54, 78, 102 }}, + { 24, 113, 1474, 4, { 12, 11, 16, 10 }, + {{ 1174, { 2812, 1704, 1171, 721 }, 2, {{ 6, 147, 117, 15 }, { 4, 148, 118, 15 }}}, + { 914, { 2188, 1326, 911, 561 }, 2, {{ 6, 73, 45, 14 }, { 14, 74, 46, 14 }}}, + { 664, { 1588, 963, 661, 407 }, 2, {{ 11, 54, 24, 15 }, { 16, 55, 25, 15 }}}, + { 514, { 1228, 744, 511, 315 }, 2, {{ 30, 46, 16, 15 }, { 2, 47, 17, 15 }}}}, + 5, { 6, 28, 54, 80, 106 }}, + { 25, 117, 1588, 4, { 12, 11, 16, 10 }, + {{ 1276, { 3057, 1853, 1273, 784 }, 2, {{ 8, 132, 106, 13 }, { 4, 133, 107, 13 }}}, + { 1000, { 2395, 1451, 997, 614 }, 2, {{ 8, 75, 47, 14 }, { 13, 76, 48, 14 }}}, + { 718, { 1718, 1041, 715, 440 }, 2, {{ 7, 54, 24, 15 }, { 22, 55, 25, 15 }}}, + { 538, { 1286, 779, 535, 330 }, 2, {{ 22, 45, 15, 15 }, { 13, 46, 16, 15 }}}}, + 5, { 6, 32, 58, 84, 110 }}, + { 26, 121, 1706, 4, { 12, 11, 16, 10 }, + {{ 1370, { 3283, 1990, 1367, 842 }, 2, {{ 10, 142, 114, 14 }, { 2, 143, 115, 14 }}}, + { 1062, { 2544, 1542, 1059, 652 }, 2, {{ 19, 74, 46, 14 }, { 4, 75, 47, 14 }}}, + { 754, { 1804, 1094, 751, 462 }, 2, {{ 28, 50, 22, 14 }, { 6, 51, 23, 14 }}}, + { 596, { 1425, 864, 593, 365 }, 2, {{ 33, 46, 16, 15 }, { 4, 47, 17, 15 }}}}, + 5, { 6, 30, 58, 86, 114 }}, + { 27, 125, 1828, 4, { 14, 13, 16, 12 }, + {{ 1468, { 3517, 2132, 1465, 902 }, 2, {{ 8, 152, 122, 15 }, { 4, 153, 123, 15 }}}, + { 1128, { 2701, 1637, 1125, 692 }, 2, {{ 22, 73, 45, 14 }, { 3, 74, 46, 14 }}}, + { 808, { 1933, 1172, 805, 496 }, 2, {{ 8, 53, 23, 15 }, { 26, 54, 24, 15 }}}, + { 628, { 1501, 910, 625, 385 }, 2, {{ 12, 45, 15, 15 }, { 28, 46, 16, 15 }}}}, + 5, { 6, 34, 62, 90, 118 }}, + { 28, 129, 1921, 3, { 14, 13, 16, 12 }, + {{ 1531, { 3669, 2223, 1528, 940 }, 2, {{ 3, 147, 117, 15 }, { 10, 148, 118, 15 }}}, + { 1193, { 2857, 1732, 1190, 732 }, 2, {{ 3, 73, 45, 14 }, { 23, 74, 46, 14 }}}, + { 871, { 2085, 1263, 868, 534 }, 2, {{ 4, 54, 24, 15 }, { 31, 55, 25, 15 }}}, + { 661, { 1581, 958, 658, 405 }, 2, {{ 11, 45, 15, 15 }, { 31, 46, 16, 15 }}}}, + 6, { 6, 26, 50, 74, 98, 122 }}, + { 29, 133, 2051, 3, { 14, 13, 16, 12 }, + {{ 1631, { 3909, 2369, 1628, 1002 }, 2, {{ 7, 146, 116, 15 }, { 7, 147, 117, 15 }}}, + { 1267, { 3035, 1839, 1264, 778 }, 2, {{ 21, 73, 45, 14 }, { 7, 74, 46, 14 }}}, + { 911, { 2181, 1322, 908, 559 }, 2, {{ 1, 53, 23, 15 }, { 37, 54, 24, 15 }}}, + { 701, { 1677, 1016, 698, 430 }, 2, {{ 19, 45, 15, 15 }, { 26, 46, 16, 15 }}}}, + 6, { 6, 30, 54, 78, 102, 126 }}, + { 30, 137, 2185, 3, { 14, 13, 16, 12 }, + {{ 1735, { 4158, 2520, 1732, 1066 }, 2, {{ 5, 145, 115, 15 }, { 10, 146, 116, 15 }}}, + { 1373, { 3289, 1994, 1370, 843 }, 2, {{ 19, 75, 47, 14 }, { 10, 76, 48, 14 }}}, + { 985, { 2358, 1429, 982, 604 }, 2, {{ 15, 54, 24, 15 }, { 25, 55, 25, 15 }}}, + { 745, { 1782, 1080, 742, 457 }, 2, {{ 23, 45, 15, 15 }, { 25, 46, 16, 15 }}}}, + 6, { 6, 26, 52, 78, 104, 130 }}, + { 31, 141, 2323, 3, { 14, 13, 16, 12 }, + {{ 1843, { 4417, 2677, 1840, 1132 }, 2, {{ 13, 145, 115, 15 }, { 3, 146, 116, 15 }}}, + { 1455, { 3486, 2113, 1452, 894 }, 2, {{ 2, 74, 46, 14 }, { 29, 75, 47, 14 }}}, + { 1033, { 2473, 1499, 1030, 634 }, 2, {{ 42, 54, 24, 15 }, { 1, 55, 25, 15 }}}, + { 793, { 1897, 1150, 790, 486 }, 2, {{ 23, 45, 15, 15 }, { 28, 46, 16, 15 }}}}, + 6, { 6, 30, 56, 82, 108, 134 }}, + { 32, 145, 2465, 3, { 14, 13, 16, 12 }, + {{ 1955, { 4686, 2840, 1952, 1201 }, 1, {{ 17, 145, 115, 15 }}}, + { 1541, { 3693, 2238, 1538, 947 }, 2, {{ 10, 74, 46, 14 }, { 23, 75, 47, 14 }}}, + { 1115, { 2670, 1618, 1112, 684 }, 2, {{ 10, 54, 24, 15 }, { 35, 55, 25, 15 }}}, + { 845, { 2022, 1226, 842, 518 }, 2, {{ 19, 45, 15, 15 }, { 35, 46, 16, 15 }}}}, + 6, { 6, 34, 60, 86, 112, 138 }}, + { 33, 149, 2611, 3, { 14, 13, 16, 12 }, + {{ 2071, { 4965, 3009, 2068, 1273 }, 2, {{ 17, 145, 115, 15 }, { 1, 146, 116, 15 }}}, + { 1631, { 3909, 2369, 1628, 1002 }, 2, {{ 14, 74, 46, 14 }, { 21, 75, 47, 14 }}}, + { 1171, { 2805, 1700, 1168, 719 }, 2, {{ 29, 54, 24, 15 }, { 19, 55, 25, 15 }}}, + { 901, { 2157, 1307, 898, 553 }, 2, {{ 11, 45, 15, 15 }, { 46, 46, 16, 15 }}}}, + 6, { 6, 30, 58, 86, 114, 142 }}, + { 34, 153, 2761, 3, { 14, 13, 16, 12 }, + {{ 2191, { 5253, 3183, 2188, 1347 }, 2, {{ 13, 145, 115, 15 }, { 6, 146, 116, 15 }}}, + { 1725, { 4134, 2506, 1722, 1060 }, 2, {{ 14, 74, 46, 14 }, { 23, 75, 47, 14 }}}, + { 1231, { 2949, 1787, 1228, 756 }, 2, {{ 44, 54, 24, 15 }, { 7, 55, 25, 15 }}}, + { 961, { 2301, 1394, 958, 590 }, 2, {{ 59, 46, 16, 15 }, { 1, 47, 17, 15 }}}}, + 6, { 6, 34, 62, 90, 118, 146 }}, + { 35, 157, 2876, 0, { 14, 13, 16, 12 }, + {{ 2306, { 5529, 3351, 2303, 1417 }, 2, {{ 12, 151, 121, 15 }, { 7, 152, 122, 15 }}}, + { 1812, { 4343, 2632, 1809, 1113 }, 2, {{ 12, 75, 47, 14 }, { 26, 76, 48, 14 }}}, + { 1286, { 3081, 1867, 1283, 790 }, 2, {{ 39, 54, 24, 15 }, { 14, 55, 25, 15 }}}, + { 986, { 2361, 1431, 983, 605 }, 2, {{ 22, 45, 15, 15 }, { 41, 46, 16, 15 }}}}, + 7, { 6, 30, 54, 78, 102, 126, 150 }}, + { 36, 161, 3034, 0, { 14, 13, 16, 12 }, + {{ 2434, { 5836, 3537, 2431, 1496 }, 2, {{ 6, 151, 121, 15 }, { 14, 152, 122, 15 }}}, + { 1914, { 4588, 2780, 1911, 1176 }, 2, {{ 6, 75, 47, 14 }, { 34, 76, 48, 14 }}}, + { 1354, { 3244, 1966, 1351, 832 }, 2, {{ 46, 54, 24, 15 }, { 10, 55, 25, 15 }}}, + { 1054, { 2524, 1530, 1051, 647 }, 2, {{ 2, 45, 15, 15 }, { 64, 46, 16, 15 }}}}, + 7, { 6, 24, 50, 76, 102, 128, 154 }}, + { 37, 165, 3196, 0, { 14, 13, 16, 12 }, + {{ 2566, { 6153, 3729, 2563, 1577 }, 2, {{ 17, 152, 122, 15 }, { 4, 153, 123, 15 }}}, + { 1992, { 4775, 2894, 1989, 1224 }, 2, {{ 29, 74, 46, 14 }, { 14, 75, 47, 14 }}}, + { 1426, { 3417, 2071, 1423, 876 }, 2, {{ 49, 54, 24, 15 }, { 10, 55, 25, 15 }}}, + { 1096, { 2625, 1591, 1093, 673 }, 2, {{ 24, 45, 15, 15 }, { 46, 46, 16, 15 }}}}, + 7, { 6, 28, 54, 80, 106, 132, 158 }}, + { 38, 169, 3362, 0, { 14, 13, 16, 12 }, + {{ 2702, { 6479, 3927, 2699, 1661 }, 2, {{ 4, 152, 122, 15 }, { 18, 153, 123, 15 }}}, + { 2102, { 5039, 3054, 2099, 1292 }, 2, {{ 13, 74, 46, 14 }, { 32, 75, 47, 14 }}}, + { 1502, { 3599, 2181, 1499, 923 }, 2, {{ 48, 54, 24, 15 }, { 14, 55, 25, 15 }}}, + { 1142, { 2735, 1658, 1139, 701 }, 2, {{ 42, 45, 15, 15 }, { 32, 46, 16, 15 }}}}, + 7, { 6, 32, 58, 84, 110, 136, 162 }}, + { 39, 173, 3532, 0, { 14, 13, 16, 12 }, + {{ 2812, { 6743, 4087, 2809, 1729 }, 2, {{ 20, 147, 117, 15 }, { 4, 148, 118, 15 }}}, + { 2216, { 5313, 3220, 2213, 1362 }, 2, {{ 40, 75, 47, 14 }, { 7, 76, 48, 14 }}}, + { 1582, { 3791, 2298, 1579, 972 }, 2, {{ 43, 54, 24, 15 }, { 22, 55, 25, 15 }}}, + { 1222, { 2927, 1774, 1219, 750 }, 2, {{ 10, 45, 15, 15 }, { 67, 46, 16, 15 }}}}, + 7, { 6, 26, 54, 82, 110, 138, 166 }}, + { 40, 177, 3706, 0, { 14, 13, 16, 12 }, + {{ 2956, { 7089, 4296, 2953, 1817 }, 2, {{ 19, 148, 118, 15 }, { 6, 149, 119, 15 }}}, + { 2334, { 5596, 3391, 2331, 1435 }, 2, {{ 18, 75, 47, 14 }, { 31, 76, 48, 14 }}}, + { 1666, { 3993, 2420, 1663, 1024 }, 2, {{ 34, 54, 24, 15 }, { 34, 55, 25, 15 }}}, + { 1276, { 3057, 1852, 1273, 784 }, 2, {{ 20, 45, 15, 15 }, { 61, 46, 16, 15 }}}}, + 7, { 6, 30, 58, 86, 114, 142, 170 }} +}; + +/* + * αのべき表現→多項式係数の整数表現 + */ +static const unsigned char qr_exp2fac[256] = { + 1, 2, 4, 8, 16, 32, 64,128, 29, 58,116,232,205,135, 19, 38, + 76,152, 45, 90,180,117,234,201,143, 3, 6, 12, 24, 48, 96,192, + 157, 39, 78,156, 37, 74,148, 53,106,212,181,119,238,193,159, 35, + 70,140, 5, 10, 20, 40, 80,160, 93,186,105,210,185,111,222,161, + 95,190, 97,194,153, 47, 94,188,101,202,137, 15, 30, 60,120,240, + 253,231,211,187,107,214,177,127,254,225,223,163, 91,182,113,226, + 217,175, 67,134, 17, 34, 68,136, 13, 26, 52,104,208,189,103,206, + 129, 31, 62,124,248,237,199,147, 59,118,236,197,151, 51,102,204, + 133, 23, 46, 92,184,109,218,169, 79,158, 33, 66,132, 21, 42, 84, + 168, 77,154, 41, 82,164, 85,170, 73,146, 57,114,228,213,183,115, + 230,209,191, 99,198,145, 63,126,252,229,215,179,123,246,241,255, + 227,219,171, 75,150, 49, 98,196,149, 55,110,220,165, 87,174, 65, + 130, 25, 50,100,200,141, 7, 14, 28, 56,112,224,221,167, 83,166, + 81,162, 89,178,121,242,249,239,195,155, 43, 86,172, 69,138, 9, + 18, 36, 72,144, 61,122,244,245,247,243,251,235,203,139, 11, 22, + 44, 88,176,125,250,233,207,131, 27, 54,108,216,173, 71,142, 1 +}; + +/* + * 多項式係数の整数表現→αのべき表現 + */ +static const unsigned char qr_fac2exp[256] = { + NAV, 0, 1, 25, 2, 50, 26,198, 3,223, 51,238, 27,104,199, 75, + 4,100,224, 14, 52,141,239,129, 28,193,105,248,200, 8, 76,113, + 5,138,101, 47,225, 36, 15, 33, 53,147,142,218,240, 18,130, 69, + 29,181,194,125,106, 39,249,185,201,154, 9,120, 77,228,114,166, + 6,191,139, 98,102,221, 48,253,226,152, 37,179, 16,145, 34,136, + 54,208,148,206,143,150,219,189,241,210, 19, 92,131, 56, 70, 64, + 30, 66,182,163,195, 72,126,110,107, 58, 40, 84,250,133,186, 61, + 202, 94,155,159, 10, 21,121, 43, 78,212,229,172,115,243,167, 87, + 7,112,192,247,140,128, 99, 13,103, 74,222,237, 49,197,254, 24, + 227,165,153,119, 38,184,180,124, 17, 68,146,217, 35, 32,137, 46, + 55, 63,209, 91,149,188,207,205,144,135,151,178,220,252,190, 97, + 242, 86,211,171, 20, 42, 93,158,132, 60, 57, 83, 71,109, 65,162, + 31, 45, 67,216,183,123,164,118,196, 23, 73,236,127, 12,111,246, + 108,161, 59, 82, 41,157, 85,170,251, 96,134,177,187,204, 62, 90, + 203, 89, 95,176,156,169,160, 81, 11,245, 22,235,122,117, 44,215, + 79,174,213,233,230,231,173,232,116,214,244,234,168, 80, 88,175 +}; + +/* + * 誤り訂正生成多項式の第2項以降の係数表(べき表現) + */ +static const unsigned char qr_gftable[QR_RSW_MAX+1][QR_RSW_MAX] = { + {0},{0},{0},{0},{0},{0},{0},{87,229,146,149,238,102,21}, + {0},{0},{251,67,46,61,118,70,64,94,32,45}, + {0},{0},{74,152,176,100,86,100,106,104,130,218,206,140,78}, + {0},{8,183,61,91,202,37,51,58,58,237,140,124,5,99,105}, + {120,104,107,109,102,161,76,3,91,191,147,169,182,194,225,120}, + {43,139,206,78,43,239,123,206,214,147,24,99,150,39,243,163,136}, + {215,234,158,94,184,97,118,170,79,187,152,148,252,179,5,98,96,153}, + {0},{17,60,79,50,61,163,26,187,202,180,221,225,83,239,156,164,212,212,188,190}, + {0},{210,171,247,242,93,230,14,109,221,53,200,74,8,172,98,80,219,134,160,105,165,231}, + {0},{229,121,135,48,211,117,251,126,159,180,169,152,192,226,228,218,111,0,117,232,87,96,227,21}, + {0},{173,125,158,2,103,182,118,17,145,201,111,28,165,53,161,21,245,142,13,102,48,227,153,145,218,70}, + {0},{168,223,200,104,224,234,108,180,110,190,195,147,205,27,232,201,21,43,245,87,42,195,212,119,242,37,9,123}, + {0},{41,173,145,152,216,31,179,182,50,48,110,86,239,96,222,125,42,173,226,193,224,130,156,37,251,216,238,40,192,180}, + {0},{10,6,106,190,249,167,4,67,209,138,138,32,242,123,89,27,120,185,80,156,38,69,171,60,28,222,80,52,254,185,220,241}, + {0},{111,77,146,94,26,21,108,19,105,94,113,193,86,140,163,125,58,158,229,239,218,103,56,70,114,61,183,129,167,13,98,62,129,51}, + {0},{200,183,98,16,172,31,246,234,60,152,115,0,167,152,113,248,238,107,18,63,218,37,87,210,105,177,120,74,121,196,117,251,113,233,30,120}, + {0},{159,34,38,228,230,59,243,95,49,218,176,164,20,65,45,111,39,81,49,118,113,222,193,250,242,168,217,41,164,247,177,30,238,18,120,153,60,193}, + {0},{59,116,79,161,252,98,128,205,128,161,247,57,163,56,235,106,53,26,187,174,226,104,170,7,175,35,181,114,88,41,47,163,125,134,72,20,232,53,35,15}, + {0},{250,103,221,230,25,18,137,231,0,3,58,242,221,191,110,84,230,8,188,106,96,147,15,131,139,34,101,223,39,101,213,199,237,254,201,123,171,162,194,117,50,96}, + {0},{190,7,61,121,71,246,69,55,168,188,89,243,191,25,72,123,9,145,14,247,1,238,44,78,143,62,224,126,118,114,68,163,52,194,217,147,204,169,37,130,113,102,73,181}, + {0},{112,94,88,112,253,224,202,115,187,99,89,5,54,113,129,44,58,16,135,216,169,211,36,1,4,96,60,241,73,104,234,8,249,245,119,174,52,25,157,224,43,202,223,19,82,15}, + {0},{228,25,196,130,211,146,60,24,251,90,39,102,240,61,178,63,46,123,115,18,221,111,135,160,182,205,107,206,95,150,120,184,91,21,247,156,140,238,191,11,94,227,84,50,163,39,34,108}, + {0},{232,125,157,161,164,9,118,46,209,99,203,193,35,3,209,111,195,242,203,225,46,13,32,160,126,209,130,160,242,215,242,75,77,42,189,32,113,65,124,69,228,114,235,175,124,170,215,232,133,205}, + {0},{116,50,86,186,50,220,251,89,192,46,86,127,124,19,184,233,151,215,22,14,59,145,37,242,203,134,254,89,190,94,59,65,124,113,100,233,235,121,22,76,86,97,39,242,200,220,101,33,239,254,116,51}, + {0},{183,26,201,87,210,221,113,21,46,65,45,50,238,184,249,225,102,58,209,218,109,165,26,95,184,192,52,245,35,254,238,175,172,79,123,25,122,43,120,108,215,80,128,201,235,8,153,59,101,31,198,76,31,156}, + {0},{106,120,107,157,164,216,112,116,2,91,248,163,36,201,202,229,6,144,254,155,135,208,170,209,12,139,127,142,182,249,177,174,190,28,10,85,239,184,101,124,152,206,96,23,163,61,27,196,247,151,154,202,207,20,61,10}, + {0},{82,116,26,247,66,27,62,107,252,182,200,185,235,55,251,242,210,144,154,237,176,141,192,248,152,249,206,85,253,142,65,165,125,23,24,30,122,240,214,6,129,218,29,145,127,134,206,245,117,29,41,63,159,142,233,125,148,123}, + {0},{107,140,26,12,9,141,243,197,226,197,219,45,211,101,219,120,28,181,127,6,100,247,2,205,198,57,115,219,101,109,160,82,37,38,238,49,160,209,121,86,11,124,30,181,84,25,194,87,65,102,190,220,70,27,209,16,89,7,33,240}, + {0},{65,202,113,98,71,223,248,118,214,94,0,122,37,23,2,228,58,121,7,105,135,78,243,118,70,76,223,89,72,50,70,111,194,17,212,126,181,35,221,117,235,11,229,149,147,123,213,40,115,6,200,100,26,246,182,218,127,215,36,186,110,106}, + {0},{45,51,175,9,7,158,159,49,68,119,92,123,177,204,187,254,200,78,141,149,119,26,127,53,160,93,199,212,29,24,145,156,208,150,218,209,4,216,91,47,184,146,47,140,195,195,125,242,238,63,99,108,140,230,242,31,204,11,178,243,217,156,213,231}, + {0},{5,118,222,180,136,136,162,51,46,117,13,215,81,17,139,247,197,171,95,173,65,137,178,68,111,95,101,41,72,214,169,197,95,7,44,154,77,111,236,40,121,143,63,87,80,253,240,126,217,77,34,232,106,50,168,82,76,146,67,106,171,25,132,93,45,105}, + {0},{247,159,223,33,224,93,77,70,90,160,32,254,43,150,84,101,190,205,133,52,60,202,165,220,203,151,93,84,15,84,253,173,160,89,227,52,199,97,95,231,52,177,41,125,137,241,166,225,118,2,54,32,82,215,175,198,43,238,235,27,101,184,127,3,5,8,163,238} +}; + +#define F0 QR_MM_FUNC +#define F1 (QR_MM_FUNC | QR_MM_BLACK) + +/* + * 位置検出パターンのデータ + */ +static const qr_byte_t qr_finderpattern[QR_DIM_FINDER][QR_DIM_FINDER] = { + { F1, F1, F1, F1, F1, F1, F1 }, + { F1, F0, F0, F0, F0, F0, F1 }, + { F1, F0, F1, F1, F1, F0, F1 }, + { F1, F0, F1, F1, F1, F0, F1 }, + { F1, F0, F1, F1, F1, F0, F1 }, + { F1, F0, F0, F0, F0, F0, F1 }, + { F1, F1, F1, F1, F1, F1, F1 } +}; + +/* + * 位置合わせパターンのデータ + */ +static const qr_byte_t qr_alignpattern[QR_DIM_ALIGN][QR_DIM_ALIGN] = { + { F1, F1, F1, F1, F1 }, + { F1, F0, F0, F0, F1 }, + { F1, F0, F1, F0, F1 }, + { F1, F0, F0, F0, F1 }, + { F1, F1, F1, F1, F1 } +}; + +#undef F0 +#undef F1 + +/* + * モード指示子(英字, 英数字, 8ビットバイト, 漢字) + */ +static const int qr_modeid[QR_EM_COUNT] = { 0x01, 0x02, 0x04, 0x08 }; + +/* + * 符号化モード名 (不使用) + */ +/*const char *qr_modename[QR_EM_COUNT] = { + "Numeric", "Alnum", "8bit-byte", "Kanji" +};*/ + +/* + * エラー訂正レベル名 + */ +const char *qr_eclname[QR_ECL_COUNT] = { "L", "M", "Q", "H" }; + +/* + * 英数字モードの符号化表 + */ +static const signed char qr_alnumtable[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + +/* + * 形式情報(2箇所)の座標(下位ビットから) + * (負数は下端/右端からのオフセット) + */ +static const qr_coord_t qr_fmtinfopos[2][QR_FIN_MAX] = { + {{ 0, 8 }, { 1, 8 }, { 2, 8 }, { 3, 8 }, + { 4, 8 }, { 5, 8 }, { 7, 8 }, { 8, 8 }, + { -7, 8 }, { -6, 8 }, { -5, 8 }, { -4, 8 }, + { -3, 8 }, { -2, 8 }, { -1, 8 }}, + {{ 8, -1 }, { 8, -2 }, { 8, -3 }, { 8, -4 }, + { 8, -5 }, { 8, -6 }, { 8, -7 }, { 8, -8 }, + { 8, 7 }, { 8, 5 }, { 8, 4 }, { 8, 3 }, + { 8, 2 }, { 8, 1 }, { 8, 0 }} +}; + +/* + * 形式情報の固定黒モジュール + */ +static const qr_coord_t qr_fmtblackpos = { -8, 8 }; + +/* + * 型番情報(2箇所)の座標(下位ビットから) + * (負数は下端/右端からのオフセット) + */ +static const qr_coord_t qr_verinfopos[2][QR_VIN_MAX] = { + {{ -11, 0 }, { -10, 0 }, { -9, 0 }, + { -11, 1 }, { -10, 1 }, { -9, 1 }, + { -11, 2 }, { -10, 2 }, { -9, 2 }, + { -11, 3 }, { -10, 3 }, { -9, 3 }, + { -11, 4 }, { -10, 4 }, { -9, 4 }, + { -11, 5 }, { -10, 5 }, { -9, 5 }}, + {{ 0, -11 }, { 0, -10 }, { 0, -9 }, + { 1, -11 }, { 1, -10 }, { 1, -9 }, + { 2, -11 }, { 2, -10 }, { 2, -9 }, + { 3, -11 }, { 3, -10 }, { 3, -9 }, + { 4, -11 }, { 4, -10 }, { 4, -9 }, + { 5, -11 }, { 5, -10 }, { 5, -9 }} +}; + +/* + * 型番情報(型番7〜40について有効) + */ +static const long qr_verinfo[QR_VER_MAX+1] = { + -1L, -1L, -1L, -1L, -1L, -1L, + -1L, 0x07c94L, 0x085bcL, 0x09a99L, 0x0a4d3L, 0x0bbf6L, + 0x0c762L, 0x0d847L, 0x0e60dL, 0x0f928L, 0x10b78L, 0x1145dL, + 0x12a17L, 0x13532L, 0x149a6L, 0x15683L, 0x168c9L, 0x177ecL, + 0x18ec4L, 0x191e1L, 0x1afabL, 0x1b08eL, 0x1cc1aL, 0x1d33fL, + 0x1ed75L, 0x1f250L, 0x209d5L, 0x216f0L, 0x228baL, 0x2379fL, + 0x24b0bL, 0x2542eL, 0x26a64L, 0x27541L, 0x28c69L +}; + +/* + * 一連の処理をする関数ポインタ型 + */ +typedef int (*qr_funcs)(QRCode *); + +/* + * 内部処理用関数のプロトタイプ + */ +static void qrAddDataBits(QRCode *qr, int n, int word); +static int qrInitDataWord(QRCode *qr); +static int qrEncodeDataWord(QRCode *qr, const qr_byte_t *source, int size, int mode); +static int qrFinalizeDataWord(QRCode *qr); +static int qrComputeECWord(QRCode *qr); +static int qrMakeCodeWord(QRCode *qr); +static int qrFillFunctionPattern(QRCode *qr); +static int qrFillCodeWord(QRCode *qr); +static void qrInitPosition(QRCode *qr); +static void qrNextPosition(QRCode *qr); +static int qrSelectMaskPattern(QRCode *qr); +static int qrApplyMaskPattern(QRCode *qr); +static int qrApplyMaskPattern2(QRCode *qr, int type); +static long qrEvaluateMaskPattern(QRCode *qr); +static int qrFillFormatInfo(QRCode *qr); + + +#endif /* _QR_PRIVATE_H_ */ diff --git a/kvm_system/main/lib/libqr/qr_util.h b/kvm_system/main/lib/libqr/qr_util.h new file mode 100644 index 0000000..51cca39 --- /dev/null +++ b/kvm_system/main/lib/libqr/qr_util.h @@ -0,0 +1,87 @@ +/* + * QR Code Generator Library: Header for Utility + * + * Core routines were originally written by Junn Ohta. + * Based on qr.c Version 0.1: 2004/4/3 (Public Domain) + * + * @package libqr + * @author Ryusuke SEKIYAMA + * @copyright 2006-2013 Ryusuke SEKIYAMA + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +#ifndef _QR_UTIL_H_ +#define _QR_UTIL_H_ + +#include "qr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* + * Determine the module is a dark module or not. + */ +#define qrIsBlack(qr, i, j) (((qr)->symbol[(i)][(j)] & QR_MM_BLACK) != 0) + +/* + * Deallocate and set to NULL. + */ +#define qrFree(ptr) { if ((ptr) != NULL) { free(ptr); (ptr) = NULL; } } + +/* + * Current function name macro. + */ +QR_API extern const char *(*qrGetCurrentFunctionName)(void); +#if defined(__FUNCTION__) +#define _QR_FUNCTION ((qrGetCurrentFunctionName) ? qrGetCurrentFunctionName() : __FUNCTION__) +#elif defined(__func__) +#define _QR_FUNCTION ((qrGetCurrentFunctionName) ? qrGetCurrentFunctionName() : __func__) +#else +#define _QR_FUNCTION ((qrGetCurrentFunctionName) ? qrGetCurrentFunctionName() : "?") +#endif + +/* + * Maximum length of filename extensions. + */ +#define QR_EXT_MAX_LEN 4 + +/* + * Constatns. + */ +extern QR_API const qr_vertable_t qr_vertable[]; +/*extern QR_API const char *qr_modename[]; */ +extern QR_API const char *qr_eclname[]; + +/* + * Functions for utility. + */ +QR_API const char *qrVersion(void); +QR_API const char *qrMimeType(int format); +QR_API const char *qrExtension(int format); +QR_API const char *qrStrError(int errcode); +QR_API void qrSetErrorInfo(QRCode *qr, int errnum, const char *param); +QR_API void qrSetErrorInfo2(QRCode *qr, int errnum, const char *param); +QR_API void qrSetErrorInfo3(QRCode *qr, int errnum, const char *fmt, ...); +QR_API int qrGetEncodedLength(QRCode *qr, int size); +QR_API int qrGetEncodedLength2(QRCode *qr, int size, int mode); +QR_API int qrGetEncodableLength(QRCode *qr, int size); +QR_API int qrGetEncodableLength2(QRCode *qr, int size, int mode); +QR_API int qrRemainedDataBits(QRCode *qr); + +/* + * Functions for checking datatype. + */ +QR_API int qrDetectDataType(const qr_byte_t *source, int size); +QR_API int qrStrPosNotNumeric(const qr_byte_t *source, int size); +QR_API int qrStrPosNotAlnum(const qr_byte_t *source, int size); +QR_API int qrStrPosNotKanji(const qr_byte_t *source, int size); +QR_API int qrStrPosNot8bit(const qr_byte_t *source, int size); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* _QR_UTIL_H_ */ diff --git a/kvm_system/main/lib/libqr/qrcmd.c b/kvm_system/main/lib/libqr/qrcmd.c new file mode 100644 index 0000000..c090c11 --- /dev/null +++ b/kvm_system/main/lib/libqr/qrcmd.c @@ -0,0 +1,626 @@ +/* + * QR Code Generator Library: Command Line Interface + * + * Core routines were originally written by Junn Ohta. + * Based on qr.c Version 0.1: 2004/4/3 (Public Domain) + * + * @package libqr + * @author Ryusuke SEKIYAMA + * @copyright 2006-2013 Ryusuke SEKIYAMA + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +#include "qrcmd.h" + +#ifdef WIN32 +#define err(code, ...) { \ + printf(__VA_ARGS__); \ + printf(": %s\r\n", strerror(errno)); \ + exit(code); \ +} +#define errx(code, ...) { \ + printf(__VA_ARGS__); \ + printf("\r\n"); \ + exit(code); \ +} +#else +#include +#endif + +#include +#include +#include + +#ifdef WIN32 +#include +#define writeln(msg) printf(msg "\r\n") +#define ewriteln(msg) printf(msg "\r\n") +#define writelnf(fmt, ...) printf(fmt "r\n", __VA_ARGS__) +#define ewritelnf(fmt, ...) printf(fmt "\r\n", __VA_ARGS__) +#else +#define writeln(msg) printf(msg "\n") +#define ewriteln(msg) fprintf(stderr, msg "\n") +#define writelnf(fmt, ...) printf(fmt "\n", __VA_ARGS__) +#define ewritelnf(fmt, ...) fprintf(stderr, fmt "\n", __VA_ARGS__) +#endif + +/* {{{ main() */ + +int +main(int argc, char **argv) +{ + QRCMD_PTR_TYPE *qr; + int mag = 1; + int sep = QR_DIM_SEP; + int fmt = QR_FMT_PBM; + QRCMD_EXTRA_PARAM_A + char output[PATH_MAX] = { '\0' }; + char *ptr = &(output[0]); + int result = 0; + +#ifdef WIN32 + setmode(fileno(stdin), O_BINARY); + setmode(fileno(stdout), O_BINARY); +#endif + + if (argc <= 1) { + writelnf("%s: QR Code Generator", argv[0]); + writelnf("try '%s --help' for more information", argv[0]); + return 1; + } + + /* + * QRコードオブジェクトを生成し、コマンド行引数からパラメータと入力データを設定する + */ + qr = qrGetParameter(argc, argv, &fmt, &sep, &mag, QRCMD_EXTRA_PARAM_C &ptr); + + /* + * データコード語をエンコードし、シンボルを配置する + */ + if (!qrCmdFinalize(qr)) { + ewritelnf("%s: %s", argv[0], qrCmdGetErrorInfo(qr)); + qrCmdDestroy(qr); + return 1; + } + + /* + * シンボルを出力する + */ +#ifdef QRCMD_STRUCTURED_APPEND + if (extra == -1) { + /* + * 連番出力 + */ + int i; + for (i = 0; i < qr->num; i++) { + if (output[0] == '\0') { + result = qrOutputSymbol(qr->qrs[i], stdout, fmt, sep, mag); + } else { + char outputs[PATH_MAX] = { '\0' }; + int written = 0; + written = snprintf(&(outputs[0]), PATH_MAX, "%s%02d.%s", + &(output[0]), i + 1, qrExtension(fmt)); + if (written < 0 || written >= PATH_MAX) { + ewritelnf("%s: output pathname is too long", argv[0]); + qrCmdDestroy(qr); + return 1; + } + result = qrOutputSymbol2(qr->qrs[i], &(outputs[0]), fmt, sep, mag); + } + if (result == -1) { + ewritelnf("%s: QR Code #%d: %s", argv[0], i, qrCmdGetErrorInfo(qr)); + qrCmdDestroy(qr); + return 1; + } + } + } else +#endif + if (output[0] == '\0') { + result = qrCmdOutputSymbol(qr, stdout, fmt, sep, mag QRCMD_EXTRA_PARAM_B); + } else { + result = qrCmdOutputSymbol2(qr, &(output[0]), fmt, sep, mag QRCMD_EXTRA_PARAM_B); + } + if (result == -1) { + ewritelnf("%s: %s", argv[0], qrCmdGetErrorInfo(qr)); + qrCmdDestroy(qr); + return 1; + } + + qrCmdDestroy(qr); + return 0; +} + +/* }}} main() */ +/* {{{ qrShowHelp() */ + +/* + * 使用方法を表示する + */ +void +qrShowHelp(void) +{ + writeln("QR Code Generator"); + writeln(); + writeln("QR Code (R) is registered trademarks of DENSO WAVE INCORPORATED"); + writeln("in JAPAN and other countries."); + writeln(); + writelnf("usage: %s [options ...] [ [ [mode] [text | -i file] ] ...] ", QRCMD_PROG_NAME); + writeln(); + writeln("input:"); + writeln(" The data which is stored in QR Code Symbol (at least 1 character)."); + writeln(" If it is not specified, read from stdin."); + writeln(); + writeln("examples:"); + writelnf(" %s -eM -x6 < input.txt > output.pbm", QRCMD_PROG_NAME); + writelnf(" %s -eM -x6 -o output.pbm -i input.txt", QRCMD_PROG_NAME); + writelnf(" %s -v2 -fBMP -o foobar.bmp -mA 'FOOBAR'", QRCMD_PROG_NAME); + writelnf(" %s -x3 -fSVG -o mixed.svg -mA 'ALNUM' -m8 ' ' -mN '001'", QRCMD_PROG_NAME); + writelnf(" %s -fAA 'Ascii Art'", QRCMD_PROG_NAME); + writeln(); + writeln("options:"); + writeln(" -V show program's version number and exit"); + writeln(" -?, -h, --help show this help message and exit"); +#ifdef QRCMD_STRUCTURED_APPEND + writeln(" -v, --version=NUM symbol version (1-40, default: 1)"); +#else + writeln(" -v, --version=NUM symbol version (1-40, default: auto)"); +#endif + writeln(" -m, --mode=MODE encoding mode (N,A,8,K,S, default: S)"); + writeln(" N: numeric, A: uppercase alphabet and numeric,"); + writeln(" 8: 8-bit byte, K: JIS X 0208 Kanji, S: auto"); + writeln(" -e, --eclevel=LEVEL error correction level (L,M,Q,H, default: M)"); + writeln(" L: 7%%, M: 15%%, Q: 25%%, H: 30%%"); + writeln(" -p, --pattern=NUM mask pattern (0-7, default: auto)"); + writeln(" -x, --magnify=NUM magnifying ratio (1-16, default: 1)"); + writeln(" -s, --separator=NUM separator pattan width (0-16, default: 4)"); + writeln(" '4' is the lower limit of the QR Code specification."); + writeln(" -f, --format=FORMAT output format (default: PBM)"); + writeln(" Available formats are followings."); + writeln(" PNG, BMP, TIFF, PBM, SVG, JSON, DIGIT, ASCII"); + writeln(" These are case-insensitive and some have aliases."); + writeln(" DIGIT -> 01"); + writeln(" ASCII -> asciiart, aa"); + writeln(" JSON -> javascript, js"); + writeln(" TIFF -> tif"); +#ifdef QRCMD_STRUCTURED_APPEND + writelnf(" -a, --maxnum=NUM maximum number of symbols (1-%d, default: %d)", QR_STA_MAX, QR_STA_MAX); + writeln(" -z, --order=NUM ordering method of symbols, in case NUM is ..."); + writeln(" = 0 (default): order to square as possible"); + writeln(" >= 1: order each NUM symbols to horizontal"); + writeln(" <= -1: order each NUM symbols to vertical"); + writeln(" --serial output as serial numbered images"); + writeln(" Number and extension will be added to output pathname."); + writeln(" (default: output as a combined image)"); +#endif + writeln(" -o, --output=PATH output pathname (default: write to stdout)"); + writeln(" -i, --input=PATH input pathname (default: read from stdin)"); + writeln(" To specify multiple files, set this option"); + writeln(" before every filename. And the encoding mode"); + writeln(" can be specified to each files."); + writeln(" (e.g. -mA -i file1 -mK -i file2 ...)"); +} + +/* }}} qrShowHelp() */ +/* {{{ utilities for qrGetParameter() */ + +#define QR_SHORT_OPT(name) (d = 2, !strncmp(ptr, name, d)) +#define QR_LONG_OPT(name) (d = sizeof(name), !strncmp(ptr, name "=", d)) + +#define QR_GETOPT_NEXT() { \ + opt = ptr; \ + ptr += d; \ + if (d == 2 && *ptr == '\0') { \ + i++; \ + if (i == argc) { \ + errx(1, "%s: %s", opt, qrStrError(QR_ERR_EMPTY_PARAM)); \ + } \ + ptr = argv[i]; \ + } \ + if (ptr == NULL || *ptr == '\0') { \ + errx(1, "%s: %s", opt, qrStrError(QR_ERR_EMPTY_PARAM)); \ + } \ +} + +/* }}} utilities for qrGetParameter() */ +/* {{{ qrGetParameter() */ + +/* + * コマンド行引数からパラメータと入力データを設定し、出力ファイル名を取得する + */ +QRCMD_PTR_TYPE * +qrGetParameter(int argc, char **argv, + int *fmt, int *sep, int *mag, QRCMD_EXTRA_PARAM_D char **output) +{ + QRCMD_PTR_TYPE *qr; + char *opt, *ptr; + int i; + size_t d; + int version = QRCMD_DEFAULT_VERSION; + int mode = QR_EM_AUTO; + int eclevel = QR_ECL_M; + int masktype = -1; + QRCMD_MAX_NUM_A + int errcode = QR_ERR_NONE; + int has_data = 0; + + /* + * 引数のパラメータを取得する + */ + for (i = 1; i < argc; i++) { + ptr = argv[i]; + if (!strcmp(ptr, "-?") || !strcasecmp(ptr, "-h") || !strcmp(ptr, "--help")) { + /* + * 使用方法 + */ + qrShowHelp(); + exit(1); + + } else if (!strcmp(ptr, "-V")) { + /* + * バージョン + */ + writelnf("%s: QR Code Generator", QRCMD_PROG_NAME); + writelnf("qrcmd version: %s", QRCMD_PROG_VERSION); + writelnf("libqr version: %s", qrVersion()); + exit(1); + + } else if (QR_SHORT_OPT("-v") || QR_LONG_OPT("--version")) { + /* + * 型番 + */ + QR_GETOPT_NEXT(); + if (*ptr < '0' || *ptr > '9') { + errx(1, "%s: %s", ptr, qrStrError(QR_ERR_INVALID_VERSION)); + } + version = atoi(ptr); + if (version <= 0 || version > QR_VER_MAX) { + errx(1, "%d: %s", version, qrStrError(QR_ERR_INVALID_VERSION)); + } + + } else if (QR_SHORT_OPT("-m") || QR_LONG_OPT("--mode")) { + /* + * 符号化モード + */ + QR_GETOPT_NEXT(); + switch (*ptr) { + case 's': + case 'S': + mode = QR_EM_AUTO; + break; + case 'n': + case 'N': + mode = QR_EM_NUMERIC; + break; + case 'a': + case 'A': + mode = QR_EM_ALNUM; + break; + case '8': + case 'B': + mode = QR_EM_8BIT; + break; + case 'k': + case 'K': + mode = QR_EM_KANJI; + break; + default: + errx(1, "%s: %s", ptr, qrStrError(QR_ERR_INVALID_MODE)); + } + + } else if (QR_SHORT_OPT("-e") || QR_LONG_OPT("--eclevel")) { + /* + * 誤り訂正レベル + */ + QR_GETOPT_NEXT(); + switch (*ptr) { + case 'l': + case 'L': + eclevel = QR_ECL_L; + break; + case 'm': + case 'M': + eclevel = QR_ECL_M; + break; + case 'q': + case 'Q': + eclevel = QR_ECL_Q; + break; + case 'h': + case 'H': + eclevel = QR_ECL_H; + break; + default: + errx(1, "%s: %s", ptr, qrStrError(QR_ERR_INVALID_ECL)); + } + + } else if (QR_SHORT_OPT("-p") || QR_LONG_OPT("--pattern")) { + /* + * マスクパターン種別 + */ + QR_GETOPT_NEXT(); + if (*ptr < '0' || *ptr > '9') { + errx(1, "%s: %s", ptr, qrStrError(QR_ERR_INVALID_MPT)); + } + masktype = atoi(ptr); + if (masktype < 0 || masktype >= QR_MPT_MAX) { + errx(1, "%d: %s", masktype, qrStrError(QR_ERR_INVALID_MPT)); + } + + } else if (QR_SHORT_OPT("-x") || QR_LONG_OPT("--magnify")) { + /* + * ピクセル表示倍率 + */ + QR_GETOPT_NEXT(); + if (*ptr < '0' || *ptr > '9') { + errx(1, "%s: %s", ptr, qrStrError(QR_ERR_INVALID_MAG)); + } + *mag = atoi(ptr); + if (*mag < 0 || *mag > QR_MAG_MAX) { + errx(1, "%d: %s", *mag, qrStrError(QR_ERR_INVALID_MAG)); + } + + } else if (QR_SHORT_OPT("-s") || QR_LONG_OPT("--separator")) { + /* + * 分離パターン幅 + */ + QR_GETOPT_NEXT(); + if (*ptr < '0' || *ptr > '9') { + errx(1, "%s: %s", ptr, qrStrError(QR_ERR_INVALID_SEP)); + } + *sep = atoi(ptr); + if (*sep < 0 || *sep > QR_SEP_MAX) { + errx(1, "%d: %s", *sep, qrStrError(QR_ERR_INVALID_SEP)); + } + + } else if (QR_SHORT_OPT("-f") || QR_LONG_OPT("--format")) { + /* + * 出力形式 + */ + QR_GETOPT_NEXT(); + if (!strcasecmp(ptr, "digit") || !strcasecmp(ptr, "01")) { + *fmt = QR_FMT_DIGIT; + } else if (!strcasecmp(ptr, "asciiart") || + !strcasecmp(ptr, "ascii") || + !strcasecmp(ptr, "aa")) + { + *fmt = QR_FMT_ASCII; + } else if (!strcasecmp(ptr, "javascript") || + !strcasecmp(ptr, "json") || + !strcasecmp(ptr, "js")) + { + *fmt = QR_FMT_JSON; + } else if (!strcasecmp(ptr, "pbm")) { + *fmt = QR_FMT_PBM; + } else if (!strcasecmp(ptr, "bmp")) { + *fmt = QR_FMT_BMP; + } else if (!strcasecmp(ptr, "svg")) { + *fmt = QR_FMT_SVG; + } else if (!strcasecmp(ptr, "tiff") | !strcasecmp(ptr, "tif")) { +#ifdef QR_ENABLE_TIFF + *fmt = QR_FMT_TIFF; +#else + +#endif /* QR_ENABLE_TIFF */ +#ifdef QR_ENABLE_PNG + } else if (!strcasecmp(ptr, "png")) { + *fmt = QR_FMT_PNG; +#endif /* QR_ENABLE_PNG */ + } else { + errx(1, "%s: %s", ptr, qrStrError(QR_ERR_INVALID_FMT)); + } + + } else if (QR_SHORT_OPT("-o") || QR_LONG_OPT("--output")) { + /* + * 出力ファイル名 + */ + QR_GETOPT_NEXT(); + size_t pathlen; + pathlen = strlen(ptr); + if (pathlen >= PATH_MAX) { + errx(1, "argv[%d]: %s", i, strerror(ENAMETOOLONG)); + } + if (*output[0] != '\0') { + errx(1, "%s: %s: Duplicated declaration of output pathname", + *output, ptr); + } + strncpy(*output, ptr, pathlen); + +#ifdef QRCMD_STRUCTURED_APPEND + + } else if (QR_SHORT_OPT("-a") || QR_LONG_OPT("--maxnum")) { + /* + * 最大シンボル数 + */ + QR_GETOPT_NEXT(); + if (*ptr < '0' || *ptr > '9') { + errx(1, "%s: %s", ptr, qrStrError(QR_ERR_INVALID_MAXNUM)); + } + maxnum = atoi(ptr); + if (maxnum < 2 || maxnum > QR_STA_MAX) { + errx(1, "%d: %s", maxnum, qrStrError(QR_ERR_INVALID_MAXNUM)); + } + + } else if (QR_SHORT_OPT("-z") || QR_LONG_OPT("--order")) { + /* + * 並べ方 + */ + QR_GETOPT_NEXT(); + if (*ptr != '-' && (*ptr < '0' || *ptr > '9')) { + /*errx(1, "%s: %s", ptr, qrStrError(QR_ERR_UNKNOWN));*/ + continue; + } + *order = atoi(ptr); + + } else if (!strcmp(ptr, "--serial")) { + /* + * 連番 + */ + if (*extra != 0) { + errx(1, "Serial image output and GIF animation output are exclusive."); + } + *extra = -1; + + } else if (!strcmp(ptr, "--animation") || !strncmp(ptr, "--animation=", 12)) { + /* + * GIFアニメ + */ + if (*extra != 0) { + errx(1, "Serial image output and GIF animation output are exclusive."); + } + if (strlen(ptr) == 11) { + *extra = 100; + } else { + double _f; + ptr += 12; + if (*ptr < '0' || *ptr > '9') { + errx(1, "%s: Invalid animation delay.", ptr); + } + _f = atof(ptr); + *extra = (int)(_f * 100); + if (*extra == 0) { + errx(1, "Zero animation delay."); + } + } + +#endif /* QRCMD_STRUCTURED_APPEND */ + + } else { + break; + } + } + + /* + * QRコードオブジェクトを初期化する + */ + qr = qrCmdInit(version, mode, eclevel, masktype, QRCMD_MAX_NUM_B &errcode); + if (qr == NULL) { + errx(1, "%s", qrStrError(errcode)); + } + + /* + * 入力データを取得する + */ + for (; i < argc; i++) { + ptr = argv[i]; + if (QR_SHORT_OPT("-m") || QR_LONG_OPT("--mode")) { + /* + * 符号化モードを上書き + */ + QR_GETOPT_NEXT(); + switch (*ptr) { + case 'n': + case 'N': + mode = QR_EM_NUMERIC; + break; + case 'a': + case 'A': + mode = QR_EM_ALNUM; + break; + case '8': + case 'B': + mode = QR_EM_8BIT; + break; + case 'k': + case 'K': + mode = QR_EM_KANJI; + break; + default: + qrCmdDestroy(qr); + errx(1, "%s: %s", ptr, qrStrError(QR_ERR_INVALID_MODE)); + } + + } else if (QR_SHORT_OPT("-i") || QR_LONG_OPT("--input")) { + qr_byte_t source[QRCMD_SRC_MAX]; + int srclen = 0; + FILE *fp; + int c; + /* + * 入力データをファイルから読む + */ + QR_GETOPT_NEXT(); + fp = fopen(ptr, "rb"); + if (fp == NULL) { + qrCmdDestroy(qr); + err(1, "%s", ptr); + } + while ((c = fgetc(fp)) != EOF && srclen < QRCMD_SRC_MAX){ + source[srclen++] = (qr_byte_t)c; + } + fclose(fp); + if (srclen == 0) { + qrCmdDestroy(qr); + errx(1, "%s: %s", ptr, qrStrError(QR_ERR_EMPTY_SRC)); + } else if (c != EOF) { + qrCmdDestroy(qr); + errx(1, "%s: %s", ptr, qrStrError(QR_ERR_LARGE_SRC)); + } + if (!qrCmdAddData2(qr, source, srclen, mode)) { + char errinfo[QR_ERR_MAX]; + snprintf(&(errinfo[0]), QR_ERR_MAX, "%s: %s", ptr, qrCmdGetErrorInfo(qr)); + qrCmdDestroy(qr); + errx(1, "%s", errinfo); + } + has_data++; + + } else if (*ptr != '-') { + qr_byte_t source[QRCMD_SRC_MAX]; + int srclen = 0; + /* + * 入力データを引数から得る + */ + srclen = strlen(ptr); + if (srclen == 0) { + qrCmdDestroy(qr); + errx(1, "argv[%d]: %s", i, qrStrError(QR_ERR_EMPTY_SRC)); + } else if (srclen > QRCMD_SRC_MAX) { + qrCmdDestroy(qr); + errx(1, "argv[%d]: %s", i, qrStrError(QR_ERR_LARGE_SRC)); + } + memcpy(&(source[0]), ptr, (size_t)srclen); + if (!qrCmdAddData2(qr, source, srclen, mode)) { + char errinfo[QR_ERR_MAX]; + snprintf(&(errinfo[0]), QR_ERR_MAX, "argv[%d]: %s", i, qrCmdGetErrorInfo(qr)); + qrCmdDestroy(qr); + errx(1, "%s", errinfo); + } + has_data++; + + } else { + /* + * 未定義オプション + */ + qrCmdDestroy(qr); + errx(1, "%s: %s", ptr, qrStrError(QR_ERR_INVALID_ARG)); + } + } + + /* + * 入力データが空なら、標準入力から読む + */ + if (!has_data) { + qr_byte_t source[QRCMD_SRC_MAX]; + int srclen = 0; + int c; + while ((c = getchar()) != EOF && srclen < QRCMD_SRC_MAX){ + source[srclen++] = (qr_byte_t)c; + } + if (srclen == 0) { + qrCmdDestroy(qr); + errx(1, "-stdin: %s", qrStrError(QR_ERR_EMPTY_SRC)); + } + if (c != EOF) { + qrCmdDestroy(qr); + errx(1, "-stdin: %s", qrStrError(QR_ERR_LARGE_SRC)); + } + if (!qrCmdAddData2(qr, source, srclen, mode)) { + char errinfo[QR_ERR_MAX]; + snprintf(&(errinfo[0]), QR_ERR_MAX, "%s", qrCmdGetErrorInfo(qr)); + qrCmdDestroy(qr); + errx(1, "%s", errinfo); + } + } + + return qr; +} + +/* }}} qrGetParameter() */ diff --git a/kvm_system/main/lib/libqr/qrcmd.h b/kvm_system/main/lib/libqr/qrcmd.h new file mode 100644 index 0000000..4b4f4f2 --- /dev/null +++ b/kvm_system/main/lib/libqr/qrcmd.h @@ -0,0 +1,110 @@ +/* + * QR Code Generator Library: Header for Command Line Interface + * + * Core routines were originally written by Junn Ohta. + * Based on qr.c Version 0.1: 2004/4/3 (Public Domain) + * + * @package libqr + * @author Ryusuke SEKIYAMA + * @copyright 2006-2013 Ryusuke SEKIYAMA + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +#ifndef _QRCMD_H_ +#define _QRCMD_H_ + +/* {{{ include headers */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "qr.h" +#include "qr_util.h" + +/* }}} */ +/* {{{ version information */ + +#define QRCMD_PROG_VERSION "0.2.0" + +/* }}} */ +/* {{{ whether enable structured append or not */ + +#ifdef QRCMD_STRUCTURED_APPEND +/* {{{ enable structured append */ + +/* parameters */ +#define QRCMD_PTR_TYPE QRStructured +#define QRCMD_EXTRA_PARAM_A int order = 0; int extra = 0; +#define QRCMD_EXTRA_PARAM_B , order +#define QRCMD_EXTRA_PARAM_C &order, &extra, +#define QRCMD_EXTRA_PARAM_D int *order, int *extra, +#define QRCMD_MAX_NUM_A int maxnum = QR_STA_MAX; +#define QRCMD_MAX_NUM_B maxnum, +#define QRCMD_DEFAULT_VERSION 1 + +/* functions */ +#define qrCmdInit qrsInit +#define qrCmdDestroy qrsDestroy +#define qrCmdFinalize qrsFinalize +#define qrCmdGetErrorInfo qrsGetErrorInfo +#define qrCmdAddData qrsAddData +#define qrCmdAddData2 qrsAddData2 +#define qrCmdOutputSymbol qrsOutputSymbols +#define qrCmdOutputSymbol2 qrsOutputSymbols2 + +/* others */ +#ifndef QRCMD_PROG_NAME +#define QRCMD_PROG_NAME "qrs" +#endif +#ifndef QR_SA_SRC_MAX +#define QR_SA_SRC_MAX 112233 +#endif +#define QRCMD_SRC_MAX QR_SA_SRC_MAX + +/* }}} */ +#else +/* {{{ disable structured append */ + +/* parameters */ +#define QRCMD_PTR_TYPE QRCode +#define QRCMD_EXTRA_PARAM_A +#define QRCMD_EXTRA_PARAM_B +#define QRCMD_EXTRA_PARAM_C +#define QRCMD_EXTRA_PARAM_D +#define QRCMD_MAX_NUM_A +#define QRCMD_MAX_NUM_B +#define QRCMD_DEFAULT_VERSION -1 + +/* functions */ +#define qrCmdInit qrInit +#define qrCmdDestroy qrDestroy +#define qrCmdFinalize qrFinalize +#define qrCmdGetErrorInfo qrGetErrorInfo +#define qrCmdAddData qrAddData +#define qrCmdAddData2 qrAddData2 +#define qrCmdOutputSymbol qrOutputSymbol +#define qrCmdOutputSymbol2 qrOutputSymbol2 + +/* others */ +#ifndef QRCMD_PROG_NAME +#define QRCMD_PROG_NAME "qr" +#endif +#define QRCMD_SRC_MAX QR_SRC_MAX + +/* }}} */ +#endif /* QRCMD_STRUCTURED_APPEND */ + +/* }}} */ +/* {{{ function prototype declarations */ + +QRCMD_PTR_TYPE * +qrGetParameter(int argc, char **argv, + int *fmt, int *sep, int *mag, QRCMD_EXTRA_PARAM_D char **output); + +void +qrShowHelp(void); + +/* }}} */ + +#endif /* _QRCMD_H_ */ diff --git a/kvm_system/main/lib/libqr/qrcnv.c b/kvm_system/main/lib/libqr/qrcnv.c new file mode 100644 index 0000000..519d94d --- /dev/null +++ b/kvm_system/main/lib/libqr/qrcnv.c @@ -0,0 +1,672 @@ +/* + * QR Code Generator Library: Symbol Converters for Basic Output Formats + * + * Core routines were originally written by Junn Ohta. + * Based on qr.c Version 0.1: 2004/4/3 (Public Domain) + * + * @package libqr + * @author Ryusuke SEKIYAMA + * @copyright 2006-2013 Ryusuke SEKIYAMA + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +#include "qrcnv.h" + +/* {{{ utility macro */ + +#define repeat(m, n) for ((m) = 0; (m) < (n); (m)++) + +/* }}} */ +/* {{{ symbol writing macro */ + +#define qrInitRow(filler) { \ + memset(rbuf, (filler), (size_t)rsize); \ + rptr = rbuf; \ +} + +#define qrWriteRow(m, n) { \ + wsize = (int)(rptr - rbuf); \ + for ((m) = 0; (m) < (n); (m)++) { \ + memcpy(sptr, rbuf, (size_t)wsize); \ + sptr += wsize; \ + } \ + if (wsize < rsize) { \ + *size -= (rsize - wsize) * (n); \ + } \ +} + +/* + * シンボルを出力する際の定型作業をまとめたマクロ + * + * このマクロを呼び出す前に以下の4つのマクロをdefineし、 + * 呼び出した後はundefする + * qrWriteBOR() 行頭を書き込む + * qrWriteEOR() 行末を書き込む + * qrWriteBLM(m, n) 明モジュールを書き込む + * qrWriteDKM(m, n) 暗モジュールを書き込む +*/ +#define qrWriteSymbol(qr, filler) { \ + /* 分離パターン (上) */ \ + if (sepdim > 0) { \ + qrInitRow(filler); \ + qrWriteBOR(); \ + qrWriteBLM(j, imgdim); \ + qrWriteEOR(); \ + qrWriteRow(i, sepdim); \ + } \ + for (i = 0; i < dim; i++) { \ + /* 行を初期化 */ \ + qrInitRow(filler); \ + /* 行頭 */ \ + qrWriteBOR(); \ + /* 分離パターン (左) */ \ + qrWriteBLM(j, sepdim); \ + /* シンボル本体 */ \ + for (j = 0; j < dim; j++) { \ + if (qrIsBlack((qr), i, j)) { \ + qrWriteDKM(jx, mag); \ + } else { \ + qrWriteBLM(jx, mag); \ + } \ + } \ + /* 分離パターン (右) */ \ + qrWriteBLM(j, sepdim); \ + /* 行末 */ \ + qrWriteEOR(); \ + /* 行をmag回繰り返し書き込む */ \ + qrWriteRow(ix, mag); \ + } \ + /* 分離パターン (下) */ \ + if (sepdim > 0) { \ + qrInitRow(filler); \ + qrWriteBOR(); \ + qrWriteBLM(j, imgdim); \ + qrWriteEOR(); \ + qrWriteRow(i, sepdim); \ + } \ +} + +/* }}} */ +/* {{{ Structured append symbol writing macro */ + +#define qrsWriteSymbols(st, filler) { \ + for (k = 0; k < rows; k++) { \ + /* 分離パターン (上) */ \ + if (sepdim > 0) { \ + qrInitRow(filler); \ + qrWriteBOR(); \ + qrWriteBLM(j, xdim); \ + qrWriteEOR(); \ + qrWriteRow(i, sepdim); \ + } \ + for (i = 0; i < dim; i++) { \ + /* 行を初期化 */ \ + qrInitRow(filler); \ + /* 行頭 */ \ + qrWriteBOR(); \ + for (kx = 0; kx < cols; kx++) { \ + /* 分離パターン (左) */ \ + qrWriteBLM(j, sepdim); \ + /* シンボル本体 */ \ + if (order < 0) { \ + pos = k + rows * kx; \ + } else { \ + pos = cols * k + kx; \ + } \ + if (pos < (st)->num) { \ + for (j = 0; j < dim; j++) { \ + if (qrIsBlack((st)->qrs[pos], i, j)) { \ + qrWriteDKM(jx, mag); \ + } else { \ + qrWriteBLM(jx, mag); \ + } \ + } \ + } else { \ + qrWriteBLM(j, zdim); \ + } \ + } \ + /* 分離パターン (右) */ \ + qrWriteBLM(j, sepdim); \ + /* 行末 */ \ + qrWriteEOR(); \ + /* 行をmag回繰り返し書き込む */ \ + qrWriteRow(ix, mag); \ + } \ + } \ + /* 分離パターン (下) */ \ + if (sepdim > 0) { \ + qrInitRow(filler); \ + qrWriteBOR(); \ + qrWriteBLM(j, xdim); \ + qrWriteEOR(); \ + qrWriteRow(i, sepdim); \ + } \ +} + +/* }}} */ +/* {{{ Digit formatted symbol writing macro */ + +#define qrWriteBOR_Digit() +#define qrWriteEOR_Digit() { *rptr++ = ' '; } +#define qrWriteBLM_Digit(m, n) { rptr += (n); } +#define qrWriteDKM_Digit(m, n) { repeat(m, n) { *rptr++ = '1'; } } + +/* }}} */ +/* {{{ Ascii art formatted symbol writing macro */ + +#define qrWriteBOR_ASCII() +#ifdef WIN32 +#define qrWriteEOR_ASCII() { *rptr++ = '\r'; *rptr++ = '\n'; } +#else +#define qrWriteEOR_ASCII() { *rptr++ = '\n'; } +#endif +#ifdef _QRCNV_AA_STYLE_U2588 +#define QRCNV_AA_UNIT 3 +#define qrWriteBLM_ASCII(m, n) { rptr += (n) * 2; } +#define qrWriteDKM_ASCII(m, n) { repeat(m, n) { *rptr++ = 0xe2; *rptr++ = 0x96; *rptr++ = 0x88; } } +#else +#define QRCNV_AA_UNIT 2 +#define qrWriteBLM_ASCII(m, n) { rptr += (n) * 2; } +#define qrWriteDKM_ASCII(m, n) { repeat(m, n) { *rptr++ = 'X'; *rptr++ = 'X'; } } +#endif + +/* }}} */ +/* {{{ JSON formatted symbol writing macro */ + +#define qrWriteBOR_JSON() { *rptr++ = '['; } +#define qrWriteEOR_JSON() { rptr--; *rptr++ = ']'; rptr++; } +#ifdef _QR_JSON_STYLE_BOOLELAN +#define QRCNV_JSON_UNIT 6 +#define qrWriteBLM_JSON(m, n) { repeat(m, n) { memcpy(rptr, "false", 5); rptr += 6; } } +#define qrWriteDKM_JSON(m, n) { repeat(m, n) { memcpy(rptr, "true", 4); rptr += 5; } } +#else +#define QRCNV_JSON_UNIT 2 +#define qrWriteBLM_JSON(m, n) { repeat(m, n) { *rptr++ = '0'; rptr++; } } +#define qrWriteDKM_JSON(m, n) { repeat(m, n) { *rptr++ = '1'; rptr++; } } +#endif + +/* }}} */ +/* {{{ PBM formatted symbol writing macro */ + +#define qrWriteBOR_PBM() +#define qrWriteEOR_PBM() { *rptr++ = '\n'; } +#define qrWriteBLM_PBM(m, n) { repeat(m, n) { rptr++; *rptr++ = '0'; } } +#define qrWriteDKM_PBM(m, n) { repeat(m, n) { rptr++; *rptr++ = '1'; } } + +/* }}} */ +/* {{{ qrSymbolToDigit() */ + +/* + * 生成されたQRコードシンボルを0,1と空白で構成される文字列に変換する + */ +QR_API qr_byte_t * +qrSymbolToDigit(QRCode *qr, int sep, int mag, int *size) +{ + qr_byte_t *rbuf, *rptr; + qr_byte_t *sbuf, *sptr; + int rsize, wsize; + int i, j, ix, jx, dim, imgdim, sepdim; + + QRCNV_CHECK_STATE(); + QRCNV_GET_SIZE(); + + /* + * 変換後のサイズを計算し、メモリを確保する + */ + rsize = imgdim + 1; + *size = rsize * imgdim - 1; + QRCNV_MALLOC(rsize, *size + 1); + + sptr = sbuf; + +#define qrWriteBOR qrWriteBOR_Digit +#define qrWriteEOR qrWriteEOR_Digit +#define qrWriteBLM qrWriteBLM_Digit +#define qrWriteDKM qrWriteDKM_Digit + + /* + * シンボルを書き込む + */ + qrWriteSymbol(qr, '0'); + + /* + * 最後の文字(スペース)を終端文字に置換する + */ + *(--sptr) = '\0'; + +#undef qrWriteBOR +#undef qrWriteEOR +#undef qrWriteBLM +#undef qrWriteDKM + + free(rbuf); + + return sbuf; +} + +/* }}} */ +/* {{{ qrSymbolToASCII() */ + +/* + * 生成されたQRコードシンボルを0,1と空白で構成される文字列に変換する + */ +QR_API qr_byte_t * +qrSymbolToASCII(QRCode *qr, int sep, int mag, int *size) +{ + qr_byte_t *rbuf, *rptr; + qr_byte_t *sbuf, *sptr; + int rsize, wsize; + int i, j, ix, jx, dim, imgdim, sepdim; + + QRCNV_CHECK_STATE(); + QRCNV_GET_SIZE(); + + /* + * 変換後のサイズを計算し、メモリを確保する + */ + rsize = imgdim * QRCNV_AA_UNIT + QRCNV_EOL_SIZE; + *size = rsize * imgdim; + QRCNV_MALLOC(rsize, *size + 1); + + sptr = sbuf; + +#define qrWriteBOR qrWriteBOR_ASCII +#define qrWriteEOR qrWriteEOR_ASCII +#define qrWriteBLM qrWriteBLM_ASCII +#define qrWriteDKM qrWriteDKM_ASCII + + /* + * シンボルを書き込む + */ + qrWriteSymbol(qr, ' '); + + /* + * 終端文字を書き込む + */ + *sptr = '\0'; + +#undef qrWriteBOR +#undef qrWriteEOR +#undef qrWriteBLM +#undef qrWriteDKM + + free(rbuf); + + return sbuf; +} + +/* }}} */ +/* {{{ qrSymbolToJSON() */ + +/* + * 生成されたQRコードシンボルをJSON形式の文字列に変換する + * JSONをデコードすると二次元配列が得られる + */ +QR_API qr_byte_t * +qrSymbolToJSON(QRCode *qr, int sep, int mag, int *size) +{ + qr_byte_t *rbuf, *rptr; + qr_byte_t *sbuf, *sptr; + int rsize, wsize; + int i, j, ix, jx, dim, imgdim, sepdim; + + QRCNV_CHECK_STATE(); + QRCNV_GET_SIZE(); + + /* + * 変換後のサイズを計算し、メモリを確保する + */ + rsize = 1 + imgdim * QRCNV_JSON_UNIT + 1; + *size = 1 + rsize * imgdim - 1 + 1; + QRCNV_MALLOC(rsize, *size + 1); + + sptr = sbuf; + +#define qrWriteBOR qrWriteBOR_JSON +#define qrWriteEOR qrWriteEOR_JSON +#define qrWriteBLM qrWriteBLM_JSON +#define qrWriteDKM qrWriteDKM_JSON + + /* + * ヘッダを書き込む + */ + *sptr++ = '['; + + /* + * シンボルを書き込む + */ + qrWriteSymbol(qr, ','); + + /* + * フッタと終端文字を書き込む + */ + sptr--; + *sptr++ = ']'; + *sptr = '\0'; + +#undef qrWriteBOR +#undef qrWriteEOR +#undef qrWriteBLM +#undef qrWriteDKM + + free(rbuf); + + return sbuf; +} + +/* }}} */ +/* {{{ qrSymbolToPBM() */ + +/* + * 生成されたQRコードシンボルをモノクロ2値の + * アスキー形式Portable Bitmap(PBM)に変換する + */ +QR_API qr_byte_t * +qrSymbolToPBM(QRCode *qr, int sep, int mag, int *size) +{ + qr_byte_t *rbuf, *rptr; + qr_byte_t *sbuf, *sptr; + int rsize, wsize; + int i, j, ix, jx, dim, imgdim, sepdim; + char header[64]; + int hsize; + + QRCNV_CHECK_STATE(); + QRCNV_GET_SIZE(); + + /* + * 変換後のサイズを計算し、メモリを確保する + */ + hsize = snprintf(&(header[0]), sizeof(header), "P1\n%d %d\n", imgdim, imgdim); + if (hsize == -1 || header[hsize - 1] != '\n') { + QRCNV_RETURN_FAILURE(QR_ERR_UNKNOWN, _QR_FUNCTION); + } + rsize = imgdim * 2 + 1; + *size = hsize + rsize * imgdim; + QRCNV_MALLOC(rsize, *size + 1); + + sptr = sbuf; + +#define qrWriteBOR qrWriteBOR_PBM +#define qrWriteEOR qrWriteEOR_PBM +#define qrWriteBLM qrWriteBLM_PBM +#define qrWriteDKM qrWriteDKM_PBM + + /* + * ヘッダを書き込む + */ + memcpy(sptr, header, (size_t)hsize); + sptr += hsize; + + /* + * シンボルを書き込む + */ + qrWriteSymbol(qr, ' '); + + /* + * 終端文字を書き込む + */ + *sptr = '\0'; + +#undef qrWriteBOR +#undef qrWriteEOR +#undef qrWriteBLM +#undef qrWriteDKM + + free(rbuf); + + return sbuf; +} + +/* }}} */ +/* {{{ qrsSymbolsToDigit() */ + +/* + * 構造的連接用qrSymbolToDigit() + * order は無視される + */ +QR_API qr_byte_t * +qrsSymbolsToDigit(QRStructured *st, int sep, int mag, int order, int *size) +{ + QRCode *qr = st->cur; + qr_byte_t *rbuf, *rptr; + qr_byte_t *sbuf, *sptr; + int rsize, wsize; + int i, j, k, ix, jx; + int cols, rows, xdim, ydim, zdim; + int dim, imgdim, sepdim; + + QRCNV_SA_CHECK_STATE(); + QRCNV_SA_IF_ONE(qrSymbolToDigit); + QRCNV_SA_GET_SIZE(); + + /* + * 変換後のサイズを計算し、メモリを確保する + */ + rsize = imgdim + 1; + *size = rsize * imgdim * st->num - 1; + QRCNV_MALLOC(rsize, *size + 1); + + sptr = sbuf; + +#define qrWriteBOR qrWriteBOR_Digit +#define qrWriteEOR qrWriteEOR_Digit +#define qrWriteBLM qrWriteBLM_Digit +#define qrWriteDKM qrWriteDKM_Digit + + /* + * シンボルを書き込む + */ + for (k = 0; k < st->num; k++) { + qrWriteSymbol(st->qrs[k], '0'); + *(--sptr) = '\n'; + sptr++; + } + + /* + * 最後の文字(LF)を終端文字に置換する + */ + *(--sptr) = '\0'; + +#undef qrWriteBOR +#undef qrWriteEOR +#undef qrWriteBLM +#undef qrWriteDKM + + free(rbuf); + + return sbuf; +} + +/* }}} */ +/* {{{ qrsSymbolsToASCII() */ + +/* + * 構造的連接用qrSymbolToASCII() + */ +QR_API qr_byte_t * +qrsSymbolsToASCII(QRStructured *st, int sep, int mag, int order, int *size) +{ + QRCode *qr = st->cur; + qr_byte_t *rbuf, *rptr; + qr_byte_t *sbuf, *sptr; + int rsize, wsize; + int i, j, k, ix, jx, kx; + int cols, rows, pos, xdim, ydim, zdim; + int dim, imgdim, sepdim; + + QRCNV_SA_CHECK_STATE(); + QRCNV_SA_IF_ONE(qrSymbolToASCII); + QRCNV_SA_GET_SIZE(); + + /* + * 変換後のサイズを計算し、メモリを確保する + */ + rsize = xdim * QRCNV_AA_UNIT + QRCNV_EOL_SIZE; + *size = rsize * ydim; + QRCNV_MALLOC(rsize, *size + 1); + + sptr = sbuf; + +#define qrWriteBOR qrWriteBOR_ASCII +#define qrWriteEOR qrWriteEOR_ASCII +#define qrWriteBLM qrWriteBLM_ASCII +#define qrWriteDKM qrWriteDKM_ASCII + + /* + * シンボルを書き込む + */ + qrsWriteSymbols(st, ' '); + + /* + * 終端文字を書き込む + */ + *sptr = '\0'; + +#undef qrWriteBOR +#undef qrWriteEOR +#undef qrWriteBLM +#undef qrWriteDKM + + free(rbuf); + + return sbuf; +} + +/* }}} */ +/* {{{ qrsSymbolsToJSON() */ + +/* + * 構造的連接用qrSymbolToJSON() + * order は無視される + */ +QR_API qr_byte_t * +qrsSymbolsToJSON(QRStructured *st, int sep, int mag, int order, int *size) +{ + QRCode *qr = st->cur; + qr_byte_t *rbuf, *rptr; + qr_byte_t *sbuf, *sptr; + int rsize, wsize; + int i, j, k, ix, jx; + int cols, rows, xdim, ydim, zdim; + int dim, imgdim, sepdim; + + QRCNV_SA_CHECK_STATE(); + /*QRCNV_SA_IF_ONE(qrSymbolToJSON);*/ + QRCNV_SA_GET_SIZE(); + + /* + * 変換後のサイズを計算し、メモリを確保する + */ + rsize = 1 + imgdim * QRCNV_JSON_UNIT + 1; + *size = 1 + (1 + rsize * imgdim + 1) * st->num - 1 + 1; + QRCNV_MALLOC(rsize, *size + 1); + + sptr = sbuf; + +#define qrWriteBOR qrWriteBOR_JSON +#define qrWriteEOR qrWriteEOR_JSON +#define qrWriteBLM qrWriteBLM_JSON +#define qrWriteDKM qrWriteDKM_JSON + + /* + * ヘッダを書き込む + */ + *sptr++ = '['; + + /* + * シンボルを書き込む + */ + for (k = 0; k < st->num; k++) { + *sptr++ = '['; + qrWriteSymbol(st->qrs[k], ','); + sptr--; + *sptr++ = ']'; + *sptr++ = ','; + } + + /* + * フッタと終端文字を書き込む + */ + sptr--; + *sptr++ = ']'; + *sptr = '\0'; + +#undef qrWriteBOR +#undef qrWriteEOR +#undef qrWriteBLM +#undef qrWriteDKM + + free(rbuf); + + return sbuf; +} + +/* }}} */ +/* {{{ qrsSymbolsToPBM() */ + +/* + * 構造的連接用qrSymbolToPBM() + */ +QR_API qr_byte_t * +qrsSymbolsToPBM(QRStructured *st, int sep, int mag, int order, int *size) +{ + QRCode *qr = st->cur; + qr_byte_t *rbuf, *rptr; + qr_byte_t *sbuf, *sptr; + int rsize, wsize; + int i, j, k, ix, jx, kx; + int cols, rows, pos, xdim, ydim, zdim; + int dim, imgdim, sepdim; + char header[64]; + int hsize; + + QRCNV_SA_CHECK_STATE(); + QRCNV_SA_IF_ONE(qrSymbolToPBM); + QRCNV_SA_GET_SIZE(); + + /* + * 変換後のサイズを計算し、メモリを確保する + */ + hsize = snprintf(&(header[0]), 64, "P1\n%d %d\n", xdim, ydim); + if (hsize >= 64) { + QRCNV_RETURN_FAILURE(QR_ERR_UNKNOWN, _QR_FUNCTION); + } + rsize = xdim * 2 + 1; + *size = hsize + rsize * ydim; + QRCNV_MALLOC(rsize, *size + 1); + + sptr = sbuf; + +#define qrWriteBOR qrWriteBOR_PBM +#define qrWriteEOR qrWriteEOR_PBM +#define qrWriteBLM qrWriteBLM_PBM +#define qrWriteDKM qrWriteDKM_PBM + + /* + * ヘッダを書き込む + */ + memcpy(sptr, header, (size_t)hsize); + sptr += hsize; + + /* + * シンボルを書き込む + */ + qrsWriteSymbols(st, ' '); + + /* + * 終端文字を付加する + */ + *sptr = '\0'; + +#undef qrWriteBOR +#undef qrWriteEOR +#undef qrWriteBLM +#undef qrWriteDKM + + free(rbuf); + + return sbuf; +} + +/* }}} */ diff --git a/kvm_system/main/lib/libqr/qrcnv.h b/kvm_system/main/lib/libqr/qrcnv.h new file mode 100644 index 0000000..8be6d91 --- /dev/null +++ b/kvm_system/main/lib/libqr/qrcnv.h @@ -0,0 +1,165 @@ +/* + * QR Code Generator Library: Private Definitions for Symbol Converters + * + * Core routines were originally written by Junn Ohta. + * Based on qr.c Version 0.1: 2004/4/3 (Public Domain) + * + * @package libqr + * @author Ryusuke SEKIYAMA + * @copyright 2006-2013 Ryusuke SEKIYAMA + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +#ifndef _QRCNV_H_ +#define _QRCNV_H_ + +/* {{{ include headers */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "qr.h" +#include "qr_util.h" +#include +#include +#include + +/* }}} */ +/* {{{ determine EOL size (CR+LF or LF) */ + +#ifdef WIN32 +#define QRCNV_EOL_SIZE 2 +#else +#define QRCNV_EOL_SIZE 1 +#endif + +/* }}} */ +/* {{{ error handlers */ + +#define QRCNV_RETURN_FAILURE(e, p) { \ + qrSetErrorInfo(qr, (e), (p)); \ + if (size) { \ + *size = -1; \ + } \ + return NULL; \ +} + +#define QRCNV_RETURN_FAILURE2(e, p) { \ + qrSetErrorInfo2(qr, (e), (p)); \ + if (size) { \ + *size = -1; \ + } \ + return NULL; \ +} + +#define QRCNV_RETURN_FAILURE3(e, p, ...) { \ + qrSetErrorInfo3(qr, (e), (p), __VA_ARGS__); \ + if (size) { \ + *size = -1; \ + } \ + return NULL; \ +} + +/* }}} */ +/* {{{ allocate memory for the working rowl and the symbo */ + +#define QRCNV_MALLOC(rsize, ssize) { \ + rbuf = (qr_byte_t *)malloc((size_t)(rsize)); \ + if (rbuf == NULL) { \ + QRCNV_RETURN_FAILURE2(QR_ERR_MEMORY_EXHAUSTED, _QR_FUNCTION); \ + } \ + sbuf = (qr_byte_t *)malloc((size_t)(ssize)); \ + if (sbuf == NULL) { \ + free(rbuf); \ + QRCNV_RETURN_FAILURE2(QR_ERR_MEMORY_EXHAUSTED, _QR_FUNCTION); \ + } \ +} + +/* }}} */ +/* {{{ check the state and the parameters */ + +#define QRCNV_CHECK_STATE() { \ + if (qr->state < QR_STATE_FINAL) { \ + QRCNV_RETURN_FAILURE(QR_ERR_STATE, _QR_FUNCTION); \ + } \ +} + +#define QRCNV_GET_SIZE() { \ + if (sep != -1 && (sep < 0 || mag > QR_SEP_MAX)) { \ + QRCNV_RETURN_FAILURE3(QR_ERR_INVALID_SEP, ": %d", sep); \ + } \ + if (mag <= 0 || mag > QR_MAG_MAX) { \ + QRCNV_RETURN_FAILURE3(QR_ERR_INVALID_MAG, ": %d", mag); \ + } \ + dim = qr_vertable[qr->param.version].dimension; \ + if (sep == -1) { \ + sepdim = QR_DIM_SEP * mag; \ + } else { \ + sepdim = sep * mag; \ + } \ + imgdim = dim * mag + sepdim * 2; \ +} + +/* }}} */ +/* {{{ check the state and the parameters (structured append) */ + +#define QRCNV_SA_CHECK_STATE() { \ + if (st->state < QR_STATE_FINAL) { \ + QRCNV_RETURN_FAILURE(QR_ERR_STATE, _QR_FUNCTION); \ + } \ +} + +#define QRCNV_SA_GET_SIZE() { \ + if (sep != -1 && (sep < 0 || mag > QR_SEP_MAX)) { \ + QRCNV_RETURN_FAILURE3(QR_ERR_INVALID_SEP, ": %d", sep); \ + } \ + if (mag <= 0 || mag > QR_MAG_MAX) { \ + QRCNV_RETURN_FAILURE3(QR_ERR_INVALID_MAG, ": %d", mag); \ + } \ + dim = qr_vertable[st->param.version].dimension; \ + if (sep == -1) { \ + sepdim = QR_DIM_SEP * mag; \ + } else { \ + sepdim = sep * mag; \ + } \ + zdim = dim * mag; \ + imgdim = zdim + sepdim * 2; \ + if (order > 0) { \ + if (st->num > order) { \ + cols = order; \ + rows = (st->num + order - 1) / cols; \ + } else { \ + cols = st->num; \ + rows = 1; \ + } \ + } else if (order < 0) { \ + int _a; \ + _a = abs(order); \ + if (st->num > _a) { \ + rows = _a; \ + cols = (st->num + _a - 1) / rows; \ + } else { \ + cols = 1; \ + rows = st->num; \ + } \ + } else { \ + double _r; \ + _r = sqrt((double)st->num); \ + cols = (int)ceil(_r); \ + rows = (int)floor(_r); \ + if (cols * rows < st->num) { \ + rows = (int)ceil(_r); \ + } \ + } \ + xdim = (zdim + sepdim) * cols + sepdim; \ + ydim = (zdim + sepdim) * rows + sepdim; \ +} + +#define QRCNV_SA_IF_ONE(func) { \ + if (st->num == 1) { \ + return (func)(st->qrs[0], sep, mag, size); \ + } \ +} + +#endif /* _QRCNV_H_ */ diff --git a/kvm_system/main/lib/libqr/qrcnv_bmp.c b/kvm_system/main/lib/libqr/qrcnv_bmp.c new file mode 100644 index 0000000..79a6cc3 --- /dev/null +++ b/kvm_system/main/lib/libqr/qrcnv_bmp.c @@ -0,0 +1,324 @@ +/* + * QR Code Generator Library: Symbol Converters for Windows Bitmap + * + * Core routines were originally written by Junn Ohta. + * Based on qr.c Version 0.1: 2004/4/3 (Public Domain) + * + * @package libqr + * @author Ryusuke SEKIYAMA + * @copyright 2006-2013 Ryusuke SEKIYAMA + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +#include "qrcnv.h" +#if defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__) +#include +#endif + +/* {{{ size constants */ + +#define QRCNV_BMP_BISIZE 40 /* Windows Bitmap */ +#define QRCNV_BMP_OFFBITS 62 /* 14(bf) + 40(bi) + 4(rgbq) + 4(rgbq) */ +#define QRCNV_BMP_PPM 3780 /* 96 dpi ~= 3780 ppm */ + /* 72 dpi ~= 2835 ppm */ + +/* }}} */ +/* {{{ utility macro */ + +#if defined(__BIG_ENDIAN__) +#define qrBmpWriteShort(ptr, n) { \ + uint16_t us = (uint16_t)((n) & 0xffffU); \ + qr_byte_t *tmp = (qr_byte_t *)&us; \ + *(ptr)++ = tmp[1]; \ + *(ptr)++ = tmp[0]; \ +} +#elif defined(__LITTLE_ENDIAN__) +#define qrBmpWriteShort(ptr, n) { \ + uint16_t us = (uint16_t)((n) & 0xffffU); \ + qr_byte_t *tmp = (qr_byte_t *)&us; \ + *(ptr)++ = tmp[0]; \ + *(ptr)++ = tmp[1]; \ +} +#else +#define qrBmpWriteShort(ptr, n) { \ + *(ptr)++ = (n) & 0xffU; \ + *(ptr)++ = ((n) >> 8) & 0xffU; \ +} +#endif + +#if defined(__BIG_ENDIAN__) +#define qrBmpWriteLong(ptr, n) { \ + uint32_t ul = (uint32_t)(n); \ + qr_byte_t *tmp = (qr_byte_t *)&ul; \ + *(ptr)++ = tmp[3]; \ + *(ptr)++ = tmp[2]; \ + *(ptr)++ = tmp[1]; \ + *(ptr)++ = tmp[0]; \ +} +#elif defined(__LITTLE_ENDIAN__) +#define qrBmpWriteLong(ptr, n) { \ + uint32_t ul = (uint32_t)(n); \ + qr_byte_t *tmp = (qr_byte_t *)&ul; \ + *(ptr)++ = tmp[0]; \ + *(ptr)++ = tmp[1]; \ + *(ptr)++ = tmp[2]; \ + *(ptr)++ = tmp[3]; \ +} +#else +#define qrBmpWriteLong(ptr, n) { \ + *(ptr)++ = (n) & 0xffU; \ + *(ptr)++ = ((n) >> 8) & 0xffU; \ + *(ptr)++ = ((n) >> 16) & 0xffU; \ + *(ptr)++ = ((n) >> 24) & 0xffU; \ +} +#endif + +#define qrBmpNextPixel() { \ + if (pxshift == 0) { \ + rptr++; \ + pxshift = 7; \ + } else { \ + pxshift--; \ + } \ +} + +/* }}} */ +/* {{{ function prototypes */ + +static qr_byte_t * +qrBmpWriteHeader(qr_byte_t *bof, int size, int width, int height, int imagesize); + +/* }}} */ +/* {{{ qrSymbolToBMP() */ + +/* + * 生成されたQRコードシンボルをモノクロ2値の + * Windows Bitmap(BMP)に変換する + */ +QR_API qr_byte_t * +qrSymbolToBMP(QRCode *qr, int sep, int mag, int *size) +{ + qr_byte_t *rbuf, *rptr; + qr_byte_t *sbuf, *sptr; + int rsize, rmod, imgsize; + int sepskips, pxshift; + int i, j, ix, jx, dim, imgdim, sepdim; + + QRCNV_CHECK_STATE(); + QRCNV_GET_SIZE(); + + /* + * 変換後のサイズを計算し、メモリを確保する + */ + rsize = (imgdim + 7) / 8; + if ((rmod = (rsize % 4)) != 0) { + rsize += 4 - rmod; + } + imgsize = rsize * imgdim; + *size = QRCNV_BMP_OFFBITS + imgsize; + QRCNV_MALLOC(rsize, *size); + + /* + * ヘッダを書き込む + */ + sptr = qrBmpWriteHeader(sbuf, *size, imgdim, imgdim, imgsize); + + /* + * シンボルを書き込む + */ + sepskips = rsize * sepdim; + /* 分離パターン (下) */ + if (sepskips) { + memset(sptr, 0, (size_t)sepskips); + sptr += sepskips; + } + for (i = dim - 1; i >= 0; i--) { + memset(rbuf, 0, (size_t)rsize); + pxshift = 7; + rptr = rbuf; + /* 分離パターン (左) */ + for (j = 0; j < sepdim; j++) { + qrBmpNextPixel(); + } + /* シンボル本体 */ + for (j = 0; j < dim; j++) { + if (qrIsBlack(qr, i, j)) { + for (jx = 0; jx < mag; jx++) { + *rptr |= 1 << pxshift; + qrBmpNextPixel(); + } + } else { + for (jx = 0; jx < mag; jx++) { + qrBmpNextPixel(); + } + } + } + /* 行をmag回繰り返し書き込む */ + for (ix = 0; ix < mag; ix++) { + memcpy(sptr, rbuf, (size_t)rsize); + sptr += rsize; + } + } + /* 分離パターン (上) */ + if (sepskips) { + memset(sptr, 0, (size_t)sepskips); + sptr += sepskips; + } + + free(rbuf); + + return sbuf; +} + +/* }}} */ +/* {{{ qrsSymbolsToBMP() */ + +/* + * 構造的連接用qrSymbolToBMP() + */ +QR_API qr_byte_t * +qrsSymbolsToBMP(QRStructured *st, int sep, int mag, int order, int *size) +{ + QRCode *qr = st->cur; + qr_byte_t *rbuf, *rptr; + qr_byte_t *sbuf, *sptr; + int rsize, rmod, imgsize; + int sepskips, pxshift; + int i, j, k, ix, jx, kx; + int cols, rows, pos, xdim, ydim, zdim; + int dim, imgdim, sepdim; + + QRCNV_SA_CHECK_STATE(); + QRCNV_SA_IF_ONE(qrSymbolToBMP); + QRCNV_SA_GET_SIZE(); + + /* + * 変換後のサイズを計算し、メモリを確保する + */ + rsize = (xdim + 7) / 8; + if ((rmod = (rsize % 4)) != 0) { + rsize += 4 - rmod; + } + imgsize = rsize * ydim; + *size = QRCNV_BMP_OFFBITS + imgsize; + QRCNV_MALLOC(rsize, *size); + + /* + * ヘッダを書き込む + */ + sptr = qrBmpWriteHeader(sbuf, *size, xdim, ydim, imgsize); + + /* + * シンボルを書き込む + */ + sepskips = rsize * sepdim; + for (k = rows - 1; k >= 0; k--) { + /* 分離パターン (下) */ + if (sepskips) { + memset(sptr, 0, (size_t)sepskips); + sptr += sepskips; + } + for (i = dim - 1; i >= 0; i--) { + memset(rbuf, 0, (size_t)rsize); + pxshift = 7; + rptr = rbuf; + for (kx = 0; kx < cols; kx++) { + /* 分離パターン (左) */ + for (j = 0; j < sepdim; j++) { + qrBmpNextPixel(); + } + /* シンボル本体 */ + if (order < 0) { + pos = k + rows * kx; + } else { + pos = cols * k + kx; + } + if (pos >= st->num) { + break; + } + for (j = 0; j < dim; j++) { + if (qrIsBlack(st->qrs[pos], i, j)) { + for (jx = 0; jx < mag; jx++) { + *rptr |= 1 << pxshift; + qrBmpNextPixel(); + } + } else { + for (jx = 0; jx < mag; jx++) { + qrBmpNextPixel(); + } + } + } + } + /* 行をmag回繰り返し書き込む */ + for (ix = 0; ix < mag; ix++) { + memcpy(sptr, rbuf, (size_t)rsize); + sptr += rsize; + } + } + } + /* 分離パターン (上) */ + if (sepskips) { + memset(sptr, 0, (size_t)sepskips); + sptr += sepskips; + } + + free(rbuf); + + return sbuf; +} + +/* }}} */ +/* {{{ qrBmpWriteHeader() */ + +static qr_byte_t * +qrBmpWriteHeader(qr_byte_t *bof, int size, int width, int height, int imagesize) +{ + qr_byte_t *ptr; + + ptr = bof; + + /* + * BITMAPFILEHEADER + */ + *ptr++ = 'B'; /* bfType */ + *ptr++ = 'M'; /* bfType */ + qrBmpWriteLong(ptr, size); /* bfSize */ + qrBmpWriteShort(ptr, 0); /* bfReserved1 */ + qrBmpWriteShort(ptr, 0); /* bfReserved2 */ + qrBmpWriteLong(ptr, QRCNV_BMP_OFFBITS); /* bfOffBits */ + + /* + * BMPINFOHEADER + */ + qrBmpWriteLong(ptr, QRCNV_BMP_BISIZE); /* biSize */ + qrBmpWriteLong(ptr, width); /* biWidth */ + qrBmpWriteLong(ptr, height); /* biHeight */ + qrBmpWriteShort(ptr, 1); /* biPlanes */ + qrBmpWriteShort(ptr, 1); /* biBitCount - 1 bit per pixel */ + qrBmpWriteLong(ptr, 0); /* biCopmression - BI_RGB */ + qrBmpWriteLong(ptr, imagesize); /* biSizeImage */ + qrBmpWriteLong(ptr, QRCNV_BMP_PPM); /* biXPixPerMeter */ + qrBmpWriteLong(ptr, QRCNV_BMP_PPM); /* biYPixPerMeter */ + qrBmpWriteLong(ptr, 2); /* biClrUsed */ + qrBmpWriteLong(ptr, 2); /* biCirImportant */ + + /* + * RGBQUAD - white + */ + *ptr++ = 255; /* rgbBlue */ + *ptr++ = 255; /* rgbGreen */ + *ptr++ = 255; /* rgbRed */ + *ptr++ = 0; /* rgbReserved */ + + /* + *RGBQUAD - black + */ + *ptr++ = 0; /* rgbBlue */ + *ptr++ = 0; /* rgbGreen */ + *ptr++ = 0; /* rgbRed */ + *ptr++ = 0; /* rgbReserved */ + + return ptr; +} + +/* }}} */ diff --git a/kvm_system/main/lib/oled_ctrl/oled_ctrl.cpp b/kvm_system/main/lib/oled_ctrl/oled_ctrl.cpp new file mode 100644 index 0000000..994edc4 --- /dev/null +++ b/kvm_system/main/lib/oled_ctrl/oled_ctrl.cpp @@ -0,0 +1,682 @@ +#include "oled_ctrl.h" + +using namespace maix; +using namespace maix::sys; +using namespace maix::peripheral; +i2c::I2C oled_alpha(1, i2c::Mode::MASTER); +i2c::I2C oled_beta(5, i2c::Mode::MASTER); + +uint8_t OLED_state = 0; +uint8_t kvm_hw_ver = 0; + +/* mode = OLED_CMD + * = OLED_DATA */ +void oled_write_register(uint8_t mode, uint8_t data) +{ + if(OLED_state){ + uint8_t buf[2]; + + buf[0] = mode; + buf[1] = data; + if(kvm_hw_ver == 0){ + if(oled_alpha.writeto(OLED_ADDR, buf, 2) == (int)-err::Err::ERR_IO){ + return; + } + } else if(kvm_hw_ver == 1){ + if(oled_beta.writeto(OLED_ADDR, buf, 2) == (int)-err::Err::ERR_IO){ + return; + } + } else if(kvm_hw_ver == 2){ + if(oled_beta.writeto(OLED_PCIe_ADDR, buf, 2) == (int)-err::Err::ERR_IO){ + return; + } + } + return; + } + return; +} + +int oled_exist(void) +{ + // gpio::GPIO oled_rst("GPIOP19", gpio::Mode::OUT, gpio::Pull::PULL_UP); + // oled_rst.high(); + // system("devmem 0x030010D4 32 0x3"); + // system("devmem 0x030010D0 32 0x2"); + // system("devmem 0x030010DC 32 0x2"); + + if(access("/etc/kvm/hw", F_OK) == 0){ + uint8_t RW_Data[2]; + FILE *fp = fopen("/etc/kvm/hw", "r"); + fread(RW_Data, sizeof(char), 2, fp); + fclose(fp); + if(RW_Data[0] == 'b') kvm_hw_ver = 1; + else if(RW_Data[0] == 'p') kvm_hw_ver = 2; + } + + uint8_t buf[2]; + + buf[0] = OLED_CMD; + buf[1] = 0xAE; + if(kvm_hw_ver == 0){ + if(oled_alpha.writeto(OLED_ADDR, buf, 2) == (int)-err::Err::ERR_IO){ + return 0; + } + } else if(kvm_hw_ver == 1){ + printf("beta\r\n"); + if(oled_beta.writeto(OLED_ADDR, buf, 2) == (int)-err::Err::ERR_IO){ + return 0; + } + } else if(kvm_hw_ver == 2){ + printf("PCIe\r\n"); + if(oled_beta.writeto(OLED_PCIe_ADDR, buf, 2) == (int)-err::Err::ERR_IO){ + return 0; + } + } + return 1; +} + +// 坐标设置 +void OLED_Set_Pos(uint8_t x, uint8_t y) +{ + // oled_write_register(OLED_CMD, 0xb0+y); + // oled_write_register(OLED_CMD, ((x&0xf0)>>4)|0x10); + // oled_write_register(OLED_CMD, (x&0x0f)); + if(kvm_hw_ver == 2){ + x += 32; + y += 8; + } + oled_write_register(OLED_CMD, 0xb0+y); + oled_write_register(OLED_CMD, ((x&0xf0)>>4)|0x10); + oled_write_register(OLED_CMD, (x&0x0f)); +} + +//开启OLED显示 +void OLED_Display_On() +{ + oled_write_register(OLED_CMD, 0X8D); + oled_write_register(OLED_CMD, 0X14); + oled_write_register(OLED_CMD, 0XAF); +} + +//关闭OLED显示 +void OLED_Display_Off() +{ + oled_write_register(OLED_CMD, 0X8D); + oled_write_register(OLED_CMD, 0X10); + oled_write_register(OLED_CMD, 0XAE); +} + +//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!! +void OLED_Clear(void) +{ + uint8_t i,n; + for(i=0;i<8;i++) + { + oled_write_register(OLED_CMD, 0xb0+i); + oled_write_register(OLED_CMD, 0x00); + oled_write_register(OLED_CMD, 0x10); + for(n=0;n<128;n++)oled_write_register(OLED_DATA, 0x00); + } //更新显示 +} + +void OLED_Fill(void) +{ + uint8_t i,n; + for(i=0;i<8;i++) + { + oled_write_register(OLED_CMD, 0xb0+i); + oled_write_register(OLED_CMD, 0x00); + oled_write_register(OLED_CMD, 0x10); + for(n=0;n<128;n++)oled_write_register(OLED_DATA, 0xFF); + } //更新显示 +} + +//在指定位置显示一个字符,包括部分字符 +//x:0~127 +//y:0~63 +//sizey:选择字体 6x8 8x16 +void OLED_ShowChar(uint8_t x,uint8_t y,char chr,uint8_t sizey) +{ + uint8_t c=0,sizex=sizey/2; + uint16_t i=0,size1; + if(sizey==8)size1=6; + else if(sizey==4)size1=4; + else size1=(sizey/8+((sizey%8)?1:0))*(sizey/2); + c=chr-' ';//得到偏移后的值 + OLED_Set_Pos(x, y); + for(i=0; i +#include +#include +#include +#include + +#define OLED_DISABLE 0 +#define OLED_ENABLE 1 +#define OLED_ADDR 0x3D +#define OLED_PCIe_ADDR 0x3C +#define OLED_CMD 0x00 +#define OLED_DATA 0x40 + +#define HDMI_STATE 0x01 +#define HID_STATE 0x02 +#define ETH_STATE 0x04 +#define WIFI_STATE 0x08 + +#define KVM_INIT 0x00 +#define KVM_ETH_IP 0x01 +#define KVM_WIFI_IP 0x02 +#define KVM_HDMI_STATE 0x03 +#define KVM_HDMI_RES 0x04 +#define KVM_STEAM_TYPE 0x05 +#define KVM_STEAM_FPS 0x06 +#define KVM_JPG_QLTY 0x07 +#define KVM_CPU_IDLE 0x08 + +#define KVM_RES_none 0x00 +#define KVM_RES_480P 0x01 +#define KVM_RES_600P 0x02 +#define KVM_RES_720P 0x03 +#define KVM_RES_1080P 0x04 + +#define KVM_TYPE_none 0x00 +#define KVM_TYPE_MJPG 0x01 +#define KVM_TYPE_H264 0x02 + +#define AlignRightEND 127 +#define AlignRightEND_P 63 + +extern uint8_t OLED_state; +extern uint8_t kvm_hw_ver; + +/************************************6*8的点阵************************************/ +const uint8_t oled_asc2_0806[][6] ={ +{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// sp +{0x00, 0x00, 0x00, 0x2f, 0x00, 0x00},// ! +{0x00, 0x00, 0x07, 0x00, 0x07, 0x00},// " +{0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14},// # +{0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12},// $ +{0x00, 0x23, 0x13, 0x08, 0x64, 0x62},// % +{0x00, 0x36, 0x49, 0x55, 0x22, 0x50},// & +{0x00, 0x00, 0x05, 0x03, 0x00, 0x00},// ' +{0x00, 0x00, 0x1c, 0x22, 0x41, 0x00},// ( +{0x00, 0x00, 0x41, 0x22, 0x1c, 0x00},// ) +// {0x00, 0x14, 0x08, 0x3E, 0x08, 0x14},// * +{0x00, 0x00, 0x28, 0x10, 0x28, 0x00},// *->x +{0x00, 0x08, 0x08, 0x3E, 0x08, 0x08},// + +{0x00, 0x00, 0x00, 0xA0, 0x60, 0x00},// , +{0x00, 0x08, 0x08, 0x08, 0x08, 0x08},// - +{0x00, 0x00, 0x60, 0x60, 0x00, 0x00},// . +{0x00, 0x20, 0x10, 0x08, 0x04, 0x02},// / +{0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E},// 0 +{0x00, 0x00, 0x42, 0x7F, 0x40, 0x00},// 1 +{0x00, 0x42, 0x61, 0x51, 0x49, 0x46},// 2 +{0x00, 0x21, 0x41, 0x45, 0x4B, 0x31},// 3 +{0x00, 0x18, 0x14, 0x12, 0x7F, 0x10},// 4 +{0x00, 0x27, 0x45, 0x45, 0x45, 0x39},// 5 +{0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30},// 6 +{0x00, 0x01, 0x71, 0x09, 0x05, 0x03},// 7 +{0x00, 0x36, 0x49, 0x49, 0x49, 0x36},// 8 +{0x00, 0x06, 0x49, 0x49, 0x29, 0x1E},// 9 +{0x00, 0x00, 0x36, 0x36, 0x00, 0x00},// : +{0x00, 0x00, 0x56, 0x36, 0x00, 0x00},// ; +{0x00, 0x08, 0x14, 0x22, 0x41, 0x00},// < +{0x00, 0x14, 0x14, 0x14, 0x14, 0x14},// = +{0x00, 0x00, 0x41, 0x22, 0x14, 0x08},// > +{0x00, 0x02, 0x01, 0x51, 0x09, 0x06},// ? +{0x00, 0x32, 0x49, 0x59, 0x51, 0x3E},// @ +{0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C},// A +{0x00, 0x7F, 0x49, 0x49, 0x49, 0x36},// B +{0x00, 0x3E, 0x41, 0x41, 0x41, 0x22},// C +{0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C},// D +{0x00, 0x7F, 0x49, 0x49, 0x49, 0x41},// E +{0x00, 0x7F, 0x09, 0x09, 0x09, 0x01},// F +{0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A},// G +{0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F},// H +{0x00, 0x00, 0x41, 0x7F, 0x41, 0x00},// I +{0x00, 0x20, 0x40, 0x41, 0x3F, 0x01},// J +{0x00, 0x7F, 0x08, 0x14, 0x22, 0x41},// K +{0x00, 0x7F, 0x40, 0x40, 0x40, 0x40},// L +{0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F},// M +{0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F},// N +{0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E},// O +{0x00, 0x7F, 0x09, 0x09, 0x09, 0x06},// P +{0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E},// Q +{0x00, 0x7F, 0x09, 0x19, 0x29, 0x46},// R +{0x00, 0x46, 0x49, 0x49, 0x49, 0x31},// S +{0x00, 0x01, 0x01, 0x7F, 0x01, 0x01},// T +{0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F},// U +{0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F},// V +{0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F},// W +{0x00, 0x63, 0x14, 0x08, 0x14, 0x63},// X +{0x00, 0x07, 0x08, 0x70, 0x08, 0x07},// Y +{0x00, 0x61, 0x51, 0x49, 0x45, 0x43},// Z +{0x00, 0x00, 0x7F, 0x41, 0x41, 0x00},// [ +{0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55},// 55 +{0x00, 0x00, 0x41, 0x41, 0x7F, 0x00},// ] +{0x00, 0x04, 0x02, 0x01, 0x02, 0x04},// ^ +{0x00, 0x40, 0x40, 0x40, 0x40, 0x40},// _ +{0x00, 0x00, 0x01, 0x02, 0x04, 0x00},// ' +{0x00, 0x20, 0x54, 0x54, 0x54, 0x78},// a +{0x00, 0x7F, 0x48, 0x44, 0x44, 0x38},// b +{0x00, 0x38, 0x44, 0x44, 0x44, 0x20},// c +{0x00, 0x38, 0x44, 0x44, 0x48, 0x7F},// d +{0x00, 0x38, 0x54, 0x54, 0x54, 0x18},// e +{0x00, 0x08, 0x7E, 0x09, 0x01, 0x02},// f +{0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C},// g +{0x00, 0x7F, 0x08, 0x04, 0x04, 0x78},// h +{0x00, 0x00, 0x44, 0x7D, 0x40, 0x00},// i +{0x00, 0x40, 0x80, 0x84, 0x7D, 0x00},// j +{0x00, 0x7F, 0x10, 0x28, 0x44, 0x00},// k +{0x00, 0x00, 0x41, 0x7F, 0x40, 0x00},// l +{0x00, 0x7C, 0x04, 0x18, 0x04, 0x78},// m +{0x00, 0x7C, 0x08, 0x04, 0x04, 0x78},// n +{0x00, 0x38, 0x44, 0x44, 0x44, 0x38},// o +{0x00, 0xFC, 0x24, 0x24, 0x24, 0x18},// p +{0x00, 0x18, 0x24, 0x24, 0x18, 0xFC},// q +{0x00, 0x7C, 0x08, 0x04, 0x04, 0x08},// r +{0x00, 0x48, 0x54, 0x54, 0x54, 0x20},// s +{0x00, 0x04, 0x3F, 0x44, 0x40, 0x20},// t +{0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C},// u +{0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C},// v +{0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C},// w +{0x00, 0x44, 0x28, 0x10, 0x28, 0x44},// x +{0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C},// y +{0x00, 0x44, 0x64, 0x54, 0x4C, 0x44},// z +{0x14, 0x14, 0x14, 0x14, 0x14, 0x14},// horiz lines + +}; + +const uint8_t oled_asc2_0804[][4] ={ +{0x00,0x00,0x00,0x00},// sp +{0x7c,0x52,0x7c,0x00},// ! +{0x00,0x0c,0x00,0x0c},// " +{0x00,0x7c,0x28,0x7c},// # +{0x00,0x5c,0x5e,0x74},// $ +{0x6c,0x30,0x18,0x6c},// % +{0x00,0x68,0x54,0x68},// & +{0x00,0x00,0x0c,0x00},// ' +{0x00,0x38,0x44,0x00},// ( +{0x00,0x44,0x38,0x00},// ) +{0x00,0x00,0x30,0x00},// * +{0x00,0x10,0x38,0x10},// + +{0x00,0x00,0x60,0x00},// , +{0x00,0x10,0x10,0x10},// - +{0x00,0x00,0x40,0x00},// . +{0x00,0x40,0x38,0x04},// / +{0x00,0x7c,0x44,0x7c},// 0 +{0x00,0x44,0x7c,0x40},// 1 +{0x00,0x74,0x54,0x5c},// 2 +{0x00,0x54,0x54,0x7c},// 3 +{0x00,0x1c,0x10,0x7c},// 4 +{0x00,0x5c,0x54,0x74},// 5 +{0x00,0x7c,0x54,0x74},// 6 +{0x00,0x04,0x04,0x7c},// 7 +{0x00,0x7c,0x54,0x7c},// 8 +{0x00,0x5c,0x54,0x7c},// 9 +{0x00,0x00,0x28,0x00},// : +{0x00,0x40,0x28,0x00},// ; +{0x00,0x10,0x28,0x44},// < +{0x00,0x28,0x28,0x28},// = +{0x00,0x44,0x28,0x10},// > +{0x00,0x04,0x54,0x0c},// ? +{0x38,0x64,0x54,0x78},// @ +{0x00,0x78,0x14,0x78},// A +{0x00,0x7c,0x54,0x38},// B +{0x00,0x38,0x44,0x44},// C +{0x00,0x7c,0x44,0x38},// D +{0x00,0x7c,0x54,0x54},// E +{0x00,0x7c,0x14,0x14},// F +{0x00,0x6c,0x54,0x74},// G +{0x00,0x7c,0x10,0x7c},// H +{0x00,0x44,0x7c,0x44},// I +{0x00,0x44,0x7c,0x04},// J +{0x00,0x7c,0x10,0x6c},// K +{0x00,0x7c,0x40,0x40},// L +{0x00,0x7c,0x18,0x7c},// M +{0x00,0x6c,0x18,0x74},// N +{0x00,0x38,0x44,0x38},// O +{0x00,0x7c,0x14,0x1c},// P +{0x00,0x3c,0x24,0x7c},// Q +{0x00,0x7c,0x14,0x6c},// R +{0x00,0x58,0x54,0x64},// S +{0x00,0x04,0x7c,0x04},// T +{0x00,0x3c,0x40,0x7c},// U +{0x00,0x3c,0x60,0x3c},// V +{0x00,0x7c,0x30,0x7c},// W +{0x00,0x6c,0x10,0x6c},// X +{0x00,0x0c,0x70,0x0c},// Y +{0x00,0x64,0x54,0x4c},// Z +{0x00,0x7c,0x44,0x00},// [ +{0x28,0x54,0x28,0x54},// 55 +{0x00,0x44,0x7c,0x00},// ] +}; + +//16*16 ASCII字符集点阵 +const uint8_t oled_asc2_1608[][16]={ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/ +{0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00},/*"!",1*/ +{0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",2*/ +{0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00},/*"#",3*/ +{0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00},/*"$",4*/ +{0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00},/*"%",5*/ +{0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10},/*"&",6*/ +{0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/ +{0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00},/*"(",8*/ +{0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00},/*")",9*/ +{0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00},/*"*",10*/ +{0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00},/*"+",11*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00},/*",",12*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01},/*"-",13*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00},/*".",14*/ +{0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00},/*"/",15*/ +{0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00},/*"0",16*/ +{0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"1",17*/ +{0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00},/*"2",18*/ +{0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00},/*"3",19*/ +{0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00},/*"4",20*/ +{0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00},/*"5",21*/ +{0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00},/*"6",22*/ +{0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00},/*"7",23*/ +{0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00},/*"8",24*/ +{0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00},/*"9",25*/ +{0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00},/*":",26*/ +{0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00},/*";",27*/ +{0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00},/*"<",28*/ +{0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00},/*"=",29*/ +{0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00},/*">",30*/ +{0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00},/*"?",31*/ +{0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00},/*"@",32*/ +{0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20},/*"A",33*/ +{0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00},/*"B",34*/ +{0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00},/*"C",35*/ +{0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00},/*"D",36*/ +{0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00},/*"E",37*/ +{0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00},/*"F",38*/ +{0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00},/*"G",39*/ +{0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20},/*"H",40*/ +{0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"I",41*/ +{0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00},/*"J",42*/ +{0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00},/*"K",43*/ +{0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00},/*"L",44*/ +{0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00},/*"M",45*/ +{0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00},/*"N",46*/ +{0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00},/*"O",47*/ +{0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00},/*"P",48*/ +{0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00},/*"Q",49*/ +{0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20},/*"R",50*/ +{0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00},/*"S",51*/ +{0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00},/*"T",52*/ +{0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00},/*"U",53*/ +{0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00},/*"V",54*/ +{0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00},/*"W",55*/ +{0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20},/*"X",56*/ +{0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00},/*"Y",57*/ +{0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00},/*"Z",58*/ +{0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00},/*"[",59*/ +{0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00},/*"\",60*/ +{0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00},/*"]",61*/ +{0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"^",62*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80},/*"_",63*/ +{0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/ +{0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20},/*"a",65*/ +{0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00},/*"b",66*/ +{0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00},/*"c",67*/ +{0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20},/*"d",68*/ +{0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00},/*"e",69*/ +{0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"f",70*/ +{0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00},/*"g",71*/ +{0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20},/*"h",72*/ +{0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"i",73*/ +{0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00},/*"j",74*/ +{0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00},/*"k",75*/ +{0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"l",76*/ +{0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F},/*"m",77*/ +{0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20},/*"n",78*/ +{0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00},/*"o",79*/ +{0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00},/*"p",80*/ +{0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80},/*"q",81*/ +{0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00},/*"r",82*/ +{0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00},/*"s",83*/ +{0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00},/*"t",84*/ +{0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20},/*"u",85*/ +{0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00},/*"v",86*/ +{0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00},/*"w",87*/ +{0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00},/*"x",88*/ +{0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00},/*"y",89*/ +{0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00},/*"z",90*/ +{0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40},/*"{",91*/ +{0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00},/*"|",92*/ +{0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00},/*"}",93*/ +{0x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"~",94*/ +}; + +// [!] +const uint8_t etherror[6] +{0x00,0x3e,0x7f,0x51,0x7f,0x3e}; // [!] + +//6*xx 图标点阵 +const uint8_t oled_kvm_0621[][21]{ +{0x00,0x3e,0x08,0x08,0x3e,0x00,0x3e,0x22,0x22,0x1c,0x00,0x3c,0x02,0x0c,0x02,0x3c,0x00,0x22,0x3e,0x22,0x00},/*"HDMI=0",0*,21*/ +{0x3e,0x41,0x77,0x77,0x41,0x7f,0x41,0x5d,0x5d,0x63,0x7f,0x43,0x7d,0x73,0x7d,0x43,0x7f,0x5d,0x41,0x5d,0x3e},/*"HDMI=1",0*,21*/ +{0x00,0x3e,0x08,0x08,0x3e,0x00,0x22,0x3e,0x20,0x00,0x3e,0x22,0x22,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"USB=0",0, 15*/ +{0x3e,0x41,0x77,0x77,0x41,0x7f,0x5d,0x41,0x5f,0x7f,0x41,0x5d,0x5d,0x63,0x3e,0x00,0x00,0x00,0x00,0x00,0x00},/*"USB=1",1, 15*/ +{0x00,0x3e,0x2a,0x2a,0x22,0x00,0x02,0x3e,0x02,0x00,0x3e,0x08,0x08,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"ETH=0",1, 15*/ +{0x3e,0x41,0x55,0x55,0x5d,0x7f,0x7d,0x41,0x7d,0x7f,0x41,0x77,0x77,0x41,0x3e,0x00,0x00,0x00,0x00,0x00,0x00},/*"ETH=1",1, 15*/ +{0x00,0x1e,0x20,0x18,0x20,0x1e,0x00,0x3a,0x00,0x3e,0x0a,0x0a,0x00,0x3a,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"WiFi=0",1, 15*/ +{0x3e,0x61,0x5f,0x67,0x5f,0x61,0x7f,0x45,0x7f,0x41,0x75,0x75,0x7f,0x45,0x3e,0x00,0x00,0x00,0x00,0x00,0x00},/*"WiFi=1",1, 15*/ +}; +const uint8_t oled_kvm_logo[116] = +{ + 0xf8,0x1f,0xfc,0x3f,0xf6,0x67,0x06,0x60,0xce,0x6f,0x3e,0x7f,0xfe,0x7c,0xf6,0x73,0x06,0x60,0xe6,0x6f, + 0xfe,0x7f,0xfe,0x71,0xfe,0x6e,0xfe,0x6e,0xfe,0x61,0xfe,0x7f,0xfe,0x60,0xfe,0x7e,0xfe,0x7e,0xfe,0x60, + 0xfe,0x7f,0xfe,0x71,0xfe,0x6e,0xfe,0x6e,0xfe,0x71,0xfe,0x7f,0xf6,0x6f,0x06,0x60,0x76,0x6f,0x3e,0x7e, + 0x8e,0x79,0xe6,0x63,0xfe,0x6f,0xf6,0x7f,0x06,0x7f,0x7e,0x78,0xfe,0x63,0xfe,0x79,0x3e,0x7e,0x86,0x7f, + 0xf6,0x6f,0x7e,0x60,0x86,0x6f,0x86,0x7f,0x7e,0x7c,0x86,0x7f,0x86,0x6f,0x7e,0x60,0xfe,0x6f,0xfc,0x3f, + 0xf8,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x3f,0xfc,0x3f +}; +const uint8_t oled_sipeed_logo[32] = { +0x00,0x00,0xf8,0x1f,0xfc,0x3f,0xf6,0x7f,0xb2,0x7f,0x1e,0x67,0x0e,0x66,0x66,0x66, +0x66,0x66,0x66,0x66,0x66,0x70,0xfe,0x78,0xfe,0x7d,0xfc,0x3f,0xf8,0x1f,0x00,0x00 +}; +int oled_exist(void); +void OLED_Clear(void); +void OLED_Fill(void); +void OLED_Init(void); +void OLED_Revolve(void); +void OLED_ShowState(uint8_t x,uint8_t y,char chr,uint8_t size); +void OLED_DisplayTurn(uint8_t i); +void OLED_ColorTurn(uint8_t i); +void OLED_ShowError(uint8_t x,uint8_t y,uint8_t _state); +void OLED_ShowCharTurn(uint8_t x,uint8_t y,char chr,uint8_t sizey); +void OLED_ShowNum(uint8_t x, uint8_t y, uint8_t num, uint8_t len, uint8_t sizey); +void OLED_ShowString(uint8_t x, uint8_t y, char *chr, uint8_t sizey); +void OLED_ShowStringTurn(uint8_t x, uint8_t y, char *chr, uint8_t sizey); +void OLED_ShowStringtoend(uint8_t x, uint8_t y, char *chr, uint8_t sizey, uint8_t end); +void OLED_ShowString_AlignRight(uint8_t x_end, uint8_t y, char *chr, uint8_t size); +void OLED_ROW(uint8_t _EN); +void OLED_ShowLogo(); +void OLED_ShowSipeedLogo(); +void OLED_Showline(); +void OLED_Showline_1(); +void OLED_ShowIMG(uint8_t x,uint8_t y,char *chr,uint8_t width,uint8_t height); +void OLED_ShowKVMStreamState(uint8_t kvm_state_s, void* pdata); +void OLED_Show_Res(uint16_t _w, uint16_t _h); +void OLED_ShowKVMState(uint8_t _Interface, int8_t _EN); +void OLED_Show_Network_Error(uint8_t _state); + +#endif // OLED_CTRL_H_ \ No newline at end of file diff --git a/kvm_system/main/lib/oled_ui/oled_ui.cpp b/kvm_system/main/lib/oled_ui/oled_ui.cpp new file mode 100644 index 0000000..74923fd --- /dev/null +++ b/kvm_system/main/lib/oled_ui/oled_ui.cpp @@ -0,0 +1,506 @@ +#include "oled_ui.h" + +using namespace maix; +using namespace maix::sys; + +extern kvm_sys_state_t kvm_sys_state; +extern kvm_oled_state_t kvm_oled_state; + +void kvm_init_cube_ui(void) +{ + uint8_t temp; + char* str_temp = "192.168.1.243"; + + OLED_Clear(); + // OLED_Revolve(); + OLED_ShowLogo(); + OLED_ShowSipeedLogo(); + OLED_ShowKVMState(HDMI_STATE, 0); + OLED_ShowKVMState(HID_STATE, 0); + OLED_ShowKVMState(ETH_STATE, 0); + OLED_ShowKVMState(WIFI_STATE, 0); + OLED_Showline(); + OLED_ShowKVMStreamState(KVM_INIT, &temp); + temp = 0; + OLED_ShowKVMStreamState(KVM_ETH_IP, &temp); + temp = KVM_RES_none; + OLED_ShowKVMStreamState(KVM_HDMI_RES, &temp); + temp = KVM_TYPE_none; + OLED_ShowKVMStreamState(KVM_STEAM_TYPE, &temp); + temp = 0; + OLED_ShowKVMStreamState(KVM_STEAM_FPS, &temp); + temp = 80; + OLED_ShowKVMStreamState(KVM_JPG_QLTY, &temp); +} + +void kvm_init_pcie_ui(void) +{ + OLED_Revolve(); + OLED_Showline_1(); + OLED_ShowSipeedLogo(); + OLED_ShowKVMState(HDMI_STATE, 0); + OLED_ShowKVMState(HID_STATE, 0); + OLED_ShowKVMState(ETH_STATE, 0); + OLED_ShowKVMState(WIFI_STATE, 0); + + // OLED_ShowString(0, 2, "!192.168.222.197", 4); + // OLED_ShowString(1, 2, " 192.168.2.197", 4); + // OLED_ShowString(1, 3, "1920*1080", 4); + // OLED_ShowString(41, 3, " FPS", 4); + + // OLED_ShowString_AlignRight(AlignRightEND_P, 2, "192.168.0.69", 4); + // OLED_ShowString_AlignRight(37, 3, "1920*1080", 4); + OLED_ShowString_AlignRight(AlignRightEND_P, 3, " FPS", 4); + // OLED_ShowString(0, 3, "\"ABCDEFGHIJKLMMN\'", 4); + // OLED_ShowString(5, 2, "1", 4); +} + +void kvm_init_ui(void) +{ + if(kvm_hw_ver != 2){ + kvm_init_cube_ui(); + } else { + kvm_init_pcie_ui(); + } +} + +void qrcode_to_oled(QRCode *qr) +{ + char *p_oled_data; + uint16_t count = 0; + uint8_t bit; + uint8_t begin_x = 2; + uint8_t begin_y = 2; + p_oled_data = (char *)malloc( 132 * sizeof(char)); + if(p_oled_data != NULL){ + // fill + for(int i = 0; i < 132; i++){ + p_oled_data[i] = 0xFF; + } + // i | ; j - + for(int i = 0; i < 29; i++){ + for(int j = 0; j < 29; j++){ + if(qrIsBlacke(qr, i, j)){ + // 敲黑点 + uint16_t data_index = ((i+begin_y)/8)*33+(j+begin_x); + uint8_t mask = ~(0x01 << ((i+begin_y)%8)); + p_oled_data[data_index] &= mask; + } + } + } + OLED_Fill(); + OLED_ShowIMG(29, 0, p_oled_data, 33, 4); + free(p_oled_data); + } +} + +int qrencode(char *string) +{ + // test: qrencode("WIFI:T:WPA2;S:NanoKVM;P:12345678;;"); + int errcode = QR_ERR_NONE; + QRCode* p = qrInit(3, QR_EM_8BIT, 1, 4, &errcode); + if (p == NULL) { + printf("error\n"); + return -1; + } + qrAddData(p, (const qr_byte_t*)string, strlen(string)); + if (!qrFinalize(p)) { + printf("finalize error\n"); + return -1; + } + + qrcode_to_oled(p); + if(string[0] == 'W'){ + OLED_ShowStringTurn(3, 1, "WiFi", 8); + OLED_ShowStringTurn(3, 2, "AP:", 8); + } else if(string[0] == 'h'){ + if(string[7] == '1'){ + OLED_ShowStringTurn(3, 1, "Web:", 8); + } else if(string[8] == 'w'){ + OLED_ShowStringTurn(3, 1, "WiKi", 8); + } + } + int size = 0; + // width = height = qr_vertable[version] * mag + sep * mag * 2 + qr_byte_t * buffer = qrSymbolToBMP(p, 5, 5, &size); + if (buffer == NULL) { + printf("error %s", qrGetErrorInfo(p)); + return -1; + } + ofstream f("/etc/kvm/wifi_config.bmp"); + if (f.fail()) { + return -1; + } + f.write((const char *)buffer, size); + f.close(); + return 0; +} + +ip_addr_t show_which_ip(void) +{ + if(kvm_sys_state.wifi_state == -2) return ETH_IP; + static uint8_t run_count = 0; + static ip_addr_t ip_type = ETH_IP; + run_count++; + if(run_count > IP_Change_time/STATE_DELAY){ + run_count = 0; + switch(ip_type){ + case ETH_IP: + ip_type = WiFi_IP; + break; + case WiFi_IP: + ip_type = ETH_IP; + break; + default: + ip_type = ETH_IP; + } + } + // printf("show_which_ip? %d\n", ip_type); + return ip_type; +} + +uint8_t ip_changed(ip_addr_t ip_type) +{ + uint8_t *kvm_sys_ip; + uint8_t *kvm_oled_ip; + uint8_t ret; + if(ip_type == ETH_IP){ + kvm_sys_ip = kvm_sys_state.eth_addr; + kvm_oled_ip = kvm_oled_state.eth_addr; + } else if(ip_type == WiFi_IP){ + kvm_sys_ip = kvm_sys_state.wifi_addr; + kvm_oled_ip = kvm_oled_state.wifi_addr; + } else ret = 0; + for (int i = 0; i < 16; i++){ + if(kvm_sys_ip[i] == 0) ret = 0; + if(kvm_sys_ip[i] != kvm_oled_ip[i]) ret = 1; + } + if(ret == 1){ + memcpy(kvm_oled_ip, kvm_sys_ip, 16); + } + return ret; +} + +void kvm_eth_state_disp(ip_addr_t _ip_type, uint8_t first_disp) +{ + static ip_addr_t _ip_type_old = NULL_IP; + uint8_t temp; + // printf("[kvmd]eth_state = %d\n", kvm_sys_state.eth_state); + if( (kvm_oled_state.eth_state != kvm_sys_state.eth_state) || + (_ip_type_old != _ip_type) || + first_disp || ip_changed(ETH_IP)) + { + kvm_oled_state.eth_state = kvm_sys_state.eth_state; + _ip_type_old = _ip_type; + switch(kvm_oled_state.eth_state){ + case -1: + case 0: + temp = 0; + OLED_ShowKVMState(ETH_STATE, 0); + if(_ip_type == ETH_IP) + OLED_ShowKVMStreamState(KVM_ETH_IP, &temp); + break; + case 1: + OLED_ShowKVMState(ETH_STATE, 1); + if(_ip_type == ETH_IP) + OLED_ShowKVMStreamState(KVM_ETH_IP, &temp); + break; + case 2: + OLED_Show_Network_Error(1); + case 3: + OLED_Show_Network_Error(0); + OLED_ShowKVMState(ETH_STATE, 1); + if(_ip_type == ETH_IP) + OLED_ShowKVMStreamState(KVM_ETH_IP, kvm_sys_state.eth_addr); + break; + } + } +} + +void kvm_wifi_state_disp(ip_addr_t _ip_type, uint8_t first_disp) +{ + static ip_addr_t _ip_type_old = NULL_IP; + uint8_t temp; + // printf("[kvmd]wifi_state = %d\n", kvm_sys_state.wifi_state); + if( (kvm_oled_state.wifi_state != kvm_sys_state.wifi_state) || + (_ip_type_old != _ip_type) || + first_disp || ip_changed(WiFi_IP)) + { + kvm_oled_state.wifi_state = kvm_sys_state.wifi_state; + _ip_type_old = _ip_type; + switch(kvm_oled_state.wifi_state){ + case -2: + OLED_ShowKVMState(WIFI_STATE, -1); + break; + case -1: + case 0: + temp = 0; + OLED_ShowKVMState(WIFI_STATE, 0); + if(_ip_type == WiFi_IP) + OLED_ShowKVMStreamState(KVM_WIFI_IP, &temp); + break; + case 1: + OLED_ShowKVMState(WIFI_STATE, 1); + if(_ip_type == WiFi_IP){ + OLED_ShowKVMStreamState(KVM_WIFI_IP, kvm_sys_state.wifi_addr); + } + break; + } + } +} + +void kvm_usb_state_disp(uint8_t first_disp) +{ + if((kvm_oled_state.usb_state != kvm_sys_state.usb_state) || first_disp){ + kvm_oled_state.usb_state = kvm_sys_state.usb_state; + switch(kvm_oled_state.usb_state){ + case -1: + case 0: + OLED_ShowKVMState(HID_STATE, 0); + break; + case 1: + OLED_ShowKVMState(HID_STATE, 1); + break; + } + } +} + +void kvm_hdmi_state_disp(uint8_t first_disp) +{ + if((kvm_oled_state.hdmi_state != kvm_sys_state.hdmi_state) || first_disp){ + kvm_oled_state.hdmi_state = kvm_sys_state.hdmi_state; + switch(kvm_oled_state.hdmi_state){ + case -1: + case 0: + OLED_ShowKVMState(HDMI_STATE, 0); + break; + case 1: + OLED_ShowKVMState(HDMI_STATE, 1); + break; + } + } +} + +void kvm_fps_disp(uint8_t first_disp) +{ + if((kvm_oled_state.now_fps != kvm_sys_state.now_fps) || first_disp){ + kvm_oled_state.now_fps = kvm_sys_state.now_fps; + OLED_ShowKVMStreamState(KVM_STEAM_FPS, &kvm_oled_state.now_fps); + } +} + +void kvm_res_disp(uint8_t first_disp) +{ + if( (kvm_oled_state.hdmi_width != kvm_sys_state.hdmi_width) || \ + (kvm_oled_state.hdmi_height != kvm_sys_state.hdmi_height) || \ + first_disp ){ + kvm_oled_state.hdmi_width = kvm_sys_state.hdmi_width; + kvm_oled_state.hdmi_height = kvm_sys_state.hdmi_height; + OLED_Show_Res(kvm_sys_state.hdmi_width, kvm_sys_state.hdmi_height); + } +} + +void kvm_type_disp(uint8_t first_disp) +{ + if( (kvm_oled_state.type != kvm_sys_state.type) || first_disp){ + kvm_oled_state.type = kvm_sys_state.type; + OLED_ShowKVMStreamState(KVM_STEAM_TYPE, &kvm_oled_state.type); + } +} + +void kvm_qlty_disp(uint8_t first_disp) +{ + if( (kvm_oled_state.qlty != kvm_sys_state.qlty) || first_disp){ + kvm_oled_state.qlty = kvm_sys_state.qlty; + OLED_ShowKVMStreamState(KVM_JPG_QLTY, &kvm_sys_state.qlty); + } +} + +void kvm_main_disp(uint8_t first_disp) +{ + if(first_disp){ + OLED_Clear(); + kvm_init_ui(); + } +} + +void kvm_oled_clear(uint8_t subpage_changed) +{ + if(subpage_changed){ + OLED_Clear(); + } +} + +void kvm_main_ui_disp(uint8_t first_disp, uint8_t subpage_changed) +{ + ip_addr_t now_ip_type; + // if(kvm_oled_state.sub_page == 0) + // if(kvm_oled_state.oled_sleep_state == 1){ + if(kvm_oled_state.sub_page == 1){ + // main page (oled sleep) + kvm_oled_clear(first_disp || subpage_changed); + kvm_oled_state.oled_sleep_state = 1; + } else { + // main page + kvm_oled_state.oled_sleep_state = 0; + now_ip_type = show_which_ip(); + kvm_main_disp(first_disp || subpage_changed); + kvm_eth_state_disp(now_ip_type, first_disp || subpage_changed); + kvm_wifi_state_disp(now_ip_type, first_disp || subpage_changed); + kvm_usb_state_disp(first_disp || subpage_changed); + kvm_hdmi_state_disp(first_disp || subpage_changed); + kvm_fps_disp(first_disp || subpage_changed); + kvm_res_disp(first_disp || subpage_changed); + kvm_type_disp(first_disp || subpage_changed); + kvm_qlty_disp(first_disp || subpage_changed); + } +} + +uint8_t show_which_page() +{ + static uint8_t run_count = 0xfe; + static uint8_t show_type = 0; // 0 不动 1 QRcode; 2 text + if(sta_connect_ap()){ + if(ssid_pass_ok()){ + // + } + } + run_count++; + if(run_count > QR_Change_time/STATE_DELAY){ + run_count = 0; + if(show_type == 1) show_type = 2; + else show_type = 1; + return show_type; + } + return 0; +} + +void show_text_wifi_config(char *ap_ssid) +{ + OLED_Clear(); + OLED_ShowString(0, 0, "SSID:", 8); + OLED_ShowString_AlignRight(63, 1, "NanoKVM", 8); + OLED_ShowString(0, 2, "PASS:", 8); + OLED_ShowString_AlignRight(63, 3, ap_ssid, 8); +} + +void show_wifi_config_ip(void) +{ + OLED_Clear(); + get_ip_addr(WiFi_IP); + OLED_ShowString(0, 1, "Config IP:", 8); + OLED_ShowString_AlignRight(63, 2, (char*)kvm_sys_state.wifi_addr, 4); +} + +void show_wifi_config_QR(void) +{ + static char cmd[70]; + OLED_Clear(); + get_ip_addr(WiFi_IP); + printf("http://%s/#/wifi\n", kvm_sys_state.wifi_addr); + sprintf(cmd, "http://%s/#/wifi", kvm_sys_state.wifi_addr); + qrencode(cmd); +} + +void show_wifi_starting(void) +{ + OLED_Clear(); + OLED_ShowString(0, 1, "WiFi AP is", 8); + OLED_ShowString(0, 2, "Starting..", 8); +} + +void show_wifi_connecting(void) +{ + OLED_Clear(); + OLED_ShowString(0, 1, "WiFi", 8); + OLED_ShowString(0, 2, "Connect...", 8); +} + +void kvm_wifi_config_ui_disp(uint8_t first_disp, uint8_t subpage_changed) +{ + static char cmd[70]; + // printf("[kvmd]kvm_wifi_config_ui_disp %d | %d\n", first_disp, subpage_changed); + if(first_disp) kvm_start_wifi_config_process(); // 略有不妥,就这样吧 + if(first_disp || subpage_changed){ + switch(kvm_oled_state.sub_page){ + case 0: // wifi ap is starting + show_wifi_starting(); + break; + case 1: // QRcode + printf("WIFI:T:WPA2;S:NanoKVM;P:%s;;\n", kvm_sys_state.wifi_ap_pass); + sprintf(cmd, "WIFI:T:WPA2;S:NanoKVM;P:%s;;", kvm_sys_state.wifi_ap_pass); + qrencode(cmd); + break; + case 2: // Textcode + show_text_wifi_config(kvm_sys_state.wifi_ap_pass); + break; + case 3: // open IP with QR Code + show_wifi_config_QR(); + break; + case 4: // open IP + show_wifi_config_ip(); + break; + case 5: // Connecting... + show_wifi_connecting(); + break; + } + } + // switch(show_which_page()) +} + +void oled_auto_sleep_time_update(void) +{ + kvm_oled_state.oled_sleep_start = time::time_ms(); +} + +void oled_auto_sleep(void) +{ + uint8_t tmp8; + uint8_t sleep_close_signal = 0; + FILE *fp; + int file_size; + uint8_t RW_Data[10]; + if(access("/etc/kvm/oled_sleep", F_OK) == 0){ + fp = fopen("/etc/kvm/oled_sleep", "r"); + fseek(fp, 0, SEEK_END); + file_size = ftell(fp); + fseek(fp, 0, SEEK_SET); + fread(RW_Data, sizeof(char), file_size, fp); + fclose(fp); + if(file_size != 0){ + tmp8 = atoi((char*)RW_Data); + } else { + tmp8 = OLED_SLEEP_DELAY_DEFAULT; + } + if(tmp8 != kvm_oled_state.oled_sleep_param){ + // printf("/etc/kvm/oled_sleep = %d\n", tmp8); + kvm_oled_state.oled_sleep_param = tmp8; + if(kvm_oled_state.oled_sleep_param < OLED_SLEEP_DELAY_MIN){ + sleep_close_signal = 1; + } else { + // printf("oled_auto_sleep_time_update\n"); + oled_auto_sleep_time_update(); + } + } + } else { + if(kvm_oled_state.oled_sleep_param != 0){ + kvm_oled_state.oled_sleep_param = 0; + sleep_close_signal = 1; + } + } + + if(kvm_oled_state.page == 0){ + if(kvm_oled_state.oled_sleep_param < OLED_SLEEP_DELAY_MIN){ + if(sleep_close_signal == 1){ + kvm_sys_state.sub_page = 0; + } + } else { + if((time::time_ms() - kvm_oled_state.oled_sleep_start)/1000 >= kvm_oled_state.oled_sleep_param){ + // kvm_oled_state.oled_sleep_state = 1; + kvm_sys_state.sub_page = 1; + } else { + kvm_sys_state.sub_page = 0; + } + } + } +} diff --git a/kvm_system/main/lib/oled_ui/oled_ui.h b/kvm_system/main/lib/oled_ui/oled_ui.h new file mode 100644 index 0000000..329873e --- /dev/null +++ b/kvm_system/main/lib/oled_ui/oled_ui.h @@ -0,0 +1,11 @@ +#ifndef OLED_UI_H_ +#define OLED_UI_H_ +#include "config.h" +#include "oled_ctrl.h" + +void kvm_main_ui_disp(uint8_t first_disp, uint8_t subpage_changed); +void kvm_wifi_config_ui_disp(uint8_t first_disp, uint8_t subpage_changed); +void oled_auto_sleep_time_update(void); +void oled_auto_sleep(void); + +#endif // OLED_UI_H_ \ No newline at end of file diff --git a/kvm_system/main/lib/system_ctrl/system_ctrl.cpp b/kvm_system/main/lib/system_ctrl/system_ctrl.cpp new file mode 100644 index 0000000..c367deb --- /dev/null +++ b/kvm_system/main/lib/system_ctrl/system_ctrl.cpp @@ -0,0 +1,181 @@ +#include "system_ctrl.h" + +using namespace maix; +using namespace maix::sys; + +extern kvm_sys_state_t kvm_sys_state; +extern kvm_oled_state_t kvm_oled_state; + +void gen_hostapd_conf(char* ap_ssid) +{ + char file_data[300] = {0}; + FILE * fp; + sprintf(file_data, "ctrl_interface=/var/run/hostapd\nctrl_interface_group=0\nssid=NanoKVM\nhw_mode=g\nchannel=1\nbeacon_int=100\ndtim_period=2\nmax_num_sta=255\nrts_threshold=-1\nfragm_threshold=-1\nmacaddr_acl=0\nauth_algs=3\nwpa=2\nwpa_passphrase=%s\nieee80211n=1\n", ap_ssid); + fp = fopen("/etc/hostapd.conf", "w"); + fwrite(file_data, sizeof(file_data) , 1, fp ); + fclose(fp); +} + +void gen_udhcpd_conf() +{ + char file_data[300] = {0}; + FILE * fp; + sprintf(file_data, "start 10.10.10.100\nend 10.10.10.200\ninterface wlan0\npidfile /var/run/udhcpd.wlan0.pid\nlease_file /var/lib/misc/udhcpd.wlan0.leases\noption subnet 255.255.255.0\noption lease 864000\n"); + fp = fopen("/etc/udhcpd.wlan0.conf", "w"); + fwrite(file_data, sizeof(file_data) , 1, fp ); + fclose(fp); +} + +void gen_dnsmasq_conf() +{ + char file_data[300] = {0}; + FILE * fp; + sprintf(file_data, "bind-interfaces\ninterface=wlan0\ndhcp-range=10.10.10.2,10.10.10.254\naddress=/#/10.0.0.1\n"); + fp = fopen("/etc/udhcpd.wlan0.conf", "w"); + fwrite(file_data, sizeof(file_data) , 1, fp ); + fclose(fp); +} + +uint8_t sta_connect_ap(void) +{ + uint8_t RW_Data[10]; + FILE *fp; + fp = popen("hostapd_cli all sta | grep aid", "r"); + fgets((char*)RW_Data, 2, fp); + pclose(fp); + if(RW_Data[0] == 'a') return 1; + else return 0; +} + +uint8_t ssid_pass_ok(void) +{ + if(access("/kvmapp/kvm/wifi_try_connect", F_OK) == 0) return 1; + else return 0; +} + +uint8_t wifi_connected(void) +{ + uint8_t RW_Data[20]; + FILE *fp; + fp = popen("wpa_cli -i wlan0 status | grep \"wpa_state\"", "r"); + fgets((char*)RW_Data, 15, fp); + pclose(fp); + if(RW_Data[10] == 'S') return 0; + else if(RW_Data[10] == 'C') return 1; + else return 0; +} + +void kvm_start_wifi_config_process(void) +{ + if(kvm_sys_state.wifi_config_process == -1){ + // printf("[kvmw]开始配置wifi\n"); + kvm_sys_state.wifi_config_process = 0; + kvm_sys_state.sub_page = 0; + } +} + +void kvm_wifi_web_config_process() +{ + if(ssid_pass_ok()){ + system("rm /kvmapp/kvm/wifi_try_connect"); + system("/etc/init.d/S30wifi restart"); + kvm_sys_state.wifi_config_process = 3; + // 尝试连接wifi + if(kvm_sys_state.wifi_config_process == 3){ + // time::sleep_ms(WIFI_CONNECTION_DELAY); + if(wifi_connected()){ + // 连上了 + kvm_sys_state.wifi_config_process = -1; + } else { + // 没连上 + kvm_sys_state.wifi_config_process = 0; + } + } + } +} + +void kvm_wifi_config_process() +{ + int temp; + char ran_num; + static char cmd[70]; + switch(kvm_sys_state.wifi_config_process){ + case -1: + // printf("[kvms]Not in the process of configuring WiFi\n"); + break; + case 0: // 启动wifi + srand((unsigned)time::time_ms()); + for(temp = 0; temp < 4; temp++){ + do{ + ran_num = (char)rand()%10 + '0'; + if(temp == 0) break; + } while (ran_num == kvm_sys_state.wifi_ap_pass[(temp-1)*2]); + kvm_sys_state.wifi_ap_pass[temp*2] = ran_num; + kvm_sys_state.wifi_ap_pass[temp*2+1] = ran_num; + } + kvm_sys_state.wifi_ap_pass[8] = '\0'; + + sprintf(cmd, "echo %s > /kvmapp/kvm/ap.pass", kvm_sys_state.wifi_ap_pass); + system("echo NanoKVM > /kvmapp/kvm/ap.ssid"); + system(cmd); + system("/etc/init.d/S30wifi ap"); + + kvm_sys_state.wifi_config_process = 1; + kvm_sys_state.sub_page = 1; + break; + case 1: // 等待设备连接 + if(sta_connect_ap()){ + kvm_sys_state.wifi_config_process = 2; + kvm_sys_state.sub_page = 3; + } + break; + case 2: // 等待输入帐号密码 + if(ssid_pass_ok()){ + system("rm /kvmapp/kvm/wifi_try_connect"); + system("/etc/init.d/S30wifi restart"); + kvm_sys_state.wifi_config_process = 3; + kvm_sys_state.sub_page = 5; + } + break; + case 3: // 尝试连接wifi + time::sleep_ms(WIFI_CONNECTION_DELAY); + if(wifi_connected()){ + // 连上了 + kvm_sys_state.wifi_config_process = -1; + kvm_sys_state.page = 0; + kvm_sys_state.sub_page = 0; + } else { + // 没连上 + kvm_sys_state.wifi_config_process = 0; + kvm_sys_state.sub_page = 0; + } + break; + } +} + +uint8_t kvm_reset_password(void) +{ + FILE *fp = popen("bash", "w"); + if (fp == NULL) { + perror("popen"); + return 0; + } + + fputs("passwd root\n", fp); + time::sleep_ms(10); + fputs("root\n", fp); + time::sleep_ms(10); + fputs("root\n", fp); + time::sleep_ms(10); + fputs("rm /etc/kvm/pwd\n", fp); + time::sleep_ms(10); + fputs("sync\n", fp); + time::sleep_ms(10); + fputs("exit\n", fp); // 退出 bash + + if (pclose(fp) == -1) { + perror("pclose"); + return 1; + } + return 0; +} \ No newline at end of file diff --git a/kvm_system/main/lib/system_ctrl/system_ctrl.h b/kvm_system/main/lib/system_ctrl/system_ctrl.h new file mode 100644 index 0000000..e16f246 --- /dev/null +++ b/kvm_system/main/lib/system_ctrl/system_ctrl.h @@ -0,0 +1,16 @@ +#ifndef SYSTEM_CTRL_H_ +#define SYSTEM_CTRL_H_ +#include "config.h" + +void gen_hostapd_conf(char* ap_ssid); +void gen_udhcpd_conf(); +void gen_dnsmasq_conf(); +uint8_t sta_connect_ap(void); +uint8_t ssid_pass_ok(void); +uint8_t wifi_connected(void); +void kvm_start_wifi_config_process(void); +void kvm_wifi_web_config_process(); +void kvm_wifi_config_process(); +uint8_t kvm_reset_password(void); + +#endif // SYSTEM_CTRL_H_ \ No newline at end of file diff --git a/kvm_system/main/lib/system_init/system_init.cpp b/kvm_system/main/lib/system_init/system_init.cpp new file mode 100644 index 0000000..f0c4cd3 --- /dev/null +++ b/kvm_system/main/lib/system_init/system_init.cpp @@ -0,0 +1,241 @@ +#include "config.h" +#include "system_init.h" + +using namespace maix; +using namespace maix::sys; + +extern kvm_sys_state_t kvm_sys_state; +extern kvm_oled_state_t kvm_oled_state; + +void new_app_init(uint8_t safe_update) +{ + // first start + system("cp -f /kvmapp/system/update-nanokvm.py /etc/kvm/"); + system("rm /etc/init.d/S02udisk"); + system("cp /kvmapp/system/init.d/S01fs /etc/init.d/"); + system("cp /kvmapp/system/init.d/S03usbdev /etc/init.d/"); + system("cp /kvmapp/system/init.d/S15kvmhwd /etc/init.d/"); + system("cp /kvmapp/system/init.d/S30eth /etc/init.d/"); + system("cp /kvmapp/system/init.d/S50sshd /etc/init.d/"); + if(kvm_wifi_exist()) system("cp /kvmapp/system/init.d/S30wifi /etc/init.d/"); + else system("rm /etc/init.d/S30wifi"); + system("cp /kvmapp/system/init.d/S98tailscaled /etc/init.d/"); + if(safe_update == 0){ + system("cp /kvmapp/system/init.d/S95nanokvm /etc/init.d/"); // /kvmapp/system/init.d/S95nanokvm还没跑完直接覆盖可能出问题 + } + + // system("rm /etc/init.d/S04backlight"); + // system("rm /etc/init.d/S05tp"); + // system("rm /etc/init.d/S40bluetoothd"); + // system("rm /etc/init.d/S99*"); + + system("mkdir /kvmapp/kvm"); + system("mkdir /etc/kvm"); + system("echo 0 > /kvmapp/kvm/now_fps"); + system("echo 30 > /kvmapp/kvm/fps"); + system("echo 2000 > /kvmapp/kvm/qlty"); + system("echo 720 > /kvmapp/kvm/res"); + system("echo h264 > /kvmapp/kvm/type"); + system("echo 0 > /kvmapp/kvm/state"); + system("touch /etc/kvm/frame_detact"); + + // rm jpg_stream & kvm_stream + system("rm -r /kvmapp/jpg_stream"); + system("rm /kvmapp/kvm_system/kvm_stream"); + + // rm kvm_new_app + system("rm /kvmapp/kvm_new_app"); + system("sync"); + // system("/etc/init.d/S95nanokvm restart"); + + // update ko + FILE *fp; + uint8_t RW_Data_0[30]; + uint8_t RW_Data_1[30]; + fp = popen("md5sum /mnt/system/ko/soph_mipi_rx.ko | grep 086ed01749188975afaa40fb569374f8 | awk '{print $2}'", "r"); + if ( NULL == fp ) + { + pclose(fp); + // return; + } + fgets((char*)RW_Data_0, 10, fp); + pclose(fp); + fp = popen("md5sum /mnt/system/ko/soph_mipi_rx.ko | grep 69be7eeded3777f750480a5dd5a1aa26 | awk '{print $2}'", "r"); + if ( NULL == fp ) + { + pclose(fp); + // return; + } + fgets((char*)RW_Data_1, 10, fp); + pclose(fp); + + int8_t hdmi_ver = -1; + + if(access("/etc/kvm/hdmi_version", F_OK) == 0){ + uint8_t RW_Data[2]; + FILE *fp = fopen("/etc/kvm/hdmi_version", "r"); + fread(RW_Data, sizeof(char), 2, fp); + fclose(fp); + if(RW_Data[0] == 'c') hdmi_ver = 1; + else if(RW_Data[0] == 'u') hdmi_ver = 2; + } + + if(hdmi_ver == 2){ + if(RW_Data_1[0] != '/'){ + system("cp /kvmapp/system/ko/soph_mipi_rx.ko /mnt/system/ko/soph_mipi_rx.ko"); + system("sync"); + system("reboot"); + } else { + system("sync"); + system("/etc/init.d/S15kvmhwd start"); + system("/etc/init.d/S95nanokvm restart"); + } + } else { + if((RW_Data_0[0] != '/') && (RW_Data_1[0] != '/')){ + system("cp /kvmapp/system/ko/soph_mipi_rx.ko /mnt/system/ko/soph_mipi_rx.ko"); + system("sync"); + system("reboot"); + } else { + system("sync"); + system("/etc/init.d/S15kvmhwd start"); + system("/etc/init.d/S95nanokvm restart"); + } + } + + if(access("/root/old/kvm_new_img", F_OK) == 0){ + system("rm -r /root/old"); + } +} + +void update_resolv_conf(void) +{ + FILE *fp = NULL; + // fp = fopen("/boot/resolv.conf", "w+"); + fp = fopen("/boot/resolv.conf", "w"); + // 阿里: 223.5.5.5 + // 腾讯: 119.29.29.29 + fprintf(fp, "nameserver 192.168.0.1\nnameserver 8.8.4.4\nnameserver 8.8.8.8\nnameserver 114.114.114.114\nnameserver 119.29.29.29\nnameserver 223.5.5.5"); + fclose(fp); + system("rm -rf /etc/resolv.conf"); + system("cp -vf /etc/resolv.conf /etc/resolv.conf.old"); + system("cp -vf /boot/resolv.conf /etc/resolv.conf"); +} + +void init_upadte(void) +{ + if(access("/kvmapp/kvm_new_app", F_OK) == 0){ + new_app_init(0); + } + + // PCIe Patch + if(access("/kvmapp/jpg_stream/dl_lib/libmaixcam_lib.so", F_OK) == 0){ + system("cp -f /kvmapp/jpg_stream/dl_lib/libmaixcam_lib.so /kvmapp/kvm_system/dl_lib/"); + new_app_init(1); + } + + // DNS Patch + system("tailscale set --accept-dns=false"); + if(access("/boot/resolv.conf", F_OK) != 0){ + // 不存在直接覆盖 + update_resolv_conf(); + } else { + // 存在则检测是否拷贝/DNS是否正确 + uint8_t RW_Data[10] = {0}; + FILE *fp; + fp = popen("cat /etc/resolv.conf | grep 119.29.29.29", "r"); + fgets((char*)RW_Data, 2, fp); + pclose(fp); + if(RW_Data[0] != 'n') { + update_resolv_conf(); + } + } + + // libmaixcam_lib.so + if(access("/kvmapp/kvm_system/dl_lib/libmaixcam_lib.so", F_OK) == 0){ + // exist + system("cp -f /kvmapp/kvm_system/dl_lib/libmaixcam_lib.so /kvmapp/server/dl_lib"); + } else { + printf("kvm_system not exist lib!\n"); + } + system("sync"); + system("killall NanoKVM-Server"); + system("rm -r /tmp/server"); + system("cp -r /kvmapp/server /tmp/"); + system("/tmp/server/NanoKVM-Server &"); +} + +void first_start(void) +{ + if(access("/kvmapp/kvm_new_img", F_OK) == 0){ + // init oled + OLED_state = oled_exist(); + if(OLED_state){ + printf("oled exist\r\n"); + } else { + printf("oled not exist\r\n"); + } + if(OLED_state){ + OLED_Init(); + OLED_ColorTurn(0); //0正常显示 1 反色显示 + OLED_DisplayTurn(0); //0正常显示 1 屏幕翻转显示 + // OLED_INIT_UI(); + + if(kvm_hw_ver == 2){ + OLED_Revolve(); + } + } + uint8_t update_begin = 0; + while(1){ + if(chack_net_state(ETH_ROUTE) && get_ip_addr(ETH_IP)){ + OLED_Clear(); + if(kvm_hw_ver != 2){ + if(update_begin == 0){ + update_begin = 1; + OLED_ShowString(1, 2, "Auto-updating...", 16); + OLED_ShowStringtoend(1, 4, (char*)kvm_sys_state.eth_addr, 16, 0); + system("python /kvmapp/system/update-nanokvm.py"); + } else { + OLED_ShowString(1, 0, "Auto-update fail", 16); + OLED_ShowString(1, 2, "Please open the ", 16); + OLED_ShowStringtoend(1, 4, (char*)kvm_sys_state.eth_addr, 16, 0); + OLED_ShowString(1, 6, "update KVM APP ", 16); + } + } else { + // PCIe + if(update_begin == 0){ + update_begin = 1; + OLED_ShowString(0, 1, "Updating...", 8); + OLED_ShowString_AlignRight(AlignRightEND_P, 2, (char*)kvm_sys_state.eth_addr, 4); + system("python /kvmapp/system/update-nanokvm.py"); + } else { + OLED_ShowString(0, 0, "Update fail", 8); + OLED_ShowString(0, 1, "Please open", 8); + OLED_ShowString_AlignRight(AlignRightEND_P, 2, (char*)kvm_sys_state.eth_addr, 4); + OLED_ShowString(0, 3, "update APP" , 8); + } + } + while(1){ + time::sleep_ms(1000); + if(chack_net_state(ETH_ROUTE) == 0) { + OLED_Clear(); + break; + } + } + } else { + get_ip_addr(ETH_ROUTE); + if(kvm_hw_ver != 2){ + OLED_ShowString(1, 2, " Please connect ", 16); + OLED_ShowString(1, 4, " to the network ", 16); + OLED_ShowString(1, 6, " to update app ", 16); + } else { + // PCIe + OLED_ShowString(0, 0, "Please link", 8); + OLED_ShowString(0, 1, "to network", 8); + OLED_ShowString(0, 2, "update APP" , 8); + } + + time::sleep_ms(10); + } + } + } +} \ No newline at end of file diff --git a/kvm_system/main/lib/system_init/system_init.h b/kvm_system/main/lib/system_init/system_init.h new file mode 100644 index 0000000..b0a9e7c --- /dev/null +++ b/kvm_system/main/lib/system_init/system_init.h @@ -0,0 +1,10 @@ +#ifndef SYSTEM_INIT_H_ +#define SYSTEM_INIT_H_ +#include "config.h" + +void new_app_init(uint8_t safe_update); +void update_resolv_conf(void); +void init_upadte(void); +void first_start(void); + +#endif // SYSTEM_INIT_H_ diff --git a/kvm_system/main/lib/system_state/system_state.cpp b/kvm_system/main/lib/system_state/system_state.cpp new file mode 100644 index 0000000..be0461f --- /dev/null +++ b/kvm_system/main/lib/system_state/system_state.cpp @@ -0,0 +1,544 @@ +#include "config.h" +#include "system_state.h" + +using namespace maix; +using namespace maix::sys; + +extern kvm_sys_state_t kvm_sys_state; +extern kvm_oled_state_t kvm_oled_state; + +// net_port +int get_ip_addr(ip_addr_t ip_type) +{ + switch (ip_type){ + case ETH_IP: // eth_addr + if(strcmp(ip_address()["eth0"].c_str(), (char*)kvm_sys_state.eth_addr) != 0){ + if(*(ip_address()["eth0"].c_str()) == NULL){ + printf("can`t get ip addr\r\n"); + kvm_sys_state.eth_addr[0] = 0; + return 0; + } + for(int i = 0; i <= 15; i++) + { + kvm_sys_state.eth_addr[i] = *(ip_address()["eth0"].c_str() + i); + printf("%c", kvm_sys_state.eth_addr[i]); + } + printf("\r\n"); + } + return 1; + case WiFi_IP: // wifi_addr + if(strcmp(ip_address()["wlan0"].c_str(), (char*)kvm_sys_state.wifi_addr) != 0){ + if(*(ip_address()["wlan0"].c_str()) == NULL){ + printf("can`t get ip addr\r\n"); + kvm_sys_state.wifi_addr[0] = 0; + return 0; + } + for(int i = 0; i <= 15; i++) + { + kvm_sys_state.wifi_addr[i] = *(ip_address()["wlan0"].c_str() + i); + printf("%c", kvm_sys_state.wifi_addr[i]); + } + printf("\r\n"); + } + return 1; + case Tailscale_IP: // tail_addr + if(*(ip_address()["tailscale0"].c_str()) == NULL){ + printf("can`t get ip addr\r\n"); + kvm_sys_state.tail_addr[0] = 0; + return 0; + } + for(int i = 0; i <= 15; i++) + { + kvm_sys_state.tail_addr[i] = *(ip_address()["tailscale0"].c_str() + i); + printf("%c", kvm_sys_state.tail_addr[i]); + } + printf("\r\n"); + return 1; + case RNDIS_IP: // rndis_addr + if(*(ip_address()["usb0"].c_str()) == NULL){ + printf("can`t get ip addr\r\n"); + kvm_sys_state.rndis_addr[0] = 0; + return 0; + } + for(int i = 0; i <= 15; i++) + { + kvm_sys_state.rndis_addr[i] = *(ip_address()["usb0"].c_str() + i); + printf("%c", kvm_sys_state.rndis_addr[i]); + } + printf("\r\n"); + return 1; + case ETH_ROUTE: // eth_route + if(access("/etc/kvm/gateway", F_OK) != 0){ + // 不存在gateway文件 + memset( kvm_sys_state.eth_route, 0, sizeof( kvm_sys_state.eth_route ) ); + char Cmd[100]={0}; + memset( Cmd, 0, sizeof( Cmd ) ); + sprintf( Cmd,"ip route | grep -i '^default' | grep -i 'eth0' | awk '{print $3}'"); + FILE* fp = popen( Cmd, "r" ); + if ( NULL == fp ) + { + pclose(fp); + return 0; + } + memset( kvm_sys_state.eth_route, 0, sizeof( kvm_sys_state.eth_route ) ); + while ( NULL != fgets( (char*)kvm_sys_state.eth_route,sizeof( kvm_sys_state.eth_route ),fp )) + { + // printf("ip=%s\n",kvm_sys_state.eth_route); + break; + } + if(kvm_sys_state.eth_route[0] == 0){ + // 开机时未插入ETH + pclose(fp); + return 0; + } + for(int i = 0; i < 40; i++){ + if(kvm_sys_state.eth_route[i] == 10){ + kvm_sys_state.eth_route[i] = ' '; + break; + } + } + pclose(fp); + return 1; + } else { + int file_size; + FILE *fp = fopen("/etc/kvm/gateway", "r"); + fseek(fp, 0, SEEK_END); + file_size = ftell(fp); + fseek(fp, 0, SEEK_SET); + fread(kvm_sys_state.eth_route, sizeof(char), file_size, fp); + fclose(fp); + return 1; + } + case WiFi_ROUTE: // wifi_route + memset( kvm_sys_state.wifi_route, 0, sizeof( kvm_sys_state.wifi_route ) ); + char Cmd[100]={0}; + memset( Cmd, 0, sizeof( Cmd ) ); + sprintf( Cmd,"ip route | grep -i '^default' | grep -i 'wlan0' | awk '{print $3}'"); + FILE* fp = popen( Cmd, "r" ); + if ( NULL == fp ) + { + pclose(fp); + return 0; + } + memset( kvm_sys_state.wifi_route, 0, sizeof( kvm_sys_state.wifi_route ) ); + while ( NULL != fgets( (char*)kvm_sys_state.wifi_route,sizeof( kvm_sys_state.wifi_route ),fp )) + { + // printf("ip=%s\n",kvm_sys_state.wifi_route); + break; + } + if(kvm_sys_state.wifi_route[0] == 0){ + // 开机时未插入ETH + pclose(fp); + return 0; + } + for(int i = 0; i < 40; i++){ + if(kvm_sys_state.wifi_route[i] == 10){ + kvm_sys_state.wifi_route[i] = ' '; + break; + } + } + pclose(fp); + return 1; + } + return 0; +} + +int chack_net_state(ip_addr_t use_ip_type) +{ + char Cmd[100]={0}; + if (use_ip_type == ETH_ROUTE) sprintf( Cmd,"ping -I eth0 -w 1 %s > /dev/null", kvm_sys_state.eth_route); + else if (use_ip_type == WiFi_ROUTE) sprintf( Cmd,"ping -I wlan0 -w 1 %s > /dev/null", kvm_sys_state.wifi_route); + else return -1; // 不支持的端口 + if(system(Cmd) == 0){ // 256:不通; = 0:通 + return 1; + } + return 0; +} + +void patch_eth_wifi(void) +{ + // system("ip link set eth0 down"); + // system("ip link set eth0 up"); + // system("udhcpc -i eth0 &"); +} + +int kvm_eth_cable_exist() +{ + int temp; + FILE *fp; + int file_size; + uint8_t RW_Data[10]; + fp = fopen("/sys/class/net/eth0/carrier", "r"); + fseek(fp, 0, SEEK_END); + file_size = ftell(fp); + fseek(fp, 0, SEEK_SET); + fread(RW_Data, sizeof(char), file_size, fp); + fclose(fp); + if(RW_Data[0] == '0') return 0; + else if(RW_Data[0] == '1') return 1; + return -1; +} + +int kvm_wifi_exist() +{ + // if(access("/sys/bus/sdio/devices/mmc1*", F_OK) == 0) return 1; + // else return 0; + uint8_t RW_Data[10]; + FILE *fp; + fp = popen("ifconfig | grep wlan", "r"); + fgets((char*)RW_Data, 2, fp); + pclose(fp); + if(RW_Data[0] == 'w') return 1; + else return 0; +} + +int kvm_rndis_exist() +{ + // if(access("/sys/kernel/config/usb_gadget/g0/configs/c.1/rndis.usb0", F_OK) == 0) return 1; + // else return 0; + + int temp; + FILE *fp; + int file_size; + uint8_t RW_Data[10]; + fp = fopen("/sys/class/net/usb0/carrier", "r"); + fseek(fp, 0, SEEK_END); + file_size = ftell(fp); + fseek(fp, 0, SEEK_SET); + fread(RW_Data, sizeof(char), file_size, fp); + fclose(fp); + if(RW_Data[0] == '0') return 0; + else if(RW_Data[0] == '1') return 1; + return -1; +} + +int kvm_tailscale_exist() +{ + // tailscale status + + int temp; + FILE *fp; + int file_size; + uint8_t RW_Data[10]; + fp = fopen("ifconfig tailscale0 | grep 'inet addr' | awk '{print $2}'", "r"); + fseek(fp, 0, SEEK_END); + file_size = ftell(fp); + fseek(fp, 0, SEEK_SET); + fread(RW_Data, sizeof(char), file_size, fp); + fclose(fp); + if(RW_Data[0] == 'a') return 1; + else return 0; + return -1; +} + +void kvm_update_usb_state() +{ + // usb_state, hid_state, rndis_state, udisk_state + FILE *fp; + int file_size; + uint8_t RW_Data[10]; + fp = fopen("/sys/class/udc/4340000.usb/state", "r"); + fseek(fp, 0, SEEK_END); + file_size = ftell(fp); + fseek(fp, 0, SEEK_SET); + fread(RW_Data, sizeof(char), file_size, fp); + fclose(fp); + if(RW_Data[0] == 'n') kvm_sys_state.usb_state = 0; + else if(RW_Data[0] == 'c') kvm_sys_state.usb_state = 1; + else kvm_sys_state.usb_state = -1; + // hid_state & udisk_state (rndis_state单独处理) + if(kvm_sys_state.usb_state == 1){ + if(access("/sys/kernel/config/usb_gadget/g0/configs/c.1/hid.GS*", F_OK) == 0) + kvm_sys_state.hid_state = 1; + if(access("/sys/kernel/config/usb_gadget/g0/configs/c.1/mass_storage.disk0", F_OK) == 0) + kvm_sys_state.udisk_state = 1; + } else { + kvm_sys_state.hid_state = 0; + kvm_sys_state.udisk_state = 0; + } +} + +void kvm_update_hdmi_state() +{ + static uint8_t check_times = 4; + FILE *fp; + int file_size; + uint8_t RW_Data[10]; + if(++check_times > 5){ + check_times = 0; + fp = popen("cat /proc/cvitek/vi_dbg | grep VIFPS | awk '{print $3}'", "r"); + if (fp == NULL) { + pclose(fp); + return; + } + fgets((char*)RW_Data, 2, fp); + pclose(fp); + // printf("[kvmd]HDMI exist? %c\n", RW_Data[0]); + if (RW_Data[0] != '0'){ + kvm_sys_state.hdmi_state = 1; + } else { + kvm_sys_state.hdmi_state = 0; + } + } +} + +void kvm_update_stream_fps(void) +{ + FILE *fp; + int file_size; + uint8_t RW_Data[10]; + + // FPS + fp = fopen("/kvmapp/kvm/now_fps", "r"); + fseek(fp, 0, SEEK_END); + file_size = ftell(fp); + fseek(fp, 0, SEEK_SET); + fread(RW_Data, sizeof(char), file_size, fp); + fclose(fp); + RW_Data[file_size] = 0; + kvm_sys_state.now_fps = atoi((char*)RW_Data); +} + +void kvm_update_stream_type(void) +{ + FILE *fp; + int file_size; + uint8_t RW_Data[10]; + + // type + fp = fopen("/kvmapp/kvm/type", "r"); + fseek(fp, 0, SEEK_END); + file_size = ftell(fp); + fseek(fp, 0, SEEK_SET); + fread(RW_Data, sizeof(char), file_size, fp); + fclose(fp); + if(RW_Data[0] == 'm') kvm_sys_state.type = KVM_TYPE_MJPG; + else if(RW_Data[0] == 'h') kvm_sys_state.type = KVM_TYPE_H264; + else kvm_sys_state.type = KVM_TYPE_none; +} + +void kvm_update_stream_qlty(void) +{ + FILE *fp; + int file_size; + uint8_t RW_Data[10]; + uint16_t tmp16; + + // QLTY + fp = fopen("/kvmapp/kvm/qlty", "r"); + fseek(fp, 0, SEEK_END); + file_size = ftell(fp); + fseek(fp, 0, SEEK_SET); + fread(RW_Data, sizeof(char), file_size, fp); + fclose(fp); + RW_Data[file_size] = 0; + tmp16 = atoi((char*)RW_Data); + if(kvm_sys_state.type == KVM_TYPE_MJPG){ + if(tmp16 < 60) kvm_sys_state.qlty = 1; + else if(tmp16 >= 60 && tmp16 < 75) kvm_sys_state.qlty = 2; + else if(tmp16 >= 75 && tmp16 < 90) kvm_sys_state.qlty = 3; + else if(tmp16 >= 90 && tmp16 <= 100) kvm_sys_state.qlty = 4; + else kvm_sys_state.qlty = 4; + } else { + if(tmp16 < 1500) kvm_sys_state.qlty = 1; + else if(tmp16 >= 1500 && tmp16 < 2500) kvm_sys_state.qlty = 2; + else if(tmp16 >= 2500 && tmp16 < 3500) kvm_sys_state.qlty = 3; + else if(tmp16 >= 3500 && tmp16 <= 5000) kvm_sys_state.qlty = 4; + else kvm_sys_state.qlty = 4; + } +} + +void kvm_update_hdmi_res(void) +{ + FILE *fp; + int file_size; + uint8_t RW_Data[10]; + // HDMI width + fp = fopen("/kvmapp/kvm/width", "r"); + fseek(fp, 0, SEEK_END); + file_size = ftell(fp); + fseek(fp, 0, SEEK_SET); + fread(RW_Data, sizeof(char), file_size, fp); + fclose(fp); + RW_Data[file_size] = 0; + kvm_sys_state.hdmi_width = atoi((char*)RW_Data); + // HDMI height + fp = fopen("/kvmapp/kvm/height", "r"); + fseek(fp, 0, SEEK_END); + file_size = ftell(fp); + fseek(fp, 0, SEEK_SET); + fread(RW_Data, sizeof(char), file_size, fp); + fclose(fp); + RW_Data[file_size] = 0; + kvm_sys_state.hdmi_height = atoi((char*)RW_Data); +} + +void kvm_update_eth_state(void) +{ + // 嗨得是老架构啊 + static uint8_t eth_cable_state = 0; + // if(kvm_eth_cable_exist() == 1){ + // if(eth_cable_state == 0){ + // system("udhcpc -i eth0 &"); + // } + // eth_cable_state = 1; + // } else { + // eth_cable_state = 0; + // } + eth_cable_state = kvm_eth_cable_exist(); + + if(eth_cable_state){ + // 获取实时IP + if(strcmp(ip_address()["eth0"].c_str(), (char*)kvm_sys_state.eth_addr) != 0){ + // if(1){ + if(get_ip_addr(ETH_IP)){ + kvm_sys_state.eth_state = 2; + } else { + kvm_sys_state.eth_state = 1; + return; + } + // OLED_ShowKVMStreamState(KVM_IP, kvm_sys_state.ip_addr); + } + // ping 网关 + if(kvm_sys_state.eth_route[0] == 0){ + get_ip_addr(ETH_ROUTE); + } else { + if(chack_net_state(ETH_ROUTE)){ + // 网络通 + kvm_sys_state.eth_state = 3; + } else { + kvm_sys_state.eth_state = 2; + } + } + + } else { + kvm_sys_state.eth_state = 0; + patch_eth_wifi(); + } + + /* + switch (kvm_sys_state.eth_state){ + case -1: + // 初始缺省值 + kvm_sys_state.eth_state = 0; + case 0: + // 存在PHY + printf("kvm_update_eth_state case 0\n"); + if (kvm_eth_cable_exist()) { + // 已插入 + // system("udhcpc -i eth0 > /dev/null &"); + kvm_sys_state.eth_state = 1; + } else break; + // break; // 消除短暂感叹号 + case 1: + // 线缆已插入&无网络 + if (get_ip_addr(ETH_IP)){ + kvm_sys_state.eth_state = 2; + } else break; + case 2: + // 已获取ip + // system("udhcpc -i eth0 > /dev/null"); + if (get_ip_addr(ETH_ROUTE) && chack_net_state(ETH_ROUTE)){ + // ping 通 + kvm_sys_state.eth_state = 3; + } + if (kvm_eth_cable_exist() == 0) { + // 未插入 + kvm_sys_state.eth_state = 0; + patch_eth_wifi(); + } + break; + case 3: + // 有网络&检测是否拔出/持续检测是否能ping通 + if (kvm_sys_state.eth_route[0] != 0){ + if (chack_net_state(ETH_ROUTE) == 0){ + // ping不通 + kvm_sys_state.eth_state = 2; + // patch_eth_wifi(); + } + } + if (kvm_eth_cable_exist() == 0) { + // 未插入 + kvm_sys_state.eth_state = 0; + patch_eth_wifi(); + } + break; + default: + kvm_sys_state.eth_state = 0; + } + */ +} + +void kvm_update_wifi_state(void) +{ + // 无wifi模块(检测存在?)->有模块&未联网(检测是否联网)-> + if(kvm_sys_state.wifi_state == -2) return; + switch (kvm_sys_state.wifi_state){ + case -1: + // 初始缺省值 + if (kvm_wifi_exist()) { + kvm_sys_state.wifi_state = 0; + system("touch /etc/kvm/wifi_exist"); + } + else { + kvm_sys_state.wifi_state = -2; // 不存在wifi模块,直接跳出 + system("rm /etc/kvm/wifi_exist"); + return; + } + // break; // 直接开始检测联网 + case 0: + // 存在WiFi&未联网 + system("echo 0 > /kvmapp/kvm/wifi_state"); + if (get_ip_addr(WiFi_IP) && get_ip_addr(WiFi_ROUTE)){ + // 已获取ip+route + if (chack_net_state(WiFi_ROUTE)){ + // ping 通 + kvm_sys_state.wifi_state = 1; + } + } + break; + case 1: + // 已联网&持续检测是否能ping通 + system("echo 1 > /kvmapp/kvm/wifi_state"); + get_ip_addr(WiFi_IP); + if (kvm_sys_state.wifi_route[0] != 0){ + if (chack_net_state(WiFi_ROUTE) == 0){ + // ping 通 + kvm_sys_state.wifi_state = 0; + } + } + // default: + // kvm_sys_state.wifi_state = -1; + } +} + +void kvm_update_rndis_state(void) +{ + if (kvm_rndis_exist()) { + if(kvm_sys_state.rndis_state != 1){ + if (get_ip_addr(RNDIS_IP)) { + kvm_sys_state.rndis_state = 1; + } + } + } + else kvm_sys_state.rndis_state = 0; +} + +void kvm_update_tailscale_state(void) +{ + if (kvm_tailscale_exist()) { + if(kvm_sys_state.tail_state != 1){ + if (get_ip_addr(Tailscale_IP)) { + kvm_sys_state.tail_state = 1; + } + } + } + else kvm_sys_state.tail_state = 0; +} + +//============================================================================ + +uint8_t ion_free_space(void) +{ + //cat /sys/kernel/debug/ion/cvi_carveout_heap_dump/summary | grep "usage rate:" | awk '{print $2}' +} \ No newline at end of file diff --git a/kvm_system/main/lib/system_state/system_state.h b/kvm_system/main/lib/system_state/system_state.h new file mode 100644 index 0000000..93ae2c7 --- /dev/null +++ b/kvm_system/main/lib/system_state/system_state.h @@ -0,0 +1,30 @@ +#ifndef SYSTEM_STATE_H_ +#define SYSTEM_STATE_H_ +#include "config.h" + +enum ip_addr_t +{ + ETH_IP=1, WiFi_IP, Tailscale_IP, RNDIS_IP, ETH_ROUTE, WiFi_ROUTE, NULL_IP +}; + +// net_port +int get_ip_addr(ip_addr_t ip_type); +int chack_net_state(ip_addr_t use_ip_type); +void patch_eth_wifi(void); +int kvm_eth_cable_exist(); +int kvm_wifi_exist(); +int kvm_rndis_exist(); +int kvm_tailscale_exist(); +void kvm_update_usb_state(); +void kvm_update_hdmi_state(); +void kvm_update_stream_fps(void); +void kvm_update_stream_type(void); +void kvm_update_stream_qlty(void); +void kvm_update_hdmi_res(void); +void kvm_update_eth_state(void); +void kvm_update_wifi_state(void); +void kvm_update_rndis_state(void); +void kvm_update_tailscale_state(void); +uint8_t ion_free_space(void); + +#endif // SYSTEM_STATE_H_ diff --git a/kvm_system/main/src/main.cpp b/kvm_system/main/src/main.cpp new file mode 100644 index 0000000..2476842 --- /dev/null +++ b/kvm_system/main/src/main.cpp @@ -0,0 +1,233 @@ +#include "config.h" + +using namespace maix; +using namespace maix::sys; +using namespace maix::peripheral; + +kvm_sys_state_t kvm_sys_state; +kvm_oled_state_t kvm_oled_state; + +/* +init.d: +/etc/init.d/S00kmod +/etc/init.d/S01fs + +*/ + +void build_recovery(void) +{ + uint8_t need_recovery = 0; + if (access("/recovery", F_OK) != 0) { + printf("unexist /recovery\n"); + mkdir("/recovery", 0777); + need_recovery = 1; + } else { + printf("exist /recovery\n"); + + } +} + +void* thread_oled_handle(void * arg) +{ + OLED_Init(); + OLED_ColorTurn(0); //0正常显示 1 反色显示 + OLED_DisplayTurn(0); //0正常显示 1 屏幕翻转显示 + OLED_Clear(); + + while(kvm_sys_state.oled_thread_running) + { + oled_auto_sleep(); + // printf("[kvmd]thread_oled_handle - while\n"); + uint8_t page_changed = (kvm_oled_state.page == kvm_sys_state.page)? 0:1; + uint8_t subpage_changed = (kvm_oled_state.sub_page == kvm_sys_state.sub_page)? 0:1; + // printf("subpage_changed = %d", subpage_changed); + // printf("kvm_oled_state.sub_page = %d", kvm_oled_state.sub_page); + // printf("kvm_sys_state.sub_page = %d\n", kvm_sys_state.sub_page); + kvm_oled_state.page = kvm_sys_state.page; + kvm_oled_state.sub_page = kvm_sys_state.sub_page; + + + switch(kvm_oled_state.page){ + case 0 : // main page + kvm_main_ui_disp(page_changed, subpage_changed); + break; + case 1 : // wifi config page + kvm_wifi_config_ui_disp(page_changed, subpage_changed); + break; + default: + OLED_Clear(); + } + time::sleep_ms(OLED_DELAY); + } + OLED_Clear(); + kvm_sys_state.oled_thread_running = -1; +} + +void* thread_key_handle(void * arg) +{ + uint64_t __attribute__((unused)) press_time; + uint32_t press_cycle; + int fd = open ("/dev/input/event0", O_RDONLY); + if (fd == -1) { + kvm_sys_state.key_thread_running = 0; + } + struct input_event event; + + while(kvm_sys_state.key_thread_running) + { + read (fd, &event, sizeof (event)); + if (event.type == EV_KEY) { + if (event.value == 1){ + // printf ("[kvmk]按键按下\n"); + press_time = time::time_ms(); + } else if (event.value == 0){ + oled_auto_sleep_time_update(); + // printf ("[kvmk]按键抬起\n"); + press_cycle = time::time_ms() - press_time; + if(press_cycle >= KEY_LONGLONG_PRESS){ + kvm_reset_password(); + } else if (press_cycle >= KEY_LONG_PRESS && press_cycle < KEY_LONGLONG_PRESS){ + // long + // printf ("[kvmk]按键长按\n"); + // printf("[kvmk]wifi_state = %d\n", kvm_sys_state.wifi_state); + if(kvm_sys_state.wifi_state == -2){ + kvm_sys_state.page = 0; + kvm_sys_state.sub_page = 0; + continue; + } + switch(kvm_sys_state.page){ + case 0: // main page + kvm_sys_state.page = 1; + kvm_sys_state.sub_page = 0; + break; + case 1: // wifi coonfig page + system("/etc/init.d/S30wifi restart"); + kvm_sys_state.page = 0; + kvm_sys_state.sub_page = 0; + kvm_sys_state.wifi_config_process = -1; + break; + } + } else { + // short + // printf ("[kvmk]按键短按\n"); + // printf ("[kvmk]wifi_config_process = %d\n", kvm_sys_state.wifi_config_process); + // printf ("[kvmk]page = %d\n", kvm_sys_state.page); + // printf ("[kvmk]sub_page = %d\n", kvm_sys_state.sub_page); + switch(kvm_sys_state.page){ + case 0: // main page + if(kvm_sys_state.sub_page == 0) kvm_sys_state.sub_page = 1; + else kvm_sys_state.sub_page = 0; + break; + case 1: // wifi coonfig page + switch(kvm_sys_state.wifi_config_process){ + case 1: // QR1<->TEXT2 + if(kvm_sys_state.sub_page == 1) kvm_sys_state.sub_page = 2; + else kvm_sys_state.sub_page = 1; + // printf("[kvmk]sub_page = %d\n", kvm_sys_state.sub_page); + break; + case 2: + if(kvm_sys_state.sub_page == 1) kvm_sys_state.sub_page = 2; + else if(kvm_sys_state.sub_page == 2) kvm_sys_state.sub_page = 3; + else if(kvm_sys_state.sub_page == 3) kvm_sys_state.sub_page = 4; + else kvm_sys_state.sub_page = 1; + break; + } + break; + } + } + } + } + time::sleep_ms(KEY_DELAY); + } + kvm_sys_state.key_thread_running = 0; +} + +void* thread_sys_handle(void * arg) +{ + while(kvm_sys_state.sys_thread_running) + { + // printf("[kvmsys]main while start!\n"); + // net + if(kvm_sys_state.page == 0){ + kvm_update_eth_state(); + kvm_update_wifi_state(); + // kvm_update_rndis_state(); + // kvm_update_tailscale_state(); + // sys_state + kvm_update_usb_state(); + kvm_update_hdmi_state(); + kvm_update_stream_fps(); + kvm_update_hdmi_res(); + kvm_update_stream_type(); + kvm_update_stream_qlty(); + + kvm_wifi_web_config_process(); + } else if(kvm_sys_state.page == 1){ + kvm_wifi_config_process(); + } + + time::sleep_ms(STATE_DELAY); + } + kvm_sys_state.sys_thread_running = 0; +} + +int main(int argc, char* argv[]) +{ + // Catch SIGINT signal(e.g. Ctrl + C), and set exit flag to true. + signal(SIGINT, [](int sig){ + kvm_sys_state.oled_thread_running = 0; + kvm_sys_state.key_thread_running = 0; + kvm_sys_state.sys_thread_running = 0; + app::set_exit_flag(true); + log::info("[kvms]Prepare to exit\n"); + }); + + pthread_t sys_state_thread; + pthread_t display_thread; + pthread_t key_thread; + + // first_start(); + + init_upadte(); + + OLED_state = oled_exist(); + if(OLED_state){ + printf("oled exist\r\n"); + system("touch /etc/kvm/oled_exist"); + } else { + printf("oled not exist\r\n"); + system("rm /etc/kvm/oled_exist"); + } + + if(kvm_sys_state.sys_thread_running == 0){ + kvm_sys_state.sys_thread_running = 1; + if (0 != pthread_create(&sys_state_thread, NULL, thread_sys_handle, NULL)) { + kvm_sys_state.sys_thread_running = 0; + printf("[kvms]create thread failed!\r\n"); + } + } + if(OLED_state == 1 && kvm_sys_state.oled_thread_running == 0){ + kvm_sys_state.oled_thread_running = 1; + if (0 != pthread_create(&display_thread, NULL, thread_oled_handle, NULL)) { + kvm_sys_state.oled_thread_running = 0; + printf("[kvms]create thread failed!\r\n"); + } + } + if(kvm_sys_state.key_thread_running == 0){ + kvm_sys_state.key_thread_running = 1; + if (0 != pthread_create(&key_thread, NULL, thread_key_handle, NULL)) { + kvm_sys_state.key_thread_running = 0; + printf("[kvms]create thread failed!\r\n"); + } + } + + // while(!app::need_exit()){ + while(kvm_sys_state.sys_thread_running){ + time::sleep_ms(1000); + } + kvm_sys_state.sys_thread_running = 0; + kvm_sys_state.oled_thread_running = 0; + kvm_sys_state.key_thread_running = 0; + while(kvm_sys_state.oled_thread_running != -1) time::sleep_ms(100); +} + diff --git a/kvmapp/.DS_Store b/kvmapp/.DS_Store new file mode 100755 index 0000000..418f549 Binary files /dev/null and b/kvmapp/.DS_Store differ diff --git a/kvmapp/jpg_stream/S95nanokvm b/kvmapp/jpg_stream/S95nanokvm new file mode 100755 index 0000000..056508f --- /dev/null +++ b/kvmapp/jpg_stream/S95nanokvm @@ -0,0 +1,91 @@ +#!/bin/sh +# nanokvm Rev2.1 + +case "$1" in + start) + echo -n kvm > /boot/hostname.prefix + cp /mnt/data/sensor_cfg.ini.LT /mnt/data/sensor_cfg.ini + + str_value=$(cat /sys/class/cvi-base/base_uid | awk '{print $2}') + first_uint=$(echo $str_value | cut -d'_' -f1) + second_uint=$(echo $str_value | cut -d'_' -f2) + result="$first_uint$second_uint" + echo $result > /device_key + + # if [ ! -e /etc/kvm/hw ] + # then + + # fi + + # echo 504 > /sys/class/gpio/export # pwr led + # echo 505 > /sys/class/gpio/export # hdd led + # echo 503 > /sys/class/gpio/export # pwr key + # echo 507 > /sys/class/gpio/export # rst key + + # echo in > /sys/class/gpio/gpio504/direction # pwr led + # echo in > /sys/class/gpio/gpio505/direction # hdd led + # echo out > /sys/class/gpio/gpio503/direction # pwr key + # echo out > /sys/class/gpio/gpio507/direction # rst key + + iptables -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT + iptables -A OUTPUT -o eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT + iptables -A OUTPUT -o eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT + iptables -A INPUT -i eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT + iptables -A OUTPUT -o eth0 -p tcp --sport 8000 -m state --state ESTABLISHED -j DROP + + cp -r /kvmapp/kvm_system /tmp/ + /tmp/kvm_system/kvm_system & + + # if [ -e /kvmapp/kvm_stream ] + # then + # cp -r /kvmapp/kvm_stream /tmp/ + # /tmp/kvm_stream/kvm_stream & + # fi + + cp -r /kvmapp/server /tmp/ + /tmp/server/NanoKVM-Server & + ;; + stop) + killall kvm_system + # killall kvm_stream + killall NanoKVM-Server + rm -r /tmp/kvm_system + # rm -r /tmp/kvm_stream + rm -r /tmp/server + echo "OK" + ;; + # restart_stream) + # killall kvm_stream + # rm -r /tmp/kvm_stream + # if [ -e /kvmapp/kvm_stream ] + # then + # cp -r /kvmapp/kvm_stream /tmp/ + # /tmp/kvm_stream/kvm_stream & + # echo "OK" + # fi + # ;; + restart) + killall kvm_system + # killall kvm_stream + killall NanoKVM-Server + rm -r /tmp/kvm_system + # rm -r /tmp/kvm_stream + rm -r /tmp/server + + cp -r /kvmapp/kvm_system /tmp/ + /tmp/kvm_system/kvm_system & + + # if [ -e /kvmapp/kvm_stream ] + # then + # cp -r /kvmapp/kvm_stream /tmp/ + # /tmp/kvm_stream/kvm_stream & + # fi + + cp -r /kvmapp/server /tmp/ + /tmp/server/NanoKVM-Server & + + sync + + echo "OK" + ;; +esac \ No newline at end of file diff --git a/kvmapp/jpg_stream/jpg_stream b/kvmapp/jpg_stream/jpg_stream new file mode 100755 index 0000000..1a0030f --- /dev/null +++ b/kvmapp/jpg_stream/jpg_stream @@ -0,0 +1,5 @@ +rm /etc/init.d/S95webkvm +cp /kvmapp/jpg_stream/S95nanokvm /etc/init.d/ +cp /kvmapp/jpg_stream/dl_lib/libmaixcam_lib.so /kvmapp/kvm_system/dl_lib +rm -r /kvmapp/jpg_stream +/etc/init.d/S95nanokvm restart diff --git a/kvmapp/kvm_new_app b/kvmapp/kvm_new_app new file mode 100644 index 0000000..e69de29 diff --git a/kvmapp/kvm_system/kvm_stream b/kvmapp/kvm_system/kvm_stream new file mode 100755 index 0000000..e69de29 diff --git a/kvmapp/kvm_system/kvm_system b/kvmapp/kvm_system/kvm_system new file mode 100755 index 0000000..f2c63d0 Binary files /dev/null and b/kvmapp/kvm_system/kvm_system differ diff --git a/kvmapp/system/init.d/S01fs b/kvmapp/system/init.d/S01fs new file mode 100755 index 0000000..3391d66 --- /dev/null +++ b/kvmapp/system/init.d/S01fs @@ -0,0 +1,42 @@ +#!/bin/sh + +if [ "$1" = "start" ] +then + # use all sdcard free space for data + parted -s /dev/mmcblk0 "resizepart 2 -0" + echo "yes + 8192MB + " | parted ---pretend-input-tty /dev/mmcblk0 "resizepart 2 8192MB" + # resize data filesystem + (resize2fs /dev/mmcblk0p2) & + + + . /etc/profile + printf "mounting filesystem : " + mkdir -p /boot + mount -t vfat /dev/mmcblk0p1 /boot + mount -t configfs configfs /sys/kernel/config + mount -t debugfs debugfs /sys/kernel/debug + + if [ -e /boot/usb.disk0 ] + then + if [ ! -e /etc/kvm.disk0 ] + then + touch /etc/kvm.disk0 + # use all sdcard free space for data + parted -s /dev/mmcblk0 "mkpart primary 8193MB 100%" + sleep 1 + # resize data filesystem + (mkfs.exfat /dev/mmcblk0p3) & + sleep 1 + fi + fi + + if [ -e /dev/mmcblk0p3 ] + then + mkdir -p /data + mount /dev/mmcblk0p3 /data + fi + + echo "OK" +fi diff --git a/kvmapp/system/init.d/S03usbdev b/kvmapp/system/init.d/S03usbdev new file mode 100755 index 0000000..1cd5ba8 --- /dev/null +++ b/kvmapp/system/init.d/S03usbdev @@ -0,0 +1,128 @@ +#!/bin/sh +if [ "$1" = "start" ] +then + . /etc/profile + echo "usb mode: device" + cd /sys/kernel/config/usb_gadget + + mkdir g0 + cd g0 + # echo 0x3346 > idVendor + # echo 0x1009 > idProduct + # mkdir strings/0x409 + # echo '0123456789ABCDEF' > strings/0x409/serialnumber + # echo 'flyingrtx' > strings/0x409/manufacturer + # echo 'licheervnano' > strings/0x409/product + + echo 0x3346 > idVendor + echo 0x1009 > idProduct + mkdir strings/0x409 + echo '0123456789ABCDEF' > strings/0x409/serialnumber + echo 'sipeed' > strings/0x409/manufacturer + echo 'NanoKVM' > strings/0x409/product + + mkdir configs/c.1 + echo 0xE0 > configs/c.1/bmAttributes + echo 120 > configs/c.1/MaxPower + mkdir configs/c.1/strings/0x409 + echo "NanoKVM" > configs/c.1/strings/0x409/configuration + + if [ -e /boot/usb.ncm ] + then + mkdir functions/ncm.usb0 + ln -s functions/ncm.usb0 configs/c.1/ + else + if [ -e /boot/usb.rndis0 ] + then + mkdir functions/rndis.usb0 + ln -s functions/rndis.usb0 configs/c.1/ + fi + fi + + # keyboard + mkdir functions/hid.GS0 + if [ -e /boot/BIOS ] + then + echo 1 > functions/hid.GS0/subclass + fi + if [ ! -e /boot/usb.notwakeup ] + then + echo 1 > functions/hid.GS0/wakeup_on_write + fi + echo 1 > functions/hid.GS0/protocol + echo 6 > functions/hid.GS0/report_length +# echo -ne \\x05\\x01\\x09\\x06\\xa1\\x01\\x05\\x07\\x19\\xe0\\x29\\xe7\\x15\\x00\\x25\\x10\\x75\\x01\\x95\\x08\\x01\\x02\\x95\\x01\\x75\\x08\\x01\\x03\\x95\\x05\\x75\\x01\\x05\\x08\\x19\\x01\\x29\\x05\\x91\\x02\\x95\\x01\\x75\\x03\\x91\\x03\\x95\\x06\\x75\\x08\\x15\\x00\\x25\\x65\\x05\\x07\\x19\\x00\\x29\\x65\\x81\\x00\\xc0 > functions/hid.GS0/report_desc + echo -ne \\x05\\x01\\x09\\x06\\xa1\\x01\\x05\\x07\\x19\\xe0\\x29\\xe7\\x15\\x00\\x25\\x01\\x75\\x01\\x95\\x08\\x81\\x02\\x95\\x01\\x75\\x08\\x81\\x03\\x95\\x05\\x75\\x01\\x05\\x08\\x19\\x01\\x29\\x05\\x91\\x02\\x95\\x01\\x75\\x03\\x91\\x03\\x95\\x06\\x75\\x08\\x15\\x00\\x25\\x65\\x05\\x07\\x19\\x00\\x29\\x65\\x81\\x00\\xc0 > functions/hid.GS0/report_desc + ln -s functions/hid.GS0 configs/c.1 + + # mouse + mkdir functions/hid.GS1 + if [ -e /boot/BIOS ] + then + echo 1 > functions/hid.GS1/subclass + fi + if [ ! -e /boot/usb.notwakeup ] + then + echo 1 > functions/hid.GS1/wakeup_on_write + fi + echo 2 > functions/hid.GS1/protocol + echo -ne \\x34 > functions/hid.GS1/report_length + echo -ne \\x5\\x1\\x9\\x2\\xa1\\x1\\x9\\x1\\xa1\\x0\\x5\\x9\\x19\\x1\\x29\\x3\\x15\\x0\\x25\\x1\\x95\\x3\\x75\\x1\\x81\\x2\\x95\\x1\\x75\\x5\\x81\\x3\\x5\\x1\\x9\\x30\\x9\\x31\\x9\\x38\\x15\\x81\\x25\\x7f\\x75\\x8\\x95\\x3\\x81\\x6\\xc0\\xc0 > functions/hid.GS1/report_desc + ln -s functions/hid.GS1 configs/c.1 + + # touchpad + mkdir functions/hid.GS2 + if [ -e /boot/BIOS ] + then + echo 1 > functions/hid.GS2/subclass + fi + if [ ! -e /boot/usb.notwakeup ] + then + echo 1 > functions/hid.GS2/wakeup_on_write + fi + echo 2 > functions/hid.GS2/protocol + echo 6 > functions/hid.GS2/report_length + echo -ne \\x05\\x01\\x09\\x02\\xa1\\x01\\x09\\x01\\xa1\\x00\\x05\\x09\\x19\\x01\\x29\\x03\\x15\\x00\\x25\\x01\\x95\\x03\\x75\\x01\\x81\\x02\\x95\\x01\\x75\\x05\\x81\\x01\\x05\\x01\\x09\\x30\\x09\\x31\\x15\\x00\\x26\\xff\\x7f\\x35\\x00\\x46\\xff\\x7f\\x75\\x10\\x95\\x02\\x81\\x02\\x05\\x01\\x09\\x38\\x15\\x81\\x25\\x7f\\x35\\x00\\x45\\x00\\x75\\x08\\x95\\x01\\x81\\x06\\xc0\\xc0 > functions/hid.GS2/report_desc + ln -s functions/hid.GS2 configs/c.1 + + if [ -e /boot/usb.disk0 ] + then + mkdir functions/mass_storage.disk0 + ln -s functions/mass_storage.disk0 configs/c.1/ + echo 1 > functions/mass_storage.disk0/lun.0/removable + if [ -e /boot/usb.disk0.ro ] + then + echo 1 > functions/mass_storage.disk0/lun.0/ro + echo 0 > functions/mass_storage.disk0/lun.0/cdrom + fi + disk=$(cat /boot/usb.disk0) + if [ -z "${disk}" ] + then + # if [ ! -e /mnt/usbdisk.img ] + # then + # fallocate -l 8G /mnt/usbdisk.img + # mkfs.vfat /mnt/usbdisk.img + # fi + echo /dev/mmcblk0p3 > functions/mass_storage.disk0/lun.0/file + else + cat /boot/usb.disk0 > functions/mass_storage.disk0/lun.0/file + fi + fi + + ls /sys/class/udc/ | cat > UDC + echo device > /proc/cviusb/otg_role +fi + +if [ "$1" = "stop" ] +then + echo '' > /sys/kernel/config/usb_gadget/g0/UDC + echo host > /proc/cviusb/otg_role +fi + +if [ "$1" = "restart" ] +then + echo > /sys/kernel/config/usb_gadget/g0/UDC + sleep 1 + ls /sys/class/udc/ | cat > /sys/kernel/config/usb_gadget/g0/UDC + echo "USB Restart OK!" +fi diff --git a/kvmapp/system/init.d/S15kvmhwd b/kvmapp/system/init.d/S15kvmhwd new file mode 100755 index 0000000..0b414e6 --- /dev/null +++ b/kvmapp/system/init.d/S15kvmhwd @@ -0,0 +1,209 @@ +#!/bin/sh +# kvmhwd Rev2.3 + +Alpha_OLED_RST_Pin=371 +Beta_OLED_RST_Pin=502 +Beta_OLED_SCL=595 +Beta_OLED_SDA=507 +WiFi_EN_Pin=506 +Alpha_PWR_LED_Pin=504 +Alpha_HDD_LED_Pin=505 +Alpha_PWR_KEY_Pin=503 +Alpha_RST_KEY_Pin=507 +Beta_PWR_LED_Pin=504 +Beta_PWR_KEY_Pin=503 +Beta_RST_KEY_Pin=505 +PCIe_HDMI_RST_Pin=451 + +init_alpha_hw(){ + devmem 0x030010D0 32 0x2 # I2C1_SCL + devmem 0x030010DC 32 0x2 # I2C1_SDA + devmem 0x030010D4 32 0x3 # OLED_RST + devmem 0x0300103C 32 0x3 # GPIOA15 + devmem 0x03001050 32 0x3 # GPIOA22 + devmem 0x0300105C 32 0x3 # GPIOA23 + devmem 0x03001060 32 0x3 # GPIOA24 + devmem 0x03001054 32 0x3 # GPIOA25 + devmem 0x03001058 32 0x3 # GPIOA27 + + devmem 0x03001068 32 0x6 # GPIOA 18 UART1 RX + devmem 0x03001064 32 0x6 # GPIOA 19 UART1 TX + devmem 0x03001070 32 0x2 # GPIOA 28 UART2 TX + devmem 0x03001074 32 0x2 # GPIOA 29 UART2 RX + + echo ${Alpha_OLED_RST_Pin} > /sys/class/gpio/export # OLED_RST + echo out > /sys/class/gpio/gpio${Alpha_OLED_RST_Pin}/direction + echo 1 > /sys/class/gpio/gpio${Alpha_OLED_RST_Pin}/value + + echo ${Alpha_PWR_LED_Pin} > /sys/class/gpio/export # pwr led + echo ${Alpha_HDD_LED_Pin} > /sys/class/gpio/export # hdd led + echo ${Alpha_PWR_KEY_Pin} > /sys/class/gpio/export # pwr key + echo ${Alpha_RST_KEY_Pin} > /sys/class/gpio/export # rst key + + echo in > /sys/class/gpio/gpio${Alpha_PWR_LED_Pin}/direction # pwr led + echo in > /sys/class/gpio/gpio${Alpha_HDD_LED_Pin}/direction # hdd led + echo out > /sys/class/gpio/gpio${Alpha_PWR_KEY_Pin}/direction # pwr key + echo out > /sys/class/gpio/gpio${Alpha_RST_KEY_Pin}/direction # rst key + + rmmod /mnt/system/ko/i2c-gpio.ko + rmmod /mnt/system/ko/i2c-algo-bit.ko + + # rm /etc/init.d/S25wifimod + # rm /etc/init.d/S30wifi +} + +init_beta_pcie_hw(){ + devmem 0x0300103C 32 0x3 # GPIOA15 + devmem 0x03001050 32 0x3 # GPIOA22 + devmem 0x0300105C 32 0x3 # GPIOA23 + devmem 0x03001060 32 0x3 # GPIOA24 + devmem 0x03001054 32 0x3 # GPIOA25 + devmem 0x03001058 32 0x3 # GPIOA27 + + devmem 0x030010E4 32 0x0 # SDIO CLK + devmem 0x030010E0 32 0x0 # SDIO CMD + devmem 0x030010DC 32 0x0 # SDIO D0 + devmem 0x030010D8 32 0x0 # SDIO D1 + devmem 0x030010D4 32 0x0 # SDIO D2 + devmem 0x030010D0 32 0x0 # SDIO D3 + + devmem 0x03001068 32 0x6 # GPIOA 18 UART1 RX + devmem 0x03001064 32 0x6 # GPIOA 19 UART1 TX + devmem 0x03001070 32 0x2 # GPIOA 28 UART2 TX + devmem 0x03001074 32 0x2 # GPIOA 29 UART2 RX + + echo ${Beta_OLED_RST_Pin} > /sys/class/gpio/export # Beta OLED_RST + echo out > /sys/class/gpio/gpio${Beta_OLED_RST_Pin}/direction + echo 1 > /sys/class/gpio/gpio${Beta_OLED_RST_Pin}/value + + echo ${Beta_PWR_LED_Pin} > /sys/class/gpio/export # pwr led + echo ${Beta_PWR_KEY_Pin} > /sys/class/gpio/export # pwr key + echo ${Beta_RST_KEY_Pin} > /sys/class/gpio/export # rst key + echo ${PCIe_HDMI_RST_Pin} > /sys/class/gpio/export # hdmi rst key + + echo in > /sys/class/gpio/gpio${Beta_PWR_LED_Pin}/direction # pwr led + echo out > /sys/class/gpio/gpio${Beta_PWR_KEY_Pin}/direction # pwr key + echo out > /sys/class/gpio/gpio${Beta_RST_KEY_Pin}/direction # rst key + echo out > /sys/class/gpio/gpio${PCIe_HDMI_RST_Pin}/direction # rst key + + echo 1 > /sys/class/gpio/gpio${PCIe_HDMI_RST_Pin}/value # rst key + + rmmod /mnt/system/ko/i2c-gpio.ko + rmmod /mnt/system/ko/i2c-algo-bit.ko + insmod /mnt/system/ko/i2c-algo-bit.ko + insmod /mnt/system/ko/i2c-gpio.ko +} + +kvm_hw_detect(){ + if [ ! -e /etc/kvm/hdmi_version ] + then + rm /etc/kvm/hw + fi + if [ -e /etc/kvm/hw ] + then + echo "/etc/kvm/hw exist" + else + echo "/etc/kvm/hw not exist" + if [ -d "/etc/kvm/" ] + then + echo "/etc/kvm/ exist" + else + mkdir /etc/kvm/ + fi + devmem 0x0300104C 32 0x3 # GPIOA26 / WiFi_EN + echo ${WiFi_EN_Pin} > /sys/class/gpio/export # WiFi_EN + echo out > /sys/class/gpio/gpio${WiFi_EN_Pin}/direction + echo 0 > /sys/class/gpio/gpio${WiFi_EN_Pin}/value + + devmem 0x0300103C 32 0x3 # GPIOA15 + devmem 0x03001050 32 0x3 # GPIOA22 + devmem 0x0300105C 32 0x3 # GPIOA23 + devmem 0x03001060 32 0x3 # GPIOA24 + devmem 0x03001054 32 0x3 # GPIOA25 + devmem 0x03001058 32 0x3 # GPIOA27 + + devmem 0x030010D0 32 0x2 # I2C1_SCL + devmem 0x030010DC 32 0x2 # I2C1_SDA + devmem 0x030010D4 32 0x3 # OLED_RST + echo ${Alpha_OLED_RST_Pin} > /sys/class/gpio/export # OLED_RST + echo out > /sys/class/gpio/gpio${Alpha_OLED_RST_Pin}/direction + echo 1 > /sys/class/gpio/gpio${Alpha_OLED_RST_Pin}/value + + kvm_tmp=$(i2cdetect -ry 1 0x3d 0x3d | grep 3d) + if [ -n "$kvm_tmp" ] + then + # alpha hw + echo "alpha" > /etc/kvm/hw + else + # beta/pcie hw + echo ${Alpha_OLED_RST_Pin} > /sys/class/gpio/unexport # OLED_RST + echo ${Beta_OLED_RST_Pin} > /sys/class/gpio/export # Beta_OLED_RST_Pin + echo out > /sys/class/gpio/gpio${Beta_OLED_RST_Pin}/direction + echo 1 > /sys/class/gpio/gpio${Beta_OLED_RST_Pin}/value + + rmmod /mnt/system/ko/i2c-gpio.ko + rmmod /mnt/system/ko/i2c-algo-bit.ko + insmod /mnt/system/ko/i2c-algo-bit.ko + insmod /mnt/system/ko/i2c-gpio.ko + + kvm_tmp=$(i2cdetect -ry 4 0x2c 0x2c | grep 2c) + if [ -n "$kvm_tmp" ] + then + echo "c" > /etc/kvm/hdmi_version + else + echo "u" > /etc/kvm/hdmi_version + fi + + kvm_tmp=$(i2cdetect -ry 5 0x3c 0x3c | grep 3c) + if [ -n "$kvm_tmp" ] + then + echo "pcie" > /etc/kvm/hw + sync + reboot + else + echo "beta" > /etc/kvm/hw + # rm /etc/init.d/S25wifimod + # rm /etc/init.d/S30wifi + sync + fi + + echo 1 > /sys/class/gpio/gpio${WiFi_EN_Pin}/value + echo ${WiFi_EN_Pin} > /sys/class/gpio/unexport # WiFi_EN + fi + fi + sync +} + +kvm_hw_init(){ + FIND_FILE="/etc/kvm/hw" + if [ `grep -c "alpha" $FIND_FILE` -ne '0' ] + then + echo "hw = alpha!" + init_alpha_hw + fi + if [ `grep -c "beta" $FIND_FILE` -ne '0' ] + then + echo "hw = beta!" + init_beta_pcie_hw + fi + if [ `grep -c "pcie" $FIND_FILE` -ne '0' ] + then + echo "hw = pcie!" + init_beta_pcie_hw + fi +} + +case "$1" in + start) + kvm_hw_detect + kvm_hw_init + ;; + re-detect) + rm /etc/kvm/hw + kvm_hw_detect + kvm_hw_init + ;; + re-init) + kvm_hw_init + ;; +esac diff --git a/kvmapp/system/init.d/S30eth b/kvmapp/system/init.d/S30eth new file mode 100755 index 0000000..92928e4 --- /dev/null +++ b/kvmapp/system/init.d/S30eth @@ -0,0 +1,115 @@ +#!/bin/sh + +. /etc/profile + +# /boot/eth.nodhcp for example +# ipaddr/net gw[optional] +# 192.168.0.101/24 192.168.0.1 +# 192.168.3.116/22 + +RESERVE_INET="192.168.0.1/24" + +start() { + printf "start ethernet: " + if [ -e /boot/eth.nodhcp ] + then + [ -e /boot/eth.nodhcp ] && + cat /boot/eth.nodhcp | while read inet gw + do + addr=${inet%/*} + netid=${inet#*/} + [ -z $gw ] && + gw=$( echo $addr| ( IFS='.' read a b c d; echo $(( + (((((($a<<8)+$b)<<8)+$c)<<8)+$d) + & (((1<<$netid)-1)<<(32-$netid)) + )) + )) && + gw=$(($gw>>24&0xff)).$(($gw>>16&0xff)).$(($gw>>8&0xff)).$((1+( $gw>>0&0xff ))) + + arping -Dqc2 -Ieth0 $addr || continue + ip a add $inet brd + dev eth0 + ip r add default via $gw dev eth0 + cat > /etc/resolve.conf << EOF +nameserver $gw +nameserver 8.8.8.8 +nameserver 114.114.114.114 +EOF + break + done && + ip a show dev eth0|grep inet || ( + udhcpc -i eth0 -t 3 -T 1 -A 5 -b -p /run/udhcpc.eth0.pid &>/dev/null + ip a show dev eth0|grep inet + ) || ( + # failed to apply dynamic addr, need a available static addr to visit the LAN + inet=$RESERVE_INET + addr=${inet%/*} + ip a add $inet brd + dev eth0 + ) || exit 1 + else + (udhcpc -i eth0 -t 10 -T 1 -A 5 -b -p /run/udhcpc.eth0.pid) & + fi + + echo "OK" +} +stop() { + [[ ! -e "/run/udhcpc.eth0.pid" ]] && echo "udhcpc is not running..." && exit 1 + kill `cat /run/udhcpc.eth0.pid` + rm /run/udhcpc.eth0.pid +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart|reload) + $0 stop + $0 start + ;; + doc) + cat < /etc/wpa_supplicant.conf + wpa_passphrase "$ssid" "$pass" >> /etc/wpa_supplicant.conf + wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant.conf + if [ ! -e /boot/wifi.nodhcp ] + then + (udhcpc -i wlan0 -t 10 -T 1 -A 5 -b -p /run/udhcpc.wlan0.pid) & + fi +} + +ap_start() { + echo "wifi mode: ap" + id2=$(printf "%d" 0x$(sha512sum /sys/class/cvi-base/base_uid | head -c 2)) + id3=$(printf "%d" 0x$(sha512sum /sys/class/cvi-base/base_uid | head -c 4 | tail -c 2)) + if [ "$id2" = "$id3" ] + then + id2=$((id2 + 1)) + fi + if [ "$id2" -ge 255 ] + then + id2=253 + fi + if [ "$id3" -ge 255 ] + then + id3=254 + fi + ssid="" + pass="" + if [ -e /kvmapp/kvm/ap.ssid ] + then + ssid=`cat /kvmapp/kvm/ap.ssid` + fi + if [ -e /kvmapp/kvm/ap.pass ] + then + pass=`cat /kvmapp/kvm/ap.pass` + fi + gen_hostapd_conf "$ssid" "$pass" > /etc/hostapd.conf + ipv4_prefix=10.$id3.$id2 + if [ ! -e /etc/udhcpd.wlan0.conf ] + then + gen_udhcpd_conf wlan0 "${ipv4_prefix}" > /etc/udhcpd.wlan0.conf + fi + # gen_dnsmasq_conf "${ipv4_prefix}" > /etc/dnsmasq.conf + + # iptables --policy INPUT ACCEPT + # iptables --policy FORWARD ACCEPT + # iptables --policy OUTPUT ACCEPT + # iptables -F + # iptables -t nat -F + # iptables -t nat -A PREROUTING -i wlan0 -p udp --dport 53 -j DNAT --to ${ipv4_prefix}.1 + + ifconfig wlan0 up + ip route del default || true + ip add flush dev wlan0 + ip addr add $ipv4_prefix.1/24 dev wlan0 + # dnsmasq --pid-file=/tmp/dnsmasq.run -C /etc/dnsmasq.conf + hostapd -B -i wlan0 /etc/hostapd.conf + udhcpd -S /etc/udhcpd.wlan0.conf +} + +stop() { + ps -ef|grep hostapd|grep -v grep|awk '{print $1}'|xargs kill -2 || true + ps -ef|grep "udhcpd -S /etc/udhcpd.wlan0.conf" |grep -v grep|awk '{print $1}'|xargs kill -2 || true + killall wpa_supplicant || true + if [ -e /run/udhcpc.wlan0.pid ] + then + kill `cat /run/udhcpc.wlan0.pid` || true + rm -f /run/udhcpc.wlan0.pid + fi + if [ -e /var/run/udhcpd.wlan0.pid ] + then + kill `cat /var/run/udhcpd.wlan0.pid` || true + rm -f /var/run/udhcpd.wlan0.pid + fi + if [ -e /tmp/dnsmasq.run ] + then + kill `cat /tmp/dnsmasq.run` || true + rm -f /tmp/dnsmasq.run + fi + # if [ -e /etc/wpa_supplicant.conf] + # then + # echo > /etc/wpa_supplicant.conf + # fi + airmon-ng stop wlan0mon || true +} + +restart() { + stop + start +} + +if [ "${1}" = "start" ] +then + start +elif [ "${1}" = "stop" ] +then + stop +elif [ "${1}" = "ap" ] +then + stop + ap_start +elif [ "${1}" = "restart" ] +then + restart +fi diff --git a/kvmapp/system/init.d/S50sshd b/kvmapp/system/init.d/S50sshd new file mode 100755 index 0000000..911ed91 --- /dev/null +++ b/kvmapp/system/init.d/S50sshd @@ -0,0 +1,61 @@ +#!/bin/sh +# +# sshd Starts sshd. +# + +# Make sure the ssh-keygen progam exists +[ -f /usr/bin/ssh-keygen ] || exit 0 + +umask 077 + +startssh() { + /usr/bin/ssh-keygen -A + + printf "Starting sshd: " + /usr/sbin/sshd + touch /var/lock/sshd + echo "OK" +} +start() { + # Create any missing keys + if [ -e /etc/kvm/ssh_stop ] + then + if [ -e /boot/start_ssh_once ] + then + rm /boot/start_ssh_once + startssh + else + echo "SSH does not start" + fi + else + startssh + fi +} +stop() { + printf "Stopping sshd: " + killall sshd + rm -f /var/lock/sshd + echo "OK" +} +restart() { + stop + start +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart|reload) + restart + ;; + *) + echo "Usage: $0 {start|stop|restart}" + exit 1 +esac + +exit $? + diff --git a/kvmapp/system/init.d/S95nanokvm b/kvmapp/system/init.d/S95nanokvm new file mode 100755 index 0000000..b028421 --- /dev/null +++ b/kvmapp/system/init.d/S95nanokvm @@ -0,0 +1,50 @@ +#!/bin/sh +# nanokvm Rev3.0 + +case "$1" in + start) + echo -n kvm > /boot/hostname.prefix + cp /mnt/data/sensor_cfg.ini.LT /mnt/data/sensor_cfg.ini + + str_value=$(cat /sys/class/cvi-base/base_uid | awk '{print $2}') + first_uint=$(echo $str_value | cut -d'_' -f1) + second_uint=$(echo $str_value | cut -d'_' -f2) + result="$first_uint$second_uint" + echo $result > /device_key + + iptables -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT + iptables -A OUTPUT -o eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT + iptables -A OUTPUT -o eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT + iptables -A INPUT -i eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT + iptables -A OUTPUT -o eth0 -p tcp --sport 8000 -m state --state ESTABLISHED -j DROP + + cp -r /kvmapp/kvm_system /tmp/ + /tmp/kvm_system/kvm_system & + + # cp -r /kvmapp/server /tmp/ + # /tmp/server/NanoKVM-Server & + ;; + stop) + killall kvm_system + killall NanoKVM-Server + rm -r /tmp/kvm_system + rm -r /tmp/server + echo "OK" + ;; + restart) + killall kvm_system + killall NanoKVM-Server + rm -r /tmp/kvm_system + rm -r /tmp/server + + cp -r /kvmapp/kvm_system /tmp/ + /tmp/kvm_system/kvm_system & + + # cp -r /kvmapp/server /tmp/ + # /tmp/server/NanoKVM-Server & + + sync + + echo "OK" + ;; +esac \ No newline at end of file diff --git a/kvmapp/system/init.d/S98tailscaled b/kvmapp/system/init.d/S98tailscaled new file mode 100755 index 0000000..d9a683e --- /dev/null +++ b/kvmapp/system/init.d/S98tailscaled @@ -0,0 +1,113 @@ +#!/bin/sh + +DAEMON="tailscaled" +PIDFILE="/var/run/$DAEMON.pid" + +# Set the port to listen on for incoming VPN packets. +# Remote nodes will automatically be informed about the new port number, +# but you might want to configure this in order to set external firewall +# settings. +PORT="41641" + +# Extra flags you might want to pass to tailscaled. +FLAGS="" + +# You need tailscaled at /usr/sbin to server, and tailscale at /usr/bin to operate +# STATIC version needed. Download page at https://pkgs.tailscale.com/stable/#static +PKG_URL_LATEST="https://pkgs.tailscale.com/stable/tailscale_latest_riscv64.tgz" +[ ! -x /usr/sbin/$DAEMON ] && + echo "/usr/sbin/$DAEMON not found, please download it from $PKG_URL_LATEST" && + echo "Then unpack it, copy $DAEMON to /usr/sbin and copy tailscale to /usr/bin" && + exit 1 +VERSION=$(/usr/sbin/$DAEMON --version|sed -n '1p'|xargs echo -n) + +[ -x /usr/bin/tailscale ] || echo "/usr/bin/tailscale not found, your installation of tailscale may be broken" + +# just for those need forwarding +[ ! -f /etc/sysctl.d/99-tailscale.conf ] && + mkdir -p /etc/sysctl.d/ && + echo "missing /etc/sysctl.d/99-tailscale.conf, try make it below:" && + (tee /etc/sysctl.d/99-tailscale.conf </dev/null + [ $? = 0 ] && echo "OK" || echo "FAIL" + ;; + restart|reload) + $0 stop + $0 start + ;; + doc) + cat <