283 lines
7.2 KiB
C
283 lines
7.2 KiB
C
|
/****************************************************************************
|
||
|
* apps/system/uniqueid/uniqueid_main.c
|
||
|
*
|
||
|
* 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 <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <sys/boardctl.h>
|
||
|
#include <unistd.h>
|
||
|
|
||
|
/****************************************************************************
|
||
|
* Pre-processor Definitions
|
||
|
****************************************************************************/
|
||
|
|
||
|
/****************************************************************************
|
||
|
* Private Data
|
||
|
****************************************************************************/
|
||
|
|
||
|
struct cfg_s
|
||
|
{
|
||
|
const FAR char *delim;
|
||
|
const FAR char *format;
|
||
|
uint8_t positions[CONFIG_BOARDCTL_UNIQUEID_SIZE];
|
||
|
size_t count;
|
||
|
const FAR char *prefix;
|
||
|
};
|
||
|
|
||
|
/****************************************************************************
|
||
|
* Private Functions
|
||
|
****************************************************************************/
|
||
|
|
||
|
static int parse_positions(FAR char *arg, FAR uint8_t *positions,
|
||
|
FAR size_t *count)
|
||
|
{
|
||
|
char *list_save;
|
||
|
char *list_item;
|
||
|
char *range_save;
|
||
|
char *range_item;
|
||
|
char *endptr;
|
||
|
int pos;
|
||
|
int pos2;
|
||
|
|
||
|
#define APPEND_POSITION(pos) \
|
||
|
do \
|
||
|
{ \
|
||
|
if ((*count) >= CONFIG_BOARDCTL_UNIQUEID_SIZE) \
|
||
|
{ \
|
||
|
fprintf(stderr, "ERROR: Too many bytes selected\n"); \
|
||
|
return -1; \
|
||
|
} \
|
||
|
\
|
||
|
positions[*count] = pos; \
|
||
|
(*count)++; \
|
||
|
} \
|
||
|
while (0);
|
||
|
|
||
|
list_item = strtok_r(arg, ",", &list_save);
|
||
|
while (list_item)
|
||
|
{
|
||
|
range_item = strtok_r(list_item, "-", &range_save);
|
||
|
pos = strtol(range_item, &endptr, 0);
|
||
|
if (endptr == range_item || *endptr != '\0')
|
||
|
{
|
||
|
fprintf(stderr, "ERROR: Invalid byte position: '%s'\n",
|
||
|
range_item);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
pos--;
|
||
|
if (pos < 0 || pos >= CONFIG_BOARDCTL_UNIQUEID_SIZE)
|
||
|
{
|
||
|
fprintf(stderr, "ERROR: Invalid byte position: '%s'\n",
|
||
|
range_item);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
range_item = strtok_r(0, "-", &range_save);
|
||
|
if (range_item)
|
||
|
{
|
||
|
pos2 = strtol(range_item, &endptr, 0);
|
||
|
if (endptr == range_item || *endptr != '\0')
|
||
|
{
|
||
|
fprintf(stderr, "ERROR: Invalid byte position: '%s'\n",
|
||
|
range_item);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
pos2--;
|
||
|
if (pos2 < 0 || pos2 >= CONFIG_BOARDCTL_UNIQUEID_SIZE)
|
||
|
{
|
||
|
fprintf(stderr, "ERROR: Invalid byte position: '%s'\n",
|
||
|
range_item);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
range_item = strtok_r(0, "-", &range_save);
|
||
|
if (range_item)
|
||
|
{
|
||
|
fprintf(stderr, "ERROR: Invalid byte range: '%d-%d-%s'\n",
|
||
|
pos + 1, pos2 + 1, range_item);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (pos2 > pos)
|
||
|
{
|
||
|
for (; pos <= pos2; pos++)
|
||
|
{
|
||
|
APPEND_POSITION(pos);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (; pos >= pos2; pos--)
|
||
|
{
|
||
|
APPEND_POSITION(pos);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
APPEND_POSITION(pos);
|
||
|
}
|
||
|
|
||
|
list_item = strtok_r(0, ",", &list_save);
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int parsearg(int argc, FAR char *argv[], FAR struct cfg_s *cfg)
|
||
|
{
|
||
|
int opt;
|
||
|
int len;
|
||
|
|
||
|
while ((opt = getopt(argc, argv, ":b:d:f:p:")) != ERROR)
|
||
|
{
|
||
|
switch (opt)
|
||
|
{
|
||
|
case 'b':
|
||
|
if (parse_positions(optarg, cfg->positions, &cfg->count) != 0)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 'd':
|
||
|
cfg->delim = optarg;
|
||
|
break;
|
||
|
|
||
|
case 'f':
|
||
|
len = strlen(optarg);
|
||
|
if (len == 0)
|
||
|
{
|
||
|
fprintf(stderr, "ERROR: Invalid format: '%s'\n", optarg);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
switch (optarg[len - 1])
|
||
|
{
|
||
|
case 'd':
|
||
|
case 'i':
|
||
|
case 'o':
|
||
|
case 'u':
|
||
|
case 'x':
|
||
|
case 'X':
|
||
|
case 'c':
|
||
|
cfg->format = optarg;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
fprintf(stderr, "ERROR: Invalid format: '%s'\n", optarg);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case 'p':
|
||
|
cfg->prefix = optarg;
|
||
|
break;
|
||
|
|
||
|
case ':':
|
||
|
fprintf(stderr, "ERROR: Option needs a value: '%c'\n", optopt);
|
||
|
return -1;
|
||
|
|
||
|
case '?':
|
||
|
fprintf(stderr, "ERROR: Unrecognized option: '%c'\n", optopt);
|
||
|
return -1;
|
||
|
|
||
|
default:
|
||
|
fprintf(stderr, "ERROR: Unhandled getopt: '%c'\n", opt);
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (optind != argc)
|
||
|
{
|
||
|
fprintf(stderr, "ERROR: Too many arguments\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/****************************************************************************
|
||
|
* Public Functions
|
||
|
****************************************************************************/
|
||
|
|
||
|
int main(int argc, FAR char *argv[])
|
||
|
{
|
||
|
uint8_t uniqueid[CONFIG_BOARDCTL_UNIQUEID_SIZE];
|
||
|
char *formatter;
|
||
|
int i;
|
||
|
|
||
|
struct cfg_s cfg = {
|
||
|
.format = "02x",
|
||
|
};
|
||
|
|
||
|
if (parsearg(argc, argv, &cfg) != 0)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (cfg.count == 0)
|
||
|
{
|
||
|
/* Print all bytes if none were specified. */
|
||
|
|
||
|
cfg.count = CONFIG_BOARDCTL_UNIQUEID_SIZE;
|
||
|
for (i = 0; i < cfg.count; i++)
|
||
|
{
|
||
|
cfg.positions[i] = i;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
memset(uniqueid, 0, sizeof(uniqueid));
|
||
|
if (boardctl(BOARDIOC_UNIQUEID, (uintptr_t)&uniqueid) != OK)
|
||
|
{
|
||
|
fprintf(stderr, "ERROR! board_uniqueid() failed\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
formatter = malloc(strlen(cfg.format) + 2);
|
||
|
sprintf(formatter, "%%%s", cfg.format);
|
||
|
|
||
|
if (cfg.prefix != NULL)
|
||
|
{
|
||
|
printf("%s", cfg.prefix);
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < cfg.count; i++)
|
||
|
{
|
||
|
if (i > 0 && cfg.delim != NULL)
|
||
|
{
|
||
|
printf("%s", cfg.delim);
|
||
|
}
|
||
|
|
||
|
printf(formatter, uniqueid[cfg.positions[i]]);
|
||
|
}
|
||
|
|
||
|
putchar('\n');
|
||
|
free(formatter);
|
||
|
|
||
|
return EXIT_SUCCESS;
|
||
|
}
|