2 * GraphLCD driver library
4 * network.c - Network output device
5 * Output goes to a network client.
7 * This file is released under the GNU General Public License. Refer
8 * to the COPYING file distributed with this package.
10 * (c) 2004 Andreas Regel <andreas.regel AT powarman.de>
16 #include <sys/types.h>
17 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
30 cDriverNetwork::cDriverNetwork(cDriverConfig * config)
33 oldConfig = new cDriverConfig(*config);
36 clientConnected = false;
39 cDriverNetwork::~cDriverNetwork()
44 int cDriverNetwork::Init()
46 width = config->width;
49 height = config->height;
52 lineSize = (width + 7) / 8;
54 for (unsigned int i = 0; i < config->options.size(); i++)
56 if (config->options[i].name == "")
61 newLCD = new unsigned char[lineSize * height];
63 memset(newLCD, 0, lineSize * height);
64 oldLCD = new unsigned char[lineSize * height];
66 memset(oldLCD, 0, lineSize * height);
74 if (pthread_create(&childTid, NULL, (void *(*) (void *)) &ServerThread, (void *)this) != 0)
76 syslog(LOG_ERR, "%s: error creating server thread.\n", config->name.c_str());
80 syslog(LOG_INFO, "%s: network driver initialized.\n", config->name.c_str());
84 int cDriverNetwork::DeInit()
88 usleep(3000000); // wait 3 seconds
89 pthread_cancel(childTid);
99 int cDriverNetwork::CheckSetup()
101 if (config->width != oldConfig->width ||
102 config->height != oldConfig->height)
109 if (config->upsideDown != oldConfig->upsideDown ||
110 config->invert != oldConfig->invert)
112 oldConfig->upsideDown = config->upsideDown;
113 oldConfig->invert = config->invert;
119 void cDriverNetwork::Clear()
121 memset(newLCD, 0, lineSize * height);
124 void cDriverNetwork::Set8Pixels(int x, int y, unsigned char data)
126 if (x >= width || y >= height)
129 if (!config->upsideDown)
131 // normal orientation
132 newLCD[lineSize * y + x / 8] |= data;
136 // upside down orientation
139 newLCD[lineSize * y + x / 8] |= ReverseBits(data);
143 void cDriverNetwork::Refresh(bool refreshAll)
149 if (CheckSetup() > 0)
152 for (i = 0; i < lineSize * height; i++)
154 if (newLCD[i] != oldLCD[i])
161 if (refresh && clientConnected)
168 sprintf(msg, "update begin %d %d\r\n", width, height);
169 sent = send(clientSocket, msg, strlen(msg), 0);
172 syslog(LOG_ERR, "%s: error sending message: %s.\n", config->name.c_str(), strerror(errno));
173 clientConnected = false;
176 for (y = 0; y < height; y++)
178 sprintf(msg, "update line %d ", y);
179 for (x = 0; x < lineSize; x++)
182 sprintf(tmp, "%02X", newLCD[y * lineSize + x]);
184 oldLCD[i] = newLCD[i];
187 sent = send(clientSocket, msg, strlen(msg), 0);
190 syslog(LOG_ERR, "%s: error sending message: %s.\n", config->name.c_str(), strerror(errno));
191 clientConnected = false;
195 sprintf(msg, "update end\r\n");
196 sent = send(clientSocket, msg, strlen(msg), 0);
199 syslog(LOG_ERR, "%s: error sending message: %s.\n", config->name.c_str(), strerror(errno));
200 clientConnected = false;
206 void * cDriverNetwork::ServerThread(cDriverNetwork * Driver)
209 struct sockaddr_in address;
214 struct timeval timeout;
216 serverSocket = socket(AF_INET, SOCK_STREAM, 0);
217 if (serverSocket == -1)
219 syslog(LOG_ERR, "%s: error creating server socket.\n", Driver->config->name.c_str());
224 setsockopt(serverSocket, SOL_SOCKET, SO_REUSEADDR, &y, sizeof(int));
226 address.sin_family = AF_INET;
227 address.sin_addr.s_addr = INADDR_ANY;
228 address.sin_port = htons(2003);
229 if (bind(serverSocket, (struct sockaddr *) &address, sizeof(address)) != 0)
231 syslog(LOG_ERR, "%s: error port %d is already used.\n", Driver->config->name.c_str(), 2003);
235 listen(serverSocket, 1);
236 addrlen = sizeof(struct sockaddr_in);
239 FD_SET(serverSocket, &set);
242 while (Driver->running)
247 if (select(FD_SETSIZE, &set, NULL, NULL, &timeout) < 0)
249 syslog(LOG_ERR, "%s: error during select.\n", Driver->config->name.c_str());
253 if (FD_ISSET(serverSocket, &set))
255 clientSocket = accept(serverSocket, (struct sockaddr *) &address, &addrlen);
256 if (clientSocket > 0)
258 Driver->clientSocket = clientSocket;
259 Driver->clientConnected = true;
267 } // end of namespace