shell.c 5.08 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
/*
 * This work is part of the White Rabbit project
 *
 * Copyright (C) 2012 CERN (www.cern.ch)
 * Copyright (C) 2012 GSI (www.gsi.de)
 * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
 * Author: Wesley W. Terpstra <w.terpstra@gsi.de>
 * Author: Grzegorz Daniluk <grzegorz.daniluk@cern.ch>
 *
 * Released according to the GNU GPL, version 2 or any later version.
 */
12 13 14 15
#include <stdio.h>
#include <string.h>
#include <errno.h>

16
#include <wrc.h>
17 18
#include "util.h"
#include "uart.h"
19
#include "syscon.h"
20
#include "shell.h"
21
#include "eeprom.h"
22

23
#define SH_MAX_LINE_LEN 80
24
#define SH_MAX_ARGS 8
25
#define SH_ENVIRON_SIZE 256
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43

/* interactive shell state definitions */

#define SH_PROMPT 0
#define SH_INPUT 1
#define SH_EXEC 2

#define ESCAPE_FLAG 0x10000

#define KEY_LEFT (ESCAPE_FLAG | 68)
#define KEY_RIGHT (ESCAPE_FLAG | 67)
#define KEY_ENTER (13)
#define KEY_ESCAPE (27)
#define KEY_BACKSPACE (127)
#define KEY_DELETE (126)

struct shell_cmd {
	char *name;
44
	int (*exec) (const char *args[]);
45 46 47
};

static const struct shell_cmd cmds_list[] = {
48 49 50 51 52 53 54 55 56 57 58 59 60
	{"pll",		cmd_pll},
	{"gui",		cmd_gui},
	{"ver",		cmd_version},
	{"stat",	cmd_stat},
	{"ptp",		cmd_ptp},
	{"mode",	cmd_mode},
	{"calibration",	cmd_calib},
	{"set",		cmd_set},
	{"env",		cmd_env},
	{"saveenv",	cmd_saveenv},
	{"time",	cmd_time},
	{"sfp",		cmd_sfp},
	{"init",	cmd_init},
61
#ifdef CONFIG_ETHERBONE
62
	{"ip",		cmd_ip},
63
#endif
64 65
	{"mac",		cmd_mac},
	{"sdb",		cmd_sdb},
66

67 68
	{NULL,	NULL}
};
69 70 71 72 73 74 75 76

static char cmd_buf[SH_MAX_LINE_LEN + 1];
static int cmd_pos = 0, cmd_len = 0;
static int state = SH_PROMPT;
static int current_key = 0;

static int insert(char c)
{
77
	if (cmd_len >= SH_MAX_LINE_LEN)
78 79
		return 0;

80 81 82
	if (cmd_pos != cmd_len)
		memmove(&cmd_buf[cmd_pos + 1], &cmd_buf[cmd_pos],
			cmd_len - cmd_pos);
83 84 85 86 87 88 89 90 91 92

	cmd_buf[cmd_pos] = c;
	cmd_pos++;
	cmd_len++;

	return 1;
}

static void delete(int where)
{
93
	memmove(&cmd_buf[where], &cmd_buf[where + 1], cmd_len - where);
94 95 96 97 98 99 100 101 102 103
	cmd_len--;
}

static void esc(char code)
{
	mprintf("\033[1%c", code);
}

static int _shell_exec()
{
104
	char *tokptr[SH_MAX_ARGS + 1];
105 106 107
	int n = 0, i = 0;

	memset(tokptr, 0, sizeof(tokptr));
108

109 110
	while (1) {
		if (n >= SH_MAX_ARGS)
111 112
			break;

113 114
		while (cmd_buf[i] == ' ' && cmd_buf[i])
			cmd_buf[i++] = 0;
115

116
		if (!cmd_buf[i])
117 118
			break;

119 120 121
		tokptr[n++] = &cmd_buf[i];
		while (cmd_buf[i] != ' ' && cmd_buf[i])
			i++;
122

123
		if (!cmd_buf[i])
124 125 126
			break;
	}

127
	if (!n)
128 129
		return 0;

130
	if (*tokptr[0] == '#')
131 132
		return 0;

133 134 135 136
	for (i = 0; cmds_list[i].name; i++)
		if (!strcasecmp(cmds_list[i].name, tokptr[0])) {
			int rv = cmds_list[i].exec((const char **)tokptr + 1);
			if (rv < 0)
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
				mprintf("Err %d\n", rv);
			return rv;
		}

	mprintf("Unrecognized command.\n");
	return -EINVAL;
}

