Use diskwatch only
This commit is contained in:
parent
43118a9844
commit
1d7e3643c2
2
Makefile
2
Makefile
@ -7,7 +7,7 @@ PID_DIR = /var/run
|
||||
# ############################
|
||||
|
||||
SRC = $(wildcard *.c)
|
||||
TARGET = qnapd
|
||||
TARGET = diskwatch
|
||||
BUILD_DIR = build
|
||||
CFLAGS = -O2 -g -pipe -Wall -Wno-unused-result -DPROGNAME='"$(TARGET)"'
|
||||
CFLAGS += -MMD -MF $(BUILD_DIR)/$(*D)/$(*F).d
|
||||
|
8
TODO
8
TODO
@ -1,8 +0,0 @@
|
||||
- dynamic pages
|
||||
- refresh of dynamic pages (clock, loadavg)
|
||||
|
||||
- disk utilization (MB/GB)
|
||||
- mntpoints given in config
|
||||
|
||||
- network usage?
|
||||
- cpu usage?
|
76
diskwatch.c
76
diskwatch.c
@ -31,7 +31,6 @@
|
||||
#include "configfile.h"
|
||||
#include "diskwatch.h"
|
||||
#include "event.h"
|
||||
#include "lcd.h"
|
||||
#include "list.h"
|
||||
#include "logging.h"
|
||||
|
||||
@ -56,79 +55,11 @@ struct disk_entry {
|
||||
|
||||
struct diskwatch {
|
||||
struct list_head disk_list;
|
||||
struct lcddev *lcd;
|
||||
struct event_timeout *check_timeout;
|
||||
};
|
||||
|
||||
static struct diskwatch diskwatch_glob;
|
||||
|
||||
static int diskwatch_check_standby(struct disk_entry *entry);
|
||||
|
||||
static int lcdpage_diskwatch(struct lcddev *lcd, int event, void *privdata)
|
||||
{
|
||||
static struct disk_entry *entry;
|
||||
struct diskwatch *dwatch = (struct diskwatch *)privdata;
|
||||
|
||||
if (entry == NULL) {
|
||||
if (list_empty(&dwatch->disk_list)) {
|
||||
return LCDPAGE_COMMAND_NEXT;
|
||||
}
|
||||
|
||||
entry = list_entry(dwatch->disk_list.next, struct disk_entry, list);
|
||||
}
|
||||
|
||||
switch (event) {
|
||||
case LCDPAGE_EVENT_BUTTON1:
|
||||
if (entry->list.next == &dwatch->disk_list) {
|
||||
entry = NULL;
|
||||
return LCDPAGE_COMMAND_NEXT;
|
||||
}
|
||||
|
||||
entry = list_entry(entry->list.next, struct disk_entry, list);
|
||||
lcd_set_backlight(lcd, 1);
|
||||
break;
|
||||
|
||||
case LCDPAGE_EVENT_ENTER:
|
||||
entry = list_entry(dwatch->disk_list.next, struct disk_entry, list);
|
||||
lcd_set_backlight(lcd, 1);
|
||||
break;
|
||||
|
||||
case LCDPAGE_EVENT_BACKLIGHT:
|
||||
case LCDPAGE_EVENT_EXIT:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
char line1[32];
|
||||
char line2[32];
|
||||
|
||||
snprintf(line1, sizeof(line1), "DISK(%s):", entry->device);
|
||||
if (entry->flags & F_PRESENT) {
|
||||
diskwatch_check_standby(entry);
|
||||
|
||||
if (entry->flags & F_STANDBY) {
|
||||
snprintf(line2, sizeof(line2), "STANDBY");
|
||||
} else {
|
||||
int timeout = entry->standby_timeout - time(NULL);
|
||||
int hours = timeout / 3600;
|
||||
timeout = timeout % 3600;
|
||||
int minutes = timeout / 60;
|
||||
timeout = timeout % 60;
|
||||
|
||||
snprintf(line2, sizeof(line2), "RUN -%02d:%02d:%02d", hours, minutes, timeout);
|
||||
}
|
||||
|
||||
} else {
|
||||
snprintf(line2, sizeof(line2), "not present");
|
||||
}
|
||||
|
||||
lcd_setlines(lcd, line1, line2);
|
||||
|
||||
return 1000;
|
||||
}
|
||||
|
||||
static int diskwatch_check_standby(struct disk_entry *entry)
|
||||
{
|
||||
if (!(entry->flags & F_PRESENT))
|
||||
@ -315,7 +246,7 @@ void diskwatch_exit(void)
|
||||
}
|
||||
}
|
||||
|
||||
int diskwatch_init(struct lcddev *lcd)
|
||||
int diskwatch_init(void)
|
||||
{
|
||||
struct diskwatch *dwatch = &diskwatch_glob;
|
||||
|
||||
@ -331,10 +262,5 @@ int diskwatch_init(struct lcddev *lcd)
|
||||
config_get_int("diskwatch", "check_interval", &check_interval, 60);
|
||||
dwatch->check_timeout = event_add_timeout_ms(check_interval * 1000, diskwatch_check_stats, 0, dwatch);
|
||||
|
||||
dwatch->lcd = lcd;
|
||||
if (dwatch->lcd != NULL) {
|
||||
lcd_addpage_cb(dwatch->lcd, 150, lcdpage_diskwatch, dwatch);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
11
diskwatch.conf
Normal file
11
diskwatch.conf
Normal file
@ -0,0 +1,11 @@
|
||||
[global]
|
||||
pidfile diskwatch.pid
|
||||
logfile diskwatch.log
|
||||
|
||||
[diskwatch]
|
||||
check_interval 60
|
||||
|
||||
#disk /dev/sda,7200
|
||||
disk /dev/sdb,120
|
||||
#disk /dev/sdc,7200
|
||||
#disk /dev/sdd,7200
|
@ -1,9 +1,7 @@
|
||||
#ifndef _DISKWATCH_H_
|
||||
#define _DISKWATCH_H_
|
||||
|
||||
#include "lcd.h"
|
||||
|
||||
void diskwatch_exit(void);
|
||||
int diskwatch_init(struct lcddev *lcd);
|
||||
int diskwatch_init(void);
|
||||
|
||||
#endif /* _DISKWATCH_H_ */
|
||||
|
699
lcd.c
699
lcd.c
@ -1,699 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 05/2011 by Olaf Rempel *
|
||||
* razzor@kopf-tisch.de *
|
||||
* *
|
||||
* This program 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 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include "event.h"
|
||||
#include "lcd.h"
|
||||
#include "list.h"
|
||||
#include "logging.h"
|
||||
|
||||
#define _LCD_DEBUG 0
|
||||
#define _LCD_DUMMY 1
|
||||
|
||||
#define LCD_SCROLL_SPEED 750 /* 750ms */
|
||||
#define LCD_RESET_TIMEOUT 250 /* 250ms */
|
||||
#define LCD_RESET_RETRY_TIMEOUT 10000 /* 10s */
|
||||
|
||||
#define A125_CMD_GETBUTTON { 0x4D, 0x06 } // not tried
|
||||
#define A125_CMD_SETLINE { 0x4D, 0x0C, 0x00, 0x10 } // [2] is line, append 16 chars
|
||||
#define A125_CMD_CLEAR { 0x4D, 0x0D } // works, but slow
|
||||
#define A125_CMD_BACKLIGHT { 0x4D, 0x5E, 0x00 } // [2] is on/off
|
||||
#define A125_CMD_RESET { 0x4D, 0xFF }
|
||||
|
||||
#define A125_EVENT_ID { 0x53, 0x01 } // never seen
|
||||
#define A125_EVENT_BUTTON1 { 0x53, 0x05, 0x00, 0x01 }
|
||||
#define A125_EVENT_BUTTON2 { 0x53, 0x05, 0x00, 0x02 }
|
||||
#define A125_EVENT_VERSION { 0x53, 0x08 } // never seen
|
||||
#define A125_EVENT_ACTINFO { 0x53, 0xAA }
|
||||
#define A125_EVENT_INVALID { 0x53, 0xFB } // never seen
|
||||
|
||||
struct lcdpage {
|
||||
struct list_head list;
|
||||
int priority;
|
||||
|
||||
int (*callback)(struct lcddev *dev, int event, void *privdata);
|
||||
void *privdata;
|
||||
};
|
||||
|
||||
enum lcdstate {
|
||||
LCD_STATE_NOT_INITIALIZED = 0x00,
|
||||
LCD_STATE_INITIALIZING,
|
||||
LCD_STATE_INITIALIZING_FAILED,
|
||||
LCD_STATE_READY,
|
||||
};
|
||||
|
||||
struct lcddev {
|
||||
int fd;
|
||||
#if (_LCD_DUMMY)
|
||||
struct event_fd *fakedevice_event;
|
||||
#endif /* (_LCD_DUMMY) */
|
||||
struct termios oldtio;
|
||||
|
||||
enum lcdstate state;
|
||||
|
||||
int backlight_enabled;
|
||||
int backlight_timeout_ms;
|
||||
|
||||
struct list_head page_list;
|
||||
struct lcdpage *current_page;
|
||||
|
||||
const char *line_data[2];
|
||||
int line_length[2];
|
||||
int scroll_pos;
|
||||
|
||||
int update_ms;
|
||||
|
||||
struct event_fd *read_event;
|
||||
struct event_timeout *reset_timeout;
|
||||
struct event_timeout *backlight_timeout;
|
||||
struct event_timeout *scroll_timeout;
|
||||
struct event_timeout *update_timeout;
|
||||
};
|
||||
|
||||
static void lcd_pagecallback(struct lcddev *dev, int event);
|
||||
|
||||
void lcd_close(struct lcddev *dev)
|
||||
{
|
||||
if (dev->current_page) {
|
||||
dev->current_page->callback(dev, LCDPAGE_EVENT_EXIT, dev->current_page->privdata);
|
||||
dev->current_page = NULL;
|
||||
}
|
||||
|
||||
struct lcdpage *search, *tmp;
|
||||
list_for_each_entry_safe(search, tmp, &dev->page_list, list) {
|
||||
free(search);
|
||||
}
|
||||
|
||||
if (dev->reset_timeout) {
|
||||
event_remove_timeout(dev->reset_timeout);
|
||||
dev->reset_timeout = NULL;
|
||||
}
|
||||
|
||||
if (dev->backlight_timeout) {
|
||||
event_remove_timeout(dev->backlight_timeout);
|
||||
dev->backlight_timeout = NULL;
|
||||
}
|
||||
|
||||
if (dev->update_timeout) {
|
||||
event_remove_timeout(dev->update_timeout);
|
||||
dev->update_timeout = NULL;
|
||||
}
|
||||
|
||||
if (dev->scroll_timeout) {
|
||||
event_remove_timeout(dev->scroll_timeout);
|
||||
dev->scroll_timeout = NULL;
|
||||
}
|
||||
|
||||
if (dev->read_event) {
|
||||
event_remove_fd(dev->read_event);
|
||||
dev->read_event = NULL;
|
||||
}
|
||||
|
||||
#if (_LCD_DUMMY)
|
||||
if (dev->fakedevice_event != NULL) {
|
||||
int fd = event_get_fd(dev->fakedevice_event);
|
||||
event_remove_fd(dev->fakedevice_event);
|
||||
dev->fakedevice_event = NULL;
|
||||
close(fd);
|
||||
|
||||
} else
|
||||
#endif /* (_LCD_DUMMY) */
|
||||
{
|
||||
tcsetattr(dev->fd, TCSANOW, &dev->oldtio);
|
||||
}
|
||||
|
||||
close(dev->fd);
|
||||
free(dev);
|
||||
}
|
||||
|
||||
static int lcd_realdevice_open(struct lcddev *dev, const char *device)
|
||||
{
|
||||
dev->fd = open(device, O_RDWR | O_NOCTTY);
|
||||
if (dev->fd < 0) {
|
||||
log_print(LOG_ERROR, "%s(): failed to open '%s'", __FUNCTION__, device);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fcntl(dev->fd, F_SETFD, FD_CLOEXEC) < 0) {
|
||||
log_print(LOG_ERROR, "%s(): fcntl(FD_CLOEXEC)", __FUNCTION__);
|
||||
close(dev->fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tcgetattr(dev->fd, &dev->oldtio);
|
||||
|
||||
struct termios newtio;
|
||||
memset(&newtio, 0, sizeof(newtio));
|
||||
newtio.c_iflag |= IGNBRK;
|
||||
newtio.c_lflag &= ~(ISIG | ICANON | ECHO);
|
||||
newtio.c_cflag = B1200 | CS8 | CLOCAL | CREAD;
|
||||
newtio.c_cc[VMIN] = 1;
|
||||
newtio.c_cc[VTIME] = 0;
|
||||
cfsetospeed(&newtio, B1200);
|
||||
cfsetispeed(&newtio, B1200);
|
||||
|
||||
int err = tcsetattr(dev->fd, TCSAFLUSH, &newtio);
|
||||
if (err < 0) {
|
||||
log_print(LOG_ERROR, "%s(): failed to set termios", __FUNCTION__);
|
||||
close(dev->fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (_LCD_DUMMY)
|
||||
static int lcd_fakedevice_reply(int fd, void *privdata)
|
||||
{
|
||||
struct lcddev *dev = (struct lcddev *)privdata;
|
||||
char buf[32];
|
||||
|
||||
if (read(fd, buf, sizeof(buf)) <= 0) {
|
||||
dev->fakedevice_event = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
char reset_expect[] = A125_CMD_RESET;
|
||||
if (memcmp(buf, reset_expect, sizeof(reset_expect)) == 0) {
|
||||
char actinfo_cmd[] = A125_EVENT_ACTINFO;
|
||||
write(fd, actinfo_cmd, sizeof(actinfo_cmd));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lcd_fakedevice_open(struct lcddev *dev)
|
||||
{
|
||||
int fd[2];
|
||||
|
||||
if (socketpair(AF_LOCAL, SOCK_STREAM, 0 , fd) < 0) {
|
||||
log_print(LOG_ERROR, "%s(): socketpair() failed", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fcntl(fd[0], F_SETFD, FD_CLOEXEC) < 0) {
|
||||
log_print(LOG_ERROR, "%s(): fcntl(FD_CLOEXEC)", __FUNCTION__);
|
||||
close(fd[0]);
|
||||
close(fd[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fcntl(fd[1], F_SETFD, FD_CLOEXEC) < 0) {
|
||||
log_print(LOG_ERROR, "%s(): fcntl(FD_CLOEXEC)", __FUNCTION__);
|
||||
close(fd[0]);
|
||||
close(fd[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dev->fd = fd[0];
|
||||
dev->fakedevice_event = event_add_readfd(NULL, fd[1], lcd_fakedevice_reply, dev);
|
||||
return 0;
|
||||
}
|
||||
#endif /* (_LCD_DUMMY) */
|
||||
|
||||
#if (_LCD_DEBUG > 1)
|
||||
static void lcd_dump(const char *prefix, int len, int size, const char *data)
|
||||
{
|
||||
int i;
|
||||
int pos = 0;
|
||||
char buf[256];
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
pos += snprintf(buf, sizeof(buf) - pos, "0x%X ", (unsigned char)data[i]);
|
||||
}
|
||||
|
||||
log_print(LOG_DEBUG, "%s:[%d/%d]: %s", prefix, len, size, buf);
|
||||
}
|
||||
#endif /* (_LCD_DEBUG > 1) */
|
||||
|
||||
static int lcd_read(struct lcddev *dev, const char *buf, int len)
|
||||
{
|
||||
int retval = 0, cnt = 0;
|
||||
while (cnt < len) {
|
||||
retval = read(dev->fd, (char *)buf + cnt, len - cnt);
|
||||
if (retval <= 0)
|
||||
break;
|
||||
|
||||
cnt += retval;
|
||||
}
|
||||
#if (_LCD_DEBUG > 1)
|
||||
lcd_dump(__FUNCTION__, cnt, len, buf);
|
||||
#endif /* (_LCD_DEBUG > 1) */
|
||||
return (cnt != 0) ? cnt : retval;
|
||||
}
|
||||
|
||||
static int lcd_write(struct lcddev *dev, char *buf, int len)
|
||||
{
|
||||
int retval = write(dev->fd, buf, len);
|
||||
|
||||
#if (_LCD_DEBUG > 1)
|
||||
lcd_dump(__FUNCTION__, retval, len, buf);
|
||||
#endif /* (_LCD_DEBUG > 1) */
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void lcd_reset(struct lcddev *dev);
|
||||
|
||||
static int lcd_reset_retry_timeout_cb(int timerid, void *privdata)
|
||||
{
|
||||
struct lcddev *dev = (struct lcddev *)privdata;
|
||||
dev->reset_timeout = NULL;
|
||||
|
||||
lcd_reset(dev);
|
||||
return -1; /* singleshot */
|
||||
}
|
||||
|
||||
static int lcd_reset_timeout_cb(int timerid, void *privdata)
|
||||
{
|
||||
struct lcddev *dev = (struct lcddev *)privdata;
|
||||
|
||||
log_print(LOG_ERROR, "failed to initalize LCD");
|
||||
dev->state = LCD_STATE_INITIALIZING_FAILED;
|
||||
|
||||
dev->reset_timeout = event_add_timeout_ms(LCD_RESET_RETRY_TIMEOUT, lcd_reset_retry_timeout_cb, 0, dev);
|
||||
|
||||
return -1; /* singleshot */
|
||||
}
|
||||
|
||||
static void lcd_reset(struct lcddev *dev)
|
||||
{
|
||||
#if (_LCD_DEBUG > 0)
|
||||
log_print(LOG_DEBUG, "%s()", __FUNCTION__);
|
||||
#endif /* (_LCD_DEBUG > 0) */
|
||||
|
||||
char cmd[] = A125_CMD_RESET;
|
||||
lcd_write(dev, cmd, sizeof(cmd));
|
||||
|
||||
/* force next backlight command */
|
||||
dev->backlight_enabled = -1;
|
||||
|
||||
dev->state = LCD_STATE_INITIALIZING;
|
||||
|
||||
dev->reset_timeout = event_add_timeout_ms(LCD_RESET_TIMEOUT, lcd_reset_timeout_cb, 0, dev);
|
||||
}
|
||||
|
||||
static int lcd_backlight(struct lcddev *dev, int enable)
|
||||
{
|
||||
if (dev->state != LCD_STATE_READY)
|
||||
return -1;
|
||||
|
||||
#if (_LCD_DEBUG > 0)
|
||||
log_print(LOG_DEBUG, "%s(%d)", __FUNCTION__, enable);
|
||||
#endif /* (_LCD_DEBUG > 0) */
|
||||
|
||||
if (dev->backlight_enabled != enable) {
|
||||
char cmd[] = A125_CMD_BACKLIGHT;
|
||||
|
||||
cmd[2] = (enable) ? 0x01 : 0x00;
|
||||
lcd_write(dev, cmd, sizeof(cmd));
|
||||
|
||||
dev->backlight_enabled = enable;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lcd_backlight_timeout_cb(int timerid, void *privdata)
|
||||
{
|
||||
struct lcddev *dev = (struct lcddev *)privdata;
|
||||
dev->backlight_timeout = NULL;
|
||||
|
||||
lcd_set_backlight(dev, 0);
|
||||
|
||||
return -1; /* singleshot */
|
||||
}
|
||||
|
||||
int lcd_set_backlight(struct lcddev *dev, int enable)
|
||||
{
|
||||
if (dev->backlight_timeout != NULL) {
|
||||
event_remove_timeout(dev->backlight_timeout);
|
||||
dev->backlight_timeout = NULL;
|
||||
}
|
||||
|
||||
if (!enable) {
|
||||
lcd_pagecallback(dev, LCDPAGE_EVENT_BACKLIGHT);
|
||||
|
||||
/* callback re-enabled backlight */
|
||||
if (dev->backlight_timeout != NULL) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int retval = lcd_backlight(dev, enable);
|
||||
|
||||
if (enable) {
|
||||
/* start backlight timeout */
|
||||
dev->backlight_timeout = event_add_timeout_ms(dev->backlight_timeout_ms, lcd_backlight_timeout_cb, 0, dev);
|
||||
|
||||
} else {
|
||||
/* disable updates (display is not visible) */
|
||||
if (dev->update_timeout != NULL) {
|
||||
event_remove_timeout(dev->update_timeout);
|
||||
dev->update_timeout = NULL;
|
||||
}
|
||||
|
||||
/* disable scrolling (display is not visible) */
|
||||
if (dev->scroll_timeout != NULL) {
|
||||
event_remove_timeout(dev->scroll_timeout);
|
||||
dev->scroll_timeout = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int lcd_update_timeout_cb(int timerid, void *privdata)
|
||||
{
|
||||
struct lcddev *dev = (struct lcddev *)privdata;
|
||||
|
||||
dev->update_timeout = NULL;
|
||||
lcd_pagecallback(dev, LCDPAGE_EVENT_UPDATE);
|
||||
|
||||
return -1; /* singleshot */
|
||||
}
|
||||
|
||||
static void lcd_update_start(struct lcddev *dev, int update_ms)
|
||||
{
|
||||
dev->update_ms = update_ms;
|
||||
|
||||
if (dev->update_timeout != NULL) {
|
||||
event_remove_timeout(dev->update_timeout);
|
||||
dev->update_timeout = NULL;
|
||||
}
|
||||
|
||||
if (update_ms > 0) {
|
||||
dev->update_timeout = event_add_timeout_ms(update_ms, lcd_update_timeout_cb, 0, dev);
|
||||
}
|
||||
}
|
||||
|
||||
static int lcd_read_cb(int fd, void *privdata)
|
||||
{
|
||||
struct lcddev *dev = (struct lcddev *)privdata;
|
||||
|
||||
char buf[4];
|
||||
int size = (dev->state != LCD_STATE_INITIALIZING) ? sizeof(buf) : 2;
|
||||
int len = lcd_read(dev, buf, size);
|
||||
|
||||
if (dev->state == LCD_STATE_INITIALIZING) {
|
||||
char expect[] = A125_EVENT_ACTINFO;
|
||||
|
||||
if (len != sizeof(expect))
|
||||
return 0;
|
||||
|
||||
if (memcmp(buf, expect, sizeof(expect)) == 0) {
|
||||
event_remove_timeout(dev->reset_timeout);
|
||||
dev->reset_timeout = NULL;
|
||||
|
||||
dev->state = LCD_STATE_READY;
|
||||
|
||||
/* trigger application to set data */
|
||||
lcd_pagecallback(dev, LCDPAGE_EVENT_ENTER);
|
||||
}
|
||||
|
||||
} else if (dev->state == LCD_STATE_READY) {
|
||||
char expect1[] = A125_EVENT_BUTTON1;
|
||||
char expect2[] = A125_EVENT_BUTTON2;
|
||||
|
||||
if (len != sizeof(expect1) && len != sizeof(expect2))
|
||||
return 0;
|
||||
|
||||
if (memcmp(buf, expect1, sizeof(buf)) == 0) {
|
||||
lcd_pagecallback(dev, LCDPAGE_EVENT_BUTTON1);
|
||||
|
||||
} else if (memcmp(buf, expect2, sizeof(buf)) == 0) {
|
||||
lcd_pagecallback(dev, LCDPAGE_EVENT_BUTTON2);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lcd_setline(struct lcddev *dev, int line, int len, const char *buf)
|
||||
{
|
||||
if (dev->state != LCD_STATE_READY)
|
||||
return -1;
|
||||
|
||||
char cmd[20 +1] = A125_CMD_SETLINE;
|
||||
cmd[2] = line;
|
||||
|
||||
memset(cmd +4, ' ', 16);
|
||||
memcpy(cmd +4, buf, (len > 16) ? 16 : len);
|
||||
cmd[20] = '\0';
|
||||
|
||||
#if (_LCD_DEBUG > 0)
|
||||
log_print(LOG_DEBUG, "%s(%d, '%-16s')", __FUNCTION__, line, cmd +4);
|
||||
#endif /* (_LCD_DEBUG > 0) */
|
||||
|
||||
lcd_write(dev, cmd, 20);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lcd_scroll_timeout_cb(int timerid, void *privdata)
|
||||
{
|
||||
struct lcddev *dev = (struct lcddev *)privdata;
|
||||
int i, reset_pos = 0;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
int line_pos = dev->scroll_pos;
|
||||
if (line_pos < 0)
|
||||
line_pos = 0;
|
||||
|
||||
/* mark line as complete if one space is visible after message */
|
||||
if ((dev->line_length[i] - line_pos) <= 15) {
|
||||
reset_pos++;
|
||||
}
|
||||
|
||||
/* do not scroll further if message is not visible */
|
||||
if ((dev->line_length[i] - line_pos) < 0) {
|
||||
line_pos = dev->line_length[i];
|
||||
}
|
||||
|
||||
lcd_setline(dev, i, dev->line_length[i] - line_pos, dev->line_data[i] + line_pos);
|
||||
}
|
||||
|
||||
dev->scroll_pos++;
|
||||
|
||||
if (reset_pos == 2)
|
||||
dev->scroll_pos = -1;
|
||||
|
||||
/* periodic */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lcd_scroll_start(struct lcddev *dev)
|
||||
{
|
||||
if (dev->scroll_timeout != NULL) {
|
||||
event_remove_timeout(dev->scroll_timeout);
|
||||
dev->scroll_timeout = NULL;
|
||||
}
|
||||
|
||||
if ((dev->line_length[0] > 16) || (dev->line_length[1] > 16)) {
|
||||
dev->scroll_timeout = event_add_timeout_ms(LCD_SCROLL_SPEED, lcd_scroll_timeout_cb, 0, dev);
|
||||
}
|
||||
}
|
||||
|
||||
int lcd_setlines(struct lcddev *dev, const char *line1, const char *line2)
|
||||
{
|
||||
int i;
|
||||
int line_length[2] = { 0, 0 };
|
||||
const char *line[2] = { line1, line2 };
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (line[i] != NULL) {
|
||||
line_length[i] = strlen(line[i]);
|
||||
|
||||
if ((line_length[i] == dev->line_length[i]) && (dev->line_data[i] != NULL)) {
|
||||
if (memcmp(line[i], dev->line_data[i], line_length[i]) == 0) {
|
||||
/* same data, no update needed */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->line_data[i] != NULL) {
|
||||
free((void *)dev->line_data[i]);
|
||||
dev->line_data[i] = NULL;
|
||||
}
|
||||
|
||||
if (line[i] != NULL) {
|
||||
dev->line_data[i] = strdup(line[i]);
|
||||
}
|
||||
dev->line_length[i] = line_length[i];
|
||||
|
||||
if (dev->backlight_enabled) {
|
||||
lcd_setline(dev, i, dev->line_length[i], dev->line_data[i]);
|
||||
|
||||
dev->scroll_pos = 0;
|
||||
lcd_scroll_start(dev);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lcd_pagecallback(struct lcddev *dev, int event)
|
||||
{
|
||||
if (dev->state != LCD_STATE_READY) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev->current_page == NULL) {
|
||||
if (list_empty(&dev->page_list)) {
|
||||
return;
|
||||
}
|
||||
|
||||
dev->current_page = list_entry(dev->page_list.next, struct lcdpage, list);
|
||||
}
|
||||
|
||||
if ((dev->backlight_enabled == 0x00) && ((event == LCDPAGE_EVENT_BUTTON1) || (event == LCDPAGE_EVENT_BUTTON2))) {
|
||||
lcd_set_backlight(dev, 1);
|
||||
|
||||
event = LCDPAGE_EVENT_UPDATE;
|
||||
|
||||
/* restart scrolling if needed */
|
||||
lcd_scroll_start(dev);
|
||||
}
|
||||
|
||||
int next;
|
||||
do {
|
||||
#if (_LCD_DEBUG > 0)
|
||||
log_print(LOG_DEBUG, "%s: cb(%p, 0x%x)", __FUNCTION__, dev->current_page, event);
|
||||
#endif
|
||||
int retval = dev->current_page->callback(dev, event, dev->current_page->privdata);
|
||||
#if (_LCD_DEBUG > 0)
|
||||
log_print(LOG_DEBUG, "%s: cb(%p, 0x%x) => 0x%x", __FUNCTION__, dev->current_page, event, retval);
|
||||
#endif
|
||||
|
||||
next = (retval == LCDPAGE_COMMAND_NEXT);
|
||||
if (next) {
|
||||
struct lcdpage *page = dev->current_page;
|
||||
|
||||
if (page->list.next != &dev->page_list) {
|
||||
page = list_entry(page->list.next, struct lcdpage, list);
|
||||
} else {
|
||||
page = list_entry(page->list.next->next, struct lcdpage, list);
|
||||
}
|
||||
|
||||
/* no other page ready */
|
||||
if (page == dev->current_page) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* remove update interval for next page */
|
||||
if (dev->update_timeout != NULL) {
|
||||
event_remove_timeout(dev->update_timeout);
|
||||
dev->update_timeout = NULL;
|
||||
}
|
||||
|
||||
/* remove scroll interval for next page */
|
||||
if (dev->scroll_timeout != NULL) {
|
||||
event_remove_timeout(dev->scroll_timeout);
|
||||
dev->scroll_timeout = NULL;
|
||||
}
|
||||
|
||||
dev->current_page->callback(dev, LCDPAGE_EVENT_EXIT, dev->current_page->privdata);
|
||||
dev->current_page = page;
|
||||
event = LCDPAGE_EVENT_ENTER;
|
||||
|
||||
/* retval is update interval */
|
||||
} else if ((event != LCDPAGE_EVENT_BACKLIGHT) && (event != LCDPAGE_EVENT_EXIT)) {
|
||||
lcd_update_start(dev, retval);
|
||||
}
|
||||
} while (next);
|
||||
}
|
||||
|
||||
int lcd_addpage_cb(struct lcddev *dev,
|
||||
int priority,
|
||||
int (*event_callback)(struct lcddev *dev, int event, void *privdata),
|
||||
void *event_privdata)
|
||||
{
|
||||
struct lcdpage *page = malloc(sizeof(struct lcdpage));
|
||||
if (page == NULL) {
|
||||
log_print(LOG_ERROR, "%s(): out of memory", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
page->priority = priority;
|
||||
page->callback = event_callback;
|
||||
page->privdata = event_privdata;
|
||||
|
||||
int inserted = 0;
|
||||
struct lcdpage *search;
|
||||
list_for_each_entry(search, &dev->page_list, list) {
|
||||
if (page->priority > search->priority) {
|
||||
list_add_tail(&page->list, &search->list);
|
||||
inserted = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!inserted) {
|
||||
list_add_tail(&page->list, &dev->page_list);
|
||||
}
|
||||
|
||||
if (dev->current_page == NULL) {
|
||||
lcd_pagecallback(dev, LCDPAGE_EVENT_ENTER);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct lcddev * lcd_open(const char *devicename, int backlight_timeout)
|
||||
{
|
||||
struct lcddev *dev = malloc(sizeof(struct lcddev));
|
||||
if (dev == NULL) {
|
||||
log_print(LOG_ERROR, "%s(): out of memory", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(dev, 0, sizeof(struct lcddev));
|
||||
|
||||
INIT_LIST_HEAD(&dev->page_list);
|
||||
|
||||
int retval;
|
||||
#if (_LCD_DUMMY)
|
||||
if (strncmp(devicename, "dummy", 5) == 0) {
|
||||
retval = lcd_fakedevice_open(dev);
|
||||
} else
|
||||
#endif /* (_LCD_DUMMY) */
|
||||
{
|
||||
retval = lcd_realdevice_open(dev, devicename);
|
||||
}
|
||||
|
||||
if (retval < 0) {
|
||||
free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dev->read_event = event_add_readfd(NULL, dev->fd, lcd_read_cb, dev);
|
||||
dev->backlight_timeout_ms = backlight_timeout * 1000;
|
||||
|
||||
lcd_reset(dev);
|
||||
return dev;
|
||||
}
|
25
lcd.h
25
lcd.h
@ -1,25 +0,0 @@
|
||||
#ifndef _LCD_H_
|
||||
#define _LCD_H_
|
||||
|
||||
struct lcddev; /* private data */
|
||||
|
||||
struct lcddev * lcd_open(const char *devicename, int backlight_timeout);
|
||||
void lcd_close(struct lcddev *dev);
|
||||
|
||||
int lcd_set_backlight(struct lcddev *dev, int enable);
|
||||
int lcd_setlines(struct lcddev *dev, const char *line1, const char *line2);
|
||||
|
||||
#define LCDPAGE_EVENT_BUTTON1 0xFFFFFF01 /* button "enter" pressed */
|
||||
#define LCDPAGE_EVENT_BUTTON2 0xFFFFFF02 /* button "select" pressed */
|
||||
#define LCDPAGE_EVENT_BACKLIGHT 0xFFFFFF03 /* backlight timeout */
|
||||
#define LCDPAGE_EVENT_ENTER 0xFFFFFF05 /* page entered */
|
||||
#define LCDPAGE_EVENT_EXIT 0xFFFFFF06 /* page left */
|
||||
#define LCDPAGE_EVENT_UPDATE 0xFFFFFF07 /* update content */
|
||||
#define LCDPAGE_COMMAND_NEXT 0xFFFFFF80 /* change to next page */
|
||||
|
||||
int lcd_addpage_cb(struct lcddev *dev,
|
||||
int priority,
|
||||
int (*event_callback)(struct lcddev *dev, int event, void *privdata),
|
||||
void *event_privdata);
|
||||
|
||||
#endif /* _LCD_H_ */
|
238
lcdpage.c
238
lcdpage.c
@ -1,238 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 12/2012 by Olaf Rempel *
|
||||
* razzor@kopf-tisch.de *
|
||||
* *
|
||||
* This program 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 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "lcd.h"
|
||||
#include "lcdpage.h"
|
||||
|
||||
/*
|
||||
* system:
|
||||
* - os version done
|
||||
* - kernel version done
|
||||
* - hostname done
|
||||
* - date/time done
|
||||
* - uptime done
|
||||
* - avgload done
|
||||
* - cpu usage
|
||||
* - memory/swap usage
|
||||
* - temperature done (pic.c)
|
||||
* - fan error done (pic.c)
|
||||
*
|
||||
* disk drives:
|
||||
* - temperature -> disk
|
||||
* - state (idle / running), time to idle -> disk
|
||||
* - current i/o (aggregated?)
|
||||
*
|
||||
* partitions:
|
||||
* - used / free / total
|
||||
*
|
||||
* ethernet interface:
|
||||
* - link (10/100/1000)
|
||||
* - current i/o
|
||||
*
|
||||
* ip interface:
|
||||
* - ip address/netmask
|
||||
* - default gateway
|
||||
* - dns
|
||||
*
|
||||
*/
|
||||
|
||||
static int lcdpage_system(struct lcddev *dev, int event, void *privdata)
|
||||
{
|
||||
static int subpage;
|
||||
int retval = 0;
|
||||
char line1[64];
|
||||
char line2[64];
|
||||
|
||||
memset(line1, 0x00, sizeof(line1));
|
||||
memset(line2, 0x00, sizeof(line2));
|
||||
|
||||
switch (event) {
|
||||
case LCDPAGE_EVENT_BUTTON1:
|
||||
lcd_set_backlight(dev, 1);
|
||||
subpage++;
|
||||
break;
|
||||
|
||||
case LCDPAGE_EVENT_ENTER:
|
||||
lcd_set_backlight(dev, 1);
|
||||
subpage = 0;
|
||||
break;
|
||||
|
||||
case LCDPAGE_EVENT_BACKLIGHT:
|
||||
case LCDPAGE_EVENT_EXIT:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (subpage == 0) {
|
||||
FILE *fp = fopen("/etc/issue.net", "r");
|
||||
if (fp != NULL) {
|
||||
fread(line1, 1, sizeof(line1), fp);
|
||||
fclose(fp);
|
||||
|
||||
char *trim = memchr(line1, 0x0A, sizeof(line1));
|
||||
if (trim != NULL)
|
||||
*trim = '\0';
|
||||
|
||||
trim = memchr(line1, 0x0D, sizeof(line1));
|
||||
if (trim != NULL)
|
||||
*trim = '\0';
|
||||
} else {
|
||||
strcpy(line1, "<unknown>");
|
||||
}
|
||||
|
||||
struct utsname utsbuf;
|
||||
uname(&utsbuf);
|
||||
|
||||
snprintf(line2, sizeof(line2), "%s %s", utsbuf.sysname, utsbuf.release);
|
||||
|
||||
lcd_setlines(dev, line1, line2);
|
||||
|
||||
} else if (subpage == 1) {
|
||||
/* copy hostname */
|
||||
if (gethostname(line2, sizeof(line2)) < 0) {
|
||||
strcpy(line2, "<unknown>");
|
||||
}
|
||||
|
||||
int len = strlen(line2);
|
||||
line2[len++] = '.';
|
||||
|
||||
/* append domainname */
|
||||
if (getdomainname(line2 + len, sizeof(line2) - len) < 0) {
|
||||
strcpy(line2 + len, "unknown");
|
||||
}
|
||||
|
||||
lcd_setlines(dev, "Hostname:", line2);
|
||||
|
||||
} else if (subpage == 2) {
|
||||
struct tm tmp;
|
||||
time_t now;
|
||||
|
||||
time(&now);
|
||||
localtime_r(&now, &tmp);
|
||||
|
||||
strftime(line1, sizeof(line1), "Time: %H:%M:%S", &tmp);
|
||||
strftime(line2, sizeof(line2), "Date: %Y/%m/%d", &tmp);
|
||||
|
||||
lcd_setlines(dev, line1, line2);
|
||||
retval = 1000; /* update every second */
|
||||
|
||||
} else if (subpage == 3) {
|
||||
struct sysinfo info;
|
||||
|
||||
if (sysinfo(&info) < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tmp, days, hours, minutes;
|
||||
|
||||
days = info.uptime / 86400;
|
||||
tmp = info.uptime % 86400;
|
||||
|
||||
hours = tmp / 3600;
|
||||
tmp = tmp % 3600;
|
||||
|
||||
minutes = tmp / 60;
|
||||
tmp = tmp % 60;
|
||||
|
||||
snprintf(line2, sizeof(line2), " %03dd %02d:%02d:%02d", days, hours, minutes, tmp);
|
||||
lcd_setlines(dev, "Uptime:", line2);
|
||||
retval = 1000;
|
||||
|
||||
} else if (subpage == 4) {
|
||||
double loadavg[3];
|
||||
|
||||
if (getloadavg(loadavg, 3) < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
snprintf(line2, sizeof(line2), " %1.2f %1.2f %1.2f", loadavg[0], loadavg[1], loadavg[2]);
|
||||
lcd_setlines(dev, "Load Average:", line2);
|
||||
retval = 1000;
|
||||
|
||||
} else {
|
||||
return LCDPAGE_COMMAND_NEXT;
|
||||
}
|
||||
|
||||
/* update every 1000ms */
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int lcdpage_network(struct lcddev *dev, int event, void *privdata)
|
||||
{
|
||||
static int subpage;
|
||||
|
||||
switch (event) {
|
||||
case LCDPAGE_EVENT_BUTTON1:
|
||||
lcd_set_backlight(dev, 1);
|
||||
subpage++;
|
||||
break;
|
||||
|
||||
case LCDPAGE_EVENT_ENTER:
|
||||
lcd_set_backlight(dev, 1);
|
||||
subpage = 0;
|
||||
break;
|
||||
|
||||
case LCDPAGE_EVENT_BACKLIGHT:
|
||||
case LCDPAGE_EVENT_EXIT:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (subpage) {
|
||||
case 0:
|
||||
lcd_setlines(dev, "Address(br0):", "10.10.250.135");
|
||||
break;
|
||||
case 1:
|
||||
lcd_setlines(dev, "Netmask(br0):", "255.255.0.0");
|
||||
break;
|
||||
case 2:
|
||||
lcd_setlines(dev, "Gateway(br0):", "10.10.250.250");
|
||||
break;
|
||||
default:
|
||||
return LCDPAGE_COMMAND_NEXT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lcdpage_free(void)
|
||||
{
|
||||
/* nothing to do, lcdpages are cleaned up in lcd_close() */
|
||||
}
|
||||
|
||||
int lcdpage_init(struct lcddev *dev)
|
||||
{
|
||||
lcd_addpage_cb(dev, 200, lcdpage_system, NULL);
|
||||
lcd_addpage_cb(dev, 100, lcdpage_network, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
#ifndef _LCDPAGE_H_
|
||||
#define _LCDPAGE_H_
|
||||
|
||||
#include "lcd.h"
|
||||
|
||||
int lcdpage_init(struct lcddev *dev);
|
||||
void lcdpage_free(void);
|
||||
|
||||
#endif /* _LCDPAGE_H_ */
|
@ -28,18 +28,13 @@
|
||||
#include "configfile.h"
|
||||
#include "diskwatch.h"
|
||||
#include "event.h"
|
||||
#include "lcd.h"
|
||||
#include "lcdpage.h"
|
||||
#include "logging.h"
|
||||
#include "pic.h"
|
||||
#include "pidfile.h"
|
||||
#include "signals.h"
|
||||
|
||||
#define DEFAULT_CONFIG "qnapd.conf"
|
||||
#define DEFAULT_LOGFILE "qnapd.log"
|
||||
#define DEFAULT_PIDFILE "qnapd.pid"
|
||||
|
||||
#define LCD_TIMEOUT 15
|
||||
#define DEFAULT_CONFIG "diskwatch.conf"
|
||||
#define DEFAULT_LOGFILE "diskwatch.log"
|
||||
#define DEFAULT_PIDFILE "diskwatch.pid"
|
||||
|
||||
static struct option opts[] = {
|
||||
{ "config", 1, 0, 'c' },
|
||||
@ -83,7 +78,7 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
|
||||
case 'h': /* help */
|
||||
printf("Usage: qnapd [options]\n"
|
||||
printf("Usage: diskwatch [options]\n"
|
||||
"Options: \n"
|
||||
" --config -c configfile use this configfile\n"
|
||||
" --debug -d do not fork and log to stderr\n"
|
||||
@ -109,7 +104,7 @@ int main(int argc, char *argv[])
|
||||
/* check pidfile */
|
||||
const char *pidfile = config_get_string("global", "pidfile", DEFAULT_PIDFILE);
|
||||
if (pidfile_check(pidfile, 1) != 0) {
|
||||
log_print(LOG_ERROR, "qnapd already running");
|
||||
log_print(LOG_ERROR, "diskwatch already running");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -134,42 +129,13 @@ int main(int argc, char *argv[])
|
||||
signal_init();
|
||||
signal_add_callback(SIGHUP, trigger_restart, NULL);
|
||||
|
||||
log_print(LOG_EVERYTIME, "qnapd started (pid:%d)", getpid());
|
||||
log_print(LOG_EVERYTIME, "diskwatch started (pid:%d)", getpid());
|
||||
|
||||
while (1) {
|
||||
struct lcddev *lcd = NULL;
|
||||
struct picdev *pic = NULL;
|
||||
int abort = 0;
|
||||
|
||||
do {
|
||||
const char *devicename = config_get_string("global", "lcddevice", NULL);
|
||||
if (devicename != NULL) {
|
||||
int lcdtimeout;
|
||||
|
||||
config_get_int("global", "lcdtimeout", &lcdtimeout, LCD_TIMEOUT);
|
||||
|
||||
lcd = lcd_open(devicename, lcdtimeout);
|
||||
if (lcd == NULL) {
|
||||
abort = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (lcdpage_init(lcd) < 0) {
|
||||
abort = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
devicename = config_get_string("global", "picdevice", NULL);
|
||||
if (devicename != NULL) {
|
||||
pic = pic_open(devicename, lcd);
|
||||
if (pic == NULL) {
|
||||
abort = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (diskwatch_init(lcd) < 0) {
|
||||
if (diskwatch_init() < 0) {
|
||||
abort = 1;
|
||||
break;
|
||||
}
|
||||
@ -180,15 +146,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
diskwatch_exit();
|
||||
|
||||
if (pic != NULL) {
|
||||
pic_close(pic);
|
||||
}
|
||||
|
||||
if (lcd != NULL) {
|
||||
lcdpage_free();
|
||||
lcd_close(lcd);
|
||||
}
|
||||
|
||||
config_free();
|
||||
|
||||
if (abort)
|
||||
@ -201,7 +158,7 @@ int main(int argc, char *argv[])
|
||||
if (!debug && log_init(logfile) < 0)
|
||||
break;
|
||||
|
||||
log_print(LOG_EVERYTIME, "qnapd restarted (pid:%d) ", getpid());
|
||||
log_print(LOG_EVERYTIME, "diskwatch restarted (pid:%d) ", getpid());
|
||||
}
|
||||
|
||||
return 0;
|
257
pic.c
257
pic.c
@ -1,257 +0,0 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 02/2012 by Olaf Rempel *
|
||||
* razzor@kopf-tisch.de *
|
||||
* *
|
||||
* This program 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 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program 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., *
|
||||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
||||
***************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include "event.h"
|
||||
#include "lcd.h"
|
||||
#include "logging.h"
|
||||
#include "pic.h"
|
||||
|
||||
struct picdev {
|
||||
int fd;
|
||||
struct termios oldtio;
|
||||
|
||||
int fan_speed;
|
||||
int fan_error;
|
||||
int temperature;
|
||||
|
||||
struct event_fd *read_event;
|
||||
};
|
||||
|
||||
static int pic_close_device(struct picdev *dev)
|
||||
{
|
||||
tcsetattr(dev->fd, TCSANOW, &dev->oldtio);
|
||||
close(dev->fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pic_open_device(struct picdev *dev, const char *device)
|
||||
{
|
||||
dev->fd = open(device, O_RDWR | O_NOCTTY);
|
||||
if (dev->fd < 0) {
|
||||
log_print(LOG_ERROR, "%s(): failed to open '%s'", __FUNCTION__, device);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fcntl(dev->fd, F_SETFD, FD_CLOEXEC) < 0) {
|
||||
log_print(LOG_ERROR, "%s(): fcntl(FD_CLOEXEC)", __FUNCTION__);
|
||||
close(dev->fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tcgetattr(dev->fd, &dev->oldtio);
|
||||
|
||||
struct termios newtio;
|
||||
memset(&newtio, 0, sizeof(newtio));
|
||||
newtio.c_iflag |= IGNBRK;
|
||||
newtio.c_lflag &= ~(ISIG | ICANON | ECHO);
|
||||
newtio.c_cflag = B19200 | CS8 | CLOCAL | CREAD;
|
||||
newtio.c_cc[VMIN] = 1;
|
||||
newtio.c_cc[VTIME] = 0;
|
||||
cfsetospeed(&newtio, B19200);
|
||||
cfsetispeed(&newtio, B19200);
|
||||
|
||||
int err = tcsetattr(dev->fd, TCSAFLUSH, &newtio);
|
||||
if (err < 0) {
|
||||
log_print(LOG_ERROR, "%s(): failed to set termios", __FUNCTION__);
|
||||
close(dev->fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pic_set_fanspeed(struct picdev *dev, char value)
|
||||
{
|
||||
if (value < PIC_CMD_FANSPEED_0 || value > PIC_CMD_FANSPEED_5)
|
||||
return -1;
|
||||
|
||||
dev->fan_speed = value - PIC_CMD_FANSPEED_0;
|
||||
|
||||
write(dev->fd, &value, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pic_set_buzzer(struct picdev *dev, char value)
|
||||
{
|
||||
if (value < PIC_CMD_BUZZ_SHORT || value > PIC_CMD_BUZZ_LONG)
|
||||
return -1;
|
||||
|
||||
write(dev->fd, &value, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pic_set_status_led(struct picdev *dev, char value)
|
||||
{
|
||||
if (value < PIC_CMD_STATUSLED_RED_2HZ || value > PIC_CMD_STATUSLED_REDGREEN_1HZ)
|
||||
return -1;
|
||||
|
||||
write(dev->fd, &value, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pic_set_usb_led(struct picdev *dev, char value)
|
||||
{
|
||||
if (value < PIC_CMD_USBLED_ON || value > PIC_CMD_USBLED_OFF)
|
||||
return -1;
|
||||
|
||||
write(dev->fd, &value, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pic_read_cb(int fd, void *privdata)
|
||||
{
|
||||
struct picdev *dev = (struct picdev *)privdata;
|
||||
|
||||
unsigned char event;
|
||||
int len = read(dev->fd, &event, 1);
|
||||
if (len < 0)
|
||||
return -1;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case PIC_EVENT_FAN1_ERR:
|
||||
pic_set_buzzer(dev, PIC_CMD_BUZZ_SHORT);
|
||||
dev->fan_error = 1;
|
||||
break;
|
||||
|
||||
case PIC_EVENT_FAN1_OK:
|
||||
dev->fan_error = 0;
|
||||
break;
|
||||
|
||||
case PIC_EVENT_FAN2_ERR:
|
||||
case PIC_EVENT_FAN2_OK:
|
||||
break;
|
||||
|
||||
case PIC_EVENT_TEMP_RANGE_MIN ... PIC_EVENT_TEMP_RANGE_MAX:
|
||||
dev->temperature = event - 128;
|
||||
break;
|
||||
|
||||
case PIC_EVENT_TEMP_WARN:
|
||||
pic_set_buzzer(dev, PIC_CMD_BUZZ_SHORT);
|
||||
dev->temperature = 75;
|
||||
break;
|
||||
|
||||
case PIC_EVENT_TEMP_CRIT:
|
||||
dev->temperature = 80;
|
||||
break;
|
||||
|
||||
default:
|
||||
log_print(LOG_DEBUG, "%s(): unknown event 0x%02x", __FUNCTION__, event);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lcdpage_case(struct lcddev *lcd, int event, void *privdata)
|
||||
{
|
||||
struct picdev *dev = (struct picdev *)privdata;
|
||||
|
||||
switch (event) {
|
||||
case LCDPAGE_EVENT_BUTTON1:
|
||||
return LCDPAGE_COMMAND_NEXT;
|
||||
|
||||
case LCDPAGE_EVENT_BUTTON2:
|
||||
{
|
||||
int fan_speed = PIC_CMD_FANSPEED_0 + dev->fan_speed +1;
|
||||
|
||||
if (fan_speed > PIC_CMD_FANSPEED_5)
|
||||
fan_speed = PIC_CMD_FANSPEED_0;
|
||||
|
||||
pic_set_fanspeed(dev, fan_speed);
|
||||
lcd_set_backlight(lcd, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
case LCDPAGE_EVENT_ENTER:
|
||||
lcd_set_backlight(lcd, 1);
|
||||
break;
|
||||
|
||||
case LCDPAGE_EVENT_BACKLIGHT:
|
||||
case LCDPAGE_EVENT_EXIT:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
char line1_ok[] = "FAN(OK): TEMP:";
|
||||
char line1_err[] = "FAN(ERR): TEMP:";
|
||||
char line2[20];
|
||||
|
||||
snprintf(line2, sizeof(line2), "[ ] %02d C ", dev->temperature);
|
||||
|
||||
int i;
|
||||
for (i = 1; i <= dev->fan_speed; i++) {
|
||||
line2[i] = '#';
|
||||
}
|
||||
|
||||
lcd_setlines(lcd, (dev->fan_error ? line1_err : line1_ok), line2);
|
||||
return 1000;
|
||||
}
|
||||
|
||||
struct picdev * pic_open(const char *devicename, struct lcddev *lcd)
|
||||
{
|
||||
struct picdev *dev = malloc(sizeof(struct picdev));
|
||||
if (dev == NULL) {
|
||||
log_print(LOG_ERROR, "%s(): out of memory", __FUNCTION__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(dev, 0, sizeof(struct picdev));
|
||||
|
||||
if (pic_open_device(dev, devicename) < 0) {
|
||||
free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dev->read_event = event_add_readfd(NULL, dev->fd, pic_read_cb, dev);
|
||||
|
||||
if (lcd != NULL) {
|
||||
lcd_addpage_cb(lcd, 190, lcdpage_case, dev);
|
||||
}
|
||||
|
||||
pic_set_fanspeed(dev, PIC_CMD_FANSPEED_1);
|
||||
pic_set_status_led(dev, PIC_CMD_STATUSLED_GREENON);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
void pic_close(struct picdev *dev)
|
||||
{
|
||||
if (dev->read_event != NULL) {
|
||||
event_remove_fd(dev->read_event);
|
||||
dev->read_event = NULL;
|
||||
}
|
||||
|
||||
pic_close_device(dev);
|
||||
|
||||
free(dev);
|
||||
}
|
64
pic.h
64
pic.h
@ -1,64 +0,0 @@
|
||||
#ifndef _PIC_H_
|
||||
#define _PIC_H_
|
||||
|
||||
struct picdev; /* private data */
|
||||
|
||||
struct picdev * pic_open(const char *devicename, struct lcddev *lcd);
|
||||
void pic_close(struct picdev *dev);
|
||||
|
||||
#define PIC_CMD_FANSPEED_0 0x30
|
||||
#define PIC_CMD_FANSPEED_1 0x31
|
||||
#define PIC_CMD_FANSPEED_2 0x32
|
||||
#define PIC_CMD_FANSPEED_3 0x33
|
||||
#define PIC_CMD_FANSPEED_4 0x34
|
||||
#define PIC_CMD_FANSPEED_5 0x35
|
||||
|
||||
#define PIC_CMD_POWER_OFF 0x41
|
||||
|
||||
#define PIC_CMD_AUTOPOWER_ON 0x48
|
||||
#define PIC_CMD_AUTOPOWER_OFF 0x49
|
||||
|
||||
#define PIC_EVENT_POWER_BUTTON 0x40
|
||||
|
||||
#define PIC_CMD_POWERLED_OFF 0x4B
|
||||
#define PIC_CMD_POWERLED_2HZ 0x4C
|
||||
#define PIC_CMD_POWERLED_ON 0x4D
|
||||
#define PIC_CMD_POWERLED_1HZ 0x4E
|
||||
|
||||
#define PIC_CMD_BUZZ_SHORT 0x50
|
||||
#define PIC_CMD_BUZZ_LONG 0x51
|
||||
|
||||
#define PIC_CMD_STATUSLED_RED_2HZ 0x54
|
||||
#define PIC_CMD_STATUSLED_GREEN_2HZ 0x55
|
||||
#define PIC_CMD_STATUSLED_GREENON 0x56
|
||||
#define PIC_CMD_STATUSLED_REDON 0x57
|
||||
#define PIC_CMD_STATUSLED_REDGREEN_2HZ 0x58
|
||||
#define PIC_CMD_STATUSLED_OFF 0x59
|
||||
#define PIC_CMD_STATUSLED_GREEN_1HZ 0x5A
|
||||
#define PIC_CMD_STATUSLED_RED_1HZ 0x5B
|
||||
#define PIC_CMD_STATUSLED_REDGREEN_1HZ 0x5C
|
||||
|
||||
#define PIC_CMD_USBLED_ON 0x60
|
||||
#define PIC_CMD_USBLED_8HZ 0x61
|
||||
#define PIC_CMD_USBLED_OFF 0x62
|
||||
|
||||
#define PIC_EVENT_FAN1_ERR 0x73
|
||||
#define PIC_EVENT_FAN1_OK 0x74
|
||||
#define PIC_EVENT_FAN2_ERR 0x75
|
||||
#define PIC_EVENT_FAN2_OK 0x76
|
||||
#define PIC_EVENT_FAN3_ERR 0x77
|
||||
#define PIC_EVENT_FAN3_OK 0x78
|
||||
#define PIC_EVENT_FAN4_ERR 0x79
|
||||
#define PIC_EVENT_FAN4_OK 0x7A
|
||||
|
||||
#define PIC_EVENT_TEMP_RANGE_MIN 0x80 /* 0°C */
|
||||
#define PIC_EVENT_TEMP_RANGE_MAX 0xC6 /* 70°C */
|
||||
#define PIC_EVENT_TEMP_WARN 0x38 /* 71-79°C */
|
||||
#define PIC_EVENT_TEMP_CRIT 0x39 /* >= 80°C */
|
||||
|
||||
int pic_set_fanspeed(struct picdev *dev, char value);
|
||||
int pic_set_buzzer(struct picdev *dev, char value);
|
||||
int pic_set_status_led(struct picdev *dev, char value);
|
||||
int pic_set_usb_led(struct picdev *dev, char value);
|
||||
|
||||
#endif /* _PIC_H_ */
|
20
qnapd.conf
20
qnapd.conf
@ -1,20 +0,0 @@
|
||||
[global]
|
||||
|
||||
#lcddevice /dev/ttyS0
|
||||
#picdevice /dev/ttyS1
|
||||
|
||||
#lcddevice dummy
|
||||
|
||||
lcdtimeout 15
|
||||
|
||||
pidfile qnapd.pid
|
||||
logfile qnapd.log
|
||||
|
||||
[diskwatch]
|
||||
check_interval 60
|
||||
hddtemp_server 127.0.0.1:7634
|
||||
|
||||
#disk /dev/sda,7200
|
||||
#disk /dev/sdb,7200
|
||||
#disk /dev/sdc,7200
|
||||
#disk /dev/sdd,7200
|
Loading…
Reference in New Issue
Block a user