Reinhard Russinger 2 gadi atpakaļ
vecāks
revīzija
241b242721

+ 16 - 0
board/PSG/iot2050/rootfs/etc/tinc/psgnet/hosts/PSG_IOT2050_98

@@ -0,0 +1,16 @@
+#--- automatisch erstellt
+Subnet = 10.222.0.98/32
+
+-----BEGIN RSA PUBLIC KEY-----
+MIICCgKCAgEA5goFVzD8whGdu27f9lcYqzmO4V/0x0VxvHkmaWNXLCMORnO1PrQT
+Se3NPZ+v+ze510xQDkTPAGo7x5tNJUTxLE/QS59lJwzAl+nZ+EOr3e+0rPp25Hm0
+XjG/or2twn2lnRxhc+1PeokBHegUhq3/y5rqEmC+rwhmQWiUZXYln9OOIV/3n4qa
+wAZJy+7mniTtPRmYqF2+TwwD89kyyqaSaX6hPzzQE7B2u0N8uX5VvI65Jeu6gwTY
+NVOTurXaaFxN3gEF0hAupE5nirKGdnoWUHn5RsXlZBGNSnTx4qRv2BiPvSA4mje0
+99wbdlMdu3g8OmbyN9r8Yc/sm12q6V0/Zmh5bP5RdXkioCmWXO8rXEriQGXSw/G7
+lsK2izDNnq47L/ixUT9G0Aw3vWTpvQKP65xPAOjTDPklcvbjaRLpLZ3OCqvAwAF/
+BaZ126uHZA7Xn2nQrA9q1ur2EQey6TNcRNxmb0S7CZtGWVLQw/2iblWLTS3HdGhF
+WI+Qyd3HIHLaaI2BmEqm1S9Tl++GnrdwwjN175CBf0M8LYsDwaIRAXhAlG3Wc2Or
+HnKcU+wPMennxEuueNU3tcGMxGUAWQmQRH3eA8LGoL/cEtO3SqaZ2YM9MWAqFB3I
+wk05dPruZr9eR4Y50PP61nhrqYTaGpji+Mix77MdxHXNJGw4L/7cOHkCAwEAAQ==
+-----END RSA PUBLIC KEY-----

+ 16 - 0
board/PSG/iot2050/rootfs/etc/tinc/psgnet/hosts/psgnet

@@ -0,0 +1,16 @@
+Address = gogs.psg-bgh.de 756
+Subnet = 10.222.0.1/32
+
+-----BEGIN RSA PUBLIC KEY-----
+MIICCgKCAgEA0C7f+XIVcIJ0hHPkLXQ2HSAsqRBGuZBND3opPEI9IlR13HemSpIT
+N0ME4guB94I6RyUyTu/JhHzwUUFNnD/3OtEu3fPmmyjPUk0+nhsvoaqN9JBT/U9/
+ujgziNR5N1l6m/51FDU0dryOLASgnyWEPr7ozesrUcZxV12iAdspa2zsDMoLBhbC
+/ro2pqp0cSNzsuWhV2qEXiJEoTIU71t6t0cvWpXzwGSqUPxxJuQ74I0Xx7q/6eFm
+jy44x7L5OX/EIqanSUoQ+pFCit7Vdb1CNU+s6OWnxA9dxxWdVfCkB9CrPbto4o8t
+R6qbA2Y8F5hOAdeEYD/rpqAs/WcvNxiMtK0Zkr1sJIQv9ujY6dwCv9LShsEtCJkk
+F4eYuak2kGStWBQmpbCBqAleglt9pI7azzBi4Dt/17O4qQZJLjJuaT6TOc2cx8+s
+D24x3mUwpsYhUNx19/e5IYlJZSQhJNHUa212LT+7dmjwkAoUGZ2ZUIjWUpOBAPXJ
+K2FAunOOPd5HImIKz3ST6zHTy9L0xnGSK4K52//bfsOnpo4pGtu5ERWqU+66gjyq
+MJLBKcajRP9JZIyFvHgJYBE1LFo4e7hs4SHf3hon8TptcuVcL5ANQm8ZXyQH5riL
+Sxx0a9uhkBFpLcvy1VIWgtyYyFDe+4PyXAP+CPvkJc69PuIibN9Vk+ECAwEAAQ==
+-----END RSA PUBLIC KEY-----

+ 52 - 0
board/PSG/iot2050/rootfs/etc/tinc/psgnet/rsa_key.priv

@@ -0,0 +1,52 @@
+
+-----BEGIN RSA PRIVATE KEY-----
+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
+-----END RSA PRIVATE KEY-----

+ 2 - 0
board/PSG/iot2050/rootfs/etc/tinc/psgnet/tinc-down

@@ -0,0 +1,2 @@
+#!/bin/sh
+ifconfig $INTERFACE down

+ 2 - 0
board/PSG/iot2050/rootfs/etc/tinc/psgnet/tinc-up

@@ -0,0 +1,2 @@
+#!/bin/sh
+ifconfig $INTERFACE 10.222.0.98 netmask 255.255.0.0

+ 6 - 0
board/PSG/iot2050/rootfs/etc/tinc/psgnet/tinc.conf

@@ -0,0 +1,6 @@
+Name = PSG_IOT2050_98
+AddressFamily = ipv4
+Interface = tun5
+Port = 756
+Mode = switch
+ConnectTo = psgnet

+ 1 - 1
configs/iot2050_V2_defconfig

@@ -33,6 +33,7 @@ BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="../PSG/board/PSG/iot2050/files/iot2050_d
 BR2_LINUX_KERNEL_DTS_SUPPORT=y
 BR2_LINUX_KERNEL_DTS_SUPPORT=y
 BR2_LINUX_KERNEL_INTREE_DTS_NAME="ti/k3-am6528-iot2050-basic-pg2"
 BR2_LINUX_KERNEL_INTREE_DTS_NAME="ti/k3-am6528-iot2050-basic-pg2"
 BR2_LINUX_KERNEL_DTB_KEEP_DIRNAME=y
 BR2_LINUX_KERNEL_DTB_KEEP_DIRNAME=y
+BR2_LINUX_KERNEL_DTB_OVERLAY_SUPPORT=y
 BR2_LINUX_KERNEL_INSTALL_TARGET=y
 BR2_LINUX_KERNEL_INSTALL_TARGET=y
 BR2_PACKAGE_BUSYBOX_CONFIG="../PSG/board/PSG/iot2050/busybox.config"
 BR2_PACKAGE_BUSYBOX_CONFIG="../PSG/board/PSG/iot2050/busybox.config"
 BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
 BR2_PACKAGE_BUSYBOX_SHOW_OTHERS=y
@@ -315,4 +316,3 @@ BR2_PACKAGE_HOST_MTOOLS=y
 BR2_PACKAGE_HOST_UBOOT_TOOLS=y
 BR2_PACKAGE_HOST_UBOOT_TOOLS=y
 BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT=y
 BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT=y
 BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT_SOURCE="../PSG/board/PSG/iot2050/boot.cmd"
 BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT_SOURCE="../PSG/board/PSG/iot2050/boot.cmd"
-# BR2_PACKAGE_SWITCHSERIALMODE is not set

+ 4 - 6
package/switchserialmode/src/Makefile

@@ -3,15 +3,13 @@ rcdir = .
 CC = $(CROSS_COMPILE)gcc 
 CC = $(CROSS_COMPILE)gcc 
 CPP = $(CROSS_COMPILE)gcc -E
 CPP = $(CROSS_COMPILE)gcc -E
 
 
-#LIBS = -lgpiod -lusb-1.0 
-LIBS =  -lusb-1.0
-CFLAGS =  -I $(SYSROOTARM)/usr/include -I ./
-##LDFLAGS = -L $(SYSROOTARM)/usr/lib -L $(SYSROOTARM)/lib
+LIBS = -lgpiod -lusb-1.0 
+CFLAGS = -I ./
 #---------------------------------------------
 #---------------------------------------------
 PROGNAME = switchserialmode
 PROGNAME = switchserialmode
 #---------------------------------------------
 #---------------------------------------------
 
 
-OBJECTS = $(PROGNAME).o gpio_helper.o serial/cp2102n.o serial/omap_8250.o transceiver/sp339e.o
+OBJECTS = $(PROGNAME).o
 all:    $(PROGNAME)
 all:    $(PROGNAME)
 
 
 $(PROGNAME): $(OBJECTS) 
 $(PROGNAME): $(OBJECTS) 
@@ -21,4 +19,4 @@ $(PROGNAME): $(OBJECTS)
 	$(CC) $(CFLAGS) -c $<  -o $(basename $<).o
 	$(CC) $(CFLAGS) -c $<  -o $(basename $<).o
 
 
 clean:
 clean:
-	rm -f $(OBJECTS) switchserialmode core *.gdb *.o *~
+	rm -f $(OBJECTS) $(PROGNAME) core *.gdb *.o *~

BIN
package/switchserialmode/src/gpio_helper


+ 0 - 34
package/switchserialmode/src/gpio_helper.c

