mirror of
https://github.com/apache/nuttx-apps.git
synced 2025-10-20 12:55:43 +08:00

Add plcatool - simple tool for managing PLCA configuration in 10BASE-T1S PHYs. Signed-off-by: michal matias <mich4l.matias@gmail.com>
714 lines
18 KiB
C
714 lines
18 KiB
C
/****************************************************************************
|
|
* apps/netutils/plcatool/plcatool.c
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
#include <net/if.h>
|
|
#include <sys/ioctl.h>
|
|
|
|
#include "oa_tc14.h"
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
#define ARGS_REMAIN(argc, pos) ((argc) - (pos))
|
|
|
|
#define PLCATOOL_CFG_SET_BIT 0x8000
|
|
#define PLCATOOL_CFG_SET(cfg, field, val) \
|
|
do {(cfg)->field = PLCATOOL_CFG_SET_BIT | ((val) & 0xff);} while (0)
|
|
|
|
#define PLCATOOL_CFG_VAL(cfg, field) ((cfg)->field & 0xff)
|
|
|
|
#define NODE_ID_MIN 0
|
|
#define NODE_ID_MAX 255
|
|
|
|
#define NODE_CNT_MIN 1
|
|
#define NODE_CNT_MAX 255
|
|
|
|
#define TO_TMR_MIN 0
|
|
#define TO_TMR_MAX 255
|
|
|
|
#define BURST_CNT_MIN 0
|
|
#define BURST_CNT_MAX 255
|
|
|
|
#define BURST_TMR_MIN 0
|
|
#define BURST_TMR_MAX 255
|
|
|
|
/****************************************************************************
|
|
* Private Types
|
|
****************************************************************************/
|
|
|
|
enum plcatool_cmd_e
|
|
{
|
|
PLCA_CMD_SET,
|
|
PLCA_CMD_GET,
|
|
PLCA_CMD_STATUS,
|
|
PLCA_CMD_HELP
|
|
};
|
|
|
|
/* Lower 8 bits are value, the most significant bit indicates whether set */
|
|
|
|
struct plcatool_cfg_s
|
|
{
|
|
enum plcatool_cmd_e cmd;
|
|
|
|
FAR char *ifname;
|
|
|
|
uint8_t phy;
|
|
|
|
uint16_t enable;
|
|
uint16_t node_cnt;
|
|
uint16_t node_id;
|
|
uint16_t to_tmr;
|
|
uint16_t burst_cnt;
|
|
uint16_t burst_tmr;
|
|
};
|
|
|
|
/****************************************************************************
|
|
* Private Data
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Private Function Prototypes
|
|
****************************************************************************/
|
|
|
|
static int get_num(FAR const char *str, FAR int *result);
|
|
static int parse_args(int argc, FAR char *argv[],
|
|
FAR struct plcatool_cfg_s *cfg);
|
|
static int write_plca_mmd(FAR const char *ifname, int phy,
|
|
uint16_t address, uint16_t data);
|
|
static int read_plca_mmd(FAR const char *ifname, int phy,
|
|
uint16_t address, FAR uint16_t *data);
|
|
static int verify_support(FAR struct plcatool_cfg_s *cfg,
|
|
FAR bool *supported);
|
|
static int plcatool_set(FAR struct plcatool_cfg_s *cfg);
|
|
static int plcatool_get(FAR struct plcatool_cfg_s *cfg);
|
|
static int plcatool_status(FAR struct plcatool_cfg_s *cfg);
|
|
static void plcatool_usage(bool err);
|
|
|
|
/****************************************************************************
|
|
* Private Functions
|
|
****************************************************************************/
|
|
|
|
static int get_num(FAR const char *str, FAR int *result)
|
|
{
|
|
FAR char *endptr;
|
|
*result = (int)strtol(str, &endptr, 0);
|
|
|
|
if (*endptr != '\0')
|
|
{
|
|
return ERROR;
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
static int parse_args(int argc, FAR char *argv[],
|
|
FAR struct plcatool_cfg_s *cfg)
|
|
{
|
|
FAR const char *cmd;
|
|
int argpos = 1;
|
|
|
|
if (argc < 2)
|
|
{
|
|
return ERROR;
|
|
}
|
|
|
|
if (strcmp(argv[argpos++], "--phy") == 0)
|
|
{
|
|
int phynum;
|
|
|
|
if (ARGS_REMAIN(argc, argpos) < 3) /* at least phynum, cmd, intf */
|
|
{
|
|
return ERROR;
|
|
}
|
|
|
|
if (get_num(argv[argpos++], &phynum))
|
|
{
|
|
return ERROR;
|
|
}
|
|
|
|
if (0 <= phynum && phynum <= 31)
|
|
{
|
|
cfg->phy = phynum;
|
|
}
|
|
else
|
|
{
|
|
return ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
argpos = 1;
|
|
cfg->phy = 0;
|
|
}
|
|
|
|
cmd = argv[argpos++];
|
|
|
|
if (strcmp(cmd, "set") == 0)
|
|
{
|
|
cfg->cmd = PLCA_CMD_SET;
|
|
|
|
if (ARGS_REMAIN(argc, argpos) < 3) /* name, at least one param-value */
|
|
{
|
|
return ERROR;
|
|
}
|
|
|
|
cfg->ifname = argv[argpos++];
|
|
|
|
while (ARGS_REMAIN(argc, argpos) >= 2) /* at least one param-value */
|
|
{
|
|
FAR const char *param = argv[argpos++];
|
|
FAR const char *value = argv[argpos++];
|
|
|
|
if (strcmp(param, "enable") == 0)
|
|
{
|
|
if (cfg->enable)
|
|
{
|
|
return ERROR;
|
|
}
|
|
|
|
if (strcmp(value, "on") == 0)
|
|
{
|
|
PLCATOOL_CFG_SET(cfg, enable, 1);
|
|
}
|
|
else if (strcmp(value, "off") == 0)
|
|
{
|
|
PLCATOOL_CFG_SET(cfg, enable, 0);
|
|
}
|
|
else
|
|
{
|
|
return ERROR;
|
|
}
|
|
}
|
|
else if (strcmp(param, "node-id") == 0)
|
|
{
|
|
int n;
|
|
|
|
if (cfg->node_id)
|
|
{
|
|
return ERROR;
|
|
}
|
|
|
|
if (get_num(value, &n))
|
|
{
|
|
return ERROR;
|
|
}
|
|
|
|
if (NODE_ID_MIN <= n && n <= NODE_ID_MAX)
|
|
{
|
|
PLCATOOL_CFG_SET(cfg, node_id, n);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "node-id out of range\n");
|
|
return ERROR;
|
|
}
|
|
}
|
|
else if (strcmp(param, "node-cnt") == 0)
|
|
{
|
|
int n;
|
|
|
|
if (cfg->node_cnt)
|
|
{
|
|
return ERROR;
|
|
}
|
|
|
|
if (get_num(value, &n))
|
|
{
|
|
fprintf(stderr, "Not a valid integer\n");
|
|
return ERROR;
|
|
}
|
|
|
|
if (NODE_CNT_MIN <= n && n <= NODE_CNT_MAX)
|
|
{
|
|
PLCATOOL_CFG_SET(cfg, node_cnt, n);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "node-cnt out of range\n");
|
|
return ERROR;
|
|
}
|
|
}
|
|
else if (strcmp(param, "to-tmr") == 0)
|
|
{
|
|
int n;
|
|
|
|
if (cfg->to_tmr)
|
|
{
|
|
return ERROR;
|
|
}
|
|
|
|
if (get_num(value, &n))
|
|
{
|
|
fprintf(stderr, "Not a valid integer\n");
|
|
return ERROR;
|
|
}
|
|
|
|
if (TO_TMR_MIN <= n && n <= TO_TMR_MAX)
|
|
{
|
|
PLCATOOL_CFG_SET(cfg, to_tmr, n);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "to_tmr out of range\n");
|
|
return ERROR;
|
|
}
|
|
}
|
|
else if (strcmp(param, "burst-cnt") == 0)
|
|
{
|
|
int n;
|
|
|
|
if (cfg->burst_cnt)
|
|
{
|
|
return ERROR;
|
|
}
|
|
|
|
if (get_num(value, &n))
|
|
{
|
|
fprintf(stderr, "Not a valid integer\n");
|
|
return ERROR;
|
|
}
|
|
|
|
if (BURST_CNT_MIN <= n && n <= BURST_CNT_MAX)
|
|
{
|
|
PLCATOOL_CFG_SET(cfg, burst_cnt, n);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "burst-cnt out of range\n");
|
|
return ERROR;
|
|
}
|
|
}
|
|
else if (strcmp(param, "burst-tmr") == 0)
|
|
{
|
|
int n;
|
|
|
|
if (cfg->burst_tmr)
|
|
{
|
|
return ERROR;
|
|
}
|
|
|
|
if (get_num(value, &n))
|
|
{
|
|
fprintf(stderr, "Not a valid integer\n");
|
|
return ERROR;
|
|
}
|
|
|
|
if (BURST_TMR_MIN <= n && n <= BURST_TMR_MAX)
|
|
{
|
|
PLCATOOL_CFG_SET(cfg, burst_tmr, n);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "burst-tmr out of range\n");
|
|
return ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return ERROR;
|
|
}
|
|
}
|
|
|
|
if (ARGS_REMAIN(argc, argpos) != 0)
|
|
{
|
|
return ERROR;
|
|
}
|
|
}
|
|
else if (strcmp(cmd, "get") == 0)
|
|
{
|
|
cfg->cmd = PLCA_CMD_GET;
|
|
|
|
if (ARGS_REMAIN(argc, argpos) != 1) /* ifname */
|
|
{
|
|
return ERROR;
|
|
}
|
|
|
|
cfg->ifname = argv[argpos++];
|
|
if (strlen(cfg->ifname) > IFNAMSIZ)
|
|
{
|
|
fprintf(stderr, "No such interface\n");
|
|
return ERROR;
|
|
}
|
|
}
|
|
else if (strcmp(cmd, "status") == 0)
|
|
{
|
|
cfg->cmd = PLCA_CMD_STATUS;
|
|
|
|
if (ARGS_REMAIN(argc, argpos) != 1) /* ifname */
|
|
{
|
|
return ERROR;
|
|
}
|
|
|
|
cfg->ifname = argv[argpos++];
|
|
if (strlen(cfg->ifname) > IFNAMSIZ)
|
|
{
|
|
fprintf(stderr, "No such interface\n");
|
|
return ERROR;
|
|
}
|
|
}
|
|
else if (strcmp(cmd, "-h") == 0)
|
|
{
|
|
cfg->cmd = PLCA_CMD_HELP;
|
|
|
|
if (ARGS_REMAIN(argc, argpos) != 0)
|
|
{
|
|
return ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return ERROR;
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
static int write_plca_mmd(FAR const char *ifname, int phy,
|
|
uint16_t address, uint16_t data)
|
|
{
|
|
struct ifreq req;
|
|
int retval;
|
|
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
|
strcpy(req.ifr_name, ifname);
|
|
req.ifr_ifru.ifru_mii_data.phy_id = mdio_phy_id_c45(OA_TC14_PLCA_MMD, phy);
|
|
req.ifr_ifru.ifru_mii_data.reg_num = address;
|
|
req.ifr_ifru.ifru_mii_data.val_in = data;
|
|
retval = ioctl(sockfd, SIOCSMIIREG, (unsigned long)(&req));
|
|
if (retval)
|
|
{
|
|
close(sockfd);
|
|
fprintf(stderr, "Write unsuccessful\n");
|
|
return ERROR;
|
|
}
|
|
|
|
close(sockfd);
|
|
return OK;
|
|
}
|
|
|
|
static int read_plca_mmd(FAR const char *ifname, int phy,
|
|
uint16_t address, FAR uint16_t *data)
|
|
{
|
|
struct ifreq req;
|
|
int retval;
|
|
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
|
strcpy(req.ifr_name, ifname);
|
|
req.ifr_ifru.ifru_mii_data.phy_id = mdio_phy_id_c45(OA_TC14_PLCA_MMD, phy);
|
|
req.ifr_ifru.ifru_mii_data.reg_num = address;
|
|
|
|
retval = ioctl(sockfd, SIOCGMIIREG, (unsigned long)(&req));
|
|
if (retval)
|
|
{
|
|
close(sockfd);
|
|
fprintf(stderr, "Read unsuccessful\n");
|
|
return ERROR;
|
|
}
|
|
|
|
*data = req.ifr_ifru.ifru_mii_data.val_out;
|
|
|
|
close(sockfd);
|
|
return OK;
|
|
}
|
|
|
|
static int verify_support(FAR struct plcatool_cfg_s *cfg,
|
|
FAR bool *supported)
|
|
{
|
|
uint16_t reg;
|
|
if (read_plca_mmd(cfg->ifname, cfg->phy, OA_TC14_IDVER_ADDR, ®))
|
|
{
|
|
return ERROR;
|
|
}
|
|
|
|
*supported = reg == OA_TC14_IDVER_VAL ? true : false;
|
|
|
|
return OK;
|
|
}
|
|
|
|
static int plcatool_set(FAR struct plcatool_cfg_s *cfg)
|
|
{
|
|
uint16_t reg;
|
|
bool supported;
|
|
|
|
/* Verify the correct address map code */
|
|
|
|
if (verify_support(cfg, &supported))
|
|
{
|
|
return EIO;
|
|
}
|
|
|
|
if (!supported)
|
|
{
|
|
fprintf(stderr, "Device not supported\n");
|
|
return EINVAL;
|
|
}
|
|
|
|
/* node-cnt, node-id */
|
|
|
|
if (cfg->node_cnt || cfg->node_id)
|
|
{
|
|
if (read_plca_mmd(cfg->ifname, cfg->phy, OA_TC14_CTRL1_ADDR, ®))
|
|
{
|
|
return EIO;
|
|
}
|
|
|
|
if (cfg->node_cnt)
|
|
{
|
|
int val = PLCATOOL_CFG_VAL(cfg, node_cnt);
|
|
reg &= ~OA_TC14_CTRL1_NCNT_MASK;
|
|
reg |= oa_tc14_field(val, CTRL1_NCNT);
|
|
}
|
|
|
|
if (cfg->node_id)
|
|
{
|
|
int val = PLCATOOL_CFG_VAL(cfg, node_id);
|
|
reg &= ~OA_TC14_CTRL1_ID_MASK;
|
|
reg |= oa_tc14_field(val, CTRL1_ID);
|
|
}
|
|
|
|
if (write_plca_mmd(cfg->ifname, cfg->phy, OA_TC14_CTRL1_ADDR, reg))
|
|
{
|
|
return EIO;
|
|
}
|
|
}
|
|
|
|
/* to-tmr */
|
|
|
|
if (cfg->to_tmr)
|
|
{
|
|
int val = PLCATOOL_CFG_VAL(cfg, to_tmr);
|
|
reg = oa_tc14_field(val, TOTMR_TOT);
|
|
|
|
if (write_plca_mmd(cfg->ifname, cfg->phy, OA_TC14_TOTMR_ADDR, reg))
|
|
{
|
|
return EIO;
|
|
}
|
|
}
|
|
|
|
/* burst-cnt, burst-tmr */
|
|
|
|
if (cfg->burst_cnt || cfg->burst_tmr)
|
|
{
|
|
if (read_plca_mmd(cfg->ifname, cfg->phy, OA_TC14_BURST_ADDR, ®))
|
|
{
|
|
return EIO;
|
|
}
|
|
|
|
if (cfg->burst_cnt)
|
|
{
|
|
int val = PLCATOOL_CFG_VAL(cfg, burst_cnt);
|
|
reg &= ~OA_TC14_BURST_MAXBC_MASK;
|
|
reg |= oa_tc14_field(val, BURST_MAXBC);
|
|
}
|
|
|
|
if (cfg->burst_tmr)
|
|
{
|
|
int val = PLCATOOL_CFG_VAL(cfg, burst_tmr);
|
|
reg &= ~OA_TC14_BURST_BTMR_MASK;
|
|
reg |= oa_tc14_field(val, BURST_BTMR);
|
|
}
|
|
|
|
if (write_plca_mmd(cfg->ifname, cfg->phy, OA_TC14_BURST_ADDR, reg))
|
|
{
|
|
return EIO;
|
|
}
|
|
}
|
|
|
|
/* enable */
|
|
|
|
if (cfg->enable)
|
|
{
|
|
int val;
|
|
if (read_plca_mmd(cfg->ifname, cfg->phy, OA_TC14_CTRL0_ADDR, ®))
|
|
{
|
|
return EIO;
|
|
}
|
|
|
|
val = PLCATOOL_CFG_VAL(cfg, enable);
|
|
reg &= ~OA_TC14_CTRL0_EN_MASK;
|
|
reg |= oa_tc14_field(val, CTRL0_EN);
|
|
|
|
if (write_plca_mmd(cfg->ifname, cfg->phy, OA_TC14_CTRL0_ADDR, reg))
|
|
{
|
|
return EIO;
|
|
}
|
|
|
|
read_plca_mmd(cfg->ifname, cfg->phy, OA_TC14_CTRL0_ADDR, ®);
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
static int plcatool_get(FAR struct plcatool_cfg_s *cfg)
|
|
{
|
|
uint16_t ctrl0;
|
|
uint16_t ctrl1;
|
|
uint16_t totmr;
|
|
uint16_t burst;
|
|
bool supported;
|
|
|
|
/* Verify the correct address map code */
|
|
|
|
if (verify_support(cfg, &supported))
|
|
{
|
|
return EIO;
|
|
}
|
|
|
|
if (!supported)
|
|
{
|
|
fprintf(stderr, "Device not supported\n");
|
|
return EINVAL;
|
|
}
|
|
|
|
if (read_plca_mmd(cfg->ifname, cfg->phy, OA_TC14_CTRL0_ADDR, &ctrl0) ||
|
|
read_plca_mmd(cfg->ifname, cfg->phy, OA_TC14_CTRL1_ADDR, &ctrl1) ||
|
|
read_plca_mmd(cfg->ifname, cfg->phy, OA_TC14_TOTMR_ADDR, &totmr) ||
|
|
read_plca_mmd(cfg->ifname, cfg->phy, OA_TC14_BURST_ADDR, &burst))
|
|
{
|
|
return EIO;
|
|
}
|
|
|
|
cfg->enable = oa_tc14_get_field(ctrl0, CTRL0_EN);
|
|
cfg->node_id = oa_tc14_get_field(ctrl1, CTRL1_ID);
|
|
cfg->node_cnt = oa_tc14_get_field(ctrl1, CTRL1_NCNT);
|
|
cfg->to_tmr = oa_tc14_get_field(totmr, TOTMR_TOT);
|
|
cfg->burst_cnt = oa_tc14_get_field(burst, BURST_MAXBC);
|
|
cfg->burst_tmr = oa_tc14_get_field(burst, BURST_BTMR);
|
|
|
|
printf("PLCA settings for %s\n", cfg->ifname);
|
|
printf("\tEnabled: %s\n", cfg->enable ? "Yes" : "No");
|
|
printf("\tlocal node ID: %d (%s)\n", cfg->node_id,
|
|
cfg->node_id == 0 ? "coordinator" :
|
|
(cfg->node_id == 255 ? "unconfigured" : "follower"));
|
|
printf("\tNode count: %d%s\n", cfg->node_cnt,
|
|
cfg->node_id ? " (ignored)" : "");
|
|
printf("\tTO timer: %d BT\n", cfg->to_tmr);
|
|
printf("\tBurst count: %d (%s)\n", cfg->burst_cnt,
|
|
cfg->burst_cnt > 0 ? "enabled" : "disabled");
|
|
printf("\tBurst timer: %d BT\n", cfg->burst_tmr);
|
|
|
|
return OK;
|
|
}
|
|
|
|
static int plcatool_status(FAR struct plcatool_cfg_s *cfg)
|
|
{
|
|
uint16_t status;
|
|
bool supported;
|
|
|
|
/* Verify the correct address map code */
|
|
|
|
if (verify_support(cfg, &supported))
|
|
{
|
|
return EIO;
|
|
}
|
|
|
|
if (!supported)
|
|
{
|
|
fprintf(stderr, "Device not supported\n");
|
|
return EINVAL;
|
|
}
|
|
|
|
if (read_plca_mmd(cfg->ifname, cfg->phy, OA_TC14_STATUS_ADDR, &status))
|
|
{
|
|
return EIO;
|
|
}
|
|
|
|
printf("PLCA status of %s\n", cfg->ifname);
|
|
printf("\tStatus: %s\n",
|
|
oa_tc14_get_field(status, STATUS_PST) ? "on" : "off");
|
|
|
|
return OK;
|
|
}
|
|
|
|
static void plcatool_usage(bool err)
|
|
{
|
|
FAR FILE *out = err ? stderr : stdout;
|
|
|
|
fprintf(out, "Usage:\n");
|
|
fprintf(out, " plcatool [--phy N] status <ifname>\n");
|
|
fprintf(out, " plcatool [--phy N] get <ifname>\n");
|
|
fprintf(out, " plcatool [--phy N] set <ifname> <param> <value> "
|
|
"[<param> <value>] ...\n");
|
|
fprintf(out, " Accepted <param> <value> pairs:\n");
|
|
fprintf(out, " enable on | off\n");
|
|
fprintf(out, " node-id N in [%d .. %d]\n",
|
|
NODE_ID_MIN, NODE_ID_MAX);
|
|
fprintf(out, " node-cnt N in [%d .. %d]\n",
|
|
NODE_CNT_MIN, NODE_CNT_MAX);
|
|
fprintf(out, " to-tmr N in [%d .. %d]\n",
|
|
TO_TMR_MIN, TO_TMR_MAX);
|
|
fprintf(out, " burst-cnt N in [%d .. %d]\n",
|
|
BURST_CNT_MIN, BURST_CNT_MAX);
|
|
fprintf(out, " burst-tmr N in [%d .. %d]\n",
|
|
BURST_TMR_MIN, BURST_TMR_MAX);
|
|
fprintf(out, " plcatool -h\n");
|
|
fprintf(out, " --phy N defaults to 0\n");
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
int main(int argc, FAR char *argv[])
|
|
{
|
|
struct plcatool_cfg_s cfg;
|
|
memset(&cfg, 0, sizeof(cfg));
|
|
|
|
int err = parse_args(argc, argv, &cfg);
|
|
if (err)
|
|
{
|
|
plcatool_usage(err);
|
|
return EINVAL;
|
|
}
|
|
|
|
switch (cfg.cmd)
|
|
{
|
|
case PLCA_CMD_SET:
|
|
return plcatool_set(&cfg);
|
|
|
|
case PLCA_CMD_GET:
|
|
return plcatool_get(&cfg);
|
|
|
|
case PLCA_CMD_STATUS:
|
|
return plcatool_status(&cfg);
|
|
|
|
case PLCA_CMD_HELP:
|
|
plcatool_usage(false);
|
|
break;
|
|
}
|
|
|
|
return OK;
|
|
}
|