Initial revision

This commit is contained in:
William Ferrell
1999-12-09 23:15:14 +00:00
commit 2635c3085d
139 changed files with 24298 additions and 0 deletions
+52
View File
@@ -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 . &
+89
View File
@@ -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;
}
+26
View File
@@ -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
+986
View File
@@ -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;
}
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
+41
View File
@@ -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
+27
View File
@@ -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
+266
View File
@@ -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;
}
+40
View File
@@ -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
+718
View File
@@ -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);
*/
}
+26
View File
@@ -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
+92
View File
@@ -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
+45
View File
@@ -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
+31
View File
@@ -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
+322
View File
@@ -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;
}
+24
View File
@@ -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
+288
View File
@@ -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;
}
+26
View File
@@ -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
+311
View File
@@ -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;
}
+119
View File
@@ -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
+562
View File
@@ -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]);
}
}
}
+49
View File
@@ -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
+21
View File
@@ -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
}
}
+218
View File
@@ -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 */
+12
View File
@@ -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
+218
View File
@@ -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;
}
+12
View File
@@ -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
+727
View File
@@ -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;
}
+95
View File
@@ -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
+124
View File
@@ -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 */
+51
View File
@@ -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 ****/
+236
View 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);
}
+25
View File
@@ -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
+562
View File
@@ -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...
}
+33
View File
@@ -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
View File
@@ -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;
}
+9
View File
@@ -0,0 +1,9 @@
#ifndef INPUT_H
#define INPUT_H
// Accepts and uses keypad input while displaying screens...
int handle_input();
#endif
+369
View File
@@ -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);
}
+31
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+16
View File
@@ -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
View File
@@ -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;
}
+7
View File
@@ -0,0 +1,7 @@
#ifndef PARSE_H
#define PARSE_H
// This should be pretty self-explanatory...
int parse_all_client_messages();
#endif
+526
View File
@@ -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;
}
+29
View File
@@ -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
View File
@@ -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;
}
+29
View File
@@ -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
+273
View File
@@ -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);
}
+31
View File
@@ -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
+228
View File
@@ -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;
}
+14
View File
@@ -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
View File
@@ -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;
}
+18
View File
@@ -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
View File
@@ -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;
}
+45
View File
@@ -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