@@ -1,34 +0,0 @@
-/*
- * Copyright (c) Siemens AG, 2019-2022
- *
- * Authors:
- *  Gao Nian <nian.gao@siemens.com>
- *  Chao Zeng <chao.zeng@siemens.com>
- *
- * This file is subject to the terms and conditions of the MIT License.  See
- * COPYING.MIT file in the top-level directory.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <gpiod.h>
-#include <string.h>
-#include "gpio_helper.h"
-
-void gpio_set(const uint8_t *line_name, uint32_t value)
-{
-    struct gpiod_line *line;
-
-    line = gpiod_line_find(line_name);
-    if (!line) {
-        printf("Unable to find GPIO line %s\n", line_name);
-        return;
-    }
-
-    if (gpiod_line_request_output(line, "switchserialmode", value) < 0) {
-        perror("gpiod_line_request_output");
-    }
-
-    gpiod_line_release(line);
-    gpiod_line_close_chip(line);
-}

+ 0 - 7
package/switchserialmode/src/gpio_helper.h

@@ -1,7 +0,0 @@
-#ifndef GPIOHELPER
-#define GPIOHELPER
-
-#include <stdint.h>
-
-void gpio_set(const uint8_t *line_name, uint32_t value);
-#endif

BIN
package/switchserialmode/src/gpio_helper.o


BIN
package/switchserialmode/src/serial/cp2102n


+ 0 - 366
package/switchserialmode/src/serial/cp2102n.c

@@ -1,366 +0,0 @@
-/*
- * Copyright (c) Siemens AG, 2019-2022
- *
- * Authors:
- *  Gao Nian <nian.gao@siemens.com>
- *  Chao Zeng <chao.zeng@siemens.com>
- *
- * This file is subject to the terms and conditions of the MIT License.  See
- * COPYING.MIT file in the top-level directory.
- */
-
-#include <string.h>
-#include <unistd.h>
-#include <termios.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <libusb-1.0/libusb.h>
-#include <stdarg.h>
-#include <assert.h>
-#include "gpio_helper.h"
-#include "switchserialmode.h"
-
-#define MAIN_GPIO_CONTROL_1_INDEX      600
-#define CP2102N_RS485_BIT              4
-#define MAIN_GPIO_CONTROL_2_INDEX      601
-#define CP2102N_RS485_LOGIC_BIT        0
-#define CP2102N_RS485_SETUP_INDEX      669
-#define CP2102N_RS485_HOLD_INDEX       671
-#define MAIN_RESET_LATCH_P1_INDEX      587
-#define CP2102N_GPIO2_RESET_LATH_BIT   5
-
-#define CP2102N_MAX_CONFIG_LENGTH      0x02a6
-
-#define IS_CP2102N_RS485PIN_RS485_MODE(config)    ((config)[MAIN_GPIO_CONTROL_1_INDEX] \
-                                                            & (1 << CP2102N_RS485_BIT))
-#define IS_CP2102N_RS485PIN_RS485_LOGIC(config)   (config[MAIN_GPIO_CONTROL_2_INDEX] \
-                                                            & (1 << CP2102N_RS485_LOGIC_BIT))
-#define GET_CP2102N_GPIO2_RESET_LATH(config)   (config[MAIN_RESET_LATCH_P1_INDEX] \
-                                                            & (uint8_t)(1 << CP2102N_GPIO2_RESET_LATH_BIT))
-#define GET_CP2102N_RS485_SETUP_TIME(config)   (((config[CP2102N_RS485_SETUP_INDEX] << 8) & 0xff00)\
-                                                            | (config[CP2102N_RS485_SETUP_INDEX + 1] & 0xff))
-#define GET_CP2102N_RS485_HOLD_TIME(config)   (((config[CP2102N_RS485_HOLD_INDEX] << 8) & 0xff00) \
-                                                            | (config[CP2102N_RS485_HOLD_INDEX + 1] & 0xff))
-
-typedef struct cp2102n_conf_ops {
-    uint8_t deviceConf[CP2102N_MAX_CONFIG_LENGTH];
-    uint16_t confCheckSum;
-    libusb_device_handle *usbHandle;
-    /*cfg update function*/
-    void (*cfg_rs485_setup_time)(struct cp2102n_conf_ops *conf, uint32_t timeVal);
-    void (*cfg_rs485_hold_time)(struct cp2102n_conf_ops *conf, uint32_t timeVal);
-    void (*cfg_rs485pin_to_gpio)(struct cp2102n_conf_ops *conf);
-    void (*cfg_rs485pin_to_rs485)(struct cp2102n_conf_ops *conf);
-    void (*cfg_rs485_logic)(struct cp2102n_conf_ops *conf, uint8_t logic);
-    void (*cfg_rs485pin_gpio_reset_level)(struct cp2102n_conf_ops *conf, uint8_t rstLogic);
-} cp2102n_conf_ops_t;
-
-static cp2102n_conf_ops_t *cp2102n_cfg_operation = NULL;
-
-static void cfg_cp2102n_rs485_setup_time(struct cp2102n_conf_ops *conf, uint32_t timeVal)
-{
-    conf->deviceConf[CP2102N_RS485_SETUP_INDEX] = (uint8_t)(((timeVal) >> 8) & 0xff);
-    conf->deviceConf[CP2102N_RS485_SETUP_INDEX + 1] = (uint8_t)((timeVal) & 0xff);
-}
-
-static void cfg_cp2102n_rs485_hold_time(struct cp2102n_conf_ops *conf, uint32_t timeVal)
-{
-    conf->deviceConf[CP2102N_RS485_HOLD_INDEX] = (uint8_t)(((timeVal) >> 8) & 0xff);
-    conf->deviceConf[CP2102N_RS485_HOLD_INDEX + 1] = (uint8_t)((timeVal) & 0xff);
-}
-
-static void cfg_cp2102n_rs485pin_to_gpio(struct cp2102n_conf_ops *conf)
-{
-    conf->deviceConf[MAIN_GPIO_CONTROL_1_INDEX] &= (uint8_t)(~(1 << CP2102N_RS485_BIT));
-}
-
-static void cfg_cp2102n_rs485pin_to_rs485(struct cp2102n_conf_ops *conf)
-{
-    conf->deviceConf[MAIN_GPIO_CONTROL_1_INDEX] |= (uint8_t)(1 << CP2102N_RS485_BIT);
-}
-
-static void cfg_cp2102n_rs485_logic(struct cp2102n_conf_ops *conf, uint8_t logic)
-{
-    if (logic)
-        conf->deviceConf[MAIN_GPIO_CONTROL_2_INDEX] |= (uint8_t)(1 << CP2102N_RS485_LOGIC_BIT);
-    else
-        conf->deviceConf[MAIN_GPIO_CONTROL_2_INDEX] &= (uint8_t)(~(1 << CP2102N_RS485_LOGIC_BIT));
-}
-
-static void cfg_cp2102n_rs485pin_gpio_reset_level(struct cp2102n_conf_ops *conf, uint8_t rstLogic)
-{
-    if(rstLogic)
-        conf->deviceConf[MAIN_RESET_LATCH_P1_INDEX] |= (uint8_t)(1 << CP2102N_GPIO2_RESET_LATH_BIT);
-    else
-        conf->deviceConf[MAIN_RESET_LATCH_P1_INDEX] &= (uint8_t)(~(1 << CP2102N_GPIO2_RESET_LATH_BIT));
-}
-
-static int8_t cp2102n_read_config(struct cp2102n_conf_ops *conf)
-{
-    assert(conf->usbHandle);
-    uint32_t rlen = libusb_control_transfer(conf->usbHandle, 0xC0, 0xFF,
-                                            0x0E, /* wValue */
-                                            0, /* WIndex */
-                                            conf->deviceConf, /* data */
-                                            CP2102N_MAX_CONFIG_LENGTH, /* data size */
-                                            0);
-
-    return (rlen == CP2102N_MAX_CONFIG_LENGTH) ? SUCCESS : ERROR;
-}
-
-static int8_t cp2102n_write_config_to_device(struct cp2102n_conf_ops *conf)
-{
-    assert(conf->usbHandle);
-    uint32_t wlen = libusb_control_transfer(conf->usbHandle, 0x40, 0xFF,
-                                            0x370F, /* wValue */
-                                            0, /* WIndex */
-                                            conf->deviceConf, /* data */
-                                            CP2102N_MAX_CONFIG_LENGTH, /* data size */
-                                            0);
-
-    return (wlen == CP2102N_MAX_CONFIG_LENGTH) ? SUCCESS : ERROR;
-}
-
-static int8_t find_on_board_cp2102n(libusb_device *device)
-{
-    /*
-        On iot2050 board cp2102n locate at 1.4
-     */
-    #define ROOT_HUB_PORT 1
-    #define INTERMINATE_HUB_PORT 4
-    uint8_t port_numbers[7];
-
-    int r = libusb_get_port_numbers(device, port_numbers, 7);
-    if (r != 2)
-        return ERROR;
-
-    if ((ROOT_HUB_PORT == port_numbers[0]) &&
-        INTERMINATE_HUB_PORT == port_numbers[1]) {
-        return SUCCESS;
-    }
-
-    printf("No matched cp2102n\n");
-    return ERROR;
-}
-
-static int8_t cp2102n_open(struct cp2102n_conf_ops *conf)
-{
-    libusb_device **list = NULL;
-    libusb_device *found = NULL;
-    uint8_t i;
-    const uint8_t numOfUSBDevices = libusb_get_device_list(NULL, &list);
-
-    if (numOfUSBDevices < 0) {
-        printf("Libusb_get_device_list error");
-        goto error;
-    }
-
-    for ( i = 0; i < numOfUSBDevices; i++) {
-        if (!find_on_board_cp2102n(list[i])) {
-            found = list[i];
-            break;
-        }
-    }
-
-    if (found) {
-        if (libusb_open(found, &(conf->usbHandle))) {
-            printf("Open usb failed\n");
-            goto error;
-        }
-    } else {
-        printf("No matched device found\n");
-        goto error;
-    }
-
-    libusb_free_device_list(list, 1);
-    return SUCCESS;
-
-error:
-    libusb_free_device_list(list, 1);
-    return ERROR;
-
-}
-
-static void cp2102n_close(struct cp2102n_conf_ops *conf)
-{
-    if(NULL != conf->usbHandle) {
-        libusb_close(conf->usbHandle);
-    }
-}
-
-/* cp210x checksum caculate method */
-static uint16_t fletcher16(const uint8_t *bytes, uint16_t len)
-{
-    uint16_t sum1 = 0xff, sum2 = 0xff;
-    uint16_t tlen = 0;
-
-    while (len) {
-        tlen = len >= 20 ? 20 : len;
-        len -= tlen;
-        do {
-                sum2 += sum1 += *bytes++;
-        } while (--tlen);
-        sum1 = (sum1 & 0xff) + (sum1 >> 8);
-        sum2 = (sum2 & 0xff) + (sum2 >> 8);
-    }
-    /* Second reduction step to reduce sums to 8 bits */
-    sum1 = (sum1 & 0xff) + (sum1 >> 8);
-    sum2 = (sum2 & 0xff) + (sum2 >> 8);
-    return sum2 << 8 | sum1;
-}
-
-static int8_t write_config_to_device(struct cp2102n_conf_ops *conf)
-{
-    uint16_t checkSumNew = fletcher16(conf -> deviceConf, CP2102N_MAX_CONFIG_LENGTH - 2);
-    uint8_t deviceConf[CP2102N_MAX_CONFIG_LENGTH] = {0};
-    if (conf -> confCheckSum != checkSumNew) {
-        //update checksum
-        conf->deviceConf[CP2102N_MAX_CONFIG_LENGTH - 2] = (uint8_t)((checkSumNew >> 8) & 0xff);
-        conf->deviceConf[CP2102N_MAX_CONFIG_LENGTH - 1] = (uint8_t)((checkSumNew) & 0xff);
-        if(SUCCESS != cp2102n_write_config_to_device(conf)) {
-            printf("cp2102n_write_config_to_device failed\n");
-            return ERROR;
-        }
-
-        memcpy(deviceConf, conf->deviceConf, CP2102N_MAX_CONFIG_LENGTH);
-        cp2102n_read_config(conf);
-        if (memcmp(deviceConf, conf->deviceConf, CP2102N_MAX_CONFIG_LENGTH)) {
-            printf("Write configuration failed\n");
-            return ERROR;
-        }
-    }
-    return SUCCESS;
-} 
-
-static void cp2102n_hardware_reset(void)
-{
-    /*
-        reset device to take effective right now
-        for pg1 advanced board,there is no wire connect to reset pin.reset would not work.
-        for later baord, hardware reset can take effective.
-    */
-    if (ADVANCED_BOARD_PG1 != get_board_type()) {
-        gpio_set("CP2102N-RESET", 0);
-        usleep(30 * 1000);
-        gpio_set("CP2102N-RESET", 1);
-        sleep(1);
-    }
-}
-
-static void cp2102n_set_rs485_setup_time(uint8_t setuptime)
-{
-    cp2102n_cfg_operation->cfg_rs485_setup_time(cp2102n_cfg_operation, setuptime);
-}
-
-static void cp2102n_set_rs485_hold_time(uint8_t holdtime)
-{
-    cp2102n_cfg_operation->cfg_rs485_hold_time(cp2102n_cfg_operation, holdtime);
-}
-
-static void print_cfg(uint8_t *devConf)
-{
-    if (IS_CP2102N_RS485PIN_RS485_MODE((devConf))) {
-        printf("Rs485 active-logic(%s) setup-time(0x%04x) hold-time(0x%04x)\n"
-                        , IS_CP2102N_RS485PIN_RS485_LOGIC(devConf) ? "high" : "low"
-                        , GET_CP2102N_RS485_SETUP_TIME(devConf)
-                        , GET_CP2102N_RS485_HOLD_TIME(devConf));
-    }
-    else {
-        printf("Gpio reset-logic(%s)\n", GET_CP2102N_GPIO2_RESET_LATH(devConf) ? "high" : "low");
-    }
-}
-
-static void cp2102n_print_mode(void)
-{
-    print_cfg(cp2102n_cfg_operation->deviceConf);
-}
-
-static void cp2102n_switch_mode(uint8_t *mode)
-{
-    if (0 == strcasecmp(mode, "rs232")) {
-        cp2102n_cfg_operation->cfg_rs485pin_to_gpio(cp2102n_cfg_operation);
-        cp2102n_cfg_operation->cfg_rs485pin_gpio_reset_level(cp2102n_cfg_operation, 0);
-    }
-    else if (0 == strcasecmp(mode, "rs422")) {
-        cp2102n_cfg_operation->cfg_rs485pin_to_gpio(cp2102n_cfg_operation);
-        cp2102n_cfg_operation->cfg_rs485pin_gpio_reset_level(cp2102n_cfg_operation, 1);
-    }
-    else if(0 == strcasecmp(mode, "rs485")) {
-        cp2102n_cfg_operation->cfg_rs485pin_to_rs485(cp2102n_cfg_operation);
-        cp2102n_cfg_operation->cfg_rs485_logic(cp2102n_cfg_operation, 1);
-    }
-}
-
-static int8_t cp2102_ops_init(struct cp2102n_conf_ops **conf)
-{
-    if (cp2102n_open(*conf)) {
-        printf("Open usb device failed\n");
-        return ERROR;
-    }
-
-    if (cp2102n_read_config(*conf)) {
-        printf("Read config failed\n");
-        return ERROR;
-    }
-
-    (*conf)->confCheckSum = fletcher16((*conf)->deviceConf, CP2102N_MAX_CONFIG_LENGTH - 2);
-    (*conf)->cfg_rs485_setup_time = cfg_cp2102n_rs485_setup_time;
-    (*conf)->cfg_rs485_hold_time = cfg_cp2102n_rs485_hold_time;
-    (*conf)->cfg_rs485_logic = cfg_cp2102n_rs485_logic;
-    (*conf)->cfg_rs485pin_gpio_reset_level = cfg_cp2102n_rs485pin_gpio_reset_level;
-    (*conf)->cfg_rs485pin_to_gpio = cfg_cp2102n_rs485pin_to_gpio;
-    (*conf)->cfg_rs485pin_to_rs485 = cfg_cp2102n_rs485pin_to_rs485;
-
-    return SUCCESS;
-}
-
-static int8_t cp2102n_init(uint8_t *deviceNode)
-{
-    libusb_init(NULL);
-
-    cp2102n_cfg_operation = (cp2102n_conf_ops_t *)malloc(sizeof(cp2102n_conf_ops_t));
-    memset(cp2102n_cfg_operation, 0, sizeof(cp2102n_conf_ops_t));
-
-    if (cp2102_ops_init(&cp2102n_cfg_operation)) {
-        printf("Cp2102n init falied\n");
-        return ERROR;
-    }
-
-    return SUCCESS;
-}
-
-static void cp2102n_release()
-{
-    int8_t ret = write_config_to_device(cp2102n_cfg_operation);
-    cp2102n_close(cp2102n_cfg_operation);
-    free(cp2102n_cfg_operation);
-    cp2102n_cfg_operation = NULL;
-    libusb_exit(NULL);
-    if (SUCCESS == ret)
-        cp2102n_hardware_reset();
-}
-
-static void cp2102n_pre_process(void *data)
-{
-    platform_t *preProcess = (platform_t *)data;
-    if (preProcess->private_data) {
-        controller_setting_t *privData = (controller_setting_t *)(preProcess->private_data);
-        if ((0 == GET_CP2102N_RS485_SETUP_TIME(cp2102n_cfg_operation->deviceConf)) ||
-            (0 == GET_CP2102N_RS485_HOLD_TIME(cp2102n_cfg_operation->deviceConf))) {
-            cfg_cp2102n_rs485_setup_time(cp2102n_cfg_operation, privData->setup_time);
-            cfg_cp2102n_rs485_hold_time(cp2102n_cfg_operation, privData->hold_time);
-        }
-    }
-}
-
-serial_ops_t cp210x_ops = {
-    .devName = "cp2102n24",
-    .init = cp2102n_init,
-    .setMode = cp2102n_switch_mode,
-    .getMode = cp2102n_print_mode,
-    .rs485HoldTime = cp2102n_set_rs485_hold_time,
-    .rs485SetupTime = cp2102n_set_rs485_setup_time,
-    .release = cp2102n_release,
-    .preProcess = cp2102n_pre_process,
-};

