aboutsummaryrefslogtreecommitdiffstats
path: root/plugin_loadavg.c
blob: 5952dbb195efc77e29b6f814c2a4cfef2c6b593f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/* $Id$
 * $URL$
 *
 * plugin for load average
 *
 * Copyright (C) 2003 Michael Reinelt <reinelt@eunet.at>
 * Copyright (C) 2004 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
 *
 * This file is part of LCD4Linux.
 *
 * LCD4Linux is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * LCD4Linux is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

/* 
 * exported functions:
 *
 * int plugin_init_loadavg (void)
 *  adds functions for load average
 *
 */


#include "config.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>

#include "debug.h"
#include "plugin.h"

#ifndef HAVE_GETLOADAVG
static int fd = -2;

int getloadavg(double loadavg[], int nelem)
{
    char buf[65], *p;
    ssize_t nread;
    int i;

    if (fd == -2)
	fd = open("/proc/loadavg", O_RDONLY);
    if (fd < 0)
	return -1;

    lseek(fd, 0, SEEK_SET);
    nread = read(fd, buf, sizeof buf - 1);

    if (nread < 0)
	return -1;
    buf[nread - 1] = '\0';

    if (nelem > 3)
	nelem = 3;
    p = buf;
    for (i = 0; i < nelem; ++i) {
	char *endp;
	loadavg[i] = strtod(p, &endp);
	if (endp == NULL || endp == p)
	    /* This should not happen.  The format of /proc/loadavg
	       must have changed.  Don't return with what we have,
	       signal an error.  */
	    return -1;
	p = endp;
    }

    return i;
}

#endif


static void my_loadavg(RESULT * result, RESULT * arg1)
{
    static int nelem = -1;
    int index, age;
    static double loadavg[3];
    static struct timeval last_value;
    struct timeval now;

    gettimeofday(&now, NULL);

    age = (now.tv_sec - last_value.tv_sec) * 1000 + (now.tv_usec - last_value.tv_usec) / 1000;
    /* reread every 10 msec only */
    if (nelem == -1 || age == 0 || age > 10) {

	nelem = getloadavg(loadavg, 3);
	if (nelem < 0) {
	    error("getloadavg() failed!");
	    SetResult(&result, R_STRING, "");
	    return;
	}
	last_value = now;
    }

    index = R2N(arg1);
    if (index < 1 || index > nelem) {
	error("loadavg(%d): index out of range!", index);
	SetResult(&result, R_STRING, "");
	return;
    }


    SetResult(&result, R_NUMBER, &(loadavg[index - 1]));
    return;

}

int plugin_init_loadavg(void)
{
    AddFunction("loadavg", 1, my_loadavg);
    return 0;
}

