W801_SDK_dev_env/tools/w800/wm_tool.c
2022-11-01 18:22:10 +01:00

2594 lines
65 KiB
C

#include <time.h>
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <dirent.h>
#include <unistd.h>
#include <stdarg.h>
#ifdef __MINGW32__
#include <windows.h>
#else
#include <signal.h>
#include <pthread.h>
#include <termios.h>
#include <sys/ioctl.h>
#endif
#include "zlib-1.2.11/zlib.h"
#include "zlib-1.2.11/gzguts.h"
void gz_compress OF((FILE *in, gzFile out));
void file_compress OF((char *file, char *mode));
#ifndef GZ_SUFFIX
# define GZ_SUFFIX ".gz"
#endif
#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
#define BUFLEN 4096
#define MAX_NAME_LEN 1024
#ifndef local
# define local
#endif
#define WM_TOOL_PATH_MAX 256
#define WM_TOOL_ONCE_READ_LEN 1024
#define WM_TOOL_RUN_IMG_HEADER_LEN 0x100
#define WM_TOOL_SECBOOT_IMG_ADDR (0x2100)
#define WM_TOOL_SECBOOT_HEADER_LEN (0x100)
#define WM_TOOL_SECBOOT_HEADER_POS (WM_TOOL_SECBOOT_IMG_ADDR - WM_TOOL_SECBOOT_HEADER_LEN)
//#define WM_TOOL_SECBOOT_IMG_AREA_TOTAL_LEN 9216//(56 * 1024)
#define WM_TOOL_IMG_HEAD_MAGIC_NO (0xA0FFFF9F)
#define WM_TOOL_DEFAULT_BAUD_RATE 115200
#define WM_TOOL_DOWNLOAD_TIMEOUT_SEC (60 * 1)
#define WM_TOOL_USE_1K_XMODEM 1 /* 1 for use 1k_xmodem 0 for xmodem */
#define WM_TOOL_IMAGE_VERSION_LEN 16
/* Xmodem Frame form: <SOH><blk #><255-blk #><--128 data bytes--><CRC hi><CRC lo> */
#define XMODEM_SOH 0x01
#define XMODEM_STX 0x02
#define XMODEM_EOT 0x04
#define XMODEM_ACK 0x06
#define XMODEM_NAK 0x15
#define XMODEM_CAN 0x18
#define XMODEM_CRC_CHR 'C'
#define XMODEM_CRC_SIZE 2 /* Crc_High Byte + Crc_Low Byte */
#define XMODEM_FRAME_ID_SIZE 2 /* Frame_Id + 255-Frame_Id */
#define XMODEM_DATA_SIZE_SOH 128 /* for Xmodem protocol */
#define XMODEM_DATA_SIZE_STX 1024 /* for 1K xmodem protocol */
#if (WM_TOOL_USE_1K_XMODEM)
#define XMODEM_DATA_SIZE XMODEM_DATA_SIZE_STX
#define XMODEM_HEAD XMODEM_STX
#else
#define XMODEM_DATA_SIZE XMODEM_DATA_SIZE_SOH
#define XMODEM_HEAD XMODEM_SOH
#endif
#ifdef WM_DEBUG
#define WM_TOOL_DBG_PRINT wm_tool_printf
#else
#define WM_TOOL_DBG_PRINT(...)
#endif
typedef enum {
WM_TOOL_DL_ACTION_NONE = 0,
WM_TOOL_DL_ACTION_AT,
WM_TOOL_DL_ACTION_RTS
} wm_tool_dl_action_e;
typedef enum {
WM_TOOL_DL_ERASE_NONE = 0,
WM_TOOL_DL_ERASE_ALL
} wm_tool_dl_erase_e;
typedef enum {
WM_TOOL_DL_TYPE_IMAGE = 0,
WM_TOOL_DL_TYPE_FLS
} wm_tool_dl_type_e;
typedef enum {
WM_TOOL_LAYOUT_TYPE_1M = 0,
WM_TOOL_LAYOUT_TYPE_2M = 3
} wm_tool_layout_type_e;
typedef enum {
WM_TOOL_ZIP_TYPE_UNCOMPRESS = 0,
WM_TOOL_ZIP_TYPE_COMPRESS
} wm_tool_zip_type_e;
typedef enum {
WM_TOOL_CRC32_REFLECT_OUTPUT = 1,
WM_TOOL_CRC32_REFLECT_INPUT = 2
} wm_tool_crc32_reflect_e;
typedef enum {
WM_TOOL_SHOW_LOG_NONE = 0,
WM_TOOL_SHOW_LOG_STR,
WM_TOOL_SHOW_LOG_HEX
} wm_tool_show_log_e;
typedef struct {
unsigned int magic_no;
unsigned short img_type;
unsigned short zip_type;
unsigned int run_img_addr;
unsigned int run_img_len;
unsigned int img_header_addr;
unsigned int upgrade_img_addr;
unsigned int run_org_checksum;
unsigned int upd_no;
unsigned char ver[WM_TOOL_IMAGE_VERSION_LEN];
unsigned int reserved0;
unsigned int reserved1;
unsigned int next_boot;
unsigned int hd_checksum;
} wm_tool_firmware_booter_t;
const static char *wm_tool_version = "1.0.4";
static int wm_tool_show_usage = 0;
static int wm_tool_list_com = 0;
static int wm_tool_show_ver = 0;
static char wm_tool_serial_path[WM_TOOL_PATH_MAX] = "/dev/ttyS0";
static unsigned int wm_tool_download_serial_rate = WM_TOOL_DEFAULT_BAUD_RATE;
static unsigned int wm_tool_normal_serial_rate = WM_TOOL_DEFAULT_BAUD_RATE;
static wm_tool_dl_action_e wm_tool_dl_action = WM_TOOL_DL_ACTION_NONE;
static wm_tool_dl_erase_e wm_tool_dl_erase = WM_TOOL_DL_ERASE_NONE;
static wm_tool_dl_type_e wm_tool_dl_type = WM_TOOL_DL_TYPE_IMAGE;
static char *wm_tool_download_image = NULL;
static char *wm_tool_input_binary = NULL;
static char *wm_tool_output_image = NULL;
static char *wm_tool_secboot_image = NULL;
static unsigned int wm_tool_src_binary_len = 0;
static unsigned int wm_tool_src_binary_crc = 0;
static int wm_tool_is_debug = 0;
static char wm_tool_image_version[WM_TOOL_IMAGE_VERSION_LEN];
static wm_tool_layout_type_e wm_tool_image_type = WM_TOOL_LAYOUT_TYPE_1M;
static wm_tool_zip_type_e wm_tool_zip_type = WM_TOOL_ZIP_TYPE_COMPRESS;
static unsigned int wm_tool_upd_addr = 0x8090000;
static unsigned int wm_tool_run_addr = 0x8002400;
static unsigned int wm_tool_image_header = 0x8002000;
static unsigned int wm_tool_next_image_header = 0x0;
static unsigned int wm_tool_image_upd_no = 0x0;
static unsigned int wm_tool_file_crc = 0xFFFFFFFF;
static wm_tool_show_log_e wm_tool_show_log_type = WM_TOOL_SHOW_LOG_NONE;
#ifdef __MINGW32__
#ifndef CBR_2000000
#define CBR_2000000 2000000
#endif
#ifndef CBR_1000000
#define CBR_1000000 1000000
#endif
#ifndef CBR_921600
#define CBR_921600 921600
#endif
#ifndef CBR_460800
#define CBR_460800 460800
#endif
static DWORD wm_tool_uart_block = 0;
static HANDLE wm_tool_uart_handle = NULL;
const static int wm_tool_uart_speed_array[] = {CBR_2000000, CBR_1000000, CBR_921600, CBR_460800, CBR_115200, CBR_38400,
CBR_19200, CBR_9600, CBR_4800, CBR_2400, CBR_1200};
#else /* __MINGW32__ */
#ifndef B2000000
#define B2000000 2000000
#endif
#ifndef B1000000
#define B1000000 1000000
#endif
#ifndef B921600
#define B921600 921600
#endif
#ifndef B460800
#define B460800 460800
#endif
static int wm_tool_uart_fd = -1;
static struct termios wm_tool_saved_serial_cfg;
const static int wm_tool_uart_speed_array[] = {B2000000, B1000000, B921600, B460800, B115200, B38400,
B19200, B9600, B4800, B2400, B1200};
#endif /* __MINGW32__ */
const static int wm_tool_uart_name_array[] = {2000000, 1000000, 921600, 460800, 115200, 38400,
19200, 9600, 4800, 2400, 1200};
const static unsigned char wm_tool_chip_cmd_b115200[] = {0x21, 0x0a, 0x00, 0x97, 0x4b, 0x31, 0x00, 0x00, 0x00, 0x00, 0xc2, 0x01, 0x00};
const static unsigned char wm_tool_chip_cmd_b460800[] = {0x21, 0x0a, 0x00, 0x07, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x08, 0x07, 0x00};
const static unsigned char wm_tool_chip_cmd_b921600[] = {0x21, 0x0a, 0x00, 0x5d, 0x50, 0x31, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00};
const static unsigned char wm_tool_chip_cmd_b1000000[] = {0x21, 0x0a, 0x00, 0x5e, 0x3d, 0x31, 0x00, 0x00, 0x00, 0x40, 0x42, 0x0f, 0x00};
const static unsigned char wm_tool_chip_cmd_b2000000[] = {0x21, 0x0a, 0x00, 0xef, 0x2a, 0x31, 0x00, 0x00, 0x00, 0x80, 0x84, 0x1e, 0x00};
const static unsigned char wm_tool_chip_cmd_get_mac[] = {0x21, 0x06, 0x00, 0xea, 0x2d, 0x38, 0x00, 0x00, 0x00};
static const unsigned int wm_tool_crc32_tab[] = {0x00000000L, 0x77073096L, 0xee0e612cL,
0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL,
0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L,
0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L,
0x83d385c7L, 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL,
0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L,
0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L,
0xd20d85fdL, 0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L,
0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L,
0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, 0x2802b89eL, 0x5f058808L,
0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL,
0xb6662d3dL, 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL,
0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L,
0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL,
0x91646c97L, 0xe6635c01L, 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L,
0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL,
0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL,
0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL,
0xd3d6f4fbL, 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL,
0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L,
0xb966d409L, 0xce61e49fL, 0x5edef90eL, 0x29d9c998L, 0xb0d09822L,
0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L,
0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L,
0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L,
0x7d079eb1L, 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL,
0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L,
0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L,
0x17b7be43L, 0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L,
0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L,
0xa867df55L, 0x316e8eefL, 0x4669be79L, 0xcb61b38cL, 0xbc66831aL,
0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L,
0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L,
0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L,
0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL,
0x72076785L, 0x05005713L, 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL,
0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL,
0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, 0x88085ae6L, 0xff0f6a70L,
0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L,
0x166ccf45L, 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL,
0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L,
0x47b2cf7fL, 0x30b5ffe9L, 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L,
0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L,
0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL};
static void wm_tool_signal_proc_entry(void);
static void wm_tool_stdin_to_uart(void);
static int wm_tool_printf(const char *format, ...)
{
int ret;
va_list ap;
va_start(ap, format);
ret = vprintf(format, ap);
va_end(ap);
fflush(stdout);
return ret;
}
static unsigned long long wm_tool_crc32_reflect(unsigned long long ref, unsigned char ch)
{
int i;
unsigned long long value = 0;
for ( i = 1; i < ( ch + 1 ); i++ )
{
if( ref & 1 )
value |= 1 << ( ch - i );
ref >>= 1;
}
return value;
}
static unsigned int wm_tool_crc32(unsigned int crc, unsigned char *buffer, int size, wm_tool_crc32_reflect_e mode)
{
int i;
unsigned char temp;
for (i = 0; i < size; i++)
{
if (mode & WM_TOOL_CRC32_REFLECT_INPUT)
{
temp = wm_tool_crc32_reflect(buffer[i], 8);
}
else
{
temp = buffer[i];
}
crc = wm_tool_crc32_tab[(crc ^ temp) & 0xff] ^ (crc >> 8);
}
return crc ;
}
static unsigned int wm_tool_get_crc32(unsigned char *buffer, int size, wm_tool_crc32_reflect_e mode)
{
wm_tool_file_crc = wm_tool_crc32(wm_tool_file_crc, buffer, size, mode);
if (mode & WM_TOOL_CRC32_REFLECT_OUTPUT)
{
wm_tool_file_crc = wm_tool_crc32_reflect(wm_tool_file_crc, 32);
}
return wm_tool_file_crc;
}
static unsigned short wm_tool_get_crc16(unsigned char *ptr, unsigned short count)
{
unsigned short crc, i;
crc = 0;
while (count--)
{
crc = crc ^ (int) *ptr++ << 8;
for (i = 0; i < 8; i++)
{
if (crc & 0x8000)
crc = crc << 1 ^ 0x1021;
else
crc = crc << 1;
}
}
return (crc & 0xFFFF);
}
static int wm_tool_char_to_hex(char ch)
{
int hex;
hex = -1;
if ((ch >= '0') && (ch <= '9'))
{
hex = ch - '0';
}
else if ((ch >= 'a') && (ch <= 'f'))
{
hex = ch - 'a' + 0xa;
}
else if ((ch >= 'A') && (ch <= 'F'))
{
hex = ch - 'A' + 0xa;
}
return hex;
}
static int wm_tool_str_to_hex_array(char *str, int cnt, unsigned char array[])
{
int hex;
unsigned char tmp;
unsigned char *des;
des = array;
while (cnt-- > 0)
{
hex = wm_tool_char_to_hex(*str++);
if (hex < 0)
{
return -1;
}
else
{
tmp = (hex << 4) & 0xf0;
}
hex = wm_tool_char_to_hex(*str++);
if (hex < 0)
{
return -1;
}
else
{
tmp = tmp | (hex & 0x0f);
}
*des++ = (unsigned char) tmp;
}
return ((*str == 0) ? 0 : -1);
}
static char *wm_tool_strcasestr(const char *str1, const char *str2)
{
char *cp = (char *) str1;
char *s1, *s2;
if (!*str2) return (char *) str1;
while (*cp) {
s1 = cp;
s2 = (char *) str2;
while (*s1 && *s2 && !(tolower((int)*s1) - tolower((int)*s2))) s1++, s2++;
if (!*s2) return cp;
cp++;
}
return NULL;
}
static int wm_tool_get_file_size(const char* filename)
{
FILE *fp = fopen(filename, "r");
if(!fp) return -1;
fseek(fp,0L,SEEK_END);
int size = ftell(fp);
fclose(fp);
return size;
}
static char *wm_tool_get_name(const char *name)
{
static char sz_name[WM_TOOL_PATH_MAX] = {0};
char *p = (char *)name;
char *q = (char *)name;
do
{
#ifdef __MINGW32__
p = strchr(p, '\\');
#else
p = strchr(p, '/');
#endif
if (p)
{
p++;
q = p;
}
} while (p);
strncpy(sz_name, q, WM_TOOL_PATH_MAX - 1);
#ifdef __MINGW32__
p = wm_tool_strcasestr(sz_name, ".exe");
if (p)
*p = '\0';
#endif
return sz_name;
}
static void wm_tool_print_usage(const char *name)
{
wm_tool_printf("Usage: %s [-h] [-v] [-b] [-o] [-sb] [-ct] [-it]"
" [-ua] [-ra] [-ih] [-nh] [-un] [-df] [-vs]"
" [-l] [-c] [-ws] [-ds] [-rs] [-eo] [-dl] [-sl]"
"\r\n"
"\r\n"
"WinnerMicro firmware packaging "
"and programming "
"tool\r\n\r\n"
"options:\r\n\r\n"
" -h , show usage\r\n"
" -v , show version\r\n"
"\r\n"
" -b binary , original binary file\r\n"
" -o output_name , output firmware file\r\n"
" the default is the same as the original binary file name\r\n"
" -sb second_boot , second boot file, used to generate fls file\r\n"
" -fc compress_type , whether the firmware is compressed, default is compressed\r\n"
" <0 | 1> or <uncompress | compress>\r\n"
" -it image_type , firmware image layout type, default is 0\r\n"
" <0 | 1>\r\n"
" -ua update_address , upgrade storage location (hexadecimal)\r\n"
" the default is 8090000\r\n"
" -ra run_address , runtime position (hexadecimal)\r\n"
" the default is 8002400\r\n"
" -ih image_header , image header storage location (hexadecimal)\r\n"
" the default is 8002000\r\n"
" -nh next_image_header , next image header storage location (hexadecimal)\r\n"
" the default is 0\r\n"
" -un upd_no , upd no version number (hexadecimal)\r\n"
" the default is 0\r\n"
" -df , generate debug firmware for openocd\r\n"
" -vs version_string , firmware version string, cannot exceed 16 bytes\r\n"
"\r\n"
" -l , list the local serial port\r\n"
" -c serial_name , connect a serial port\r\n"
#if defined(__APPLE__) && defined(__MACH__)
" e.g: tty.usbserial0 tty.usbserial3 tty.usbserial7\r\n"
#elif defined(__MINGW32__) || defined(__CYGWIN__)
" e.g: COM0 COM3 COM7\r\n"
#elif defined(__linux__)
" e.g: ttyUSB0 ttyUSB3 ttyUSB7\r\n"
#endif
" -ws baud_rate , set the serial port speed during normal work, default is 115200\r\n"
" <1200 - 2000000> or <1M | 2M>\r\n"
" -ds baud_rate , set the serial port speed when downloading, default is 115200\r\n"
" <115200 | 460800 | 921600 | 1000000 | 2000000> or <1M | 2M>\r\n"
" -rs reset_action , set device reset method, default is manual control\r\n"
" <none | at | rts>\r\n"
" none - manual control device reset\r\n"
" at - use the at command to control the device reset\r\n"
" rts - use the serial port rts pin to control the device reset\r\n"
" -eo erase_option , firmware area erase option\r\n"
" <all>\r\n"
" all - erase all areas\r\n"
" -dl download_firmware , firmware file to be downloaded, default download compressed image\r\n"
" -sl display_format , display the log information output from the serial port\r\n"
" <0 | 1> or <str | hex>\r\n"
" str - string mode display\r\n"
" hex - hexadecimal format\r\n"
, wm_tool_get_name(name));
return;
}
static void wm_tool_print_version(const char *name)
{
wm_tool_printf("%s %s for w800\r\nCopyright (C) 2013 - 2020 WinnerMicro, Inc.\r\n", wm_tool_get_name(name), wm_tool_version);
return;
}
static int wm_tool_parse_arv(int argc, char *argv[])
{
int opt;
int option_index = 0;
char *opt_string = "hvlc:b:o:";
int cnt = 0;
opterr = 1;/* show err info */
struct option long_options[] = {
{"dl", required_argument, NULL, 'd'},
{"ws", required_argument, NULL, 'w'},
{"ds", required_argument, NULL, 's'},
{"sb", required_argument, NULL, 'S'},
{"it", required_argument, NULL, 'i'},
{"fc", required_argument, NULL, 'C'},
{"ua", required_argument, NULL, 'u'},
{"ra", required_argument, NULL, 'r'},
{"ih", required_argument, NULL, 'H'},
{"nh", required_argument, NULL, 'n'},
{"un", required_argument, NULL, 'U'},
{"df", no_argument, NULL, 'D'},
{"vs", required_argument, NULL, 'V'},
{"rs", required_argument, NULL, 'a'},
{"eo", required_argument, NULL, 'e'},
{"sl", required_argument, NULL, 'g'},
{0, 0, NULL, 0}
};
while ( (opt = getopt_long_only(argc, argv, opt_string, long_options, &option_index)) != -1)
{
WM_TOOL_DBG_PRINT("%c-%s\r\n", opt, optarg);
switch (opt)
{
case '?':
case 'h':
{
wm_tool_show_usage = 1;
break;
}
case 'v':
{
wm_tool_show_ver = 1;
break;
}
case 'l':
{
wm_tool_list_com = 1;
break;
}
case 'c':
{
#if defined(__MINGW32__)
strcpy(wm_tool_serial_path, optarg);
#elif defined(__CYGWIN__)
sprintf(wm_tool_serial_path, "/dev/ttyS%d", atoi(optarg + strlen("COM")) - 1);
#else
sprintf(wm_tool_serial_path, "/dev/%s", optarg);
#endif
break;
}
case 'w':
{
if ('M' == optarg[1])
wm_tool_normal_serial_rate = (optarg[0] - 0x30) * 1000000;
else
wm_tool_normal_serial_rate = strtol(optarg, NULL, 10);
break;
}
case 's':
{
if ('M' == optarg[1])
wm_tool_download_serial_rate = (optarg[0] - 0x30) * 1000000;
else
wm_tool_download_serial_rate = strtol(optarg, NULL, 10);
break;
}
case 'a':
{
if (0 == strncmp(optarg, "none", strlen("none")))
wm_tool_dl_action = WM_TOOL_DL_ACTION_NONE;
else if (0 == strncmp(optarg, "at", strlen("at")))
wm_tool_dl_action = WM_TOOL_DL_ACTION_AT;
else if (0 == strncmp(optarg, "rts", strlen("rts")))
wm_tool_dl_action = WM_TOOL_DL_ACTION_RTS;
else
wm_tool_show_usage = 1;
break;
}
case 'e':
{
if (0 == strncmp(optarg, "all", strlen("all")))
wm_tool_dl_erase = WM_TOOL_DL_ERASE_ALL;
else
wm_tool_show_usage = 1;
break;
}
case 'd':
{
wm_tool_download_image = strdup(optarg);
if (wm_tool_strcasestr(wm_tool_download_image, ".fls"))
wm_tool_dl_type = WM_TOOL_DL_TYPE_FLS;
break;
}
case 'o':
{
wm_tool_output_image = strdup(optarg);
break;
}
case 'b':
{
wm_tool_input_binary = strdup(optarg);
break;
}
case 'S':
{
wm_tool_secboot_image = strdup(optarg);
break;
}
case 'i':
{
#if 0
if ('0' == optarg[0])
wm_tool_image_type = WM_TOOL_LAYOUT_TYPE_1M;
else if ('3' == optarg[0])
wm_tool_image_type = WM_TOOL_LAYOUT_TYPE_2M;
else if (0 == strncmp(optarg, "1M", strlen("1M")))
wm_tool_image_type = WM_TOOL_LAYOUT_TYPE_1M;
else if (0 == strncmp(optarg, "2M", strlen("2M")))
wm_tool_image_type = WM_TOOL_LAYOUT_TYPE_2M;
else
#endif
{
if (isdigit((int)optarg[0]))
wm_tool_image_type = atoi(optarg);//optarg[0] - 0x30;
else
wm_tool_show_usage = 1;
}
break;
}
case 'C':
{
if ('0' == optarg[0])
wm_tool_zip_type = WM_TOOL_ZIP_TYPE_UNCOMPRESS;
else if ('1' == optarg[0])
wm_tool_zip_type = WM_TOOL_ZIP_TYPE_COMPRESS;
else if (0 == strncmp(optarg, "compress", strlen("compress")))
wm_tool_zip_type = WM_TOOL_ZIP_TYPE_COMPRESS;
else if (0 == strncmp(optarg, "uncompress", strlen("uncompress")))
wm_tool_zip_type = WM_TOOL_ZIP_TYPE_UNCOMPRESS;
else
wm_tool_show_usage = 1;
break;
}
case 'u':
{
wm_tool_upd_addr = strtol(optarg, NULL, 16);
break;
}
case 'r':
{
wm_tool_run_addr = strtol(optarg, NULL, 16);
break;
}
case 'D':
{
wm_tool_is_debug = 1;
break;
}
case 'V':
{
strncpy(wm_tool_image_version, optarg, WM_TOOL_IMAGE_VERSION_LEN);
wm_tool_image_version[WM_TOOL_IMAGE_VERSION_LEN - 1] = '\0';
break;
}
case 'g':
{
if ('0' == optarg[0])
wm_tool_show_log_type = WM_TOOL_SHOW_LOG_STR;
else if ('1' == optarg[0])
wm_tool_show_log_type = WM_TOOL_SHOW_LOG_HEX;
else if (0 == strncmp(optarg, "str", strlen("str")))
wm_tool_show_log_type = WM_TOOL_SHOW_LOG_STR;
else if (0 == strncmp(optarg, "hex", strlen("hex")))
wm_tool_show_log_type = WM_TOOL_SHOW_LOG_HEX;
else
wm_tool_show_usage = 1;
break;
break;
}
case 'H':
{
wm_tool_image_header = strtol(optarg, NULL, 16);
break;
}
case 'n':
{
wm_tool_next_image_header = strtol(optarg, NULL, 16);
break;
}
case 'U':
{
wm_tool_image_upd_no = strtol(optarg, NULL, 16);
break;
}
default:
{
wm_tool_show_usage = 1;
break;
}
}
cnt++;
}
return cnt;
}
static int wm_tool_pack_image(const char *outfile)
{
FILE *fpbin = NULL;
FILE *fpimg = NULL;
int readlen = 0;
int filelen = 0;
int patch = 0;
wm_tool_firmware_booter_t fbooter;
unsigned char buf[WM_TOOL_ONCE_READ_LEN + 1];
fpbin = fopen(wm_tool_input_binary, "rb");
if (NULL == fpbin)
{
wm_tool_printf("can not open input file [%s].\r\n", wm_tool_input_binary);
return -2;
}
fpimg = fopen(outfile, "wb+");
if (NULL == fpimg)
{
wm_tool_printf("open img file error: [%s].\r\n", outfile);
fclose(fpbin);
return -3;
}
/* --------deal with upgrade image's CRC begin---- */
wm_tool_file_crc = 0xFFFFFFFF;
while (!feof(fpbin))
{
memset(buf, 0, sizeof(buf));
readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpbin);
if(readlen % 4 != 0)
{
patch = 4 - readlen%4;
readlen += patch;
}
filelen += readlen;
wm_tool_get_crc32((unsigned char*)buf, readlen, 0);
}
/* --------deal with upgrade image's CRC end---- */
wm_tool_src_binary_len = filelen;
wm_tool_src_binary_crc = wm_tool_file_crc;
memset(&fbooter, 0, sizeof(wm_tool_firmware_booter_t));
strcpy((char *)fbooter.ver, wm_tool_image_version);
fbooter.magic_no = WM_TOOL_IMG_HEAD_MAGIC_NO;
fbooter.run_org_checksum = wm_tool_file_crc;
fbooter.img_type = wm_tool_image_type;
fbooter.run_img_len = filelen;
fbooter.run_img_addr = wm_tool_run_addr;
fbooter.zip_type = WM_TOOL_ZIP_TYPE_UNCOMPRESS;
fbooter.img_header_addr = wm_tool_image_header;
fbooter.upgrade_img_addr = wm_tool_upd_addr;
fbooter.upd_no = wm_tool_image_upd_no;
fbooter.next_boot = wm_tool_next_image_header;
/* calculate image's header's CRC */
wm_tool_file_crc = 0xFFFFFFFF;
wm_tool_get_crc32((unsigned char *)&fbooter, sizeof(wm_tool_firmware_booter_t) - 4, 0);
fbooter.hd_checksum = wm_tool_file_crc;
/* write image's header to output file */
fwrite(&fbooter, 1, sizeof(wm_tool_firmware_booter_t), fpimg);
/* write image to output file */
fseek(fpbin, 0, SEEK_SET);
while (!feof(fpbin))
{
readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpbin);
fwrite(buf, 1, readlen, fpimg);
}
/* write dummy data to pad 4byte-aligned */
if (patch > 0)
{
memset(buf, 0, patch);
fwrite(buf, 1, patch, fpimg);
}
if (fpbin)
{
fclose(fpbin);
}
if (fpimg)
{
fclose(fpimg);
}
wm_tool_printf("generate normal image completed.\r\n");
return 0;
}
static int wm_tool_pack_gz_image(const char *gzbin, const char *outfile)
{
FILE *fpbin = NULL;
FILE *fpimg = NULL;
int readlen = 0;
int filelen = 0;
int patch = 0;
wm_tool_firmware_booter_t fbooter;
unsigned char buf[WM_TOOL_ONCE_READ_LEN + 1];
fpbin = fopen(gzbin, "rb");
if (NULL == fpbin)
{
wm_tool_printf("can not open input file [%s].\r\n", gzbin);
return -2;
}
fpimg = fopen(outfile, "wb+");
if (NULL == fpimg)
{
wm_tool_printf("create img file error: [%s].\r\n", outfile);
fclose(fpbin);
return -3;
}
/* --------deal with upgrade image's CRC begin---- */
wm_tool_file_crc = 0xFFFFFFFF;
while (!feof(fpbin))
{
memset(buf, 0, sizeof(buf));
readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpbin);
if(readlen % 4 != 0)
{
patch = 4 - readlen%4;
readlen += patch;
}
filelen += readlen;
wm_tool_get_crc32((unsigned char*)buf, readlen, 0);
}
/* --------deal with upgrade image's CRC end---- */
memset(&fbooter, 0, sizeof(wm_tool_firmware_booter_t));
strcpy((char *)fbooter.ver, wm_tool_image_version);
fbooter.magic_no = WM_TOOL_IMG_HEAD_MAGIC_NO;
fbooter.run_org_checksum = wm_tool_file_crc;
fbooter.img_type = wm_tool_image_type;
fbooter.run_img_len = filelen;
fbooter.run_img_addr = wm_tool_run_addr;
fbooter.zip_type = wm_tool_zip_type;
fbooter.img_header_addr = wm_tool_image_header;
fbooter.upgrade_img_addr = wm_tool_upd_addr;
fbooter.upd_no = wm_tool_image_upd_no;
fbooter.next_boot = wm_tool_next_image_header;
/* calculate image's header's CRC */
wm_tool_file_crc = 0xFFFFFFFF;
wm_tool_get_crc32((unsigned char *)&fbooter, sizeof(wm_tool_firmware_booter_t) - 4, 0);
fbooter.hd_checksum = wm_tool_file_crc;
/* write image's header to output file */
fwrite(&fbooter, 1, sizeof(wm_tool_firmware_booter_t), fpimg);
/* write image to output file */
fseek(fpbin, 0, SEEK_SET);
while (!feof(fpbin))
{
readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpbin);
fwrite(buf, 1, readlen, fpimg);
}
/* write dummy data to pad 4byte-aligned */
if (patch > 0)
{
memset(buf, 0, patch);
fwrite(buf, 1, patch, fpimg);
}
if (fpbin)
{
fclose(fpbin);
}
if (fpimg)
{
fclose(fpimg);
}
wm_tool_printf("generate compressed image completed.\r\n");
return 0;
}
static int wm_tool_pack_dbg_image(const char *image, const char *outfile)
{
FILE *fpimg = NULL;
FILE *fout = NULL;
unsigned char buf[WM_TOOL_ONCE_READ_LEN + 1];
int readlen = 0;
int i;
wm_tool_firmware_booter_t fbooter;
int appimg_len = 0;
int final_len = 0;
int magic_word = 0;
fpimg = fopen(image, "rb");
if (NULL == fpimg)
{
wm_tool_printf("open img file error: [%s].\r\n", image);
return -4;
}
magic_word = 0;
readlen = fread(&magic_word, 1, 4, fpimg);
if (magic_word != WM_TOOL_IMG_HEAD_MAGIC_NO)
{
wm_tool_printf("input [%s] file magic error.\n", image);
fclose(fpimg);
return -5;
}
fout = fopen(outfile, "wb+");
if (NULL == fout)
{
wm_tool_printf("create img file error [%s].\r\n", outfile);
fclose(fpimg);
return -6;
}
appimg_len = wm_tool_get_file_size(image);
/* write 0xFF to output file */
final_len = WM_TOOL_RUN_IMG_HEADER_LEN + (appimg_len - sizeof(wm_tool_firmware_booter_t));
for (i = 0; i < (final_len /WM_TOOL_ONCE_READ_LEN); i++)
{
memset(buf, 0xff, WM_TOOL_ONCE_READ_LEN);
fwrite(buf, 1, WM_TOOL_ONCE_READ_LEN, fout);
}
memset(buf, 0xff, final_len % WM_TOOL_ONCE_READ_LEN);
fwrite(buf, 1, final_len % WM_TOOL_ONCE_READ_LEN, fout);
memset(&fbooter, 0, sizeof(wm_tool_firmware_booter_t));
/* write sec img to output file */
fseek(fpimg, 0, SEEK_SET);
readlen = fread((unsigned char *)&fbooter, 1, sizeof(wm_tool_firmware_booter_t), fpimg);
fseek(fout, 0, SEEK_SET);
fwrite(&fbooter, 1, sizeof(wm_tool_firmware_booter_t), fout);
fseek(fout, WM_TOOL_RUN_IMG_HEADER_LEN, SEEK_SET);
while (!feof(fpimg))
{
readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpimg);
fwrite(buf, 1, readlen, fout);
}
if (fpimg)
{
fclose(fpimg);
}
if (fout)
{
fclose(fout);
}
wm_tool_printf("generate debug image completed.\r\n");
return 0;
}
static int wm_tool_pack_fls(const char *image, const char *outfile)
{
FILE *fpsec = NULL;
FILE *fpimg = NULL;
FILE *fout = NULL;
unsigned char buf[WM_TOOL_ONCE_READ_LEN + 1];
int readlen = 0;
int magic_word = 0;
fpsec = fopen(wm_tool_secboot_image,"rb");
if (NULL == fpsec)
{
wm_tool_printf("can not open input file [%s].\r\n", wm_tool_secboot_image);
return -2;
}
magic_word = 0;
readlen = fread(&magic_word, 1, 4, fpsec);
if (magic_word != WM_TOOL_IMG_HEAD_MAGIC_NO)
{
wm_tool_printf("input [%s] file magic error.\r\n", wm_tool_secboot_image);
fclose(fpsec);
return -3;
}
fpimg = fopen(image, "rb");
if (NULL == fpimg)
{
wm_tool_printf("open img file error [%s].\r\n", image);
fclose(fpsec);
return -4;
}
magic_word = 0;
readlen = fread(&magic_word, 1, 4, fpimg);
if (magic_word != WM_TOOL_IMG_HEAD_MAGIC_NO)
{
wm_tool_printf("input [%s] file magic error.\r\n", image);
fclose(fpsec);
fclose(fpimg);
return -5;
}
fout = fopen(outfile, "wb+");
if (NULL == fout)
{
wm_tool_printf("create img file error [%s].\r\n", outfile);
fclose(fpsec);
fclose(fpimg);
return -6;
}
fseek(fpsec, 0, SEEK_SET);
while (!feof(fpsec))
{
readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpsec);
fwrite(buf, 1, readlen, fout);
}
fseek(fpimg, 0, SEEK_SET);
while (!feof(fpimg))
{
readlen = fread(buf, 1, WM_TOOL_ONCE_READ_LEN, fpimg);
fwrite(buf, 1, readlen, fout);
}
if (fpsec)
{
fclose(fpsec);
}
if (fpimg)
{
fclose(fpimg);
}
if (fout)
{
fclose(fout);
}
wm_tool_printf("generate flash file completed.\r\n");
return 0;
}
static int wm_tool_gzip_bin(const char *binary, const char *gzbin)
{
#if 1
FILE *in;
gzFile out;
local char buf[BUFLEN];
int len;
in = fopen(binary, "rb");
if (in == NULL) {
perror(binary);
exit(1);
}
out = gzopen(gzbin, "wb9");
if (out == NULL) {
printf("can't gzopen %s\n", gzbin);
exit(1);
}
for (;;) {
len = (int)fread(buf, 1, sizeof(buf), in);
if (len < 0) {
printf("file read err\r\n");
exit(1);
}
if (len == 0) break;
if (gzwrite(out, buf, (unsigned)len) != len)
{
printf("gzip write wrong\r\n");
}
}
fclose(in);
if (gzclose(out) != Z_OK)
{
printf("failed gzclose");
}
#else
FILE *bfp;
gzFile gzfp;
int ret;
char buf[Z_BUFSIZE];
bfp = fopen(binary, "rb");
gzfp = gzopen((char *)gzbin, "wb+");
if (!bfp || !gzfp)
{
wm_tool_printf("can not gzip binary.\r\n");
return -1;
}
do {
ret = fread(buf, 1, sizeof(buf), bfp);
if (ret == 0)
{
printf("@@@@@@@@@@@@@ret:%d\n", ret);
break;
}
if (ret > 0)
{
ret = gzwrite(gzfp, (voidp)buf, ret);
if (ret <= 0)
{
wm_tool_printf("can not write gzip binary.\r\n");
return -2;
}
}
} while (ret > 0);
printf("====================================\n");
gzclose(gzfp);
fclose(bfp);
#endif
wm_tool_printf("compress binary completed.\r\n");
return 0;
}
static int wm_tool_pack_firmware(void)
{
int ret;
char *path;
char *name;
char *image;
char *gzbin;
char *gzimg;
char *dbgimg;
char *fls;
if (!wm_tool_input_binary)
return 1;
if (!wm_tool_output_image)
{
char *r = wm_tool_input_binary;
char *t = wm_tool_input_binary;
do
{
r = strchr(r, '.');
if (r)
{
t = r;
r++;
}
} while (r);
wm_tool_output_image = malloc(t - wm_tool_input_binary + 1);
if (!wm_tool_output_image)
return -1;
memcpy(wm_tool_output_image, wm_tool_input_binary, t - wm_tool_input_binary);
wm_tool_output_image[t - wm_tool_input_binary] = '\0';
}
char *p = wm_tool_output_image;
char *q = wm_tool_output_image;
do
{
p = strchr(p, '/');
if (p)
{
p++;
q = p;
}
} while (p);
/* output file */
name = strdup(q);
*q = '\0';
path = strdup(wm_tool_output_image);
image = malloc(strlen(path) + strlen(name) + strlen(".img") + 1);
if (!image)
return -1;
sprintf(image, "%s%s.img", path, name);
if (WM_TOOL_ZIP_TYPE_UNCOMPRESS == wm_tool_zip_type)
{
ret = wm_tool_pack_image(image);
if (ret)
return ret;
}
if (WM_TOOL_ZIP_TYPE_COMPRESS == wm_tool_zip_type)
{
gzbin = malloc(strlen(path) + strlen(name) + strlen("_gz.bin") + 1);
gzimg = malloc(strlen(path) + strlen(name) + strlen("_gz.img") + 1);
if (!gzbin || !gzimg)
return -1;
sprintf(gzbin, "%s%s.bin.gz", path, name);
sprintf(gzimg, "%s%s_gz.img", path, name);
ret = wm_tool_gzip_bin(wm_tool_input_binary, gzbin);
if (ret)
return ret;
ret = wm_tool_pack_gz_image(gzbin, gzimg);
free(gzbin);
free(gzimg);
if (ret)
return ret;
}
if (wm_tool_is_debug)
{
dbgimg = malloc(strlen(path) + strlen(name) + strlen("_dbg.img") + 1);
if (!dbgimg)
return -1;
sprintf(dbgimg, "%s%s_dbg.img", path, name);
ret = wm_tool_pack_dbg_image(image, dbgimg);
free(dbgimg);
if (ret)
return ret;
}
if (wm_tool_secboot_image)
{
fls = malloc(strlen(path) + strlen(name) + strlen(".fls") + 1);
if (!fls)
return -1;
sprintf(fls, "%s%s.fls", path, name);
ret = wm_tool_pack_fls(image, fls);
free(fls);
}
free(image);
return ret;
}
#ifdef __MINGW32__
static BOOL wm_tool_signal_proc(DWORD no)
{
switch (no)
{
case CTRL_C_EVENT:
wm_tool_signal_proc_entry();
return(FALSE);
default:
return FALSE;
}
}
static void wm_tool_signal_init(void)
{
SetConsoleCtrlHandler((PHANDLER_ROUTINE)wm_tool_signal_proc, TRUE);
}
static void wm_tool_delay_ms(int ms)
{
Sleep(ms);
return;
}
static int wm_tool_uart_set_rts(int boolflag)
{
return EscapeCommFunction(wm_tool_uart_handle,((boolflag) ? SETRTS : CLRRTS)) ? 0 : -1;
}
static int wm_tool_uart_set_dtr(int boolflag)
{
return EscapeCommFunction(wm_tool_uart_handle,((boolflag) ? SETDTR : CLRDTR)) ? 0 : -1;
}
static int wm_tool_uart_set_timeout(void)
{
BOOL ret;
COMMTIMEOUTS timeout;
timeout.ReadIntervalTimeout = MAXDWORD;
timeout.ReadTotalTimeoutConstant = 0;
timeout.ReadTotalTimeoutMultiplier = 0;
timeout.WriteTotalTimeoutConstant = 0;
timeout.WriteTotalTimeoutMultiplier = 0;
ret = SetCommTimeouts(wm_tool_uart_handle, &timeout);
if (ret)
ret = SetCommMask(wm_tool_uart_handle, EV_TXEMPTY);
return ret ? 0 : -1;
}
static void wm_tool_uart_set_block(int bolck)
{
if (bolck)
wm_tool_uart_block = INFINITE;
else
wm_tool_uart_block = 0;
return;
}
static int wm_tool_uart_set_speed(int speed)
{
int i;
int size;
DCB cfg;
size = sizeof(wm_tool_uart_speed_array) / sizeof(int);
for (i= 0; i < size; i++)
{
if (speed == wm_tool_uart_name_array[i])
{
if (GetCommState(wm_tool_uart_handle, &cfg))
{
cfg.DCBlength = sizeof(DCB);
cfg.BaudRate = wm_tool_uart_speed_array[i];
cfg.fBinary = TRUE;
cfg.fParity = FALSE;
cfg.fDtrControl = DTR_CONTROL_DISABLE;
cfg.fDsrSensitivity = FALSE;
cfg.fRtsControl = RTS_CONTROL_DISABLE;
cfg.ByteSize = 8;
cfg.StopBits = ONESTOPBIT;
cfg.fAbortOnError = FALSE;
cfg.fOutX = FALSE;
cfg.fInX = FALSE;
cfg.fErrorChar = FALSE;
cfg.fNull = FALSE;
cfg.fOutxCtsFlow = FALSE;
cfg.fOutxDsrFlow = FALSE;
cfg.Parity = NOPARITY;
cfg.fTXContinueOnXoff = FALSE;
return SetCommState(wm_tool_uart_handle, &cfg) ? 0 : -1;
}
else
{
return -3;
}
}
}
return -2;
}
static void wm_tool_uart_clear(void)
{
PurgeComm(wm_tool_uart_handle, PURGE_RXCLEAR);
return;
}
static int wm_tool_uart_open(const char *device)
{
BOOL ret;
char name[40];
sprintf(name,"\\\\.\\%s", device);
wm_tool_uart_handle = CreateFile(name, GENERIC_WRITE | GENERIC_READ,
0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
if (wm_tool_uart_handle == INVALID_HANDLE_VALUE)
{
return -1;
}
ret = SetupComm(wm_tool_uart_handle, 4096, 4096);
if (ret)
{
ret = wm_tool_uart_set_speed(WM_TOOL_DEFAULT_BAUD_RATE);
ret |= wm_tool_uart_set_timeout();
}
else
{
ret = -1;
}
return ret;
}
static int wm_tool_uart_read(void *data, unsigned int size)
{
BOOL ret;
DWORD wait;
unsigned long len = 0;
COMSTAT state;
DWORD error;
OVERLAPPED event;
do
{
memset(&event, 0, sizeof(OVERLAPPED));
event.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
ClearCommError(wm_tool_uart_handle, &error, &state);
ret = ReadFile(wm_tool_uart_handle, data, size, &len, &event);
if (!ret)
{
if (ERROR_IO_PENDING == GetLastError())
{
wait = WaitForSingleObject(event.hEvent, wm_tool_uart_block);
if (WAIT_OBJECT_0 == wait)
ret = TRUE;
}
}
} while (wm_tool_uart_block && !len);
if (ret)
{
if (len > 0)
return (int)len;
}
return -1;
}
static int wm_tool_uart_write(const void *data, unsigned int size)
{
BOOL ret;
DWORD wait;
OVERLAPPED event;
COMSTAT state;
DWORD error;
unsigned int snd = 0;
unsigned long len = 0;
memset(&event, 0, sizeof(OVERLAPPED));
event.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
do
{
ClearCommError(wm_tool_uart_handle, &error, &state);
ret = WriteFile(wm_tool_uart_handle, data + snd, size - snd, &len, &event);
if (!ret)
{
if (ERROR_IO_PENDING == GetLastError())
{
wait = WaitForSingleObject(event.hEvent, INFINITE);
if (WAIT_OBJECT_0 == wait)
ret = TRUE;
}
}
if (ret)
{
if ((len > 0) && (snd != size))
{
snd += len;
}
else
{
return size;
}
}
else
{
break;
}
} while (1);
return -1;
}
static void wm_tool_uart_close(void)
{
FlushFileBuffers(wm_tool_uart_handle);
CloseHandle(wm_tool_uart_handle);
wm_tool_uart_handle = NULL;
return;
}
static DWORD WINAPI wm_tool_uart_tx_thread(LPVOID arg)
{
wm_tool_stdin_to_uart();
return 0;
}
static int wm_tool_create_thread(void)
{
HANDLE thread_handle;
thread_handle = CreateThread(0, 0, wm_tool_uart_tx_thread, NULL, 0, NULL);
CloseHandle(thread_handle);
return 0;
}
#else
static void wm_tool_signal_proc(int no)
{
wm_tool_signal_proc_entry();
}
static void wm_tool_signal_init(void)
{
signal(SIGINT, wm_tool_signal_proc);
}
static void wm_tool_delay_ms(int ms)
{
usleep(ms * 1000);
return;
}
static int wm_tool_uart_set_rts(int boolflag)
{
int ret;
int controlbits;
ret = ioctl(wm_tool_uart_fd, TIOCMGET, &controlbits);
if (ret < 0)
{
WM_TOOL_DBG_PRINT("TIOCMGET failed!\r\n");
return ret;
}
if (controlbits & TIOCM_RTS)
{
WM_TOOL_DBG_PRINT("TIOCM_RTS!, %d!\r\n", boolflag);
}
else
{
WM_TOOL_DBG_PRINT("~TIOCM_RTS!, %d!\r\n", boolflag);
}
if (boolflag)
controlbits |= TIOCM_RTS;
else
controlbits &= ~TIOCM_RTS;
ret = ioctl(wm_tool_uart_fd, TIOCMSET, &controlbits);
if (ret < 0)
{
WM_TOOL_DBG_PRINT("TIOCMSET failed!\r\n");
}
if (ret >= 0)
ret = 0;
return ret;
}
static int wm_tool_uart_set_dtr(int boolflag)
{
int ret;
int controlbits;
ret = ioctl(wm_tool_uart_fd, TIOCMGET, &controlbits);
if (ret < 0)
{
WM_TOOL_DBG_PRINT("TIOCMGET failed!\r\n");
return ret;
}
if (controlbits & TIOCM_DTR)
{
WM_TOOL_DBG_PRINT("TIOCM_DTR, %d!\r\n", boolflag);
}
else
{
WM_TOOL_DBG_PRINT("~TIOCM_DTR, %d!\r\n", boolflag);
}
if (boolflag)
controlbits |= TIOCM_DTR;
else
controlbits &= ~TIOCM_DTR;
ret = ioctl(wm_tool_uart_fd, TIOCMSET, &controlbits);
if (ret < 0)
{
WM_TOOL_DBG_PRINT("TIOCMSET failed!\r\n");
}
if (ret >= 0)
ret = 0;
return ret;
}
static void wm_tool_uart_set_block(int bolck)
{
int comopt;
comopt = fcntl(wm_tool_uart_fd, F_GETFL, 0);
if (bolck)
fcntl(wm_tool_uart_fd, F_SETFL, comopt & ~O_NDELAY);
else
fcntl(wm_tool_uart_fd, F_SETFL, comopt | O_NDELAY);
return;
}
static int wm_tool_uart_set_speed(int speed)
{
int i;
int size;
int status = -1;
struct termios opt;
tcgetattr(wm_tool_uart_fd, &opt);
size = sizeof(wm_tool_uart_speed_array) / sizeof(int);
for (i= 0; i < size; i++)
{
if (speed == wm_tool_uart_name_array[i])
{
cfsetispeed(&opt, wm_tool_uart_speed_array[i]);
cfsetospeed(&opt, wm_tool_uart_speed_array[i]);
status = tcsetattr(wm_tool_uart_fd, TCSANOW, &opt);
break;
}
}
return status;
}
static void wm_tool_uart_clear(void)
{
tcflush(wm_tool_uart_fd, TCIFLUSH);
return;
}
static int wm_tool_uart_open(const char *device)
{
struct termios tty;
wm_tool_uart_fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
if (-1 == wm_tool_uart_fd)
{
return -1;
}
tcgetattr(wm_tool_uart_fd, &wm_tool_saved_serial_cfg);
wm_tool_uart_set_dtr(0);
tcgetattr(wm_tool_uart_fd, &tty);
/* databit 8bit */
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
/* set into raw, no echo mode */
tty.c_iflag = IGNBRK;
tty.c_lflag = 0;
tty.c_oflag = 0;
tty.c_cflag |= CLOCAL | CREAD;
tty.c_cflag &= ~CRTSCTS;
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 5;
/* have no software flow control */
tty.c_iflag &= ~(IXON|IXOFF|IXANY);
/* parity none */
tty.c_cflag &= ~(PARENB | PARODD);
/* stopbit 1bit */
tty.c_cflag &= ~CSTOPB;
tcsetattr(wm_tool_uart_fd, TCSANOW, &tty);
return wm_tool_uart_set_speed(WM_TOOL_DEFAULT_BAUD_RATE);
}
static int wm_tool_uart_read(void *data, unsigned int size)
{
return read(wm_tool_uart_fd, data, size);
}
static int wm_tool_uart_write(const void *data, unsigned int size)
{
int snd = 0;
int ret = 0;
do
{
ret = write(wm_tool_uart_fd, data + snd, size - snd);
if (ret > 0)
{
snd += ret;
if (snd == size)
{
return size;
}
}
else
{
break;
}
} while (1);
return -1;
}
static void wm_tool_uart_close(void)
{
tcsetattr(wm_tool_uart_fd, TCSANOW, &wm_tool_saved_serial_cfg);
tcdrain(wm_tool_uart_fd);
tcflush(wm_tool_uart_fd, TCIOFLUSH);
close(wm_tool_uart_fd);
wm_tool_uart_fd = -1;
return;
}
static void *wm_tool_uart_tx_thread(void *arg)
{
wm_tool_stdin_to_uart();
return NULL;
}
static int wm_tool_create_thread(void)
{
pthread_t thread_id;
return pthread_create(&thread_id, NULL, wm_tool_uart_tx_thread, NULL);
}
#endif
static void wm_tool_signal_proc_entry(void)
{
WM_TOOL_DBG_PRINT("signal exit.\r\n");
exit(0);
}
static void wm_tool_stdin_to_uart(void)
{
int ret;
char buf[WM_TOOL_ONCE_READ_LEN];
while (1)
{
if (fgets(buf, WM_TOOL_ONCE_READ_LEN, stdin))
{
ret = wm_tool_uart_write(buf, strlen(buf));
if (ret <= 0)
{
WM_TOOL_DBG_PRINT("failed to write [%s].\r\n", buf);
}
}
}
return;
}
static int wm_tool_show_log_from_serial(void)
{
int i;
int ret;
unsigned int j = 0;
unsigned char buf[WM_TOOL_ONCE_READ_LEN + 1];
ret = wm_tool_uart_open(wm_tool_serial_path);
if (ret)
{
wm_tool_printf("can not open serial\r\n");
return ret;
}
if (WM_TOOL_DEFAULT_BAUD_RATE != wm_tool_normal_serial_rate)
{
ret = wm_tool_uart_set_speed(wm_tool_normal_serial_rate);
if (ret)
{
wm_tool_printf("can not set serial baud rate.\r\n");
wm_tool_uart_close();
return ret;
}
}
ret = wm_tool_create_thread();
if (ret)
{
wm_tool_printf("can not create thread.\r\n");
wm_tool_uart_close();
return ret;
}
wm_tool_uart_set_block(0);
wm_tool_signal_init();
while (1)
{
ret = wm_tool_uart_read(buf, WM_TOOL_ONCE_READ_LEN);
if (ret > 0)
{
if (WM_TOOL_SHOW_LOG_STR == wm_tool_show_log_type)
{
buf[ret] = '\0';
wm_tool_printf("%s", (char *)buf);
}
else if (WM_TOOL_SHOW_LOG_HEX == wm_tool_show_log_type)
{
for (i = 0; i < ret; i++, j++)
{
wm_tool_printf("%02X ", buf[i]);
if ((j + 1) % 16 == 0)
{
wm_tool_printf("\r\n");
}
}
}
else
{
break;
}
}
else
{
wm_tool_delay_ms(1);
}
}
wm_tool_uart_close();
return ret;
}
static int wm_tool_set_wifi_chip_speed(int speed)
{
int ret;
if (2000000 == speed)
{
ret = wm_tool_uart_write(wm_tool_chip_cmd_b2000000, sizeof(wm_tool_chip_cmd_b2000000));
}
else if (1000000 == speed)
{
ret = wm_tool_uart_write(wm_tool_chip_cmd_b1000000, sizeof(wm_tool_chip_cmd_b1000000));
}
else if (921600 == speed)
{
ret = wm_tool_uart_write(wm_tool_chip_cmd_b921600, sizeof(wm_tool_chip_cmd_b921600));
}
else if (460800 == speed)
{
ret = wm_tool_uart_write(wm_tool_chip_cmd_b460800, sizeof(wm_tool_chip_cmd_b460800));
}
else
{
ret = wm_tool_uart_write(wm_tool_chip_cmd_b115200, sizeof(wm_tool_chip_cmd_b115200));
}
return ret;
}
static int wm_tool_send_esc2uart(int ms)
{
int i;
int err = 0;
unsigned char esc_key = 27;
for (i = 0; i < (ms / 10); i++)
{
err = wm_tool_uart_write(&esc_key, 1);
wm_tool_delay_ms(10);/* 10-50ms */
}
return err;
}
static int wm_tool_erase_image(wm_tool_dl_erase_e type)
{
int cnt = 0;
int ret = -1;
unsigned char ch;
unsigned char rom_cmd[] = {0x21, 0x0a, 0x00, 0xc3, 0x35, 0x32, 0x00, 0x00, 0x00, 0x02, 0x00, 0xfe, 0x01}; /*2M-8k*/
WM_TOOL_DBG_PRINT("start erase.\r\n");
if (WM_TOOL_DL_ERASE_ALL == type)
{
wm_tool_printf("erase flash...\r\n");
ret = wm_tool_uart_write(rom_cmd, sizeof(rom_cmd));
}
if (ret <= 0)
return -1;
wm_tool_uart_clear();
wm_tool_uart_set_block(1);
do
{
ret = wm_tool_uart_read(&ch, 1);
if (ret > 0)
{
if (('C' == ch) || ('P' == ch))
cnt++;
else
cnt = 0;
}
else
{
wm_tool_printf("erase error, errno = %d.\r\n", errno);
return -2;
}
} while (cnt < 3);
wm_tool_uart_set_block(0);
wm_tool_printf("erase finish.\r\n");
return 0;
}
static int wm_tool_query_mac(void)
{
int ret = -1;
int err;
int offset = 0;
char macstr[32] = {0};
int len = strlen("MAC:AABBCCDDEEFF\n");/* resp format, ROM "Mac:AABBCCDDEEFF\n", SECBOOT "MAC:AABBCCDDEEFF\n" */
unsigned char macaddr[6] = {0};
wm_tool_uart_clear();
wm_tool_uart_set_block(1);
err = wm_tool_uart_write(wm_tool_chip_cmd_get_mac, sizeof(wm_tool_chip_cmd_get_mac));
if (err > 0)
{
do
{
err = wm_tool_uart_read((unsigned char *)(macstr + offset), sizeof(macstr) - 1 - offset);
if (err > 0)
{
offset += err;
if (offset >= len)
{
macstr[len - 1] = '\0';/* \n -> 0 */
err = wm_tool_str_to_hex_array(macstr + strlen("MAC:"), 6, macaddr);
if (!err)
{
wm_tool_printf("mac %02X-%02X-%02X-%02X-%02X-%02X.\r\n", macaddr[0],
macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]);
if (!strncmp(macstr, "Mac:", strlen("Mac:")) &&
(WM_TOOL_DL_TYPE_FLS != wm_tool_dl_type) &&
!wm_tool_dl_erase)
{
wm_tool_printf("please download the firmware in .fls format.\r\n");
}
else
{
ret = 0;
}
}
break;
}
}
} while (err > 0);
}
wm_tool_uart_set_block(0);
return ret;
}
static int wm_tool_xmodem_download(const char *image)
{
FILE *imgfp;
unsigned char packet_data[XMODEM_DATA_SIZE];
unsigned char frame_data[XMODEM_DATA_SIZE + XMODEM_CRC_SIZE + XMODEM_FRAME_ID_SIZE + 1];
int complete, retry_num, pack_counter, read_number, write_number = 0, i;
unsigned short crc_value;
unsigned char ack_id;
int sndlen;
int ret = -111;
imgfp = fopen(image, "rb");
if (!imgfp)
{
wm_tool_printf("can not open image to download.\r\n");
return -1;
}
sndlen = 0;
pack_counter = 0;
complete = 0;
retry_num = 0;
wm_tool_printf("start download.\r\n");
wm_tool_printf("0%% [");
wm_tool_uart_clear();
wm_tool_uart_set_block(1);
ack_id = XMODEM_ACK;
while (!complete)
{
WM_TOOL_DBG_PRINT("switch ack_id = %x\r\n", ack_id);
switch(ack_id)
{
case XMODEM_ACK:
{
retry_num = 0;
pack_counter++;
read_number = fread(packet_data, sizeof(char), XMODEM_DATA_SIZE, imgfp);
WM_TOOL_DBG_PRINT("fread = %d\r\n", read_number);
if (read_number > 0)
{
sndlen += read_number;
if (read_number < XMODEM_DATA_SIZE)
{
WM_TOOL_DBG_PRINT("start filling the last frame!\r\n");
for ( ; read_number < XMODEM_DATA_SIZE; read_number++)
packet_data[read_number] = 0x0;
}
frame_data[0] = XMODEM_HEAD;
frame_data[1] = (char)pack_counter;
frame_data[2] = (char)(255 - frame_data[1]);
for (i = 0; i < XMODEM_DATA_SIZE; i++)
frame_data[i + 3] = packet_data[i];
crc_value = wm_tool_get_crc16(packet_data, XMODEM_DATA_SIZE);
frame_data[XMODEM_DATA_SIZE + 3]=(unsigned char)(crc_value >> 8);
frame_data[XMODEM_DATA_SIZE + 4]=(unsigned char)(crc_value);
write_number = wm_tool_uart_write(frame_data, XMODEM_DATA_SIZE + 5);
if (write_number <= 0)
wm_tool_printf("write serial error, errno = %d.\r\n", errno);
WM_TOOL_DBG_PRINT("waiting for ack, %d, %d ...\r\n", pack_counter, write_number);
while ((wm_tool_uart_read(&ack_id, 1)) <= 0);
if (ack_id == XMODEM_ACK)
{
WM_TOOL_DBG_PRINT("Ok!\r\n");
if (sndlen % 10240 == 0)
{
wm_tool_printf("#");
}
}
else
{
WM_TOOL_DBG_PRINT("error = %x!\r\n", ack_id);
}
}
else
{
ack_id = XMODEM_EOT;
complete = 1;
WM_TOOL_DBG_PRINT("waiting for complete ack ...\r\n");
while (ack_id != XMODEM_ACK)
{
ack_id = XMODEM_EOT;
write_number = wm_tool_uart_write(&ack_id, 1);
if (write_number <= 0)
wm_tool_printf("write serial error, errno = %d.\r\n", errno);
while ((wm_tool_uart_read(&ack_id, 1)) <= 0);
}
WM_TOOL_DBG_PRINT("ok\r\n");
wm_tool_printf("] 100%%\r\n");
wm_tool_printf("download completed.\r\n");
ret = 0;
}
break;
}
case XMODEM_NAK:
{
if ( retry_num++ > 100)
{
WM_TOOL_DBG_PRINT("retry too many times, quit!\r\n");
wm_tool_printf("download firmware timeout.\r\n");
complete = 1;
}
else
{
write_number = wm_tool_uart_write(frame_data, XMODEM_DATA_SIZE + 5);
if (write_number <= 0)
wm_tool_printf("write serial error, errno = %d.\r\n", errno);
WM_TOOL_DBG_PRINT("retry for ack, %d, %d ...\r\n", pack_counter, write_number);
while ((wm_tool_uart_read(&ack_id, 1)) <= 0);
if (ack_id == XMODEM_ACK)
{
WM_TOOL_DBG_PRINT("ok\r\n");
}
else
{
WM_TOOL_DBG_PRINT("error!\r\n");
}
}
break;
}
default:
{
WM_TOOL_DBG_PRINT("fatal error!\r\n");
WM_TOOL_DBG_PRINT("unknown xmodem protocal [%x].\r\n", ack_id);
wm_tool_printf("\r\ndownload failed, please reset and try again.\r\n");
complete = 1;
break;
}
}
}
wm_tool_uart_set_block(0);
fclose(imgfp);
return ret;
}
static int wm_tool_download_firmware(void)
{
int ret;
int cnt = 0;
int note = 1;
int timeout = 0;
float timeuse;
time_t start, end;
unsigned char ch;
wm_tool_printf("connecting serial...\r\n");
ret = wm_tool_uart_open(wm_tool_serial_path);
if (ret)
{
wm_tool_printf("can not open serial\r\n");
return ret;
}
/* In some cases, setting the serial port initialization setting requires a delay. */
wm_tool_delay_ms(500);
wm_tool_printf("serial connected.\r\n");
if (WM_TOOL_DL_ACTION_AT == wm_tool_dl_action)
{
if (WM_TOOL_DEFAULT_BAUD_RATE != wm_tool_normal_serial_rate)
wm_tool_uart_set_speed(wm_tool_normal_serial_rate);
#if 0 /* use erase option */
if (WM_TOOL_DL_TYPE_FLS == wm_tool_dl_type)
{
ret = wm_tool_uart_write("AT+&FLSW=8002000,0\r\n", strlen("AT+&FLSW=8002000,0\r\n"));
if (ret <= 0)
{
wm_tool_printf("destroy secboot failed.\r\n");
wm_tool_uart_close();
return -3;
}
wm_tool_delay_ms(300);
}
#endif
ret = wm_tool_uart_write("AT+Z\r\n", strlen("AT+Z\r\n"));
if (ret <= 0)
{
wm_tool_printf("reset error.\r\n");
wm_tool_uart_close();
return -4;
}
if (WM_TOOL_DEFAULT_BAUD_RATE != wm_tool_normal_serial_rate)
wm_tool_uart_set_speed(WM_TOOL_DEFAULT_BAUD_RATE);
}
else if (WM_TOOL_DL_ACTION_RTS == wm_tool_dl_action)
{
ret = wm_tool_uart_set_dtr(0);
ret |= wm_tool_uart_set_rts(1);
wm_tool_delay_ms(50);
ret |= wm_tool_uart_set_dtr(1);
ret |= wm_tool_uart_set_rts(0);
wm_tool_delay_ms(50);
ret |= wm_tool_uart_set_dtr(0);
if (ret < 0)
{
wm_tool_printf("set rts to reboot error.\r\n");
wm_tool_uart_close();
return -5;
}
}
wm_tool_printf("wait serial sync...");
wm_tool_send_esc2uart(500);/* used for delay */
start = time(NULL);
do
{
ret = wm_tool_uart_read(&ch, 1);
WM_TOOL_DBG_PRINT("ret=%d, %x-%c\r\n", ret, ch, ch);
if (ret > 0)
{
if (('C' == ch) || ('P' == ch))
cnt++;
else
cnt = 0;
}
else
{
wm_tool_send_esc2uart(30);
}
end = time(NULL);
timeuse = difftime(end, start);
if (timeuse >= 1)
{
wm_tool_printf(".");
timeout++;
if ((timeout >= (WM_TOOL_DOWNLOAD_TIMEOUT_SEC / 10)) && note)
{
wm_tool_printf("\r\nplease manually reset the device.\r\n");
note = 0;
}
else if (timeout > WM_TOOL_DOWNLOAD_TIMEOUT_SEC)
{
wm_tool_uart_close();
wm_tool_printf("\r\nserial sync timeout.\r\n");
return -6;
}
start = time(NULL);
}
} while (cnt < 3);
wm_tool_printf("\r\nserial sync sucess.\r\n");
ret = wm_tool_query_mac();
if (ret)
{
wm_tool_uart_close();
wm_tool_printf("download failed.\r\n");
return ret;
}
if (WM_TOOL_DL_ERASE_ALL == wm_tool_dl_erase)
{
ret = wm_tool_erase_image(WM_TOOL_DL_ERASE_ALL);
if (ret)
{
wm_tool_uart_close();
wm_tool_printf("failed to erase.\r\n");
return ret;
}
}
if (!wm_tool_download_image && wm_tool_dl_erase)
{
return 0;
}
if (WM_TOOL_DEFAULT_BAUD_RATE != wm_tool_download_serial_rate)
{
ret = wm_tool_set_wifi_chip_speed(wm_tool_download_serial_rate);
if (ret > 0)
{
wm_tool_delay_ms(1 * 1000);
wm_tool_uart_set_speed(wm_tool_download_serial_rate);
}
}
ret = wm_tool_xmodem_download(wm_tool_download_image);
if (WM_TOOL_DEFAULT_BAUD_RATE != wm_tool_download_serial_rate)
{
wm_tool_delay_ms(1 * 1000);
wm_tool_set_wifi_chip_speed(WM_TOOL_DEFAULT_BAUD_RATE);
wm_tool_delay_ms(1 * 1000);
}
if (!ret)
{
if (WM_TOOL_DL_TYPE_FLS == wm_tool_dl_type)
{
if (WM_TOOL_DL_ACTION_RTS == wm_tool_dl_action)/* auto reset */
{
wm_tool_uart_set_dtr(0);
wm_tool_uart_set_rts(1);
wm_tool_delay_ms(50);
wm_tool_uart_set_dtr(1);
wm_tool_uart_set_rts(0);
wm_tool_delay_ms(50);
wm_tool_uart_set_dtr(0);
}
else
{
wm_tool_printf("please manually reset the device.\r\n");
}
}
}
wm_tool_uart_close();
return ret;
}
static void wm_tool_show_local_com(void)
{
#if defined(__APPLE__) && defined(__MACH__)
char *comstr = "tty.usbserial";
#elif defined(__CYGWIN__)
int num;
char *comstr = "ttyS";
#elif defined(__linux__)
char *comstr = "ttyUSB";
#endif
#if defined(__APPLE__) || defined(__MACH__) || defined(__CYGWIN__) || defined(__linux__)
DIR *dir;
struct dirent *file;
dir = opendir("/dev");
if (dir)
{
while (NULL != (file = readdir(dir)))
{
if ((0 == strncmp(file->d_name, comstr, strlen(comstr))) && (DT_CHR == file->d_type))
{
#if defined(__CYGWIN__)
num = atoi(file->d_name + strlen(comstr));
wm_tool_printf("COM%d ", num + 1);
#else
wm_tool_printf("%s ", file->d_name);
#endif
}
}
closedir(dir);
wm_tool_printf("\r\n");
}
#elif defined(__MINGW32__)
LONG ret;
HKEY key;
DWORD i = 0;
DWORD knlen;
char kname[WM_TOOL_PATH_MAX] = {0};
DWORD kvlen;
char kvalue[WM_TOOL_PATH_MAX] = {0};
REGSAM kmask = KEY_READ;
#if defined(KEY_WOW64_64KEY)
BOOL is_64;
if (IsWow64Process(GetCurrentProcess(), &is_64))
{
if (is_64)
kmask |= KEY_WOW64_64KEY;
}
#endif
ret = RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, NULL, 0, kmask, NULL, &key, NULL);
if (ret != ERROR_SUCCESS)
{
return;
}
do{
knlen = sizeof(kname);
kvlen = sizeof(kvalue);
ret = RegEnumValue(key, i, kname, &knlen, 0, NULL, (LPBYTE)kvalue, &kvlen);
if (ret == ERROR_SUCCESS)
{
if (strcmp(kvalue, "") != 0)
{
wm_tool_printf("%s ", kvalue);
}
}
i++;
} while (ret != ERROR_NO_MORE_ITEMS);
RegCloseKey(key);
wm_tool_printf("\r\n");
#else
wm_tool_printf("\r\nunsupported system.\r\n");
#endif
return;
}
static void wm_tool_free_res(void)
{
if (wm_tool_download_image)
free(wm_tool_download_image);
if (wm_tool_output_image)
free(wm_tool_output_image);
if (wm_tool_input_binary)
free(wm_tool_input_binary);
if (wm_tool_secboot_image)
free(wm_tool_secboot_image);
return;
}
int main(int argc, char *argv[])
{
int ret = 0;
if (!wm_tool_parse_arv(argc, argv))
{
wm_tool_print_usage(argv[0]);
wm_tool_free_res();
return 0;
}
if (wm_tool_show_usage)
{
wm_tool_print_usage(argv[0]);
wm_tool_free_res();
return 0;
}
if (wm_tool_show_ver)
{
wm_tool_print_version(argv[0]);
wm_tool_free_res();
return 0;
}
if (wm_tool_list_com)
{
wm_tool_show_local_com();
wm_tool_free_res();
return 0;
}
if (wm_tool_input_binary)
{
ret = wm_tool_pack_firmware();
}
if (wm_tool_download_image || wm_tool_dl_erase)
{
ret = wm_tool_download_firmware();
}
if (wm_tool_show_log_type)
{
ret = wm_tool_show_log_from_serial();
}
if (ret > 0)
wm_tool_print_usage(argv[0]);
wm_tool_free_res();
return ret;
}