int shell_exec(const char *cmd)
{
	strncpy(cmd_buf, cmd, SH_MAX_LINE_LEN);
	cmd_len = strlen(cmd_buf);
	return _shell_exec();
}

void shell_init()
{
154
	env_init();
155 156
	cmd_len = cmd_pos = 0;
	state = SH_PROMPT;
157
	mprintf("\033[2J\033[1;1H");
158 159 160 161 162
}

void shell_interactive()
{
	int c;
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
	switch (state) {
	case SH_PROMPT:
		mprintf("wrc# ");
		cmd_pos = 0;
		cmd_len = 0;
		state = SH_INPUT;
		break;

	case SH_INPUT:
		c = uart_read_byte();

		if (c < 0)
			return;

		if (c == 27 || ((current_key & ESCAPE_FLAG) && c == 91))
			current_key = ESCAPE_FLAG;
		else
			current_key |= c;

		if (current_key & 0xff) {

			switch (current_key) {
			case KEY_LEFT:
				if (cmd_pos > 0) {
					cmd_pos--;
					esc('D');
				}
				break;
			case KEY_RIGHT:
				if (cmd_pos < cmd_len) {
					cmd_pos++;
					esc('C');
				}
				break;

			case KEY_ENTER:
				mprintf("\n");
				state = SH_EXEC;
				break;
202

203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
			case KEY_DELETE:
				if (cmd_pos != cmd_len) {
					delete(cmd_pos);
					esc('P');
				}
				break;

			case KEY_BACKSPACE:
				if (cmd_pos > 0) {
					esc('D');
					esc('P');
					delete(cmd_pos - 1);
					cmd_pos--;
				}
				break;
218

219 220 221 222 223 224 225 226
			case '\t':
				break;

			default:
				if (!(current_key & ESCAPE_FLAG)
				    && insert(current_key)) {
					esc('@');
					mprintf("%c", current_key);
227
				}
228 229
				break;

230
			}
231 232 233
			current_key = 0;
		}
		break;
234

235 236 237 238 239
	case SH_EXEC:
		cmd_buf[cmd_len] = 0;
		_shell_exec();
		state = SH_PROMPT;
		break;
240 241
	}
}
242

243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
const char *fromhex(const char *hex, int *v)
{
	int o = 0;

	for (; *hex; ++hex) {
		if (*hex >= '0' && *hex <= '9') {
			o = (o << 4) + (*hex - '0');
		} else if (*hex >= 'A' && *hex <= 'F') {
			o = (o << 4) + (*hex - 'A') + 10;
		} else if (*hex >= 'a' && *hex <= 'f') {
			o = (o << 4) + (*hex - 'a') + 10;
		} else {
			break;
		}
	}

	*v = o;
	return hex;
261 262
}

263 264 265
const char *fromdec(const char *dec, int *v)
{
	int o = 0;
266

267 268 269 270 271 272 273
	for (; *dec; ++dec) {
		if (*dec >= '0' && *dec <= '9') {
			o = (o * 10) + (*dec - '0');
		} else {
			break;
		}
	}
274

275 276
	*v = o;
	return dec;
277
}
278 279 280

int shell_boot_script(void)
{
281
	uint8_t next = 0;
282

283
	//first check if EEPROM is really there
284
	eeprom_present(WRPC_FMC_I2C, FMC_EEPROM_ADR);
285 286 287 288 289
	if (!has_eeprom)
		return -1;

	while (1) {
		cmd_len = eeprom_init_readcmd(WRPC_FMC_I2C, FMC_EEPROM_ADR,
290 291
					      (uint8_t *)cmd_buf,
					      SH_MAX_LINE_LEN, next);
292 293 294 295 296 297 298 299 300 301 302 303 304
		if (cmd_len <= 0) {
			if (next == 0)
				mprintf("Empty init script...\n");
			break;
		}
		cmd_buf[cmd_len - 1] = 0;

		mprintf("executing: %s\n", cmd_buf);
		_shell_exec();
		next = 1;
	}

	return 0;
305
}