ethlcd driver improvements
Mariusz Bialonczyk <[email protected]>
| Newsgroups | gmane.comp.sysutils.lcdproc |
|---|---|
| Message-ID | <[email protected]> |
Hello I am sending some driver improvements: - added helper function for sending data - checking for correct device response - added timeouts for socket (fixes LCDd hang up eg. when device disappear) Please commit if you don't have objections. best regards, -- Mariusz Białończyk jabber/e-mail: [email protected] http://manio.skyboo.net _______________________________________________ LCDproc mailing list [email protected] http://lists.omnipotent.net/mailman/listinfo/lcdproc
ethlcd.diff
(text/x-diff, 6.1 KB)
commit 27db3f541d69bc5ebae499d3ac6e5864e548612b Author: Mariusz Bialonczyk <[email protected]> Date: Fri Mar 11 22:40:25 2011 +0100 added helper function for sending data checking for correct device response added timeouts for socket (fixes LCDd hang up eg. when device disappear) diff --git a/server/drivers/hd44780-ethlcd.c b/server/drivers/hd44780-ethlcd.c index 0d3f117..0dd8dd3 100644 --- a/server/drivers/hd44780-ethlcd.c +++ b/server/drivers/hd44780-ethlcd.c @@ -16,16 +16,27 @@ * */ -#include "hd44780-ethlcd.h" -#include "hd44780-low.h" -#include "shared/sockets.h" -#include "report.h" +/* + * Changes: + * 2008-08-20 Mariusz Bialonczyk <[email protected]> + * - initial driver version + * 2010-05-10 Mariusz Bialonczyk <[email protected]> + * - fix setting blocking mode + * 2011-03-11 Mariusz Bialonczyk <[email protected]> + * - added helper function for sending data + * - checking for correct device response + * - added timeouts for socket (fixes LCDd hang up eg. when device disappear) + */ -#include <stdio.h> #include <string.h> -#include <limits.h> #include <fcntl.h> #include <errno.h> +#include <sys/socket.h> + +#include "hd44780-ethlcd.h" +#include "hd44780-low.h" +#include "shared/sockets.h" +#include "report.h" void ethlcd_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char flags, unsigned char ch); @@ -35,6 +46,9 @@ void ethlcd_HD44780_close(PrivateData *p); // fake pause function (pausing is handled by ethlcd device itself) void ethlcd_HD44780_uPause(PrivateData *p, int usecs) {} +// helper function +static void ethlcd_senddata(PrivateData *p, unsigned char *data, int length); + /** * Initialize the driver. @@ -46,6 +60,7 @@ int hd_init_ethlcd(Driver *drvthis) { char hostname[256]; unsigned long flags = 0; + struct timeval tv; PrivateData *p = (PrivateData*) drvthis->private_data; HD44780_functions *hd44780_functions = p->hd44780_functions; @@ -82,6 +97,22 @@ int hd_init_ethlcd(Driver *drvthis) return -1; } + //setting timeouts + tv.tv_sec = ETHLCD_TIMEOUT; + tv.tv_usec = 0; + if (setsockopt(p->sock, SOL_SOCKET, SO_RCVTIMEO, (void *) &tv, sizeof(struct timeval)) < 0) + { + report(RPT_ERR, "%s[%s]: Cannot set receive timeout: %s", + drvthis->name, ETHLCD_DRV_NAME, strerror(errno)); + return -1; + } + if (setsockopt(p->sock, SOL_SOCKET, SO_SNDTIMEO, (void *) &tv, sizeof(struct timeval)) < 0) + { + report(RPT_ERR, "%s[%s]: Cannot set send timeout: %s", + drvthis->name, ETHLCD_DRV_NAME, strerror(errno)); + return -1; + } + // Set up two-line, small character (5x8) mode hd44780_functions->senddata(p, 0, RS_INSTR, FUNCSET | IF_4BIT | TWOLINE | SMALLCHAR); @@ -105,7 +136,7 @@ int hd_init_ethlcd(Driver *drvthis) */ void ethlcd_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char flags, unsigned char ch) { - static char buff[2]; + static unsigned char buff[2]; if (flags == RS_INSTR) buff[0] = ETHLCD_SEND_INSTR; @@ -113,8 +144,7 @@ void ethlcd_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned c buff[0] = ETHLCD_SEND_DATA; buff[1] = ch; - sock_send(p->sock, buff, 2); //send data to device - sock_recv(p->sock, &buff, 1); //wait for reply + ethlcd_senddata(p, buff, 2); } @@ -126,15 +156,12 @@ void ethlcd_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned c unsigned char ethlcd_HD44780_scankeypad(PrivateData *p) { unsigned char readval; - static char buff[2]; + static unsigned char buff[2]; buff[0] = ETHLCD_GET_BUTTONS; - sock_send(p->sock, buff, 1); //send data to device - sock_recv(p->sock, &buff, 2); //wait for answer + ethlcd_senddata(p, buff, 1); - if (buff[0] != ETHLCD_GET_BUTTONS) //check if this is true reply for our packet - return 0; //answer should be in second byte on bits 0-6 in negative logic: readval = buff[1]; @@ -159,7 +186,7 @@ unsigned char ethlcd_HD44780_scankeypad(PrivateData *p) */ void ethlcd_HD44780_backlight(PrivateData *p, unsigned char state) { - static char buff[2]; + static unsigned char buff[2]; buff[0] = ETHLCD_SET_BACKLIGHT; @@ -173,8 +200,7 @@ void ethlcd_HD44780_backlight(PrivateData *p, unsigned char state) else buff[1] = ETHLCD_BACKLIGHT_OFF; - sock_send(p->sock, buff, 2); //send data to device - sock_recv(p->sock, &buff, 1); //wait for reply + ethlcd_senddata(p, buff, 2); } @@ -186,3 +212,49 @@ void ethlcd_HD44780_close(PrivateData *p) { sock_close(p->sock); } + + +/** + * Send the data to ethlcd device. + * \param p Pointer to driver's private data structure. + * \param data Pointer to buffer with data to send. + * \param length Number of bytes to send. + */ +static void ethlcd_senddata(PrivateData *p, unsigned char *data, int length) +{ + int response_len, len; + unsigned char cmd; + + /* Send data to device */ + cmd = data[0]; //storing command byte for verification + len = sock_send(p->sock, data, length); + if (len <= 0) + { + p->hd44780_functions->drv_report(RPT_ERR, "%s: Write to socket failed: %s. Exiting", + ETHLCD_DRV_NAME, strerror(errno)); + exit (-1); + } + + /* Check if this is a command with reply */ + if (cmd == ETHLCD_GET_BUTTONS) + response_len = 2; + else + response_len = 1; + + /* Wait for reply */ + len = sock_recv(p->sock, data, response_len); + if (len <= 0) + { + p->hd44780_functions->drv_report(RPT_ERR, "%s: Read from socket failed: %s. Exiting", + ETHLCD_DRV_NAME, strerror(errno)); + exit (-1); + } + + /* Check reply */ + if (data[0] != cmd) + { + p->hd44780_functions->drv_report(RPT_ERR, "%s: Invalid device response (want 0x%02X, got 0x%02X). Exiting", + ETHLCD_DRV_NAME, cmd, data[0]); + exit (-1); + } +} diff --git a/server/drivers/hd44780-ethlcd.h b/server/drivers/hd44780-ethlcd.h index dc3875b..6de5456 100644 --- a/server/drivers/hd44780-ethlcd.h +++ b/server/drivers/hd44780-ethlcd.h @@ -6,8 +6,9 @@ // initialise this particular driver int hd_init_ethlcd(Driver *drvthis); -#define ETHLCD_DRV_NAME "ethlcd" -#define DEFAULT_ETHLCD_PORT 2425 +#define ETHLCD_DRV_NAME "ethlcd" +#define DEFAULT_ETHLCD_PORT 2425 +#define ETHLCD_TIMEOUT 5 // ethlcd protocol constants: #define ETHLCD_SEND_INSTR 0x01