Files
lcdproc/server/drivers/lcd.c
T
2001-11-29 14:09:13 +00:00

711 lines
15 KiB
C

/*
* Driver master (lcd.c)
*
* This code actually sets up the drivers as requested,
* initializes drivers, and allocates memory for drivers.
*
*/
/*
* These drivers don't seem to be in the build process yet;
* so here we fake it and define these variables...!
*
* Not pretty, but it works and its up here so everyone
* can see... and you can yank them out of the comments
* to make it work.
*/
// #define SVGALIB_DRV
// #define T6963_DRV
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
#include <string.h>
#include <sys/errno.h>
#include <syslog.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "shared/LL.h"
#include "shared/report.h"
#include "lcd.h"
static int lcd_drv_init (lcd_logical_driver * driver, char *args);
static void lcd_drv_close ();
static void lcd_drv_clear ();
static void lcd_drv_flush ();
static void lcd_drv_string (int x, int y, char *string);
static void lcd_drv_chr (int x, int y, char c);
static int lcd_drv_contrast (int contrast);
static void lcd_drv_backlight (int on);
static void lcd_drv_output (int on);
static void lcd_drv_init_vbar ();
static void lcd_drv_init_hbar ();
static void lcd_drv_init_num ();
static void lcd_drv_num (int x, int num);
static void lcd_drv_set_char (int n, char *dat);
static void lcd_drv_vbar (int x, int len);
static void lcd_drv_hbar (int x, int y, int len);
static void lcd_drv_icon (int which, char dest);
static void lcd_drv_flush_box (int lft, int top, int rgt, int bot);
static void lcd_drv_draw_frame ();
static char lcd_drv_getkey ();
static char lcd_drv_getkey_loop ();
static char *lcd_drv_getinfo ();
static void lcd_drv_heartbeat (int type);
/*
* Add all of the driver's header files in...
* but WHY?
*
*/
#ifdef LCDM001_DRV
#include "lcdm001.h"
#endif
#ifdef MTXORB_DRV
#include "MtxOrb.h"
#endif
#ifdef CFONTZ_DRV
#include "CFontz.h"
#endif
#ifdef LB216_DRV
#include "lb216.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
#ifdef LIRCIN_DRV
#include "lircin.h"
#endif
#ifdef BAYRAD_DRV
#include "bayrad.h"
#endif
#ifdef SED1330_DRV
#include "sed1330.h"
#endif
#ifdef SED1520_DRV
#include "sed1520.h"
#endif
#ifdef STV5730_DRV
#include "stv5730.h"
#endif
#ifdef GLK_DRV
#include "glk.h"
#endif
#ifdef SVGALIB_DRV
#include "svgalib_drv.h"
#endif
#ifdef T6963_DRV
#include "t6963.h"
#endif
// Make program more readable and understandable;
// hide details...
//#define ResetList(a) LL_Rewind(a)
//#define GetDriverData(a) ((lcd_logical_driver *)LL_Get(a))
//#define NextDriver(a) (LL_Next(a))
//#define MoreDrivers(a) (LL_Next(a) == 0)
//#define DriverPresent(a) (a)
//#define FunctionPresent(a) ((a) != 0)
// TODO: Make a Windows server, and clients...?
lcd_logical_driver lcd, *lcd_root = NULL, *lcd_ptr = NULL;
// TODO: Add multiple names for the same driver?
//
// Would allow the use of "MatrixOrbital" (for example) or
// "Joystick" or "CrystalFontz" or similar more memorable
// names, as well as older ones...
//
lcd_physical_driver drivers[] = {
#ifdef LCDM001_DRV
{"lcdm001", lcdm001_init,},
{"LCDM001", lcdm001_init,},
#endif
#ifdef MTXORB_DRV
{"MtxOrb", MtxOrb_init,},
{"MatrixOrbital", MtxOrb_init,},
#endif
#ifdef CFONTZ_DRV
{"CFontz", CFontz_init,},
{"CrystalFontz", CFontz_init,},
#endif
#ifdef HD44780_DRV
{"HD44780", HD44780_init,},
{"Hitachi", HD44780_init,},
#endif
#ifdef SLI_DRV
{"sli", sli_init,},
{"Wirz", sli_init,},
#endif
#ifdef LB216_DRV
{"LB216", LB216_init,},
#endif
#ifdef TEXT_DRV
{"text", text_init,},
#endif
#ifdef DEBUG_DRV
{"debug", debug_init,},
#endif
#ifdef CURSES_DRV
{"curses", curses_drv_init,},
{"ncurses", curses_drv_init,},
#endif
#ifdef JOY_DRV
{"joy", joy_init,},
{"joystick", joy_init,},
#endif
#ifdef IRMANIN_DRV
{"irmanin", irmanin_init,},
#endif
#ifdef LIRCIN_DRV
{"lircin", lircin_init,},
#endif
#ifdef BAYRAD_DRV
{"BayRAD", bayrad_init,},
#endif
#ifdef GLK_DRV
{"glk", glk_init,},
{"glc", glk_init,},
#endif
#ifdef SED1330_DRV
{"sed1330", sed1330_init,},
#endif
#ifdef SED1520_DRV
{"sed1520", sed1520_init,},
#endif
#ifdef STV5730_DRV
{"stv5730", stv5730_init,},
#endif
#ifdef SVGALIB_DRV
{"svgalib", svgalib_drv_init,},
{"vga", svgalib_drv_init,},
{"svga", svgalib_drv_init,},
#endif
#ifdef T6963_DRV
{"t6963", t6963_init,},
{"Toshiba", t6963_init,},
#endif
{NULL, NULL,},
};
LinkedList *list;
#define CurrentDriver (drivers[i].name)
#define NextDriver (drivers[i+1].name)
void
lcd_list_drivers (void) {
int i = 0;
printf("\t");
while (CurrentDriver != NULL) {
printf("%s", CurrentDriver);
if (NextDriver != NULL)
printf(", ");
i++;
if ((i % 8) == 0)
printf("\n\t");
}
printf("\n");
}
////////////////////////////////////////////////////////////
// This function initializes a few basics as well as the
// "base" array. To initialize a specific driver, use the
// lcd_add_driver() function.
//
// This was eliminated; everything
// done here is to be replaced by the use of lcd_add_driver()...
int
lcd_init (char *args)
{
return 0;
}
// This sets up all of the "wrapper" driver functions
// which call all of the drivers in turn.
//
static int
lcd_drv_init (struct lcd_logical_driver *driver, char *args)
{
driver->wid = LCD_STD_WIDTH;
driver->hgt = LCD_STD_HEIGHT;
driver->cellwid = LCD_STD_CELL_WIDTH;
driver->cellhgt = LCD_STD_CELL_HEIGHT;
driver->framebuf = NULL;
driver->nextkey = NULL;
driver->daemonize = 1;
// Set up these wrapper functions...
driver->clear = lcd_drv_clear;
driver->string = lcd_drv_string;
driver->chr = lcd_drv_chr;
driver->vbar = lcd_drv_vbar;
driver->hbar = lcd_drv_hbar;
driver->init_num = lcd_drv_init_num;
driver->num = lcd_drv_num;
driver->init = lcd_drv_init;
driver->close = lcd_drv_close;
driver->flush = lcd_drv_flush;
driver->flush_box = lcd_drv_flush_box;
driver->contrast = lcd_drv_contrast;
driver->backlight = lcd_drv_backlight;
driver->output = lcd_drv_output;
driver->set_char = lcd_drv_set_char;
driver->icon = lcd_drv_icon;
driver->init_vbar = lcd_drv_init_vbar;
driver->init_hbar = lcd_drv_init_hbar;
driver->draw_frame = lcd_drv_draw_frame;
driver->getkey = lcd_drv_getkey;
driver->getinfo = lcd_drv_getinfo;
driver->heartbeat = lcd_drv_heartbeat;
return 1; // 1 is arbitrary. (must be 1 or more)
}
#define ChkNull(a,b,c) if ((driver->a) == 0) { syslog(LOG_INFO, "warning: %s: null entries deprecated!", (c)); driver->a = (b); }
#define ChkBaseDrv(a,b,c) if ((driver->a) == (void *) -1) { syslog(LOG_ERR, "warning: %s: base driver has been REMOVED!", (c)); driver->a = (b); }
static int
lcd_drv_patch_init (struct lcd_logical_driver *driver)
{
// These are to patch drivers that use "NULL" as a valid value...
ChkNull(clear, lcd_drv_clear, "clear");
ChkNull(string, lcd_drv_string, "string");
ChkNull(chr, lcd_drv_chr, "chr");
ChkNull(vbar, lcd_drv_vbar, "vbar");
ChkNull(hbar, lcd_drv_hbar, "hbar");
ChkNull(init_num, lcd_drv_init_num, "init_num");
ChkNull(num, lcd_drv_num, "num");
ChkNull(init, lcd_drv_init, "init");
ChkNull(close, lcd_drv_close, "close");
ChkNull(flush, lcd_drv_flush, "flush");
ChkNull(flush_box, lcd_drv_flush_box, "flush_box");
ChkNull(contrast, lcd_drv_contrast, "contrast");
ChkNull(backlight, lcd_drv_backlight, "backlight");
ChkNull(output, lcd_drv_output, "output");
ChkNull(set_char, lcd_drv_set_char, "set_char");
ChkNull(icon, lcd_drv_icon, "icon");
ChkNull(init_vbar, lcd_drv_init_vbar, "init_vbar");
ChkNull(init_hbar, lcd_drv_init_hbar, "init_hbar");
ChkNull(draw_frame, lcd_drv_draw_frame, "draw_frame");
ChkNull(getkey, lcd_drv_getkey, "getkey");
ChkNull(getinfo, lcd_drv_getinfo, "getinfo");
ChkNull(heartbeat, lcd_drv_heartbeat, "heartbeat");
// Now check for base driver entries...;
ChkBaseDrv(clear, lcd_drv_clear, "clear");
ChkBaseDrv(string, lcd_drv_string, "string");
ChkBaseDrv(chr, lcd_drv_chr, "chr");
ChkBaseDrv(vbar, lcd_drv_vbar, "vbar");
ChkBaseDrv(hbar, lcd_drv_hbar, "hbar");
ChkBaseDrv(init_num, lcd_drv_init_num, "init_num");
ChkBaseDrv(num, lcd_drv_num, "num");
ChkBaseDrv(init, lcd_drv_init, "init");
ChkBaseDrv(close, lcd_drv_close, "close");
ChkBaseDrv(flush, lcd_drv_flush, "flush");
ChkBaseDrv(flush_box, lcd_drv_flush_box, "flush_box");
ChkBaseDrv(contrast, lcd_drv_contrast, "contrast");
ChkBaseDrv(backlight, lcd_drv_backlight, "backlight");
ChkBaseDrv(output, lcd_drv_output, "output");
ChkBaseDrv(set_char, lcd_drv_set_char, "set_char");
ChkBaseDrv(icon, lcd_drv_icon, "icon");
ChkBaseDrv(init_vbar, lcd_drv_init_vbar, "init_vbar");
ChkBaseDrv(init_hbar, lcd_drv_init_hbar, "init_hbar");
ChkBaseDrv(draw_frame, lcd_drv_draw_frame, "draw_frame");
ChkBaseDrv(getkey, lcd_drv_getkey, "getkey");
ChkBaseDrv(getinfo, lcd_drv_getinfo, "getinfo");
ChkBaseDrv(heartbeat, lcd_drv_heartbeat, "heartbeat");
return 0;
}
/*
* This function can be replaced later with something
* that utilizes the results of dynamic library loading
*
*/
void *
lcd_find_init (char *driver) {
int i;
if (!driver)
return NULL;
for (i = 0; drivers[i].name; i++) {
if (strcasecmp(driver, drivers[i].name) == 0) {
return (*drivers[i].init);
}
}
return NULL;
}
// TODO: lcd_remove_driver()
struct lcd_logical_driver *
lcd_allocate_driver () {
struct lcd_logical_driver *driver;
//int driver_size;
// This bit of fakery allows us to use lcd as the first
// allocated buffer, which is what everything currently uses for
// output in the main server code.
#define FirstTime (lcd_ptr->framebuf == NULL)
if ((driver = malloc(sizeof(lcd_logical_driver))) == NULL) {
syslog(LOG_ERR, "error allocating driver space!");
return NULL;
}
if (lcd_root == NULL)
lcd_root = driver;
if (lcd_ptr == NULL)
lcd_ptr = driver;
return driver;
}
// This initializes the specified driver and sends parameters to
// it. This is the function which calls, for example,
// MtxOrb_init. The specifics come from the drivers[] array.
static char (*main_getkey) () = NULL;
int
lcd_add_driver (char *driver, char *args)
{
int i;
char buf[80];
int (*init_driver) ();
lcd_logical_driver *ptr = NULL;
lcd_logical_driver *add = NULL;
if (!driver)
return -1;
if ((init_driver = (void *) lcd_find_init(driver)) != NULL) {
snprintf(buf, sizeof(buf), "adding %s driver", driver);
syslog(LOG_INFO, buf);
// This creates an instance of the lcd structure specific to the
// driver... it is passed to the driver's init routine...
if ((add = lcd_allocate_driver()) == NULL)
return -1;
memset (add, 0, sizeof (lcd_logical_driver));
// Default settings for the driver...
lcd_drv_init(add, NULL);
i = init_driver (add, args);
if (!add->framebuf) {
if ((add->framebuf = malloc (add->wid * add->hgt)) == NULL) {
snprintf (buf, sizeof(buf), "couldn't allocate framebuffer of %d chars for driver \"%s\"",
(add->wid * add->hgt), driver);
syslog (LOG_ERR, buf);
// free (add);
return -1;
}
}
memset (add->framebuf, ' ', (add->wid * add->hgt));
// Now patch up the returned driver structure
// before returning
lcd_drv_patch_init (add); // patches drivers that think NULL is okay...
if (main_getkey == NULL) {
// Patch the getkey with the getkey loop...
main_getkey = add->getkey;
add->getkey = lcd_drv_getkey_loop;
add->nextkey = NULL;
} else {
// Tack additional drivers onto the getkey list...
ptr = lcd_root;
while (ptr->nextkey)
ptr = ptr->nextkey;
// ptr now points to a driver which contains
// a nextkey which is NULL... add the new
// driver in.
ptr->nextkey = add;
}
return i;
} else {
snprintf(buf, sizeof(buf), "invalid driver: %s", driver);
syslog(LOG_ERR, buf);
}
return -1;
}
// TODO: Put lcd_shutdown in the shutdown function...
int
lcd_shutdown ()
{
//lcd_logical_driver *driver;
// This does not shutdown any input sources;
// is that sufficient?
lcd_root->close ();
return 0;
}
//////////////////////////////////////////////////////////////////////
// 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.
//////////////////////////////////////////////////////////////////////
/*
* The functions below are null functions which are used
* when a particular driver does not set them.
*
*/
// lcd_drv_close ()
// lcd_drv_clear ()
// lcd_drv_flush ()
// lcd_drv_string (int x, int y, char string[])
// lcd_drv_chr (int x, int y, char c)
// lcd_drv_contrast (int contrast)
// lcd_drv_backlight (int on)
// lcd_drv_output (int on)
// lcd_drv_init_vbar ()
// lcd_drv_init_hbar ()
// lcd_drv_init_num ()
// lcd_drv_num (int x, int num)
// lcd_drv_set_char (int n, char *dat)
// lcd_drv_vbar (int x, int len)
// lcd_drv_hbar (int x, int y, int len)
// lcd_drv_icon (int which, char dest)
// lcd_drv_flush_box (int lft, int top, int rgt, int bot)
// lcd_drv_draw_frame (char *dat)
// lcd_drv_getkey ()
// lcd_drv_getinfo ()
static void
lcd_drv_close ()
{
;
}
static void
lcd_drv_clear ()
{
;
}
static void
lcd_drv_flush ()
{
;
}
static void
lcd_drv_string (int x, int y, char *string)
{
;
}
static void
lcd_drv_chr (int x, int y, char c)
{
;
}
static int
lcd_drv_contrast (int contrast)
{
return -1;
}
static void
lcd_drv_backlight (int on)
{
;
}
static void
lcd_drv_output (int on)
{
;
}
static void
lcd_drv_init_vbar ()
{
;
}
static void
lcd_drv_init_hbar ()
{
;
}
static void
lcd_drv_init_num ()
{
;
}
static void
lcd_drv_num (int x, int num)
{
;
}
static void
lcd_drv_set_char (int n, char *dat)
{
;
}
static void
lcd_drv_vbar (int x, int len)
{
;
}
static void
lcd_drv_hbar (int x, int y, int len)
{
;
}
static void
lcd_drv_icon (int which, char dest)
{
;
}
static void
lcd_drv_flush_box (int lft, int top, int rgt, int bot)
{
;
}
static void
lcd_drv_draw_frame (char *dat)
{
;
}
static char *
lcd_drv_getinfo ()
{
return NULL;
}
static char
lcd_drv_getkey ()
{
return 0;
}
// This loops through all defined getkeys, returning
// the first input that it finds, if any.
static char
lcd_drv_getkey_loop () {
lcd_logical_driver *driver;
char c;
if ((c = main_getkey()) != 0)
return c;
driver = lcd_root;
while ((driver = driver->nextkey) != NULL)
if ((c = driver->getkey()) > 0)
return c;
return 0;
}
static void
lcd_drv_heartbeat (int type)
{
;
}