simio: console can print to file
This is usefull for `tail -f`.
This commit is contained in:
parent
1cb2e5664b
commit
8ce536556a
|
@ -16,6 +16,7 @@
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
@ -32,6 +33,9 @@ struct console {
|
||||||
address_t base_addr;
|
address_t base_addr;
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
unsigned buffer_offset;
|
unsigned buffer_offset;
|
||||||
|
|
||||||
|
/* File output */
|
||||||
|
FILE *file;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct simio_device *console_create(char **arg_text)
|
static struct simio_device *console_create(char **arg_text)
|
||||||
|
@ -56,6 +60,11 @@ static struct simio_device *console_create(char **arg_text)
|
||||||
static void console_destroy(struct simio_device *dev)
|
static void console_destroy(struct simio_device *dev)
|
||||||
{
|
{
|
||||||
struct console *c = (struct console *)dev;
|
struct console *c = (struct console *)dev;
|
||||||
|
|
||||||
|
if (c->file != NULL) {
|
||||||
|
fclose(c->file);
|
||||||
|
}
|
||||||
|
|
||||||
free(c);
|
free(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,6 +72,10 @@ static void console_reset(struct simio_device *dev)
|
||||||
{
|
{
|
||||||
struct console *c = (struct console *)dev;
|
struct console *c = (struct console *)dev;
|
||||||
c->buffer_offset = 0;
|
c->buffer_offset = 0;
|
||||||
|
|
||||||
|
if (c->file != NULL) {
|
||||||
|
rewind(c->file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int config_addr(address_t *addr, char **arg_text)
|
static int config_addr(address_t *addr, char **arg_text)
|
||||||
|
@ -82,15 +95,40 @@ static int config_addr(address_t *addr, char **arg_text)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int config_output(FILE **file, char **arg_text)
|
||||||
|
{
|
||||||
|
char *path = get_arg(arg_text);
|
||||||
|
|
||||||
|
if (path == NULL) {
|
||||||
|
printc_err("console: config: expected path\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't leak the descriptor if configured multiple times
|
||||||
|
if ((*file != NULL) && (*file != stdout)) {
|
||||||
|
fclose(*file);
|
||||||
|
}
|
||||||
|
|
||||||
|
*file = fopen(path, "w");
|
||||||
|
if (*file == NULL) {
|
||||||
|
printc_err("console: can't open %s for writing\n", path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int console_config(struct simio_device *dev,
|
static int console_config(struct simio_device *dev,
|
||||||
const char *param, char **arg_text)
|
const char *param, char **arg_text)
|
||||||
{
|
{
|
||||||
struct console *c = (struct console *)dev;
|
struct console *c = (struct console *)dev;
|
||||||
|
|
||||||
if (!strcasecmp(param, "base"))
|
if (!strcasecmp(param, "base")) {
|
||||||
{
|
|
||||||
return config_addr(&c->base_addr, arg_text);
|
return config_addr(&c->base_addr, arg_text);
|
||||||
}
|
}
|
||||||
|
else if (!strcasecmp(param, "output")) {
|
||||||
|
return config_output(&c->file, arg_text);
|
||||||
|
}
|
||||||
|
|
||||||
printc_err("console: config: unknown parameter: %s\n", param);
|
printc_err("console: config: unknown parameter: %s\n", param);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -108,7 +146,26 @@ static int console_write_b(struct simio_device *dev,
|
||||||
address_t addr, uint8_t data)
|
address_t addr, uint8_t data)
|
||||||
{
|
{
|
||||||
struct console *c = (struct console *)dev;
|
struct console *c = (struct console *)dev;
|
||||||
if (addr == c->base_addr)
|
|
||||||
|
if (addr != c->base_addr) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// write either to file or buffer
|
||||||
|
if (c->file != NULL)
|
||||||
|
{
|
||||||
|
size_t nbytes = sizeof(data);
|
||||||
|
if (fwrite(&data, nbytes, 1, c->file) != nbytes) {
|
||||||
|
printc_err("console: write error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for tail -f
|
||||||
|
if (data == '\n') {
|
||||||
|
fflush(c->file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // buffer
|
||||||
{
|
{
|
||||||
c->buffer[c->buffer_offset++] = data;
|
c->buffer[c->buffer_offset++] = data;
|
||||||
if (data == '\n' || c->buffer_offset == sizeof c->buffer)
|
if (data == '\n' || c->buffer_offset == sizeof c->buffer)
|
||||||
|
@ -117,17 +174,20 @@ static int console_write_b(struct simio_device *dev,
|
||||||
c->buffer_offset = 0;
|
c->buffer_offset = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct simio_class simio_console = {
|
const struct simio_class simio_console = {
|
||||||
.name = "console",
|
.name = "console",
|
||||||
.help =
|
.help =
|
||||||
"This peripheral prints to stdout every byte written to base address\n"
|
"This peripheral prints to buffer or file every byte written to base address\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Config arguments are:\n"
|
"Config arguments are:\n"
|
||||||
" base <address>\n"
|
" base <address>\n"
|
||||||
" Set the peripheral base address. Defaults to 0x00FF\n"
|
" Set the peripheral base address. Defaults to 0x00FF\n"
|
||||||
|
" output <path>\n"
|
||||||
|
" Print to file instead of a buffer.\n"
|
||||||
"\n",
|
"\n",
|
||||||
|
|
||||||
.create = console_create,
|
.create = console_create,
|
||||||
|
|
Loading…
Reference in New Issue