Initial revision
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
include ../Makefile.config
|
||||
|
||||
########################################################################
|
||||
# You shouldn't need to touch anything below here.
|
||||
########################################################################
|
||||
|
||||
TARGET = LCDd
|
||||
DIRS = drivers
|
||||
OBJ += sock.o clients.o parse.o client_functions.o client_data.o screen.o \
|
||||
widget.o screenlist.o render.o serverscreens.o main.o input.o \
|
||||
menu.o menus.o
|
||||
LIB += drivers/libLCDdrivers.a ../shared/libLCDstuff.a
|
||||
|
||||
ifeq ($(IRMAN),1)
|
||||
LIB += ../../libirman-0.4.1b/libirman.a
|
||||
endif
|
||||
|
||||
|
||||
include ../Makefile.config
|
||||
|
||||
###################################################################
|
||||
# Compilation...
|
||||
#
|
||||
#all: $(OBJ)
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJ) $(LIB) Makefile
|
||||
$(GCC) -s $(MISC) -o $(TARGET) $(OBJ) $(LIB)
|
||||
|
||||
%.o: %.c %.h Makefile
|
||||
$(GCC) -c $(MISC) $<
|
||||
|
||||
|
||||
##################################################################
|
||||
# Installation
|
||||
#
|
||||
install: $(TARGET)
|
||||
@echo Installing LCD Server...
|
||||
install -m 0755 -o root -g root $(TARGET) /usr/local/bin/
|
||||
|
||||
|
||||
##################################################################
|
||||
# Other stuff...
|
||||
#
|
||||
clean:
|
||||
@for i in $(DIRS); do \
|
||||
(cd $$i; [ -f Makefile ] && $(MAKE) $@) \
|
||||
done
|
||||
rm -f $(OBJ) $(TARGET) *~ core
|
||||
|
||||
edit:
|
||||
emacs . &
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
client_data.c
|
||||
|
||||
Creates and destroys a client's data structures. These are mainly
|
||||
its name, screen list, and menu list.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../shared/debug.h"
|
||||
|
||||
#include "client_data.h"
|
||||
#include "screen.h"
|
||||
#include "screenlist.h"
|
||||
|
||||
|
||||
|
||||
int client_data_init(client_data *d)
|
||||
{
|
||||
if(!d) return -1;
|
||||
|
||||
d->ack = 0;
|
||||
d->name = NULL;
|
||||
|
||||
d->screenlist = LL_new();
|
||||
if(!d->screenlist)
|
||||
{
|
||||
fprintf(stderr, "client_data_init: Error allocating screenlist\n");
|
||||
return -1;
|
||||
}
|
||||
/* TODO: this section... (client menus)
|
||||
d->menulist = LL_new();
|
||||
if(!d->menulist)
|
||||
{
|
||||
fprintf(stderr, "client_data_init: Error allocating menulist\n");
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
int client_data_destroy(client_data *d)
|
||||
{
|
||||
screen *s;
|
||||
|
||||
debug("client_data_destroy\n");
|
||||
|
||||
if(!d) return -1;
|
||||
|
||||
d->ack = 0;
|
||||
|
||||
// Clean up the name...
|
||||
if(d->name)
|
||||
free(d->name);
|
||||
|
||||
// Clean up the screenlist...
|
||||
debug("client_data_destroy: Cleaning screenlist\n");
|
||||
LL_Rewind(d->screenlist);
|
||||
do {
|
||||
s = (screen *)LL_Get(d->screenlist);
|
||||
if(s)
|
||||
{
|
||||
debug("client_data_destroy: removing screen %s\n", s->id);
|
||||
|
||||
// FIXME? This shouldn't be handled here...
|
||||
// Now, remove it from the screenlist...
|
||||
if(screenlist_remove_all(s) < 0)
|
||||
{
|
||||
// Not a serious error..
|
||||
fprintf(stderr, "client_data_destroy: Error dequeueing screen\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Free its memory...
|
||||
screen_destroy(s);
|
||||
}
|
||||
} while(LL_Next(d->screenlist) == 0);
|
||||
LL_Destroy(d->screenlist);
|
||||
|
||||
// TODO: clean up the rest of the data...
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef CLIENT_DATA_H
|
||||
#define CLIENT_DATA_H
|
||||
|
||||
#include "../shared/LL.h"
|
||||
|
||||
|
||||
#define CLIENT_NAME_SIZE 256
|
||||
|
||||
typedef struct client_data
|
||||
{
|
||||
int ack;
|
||||
char *name;
|
||||
// and other stuff... doesn't matter yet
|
||||
LL * screenlist;
|
||||
// list of accepted keys... (?)
|
||||
LL * menulist;
|
||||
|
||||
} client_data;
|
||||
|
||||
|
||||
// sets up an existing (empty) client_data struct
|
||||
int client_data_init(client_data *d);
|
||||
// destroys members of a client's data
|
||||
int client_data_destroy(client_data *d);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,986 @@
|
||||
/*
|
||||
client_functions.c
|
||||
|
||||
This contains definitions for all the functions which clients can run.
|
||||
The functions here are to be called only from parse.c's interpreter.
|
||||
|
||||
The client's available function set is defined here, as is the syntax
|
||||
for each command.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "../shared/debug.h"
|
||||
#include "../shared/sockets.h"
|
||||
|
||||
#include "drivers/lcd.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "render.h"
|
||||
#include "clients.h"
|
||||
#include "parse.h"
|
||||
#include "screen.h"
|
||||
#include "widget.h"
|
||||
#include "client_functions.h"
|
||||
|
||||
|
||||
client_function commands[] = {
|
||||
{"test_func", test_func_func },
|
||||
{"hello", hello_func},
|
||||
{"client_set", client_set_func},
|
||||
{"client_add_key", client_add_key_func},
|
||||
{"client_del_key", client_del_key_func},
|
||||
{"screen_add", screen_add_func},
|
||||
{"screen_del", screen_del_func},
|
||||
{"screen_set", screen_set_func},
|
||||
{"widget_add", widget_add_func},
|
||||
{"widget_del", widget_del_func},
|
||||
{"widget_set", widget_set_func},
|
||||
{"menu_add", menu_add_func},
|
||||
{"menu_del", menu_del_func},
|
||||
{"menu_set", menu_set_func},
|
||||
// TODO: Adhere these to the naming convention?
|
||||
{"menu_item_add", menu_item_add_func},
|
||||
{"menu_item_del", menu_item_del_func},
|
||||
{"menu_item_set", menu_item_set_func},
|
||||
// Misc stuff...
|
||||
{"backlight", backlight_func},
|
||||
{"output", output_func},
|
||||
{NULL, NULL },
|
||||
};
|
||||
|
||||
|
||||
// TODO: Maybe more error-checking for "->"'s?
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Debugging only.. prints out a list of arguments it receives
|
||||
//
|
||||
int test_func_func(client *c, int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
char str[256];
|
||||
|
||||
for(i=0; i<argc; i++)
|
||||
{
|
||||
sprintf(str, "test_func_func: %i -> %s\n", i, argv[i]);
|
||||
printf(str);
|
||||
sock_send_string(c->sock, str);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The client must say "hello" before doing anything else.
|
||||
//
|
||||
// It returns a string of info about the server to the client
|
||||
//
|
||||
int hello_func(client *c, int argc, char **argv)
|
||||
{
|
||||
char str[256];
|
||||
|
||||
// TODO: Give *real* info about the server/lcd...
|
||||
|
||||
debug("Hello!\n");
|
||||
|
||||
sprintf(str,
|
||||
"connect LCDproc %s lcd wid %i hgt %i cellwid %i cellhgt %i\n",
|
||||
version, lcd.wid, lcd.hgt, lcd.cellwid, lcd.cellhgt);
|
||||
sock_send_string(c->sock, str);
|
||||
|
||||
if(c->data)
|
||||
c->data->ack = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// sets info about the client, such as its name
|
||||
//
|
||||
int client_set_func(client *c, int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(!c->data->ack) return 1;
|
||||
|
||||
for(i=1; i<argc; i++)
|
||||
{
|
||||
// Handle the "name" parameter
|
||||
if(0 == strcmp(argv[i], "name"))
|
||||
{
|
||||
if(argc > i+1)
|
||||
{
|
||||
i++;
|
||||
debug("client_set: name=\"%s\"\n", argv[i]);
|
||||
|
||||
// set the name...
|
||||
if(c->data->name)
|
||||
free(c->data->name);
|
||||
c->data->name = strdup(argv[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
sock_send_string(c->sock, "huh? name requires a parameter\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sock_send_string(c->sock, "huh? invalid parameter\n");
|
||||
}
|
||||
}
|
||||
|
||||
// If there were no parameters...
|
||||
if(argc == 1)
|
||||
sock_send_string(c->sock, "huh? What do you want to set?\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Tells the server the client would like to accept keypresses
|
||||
// of a particular type
|
||||
//
|
||||
int client_add_key_func(client *c, int argc, char **argv)
|
||||
{
|
||||
|
||||
|
||||
if(!c->data->ack) return 1;
|
||||
|
||||
sock_send_string(c->sock, "huh? Not implemented yet.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Tells the server the client would NOT like to accept keypresses
|
||||
// of a particular type
|
||||
//
|
||||
int client_del_key_func(client *c, int argc, char **argv)
|
||||
{
|
||||
|
||||
|
||||
if(!c->data->ack) return 1;
|
||||
|
||||
sock_send_string(c->sock, "huh? Not implemented yet.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Tells the server the client has another screen to offer
|
||||
//
|
||||
int screen_add_func(client *c, int argc, char **argv)
|
||||
{
|
||||
int err=0;
|
||||
|
||||
if(!c->data->ack) return 1;
|
||||
|
||||
if(argc < 2)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Specify a screen #id\n");
|
||||
return 0;
|
||||
}
|
||||
if(argc > 2)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Too many parameters...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
debug("screen_add: Adding screen %s\n", argv[1]);
|
||||
err = screen_add(c, argv[1]);
|
||||
if(err < 0)
|
||||
fprintf(stderr, "screen_add_func: Error adding screen\n");
|
||||
if(err > 0)
|
||||
sock_send_string(c->sock,
|
||||
"huh? You already have a screen with that id#\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Client requests that the server forget about a screen
|
||||
//
|
||||
int screen_del_func(client *c, int argc, char **argv)
|
||||
{
|
||||
int err=0;
|
||||
|
||||
if(!c->data->ack) return 1;
|
||||
|
||||
if(argc < 2)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Specify a screen #id\n");
|
||||
return 0;
|
||||
}
|
||||
if(argc > 2)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Too many parameters...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
debug("screen_del: Deleting screen %s\n", argv[1]);
|
||||
err = screen_remove(c, argv[1]);
|
||||
if(err < 0)
|
||||
fprintf(stderr, "screen_del_func: Error removing screen\n");
|
||||
if(err > 0)
|
||||
sock_send_string(c->sock,
|
||||
"huh? You don't have a screen with that id#\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Configures info about a particular screen, such as its
|
||||
// name, priority, or duration
|
||||
//
|
||||
int screen_set_func(client *c, int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
int number;
|
||||
char *id;
|
||||
screen *s;
|
||||
|
||||
if(!c->data->ack) return 1;
|
||||
|
||||
|
||||
// If there weren't enough parameters...
|
||||
if(argc < 2)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? You must specify a screen id\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(argc == 2)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? What do you want to set?\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
id = argv[1];
|
||||
s = screen_find(c, id);
|
||||
if(!s)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Invalid screen id\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle the rest of the parameters
|
||||
for(i=2; i<argc; i++)
|
||||
{
|
||||
// Handle the "name" parameter
|
||||
if(0 == strcmp(argv[i], "name"))
|
||||
{
|
||||
if(argc > i+1)
|
||||
{
|
||||
i++;
|
||||
debug("screen_set: name=\"%s\"\n", argv[i]);
|
||||
|
||||
// set the name...
|
||||
if(s->name)
|
||||
free(s->name);
|
||||
s->name = strdup(argv[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
sock_send_string(c->sock, "huh? name requires a parameter\n");
|
||||
}
|
||||
}
|
||||
// Handle the "priority" parameter
|
||||
else if(0 == strcmp(argv[i], "priority"))
|
||||
{
|
||||
if(argc > i+1)
|
||||
{
|
||||
i++;
|
||||
debug("screen_set: priority=\"%s\"\n", argv[i]);
|
||||
|
||||
// set the priority...
|
||||
number = atoi(argv[i]);
|
||||
if(number > 0)
|
||||
s->priority = number;
|
||||
}
|
||||
else
|
||||
{
|
||||
sock_send_string(c->sock, "huh? priority requires a parameter\n");
|
||||
}
|
||||
}
|
||||
// Handle the "duration" parameter
|
||||
else if(0 == strcmp(argv[i], "duration"))
|
||||
{
|
||||
if(argc > i+1)
|
||||
{
|
||||
i++;
|
||||
debug("screen_set: duration=\"%s\"\n", argv[i]);
|
||||
|
||||
// set the duration...
|
||||
number = atoi(argv[i]);
|
||||
if(number > 0)
|
||||
s->duration = number;
|
||||
}
|
||||
else
|
||||
{
|
||||
sock_send_string(c->sock, "huh? duration requires a parameter\n");
|
||||
}
|
||||
}
|
||||
// Handle the "wid" parameter
|
||||
else if(0 == strcmp(argv[i], "wid"))
|
||||
{
|
||||
if(argc > i+1)
|
||||
{
|
||||
i++;
|
||||
debug("screen_set: wid=\"%s\"\n", argv[i]);
|
||||
|
||||
// set the duration...
|
||||
number = atoi(argv[i]);
|
||||
if(number > 0)
|
||||
s->wid = number;
|
||||
}
|
||||
else
|
||||
{
|
||||
sock_send_string(c->sock, "huh? wid requires a parameter\n");
|
||||
}
|
||||
}
|
||||
// Handle the "hgt" parameter
|
||||
else if(0 == strcmp(argv[i], "hgt"))
|
||||
{
|
||||
if(argc > i+1)
|
||||
{
|
||||
i++;
|
||||
debug("screen_set: hgt=\"%s\"\n", argv[i]);
|
||||
|
||||
// set the duration...
|
||||
number = atoi(argv[i]);
|
||||
if(number > 0)
|
||||
s->hgt = number;
|
||||
}
|
||||
else
|
||||
{
|
||||
sock_send_string(c->sock, "huh? hgt requires a parameter\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sock_send_string(c->sock, "huh? invalid parameter\n");
|
||||
}
|
||||
} // done checking argv
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Adds a widget to a screen, but doesn't give it a value
|
||||
//
|
||||
int widget_add_func(client *c, int argc, char **argv)
|
||||
{
|
||||
int err;
|
||||
|
||||
char *type;
|
||||
char *sid;
|
||||
char *wid;
|
||||
char *in = NULL;
|
||||
screen *s;
|
||||
|
||||
|
||||
if(!c->data->ack) return 1;
|
||||
|
||||
|
||||
// If there weren't enough parameters...
|
||||
if(argc < 2)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? You must specify a screen id\n");
|
||||
return 0;
|
||||
}
|
||||
if(argc < 3)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? You must specify a widget id\n");
|
||||
return 0;
|
||||
}
|
||||
if(argc < 4)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? You must specify a widget type\n");
|
||||
return 0;
|
||||
}
|
||||
if(argc > 6)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Too many parameters\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
sid = argv[1];
|
||||
wid = argv[2];
|
||||
|
||||
s = screen_find(c, sid);
|
||||
if(!s)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Invalid screen id\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
type = argv[3];
|
||||
|
||||
// Check for additional flags...
|
||||
if(argc > 4)
|
||||
{
|
||||
// Handle the "-in" flag to place widgets in a container...
|
||||
if(0 == strcmp(argv[4], "-in"))
|
||||
{
|
||||
if(argc < 6)
|
||||
{
|
||||
sock_send_string(c->sock,
|
||||
"huh? Specify a frame to place widget in\n");
|
||||
return 0;
|
||||
}
|
||||
in = argv[5];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add the widget and set its type...
|
||||
err = widget_add(s, wid, type, in, c->sock);
|
||||
if(err<0)
|
||||
fprintf(stderr, "widget_add_func: Error adding widget\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Removes a widget from a screen, and forgets about it
|
||||
//
|
||||
int widget_del_func(client *c, int argc, char **argv)
|
||||
{
|
||||
int err=0;
|
||||
|
||||
char *sid;
|
||||
char *wid;
|
||||
screen *s;
|
||||
|
||||
if(!c->data->ack) return 1;
|
||||
|
||||
// Check the number of parameters...
|
||||
if(argc < 2)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Specify a screen #id\n");
|
||||
return 0;
|
||||
}
|
||||
if(argc < 3)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Specify a widget #id\n");
|
||||
return 0;
|
||||
}
|
||||
if(argc > 3)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Too many parameters...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
sid = argv[1];
|
||||
wid = argv[2];
|
||||
|
||||
debug("screen_del: Deleting widget %s.%s\n", sid, wid);
|
||||
|
||||
s = screen_find(c, sid);
|
||||
if(!s)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Invalid screen id\n");
|
||||
}
|
||||
|
||||
err = widget_remove(s, wid, c->sock);
|
||||
if(err < 0)
|
||||
fprintf(stderr, "widget_del_func: Error removing widget\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Configures information about a widget, such as its size, shape,
|
||||
// contents, position, speed, etc...
|
||||
//
|
||||
// Ack! This is long!
|
||||
int widget_set_func(client *c, int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
int x, y;
|
||||
int left, top, right, bottom;
|
||||
int length, direction;
|
||||
int width, height;
|
||||
int speed;
|
||||
char *sid, *wid;
|
||||
screen *s;
|
||||
widget *w;
|
||||
|
||||
if(!c->data->ack) return 1;
|
||||
|
||||
|
||||
// If there weren't enough parameters...
|
||||
if(argc < 2)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? You must specify a screen id\n");
|
||||
return 0;
|
||||
}
|
||||
if(argc < 3)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? You must specify a widget id\n");
|
||||
return 0;
|
||||
}
|
||||
if(argc < 4)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? You must send some widget data\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
sid = argv[1];
|
||||
wid = argv[2];
|
||||
s = screen_find(c, sid);
|
||||
if(!s)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Invalid screen id\n");
|
||||
return 0;
|
||||
}
|
||||
w = widget_find(s, wid);
|
||||
if(!w)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Invalid widget id\n");
|
||||
// Client Debugging...
|
||||
{
|
||||
int i;
|
||||
fprintf(stderr, "huh? Invalid widget id (%s)\n", wid);
|
||||
for(i=0; i<argc; i++)
|
||||
fprintf(stderr, "%s ", argv[i]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// FIXME? Shouldn't this be handled in widget.c?
|
||||
i = 3;
|
||||
switch(w->type)
|
||||
{
|
||||
case WID_STRING: // String takes "x y text"
|
||||
if(argc != i+3)
|
||||
sock_send_string(c->sock, "huh? Wrong number of arguments\n");
|
||||
else
|
||||
{
|
||||
if((!isdigit(argv[i][0])) || (!isdigit(argv[i+1][0])))
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Invalid coordinates\n");
|
||||
}
|
||||
else // Set all the data...
|
||||
{
|
||||
x = atoi(argv[i]);
|
||||
y = atoi(argv[i+1]);
|
||||
w->x = x;
|
||||
w->y = y;
|
||||
if(w->text)
|
||||
free(w->text);
|
||||
w->text = strdup(argv[i+2]);
|
||||
if(!w->text)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"widget_set_func: Error allocating string\n");
|
||||
return -1;
|
||||
}
|
||||
debug("Widget %s set to %s\n", wid, w->text);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WID_HBAR: // Hbar takes "x y length"
|
||||
if(argc != i+3)
|
||||
sock_send_string(c->sock, "huh? Wrong number of arguments\n");
|
||||
else
|
||||
{
|
||||
if((!isdigit(argv[i][0])) || (!isdigit(argv[i+1][0])))
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Invalid coordinates\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
x = atoi(argv[i]);
|
||||
y = atoi(argv[i+1]);
|
||||
length = atoi(argv[i+2]);
|
||||
w->x = x;
|
||||
w->y = y;
|
||||
w->length = length;
|
||||
}
|
||||
debug("Widget %s set to %i\n", wid, w->length);
|
||||
}
|
||||
break;
|
||||
case WID_VBAR: // Vbar takes "x y length"
|
||||
if(argc != i+3)
|
||||
sock_send_string(c->sock, "huh? Wrong number of arguments\n");
|
||||
else
|
||||
{
|
||||
if((!isdigit(argv[i][0])) || (!isdigit(argv[i+1][0])))
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Invalid coordinates\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
x = atoi(argv[i]);
|
||||
y = atoi(argv[i+1]);
|
||||
length = atoi(argv[i+2]);
|
||||
w->x = x;
|
||||
w->y = y;
|
||||
w->length = length;
|
||||
}
|
||||
debug("Widget %s set to %i\n", wid, w->length);
|
||||
}
|
||||
break;
|
||||
case WID_ICON: // Icon takes "x y binary_data"
|
||||
if(argc != i+3)
|
||||
sock_send_string(c->sock, "huh? Wrong number of arguments\n");
|
||||
else
|
||||
{
|
||||
if((!isdigit(argv[i][0])) || (!isdigit(argv[i+1][0])))
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Invalid coordinates\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
x = atoi(argv[i]);
|
||||
y = atoi(argv[i+1]);
|
||||
w->x = x;
|
||||
w->y = y;
|
||||
// TODO: Parse binary data and copy it to widget's data...
|
||||
}
|
||||
}
|
||||
sock_send_string(c->sock, "huh? Widget type not yet implemented\n");
|
||||
break;
|
||||
case WID_TITLE: // title takes "text"
|
||||
if(argc != i+1)
|
||||
sock_send_string(c->sock, "huh? Wrong number of arguments\n");
|
||||
else
|
||||
{
|
||||
if(w->text)
|
||||
free(w->text);
|
||||
w->text = strdup(argv[i]);
|
||||
if(!w->text)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"widget_set_func: Error allocating string\n");
|
||||
return -1;
|
||||
}
|
||||
debug("Widget %s set to %s\n", wid, w->text);
|
||||
}
|
||||
break;
|
||||
case WID_SCROLLER: // Scroller takes "left top right bottom direction speed text"
|
||||
if(argc != i+7) {
|
||||
sock_send_string(c->sock, "huh? Wrong number of arguments\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if((!isdigit(argv[i][0])) ||
|
||||
(!isdigit(argv[i+1][0])) ||
|
||||
(!isdigit(argv[i+2][0])) ||
|
||||
(!isdigit(argv[i+3][0])))
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Invalid coordinates\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
left = atoi(argv[i]);
|
||||
//debug("left: %d\n",left);
|
||||
top = atoi(argv[i+1]);
|
||||
//debug("top: %d\n",top);
|
||||
right = atoi(argv[i+2]);
|
||||
//debug("right: %d\n",right);
|
||||
bottom = atoi(argv[i+3]);
|
||||
//debug("bottom: %d\n",bottom);
|
||||
direction = (int)(argv[i+4][0]);
|
||||
//debug("dir: %c\n",(char)direction);
|
||||
speed = atoi(argv[i+5]);
|
||||
//debug("speed: %d\n",speed);
|
||||
// Direction must be v or h
|
||||
if(((char)direction != 'h') && ((char)direction != 'v'))
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Invalid direction\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
w->left = left;
|
||||
w->top = top;
|
||||
w->right = right;
|
||||
w->bottom = bottom;
|
||||
w->length = direction;
|
||||
w->speed = speed;
|
||||
if(w->text)
|
||||
free(w->text);
|
||||
w->text = strdup(argv[i+6]);
|
||||
if(!w->text)
|
||||
{
|
||||
fprintf(stderr, "widget_set_func: Error allocating string\n");
|
||||
return -1;
|
||||
}
|
||||
debug("Widget %s set to %s\n", wid, w->text);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WID_FRAME: // Frame takes "left top right bottom wid hgt direction speed"
|
||||
if(argc != i+8) {
|
||||
sock_send_string(c->sock, "huh? Wrong number of arguments\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if((!isdigit(argv[i][0])) ||
|
||||
(!isdigit(argv[i+1][0])) ||
|
||||
(!isdigit(argv[i+2][0])) ||
|
||||
(!isdigit(argv[i+3][0])) ||
|
||||
(!isdigit(argv[i+4][0])) ||
|
||||
(!isdigit(argv[i+5][0])))
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Invalid coordinates\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
left = atoi(argv[i]);
|
||||
//debug("left: %d\n",left);
|
||||
top = atoi(argv[i+1]);
|
||||
//debug("top: %d\n",top);
|
||||
right = atoi(argv[i+2]);
|
||||
//debug("right: %d\n",right);
|
||||
bottom = atoi(argv[i+3]);
|
||||
//debug("bottom: %d\n",bottom);
|
||||
width = atoi(argv[i+4]);
|
||||
//debug("right: %d\n",right);
|
||||
height = atoi(argv[i+5]);
|
||||
//debug("bottom: %d\n",bottom);
|
||||
direction = (int)(argv[i+6][0]);
|
||||
//debug("dir: %c\n",(char)direction);
|
||||
speed = atoi(argv[i+7]);
|
||||
//debug("speed: %d\n",speed);
|
||||
// Direction must be v or h
|
||||
if(((char)direction != 'h') && ((char)direction != 'v'))
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Invalid direction\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
w->left = left;
|
||||
w->top = top;
|
||||
w->right = right;
|
||||
w->bottom = bottom;
|
||||
w->wid = width;
|
||||
w->hgt = height;
|
||||
w->length = direction;
|
||||
w->speed = speed;
|
||||
debug("Widget %s set to (%i,%i)-(%i,%i) %ix%i\n",
|
||||
wid, left, top, right, bottom, width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WID_NUM: // Num takes "x num"
|
||||
if(argc != i+2)
|
||||
sock_send_string(c->sock, "huh? Wrong number of arguments\n");
|
||||
else
|
||||
{
|
||||
if(!isdigit(argv[i][0]))
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Invalid coordinates\n");
|
||||
} else if(!isdigit(argv[i+1][0]))
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Invalid number\n");
|
||||
} else
|
||||
{
|
||||
x = atoi(argv[i]);
|
||||
y = atoi(argv[i+1]);
|
||||
w->x = x;
|
||||
w->y = y;
|
||||
}
|
||||
debug("Widget %s set to %i\n", wid, w->y);
|
||||
}
|
||||
break;
|
||||
case WID_NONE:
|
||||
default:
|
||||
sock_send_string(c->sock, "huh? Widget has no type\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Adds a menu to the client; handled by the server...
|
||||
//
|
||||
int menu_add_func(client *c, int argc, char **argv)
|
||||
{
|
||||
|
||||
|
||||
if(!c->data->ack) return 1;
|
||||
|
||||
sock_send_string(c->sock, "huh? Not implemented yet.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Removes a client's menu and all contents from the server
|
||||
//
|
||||
int menu_del_func(client *c, int argc, char **argv)
|
||||
{
|
||||
|
||||
|
||||
if(!c->data->ack) return 1;
|
||||
|
||||
sock_send_string(c->sock, "huh? Not implemented yet.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Sets info about a menu, but not its items
|
||||
//
|
||||
// For example, should the menu be top-level, or buried somewhere?
|
||||
//
|
||||
int menu_set_func(client *c, int argc, char **argv)
|
||||
{
|
||||
|
||||
|
||||
if(!c->data->ack) return 1;
|
||||
|
||||
sock_send_string(c->sock, "huh? Not implemented yet.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Adds an item to a menu
|
||||
//
|
||||
int menu_item_add_func(client *c, int argc, char **argv)
|
||||
{
|
||||
|
||||
|
||||
if(!c->data->ack) return 1;
|
||||
|
||||
sock_send_string(c->sock, "huh? Not implemented yet.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Deletes an item from a menu
|
||||
//
|
||||
int menu_item_del_func(client *c, int argc, char **argv)
|
||||
{
|
||||
|
||||
|
||||
if(!c->data->ack) return 1;
|
||||
|
||||
sock_send_string(c->sock, "huh? Not implemented yet.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Sets the info about a menu item
|
||||
//
|
||||
// For example, text displayed, widget type, value, etc...
|
||||
//
|
||||
int menu_item_set_func(client *c, int argc, char **argv)
|
||||
{
|
||||
|
||||
|
||||
if(!c->data->ack) return 1;
|
||||
|
||||
sock_send_string(c->sock, "huh? Not implemented yet.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Toggles the backlight, if enabled.
|
||||
//
|
||||
int backlight_func(client *c, int argc, char **argv)
|
||||
{
|
||||
if(!c->data->ack) return 1;
|
||||
|
||||
// Check the number of parameters...
|
||||
if(argc < 2)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Specify a screen #id\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(argc > 2)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Too many parameters...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
debug("backlight(%s)\n", argv[1]);
|
||||
|
||||
|
||||
switch(backlight)
|
||||
{
|
||||
case BACKLIGHT_OPEN:
|
||||
if(0 == strcmp("on", argv[1]))
|
||||
{
|
||||
backlight_state = BACKLIGHT_ON;
|
||||
}
|
||||
if(0 == strcmp("off", argv[1]))
|
||||
{
|
||||
backlight_state = BACKLIGHT_OFF;
|
||||
}
|
||||
if(0 == strcmp("toggle", argv[1]))
|
||||
{
|
||||
if(backlight_state == BACKLIGHT_ON)
|
||||
backlight_state = BACKLIGHT_OFF;
|
||||
else if(backlight_state == BACKLIGHT_OFF)
|
||||
backlight_state = BACKLIGHT_ON;
|
||||
}
|
||||
if(0 == strcmp("blink", argv[1]))
|
||||
{
|
||||
backlight_state |= BACKLIGHT_BLINK;
|
||||
}
|
||||
if(0 == strcmp("flash", argv[1]))
|
||||
{
|
||||
backlight_state |= BACKLIGHT_FLASH;
|
||||
}
|
||||
break;
|
||||
case BACKLIGHT_VIS:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Sets the output port on MtxOrb LCDs
|
||||
int output_func(client *c, int argc, char **argv)
|
||||
{
|
||||
if(argc != 2)
|
||||
{
|
||||
sock_send_string(c->sock, "huh? Too many parameters...\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(0 == strcmp(argv[1], "on"))
|
||||
output_state = 1;
|
||||
else
|
||||
output_state = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
#ifndef CLIENT_FUNCTION_H
|
||||
#define CLIENT_FUNCTION_H
|
||||
|
||||
|
||||
/*
|
||||
The function list for clients is stored in a table, and the items each
|
||||
point to a function to call, defined below.
|
||||
*/
|
||||
|
||||
typedef struct client_function
|
||||
{
|
||||
char *keyword;
|
||||
int (*function)(client *c, int argc, char **argv);
|
||||
} client_function;
|
||||
|
||||
// FIXME? Do these really need to be visible from other sources?
|
||||
int test_func_func(client *c, int argc, char **argv);
|
||||
int hello_func(client *c, int argc, char **argv);
|
||||
int client_set_func(client *c, int argc, char **argv);
|
||||
int client_add_key_func(client *c, int argc, char **argv);
|
||||
int client_del_key_func(client *c, int argc, char **argv);
|
||||
int screen_add_func(client *c, int argc, char **argv);
|
||||
int screen_del_func(client *c, int argc, char **argv);
|
||||
int screen_set_func(client *c, int argc, char **argv);
|
||||
int widget_add_func(client *c, int argc, char **argv);
|
||||
int widget_del_func(client *c, int argc, char **argv);
|
||||
int widget_set_func(client *c, int argc, char **argv);
|
||||
int menu_add_func(client *c, int argc, char **argv);
|
||||
int menu_del_func(client *c, int argc, char **argv);
|
||||
int menu_set_func(client *c, int argc, char **argv);
|
||||
int menu_item_add_func(client *c, int argc, char **argv);
|
||||
int menu_item_del_func(client *c, int argc, char **argv);
|
||||
int menu_item_set_func(client *c, int argc, char **argv);
|
||||
int backlight_func(client *c, int argc, char **argv);
|
||||
int output_func(client *c, int argc, char **argv);
|
||||
|
||||
extern client_function commands[];
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef CLIENT_MENU_H
|
||||
#define CLIENT_MENU_H
|
||||
|
||||
/*
|
||||
hee-hee.. this isn't implemented yet.
|
||||
|
||||
Eventually, it'll handle client-supplied menus, and send back info about
|
||||
what the user does.
|
||||
*/
|
||||
|
||||
typedef struct client_menu
|
||||
{
|
||||
char id[];
|
||||
LL * items;
|
||||
} client_menu;
|
||||
|
||||
typedef struct client_menu_item
|
||||
{
|
||||
char id[];
|
||||
int type; // Title, function, submenu, slider, checkbox, etc...
|
||||
int value; // Holds stuff like "true", 43, etc...
|
||||
char text[]; // Text to display here...
|
||||
char child[]; // For the "submenu" type
|
||||
} client_menu;
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
|
||||
clients.c
|
||||
|
||||
Inits/shuts down client system,
|
||||
creates/destroys individual clients,
|
||||
enqueues/dequeues messages from clients,
|
||||
and searches for clients in the list.
|
||||
|
||||
:)
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "clients.h"
|
||||
#include "client_data.h"
|
||||
#include "../shared/debug.h"
|
||||
|
||||
|
||||
|
||||
LL * clients;
|
||||
|
||||
// Initialize and kill client list...
|
||||
int client_init()
|
||||
{
|
||||
debug("client_init()\n");
|
||||
|
||||
clients = LL_new();
|
||||
if(!clients)
|
||||
{
|
||||
fprintf(stderr, "client_init: Unable to create client list\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int client_shutdown()
|
||||
{
|
||||
// TODO: Close all connections first...
|
||||
client *c;
|
||||
|
||||
debug("client_shutdown()\n");
|
||||
|
||||
|
||||
// Free all client structures...
|
||||
// Note that the regular list loop doesn't work here, because
|
||||
// client_destroy() calls LL_Remove()
|
||||
for(c = LL_Pop(clients);
|
||||
c;
|
||||
c = LL_Pop(clients))
|
||||
{
|
||||
debug("client_shutdown: ...\n");
|
||||
if(c)
|
||||
{
|
||||
debug("client_shutdown: ... %i ...\n", c->sock);
|
||||
if(0 != client_destroy(c))
|
||||
{
|
||||
fprintf(stderr, "client_shutdown: Error freeing client\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("client_shutdown: Freed client...\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("client_shutdown: No client!\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Then, free the list...
|
||||
LL_Destroy(clients);
|
||||
|
||||
debug("client_shutdown: done\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Create and destroy clients....
|
||||
client * client_create(int sock)
|
||||
{
|
||||
client *c;
|
||||
|
||||
debug("client_create(%i)\n", sock);
|
||||
|
||||
// Allocate new client...
|
||||
c = malloc(sizeof(client));
|
||||
if(!c)
|
||||
{
|
||||
fprintf(stderr, "client_create: error allocating new client\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Init struct members
|
||||
c->sock = 0;
|
||||
c->data = NULL;
|
||||
c->messages = NULL;
|
||||
|
||||
|
||||
c->sock = sock;
|
||||
|
||||
// Set up message list...
|
||||
c->messages = LL_new();
|
||||
if(!c->messages)
|
||||
{
|
||||
fprintf(stderr, "client_create: error allocating message list\n");
|
||||
free(c);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO: allocate and init client data...
|
||||
c->data = malloc(sizeof(client_data));
|
||||
if(!c->data)
|
||||
{
|
||||
fprintf(stderr, "client_create: error allocating client data\n");
|
||||
free(c->messages);
|
||||
free(c);
|
||||
return NULL;
|
||||
}
|
||||
else if(client_data_init(c->data) < 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO: Check for errors while adding the client to the list?
|
||||
LL_Push(clients, (void *)c);
|
||||
|
||||
return c;
|
||||
}
|
||||
int client_destroy(client *c)
|
||||
{
|
||||
// TODO: Close the socket connection here?
|
||||
int err;
|
||||
|
||||
char *str;
|
||||
|
||||
debug("client_destroy()\n");
|
||||
|
||||
if(!c) return -1;
|
||||
|
||||
// Eat the rest of the incoming requests...
|
||||
debug("client_destroy: get_messages\n");
|
||||
while((str = client_get_message(c)))
|
||||
{
|
||||
if(str) {
|
||||
debug("client_destroy: kill message %s\n", str);
|
||||
free(str);
|
||||
}
|
||||
}
|
||||
|
||||
err = LL_Destroy(c->messages);
|
||||
|
||||
// Free client's other data
|
||||
client_data_destroy(c->data);
|
||||
|
||||
/*
|
||||
// FIXME? Should the connection get closed here or elsewhere?
|
||||
if(c->sock) close(c->sock);
|
||||
c->sock = 0;
|
||||
*/
|
||||
|
||||
// Remove the client from the clients list...
|
||||
LL_Remove(clients, c);
|
||||
|
||||
free(c);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Add and remove messages from the client's queue...
|
||||
int client_add_message(client *c, char *message)
|
||||
{
|
||||
int err = 0;
|
||||
char *dup;
|
||||
char *str, *cp;
|
||||
char delimiters[] = "\n\r\0";
|
||||
// int len;
|
||||
|
||||
//debug("client_add_message(%s)\n", message);
|
||||
|
||||
if(!c) return -1;
|
||||
if(!message) return -1;
|
||||
|
||||
// len = strlen(message);
|
||||
// if(len < 1) return 0;
|
||||
|
||||
// Copy the string to avoid overwriting the original...
|
||||
dup = strdup(message);
|
||||
if(!dup)
|
||||
{
|
||||
fprintf(stderr, "client_add_message: Error allocating new string\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Now split the string into lines and enqueue each one...
|
||||
for(str = strtok(dup, delimiters); str; str=strtok(NULL, delimiters))
|
||||
{
|
||||
cp = strdup(str);
|
||||
debug("client_add_message: %s\n", cp);
|
||||
err += LL_Enqueue(c->messages, (void *)cp);
|
||||
}
|
||||
|
||||
//debug("client_add_message(%s): %i errors\n", message, err);
|
||||
free(dup); // Fixed memory leak...
|
||||
|
||||
// Err is the number of errors encountered...
|
||||
return err;
|
||||
|
||||
}
|
||||
// Woo-hoo! A simple function. :)
|
||||
char * client_get_message(client *c)
|
||||
{
|
||||
char *str;
|
||||
|
||||
//debug("client_get_message()\n");
|
||||
|
||||
if(!c) return NULL;
|
||||
|
||||
str = (char *)LL_Dequeue(c->messages);
|
||||
|
||||
//debug("client_get_message: \"%s\"\n", str);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
// Get and set the client's data...
|
||||
int client_set(client *c, void *data)
|
||||
{
|
||||
// You know, I really doubt this function will be useful...
|
||||
return 0;
|
||||
}
|
||||
void * client_get(client *c)
|
||||
{
|
||||
// But this one might be handy...
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
client * client_find_sock(int sock)
|
||||
{
|
||||
client * c;
|
||||
|
||||
// debug("client_find_sock(%i)\n", sock);
|
||||
|
||||
LL_Rewind(clients);
|
||||
do{
|
||||
c = (client *)LL_Get(clients);
|
||||
// debug("client_find_sock: ... %i ...\n", c->sock);
|
||||
if(c->sock == sock)
|
||||
{
|
||||
// debug("client_find_sock: ..! %i !..\n", c->sock);
|
||||
return c;
|
||||
}
|
||||
} while(LL_Next(clients) == 0);
|
||||
|
||||
debug("client_find_sock: failed\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#ifndef CLIENTS_H
|
||||
#define CLIENTS_H
|
||||
|
||||
#include "client_data.h"
|
||||
#include "../shared/LL.h"
|
||||
|
||||
typedef struct client
|
||||
{
|
||||
int sock;
|
||||
LL *messages;
|
||||
client_data *data;
|
||||
|
||||
} client;
|
||||
|
||||
extern LL *clients;
|
||||
|
||||
|
||||
// Initialize and kill client list...
|
||||
int client_init();
|
||||
int client_shutdown();
|
||||
|
||||
|
||||
// Create and destroy clients....
|
||||
client * client_create(int sock);
|
||||
int client_destroy(client *c);
|
||||
|
||||
// Add and remove messages from the client's queue...
|
||||
int client_add_message(client *c, char *message);
|
||||
char * client_get_message(client *c);
|
||||
|
||||
// Get and set the client's data...
|
||||
// Not used at all yet, and may never be. Oh, well.
|
||||
int client_set(client *c, void *data);
|
||||
void * client_get(client *c);
|
||||
|
||||
// Search for a client with a particular filedescriptor...
|
||||
client * client_find_sock(int sock);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,718 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "lcd.h"
|
||||
#include "CFontz.h"
|
||||
#include "drv_base.h"
|
||||
|
||||
#include "../render.h"
|
||||
|
||||
#include "../../shared/debug.h"
|
||||
#include "../../shared/str.h"
|
||||
|
||||
static int custom=0;
|
||||
typedef enum {
|
||||
hbar = 1,
|
||||
vbar = 2,
|
||||
bign = 4,
|
||||
beat = 8 } custom_type;
|
||||
|
||||
|
||||
|
||||
static int fd;
|
||||
|
||||
static void CFontz_linewrap(int on);
|
||||
static void CFontz_autoscroll(int on);
|
||||
static void CFontz_hidecursor();
|
||||
static void CFontz_reboot();
|
||||
|
||||
// TODO: Get rid of this variable?
|
||||
lcd_logical_driver *CFontz;
|
||||
// TODO: Get the frame buffers working right
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Opens com port and sets baud correctly...
|
||||
//
|
||||
int CFontz_init(lcd_logical_driver *driver, char *args)
|
||||
{
|
||||
char *argv[64];
|
||||
int argc;
|
||||
struct termios portset;
|
||||
int i;
|
||||
int tmp;
|
||||
int reboot=0;
|
||||
|
||||
int contrast=140;
|
||||
char device[256] = "/dev/lcd";
|
||||
int speed=B9600;
|
||||
|
||||
CFontz = driver;
|
||||
|
||||
//debug("CFontz_init: Args(all): %s\n", args);
|
||||
|
||||
argc = get_args(argv, args, 64);
|
||||
|
||||
/*
|
||||
for(i=0; i<argc; i++)
|
||||
{
|
||||
printf("Arg(%i): %s\n", i, argv[i]);
|
||||
}
|
||||
*/
|
||||
|
||||
for(i=0; i<argc; i++)
|
||||
{
|
||||
//printf("Arg(%i): %s\n", i, argv[i]);
|
||||
if(0 == strcmp(argv[i], "-d") ||
|
||||
0 == strcmp(argv[i], "--device"))
|
||||
{
|
||||
if(i + 1 > argc) {
|
||||
fprintf(stderr, "CFontz_init: %s requires an argument\n",
|
||||
argv[i]);
|
||||
return -1;
|
||||
}
|
||||
strcpy(device, argv[++i]);
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-c") ||
|
||||
0 == strcmp(argv[i], "--contrast"))
|
||||
{
|
||||
if(i + 1 > argc) {
|
||||
fprintf(stderr, "CFontz_init: %s requires an argument\n",
|
||||
argv[i]);
|
||||
return -1;
|
||||
}
|
||||
tmp = atoi(argv[++i]);
|
||||
if((tmp < 0) || (tmp > 255)){
|
||||
fprintf(stderr, "CFontz_init: %s argument must between 0 and 255. Using default value.\n",
|
||||
argv[i]);
|
||||
} else contrast = tmp;
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-b") ||
|
||||
0 == strcmp(argv[i], "--brightness"))
|
||||
{
|
||||
if(i + 1 > argc) {
|
||||
fprintf(stderr, "CFontz_init: %s requires an argument\n",
|
||||
argv[i]);
|
||||
return -1;
|
||||
}
|
||||
tmp = atoi(argv[++i]);
|
||||
if((tmp < 0) || (tmp > 255)){
|
||||
fprintf(stderr, "CFontz_init: %s argument must between 0 and 255. Using default value.\n",
|
||||
argv[i]);
|
||||
} else backlight_brightness = tmp;
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-o") ||
|
||||
0 == strcmp(argv[i], "--off-bright"))
|
||||
{
|
||||
if(i + 1 > argc) {
|
||||
fprintf(stderr, "CFontz_init: %s requires an argument\n",
|
||||
argv[i]);
|
||||
return -1;
|
||||
}
|
||||
tmp = atoi(argv[++i]);
|
||||
if((tmp < 0) || (tmp > 255)){
|
||||
fprintf(stderr, "CFontz_init: %s argument must between 0 and 255. Using default value.\n",
|
||||
argv[i]);
|
||||
} else backlight_off_brightness = tmp;
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-s") ||
|
||||
0 == strcmp(argv[i], "--speed"))
|
||||
{
|
||||
if(i + 1 > argc) {
|
||||
fprintf(stderr, "CFontz_init: %s requires an argument\n",
|
||||
argv[i]);
|
||||
return -1;
|
||||
}
|
||||
tmp = atoi(argv[++i]);
|
||||
if(tmp==1200) speed=B1200;
|
||||
else if(tmp==2400) speed=B2400;
|
||||
else if(tmp==9600) speed=B9600;
|
||||
else if(tmp==19200) speed=B19200;
|
||||
else {
|
||||
fprintf(stderr, "CFontz_init: %s argument must be 1200, 2400, or 9600. Using default value.\n",
|
||||
argv[i]);
|
||||
}
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-h") ||
|
||||
0 == strcmp(argv[i], "--help"))
|
||||
{
|
||||
printf("LCDproc CrystalFontz LCD driver\n"
|
||||
"\t-d\t--device\tSelect the output device to use [/dev/lcd]\n"
|
||||
"\t-t\t--type\t\tSelect the LCD type (size) [20x4]\n"
|
||||
"\t-c\t--contrast\tSet the initial contrast [140]\n"
|
||||
"\t-b\t--brightness\tSet the initial brightness [255]\n"
|
||||
"\t-o\t--off-bright\tSet the initial brightness [0]\n"
|
||||
"\t-s\t--speed\t\tSet the communication speed [9600]\n"
|
||||
"\t-r\t--reboot\tReinitialize the LCD's BIOS\n"
|
||||
"\t-h\t--help\t\tShow this help information\n");
|
||||
return -1;
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-r") ||
|
||||
0 == strcmp(argv[i], "--reboot"))
|
||||
{
|
||||
printf("LCDd: rebooting CrystalFontz LCD...\n");
|
||||
reboot=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Invalid parameter: %s\n", argv[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Set up io port correctly, and open it...
|
||||
fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
if (fd == -1)
|
||||
{
|
||||
fprintf(stderr, "CFontz_init: failed (%s)\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
//else fprintf(stderr, "CFontz_init: opened device %s\n", device);
|
||||
tcgetattr(fd, &portset);
|
||||
// This is necessary in Linux, but does not exist in irix.
|
||||
#ifndef IRIX
|
||||
cfmakeraw(&portset);
|
||||
#endif
|
||||
cfsetospeed(&portset, speed);
|
||||
cfsetispeed(&portset, speed);
|
||||
tcsetattr(fd, TCSANOW, &portset);
|
||||
|
||||
|
||||
// Set display-specific stuff..
|
||||
if(reboot)
|
||||
{
|
||||
CFontz_reboot();
|
||||
sleep(4);
|
||||
reboot=0;
|
||||
}
|
||||
sleep(1);
|
||||
CFontz_hidecursor();
|
||||
CFontz_linewrap(1);
|
||||
CFontz_autoscroll(0);
|
||||
CFontz_backlight(backlight_brightness);
|
||||
|
||||
|
||||
if(!driver->framebuf)
|
||||
{
|
||||
fprintf(stderr, "CFontz_init: No frame buffer.\n");
|
||||
driver->close();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// Set the functions the driver supports...
|
||||
|
||||
driver->clear = (void *)-1;
|
||||
driver->string = (void *)-1;
|
||||
// driver->chr = CFontz_chr;
|
||||
driver->chr = CFontz_chr;
|
||||
driver->vbar = CFontz_vbar;
|
||||
driver->init_vbar = CFontz_init_vbar;
|
||||
driver->hbar = CFontz_hbar;
|
||||
driver->init_hbar = CFontz_init_hbar;
|
||||
driver->num = CFontz_num;
|
||||
driver->init_num = CFontz_init_num;
|
||||
|
||||
driver->init = CFontz_init;
|
||||
driver->close = CFontz_close;
|
||||
driver->flush = CFontz_flush;
|
||||
driver->flush_box = CFontz_flush_box;
|
||||
driver->contrast = CFontz_contrast;
|
||||
driver->backlight = CFontz_backlight;
|
||||
driver->set_char = CFontz_set_char;
|
||||
driver->icon = CFontz_icon;
|
||||
driver->draw_frame = CFontz_draw_frame;
|
||||
|
||||
CFontz_contrast(contrast);
|
||||
|
||||
lcd.cellwid = 6;
|
||||
lcd.cellhgt = 8;
|
||||
|
||||
debug("CFontz: foo!\n");
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Clean-up
|
||||
//
|
||||
void CFontz_close()
|
||||
{
|
||||
close (fd);
|
||||
|
||||
if(CFontz->framebuf) free(CFontz->framebuf);
|
||||
|
||||
CFontz->framebuf = NULL;
|
||||
}
|
||||
|
||||
|
||||
void CFontz_flush()
|
||||
{
|
||||
CFontz_draw_frame(lcd.framebuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CFontz_flush_box(int lft, int top, int rgt, int bot)
|
||||
{
|
||||
int y;
|
||||
char out[LCD_MAX_WIDTH];
|
||||
|
||||
|
||||
// printf("Flush (%i,%i)-(%i,%i)\n", lft, top, rgt, bot);
|
||||
|
||||
for(y=top; y<=bot; y++)
|
||||
{
|
||||
sprintf(out, "%c%c%c", 17, lft, y);
|
||||
write(fd, out, 4);
|
||||
write(fd, lcd.framebuf+(y*lcd.wid)+lft, rgt-lft+1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Prints a character on the lcd display, at position (x,y). The
|
||||
// upper-left is (1,1), and the lower right should be (20,4).
|
||||
//
|
||||
void CFontz_chr(int x, int y, char c)
|
||||
{
|
||||
y--;
|
||||
x--;
|
||||
|
||||
if(c < 32 && c >= 0) c += 128;
|
||||
lcd.framebuf[(y*lcd.wid) + x] = c;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Changes screen contrast (0-255; 140 seems good)
|
||||
//
|
||||
int CFontz_contrast(int contrast)
|
||||
{
|
||||
int realcontrast;
|
||||
char out[4];
|
||||
static int status=140;
|
||||
|
||||
if(contrast > 0)
|
||||
{
|
||||
status=contrast;
|
||||
realcontrast = (((int)(status)) * 100) / 255;
|
||||
sprintf(out, "%c%c", 15, realcontrast);
|
||||
write(fd, out, 3);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Sets the backlight on or off -- can be done quickly for
|
||||
// an intermediate brightness...
|
||||
//
|
||||
void CFontz_backlight(int on)
|
||||
{
|
||||
char out[4];
|
||||
if(on)
|
||||
{
|
||||
sprintf(out, "%c%c", 14, (unsigned char)(on * 100 / 255));
|
||||
//sprintf(out, "%c%c", 14, 100);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(out, "%c%c", 14, 0);
|
||||
}
|
||||
write(fd, out, 3);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Toggle the built-in linewrapping feature
|
||||
//
|
||||
static void CFontz_linewrap(int on)
|
||||
{
|
||||
char out[4];
|
||||
if(on)
|
||||
sprintf(out, "%c", 23);
|
||||
else
|
||||
sprintf(out, "%c", 24);
|
||||
write(fd, out, 1);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Toggle the built-in automatic scrolling feature
|
||||
//
|
||||
static void CFontz_autoscroll(int on)
|
||||
{
|
||||
char out[4];
|
||||
if(on)
|
||||
sprintf(out, "%c", 19);
|
||||
else
|
||||
sprintf(out, "%c", 20);
|
||||
write(fd, out, 1);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Get rid of the blinking curson
|
||||
//
|
||||
static void CFontz_hidecursor()
|
||||
{
|
||||
char out[4];
|
||||
sprintf(out, "%c", 4);
|
||||
write(fd, out, 1);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Reset the display bios
|
||||
//
|
||||
static void CFontz_reboot()
|
||||
{
|
||||
char out[4];
|
||||
sprintf(out, "%c", 26);
|
||||
write(fd, out, 1);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Sets up for vertical bars. Call before lcd.vbar()
|
||||
//
|
||||
void CFontz_init_vbar()
|
||||
{
|
||||
char a[] = {
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,1,1,1,1,1,
|
||||
};
|
||||
char b[] = {
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,1,1,1,1,1,
|
||||
0,1,1,1,1,1,
|
||||
};
|
||||
char c[] = {
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,1,1,1,1,1,
|
||||
0,1,1,1,1,1,
|
||||
0,1,1,1,1,1,
|
||||
};
|
||||
char d[] = {
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,1,1,1,1,1,
|
||||
0,1,1,1,1,1,
|
||||
0,1,1,1,1,1,
|
||||
0,1,1,1,1,1,
|
||||
};
|
||||
char e[] = {
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,1,1,1,1,1,
|
||||
0,1,1,1,1,1,
|
||||
0,1,1,1,1,1,
|
||||
0,1,1,1,1,1,
|
||||
0,1,1,1,1,1,
|
||||
};
|
||||
char f[] = {
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,1,1,1,1,1,
|
||||
0,1,1,1,1,1,
|
||||
0,1,1,1,1,1,
|
||||
0,1,1,1,1,1,
|
||||
0,1,1,1,1,1,
|
||||
0,1,1,1,1,1,
|
||||
};
|
||||
char g[] = {
|
||||
0,0,0,0,0,0,
|
||||
0,1,1,1,1,1,
|
||||
0,1,1,1,1,1,
|
||||
0,1,1,1,1,1,
|
||||
0,1,1,1,1,1,
|
||||
0,1,1,1,1,1,
|
||||
0,1,1,1,1,1,
|
||||
0,1,1,1,1,1,
|
||||
};
|
||||
|
||||
if(custom!=vbar) {
|
||||
CFontz_set_char(1,a);
|
||||
CFontz_set_char(2,b);
|
||||
CFontz_set_char(3,c);
|
||||
CFontz_set_char(4,d);
|
||||
CFontz_set_char(5,e);
|
||||
CFontz_set_char(6,f);
|
||||
CFontz_set_char(7,g);
|
||||
custom=vbar;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Inits horizontal bars...
|
||||
//
|
||||
void CFontz_init_hbar()
|
||||
{
|
||||
|
||||
char a[] = {
|
||||
1,0,0,0,0,0,
|
||||
1,0,0,0,0,0,
|
||||
1,0,0,0,0,0,
|
||||
1,0,0,0,0,0,
|
||||
1,0,0,0,0,0,
|
||||
1,0,0,0,0,0,
|
||||
1,0,0,0,0,0,
|
||||
1,0,0,0,0,0,
|
||||
};
|
||||
char b[] = {
|
||||
1,1,0,0,0,0,
|
||||
1,1,0,0,0,0,
|
||||
1,1,0,0,0,0,
|
||||
1,1,0,0,0,0,
|
||||
1,1,0,0,0,0,
|
||||
1,1,0,0,0,0,
|
||||
1,1,0,0,0,0,
|
||||
1,1,0,0,0,0,
|
||||
};
|
||||
char c[] = {
|
||||
1,1,1,0,0,0,
|
||||
1,1,1,0,0,0,
|
||||
1,1,1,0,0,0,
|
||||
1,1,1,0,0,0,
|
||||
1,1,1,0,0,0,
|
||||
1,1,1,0,0,0,
|
||||
1,1,1,0,0,0,
|
||||
1,1,1,0,0,0,
|
||||
};
|
||||
char d[] = {
|
||||
1,1,1,1,0,0,
|
||||
1,1,1,1,0,0,
|
||||
1,1,1,1,0,0,
|
||||
1,1,1,1,0,0,
|
||||
1,1,1,1,0,0,
|
||||
1,1,1,1,0,0,
|
||||
1,1,1,1,0,0,
|
||||
1,1,1,1,0,0,
|
||||
};
|
||||
char e[] = {
|
||||
1,1,1,1,1,0,
|
||||
1,1,1,1,1,0,
|
||||
1,1,1,1,1,0,
|
||||
1,1,1,1,1,0,
|
||||
1,1,1,1,1,0,
|
||||
1,1,1,1,1,0,
|
||||
1,1,1,1,1,0,
|
||||
1,1,1,1,1,0,
|
||||
};
|
||||
char f[] = {
|
||||
1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,
|
||||
};
|
||||
|
||||
if(custom!=hbar) {
|
||||
CFontz_set_char(1,a);
|
||||
CFontz_set_char(2,b);
|
||||
CFontz_set_char(3,c);
|
||||
CFontz_set_char(4,d);
|
||||
CFontz_set_char(5,e);
|
||||
CFontz_set_char(6,f);
|
||||
custom=hbar;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Draws a vertical bar...
|
||||
//
|
||||
void CFontz_vbar(int x, int len)
|
||||
{
|
||||
char map[9] = {32, 1, 2, 3, 4, 5, 6, 7, 255 };
|
||||
|
||||
|
||||
int y;
|
||||
for(y=lcd.hgt; y > 0 && len>0; y--)
|
||||
{
|
||||
if(len >= lcd.cellhgt) CFontz_chr(x, y, 255);
|
||||
else CFontz_chr(x, y, map[len]);
|
||||
|
||||
len -= lcd.cellhgt;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Draws a horizontal bar to the right.
|
||||
//
|
||||
void CFontz_hbar(int x, int y, int len)
|
||||
{
|
||||
char map[7] = { 32, 1, 2, 3, 4, 5, 6 };
|
||||
|
||||
for(; x<=lcd.wid && len>0; x++)
|
||||
{
|
||||
if(len >= lcd.cellwid) CFontz_chr(x,y,map[6]);
|
||||
else CFontz_chr(x, y, map[len]);
|
||||
|
||||
len -= lcd.cellwid;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Sets up for big numbers.
|
||||
//
|
||||
void CFontz_init_num()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Writes a big number.
|
||||
//
|
||||
void CFontz_num(int x, int num)
|
||||
{
|
||||
char out[5];
|
||||
sprintf(out, "%c%c%c", 28, x, num);
|
||||
write(fd, out, 3);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Sets a custom character from 0-7...
|
||||
//
|
||||
// For input, values > 0 mean "on" and values <= 0 are "off".
|
||||
//
|
||||
// The input is just an array of characters...
|
||||
//
|
||||
void CFontz_set_char(int n, char *dat)
|
||||
{
|
||||
char out[4];
|
||||
int row, col;
|
||||
int letter;
|
||||
|
||||
if(n < 0 || n > 7) return;
|
||||
if(!dat) return;
|
||||
|
||||
sprintf(out, "%c%c", 25, n);
|
||||
write(fd, out, 2);
|
||||
|
||||
|
||||
for(row=0; row<lcd.cellhgt; row++)
|
||||
{
|
||||
letter = 0;
|
||||
for(col=0; col<lcd.cellwid; col++)
|
||||
{
|
||||
letter <<= 1;
|
||||
letter |= (dat[(row*lcd.cellwid) + col] > 0);
|
||||
}
|
||||
write(fd, &letter, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CFontz_icon(int which, char dest)
|
||||
{
|
||||
char icons[3][6*8] = {
|
||||
{
|
||||
1,1,1,1,1,1, // Empty Heart
|
||||
1,0,1,0,1,1,
|
||||
0,0,0,0,0,1,
|
||||
0,0,0,0,0,1,
|
||||
0,0,0,0,0,1,
|
||||
1,0,0,0,1,1,
|
||||
1,1,0,1,1,1,
|
||||
1,1,1,1,1,1,
|
||||
},
|
||||
|
||||
{
|
||||
1,1,1,1,1,1, // Filled Heart
|
||||
1,0,1,0,1,1,
|
||||
0,1,0,1,0,1,
|
||||
0,1,1,1,0,1,
|
||||
0,1,1,1,0,1,
|
||||
1,0,1,0,1,1,
|
||||
1,1,0,1,1,1,
|
||||
1,1,1,1,1,1,
|
||||
},
|
||||
|
||||
{
|
||||
0,0,0,0,0,0, // Ellipsis
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,
|
||||
1,0,1,0,1,0,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
if(custom==bign) custom=beat;
|
||||
CFontz_set_char(dest, &icons[which][0]);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Blasts a single frame onscreen, to the lcd...
|
||||
//
|
||||
// Input is a character array, sized lcd.wid*lcd.hgt
|
||||
//
|
||||
void CFontz_draw_frame(char *dat)
|
||||
{
|
||||
char out[LCD_MAX_WIDTH * LCD_MAX_HEIGHT];
|
||||
int i;
|
||||
|
||||
if(!dat) return;
|
||||
|
||||
// Custom characters start at 128, not at 0.
|
||||
/*
|
||||
for(i=0; i<lcd.wid*lcd.hgt; i++)
|
||||
{
|
||||
if(dat[i] < 32 && dat[i] >= 0) dat[i] += 128;
|
||||
}
|
||||
*/
|
||||
|
||||
for(i=0; i<lcd.hgt; i++)
|
||||
{
|
||||
sprintf(out, "%c%c%c", 17, 0, i);
|
||||
write(fd, out, 3);
|
||||
write(fd, dat+(lcd.wid*i), lcd.wid);
|
||||
}
|
||||
/*
|
||||
sprintf(out, "%c", 1);
|
||||
write(fd, out, 1);
|
||||
write(fd, dat, lcd.wid*lcd.hgt);
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef CFONTZ_H
|
||||
#define CFONTZ_H
|
||||
|
||||
|
||||
extern lcd_logical_driver *CFontz;
|
||||
|
||||
int CFontz_init(lcd_logical_driver *driver, char *device);
|
||||
void CFontz_close();
|
||||
void CFontz_flush();
|
||||
void CFontz_flush_box(int lft, int top, int rgt, int bot);
|
||||
void CFontz_chr(int x, int y, char c) ;
|
||||
int CFontz_contrast(int contrast);
|
||||
void CFontz_backlight(int on);
|
||||
void CFontz_init_vbar();
|
||||
void CFontz_init_hbar();
|
||||
void CFontz_vbar(int x, int len);
|
||||
void CFontz_hbar(int x, int y, int len);
|
||||
void CFontz_init_num();
|
||||
void CFontz_num(int x, int num);
|
||||
void CFontz_set_char(int n, char *dat);
|
||||
void CFontz_icon(int which, char dest);
|
||||
void CFontz_draw_frame(char *dat);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,92 @@
|
||||
# example irmanrc file for libirman 0.4.1
|
||||
# should be either /usr/local/etc/irmanrc.conf or ~/.irmanrc
|
||||
|
||||
# set the default port name
|
||||
port /dev/ttyS0
|
||||
|
||||
bind jvc-play 7ddfd7fc0000
|
||||
bind jvc-pause 7dddd7fc0000
|
||||
bind jvc-stop 7ddd7ffc0000
|
||||
bind jvc-prev 7ddff5fc0000
|
||||
bind jvc-next 7dddf5fc0000
|
||||
bind jvc-fwd 7ddf5ffc0000
|
||||
bind jvc-rew 7ddd5ffc0000
|
||||
bind jvc-1 7ffdff7c0000
|
||||
bind jvc-2 7fff7f7c0000
|
||||
bind jvc-3 7ffd7f7c0000
|
||||
bind jvc-4 7fffdf7c0000
|
||||
bind jvc-5 7ffddf7c0000
|
||||
bind jvc-6 7fff5f7c0000
|
||||
bind jvc-7 7ffd5f7c0000
|
||||
bind jvc-8 7ffff77c0000
|
||||
bind jvc-9 7ffdf77c0000
|
||||
bind jvc-0 7fffff7c0000
|
||||
bind jvc-rec e51000000000
|
||||
bind jvc-vol+ b91000000000
|
||||
bind jvc-vol- ad1000000000
|
||||
bind jvc-mute f91000000000
|
||||
bind jvc-/|// f11000000000
|
||||
bind jvc-display 151000000000
|
||||
bind jvc-search<< 351000000000
|
||||
bind jvc-search>> 491000000000
|
||||
bind jvc-operate c91000000000
|
||||
|
||||
bind sony-md-power a9e000000000
|
||||
bind sony-md-eject 69e000000000
|
||||
bind -cancel 051000000000
|
||||
|
||||
alias workman-play jvc-play
|
||||
alias workman-pause jvc-pause
|
||||
alias workman-stop jvc-stop
|
||||
alias workman-prev jvc-prev
|
||||
alias workman-next jvc-next
|
||||
alias workman-rew jvc-rew
|
||||
alias workman-fwd jvc-fwd
|
||||
#alias workman-power jvc-power
|
||||
#alias workman-eject jvc-eject
|
||||
|
||||
alias ircd-play jvc-play
|
||||
alias ircd-pause jvc-pause
|
||||
alias ircd-stop jvc-stop
|
||||
alias ircd-prev jvc-rew
|
||||
alias ircd-next jvc-fwd
|
||||
#alias ircd-power jvc-power
|
||||
#alias ircd-eject jvc-eject
|
||||
|
||||
alias lcdproc-A jvc-1
|
||||
alias lcdproc-B jvc-2
|
||||
alias lcdproc-C jvc-3
|
||||
alias lcdproc-D jvc-4
|
||||
alias lcdproc-E jvc-5
|
||||
alias lcdproc-F jvc-6
|
||||
alias lcdproc-G jvc-7
|
||||
alias lcdproc-H jvc-8
|
||||
alias lcdproc-I jvc-9
|
||||
alias lcdproc-J jvc-0
|
||||
alias lcdproc-K jvc-play
|
||||
alias lcdproc-L jvc-pause
|
||||
alias lcdproc-M jvc-stop
|
||||
alias lcdproc-N jvc-prev
|
||||
alias lcdproc-O jvc-next
|
||||
alias lcdproc-P jvc-fwd
|
||||
alias lcdproc-Q jvc-rew
|
||||
alias lcdproc-R jvc-rec
|
||||
alias lcdproc-S jvc-vol+
|
||||
alias lcdproc-T jvc-vol-
|
||||
alias lcdproc-U jvc-mute
|
||||
alias lcdproc-V jvc-/|//
|
||||
alias lcdproc-W jvc-display
|
||||
alias lcdproc-X jvc-search<<
|
||||
alias lcdproc-Y jvc-search>>
|
||||
alias lcdproc-Z jvc-operate
|
||||
|
||||
|
||||
# just an idea for 0.5
|
||||
# assign workman sony-md
|
||||
# would be like: alias workman-* sony-md-*
|
||||
# this allows remote level control.
|
||||
# { "(remote level) control", not "remote (level control)"! }
|
||||
# also
|
||||
# set REMOTES /usr/local/share/libir/
|
||||
# include ${REMOTES}/sony-md
|
||||
# include ${REMOTES}/philips-rc5
|
||||
@@ -0,0 +1,45 @@
|
||||
########################################################################
|
||||
# You shouldn't need to touch anything below here.
|
||||
########################################################################
|
||||
include ../../Makefile.config
|
||||
|
||||
TARGET = libLCDdrivers.a
|
||||
OBJ += lcd.o drv_base.o $(DOBJ)
|
||||
SOURCES = Makefile lcd.c lcd.h \
|
||||
MtxOrb.c MtxOrb.h wirz-sli.c wirz-sli.h text.c text.h \
|
||||
curses_drv.c curses_drv.h drv_base.c drv_base.h \
|
||||
hd44780.c hd44780.h port.h joy.c joy.h irman.c irman.h \
|
||||
CFontz.c CFontz.h
|
||||
INCLUDE = -I../../shared
|
||||
|
||||
|
||||
###################################################################
|
||||
# Compilation...
|
||||
#
|
||||
all: $(TARGET)
|
||||
|
||||
|
||||
$(TARGET): $(OBJ) Makefile
|
||||
$(AR) rcs $(TARGET) $(OBJ)
|
||||
#$(TARGET): $(OBJ) Makefile
|
||||
# $(GCC) -s $(MISC) $(INCLUDE) -o $(TARGET) $(OBJ) $(LIB)
|
||||
|
||||
%.o: %.c %.h Makefile
|
||||
$(GCC) -c $(MISC) $(INCLUDE) $<
|
||||
|
||||
|
||||
##################################################################
|
||||
# Other stuff...
|
||||
#
|
||||
clean:
|
||||
rm -f $(OBJ) *.o $(DOBJ) $(TARGET) *~ core
|
||||
|
||||
edit:
|
||||
nedit $(SOURCES) $(EXTRAS) &
|
||||
|
||||
todo:
|
||||
@echo ---------------===========================================
|
||||
@grep TODO $(SOURCES) | grep -v SOURCES
|
||||
@grep FIXME $(SOURCES) | grep -v SOURCES
|
||||
@echo ---------------===========================================
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,31 @@
|
||||
#ifndef MTXORB_H
|
||||
#define MTXORB_H
|
||||
|
||||
|
||||
extern lcd_logical_driver *MtxOrb;
|
||||
|
||||
int MtxOrb_init(lcd_logical_driver *driver, char *device);
|
||||
void MtxOrb_clear();
|
||||
void MtxOrb_close();
|
||||
void MtxOrb_flush();
|
||||
void MtxOrb_flush_box(int lft, int top, int rgt, int bot);
|
||||
void MtxOrb_chr(int x, int y, char c) ;
|
||||
int MtxOrb_contrast(int contrast);
|
||||
void MtxOrb_backlight(int on);
|
||||
void MtxOrb_output(int on);
|
||||
void MtxOrb_init_vbar();
|
||||
void MtxOrb_init_hbar();
|
||||
void MtxOrb_vbar(int x, int len);
|
||||
void MtxOrb_hbar(int x, int y, int len);
|
||||
void MtxOrb_init_num();
|
||||
void MtxOrb_num(int x, int num);
|
||||
void MtxOrb_set_char(int n, char *dat);
|
||||
void MtxOrb_icon(int which, char dest);
|
||||
void MtxOrb_draw_frame(char *dat);
|
||||
char MtxOrb_getkey();
|
||||
|
||||
void MtxOrb_init_all(int type);
|
||||
int MtxOrb_ask_bar(int type);
|
||||
void MtxOrb_set_known_char(int car, int type);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,322 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/errno.h>
|
||||
#ifdef xBSD
|
||||
#include <ncurses.h>
|
||||
#else
|
||||
#include <curses.h>
|
||||
#endif
|
||||
|
||||
#include "../../shared/str.h"
|
||||
|
||||
#include "lcd.h"
|
||||
#include "curses_drv.h"
|
||||
#include "drv_base.h"
|
||||
|
||||
|
||||
lcd_logical_driver *curses_drv;
|
||||
|
||||
int PAD=255;
|
||||
int ELLIPSIS=7;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////////////////////// For Curses Terminal Output ////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static char icon_char = '@';
|
||||
|
||||
|
||||
int curses_drv_init(struct lcd_logical_driver *driver, char *args)
|
||||
{
|
||||
char *argv[64];
|
||||
int argc;
|
||||
int i,j;
|
||||
|
||||
|
||||
argc = get_args(argv, args, 64);
|
||||
|
||||
for(i=0; i<argc; i++)
|
||||
{
|
||||
if(0 == strcmp(argv[i], "-f") ||
|
||||
0 == strcmp(argv[i], "--forecolor"))
|
||||
{
|
||||
if(i + 1 > argc) {
|
||||
fprintf(stderr, "curses_init: %s requires an argument\n",
|
||||
argv[i]);
|
||||
return -1;
|
||||
}
|
||||
// TODO: color display in curses driver!
|
||||
printf("Sorry, colors not yet implemented...\n");
|
||||
//strcpy(device, argv[++i]);
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-b") ||
|
||||
0 == strcmp(argv[i], "--backcolor"))
|
||||
{
|
||||
if(i + 1 > argc) {
|
||||
fprintf(stderr, "curses_init: %s requires an argument\n",
|
||||
argv[i]);
|
||||
return -1;
|
||||
}
|
||||
// TODO: color display in curses driver!
|
||||
printf("Sorry, colors not yet implemented...\n");
|
||||
//strcpy(device, argv[++i]);
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-B") ||
|
||||
0 == strcmp(argv[i], "--backlight"))
|
||||
{
|
||||
if(i + 1 > argc) {
|
||||
fprintf(stderr, "curses_init: %s requires an argument\n",
|
||||
argv[i]);
|
||||
return -1;
|
||||
}
|
||||
// TODO: color display in curses driver!
|
||||
printf("Sorry, colors not yet implemented...\n");
|
||||
//strcpy(device, argv[++i]);
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-h") ||
|
||||
0 == strcmp(argv[i], "--help"))
|
||||
{
|
||||
printf("LCDproc [n]curses driver\n"
|
||||
"\t-f\t--forecolor\tChange the foreground color\n"
|
||||
"\t-b\t--backcolor\tChange the backlight's \"off\" color\n"
|
||||
"\t-B\t--backlight\tChange the backlight's \"on\" color\n"
|
||||
"\t-h\t--help\t\tShow this help information\n");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Invalid parameter: %s\n", argv[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
curses_drv = driver;
|
||||
|
||||
// Init curses...
|
||||
initscr();
|
||||
cbreak();
|
||||
noecho();
|
||||
nodelay(stdscr, TRUE);
|
||||
nonl();
|
||||
intrflush(stdscr, FALSE);
|
||||
keypad(stdscr, TRUE);
|
||||
|
||||
curses_drv_clear();
|
||||
|
||||
// Override output functions...
|
||||
driver->clear = curses_drv_clear;
|
||||
driver->string = curses_drv_string;
|
||||
driver->chr = curses_drv_chr;
|
||||
driver->vbar = curses_drv_vbar;
|
||||
driver->init_vbar = NULL;
|
||||
driver->hbar = curses_drv_hbar;
|
||||
driver->init_hbar = NULL;
|
||||
driver->num = curses_drv_num;
|
||||
driver->init_num = curses_drv_init_num;
|
||||
|
||||
driver->init = curses_drv_init;
|
||||
driver->close = curses_drv_close;
|
||||
driver->flush = curses_drv_flush;
|
||||
driver->flush_box = curses_drv_flush_box;
|
||||
driver->contrast = NULL;
|
||||
driver->backlight = NULL;
|
||||
driver->set_char = NULL;
|
||||
driver->icon = curses_drv_icon;
|
||||
driver->draw_frame = curses_drv_draw_frame;
|
||||
|
||||
driver->getkey = curses_drv_getkey;
|
||||
|
||||
// Change the character used for padding the title bars...
|
||||
PAD = '#';
|
||||
// Change the character used for "..."
|
||||
ELLIPSIS = '~';
|
||||
|
||||
return 200; // 200 is arbitrary. (must be 1 or more)
|
||||
}
|
||||
|
||||
void curses_drv_close()
|
||||
{
|
||||
// Close curses
|
||||
clear();
|
||||
move(0,0);
|
||||
refresh();
|
||||
endwin();
|
||||
|
||||
drv_base_close();
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Clears the LCD screen
|
||||
//
|
||||
void curses_drv_clear()
|
||||
{
|
||||
clear();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Prints a string on the lcd display, at position (x,y). The
|
||||
// upper-left is (1,1), and the lower right should be (20,4).
|
||||
//
|
||||
void curses_drv_string(int x, int y, char string[])
|
||||
{
|
||||
int i;
|
||||
unsigned char *c;
|
||||
|
||||
for(i=0; string[i]; i++)
|
||||
{
|
||||
c = &string[i];
|
||||
switch(*c)
|
||||
{
|
||||
case 0: *c = icon_char; break;
|
||||
case 255: *c = '#'; break;
|
||||
}
|
||||
}
|
||||
mvaddstr(y-1, x-1, string);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Prints a character on the lcd display, at position (x,y). The
|
||||
// upper-left is (1,1), and the lower right should be (20,4).
|
||||
//
|
||||
void curses_drv_chr(int x, int y, char c)
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case 0: c = icon_char; break;
|
||||
case -1: c = '#'; break;
|
||||
}
|
||||
|
||||
mvaddch(y-1, x-1, c);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Sets up for big numbers.
|
||||
//
|
||||
void curses_drv_init_num()
|
||||
{
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Writes a big number.
|
||||
//
|
||||
void curses_drv_num(int x, int num)
|
||||
{
|
||||
char c;
|
||||
int y, dx;
|
||||
|
||||
c='0'+num;
|
||||
// printf(&c,"%1d",num);
|
||||
|
||||
for(y=1; y<5; y++)
|
||||
for(dx=0; dx<3; dx++)
|
||||
curses_drv_chr(x+dx, y, c);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Draws a vertical bar; erases entire column onscreen.
|
||||
//
|
||||
void curses_drv_vbar(int x, int len)
|
||||
{
|
||||
char map[]="_.,,ooO8";
|
||||
|
||||
int y;
|
||||
for(y=lcd.hgt; y > 0 && len>0; y--)
|
||||
{
|
||||
if(len >= lcd.cellhgt) curses_drv_chr(x, y, '8');
|
||||
else curses_drv_chr(x, y, map[len-1]);
|
||||
|
||||
len -= lcd.cellhgt;
|
||||
}
|
||||
|
||||
// move(4-len/lcd.cellhgt, x-1);
|
||||
// vline(0, len/lcd.cellhgt);
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Draws a horizontal bar to the right.
|
||||
//
|
||||
void curses_drv_hbar(int x, int y, int len)
|
||||
{
|
||||
for(; x<=lcd.wid && len>0; x++)
|
||||
{
|
||||
if(len>=lcd.cellwid)
|
||||
curses_drv_chr(x, y, '=');
|
||||
else
|
||||
curses_drv_chr(x, y, '-');
|
||||
|
||||
len -= lcd.cellwid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// move(y-1, x-1);
|
||||
// hline(0, len/lcd.cellwid);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Sets character 0 to an icon...
|
||||
//
|
||||
void curses_drv_icon(int which, char dest)
|
||||
{
|
||||
if(dest == 0)
|
||||
switch(which)
|
||||
{
|
||||
case 0: icon_char = '+'; break;
|
||||
case 1: icon_char = '*'; break;
|
||||
default: icon_char = '#'; break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Flushes all output to the lcd...
|
||||
//
|
||||
void curses_drv_flush()
|
||||
{
|
||||
curses_drv_draw_frame(curses_drv->framebuf);
|
||||
}
|
||||
|
||||
|
||||
void curses_drv_flush_box(int lft, int top, int rgt, int bot)
|
||||
{
|
||||
curses_drv_flush();
|
||||
}
|
||||
|
||||
|
||||
void curses_drv_draw_frame(char *dat)
|
||||
{
|
||||
// border(0, 0, 0, 0, 0, 0, lcd.wid+1, lcd.hgt+1);
|
||||
|
||||
refresh();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
char curses_drv_getkey()
|
||||
{
|
||||
int i;
|
||||
|
||||
i = getch();
|
||||
|
||||
if(i == KEY_LEFT) return 'D';
|
||||
if(i == KEY_UP) return 'B';
|
||||
if(i == KEY_DOWN) return 'C';
|
||||
if(i == KEY_RIGHT) return 'A';
|
||||
|
||||
if(i != ERR) return i;
|
||||
else return 0;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef LCD_CURSES_H
|
||||
#define LCD_CURSES_H
|
||||
|
||||
|
||||
extern lcd_logical_driver *curses_drv;
|
||||
|
||||
int curses_drv_init(struct lcd_logical_driver *driver, char *args);
|
||||
void curses_drv_close();
|
||||
void curses_drv_clear();
|
||||
void curses_drv_flush();
|
||||
void curses_drv_string(int x, int y, char string[]);
|
||||
void curses_drv_chr(int x, int y, char c);
|
||||
void curses_drv_vbar(int x, int len);
|
||||
void curses_drv_hbar(int x, int y, int len);
|
||||
void curses_drv_icon(int which, char dest);
|
||||
void curses_drv_flush();
|
||||
void curses_drv_flush_box(int lft, int top, int rgt, int bot);
|
||||
void curses_drv_draw_frame(char *dat);
|
||||
char curses_drv_getkey();
|
||||
void curses_drv_init_num();
|
||||
void curses_drv_num(int x, int num);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,288 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
#include "../lcd.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////////////////////// For Debugging Output //////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// TODO: somehow allow access to the driver->framebuffer to each
|
||||
// function...
|
||||
|
||||
|
||||
int debug_init(struct lcd_logical_driver *driver, char *args)
|
||||
{
|
||||
printf("debug_init(%s)\n", device);
|
||||
|
||||
if(!driver->framebuf)
|
||||
{
|
||||
printf("Allocating frame buffer (%ix%i)\n", lcd.wid, lcd.hgt);
|
||||
driver->framebuf = malloc(lcd.wid * lcd.hgt);
|
||||
}
|
||||
|
||||
|
||||
if(!driver->framebuf)
|
||||
{
|
||||
debug_close();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(driver->framebuf) printf("Frame buffer: %i\n", (int)driver->framebuf);
|
||||
|
||||
debug_clear();
|
||||
|
||||
driver->clear = debug_clear;
|
||||
driver->string = debug_string;
|
||||
driver->chr = debug_chr;
|
||||
driver->vbar = debug_vbar;
|
||||
driver->hbar = debug_hbar;
|
||||
driver->init_num = debug_init_num;
|
||||
driver->num = debug_num;
|
||||
|
||||
driver->init = debug_init;
|
||||
driver->close = debug_close;
|
||||
driver->flush = debug_flush;
|
||||
driver->flush_box = debug_flush_box;
|
||||
driver->contrast = debug_contrast;
|
||||
driver->backlight = debug_backlight;
|
||||
driver->set_char = debug_set_char;
|
||||
driver->icon = debug_icon;
|
||||
driver->init_vbar = debug_init_vbar;
|
||||
driver->init_hbar = debug_init_hbar;
|
||||
driver->draw_frame = debug_draw_frame;
|
||||
|
||||
driver->getkey = debug_getkey;
|
||||
|
||||
|
||||
return 200; // 200 is arbitrary. (must be 1 or more)
|
||||
}
|
||||
|
||||
void debug_close()
|
||||
{
|
||||
// Ack! This shouldn't crash the program, but does.. Why??
|
||||
|
||||
|
||||
printf("debug_close()\n");
|
||||
|
||||
// This is the line which crashes.
|
||||
if(driver->framebuf) free(driver->framebuf);
|
||||
|
||||
if(driver->framebuf) printf("Frame buffer: %i\n", (int)driver->framebuf);
|
||||
driver->framebuf = NULL;
|
||||
// printf("debug_close() finished\n");
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Clears the LCD screen
|
||||
//
|
||||
void debug_clear()
|
||||
{
|
||||
printf("clear()\n");
|
||||
|
||||
memset(driver->framebuf, ' ', lcd.wid*lcd.hgt);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Flushes all output to the lcd...
|
||||
//
|
||||
void debug_flush()
|
||||
{
|
||||
printf("flush()\n");
|
||||
|
||||
lcd.draw_frame();
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Prints a string on the lcd display, at position (x,y). The
|
||||
// upper-left is (1,1), and the lower right should be (20,4).
|
||||
//
|
||||
void debug_string(int x, int y, char string[])
|
||||
{
|
||||
|
||||
int i;
|
||||
|
||||
printf("string(%i, %i):%s \n", x, y, string);
|
||||
|
||||
|
||||
x -= 1; // Convert 1-based coords to 0-based...
|
||||
y -= 1;
|
||||
|
||||
for(i=0; string[i]; i++)
|
||||
{
|
||||
driver->framebuf[(y*lcd.wid) + x + i] = string[i];
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Prints a character on the lcd display, at position (x,y). The
|
||||
// upper-left is (1,1), and the lower right should be (20,4).
|
||||
//
|
||||
void debug_chr(int x, int y, char c)
|
||||
{
|
||||
printf("character(%i, %i):%c\n", x, y, c);
|
||||
|
||||
|
||||
y--;
|
||||
x--;
|
||||
|
||||
lcd.framebuf[(y*lcd.wid) + x] = c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void debug_contrast(int contrast)
|
||||
{
|
||||
printf("Contrast: %i\n", contrast);
|
||||
}
|
||||
|
||||
void debug_backlight(int on)
|
||||
{
|
||||
if(on)
|
||||
{
|
||||
printf("Backlight ON\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Backlight OFF\n");
|
||||
}
|
||||
}
|
||||
|
||||
void debug_init_vbar()
|
||||
{
|
||||
printf("Vertical bars.\n");
|
||||
}
|
||||
|
||||
void debug_init_hbar()
|
||||
{
|
||||
printf("Horizontal bars.\n");
|
||||
}
|
||||
|
||||
void debug_init_num()
|
||||
{
|
||||
printf("Big Numbers.\n");
|
||||
}
|
||||
|
||||
void debug_num(int x, int num)
|
||||
{
|
||||
printf("BigNum(%i, %i)\n", x, num);
|
||||
}
|
||||
|
||||
void debug_set_char(int n, char *dat)
|
||||
{
|
||||
printf("Set Character %i\n", n);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Draws a vertical bar; erases entire column onscreen.
|
||||
//
|
||||
void debug_vbar(int x, int len)
|
||||
{
|
||||
int y;
|
||||
|
||||
printf("Vbar(%i, %i)\n", x, len);
|
||||
|
||||
|
||||
for(y=lcd.hgt; y > 0 && len>0; y--)
|
||||
{
|
||||
debug_chr(x, y, '|');
|
||||
|
||||
len -= lcd.cellhgt;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Draws a horizontal bar to the right.
|
||||
//
|
||||
void debug_hbar(int x, int y, int len)
|
||||
{
|
||||
printf("Hbar(%i, %i, %i)\n", x, y, len);
|
||||
|
||||
|
||||
for(; x<lcd.wid && len>0; x++)
|
||||
{
|
||||
debug_chr(x,y,'-');
|
||||
|
||||
len -= lcd.cellwid;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Sets character 0 to an icon...
|
||||
//
|
||||
void debug_icon(int which, char dest)
|
||||
{
|
||||
printf("Char %i is icon %i\n", dest, which);
|
||||
}
|
||||
|
||||
|
||||
void debug_flush_box(int lft, int top, int rgt, int bot)
|
||||
{
|
||||
printf("Flush Box(%i, %i)-(%i, %i)\n", lft, top, rgt, bot);
|
||||
|
||||
|
||||
debug_flush();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void debug_draw_frame(char *dat)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
char out[LCD_MAX_WIDTH];
|
||||
|
||||
printf("draw_frame()\n");
|
||||
|
||||
|
||||
if(!dat) return;
|
||||
|
||||
// printf("Frame (%ix%i): \n%s\n", lcd.wid, lcd.hgt, dat);
|
||||
|
||||
for(i=0; i<lcd.wid; i++)
|
||||
{
|
||||
out[i] = '-';
|
||||
}
|
||||
out[lcd.wid] = 0;
|
||||
printf("+%s+\n", out);
|
||||
|
||||
|
||||
for(i=0; i<lcd.hgt; i++)
|
||||
{
|
||||
for(j=0; j<lcd.wid; j++)
|
||||
{
|
||||
out[j] = dat[j+(i*lcd.wid)];
|
||||
}
|
||||
out[lcd.wid] = 0;
|
||||
printf("|%s|\n", out);
|
||||
|
||||
}
|
||||
|
||||
for(i=0; i<lcd.wid; i++)
|
||||
{
|
||||
out[i] = '-';
|
||||
}
|
||||
out[lcd.wid] = 0;
|
||||
printf("+%s+\n", out);
|
||||
|
||||
}
|
||||
|
||||
|
||||
char debug_getkey()
|
||||
{
|
||||
printf("Trying to grab keypress.\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef LCD_DEBUG_H
|
||||
#define LCD_DEBUG_H
|
||||
|
||||
|
||||
int debug_init(struct lcd_logical_driver *driver, char *args);
|
||||
void debug_close();
|
||||
void debug_clear();
|
||||
void debug_flush();
|
||||
void debug_string(int x, int y, char string[]);
|
||||
void debug_chr(int x, int y, char c);
|
||||
void debug_contrast(int contrast);
|
||||
void debug_backlight(int on);
|
||||
void debug_init_vbar();
|
||||
void debug_init_hbar();
|
||||
void debug_init_num();
|
||||
void debug_vbar(int x, int len);
|
||||
void debug_hbar(int x, int y, int len);
|
||||
void debug_num(int x, int num);
|
||||
void debug_set_char(int n, char *dat);
|
||||
void debug_icon(int which, char dest);
|
||||
void debug_flush_box(int lft, int top, int rgt, int bot);
|
||||
void debug_draw_frame(char *dat);
|
||||
char debug_getkey();
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,311 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
#include "lcd.h"
|
||||
#include "drv_base.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////////////////////// Base "class" to derive from ///////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
lcd_logical_driver *drv_base;
|
||||
|
||||
// TODO: Get lcd.framebuf to properly work as whatever driver is running...
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// init() should set up any device-specific stuff, and
|
||||
// point all the function pointers.
|
||||
int drv_base_init(struct lcd_logical_driver *driver, char *args)
|
||||
{
|
||||
// printf("drv_base_init()\n");
|
||||
|
||||
drv_base = driver;
|
||||
|
||||
driver->wid = 20;
|
||||
driver->hgt = 4;
|
||||
|
||||
// You must use driver->framebuf here, but may use lcd.framebuf later.
|
||||
if(!driver->framebuf)
|
||||
driver->framebuf = malloc(driver->wid * driver->hgt);
|
||||
|
||||
if(!driver->framebuf)
|
||||
{
|
||||
drv_base_close();
|
||||
return -1;
|
||||
}
|
||||
// Debugging...
|
||||
// if(lcd.framebuf) printf("Frame buffer: %i\n", (int)lcd.framebuf);
|
||||
|
||||
memset(driver->framebuf, ' ', driver->wid*driver->hgt);
|
||||
// drv_base_clear();
|
||||
|
||||
driver->cellwid = 5;
|
||||
driver->cellhgt = 8;
|
||||
|
||||
driver->clear = drv_base_clear;
|
||||
driver->string = drv_base_string;
|
||||
driver->chr = drv_base_chr;
|
||||
driver->vbar = drv_base_vbar;
|
||||
driver->init_vbar = drv_base_init_vbar;
|
||||
driver->hbar = drv_base_hbar;
|
||||
driver->init_hbar = drv_base_init_hbar;
|
||||
driver->num = drv_base_num;
|
||||
driver->init_num = drv_base_init_num;
|
||||
|
||||
driver->init = drv_base_init;
|
||||
driver->close = drv_base_close;
|
||||
driver->flush = drv_base_flush;
|
||||
driver->flush_box = drv_base_flush_box;
|
||||
driver->contrast = drv_base_contrast;
|
||||
driver->backlight = drv_base_backlight;
|
||||
driver->set_char = drv_base_set_char;
|
||||
driver->icon = drv_base_icon;
|
||||
driver->draw_frame = drv_base_draw_frame;
|
||||
|
||||
driver->getkey = drv_base_getkey;
|
||||
|
||||
|
||||
return 200; // 200 is arbitrary. (must be 1 or more)
|
||||
}
|
||||
|
||||
|
||||
// Below here, you may use either lcd.framebuf or driver->framebuf..
|
||||
// lcd.framebuf will be set to the appropriate buffer before calling
|
||||
// your driver.
|
||||
|
||||
void drv_base_close()
|
||||
{
|
||||
if(lcd.framebuf != NULL) free(lcd.framebuf);
|
||||
|
||||
lcd.framebuf = NULL;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Clears the LCD screen
|
||||
//
|
||||
void drv_base_clear()
|
||||
{
|
||||
memset(lcd.framebuf, ' ', lcd.wid*lcd.hgt);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Flushes all output to the lcd...
|
||||
//
|
||||
void drv_base_flush()
|
||||
{
|
||||
//lcd.draw_frame(lcd.framebuf);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Prints a string on the lcd display, at position (x,y). The
|
||||
// upper-left is (1,1), and the lower right should be (20,4).
|
||||
//
|
||||
void drv_base_string(int x, int y, char string[])
|
||||
{
|
||||
int i;
|
||||
|
||||
x -= 1; // Convert 1-based coords to 0-based...
|
||||
y -= 1;
|
||||
|
||||
for(i=0; string[i]; i++)
|
||||
{
|
||||
// Check for buffer overflows...
|
||||
if((y*lcd.wid) + x + i > (lcd.wid*lcd.hgt)) break;
|
||||
lcd.framebuf[(y*lcd.wid) + x + i] = string[i];
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Prints a character on the lcd display, at position (x,y). The
|
||||
// upper-left is (1,1), and the lower right should be (20,4).
|
||||
//
|
||||
void drv_base_chr(int x, int y, char c)
|
||||
{
|
||||
y--;
|
||||
x--;
|
||||
|
||||
lcd.framebuf[(y*lcd.wid) + x] = c;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Sets the contrast of the display. Value is 0-255, where 140 is
|
||||
// what I consider "just right".
|
||||
//
|
||||
int drv_base_contrast(int contrast)
|
||||
{
|
||||
// printf("Contrast: %i\n", contrast);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Turns the lcd backlight on or off...
|
||||
//
|
||||
void drv_base_backlight(int on)
|
||||
{
|
||||
/*
|
||||
if(on)
|
||||
{
|
||||
printf("Backlight ON\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Backlight OFF\n");
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Tells the driver to get ready for vertical bargraphs.
|
||||
//
|
||||
void drv_base_init_vbar()
|
||||
{
|
||||
// printf("Vertical bars.\n");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Tells the driver to get ready for horizontal bargraphs.
|
||||
//
|
||||
void drv_base_init_hbar()
|
||||
{
|
||||
// printf("Horizontal bars.\n");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Tells the driver to get ready for big numbers, if possible.
|
||||
//
|
||||
void drv_base_init_num()
|
||||
{
|
||||
// printf("Big Numbers.\n");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Draws a big (4-row) number.
|
||||
//
|
||||
void drv_base_num(int x, int num)
|
||||
{
|
||||
// printf("BigNum(%i, %i)\n", x, num);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Changes the font data of character n.
|
||||
//
|
||||
void drv_base_set_char(int n, char *dat)
|
||||
{
|
||||
// printf("Set Character %i\n", n);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Draws a vertical bar, from the bottom of the screen up.
|
||||
//
|
||||
void drv_base_vbar(int x, int len)
|
||||
{
|
||||
int y;
|
||||
for(y=lcd.hgt; y > 0 && len>0; y--)
|
||||
{
|
||||
drv_base_chr(x, y, '|');
|
||||
|
||||
len -= lcd.cellhgt;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Draws a horizontal bar to the right.
|
||||
//
|
||||
void drv_base_hbar(int x, int y, int len)
|
||||
{
|
||||
for(; x<=lcd.wid && len>0; x++)
|
||||
{
|
||||
drv_base_chr(x,y,'-');
|
||||
|
||||
len -= lcd.cellwid;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Sets character 0 to an icon...
|
||||
//
|
||||
void drv_base_icon(int which, char dest)
|
||||
{
|
||||
// printf("Char %i set to icon %i\n", dest, which);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Send a rectangular area to the display.
|
||||
//
|
||||
// I've just called drv_base_flush() because there's not much point yet
|
||||
// in flushing less than the entire framebuffer.
|
||||
//
|
||||
void drv_base_flush_box(int lft, int top, int rgt, int bot)
|
||||
{
|
||||
//drv_base_flush();
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Draws the framebuffer on the display.
|
||||
//
|
||||
// The commented-out code is from the text driver.
|
||||
//
|
||||
void drv_base_draw_frame(char *dat)
|
||||
{
|
||||
/*
|
||||
int i, j;
|
||||
|
||||
char out[LCD_MAX_WIDTH];
|
||||
|
||||
if(!dat) return;
|
||||
|
||||
for(i=0; i<lcd.wid; i++)
|
||||
{
|
||||
out[i] = '-';
|
||||
}
|
||||
out[lcd.wid] = 0;
|
||||
printf("+%s+\n", out);
|
||||
|
||||
|
||||
for(i=0; i<lcd.hgt; i++)
|
||||
{
|
||||
for(j=0; j<lcd.wid; j++)
|
||||
{
|
||||
out[j] = dat[j+(i*lcd.wid)];
|
||||
}
|
||||
out[lcd.wid] = 0;
|
||||
printf("|%s|\n", out);
|
||||
|
||||
}
|
||||
|
||||
for(i=0; i<lcd.wid; i++)
|
||||
{
|
||||
out[i] = '-';
|
||||
}
|
||||
out[lcd.wid] = 0;
|
||||
printf("+%s+\n", out);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Tries to read a character from an input device...
|
||||
//
|
||||
// Return 0 for "nothing available".
|
||||
//
|
||||
char drv_base_getkey()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
#ifndef LCD_DRV_BASE_H
|
||||
#define LCD_DRV_BASE_H
|
||||
|
||||
/********************************************************************
|
||||
How to make a driver for LCDproc
|
||||
|
||||
Note: Insert the name of your driver in place of the phrase "new_driver".
|
||||
|
||||
1. Copy drv_base.c and drv_base.h to new_driver.c and new_driver.h.
|
||||
|
||||
2. Decide which functions you want to override, which ones you want
|
||||
to leave alone, and which ones you don't want at all. If you
|
||||
write your own driver functions, they will get called when
|
||||
appropriate. Or, you can let the default driver "drv_base"
|
||||
handle a function for you. But, if you really don't want a
|
||||
function, you can completely prevent your driver from providing
|
||||
it. This is discussed in step 5.
|
||||
|
||||
2.1. Remove all functions which you don't want to override, and the
|
||||
ones you don't want at all.
|
||||
|
||||
3. Rename all functions from "drv_base_*" to "new_driver_*".
|
||||
|
||||
4. Write the new driver functions.
|
||||
Be sure to do one of the following in/for your new_driver_close():
|
||||
- free the framebuffer lcd.framebuf
|
||||
- let the default driver handle close()
|
||||
- call drv_base_close()
|
||||
This will ensure that the frame buffer gets freed.
|
||||
|
||||
5. Register your functions in your new_driver_init(), like the following:
|
||||
driver->clear = new_driver_clear; // We want to handle this one
|
||||
driver->string = (void *)-1; // Leave this to the default
|
||||
driver->getkey = NULL; // This should never get called
|
||||
|
||||
The convention here is to set NULL for all the functions which
|
||||
your driver doesn't handle (and which you don't want the default
|
||||
functions to be called for). Or, set -1 to indicate that the
|
||||
driver should support the function but can use the default
|
||||
behavior in drv_base.c. Or, to indicate that your driver should
|
||||
handle a function, just set it like clear() above.
|
||||
|
||||
6. Add the driver to lcd.c, in the physical drivers section, protected
|
||||
by an #ifdef like the rest of the drivers are.
|
||||
|
||||
7. Add your driver to the Makefile, and Makefile.config, in the same
|
||||
style as the existing ones.
|
||||
|
||||
|
||||
Notes:
|
||||
|
||||
Don't call lcd.whatever() functions within your driver. This causes
|
||||
a lot of potentially puzzling problems.
|
||||
|
||||
However, feel free to access lcd.framebuf in your driver (but not in
|
||||
your init() function!). It will always point to the frame buffer
|
||||
you should be writing to. This will usually be your own frame
|
||||
buffer, but could potentially be another frame buffer, if another
|
||||
driver wants to access your functions.
|
||||
|
||||
Your driver will be provided with a frame buffer which contains one
|
||||
byte per character on the LCD. The default is a 20x4, so that's 80
|
||||
bytes. You can free this and reallocate it to something else if you
|
||||
need to. A graphical driver may want to do this, for example.
|
||||
|
||||
If you don't set a function pointer, it will default to NULL, since
|
||||
they get nullified before the driver's init() is called.
|
||||
|
||||
Assume that your driver may be added or removed dynamically, and
|
||||
that more than one instance may exist at a time. In other words, it
|
||||
should init and close cleanly, and not depend on global variables.
|
||||
|
||||
Special arguments will be passed through the "args" variable to your
|
||||
_init() function. This is just a string, and you determine the
|
||||
syntax of it. Please document the syntax so that it can easily be
|
||||
included in the lcdproc config file. I suggest arguments such as
|
||||
"port=0x378" or "-device /dev/ttyS0". These come directly from the
|
||||
lcdproc server config file, so they should be human-readable. An
|
||||
example may look like this:
|
||||
|
||||
# Set up two MtxOrb LCD's and a curses display on VT 2
|
||||
Driver MtxOrb -device /dev/ttyS0 -keypad on
|
||||
Driver curses -color off -size 20x4 -vt 2
|
||||
Driver MtxOrb -device /dev/ttyS3 -size 20x2 -keypad off
|
||||
# Before you ask, no, not all of these options are implemented yet.
|
||||
|
||||
Also, the driver API (if it can be called that) may change soon.
|
||||
There seem to be several functions which just don't do anything
|
||||
important... and there are other potential improvements too.
|
||||
|
||||
And... When in doubt, look at how the other drivers do it. :)
|
||||
|
||||
******************************************************************/
|
||||
|
||||
extern lcd_logical_driver *drv_base;
|
||||
|
||||
int drv_base_init(struct lcd_logical_driver *driver, char *args);
|
||||
void drv_base_close();
|
||||
void drv_base_clear();
|
||||
void drv_base_flush();
|
||||
void drv_base_string(int x, int y, char string[]);
|
||||
void drv_base_chr(int x, int y, char c);
|
||||
int drv_base_contrast(int contrast);
|
||||
void drv_base_backlight(int on);
|
||||
void drv_base_output(int on);
|
||||
void drv_base_vbar(int x, int len);
|
||||
void drv_base_init_vbar();
|
||||
void drv_base_hbar(int x, int y, int len);
|
||||
void drv_base_init_hbar();
|
||||
void drv_base_num(int x, int num);
|
||||
void drv_base_init_num();
|
||||
void drv_base_set_char(int n, char *dat);
|
||||
void drv_base_icon(int which, char dest);
|
||||
void drv_base_flush_box(int lft, int top, int rgt, int bot);
|
||||
void drv_base_draw_frame(char *dat);
|
||||
char drv_base_getkey();
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,562 @@
|
||||
/* Driver module for Hitachi HD44780 based Optrex DMC-20481 LCD display
|
||||
* The module is operated in it's 4 bit-mode to be connected to a single
|
||||
* 8 bit-port
|
||||
*
|
||||
* Copyright (c) 1998 Richard Rognlie GNU Public License
|
||||
* <rrognlie@gamerz.net>
|
||||
*
|
||||
* Large quantities of this code lifted (nearly verbatim) from
|
||||
* the lcd4.c module of lcdtext. Copyright (C) 1997 Matthias Prinke
|
||||
* <m.prinke@trashcan.mcnet.de> and covered by GNU's GPL.
|
||||
* In particular, this program is free software and comes WITHOUT
|
||||
* ANY WARRANTY.
|
||||
*
|
||||
* Matthias stole (er, adapted) the code from the package lcdtime by
|
||||
* Benjamin Tse (blt@mundil.cs.mu.oz.au), August/October 1995
|
||||
* which uses the LCD-controller's 8 bit-mode.
|
||||
* References: port.h by <damianf@wpi.edu>
|
||||
* Data Sheet LTN211, Philips
|
||||
* Various FAQs and TXTs about Hitachi's LCD Controller HD44780 -
|
||||
* www.paranoia.com/~filipg is a good starting point ???
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/perm.h>
|
||||
|
||||
#include "../../shared/str.h"
|
||||
|
||||
#include "lcd.h"
|
||||
#include "hd44780.h"
|
||||
#include "drv_base.h"
|
||||
|
||||
|
||||
lcd_logical_driver *HD44780;
|
||||
|
||||
#define EN 64
|
||||
#define RW 32
|
||||
#define RS 16
|
||||
|
||||
#ifndef LPTPORT
|
||||
unsigned int port = 0x378;
|
||||
#else
|
||||
unsigned int port = LPTPORT;
|
||||
#endif
|
||||
|
||||
static int lcd_x=0;
|
||||
static int lcd_y=0;
|
||||
|
||||
static void HD44780_linewrap(int on);
|
||||
static void HD44780_autoscroll(int on);
|
||||
|
||||
static int lp;
|
||||
|
||||
static void HD44780_senddata(unsigned char flags, unsigned char ch)
|
||||
{
|
||||
unsigned char h = ch >> 4;
|
||||
unsigned char l = ch & 15;
|
||||
|
||||
port_out(lp, 128 | EN | flags | h); usleep(1); port_out(lp, 128 | flags | h);
|
||||
port_out(lp, 128 | EN | flags | l); usleep(1); port_out(lp, 128 | flags | l);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Opens com port and sets baud correctly...
|
||||
//
|
||||
int HD44780_init(lcd_logical_driver *driver, char *args)
|
||||
{
|
||||
char *argv[64];
|
||||
int argc;
|
||||
int i;
|
||||
|
||||
|
||||
HD44780 = driver;
|
||||
|
||||
|
||||
argc = get_args(argv, args, 64);
|
||||
|
||||
for(i=0; i<argc; i++)
|
||||
{
|
||||
//printf("Arg(%i): %s\n", i, argv[i]);
|
||||
if(0 == strcmp(argv[i], "-p") ||
|
||||
0 == strcmp(argv[i], "--port"))
|
||||
{
|
||||
if(i + 1 > argc) {
|
||||
fprintf(stderr, "HD44780_init: %s requires an argument\n",
|
||||
argv[i]);
|
||||
return -1;
|
||||
}
|
||||
printf("Sorry, runtime lpt-port switching not yet implemented...\n");
|
||||
//strcpy(device, argv[++i]);
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-c") ||
|
||||
0 == strcmp(argv[i], "--contrast"))
|
||||
{
|
||||
if(i + 1 > argc) {
|
||||
fprintf(stderr, "HD44780_init: %s requires an argument\n",
|
||||
argv[i]);
|
||||
return -1;
|
||||
}
|
||||
printf("Sorry, contrast changing not yet implemented...\n");
|
||||
//contrast = atoi(argv[++i]);
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-h") ||
|
||||
0 == strcmp(argv[i], "--help"))
|
||||
{
|
||||
printf("LCDproc HD44780 driver\n"
|
||||
"\t-p\t--port\tSelect the output device to use [0x%x]\n"
|
||||
"\t-c\t--contrast\tSet the initial contrast [default]\n"
|
||||
"\t-h\t--help\t\tShow this help information\n",
|
||||
port);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Invalid parameter: %s\n", argv[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Set up io port correctly, and open it...
|
||||
if ((ioperm(port,1,1)) == -1) {
|
||||
fprintf(stderr, "HD44780_init: failed (%s)\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
lp = port;
|
||||
|
||||
// init HD44780
|
||||
port_out(lp, 128 | EN | 3); usleep(1); port_out(lp, 128 | 3); usleep(5000);
|
||||
port_out(lp, 128 | EN | 3); usleep(1); port_out(lp, 128 | 3); usleep(150);
|
||||
port_out(lp, 128 | EN | 3); usleep(1); port_out(lp, 128 | 3);
|
||||
// now in 8-bit mode... set 4-bit mode
|
||||
port_out(lp, 128 | EN | 2); usleep(1); port_out(lp, 128 | 2);
|
||||
// now in 4-bit mode... set 2 line, small char mode
|
||||
HD44780_senddata(0, 32 | 8);
|
||||
|
||||
//clear
|
||||
HD44780_senddata(0, 1);
|
||||
// set lcd on (4), cursor_on (2), and cursor_blink(1)
|
||||
HD44780_senddata(0, 8 | 4 | 0 | 0);
|
||||
|
||||
// Set display-specific stuff..
|
||||
//HD44780_linewrap(1);
|
||||
//HD44780_autoscroll(1);
|
||||
|
||||
// Make sure the frame buffer is there...
|
||||
if (!HD44780->framebuf)
|
||||
HD44780->framebuf = (unsigned char *) malloc(lcd.wid * lcd.hgt);
|
||||
|
||||
if (!HD44780->framebuf) {
|
||||
//HD44780_close();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// Set the functions the driver supports...
|
||||
|
||||
driver->clear = (void *)-1;
|
||||
driver->string = (void *)-1;
|
||||
driver->chr = (void *)-1;
|
||||
driver->vbar = HD44780_vbar;
|
||||
driver->init_vbar = HD44780_init_vbar;
|
||||
driver->hbar = HD44780_hbar;
|
||||
driver->init_hbar = HD44780_init_hbar;
|
||||
driver->num = HD44780_num;
|
||||
driver->init_num = HD44780_init_num;
|
||||
|
||||
driver->init = HD44780_init;
|
||||
driver->close = (void *)-1;
|
||||
driver->flush = HD44780_flush;
|
||||
driver->flush_box = HD44780_flush_box;
|
||||
driver->contrast = HD44780_contrast;
|
||||
driver->backlight = HD44780_backlight;
|
||||
driver->set_char = HD44780_set_char;
|
||||
driver->icon = HD44780_icon;
|
||||
driver->draw_frame = HD44780_draw_frame;
|
||||
|
||||
driver->getkey = NULL;
|
||||
|
||||
return lp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Clean-up
|
||||
//
|
||||
/*
|
||||
void HD44780_close()
|
||||
{
|
||||
drv_base_close();
|
||||
}
|
||||
*/
|
||||
|
||||
static void HD44780_position(int x, int y)
|
||||
{
|
||||
int val = x + (y%2) * 0x40;
|
||||
if (y>=2) val += 20;
|
||||
|
||||
HD44780_senddata(0,128|val);
|
||||
|
||||
lcd_x = x;
|
||||
lcd_y = y;
|
||||
}
|
||||
|
||||
void HD44780_flush()
|
||||
{
|
||||
HD44780_draw_frame(lcd.framebuf);
|
||||
}
|
||||
|
||||
|
||||
void HD44780_flush_box(int lft, int top, int rgt, int bot)
|
||||
{
|
||||
int x,y;
|
||||
|
||||
// printf("Flush (%i,%i)-(%i,%i)\n", lft, top, rgt, bot);
|
||||
|
||||
for (y=top; y<=bot; y++) {
|
||||
HD44780_position(lft,y);
|
||||
|
||||
for (x=lft ; x<=rgt ; x++) {
|
||||
HD44780_senddata(RS,lcd.framebuf[(y*20)+x]);
|
||||
}
|
||||
//write(fd, lcd.framebuf[(y*20)+lft, rgt-lft+1]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Changes screen contrast (0-255; 140 seems good)
|
||||
//
|
||||
int HD44780_contrast(int contrast)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Sets the backlight on or off -- can be done quickly for
|
||||
// an intermediate brightness...
|
||||
//
|
||||
void HD44780_backlight(int on)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Toggle the built-in linewrapping feature
|
||||
//
|
||||
static void HD44780_linewrap(int on)
|
||||
{
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Toggle the built-in automatic scrolling feature
|
||||
//
|
||||
static void HD44780_autoscroll(int on)
|
||||
{
|
||||
HD44780_senddata(0,4 | on * 2);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Sets up for vertical bars. Call before lcd.vbar()
|
||||
//
|
||||
void HD44780_init_vbar()
|
||||
{
|
||||
char a[] = {
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
1,1,1,1,1,
|
||||
};
|
||||
char b[] = {
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
};
|
||||
char c[] = {
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
};
|
||||
char d[] = {
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
};
|
||||
char e[] = {
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
};
|
||||
char f[] = {
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
};
|
||||
char g[] = {
|
||||
0,0,0,0,0,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
};
|
||||
|
||||
HD44780_set_char(1,a);
|
||||
HD44780_set_char(2,b);
|
||||
HD44780_set_char(3,c);
|
||||
HD44780_set_char(4,d);
|
||||
HD44780_set_char(5,e);
|
||||
HD44780_set_char(6,f);
|
||||
HD44780_set_char(7,g);
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Inits horizontal bars...
|
||||
//
|
||||
void HD44780_init_hbar()
|
||||
{
|
||||
|
||||
char a[] = {
|
||||
1,0,0,0,0,
|
||||
1,0,0,0,0,
|
||||
1,0,0,0,0,
|
||||
1,0,0,0,0,
|
||||
1,0,0,0,0,
|
||||
1,0,0,0,0,
|
||||
1,0,0,0,0,
|
||||
1,0,0,0,0,
|
||||
};
|
||||
char b[] = {
|
||||
1,1,0,0,0,
|
||||
1,1,0,0,0,
|
||||
1,1,0,0,0,
|
||||
1,1,0,0,0,
|
||||
1,1,0,0,0,
|
||||
1,1,0,0,0,
|
||||
1,1,0,0,0,
|
||||
1,1,0,0,0,
|
||||
};
|
||||
char c[] = {
|
||||
1,1,1,0,0,
|
||||
1,1,1,0,0,
|
||||
1,1,1,0,0,
|
||||
1,1,1,0,0,
|
||||
1,1,1,0,0,
|
||||
1,1,1,0,0,
|
||||
1,1,1,0,0,
|
||||
1,1,1,0,0,
|
||||
};
|
||||
char d[] = {
|
||||
1,1,1,1,0,
|
||||
1,1,1,1,0,
|
||||
1,1,1,1,0,
|
||||
1,1,1,1,0,
|
||||
1,1,1,1,0,
|
||||
1,1,1,1,0,
|
||||
1,1,1,1,0,
|
||||
1,1,1,1,0,
|
||||
};
|
||||
|
||||
HD44780_set_char(1,a);
|
||||
HD44780_set_char(2,b);
|
||||
HD44780_set_char(3,c);
|
||||
HD44780_set_char(4,d);
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Draws a vertical bar...
|
||||
//
|
||||
void HD44780_vbar(int x, int len)
|
||||
{
|
||||
char map[9] = {32, 1, 2, 3, 4, 5, 6, 7, 255 };
|
||||
|
||||
int y;
|
||||
for(y=lcd.hgt; y > 0 && len>0; y--) {
|
||||
if (len >= lcd.cellhgt)
|
||||
drv_base_chr(x, y, 255);
|
||||
else
|
||||
drv_base_chr(x, y, map[len]);
|
||||
|
||||
len -= lcd.cellhgt;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Draws a horizontal bar to the right.
|
||||
//
|
||||
void HD44780_hbar(int x, int y, int len)
|
||||
{
|
||||
char map[6] = { 32, 1, 2, 3, 4, 255 };
|
||||
|
||||
for (; x<=lcd.wid && len>0; x++) {
|
||||
if (len >= lcd.cellwid)
|
||||
drv_base_chr(x,y,255);
|
||||
else
|
||||
drv_base_chr(x, y, map[len]);
|
||||
|
||||
len -= lcd.cellwid;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Sets up for big numbers.
|
||||
//
|
||||
void HD44780_init_num()
|
||||
{
|
||||
char out[3];
|
||||
sprintf(out, "%cn", 254);
|
||||
//write(fd, out, 2);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Writes a big number.
|
||||
//
|
||||
void HD44780_num(int x, int num)
|
||||
{
|
||||
char out[5];
|
||||
sprintf(out, "%c#%c%c", 254, x, num);
|
||||
//write(fd, out, 4);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Sets a custom character from 0-7...
|
||||
//
|
||||
// For input, values > 0 mean "on" and values <= 0 are "off".
|
||||
//
|
||||
// The input is just an array of characters...
|
||||
//
|
||||
void HD44780_set_char(int n, char *dat)
|
||||
{
|
||||
int row, col;
|
||||
int letter;
|
||||
|
||||
if(n < 0 || n > 7) return;
|
||||
if(!dat) return;
|
||||
|
||||
HD44780_senddata(0, 64 | n*8);
|
||||
|
||||
for(row=0; row<lcd.cellhgt; row++) {
|
||||
letter = 0;
|
||||
for(col=0; col<lcd.cellwid; col++) {
|
||||
letter <<= 1;
|
||||
letter |= (dat[(row*lcd.cellwid) + col] > 0);
|
||||
}
|
||||
HD44780_senddata(RS, letter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void HD44780_icon(int which, char dest)
|
||||
{
|
||||
char icons[3][5*8] = {
|
||||
{
|
||||
1,1,1,1,1, // Empty Heart
|
||||
1,0,1,0,1,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
1,0,0,0,1,
|
||||
1,1,0,1,1,
|
||||
1,1,1,1,1,
|
||||
},
|
||||
|
||||
{
|
||||
1,1,1,1,1, // Filled Heart
|
||||
1,0,1,0,1,
|
||||
0,1,0,1,0,
|
||||
0,1,1,1,0,
|
||||
0,1,1,1,0,
|
||||
1,0,1,0,1,
|
||||
1,1,0,1,1,
|
||||
1,1,1,1,1,
|
||||
},
|
||||
|
||||
{
|
||||
0,0,0,0,0, // Ellipsis
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
1,0,1,0,1,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
|
||||
HD44780_set_char(dest, &icons[which][0]);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Blasts a single frame onscreen, to the lcd...
|
||||
//
|
||||
// Input is a character array, sized lcd.wid*lcd.hgt
|
||||
//
|
||||
void HD44780_draw_frame(char *dat)
|
||||
{
|
||||
int x,y;
|
||||
|
||||
if (!dat) return;
|
||||
|
||||
for (y=0; y<=3; y++) {
|
||||
HD44780_position(0,y);
|
||||
|
||||
for (x=0 ; x<=19 ; x++) {
|
||||
HD44780_senddata(RS,dat[(y*lcd.wid)+x]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/* Driver module for Hitachi HD44780 based Optrex DMC-20481 LCD display
|
||||
* The module is operated in it's 4 bit-mode to be connected to a single
|
||||
* 8 bit-port
|
||||
*
|
||||
* Copyright (c) 1998 Richard Rognlie GNU Public License
|
||||
* <rrognlie@gamerz.net>
|
||||
*
|
||||
* Large quantities of this code lifted (nearly verbatim) from
|
||||
* the lcd4.c module of lcdtext. Copyright (C) 1997 Matthias Prinke
|
||||
* <m.prinke@trashcan.mcnet.de> and covered by GNU's GPL.
|
||||
* In particular, this program is free software and comes WITHOUT
|
||||
* ANY WARRANTY.
|
||||
*
|
||||
* Matthias stole (er, adapted) the code from the package lcdtime by
|
||||
* Benjamin Tse (blt@mundil.cs.mu.oz.au), August/October 1995
|
||||
* which uses the LCD-controller's 8 bit-mode.
|
||||
* References: port.h by <damianf@wpi.edu>
|
||||
* Data Sheet LTN211, Philips
|
||||
* Various FAQs and TXTs about Hitachi's LCD Controller HD44780 -
|
||||
* www.paranoia.com/~filipg is a good starting point ???
|
||||
*/
|
||||
|
||||
#ifndef HD44780_H
|
||||
#define HD44780_H
|
||||
|
||||
#include "port.h"
|
||||
|
||||
|
||||
extern lcd_logical_driver *hd44780;
|
||||
|
||||
int HD44780_init(struct lcd_logical_driver *driver, char *args);
|
||||
void HD44780_close();
|
||||
void HD44780_flush();
|
||||
void HD44780_flush_box(int lft, int top, int rgt, int bot);
|
||||
int HD44780_contrast(int contrast);
|
||||
void HD44780_backlight(int on);
|
||||
void HD44780_init_vbar();
|
||||
void HD44780_init_hbar();
|
||||
void HD44780_vbar(int x, int len);
|
||||
void HD44780_hbar(int x, int y, int len);
|
||||
void HD44780_init_num();
|
||||
void HD44780_num(int x, int num);
|
||||
void HD44780_set_char(int n, char *dat);
|
||||
void HD44780_icon(int which, char dest);
|
||||
void HD44780_draw_frame(char *dat);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
Hmm...
|
||||
|
||||
How to do multiple drivers...
|
||||
|
||||
|
||||
lcd_sample_func(parameters)
|
||||
{
|
||||
D'oh..
|
||||
}
|
||||
|
||||
lcd_driver_caller()
|
||||
{
|
||||
foreach driver (@drivers)
|
||||
{
|
||||
if(driver supports function)
|
||||
call driver's function
|
||||
else if(driver uses defaults)
|
||||
call default function
|
||||
else don't do anything
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
/* irmanin.c - test/demo of LIBIR's to interface with lcdproc (LCDd) */
|
||||
/* Copyright (C) 1999 David Glaude loosely based on workmanir.c */
|
||||
/* workmanir.c - test/demo of LIBIR's high level command functions */
|
||||
/* Copyright (C) 1998 Tom Wheeley, see file COPYING for details */
|
||||
#include <config.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#define __u32 unsigned int
|
||||
#define __u8 unsigned char
|
||||
|
||||
|
||||
#include "../../shared/debug.h"
|
||||
#include "../../shared/str.h"
|
||||
|
||||
#define NAME_LENGTH 128
|
||||
|
||||
#include "lcd.h"
|
||||
#include "irmanin.h"
|
||||
#include "../../../libirman-0.4.1b/irman.h"
|
||||
|
||||
|
||||
char *progname = "irmanin";
|
||||
|
||||
char *codes[] = {
|
||||
/* dummy */ NULL,
|
||||
/* KeyToLcd */ "lcdproc-A",
|
||||
/* KeyToLcd */ "lcdproc-B",
|
||||
/* KeyToLcd */ "lcdproc-C",
|
||||
/* KeyToLcd */ "lcdproc-D",
|
||||
/* KeyToLcd */ "lcdproc-E",
|
||||
/* KeyToLcd */ "lcdproc-F",
|
||||
/* KeyToLcd */ "lcdproc-G",
|
||||
/* KeyToLcd */ "lcdproc-H",
|
||||
/* KeyToLcd */ "lcdproc-I",
|
||||
/* KeyToLcd */ "lcdproc-J",
|
||||
/* KeyToLcd */ "lcdproc-K",
|
||||
/* KeyToLcd */ "lcdproc-L",
|
||||
/* KeyToLcd */ "lcdproc-M",
|
||||
/* KeyToLcd */ "lcdproc-N",
|
||||
/* KeyToLcd */ "lcdproc-O",
|
||||
/* KeyToLcd */ "lcdproc-P",
|
||||
/* KeyToLcd */ "lcdproc-Q",
|
||||
/* KeyToLcd */ "lcdproc-R",
|
||||
/* KeyToLcd */ "lcdproc-S",
|
||||
/* KeyToLcd */ "lcdproc-T",
|
||||
/* KeyToLcd */ "lcdproc-U",
|
||||
/* KeyToLcd */ "lcdproc-V",
|
||||
/* KeyToLcd */ "lcdproc-W",
|
||||
/* KeyToLcd */ "lcdproc-X",
|
||||
/* KeyToLcd */ "lcdproc-Y",
|
||||
/* KeyToLcd */ "lcdproc-Z",
|
||||
/* end */ NULL
|
||||
};
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////////////////////// Base "class" to derive from ///////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
lcd_logical_driver *irmanin;
|
||||
|
||||
//void sigterm(int sig)
|
||||
//{
|
||||
// ir_free_commands();
|
||||
// ir_finish();
|
||||
// raise(sig);
|
||||
//}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// init() should set up any device-specific stuff, and
|
||||
// point all the function pointers.
|
||||
int irmanin_init(struct lcd_logical_driver *driver, char *args)
|
||||
{
|
||||
char device[256];
|
||||
char *ptrdevice;
|
||||
char config[256];
|
||||
char *ptrconfig;
|
||||
|
||||
char *portname;
|
||||
|
||||
char *argv[64];
|
||||
int argc, i, j;
|
||||
char *filename;
|
||||
|
||||
ptrconfig=NULL;
|
||||
ptrdevice=NULL;
|
||||
|
||||
irmanin = driver;
|
||||
|
||||
argc = get_args(argv, args, 64);
|
||||
|
||||
for(i=0; i<argc; i++)
|
||||
{
|
||||
//printf("Arg(%i): %s\n", i, argv[i]);
|
||||
if(0 == strcmp(argv[i], "-d") ||
|
||||
0 == strcmp(argv[i], "--device"))
|
||||
{
|
||||
if(i + 1 > argc) {
|
||||
fprintf(stderr, "irmanin_init: %s requires an argument\n",
|
||||
argv[i]);
|
||||
return -1;
|
||||
}
|
||||
strcpy(device, argv[++i]);
|
||||
ptrdevice=device;
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-c") ||
|
||||
0 == strcmp(argv[i], "--config"))
|
||||
{
|
||||
if(i + 1 > argc) {
|
||||
fprintf(stderr, "irmanin_init: %s requires an argument\n",
|
||||
argv[i]);
|
||||
return -1;
|
||||
}
|
||||
strcpy(config, argv[++i]);
|
||||
ptrconfig=config;
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-h") ||
|
||||
0 == strcmp(argv[i], "--help"))
|
||||
{
|
||||
printf("LCDproc IrMan input driver\n"
|
||||
"\t-d\t--device\tSelect the input device to use\n"
|
||||
"\t-d\t--config\tSelect the configuration file to use\n"
|
||||
"\t-h\t--help\t\tShow this help information\n");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Invalid parameter: %s\n", argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (ir_init_commands(ptrconfig, 1) < 0) {
|
||||
fprintf(stderr, "error initialising commands: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
portname = ir_default_portname();
|
||||
if(portname==NULL){
|
||||
if(ptrdevice==NULL){
|
||||
portname=ptrdevice;
|
||||
}else{
|
||||
fprintf(stderr, "error no device defined\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
driver->getkey = irmanin_getkey;
|
||||
driver->close = irmanin_close;
|
||||
|
||||
for (i=1; codes[i] != NULL; i++) {
|
||||
if (ir_register_command(codes[i], i) < 0) {
|
||||
if (errno == ENOENT) {
|
||||
fprintf(stderr, "%s: no code set for `%s'\n", progname, codes[i]);
|
||||
} else {
|
||||
fprintf(stderr, "error registering `%s': `%s'\n", codes[i], strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
if (ir_init(portname) < 0) {
|
||||
fprintf(stderr, "%s: error initialising Irman: `%s'\n", strerror(errno), portname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 1; // 200 is arbitrary. (must be 1 or more)
|
||||
}
|
||||
|
||||
|
||||
void irmanin_close()
|
||||
{
|
||||
if(irmanin->framebuf != NULL) free(irmanin->framebuf);
|
||||
|
||||
irmanin->framebuf = NULL;
|
||||
|
||||
ir_free_commands();
|
||||
ir_finish();
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Tries to read a character from an input device...
|
||||
//
|
||||
// Return 0 for "nothing available".
|
||||
//
|
||||
char irmanin_getkey()
|
||||
{
|
||||
int i;
|
||||
int cmd;
|
||||
char key;
|
||||
|
||||
key=(char)0;
|
||||
switch (cmd=ir_poll_command()) {
|
||||
case IR_CMD_ERROR:
|
||||
fprintf(stderr, "%s: error reading command: %s\n", progname, strerror(errno));
|
||||
break;
|
||||
case IR_CMD_UNKNOWN:
|
||||
break;
|
||||
default:
|
||||
key=(char)('A'-1+cmd);
|
||||
break;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
/* end of irmanin.c */
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef LCD_IRMANIN__H
|
||||
#define LCD_IRMANIN_H
|
||||
|
||||
|
||||
extern lcd_logical_driver *joy;
|
||||
|
||||
int irmanin_init(struct lcd_logical_driver *driver, char *args);
|
||||
void irmanin_close();
|
||||
char irmanin_getkey();
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,218 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
#define __u32 unsigned int
|
||||
#define __u8 unsigned char
|
||||
#include <linux/joystick.h>
|
||||
|
||||
|
||||
#include "../../shared/debug.h"
|
||||
#include "../../shared/str.h"
|
||||
|
||||
#define NAME_LENGTH 128
|
||||
|
||||
|
||||
|
||||
#include "lcd.h"
|
||||
#include "joy.h"
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////////////////////// Base "class" to derive from ///////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
lcd_logical_driver *joy;
|
||||
|
||||
int fd;
|
||||
|
||||
struct js_event js;
|
||||
|
||||
char axes = 2;
|
||||
char buttons = 2;
|
||||
int jsversion = 0x000800;
|
||||
char jsname[NAME_LENGTH] = "Unknown";
|
||||
|
||||
int *axis;
|
||||
int *button;
|
||||
|
||||
|
||||
// Configured for a Gravis Gamepad (2 axis, 4 button)
|
||||
char *axismap = "EFGHIJKLMNOPQRST";
|
||||
char *buttonmap = "BDACEFGHIJKLMNOP";
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// init() should set up any device-specific stuff, and
|
||||
// point all the function pointers.
|
||||
int joy_init(struct lcd_logical_driver *driver, char *args)
|
||||
{
|
||||
char device[256];
|
||||
char *argv[64];
|
||||
int argc, i, j;
|
||||
|
||||
joy = driver;
|
||||
|
||||
|
||||
strcpy(device, "/dev/js0");
|
||||
|
||||
argc = get_args(argv, args, 64);
|
||||
|
||||
for(i=0; i<argc; i++)
|
||||
{
|
||||
//printf("Arg(%i): %s\n", i, argv[i]);
|
||||
if(0 == strcmp(argv[i], "-d") ||
|
||||
0 == strcmp(argv[i], "--device"))
|
||||
{
|
||||
if(i + 1 > argc) {
|
||||
fprintf(stderr, "joy_init: %s requires an argument\n",
|
||||
argv[i]);
|
||||
return -1;
|
||||
}
|
||||
strcpy(device, argv[++i]);
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-a") ||
|
||||
0 == strcmp(argv[i], "--axes"))
|
||||
{
|
||||
if(i + 1 > argc) {
|
||||
fprintf(stderr, "joy_init: %s requires an argument\n",
|
||||
argv[i]);
|
||||
return -1;
|
||||
}
|
||||
strncpy(axismap, argv[++i], 16);
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-b") ||
|
||||
0 == strcmp(argv[i], "--buttons"))
|
||||
{
|
||||
if(i + 1 > argc) {
|
||||
fprintf(stderr, "joy_init: %s requires an argument\n",
|
||||
argv[i]);
|
||||
return -1;
|
||||
}
|
||||
strncpy(buttonmap, argv[++i], 16);
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-h") ||
|
||||
0 == strcmp(argv[i], "--help"))
|
||||
{
|
||||
printf("LCDproc Joystick input driver\n"
|
||||
"\t-d\t--device\tSelect the input device to use [/dev/js0]\n"
|
||||
"\t-a\t--axes\t\tModify the axis map [%s]\n"
|
||||
"\t-b\t--buttons\tModify the button map [%s]\n"
|
||||
"\t-h\t--help\t\tShow this help information\n",
|
||||
axismap, buttonmap);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Invalid parameter: %s\n", argv[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
driver->getkey = joy_getkey;
|
||||
driver->close = joy_close;
|
||||
|
||||
|
||||
/* FIXME: This crashes!
|
||||
if(args)
|
||||
{
|
||||
if(strlen(args) > 0)
|
||||
strcpy(device, args);
|
||||
}
|
||||
*/
|
||||
|
||||
fd = open (device, O_RDONLY);
|
||||
fcntl(fd, F_SETFL, O_NONBLOCK);
|
||||
|
||||
if(fd < 0) return -1;
|
||||
|
||||
ioctl(fd, JSIOCGVERSION, &jsversion);
|
||||
ioctl(fd, JSIOCGAXES, &axes);
|
||||
ioctl(fd, JSIOCGBUTTONS, &buttons);
|
||||
ioctl(fd, JSIOCGNAME(NAME_LENGTH), jsname);
|
||||
|
||||
debug("Joystick (%s) has %d axes and %d buttons. Driver version is %d.%d.%d.\n",
|
||||
jsname, axes, buttons,
|
||||
jsversion >> 16, (jsversion >> 8) & 0xff, jsversion & 0xff);
|
||||
|
||||
axis = calloc(axes, sizeof(int));
|
||||
button = calloc(buttons, sizeof(char));
|
||||
|
||||
return fd; // 200 is arbitrary. (must be 1 or more)
|
||||
}
|
||||
|
||||
|
||||
void joy_close()
|
||||
{
|
||||
if(joy->framebuf != NULL) free(joy->framebuf);
|
||||
close(fd);
|
||||
|
||||
joy->framebuf = NULL;
|
||||
|
||||
// Why do I have so much trouble getting memory freed without segfaults??
|
||||
//if(axis) free(axis);
|
||||
//if(button) free(button);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Tries to read a character from an input device...
|
||||
//
|
||||
// Return 0 for "nothing available".
|
||||
//
|
||||
char joy_getkey()
|
||||
{
|
||||
int i;
|
||||
int err;
|
||||
|
||||
err = read(fd, &js, sizeof(struct js_event));
|
||||
if (err <= 0) return 0;
|
||||
if (err != sizeof(struct js_event)) {
|
||||
fprintf(stderr, "\nerror reading joystick\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// if(js.type & JS_EVENT_INIT) return 0;
|
||||
|
||||
switch(js.type & ~JS_EVENT_INIT) {
|
||||
case JS_EVENT_BUTTON:
|
||||
button[js.number] = js.value;
|
||||
break;
|
||||
case JS_EVENT_AXIS:
|
||||
axis[js.number] = js.value;
|
||||
break;
|
||||
}
|
||||
|
||||
if (buttons) {
|
||||
//printf("Buttons: ");
|
||||
for (i = 0; i < buttons; i++)
|
||||
//printf("%2d:%s ", i, button[i] ? "on " : "off");
|
||||
if(button[i]) return buttonmap[i];
|
||||
}
|
||||
|
||||
if (axes) {
|
||||
//printf("Axes: ");
|
||||
for (i = 0; i < axes; i++)
|
||||
{
|
||||
//printf("%2d:%6d ", i, axis[i]);
|
||||
// Eliminate noise...
|
||||
if(axis[i] > 20000) return axismap[(2*i) + 1];
|
||||
if(axis[i] < -20000) return axismap[(2*i)];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef LCD_JOY_H
|
||||
#define LCD_JOY_H
|
||||
|
||||
|
||||
extern lcd_logical_driver *joy;
|
||||
|
||||
int joy_init(struct lcd_logical_driver *driver, char *args);
|
||||
void joy_close();
|
||||
char joy_getkey();
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,727 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
#include "LL.h"
|
||||
|
||||
#include "lcd.h"
|
||||
|
||||
#include "drv_base.h"
|
||||
|
||||
#ifdef MTXORB_DRV
|
||||
#include "MtxOrb.h"
|
||||
#endif
|
||||
|
||||
#ifdef CFONTZ_DRV
|
||||
#include "CFontz.h"
|
||||
#endif
|
||||
|
||||
#ifdef TEXT_DRV
|
||||
#include "text.h"
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_DRV
|
||||
#include "debug.h"
|
||||
#endif
|
||||
|
||||
#ifdef CURSES_DRV
|
||||
#include "curses_drv.h"
|
||||
#endif
|
||||
|
||||
#ifdef HD44780_DRV
|
||||
#include "hd44780.h"
|
||||
#endif
|
||||
|
||||
#ifdef SLI_DRV
|
||||
#include "wirz-sli.h"
|
||||
#endif
|
||||
|
||||
#ifdef JOY_DRV
|
||||
#include "joy.h"
|
||||
#endif
|
||||
|
||||
#ifdef IRMANIN_DRV
|
||||
#include "irmanin.h"
|
||||
#endif
|
||||
|
||||
// TODO: Make a Windows server, and clients...?
|
||||
|
||||
|
||||
lcd_logical_driver lcd;
|
||||
|
||||
lcd_physical_driver drivers[] =
|
||||
{
|
||||
{ "base", drv_base_init, },
|
||||
#ifdef MTXORB_DRV
|
||||
{ "MtxOrb", MtxOrb_init, },
|
||||
#endif
|
||||
#ifdef CFONTZ_DRV
|
||||
{ "CFontz", CFontz_init, },
|
||||
#endif
|
||||
#ifdef HD44780_DRV
|
||||
{ "HD44780", HD44780_init, },
|
||||
#endif
|
||||
#ifdef SLI_DRV
|
||||
{ "sli", sli_init, },
|
||||
#endif
|
||||
#ifdef TEXT_DRV
|
||||
{ "text", text_init, },
|
||||
#endif
|
||||
#ifdef DEBUG_DRV
|
||||
{ "debug", debug_init, },
|
||||
#endif
|
||||
#ifdef CURSES_DRV
|
||||
{ "curses", curses_drv_init, },
|
||||
#endif
|
||||
#ifdef JOY_DRV
|
||||
{ "joy", joy_init, },
|
||||
#endif
|
||||
#ifdef IRMANIN_DRV
|
||||
{ "irmanin", irmanin_init, },
|
||||
#endif
|
||||
{ NULL, NULL, },
|
||||
|
||||
};
|
||||
|
||||
LL *list;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// This sets up which driver to use and initializes stuff.
|
||||
//
|
||||
int lcd_init(char *args)
|
||||
{
|
||||
// int i;
|
||||
int err;
|
||||
|
||||
list = LL_new();
|
||||
if(!list)
|
||||
{
|
||||
printf("Error allocating driver list.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
lcd_drv_init(NULL, NULL);
|
||||
|
||||
err = lcd_add_driver("base", args);
|
||||
|
||||
lcd.wid = 20;
|
||||
lcd.hgt = 4;
|
||||
|
||||
return err;
|
||||
|
||||
/*
|
||||
drv_base_init(args);
|
||||
|
||||
for(i=0; drivers[i].name; i++)
|
||||
{
|
||||
if(!strcmp(driver, drivers[i].name))
|
||||
{
|
||||
return drivers[i].init(args);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Invalid driver: %s\n", driver);
|
||||
return -1;
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
// TODO: lcd_remove_driver()
|
||||
|
||||
int lcd_add_driver(char *driver, char *args)
|
||||
{
|
||||
int i;
|
||||
|
||||
lcd_logical_driver *add;
|
||||
|
||||
for(i=0; drivers[i].name; i++)
|
||||
{
|
||||
|
||||
//printf("Checking driver: %s\n", drivers[i].name);
|
||||
|
||||
if(0 == strcmp(driver, drivers[i].name))
|
||||
{
|
||||
|
||||
//printf("Found driver: %s (%s)\n", drivers[i].name, driver);
|
||||
|
||||
add = malloc(sizeof(lcd_logical_driver));
|
||||
if(!add)
|
||||
{
|
||||
printf("Couldn't allocate driver \"%s\".\n", driver);
|
||||
return -1;
|
||||
}
|
||||
//printf("Allocated driver\n");
|
||||
memset(add, 0, sizeof(lcd_logical_driver));
|
||||
|
||||
add->wid = lcd.wid; add->hgt = lcd.hgt;
|
||||
add->cellwid = lcd.cellwid; add->cellhgt = lcd.cellhgt;
|
||||
|
||||
// printf("LCD driver info:\n\twid: %i\thgt: %i\n",
|
||||
// add->wid, add->hgt);
|
||||
|
||||
add->framebuf = malloc(add->wid * add->hgt);
|
||||
|
||||
if(!add->framebuf)
|
||||
{
|
||||
printf("Couldn't allocate framebuffer for driver \"%s\".\n",
|
||||
driver);
|
||||
free(add);
|
||||
return -1;
|
||||
}
|
||||
//printf("Allocated frame buffer\n");
|
||||
|
||||
LL_Push(list, (void *)add);
|
||||
|
||||
return drivers[i].init(add, args);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO: Put lcd_shutdown in the shutdown function...
|
||||
int lcd_shutdown()
|
||||
{
|
||||
lcd_logical_driver *driver;
|
||||
|
||||
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
driver = (lcd_logical_driver *)LL_Get(list);
|
||||
if(driver)
|
||||
{
|
||||
//printf("driver...\n");
|
||||
lcd.framebuf = driver->framebuf;
|
||||
|
||||
if((int)driver->close > 0)
|
||||
{
|
||||
driver->close();
|
||||
}
|
||||
else if((int)driver->close == -1)
|
||||
{
|
||||
drv_base->close();
|
||||
}
|
||||
|
||||
LL_Shift(list);
|
||||
// FIXME: This crashes!
|
||||
//if(driver) free(driver);
|
||||
//printf("...freed\n");
|
||||
}
|
||||
|
||||
} while(LL_Length(list) > 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int lcd_drv_init(struct lcd_logical_driver *driver, char *args)
|
||||
{
|
||||
// printf("lcd_drv_init()\n");
|
||||
|
||||
lcd.wid = LCD_MAX_WID;
|
||||
lcd.hgt = LCD_MAX_HGT;
|
||||
|
||||
lcd.framebuf = NULL;
|
||||
/*
|
||||
if(!lcd.framebuf)
|
||||
lcd.framebuf = malloc(lcd.wid * lcd.hgt);
|
||||
|
||||
if(!lcd.framebuf)
|
||||
{
|
||||
lcd_drv_close();
|
||||
return -1;
|
||||
}
|
||||
memset(lcd.framebuf, ' ', lcd.wid*lcd.hgt);
|
||||
*/
|
||||
// Debugging...
|
||||
// if(lcd.framebuf) printf("Frame buffer: %i\n", (int)lcd.framebuf);
|
||||
|
||||
lcd.cellwid = 5;
|
||||
lcd.cellhgt = 8;
|
||||
|
||||
// Set up these wrapper functions...
|
||||
lcd.clear = lcd_drv_clear;
|
||||
lcd.string = lcd_drv_string;
|
||||
lcd.chr = lcd_drv_chr;
|
||||
lcd.vbar = lcd_drv_vbar;
|
||||
lcd.hbar = lcd_drv_hbar;
|
||||
lcd.init_num = lcd_drv_init_num;
|
||||
lcd.num = lcd_drv_num;
|
||||
|
||||
lcd.init = lcd_drv_init;
|
||||
lcd.close = lcd_drv_close;
|
||||
lcd.flush = lcd_drv_flush;
|
||||
lcd.flush_box = lcd_drv_flush_box;
|
||||
lcd.contrast = lcd_drv_contrast;
|
||||
lcd.backlight = lcd_drv_backlight;
|
||||
lcd.output = lcd_drv_output;
|
||||
lcd.set_char = lcd_drv_set_char;
|
||||
lcd.icon = lcd_drv_icon;
|
||||
lcd.init_vbar = lcd_drv_init_vbar;
|
||||
lcd.init_hbar = lcd_drv_init_hbar;
|
||||
lcd.draw_frame = lcd_drv_draw_frame;
|
||||
|
||||
lcd.getkey = lcd_drv_getkey;
|
||||
|
||||
|
||||
return 1; // 1 is arbitrary. (must be 1 or more)
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// All functions below here call their respective driver functions...
|
||||
//
|
||||
// The way it works is this:
|
||||
// It loops through the list of drivers, calling each one to keep
|
||||
// them all synchronized. During this loop...
|
||||
// - First, set the framebuffer to point to the drivers' framebuffer.
|
||||
// (this ensures that whatever driver gets called will operate on
|
||||
// the correct buffer)
|
||||
// - Then, it checks to see what sort of call to make.
|
||||
// driver->func() > 0 means it should call the driver function.
|
||||
// driver->func() == NULL means it should not make a call.
|
||||
// driver->func() == -1 means it should call the generic driver.
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void lcd_drv_close()
|
||||
{
|
||||
lcd_logical_driver *driver;
|
||||
|
||||
// printf("lcd_drv_close()\n");
|
||||
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
driver = (lcd_logical_driver *)LL_Get(list);
|
||||
if(driver)
|
||||
{
|
||||
lcd.framebuf = driver->framebuf;
|
||||
|
||||
if((int)driver->close > 0)
|
||||
{
|
||||
printf("Calling close()\n");
|
||||
driver->close();
|
||||
}
|
||||
else if((int)driver->close == -1)
|
||||
{
|
||||
drv_base->close();
|
||||
}
|
||||
}
|
||||
} while(LL_Next(list) == 0);
|
||||
|
||||
}
|
||||
|
||||
void lcd_drv_clear()
|
||||
{
|
||||
lcd_logical_driver *driver;
|
||||
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
driver = (lcd_logical_driver *)LL_Get(list);
|
||||
if(driver)
|
||||
{
|
||||
lcd.framebuf = driver->framebuf;
|
||||
|
||||
if((int)driver->clear > 0)
|
||||
driver->clear();
|
||||
else if((int)driver->clear == -1)
|
||||
{
|
||||
drv_base->clear();
|
||||
}
|
||||
}
|
||||
} while(LL_Next(list) == 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void lcd_drv_flush()
|
||||
{
|
||||
lcd_logical_driver *driver;
|
||||
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
driver = (lcd_logical_driver *)LL_Get(list);
|
||||
if(driver)
|
||||
{
|
||||
lcd.framebuf = driver->framebuf;
|
||||
|
||||
if((int)driver->flush > 0)
|
||||
driver->flush();
|
||||
else if((int)driver->flush == -1)
|
||||
{
|
||||
drv_base->flush();
|
||||
}
|
||||
}
|
||||
} while(LL_Next(list) == 0);
|
||||
}
|
||||
|
||||
|
||||
void lcd_drv_string(int x, int y, char string[])
|
||||
{
|
||||
lcd_logical_driver *driver;
|
||||
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
driver = (lcd_logical_driver *)LL_Get(list);
|
||||
if(driver)
|
||||
{
|
||||
lcd.framebuf = driver->framebuf;
|
||||
|
||||
if((int)driver->string > 0)
|
||||
driver->string(x,y,string);
|
||||
else if((int)driver->string == -1)
|
||||
{
|
||||
drv_base->string(x,y,string);
|
||||
}
|
||||
}
|
||||
} while(LL_Next(list) == 0);
|
||||
}
|
||||
|
||||
void lcd_drv_chr(int x, int y, char c)
|
||||
{
|
||||
lcd_logical_driver *driver;
|
||||
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
driver = (lcd_logical_driver *)LL_Get(list);
|
||||
if(driver)
|
||||
{
|
||||
lcd.framebuf = driver->framebuf;
|
||||
|
||||
if((int)driver->chr > 0)
|
||||
driver->chr(x,y,c);
|
||||
else if((int)driver->chr == -1)
|
||||
{
|
||||
drv_base->chr(x,y,c);
|
||||
}
|
||||
}
|
||||
} while(LL_Next(list) == 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int lcd_drv_contrast(int contrast)
|
||||
{
|
||||
int res=0;
|
||||
|
||||
lcd_logical_driver *driver;
|
||||
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
driver = (lcd_logical_driver *)LL_Get(list);
|
||||
if(driver)
|
||||
{
|
||||
lcd.framebuf = driver->framebuf;
|
||||
|
||||
if((int)driver->contrast > 0)
|
||||
{
|
||||
res=driver->contrast(contrast);
|
||||
if(res >= 0) return res;
|
||||
}
|
||||
/*
|
||||
else if((int)driver->contrast == -1)
|
||||
{
|
||||
res=drv_base->contrast(contrast);
|
||||
}
|
||||
*/
|
||||
}
|
||||
} while(LL_Next(list) == 0);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void lcd_drv_backlight(int on)
|
||||
{
|
||||
lcd_logical_driver *driver;
|
||||
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
driver = (lcd_logical_driver *)LL_Get(list);
|
||||
if(driver)
|
||||
{
|
||||
lcd.framebuf = driver->framebuf;
|
||||
|
||||
if((int)driver->backlight > 0)
|
||||
driver->backlight(on);
|
||||
else if((int)driver->backlight == -1)
|
||||
{
|
||||
drv_base->backlight(on);
|
||||
}
|
||||
}
|
||||
} while(LL_Next(list) == 0);
|
||||
}
|
||||
|
||||
void lcd_drv_output(int on)
|
||||
{
|
||||
lcd_logical_driver *driver;
|
||||
LL_Rewind(list);
|
||||
do
|
||||
{
|
||||
driver = (lcd_logical_driver *)LL_Get(list);
|
||||
if(driver)
|
||||
{
|
||||
lcd.framebuf = driver->framebuf;
|
||||
if((int)driver->output > 0)
|
||||
driver->output(on);
|
||||
else if((int)driver->output == -1)
|
||||
{
|
||||
drv_base->output(on);
|
||||
}
|
||||
}
|
||||
} while(LL_Next(list) == 0);
|
||||
}
|
||||
|
||||
|
||||
void lcd_drv_init_vbar()
|
||||
{
|
||||
lcd_logical_driver *driver;
|
||||
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
driver = (lcd_logical_driver *)LL_Get(list);
|
||||
if(driver)
|
||||
{
|
||||
lcd.framebuf = driver->framebuf;
|
||||
|
||||
if((int)driver->init_vbar > 0)
|
||||
driver->init_vbar();
|
||||
else if((int)driver->init_vbar == -1)
|
||||
{
|
||||
drv_base->init_vbar();
|
||||
}
|
||||
}
|
||||
} while(LL_Next(list) == 0);
|
||||
}
|
||||
|
||||
void lcd_drv_init_hbar()
|
||||
{
|
||||
lcd_logical_driver *driver;
|
||||
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
driver = (lcd_logical_driver *)LL_Get(list);
|
||||
if(driver)
|
||||
{
|
||||
lcd.framebuf = driver->framebuf;
|
||||
|
||||
if((int)driver->init_hbar > 0)
|
||||
driver->init_hbar();
|
||||
else if((int)driver->init_hbar == -1)
|
||||
{
|
||||
drv_base->init_hbar();
|
||||
}
|
||||
}
|
||||
} while(LL_Next(list) == 0);
|
||||
}
|
||||
|
||||
void lcd_drv_init_num()
|
||||
{
|
||||
lcd_logical_driver *driver;
|
||||
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
driver = (lcd_logical_driver *)LL_Get(list);
|
||||
if(driver)
|
||||
{
|
||||
lcd.framebuf = driver->framebuf;
|
||||
|
||||
if((int)driver->init_num > 0)
|
||||
driver->init_num();
|
||||
else if((int)driver->init_num == -1)
|
||||
{
|
||||
drv_base->init_num();
|
||||
}
|
||||
}
|
||||
} while(LL_Next(list) == 0);
|
||||
}
|
||||
|
||||
void lcd_drv_num(int x, int num)
|
||||
{
|
||||
lcd_logical_driver *driver;
|
||||
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
driver = (lcd_logical_driver *)LL_Get(list);
|
||||
if(driver)
|
||||
{
|
||||
lcd.framebuf = driver->framebuf;
|
||||
|
||||
if((int)driver->num > 0)
|
||||
driver->num(x,num);
|
||||
else if((int)driver->num == -1)
|
||||
{
|
||||
drv_base->num(x,num);
|
||||
}
|
||||
}
|
||||
} while(LL_Next(list) == 0);
|
||||
}
|
||||
|
||||
void lcd_drv_set_char(int n, char *dat)
|
||||
{
|
||||
lcd_logical_driver *driver;
|
||||
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
driver = (lcd_logical_driver *)LL_Get(list);
|
||||
if(driver)
|
||||
{
|
||||
lcd.framebuf = driver->framebuf;
|
||||
|
||||
if((int)driver->set_char > 0)
|
||||
driver->set_char(n,dat);
|
||||
else if((int)driver->set_char == -1)
|
||||
{
|
||||
drv_base->set_char(n,dat);
|
||||
}
|
||||
}
|
||||
} while(LL_Next(list) == 0);
|
||||
}
|
||||
|
||||
void lcd_drv_vbar(int x, int len)
|
||||
{
|
||||
lcd_logical_driver *driver;
|
||||
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
driver = (lcd_logical_driver *)LL_Get(list);
|
||||
if(driver)
|
||||
{
|
||||
lcd.framebuf = driver->framebuf;
|
||||
|
||||
if((int)driver->vbar > 0)
|
||||
driver->vbar(x,len);
|
||||
else if((int)driver->vbar == -1)
|
||||
{
|
||||
drv_base->vbar(x,len);
|
||||
}
|
||||
}
|
||||
} while(LL_Next(list) == 0);
|
||||
}
|
||||
|
||||
void lcd_drv_hbar(int x, int y, int len)
|
||||
{
|
||||
lcd_logical_driver *driver;
|
||||
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
driver = (lcd_logical_driver *)LL_Get(list);
|
||||
if(driver)
|
||||
{
|
||||
lcd.framebuf = driver->framebuf;
|
||||
|
||||
if((int)driver->hbar > 0)
|
||||
driver->hbar(x,y,len);
|
||||
else if((int)driver->hbar == -1)
|
||||
{
|
||||
drv_base->hbar(x,y,len);
|
||||
}
|
||||
}
|
||||
} while(LL_Next(list) == 0);
|
||||
}
|
||||
|
||||
|
||||
void lcd_drv_icon(int which, char dest)
|
||||
{
|
||||
lcd_logical_driver *driver;
|
||||
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
driver = (lcd_logical_driver *)LL_Get(list);
|
||||
if(driver)
|
||||
{
|
||||
lcd.framebuf = driver->framebuf;
|
||||
|
||||
if((int)driver->icon > 0)
|
||||
driver->icon(which,dest);
|
||||
else if((int)driver->icon == -1)
|
||||
{
|
||||
drv_base->icon(which,dest);
|
||||
}
|
||||
}
|
||||
} while(LL_Next(list) == 0);
|
||||
}
|
||||
|
||||
|
||||
void lcd_drv_flush_box(int lft, int top, int rgt, int bot)
|
||||
{
|
||||
lcd_logical_driver *driver;
|
||||
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
driver = (lcd_logical_driver *)LL_Get(list);
|
||||
if(driver)
|
||||
{
|
||||
lcd.framebuf = driver->framebuf;
|
||||
|
||||
if((int)driver->flush_box > 0)
|
||||
driver->flush_box(lft,top,rgt,bot);
|
||||
else if((int)driver->flush_box == -1)
|
||||
{
|
||||
drv_base->flush_box(lft,top,rgt,bot);
|
||||
}
|
||||
}
|
||||
} while(LL_Next(list) == 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// TODO: Check whether lcd.draw_frame() should really take a framebuffer
|
||||
// TODO: as an argument, or if it should always use lcd.framebuf
|
||||
void lcd_drv_draw_frame(char *dat)
|
||||
{
|
||||
lcd_logical_driver *driver;
|
||||
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
driver = (lcd_logical_driver *)LL_Get(list);
|
||||
if(driver)
|
||||
{
|
||||
lcd.framebuf = driver->framebuf;
|
||||
|
||||
if((int)driver->draw_frame > 0)
|
||||
driver->draw_frame(dat);
|
||||
else if((int)driver->draw_frame == -1)
|
||||
{
|
||||
drv_base->draw_frame(dat);
|
||||
}
|
||||
}
|
||||
} while(LL_Next(list) == 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
char lcd_drv_getkey()
|
||||
{
|
||||
lcd_logical_driver *driver;
|
||||
|
||||
char key;
|
||||
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
driver = (lcd_logical_driver *)LL_Get(list);
|
||||
if(driver)
|
||||
{
|
||||
lcd.framebuf = driver->framebuf;
|
||||
|
||||
if((int)driver->getkey > 0)
|
||||
{
|
||||
key = driver->getkey();
|
||||
if(key) return key;
|
||||
}
|
||||
else if((int)driver->getkey == -1)
|
||||
{
|
||||
key = drv_base->getkey();
|
||||
if(key) return key;
|
||||
}
|
||||
}
|
||||
} while(LL_Next(list) == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
#ifndef LCD_H
|
||||
#define LCD_H
|
||||
|
||||
// Maximum supported sizes
|
||||
#define LCD_MAX_WID 256
|
||||
#define LCD_MAX_WIDTH 256
|
||||
#define LCD_MAX_HGT 256
|
||||
#define LCD_MAX_HEIGHT 256
|
||||
|
||||
|
||||
int lcd_init(char *args);
|
||||
int lcd_add_driver(char *driver, char *args);
|
||||
int lcd_shutdown();
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Driver functions / info held here...
|
||||
//
|
||||
// Feel free to override any/all functions here with real driver
|
||||
// functions...
|
||||
//
|
||||
typedef struct lcd_logical_driver
|
||||
{
|
||||
// Size in cells of the LCD
|
||||
int wid, hgt;
|
||||
// Size of each LCD cell, in pixels
|
||||
int cellwid, cellhgt;
|
||||
// Frame buffer...
|
||||
char *framebuf;
|
||||
|
||||
// Functions which might be the same for all drivers...
|
||||
void (*clear)();
|
||||
void (*string)(int x, int y, char lcd[]);
|
||||
|
||||
void (*chr)(int x, int y, char c);
|
||||
void (*vbar)(int x, int len);
|
||||
void (*hbar)(int x, int y, int len);
|
||||
void (*init_num)();
|
||||
void (*num)(int x, int num);
|
||||
|
||||
// Functions which should probably be implemented in each driver...
|
||||
int (*init)(struct lcd_logical_driver *driver, char *args);
|
||||
void (*close)();
|
||||
void (*flush)();
|
||||
void (*flush_box)(int lft, int top, int rgt, int bot);
|
||||
int (*contrast)(int contrast);
|
||||
void (*backlight)(int on);
|
||||
void (*output)(int on);
|
||||
void (*set_char)(int n, char *dat);
|
||||
void (*icon)(int which, char dest);
|
||||
void (*init_vbar)();
|
||||
void (*init_hbar)();
|
||||
void (*draw_frame)();
|
||||
|
||||
// Returns 0 for "no key pressed", or (A-Z).
|
||||
char (*getkey)();
|
||||
|
||||
// more?
|
||||
|
||||
} lcd_logical_driver;
|
||||
|
||||
typedef struct lcd_physical_driver
|
||||
{
|
||||
char *name;
|
||||
int (*init)(struct lcd_logical_driver *driver, char *device);
|
||||
} lcd_physical_driver;
|
||||
|
||||
|
||||
extern lcd_logical_driver lcd;
|
||||
|
||||
|
||||
int lcd_drv_init(lcd_logical_driver *driver, char *args);
|
||||
void lcd_drv_close();
|
||||
void lcd_drv_clear();
|
||||
void lcd_drv_flush();
|
||||
void lcd_drv_string(int x, int y, char string[]);
|
||||
void lcd_drv_chr(int x, int y, char c);
|
||||
int lcd_drv_contrast(int contrast);
|
||||
void lcd_drv_backlight(int on);
|
||||
void lcd_drv_output(int on);
|
||||
void lcd_drv_init_vbar();
|
||||
void lcd_drv_init_hbar();
|
||||
void lcd_drv_init_num();
|
||||
void lcd_drv_num(int x, int num);
|
||||
void lcd_drv_set_char(int n, char *dat);
|
||||
void lcd_drv_vbar(int x, int len);
|
||||
void lcd_drv_hbar(int x, int y, int len);
|
||||
void lcd_drv_icon(int which, char dest);
|
||||
void lcd_drv_flush_box(int lft, int top, int rgt, int bot);
|
||||
void lcd_drv_draw_frame();
|
||||
char lcd_drv_getkey();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
/* lcddriver.cd - test/demo of LIBIR's to interface with lcdproc (LCDd) */
|
||||
/* Copyright (C) 1999 David Glaude loosely based on workmanir.c */
|
||||
/* workmanir.c - test/demo of LIBIR's high level command functions */
|
||||
/* Copyright (C) 1998 Tom Wheeley, see file COPYING for details */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "irman.h"
|
||||
|
||||
char *progname = "lcddriver";
|
||||
|
||||
char *codes[] = {
|
||||
/* dummy */ NULL,
|
||||
/* KeyToLcd */ "lcdproc-A",
|
||||
/* KeyToLcd */ "lcdproc-B",
|
||||
/* KeyToLcd */ "lcdproc-C",
|
||||
/* KeyToLcd */ "lcdproc-D",
|
||||
/* KeyToLcd */ "lcdproc-E",
|
||||
/* KeyToLcd */ "lcdproc-F",
|
||||
/* KeyToLcd */ "lcdproc-G",
|
||||
/* KeyToLcd */ "lcdproc-H",
|
||||
/* KeyToLcd */ "lcdproc-I",
|
||||
/* KeyToLcd */ "lcdproc-J",
|
||||
/* KeyToLcd */ "lcdproc-K",
|
||||
/* KeyToLcd */ "lcdproc-L",
|
||||
/* KeyToLcd */ "lcdproc-M",
|
||||
/* KeyToLcd */ "lcdproc-N",
|
||||
/* KeyToLcd */ "lcdproc-O",
|
||||
/* KeyToLcd */ "lcdproc-P",
|
||||
/* KeyToLcd */ "lcdproc-Q",
|
||||
/* KeyToLcd */ "lcdproc-R",
|
||||
/* KeyToLcd */ "lcdproc-S",
|
||||
/* KeyToLcd */ "lcdproc-T",
|
||||
/* KeyToLcd */ "lcdproc-U",
|
||||
/* KeyToLcd */ "lcdproc-V",
|
||||
/* KeyToLcd */ "lcdproc-W",
|
||||
/* KeyToLcd */ "lcdproc-X",
|
||||
/* KeyToLcd */ "lcdproc-Y",
|
||||
/* KeyToLcd */ "lcdproc-Z",
|
||||
/* end */ NULL
|
||||
};
|
||||
|
||||
|
||||
//void sigterm(int sig)
|
||||
//{
|
||||
// ir_free_commands();
|
||||
// ir_finish();
|
||||
// raise(sig);
|
||||
//}
|
||||
|
||||
|
||||
// INIT $$$
|
||||
int INIT()
|
||||
{
|
||||
int i;
|
||||
char *filename;
|
||||
|
||||
if (ir_init_commands(NULL, 1) < 0) {
|
||||
fprintf(stderr, "error initialising commands: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
filename = ir_default_portname();
|
||||
filename = "option";
|
||||
}
|
||||
|
||||
for (i=1; codes[i] != NULL; i++) {
|
||||
if (ir_register_command(codes[i], i) < 0) {
|
||||
if (errno == ENOENT) {
|
||||
fprintf(stderr, "%s: no code set for `%s'\n", progname, codes[i]);
|
||||
} else {
|
||||
fprintf(stderr, "error registering `%s': `%s'\n", codes[i], strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
if (ir_init(filename) < 0) {
|
||||
fprintf(stderr, "%s: error initialising Irman: `%s'\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// KEY $$$
|
||||
int KEY(void)
|
||||
{
|
||||
int i;
|
||||
int cmd;
|
||||
char key;
|
||||
|
||||
key=(char)0;
|
||||
for(i=1;i;) {
|
||||
switch (cmd=ir_get_command()) {
|
||||
case IR_CMD_ERROR:
|
||||
fprintf(stderr, "%s: error reading command: %s\n", progname, strerror(errno));
|
||||
// No exit in LCDd !!!
|
||||
// exit(1);
|
||||
|
||||
case IR_CMD_UNKNOWN:
|
||||
fprintf(stderr,"IR unknown command\n");
|
||||
default: key='A'-1+cmd; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// CLOSE $$$
|
||||
int CLOSE()
|
||||
{
|
||||
ir_free_commands();
|
||||
ir_finish();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* end of lcddriver.c */
|
||||
@@ -0,0 +1,51 @@
|
||||
/*-----------------------------------------------------------------------------
|
||||
* port.h (by damianf@wpi.edu)
|
||||
* Low level I/O functions taken from led-stat.txt
|
||||
*
|
||||
* Jan 22 95
|
||||
*
|
||||
* DOS part (tested only with DOS version of GCC, DJGPP)
|
||||
* by M.Prinke <m.prinke@trashcan.mcnet.de> 3/97
|
||||
*/
|
||||
|
||||
/* #define DOS */
|
||||
|
||||
#ifndef PORT_H
|
||||
#define PORT_H
|
||||
#endif
|
||||
|
||||
#ifndef DOS
|
||||
static inline int port_in( int port )
|
||||
{
|
||||
unsigned char value;
|
||||
__asm__ volatile ("inb %1,%0"
|
||||
: "=a" (value)
|
||||
: "d" ((unsigned short)port));
|
||||
return value;
|
||||
}
|
||||
|
||||
static inline void port_out( unsigned short int port, unsigned char val )
|
||||
{
|
||||
__asm__ volatile (
|
||||
"outb %0,%1\n"
|
||||
:
|
||||
: "a" (val), "d" (port)
|
||||
);
|
||||
}
|
||||
#else
|
||||
#include <pc.h>
|
||||
|
||||
static inline int port_in( int port )
|
||||
{
|
||||
unsigned char value;
|
||||
value = inportb((unsigned short) port);
|
||||
return (int)value;
|
||||
}
|
||||
|
||||
static inline void port_out( unsigned int port, unsigned char val )
|
||||
{
|
||||
outportb((unsigned short) port, val);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**** END OF FILE ****/
|
||||
@@ -0,0 +1,236 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
#include "lcd.h"
|
||||
#include "text.h"
|
||||
#include "drv_base.h"
|
||||
|
||||
|
||||
lcd_logical_driver *text;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
////////////////////// For Text-Mode Output //////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int text_init(lcd_logical_driver *driver, char *args)
|
||||
{
|
||||
text = driver;
|
||||
|
||||
if(!driver->framebuf)
|
||||
{
|
||||
driver->close();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
driver->wid = 20;
|
||||
driver->hgt = 4;
|
||||
driver->cellwid = 5;
|
||||
driver->cellhgt = 8;
|
||||
|
||||
driver->clear = (void *)-1;
|
||||
driver->string = (void *)-1;
|
||||
driver->chr = (void *)-1;
|
||||
driver->vbar = text_vbar;
|
||||
driver->init_vbar = NULL;
|
||||
driver->hbar = text_hbar;
|
||||
driver->init_hbar = NULL;
|
||||
driver->num = (void *)-1;
|
||||
driver->init_num = NULL;
|
||||
|
||||
driver->init = text_init;
|
||||
driver->close = text_close;
|
||||
driver->flush = text_flush;
|
||||
driver->flush_box = NULL;
|
||||
driver->contrast = NULL;
|
||||
driver->backlight = NULL;
|
||||
driver->set_char = NULL;
|
||||
driver->icon = NULL;
|
||||
driver->draw_frame = text_draw_frame;
|
||||
|
||||
driver->getkey = NULL;
|
||||
|
||||
|
||||
return 200; // 200 is arbitrary. (must be 1 or more)
|
||||
}
|
||||
|
||||
void text_close()
|
||||
{
|
||||
drv_base_close();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Clears the LCD screen
|
||||
//
|
||||
void text_clear()
|
||||
{
|
||||
memset(lcd.framebuf, ' ', lcd.wid*lcd.hgt);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// Flushes all output to the lcd...
|
||||
//
|
||||
void text_flush()
|
||||
{
|
||||
text_draw_frame(lcd.framebuf);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Prints a string on the lcd display, at position (x,y). The
|
||||
// upper-left is (1,1), and the lower right should be (20,4).
|
||||
//
|
||||
void text_string(int x, int y, char string[])
|
||||
{
|
||||
int i;
|
||||
|
||||
x -= 1; // Convert 1-based coords to 0-based...
|
||||
y -= 1;
|
||||
|
||||
for(i=0; string[i]; i++)
|
||||
{
|
||||
lcd.framebuf[(y*lcd.wid) + x + i] = string[i];
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Prints a character on the lcd display, at position (x,y). The
|
||||
// upper-left is (1,1), and the lower right should be (20,4).
|
||||
//
|
||||
void text_chr(int x, int y, char c)
|
||||
{
|
||||
y--;
|
||||
x--;
|
||||
|
||||
lcd.framebuf[(y*lcd.wid) + x] = c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int text_contrast(int contrast)
|
||||
{
|
||||
// printf("Contrast: %i\n", contrast);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void text_backlight(int on)
|
||||
{
|
||||
/*
|
||||
if(on)
|
||||
{
|
||||
printf("Backlight ON\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Backlight OFF\n");
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void text_init_vbar()
|
||||
{
|
||||
// printf("Vertical bars.\n");
|
||||
}
|
||||
|
||||
void text_init_hbar()
|
||||
{
|
||||
// printf("Horizontal bars.\n");
|
||||
}
|
||||
|
||||
void text_init_num()
|
||||
{
|
||||
// printf("Big Numbers.\n");
|
||||
}
|
||||
|
||||
void text_num(int x, int num)
|
||||
{
|
||||
// printf("BigNum(%i, %i)\n", x, num);
|
||||
}
|
||||
|
||||
void text_set_char(int n, char *dat)
|
||||
{
|
||||
// printf("Set Character %i\n", n);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Draws a vertical bar; erases entire column onscreen.
|
||||
//
|
||||
void text_vbar(int x, int len)
|
||||
{
|
||||
int y;
|
||||
for(y=lcd.hgt; y > 0 && len>0; y--)
|
||||
{
|
||||
text_chr(x, y, '|');
|
||||
|
||||
len -= lcd.cellhgt;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Draws a horizontal bar to the right.
|
||||
//
|
||||
void text_hbar(int x, int y, int len)
|
||||
{
|
||||
for(; x<=lcd.wid && len>0; x++)
|
||||
{
|
||||
text_chr(x,y,'-');
|
||||
|
||||
len -= lcd.cellwid;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void text_flush_box(int lft, int top, int rgt, int bot)
|
||||
{
|
||||
text_flush();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void text_draw_frame(char *dat)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
char out[LCD_MAX_WIDTH];
|
||||
|
||||
if(!dat) return;
|
||||
|
||||
// printf("Frame (%ix%i): \n%s\n", lcd.wid, lcd.hgt, dat);
|
||||
|
||||
for(i=0; i<lcd.wid; i++)
|
||||
{
|
||||
out[i] = '-';
|
||||
}
|
||||
out[lcd.wid] = 0;
|
||||
printf("+%s+\n", out);
|
||||
|
||||
|
||||
for(i=0; i<lcd.hgt; i++)
|
||||
{
|
||||
for(j=0; j<lcd.wid; j++)
|
||||
{
|
||||
out[j] = dat[j+(i*lcd.wid)];
|
||||
}
|
||||
out[lcd.wid] = 0;
|
||||
printf("|%s|\n", out);
|
||||
|
||||
}
|
||||
|
||||
for(i=0; i<lcd.wid; i++)
|
||||
{
|
||||
out[i] = '-';
|
||||
}
|
||||
out[lcd.wid] = 0;
|
||||
printf("+%s+\n", out);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef LCD_TEXT_H
|
||||
#define LCD_TEXT_H
|
||||
|
||||
extern lcd_logical_driver *text;
|
||||
|
||||
int text_init(struct lcd_logical_driver *driver, char *args);
|
||||
void text_close();
|
||||
void text_clear();
|
||||
void text_flush();
|
||||
void text_string(int x, int y, char string[]);
|
||||
void text_chr(int x, int y, char c);
|
||||
int text_contrast(int contrast);
|
||||
void text_backlight(int on);
|
||||
void text_init_vbar();
|
||||
void text_init_hbar();
|
||||
void text_init_num();
|
||||
void text_vbar(int x, int len);
|
||||
void text_hbar(int x, int y, int len);
|
||||
void text_num(int x, int num);
|
||||
void text_set_char(int n, char *dat);
|
||||
void text_flush_box(int lft, int top, int rgt, int bot);
|
||||
void text_draw_frame(char *dat);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,562 @@
|
||||
/* wirz-sli.c -- Source file for LCDproc Wirz SLI driver
|
||||
Copyright (C) 1999 Horizon Technologies-http://horizon.pair.com/
|
||||
Written by Bryan Rittmeyer <bryanr@pair.com> - Released under GPL
|
||||
|
||||
LCD info: http://www.wirz.com/sli/ */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "lcd.h"
|
||||
#include "wirz-sli.h"
|
||||
#include "drv_base.h"
|
||||
|
||||
#include "../../shared/debug.h"
|
||||
#include "../../shared/str.h"
|
||||
|
||||
static int custom=0;
|
||||
typedef enum {
|
||||
hbar = 1,
|
||||
vbar = 2,
|
||||
bign = 4,
|
||||
beat = 8 } custom_type;
|
||||
|
||||
static int fd;
|
||||
static char lastframe[32];
|
||||
|
||||
lcd_logical_driver *sli;
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Opens com port and sets baud correctly...
|
||||
//
|
||||
int sli_init(lcd_logical_driver *driver, char *args)
|
||||
{
|
||||
char *argv[64];
|
||||
int argc;
|
||||
struct termios portset;
|
||||
int i;
|
||||
int tmp;
|
||||
char out[2];
|
||||
|
||||
char device[256] = "/dev/lcd";
|
||||
int speed=B19200;
|
||||
|
||||
sli = driver;
|
||||
|
||||
//debug("sli_init: Args(all): %s\n", args);
|
||||
|
||||
argc = get_args(argv, args, 64);
|
||||
|
||||
/*
|
||||
for(i=0; i<argc; i++)
|
||||
{
|
||||
printf("Arg(%i): %s\n", i, argv[i]);
|
||||
}
|
||||
*/
|
||||
|
||||
for(i=0; i<argc; i++)
|
||||
{
|
||||
//printf("Arg(%i): %s\n", i, argv[i]);
|
||||
if(0 == strcmp(argv[i], "-d") ||
|
||||
0 == strcmp(argv[i], "--device"))
|
||||
{
|
||||
if(i + 1 > argc) {
|
||||
fprintf(stderr, "sli_init: %s requires an argument\n",
|
||||
argv[i]);
|
||||
return -1;
|
||||
}
|
||||
strcpy(device, argv[++i]);
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-s") ||
|
||||
0 == strcmp(argv[i], "--speed"))
|
||||
{
|
||||
if(i + 1 > argc) {
|
||||
fprintf(stderr, "sli_init: %s requires an argument\n",
|
||||
argv[i]);
|
||||
return -1;
|
||||
}
|
||||
tmp = atoi(argv[++i]);
|
||||
if(tmp==1200) speed=B1200;
|
||||
else if(tmp==2400) speed=B2400;
|
||||
else if(tmp==9600) speed=B9600;
|
||||
else if(tmp==19200) speed=B19200;
|
||||
else if(tmp==38400) speed=B38400;
|
||||
else if(tmp==57600) speed=B57600;
|
||||
else if(tmp==115200) speed=B115200;
|
||||
else {
|
||||
fprintf(stderr, "sli_init: %s argument must be 1200, 2400, 9600, 19200, 38400, 57600, or 115200. Using default value (19200).\n",
|
||||
argv[i]);
|
||||
}
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-h") ||
|
||||
0 == strcmp(argv[i], "--help"))
|
||||
{
|
||||
printf("LCDproc Wirz SLI LCD driver\n"
|
||||
"\t-d\t--device\tSelect the output device to use [/dev/lcd]\n"
|
||||
"\t-s\t--speed\t\tSet the communication speed [19200]\n"
|
||||
"\t-h\t--help\t\tShow this help information\n");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Invalid parameter: %s\n", argv[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Set up io port correctly, and open it...
|
||||
fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
if (fd == -1)
|
||||
{
|
||||
fprintf(stderr, "sli_init: failed (%s)\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
//else fprintf(stderr, "sli_init: opened device %s\n", device);
|
||||
tcgetattr(fd, &portset);
|
||||
// This is necessary in Linux, but does not exist in irix.
|
||||
#ifndef IRIX
|
||||
cfmakeraw(&portset);
|
||||
#endif
|
||||
cfsetospeed(&portset, speed);
|
||||
tcsetattr(fd, TCSANOW, &portset);
|
||||
|
||||
/* Initialize SLI using autobaud detection, and then turn off cursor
|
||||
and clear screen */
|
||||
usleep(150000); /* 150ms delay to allow SLI to power on */
|
||||
out[0]=13; /* CR for SLI autobaud */
|
||||
write(fd, out, 1);
|
||||
usleep(3000); /* 3ms delay.. wait for it to autobaud */
|
||||
out[0]=0x0FE;
|
||||
out[1]=0x00C; /* No cursor */
|
||||
write(fd, out, 2);
|
||||
out[0]=0x0FE;
|
||||
out[1]=0x001; /* Clear LCD, not sure if this belongs here */
|
||||
write(fd, out, 2);
|
||||
|
||||
|
||||
if(!driver->framebuf)
|
||||
{
|
||||
fprintf(stderr, "sli_init: No frame buffer.\n");
|
||||
driver->close();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set LCD parameters (I use a 16x2 LCD) -- small but still useful
|
||||
// Its also much cheaper than the higher quality Matrix Orbital modules
|
||||
// Currently, $30 for interface kit and 16x2 non-backlit LCD...
|
||||
driver->wid = 15;
|
||||
driver->hgt = 2;
|
||||
|
||||
|
||||
// Set the functions the driver supports...
|
||||
|
||||
driver->clear = (void *)-1;
|
||||
driver->string = (void *)-1;
|
||||
driver->chr = (void *)-1;
|
||||
driver->vbar = sli_vbar;
|
||||
driver->init_vbar = sli_init_vbar;
|
||||
driver->hbar = sli_hbar;
|
||||
driver->init_hbar = sli_init_hbar;
|
||||
driver->num = (void *)-1;
|
||||
driver->init_num = (void *)-1;
|
||||
|
||||
driver->init = sli_init;
|
||||
driver->close = sli_close;
|
||||
driver->flush = sli_flush;
|
||||
driver->flush_box = sli_flush_box;
|
||||
driver->contrast = (void *)-1;
|
||||
driver->backlight = (void *)-1;
|
||||
driver->set_char = sli_set_char;
|
||||
driver->icon = sli_icon;
|
||||
driver->draw_frame = sli_draw_frame;
|
||||
|
||||
driver->getkey = (void *)-1;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
/* Clean-up */
|
||||
void sli_close()
|
||||
{
|
||||
close(fd);
|
||||
|
||||
if(sli->framebuf) free(sli->framebuf);
|
||||
|
||||
sli->framebuf = NULL;
|
||||
}
|
||||
|
||||
|
||||
void sli_flush()
|
||||
{
|
||||
sli_draw_frame(lcd.framebuf);
|
||||
}
|
||||
|
||||
|
||||
/* no bounds checking is done in MtxOrb.c (which I shamelessly ripped)
|
||||
this is bad imho, so I added it.. may remove later
|
||||
speed is not a huge issue though, this isnt a
|
||||
device driver or anything ;) */
|
||||
void sli_flush_box(int lft, int top, int rgt, int bot)
|
||||
{
|
||||
int y;
|
||||
char out[2]; /* Why does the matrix driver allocate so much here? */
|
||||
|
||||
/* simple bounds checking */
|
||||
if((top>lcd.hgt)|(bot>lcd.hgt))
|
||||
return;
|
||||
|
||||
if((lft>lcd.wid)|(rgt>lcd.wid))
|
||||
return;
|
||||
|
||||
// printf("Flush (%i,%i)-(%i,%i)\n", lft, top, rgt, bot);
|
||||
|
||||
/* I like having hex, everywhere and all the time */
|
||||
for(y=top; y<=bot; y++)
|
||||
{
|
||||
if(y==1)
|
||||
sprintf(out, "%c%c", 0x0FE, 0x080+lft);
|
||||
if(y==2)
|
||||
sprintf(out, "%c%c", 0x0FE, 0x0C0+lft);
|
||||
write(fd, out, 0x002);
|
||||
write(fd, lcd.framebuf+(y*lcd.wid)+lft, rgt-lft+1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Prints a character on the lcd display, at position (x,y). The
|
||||
// upper-left is (1,1), and the lower right should be (20,4).
|
||||
//
|
||||
void sli_chr(int x, int y, char c)
|
||||
{
|
||||
y--;
|
||||
x--;
|
||||
|
||||
lcd.framebuf[(y*lcd.wid) + x] = c;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Sets up for vertical bars. Call before lcd.vbar()
|
||||
//
|
||||
|
||||
/* Because of the way we do this (custom characters in CGRAM)
|
||||
we can't have both horizontal and vertical bars at once...
|
||||
this also appears to be a limitation of the Matrix Orbital
|
||||
modules so I will assume that all client coders know about it
|
||||
|
||||
I think it would be cool to use triangular stuff for the non-full
|
||||
characters, so that you can do both bar types at once.. maybe I
|
||||
will release a new version of the SLI driver that attempts this */
|
||||
|
||||
void sli_init_vbar()
|
||||
{
|
||||
char a[] = {
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
1,1,1,1,1,
|
||||
};
|
||||
char b[] = {
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
};
|
||||
char c[] = {
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
};
|
||||
char d[] = {
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
};
|
||||
char e[] = {
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
};
|
||||
char f[] = {
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
};
|
||||
char g[] = {
|
||||
0,0,0,0,0,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
};
|
||||
|
||||
if(custom!=vbar) {
|
||||
sli_set_char(1,a);
|
||||
sli_set_char(2,b);
|
||||
sli_set_char(3,c);
|
||||
sli_set_char(4,d);
|
||||
sli_set_char(5,e);
|
||||
sli_set_char(6,f);
|
||||
sli_set_char(7,g);
|
||||
custom=vbar;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Inits horizontal bars...
|
||||
//
|
||||
void sli_init_hbar()
|
||||
{
|
||||
|
||||
char a[] = {
|
||||
1,0,0,0,0,
|
||||
1,0,0,0,0,
|
||||
1,0,0,0,0,
|
||||
1,0,0,0,0,
|
||||
1,0,0,0,0,
|
||||
1,0,0,0,0,
|
||||
1,0,0,0,0,
|
||||
1,0,0,0,0,
|
||||
};
|
||||
char b[] = {
|
||||
1,1,0,0,0,
|
||||
1,1,0,0,0,
|
||||
1,1,0,0,0,
|
||||
1,1,0,0,0,
|
||||
1,1,0,0,0,
|
||||
1,1,0,0,0,
|
||||
1,1,0,0,0,
|
||||
1,1,0,0,0,
|
||||
};
|
||||
char c[] = {
|
||||
1,1,1,0,0,
|
||||
1,1,1,0,0,
|
||||
1,1,1,0,0,
|
||||
1,1,1,0,0,
|
||||
1,1,1,0,0,
|
||||
1,1,1,0,0,
|
||||
1,1,1,0,0,
|
||||
1,1,1,0,0,
|
||||
};
|
||||
char d[] = {
|
||||
1,1,1,1,0,
|
||||
1,1,1,1,0,
|
||||
1,1,1,1,0,
|
||||
1,1,1,1,0,
|
||||
1,1,1,1,0,
|
||||
1,1,1,1,0,
|
||||
1,1,1,1,0,
|
||||
1,1,1,1,0,
|
||||
};
|
||||
|
||||
if(custom!=hbar) {
|
||||
sli_set_char(1,a);
|
||||
sli_set_char(2,b);
|
||||
sli_set_char(3,c);
|
||||
sli_set_char(4,d);
|
||||
custom=hbar;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Draws a vertical bar...
|
||||
//
|
||||
|
||||
/* It would be cool if you could start a vertical bar at any y
|
||||
like the horizontal bar routine can start at any x... but
|
||||
since we only have 2 lines anyway this is rather pointless
|
||||
for me to add */
|
||||
|
||||
void sli_vbar(int x, int len)
|
||||
{
|
||||
char map[9] = {32, 1, 2, 3, 4, 5, 6, 7, 255 };
|
||||
|
||||
|
||||
int y;
|
||||
for(y=lcd.hgt; y > 0 && len>0; y--)
|
||||
{
|
||||
if(len >= lcd.cellhgt) sli_chr(x, y, 255);
|
||||
else sli_chr(x, y, map[len]);
|
||||
|
||||
len -= lcd.cellhgt;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Draws a horizontal bar to the right.
|
||||
//
|
||||
void sli_hbar(int x, int y, int len)
|
||||
{
|
||||
char map[6] = { 32, 1, 2, 3, 4, 255 };
|
||||
|
||||
for(; x<=lcd.wid && len>0; x++)
|
||||
{
|
||||
if(len >= lcd.cellwid) sli_chr(x,y,255);
|
||||
else sli_chr(x, y, map[len]);
|
||||
|
||||
len -= lcd.cellwid;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Sets a custom character from 0-7...
|
||||
//
|
||||
// For input, values > 0 mean "on" and values <= 0 are "off".
|
||||
//
|
||||
// The input is just an array of characters...
|
||||
//
|
||||
void sli_set_char(int n, char *dat)
|
||||
{
|
||||
char out[2];
|
||||
int row, col;
|
||||
int letter;
|
||||
|
||||
/* SLI also has 8 user definable characters */
|
||||
if(n < 0 || n > 7) return;
|
||||
if(!dat) return;
|
||||
|
||||
/* Move cursor to CGRAM */
|
||||
out[0]=0x0FE;
|
||||
out[1]=0x040+8*n;
|
||||
write(fd, out, 2);
|
||||
|
||||
for(row=0; row<lcd.cellhgt; row++)
|
||||
{
|
||||
letter = 0;
|
||||
for(col=0; col<lcd.cellwid; col++)
|
||||
{
|
||||
letter <<= 1;
|
||||
letter |= (dat[(row*lcd.cellwid) + col] > 0);
|
||||
}
|
||||
letter|=0x020; /* SLI can't accept CR, LF, etc in this character! */
|
||||
write(fd, &letter, 1);
|
||||
}
|
||||
|
||||
/* Move cursor back to DDRAM */
|
||||
out[0]=0x0FE;
|
||||
out[1]=0x080;
|
||||
write(fd, out, 2);
|
||||
}
|
||||
|
||||
|
||||
void sli_icon(int which, char dest)
|
||||
{
|
||||
char icons[3][5*8] = {
|
||||
{
|
||||
1,1,1,1,1, // Empty Heart
|
||||
1,0,1,0,1,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
1,0,0,0,1,
|
||||
1,1,0,1,1,
|
||||
1,1,1,1,1,
|
||||
},
|
||||
|
||||
{
|
||||
1,1,1,1,1, // Filled Heart
|
||||
1,0,1,0,1,
|
||||
0,1,0,1,0,
|
||||
0,1,1,1,0,
|
||||
0,1,1,1,0,
|
||||
1,0,1,0,1,
|
||||
1,1,0,1,1,
|
||||
1,1,1,1,1,
|
||||
},
|
||||
|
||||
{
|
||||
0,0,0,0,0, // Ellipsis
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
0,0,0,0,0,
|
||||
1,0,1,0,1,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
if(custom==bign) custom=beat;
|
||||
sli_set_char(dest, &icons[which][0]);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Blasts a single frame onscreen, to the lcd...
|
||||
//
|
||||
// Input is a character array, sized lcd.wid*lcd.hgt
|
||||
//
|
||||
void sli_draw_frame(char *dat)
|
||||
{
|
||||
char out[2]; /* Again, why does the Matrix driver allocate so much here? */
|
||||
int y;
|
||||
|
||||
if(!dat) return;
|
||||
|
||||
/*
|
||||
out[0]=0x0FE;
|
||||
out[1]=0x001;
|
||||
write(fd, out, 2);
|
||||
*/
|
||||
|
||||
/* Don't update if we have no new data
|
||||
this keeps me from getting a migraine
|
||||
(just like those copyleft penguin mints... mmmmmm) */
|
||||
|
||||
// if (!strncmp(dat,lastframe,32)) /* Nothing has changed */
|
||||
// return;
|
||||
|
||||
/* Do the actual refresh */
|
||||
out[0]=0x0FE;
|
||||
out[1]=0x080;
|
||||
write(fd, out, 2);
|
||||
write(fd, &dat[0], 16);
|
||||
usleep(10);
|
||||
write(fd, &dat[16],15);
|
||||
|
||||
// strncpy(lastframe,dat,32); // Update lastframe...
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/* wirz-sli.h -- Header file for LCDproc Wirz SLI driver
|
||||
Copyright (C) 1999 Horizon Technologies-http://horizon.pair.com/
|
||||
Written by Bryan Rittmeyer <bryanr@pair.com> - Released under GPL
|
||||
|
||||
LCD info: http://www.wirz.com/sli/ */
|
||||
|
||||
#ifndef SLI_H
|
||||
#define SLI_H
|
||||
|
||||
|
||||
extern lcd_logical_driver *sli;
|
||||
|
||||
int sli_init(lcd_logical_driver *driver, char *device);
|
||||
void sli_close();
|
||||
void sli_flush();
|
||||
void sli_flush_box(int lft, int top, int rgt, int bot);
|
||||
void sli_chr(int x, int y, char c) ;
|
||||
int sli_contrast(int contrast);
|
||||
void sli_backlight(int on);
|
||||
void sli_init_vbar();
|
||||
void sli_init_hbar();
|
||||
void sli_vbar(int x, int len);
|
||||
void sli_hbar(int x, int y, int len);
|
||||
void sli_init_num();
|
||||
void sli_num(int x, int num);
|
||||
void sli_set_char(int n, char *dat);
|
||||
void sli_icon(int which, char dest);
|
||||
void sli_draw_frame(char *dat);
|
||||
char sli_getkey();
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
|
||||
input.c
|
||||
|
||||
Handles keypad (and other?) input from the user.
|
||||
|
||||
Currently, the keys are as follows:
|
||||
|
||||
Context Key Function
|
||||
------- --- --------
|
||||
Normal "normal" context is handled in this source file.
|
||||
A Pause/Continue
|
||||
B Back(Go to previous screen)
|
||||
C Forward(Go to next screen)
|
||||
D Open main menu
|
||||
E-Z Sent to client, if any; ignored otherwise
|
||||
|
||||
(menu keys are not handled here, but in the menu code)
|
||||
Menu
|
||||
A Enter/select
|
||||
B Up/Left
|
||||
C Down/Right
|
||||
D Exit/Cancel
|
||||
E-Z Ignored
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../shared/sockets.h"
|
||||
#include "../shared/debug.h"
|
||||
|
||||
#include "drivers/lcd.h"
|
||||
|
||||
#include "client_data.h"
|
||||
#include "clients.h"
|
||||
#include "screen.h"
|
||||
#include "screenlist.h"
|
||||
#include "menus.h"
|
||||
|
||||
#include "input.h"
|
||||
|
||||
|
||||
int server_input(int key);
|
||||
|
||||
// FIXME! The server tends to crash when "E" is pressed.. (?!)
|
||||
// (but only when the joystick driver is the last one on the list...)
|
||||
|
||||
// Checks for keypad input, and dispatches it
|
||||
int handle_input()
|
||||
{
|
||||
char str[256];
|
||||
int key;
|
||||
screen *s;
|
||||
client *c;
|
||||
|
||||
key = lcd.getkey();
|
||||
|
||||
if (!key) return 0;
|
||||
|
||||
debug("handle_input(%c)\n", (char)key);
|
||||
|
||||
if(key)
|
||||
{
|
||||
s = screenlist_current();
|
||||
if(s)
|
||||
{
|
||||
c = s->parent;
|
||||
if(c)
|
||||
{
|
||||
// TODO: Interpret and translate keys!
|
||||
// If the client should have this keypress...
|
||||
// Send keypress to client
|
||||
if(key >= 'E' && key <= 'Z')
|
||||
{
|
||||
// TODO: Implement client "acceptable key" lists
|
||||
sprintf(str, "key %c\n", key);
|
||||
sock_send_string(c->sock, str);
|
||||
}
|
||||
// Otherwise, tell the server about it.
|
||||
else
|
||||
{
|
||||
server_input(key);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If no parent, it means we're on the server screen.
|
||||
// so, the server gets all keypresses there.
|
||||
server_input(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int server_input(int key)
|
||||
{
|
||||
debug("server_input(%c)\n", (char)key);
|
||||
|
||||
switch(key)
|
||||
{
|
||||
case 'A':
|
||||
if(screenlist_action == SCR_HOLD)
|
||||
screenlist_action = 0;
|
||||
else
|
||||
screenlist_action = SCR_HOLD;
|
||||
break;
|
||||
case 'B':
|
||||
screenlist_action = SCR_BACK;
|
||||
screenlist_prev();
|
||||
break;
|
||||
case 'C':
|
||||
screenlist_action = SCR_SKIP;
|
||||
screenlist_next();
|
||||
break;
|
||||
case 'D':
|
||||
debug("got the menu key!\n");
|
||||
server_menu();
|
||||
break;
|
||||
default:
|
||||
debug("server_input: Invalid key \"%c\" (%i)\n",
|
||||
(char)key, key);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef INPUT_H
|
||||
#define INPUT_H
|
||||
|
||||
|
||||
// Accepts and uses keypad input while displaying screens...
|
||||
int handle_input();
|
||||
|
||||
|
||||
#endif
|
||||
+369
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
main.c for LCDd
|
||||
|
||||
Contains main(), plus signal callback functions and a help screen.
|
||||
|
||||
Program init, command-line handling, and the main loop are
|
||||
implemented here. Also, minimal data about the program such as
|
||||
the revision number.
|
||||
|
||||
Some of this stuff should probably be move elsewhere eventually,
|
||||
such as command-line handling and the main loop. main() is supposed
|
||||
to be "dumb".
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../shared/debug.h"
|
||||
|
||||
#include "drivers/lcd.h"
|
||||
#include "sock.h"
|
||||
#include "clients.h"
|
||||
#include "screenlist.h"
|
||||
#include "screen.h"
|
||||
#include "parse.h"
|
||||
#include "render.h"
|
||||
#include "serverscreens.h"
|
||||
#include "input.h"
|
||||
#include "main.h"
|
||||
|
||||
|
||||
char *version = VERSION;
|
||||
char *build_date = __DATE__;
|
||||
|
||||
|
||||
/* no longer needed
|
||||
static screen_size sizes[] =
|
||||
{
|
||||
{"16x2", 16, 2},
|
||||
{"16x4", 16, 4},
|
||||
{"20x2", 20, 2},
|
||||
{"20x4", 20, 4},
|
||||
{"40x2", 40, 2},
|
||||
{"40x4", 40, 4},
|
||||
{NULL , 0, 0},
|
||||
};
|
||||
*/
|
||||
|
||||
// This is currently only a list of available arguments, but doesn't
|
||||
// really *do* anything. It just helps to figure out which parameters
|
||||
// go to the server, and which ones go to individual drivers...
|
||||
static parameter args[] =
|
||||
{
|
||||
{"-h", "--help"},
|
||||
{"-d", "--driver"},
|
||||
{"-t", "--type"},
|
||||
{"-f", "--foreground"},
|
||||
{"-b", "--backlight"},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
|
||||
void exit_program(int val);
|
||||
void HelpScreen();
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// TODO: Use a config file!
|
||||
//char cfgfile[256] = "/etc/LCDd.cf";
|
||||
int i, err, tmp;
|
||||
int daemon_mode=1;
|
||||
int disable_server_screen=0;
|
||||
int child;
|
||||
screen *s = NULL;
|
||||
char *str, *ing; // strings for commandline handling
|
||||
// screen_size *size = &sizes[0]; // No longer needed
|
||||
|
||||
|
||||
|
||||
// Ctrl-C will cause a clean exit...
|
||||
signal(SIGINT, exit_program);
|
||||
// and "kill"...
|
||||
signal(SIGTERM, exit_program);
|
||||
// and "kill -HUP" (hangup)...
|
||||
signal(SIGHUP, exit_program);
|
||||
// and just in case, "kill -KILL" (which cannot be trapped; but oh well)
|
||||
signal(SIGKILL, exit_program);
|
||||
|
||||
|
||||
|
||||
// If no paramaters given, give the help screen.
|
||||
if(argc == 1) HelpScreen();
|
||||
|
||||
// Don't spawn a child if we're using the curses driver
|
||||
for(i=1; i<argc; i++)
|
||||
{
|
||||
if(0 == strcmp(argv[i], "-f") ||
|
||||
0 == strcmp(argv[i], "--foreground") ||
|
||||
0 == strcmp(argv[i], "curses"))
|
||||
daemon_mode = 0;
|
||||
}
|
||||
|
||||
// Now, go into daemon mode...
|
||||
#ifndef DEBUG
|
||||
if(daemon_mode)
|
||||
{
|
||||
if ((child = fork()) != 0)
|
||||
{
|
||||
usleep(1500000); // Wait for child to initialize
|
||||
exit(0); /* PARENT EXITS */
|
||||
}
|
||||
// This line removed because it eats error messages...
|
||||
//setsid(); /* RELEASE TTY */
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// Set up lcd driver base system
|
||||
lcd_init("");
|
||||
|
||||
|
||||
// Parse the command line now...
|
||||
// TODO: Move this to a separate function?
|
||||
for(i=1; i<argc; i++)
|
||||
{
|
||||
if(0 == strcmp(argv[i], "-d") ||
|
||||
0 == strcmp(argv[i], "--driver"))
|
||||
{
|
||||
if(argc <= i+1) HelpScreen();
|
||||
str = argv[++i];
|
||||
ing = NULL;
|
||||
|
||||
// Check to see if the next parameter is intended for LCDd,
|
||||
// or if it should be passed to the driver...
|
||||
if(argc > i+1)
|
||||
{
|
||||
int j, skip=0;
|
||||
for(j=1; args[j].lg; j++) // check each option except "help"
|
||||
if(! strcmp(argv[i+1], args[j].sh) ||
|
||||
! strcmp(argv[i+1], args[j].lg)) skip=1;
|
||||
|
||||
if(! skip)
|
||||
{
|
||||
ing = argv[++i];
|
||||
}
|
||||
//else i++;
|
||||
}
|
||||
err = lcd_add_driver(str, ing);
|
||||
if(err <= 0)
|
||||
{
|
||||
printf("Error loading driver %s. Continuing anyway...\n",
|
||||
str);
|
||||
}
|
||||
if((err > 0) && (0 == strcmp(str, "curses"))) daemon_mode=0;
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-h") ||
|
||||
0 == strcmp(argv[i], "--help"))
|
||||
{
|
||||
HelpScreen();
|
||||
}
|
||||
// Redundant, but it prevents errors...
|
||||
else if(0 == strcmp(argv[i], "-f") ||
|
||||
0 == strcmp(argv[i], "--foreground"))
|
||||
{
|
||||
daemon_mode = 0;
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-b") ||
|
||||
0 == strcmp(argv[i], "--backlight"))
|
||||
{
|
||||
if(argc <= i+1) HelpScreen();
|
||||
str = argv[++i];
|
||||
if(0 == strcmp(str, "off"))
|
||||
backlight_state = backlight = BACKLIGHT_OFF;
|
||||
else if(0 == strcmp(str, "on"))
|
||||
backlight_state = backlight = BACKLIGHT_ON;
|
||||
else if(0 == strcmp(str, "open"))
|
||||
backlight = BACKLIGHT_OPEN;
|
||||
else HelpScreen();
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-t") ||
|
||||
0 == strcmp(argv[i], "--type"))
|
||||
{
|
||||
if(i + 1 > argc)
|
||||
HelpScreen();
|
||||
else
|
||||
{
|
||||
int wid, hgt;
|
||||
|
||||
i++;
|
||||
sscanf(argv[i], "%ix%i", &wid, &hgt);
|
||||
if(wid>80 || wid<16 || hgt>25 || hgt<2)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"LCDd: Invalid lcd size \"%s\". Using 20x4.\n",
|
||||
argv[i]);
|
||||
lcd.wid = 20;
|
||||
lcd.hgt = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
lcd.wid = wid;
|
||||
lcd.hgt = hgt;
|
||||
}
|
||||
|
||||
/* no longer needed
|
||||
int j=0, valid=0;
|
||||
i++;
|
||||
for(j=0; sizes[j].size; j++)
|
||||
{
|
||||
if(0 == strcmp(sizes[j].size, argv[i]))
|
||||
{
|
||||
valid = 1;
|
||||
size = &sizes[j];
|
||||
lcd.wid = size->wid;
|
||||
lcd.hgt = size->hgt;
|
||||
}
|
||||
}
|
||||
if(!valid)
|
||||
{
|
||||
fprintf(stderr, "LCDd: Invalid lcd size \"%s\". Using 20x4.\n", argv[i]);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-i") ||
|
||||
0 == strcmp(argv[i], "--serverinfo"))
|
||||
{
|
||||
if(i + 1 > argc)
|
||||
HelpScreen();
|
||||
else
|
||||
{
|
||||
i++;
|
||||
if(0 == strcmp(argv[i], "off")) disable_server_screen = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise... Get help!
|
||||
printf("Invalid parameter: %s\n", argv[i]);
|
||||
HelpScreen();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Now init a bunch of required stuff...
|
||||
|
||||
if(sock_create_server() <= 0)
|
||||
{
|
||||
printf("Error opening socket.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(client_init() < 0)
|
||||
{
|
||||
printf("Error initializing client list\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(screenlist_init() < 0)
|
||||
{
|
||||
printf("Error initializing screen list\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Make sure the server screen shows up every once in a while..
|
||||
if(server_screen_init() < 0)
|
||||
{
|
||||
printf("Error initializing server screens\n");
|
||||
return 1;
|
||||
}
|
||||
else if(disable_server_screen)
|
||||
{
|
||||
server_screen->priority = 256;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Main loop...
|
||||
while(1)
|
||||
{
|
||||
sock_poll_clients();
|
||||
parse_all_client_messages();
|
||||
handle_input();
|
||||
|
||||
// TODO: Move this code to screenlist.c...
|
||||
// ... it should just say "handle_screens();"
|
||||
// Timer gets reset by screenlist_next()
|
||||
timer++;
|
||||
// this line's here because s was getting overwritten at one time...
|
||||
//s = screenlist_current();
|
||||
if(s && (timer >= s->duration))
|
||||
{
|
||||
screenlist_next();
|
||||
}
|
||||
// Just in case it gets out of hand...
|
||||
if(timer >= 0x10000) timer = 0;
|
||||
update_server_screen(timer);
|
||||
s = screenlist_current();
|
||||
|
||||
// render something here...
|
||||
if(s) draw_screen(s, timer);
|
||||
else no_screen_screen(timer);
|
||||
|
||||
usleep(TIME_UNIT);
|
||||
}
|
||||
|
||||
|
||||
// Quit!
|
||||
exit_program(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void exit_program(int val)
|
||||
{
|
||||
// TODO: These things shouldn't be so interdependent. The order
|
||||
// things are shut down in shouldn't matter...
|
||||
|
||||
// Say goodbye!
|
||||
goodbye_screen();
|
||||
// Can go anywhere...
|
||||
lcd_shutdown();
|
||||
|
||||
// Must come before screenlist_shutdown
|
||||
client_shutdown();
|
||||
// Must come after client_shutdown
|
||||
screenlist_shutdown();
|
||||
// Should come after client_shutdown
|
||||
sock_close_all();
|
||||
|
||||
exit(0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void HelpScreen()
|
||||
{
|
||||
printf("LCDproc server daemon, %s\n", version);
|
||||
printf("Copyright (c) 1999 Scott Scriven, William Ferrell, and misc contributors\n");
|
||||
printf("This program is freely redistributable under the terms of the GNU Public License\n\n");
|
||||
printf("Usage: lcdproc [options]\n");
|
||||
printf("\tOptions in []'s are optional. Available options are:\n");
|
||||
printf("\t-h\t--help\n\t\t\tDisplay this help screen\n");
|
||||
printf("\t-t\t--type <size>\n\t\t\tSelect an LCD size (20x4, 16x2, etc...)\n");
|
||||
printf("\t-d\t--driver <driver> [args]\n\t\t\tAdd a driver to use:\n");
|
||||
printf("\t\t\tCFontz, curses, HD44780, irmanin, joy,\n\t\t\tMtxOrb, text\n");
|
||||
printf("\t\t\t(args will be passed to the driver for init)\n");
|
||||
printf("\t-f\t--foreground\n\t\t\tRun in the foreground (no daemon)\n");
|
||||
printf("\t-b\t--backlight <mode>\n\t\t\tSet backlight mode (on, off, open)\n");
|
||||
printf("\t-i\t--serverinfo off\n\t\t\tSet the server screen to low priority\n");
|
||||
printf("\n");
|
||||
printf("\tUse \"man LCDd\" for more info.\n");
|
||||
printf("\tHelp on each driver's parameters are obtained upon request:\n\t\t\"LCDd -d driver --help\"\n");
|
||||
printf("Example:\n");
|
||||
printf("\tLCDd -d MtxOrb \"--device /dev/lcd --contrast 200\" -d joy\n");
|
||||
printf("\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
/*
|
||||
contains a few things that other parts of the program might want
|
||||
to know about...
|
||||
*/
|
||||
|
||||
extern char *version;
|
||||
extern char *build_date;
|
||||
|
||||
void exit_program(int val);
|
||||
|
||||
// 1/8th second is a single time unit...
|
||||
#define TIME_UNIT 125000
|
||||
// But I plan to double the framerate soon, or make it variable...
|
||||
//#define TIME_UNIT (125000/2)
|
||||
|
||||
typedef struct screen_size
|
||||
{
|
||||
char * size;
|
||||
int wid, hgt;
|
||||
} screen_size;
|
||||
|
||||
typedef struct parameter
|
||||
{
|
||||
char * sh, * lg; // short and long versions
|
||||
} parameter;
|
||||
|
||||
|
||||
#endif
|
||||
+355
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
menu.c
|
||||
|
||||
Handles server-supplied menus defined by a table. Read menu.h for
|
||||
more information.
|
||||
|
||||
Menus are similar to "pull-down" menus, but have some extra features.
|
||||
They can contain "normal" menu items, checkboxes, sliders, "movers",
|
||||
etc..
|
||||
|
||||
I should probably find a more elegant way of doing this in order
|
||||
to handle dynamically-changing menus such as the client list. Tcl/Tk
|
||||
has neat ways to do it. Hmm...
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "parse.h"
|
||||
#include "sock.h"
|
||||
#include "render.h"
|
||||
#include "main.h"
|
||||
|
||||
#include "drivers/lcd.h"
|
||||
#include "menu.h"
|
||||
|
||||
// FIXME: Implement this where it is supposed to be...
|
||||
#include <time.h>
|
||||
void framedelay()
|
||||
{
|
||||
sock_poll_clients();
|
||||
parse_all_client_messages();
|
||||
|
||||
usleep(TIME_UNIT);
|
||||
}
|
||||
|
||||
static void draw_heartbeat()
|
||||
{
|
||||
static int timer = 0;
|
||||
|
||||
if(heartbeat)
|
||||
{
|
||||
// Set this to pulsate like a real heart beat...
|
||||
// (binary is fun... :)
|
||||
lcd.icon(!((timer+4)&5), 0);
|
||||
lcd.chr(lcd.wid, 1, 0);
|
||||
}
|
||||
lcd.flush();
|
||||
|
||||
timer++;
|
||||
timer &= 0x0f;
|
||||
}
|
||||
|
||||
static int PAD = 255;
|
||||
|
||||
|
||||
|
||||
typedef struct menu_info
|
||||
{
|
||||
int selected;
|
||||
int length;
|
||||
} menu_info;
|
||||
|
||||
|
||||
|
||||
static int draw_menu(Menu menu, menu_info *info);
|
||||
static int fill_menu_info(Menu menu, menu_info *info);
|
||||
static int menu_handle_action(menu_item *item);
|
||||
|
||||
static int slid_func(menu_item *item);
|
||||
|
||||
|
||||
int do_menu(Menu menu)
|
||||
{
|
||||
menu_info info;
|
||||
int key=0;
|
||||
int status=MENU_OK;
|
||||
int done=0;
|
||||
|
||||
int (*func)();
|
||||
int (*readfunc)(int);
|
||||
|
||||
|
||||
if(!menu) return MENU_ERROR;
|
||||
|
||||
fill_menu_info(menu, &info);
|
||||
|
||||
|
||||
while(!done)
|
||||
{
|
||||
// Keep the cursor off titles... (?)
|
||||
while(menu[info.selected].type == TYPE_TITL)
|
||||
{
|
||||
info.selected++;
|
||||
// If the title is the last thing in the menu...
|
||||
if(!menu[info.selected].text) info.selected -= 2;
|
||||
}
|
||||
|
||||
|
||||
draw_menu(menu, &info);
|
||||
|
||||
// FIXME: This should use a better keypress interface, which
|
||||
// FIXME: handles things according to keybindings...
|
||||
|
||||
for(key = lcd.getkey(); key==0; key = lcd.getkey())
|
||||
{
|
||||
// sleep for 1/8th second...
|
||||
framedelay();
|
||||
// do the heartbeat...
|
||||
draw_heartbeat();
|
||||
// Check for client input...
|
||||
}
|
||||
|
||||
|
||||
// Handle the key according to the keybindings...
|
||||
switch(key)
|
||||
{
|
||||
case 'D': done=1; break;
|
||||
case 'B': if(info.selected > 0) info.selected--;
|
||||
while(menu[info.selected].type == TYPE_TITL)
|
||||
{
|
||||
if(info.selected > 0)
|
||||
info.selected--;
|
||||
else break;
|
||||
}
|
||||
break;
|
||||
case 'C': if(menu[info.selected+1].text) info.selected++; break;
|
||||
case 'A':
|
||||
switch(menu[info.selected].type)
|
||||
{
|
||||
case TYPE_MENU: status = do_menu(menu[info.selected].data);
|
||||
break;
|
||||
case TYPE_FUNC:
|
||||
func = menu[info.selected].data;
|
||||
if(func)
|
||||
status = func();
|
||||
break;
|
||||
case TYPE_CHEK:
|
||||
readfunc = menu[info.selected].data;
|
||||
if(readfunc)
|
||||
status = readfunc(MENU_CHECK);
|
||||
status &= 0xffff0000;
|
||||
break;
|
||||
case TYPE_SLID:
|
||||
func = menu[info.selected].data;
|
||||
if(func)
|
||||
status = slid_func(&menu[info.selected]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch(status)
|
||||
{
|
||||
case MENU_OK:
|
||||
break;
|
||||
case MENU_CLOSE:
|
||||
return MENU_OK;
|
||||
case MENU_QUIT:
|
||||
return MENU_QUIT;
|
||||
// case MENU_KILL:
|
||||
// return MENU_KILL;
|
||||
case MENU_ERROR:
|
||||
return MENU_ERROR;
|
||||
}
|
||||
|
||||
// status = menu_handle_action(&menu[info.selected]);
|
||||
// TODO: It should now do special stuff for "mover" widgets,
|
||||
// TODO: and handle the return code appropriately.
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
static int draw_menu(Menu menu, menu_info *info)
|
||||
{
|
||||
int i;
|
||||
int x=1, y=1;
|
||||
int top=0, bottom=0;
|
||||
|
||||
int (*readfunc)(int);
|
||||
|
||||
// these should maybe be removed:
|
||||
int wid=lcd.wid, hgt=lcd.hgt;
|
||||
|
||||
|
||||
if(!menu) return MENU_ERROR;
|
||||
|
||||
lcd.clear();
|
||||
|
||||
|
||||
// Scroll down until the selected item is centered, if possible...
|
||||
top = info->selected - (hgt/2);
|
||||
if(top<0) top=0;
|
||||
bottom = top+hgt;
|
||||
if(bottom > info->length) bottom=info->length;
|
||||
top = bottom-hgt;
|
||||
if(top<0) top=0;
|
||||
|
||||
|
||||
|
||||
// Draw all visible items...
|
||||
for(i=top; i<bottom; i++, y++)
|
||||
{
|
||||
if(i == info->selected) lcd.chr(2,y,'>');
|
||||
|
||||
switch(menu[i].type)
|
||||
{
|
||||
case TYPE_TITL:
|
||||
lcd.chr(1,y,PAD);
|
||||
lcd.chr(2,y,PAD);
|
||||
lcd.string(4,y,menu[i].text);
|
||||
for(x=strlen(menu[i].text)+5; x <= wid; x++)
|
||||
lcd.chr(x,y,PAD);
|
||||
break;
|
||||
case TYPE_MENU:
|
||||
lcd.string(3,y,menu[i].text);
|
||||
lcd.chr(wid,y,'>');
|
||||
break;
|
||||
case TYPE_FUNC:
|
||||
lcd.string(3,y,menu[i].text);
|
||||
break;
|
||||
case TYPE_CHEK:
|
||||
if(menu[i].data)
|
||||
{
|
||||
readfunc = menu[i].data;
|
||||
if(readfunc(MENU_READ))
|
||||
lcd.chr(wid,y,'Y');
|
||||
else
|
||||
lcd.chr(wid,y,'N');
|
||||
}
|
||||
lcd.string(3,y,menu[i].text);
|
||||
break;
|
||||
case TYPE_SLID:
|
||||
lcd.string(3,y,menu[i].text);
|
||||
break;
|
||||
case TYPE_MOVE:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(top != 0)
|
||||
lcd.chr(1,1,'^');
|
||||
if(bottom < info->length)
|
||||
lcd.chr(1,hgt,'v');
|
||||
|
||||
|
||||
draw_heartbeat();
|
||||
//lcd.flush();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int fill_menu_info(Menu menu, menu_info *info)
|
||||
{
|
||||
int i;
|
||||
|
||||
info->selected = 0;
|
||||
|
||||
// count the entries in the menu
|
||||
for(i=0; menu[i].text; i++);
|
||||
|
||||
info->length = i;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int menu_handle_action(menu_item *item)
|
||||
{
|
||||
return MENU_OK;
|
||||
}
|
||||
|
||||
|
||||
static int slid_func(menu_item *item)
|
||||
{
|
||||
char str[16];
|
||||
int key = 0;
|
||||
int value = 0;
|
||||
int x, y=1;
|
||||
int (*readfunc)(int);
|
||||
|
||||
readfunc = item->data;
|
||||
|
||||
lcd.init_hbar();
|
||||
|
||||
while(key != 'A' && key != 'D')
|
||||
{
|
||||
// Draw the title...
|
||||
lcd.clear();
|
||||
lcd.chr(1,y,PAD);
|
||||
lcd.chr(2,y,PAD);
|
||||
lcd.string(4,y,item->text);
|
||||
for(x=strlen(item->text)+5; x <= lcd.wid; x++)
|
||||
lcd.chr(x,y,PAD);
|
||||
|
||||
// Draw the slider now...
|
||||
value = readfunc(MENU_READ);
|
||||
if(value < 0 || value >= MENU_CLOSE)
|
||||
return value;
|
||||
sprintf(str, "%i", value);
|
||||
if(lcd.hgt >= 4)
|
||||
{
|
||||
lcd.string(8, 4, str);
|
||||
value = (lcd.wid * lcd.cellwid * value / 256);
|
||||
lcd.hbar(1, 3, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
lcd.string(17, 2, str);
|
||||
value = ((lcd.wid-4) * lcd.cellwid * value / 256);
|
||||
lcd.hbar(1, 2, value);
|
||||
}
|
||||
//lcd.flush();
|
||||
|
||||
for(key = lcd.getkey(); key==0; key = lcd.getkey())
|
||||
{
|
||||
// do the heartbeat...
|
||||
draw_heartbeat();
|
||||
// sleep for 1/8th second...
|
||||
framedelay();
|
||||
// Check for client input...
|
||||
}
|
||||
|
||||
switch(key)
|
||||
{
|
||||
case 'B':
|
||||
value = readfunc(MENU_MINUS);
|
||||
break;
|
||||
case 'C':
|
||||
value = readfunc(MENU_PLUS);
|
||||
break;
|
||||
}
|
||||
|
||||
if(value >= MENU_CLOSE
|
||||
|| value < 0
|
||||
|| key == 'A'
|
||||
|| key == 'D')
|
||||
return value;
|
||||
}
|
||||
|
||||
return MENU_OK;
|
||||
}
|
||||
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
#ifndef MENU_H
|
||||
#define MENU_H
|
||||
|
||||
|
||||
#if 0
|
||||
/*************************************************************************
|
||||
Menus!
|
||||
|
||||
This is how the LCDproc menu stuff works...
|
||||
|
||||
Each item has three values:
|
||||
|
||||
Title -- Text
|
||||
Type -- menu, function, checkbox, slider, mover
|
||||
Data -- Child, ExecFunc, CheckFunc, SlidFunc, ???
|
||||
|
||||
When an item is picked, do_menu() decides what to do based on type.
|
||||
--"Menus" will recurse into the "data", assuming it is a child menu.
|
||||
--"Function"-type items will have their function called.
|
||||
--CheckBox-type items will have their function called with a "read"
|
||||
parameter to get an on/off signal, and called with a "set" signal when
|
||||
picked.
|
||||
--Sliders will have the same "read" thing, and the "set" function will
|
||||
take a plus or minus parameter.
|
||||
--The Movers will act like a label until picked, and then the +/- keys
|
||||
will both rearrange the menu, and send the item a signal of some sort
|
||||
to indicate what happened. It will act like a label again after the
|
||||
user presses Enter again.
|
||||
|
||||
The "Data" field will really be a "void *", which is the "generic"
|
||||
data type in C...
|
||||
|
||||
Anyway, this sort of thing would be declared this way:
|
||||
|
||||
========================================================================
|
||||
|
||||
menu_item MainMenu[] = {
|
||||
"MENU", 0, 0, // Title
|
||||
"Options", TYPE_MENU, (void *)OptionsMenu,
|
||||
"Kill LCDproc", TYPE_FUNC, (void *)Shutdown_func,
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
menu_item OptionsMenu[] = {
|
||||
"OPTIONS", TYPE_TITL, 0, // Title
|
||||
"24-hour Time", TYPE_CHEK, (void *)Time24_func,
|
||||
"Contrast...", TYPE_SLID, (void *)Contrast_func,
|
||||
0, 0, 0,
|
||||
};
|
||||
|
||||
|
||||
///////////////// Elsewhere, we declare these...
|
||||
|
||||
void Shutdown_func()
|
||||
{
|
||||
// Do something here...
|
||||
return MENU_KILL; // or MENU_CLOSE, or MENU_OK, or MENU_ERROR
|
||||
}
|
||||
|
||||
int Time24_func(int input)
|
||||
{
|
||||
if(input == MENU_READ) return status;
|
||||
if(input == MENU_CHECK) toggle_status(); // does something.
|
||||
return (status | MENU_OK);
|
||||
// The status is "or"-ed with the MENU value to let do_menu()
|
||||
// know what to do after selecting the item. (two return
|
||||
// values in one. :)
|
||||
|
||||
// Also, "MENU_OK" happens to be zero, so it does not matter
|
||||
// unless you want something else (like MENU_CLOSE)
|
||||
}
|
||||
|
||||
int Contrast_func(int input)
|
||||
{
|
||||
if(input == MENU_READ) return status;
|
||||
if(input == MENU_PLUS) increment_status(); // does something.
|
||||
if(input == MENU_MINUS) decrement_status();// does something.
|
||||
return (status | MENU_OK);
|
||||
}
|
||||
|
||||
=====================================================================
|
||||
|
||||
Function return values:
|
||||
MENU_OK Keeps menu open.
|
||||
MENU_CLOSE Closes menu after item is picked.
|
||||
Leaves the parent menus open.
|
||||
MENU_QUIT Closes all menus after item is picked.
|
||||
Like a normal pulldown menu.
|
||||
MENU_KILL Same as MENU_QUIT, so far.
|
||||
MENU_ERROR Um, for errors? :)
|
||||
|
||||
Also, functions for sliders and checkboxes should return a status value
|
||||
binary OR-ed with the MENU_ return value. Checkboxes should return 0 or 1,
|
||||
and sliders should return 0-255.
|
||||
|
||||
**************************************************************************/
|
||||
#endif
|
||||
|
||||
|
||||
// Return codes from selected menu items...
|
||||
#define MENU_ERROR -0x7FFF0000
|
||||
#define MENU_OK 0
|
||||
#define MENU_CLOSE 0x10000
|
||||
#define MENU_QUIT 0x20000
|
||||
#define MENU_KILL 0x20000
|
||||
|
||||
// Menu item Types...
|
||||
#define TYPE_TITL 0
|
||||
#define TYPE_MENU 1
|
||||
#define TYPE_FUNC 2
|
||||
#define TYPE_CHEK 3
|
||||
#define TYPE_SLID 4
|
||||
#define TYPE_MOVE 5
|
||||
|
||||
#define CLIENT_MENU 0x100
|
||||
#define CLIENT_FUNC 0x101
|
||||
#define CLIENT_CHEK 0x102
|
||||
#define CLIENT_SLID 0x103
|
||||
#define CLIENT_MOVE 0x104
|
||||
|
||||
// User actions, sent to item-handling functions as input.
|
||||
#define MENU_SELECT 1
|
||||
#define MENU_CHECK 2
|
||||
#define MENU_PLUS 3
|
||||
#define MENU_MINUS 4
|
||||
#define MENU_READ 5
|
||||
|
||||
|
||||
typedef struct menu_item
|
||||
{
|
||||
char *text;
|
||||
int type;
|
||||
void *data;
|
||||
} menu_item;
|
||||
|
||||
|
||||
#define Menu menu_item *
|
||||
|
||||
|
||||
int do_menu(Menu menu);
|
||||
|
||||
|
||||
#endif
|
||||
+339
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
menus.c
|
||||
|
||||
Defines the default menus the server provides. Also includes the
|
||||
plug-in functions attached to menu items...
|
||||
|
||||
So far, all menus are static, and not dynamically generated. I'll
|
||||
have to find a way to fix this, since many menu items will be dynamic.
|
||||
(clients connected, screens available, etc...)
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../shared/debug.h"
|
||||
|
||||
#include "drivers/lcd.h"
|
||||
|
||||
#include "main.h"
|
||||
#include "menus.h"
|
||||
#include "render.h"
|
||||
#include "serverscreens.h"
|
||||
|
||||
|
||||
int Shutdown_func();
|
||||
int System_halt_func();
|
||||
int Reboot_func();
|
||||
int Close_func();
|
||||
int OK_func();
|
||||
int Time24_func(int input);
|
||||
int Heartbeat_func(int input);
|
||||
int Backlight_func(int input);
|
||||
int Server_screen_func(int input);
|
||||
int Contrast_func(int input);
|
||||
int Backlight_Brightness_func(int input);
|
||||
int Backlight_Off_Brightness_func(int input);
|
||||
int Backlight_Off_func();
|
||||
int Backlight_On_func();
|
||||
int Backlight_Open_func();
|
||||
|
||||
|
||||
menu_item main_menu[] = {
|
||||
{ "LCDproc", 0, 0 },// Title
|
||||
{ "Options", TYPE_MENU, (void *)options_menu},
|
||||
{ "Screens", TYPE_MENU, (void *)screens_menu},
|
||||
{ "Shutdown", TYPE_MENU, (void *)shutdown_menu },
|
||||
{ 0, 0, 0 },
|
||||
|
||||
};
|
||||
|
||||
menu_item options_menu[] = {
|
||||
{ "OPTIONS", TYPE_TITL, 0}, // Title
|
||||
// "24-hour Time", TYPE_CHEK, (void *)Time24_func,
|
||||
{ "Contrast...", TYPE_SLID, (void *)Contrast_func},
|
||||
{ "Backlight", TYPE_MENU, (void *)Backlight_menu},
|
||||
{ "Heartbeat", TYPE_CHEK, (void *)Heartbeat_func},
|
||||
// { "Backlight...", TYPE_SLID, (void *)Backlight_func},
|
||||
// "OK", TYPE_FUNC, (void *)OK_func,
|
||||
// "Close Menu", TYPE_FUNC, (void *)Close_func,
|
||||
// "Exit Program", TYPE_FUNC, (void *)Shutdown_func,
|
||||
// "Another Title",TYPE_TITL, 0,
|
||||
// "Main menu?", TYPE_MENU, (void *)main_menu,
|
||||
// "Nothing!", TYPE_FUNC, 0,
|
||||
{ 0, 0, 0},
|
||||
};
|
||||
|
||||
menu_item screens_menu[] = {
|
||||
{ "SCREENS", TYPE_TITL, 0}, // Title
|
||||
{ "Server Scr",TYPE_CHEK, (void *)Server_screen_func},
|
||||
{ 0, 0, 0},
|
||||
};
|
||||
|
||||
menu_item shutdown_menu[] = {
|
||||
{ "Shut Down...", TYPE_TITL, 0}, // Title
|
||||
{ "Kill LCDproc", TYPE_FUNC, (void *)Shutdown_func},
|
||||
{ "System halt", TYPE_FUNC, (void *)System_halt_func},
|
||||
{ "Reboot", TYPE_FUNC, (void *)Reboot_func},
|
||||
{ 0, 0, 0},
|
||||
};
|
||||
|
||||
menu_item Backlight_menu[] = {
|
||||
{ "BACKLIGHT MENU", TYPE_TITL, 0}, // Title
|
||||
{ "Brightness...", TYPE_SLID, (void *)Backlight_Brightness_func},
|
||||
{ "\"Off\" Brightness", TYPE_SLID, (void *)Backlight_Off_Brightness_func},
|
||||
{ "Backlight Mode:", TYPE_FUNC, 0}, // Label
|
||||
{ " - Off", TYPE_FUNC, Backlight_Off_func},
|
||||
{ " - On", TYPE_FUNC, Backlight_On_func},
|
||||
{ " - Open", TYPE_FUNC, Backlight_Open_func},
|
||||
{ 0, 0, 0},
|
||||
};
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Plug-in functions for menu items
|
||||
//
|
||||
|
||||
// Exits the program.
|
||||
int Shutdown_func()
|
||||
{
|
||||
exit_program(0);
|
||||
|
||||
return MENU_KILL;
|
||||
}
|
||||
|
||||
// Shuts down the system, if possible
|
||||
int System_halt_func()
|
||||
{
|
||||
int err;
|
||||
uid_t id;
|
||||
|
||||
id = geteuid();
|
||||
|
||||
err = system("init 0");
|
||||
|
||||
if(err < 0) return MENU_KILL;
|
||||
if(err == 127) return MENU_KILL;
|
||||
|
||||
// If we're root, exit
|
||||
if(id == 0) exit_program(0);
|
||||
|
||||
// Otherwise, assume shutdown will fail; and show more stats.
|
||||
return MENU_KILL;
|
||||
}
|
||||
|
||||
// Shuts down the system and restarts it
|
||||
int Reboot_func()
|
||||
{
|
||||
int err;
|
||||
uid_t id;
|
||||
|
||||
id = geteuid();
|
||||
|
||||
err = system("init 6");
|
||||
|
||||
if(err < 0) return MENU_KILL;
|
||||
if(err == 127) return MENU_KILL;
|
||||
|
||||
// If we're root, exit
|
||||
if(id == 0) exit_program(0);
|
||||
|
||||
// Otherwise, assume shutdown will fail; and show more stats.
|
||||
return MENU_KILL;
|
||||
}
|
||||
|
||||
int Close_func()
|
||||
{
|
||||
return MENU_CLOSE;
|
||||
}
|
||||
|
||||
int OK_func()
|
||||
{
|
||||
return MENU_OK;
|
||||
}
|
||||
|
||||
|
||||
int Time24_func(int input)
|
||||
{
|
||||
static int status=0;
|
||||
|
||||
if(input == MENU_READ) return status;
|
||||
if(input == MENU_CHECK) status ^= 1; // does something.
|
||||
return (status | MENU_OK);
|
||||
// The status is "or"-ed with the MENU value to let do_menu()
|
||||
// know what to do after selecting the item. (two return
|
||||
// values in one. :)
|
||||
|
||||
// Also, "MENU_OK" happens to be zero, so it does not matter
|
||||
// unless you want something else (like MENU_CLOSE)
|
||||
}
|
||||
|
||||
int Heartbeat_func(int input)
|
||||
{
|
||||
if(input == MENU_READ) return (heartbeat != HEART_OFF);
|
||||
if(input == MENU_CHECK)
|
||||
{
|
||||
if(heartbeat) heartbeat = HEART_OFF;
|
||||
else heartbeat = HEART_OPEN;
|
||||
}
|
||||
return ((heartbeat != HEART_OFF) | MENU_OK);
|
||||
}
|
||||
|
||||
int Backlight_func(int input)
|
||||
{
|
||||
int status = 128;
|
||||
|
||||
switch(backlight)
|
||||
{
|
||||
case BACKLIGHT_OFF:
|
||||
if(input == MENU_READ) status = 0;
|
||||
if(input == MENU_PLUS)
|
||||
{
|
||||
backlight = BACKLIGHT_OPEN;
|
||||
status = 128;
|
||||
}
|
||||
if(input == MENU_MINUS)
|
||||
{
|
||||
status = 0;
|
||||
}
|
||||
break;
|
||||
case BACKLIGHT_ON:
|
||||
if(input == MENU_READ) status = 255;
|
||||
if(input == MENU_PLUS)
|
||||
{
|
||||
status = 255;
|
||||
}
|
||||
if(input == MENU_MINUS)
|
||||
{
|
||||
backlight = BACKLIGHT_OPEN;
|
||||
status = 128;
|
||||
}
|
||||
break;
|
||||
case BACKLIGHT_OPEN:
|
||||
if(input == MENU_READ) status = 128;
|
||||
if(input == MENU_PLUS)
|
||||
{
|
||||
backlight = BACKLIGHT_ON;
|
||||
backlight_state = BACKLIGHT_ON;
|
||||
status = 255;
|
||||
}
|
||||
if(input == MENU_MINUS)
|
||||
{
|
||||
backlight = BACKLIGHT_OFF;
|
||||
backlight_state = BACKLIGHT_OFF;
|
||||
status = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
if(input == MENU_READ) return (backlight != BACKLIGHT_OFF);
|
||||
if(input == MENU_CHECK)
|
||||
{
|
||||
if(backlight) backlight = BACKLIGHT_OFF;
|
||||
else backlight = BACKLIGHT_OPEN;
|
||||
}
|
||||
*/
|
||||
lcd.backlight(backlight_state & BACKLIGHT_ON);
|
||||
|
||||
return (status | MENU_OK);
|
||||
}
|
||||
|
||||
int Server_screen_func(int input)
|
||||
{
|
||||
if(input == MENU_READ) return (server_screen->priority < 256);
|
||||
if(input == MENU_CHECK)
|
||||
{
|
||||
if(server_screen->priority < 256) server_screen->priority = 256;
|
||||
else server_screen->priority = 128;
|
||||
}
|
||||
|
||||
return (MENU_OK | (server_screen->priority < 256));
|
||||
}
|
||||
|
||||
int Contrast_func(int input)
|
||||
{
|
||||
int status;
|
||||
|
||||
status=lcd.contrast(-1);
|
||||
|
||||
if(input == MENU_READ) return status;
|
||||
if(input == MENU_PLUS) status+=5; // does something.
|
||||
if(input == MENU_MINUS) status-=5; // does something.
|
||||
|
||||
if(status<0) status=0;
|
||||
if(status>255) status=255;
|
||||
lcd.contrast(status);
|
||||
|
||||
return (status | MENU_OK);
|
||||
}
|
||||
|
||||
|
||||
void server_menu()
|
||||
{
|
||||
debug("server_menu()\n");
|
||||
|
||||
do_menu(main_menu);
|
||||
|
||||
}
|
||||
|
||||
int Backlight_Brightness_func(int input)
|
||||
{
|
||||
int status = backlight_brightness;
|
||||
|
||||
if(input == MENU_READ) return status;
|
||||
if(input == MENU_PLUS) status+=5; // does something.
|
||||
if(input == MENU_MINUS) status-=5; // does something.
|
||||
|
||||
if(status<0) status=0;
|
||||
if(status>255) status=255;
|
||||
lcd.backlight(status);
|
||||
|
||||
backlight_brightness = status;
|
||||
|
||||
return (status | MENU_OK);
|
||||
}
|
||||
|
||||
int Backlight_Off_Brightness_func(int input)
|
||||
{
|
||||
int status = backlight_off_brightness;
|
||||
|
||||
if(input == MENU_READ) return status;
|
||||
if(input == MENU_PLUS) status+=5; // does something.
|
||||
if(input == MENU_MINUS) status-=5; // does something.
|
||||
|
||||
if(status<0) status=0;
|
||||
if(status>255) status=255;
|
||||
lcd.backlight(status);
|
||||
|
||||
backlight_off_brightness = status;
|
||||
|
||||
return (status | MENU_OK);
|
||||
}
|
||||
|
||||
int Backlight_Off_func()
|
||||
{
|
||||
backlight_state = BACKLIGHT_OFF;
|
||||
backlight = BACKLIGHT_OFF;
|
||||
lcd.backlight(backlight_off_brightness);
|
||||
return MENU_OK;
|
||||
}
|
||||
|
||||
int Backlight_On_func()
|
||||
{
|
||||
backlight_state = BACKLIGHT_ON;
|
||||
backlight = BACKLIGHT_ON;
|
||||
lcd.backlight(backlight_brightness * (backlight_state & BACKLIGHT_ON));
|
||||
return MENU_OK;
|
||||
}
|
||||
|
||||
int Backlight_Open_func()
|
||||
{
|
||||
backlight = BACKLIGHT_OPEN;
|
||||
return MENU_OK;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef MENUS_H
|
||||
#define MENUS_H
|
||||
|
||||
#include "menu.h"
|
||||
|
||||
// These probably don't need to be defined here...
|
||||
extern menu_item main_menu[];
|
||||
extern menu_item options_menu[];
|
||||
extern menu_item screens_menu[];
|
||||
extern menu_item shutdown_menu[];
|
||||
extern menu_item Backlight_menu[];
|
||||
|
||||
// Brings up the main menu...
|
||||
void server_menu();
|
||||
|
||||
#endif
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
parse.c
|
||||
|
||||
Handles input commands from clients, by splitting strings into tokens
|
||||
and passing arguments to the appropriate handler.
|
||||
|
||||
It works much like a command line. Only the first token is used to
|
||||
determine what function to call.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../shared/LL.h"
|
||||
#include "../shared/sockets.h"
|
||||
#include "../shared/debug.h"
|
||||
#include "clients.h"
|
||||
#include "client_functions.h"
|
||||
#include "parse.h"
|
||||
|
||||
|
||||
|
||||
int parse_all_client_messages()
|
||||
{
|
||||
int i, j;
|
||||
int newtoken, inquote;
|
||||
client *c;
|
||||
char *str;
|
||||
// char *tok;
|
||||
int argc;
|
||||
char *argv[256];
|
||||
char delimiters[] = " \0";
|
||||
char leftquote[] = "\0\"'`([{\0";
|
||||
char rightquote[] = "\0\"'`)]}\0";
|
||||
char errmsg[256];
|
||||
int invalid=0;
|
||||
|
||||
//debug("parse: Rewinding list...\n");
|
||||
LL_Rewind(clients);
|
||||
do {
|
||||
// Get the next client...
|
||||
//debug("parse: Getting client...\n");
|
||||
c = LL_Get(clients);
|
||||
if(c)
|
||||
{
|
||||
// And parse all its messages...
|
||||
//debug("parse: Getting messages...\n");
|
||||
for(str = client_get_message(c); str; str = client_get_message(c))
|
||||
{
|
||||
debug("parse: ...%s\n", str);
|
||||
// Now, split up the string...
|
||||
//len = strlen(str);
|
||||
argc=0;
|
||||
newtoken=1;
|
||||
inquote=0;
|
||||
for(i=0; str[i]; i++)
|
||||
{
|
||||
if(inquote) // Scan for the end of the quote
|
||||
{
|
||||
if(str[i] == rightquote[inquote])
|
||||
{ // Found the end of the quote
|
||||
inquote=0;
|
||||
str[i] = 0;
|
||||
newtoken=1;
|
||||
}
|
||||
}
|
||||
else // Normal operation; split at delimiters
|
||||
{
|
||||
for(j=1; leftquote[j]; j++)
|
||||
{
|
||||
// Found the beginning of a new quote...
|
||||
if(str[i] == leftquote[j])
|
||||
{
|
||||
inquote = j;
|
||||
str[i] = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
for(j=0; delimiters[j]; j++)
|
||||
{
|
||||
// Break into a new string...
|
||||
if(str[i] == delimiters[j])
|
||||
{
|
||||
str[i] = 0;
|
||||
newtoken = 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(newtoken && str[i])
|
||||
{
|
||||
newtoken=0;
|
||||
argv[argc] = str + i;
|
||||
argc++;
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
if(inquote)
|
||||
{
|
||||
sprintf(errmsg, "huh? Unterminated string: missing %c\n",
|
||||
rightquote[inquote]);
|
||||
sock_send_string(c->sock, errmsg);
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
for(tok = strtok(str, delimiters);
|
||||
tok;
|
||||
tok=strtok(NULL, delimiters))
|
||||
{
|
||||
argv[argc] = tok;
|
||||
argc++;
|
||||
}
|
||||
*/
|
||||
argv[argc] = NULL;
|
||||
if(argc < 1) continue;
|
||||
|
||||
// Now find and call the appropriate function...
|
||||
// debug("parse: Finding function...\n");
|
||||
invalid = 1;
|
||||
for(i=0; commands[i].keyword; i++)
|
||||
{
|
||||
// debug("(checking %s)\n", commands[i].keyword);
|
||||
if(0 == strcmp(argv[0], commands[i].keyword))
|
||||
{
|
||||
// debug("(FOUND %s)\n", commands[i].keyword);
|
||||
invalid = commands[i].function(c, argc, argv);
|
||||
// debug("parse: Returned %i...\n", err);
|
||||
}
|
||||
}
|
||||
if(invalid)
|
||||
{
|
||||
// FIXME: Check for buffer overflows here...
|
||||
sprintf(errmsg, "huh? Invalid command \"%s\"\n", argv[0]);
|
||||
sock_send_string(c->sock, errmsg);
|
||||
}
|
||||
|
||||
free(str); // fixed memory leak?
|
||||
} // end for(str...)
|
||||
} // end if (c)
|
||||
} while (LL_Next(clients) == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef PARSE_H
|
||||
#define PARSE_H
|
||||
|
||||
// This should be pretty self-explanatory...
|
||||
int parse_all_client_messages();
|
||||
|
||||
#endif
|
||||
+526
@@ -0,0 +1,526 @@
|
||||
/*
|
||||
render.c
|
||||
|
||||
Draws screens on the LCD.
|
||||
|
||||
This needs to be greatly expanded and redone for greater flexibility.
|
||||
For example, it should support multiple screen sizes, more flexible
|
||||
widgets, and multiple simultaneous screens.
|
||||
|
||||
This will probably take a while to do. :(
|
||||
|
||||
|
||||
THIS FILE IS MESSY! Anyone care to rewrite it nicely? Please?? :)
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../shared/debug.h"
|
||||
#include "../shared/LL.h"
|
||||
|
||||
#include "drivers/lcd.h"
|
||||
|
||||
#include "screen.h"
|
||||
#include "screenlist.h"
|
||||
#include "widget.h"
|
||||
#include "render.h"
|
||||
|
||||
|
||||
|
||||
int heartbeat=HEART_OPEN;
|
||||
int backlight=BACKLIGHT_OPEN;
|
||||
int backlight_state = BACKLIGHT_OPEN;
|
||||
int backlight_brightness=255;
|
||||
int backlight_off_brightness=0;
|
||||
int output_state = 0;
|
||||
|
||||
static int reset;
|
||||
|
||||
#define BUFSIZE 1024
|
||||
|
||||
static int draw_frame(LL *list, char fscroll,
|
||||
int left, int top, int right, int bottom,
|
||||
int fwid, int fhgt,
|
||||
int fspeed, int timer);
|
||||
|
||||
|
||||
int draw_screen(screen *s, int timer)
|
||||
{
|
||||
static screen *old_s=NULL;
|
||||
int tmp=0;
|
||||
|
||||
//debug("Render...\n");
|
||||
//return 0;
|
||||
|
||||
reset = 1;
|
||||
|
||||
//debug("draw_screen: %8x, %i\n", (int)s, timer);
|
||||
|
||||
if(!s) return -1;
|
||||
|
||||
if(s == old_s) reset = 0;
|
||||
old_s = s;
|
||||
|
||||
|
||||
|
||||
lcd.clear();
|
||||
|
||||
|
||||
switch(backlight_state)
|
||||
{
|
||||
case BACKLIGHT_OFF:
|
||||
lcd.backlight(backlight_off_brightness);
|
||||
break;
|
||||
case BACKLIGHT_ON:
|
||||
lcd.backlight(backlight_brightness);
|
||||
break;
|
||||
default:
|
||||
if(backlight_state & BACKLIGHT_FLASH)
|
||||
{
|
||||
tmp = (!((timer&7) == 7));
|
||||
if(backlight_state & 1)
|
||||
lcd.backlight(tmp?backlight_brightness:backlight_off_brightness);
|
||||
//lcd.backlight(backlight_brightness * (!((timer&7) == 7)));
|
||||
else
|
||||
lcd.backlight(!tmp?backlight_brightness:backlight_off_brightness);
|
||||
//lcd.backlight(backlight_brightness * ((timer&7) == 7));
|
||||
}
|
||||
else if(backlight_state & BACKLIGHT_BLINK)
|
||||
{
|
||||
tmp = (!((timer&14) == 14));
|
||||
if(backlight_state & 1)
|
||||
lcd.backlight(tmp?backlight_brightness:backlight_off_brightness);
|
||||
//lcd.backlight(backlight_brightness * (!((timer&14) == 14)));
|
||||
else
|
||||
lcd.backlight(!tmp?backlight_brightness:backlight_off_brightness);
|
||||
//lcd.backlight(backlight_brightness * ((timer&14) == 14));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
lcd.output(output_state);
|
||||
|
||||
draw_frame(s->widgets, 'v',
|
||||
0, 0, lcd.wid, lcd.hgt,
|
||||
s->wid, s->hgt,
|
||||
s->duration/s->hgt, timer);
|
||||
|
||||
|
||||
//debug("draw_screen done\n");
|
||||
|
||||
|
||||
if(heartbeat)
|
||||
{
|
||||
if(s->heartbeat || heartbeat == HEART_ON)
|
||||
{
|
||||
// Set this to pulsate like a real heart beat...
|
||||
// (binary is fun... :)
|
||||
lcd.icon(!((timer+4)&5), 0);
|
||||
lcd.chr(lcd.wid, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
lcd.flush();
|
||||
|
||||
//debug("draw_screen: %8x, %i\n", s, timer);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int draw_frame(LL *list, char fscroll,
|
||||
int left, int top, int right, int bottom,
|
||||
int fwid, int fhgt,
|
||||
int fspeed, int timer)
|
||||
{
|
||||
char str[BUFSIZE]; // scratch buffer
|
||||
widget *w;
|
||||
|
||||
int wid, hgt; // Width and height of visible frame area
|
||||
int x, y;
|
||||
int fx, fy; // Scrolling offset for the frame...
|
||||
int length, speed;
|
||||
//int lines;
|
||||
|
||||
int reset = 1;
|
||||
|
||||
wid = right - left; // This is the size of the visible frame area
|
||||
hgt = bottom - top;
|
||||
|
||||
fx = 0;
|
||||
fy = 0;
|
||||
if(fscroll == 'v')
|
||||
{
|
||||
|
||||
if(fspeed > 0)
|
||||
fy = (timer-fspeed) / fspeed;
|
||||
if(fspeed < 0)
|
||||
fy = (-fspeed) * timer;
|
||||
if(fy < 0) fy = 0;
|
||||
|
||||
// Make sure the whole frame gets displayed, at least...
|
||||
if(!screenlist_action) screenlist_action = RENDER_HOLD;
|
||||
if((fy) > fhgt - 1)
|
||||
{
|
||||
// Release hold after it has been displayed
|
||||
if(!screenlist_action || screenlist_action == RENDER_HOLD)
|
||||
screenlist_action = 0;
|
||||
}
|
||||
|
||||
fy %= fhgt;
|
||||
if(fy > fhgt - hgt) fy = fhgt - hgt;
|
||||
}
|
||||
else if (fscroll == 'h')
|
||||
{ // TODO: Frames don't scroll horizontally yet!
|
||||
|
||||
}
|
||||
|
||||
//debug("draw_screen: %8x, %i\n", s, timer);
|
||||
|
||||
if(!list) return -1;
|
||||
|
||||
//debug("draw_frame: %8x, %i\n", frame, timer);
|
||||
|
||||
|
||||
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
w = (widget *)LL_Get(list);
|
||||
if(!w) return -1;
|
||||
|
||||
// TODO: Make this cleaner and more flexible!
|
||||
switch(w->type)
|
||||
{
|
||||
case WID_STRING:
|
||||
if((w->x > 0) && (w->y > 0) && (w->text))
|
||||
{
|
||||
if((w->y <= hgt + fy) &&
|
||||
(w->y > fy))
|
||||
{
|
||||
strncpy(str, w->text, wid - w->x + 1);
|
||||
str[wid - w->x + 1] = 0;
|
||||
lcd.string(w->x + left,
|
||||
w->y + top - fy,
|
||||
str);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WID_HBAR:
|
||||
if(reset)
|
||||
{
|
||||
lcd.init_hbar();
|
||||
reset = 0;
|
||||
}
|
||||
if((w->x > 0) && (w->y > 0))
|
||||
{
|
||||
if((w->y <= hgt + fy) &&
|
||||
(w->y > fy))
|
||||
{
|
||||
if(w->length > 0)
|
||||
{
|
||||
if((w->length / lcd.cellwid) < wid - w->x + 1)
|
||||
lcd.hbar(w->x + left,
|
||||
w->y + top - fy,
|
||||
w->length);
|
||||
else
|
||||
lcd.hbar(w->x + left,
|
||||
w->y + top - fy,
|
||||
wid * lcd.cellwid);
|
||||
}
|
||||
else if(w->length < 0)
|
||||
{
|
||||
// TODO: Rearrange stuff to get left-extending
|
||||
// hbars to draw correctly...
|
||||
// .. er, this'll require driver modifications,
|
||||
// so I'll leave it out for now.
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WID_VBAR: // FIXME: Vbars don't work in frames!
|
||||
if(reset)
|
||||
{
|
||||
lcd.init_vbar();
|
||||
reset = 0;
|
||||
}
|
||||
if((w->x > 0) && (w->y > 0))
|
||||
{
|
||||
if(w->length > 0)
|
||||
{
|
||||
lcd.vbar(w->x, w->length);
|
||||
}
|
||||
else if(w->length < 0)
|
||||
{
|
||||
// TODO: Rearrange stuff to get down-extending
|
||||
// vbars to draw correctly...
|
||||
// .. er, this'll require driver modifications,
|
||||
// so I'll leave it out for now.
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WID_ICON: // FIXME: Not implemented
|
||||
break;
|
||||
case WID_TITLE: // FIXME: Doesn't work quite right in frames...
|
||||
if(!w->text) break;
|
||||
if(wid < 8) break;
|
||||
|
||||
memset(str, 255, wid);
|
||||
str[2] = ' ';
|
||||
length = strlen(w->text);
|
||||
if(length <= wid-6)
|
||||
{
|
||||
memcpy(str+3, w->text, length);
|
||||
str[length+3] = ' ';
|
||||
}
|
||||
else // Scroll the title, if it doesn't fit...
|
||||
{
|
||||
speed = 1;
|
||||
x = timer / speed;
|
||||
y = x / length;
|
||||
|
||||
// Make sure the whole title gets displayed, at least...
|
||||
if(!screenlist_action) screenlist_action = RENDER_HOLD;
|
||||
if(x > length - 6)
|
||||
{
|
||||
// Release hold after it has been displayed
|
||||
if(!screenlist_action || screenlist_action == RENDER_HOLD)
|
||||
screenlist_action = 0;
|
||||
}
|
||||
x %= (length);
|
||||
x -= 3;
|
||||
if(x < 0) x = 0;
|
||||
if(x > length - (wid-6)) x = length - (wid-6);
|
||||
|
||||
if(y&1) // Scrolling backwards...
|
||||
{
|
||||
x = (length-(wid-6)) - x;
|
||||
}
|
||||
strncpy(str+3, w->text+x, (wid-6));
|
||||
str[wid-3] = ' ';
|
||||
}
|
||||
str[wid] = 0;
|
||||
|
||||
lcd.string(1 + left, 1 + top, str);
|
||||
break;
|
||||
case WID_SCROLLER: // FIXME: doesn't work in frames...
|
||||
{
|
||||
int offset;
|
||||
int screen_width;
|
||||
if (!w->text) break;
|
||||
if (w->right < w->left) break;
|
||||
//printf("rendering: %s %d\n",w->text,timer);
|
||||
screen_width = w->right - w->left + 1;
|
||||
switch (w->length)
|
||||
{ // actually, direction...
|
||||
// FIXED: Horz scrollers don't show the
|
||||
// last letter in the string... (1-off error?)
|
||||
case 'h':
|
||||
length = strlen(w->text) + 1;
|
||||
if (length <= screen_width)
|
||||
{
|
||||
/* it fits within the box, just render it */
|
||||
lcd.string(w->left,w->top,w->text);
|
||||
}
|
||||
else
|
||||
{
|
||||
int effLength = length - screen_width;
|
||||
int necessaryTimeUnits = 0;
|
||||
if (!screenlist_action) screenlist_action = RENDER_HOLD;
|
||||
if (w->speed > 0) {
|
||||
necessaryTimeUnits = effLength * w->speed;
|
||||
if (((timer / (effLength*w->speed)) % 2) == 0) {
|
||||
//wiggle one way
|
||||
offset = (timer % (effLength*w->speed))
|
||||
/ w->speed;
|
||||
}
|
||||
else
|
||||
{
|
||||
//wiggle the other
|
||||
offset = (((timer % (effLength*w->speed))
|
||||
- (effLength*w->speed) + 1)
|
||||
/ w->speed) * -1;
|
||||
}
|
||||
}
|
||||
else if (w->speed < 0)
|
||||
{
|
||||
necessaryTimeUnits = effLength / (w->speed * -1);
|
||||
if (((timer / (effLength/(w->speed*-1))) % 2) == 0)
|
||||
{
|
||||
offset = (timer % (effLength/(w->speed*-1)))
|
||||
* w->speed * -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = (((timer % (effLength/(w->speed*-1)))
|
||||
* w->speed * -1) - effLength + 1) * -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = 0;
|
||||
if(screenlist_action == RENDER_HOLD)
|
||||
screenlist_action = 0;
|
||||
}
|
||||
if (timer > necessaryTimeUnits)
|
||||
{
|
||||
if(screenlist_action == RENDER_HOLD)
|
||||
screenlist_action = 0;
|
||||
}
|
||||
if (offset <= length)
|
||||
{
|
||||
strncpy(str,&((w->text)[offset]),screen_width);
|
||||
str[screen_width] = '\0';
|
||||
//printf("%s : %d\n",str,length-offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
str[0] = '\0';
|
||||
}
|
||||
lcd.string(w->left,w->top,str);
|
||||
}
|
||||
break;
|
||||
// FIXME: Vert scrollers don't always seem to scroll
|
||||
// back up after hitting the bottom. They jump back to
|
||||
// the top instead... (nevermind?)
|
||||
case 'v':
|
||||
{
|
||||
int i=0;
|
||||
length = strlen(w->text);
|
||||
if (length <= screen_width)
|
||||
{
|
||||
/* no scrolling required...*/
|
||||
lcd.string(w->left,w->top,w->text);
|
||||
}
|
||||
else
|
||||
{
|
||||
int lines_required =
|
||||
(length / screen_width)
|
||||
+ (length % screen_width ? 1 : 0);
|
||||
int available_lines = (w->bottom - w->top + 1);
|
||||
if (lines_required <= available_lines)
|
||||
{
|
||||
// easy...
|
||||
for(i=0;i<lines_required;i++)
|
||||
{
|
||||
strncpy(str,
|
||||
&((w->text)[i*screen_width]),
|
||||
screen_width);
|
||||
str[screen_width] = '\0';
|
||||
lcd.string(w->left,w->top + i,str);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int necessaryTimeUnits = 0;
|
||||
int effLines = lines_required - available_lines + 1;
|
||||
int begin = 0;
|
||||
if (!screenlist_action)
|
||||
screenlist_action = RENDER_HOLD;
|
||||
//printf("length: %d sw: %d lines req: %d avail lines: %d effLines: %d \n",length,screen_width,lines_required,available_lines,effLines);
|
||||
if (w->speed > 0)
|
||||
{
|
||||
necessaryTimeUnits = effLines * w->speed;
|
||||
if (((timer / (effLines*w->speed)) % 2) == 0)
|
||||
{
|
||||
//printf("up ");
|
||||
begin = (timer % (effLines*w->speed))
|
||||
/ w->speed;
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("down ");
|
||||
begin = (((timer % (effLines*w->speed))
|
||||
- (effLines*w->speed) + 1)/w->speed)
|
||||
* -1;
|
||||
}
|
||||
}
|
||||
else if (w->speed < 0)
|
||||
{
|
||||
necessaryTimeUnits = effLines / (w->speed * -1);
|
||||
if (((timer / (effLines/(w->speed*-1))) % 2) == 0)
|
||||
{
|
||||
begin = (timer % (effLines/(w->speed*-1)))
|
||||
* w->speed * -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
begin = (((timer % (effLines/(w->speed*-1)))
|
||||
* w->speed * -1) - effLines + 1)
|
||||
* -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
begin = 0;
|
||||
}
|
||||
//printf("rendering begin: %d timer: %d effLines: %d\n",begin,timer,effLines);
|
||||
for(i=begin;i<begin+available_lines;i++)
|
||||
{
|
||||
strncpy(str,
|
||||
&((w->text)[i*(screen_width)]),
|
||||
screen_width);
|
||||
str[screen_width] = '\0';
|
||||
//printf("rendering: '%s' of %s\n",
|
||||
//str,w->text);
|
||||
lcd.string(w->left,w->top + (i-begin),str);
|
||||
}
|
||||
if (timer > necessaryTimeUnits)
|
||||
{
|
||||
if(screenlist_action == RENDER_HOLD)
|
||||
screenlist_action = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WID_FRAME:
|
||||
{
|
||||
// FIXME: doesn't handle nested frames quite right!
|
||||
// doesn't handle scrolling in nested frames at all...
|
||||
int new_left, new_top, new_right, new_bottom;
|
||||
new_left = left + w->left - 1;
|
||||
new_top = top + w->top - 1;
|
||||
new_right = left + w->right;
|
||||
new_bottom = top + w->bottom;
|
||||
if(new_right > right) new_right = right;
|
||||
if(new_bottom > bottom) new_bottom = bottom;
|
||||
if(new_left >= right ||
|
||||
new_top >= bottom)
|
||||
{ // Do nothing if it's invisible...
|
||||
}
|
||||
else
|
||||
{
|
||||
draw_frame(w->kids, w->length,
|
||||
new_left, new_top, new_right, new_bottom,
|
||||
w->wid, w->hgt,
|
||||
w->speed, timer);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WID_NUM: // FIXME: doesn't work in frames...
|
||||
if((w->x > 0) && (w->y >= 0) && (w->y <= 9))
|
||||
{
|
||||
if(reset)
|
||||
{
|
||||
lcd.init_num();
|
||||
reset = 0;
|
||||
}
|
||||
lcd.num(w->x + left, w->y);
|
||||
}
|
||||
break;
|
||||
case WID_NONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} while(LL_Next(list) == 0);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef RENDER_H
|
||||
#define RENDER_H
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
|
||||
#define HEART_OFF 0
|
||||
#define HEART_ON 1
|
||||
#define HEART_OPEN 2
|
||||
|
||||
#define BACKLIGHT_OFF 0
|
||||
#define BACKLIGHT_ON 1
|
||||
#define BACKLIGHT_OPEN 2
|
||||
#define BACKLIGHT_LOAD 3
|
||||
#define BACKLIGHT_VIS 4
|
||||
|
||||
#define BACKLIGHT_BLINK 0x100
|
||||
#define BACKLIGHT_FLASH 0x200
|
||||
|
||||
extern int heartbeat;
|
||||
extern int backlight;
|
||||
extern int backlight_state;
|
||||
extern int backlight_brightness;
|
||||
extern int backlight_off_brightness;
|
||||
extern int output_state;
|
||||
int draw_screen(screen *s, int timer);
|
||||
|
||||
|
||||
#endif
|
||||
+171
@@ -0,0 +1,171 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../shared/debug.h"
|
||||
|
||||
#include "drivers/lcd.h"
|
||||
|
||||
#include "clients.h"
|
||||
#include "client_data.h"
|
||||
#include "widget.h"
|
||||
#include "screenlist.h"
|
||||
#include "screen.h"
|
||||
|
||||
|
||||
screen * screen_create()
|
||||
{
|
||||
screen *s;
|
||||
|
||||
s = malloc(sizeof(screen));
|
||||
if(!s)
|
||||
{
|
||||
fprintf(stderr, "screen_create: Error allocating new screen\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s->id=NULL;
|
||||
s->name=NULL;
|
||||
s->priority=128;
|
||||
// TODO: Make the screen duration configurable!
|
||||
s->duration = 32;
|
||||
s->heartbeat = 1;
|
||||
s->wid = lcd.wid;
|
||||
s->hgt = lcd.hgt;
|
||||
s->parent = NULL;
|
||||
s->widgets=NULL;
|
||||
|
||||
s->widgets = LL_new();
|
||||
if(!s->widgets)
|
||||
{
|
||||
fprintf(stderr, "screen_create: Error allocating widget list\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int screen_destroy(screen *s)
|
||||
{
|
||||
widget *w;
|
||||
|
||||
if(!s) return -1;
|
||||
|
||||
LL_Rewind(s->widgets);
|
||||
do {
|
||||
// Free a widget...
|
||||
w = LL_Get(s->widgets);
|
||||
widget_destroy(w);
|
||||
} while (LL_Next(s->widgets) == 0);
|
||||
LL_Destroy(s->widgets);
|
||||
|
||||
|
||||
if(s->id)
|
||||
free(s->id);
|
||||
if(s->name)
|
||||
free(s->name);
|
||||
|
||||
free(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
screen *screen_find(client *c, char *id)
|
||||
{
|
||||
screen *s;
|
||||
|
||||
if(!c) return NULL;
|
||||
if(!id) return NULL;
|
||||
|
||||
debug("client_find_screen(%s)\n", id);
|
||||
|
||||
LL_Rewind(c->data->screenlist);
|
||||
do {
|
||||
s = LL_Get(c->data->screenlist);
|
||||
if( (s) && (0 == strcmp(s->id, id)))
|
||||
{
|
||||
debug("client_find_screen: Found %s\n", id);
|
||||
return s;
|
||||
}
|
||||
} while(LL_Next(c->data->screenlist) == 0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int screen_add(client *c, char *id)
|
||||
{
|
||||
screen *s;
|
||||
|
||||
if(!c) return -1;
|
||||
if(!id) return -1;
|
||||
|
||||
// Make sure this screen doesn't already exist...
|
||||
s = screen_find(c, id);
|
||||
if(s)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
s = screen_create();
|
||||
if(!s)
|
||||
{
|
||||
fprintf(stderr, "screen_add: Error creating screen\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
s->parent = c;
|
||||
|
||||
s->id = strdup(id);
|
||||
if(!s->id)
|
||||
{
|
||||
fprintf(stderr, "screen_add: Error allocating name\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO: Check for errors here?
|
||||
LL_Push(c->data->screenlist, (void *)s);
|
||||
|
||||
|
||||
// Now, add it to the screenlist...
|
||||
if(screenlist_add(s) < 0)
|
||||
{
|
||||
fprintf(stderr, "screen_add: Error queueing new screen\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int screen_remove(client *c, char *id)
|
||||
{
|
||||
screen *s;
|
||||
|
||||
if(!c) return -1;
|
||||
if(!id) return -1;
|
||||
|
||||
// Make sure this screen *does* exist...
|
||||
s = screen_find(c, id);
|
||||
if(!s)
|
||||
{
|
||||
fprintf(stderr, "screen_remove: Error finding screen %s\n", id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// TODO: Check for errors here?
|
||||
LL_Remove(c->data->screenlist, (void *)s);
|
||||
|
||||
// ... and here?
|
||||
screen_destroy(s);
|
||||
|
||||
// Now, remove it from the screenlist...
|
||||
if(screenlist_remove_all(s) < 0)
|
||||
{
|
||||
// Not a serious error..
|
||||
fprintf(stderr, "screen_remove: Error dequeueing screen\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef SCREEN_H
|
||||
#define SCREEN_H
|
||||
|
||||
#include "../shared/LL.h"
|
||||
#include "clients.h"
|
||||
|
||||
typedef struct screen
|
||||
{
|
||||
char *id;
|
||||
char *name;
|
||||
int wid, hgt;
|
||||
int priority;
|
||||
int duration;
|
||||
int heartbeat;
|
||||
LL * widgets;
|
||||
client *parent;
|
||||
} screen;
|
||||
|
||||
|
||||
screen * screen_create();
|
||||
int screen_destroy(screen *s);
|
||||
|
||||
screen * screen_find(client *c, char *id);
|
||||
|
||||
int screen_add(client *c, char *id);
|
||||
int screen_remove(client *c, char *id);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,273 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../shared/LL.h"
|
||||
#include "../shared/sockets.h"
|
||||
#include "../shared/debug.h"
|
||||
#include "screenlist.h"
|
||||
#include "screen.h"
|
||||
#include "clients.h"
|
||||
|
||||
|
||||
|
||||
int screenlist_action=0;
|
||||
|
||||
int timer=0;
|
||||
|
||||
LL * screenlist;
|
||||
|
||||
|
||||
int screenlist_add_end(screen *screen);
|
||||
screen * screenlist_next_roll();
|
||||
screen * screenlist_prev_roll();
|
||||
screen * screenlist_next_priority();
|
||||
|
||||
int compare_priority(void *one, void *two);
|
||||
int compare_addresses(void *one, void *two);
|
||||
|
||||
|
||||
int screenlist_init()
|
||||
{
|
||||
debug("screenlist_init()\n");
|
||||
|
||||
screenlist = LL_new();
|
||||
if(!screenlist)
|
||||
{
|
||||
fprintf(stderr, "screenlist_init: Error allocating list\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
screenlist_action = 0;
|
||||
timer = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int screenlist_shutdown()
|
||||
{
|
||||
debug("screenlist_shutdown()\n");
|
||||
|
||||
LL_Destroy(screenlist);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int screenlist_remove(screen *s)
|
||||
{
|
||||
debug("screenlist_remove()\n");
|
||||
|
||||
if(!LL_Remove(screenlist, s))
|
||||
return -1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
int screenlist_remove_all(screen *s)
|
||||
{
|
||||
int i=0;
|
||||
|
||||
debug("screenlist_remove_all()\n");
|
||||
|
||||
while(LL_Remove(screenlist, s))
|
||||
i++;
|
||||
|
||||
debug("screenlist_remove_all()... got %i\n", i);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
LL * screenlist_getlist()
|
||||
{
|
||||
debug("screenlist_getlist()\n");
|
||||
|
||||
return screenlist;
|
||||
}
|
||||
|
||||
screen * screenlist_current()
|
||||
{
|
||||
char str[256];
|
||||
screen *s;
|
||||
static screen *old_s = NULL;
|
||||
client *c;
|
||||
|
||||
|
||||
//debug("screenlist_current:\n");
|
||||
//LL_dprint(screenlist);
|
||||
|
||||
|
||||
s = (screen *)LL_GetFirst(screenlist);
|
||||
|
||||
// FIXME: Make sure the screen/client exists!
|
||||
if(s != old_s)
|
||||
{
|
||||
debug("screenlist_current: new screen\n");
|
||||
timer = 0;
|
||||
|
||||
// Tell the client we're done with the current screen
|
||||
if(old_s)
|
||||
{
|
||||
//debug("screenlist_current: ignoring old screen\n");
|
||||
LL_Rewind(screenlist);
|
||||
if(old_s != LL_Find(screenlist, compare_addresses, old_s))
|
||||
{
|
||||
debug("screenlist: Didn't find screen 0x%8x!\n", (int)old_s);
|
||||
}
|
||||
else {
|
||||
//debug("screenlist_current: ... sending ignore\n");
|
||||
c = old_s->parent;
|
||||
if(c) // Tell the client we're not listening any more...
|
||||
{
|
||||
sprintf(str, "ignore %s\n", old_s->id);
|
||||
sock_send_string(c->sock, str);
|
||||
}
|
||||
else // The server has the display, so do nothing
|
||||
{
|
||||
}
|
||||
//debug("screenlist_current: ... sent ignore\n");
|
||||
}
|
||||
}
|
||||
if(s)
|
||||
{
|
||||
//debug("screenlist_current: listening to new screen\n");
|
||||
c = s->parent;
|
||||
if(c) // Tell the client we're paying attention...
|
||||
{
|
||||
sprintf(str, "listen %s\n", s->id);
|
||||
sock_send_string(c->sock, str);
|
||||
}
|
||||
else // The server has the display, so do nothing
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
old_s = s;
|
||||
|
||||
//debug("screenlist_current: return %8x\n", s);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int screenlist_add(screen *s)
|
||||
{
|
||||
// TODO: Different queueing modes...
|
||||
return screenlist_add_end(s);
|
||||
}
|
||||
|
||||
screen * screenlist_next()
|
||||
{
|
||||
screen *s;
|
||||
|
||||
//debug("Screenlist_next()\n");
|
||||
|
||||
s = screenlist_current();
|
||||
|
||||
// If we're on hold, don't advance!
|
||||
if(screenlist_action == SCR_HOLD) return s;
|
||||
if(screenlist_action == RENDER_HOLD) return s;
|
||||
|
||||
// Otherwise, reset it to regular operation
|
||||
screenlist_action = 0;
|
||||
|
||||
|
||||
//debug("Screenlist_next: calling handler...\n");
|
||||
|
||||
// Call the selected queuing function...
|
||||
// TODO: Different queueing modes...
|
||||
s = screenlist_next_priority();
|
||||
//s = screenlist_next_roll();
|
||||
|
||||
//debug("Screenlist_next() done\n");
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
screen * screenlist_prev()
|
||||
{
|
||||
screen *s;
|
||||
|
||||
s = screenlist_current();
|
||||
|
||||
// If we're on hold, don't advance!
|
||||
if(screenlist_action == SCR_HOLD) return s;
|
||||
if(screenlist_action == RENDER_HOLD) return s;
|
||||
|
||||
// Otherwise, reset it no regular operation
|
||||
screenlist_action = 0;
|
||||
|
||||
|
||||
// Call the selected queuing function...
|
||||
// TODO: Different queueing modes...
|
||||
s = screenlist_prev_roll();
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
// Adds new screens to the end of the screenlist...
|
||||
int screenlist_add_end(screen *screen)
|
||||
{
|
||||
debug("screenlist_add_end()\n");
|
||||
|
||||
return LL_Push(screenlist, (void *)screen);
|
||||
}
|
||||
|
||||
// Simple round-robin approach to screen cycling...
|
||||
screen * screenlist_next_roll()
|
||||
{
|
||||
//debug("screenlist_next_roll()\n");
|
||||
|
||||
if(LL_UnRoll(screenlist) != 0) return NULL;
|
||||
|
||||
return screenlist_current();
|
||||
}
|
||||
|
||||
// Strict priority queue approach...
|
||||
screen * screenlist_next_priority()
|
||||
{
|
||||
//screen *s, *t;
|
||||
//debug("screenlist_next_priority\n");
|
||||
|
||||
if(LL_UnRoll(screenlist) != 0) return NULL;
|
||||
|
||||
LL_Sort(screenlist, compare_priority);
|
||||
|
||||
return screenlist_current();
|
||||
}
|
||||
|
||||
// Simple round-robin approach to screen cycling...
|
||||
screen * screenlist_prev_roll()
|
||||
{
|
||||
//debug("screenlist_prev_roll()\n");
|
||||
|
||||
if(LL_Roll(screenlist) != 0) return NULL;
|
||||
|
||||
return screenlist_current();
|
||||
}
|
||||
|
||||
|
||||
int compare_priority(void *one, void *two)
|
||||
{
|
||||
screen *a, *b;
|
||||
|
||||
//debug("compare_priority: %8x %8x\n", one, two);
|
||||
|
||||
if(!one) return 0;
|
||||
if(!two) return 0;
|
||||
|
||||
a = (screen *)one;
|
||||
b = (screen *)two;
|
||||
|
||||
//debug("compare_priority: done?\n");
|
||||
|
||||
return (a->priority - b->priority);
|
||||
}
|
||||
|
||||
int compare_addresses(void *one, void *two)
|
||||
{
|
||||
//printf("compare_addresses: 0x%x == 0x%x ???\n", one, two);
|
||||
//if(one == two) printf("Yes!\n");
|
||||
//else printf("No!\n");
|
||||
return (one != two);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef SCREENLIST_H
|
||||
#define SCREENLIST_H
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
|
||||
#define SCR_HOLD 1
|
||||
#define SCR_SKIP 2
|
||||
#define SCR_BACK 3
|
||||
#define RENDER_HOLD 11
|
||||
#define RENDER_SKIP 12
|
||||
#define RENDER_BACK 13
|
||||
|
||||
extern int screenlist_action;
|
||||
extern int timer;
|
||||
|
||||
int screenlist_init();
|
||||
int screenlist_shutdown();
|
||||
|
||||
LL * screenlist_getlist();
|
||||
screen * screenlist_current();
|
||||
|
||||
int screenlist_add(screen *s);
|
||||
screen * screenlist_next();
|
||||
screen * screenlist_prev();
|
||||
|
||||
int screenlist_remove(screen *s);
|
||||
int screenlist_remove_all(screen *s);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,228 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../shared/debug.h"
|
||||
|
||||
#include "drivers/lcd.h"
|
||||
|
||||
#include "clients.h"
|
||||
#include "screen.h"
|
||||
#include "screenlist.h"
|
||||
#include "widget.h"
|
||||
|
||||
#include "serverscreens.h"
|
||||
|
||||
screen *server_screen;
|
||||
char *id = "ClientList";
|
||||
char *name = "Client List";
|
||||
|
||||
char title[256] = "LCDproc Server";
|
||||
char one[256] = "";
|
||||
char two[256] = "";
|
||||
char three[256] = "";
|
||||
|
||||
int server_screen_init()
|
||||
{
|
||||
widget *w;
|
||||
|
||||
debug("server_screen_init\n");
|
||||
|
||||
server_screen = screen_create();
|
||||
|
||||
if(!server_screen)
|
||||
{
|
||||
fprintf(stderr, "server_screen_init: Error allocating screen\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
server_screen->id = id;
|
||||
server_screen->name = name;
|
||||
server_screen->duration = 8; // 1 second, instead of 4...
|
||||
|
||||
// TODO: Error-checking?
|
||||
widget_add(server_screen, "title", "title", NULL, 1);
|
||||
widget_add(server_screen, "one" , "string", NULL, 1);
|
||||
widget_add(server_screen, "two" , "string", NULL, 1);
|
||||
widget_add(server_screen, "three", "string", NULL, 1);
|
||||
|
||||
|
||||
// Now, initialize all the widgets...
|
||||
w = widget_find(server_screen, "title");
|
||||
if(w)
|
||||
{
|
||||
w->text = title;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "server_screen_init: Can't find title\n");
|
||||
}
|
||||
|
||||
w = widget_find(server_screen, "one");
|
||||
if(w)
|
||||
{
|
||||
w->x = 1;
|
||||
w->y = 2;
|
||||
w->text = one;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "server_screen_init: Can't find widget one\n");
|
||||
}
|
||||
|
||||
w = widget_find(server_screen, "two");
|
||||
if(w)
|
||||
{
|
||||
w->x = 1;
|
||||
w->y = 3;
|
||||
w->text = two;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "server_screen_init: Can't find widget two\n");
|
||||
}
|
||||
|
||||
w = widget_find(server_screen, "three");
|
||||
if(w)
|
||||
{
|
||||
w->x = 1;
|
||||
w->y = 4;
|
||||
w->text = three;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "server_screen_init: Can't find widget three\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
// And enqueue the screen
|
||||
screenlist_add(server_screen);
|
||||
|
||||
debug("server_screen_init done\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int update_server_screen(int timer)
|
||||
{
|
||||
client *c;
|
||||
int num_clients;
|
||||
screen *s;
|
||||
int num_screens;
|
||||
|
||||
|
||||
// Draw a title...
|
||||
//strcpy(title, "LCDproc Server");
|
||||
|
||||
|
||||
// Now get info on the number of connected clients...
|
||||
num_clients=0; num_screens=0;
|
||||
LL_Rewind(clients);
|
||||
do {
|
||||
c = LL_Get(clients);
|
||||
if(c)
|
||||
{
|
||||
num_clients++;
|
||||
LL_Rewind(c->data->screenlist);
|
||||
do {
|
||||
s = LL_Get(c->data->screenlist);
|
||||
if(s)
|
||||
{
|
||||
num_screens++;
|
||||
}
|
||||
} while(LL_Next(c->data->screenlist) == 0);
|
||||
}
|
||||
} while(LL_Next(clients) == 0);
|
||||
|
||||
if(lcd.hgt >= 3)
|
||||
{
|
||||
sprintf(one, "Clients: %i", num_clients);
|
||||
sprintf(two, "Screens: %i", num_screens);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(lcd.wid >= 20)
|
||||
sprintf(one, "%i Client%s, %i Screen%s",
|
||||
num_clients, (num_clients==1)?"":"s",
|
||||
num_screens, (num_screens==1)?"":"s");
|
||||
else // 16x2 size
|
||||
sprintf(one, "%i Cli%s, %i Scr%s",
|
||||
num_clients, (num_clients==1)?"":"s",
|
||||
num_screens, (num_screens==1)?"":"s");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int no_screen_screen(int timer)
|
||||
{
|
||||
|
||||
lcd.clear();
|
||||
|
||||
lcd.string(1, 1, "Error: No screen!");
|
||||
|
||||
lcd.flush();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int goodbye_screen()
|
||||
{
|
||||
char
|
||||
*b20 = " ",
|
||||
*t20 = " Thanks for using ",
|
||||
#ifdef LINUX
|
||||
*l20 = " LCDproc and Linux! ",
|
||||
#else
|
||||
*l20 = " LCDproc! ",
|
||||
#endif
|
||||
*b16 = " ",
|
||||
*t16 = "Thanks for using",
|
||||
#ifdef LINUX
|
||||
*l16 = " LCDproc+Linux! ",
|
||||
#else
|
||||
*l16 = " LCDproc! ",
|
||||
#endif
|
||||
*nil = "";
|
||||
|
||||
lcd.clear();
|
||||
|
||||
if(lcd.hgt >= 4)
|
||||
{
|
||||
if(lcd.wid >= 20)
|
||||
{
|
||||
lcd.string(1, 1, b20);
|
||||
lcd.string(1, 2, t20);
|
||||
lcd.string(1, 3, l20);
|
||||
lcd.string(1, 4, b20);
|
||||
}
|
||||
else
|
||||
{
|
||||
lcd.string(1, 1, b16);
|
||||
lcd.string(1, 2, t16);
|
||||
lcd.string(1, 3, l16);
|
||||
lcd.string(1, 4, b16);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(lcd.wid >= 20)
|
||||
{
|
||||
lcd.string(1, 1, t20);
|
||||
lcd.string(1, 2, l20);
|
||||
}
|
||||
else
|
||||
{
|
||||
lcd.string(1, 1, t16);
|
||||
lcd.string(1, 2, l16);
|
||||
}
|
||||
}
|
||||
|
||||
lcd.flush();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef SRVSTATS_H
|
||||
#define SRVSTATS_H
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
|
||||
extern screen *server_screen;
|
||||
|
||||
int server_screen_init();
|
||||
int update_server_screen(int timer);
|
||||
int no_screen_screen(int timer);
|
||||
int goodbye_screen();
|
||||
|
||||
#endif
|
||||
+275
@@ -0,0 +1,275 @@
|
||||
#include <unistd.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "../shared/sockets.h"
|
||||
#include "sock.h"
|
||||
#include "clients.h"
|
||||
#include "../shared/debug.h"
|
||||
|
||||
|
||||
/**************************************************
|
||||
LCDproc sockets code...
|
||||
|
||||
This is messy, and needs to be finished.
|
||||
**************************************************/
|
||||
|
||||
fd_set active_fd_set, read_fd_set;
|
||||
int orig_sock;
|
||||
|
||||
// Length of longest transmission allowed at once...
|
||||
#define MAXMSG 8192
|
||||
|
||||
|
||||
int read_from_client (int filedes);
|
||||
|
||||
|
||||
// Creates a socket in internet space
|
||||
int sock_create_inet_socket(unsigned short int port)
|
||||
{
|
||||
struct sockaddr_in name;
|
||||
int sock;
|
||||
|
||||
debug("sock_create_inet_socket(%i)\n", port);
|
||||
|
||||
/* Create the socket. */
|
||||
//debug("Creating Inet Socket\n");
|
||||
sock = socket (PF_INET, SOCK_STREAM, 0);
|
||||
if (sock < 0)
|
||||
{
|
||||
perror("Error creating socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Give the socket a name. */
|
||||
//debug("Binding Inet Socket\n");
|
||||
name.sin_family = AF_INET;
|
||||
name.sin_port = htons (port);
|
||||
name.sin_addr.s_addr = htonl (INADDR_ANY);
|
||||
if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0)
|
||||
{
|
||||
perror("Error binding socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return sock;
|
||||
|
||||
}
|
||||
|
||||
//int StartSocketServer()
|
||||
int sock_create_server()
|
||||
{
|
||||
int sock;
|
||||
|
||||
debug("sock_create_server()\n");
|
||||
|
||||
/* Create the socket and set it up to accept connections. */
|
||||
sock = sock_create_inet_socket(LCDPORT);
|
||||
if(sock < 0)
|
||||
{
|
||||
perror("sock_create_server: Error creating socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (listen (sock, 1) < 0)
|
||||
{
|
||||
perror("sock_create_server: Listen error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initialize the set of active sockets. */
|
||||
FD_ZERO (&active_fd_set);
|
||||
FD_SET (sock, &active_fd_set);
|
||||
|
||||
orig_sock = sock;
|
||||
|
||||
/*
|
||||
{
|
||||
int val, len, sock;
|
||||
sock = new;
|
||||
|
||||
len = sizeof(int);
|
||||
getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &val, &len);
|
||||
printf("SEND buffer: %i bytes\n", val);
|
||||
|
||||
len = sizeof(int);
|
||||
getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &val, &len);
|
||||
printf("RECV buffer: %i bytes\n", val);
|
||||
}
|
||||
*/
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
|
||||
int sock_poll_clients()
|
||||
{
|
||||
int i;
|
||||
int err;
|
||||
struct sockaddr_in clientname;
|
||||
size_t size;
|
||||
struct timeval t;
|
||||
client *c;
|
||||
|
||||
//debug("sock_poll_clients()\n");
|
||||
|
||||
t.tv_sec = 0;
|
||||
t.tv_usec = 0;
|
||||
|
||||
/* Block until input arrives on one or more active sockets. */
|
||||
read_fd_set = active_fd_set;
|
||||
|
||||
if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, &t) < 0)
|
||||
{
|
||||
perror("sock_poll_clients: Select error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Service all the sockets with input pending. */
|
||||
for (i = 0; i < FD_SETSIZE; ++i)
|
||||
{
|
||||
if (FD_ISSET (i, &read_fd_set))
|
||||
{
|
||||
if (i == orig_sock)
|
||||
{
|
||||
/* Connection request on original socket. */
|
||||
int new;
|
||||
size = sizeof (clientname);
|
||||
new = accept (orig_sock,
|
||||
(struct sockaddr *) &clientname,
|
||||
&size);
|
||||
if (new < 0)
|
||||
{
|
||||
perror("sock_poll_clients: Accept error");
|
||||
return -1;
|
||||
}
|
||||
debug("sock_poll_clients: connect from host %s, port %hd.\n",
|
||||
inet_ntoa (clientname.sin_addr),
|
||||
ntohs (clientname.sin_port));
|
||||
FD_SET (new, &active_fd_set);
|
||||
|
||||
fcntl(new, F_SETFL, O_NONBLOCK);
|
||||
|
||||
|
||||
// TODO: Create new "client" here... (done?)
|
||||
if ( client_create(new) == NULL)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"sock_poll_clients: error creating client %i\n",
|
||||
i);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Data arriving on an already-connected socket. */
|
||||
err = 0;
|
||||
do {
|
||||
debug("sock_poll_clients: reading...\n");
|
||||
err = read_from_client(i);
|
||||
debug("sock_poll_clients: ...done\n");
|
||||
if (err < 0)
|
||||
{
|
||||
// TODO: Destroy a "client" here... (done?)
|
||||
c = client_find_sock(i);
|
||||
if(c)
|
||||
{
|
||||
//sock_send_string(i, "bye\n");
|
||||
client_destroy(c);
|
||||
close (i);
|
||||
FD_CLR (i, &active_fd_set);
|
||||
debug("sock_poll_clients: Closed connection %i\n", i);
|
||||
}
|
||||
else fprintf(stderr,
|
||||
"sock_poll_clients: Can't find client %i\n",
|
||||
i);
|
||||
}
|
||||
} while (err > 0);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int read_from_client (int filedes)
|
||||
{
|
||||
char buffer[MAXMSG];
|
||||
int nbytes, i;
|
||||
client *c;
|
||||
|
||||
// nbytes = read (filedes, buffer, MAXMSG);
|
||||
//debug("read_from_client(%i): reading...\n", filedes);
|
||||
nbytes = sock_recv (filedes, buffer, MAXMSG);
|
||||
//debug("read_from_client(%i): ...done\n", filedes);
|
||||
debug("read_from_client(%i): %i bytes\n", filedes, nbytes);
|
||||
|
||||
|
||||
if (nbytes < 0) // Read error? No data available?
|
||||
{
|
||||
// TODO: check errno here!
|
||||
//fprintf (stderr,"read_from_client: Read error\n");
|
||||
return 0;
|
||||
}
|
||||
else if (nbytes == 0) // EOF
|
||||
return -1;
|
||||
else if (nbytes > (MAXMSG - (MAXMSG / 8))) // Very noisy client...
|
||||
{
|
||||
sock_send_string(filedes, "huh? Shut up!\n");
|
||||
return -1;
|
||||
}
|
||||
else // Data Read
|
||||
{
|
||||
buffer[nbytes] = 0;
|
||||
// Now, replace zeros with linefeeds...
|
||||
for(i=0; i<nbytes; i++)
|
||||
if(buffer[i] == 0) buffer[i] = '\n';
|
||||
// Enqueue a "client message" here...
|
||||
c = client_find_sock(filedes);
|
||||
if(c)
|
||||
{
|
||||
client_add_message(c, buffer);
|
||||
}
|
||||
else fprintf(stderr, "read_from_client: Can't find client %i\n",
|
||||
filedes);
|
||||
|
||||
debug("read_from_client: got message: `%s'\n", buffer);
|
||||
return nbytes;
|
||||
}
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
// FIXME: This talks to all open files, including
|
||||
// stdin, stdout, stderr, the LCD, etc...
|
||||
// BUT it should only talk to sockets!
|
||||
int sock_close_all()
|
||||
{
|
||||
int i;
|
||||
|
||||
debug("sock_close_all()\n");
|
||||
|
||||
for (i = 0; i < FD_SETSIZE; i++)
|
||||
{
|
||||
// TODO: Destroy a "client" here...? Nope.
|
||||
sock_send_string(i, "bye\n");
|
||||
close (i);
|
||||
FD_CLR (i, &active_fd_set);
|
||||
debug("sock_close_all: Closed connection %i\n", i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef SOCKETS_H
|
||||
#define SOCKETS_H
|
||||
|
||||
|
||||
#include "../shared/sockets.h"
|
||||
|
||||
|
||||
typedef struct sockaddr_in sockaddr_in;
|
||||
|
||||
|
||||
// Server functions...
|
||||
int sock_create_server();
|
||||
int sock_create_inet_socket(unsigned short int port);
|
||||
int sock_poll_clients();
|
||||
int sock_close_all();
|
||||
int read_from_client (int filedes);
|
||||
|
||||
#endif
|
||||
+391
@@ -0,0 +1,391 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../shared/sockets.h"
|
||||
#include "../shared/debug.h"
|
||||
|
||||
#include "screen.h"
|
||||
#include "widget.h"
|
||||
|
||||
|
||||
char *types[] = {"none",
|
||||
"string",
|
||||
"hbar",
|
||||
"vbar",
|
||||
"icon",
|
||||
"title",
|
||||
"scroller",
|
||||
"frame",
|
||||
"num",
|
||||
//"",
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
static widget * widget_finder(LL *list, char *id);
|
||||
static int widget_remover(LL *list, widget *w);
|
||||
|
||||
|
||||
widget * widget_create()
|
||||
{
|
||||
widget *w;
|
||||
|
||||
debug("widget_create()\n");
|
||||
|
||||
w = malloc(sizeof(widget));
|
||||
if(!w)
|
||||
{
|
||||
fprintf(stderr, "widget_create: Error allocating widget\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
w->id = NULL;
|
||||
w->type = 0;
|
||||
w->x = 1;
|
||||
w->y = 1;
|
||||
w->wid = 0;
|
||||
w->hgt = 0;
|
||||
w->left = 1;
|
||||
w->top = 1;
|
||||
w->right = 0;
|
||||
w->bottom = 0;
|
||||
w->length = 1;
|
||||
w->speed = 1;
|
||||
w->text = NULL;
|
||||
w->kids = NULL;
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
int widget_destroy(widget *w)
|
||||
{
|
||||
LL * list;
|
||||
widget *foo;
|
||||
|
||||
if(!w) return -1;
|
||||
|
||||
debug("widget_destroy(%s)\n", w->id);
|
||||
|
||||
if(w->id) free(w->id);
|
||||
//debug("widget_destroy: id...\n");
|
||||
if(w->text) free(w->text);
|
||||
//debug("widget_destroy: text...\n");
|
||||
|
||||
// TODO: Free kids!
|
||||
if(w->kids)
|
||||
{
|
||||
list = w->kids;
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
foo = LL_Get(list);
|
||||
if(foo)
|
||||
widget_destroy(foo);
|
||||
} while( 0 == LL_Next(list) );
|
||||
|
||||
LL_Destroy(list);
|
||||
w->kids = NULL;
|
||||
}
|
||||
|
||||
free(w);
|
||||
//debug("widget_destroy: widget...\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
widget * widget_find(screen *s, char *id)
|
||||
{
|
||||
//widget *w, *err;
|
||||
|
||||
if(!s) return NULL;
|
||||
if(!id) return NULL;
|
||||
|
||||
debug("widget_find(%s)\n", id);
|
||||
|
||||
return widget_finder(s->widgets, id);
|
||||
/*
|
||||
LL_Rewind(s->widgets);
|
||||
do {
|
||||
w = LL_Get(s->widgets);
|
||||
if( (w) && (0 == strcmp(w->id, id)))
|
||||
{
|
||||
debug("widget_find: Found %s\n", id);
|
||||
return w;
|
||||
}
|
||||
// TODO: Search kids too!
|
||||
if( w->type == WID_FRAME )
|
||||
{
|
||||
err = widget_finder(w->kids, id);
|
||||
if(err) return err;
|
||||
}
|
||||
|
||||
} while(LL_Next(s->widgets) == 0);
|
||||
|
||||
return NULL;
|
||||
*/
|
||||
}
|
||||
|
||||
widget * widget_finder(LL *list, char *id)
|
||||
{
|
||||
widget *w, *err;
|
||||
|
||||
if(!list) return NULL;
|
||||
if(!id) return NULL;
|
||||
|
||||
debug("widget_finder(%s)\n", id);
|
||||
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
//debug("widget_finder: Iteration\n");
|
||||
w = LL_Get(list);
|
||||
if(w)
|
||||
{
|
||||
//debug("widget_finder: ...\n");
|
||||
if(0 == strcmp(w->id, id))
|
||||
{
|
||||
debug("widget_finder: Found %s\n", id);
|
||||
return w;
|
||||
}
|
||||
// Search kids recursively
|
||||
//debug("widget_finder: ...\n");
|
||||
if( w->type == WID_FRAME )
|
||||
{
|
||||
err = widget_finder(w->kids, id);
|
||||
if(err) return err;
|
||||
}
|
||||
//debug("widget_finder: ...\n");
|
||||
}
|
||||
|
||||
} while(LL_Next(list) == 0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int widget_add(screen *s, char *id, char *type, char *in, int sock)
|
||||
{
|
||||
int i;
|
||||
int valid=0;
|
||||
int wid_type=0;
|
||||
widget *w, *parent;
|
||||
LL *list;
|
||||
|
||||
debug("widget_add(%s, %s, %s)\n", id, type, in);
|
||||
|
||||
|
||||
if(!s) return -1;
|
||||
if(!id) return -1;
|
||||
|
||||
list = s->widgets;
|
||||
|
||||
|
||||
if(0 == strcmp(id, "heartbeat"))
|
||||
{
|
||||
s->heartbeat = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Make sure this screen doesn't already exist...
|
||||
w = widget_find(s, id);
|
||||
if(w)
|
||||
{
|
||||
// already exists
|
||||
sock_send_string(sock,
|
||||
"huh? You already have a widget with that id#\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Make sure the container, if any, is real
|
||||
if(in)
|
||||
{
|
||||
parent = widget_find(s, in);
|
||||
if(!parent)
|
||||
{
|
||||
// no frame to use as parent
|
||||
sock_send_string(sock, "huh? Frame doesn't exist\n");
|
||||
return 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(parent->type == WID_FRAME)
|
||||
{
|
||||
list = parent->kids;
|
||||
if(!list) fprintf(stderr, "widget_add: Parent has no kids\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// no frame to use as parent
|
||||
sock_send_string(sock, "huh? Not a frame\n");
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure it's a valid widget type
|
||||
for(i=1; types[i]; i++)
|
||||
{
|
||||
if(0 == strcmp(types[i], type))
|
||||
{
|
||||
valid=1;
|
||||
wid_type=i;
|
||||
}
|
||||
}
|
||||
if(!valid)
|
||||
{
|
||||
// invalid widget type
|
||||
sock_send_string(sock, "huh? Invalid widget type\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
debug("widget_add: making widget\n");
|
||||
|
||||
|
||||
// Now, make it...
|
||||
w = widget_create();
|
||||
if(!w)
|
||||
{
|
||||
fprintf(stderr, "widget_add: Error creating widget\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
w->id = strdup(id);
|
||||
if(!w->id)
|
||||
{
|
||||
fprintf(stderr, "widget_add: Error allocating id\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
w->type = wid_type;
|
||||
|
||||
// Set up the container's widget list...
|
||||
if(w->type == WID_FRAME)
|
||||
{
|
||||
if(!w->kids)
|
||||
{
|
||||
w->kids = LL_new();
|
||||
if(!w->kids)
|
||||
{
|
||||
fprintf(stderr, "widget_add: error allocating kids for frame\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: Check for errors here?
|
||||
LL_Push(list, (void *)w);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int widget_remove(screen *s, char *id, int sock)
|
||||
{
|
||||
widget *w;
|
||||
LL *list;
|
||||
|
||||
debug("widget_remove(%s)\n", id);
|
||||
|
||||
if(!s) return -1;
|
||||
if(!id) return -1;
|
||||
|
||||
list = s->widgets;
|
||||
|
||||
|
||||
if(0 == strcmp(id, "heartbeat"))
|
||||
{
|
||||
s->heartbeat = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Make sure this screen *does* exist...
|
||||
w = widget_find(s, id);
|
||||
if(!w)
|
||||
{
|
||||
sock_send_string(sock,
|
||||
"huh? You don't have a widget with that id#\n");
|
||||
debug("widget_remove: Error finding widget %s\n", id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
// TODO: Check for errors here?
|
||||
// TODO: Make this work with frames...
|
||||
// LL_Remove(list, (void *)w);
|
||||
|
||||
|
||||
// TODO: Check for errors here?
|
||||
// widget_destroy(w);
|
||||
*/
|
||||
|
||||
return widget_remover(list, w);
|
||||
|
||||
// return 0;
|
||||
}
|
||||
|
||||
|
||||
int widget_remover(LL *list, widget *w)
|
||||
{
|
||||
widget *foo, *bar;
|
||||
int err;
|
||||
|
||||
debug("widget_remover\n");
|
||||
|
||||
if(!list) return 0;
|
||||
if(!w) return 0;
|
||||
|
||||
|
||||
// Search through the list...
|
||||
LL_Rewind(list);
|
||||
do {
|
||||
// Test each item
|
||||
foo = LL_Get(list);
|
||||
if(foo)
|
||||
{
|
||||
// Frames require recursion to search and/or destroy
|
||||
if(foo->type == WID_FRAME)
|
||||
{
|
||||
// If removing a frame, kill all its kids, too...
|
||||
if(foo == w)
|
||||
{
|
||||
if(!foo->kids)
|
||||
{
|
||||
fprintf(stderr, "widget_remover: frame has no kids\n");
|
||||
}
|
||||
else // Kill the kids...
|
||||
{
|
||||
LL_Rewind(foo->kids);
|
||||
do {
|
||||
bar = LL_Get(foo->kids);
|
||||
err = widget_remover(foo->kids, bar);
|
||||
} while(0 == LL_Next(foo->kids));
|
||||
|
||||
// Then kill the parent...
|
||||
LL_Remove(list, (void *)w);
|
||||
widget_destroy(w);
|
||||
}
|
||||
|
||||
}
|
||||
else // Otherwise, search the frame recursively...
|
||||
{
|
||||
if(!foo->kids)
|
||||
{
|
||||
fprintf(stderr, "widget_remover: frame has no kids\n");
|
||||
}
|
||||
else err = widget_remover(foo->kids, w);
|
||||
|
||||
}
|
||||
}
|
||||
else // If not a frame, remove it if it matches...
|
||||
{
|
||||
if(foo == w)
|
||||
{
|
||||
LL_Remove(list, (void *)w);
|
||||
widget_destroy(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(0 == LL_Next(list));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef WIDGET_H
|
||||
#define WIDGET_H
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
typedef struct widget
|
||||
{
|
||||
char *id;
|
||||
int type;
|
||||
// some sort of data here...
|
||||
int x, y; // Position
|
||||
int wid, hgt; // Size
|
||||
int left, top, right, bottom; // bounding rectangle
|
||||
int length; // size or direction
|
||||
int speed; // For scroller...
|
||||
char *text; // text or binary data
|
||||
LL *kids; // Frames can contain more widgets...
|
||||
} widget;
|
||||
|
||||
// These correspond to the index into the "types" array...
|
||||
#define WID_NONE 0
|
||||
#define WID_STRING 1
|
||||
#define WID_HBAR 2
|
||||
#define WID_VBAR 3
|
||||
#define WID_ICON 4
|
||||
#define WID_TITLE 5
|
||||
#define WID_SCROLLER 6
|
||||
#define WID_FRAME 7
|
||||
#define WID_NUM 8
|
||||
|
||||
#define WID_MAX_DIR 4
|
||||
|
||||
extern char *types[];
|
||||
|
||||
|
||||
widget * widget_create();
|
||||
int widget_destroy(widget *w);
|
||||
|
||||
widget * widget_find(screen *s, char *id);
|
||||
|
||||
int widget_add(screen *s, char *id, char *type, char *in, int sock);
|
||||
int widget_remove(screen *s, char *id, int sock);
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user