void plugin_exit_loadavg(void)
{
#ifndef HAVE_GETLOADAVG
    if (fd > 0)
	close(fd);
    fd = -2;
#endif
}
span> "drv.h" #include "drv_generic_text.h" #include "drv_generic_parport.h" static char Name[]="M50530"; static int Model; static unsigned char SIGNAL_EX; static unsigned char SIGNAL_IOC1; static unsigned char SIGNAL_IOC2; static unsigned char SIGNAL_GPO; // Fixme: GPO's not yet implemented static int GPOS; // static int GPO=0; typedef struct { int type; char *name; } MODEL; static MODEL Models[] = { { 0x01, "generic" }, { 0xff, "Unknown" } }; // **************************************** // *** hardware dependant functions *** // **************************************** static void drv_M5_command (unsigned int cmd, int delay) { // put data on DB1..DB8 drv_generic_parport_data (cmd&0xff); // set I/OC1 // set I/OC2 drv_generic_parport_control (SIGNAL_IOC1|SIGNAL_IOC2, (cmd&0x200?SIGNAL_IOC1:0) | (cmd&0x100?SIGNAL_IOC2:0)); // Control data setup time ndelay(200); // send command // EX signal pulse width = 500ns // Fixme: why 500 ns? Datasheet says 200ns drv_generic_parport_toggle (SIGNAL_EX, 1, 500); // wait udelay(delay); } static void drv_M5_write (int row, int col, unsigned char *data, int len) { unsigned int cmd; unsigned int pos; pos=row*48+col; if (row>3) pos-=168; drv_M5_command (0x300|pos, 20); while (len--) { cmd=*data++; drv_M5_command (0x100|cmd, 20); } } static void drv_M5_defchar (int ascii, unsigned char *matrix) { int i; drv_M5_command (0x300+192+8*(ascii-CHAR0), 20); // Fixme: looks like the M50530 cannot control the bottom line // therefore we have only 7 bytes here for (i=0; i<7; i++) { drv_M5_command (0x100|(matrix[i] & 0x3f), 20); } } // Fixme: GPO's #if 0 static void drv_M5_setGPO (int bits) { if (Lcd.gpos>0) { // put data on DB1..DB8 drv_generic_parport_data (bits); // 74HCT573 set-up time ndelay(20); // send data // 74HCT573 enable pulse width = 24ns drv_generic_parport_toggle (SIGNAL_GPO, 1, 24); } } #endif static int drv_M5_start (char *section) { char *model, *s; int rows=-1, cols=-1, gpos=-1; model=cfg_get(section, "Model", "generic"); if (model!=NULL && *model!='\0') { int i; for (i=0; Models[i].type!=0xff; i++) { if (strcasecmp(Models[i].name, model)==0) break; } if (Models[i].type==0xff) { error ("%s: %s.Model '%s' is unknown from %s", Name, section, model, cfg_source()); return -1; } Model=i; info ("%s: using model '%s'", Name, Models[Model].name); } else { error ("%s: empty '%s.Model' entry from %s", Name, section, cfg_source()); return -1; } s=cfg_get(section, "Size", NULL); if (s==NULL || *s=='\0') { error ("%s: no '%s.Size' entry from %s", Name, section, cfg_source()); return -1; } if (sscanf(s,"%dx%d",&cols,&rows)!=2 || rows<1 || cols<1) { error ("%s: bad size '%s'", Name, s); return -1; } if (cfg_number(section, "GPOs", 0, 0, 8, &gpos)<0) return -1; info ("%s: controlling %d GPO's", Name, gpos); DROWS = rows; DCOLS = cols; GPOS = gpos; if (drv_generic_parport_open(section, Name) != 0) { error ("%s: could not initialize parallel port!", Name); return -1; } if ((SIGNAL_EX = drv_generic_parport_wire_ctrl ("EX", "STROBE"))==0xff) return -1; if ((SIGNAL_IOC1 = drv_generic_parport_wire_ctrl ("IOC1", "SELECT"))==0xff) return -1; if ((SIGNAL_IOC2 = drv_generic_parport_wire_ctrl ("IOC2", "AUTOFD"))==0xff) return -1; if ((SIGNAL_GPO = drv_generic_parport_wire_ctrl ("GPO", "INIT" ))==0xff) return -1; // clear all signals drv_generic_parport_control (SIGNAL_EX|SIGNAL_IOC1|SIGNAL_IOC2|SIGNAL_GPO, 0); // set direction: write drv_generic_parport_direction (0); drv_M5_command (0x00FA, 20); // set function mode drv_M5_command (0x0020, 20); // set display mode drv_M5_command (0x0050, 20); // set entry mode drv_M5_command (0x0030, 20); // set display mode drv_M5_command (0x0001, 1250); // clear display return 0; } // **************************************** // *** plugins *** // **************************************** // none at the moment // **************************************** // *** widget callbacks *** // **************************************** // using drv_generic_text_draw(W) // using drv_generic_text_icon_draw(W) // using drv_generic_text_bar_draw(W) // **************************************** // *** exported functions *** // **************************************** // list models int drv_M5_list (void) { int i; for (i=0; Models[i].type!=0xff; i++) { printf ("%s ", Models[i].name); } return 0; } // initialize driver & display int drv_M5_init (char *section, int quiet) { WIDGET_CLASS wc; int ret; // display preferences XRES = 5; // pixel width of one char YRES = 8; // pixel height of one char CHARS = 8; // number of user-defineable characters CHAR0 = 248; // ASCII of first user-defineable char GOTO_COST = 1; // number of bytes a goto command requires // real worker functions drv_generic_text_real_write = drv_M5_write; drv_generic_text_real_defchar = drv_M5_defchar; // start display if ((ret=drv_M5_start (section))!=0) return ret; // initialize generic text driver if ((ret=drv_generic_text_init(section, Name))!=0) return ret; // initialize generic icon driver if ((ret=drv_generic_text_icon_init())!=0) return ret; // initialize generic bar driver if ((ret=drv_generic_text_bar_init(0))!=0) return ret; // add fixed chars to the bar driver drv_generic_text_bar_add_segment (0,0,255,32); // ASCII 32 = blank // register text widget wc=Widget_Text; wc.draw=drv_generic_text_draw; widget_register(&wc); // register icon widget wc=Widget_Icon; wc.draw=drv_generic_text_icon_draw; widget_register(&wc); // register bar widget wc=Widget_Bar; wc.draw=drv_generic_text_bar_draw; widget_register(&wc); // register plugins // none at the moment return 0; } // close driver & display int drv_M5_quit (void) { info("%s: shutting down.", Name); // clear all signals drv_generic_parport_control (SIGNAL_EX|SIGNAL_IOC1|SIGNAL_IOC2|SIGNAL_GPO, 0); drv_generic_parport_close(); drv_generic_text_quit(); return (0); } DRIVER drv_M50530 = { name: Name, list: drv_M5_list, init: drv_M5_init, quit: drv_M5_quit, };