BIN
package/switchserialmode/src/serial/cp2102n.o


BIN
package/switchserialmode/src/serial/omap_8250


+ 0 - 153
package/switchserialmode/src/serial/omap_8250.c

@@ -1,153 +0,0 @@
-/*
- * Copyright (c) Siemens AG, 2019-2022
- *
- * Authors:
- *  Gao Nian <nian.gao@siemens.com>
- *  Chao Zeng <chao.zeng@siemens.com>
- *
- * This file is subject to the terms and conditions of the MIT License.  See
- * COPYING.MIT file in the top-level directory.
- */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <termios.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <string.h>
-#include <linux/serial.h>
-#include <linux/types.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include "switchserialmode.h"
-
-
-#define GET_UART_RTS_ACTIVE_LOGIC(flags)  (!((flags) & SER_RS485_RTS_ON_SEND))
-
-typedef struct omap_8250 {
-    struct serial_rs485 r485Conf;
-    int32_t uartHandle;
-    int8_t (*ttyuart_set_rs485conf)(struct omap_8250 *);
-} omap_8250_ops_t;
-
-omap_8250_ops_t omap_8250_ops;
-
-static int8_t ttyuart_get_rs485conf(struct omap_8250 *ops)
-{
-    int32_t ret = ioctl(ops->uartHandle, TIOCGRS485, &(ops->r485Conf));
-    if (ret < 0) {
-        perror("Error");
-        return ERROR;
-    }
-
-    return SUCCESS;
-}
-
-static int8_t ttyuart_set_rs485conf(struct omap_8250 *ops)
-{
-    int32_t ret = ioctl(ops->uartHandle, TIOCSRS485, ops->r485Conf);
-    if (ret < 0) {
-        perror("Error");
-        return ERROR;
-    }
-
-    return SUCCESS;
-}
-
-static int8_t ttyuart_init(uint8_t *uartdev)
-{
-    int32_t fd = open(uartdev, O_RDWR);
-    if (fd < 0) {
-        printf("Open tty uart failed\n");
-        return ERROR;
-    }
-
-    omap_8250_ops.uartHandle = fd;
-    omap_8250_ops.ttyuart_set_rs485conf = ttyuart_set_rs485conf;
-
-    if (SUCCESS != ttyuart_get_rs485conf(&omap_8250_ops)) {
-        printf("Get configuration fail\n");
-        return ERROR;
-    }
-
-    return SUCCESS;
-}
-
-static void ttyuart_release(void)
-{
-    /*write conf to the device*/
-    if (SUCCESS != omap_8250_ops.ttyuart_set_rs485conf(&omap_8250_ops)) {
-        printf("Set configuration fail\n");
-    }
-
-    close(omap_8250_ops.uartHandle);
-}
-
-static void ttyuart_print_mode(void)
-{
-    const uint8_t *mode = NULL;
-    const uint8_t *activelogic = NULL;
-    struct serial_rs485 rs485Conf = omap_8250_ops.r485Conf;
-
-    if (!(rs485Conf.flags & SER_RS485_ENABLED)) {
-        mode = "rs232";
-        activelogic = "";
-    }
-    else {
-        if (rs485Conf.flags & SER_RS485_RX_DURING_TX) {
-            mode = "rs422";
-            activelogic = "";
-        }
-        else {
-            mode = "rs485";
-            activelogic = GET_UART_RTS_ACTIVE_LOGIC(rs485Conf.flags) ? "active-logic(high)" \
-                                                                        : "active-logic(low)";
-        }
-    }
-
-    printf("%s %s\n", mode, activelogic);
-}
-
-static void ttyuart_switch_mode(uint8_t *mode)
-{
-    struct serial_rs485 *rs485Conf = (struct serial_rs485 *)&(omap_8250_ops.r485Conf);
-    memset(rs485Conf, 0, sizeof(rs485Conf));
-    /*
-        The latest kernel has already handle these flags.Its could be deleted.
-        For the previous compatability, keep this settings
-    */
-    rs485Conf->flags &= ~(SER_RS485_RTS_ON_SEND);
-    rs485Conf->flags |= (SER_RS485_RTS_AFTER_SEND);
-
-    if (0 == strcasecmp(mode, "rs485")) {
-        rs485Conf->flags |= SER_RS485_ENABLED;
-    }
-    else if (0 == strcasecmp(mode, "rs422")) {
-        rs485Conf->flags |= SER_RS485_ENABLED | SER_RS485_RX_DURING_TX;
-    }
-    else if (0 == strcasecmp(mode, "rs232")) {
-        memset(rs485Conf, 0, sizeof(rs485Conf));
-    }
-}
-
-static void ttyuart_set_rs485_hold_time(uint8_t holdtime)
-{
-    printf("Set RS485 hold time not supported\n");
-}
-
-static void ttyuart_set_rs485_setup_time(uint8_t holdtime)
-{
-    printf("Set RS485 setup time not supported\n");
-}
-
-serial_ops_t ttyuart_ops = {
-    .devName = "/dev/ttyX30",
-    .init = ttyuart_init,
-    .rs485HoldTime = ttyuart_set_rs485_hold_time,
-    .rs485SetupTime = ttyuart_set_rs485_setup_time,
-    .setMode = ttyuart_switch_mode,
-    .getMode = ttyuart_print_mode,
-    .release = ttyuart_release,
-};

