123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675 |
- /* Daemon for the Pertelian LCD display.
- This program will horizontally scroll information across the display.
- Written by Ron Lauzon - 2007
- I release this code into the Public Domain.
- Use this at your own risk.
- */
- #include <stdio.h>
- #include <time.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <ctype.h>
- #include <stdlib.h>
- #include "fifo.h"
- #include "pert_interf.h"
- # define BUF_SIZE 512
- #ifdef DEBUG
- #define CONFIG_FILE_NAME "./pertd2.conf"
- #else
- #define CONFIG_FILE_NAME "/etc/pertd2.conf"
- #endif
- /* Commands */
- char *command_text[] = {"backlight on",
- "backlight off",
- "stop",
- "line1",
- "line2",
- "line3",
- "line4",
- "delay time",
- "char delay",
- "backlight mgt on",
- "backlight mgt off",
- NULL};
- enum command_enum {
- backlight_on = 0,
- backlight_off,
- stop,
- line1,
- line2,
- line3,
- line4,
- delay_time_cmd,
- char_delay_cmd,
- backlight_mgt_on,
- backlight_mgt_off,
- error_cmd=999};
- /* Config information */
- char *fifo_name = NULL;
- char *device_name = NULL;
- unsigned int delay_time = 0;
- int backlight_mgt = 0;
- /* Information about the data to display */
- char *lines[4]; /* The line text */
- int pos[4]; /* The position we are in the line */
- time_t refresh_time[4]; /* Time data was last refreshed */
- int timeout[4]; /* Number of seconds before we expire the line */
- int backlight_status; /* 0 - backlight not on, 1 - backlight on */
- /* This routine puts the program into "daemon" mode.
- * i.e. it disconnects from the current session so that
- * it's not automatically killed when the user logs off.
- */
- int daemon_init() {
- pid_t pid;
- FILE *pidfile;
- #ifdef DEBUG
- return(0); /* Don't go daemon in debug mode */
- #endif
- /* Fork off 8-) */
- if ( (pid=fork()) < 0)
- return(-1); /* If error - leave */
- else if (pid != 0)
- exit(0); /* parent exits */
- /* Child continues */
- /* Become session leader */
- setsid();
- return(0);
- }
- int is_numeric(char *buffer) {
- int i;
- /* Look through all the chars in the buffer */
- for (i=0; i<strlen(buffer); i++) {
- /* If we find a character that isn't a digit */
- if (!isdigit(buffer[i])) {
- /* It was bad data */
- return(0); /* false - not numeric */
- }
- }
- /* By the time we get here, all the characters are digits */
- return(1); /* true - numeric */
- }
- int read_config(char *config_file_name) {
- FILE *config_file;
- char line[1024];
- char *parm;
- char *value;
- #ifdef DEBUG
- printf("Opening config file %s\n",config_file_name);
- #endif
- char_delay = 1; /* default correctly for old systems */
- /* Try to open the config file */
- if ((config_file = fopen(config_file_name,"r")) != NULL) {
- /* Read lines from the config file */
- while(fgets(line,1024,config_file) != NULL) {
- /* Trim the new line */
- line[strlen(line)-1] = '\0';
- /* If comment, ignore */
- if (line[0] == '#')
- continue;
- /* If no = in the string, ignore */
- if (strchr(line,'=') == NULL)
- continue;
- /* We found a parm/value pair. Point to the value. */
- value=strchr(line,'=');
- value[0] = '\0';
- value++;
- /* Now, process the parm */
- if (strcmp(line,"fifo_name") == 0) {
- fifo_name = (char *)malloc(strlen(value)+1);
- strcpy(fifo_name,value);
- }
- if (strcmp(line,"device") == 0) {
- device_name = (char *)malloc(strlen(value)+1);
- strcpy(device_name,value);
- }
- if (strcmp(line,"delay_time") == 0) {
- delay_time=atoi(value);
- }
- if (strcmp(line,"char_delay") == 0) {
- char_delay=atoi(value);
- }
- if (strcmp(line,"backlight_mgt") == 0) {
- backlight_mgt=atoi(value);
- }
- }
- fclose(config_file);
- }
- /* Set defaults for any values not in the config file */
- if (fifo_name == NULL) {
- fifo_name = (char *)malloc(1024);
- strcpy(fifo_name,"/tmp/pertd2.fifo");
- }
- if (device_name == NULL) {
- device_name = (char *)malloc(1024);
- strcpy(device_name,"/dev/ttyUSB0");
- }
- if (delay_time == 0)
- delay_time = 500000; /* 1/2 second (500,000 milliseconds) */
- }
- int get_command() {
- char *command;
- int i;
- command = read_line();
- if (command == NULL) {
- return(error_cmd); /* No data */
- }
- /* lower case the command */
- for(i=0;i<strlen(command);i++)
- command[i] = tolower(command[i]);
- #ifdef DEBUG
- printf("Command:%s\n",command);
- #endif
- /* Loop through the commands */
- i = 0;
- while(command_text[i] != NULL) {
- /* If we found the command text */
- if (strcmp(command,command_text[i]) == 0) {
- free(command); /* memory leaks are bad */
- #ifdef DEBUG
- printf("Command_num:%d\n",i);
- #endif
- /* Return that command number */
- return(i);
- }
- i++;
- }
- /* If we got here, we didn't find the command
- * so the data is invalid. Throw it out. */
- free(command); /* memory leaks are bad */
- return(error_cmd); /* bad data */
- }
- int get_timeout() {
- char *timeout;
- int i;
- int int_timeout;
- timeout = read_line();
- if (timeout == NULL) {
- return(-1); /* No data */
- }
- /* Validate that the timeout is a number */
- if (!is_numeric(timeout)) {
- /* If it wasn't a digit, it was bad data */
- free(timeout);
- return(-1); /* bad data */
- }
- #ifdef DEBUG
- printf("Timeout:%s\n",timeout);
- #endif
- /* Convert the buffer into a int and return it */
- int_timeout = atoi(timeout);
- free(timeout);
- return(int_timeout);
- }
- char *get_line() {
- char *EOD;
- char *current_line, *temp;
- char *line_buffer;
- int current_length;
- /* Get EOD string */
- EOD = read_line();
- if (EOD == NULL) {
- return(NULL); /* no data */
- }
- /* We have data */
- /* Allocate a buffer for the line */
- current_length = 1;
- line_buffer = (char *)malloc(current_length);
- line_buffer[0] = '\0';
- /* Read the next line from the fifo */
- current_line = read_line();
- /* While we didn't hit the end of data marker
- * and we didn't run out of fifo data */
- while ((current_line != NULL)
- && (strcmp(current_line,EOD) != 0)) {
- /* If our buffer is too small */
- if ((strlen(current_line) + strlen(line_buffer)+1) > current_length) {
- /* Allocate new buffer and copy the old data over */
- temp = line_buffer;
- line_buffer = (char *)malloc(current_length+BUF_SIZE);
- memcpy(line_buffer,temp,current_length);
- current_length += BUF_SIZE;
- free(temp);
- }
- /* Add the current line to the buffer */
- if (strlen(line_buffer) > 0)
- strcat(line_buffer," ");
- strcat(line_buffer,current_line);
- free(current_line); /* memory leaks are bad */
- current_line = read_line();
- }
- if (current_line != NULL)
- free(current_line); /* memory leaks are bad */
- free(EOD);
- return(line_buffer);
- }
- void process_delay_time() {
- char *cur_line;
- /* Get the delay time */
- cur_line = read_line();
- #ifdef DEBUG
- printf("Read delay_time:%s\n",cur_line);
- #endif
- /* No delay time - exit */
- if (cur_line == NULL)
- return;
- if (strlen(cur_line) == 0)
- return;
- /* The delay time must be a number */
- if (is_numeric(cur_line)) {
- delay_time = atoi(cur_line);
- free(cur_line);
- #ifdef DEBUG
- printf("Processed delay_time:%d\n",delay_time);
- #endif
- return;
- }
- /* If it's not a number, it's bad data - ignore the command */
- }
- void process_char_delay() {
- char *cur_line;
- /* Get the delay time */
- cur_line = read_line();
- /* No char delay - exit */
- if (cur_line == NULL)
- return;
- if (strlen(cur_line) == 0)
- return;
- /* The delay time must be a number */
- if (is_numeric(cur_line)) {
- char_delay = atoi(cur_line);
- free(cur_line);
- return;
- }
- /* If it's not a number, it's bad data - ignore the command */
- }
- void process_line(int line_num) {
- int cur_timeout;
- char *cur_line;
- time_t now;
- time(&now);
- cur_timeout = get_timeout();
- if (cur_timeout < 0) {
- cur_timeout = 0;
- }
- cur_line = get_line();
- if (lines[line_num] != NULL)
- free(lines[line_num]);
- lines[line_num] = cur_line;
- timeout[line_num] = cur_timeout;
- refresh_time[line_num] = now;
- }
- int data_to_display() {
- int temp;
- int i;
- temp = 0;
- /* Look through all the lines */
- for (i=0; i<4; i++) {
- /* If the line isn't empty */
- if (lines[i] != NULL) {
- if (strlen(lines[i]) > 0) {
- return 1; /* we have data */
- }
- }
- }
- /* We only get here when no lines have data */
- return 0;
- }
- void display_date_time() {
- time_t now_t;
- struct tm *now_tm;
- char line2[PERT_DISPLAY_WIDTH+1], line3[PERT_DISPLAY_WIDTH+1];
- /* First we need to get the current time */
- now_t = time(NULL);
- /* Now, we need to convert the time_t to something useful */
- now_tm = localtime(&now_t);
- /* Format the date/time into a date line and a time line */
- /* DDD MMM DD, YYYY - 16 chars pad 4 spaces */
- strftime(line2,PERT_DISPLAY_WIDTH+1," %a %b %d, %Y ",now_tm);
- /* HH:MM:SS - 8 chars - pad 12 spaces */
- strftime(line3,PERT_DISPLAY_WIDTH+1," %T ",now_tm);
- line2[PERT_DISPLAY_WIDTH] = '\0';
- line3[PERT_DISPLAY_WIDTH] = '\0';
- #ifdef DEBUG
- printf("line2= %s\n",line2);
- printf("line3= %s\n",line3);
- #endif
- /* Put the lines on the display */
- wrtln(1,line2);
- wrtln(2,line3);
- }
- /* Copy over PERT_DISPLAY_WIDTH chars of data into line - wrapping around
- * when at the end of the data */
- char *fill_line(int lineno,int offset) {
- static char temp_line[21];
- int i;
- int temp_pos;
- /* If the line contains no data */
- if (lines[lineno] == NULL) {
- /* If we are on the first line */
- if (lineno == 0) {
- /* No data to display - return blanks to clear line */
- memset(temp_line,' ',PERT_DISPLAY_WIDTH);
- temp_line[PERT_DISPLAY_WIDTH] = '\0';
- return(temp_line);
- } else {
- /* Try to fill with some of the previous line */
- return(fill_line(lineno-1,offset + PERT_DISPLAY_WIDTH));
- }
- }
- if (strlen(lines[lineno]) == 0) {
- /* If we are on the first line */
- if (lineno == 0) {
- /* No data to display - return blanks to clear line */
- memset(temp_line,' ',PERT_DISPLAY_WIDTH);
- temp_line[PERT_DISPLAY_WIDTH] = '\0';
- return(temp_line);
- } else {
- /* Try to fill with some of the previous line */
- return(fill_line(lineno-1,offset + PERT_DISPLAY_WIDTH));
- }
- }
- /* If there are PERT_DISPLAY_WIDTH or less chars to display */
- if (strlen(lines[lineno]) < 21) {
- /* If this is the first time called */
- if (offset == 0) {
- /* Return the line and pad with blanks */
- strcpy(temp_line,(lines[lineno]));
- for (i=strlen(lines[lineno]); i<PERT_DISPLAY_WIDTH; i++)
- temp_line[i] = ' ';
- temp_line[PERT_DISPLAY_WIDTH] = '\0';
- return(temp_line);
- } else { /* not the first time called - return blanks */
- /* No data to display - return blanks to clear line */
- memset(temp_line,' ',PERT_DISPLAY_WIDTH);
- temp_line[PERT_DISPLAY_WIDTH] = '\0';
- return(temp_line);
- }
- }
- /* If there's not enough data to display */
- if (strlen(lines[lineno]) <= offset) {
- /* No data to display - return blanks to clear line */
- memset(temp_line,' ',PERT_DISPLAY_WIDTH);
- temp_line[PERT_DISPLAY_WIDTH] = '\0';
- return(temp_line);
- }
-
- /* If there are more than PERT_DISPLAY_WIDTH chars to display,
- * display PERT_DISPLAY_WIDTH starting at the last position
- * displayed */
- temp_pos = pos[lineno] + offset;
- while (temp_pos > strlen(lines[lineno]))
- temp_pos = temp_pos - strlen(lines[lineno]);
- if (temp_pos < 0)
- temp_pos = 0;
- /* For each char in the temp line */
- for (i=0; i<PERT_DISPLAY_WIDTH; i++) {
- /* If we are pointing beyond the original line,
- * start over at the beginning */
- if (temp_pos >= strlen(lines[lineno]))
- temp_pos = 0;
- /* Copy over 1 char from the original line */
- temp_line[i] = lines[lineno][temp_pos];
- temp_pos++;
- }
- /* Increment where we start */
- pos[lineno]++;
- /* If we went past the end of the line,
- * start over */
- if (pos[lineno] >= strlen(lines[lineno]))
- pos[lineno] = 0;
- /* Force an end of line */
- temp_line[PERT_DISPLAY_WIDTH] = '\0';
- return(temp_line);
- }
- int main(int argc, char *argv[]) {
- int stop_indicated;
- int processing_command;
- int i;
- time_t now;
- /* Read config file */
- if (argc > 1) {
- /* We have an argument - try to read the config file
- * using that argument */
- if (!read_config(argv[1])) {
- /* If we failed - try to read the default config file */
- read_config(CONFIG_FILE_NAME);
- }
- } else {
- /* No parm - use default config file */
- read_config(CONFIG_FILE_NAME);
- }
- #ifdef DEBUG
- printf("Device = %s\n",device_name);
- printf("Fifo = %s\n",fifo_name);
- printf("Delay time = %d\n",delay_time);
- printf("Char Delay time = %d\n",char_delay);
- #endif
- /* Initialize arrays */
- time(&now);
- for(i=0;i<4;i++) {
- lines[i] = NULL;
- refresh_time[i] = now;
- timeout[i] = 0;
- pos[i] = 0;
- }
- /* Initialize the Pertelian */
- display_init(device_name);
- /* The backlight is on when the program starts */
- backlight_status = 1;
- backlight(1);
- /* Go daemon */
- if (daemon_init() != 0) {
- fprintf(stderr,"Failed to go daemon\n");
- return(1);
- }
- /* Try to open the fifo */
- if (!open_fifo(fifo_name)) {
- fprintf(stderr,"Error creating FIFO: %s\n",fifo_name);
- return(1);
- }
- /* Loop until we are told to stop */
- stop_indicated = 0;
- while (!stop_indicated) {
- time(&now);
- /* Get the command from the fifo */
- processing_command = 1;
- while (processing_command) {
- switch (get_command()) {
- case backlight_on:
- backlight(1);
- backlight_status = 1;
- break;
- case backlight_off:
- backlight(0);
- backlight_status = 0;
- break;
- case stop:
- stop_indicated = 1;
- break;
- case line1:
- process_line(0);
- break;
- case line2:
- process_line(1);
- break;
- case line3:
- process_line(2);
- break;
- case line4:
- process_line(3);
- break;
- case delay_time_cmd:
- process_delay_time();
- break;
- case char_delay_cmd:
- process_char_delay();
- break;
- case backlight_mgt_on:
- backlight_mgt = 1;
- break;
- case backlight_mgt_off:
- backlight_mgt = 0;
- break;
- default:
- processing_command = 0; /* no command to process */
- break;
- }
- }
- #ifdef DEBUG
- printf("main:processed command\n");
- #endif
- /* Refresh the display */
- for(i=0;i<4;i++) {
- /* If the line has data */
- if (lines[i] != NULL) {
- /* If we are supposed to time the line out */
- if (timeout[i] > 0) {
- /* If the line is old */
- if (difftime(now,refresh_time[i]) > timeout[i]) {
- /* Get rid of the line */
- free(lines[i]); /* Memory leaks are bad */
- lines[i] = NULL;
- }
- }
- }
- /* Write out the line to the display */
- wrtln(i,fill_line(i,0));
- }
- /* If there was no data to display */
- if (!data_to_display()) {
- /* Let's put the date/time on the display */
- display_date_time();
- /* If the backlight is on,
- * and backight mgt is on,
- * turn the backlight off */
- if ((backlight_status == 1)
- && (backlight_mgt == 1)) {
- backlight(0);
- backlight_status=0;
- }
- } else {
- /* There was data to display.
- * If the backlight is off,
- * and backlight mangement is on,
- * turn the backlight on */
- if ((backlight_status == 0)
- && (backlight_mgt ==1)) {
- backlight(1);
- backlight_status=1;
- }
- }
- /* Pause for a bit */
- sleep_us(delay_time);
- }
- /* Display a useful message on the Pertelian */
- wrtln(0," ");
- wrtln(1,"pertd daemon stopped");
- wrtln(2," ");
- wrtln(3," ");
- /* Clean up the connect to the Pertelian */
- display_close();
- /* Done - clean up */
- close_fifo(fifo_name);
- return(0);
- }
|