blob: 21c97e02cfd2bb09d0a6d34c67a673011c3480b3 [file] [log] [blame]
/** @file uaphostcmd.c
*
* @brief This file contains uAP hostcmd functions
*
* Copyright (C) 2010-2017, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
* (the "License"). You may use, redistribute and/or modify this File in
* accordance with the terms and conditions of the License, a copy of which
* is available by writing to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
* worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
* ARE EXPRESSLY DISCLAIMED. The License provides additional details about
* this warranty disclaimer.
*
*/
/************************************************************************
Change log:
11/26/2008: initial version
************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "uaputl.h"
#ifndef MIN
/** Find minimum value */
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif /* MIN */
/********************************************************
Local Variables
********************************************************/
/********************************************************
Global Variables
********************************************************/
/********************************************************
Local Functions
********************************************************/
/*
* @brief convert String to integer
*
* @param value A pointer to string
* @return integer
*/
static t_u32
a2hex_or_atoi(char *value)
{
if (value[0] == '0' && (value[1] == 'X' || value[1] == 'x')) {
return a2hex(value + 2);
} else if (isdigit(*value)) {
return atoi(value);
} else {
return *value;
}
}
/**
* @brief Get one line from the File
*
* @param fp File handler
* @param str Storage location for data.
* @param size Maximum number of characters to read.
* @param lineno A pointer to return current line number
* @return returns string or NULL
*/
char *
mlan_config_get_line(FILE * fp, char *str, t_s32 size, int *lineno)
{
char *start, *end;
int out, next_line;
if (!fp || !str)
return NULL;
do {
read_line:
if (!fgets(str, size, fp))
break;
start = str;
start[size - 1] = '\0';
end = start + strlen(str);
(*lineno)++;
out = 1;
while (out && (start < end)) {
next_line = 0;
/* Remove empty lines and lines starting with # */
switch (start[0]) {
case ' ': /* White space */
case '\t': /* Tab */
start++;
break;
case '#':
case '\n':
case '\0':
next_line = 1;
break;
case '\r':
if (start[1] == '\n')
next_line = 1;
else
start++;
break;
default:
out = 0;
break;
}
if (next_line)
goto read_line;
}
/* Remove # comments unless they are within a double quoted
* string. Remove trailing white space. */
if ((end = strstr(start, "\""))) {
if (!(end = strstr(end + 1, "\"")))
end = start;
} else
end = start;
if ((end = strstr(end + 1, "#")))
*end-- = '\0';
else
end = start + strlen(start) - 1;
out = 1;
while (out && (start < end)) {
switch (*end) {
case ' ': /* White space */
case '\t': /* Tab */
case '\n':
case '\r':
*end = '\0';
end--;
break;
default:
out = 0;
break;
}
}
if (start == '\0')
continue;
return start;
} while (1);
return NULL;
}
/**
* @brief get hostcmd data
*
* @param ln A pointer to line number
* @param buf A pointer to hostcmd data
* @param size A pointer to the return size of hostcmd buffer
* @return UAP_SUCCESS
*/
static int
mlan_get_hostcmd_data(FILE * fp, int *ln, t_u8 *buf, t_u16 *size)
{
t_s32 errors = 0, i;
char line[256], *pos, *pos1, *pos2, *pos3;
t_u16 len;
while ((pos = mlan_config_get_line(fp, line, sizeof(line), ln))) {
(*ln)++;
if (strcmp(pos, "}") == 0) {
break;
}
pos1 = strchr(pos, ':');
if (pos1 == NULL) {
printf("Line %d: Invalid hostcmd line '%s'\n", *ln,
pos);
errors++;
continue;
}
*pos1++ = '\0';
pos2 = strchr(pos1, '=');
if (pos2 == NULL) {
printf("Line %d: Invalid hostcmd line '%s'\n", *ln,
pos);
errors++;
continue;
}
*pos2++ = '\0';
len = a2hex_or_atoi(pos1);
if (len < 1 || len > MRVDRV_SIZE_OF_CMD_BUFFER) {
printf("Line %d: Invalid hostcmd line '%s'\n", *ln,
pos);
errors++;
continue;
}
*size += len;
if (*pos2 == '"') {
pos2++;
if ((pos3 = strchr(pos2, '"')) == NULL) {
printf("Line %d: invalid quotation '%s'\n", *ln,
pos);
errors++;
continue;
}
*pos3 = '\0';
memset(buf, 0, len);
memmove(buf, pos2, MIN(strlen(pos2), len));
buf += len;
} else if (*pos2 == '\'') {
pos2++;
if ((pos3 = strchr(pos2, '\'')) == NULL) {
printf("Line %d: invalid quotation '%s'\n", *ln,
pos);
errors++;
continue;
}
*pos3 = ',';
for (i = 0; i < len; i++) {
if ((pos3 = strchr(pos2, ',')) != NULL) {
*pos3 = '\0';
*buf++ = (t_u8)a2hex_or_atoi(pos2);
pos2 = pos3 + 1;
} else
*buf++ = 0;
}
} else if (*pos2 == '{') {
t_u16 tlvlen = 0, tmp_tlvlen;
mlan_get_hostcmd_data(fp, ln, buf + len, &tlvlen);
tmp_tlvlen = tlvlen;
while (len--) {
*buf++ = (t_u8)(tmp_tlvlen & 0xff);
tmp_tlvlen >>= 8;
}
*size += tlvlen;
buf += tlvlen;
} else {
t_u32 value = a2hex_or_atoi(pos2);
while (len--) {
*buf++ = (t_u8)(value & 0xff);
value >>= 8;
}
}
}
return UAP_SUCCESS;
}
/********************************************************
Global Functions
********************************************************/
/**
* @brief Prepare host-command buffer
* @param fname path to the config file
* @param cmd_name Command name
* @param buf A pointer to comand buffer
* @return UAP_SUCCESS--success, otherwise--fail
*/
int
prepare_host_cmd_buffer(char *fname, char *cmd_name, t_u8 *buf)
{
char line[256], cmdname[256], *pos, cmdcode[10];
apcmdbuf *hostcmd;
int ln = 0;
int cmdname_found = 0, cmdcode_found = 0;
FILE *config_fp;
int ret = UAP_SUCCESS;
config_fp = fopen(fname, "r");
if (!config_fp) {
printf("Unable to find %s. Exiting...\n", fname);
return UAP_FAILURE;
}
memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
hostcmd = (apcmdbuf *)buf;
hostcmd->cmd_code = 0xffff;
snprintf(cmdname, sizeof(cmdname), "%s={", cmd_name);
cmdname_found = 0;
while ((pos = mlan_config_get_line(config_fp, line, sizeof(line), &ln))) {
if (strcmp(pos, cmdname) == 0) {
cmdname_found = 1;
snprintf(cmdcode, sizeof(cmdcode), "CmdCode=");
cmdcode_found = 0;
while ((pos =
mlan_config_get_line(config_fp, line,
sizeof(line), &ln))) {
if (strncmp(pos, cmdcode, strlen(cmdcode)) == 0) {
cmdcode_found = 1;
hostcmd->cmd_code =
a2hex_or_atoi(pos +
strlen(cmdcode));
hostcmd->size =
sizeof(apcmdbuf) -
BUF_HEADER_SIZE;
mlan_get_hostcmd_data(config_fp, &ln,
buf +
sizeof(apcmdbuf),
&hostcmd->size);
break;
}
}
if (!cmdcode_found) {
fprintf(stderr,
"uaputl: CmdCode not found in conf file\n");
ret = UAP_FAILURE;
goto done;
}
break;
}
}
if (!cmdname_found) {
fprintf(stderr,
"uaputl: cmdname '%s' is not found in conf file\n",
cmd_name);
ret = UAP_FAILURE;
goto done;
}
done:
fclose(config_fp);
return ret;
}