BIN
package/switchserialmode/src/serial/omap_8250.o


+ 1200 - 112
package/switchserialmode/src/switchserialmode.c

@@ -1,171 +1,1259 @@
 /*
 /*
- * Copyright (c) Siemens AG, 2019-2022
+ * Copyright (c) Siemens AG, 2019
  *
  *
  * Authors:
  * Authors:
  *  Gao Nian <nian.gao@siemens.com>
  *  Gao Nian <nian.gao@siemens.com>
- *  Chao Zeng <chao.zeng@siemens.com>
  *
  *
  * This file is subject to the terms and conditions of the MIT License.  See
  * This file is subject to the terms and conditions of the MIT License.  See
  * COPYING.MIT file in the top-level directory.
  * COPYING.MIT file in the top-level directory.
  */
  */
+
+#include <linux/serial.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <termios.h>
 #include <stdbool.h>
 #include <stdbool.h>
 #include <stdlib.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdio.h>
-#include <getopt.h>
 #include <string.h>
 #include <string.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include "switchserialmode.h"
+#include <malloc.h>
+#include <libusb-1.0/libusb.h>
+#include <gpiod.h>
+#include <stdarg.h>
+
+typedef unsigned char   BYTE;
+typedef unsigned int    UINT;
+typedef unsigned short  U16;
+
+typedef enum _E_STATUS {
+    e_SUCCESS                 = 0x00,
+    e_IO_ERROR                = 0x01,
+
+    e_DEVICE_NOT_FOUND        = 0xFF
+} E_STATUS;
+
+#define ERROR(msg, ...)    printf("ERROR: "msg"\n", ##__VA_ARGS__);
+
+typedef enum{
+    e_case_sensitive = 0,
+    e_case_insensitive
+}E_CASE_SENSITIVE;
+
+#define MUTIL_THREAD   100
+
+static char *format(const char *fmt, ...)
+{
+    #define MAX_STRING_SIZE   128
+
+    static char string[MUTIL_THREAD][MAX_STRING_SIZE] = {{0,0}};
+
+    static int cnt = 0;
+    if(cnt == MUTIL_THREAD)
+    {
+        cnt = 0;
+    }
+
+    memset((char *)&string[cnt][0], 0, MAX_STRING_SIZE);
+
+    va_list ap;
+    va_start(ap, fmt);
+    vsprintf((char *)&string[cnt][0], fmt, ap);
+    va_end(ap);
+
+    char *ptr = (char *)&string[cnt][0];
+    cnt++;
+
+    return ptr;
+}
+
+static char **split(const char *string, const char *delimiter, int *num)
+{
+    #define MAX_SECTION   20
+    static char *args[MUTIL_THREAD][MAX_SECTION] = {{0,0}};
+
+    #define BUF_SIZE   256
+    static char buf[MUTIL_THREAD][BUF_SIZE] = {{0,0}};
+
+    static int count = 0;
+    if(count == MUTIL_THREAD)
+    {
+        count = 0;
+    }
+
+    memset((char *)&buf[count][0], 0, BUF_SIZE);
+    memcpy((char *)&buf[count][0], string, strlen(string));
+
+    int i = 0;
+    char *p = strtok((char *)&buf[count][0], delimiter);
+    while(NULL != p)
+    {
+        args[count][i++] = p;
+        p = strtok(NULL, delimiter);
+    }
+
+    if(NULL != num)
+    {
+        *num = i;
+    }
+
+    char **ptr = &args[count][0];
+    count++;
+
+    return ptr;
+}
+
+#define ARG(fmt, ...)   split(format(fmt, ##__VA_ARGS__), " ", NULL)
+
+static bool compare_string(const char *dest, const char *arg, const E_CASE_SENSITIVE casesensitive)
+{
+    const char *DELIMITER = ",";
+
+    int num = 0;
+    char **list = split(arg, DELIMITER, &num);
+
+    int i = 0;
+    for(i = 0; i < num; i++)
+    {
+        if(casesensitive == e_case_sensitive)
+        {
+            if(0 == strncmp(list[i], dest, strlen(dest)))
+            {
+                return true;
+            }
+        }
+        else
+        {
+            if(0 == strcasecmp(list[i], dest))
+            {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+static bool check_arg(int argc, char **argv, const char *name, const E_CASE_SENSITIVE casesensitive)
+{
+    for(int i = 0; i < argc; i++)
+    {
+        if(compare_string(argv[i], name, casesensitive))
+        {
+            return true;
+        }
+    }
 
 
-extern serial_ops_t ttyuart_ops;
-extern serial_ops_t cp210x_ops;
-extern transceiver_ops_t sp339e_ops;
+    return false;
+}
+
+static int get_arg_int(int argc, char **argv, const char *name, const E_CASE_SENSITIVE casesensitive, int defaultValue)
+{
+    for(int i = 0; i < argc; i++)
+    {
+        if(compare_string(argv[i], name, casesensitive)
+            && ((i + 1) < argc)
+            && ('-' != argv[i + 1][0]))
+        {
+            return strtol(argv[i + 1], NULL, 0);
+        }
+    }
+
+    return defaultValue;
+}
+
+static char *get_arg_string(int argc, char **argv, const char *name, const E_CASE_SENSITIVE casesensitive, char *defaultValue)
+{
+    for(int i = 0; i < argc; i++)
+    {
+        if(compare_string(argv[i], name, casesensitive)
+            && ((i + 1) < argc))
+        {
+            return argv[i + 1];
+        }
+    }
+
+    return defaultValue;
+}
+
+
+#define   LEN(a)   (sizeof(a)/sizeof((a)[0]))
+
+void gpio_set(const char *line_name, int value)
+{
+    struct gpiod_line *line;
+
+    line = gpiod_line_find(line_name);
+    if (!line) {
+        ERROR("Unable to find GPIO line %s", line_name);
+        return;
+    }
+
+    if (gpiod_line_request_output(line, "switchserialmode", value) < 0) {
+        perror("gpiod_line_request_output");
+    }
+
+    gpiod_line_release(line);
+    gpiod_line_close_chip(line);
+}
+
+static void gpio_set_mode(int mode0, int mode1)
+{
+    gpio_set("UART0-enable", 1);
+    gpio_set("UART0-mode0", mode0);
+    gpio_set("UART0-mode1", mode1);
+}
+
+static void gpio_set_terminate(int onoff)
+{
+    gpio_set("UART0-terminate", onoff);
+}
 
 
-static platform_t *curr_platform = NULL;
-static controller_setting_t default_setting = {0x5, 0x5};
+static void gpio_switch_mode(const char *mode, int terminate)
+{
+    if(compare_string(mode, "rs232", e_case_insensitive))
+    {
+        gpio_set_mode(1, 0);
+        gpio_set_terminate(0);
+    }
+    else if(compare_string(mode, "rs485", e_case_insensitive))
+    {
+        gpio_set_mode(0, 1);
+        gpio_set_terminate(terminate);
+    }
+    else if(compare_string(mode, "rs422", e_case_insensitive))
+    {
+        gpio_set_mode(1, 1);
+        gpio_set_terminate(terminate);
+    }
+}
+
+
+#ifndef SER_RS485_TERMINATE_BUS
+#define SER_RS485_TERMINATE_BUS     (1 << 5)
+#endif
 
 
-boardType_e get_board_type(void)
+#define SET_UART_RTS_ACTIVE_LOGIC(flags, logic)  \
+    do{\
+        if(logic){\
+            flags &= ~(SER_RS485_RTS_ON_SEND);   \
+            flags |= (SER_RS485_RTS_AFTER_SEND); \
+        }else{\
+            flags |= (SER_RS485_RTS_ON_SEND);     \
+            flags &= ~(SER_RS485_RTS_AFTER_SEND);}\
+    }while(0)
+
+#define GET_UART_RTS_ACTIVE_LOGIC(flags)  (!((flags) & SER_RS485_RTS_ON_SEND))
+
+static E_STATUS ttyuart_get_rs485conf(const char *uartdev, struct serial_rs485 *pcfg)
 {
 {
-    int32_t ret;
-    const uint8_t *modelPath = "/proc/device-tree/model";
-    uint8_t recvBuf[30] = {0};
-    int32_t fd = open(modelPath, O_RDONLY);
+    int fd = open(uartdev, O_RDWR);
+    if(fd < 0)
+    {
+        ERROR("open %s failed", uartdev);
+        return e_IO_ERROR;
+    }
+
+    int ret = ioctl(fd, TIOCGRS485, pcfg);
+    if(ret < 0)
+    {
+        perror("Error");
+    }
+
+    close(fd);
+    return 0 == ret ? e_SUCCESS : e_IO_ERROR;
+}
+
+static void ttyuart_print_mode(const char *uartdev)
+{
+    struct serial_rs485 rs485conf;
+
+    if(e_SUCCESS != ttyuart_get_rs485conf(uartdev, &rs485conf))
+    {
+        return;
+    }
+
+    const char *mode = NULL;
+    const char *activelogic = NULL;
+    const char *terminate = NULL;
 
 
-    if (fd  < 0) {
-       perror("Get tye error");
-       return ERROR;
+    if(!(rs485conf.flags & SER_RS485_ENABLED))
+    {
+        mode = "rs232";
+        activelogic = "";
+        terminate = "";
+    }
+    else
+    {
+        if(rs485conf.flags & SER_RS485_RX_DURING_TX)
+        {
+            mode = "rs422";
+            activelogic = "";
+        }
+        else
+        {
+            mode = "rs485";
+            activelogic = GET_UART_RTS_ACTIVE_LOGIC(rs485conf.flags) ? "active-logic(high)" : "active-logic(low)";
+        }
+
+        if(rs485conf.flags & SER_RS485_TERMINATE_BUS)
+        {
+            terminate = "terminating";
+        }
+        else
+        {
+            terminate = "non-terminating";
+        }
     }
     }
 
 
-    ret = read(fd, recvBuf, 30);
-    if (ret < 0) {
+    printf("%s %s %s\n", mode, activelogic, terminate);
+}
+
+static E_STATUS ttyuart_set_rs485conf(const char *uartdev, struct serial_rs485 *pcfg)
+{
+    int fd = open(uartdev, O_RDWR);
+    if(fd < 0)
+    {
+        ERROR("open %s failed", uartdev);
+        return e_IO_ERROR;
+    }
+
+    int ret = ioctl(fd, TIOCSRS485, pcfg);
+    if(ret < 0)
+    {
         perror("Error");
         perror("Error");
     }
     }
+
     close(fd);
     close(fd);
+    return 0 == ret ? e_SUCCESS : e_IO_ERROR;
+}
 
 
-    if (0 == strcmp(recvBuf,"SIMATIC IOT2050 Advanced"))
-        return ADVANCED_BOARD_PG1;
-    else if (strstr(recvBuf,"Advanced"))
-        return ADVANCED_BOARD;
+static E_STATUS ttyuart_switchto_rs232(const char *uartdev)
+{
+    struct serial_rs485 rs485conf;
+    memset(&rs485conf, 0, sizeof(rs485conf));
 
 
-    return BASIC_BOARD;
+    return ttyuart_set_rs485conf(uartdev, &rs485conf);
 }
 }
 
 
-static void usage(void)
+static E_STATUS ttyuart_switchto_rs485(const char *uartdev, int logicLevel)
 {
 {
-    fprintf(stdout,
-        " -h, --help                     : display help information\n"
-        " -m, --mode                     : set serial work mode, the mode can be set 'rs232' 'rs422 'or 'rs485'.\n"
-        " -d, --display                  : display the current mode\n"
-        " -t, --terminator               : Terminate the RS422 or RS485 bus.\n"
-        " -s, --setup u16                : set rs485-pin's setup time in rs485 mode.\n"
-        " -o, --hold u16                 : set rs485-pin's hold time in rs485 mode.\n"
-    );
+    struct serial_rs485 rs485conf;
+    memset(&rs485conf, 0, sizeof(rs485conf));
+
+    SET_UART_RTS_ACTIVE_LOGIC(rs485conf.flags, logicLevel);
+
+    rs485conf.flags |= SER_RS485_ENABLED;
+
+    return ttyuart_set_rs485conf(uartdev, &rs485conf);
 }
 }
 
 
-static struct option serial_long_options[] = {
-    {"help", no_argument, NULL, 'h'},
-    {"mode", required_argument, NULL, 'm'},
-    {"display", no_argument, NULL, 'd'},
-    {"setup", required_argument, NULL, 's'},
-    {"hold", required_argument, NULL, 'o'},
-    {"terminator", no_argument, NULL, 't'},
-    { NULL, 0, NULL, 0}
-};
+static E_STATUS ttyuart_switchto_rs422(const char *uartdev, int logicLevel)
+{
+    struct serial_rs485 rs485conf;
+    memset(&rs485conf, 0, sizeof(rs485conf));
+
+    SET_UART_RTS_ACTIVE_LOGIC(rs485conf.flags, logicLevel);
 
 
-static void init_ops(void)
+    rs485conf.flags |= SER_RS485_ENABLED | SER_RS485_RX_DURING_TX;
+
+    return ttyuart_set_rs485conf(uartdev, &rs485conf);
+}
+
+const char * const TTYUART_USAGE = "\
+It's to operate tty serial device.\n\
+    -h,--help: display help information.\n\
+    -D,--device: specified device, like '/dev/ttyS1' etc.\n\
+    -m,--mode mode: set serial work mode, the mode can be set 'rs232' or 'rs485' or 'rs422'.\n\
+    -l,--logic level: set RTS-pin logic level when sending in rs485 mode, logic can be set '0' or '1'.\n\
+    -d,--display: display the current mode of ttyuart\n";
+
+static void ttyuart_command_handle(int argc, char **argv)
 {
 {
-    curr_platform = (platform_t *)malloc(sizeof(platform_t));
-    memset(curr_platform, 0, sizeof(platform_t));
+    if(check_arg(argc, argv, "-h,--help", e_case_sensitive))
+    {
+        printf("%s", TTYUART_USAGE);
+        return;
+    }
+
+    const char *devType = get_arg_string(argc, argv, "-D,--device", e_case_sensitive, NULL);
+    if(NULL == devType)
+    {
+        ERROR("parameter error, must specify serial device via '-D,--device'");
+        return;
+    }
 
 
-    if (get_board_type()) {
-        curr_platform->serOps = &cp210x_ops;
-        curr_platform->transOps = &sp339e_ops;;
-        curr_platform->private_data = (controller_setting_t*)&default_setting;
+    if(check_arg(argc, argv, "-d,--display", e_case_sensitive))
+    {
+        ttyuart_print_mode(devType);
+        return;
     }
     }
-    else {
-        curr_platform->serOps = &ttyuart_ops;
-        curr_platform->transOps = &sp339e_ops;
+
+    const char *mode = get_arg_string(argc, argv, "-m,--mode", e_case_sensitive, NULL);
+    if(NULL == mode)
+    {
+        ERROR("parameter error, must specify mode via '-m,--mode'");
+        return;
     }
     }
 
 
-    if (curr_platform->serOps->init(curr_platform->serOps->devName))
+    int logicLevel = get_arg_int(argc, argv, "-l,--logic", e_case_sensitive, 1);
+
+    if(0 == strcasecmp(mode, "rs232"))
     {
     {
-        printf("Init error\n");
-        exit(1);
+        ttyuart_switchto_rs232(devType);
+    }
+    else if(0 == strcasecmp(mode, "rs485"))
+    {
+        ttyuart_switchto_rs485(devType, logicLevel);
+    }
+    else if(0 == strcasecmp(mode, "rs422"))
+    {
+        ttyuart_switchto_rs422(devType, logicLevel);
+    }
+    else
+    {
+        ERROR("parameter error, don't support '%s'", mode);
     }
     }
 }
 }
 
 
-int main(int argc, char **argv)
+
+
+/* Device Part Numbers */
+typedef enum _SILABS_PARTNUM_CPXXXX {
+    CP210x_PARTNUM_UNKNOWN =  ((BYTE)(0xFF & 0x00)),
+    CP210x_PARTNUM_CP2101 = ((BYTE)(0xFF & 0x01)),
+    CP210x_PARTNUM_CP2102 = ((BYTE)(0xFF & 0x02)),
+    CP210x_PARTNUM_CP2103 = ((BYTE)(0xFF & 0x03)),
+    CP210x_PARTNUM_CP2104 = ((BYTE)(0xFF & 0x04)),
+    CP210x_PARTNUM_CP2105 = ((BYTE)(0xFF & 0x05)),
+    CP210x_PARTNUM_CP2108 = ((BYTE)(0xFF & 0x08)),
+    CP210x_PARTNUM_CP2109 = ((BYTE)(0xFF & 0x09)),
+
+    SILABS_PARTNUM_CP2110 = ((BYTE)(0xFF & 0x0A)),
+    HID_UART_PART_CP2110 = SILABS_PARTNUM_CP2110,
+
+    CP210x_PARTNUM_CP2112 = ((BYTE)(0xFF & 0x0C)),
+    HID_SMBUS_PART_CP2112 = CP210x_PARTNUM_CP2112,
+
+    SILABS_PARTNUM_CP2114 = ((BYTE)(0xFF & 0x0E)),
+    HID_UART_PART_CP2114 = SILABS_PARTNUM_CP2114,
+
+    CP210x_PARTNUM_CP2102N_QFN28 = ((BYTE)(0xFF & 0x20)),
+    CP210x_PARTNUM_CP2102N_QFN24 = ((BYTE)(0xFF & 0x21)),
+    CP210x_PARTNUM_CP2102N_QFN20 = ((BYTE)(0xFF & 0x22)),
+
+    CP210x_PARTNUM_USBXPRESS_F3XX = ((BYTE)(0xFF & 0x80)),
+    CP210x_PARTNUM_USBXPRESS_EFM8 = ((BYTE)(0xFF & 0x80)),
+    CP210x_PARTNUM_USBXPRESS_EFM32 = ((BYTE)(0xFF & 0x81))
+}SILABS_PARTNUM_CPXXXX;
+
+struct cp210x_info{
+    SILABS_PARTNUM_CPXXXX partnum;
+    const char * const name;
+};
+
+const struct cp210x_info cp210x_info_list[] = {
+    {CP210x_PARTNUM_CP2101, "CP2101"},
+    {CP210x_PARTNUM_CP2102, "CP2102"},
+    {CP210x_PARTNUM_CP2103, "CP2103"},
+    {CP210x_PARTNUM_CP2104, "CP2104"},
+    {CP210x_PARTNUM_CP2105, "CP2105"},
+    {CP210x_PARTNUM_CP2108, "CP2108"},
+    {CP210x_PARTNUM_CP2109, "CP2109"},
+
+    {SILABS_PARTNUM_CP2110, "CP2110"},
+    {CP210x_PARTNUM_CP2112, "CP2112"},
+    {SILABS_PARTNUM_CP2114, "CP2114"},
+
+    {CP210x_PARTNUM_CP2102N_QFN28, "CP2102N28"},
+    {CP210x_PARTNUM_CP2102N_QFN24, "CP2102N24"},
+    {CP210x_PARTNUM_CP2102N_QFN20, "CP2102N20"}};
+
+static libusb_context *g_LibusbContext = NULL;
+
+static const char *cp210x_find_name(SILABS_PARTNUM_CPXXXX partnum)
 {
 {
-    bool display_current_mode = false;
-    uint8_t *mode = NULL;
-    uint32_t setupTime = 0;
-    uint32_t holdTime = 0;
-    bool set_termination = false;
-    uint8_t *options = "hm:ds:o:t";
-    int32_t c;
-
-    /*parse parameter*/
-    while ((c = getopt_long(argc, argv, options,
-                serial_long_options, NULL)) != EOF) {
-    switch (c) {
-        case 'h':
-            usage();
-            exit(1);
-        case 'd':
-            display_current_mode = true;
-            break;
-        case 'm':
-            mode = strdup(optarg);
-            break;
-        case 's':
-            setupTime = atoi(optarg);
-            break;
-        case 'o':
-            holdTime = atoi(optarg);
-            break;
-        case 't':
-            set_termination = true;
+    for(int i = 0; i < sizeof(cp210x_info_list)/sizeof(cp210x_info_list[0]); i++)
+    {
+        if(cp210x_info_list[i].partnum == partnum)
+        {
+            return cp210x_info_list[i].name;
+        }
+    }
+
+    return NULL;
+}
+
+static SILABS_PARTNUM_CPXXXX cp210x_find_partnum(const char *name)
+{
+    for(int i = 0; i < sizeof(cp210x_info_list)/sizeof(cp210x_info_list[0]); i++)
+    {
+        if(0 == strcasecmp(cp210x_info_list[i].name, name))
+        {
+            return cp210x_info_list[i].partnum;
+        }
+    }
+
+    return CP210x_PARTNUM_UNKNOWN;
+}
+
+static bool is_valid_cp210x_partnum(const SILABS_PARTNUM_CPXXXX _v)
+{
+    return (((CP210x_PARTNUM_CP2101 <= _v) && (_v <= CP210x_PARTNUM_CP2105))
+                || (CP210x_PARTNUM_CP2108 == _v)
+                || (CP210x_PARTNUM_CP2109 == _v)
+                || (CP210x_PARTNUM_CP2112 == _v)
+                || ((CP210x_PARTNUM_CP2102N_QFN28 <= _v) && (_v <= CP210x_PARTNUM_CP2102N_QFN20))
+                || (CP210x_PARTNUM_USBXPRESS_F3XX == _v));
+}
+
+static bool cp210x_is_candidate_device(libusb_device *pdev)
+{
+    bool isCandidateDevice = false;   /* innocent til proven guilty */
+    struct libusb_device_descriptor devDesc;
+
+    if(0 != libusb_get_device_descriptor(pdev, &devDesc))
+    {
+        return isCandidateDevice;
+    }
+
+    switch(devDesc.bDeviceClass)
+    {
+        case LIBUSB_CLASS_PER_INTERFACE:  /* CP2102, CP2112,  */
+            if((1 == devDesc.iManufacturer) && (2 == devDesc.iProduct) && (3 <= devDesc.iSerialNumber))
+            {
+                struct libusb_config_descriptor *pconfigDesc = NULL;
+                isCandidateDevice = true;
+
+                if(0 == libusb_get_config_descriptor(pdev, 0, &pconfigDesc))
+                {
+                    if(pconfigDesc->bNumInterfaces
+                        && pconfigDesc->interface->num_altsetting
+                        && (LIBUSB_CLASS_VENDOR_SPEC != pconfigDesc->interface->altsetting->bInterfaceClass))
+                    {
+                        isCandidateDevice = false;
+                    }
+
+                    libusb_free_config_descriptor(pconfigDesc);
+                    pconfigDesc = (struct libusb_config_descriptor *)NULL;
+               }
+            }
             break;
             break;
+
         default:
         default:
-            printf("Operation not supported\n");
-            exit(1);
+            isCandidateDevice = false;
+            break;
+    }
+
+    return isCandidateDevice;
+}
+
+static E_STATUS cp210x_get_partnumber(libusb_device_handle *h, BYTE *partnum)
+{
+    int ret = libusb_control_transfer(h, 0xC0, 0xFF, 0x370B, 0x0000, partnum, 1, 7000);
+
+    if(1 == ret)
+    {
+        return e_SUCCESS;
+    }
+
+    if(LIBUSB_ERROR_TIMEOUT == ret)
+    {
+        ERROR("libusb_control_transfer timeout");
+        return e_IO_ERROR;
+    }
+
+    struct libusb_config_descriptor *configDesc = NULL;
+    E_STATUS status = e_IO_ERROR;
+
+    if(0 == libusb_get_config_descriptor(libusb_get_device(h), 0, &configDesc))
+    {
+        /* Looking for a very particular fingerprint to conclude the device is a CP2101 */
+        if ((configDesc->bNumInterfaces > 0)
+            && (configDesc->interface[0].altsetting->bNumEndpoints > 1)
+            && ((configDesc->interface[0].altsetting->endpoint[0].bEndpointAddress & 0x0F) == 0x03)
+            && ((configDesc->interface[0].altsetting->endpoint[1].bEndpointAddress & 0x0F) == 0x03))
+        {
+            *partnum = CP210x_PARTNUM_CP2101;
+            status = e_SUCCESS;
+        }
+
+        libusb_free_config_descriptor(configDesc);
+    }
+
+    return status;
+}
+
+static E_STATUS cp210x_read_config(libusb_device_handle *usbhd, BYTE *config, UINT len)
+{
+    UINT rlen = libusb_control_transfer(usbhd, 0xC0, 0xFF,
+                                                     0x0E, /* wValue */
+                                                        0, /* WIndex */
+                                                   config, /* data */
+                                                      len, /* data size */
+                                                        0);
+
+    return (rlen == len) ? e_SUCCESS : e_IO_ERROR;
+}
+
+static E_STATUS cp210x_write_config(libusb_device_handle *usbhd, BYTE *config, UINT len)
+{
+    UINT wlen = libusb_control_transfer(usbhd, 0x40, 0xFF,
+                                                   0x370F, /* wValue */
+                                                        0, /* WIndex */
+                                                   config, /* data */
+                                                      len, /* data size */
+                                                        0);
+
+    return (wlen == len) ? e_SUCCESS : e_IO_ERROR;
+}
+
+static int cp210x_list(const char **namelist, int len)
+{
+    libusb_device_handle *usbh = NULL;
+    libusb_device **list = NULL;
+
+    /* Enumerate all USB devices, returning the number of USB devices and a list of those devices */
+    const ssize_t numOfUSBDevices = libusb_get_device_list(g_LibusbContext, &list);
+
+    /* A negative count indicates an error */
+    if(numOfUSBDevices < 0)
+    {
+        ERROR("libusb_get_device_list error");
+        return 0;
+    }
+
+    int n = 0;
+
+    for(ssize_t i = 0; i < numOfUSBDevices; i++)
+    {
+        libusb_device *device = list[i];
+        libusb_device_handle *h = NULL;
+
+        if(cp210x_is_candidate_device(device) && (0 == libusb_open(list[i], &h)))
+        {
+            BYTE partNum = 0;
+
+            if((0 == cp210x_get_partnumber(h, &partNum))
+                && is_valid_cp210x_partnum((SILABS_PARTNUM_CPXXXX)partNum))
+            {
+                if(n < len)
+                {
+                    namelist[n++] = cp210x_find_name(partNum);
+                }
+            }
+
+            libusb_close(h);
+        }
+    } /* end for */
+
+    libusb_free_device_list(list, 1); /* Unreference all devices to free the device list */
+    return n;
+}
+
+static libusb_device_handle *cp210x_open(SILABS_PARTNUM_CPXXXX cp210x_partnum)
+{
+    libusb_device_handle *usbh = NULL;
+    libusb_device **list = NULL;
+
+    /* Enumerate all USB devices, returning the number of USB devices and a list of those devices */
+    const ssize_t numOfUSBDevices = libusb_get_device_list(g_LibusbContext, &list);
+
+    /* A negative count indicates an error */
+    if(numOfUSBDevices < 0)
+    {
+        ERROR("libusb_get_device_list error");
+        return NULL;
+    }
+
+    for(ssize_t i = 0; i < numOfUSBDevices; i++)
+    {
+        libusb_device *device = list[i];
+        libusb_device_handle *h = NULL;
+
+        if(cp210x_is_candidate_device(device) && (0 == libusb_open(list[i], &h)))
+        {
+            BYTE partNum = 0;
+
+            if((0 == cp210x_get_partnumber(h, &partNum))
+                && is_valid_cp210x_partnum((SILABS_PARTNUM_CPXXXX)partNum)
+                && (partNum == cp210x_partnum))
+            {
+                if(NULL == usbh)
+                {
+                    usbh = h;
+                }
+                else
+                {
+                    ERROR("conflicts, find multi '%s'", cp210x_find_name(partNum));
+                    libusb_close(usbh);
+                    libusb_close(h);
+                    return NULL;
+                }
+            }
+            else
+            {
+                libusb_close(h);
+            }
+        }
+    } /* end for */
+
+    libusb_free_device_list(list, 1);
+    return usbh;
+}
+
+static void cp210x_close(libusb_device_handle *usbh)
+{
+    if(NULL != usbh)
+    {
+        libusb_close(usbh);
+    }
+}
+
+static void cp210x_reset(libusb_device_handle *usbh)
+{
+    if(NULL != usbh)
+    {
+        libusb_reset_device(usbh);
+    }
+}
+
+static U16 fletcher16(const BYTE *bytes, U16 len)
+{
+    U16 sum1 = 0xff, sum2 = 0xff;
+    U16 tlen = 0;
+
+    while (len) {
+        tlen = len >= 20 ? 20 : len;
+        len -= tlen;
+        do {
+                sum2 += sum1 += *bytes++;
+        } while (--tlen);
+        sum1 = (sum1 & 0xff) + (sum1 >> 8);
+        sum2 = (sum2 & 0xff) + (sum2 >> 8);
+    }
+    /* Second reduction step to reduce sums to 8 bits */
+    sum1 = (sum1 & 0xff) + (sum1 >> 8);
+    sum2 = (sum2 & 0xff) + (sum2 >> 8);
+    return sum2 << 8 | sum1;
+}
+
+static void cp210x_compute_configure_checksum(BYTE *config, U16 len)
+{
+    U16 checksum = fletcher16(config, len - 2);
+    config[len - 2] = (BYTE)((checksum >> 8) & 0xff);
+    config[len - 1] = (BYTE)((checksum) & 0xff);
+}
+
+#define MAIN_GPIO_CONTROL_1_INDEX      600
+#define CP2102N_RS485_BIT              4
+#define MAIN_GPIO_CONTROL_2_INDEX      601
+#define CP2102N_RS485_LOGIC_BIT        0
+#define CP2102N_RS485_SETUP_INDEX      669
+#define CP2102N_RS485_HOLD_INDEX       671
+#define MAIN_RESET_LATCH_P1_INDEX      587
+#define CP2102N_GPIO2_RESET_LATH_BIT   5
+
+#define SET_CP2102N_RS485PIN_TO_RS585(config)   ((config)[MAIN_GPIO_CONTROL_1_INDEX] |= (BYTE)(1 << CP2102N_RS485_BIT))
+#define IS_CP2102N_RS485PIN_RS485_MODE(config)    ((config)[MAIN_GPIO_CONTROL_1_INDEX] & (1 << CP2102N_RS485_BIT))
+#define SET_CP2102N_RS485PIN_TO_GPIO(config)    ((config)[MAIN_GPIO_CONTROL_1_INDEX] &= (BYTE)(~(1 << CP2102N_RS485_BIT)))
+
+#define SET_CP2102N_RS485PIN_RS485_ACTIVE_LOGIC(config, logic)\
+    do{\
+        if(logic)\
+            config[MAIN_GPIO_CONTROL_2_INDEX] |= (BYTE)(1 << CP2102N_RS485_LOGIC_BIT);   \
+        else \
+            config[MAIN_GPIO_CONTROL_2_INDEX] &= (BYTE)(~(1 << CP2102N_RS485_LOGIC_BIT));\
+    }while(0)
+
+#define IS_CP2102N_RS485PIN_RS485_LOGIC(config)   (config[MAIN_GPIO_CONTROL_2_INDEX] & (1 << CP2102N_RS485_LOGIC_BIT))
+
+#define SET_CP2102N_GPIO2_RESET_LATH(config, logic) \
+    do{\
+        if(logic)\
+            config[MAIN_RESET_LATCH_P1_INDEX] |= (BYTE)(1 << CP2102N_GPIO2_RESET_LATH_BIT);   \
+        else\
+            config[MAIN_RESET_LATCH_P1_INDEX] &= (BYTE)(~(1 << CP2102N_GPIO2_RESET_LATH_BIT));   \
+    }while(0)
+
+#define GET_CP2102N_GPIO2_RESET_LATH(config)   (config[MAIN_RESET_LATCH_P1_INDEX] & (BYTE)(1 << CP2102N_GPIO2_RESET_LATH_BIT))
+
+#define SET_CP2102N_RS485_SETUP_TIME(config, u16vl) \
+    do{\
+        config[CP2102N_RS485_SETUP_INDEX] = (BYTE)(((u16vl) >> 8) & 0xff); \
+        config[CP2102N_RS485_SETUP_INDEX + 1] = (BYTE)((u16vl) & 0xff);    \
+    }while(0)
+
+#define GET_CP2102N_RS485_SETUP_TIME(config)   (((config[CP2102N_RS485_SETUP_INDEX] << 8) & 0xff00) | (config[CP2102N_RS485_SETUP_INDEX + 1] & 0xff))
+
+#define CFG_CP2102N_RS485_HOLD_TIME(config, u16vl) \
+    do{\
+        config[CP2102N_RS485_HOLD_INDEX] = (BYTE)(((u16vl) >> 8) & 0xff); \
+        config[CP2102N_RS485_HOLD_INDEX + 1] = (BYTE)((u16vl) & 0xff);    \
+    }while(0)
+
+#define GET_CP2102N_RS485_HOLD_TIME(config)   (((config[CP2102N_RS485_HOLD_INDEX] << 8) & 0xff00) | (config[CP2102N_RS485_HOLD_INDEX + 1] & 0xff))
+
+
+const char * const CP210X_USAGE = "\
+It's to operate cp210x device.\n\
+    -h,--help: display help information.\n\
+    -l,--list: list cp210x device.\n\
+    -D,--device: specified device, like 'cp2102', 'cp2102n24', 'cp2102n28' etc.\n\
+    -r,--read-config filename: read configuration from cp210x to filename.\n\
+    -w,--write-config filename: write configuration from filename to cp210x.\n\
+    -m,--rs485pin mode: set rs485-pin work mode, the mode can be set 'gpio' or 'rs485'.\n\
+    -g,--rs485-logic logic: set rs485-pin logic level when sending in rs485 mode, logic can be set '0' or '1'.\n\
+    -s,--setup u16: set rs485-pin's setup time in rs485 mode.\n\
+    -o,--hold u16: set rs485-pin's hold time in rs485 mode.\n\
+    -d,--display: display the current mode of cp210x.\n\
+    -v,--reset-level: set rs485-pin's default logic level in gpio mode.\n\
+    -e,--reset: reset cp210x.\n";
+
+
+typedef enum {
+    e_CONTINUE = 0,
+    e_STOP,
+}E_CMD_EXE_STATUS;
+
+#define CP210x_MAX_CONFIG_LENGTH  0x02a6
+
+typedef E_CMD_EXE_STATUS (*cmd_hander)(int argc, char **argv);
+
+static U16 g_CheckSumOld = 0;
+
+static libusb_device_handle *cp210x_cmd_open_device(int argc, char **argv)
+{
+    static libusb_device_handle *usbhd = NULL;
+    if(NULL != usbhd)
+    {
+        return usbhd;
+    }
+
+    SILABS_PARTNUM_CPXXXX ePartNum = CP210x_PARTNUM_UNKNOWN;
+    const char *devType = get_arg_string(argc, argv, "-D,--device", e_case_sensitive, NULL);
+    if(devType)
+    {
+        ePartNum = cp210x_find_partnum(devType);
+        if(CP210x_PARTNUM_UNKNOWN == ePartNum)
+        {
+            ERROR("parameter error, don't support '%s'", devType);
+            return NULL;
+        }
+    }
+    else
+    {
+        ERROR("parameter error, must specify cp210x device via '-D,--device'");
+        return NULL;
+    }
+
+    usbhd = cp210x_open(ePartNum);
+    if(NULL == usbhd)
+    {
+        ERROR("open '%s' failed", devType);
+    }
+
+    return usbhd;
+}
+
+static BYTE *cp210x_cmd_get_config(int argc, char **argv)
+{
+    static BYTE config[CP210x_MAX_CONFIG_LENGTH] = {0};
+
+    static bool isGeted = false;
+    if(isGeted)
+    {
+        return config;
+    }
+
+    libusb_device_handle *usbhd = cp210x_cmd_open_device(argc, argv);
+    if(NULL == usbhd)
+    {
+        return NULL;
+    }
+
+    memset((char*)(&(config[0])), 0, CP210x_MAX_CONFIG_LENGTH);
+
+    if(e_SUCCESS != cp210x_read_config(usbhd, config, CP210x_MAX_CONFIG_LENGTH))
+    {
+        ERROR("cp210x_read_config failed");
+        return NULL;
+    }
+
+    g_CheckSumOld = ((config[CP210x_MAX_CONFIG_LENGTH - 2] << 8) & 0xff00) | (config[CP210x_MAX_CONFIG_LENGTH - 1] & 0xff);
+    isGeted = true;
+
+    return config;
+}
+
+static E_CMD_EXE_STATUS cp210x_cmd_help(int argc, char **argv)
+{
+    printf("%s", CP210X_USAGE);
+    return e_STOP;;
+}
+
+static E_CMD_EXE_STATUS cp210x_cmd_list(int argc, char **argv)
+{
+    #define MAX_NUM   10
+    const char *namelist[MAX_NUM] = {0};
+    int num = cp210x_list(namelist, MAX_NUM);
+
+    int i = 0;
+    for(i = 0; i < num; i++)
+    {
+        if(0 == i)
+        {
+            printf("Find cp210x:\n");
         }
         }
+        printf("\t%s\n", namelist[i]);
+    }
+
+    return e_STOP;
+}
+
+static E_CMD_EXE_STATUS cp210x_cmd_print_mode(int argc, char **argv)
+{
+    BYTE *config = cp210x_cmd_get_config(argc, argv);
+    if(NULL == config)
+    {
+        return e_STOP;
+    }
+
+    if(IS_CP2102N_RS485PIN_RS485_MODE(config))
+    {
+        printf("rs485 active-logic(%s) setup-time(0x%04x) hold-time(0x%04x)\n"
+                        , IS_CP2102N_RS485PIN_RS485_LOGIC(config) ? "high" : "low"
+                        , GET_CP2102N_RS485_SETUP_TIME(config)
+                        , GET_CP2102N_RS485_HOLD_TIME(config));
+    }
+    else
+    {
+        printf("gpio reset-logic(%s)\n", GET_CP2102N_GPIO2_RESET_LATH(config) ? "high" : "low");
+    }
+
+    return e_STOP;
+}
+
+static E_CMD_EXE_STATUS cp210x_cmd_read_config(int argc, char **argv)
+{
+    const char *saveName = get_arg_string(argc, argv, "-r,--read-config", e_case_sensitive, NULL);
+    if(NULL == saveName)
+    {
+        ERROR("parameter error, '-r,--read-config' must append a file name");
+        return e_STOP;
     }
     }
 
 
-    init_ops();
+    BYTE *config = cp210x_cmd_get_config(argc, argv);
+    if(NULL == config)
+    {
+        return e_STOP;
+    }
+
+    FILE *fp = fopen(saveName, "w");
+
+    #define TMP_SIZE 10
+    char tmp[TMP_SIZE] = {0};
+    int i = 0;
+    for(i = 0; i < CP210x_MAX_CONFIG_LENGTH; i++)
+    {
+        memset(tmp, TMP_SIZE, 0);
+        sprintf(tmp, "0x%02x\n", config[i]);
+        fwrite(tmp, 1, strlen(tmp), fp);
+    }
+
+    fclose(fp);
+    return e_CONTINUE;
+}
+
+static E_CMD_EXE_STATUS cp210x_cmd_write_config(int argc, char **argv)
+{
+    const char *configName = get_arg_string(argc, argv, "-w,--write-config", e_case_sensitive, NULL);
+    if(NULL == configName)
+    {
+        ERROR("parameter error, '-w,--write-config' must append a file name");
+        return e_STOP;
+    }
+
+    BYTE config[CP210x_MAX_CONFIG_LENGTH] = {0};
+
+    FILE *fp = fopen(configName, "r");
+    if(NULL == fp)
+    {
+        ERROR("open '%s' failed", configName);
+        return e_STOP;
+    }
+
+    #define MAX_LINE   10
+    char tmp[MAX_LINE] = {0};
+    int i = 0;
+
+    while(!feof(fp) && (i < CP210x_MAX_CONFIG_LENGTH))
+    {
+        memset(tmp, 0, MAX_LINE);
+        fgets(tmp, MAX_LINE, fp);
+        config[i++] = strtol(tmp, NULL, 0);
+    }
+
+    fclose(fp);
+
+    libusb_device_handle *usbhd = cp210x_cmd_open_device(argc, argv);
+    if(NULL == usbhd)
+    {
+        return e_STOP;
+    }
+
+    cp210x_compute_configure_checksum(config, CP210x_MAX_CONFIG_LENGTH);
+
+    if(e_SUCCESS != cp210x_write_config(usbhd, config, CP210x_MAX_CONFIG_LENGTH))
+    {
+        ERROR("cp210x_write_config failed");
+        return e_STOP;
+    }
+
+    return e_CONTINUE;
+}
+
+static E_CMD_EXE_STATUS cp210x_cmd_set_mode(int argc, char **argv)
+{
+    const char *mode = get_arg_string(argc, argv, "-m,--rs485pin", e_case_sensitive, NULL);
+    if(NULL == mode)
+    {
+        ERROR("parameter error, '-m,--rs485pin' must append a mode");
+        return e_STOP;
+    }
+
+    BYTE *config = cp210x_cmd_get_config(argc, argv);
+    if(NULL == config)
+    {
+        return e_STOP;
+    }
+
+    if(0 == strcasecmp(mode, "gpio"))
+    {
+        SET_CP2102N_RS485PIN_TO_GPIO(config);
+
+    }
+    else if(0 == strcasecmp(mode, "rs485"))
+    {
+        SET_CP2102N_RS485PIN_TO_RS585(config);
+    }
+    else
+    {
+        ERROR("parameter error, '-m,--rs485pin' must append a mode, it can be 'gpio' or 'rs485'");
+        return e_STOP;
+    }
+
+    return e_CONTINUE;
+}
+
+static E_CMD_EXE_STATUS cp210x_cmd_set_rs485_logic(int argc, char **argv)
+{
+    const int logic = get_arg_int(argc, argv, "-g,--rs485-logic", e_case_sensitive, -1);
+    if(-1 == logic)
+    {
+        ERROR("parameter error, '-g,--rs485-logic' must append a value, like '0' or '1'");
+        return e_STOP;
+    }
+
+    BYTE *config = cp210x_cmd_get_config(argc, argv);
+    if(NULL == config)
+    {
+        return e_STOP;
+    }
+
+    SET_CP2102N_RS485PIN_RS485_ACTIVE_LOGIC(config, logic);
+
+    return e_CONTINUE;
+}
+
+static E_CMD_EXE_STATUS cp210x_cmd_set_rs485_setup(int argc, char **argv)
+{
+    const int setuptime = get_arg_int(argc, argv, "-s,--setup", e_case_sensitive, -1);
+    if(-1 == setuptime)
+    {
+        ERROR("parameter error, '-s,--setup' must append a unsigned short type value, like '0x1234' or '1234'");
+        return e_STOP;
+    }
 
 
-    if (display_current_mode) {
-        curr_platform->serOps->getMode();
-        return SUCCESS;
+    BYTE *config = cp210x_cmd_get_config(argc, argv);
+    if(NULL == config)
+    {
+        return e_STOP;
     }
     }
 
 
-    if (curr_platform->serOps->preProcess)
-        curr_platform->serOps->preProcess(curr_platform);
+    SET_CP2102N_RS485_SETUP_TIME(config, setuptime);
+    return e_CONTINUE;
+}
 
 
-    if (NULL != mode) {
-        curr_platform->serOps->setMode(mode);
+static E_CMD_EXE_STATUS cp210x_cmd_set_rs485_hold(int argc, char **argv)
+{
+    const int holdtime = get_arg_int(argc, argv, "-o,--hold", e_case_sensitive, -1);
+    if(-1 == holdtime)
+    {
+        ERROR("parameter error, '-o,--hold' must append a unsigned short type value, like '0x1234' or '1234'");
+        return e_STOP;
     }
     }
 
 
-    if (holdTime) {
-        curr_platform->serOps->rs485HoldTime(holdTime);
+    BYTE *config = cp210x_cmd_get_config(argc, argv);
+    if(NULL == config)
+    {
+        return e_STOP;
+    }
+
+    CFG_CP2102N_RS485_HOLD_TIME(config, holdtime);
+    return e_CONTINUE;
+}
+
+static E_CMD_EXE_STATUS cp210x_cmd_set_rs485pin_gpio_reset_level(int argc, char **argv)
+{
+    int rstLogic = get_arg_int(argc, argv, "-v,--reset-level", e_case_sensitive, -1);
+    if(-1 == rstLogic)
+    {
+        ERROR("parameter error, '-o,--hold' must append a value, like '0' or '1'");
+        return e_STOP;
+    }
+
+    BYTE *config = cp210x_cmd_get_config(argc, argv);
+    if(NULL == config)
+    {
+        return e_STOP;
+    }
+
+    SET_CP2102N_GPIO2_RESET_LATH(config, rstLogic);
+    return e_CONTINUE;
+}
+
+static E_CMD_EXE_STATUS cp210x_cmd_reset(int argc, char **argv)
+{
+    cp210x_reset(cp210x_cmd_open_device(argc, argv));
+    return e_STOP;
+}
+
+typedef struct {
+    const char *const cmd;
+    cmd_hander cmd_func;
+}cmd_list_t;
+
+cmd_list_t cmd_list[] = {
+    {"-h,--help",    cp210x_cmd_help},
+    {"-l,--list",    cp210x_cmd_list},
+    {"-d,--display", cp210x_cmd_print_mode},
+    {"-r,--read-config", cp210x_cmd_read_config},
+    {"-w,--write-config", cp210x_cmd_write_config},
+    {"-m,--rs485pin", cp210x_cmd_set_mode},
+    {"-g,--rs485-logic", cp210x_cmd_set_rs485_logic},
+    {"-s,--setup", cp210x_cmd_set_rs485_setup},
+    {"-o,--hold", cp210x_cmd_set_rs485_hold},
+    {"-v,--reset-level", cp210x_cmd_set_rs485pin_gpio_reset_level},
+    {"-e,--reset", cp210x_cmd_reset}};
+
+static void cp210x_command_handle(int argc, char **argv)
+{
+    libusb_init(&g_LibusbContext);
+
+    const int size = sizeof(cmd_list) / sizeof(cmd_list[0]);
+    int i = 0;
+    for(i = 0; i < size; i++)
+    {
+        if(check_arg(argc, argv, cmd_list[i].cmd, e_case_sensitive))
+        {
+            if(e_STOP == cmd_list[i].cmd_func(argc, argv))
+            {
+                break;
+            }
+        }
     }
     }
 
 
-    if (setupTime) {
-        curr_platform->serOps->rs485SetupTime(setupTime);
+    if(g_CheckSumOld)
+    {
+        libusb_device_handle *usbhd = cp210x_cmd_open_device(argc, argv);
+
+        BYTE *config = cp210x_cmd_get_config(argc, argv);
+        if(NULL != config)
+        {
+            cp210x_compute_configure_checksum(config, CP210x_MAX_CONFIG_LENGTH);
+            const U16 checkSumNew = ((config[CP210x_MAX_CONFIG_LENGTH - 2] << 8) & 0xff00) | (config[CP210x_MAX_CONFIG_LENGTH - 1] & 0xff);
+
+            if(g_CheckSumOld != checkSumNew)
+            {
+                if(e_SUCCESS != cp210x_write_config(usbhd, config, CP210x_MAX_CONFIG_LENGTH))
+                {
+                    ERROR("cp210x_write_config failed");
+                }
+            }
+        }
+
+        cp210x_close(usbhd);
     }
     }
 
 
-    /* configure transceiver */
-    if (NULL != mode)
-        curr_platform->transOps->transceiver_switch_mode(mode);
+    libusb_exit(g_LibusbContext);
+}
 
 
-    //default is disable terminate
-    curr_platform->transOps->transceiver_set_termination(set_termination);
+static void cp210x_hardware_reset(void)
+{
+    usleep(60*1000);
+    gpio_set("CP2102N-RESET", 0);
+    sleep(1);
+    gpio_set("CP2102N-RESET", 1);
+}
+
+static void print_usage(const char *name)
+{
+    printf("\
+It's used to set external serial port mode.\n\
+Usage:\n\
+    %s [ttyuart [options]] | [cp210x [options]] | [-m,--mode MODE]\n\n\
+Example:\n\
+    %s ttyuart -h\n\
+    %s cp210x -h\n\
+    %s -m,--mode <rs232 | rs485 | rs422> [-t,--terminate]\n\
+        -t,--terminate: Terminate the rs422 or rs485 bus.\n"
+           , name, name, name, name);
+}
 
 
-release:
-    if(curr_platform->serOps->release)
-        curr_platform->serOps->release();
-    free(curr_platform);
+int main(int argc, char **argv)
+{
+    if(1 == argc)
+    {
+        ERROR("parameter error\n");
+        print_usage(argv[0]);
+    }
+    else if(compare_string(argv[1], "-h,--help", e_case_insensitive))
+    {
+        print_usage(argv[0]);
+    }
+    else if(compare_string(argv[1], "ttyuart", e_case_insensitive))
+    {
+        ttyuart_command_handle(argc, argv);
+    }
+    else if(compare_string(argv[1], "cp210x", e_case_insensitive))
+    {
+        cp210x_command_handle(argc, argv);
+    }
+    else if(compare_string(argv[1], "-m,--mode", e_case_insensitive))
+    {
+        const int terminate = check_arg(argc, argv, "-t,--terminate", e_case_sensitive);
+        const char *mode = get_arg_string(argc, argv, "-m", e_case_sensitive, NULL);
+        if(NULL != mode)
+        {
+            gpio_switch_mode(mode, terminate);
+        }
+    }
+     else if(compare_string(argv[1], "-r,--reset", e_case_insensitive))
+    {
+        cp210x_hardware_reset();
+    }
+    else
+    {
+        ERROR("parameter error\n");
+        print_usage(argv[0]);
+    }
 
 
-    return SUCCESS;
+    return 0;
 }
 }

+ 0 - 56
package/switchserialmode/src/switchserialmode.h

@@ -1,56 +0,0 @@
-#ifndef SWITCH_SERIAL_MODE
-#define SWITCH_SERIAL_MODE
-
-#include <stdint.h>
-
-#define ERROR       -1
-#define SUCCESS     0
-
-typedef enum boardType {
-    BASIC_BOARD = 0,
-    ADVANCED_BOARD,
-    ADVANCED_BOARD_PG1
-} boardType_e;
-
-typedef struct transceiver_ops {
-    void (*transceiver_set_termination)( uint8_t onoff);
-    void (*transceiver_switch_mode)(const uint8_t *mode);
-} transceiver_ops_t;
-
-typedef struct serial_ops {
-    /*Device node*/
-    uint8_t *devName;
-
-    /*Init device resources*/
-    int8_t (*init)(uint8_t *devName);
-
-    /*Set serial mode,like rs232 rs485 rs422*/
-    void (*setMode)(uint8_t *mode);
-
-    /*Display current serial mode*/
-    void (*getMode)(void);
-
-    /*For the device which support setup and hold time*/
-    void (*rs485HoldTime)(uint8_t time);
-    void (*rs485SetupTime)(uint8_t time);
-
-    /*Release*/
-    void (*release)(void);
-
-    void (*preProcess)(void *);
-} serial_ops_t;
-
-typedef struct controller_setting {
-    uint32_t hold_time;
-    uint32_t setup_time;
-} controller_setting_t;
-
-typedef struct platform {
-    serial_ops_t *serOps;
-    transceiver_ops_t *transOps;
-    void *private_data;
-} platform_t;
-
-boardType_e get_board_type(void);
-
-#endif

BIN
package/switchserialmode/src/switchserialmode.o


BIN
package/switchserialmode/src/transceiver/sp339e


+ 0 - 50
package/switchserialmode/src/transceiver/sp339e.c

@@ -1,50 +0,0 @@
-/*
- * Copyright (c) Siemens AG, 2019-2022
- *
- * Authors:
- *  Gao Nian <nian.gao@siemens.com>
- *  Chao Zeng <chao.zeng@siemens.com>
- *
- * This file is subject to the terms and conditions of the MIT License.  See
- * COPYING.MIT file in the top-level directory.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <gpiod.h>
-#include <string.h>
-#include "switchserialmode.h"
-#include "gpio_helper.h"
-
-static void sp339e_set_mode(uint32_t mode0, uint32_t mode1)
-{
-    gpio_set("UART0-enable", 1);
-    gpio_set("UART0-mode0", mode0);
-    gpio_set("UART0-mode1", mode1);
-}
-
-static void sp339e_set_termination(uint8_t onoff)
-{
-    gpio_set("UART0-terminate", onoff);
-}
-
-static void sp339e_switch_mode(const uint8_t *mode)
-{
-    if (0 == strcasecmp(mode, "rs232"))
-    {
-        sp339e_set_mode(1, 0);
-    }
-    else if(0 == strcasecmp(mode, "rs485"))
-    {
-        sp339e_set_mode(0, 1);
-    }
-    else if(0 == strcasecmp(mode, "rs422"))
-    {
-        sp339e_set_mode(1, 1);
-    }
-}
-
-transceiver_ops_t sp339e_ops = {
-    .transceiver_set_termination = sp339e_set_termination,
-    .transceiver_switch_mode = sp339e_switch_mode,
-};

BIN
package/switchserialmode/src/transceiver/sp339e.o