Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F1880190
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Size
19 KB
Subscribers
None
View Options
diff --git a/daemon.c b/daemon.c
--- a/daemon.c
+++ b/daemon.c
@@ -1,259 +1,568 @@
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
+#include <stdlib.h>
#include <memory.h>
+#include <signal.h>
+#include <poll.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/uio.h>
+
#include "dns320l.h"
-#define FAN_POLL_TIME 15
+#define FAN_POLL_TIME 15
+#define GPIO_POLL_TIME 1
+#define SERVER_PORT 57367
+#define SYSFS_GPIO_DIR "/sys/class/gpio"
+
+int ls;
+int fd;
+
+int gpio_get_value(unsigned int gpio, unsigned int *value)
+{
+ int fd, len;
+ char buf[100];
+ char ch;
+
+ len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
+
+ fd = open(buf, O_RDONLY);
+ if (fd < 0) {
+ perror("gpio/get-value");
+ return fd;
+ }
+
+ read(fd, &ch, 1);
+
+ if (ch != '0') {
+ *value = 1;
+ } else {
+ *value = 0;
+ }
+
+ close(fd);
+ return 0;
+}
+
-int
-set_interface_attribs (int fd, int speed, int parity)
+void cleanup(int shut,int s,int howmany)
+{
+ int retval;
+
+ /*
+ * Shutdown and close sock1 completely.
+ */
+ if (shut)
+ {
+ retval = shutdown(s,howmany);
+ if (retval == -1)
+ perror ("shutdown");
+ }
+ retval = close (s);
+ if (retval)
+ perror ("close");
+}
+
+void sighandler(int sig)
+{
+ if (sig == SIGINT){
+ cleanup(0, ls,1);
+ exit(EXIT_SUCCESS);
+ }
+}
+
+void declsighandler()
+{
+ struct sigaction action;
+
+ sigemptyset(&action.sa_mask);
+ sigaddset(&action.sa_mask,SIGINT);
+ action.sa_flags = 0;
+ action.sa_handler = sighandler;
+ sigaction(SIGINT,&action,NULL);
+}
+
+int set_interface_attribs (int fd, int speed, int parity)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
printf("error %d from tcgetattr", errno);
return -1;
}
cfsetospeed (&tty, speed);
cfsetispeed (&tty, speed);
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
// disable IGNBRK for mismatched speed tests; otherwise receive break
// as \000 chars
tty.c_iflag &= ~IGNBRK; // ignore break signal
tty.c_lflag = 0; // no signaling chars, no echo,
// no canonical processing
tty.c_oflag = 0; // no remapping, no delays
tty.c_cc[VMIN] = 0; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
// enable reading
tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
tty.c_cflag |= parity;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;
if (tcsetattr (fd, TCSANOW, &tty) != 0)
{
printf("error %d from tcsetattr", errno);
return -1;
}
return 0;
}
-void
-set_blocking (int fd, int should_block)
+void set_blocking (int fd, int should_block)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
printf("error %d from tggetattr", errno);
return;
}
tty.c_cc[VMIN] = should_block ? 1 : 0;
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
if (tcsetattr (fd, TCSANOW, &tty) != 0)
printf("error %d setting term attributes", errno);
}
int CheckResponse(char *buf, const char *cmd, int len)
{
int i;
int tmp;
for(i=0;i<5;i++)
{
if(buf[i] != cmd[i])
{
printf("Char %i is %i but should be %i\n", i, buf[i], cmd[i]);
return ERR_WRONG_ANSWER;
}
}
if(buf[len-1] != cmd[len-1])
return ERR_WRONG_ANSWER;
tmp = (unsigned char)buf[5];
return tmp;
}
int SendCommand(int fd, const char *cmd, int checkAnswer)
{
int n;
int i;
unsigned int tmp;
char buf[15]; // We need to keep the DateAndTime values here
// Yes, we're sending byte by byte here - b/c the lenght of
// commands and responses can vary!
i=0;
do
{
write(fd, &cmd[i], 1);
i++;
} while(cmd[i-1] != CMD_STOP_MAGIC);
i=0;
do
{
n = read(fd, &buf[i], 1);
i++;
} while((n == 1) && (buf[i-1] != CMD_STOP_MAGIC));
if(buf[i-1] != CMD_STOP_MAGIC)
{
printf("Got no stop magic!\n");
return ERR_WRONG_ANSWER;
}
else
{
if(checkAnswer)
{
tmp = CheckResponse(buf, cmd, i);
- usleep(10000); // Give the µC some time to answer...
+ usleep(20000); // Give the µC some time to answer...
i=0;
do
{
n = read(fd, &buf[i], 1);
i++;
} while((n == 1) && (buf[i-1] != CMD_STOP_MAGIC));
if(buf[i-1] != CMD_STOP_MAGIC)
{
printf("Got no stop magic!\n");
return ERR_WRONG_ANSWER;
}
CheckResponse(buf, AckFromSerial, i);
return tmp;
}
else
{
return CheckResponse(buf, AckFromSerial, i);
}
}
}
+int HandleCommand(char *message, int messageLen, char *retMessage, int bufSize)
+{
+ int tmp;
+ int len;
+ int i;
+ char cmp[] = "DeviceReady";
+ printf("Handling Command: %s\n", message);
+
+ if(strncmp(message, "DeviceReady", messageLen) == 0)
+ {
+ printf("DeviceReady\n");
+ if(SendCommand(fd, DeviceReadyCmd, 0) == 0)
+ strncpy(retMessage, "OK\n", bufSize);
+ else
+ strncpy(retMessage, "ERR\n", bufSize);
+ }
+ else if(strncmp(message, "GetTemperature", messageLen) == 0)
+ {
+ printf("GetTemperature\n");
+ tmp = SendCommand(fd, ThermalStatusGetCmd, 1);
+ tmp = ThermalTable[tmp];
+ sprintf(retMessage, "%d", tmp);
+ len = strlen(retMessage);
+ retMessage[len] = '\n';
+ retMessage[len+1] = '\0';
+ }
+ else if(strncmp(message, "DeviceShutdown", strlen("DeviceShutdown")) == 0)
+ {
+ printf("DeviceShutdown");
+ if(messageLen >= (strlen("DeviceShutdown") + 2))
+ {
+ //tmp = atoi(&message[strlen("DeviceShutdown") + 1]); // FIXME: The parameter is never passed, we default to 10s here..
+ //printf("%s\n", tmp);
+ if(SendCommand(fd, DeviceShutdownCmd, 0) == 0)
+ strncpy(retMessage, "OK\n", bufSize);
+ else
+ strncpy(retMessage, "ERR\n", bufSize);
+ }
+ }
+ else if(strncmp(message, "quit", messageLen) == 0)
+ {
+ printf("Quit\n");
+ strncpy(retMessage, "Bye\n", bufSize);
+ return 1;
+ }
+ else
+ {
+ strncpy(retMessage, "Command not Understood!\n", bufSize);
+ }
+
+
+ //strcpy(retMessage, "OK\n");
+
+ return 0;
+}
+
int main(int args, char *argv[])
{
char *portname = "/dev/ttyS1"; // We hardcode the path, as this daemon is inteded to run on one box only
- int fd;
+ char response[100];
int n;
int i;
+ int j;
+ int powerBtn;
+ int pressed;
+ int opt;
int sleepCount;
- int sleepTimeUs;
- char buf [100];
+ int pollTimeMs;
+ char buf[100];
int temperature;
int fanSpeed;
+ struct sockaddr_in s_name;
+ struct pollfd *fds = NULL;
+ nfds_t nfds;
+ int retval;
+ int ret;
+ int atmark;
+ int msgIdx;
+ char message[100];
+ socklen_t namelength;
+ pressed = 0;
+ nfds = 1;
+ opt = 1;
+ sleepCount = 0;
+ pollTimeMs = 10; // Sleep 10ms for every loop
+ fanSpeed = -1;
+
+ if ((ls = socket (AF_INET, SOCK_STREAM, 0)) == -1){
+ perror( "socket");
+ exit(EXIT_FAILURE);
+ }
+
+ if (setsockopt(ls,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof opt)<0){
+ printf ("setsockopt (SO_RESUSEADDR): %s\r\n",strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+
+ s_name.sin_family = AF_INET;
+ s_name.sin_port = htons(SERVER_PORT);
+ s_name.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ printf(" \t Bind name to ls. \n");
+ retval = bind (ls,(struct sockaddr *)&s_name, sizeof s_name);
+ if (retval)
+ {
+ perror("bind");
+ cleanup(0, ls,1);
+ exit(EXIT_FAILURE);
+ }
+
+ printf(" \t Listen on ls for connections. \n");
+ retval = listen (ls, 5);
+ if (retval)
+ {
+ perror("listen");
+ cleanup(0, ls,1);
+ exit(EXIT_FAILURE);
+ }
+ declsighandler();
+
+
+ fds = (struct pollfd *)calloc(1,nfds*sizeof(struct pollfd));
+ fds->fd = ls;
+ fds->events = POLLIN | POLLPRI;
+
+
+
+
fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0)
{
printf("error %d opening %s: %s", errno, portname, strerror (errno));
return;
}
set_interface_attribs (fd, B115200, 0); // set speed to 115,200 bps, 8n1 (no parity)
set_blocking (fd, 0); // set no blocking
// Flush the serial port first...
read(fd, buf, 100);
if(SendCommand(fd, DeviceReadyCmd, 0) == 0)
printf("DeviceReady command sent, going to Fan Control Mode...\n");
else
{
printf("Error sending DeviceReady command, exit!\n");
return 1;
}
-
- sleepCount = 0;
- sleepTimeUs = 1000 * 100; // Sleep 100ms for every loop
- fanSpeed = 0;
while(1)
{
sleepCount = 0;
- temperature = SendCommand(fd, FanStatusGetCmd, 1);
+ temperature = SendCommand(fd, ThermalStatusGetCmd, 1);
if(temperature > 0)
{
temperature = ThermalTable[temperature];
printf("Read Temperature: %i\n", temperature);
if(temperature < (TEMP_LOW - HYSTERESIS))
{
if(fanSpeed != 0)
{
printf("Set Fan Stop\n");
SendCommand(fd, FanStopCmd, 0);
fanSpeed = 0;
}
}
else if(temperature < TEMP_LOW)
{
if(fanSpeed > 1)
{
printf("Set Fan Half\n");
SendCommand(fd, FanHalfCmd, 0);
fanSpeed = 1;
}
}
else if(temperature < (TEMP_HIGH - HYSTERESIS))
{
if(fanSpeed != 1)
{
printf("Set Fan Half\n");
SendCommand(fd, FanHalfCmd, 0);
fanSpeed = 1;
}
}
else if(temperature < TEMP_HIGH)
{
if(fanSpeed < 1)
{
printf("Set Fan Half\n");
SendCommand(fd, FanHalfCmd, 0);
fanSpeed = 1;
}
}
else
{
if(fanSpeed != 2)
{
printf("Set Fan Full\n");
SendCommand(fd, FanFullCmd, 0);
fanSpeed = 2;
}
}
}
else
{
printf("Error reading Temperature!\n");
}
- while((sleepCount * sleepTimeUs) < (FAN_POLL_TIME * 1000 * 1000))
+ while((sleepCount * pollTimeMs) < (FAN_POLL_TIME * 1000))
{
- usleep(sleepTimeUs); // Sleep 100ms, replace by socket polling code for IPC
+ if(((sleepCount * pollTimeMs) % (GPIO_POLL_TIME * 1000)) == 0)
+ {
+ if(gpio_get_value(GPIO_BUTTON_POWER, &powerBtn) == 0)
+ {
+ if((powerBtn == 0) && !pressed)
+ {
+ pressed = 1;
+ printf("Power Button Pressed!\n");
+ }
+ }
+
+ }
sleepCount++;
+
+ ret=poll(fds,nfds,pollTimeMs); // Time out after pollTimeMs
+ if (ret == -1){
+ perror ("poll");
+ exit(EXIT_FAILURE);
+ }
+ for (i=0;(i<nfds) && (ret);i++)
+ {
+ if (!(fds+i)->revents)
+ continue;
+ printf(" after : revents=0x%x, ret=%d\n\n",
+ (fds+i)->revents,
+ ret);
+ ret--;
+ if (((fds+i)->fd == ls) && ((fds+i)->revents & POLLIN))
+ {
+ /*
+ * Accept connection from socket ls:
+ * accepted connection will be on socket (fds+nfds)->fd.
+ */
+ printf(" \t POLLIN on ls. Accepting connection\n");
+ namelength = sizeof (s_name);
+ fds = (struct pollfd *)realloc(fds,(nfds+1)*sizeof(struct pollfd));
+ (fds+nfds)->fd = accept (ls, (struct sockaddr *)&s_name, &namelength);
+ if ((fds+nfds)->fd == -1)
+ {
+ perror ("accept");
+ cleanup(0, (fds+nfds)->fd, 1);
+ fds = (struct pollfd *)realloc(fds,nfds*sizeof(struct pollfd));
+ continue;
+ }
+ (fds+nfds)->events = POLLIN | POLLRDNORM;
+ nfds++;
+ continue;
+ }
+ if ((fds+i)->revents & POLLNVAL)
+ {
+ printf ("POLLNVAL on socket. Freeing resource\n");
+ nfds--;
+ memcpy(fds+i,fds+i+1,nfds-i);
+ fds = (struct pollfd *)realloc(fds,nfds*sizeof(struct pollfd));
+ continue;
+ }
+ if ((fds+i)->revents & POLLHUP)
+ {
+ printf ("\t POLLHUP => peer reset connection ...\n");
+ cleanup(0,(fds+i)->fd,2);
+ nfds--;
+ memcpy(fds+i,fds+i+1,nfds-i);
+ fds = (struct pollfd *)realloc(fds,nfds*sizeof(struct pollfd));
+ continue;
+ }
+ if ((fds+i)->revents & POLLERR){
+ printf ("\t POLLERR => peer reset connection ...\n");
+ cleanup(0,(fds+i)->fd,2);
+ nfds--;
+ memcpy(fds+i,fds+i+1,nfds-i);
+ fds = (struct pollfd *)realloc(fds,nfds*sizeof(struct pollfd));
+ continue;
+ }
+ if ((fds+i)->revents & POLLRDNORM)
+ {
+ retval = recv((fds+i)->fd, message, sizeof(message)-1, 0); // Don't forget the string terminator here!
+ printf(" \t -> (recv) retval = %d.\n",retval); /* ped */
+ msgIdx = retval;
+ if (retval <=0)
+ {
+ if (retval == 0)
+ {
+ printf ("\t recv()==0 => peer disconnected...\n");
+ cleanup(1,(fds+i)->fd,2);
+ }
+ else
+ {
+ perror ("\t receive");
+ cleanup( 0, (fds+i)->fd,1);
+ }
+ nfds--;
+ memcpy(fds+i,fds+i+1,nfds-i);
+ fds = (struct pollfd *)realloc(fds,nfds*sizeof(struct pollfd));
+ continue;
+ }
+ while((retval > 0) && (message[msgIdx-2] != '\r') && ((msgIdx+1) < sizeof(message)))
+ {
+ retval = recv((fds+i)->fd, &message[msgIdx-2], sizeof(message) - retval - 1, 0);
+ printf(" \t -> (recv) retval = %d.\n", retval);
+ if(retval > 0)
+ msgIdx += retval - 2;
+ }
+ if(msgIdx > 1)
+ if(message[msgIdx-1] == '\n')
+ if(message[msgIdx-2] == '\r')
+ message[msgIdx-2] = '\0';
+ else
+ message[msgIdx-1] = '\0';
+
+ printf (" \t Normal message : %.*s\n",retval,message);
+ msgIdx = HandleCommand(message, msgIdx, response, sizeof(response));
+ retval = send((fds+i)->fd, response, strlen(response), 0);
+ if((retval < 0) || (msgIdx == 1))
+ {
+ printf("\t send()==0 => peer disconnected...\n");
+ cleanup(1,(fds+1)->fd, 2);
+ }
+ continue;
+ }
+ }
}
-
}
return 0;
}
diff --git a/dns320l.h b/dns320l.h
--- a/dns320l.h
+++ b/dns320l.h
@@ -1,41 +1,43 @@
#ifndef DNS320L_H
#define DNS320L_H
-#define ERR_WRONG_ANSWER -1
+#define ERR_WRONG_ANSWER -1
-#define TEMP_LOW 40
-#define TEMP_HIGH 45
-#define HYSTERESIS 2
-#define CMD_START_MAGIC 0xfa
-#define CMD_STOP_MAGIC 0xfb
+#define TEMP_LOW 45
+#define TEMP_HIGH 50
+#define HYSTERESIS 2
+#define CMD_START_MAGIC 0xfa
+#define CMD_STOP_MAGIC 0xfb
+#define GPIO_BUTTON_POWER 29
-const char DeviceReadyCmd[] = {0xfa, 0x03, 0x01, 0x00, 0x00, 0x00, 0xfb};
-const char AckFromSerial[] = {0xfa, 0x30, 0x00, 0x00, 0x00, 0x00, 0xfb};
-const char FanStatusGetCmd[] = {0xfa, 0x03, 0x08, 0x00, 0x00, 0x00, 0xfb};
-const char FanStopCmd[] = {0xfa, 0x02, 0x00, 0x00, 0x00, 0x00, 0xfb};
-const char FanHalfCmd[] = {0xfa, 0x02, 0x00, 0x01, 0x00, 0x00, 0xfb};
-const char FanFullCmd[] = {0xfa, 0x02, 0x00, 0x02, 0x00, 0x00, 0xfb};
+const char DeviceReadyCmd[] = {0xfa, 0x03, 0x01, 0x00, 0x00, 0x00, 0xfb};
+const char AckFromSerial[] = {0xfa, 0x30, 0x00, 0x00, 0x00, 0x00, 0xfb};
+const char ThermalStatusGetCmd[] = {0xfa, 0x03, 0x08, 0x00, 0x00, 0x00, 0xfb};
+const char FanStopCmd[] = {0xfa, 0x02, 0x00, 0x00, 0x00, 0x00, 0xfb};
+const char FanHalfCmd[] = {0xfa, 0x02, 0x00, 0x01, 0x00, 0x00, 0xfb};
+const char FanFullCmd[] = {0xfa, 0x02, 0x00, 0x02, 0x00, 0x00, 0xfb};
+const char DeviceShutdownCmd[] = {0xfa, 0x03, 0x03, 0x01, 0x01, 0x0a, 0xfb};
const char ThermalTable[] = {0x74, 0x73, 0x72, 0x71, 0x70, 0x6F, 0x6E, 0x6D, 0x6C, 0x6B,
0x6A, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61,
0x60, 0x5F, 0x5E, 0x5D, 0x5C, 0x5B, 0x5A, 0x59, 0x58, 0x57,
0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4F, 0x4E, 0x4D,
0x4C, 0x4B, 0x4A, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43,
0x42, 0x41, 0x41, 0x40, 0x3F, 0x3E, 0x3E, 0x3D, 0x3D, 0x3C,
0x3B, 0x3A, 0x3A, 0x39, 0x38, 0x38, 0x37, 0x36, 0x36, 0x35,
0x34, 0x34, 0x33, 0x33, 0x32, 0x31, 0x31, 0x30, 0x30, 0x2F,
0x2F, 0x2E, 0x2E, 0x2D, 0x2C, 0x2C, 0x2B, 0x2B, 0x2A, 0x2A,
0x29, 0x29, 0x28, 0x28, 0x27, 0x27, 0x27, 0x26, 0x26, 0x25,
0x25, 0x24, 0x24, 0x23, 0x23, 0x22, 0x22, 0x21, 0x21, 0x21,
0x20, 0x20, 0x1F, 0x1F, 0x1E, 0x1E, 0x1E, 0x1D, 0x1D, 0x1C,
0x1C, 0x1B, 0x1B, 0x1B, 0x1B, 0x1A, 0x19, 0x19, 0x19, 0x18,
0x18, 0x17, 0x17, 0x25, 0x1B, 0x1B, 0x19, 0x19, 0x19, 0x18,
0x18, 0x17, 0x17, 0x16, 0x16, 0x16, 0x15, 0x15, 0x14, 0x14,
0x14, 0x13, 0x13, 0x12, 0x12, 0x12, 0x11, 0x11, 0x10, 0x10,
0x10, 0xF, 0xF, 0xE, 0xE, 0xE, 0xD, 0xD, 0xC, 0xC, 0xC, 0xB,
0xB, 0xA, 0xA, 9, 9, 9, 8, 8, 7, 7, 7, 6, 6, 5, 5, 4, 4, 4, 3,
3, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0};
#endif //DNS320L_H
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Fri, Jan 24, 3:09 AM (1 d, 10 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
532397
Default Alt Text
(19 KB)
Attached To
rDNSD DNS-320L Daemon
Event Timeline
Log In to Comment