From 991cae8c076d9da475bf833186219b3d2a396f29 Mon Sep 17 00:00:00 2001 From: reinelt <> Date: Sun, 16 Jan 2000 12:17:59 +0000 Subject: [lcd4linux @ 2000-01-16 12:17:59 by reinelt] Initial revision --- Makefile | 12 ++ MatrixOrbital.c | 49 ++++++ config.c | 98 +++++++++++ config.h | 3 + display.c | 57 +++++++ display.h | 30 ++++ filter.c | 117 +++++++++++++ filter.h | 2 + isdn.c | 98 +++++++++++ isdn.h | 1 + lcd2041.c | 314 +++++++++++++++++++++++++++++++++++ lcd2041.h | 14 ++ lcd4linux.c | 499 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lcd4linux.h | 6 + system.c | 306 ++++++++++++++++++++++++++++++++++ system.h | 9 + 16 files changed, 1615 insertions(+) create mode 100644 Makefile create mode 100644 MatrixOrbital.c create mode 100644 config.c create mode 100644 config.h create mode 100644 display.c create mode 100644 display.h create mode 100644 filter.c create mode 100644 filter.h create mode 100644 isdn.c create mode 100644 isdn.h create mode 100644 lcd2041.c create mode 100644 lcd2041.h create mode 100644 lcd4linux.c create mode 100644 lcd4linux.h create mode 100644 system.c create mode 100644 system.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..218e296 --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +CC=gcc -m486 -g -Wall -I. -DVERSION=\"V0.5\" + +all: lcd4linux + +#lcd4linux: lcd4linux.c config.c lcd2041.c system.c isdn.c filter.c Makefile +# ${CC} -lm -o lcd4linux lcd4linux.c config.c lcd2041.c system.c isdn.c filter.c + +lcd4linux: display.c MatrixOrbital.c + ${CC} -lm -o lcd4linux display.c MatrixOrbital.c + +clean: + rm -f lcd4linux *.o *~ diff --git a/MatrixOrbital.c b/MatrixOrbital.c new file mode 100644 index 0000000..38c2d26 --- /dev/null +++ b/MatrixOrbital.c @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "display.h" + + +int MO_init (void) +{ + printf ("initializing MatrixOrbital...\n"); + return 0; +} + +int MO_clear (void) +{ + return 0; +} + +int MO_put (int x, int y, char *text) +{ + return 0; +} + +int MO_bar (int type, int x, int y, int max, int len1, int len2) +{ + return 0; +} + +int MO_flush (void) +{ + return 0; +} + + +#define BARS ( BAR_L | BAR_R | BAR_U | BAR_D | BAR_S ) + +DISPLAY MatrixOrbital[] = { + { "LCD0821", 8, 2, 5, 8, BARS, MO_init, MO_clear, MO_put, MO_bar, MO_flush }, + { "LCD1621", 16, 2, 5, 8, BARS, MO_init, MO_clear, MO_put, MO_bar, MO_flush }, + { "LCD2021", 20, 2, 5, 8, BARS, MO_init, MO_clear, MO_put, MO_bar, MO_flush }, + { "LCD2041", 20, 4, 5, 8, BARS, MO_init, MO_clear, MO_put, MO_bar, MO_flush }, + { "LCD4021", 40, 2, 5, 8, BARS, MO_init, MO_clear, MO_put, MO_bar, MO_flush }, + { "" } +}; + diff --git a/config.c b/config.c new file mode 100644 index 0000000..c55d63c --- /dev/null +++ b/config.c @@ -0,0 +1,98 @@ +#include +#include +#include +#include + +#include "config.h" + +typedef struct { + char *key; + char *val; +} ENTRY; + +static ENTRY *Config=NULL; +static int nConfig=0; + +static char *strip (char *s) +{ + char *p; + + while (isblank(*s)) s++; + for (p=s; *p; p++) { + if (*p=='"') do p++; while (*p && *p!='\n' && *p!='"'); + if (*p=='\'') do p++; while (*p && *p!='\n' && *p!='\''); + if (*p=='#' || *p=='\n') { + *p='\0'; + break; + } + } + for (p--; p>s && isblank(*p); p--) *p='\0'; + return s; +} + +void set_cfg (char *key, char *val) +{ + int i; + + for (i=0; i +#include + +#include "display.h" + +extern DISPLAY MatrixOrbital[]; + +FAMILY Driver[] = { + { "MatrixOrbital", MatrixOrbital }, + { "" } +}; + + +static DISPLAY *Display = NULL; + +int lcd_init (char *display) +{ + int i, j; + for (i=0; Driver[i].name[0]; i++) { + for (j=0; Driver[i].Display[j].name[0]; j++) { + if (strcmp (Driver[i].Display[j].name, display)==0) { + Display=&Driver[i].Display[j]; + return Display->init(); + } + } + } + fprintf (stderr, "lcd_init(%s) failed: no such display\n", display); + return -1; +} + +int lcd_clear (void) +{ + return 0; +} + +int lcd_put (int x, int y, char *text) +{ + return 0; +} + +int lcd_bar (int type, int x, int y, int max, int len1, int len2) +{ + return 0; +} + +int lcd_flush (void) +{ + return 0; +} + +void main (void) { + int i, j; + + lcd_init ("junk"); + lcd_init ("LCD2041"); + +} diff --git a/display.h b/display.h new file mode 100644 index 0000000..0be2d50 --- /dev/null +++ b/display.h @@ -0,0 +1,30 @@ +#define BAR_L 1 +#define BAR_R 2 +#define BAR_U 4 +#define BAR_D 8 +#define BAR_S 256 + +typedef struct { + char name[16]; + int rows; + int cols; + int xres; + int yres; + int bars; + int (*init) (void); + int (*clear) (void); + int (*put) (int x, int y, char *text); + int (*bar) (int type, int x, int y, int max, int len1, int len2); + int (*flush) (void); +} DISPLAY; + +typedef struct { + char name[16]; + DISPLAY *Display; +} FAMILY; + +int lcd_init (char *display); +int lcd_clear (void); +int lcd_put (int x, int y, char *text); +int lcd_bar (int type, int x, int y, int max, int len1, int len2); +int lcd_flush (void); diff --git a/filter.c b/filter.c new file mode 100644 index 0000000..f61a9ed --- /dev/null +++ b/filter.c @@ -0,0 +1,117 @@ +#include +#include +#include +#include +#include + +#include "lcd4linux.h" +#include "filter.h" + +#define SLOTS 64 + +typedef struct { + char *name; + int slots; + struct timeval *time; + double *value; +} FILTER; + +#define SECONDS(x) (x.tv_sec+x.tv_usec/1000000.0) + +double smooth(char *name, int period, double value) +{ + static FILTER *Filter=NULL; + static int nFilter=0; + struct timeval now; + double t, v; + int i, j; + + gettimeofday (&now, NULL); + + for (i=0; iSLOTS) + slots=SLOTS; + + nFilter++; + Filter=realloc(Filter, nFilter*sizeof(FILTER)); + Filter[i].name=strdup(name); + Filter[i].slots=slots; + Filter[i].time=malloc(slots*sizeof(Filter[i].time[0])); + Filter[i].value=malloc(slots*sizeof(Filter[i].value[0])); + for (j=0; j0; j--) { + Filter[i].time[j]=Filter[i].time[j-1]; + Filter[i].value[j]=Filter[i].value[j-1]; + } + Filter[i].time[0]=now; + Filter[i].value[0]=value; + + t = SECONDS(Filter[i].time[0]) - SECONDS(Filter[i].time[Filter[i].slots-1]); + v = Filter[i].value[0]-Filter[i].value[Filter[i].slots-1]; + + if (t==0.0 || v<0.0) + return 0; + else + return v/t; +} + +double damp(char *name, double value) +{ + static FILTER *Filter=NULL; + static int nFilter=0; + struct timeval now; + double max; + int i, j; + + gettimeofday (&now, NULL); + + for (i=0; iSLOTS) + slots=SLOTS; + + nFilter++; + Filter=realloc(Filter, nFilter*sizeof(FILTER)); + Filter[i].name=strdup(name); + Filter[i].slots=slots; + Filter[i].time=malloc(slots*sizeof(Filter[i].time)); + Filter[i].value=malloc(slots*sizeof(Filter[i].value)); + for (j=0; j0; j--) { + double t = SECONDS(Filter[i].time[j]) - SECONDS(Filter[i].time[j-1]); + Filter[i].time[j]=Filter[i].time[j-1]; + Filter[i].value[j]=Filter[i].value[j-1]*exp(-t/tau); + if (Filter[i].value[j]>max) max=Filter[i].value[j]; + } + + Filter[i].time[0]=now; + Filter[i].value[0]=value; + + return max; +} diff --git a/filter.h b/filter.h new file mode 100644 index 0000000..a3b44a4 --- /dev/null +++ b/filter.h @@ -0,0 +1,2 @@ +double smooth (char *name, int period, double value); +double damp (char *name, double value); diff --git a/isdn.c b/isdn.c new file mode 100644 index 0000000..fab470a --- /dev/null +++ b/isdn.c @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "isdn.h" +#include "filter.h" +#include "lcd4linux.h" + +typedef struct { + unsigned long in; + unsigned long out; +} CPS; + + +static int Usage (void) +{ + static int fd=0; + char buffer[4096], *p; + int i, usage; + + if (fd==-1) return 0; + + fd=open ("/dev/isdninfo", O_RDONLY | O_NDELAY); + if (fd==-1) { + perror ("open(/dev/isdninfo) failed"); + return 0; + } + + if (read (fd, buffer, sizeof(buffer))==-1) { + perror ("read(/dev/isdninfo) failed"); + fd=-1; + return 0; + } + + if (close(fd)==-1) { + perror ("close(/dev/isdninfo) failed"); + fd=-1; + return 0; + } + + p=strstr(buffer, "usage:"); + if (p==NULL) { + fprintf (stderr, "parse(/dev/isdninfo) failed: no usage line\n"); + fd=-1; + return 0; + } + p+=6; + + usage=0; + for (i=0; i +#include +#include +#include +#include +#include +#include + +#include "lcd2041.h" + +#define BAR_HORI 1 +#define BAR_VERT 2 +#define BAR_DUAL 3 + +static int lcd; +static char *lcd_device=NULL; +static int bar_mode=0; + +typedef struct { + int l1; + int l2; + int chr; +} SEGMENT; + +typedef struct { + int l1; + int l2; + int lru; +} CHARACTER; + +static SEGMENT Segment[COLS+1][ROWS+1]; +static CHARACTER Character[CHAR]; + +static int lcd_open(void) +{ + int fd; + struct termios portset; + + fd = open(lcd_device, O_RDWR | O_NOCTTY | O_NDELAY); + if (fd==-1) { + fprintf (stderr, "open(%s) failed: %s\n", lcd_device, strerror(errno)); + return -1; + } + if (tcgetattr(fd, &portset)==-1) { + fprintf (stderr, "tcgetattr(%s) failed: %s\n", lcd_device, strerror(errno)); + return -1; + } + cfmakeraw(&portset); + cfsetospeed(&portset, B19200); + if (tcsetattr(fd, TCSANOW, &portset)==-1) { + fprintf (stderr, "tcsetattr(%s) failed: %s\n", lcd_device, strerror(errno)); + return -1; + } + return fd; +} + + +static void lcd_write (char *string, int len) +{ + if (lcd==-1) return; + if (write (lcd, string, len)==-1) { + if (errno==EAGAIN) { + usleep(1000); + if (write (lcd, string, len)>=0) return; + } + fprintf (stderr, "write(%s) failed: %s\n", lcd_device, strerror(errno)); + } +} + + +void lcd_clear (void) +{ + lcd_write ("\014", 1); +} + + +void lcd_put (int x, int y, char *string) +{ + char buffer[256]; + snprintf (buffer, sizeof(buffer), "\376G%c%c%s", x, y, string); + lcd_write (buffer, strlen(buffer)); +} + +void lcd_hbar (int x, int y, int dir, int max, int len) +{ + char buffer[COLS+5]; + char *p; + + if (bar_mode!=BAR_HORI) { + lcd_write ("\376h", 2); + bar_mode=BAR_HORI; + } + + if (len<1) len=1; + else if (len>max) len=max; + if (dir!=0) len=max-len; + + snprintf (buffer, sizeof(buffer), "\376G%c%c", x, y); + p=buffer+4; + + while (max>0 && p-buffer=XRES) { + *p=dir?32:255; + len-=XRES; + } else { + *p=dir?8-len:len-1; + len=0; + } + max-=XRES; + p++; + } + lcd_write (buffer, p-buffer); +} + + +void lcd_vbar (int x, int y, int dir, int max, int len) +{ + char buffer[6]; + unsigned char c; + + if (bar_mode!=BAR_VERT) { + lcd_write ("\376v", 2); + bar_mode=BAR_VERT; + } + + if (len<1) len=1; + else if (len>max) len=max; + + while (max>0 && y>0) { + if (len==0) { + c=32; + } else if (len>=XRES) { + c=255; + len-=XRES; + } else { + c=len; + len=0; + } + snprintf (buffer, sizeof(buffer), "\376G%c%c%c", x, y, c); + lcd_write (buffer, 5); + max-=XRES; + y--; + } +} + + +static void lcd_dbar_init (void) +{ + int x, y; + + bar_mode=BAR_DUAL; + + for (x=0; xmax) len1=max; + + if (len2<1) len2=1; + else if (len2>max) len2=max; + + while (max>0 && x<=COLS) { + if (len1==0) { + Segment[x][y].l1=0; + } else if (len1>=XRES) { + Segment[x][y].l1=XRES; + len1-=XRES; + } else { + Segment[x][y].l1=len1; + len1=0; + } + if (len2==0) { + Segment[x][y].l2=0; + } else if (len2>=XRES) { + Segment[x][y].l2=XRES; + len2-=XRES; + } else { + Segment[x][y].l2=len2; + len2=0; + } + max-=XRES; + x++; + } +} + +void lcd_dbar_flush (void) +{ + int i, x, y; + + for (y=0; y<=ROWS; y++) { + for (x=0; x<=COLS; x++) { + if ((Segment[x][y].l1==0 && Segment[x][y].l2==XRES) || (Segment[x][y].l1==XRES && Segment[x][y].l2==0)) + Segment[x][y].chr=lcd_dbar_char(Segment[x][y].l1, Segment[x][y].l2); + } + } + for (y=0; y<=ROWS; y++) { + for (x=0; x<=COLS; x++) { + if (Segment[x][y].l1!=-1 || Segment[x][y].l2!=-1) + Segment[x][y].chr=lcd_dbar_char(Segment[x][y].l1, Segment[x][y].l2); + } + } + + for (i=0; i0) + Character[i].lru--; + } + + for (y=0; y<=ROWS; y++) { + for (x=0; x<=COLS; x++) { + if (Segment[x][y].l1!=-1 || Segment[x][y].l2!=-1) { + char buffer[6]; + snprintf (buffer, sizeof(buffer), "\376G%c%c%c", x, y, Segment[x][y].chr); + lcd_write (buffer, 5); + } + } + } +} + + +int lcd_init (char *device) +{ + if (lcd_device) free (lcd_device); + lcd_device=strdup(device); + lcd=lcd_open(); + if (lcd==-1) return -1; + + lcd_clear(); + lcd_write ("\376B", 3); // backlight on + lcd_write ("\376K", 2); // cursor off + lcd_write ("\376T", 2); // blink off + lcd_write ("\376D", 2); // line wrapping off + lcd_write ("\376R", 2); // auto scroll off + lcd_write ("\376V", 2); // GPO off + + return 0; +} + +void lcd_contrast (int contrast) +{ + char buffer[4]; + snprintf (buffer, 4, "\376P%c", contrast); + lcd_write (buffer, 3); +} + diff --git a/lcd2041.h b/lcd2041.h new file mode 100644 index 0000000..4951d4e --- /dev/null +++ b/lcd2041.h @@ -0,0 +1,14 @@ +#define ROWS 4 +#define COLS 20 +#define XRES 5 +#define YRES 8 +#define CHAR 8 + +int lcd_init (char *device); +void lcd_contrast (int contrast); +void lcd_clear (void); +void lcd_put (int x, int y, char *string); +void lcd_hbar (int x, int y, int dir, int max, int len); +void lcd_vbar (int x, int y, int dir, int max, int len); +void lcd_dbar (int x, int y, int dir, int max, int len1, int len2); +void lcd_dbar_flush (void); diff --git a/lcd4linux.c b/lcd4linux.c new file mode 100644 index 0000000..9dbe92f --- /dev/null +++ b/lcd4linux.c @@ -0,0 +1,499 @@ +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "lcd2041.h" +#include "system.h" +#include "isdn.h" + +int tick, tack, tau; +double overload; +double temp_min, temp_max; +char *sensor; +char *row[ROWS]; + +void usage(void) +{ + printf ("LCD4Linux " VERSION " (c) 1999 Michael Reinelt "); + printf ("usage: LCD4Linux [configuration]\n"); +} + +char *parse (char *string) +{ + static char buffer[256]; + char *s=string; + char *p=buffer; + + do { + if (*s=='%') { + if (strchr("orpmlLbtdDnNiI%", *++s)==NULL) { + fprintf (stderr, "WARNING: unknown format <%%%c> in <%s>\n", *s, string); + continue; + } + *p='%'; + *(p+1)=*s; + switch (*s) { + case 'd': + if (strchr("rwmt", *++s)==NULL) { + fprintf (stderr, "WARNING: unknown disk tag <%%i%c> in <%s>\n", *s, string); + continue; + } + *(p+2)=*s; + p+=3; + break; + case 'n': + if (strchr("rwmt", *++s)==NULL) { + fprintf (stderr, "WARNING: unknown net tag <%%i%c> in <%s>\n", *s, string); + continue; + } + *(p+2)=*s; + p+=3; + break; + case 'i': + if (strchr("iomt", *++s)==NULL) { + fprintf (stderr, "WARNING: unknown ISDN tag <%%i%c> in <%s>\n", *s, string); + continue; + } + *(p+2)=*s; + p+=3; + break; + default: + p+=2; + } + + } else if (*s=='$') { + char hv, dir; + int len=0; + hv=*++s; + if (tolower(hv)!='h' && tolower(hv)!='v') { + fprintf (stderr, "invalid bar orientation '%c' in <%s>\n", hv, string); + continue; + } + s++; + if (isdigit(*s)) len=strtol(s, &s, 10); + if (len<1 || len>255) { + fprintf (stderr, "invalid bar length in <%s>\n", string); + continue; + } + dir=*s++; + if ((tolower(hv)=='h' && dir!='l' && dir !='r') || (tolower(hv)=='v' && dir!='u' && dir !='d')) { + fprintf (stderr, "invalid bar direction '%c' in <%s>\n", dir, string); + continue; + } + *p='$'; + *(p+1)=hv; + *(p+2)=len; + if (dir=='r' || dir=='u') *(p+3)='0'; + else *(p+3)='1'; + *(p+4)=*s; + switch (*s) { + case 'd': + if (strchr("rwmt", *++s)==NULL) { + fprintf (stderr, "WARNING: unknown disk tag <$i*%c> in <%s>\n", *s, string); + continue; + } + *(p+5)=*s; + p+=6; + break; + case 'n': + if (strchr("rwmt", *++s)==NULL) { + fprintf (stderr, "WARNING: unknown net tag <$i*%c> in <%s>\n", *s, string); + continue; + } + *(p+5)=*s; + p+=6; + break; + case 'i': + if (strchr("iomt", *++s)==NULL) { + fprintf (stderr, "WARNING: unknown ISDN tag <$i*%c> in <%s>\n", *s, string); + continue; + } + *(p+5)=*s; + p+=6; + break; + default: + p+=5; + } + + } else if (*s=='\\') { + unsigned int c=0; int n; + if (*(s+1)=='\\') { + *p++='\\'; + s+=2; + } else { + sscanf (s+1, "%3o%n", &c, &n); + if (c==0 || c>255) { + fprintf (stderr, "WARNING: illegal '\\' in <%s> <%s>\n", string, s); + continue; + } + *p++=c; + s+=n; + } + + } else { + *p++=*s; + } + + } while (*s++); + + return buffer; +} + + +void display (int smooth) { + static double disk_max=1.0; + static double net_max=1.0; + double busy, load, temp, disk, net, isdn; + int disk_r, disk_w; + int net_tx, net_rx; + int isdn_usage, isdn_in, isdn_out; + char buffer[256]; + int i; + + busy=Busy(); + load=Load(); + Disk (&disk_r, &disk_w); + Net (&net_rx, &net_tx); + temp=Temperature(); + isdn_usage=Isdn(&isdn_in, &isdn_out); + + if (disk_r>disk_max) disk_max=disk_r; + if (disk_w>disk_max) disk_max=disk_w; + + if (net_rx>net_max) net_max=net_rx; + if (net_tx>net_max) net_max=net_tx; + + for (i=0; ioverload?'!':' '; + break; + case 'b': + p+=sprintf (p, "%3.0f", 100.0*busy); + break; + case 'd': + switch (*++s) { + case 'r': + disk=disk_r; + break; + case 'w': + disk=disk_w; + break; + case 'm': + disk=disk_r>disk_w?disk_r:disk_w; + break; + default: + disk=disk_r+disk_w; + break; + } + disk/=1024; + if (disk<10.0) { + p+=sprintf (p, "%4.2f", disk); + } else if (disk<100.0) { + p+=sprintf (p, "%4.1f", disk); + } else { + p+=sprintf (p, "%4.0f", disk); + } + break; + case 'D': + if (disk_r+disk_w==0) + *p++=' '; + else + *p++=disk_r>disk_w?'\176':'\177'; + break; + case 'n': + switch (*++s) { + case 'r': + net=net_rx; + break; + case 'w': + net=net_tx; + break; + case 'm': + net=net_rx>net_tx?net_rx:net_tx; + break; + default: + net=net_rx+net_tx; + break; + } + net/=1024.0; + if (net<10.0) { + p+=sprintf (p, "%4.2f", net); + } else if (net<100.0) { + p+=sprintf (p, "%4.1f", net); + } else { + p+=sprintf (p, "%4.0f", net); + } + break; + case 'N': + if (net_rx+net_tx==0) + *p++=' '; + else + *p++=net_rx>net_tx?'\176':'\177'; + break; + case 't': + p+=sprintf (p, "%5.1f", temp); + break; + case 'i': + if (isdn_usage) { + switch (*++s) { + case 'i': + isdn=isdn_in; + break; + case 'o': + isdn=isdn_out; + break; + case 'm': + isdn=isdn_in>isdn_out?isdn_in:isdn_out; + break; + default: + isdn=isdn_in+isdn_out; + break; + } + isdn/=1024.0; + if (isdn<10.0) { + p+=sprintf (p, "%4.2f", isdn); + } else if (isdn<100.0) { + p+=sprintf (p, "%4.1f", isdn); + } else { + p+=sprintf (p, "%4.0f", isdn); + } + } else { + p+=sprintf (p, "----"); + s++; + } + break; + case 'I': + if (isdn_in+isdn_out==0) + *p++=' '; + else + *p++=isdn_in>isdn_out?'\176':'\177'; + break; + } + + } else if (*s=='$') { + double val; + int hv, len, dir; + hv=*++s; + len=*++s; + dir=*++s; + switch (*++s) { + case 'l': + val=load/overload; + break; + case 'b': + val=busy; + break; + case 'd': + switch (*++s) { + case 'r': + val=disk_r/disk_max; + break; + case 'w': + val=disk_w/disk_max; + break; + case 'm': + val=(disk_r>disk_w?disk_r:disk_w)/disk_max; + break; + default: + val=(disk_r+disk_w)/(2*disk_max); + break; + } + break; + case 'n': + switch (*++s) { + case 'r': + val=net_rx/net_max; + break; + case 'w': + val=net_tx/net_max; + break; + case 'm': + val=(net_rx>net_tx?net_rx:net_tx)/net_max; + break; + default: + val=(net_rx+net_tx)/(2*net_max); + break; + } + break; + case 't': + val=(temp-temp_min)/(temp_max-temp_min); + break; + case 'i': + switch (*++s) { + case 'i': + val=isdn_in; + break; + case 'o': + val=isdn_out; + break; + case 'm': + val=isdn_in>isdn_out?isdn_in:isdn_out; + break; + default: + val=isdn_in+isdn_out; + break; + } + val/=8000.0; + break; + default: + val=0.0; + } + switch (hv) { + case 'h': + lcd_hbar (p-buffer+1, i+1, dir-'0', len*XRES, val*len*XRES); + break; + case 'H': + lcd_hbar (p-buffer+1, i+1, dir-'0', len*XRES, (double)len*XRES*log(val*len*XRES+1)/log(len*XRES)); + break; + case 'v': + lcd_vbar (p-buffer+1, i+1, dir-'0', len*YRES, val*len*XRES); + break; + } + while (len-->0) { + *p++='\t'; + } + + } else { + *p++=*s; + } + } while (*s++); + + if (smooth==0) { + p=buffer; + while (*p) { + while (*p=='\t') p++; + for (s=p; *s; s++) { + if (*s=='\t') { + *s++='\0'; + break; + } + } + if (*p) { + lcd_put (p-buffer+1, i+1, p); + } + p=s; + } + } + } +} + + +void main (int argc, char *argv[]) +{ + char *cfg_file="/etc/lcd4linux.conf"; + char *port; + int i; + int contrast; + int smooth; + + if (argc>2) { + usage(); + exit (2); + } + if (argc==2) { + cfg_file=argv[1]; + } + + set_cfg ("row1", "*** %o %r ***"); + set_cfg ("row2", "%p CPU %m MB RAM"); + set_cfg ("row3", "Busy %b%% $r50b"); + set_cfg ("row4", "Load %l$r50l"); + + set_cfg ("tick", "100"); + set_cfg ("tack", "500"); + set_cfg ("tau", "500"); + set_cfg ("contrast", "140"); + set_cfg ("overload", "2.0"); + set_cfg ("temp_min", "20"); + set_cfg ("temp_max", "70"); + + set_cfg ("fifo", "/var/run/LCD4Linux"); + + if (read_cfg (cfg_file)==-1) + exit (1); + + port=get_cfg("port"); + sensor=get_cfg("temperature"); + tick=atoi(get_cfg("tick")); + tack=atoi(get_cfg("tack")); + tau=atoi(get_cfg("tau")); + contrast=atoi(get_cfg("contrast")); + overload=atof(get_cfg("overload")); + temp_min=atof(get_cfg("temp_min")); + temp_max=atof(get_cfg("temp_max")); + + if (port==NULL || *port=='\0') { + fprintf (stderr, "%s: missing 'port' entry!\n", cfg_file); + exit (1); + } + + for (i=0; itack) smooth=0; + usleep(1000*tick); + } +} diff --git a/lcd4linux.h b/lcd4linux.h new file mode 100644 index 0000000..f7c91ae --- /dev/null +++ b/lcd4linux.h @@ -0,0 +1,6 @@ +extern int tick; +extern int tack; +extern int tau; +extern char *sensor; + + diff --git a/system.c b/system.c new file mode 100644 index 0000000..0d3679f --- /dev/null +++ b/system.c @@ -0,0 +1,306 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "system.h" +#include "filter.h" +#include "lcd4linux.h" + +char *System(void) +{ + static char buffer[32]=""; + struct utsname ubuf; + + if (*buffer=='\0') { + if (uname(&ubuf)==-1) { + perror ("uname() failed"); + strcpy (buffer, "unknown"); + } else { + strncpy (buffer, ubuf.sysname, sizeof(buffer)); + } + } + return buffer; +} + +char *Release(void) +{ + static char buffer[32]=""; + struct utsname ubuf; + + if (*buffer=='\0') { + if (uname(&ubuf)==-1) { + perror ("uname() failed"); + strcpy (buffer, "unknown"); + } else { + strncpy (buffer, ubuf.release, sizeof(buffer)); + } + } + return buffer; +} + + +char *Processor(void) +{ + static char buffer[16]=""; + struct utsname ubuf; + + if (*buffer=='\0') { + if (uname(&ubuf)==-1) { + perror ("uname() failed"); + strcpy (buffer, "unknown"); + } else { + strncpy (buffer, ubuf.machine, sizeof(buffer)); + } + } + return buffer; +} + + +int Memory(void) +{ + static int value=-1; + struct stat buf; + + if (value==-1) { + if (stat("/proc/kcore", &buf)==-1) { + perror ("stat(/proc/kcore) failed"); + value=0; + } else { + value=buf.st_size>>20; + } + } + return value; +} + + +double Load (void) +{ + static int fd=-2; + char buffer[16]; + static double value=0; + static time_t now=0; + + if (fd==-1) return 0; + + if (time(NULL)==now) return value; + time(&now); + + if (fd==-2) { + fd=open("/proc/loadavg", O_RDONLY); + if (fd==-1) { + perror ("open(/proc/loadavg) failed"); + return 0; + } + } + if (lseek(fd, 0L, SEEK_SET)!=0) { + perror("lseek(/proc/loadavg) failed"); + fd=-1; + return 0; + } + if (read (fd, &buffer, sizeof(buffer)-1)==-1) { + perror("read(/proc/loadavg) failed"); + fd=-1; + return 0; + } + if (sscanf(buffer, "%lf", &value)<1) { + fprintf(stderr, "scanf(/proc/loadavg) failed\n"); + fd=-1; + return 0; + } + return (value); +} + + +double Busy (void) +{ + static int fd=-2; + char buffer[64]; + unsigned long v1, v2, v3, v4; + double busy, idle; + + if (fd==-1) return 0; + + if (fd==-2) { + fd=open("/proc/stat", O_RDONLY); + if (fd==-1) { + perror ("open(proc/stat) failed"); + return 0; + } + } + if (lseek(fd, 0L, SEEK_SET)!=0) { + perror ("lseek(/proc/stat) failed"); + fd=-1; + return 0; + } + if (read (fd, &buffer, sizeof(buffer)-1)==-1) { + perror ("read(/proc/stat) failed"); + fd=-1; + return 0; + } + if (sscanf(buffer, "%*s %lu %lu %lu %lu\n", &v1, &v2, &v3, &v4)<4) { + fprintf (stderr, "scanf(/proc/stat) failed\n"); + fd=-1; + return 0; + } + + busy=smooth("cpu_busy", 500, v1+v2+v3); + idle=smooth("cpu_idle", 500, v4); + + if (busy+idle==0.0) + return 0.0; + else + return busy/(busy+idle); +} + + +int Disk (int *r, int *w) +{ + char buffer[4096], *p; + static int fd=-2; + unsigned long r1, r2, r3, r4; + unsigned long w1, w2, w3, w4; + + *r=0; + *w=0; + + if (fd==-1) return 0; + + if (fd==-2) { + fd = open("/proc/stat", O_RDONLY | O_NDELAY); + if (fd==-1) { + perror ("open(/proc/stat) failed"); + return 0; + } + } + + if (lseek(fd, 0L, SEEK_SET)!=0) { + perror ("lseek(/proc/stat) failed"); + fd=-1; + return 0; + } + if (read (fd, &buffer, sizeof(buffer)-1)==-1) { + perror ("read(/proc/stat) failed"); + fd=-1; + return 0; + } + p=strstr(buffer, "disk_rblk"); + if (p==NULL) { + fprintf (stderr, "parse(/proc/stat) failed: no disk_rblk line\n"); + fd=-1; + return 0; + } + if (sscanf(p+9, "%lu %lu %lu %lu\n", &r1, &r2, &r3, &r4)<4) { + fprintf (stderr, "scanf(/proc/stat) failed\n"); + fd=-1; + return 0; + } + p=strstr(buffer, "disk_wblk"); + if (p==NULL) { + fprintf (stderr, "parse(/proc/stat) failed: no disk_wblk line\n"); + fd=-1; + return 0; + } + if (sscanf(p+9, "%lu %lu %lu %lu\n", &w1, &w2, &w3, &w4)<4) { + fprintf (stderr, "scanf(/proc/stat) failed\n"); + fd=-1; + return 0; + } + + *r=smooth ("disk_r", 500, r1+r2+r3+r4); + *w=smooth ("disk_w", 500, w1+w2+w3+w4); + + return *r+*w; +} + + +int Net (int *rx, int *tx) +{ + char buffer[4096], *p, *s; + static int fd=-2; + unsigned long pkg_rx, pkg_tx; + + *rx=0; + *tx=0; + + if (fd==-1) return 0; + + if (fd==-2) { + fd = open("/proc/net/dev", O_RDONLY | O_NDELAY); + if (fd==-1) { + perror ("open(/proc/net/dev) failed"); + return 0; + } + } + + if (lseek(fd, 0L, SEEK_SET)!=0) { + perror ("lseek(/proc/net/dev) failed"); + fd=-1; + return 0; + } + if (read (fd, &buffer, sizeof(buffer)-1)==-1) { + perror ("read(/proc/net/dev) failed"); + fd=-1; + return 0; + } + pkg_rx=0; + pkg_tx=0; + p=buffer; + while ((s=strsep(&p, "\n"))) { + unsigned long r, t; + if (sscanf (s, " eth%*d:%*d: %ld %*d %*d %*d %*d %ld", &r, &t)==2 || + sscanf (s, " eth%*d: %ld %*d %*d %*d %*d %ld", &r, &t)==2) { + pkg_rx+=r; + pkg_tx+=t; + } + } + *rx=smooth("net_rx", 500, pkg_rx); + *tx=smooth("net_tx", 500, pkg_tx); + + return *rx+*tx; +} + + +double Temperature (void) +{ + static int fd=-2; + char buffer[32]; + static double value=0.0; + static time_t now=0; + + if (fd==-1) return 0; + + if (time(NULL)==now) return value; + time(&now); + + if (fd==-2) { + fd=open(sensor, O_RDONLY); + if (fd==-1) { + fprintf (stderr, "open (%s) failed: %s\n", sensor, strerror(errno)); + return 0; + } + } + if (lseek(fd, 0L, SEEK_SET)!=0) { + fprintf (stderr, "lseek(%s) failed: %s\n", sensor, strerror(errno)); + fd=-1; + return 0; + } + if (read (fd, &buffer, sizeof(buffer)-1)==-1) { + fprintf (stderr, "read(%s) failed: %s\n", sensor, strerror(errno)); + fd=-1; + return 0; + } + if (sscanf(buffer, "%*f %*f %lf", &value)<1) { + fprintf (stderr, "scanf(%s) failed\n", sensor); + fd=-1; + return 0; + } + return (value); +} diff --git a/system.h b/system.h new file mode 100644 index 0000000..d3e3e28 --- /dev/null +++ b/system.h @@ -0,0 +1,9 @@ +char *System (void); +char *Release (void); +char *Processor (void); +int Memory (void); +double Load (void); +double Busy (void); +int Disk (int *r, int *w); +int Net (int *r, int *w); +double Temperature (void); -- cgit v1.2.3