/*
* Russ Cox, 17 August 1997
* [email protected]
*
* this program lets you watch the front panel of the
* modem racks remotely. just look, no touching.
*
* window '0 160 160 300' tcm bait-nmc1
* window '0 300 160 440' tcm bait-nmc2
* window '0 440 100 580' tcm -n 6 usrnmc-lh
*
* remember:
* We don't understand the software, and sometimes we don't understand
* the hardware, but we can *see* the blinking lights!
*/
#include <u.h>
#include <libc.h>
#include <libg.h>
#include "a1.h"
extern void chat(char *, ...);
enum {
Nlights = 7,
Ncards = 13,
};
int nmodem = Ncards-1;
int lights[Ncards][Nlights];
Rectangle rlight[Ncards][Nlights];
Bitmap *clr[3];
Bitmap *black, *white;
int nfd;
int chatty;
int timeint = 15;
char *usage = "%s host [-c n b a] [-t secs] [-n nmodem]\n";
char *host;
void getlights(void);
void drawlights(void);
void
main(int argc, char **argv)
{
int i, pid;
Rectangle r;
int c[3] = {204, 0x10, 0xfc}; /* fb/colors */
ARGBEGIN{
case 'n':
nmodem = atoi(ARGF());
if(nmodem > Ncards-1)
nmodem = Ncards-1;
break;
case 'c':
for(i=0; i<3; i++)
c[0] = atoi(ARGF());
break;
case 't':
timeint = atoi(ARGF());
break;
default:
fprint(2, usage, argv0);
exits("usage");
}ARGEND;
if(argc != 1) {
fprint(2, usage, argv0);
exits("usage");
}
if((nfd = dial(netmkaddr(argv[0], "udp", "161"), 0, 0, 0)) < 0) {
fprint(2, "cannot dial: %r\n");
exits("dial");
}
host = argv[0];
getlights();
binit(0,0,0);
einit(Emouse);
r.min = (Point){0,0};
r.max = (Point){1,1};
for(i=0; i<3; i++) {
clr[i] = balloc(r, 3);
point(clr[i], r.min, c[i], S);
}
black = balloc(r, 3);
white = balloc(r, 3);
point(black, r.min, 0xff, S);
point(white, r.min, 0, S);
ereshaped(screen.r);
pid = rfork(RFMEM|RFPROC);
if(pid == 0) {
for(;;) {
sleep(timeint*1000);
getlights();
drawlights();
}
exits(0);
} else if(pid < 0) {
fprint(2, "cannot rfork: %r\n");
exits("rfork");
} else for(;;){
emouse();
}
}
void
drawlights(void)
{
int i, j;
for(i=0; i<Ncards; i++)
for(j=0; j<Nlights; j++) {
if(lights[i][j] >= 0 && lights[i][j] <= 3) {
texture(&screen, rlight[i][j], clr[lights[i][j]], S);
}
}
bflush();
}
void
ereshaped(Rectangle r)
{
int i, j, y, ht, wid;
Point pw, textpt, p;
Rectangle box;
char msg[10];
/* clear screen */
screen.r = r;
bitblt(&screen, screen.r.min, &screen, r, Zero);
/* add host label in upper corner */
p = (Point){5,5};
p = add(p, screen.r.min);
string(&screen, p, font, host, S);
/* width of card slots */
wid = (Dx(r) - 10 - (nmodem))/(nmodem+1);
pw = (Point){wid+1, 0};
/* height of card slots */
p = strsize(font, "0");
y = p.y;
ht = (Dy(r) - 10 - 2*y)/(Nlights);
/* box is the first card */
/* cards are wid pixels wide black + 1 pixel white */
box.min = add(screen.r.min, (Point){5, 5+2*y});
box.max = add(screen.r.min, (Point){5+wid, 5+2*y+ht*Nlights});
/* label first card */
strcpy(msg, "1");
textpt = add(box.min, (Point){(wid/2-p.x/2), -y});
string(&screen, textpt, font, msg, S);
/* draw card */
texture(&screen, box, black, S);
/* set up card 1, light 1 */
rlight[0][0].min = add((Point){wid/4, ht/8}, box.min);
rlight[0][0].max = add((Point){wid/2, ht*3/4}, rlight[0][0].min);
/* all the other lights on the card are just offsets */
for(i=1; i<Nlights; i++) {
rlight[0][i].min = add((Point){0, ht}, rlight[0][i-1].min);
rlight[0][i].max = add((Point){0, ht}, rlight[0][i-1].max);
}
/* all the other cards and lights are offsets from previous */
for(i=1; i<nmodem+1; i++) {
/* label... */
textpt = add(pw, textpt);
msg[0] = '0'+(i+1)%10;
string(&screen, textpt, font, msg, S);
/* card... */
box.min = add(pw, box.min);
box.max = add(pw, box.max);
texture(&screen, box, black, S);
/* lights... */
for(j=0; j<Nlights; j++) {
rlight[i][j].max = add(pw, rlight[i-1][j].max);
rlight[i][j].min = add(pw, rlight[i-1][j].min);
}
}
drawlights();
}
void
getlights(void)
{
Snmp ss, *s;
SnmpPdu *pdu;
int i, j, bits, nybble;
chat("getlights()...");
s = &ss;
memset(s, 0, sizeof *s);
// Schkpdu(s, 3);
s->vers = 0;
s->private = 0;
s->type = Pget;
s->estat = s->eindex = 0;
s->npdu = 3;
for(i=0, pdu=s->pdu; i<3; i++, pdu++) {
/* you are not expected to understand this */
sprint(pdu->objid, "1.3.6.1.4.1.429.1.1.3.%d.0", i+5);
pdu->type = Anull;
}
memset(lights, 0, sizeof lights);
if(dosnmp(nfd, s, s) < 0)
return;
if(s->estat) {
chat("error in snmp pkt");
return;
}
pdu = &s->pdu[1];
if(pdu->len < (Ncards)*6) {
chat("pdu too short");
return;
}
for(i=0; i<Ncards; i++) {
chat("card %d...", i);
for(j=0,nybble=i*12; j<Nlights; j++,nybble++){
bits = (uchar)pdu->s[nybble/2];
if((nybble%2)==0)
bits >>= 4;
else
bits &= 0x0f;
switch(bits){
case 1: /* busy */
lights[i][j] = 2;
break;
case 3: /* answering */
lights[i][j] = 1;
break;
case 0: /* nothing */
lights[i][j] = 0;
break;
default:
lights[i][j] = 0;
break;
}
chat("%c", lights[i][j]);
}
chat("...");
}
}
|