00001
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <unistd.h>
00038 #include <string.h>
00039 #include <sys/types.h>
00040 #include <sys/stat.h>
00041 #include <sys/ioctl.h>
00042 #include <termios.h>
00043 #include <errno.h>
00044 #include <fcntl.h>
00045 #include <signal.h>
00046 #include <net/if.h>
00047 #include <arpa/inet.h>
00048
00049
00050 #ifdef DEBUG
00051 # define log_info(...) fprintf(stderr, __VA_ARGS__)
00052 # define log_error(...) fprintf(stderr, __VA_ARGS__)
00053 # define start_log(x)
00054 # define stop_log()
00055 #else
00056 # include <syslog.h>
00057 # define log_info(...) syslog(LOG_INFO, __VA_ARGS__)
00058 # define log_error(...) syslog(LOG_ALERT, __VA_ARGS__)
00059 # define start_log(x) openlog(x, LOG_PID, LOG_DAEMON)
00060 # define stop_log() closelog()
00061 #endif
00062
00063 #ifndef SERIAL_PORT
00064 # define SERIAL_PORT "/dev/ttyS0"
00065 #endif
00066 #define APP "LCDscroller"
00067 #ifndef RUNNING_DIR
00068 # define RUNNING_DIR "/tmp"
00069 #endif
00070 #ifndef LOCK_DIR
00071 # define LOCK_DIR "/var/run"
00072 #endif
00073 #ifndef INTERFACE
00074 # define INTERFACE "eth0"
00075 #endif
00076 #ifndef BAUD_RATE
00077 # define BAUD_RATE B19200
00078 #endif
00079
00080
00081
00082
00083 unsigned char command = 0xfe;
00084 unsigned char wrap_on = 0x43;
00085 unsigned char wrap_off = 0x44;
00086 unsigned char crsr_home = 0x48;
00087 unsigned char u_crsr_on = 0x4a;
00088 unsigned char u_crsr_off = 0x4b;
00089 unsigned char crsr_left = 0x4c;
00090 unsigned char crsr_right = 0x4d;
00091 unsigned char scroll_on = 0x51;
00092 unsigned char scroll_off = 0x52;
00093 unsigned char b_crsr_on = 0x53;
00094 unsigned char b_crsr_off = 0x54;
00095 unsigned char clear = 0x58;
00096
00097 unsigned char backlt_on = 0x42;
00098 unsigned char backlt_off = 0x46;
00099
00100 unsigned char remember = 0x93;
00101 unsigned char port_spd = 0x39;
00102 unsigned char contrast = 0x50;
00103 unsigned char contr_dflt = 0x91;
00104 unsigned char gpo_on = 0x57;
00105 unsigned char gpo_off = 0x56;
00106
00107 unsigned char baud_1200 = 0xff;
00108 unsigned char baud_2400 = 0x81;
00109 unsigned char baud_9600 = 0x20;
00110 unsigned char baud_19200 = 0x0f;
00111
00112 unsigned int line_length = 20;
00113 unsigned int line_count = 2;
00114
00115
00116
00117 int loop = 1;
00118 static void quit(int sig, siginfo_t *si, void *unused)
00119 {
00120 loop = 0;
00121 }
00122
00123
00124 void die(char *s, char *extra)
00125 {
00126 if (errno)
00127 log_error("%s: %s %s %s\n", APP, s, strerror(errno), extra);
00128 else
00129 log_error("%s: %s %s\n", APP, s, extra);
00130 stop_log();
00131 exit(-1);
00132 }
00133
00134
00135 void print_string(int lcd, char *str)
00136 {
00137 #ifdef DEBUG
00138 log_info("%s", str);
00139 #endif
00140 while (*str)
00141 write(lcd, (unsigned char *)str++, 1);
00142 }
00143
00144
00145 void lcd_cmd (int lcd, int cmd)
00146 {
00147 unsigned char buf[2];
00148 buf[0] = command;
00149 buf[1] = cmd;
00150 write(lcd, buf, 2);
00151 }
00152
00153
00154 void set_lcd_value(int lcd, int cmd, int val)
00155 {
00156 unsigned char buf[3];
00157 buf[0] = command;
00158 buf[1] = cmd;
00159 buf[2] = val;
00160 write(lcd, buf, 3);
00161 }
00162
00163
00164 int set_startup_screen(char *string)
00165 {
00166 int i, lcd;
00167 unsigned char buf[42];
00168
00169 if ((lcd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0)
00170 return -1;
00171
00172 buf[0] = command;
00173 buf[1] = 0x40;
00174 for (i = 0; i < 41; i++) {
00175 if (i < strlen(string))
00176 buf[i] = string[i];
00177 else
00178 buf[i] = ' ';
00179 }
00180 write(lcd, buf, 42);
00181 close(lcd);
00182 return 0;
00183 }
00184
00185
00186 char* getipaddress()
00187 {
00188 int fd;
00189 struct ifreq ifr;
00190 struct sockaddr_in *saddr = (struct sockaddr_in*)(&ifr.ifr_addr);
00191 strcpy(ifr.ifr_name, INTERFACE);
00192
00193 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
00194 return 0;
00195 if (ioctl(fd, SIOCGIFADDR, &ifr) < 0)
00196 return 0;
00197
00198 return inet_ntoa(saddr->sin_addr);
00199 }
00200
00201
00202 unsigned int fore_spacing(char *str)
00203 {
00204 if (strlen(str) >= line_length)
00205 return 0;
00206 return (line_length - strlen(str)) / 2;
00207 }
00208
00209
00210 unsigned int aft_spacing(char *str)
00211 {
00212 if (strlen(str) >= line_length)
00213 return 0;
00214 return line_length - strlen(str) - fore_spacing(str);
00215 }
00216
00217
00218 void lcdprint(int count, char *strings[])
00219 {
00220 char *ip = getipaddress();
00221 int lcd;
00222 if ((lcd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0) {
00223 die("open", SERIAL_PORT);
00224 }
00225
00226 while (loop) {
00227 int i, j;
00228 lcd_cmd(lcd, clear);
00229 #ifdef DEBUG
00230 log_info("\n%s:", APP);
00231 #endif
00232
00233 for (i = 0; i < count; i++) {
00234 for (j = 0; j < fore_spacing(strings[i]); j++)
00235 print_string(lcd, " ");
00236 print_string(lcd, strings[i]);
00237 for (j = 0; j < aft_spacing(strings[i]); j++)
00238 print_string(lcd, " ");
00239 sleep(1);
00240 }
00241 for (j = 0; j < fore_spacing(ip); j++)
00242 print_string(lcd, " ");
00243 print_string(lcd, ip);
00244 for (j = 0; j < aft_spacing(ip); j++)
00245 print_string(lcd, " ");
00246 sleep(2);
00247 }
00248 close(lcd);
00249 }
00250
00251
00252 void daemonize(char *lock_file)
00253 {
00254 int fd, err, lock;
00255 char pid_str[255];
00256 struct sigaction sa;
00257
00258 err = fork();
00259 if (err < 0)
00260 die("fork", "daemonize");
00261 if (err > 0)
00262 exit(0);
00263 setsid();
00264 for (fd = 0; fd <= getdtablesize(); fd++)
00265 close(fd);
00266 fd = open("/dev/null", O_RDWR);
00267 dup(fd);
00268 dup(fd);
00269 umask(027);
00270 chdir(RUNNING_DIR);
00271 if ((lock = open(lock_file, O_RDWR | O_CREAT, 0640)) < 0)
00272 die("open", lock_file);
00273 if (lockf(lock, F_TLOCK, 0) < 0)
00274 die("lockf", lock_file);
00275 sprintf(pid_str, "%d\n", getpid());
00276 write(lock, pid_str, strlen(pid_str));
00277
00278 sigemptyset(&sa.sa_mask);
00279 sa.sa_handler = SIG_IGN;
00280 if (sigaction(SIGCHLD, &sa, NULL) < 0)
00281 die("sigaction", "SIGCHLD");
00282 if (sigaction(SIGTSTP, &sa, NULL) < 0)
00283 die("sigaction", "SIGTSTP");
00284 if (sigaction(SIGTTOU, &sa, NULL) < 0)
00285 die("sigaction", "SIGTTOU");
00286 if (sigaction(SIGTTIN, &sa, NULL) < 0)
00287 die("sigaction", "SIGTTIN");
00288 }
00289
00290
00291 void init_lcd()
00292 {
00293 int fd;
00294 struct termios termios;
00295
00296 if ((fd = open(SERIAL_PORT, O_WRONLY|O_EXCL)) < 0)
00297 die("open", SERIAL_PORT);
00298 if (tcgetattr(fd, &termios) < 0)
00299 die("tcgetattr", SERIAL_PORT);
00300 cfmakeraw(&termios);
00301 cfsetospeed(&termios, BAUD_RATE);
00302 if (tcsetattr(fd, TCSANOW, &termios) < 0)
00303 die("tcsetattr", SERIAL_PORT);
00304 usleep(350000);
00305 lcd_cmd(fd, b_crsr_off);
00306 lcd_cmd(fd, u_crsr_off);
00307 lcd_cmd(fd, wrap_on);
00308 lcd_cmd(fd, scroll_on);
00309 lcd_cmd(fd, clear);
00310 close(fd);
00311 }
00312
00313
00314 int main(int argc, char *argv[]) {
00315 struct sigaction sa;
00316 char lock_file[255];
00317 char *app = rindex(argv[0], '/')+1;
00318
00319 if (argc > 2 && strcasecmp(argv[1], "--boot") == 0) {
00320 init_lcd();
00321 return set_startup_screen(argv[2]);
00322 }
00323
00324 start_log(app);
00325 log_info("%s: printing \"%s ...\" to LCD\n", APP, argv[1]);
00326 sprintf(lock_file, "%s/%s", LOCK_DIR, app);
00327 #ifndef DEBUG
00328 daemonize(lock_file);
00329 #endif
00330 sa.sa_flags = SA_SIGINFO;
00331 sigemptyset(&sa.sa_mask);
00332 sa.sa_sigaction = quit;
00333 if (sigaction(SIGTERM, &sa, NULL) < 0)
00334 die("sigaction", "SIGTERM");
00335 if (sigaction(SIGINT, &sa, NULL) < 0)
00336 die("sigaction", "SIGINT");
00337
00338 init_lcd();
00339 lcdprint(argc-1, argv+1);
00340
00341 log_info("%s: shutdown\n", APP);
00342 stop_log();
00343 unlink(lock_file);
00344 return 0;
00345 }