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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.