Merge lp:~lazyranma/ubuntu/wily/g15daemon/g15daemon.dev into lp:ubuntu/wily/g15daemon

Proposed by Alexander Ponyatykh
Status: Rejected
Rejected by: Daniel Holbach
Proposed branch: lp:~lazyranma/ubuntu/wily/g15daemon/g15daemon.dev
Merge into: lp:ubuntu/wily/g15daemon
Diff against target: 4264 lines (+3927/-31)
33 files modified
.pc/.quilt_patches (+1/-0)
.pc/.quilt_series (+1/-0)
.pc/.version (+1/-0)
.pc/01-remove-x11-setup-from-man.diff/Documentation/g15daemon.1 (+163/-0)
.pc/01-remove-x11-setup-from-man.diff/Documentation/g15daemon_client_devel.3 (+220/-0)
.pc/02-better-screenshort-creation.diff/g15daemon/utility_funcs.c (+688/-0)
.pc/03-change-syslog-facility.diff/g15daemon/main.c (+580/-0)
.pc/04-open-needs-mode.diff/g15daemon/utility_funcs.c (+702/-0)
.pc/05-send-a-sync-event-after-key-up-down.diff/plugins/g15_plugin_uinput.c (+324/-0)
.pc/06-fix-buffer-overflow.diff/libg15daemon_client/g15daemon_net.c (+297/-0)
.pc/07-reinit-on-any-error.diff/g15daemon/main.c (+580/-0)
.pc/applied-patches (+7/-0)
debian/changelog (+27/-0)
debian/control (+6/-5)
debian/docs (+0/-3)
debian/g15daemon.default (+0/-8)
debian/g15daemon.init (+18/-7)
debian/g15daemon.postinst (+8/-0)
debian/g15daemon.prerm (+5/-0)
debian/g15daemon.service (+12/-0)
debian/g15daemon.udev (+5/-6)
debian/g15daemon.upstart (+20/-0)
debian/patches/01-remove-x11-setup-from-man.diff (+127/-0)
debian/patches/02-better-screenshort-creation.diff (+39/-0)
debian/patches/03-change-syslog-facility.diff (+11/-0)
debian/patches/04-open-needs-mode.diff (+11/-0)
debian/patches/05-send-a-sync-event-after-key-up-down.diff (+30/-0)
debian/patches/06-fix-buffer-overflow.diff (+11/-0)
debian/patches/07-reinit-on-any-error.diff (+22/-0)
debian/patches/series (+7/-0)
debian/rules (+1/-0)
debian/source/format (+1/-0)
g15daemon/main.c (+2/-2)
To merge this branch: bzr merge lp:~lazyranma/ubuntu/wily/g15daemon/g15daemon.dev
Reviewer Review Type Date Requested Status
Ubuntu branches Pending
Review via email: mp+259746@code.launchpad.net

Description of the change

I've made several changes to g15daemon package, including fixing several bugs and adding native upstart job and systemd unit files. Changes are made in several commits, so you can inspect each change individually. Please review changes and merge them into the main branch if possible.

Full changelog:
  * Converted source to 3.0 (quilt) format.
  * debian/g15daemon.init: Replaced /dev/input/uinput with /dev/uinput
    (related to LP #617101).
  * debian/docs: removed obsolete file.
  * Do not fail package installation/removal if g15daemon fails to start/stop
    (LP: #617101, LP: #1103275).
  * debian/g15daemon.init: added dependency on $remote_fs
  * debian/g15daemon.init: now sources /lib/lsb/init-functions
  * Added debian/patches/07-reinit-on-any-error.diff: reinitialize on any
    error returned by libusb to correctly recover after suspend/resume.
    (LP: #1357556)
  * debian/control: removed dependency on libg15daemon-client1 for g15daemon
  * debian/control: changed priority of g15daemon to optional
  * Added native upstart job and systemd service. (LP: #1441365)
  * debian/g15daemon.default: removed SWITCH_KEY option to keep systemd and
    upstart scripts simple.

To post a comment you must log in.
Revision history for this message
Sebastien Bacher (seb128) wrote :

Thanks, that's quite some changes. Do you think some could be forwarded to Debian?

Revision history for this message
Daniel Holbach (dholbach) wrote :

Yeah, it'd be better to have the Debian maintainer's buy-in as well.

Unmerged revisions

33. By Alexander Ponyatykh

Cleanup.

32. By Alexander Ponyatykh

Migrated from cdbs to debhelper.

31. By Alexander Ponyatykh

Merged with Ubuntu main branch.
Removed upstart service file.

30. By Alexander Ponyatykh

debian/g15daemon.service: Added documantation link.

29. By Alexander Ponyatykh

Added man link to g15daemon.service

28. By Alexander Ponyatykh

changed version

27. By Alexander Ponyatykh

Updated changelog

26. By Alexander Ponyatykh

Added native upstart job and systemd service. (LP: #1441365)
debian/g15daemon.default: removed SWITCH_KEY option to keep systemd and
upstart scripts simple.

25. By Alexander Ponyatykh

debian/control: removed dependency on libg15daemon-client1 for g15daemon
debian/control: changed priority of g15daemon to optional (Policy 2.5)

24. By Alexander Ponyatykh

Fixed CDBS warning

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory '.pc'
2=== added file '.pc/.quilt_patches'
3--- .pc/.quilt_patches 1970-01-01 00:00:00 +0000
4+++ .pc/.quilt_patches 2015-05-21 10:27:39 +0000
5@@ -0,0 +1,1 @@
6+debian/patches
7
8=== added file '.pc/.quilt_series'
9--- .pc/.quilt_series 1970-01-01 00:00:00 +0000
10+++ .pc/.quilt_series 2015-05-21 10:27:39 +0000
11@@ -0,0 +1,1 @@
12+series
13
14=== added file '.pc/.version'
15--- .pc/.version 1970-01-01 00:00:00 +0000
16+++ .pc/.version 2015-05-21 10:27:39 +0000
17@@ -0,0 +1,1 @@
18+2
19
20=== added directory '.pc/01-remove-x11-setup-from-man.diff'
21=== added directory '.pc/01-remove-x11-setup-from-man.diff/Documentation'
22=== added file '.pc/01-remove-x11-setup-from-man.diff/Documentation/g15daemon.1'
23--- .pc/01-remove-x11-setup-from-man.diff/Documentation/g15daemon.1 1970-01-01 00:00:00 +0000
24+++ .pc/01-remove-x11-setup-from-man.diff/Documentation/g15daemon.1 2015-05-21 10:27:39 +0000
25@@ -0,0 +1,163 @@
26+.TH "G15Daemon" "1" "1.3" "G15tools - G15Daemon" "1"
27+.SH "NAME"
28+g15daemon \- provides access to extra keys and the LCD available on the logitech G15 keyboard.
29+.SH "DESCRIPTION"
30+G15Daemon allows users access to all extra keys by decoding them and pushing them back into the kernel via the linux UINPUT driver. This driver must be loaded before g15daemon can be used for keyboard access.
31+
32+The G15 LCD is also supported. By default, with no other clients active, g15daemon will display a clock. Client applications and scripts can access the LCD via a simple API.
33+.SH "OPTIONS"
34+The current version of G15Daemon understands the following options:
35+.br
36+.P
37+.HP
38+\-v Show version info.
39+.P
40+.HP
41+\-s By default, g15daemon uses the L1 key to switch between client screens. Using this switch on the cmdline alters this, making
42+MR (Macro Record) the button to achieve this function.
43+.P
44+.HP
45+\-k Stop a previously running copy of G15Daemon. For the keys and LCD to work, you'll have to restart the daemon manually.
46+.P
47+.HP
48+\-h Show a brief summary of commandline options available.
49+
50+.SH "BASIC USAGE"
51+G15Daemon must be run as the root user, either from a startup script (sample scripts are available in the contrib folder) or manually, via the su command.
52+
53+To run the daemon with default options, run:
54+
55+ g15daemon
56+
57+or
58+
59+ g15daemon \-s
60+to have the MR key as the client screen switch.
61+
62+If all required libraries are installed and in locations known to your operating system, the daemon will slip quietly into the background and a clock will appear on the LCD.
63+Congratulations! The linux kernel will now output keycodes for all your extra keys.
64+
65+.SH "Using the keys in X11"
66+Current versions of the Xorg Xserver dont have support for the extra keys that g15daemon provides. This support will be available in the next release of Xorg (7.2).
67+
68+For now, if you want access to the extra keys for hotkey support in X11, you need to run the xmodmaprc script on each start of X. This script is available in the contrib folder (if g15daemon is installed in the default location, the contrib folder is in /usr/share/doc/g15daemon\-${VERSION}/contrib
69+
70+Depending on your linux distribution, copying the xmodmaprc file (or pasting the text below) into ~/.Xmodmap may be all that's required.
71+
72+.SH "Xmodmaprc file"
73+Copy the following into ~/.Xmodmap (depending on your distribution) for X11 to recognise all extra G15 keys:
74+
75+\-\- cut here \-\-
76+.br
77+keycode 93 = XF86Launch1
78+.br
79+keycode 129 = XF86Launch8
80+.br
81+keycode 130 = XF86Launch9
82+.br
83+keycode 131 = XF86Launch2
84+.br
85+keycode 132 = XF86Phone
86+.br
87+keycode 133 = XF86Messenger
88+.br
89+keycode 136 = XF86LaunchD
90+.br
91+keycode 137 = XF86Support
92+.br
93+keycode 138 = XF86Word
94+.br
95+keycode 143 = XF86LaunchF
96+.br
97+keycode 144 = XF86AudioPrev
98+.br
99+keycode 150 = XF86LogOff
100+.br
101+keycode 152 = XF86Launch5
102+.br
103+keycode 153 = XF86AudioNext
104+.br
105+keycode 160 = XF86AudioMute
106+.br
107+keycode 161 = XF86Travel
108+.br
109+keycode 162 = XF86AudioPlay
110+.br
111+keycode 163 = XF86Spell
112+.br
113+keycode 164 = XF86AudioStop
114+.br
115+keycode 170 = XF86VendorHome
116+.br
117+keycode 174 = XF86AudioLowerVolume
118+.br
119+keycode 176 = XF86AudioRaiseVolume
120+.br
121+keycode 177 = XF86Launch4
122+.br
123+keycode 178 = XF86HomePage
124+.br
125+keycode 182 = XF86Away
126+.br
127+keycode 183 = XF86WebCam
128+.br
129+keycode 184 = XF86Launch0
130+.br
131+keycode 188 = XF86Music
132+.br
133+keycode 190 = XF86Launch6
134+.br
135+keycode 194 = XF86Forward
136+.br
137+keycode 195 = XF86Send
138+.br
139+keycode 205 = XF86Calendar
140+.br
141+keycode 208 = XF86Launch7
142+.br
143+keycode 209 = XF86LaunchB
144+.br
145+keycode 210 = XF86LaunchC
146+.br
147+keycode 215 = XF86Save
148+.br
149+keycode 219 = XF86WWW
150+.br
151+keycode 220 = XF86LaunchE
152+.br
153+keycode 223 = XF86Sleep
154+.br
155+keycode 228 = XF86Pictures
156+.br
157+keycode 231 = XF86LaunchA
158+.br
159+keycode 236 = XF86Mail
160+.br
161+keycode 237 = XF86AudioMedia
162+.br
163+keycode 246 = XF86iTouch
164+.br
165+keycode 247 = XF86Launch3
166+.br
167+keycode 249 = XF86ToDoList
168+.br
169+keycode 251 = XF86Calculater
170+.br
171+\-\- end cutting \-\-
172+.SH "AUTHORS"
173+The latest release of g15daemon is available at
174+.P
175+http://g15daemon.sourceforge.net
176+.P
177+G15daemon was written by Mike Lampard mlampard@users.sourceforge.net and uses the libg15 library by Philip Lawatsch and Anthony J. Mirabella of the g15tools project. (g15tools.sourceforge.net)
178+.P
179+The Python bindings for libg15daemon_client were written by Sven Ludwig.
180+.P
181+Many thanks to everyone who has assisted in reporting bugs, misfeatures and made feature requests.
182+
183+An up to date list of all authors is available in the AUTHORS file distributed in the source.
184+
185+.SH "LICENSE"
186+G15daemon, libg15daemon_client and other sourcecode in this package are licensed under the GPL (General Public License), version 2 or later. Details on this license are available in the LICENSE document in the root directory of the source package, and at http://www.fsf.org
187+
188+
189
190=== added file '.pc/01-remove-x11-setup-from-man.diff/Documentation/g15daemon_client_devel.3'
191--- .pc/01-remove-x11-setup-from-man.diff/Documentation/g15daemon_client_devel.3 1970-01-01 00:00:00 +0000
192+++ .pc/01-remove-x11-setup-from-man.diff/Documentation/g15daemon_client_devel.3 2015-05-21 10:27:39 +0000
193@@ -0,0 +1,220 @@
194+.TH "G15daemon Client Development" "" "1.0" "G15Daemon" ""
195+.SH "NAME" g15daemon_client \- G15Daemon Server / Client communication for g15daemon.
196+.SH "SYNOPSIS"
197+#include <libg15.h>
198+.br
199+#include <g15daemon_client.h>
200+
201+link with
202+
203+\-lg15daemon_client
204+
205+int new_g15_screen(int screentype);
206+.br
207+int g15_close_screen(int sock);
208+.br
209+int g15_send(int sock, char *buf, unsigned int len);
210+.br
211+int g15_recv(int sock, char *buf, unsigned int len);
212+.br
213+int g15_send_cmd (int sock, unsigned char command, unsigned char value);
214+.br
215+.SH "G15Daemon Server / Client communication"
216+G15Daemon uses INET sockets to talk to its clients, listening on localhost port 15550 for connection requests. Once connected, the server sends the text string "G15 daemon HELLO" to confirm to the client that it is a valid g15daemon process, creates a new screen, and waits for LCD buffers or commands to be sent from the client. Clients are able to create multiple screens simply by opening more socket connections to the server process. If the socket is closed or the client exits, all LCD buffers and the screen associated with that socket are automatically destroyed.
217+
218+Clients wishing to display on the LCD must send entire screens in the format of their choice. Currently partial screen updates (icons etc) are not supported.
219+
220+G15Daemon commands are sent to the daemon via the OOB (out\-of\-band) messagetype, replies are sent inband back to the client.
221+
222+.SH "int new_g15_screen(int screentype)"
223+Opens a new connection and returns a network socket for use. Creates a screen with one of the following pixel formats defined in g15daemon_client.h:
224+
225+G15_PIXELBUF: this buffer must be exactly 6880 bytes, and uses 1 byte per pixel.
226+
227+G15_TEXTBUF: currently ignored by the daemon.
228+
229+G15_WBMPBUF: this is a packed pixel buffer in WBMP format with 8 pixels per byte. Useful for perl programmers using the GD:: and G15Daemon.pm (see lang_bindings directory) perl modules.
230+
231+G15_G15RBUF: another packed pixel buffer type, also with 8 pixels/byte, and is the native libg15render format.
232+
233+Example of use:
234+
235+int screen_fd = new_g15_screen( G15_WBMPBUF );
236+
237+
238+
239+
240+
241+.SH "int g15_close_screen (int screen_fd)"
242+Simply closes a socket previously opened with new_g15_screen(). The daemon will automatically clean up any buffers and remove the LCD screen from the display list.
243+
244+Returns 0 if successful, or errno if there was an error.
245+
246+Example:
247+
248+int retval = 0;
249+int screen_fd = new_g15_screen( G15_WBMPBUF );
250+
251+... do processing and display here ...
252+
253+retval = g15_close_screen( screen_fd );
254+
255+.SH "int g15_send (int sock, char *buf, unsigned int len)"
256+A simple wrapper around send() to ensure that all 'len' bytes of data is sent to the daemon. It simply uses poll() to block until the entire message is sent.
257+
258+Returns 0 on success, \-1 if the send failed due to timeout or socket error.
259+
260+
261+
262+.SH "int g15_recv (int sock, char *buf, unsigned int len)"
263+A simple wrapper around recv() to ensure that all 'len' bytes of data are received from the daemon. It simply uses poll() to block until the entire message is received.
264+
265+Returns 0 on success, \-1 if the recv failed due to timeout or socket error.
266+
267+.SH "int g15_send_cmd ( int sock, unsigned char command, unsigned char value)"
268+Sends a command to the daemon (possible commands are listed below). Returns 0 or the return value of the command on success, \-1 on failure.
269+
270+See examples for usage.
271+
272+
273+.SH "G15Daemon Command Types"
274+.P
275+Commands and requests to the daemon are sent via OOB data packets. Changes to the backlight and mkey state will only affect the calling client. The following commands are supported as defined in g15daemon_client.h:
276+
277+.IP "G15DAEMON_KEY_HANDLER"
278+Requests that all M and G key presses are sent to this client. All keys are packed into an unsigned int, and sent to the client inband when a key is pressed.
279+
280+.IP "G15DAEMON_MKEYLEDS"
281+Sets the M key LED state. In order to change LED state, each LED that is to be turned on is OR'd with the command byte. See libg15.h for values. For examples see the end of this document.
282+
283+.IP "G15DAEMON_BACKLIGHT"
284+Sets the LCD Backlight brightness. Brightness level (0|1|2) is OR'd with the command byte. For examples see the end of this document.
285+
286+.IP "G15DAEMON_CONTRAST"
287+Sets the LCD contrast. Contrast level (0|1|2) is OR'd with the command byte. For examples see the end of this document.
288+
289+.IP "G15DAEMON_GET_KEYSTATE"
290+Requests a packet containing the current keystate. The daemon will return an unsigned int containing any keys pressed. See libg15.h for details on key values, and lcdclient_test.c in the source distribution for an example.
291+
292+.IP "G15DAEMON_SWITCH_PRIORITIES"
293+Toggles the client's LCD screen to/from the front. Clients can check their foreground/background state with the following:
294+
295+.IP "G15DAEMON_IS_FOREGROUND"
296+On reciept of this command, G15Daemon will send a 1 byte packet back with the value 1 if the client is foreground, or 0 if not.
297+
298+.IP "G15DAEMON_IS_USER_SELECTED"
299+On reciept of this command, G15daemon will return a byte indicating if the user selected the client be foreground or background.
300+
301+.SH "EXAMPLES"
302+Below is a completely nonsensical client which (poorly) demonstrates the usage of most of the commands.
303+
304+\-\-\- Cut here \-\-\-
305+.P
306+#include <stdio.h>
307+.br
308+#include <stdlib.h>
309+.br
310+#include <string.h>
311+.br
312+#include <sys/types.h>
313+.br
314+#include <sys/socket.h>
315+.br
316+#include <errno.h>
317+.br
318+#include <poll.h>
319+.br
320+#include <g15daemon_client.h>
321+.br
322+#include <libg15.h>
323+.br
324+.P
325+/* #define TEST_KEYHANDLER */
326+
327+int main(int argc, char *argv[])
328+{
329+ int g15screen_fd, retval;
330+ char lcdbuffer[6880];
331+ unsigned int keystate;
332+ char msgbuf[256];
333+ int foo = 0;
334+
335+ if((g15screen_fd = new_g15_screen(G15_PIXELBUF))<0){
336+ printf("Sorry, cant connect to the G15daemon\n");
337+ return 5;
338+ }else
339+ printf("Connected to g15daemon. sending image\n");
340+
341+ if(argc<2)
342+ retval = g15_send(g15screen_fd,(char*)logo_data,6880);
343+ else {
344+ memset(lcdbuffer,0,6880);
345+ memset(lcdbuffer,1,6880/2);
346+ retval = g15_send(g15screen_fd,(char*)lcdbuffer,6880);
347+ }
348+
349+ printf("checking key status \- press G1 to exit\n",retval);
350+
351+ while(1){
352+ keystate = 0;
353+ int foo;
354+
355+ keystate = g15_send_cmd (g15screen_fd, G15DAEMON_GET_KEYSTATE, foo);
356+ if(keystate)
357+ printf("keystate = %i\n",keystate);
358+
359+ if(keystate & G15_KEY_G1) //G1 key. See libg15.h for details on key values.
360+ break;
361+
362+ /* G2,G3 & G4 change LCD backlight */
363+ if(keystate & G15_KEY_G2){
364+ retval = g15_send_cmd (g15screen_fd, G15DAEMON_BACKLIGHT, G15_BRIGHTNESS_DARK);
365+ }
366+ if(keystate & G15_KEY_G3){
367+ retval = g15_send_cmd (g15screen_fd, G15DAEMON_BACKLIGHT, G15_BRIGHTNESS_MEDIUM);
368+ }
369+ if(keystate & G15_KEY_G4){
370+ retval = g15_send_cmd (g15screen_fd, G15DAEMON_BACKLIGHT, G15_BRIGHTNESS_BRIGHT);
371+ }
372+
373+ /* is this client in the foreground?? */
374+ retval = g15_send_cmd (g15screen_fd, G15DAEMON_IS_FOREGROUND, foo);
375+
376+ if(retval)
377+ printf("Hey, we are in the foreground, Doc\n");
378+ else
379+ printf("What dastardly wabbit put me in the background?\n");
380+
381+ retval = g15_send_cmd (g15screen_fd, G15DAEMON_IS_USER_SELECTED, foo);
382+ if(retval)
383+ printf("You wanted me in the foreground, right Doc?\n");
384+ else
385+ printf("You dastardly wabbit !\n");
386+
387+ if(retval){ /* we've been backgrounded! */
388+ sleep(2); /* remain in the background for a bit */
389+ retval = g15_send_cmd (g15screen_fd, G15DAEMON_SWITCH_PRIORITIES, foo);
390+ sleep(2); /* switch to foreground */
391+ retval = g15_send_cmd (g15screen_fd, G15DAEMON_SWITCH_PRIORITIES, foo);
392+ }
393+
394+ usleep(500);
395+#ifdef TEST_KEYHANDLER
396+ /* ok.. request that all G&M keys are passed to us.. */
397+ retval = g15_send_cmd (g15screen_fd, G15DAEMON_KEY_HANDLER, foo);
398+
399+ while(1){
400+ printf("waiting on keystate\n");
401+ keystate=0;
402+ retval = recv(g15screen_fd, &keystate , sizeof(keystate),0);
403+ if(keystate)
404+ printf("Recieved %i as keystate",keystate);
405+ }
406+#endif
407+ }
408+ g15_close_screen(g15screen_fd);
409+ return 0;
410+}
411+
412+\-\- end cutting \-\-
413+
414
415=== added directory '.pc/02-better-screenshort-creation.diff'
416=== added directory '.pc/02-better-screenshort-creation.diff/g15daemon'
417=== added file '.pc/02-better-screenshort-creation.diff/g15daemon/utility_funcs.c'
418--- .pc/02-better-screenshort-creation.diff/g15daemon/utility_funcs.c 1970-01-01 00:00:00 +0000
419+++ .pc/02-better-screenshort-creation.diff/g15daemon/utility_funcs.c 2015-05-21 10:27:39 +0000
420@@ -0,0 +1,688 @@
421+/*
422+ This file is part of g15daemon.
423+
424+ g15daemon is free software; you can redistribute it and/or modify
425+ it under the terms of the GNU General Public License as published by
426+ the Free Software Foundation; either version 2 of the License, or
427+ (at your option) any later version.
428+
429+ g15daemon is distributed in the hope that it will be useful,
430+ but WITHOUT ANY WARRANTY; without even the implied warranty of
431+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
432+ GNU General Public License for more details.
433+
434+ You should have received a copy of the GNU General Public License
435+ along with g15daemon; if not, write to the Free Software
436+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
437+
438+ (c) 2006-2008 Mike Lampard, Philip Lawatsch, and others
439+
440+ $Revision: 449 $ - $Date: 2008-01-24 17:42:07 +1030 (Thu, 24 Jan 2008) $ $Author: mlampard $
441+
442+ This daemon listens on localhost port 15550 for client connections,
443+ and arbitrates LCD display. Allows for multiple simultaneous clients.
444+ Client screens can be cycled through by pressing the 'L1' key.
445+*/
446+
447+#include <pthread.h>
448+#include <stdio.h>
449+#include <stdlib.h>
450+#include <signal.h>
451+#include <errno.h>
452+#include <string.h>
453+#include <sys/types.h>
454+#include <fcntl.h>
455+#include <unistd.h>
456+#include <sys/stat.h>
457+#include <ctype.h>
458+
459+#include <sys/time.h>
460+
461+#ifdef HAVE_CONFIG_H
462+#include <config.h>
463+#endif
464+#include "g15daemon.h"
465+#include <libg15.h>
466+#include <stdarg.h>
467+#include <libg15render.h>
468+
469+extern unsigned int g15daemon_debug;
470+extern volatile int leaving;
471+#define G15DAEMON_PIDFILE "/var/run/g15daemon.pid"
472+
473+pthread_cond_t lcd_refresh = PTHREAD_COND_INITIALIZER;
474+
475+
476+/* if no exitfunc or eventhandler, member should be NULL */
477+const plugin_info_t generic_info[] = {
478+ /* TYPE, name, initfunc, updatefreq, exitfunc, eventhandler */
479+ {G15_PLUGIN_LCD_CLIENT, "BackwardCompatible", NULL, 0, NULL, (void*)internal_generic_eventhandler},
480+ {G15_PLUGIN_NONE, "" , NULL, 0, NULL, NULL}
481+};
482+
483+/* handy function from xine_utils.c */
484+void *g15daemon_xmalloc(size_t size) {
485+ void *ptr;
486+
487+ /* prevent xmalloc(0) of possibly returning NULL */
488+ if( !size )
489+ size++;
490+
491+ if((ptr = calloc(1, size)) == NULL) {
492+ g15daemon_log(LOG_WARNING, "g15_xmalloc() failed: %s.\n", strerror(errno));
493+ return NULL;
494+ }
495+ return ptr;
496+}
497+
498+static int refresh_pending=0;
499+void g15daemon_init_refresh() {
500+ pthread_condattr_t attr;
501+ pthread_cond_init(&lcd_refresh, &attr);
502+}
503+
504+void g15daemon_send_refresh(lcd_t *lcd) {
505+ if(lcd==lcd->masterlist->current->lcd||lcd->state_changed) {
506+ pthread_cond_broadcast(&lcd_refresh);
507+ refresh_pending++;
508+ }
509+}
510+
511+void g15daemon_wait_refresh() {
512+ pthread_mutex_t dummy_mutex;
513+ struct timespec timeout;
514+ int retval;
515+ if(refresh_pending<1) {
516+ /* Create a dummy mutex which doesn't unlock for sure while waiting. */
517+ pthread_mutex_init(&dummy_mutex, NULL);
518+ pthread_mutex_lock(&dummy_mutex);
519+start:
520+ time(&timeout.tv_sec);
521+ timeout.tv_sec += 1;
522+ timeout.tv_nsec = 0L;
523+
524+ retval=pthread_cond_timedwait(&lcd_refresh, &dummy_mutex, &timeout);
525+ if(!leaving && retval == ETIMEDOUT)
526+ goto start;
527+ pthread_mutex_unlock(&dummy_mutex);
528+ pthread_mutex_destroy(&dummy_mutex);
529+ }
530+ refresh_pending--;
531+}
532+
533+void g15daemon_quit_refresh() {
534+ pthread_cond_destroy(&lcd_refresh);
535+}
536+
537+int uf_return_running(){
538+ int fd;
539+ char pidtxt[128];
540+ int pid;
541+ int l;
542+
543+ if ((fd = open(G15DAEMON_PIDFILE, O_RDWR, 0644)) < 0) {
544+ return -1;
545+ }
546+ if((l = read(fd,pidtxt,sizeof(pidtxt)-1)) < 0) {
547+ unlink (G15DAEMON_PIDFILE);
548+ close(fd);
549+ return -1;
550+ }
551+ if((pid = atoi(pidtxt)) <= 0) {
552+ g15daemon_log(LOG_ERR,"pidfile corrupt");
553+ unlink(G15DAEMON_PIDFILE);
554+ close(fd);
555+ return -1;
556+ }
557+ if((kill(pid,0) != 0) && errno != EPERM ) {
558+ g15daemon_log(LOG_ERR,"Process died - removing pidfile");
559+ unlink(G15DAEMON_PIDFILE);
560+ close(fd);
561+ return -1;
562+ }
563+
564+ return pid;
565+
566+}
567+
568+int uf_create_pidfile() {
569+
570+ char pidtxt[128];
571+ size_t l;
572+ int fd;
573+
574+ if(!uf_return_running() && (fd = open(G15DAEMON_PIDFILE, O_CREAT|O_RDWR|O_EXCL, 0644)) < 0) {
575+ g15daemon_log(LOG_ERR,"previous G15Daemon process died. removing pidfile");
576+ unlink(G15DAEMON_PIDFILE);
577+ }
578+ if ((fd = open(G15DAEMON_PIDFILE, O_CREAT|O_RDWR|O_EXCL, 0644)) < 0) {
579+ return 1;
580+ }
581+
582+ snprintf(pidtxt, sizeof(pidtxt), "%lu\n", (unsigned long) getpid());
583+
584+ if (write(fd, pidtxt, l = strlen(pidtxt)) != l) {
585+ g15daemon_log(LOG_WARNING, "write(): %s", strerror(errno));
586+ unlink(G15DAEMON_PIDFILE);
587+ }
588+
589+ if(fd>0) {
590+ close(fd);
591+ return 0;
592+ }
593+ return 1;
594+}
595+
596+
597+/* syslog wrapper */
598+int g15daemon_log (int priority, const char *fmt, ...) {
599+ va_list argp;
600+ va_start (argp, fmt);
601+ int real_prio=0;
602+
603+ switch(g15daemon_debug) {
604+ case 0:
605+ case 1:
606+ real_prio = LOG_WARNING;
607+ break;
608+ case 2:
609+ real_prio = LOG_INFO;
610+ break;
611+ default:
612+ real_prio = LOG_DEBUG;
613+ }
614+
615+ if(real_prio>=priority) {
616+ if(g15daemon_debug == 0) {
617+ vsyslog(priority, fmt, argp);
618+ } else {
619+ vfprintf(stderr,fmt,argp);
620+ fprintf(stderr,"\n");
621+ }
622+ }
623+ va_end (argp);
624+
625+ return 0;
626+}
627+
628+/* takes a 6880 byte (1byte==1pixel) buffer and packs it into libg15 format. */
629+void g15daemon_convert_buf(lcd_t *lcd, unsigned char * orig_buf)
630+{
631+ unsigned int x,y,val;
632+ for(x=0;x<160;x++)
633+ for(y=0;y<43;y++)
634+ {
635+ unsigned int pixel_offset = y * LCD_WIDTH + x;
636+ unsigned int byte_offset = pixel_offset / 8;
637+ unsigned int bit_offset = 7-(pixel_offset % 8);
638+
639+ val = orig_buf[x+(y*160)];
640+
641+ if (val)
642+ lcd->buf[byte_offset] = lcd->buf[byte_offset] | 1 << bit_offset;
643+ else
644+ lcd->buf[byte_offset] = lcd->buf[byte_offset] & ~(1 << bit_offset);
645+ }
646+}
647+
648+/* wrap the libg15 functions */
649+int uf_write_buf_to_g15(lcd_t *lcd)
650+{
651+ int retval = 0;
652+#ifdef LIBUSB_BLOCKS
653+ retval = writePixmapToLCD(lcd->buf);
654+#else
655+ pthread_mutex_lock(&g15lib_mutex);
656+ retval = writePixmapToLCD(lcd->buf);
657+ pthread_mutex_unlock(&g15lib_mutex);
658+#endif
659+ return retval;
660+}
661+
662+int uf_read_keypresses(unsigned int *keypresses, unsigned int timeout)
663+{
664+ int retval=0;
665+#ifdef LIBUSB_BLOCKS
666+ retval = getPressedKeys(keypresses, timeout);
667+#else
668+ pthread_mutex_lock(&g15lib_mutex);
669+ retval = getPressedKeys(keypresses, timeout);
670+ pthread_mutex_unlock(&g15lib_mutex);
671+#endif
672+ return retval;
673+}
674+
675+/* Sleep routine (hackish). */
676+void g15daemon_sleep(int seconds) {
677+ pthread_mutex_t dummy_mutex;
678+ static pthread_cond_t dummy_cond = PTHREAD_COND_INITIALIZER;
679+ struct timespec timeout;
680+
681+ /* Create a dummy mutex which doesn't unlock for sure while waiting. */
682+ pthread_mutex_init(&dummy_mutex, NULL);
683+ pthread_mutex_lock(&dummy_mutex);
684+
685+ timeout.tv_sec = time(NULL) + seconds;
686+ timeout.tv_nsec = 0;
687+
688+ pthread_cond_timedwait(&dummy_cond, &dummy_mutex, &timeout);
689+
690+ /* pthread_cond_destroy(&dummy_cond); */
691+ pthread_mutex_unlock(&dummy_mutex);
692+ pthread_mutex_destroy(&dummy_mutex);
693+}
694+
695+/* microsecond sleep routine. */
696+int g15daemon_usleep(int useconds) {
697+
698+ struct timeval timeout;
699+ if(useconds < 10000)
700+ useconds = 10000;
701+ timeout.tv_sec = useconds / 1000000;
702+ timeout.tv_usec = useconds % 1000000;
703+ return select (0,0,0,0,&timeout);
704+}
705+
706+/* millisecond sleep routine. */
707+int g15daemon_msleep(int milliseconds) {
708+
709+ return g15daemon_usleep(milliseconds*1000);
710+}
711+
712+
713+unsigned int g15daemon_gettime_ms(){
714+ struct timeval tv;
715+ gettimeofday(&tv,NULL);
716+ return (tv.tv_sec*1000+tv.tv_usec/1000);
717+}
718+
719+/* generic event handler used unless overridden (only loading a plugin will override currently)*/
720+int internal_generic_eventhandler(plugin_event_t *event) {
721+
722+ lcd_t *lcd = (lcd_t*) event->lcd;
723+
724+ switch (event->event)
725+ {
726+ case G15_EVENT_KEYPRESS: {
727+ if(lcd->g15plugin->plugin_handle){ /* loadable plugin */
728+ /* plugin had null for eventhandler therefore doesnt want events.. throw them away */
729+ }
730+ }
731+ break;
732+ case G15_EVENT_VISIBILITY_CHANGED:
733+ break;
734+ default:
735+ break;
736+ }
737+ return G15_PLUGIN_OK;
738+}
739+
740+
741+/* free all memory used by the config subsystem */
742+void uf_conf_free(g15daemon_t *list)
743+{
744+ config_section_t *section=list->config->sections;
745+ config_items_t *tmpitem=NULL;
746+ config_section_t *tmpsection=section;
747+
748+ while(tmpsection!=NULL){
749+ tmpitem=section->items;
750+
751+ if(section->sectionname){
752+ free(section->sectionname);
753+ while(section->items!=NULL){
754+ if(tmpitem->key!=NULL)
755+ free(tmpitem->key);
756+ if(tmpitem->value!=NULL)
757+ free(tmpitem->value);
758+ tmpitem=section->items->next;
759+ free(section->items);
760+ section->items=tmpitem;
761+ }
762+ }
763+ tmpsection=section->next;
764+ free(section);
765+ section=tmpsection;
766+ }
767+ free(section);
768+ free(list->config);
769+}
770+
771+/* write the config file with all keys/sections */
772+int uf_conf_write(g15daemon_t *list,char *filename)
773+{
774+ int config_fd=-1;
775+ config_section_t *foo=list->config->sections;
776+ config_items_t * item=NULL;
777+ char line[1024];
778+
779+ config_fd = open(filename,O_CREAT|O_RDWR|O_TRUNC);
780+ if(config_fd){
781+ snprintf(line,1024,"# G15Daemon Configuration File\n# any items entered before a [section] header\n# will be in the Global config space\n# comments you wish to keep should start with a semicolon';'\n");
782+ write(config_fd,line,strlen(line));
783+ while(foo!=NULL){
784+ item=foo->items;
785+ memset(line,0,1024);
786+ if(foo->sectionname!=NULL){
787+ snprintf(line,1024,"\n[%s]\n",foo->sectionname);
788+ write(config_fd,line,strlen(line));
789+ while(item!=NULL){
790+ memset(line,0,1024);
791+ if(item->key!=NULL){
792+ if(item->key[0]==';') // comment
793+ snprintf(line,1024,"%s\n",item->key);
794+ else
795+ snprintf(line,1024,"%s: %s\n",item->key, item->value);
796+ write(config_fd,line,strlen(line));
797+ }
798+ item=item->next;
799+ }
800+ }
801+ foo=foo->next;
802+ }
803+ close(config_fd);
804+ return 0;
805+ }
806+ return -1;
807+}
808+
809+/* search the list for valid section name return pointer to section, or NULL otherwise */
810+config_section_t* uf_search_confsection(g15daemon_t *list,char *sectionname){
811+ config_section_t *section=list->config->sections;
812+
813+ while(section!=NULL){
814+ if(0==strcmp((char*)section->sectionname,(char*)sectionname))
815+ break;
816+ section=section->next;
817+ }
818+ return section;
819+}
820+
821+/* search the list for valid key called "key" in section named "section" return pointer to item or NULL */
822+config_items_t* uf_search_confitem(config_section_t *section, char *key){
823+
824+ config_items_t * item=NULL;
825+
826+ if(section!=NULL){
827+ item=section->items;
828+ while(item!=NULL){
829+ if(0==strcmp((char*)item->key,(char*)key))
830+ break;
831+ item=item->next;
832+ }
833+ }
834+ return item;
835+}
836+
837+
838+/* return pointer to section, or create a new section if it doesnt exist */
839+config_section_t *g15daemon_cfg_load_section(g15daemon_t *masterlist,char *name) {
840+
841+ config_section_t *new = NULL;
842+ if((new=uf_search_confsection(masterlist,name))!=NULL)
843+ return new;
844+ new = g15daemon_xmalloc(sizeof(config_section_t));
845+ new->head = new;
846+ new->next = NULL;;
847+ new->sectionname=strdup(name);
848+ if(!masterlist->config->sections){
849+ masterlist->config->sections=new;
850+ masterlist->config->sections->head = new;
851+ } else {
852+ masterlist->config->sections->head->next=new;
853+ masterlist->config->sections->head = new;
854+ }
855+ return new;
856+}
857+
858+/* cleanup whitespace */
859+char * uf_remove_whitespace(char *str){
860+ int z=0;
861+ if(str==NULL)
862+ str=strdup(" ");
863+ while(isspace(str[z])&&str[z])
864+ z++;
865+ str+=z;
866+ return str;
867+}
868+
869+/* add a new key, or update the value of an already existing key, or return -1 if section doesnt exist */
870+int g15daemon_cfg_write_string(config_section_t *section, char *key, char *val){
871+
872+ config_items_t *new = NULL;
873+
874+ if(section==NULL)
875+ return -1;
876+
877+ if((uf_search_confitem(section, key))){
878+ free(new);
879+ new=uf_search_confitem(section, key);
880+ new->value=strdup(val);
881+ }else{
882+ new=g15daemon_xmalloc(sizeof(config_items_t));
883+ new->head=new;
884+ new->next=NULL;
885+
886+ new->key=strdup(key);
887+ new->value=strdup(val);
888+ if(!section->items){
889+ new->prev=NULL;
890+ section->items=new;
891+ section->items->head=new;
892+ }else{
893+ new->prev=section->items->head;
894+ section->items->head->next=new;
895+ section->items->head=new;
896+ }
897+ }
898+ return 0;
899+}
900+
901+/* remoe a key/value pair from named section */
902+int g15daemon_cfg_remove_key(config_section_t *section, char *key){
903+
904+ config_items_t *new = NULL;
905+ config_items_t *next = NULL;
906+ config_items_t *prev = NULL;
907+ if(section==NULL)
908+ return -1;
909+
910+ if((uf_search_confitem(section, key))){
911+ new=uf_search_confitem(section, key);
912+ prev=new->prev;
913+ next=new->next;
914+ if(prev){
915+ prev->next=new->next;
916+ }else{
917+ if(!next) {
918+ free(section->items);
919+ section->items=NULL;
920+ }
921+ else
922+ section->items=next;
923+ }
924+
925+ if(new->head==new){
926+ if(prev){
927+ prev->head = prev;
928+ section->items->head=prev;
929+ }
930+ if(!prev){
931+ if(!next) {
932+ free(section->items);
933+ section->items=NULL;
934+ }
935+ }
936+ }
937+ if(next){
938+ if(prev)
939+ next->prev=prev;
940+ else
941+ next->prev=NULL;
942+ }
943+ free(new->key);
944+ free(new->value);
945+ free(new);
946+ }
947+ return 0;
948+}
949+
950+int g15daemon_cfg_write_int(config_section_t *section, char *key, int val) {
951+ char tmp[1024];
952+ snprintf(tmp,1024,"%i",val);
953+ return g15daemon_cfg_write_string(section, key, tmp);
954+}
955+
956+int g15daemon_cfg_write_float(config_section_t *section, char *key, double val) {
957+ char tmp[1024];
958+ snprintf(tmp,1024,"%f",val);
959+ return g15daemon_cfg_write_string(section, key, tmp);
960+}
961+
962+/* simply write value as On or Off depending on whether val>0 */
963+int g15daemon_cfg_write_bool(config_section_t *section, char *key, unsigned int val) {
964+ char tmp[1024];
965+ snprintf(tmp,1024,"%s",val?"On":"Off");
966+ return g15daemon_cfg_write_string(section, key, tmp);
967+}
968+
969+/* the config read functions will either return a value from the config file, or the default value, which will be written to the config file if the key doesnt exist */
970+
971+/* return bool as int from key in sectionname */
972+int g15daemon_cfg_read_bool(config_section_t *section, char *key, int defaultval) {
973+
974+ int retval=0;
975+ config_items_t *item = uf_search_confitem(section, key);
976+ if(item){
977+ retval = 1^retval?(strncmp(item->value,"On",2)==0):1;
978+ return retval;
979+ }
980+ g15daemon_cfg_write_bool(section, key, defaultval);
981+ return defaultval;
982+}
983+
984+/* return int from key in sectionname */
985+int g15daemon_cfg_read_int(config_section_t *section, char *key, int defaultval) {
986+
987+ config_items_t *item = uf_search_confitem(section, key);
988+ if(item){
989+ return atoi(item->value);
990+ }
991+ g15daemon_cfg_write_int(section, key, defaultval);
992+ return defaultval;
993+}
994+
995+/* return float from key in sectionname */
996+double g15daemon_cfg_read_float(config_section_t *section, char *key, double defaultval) {
997+
998+ config_items_t *item = uf_search_confitem(section, key);
999+ if(item){
1000+ return atof(item->value);
1001+ }
1002+ g15daemon_cfg_write_float(section, key, defaultval);
1003+ return defaultval;
1004+}
1005+
1006+/* return string value from key in sectionname */
1007+char* g15daemon_cfg_read_string(config_section_t *section, char *key, char *defaultval) {
1008+
1009+ config_items_t *item = uf_search_confitem(section, key);
1010+ if(item){
1011+ return item->value;
1012+ }
1013+ g15daemon_cfg_write_string(section, key, defaultval);
1014+ return defaultval;
1015+}
1016+
1017+
1018+int uf_conf_open(g15daemon_t *list, char *filename) {
1019+
1020+ char *buffer, *lines;
1021+ int config_fd=-1;
1022+ char *sect;
1023+ char *start;
1024+ char *bar = NULL;
1025+ int i;
1026+ struct stat stats;
1027+
1028+ list->config=g15daemon_xmalloc(sizeof(configfile_t));
1029+ list->config->sections=NULL;
1030+
1031+ if (lstat(filename, &stats) == -1)
1032+ return -1;
1033+ if (!(config_fd = open(filename, O_RDWR)))
1034+ return -1;
1035+
1036+ buffer = g15daemon_xmalloc(stats.st_size + 1);
1037+
1038+ if (read(config_fd, buffer, stats.st_size) != stats.st_size)
1039+ {
1040+ free(buffer);
1041+ close(config_fd);
1042+ return -1;
1043+ }
1044+ close(config_fd);
1045+ buffer[stats.st_size] = '\0';
1046+
1047+ lines=strtok_r(buffer,"\n",&bar);
1048+ config_section_t *section=NULL;
1049+ while(lines!=NULL){
1050+ sect=strdup(lines);
1051+
1052+ i=0;
1053+ while(isspace(sect[i])){
1054+ i++;
1055+ }
1056+ start=sect+i;
1057+ if(start[0]=='#'){
1058+ /* header - ignore */
1059+ /* comments start with ; and can be produced like so:
1060+ g15daemon_cfg_write_string(noload_cfg,"; Plugins in this section will not be loaded on start","");
1061+ the value parameter must not be used.
1062+ */
1063+ } else if(strrchr(start,']')) { /* section title */
1064+ char sectiontitle[1024];
1065+ memset(sectiontitle,0,1024);
1066+ strncpy(sectiontitle,start+1,strlen(start)-2);
1067+ section = g15daemon_cfg_load_section(list,sectiontitle);
1068+ }else{
1069+ /*section keys */
1070+ if(section==NULL){
1071+ /* create an internal section "Global" which is the default for items not under a [section] header */
1072+ section=g15daemon_cfg_load_section(list,"Global");
1073+ }
1074+ char *foo=NULL;
1075+ char *key = uf_remove_whitespace( strtok_r(start,":=",&foo) );
1076+ char *val = uf_remove_whitespace( strtok_r(NULL,":=", &foo) );
1077+
1078+ g15daemon_cfg_write_string(section,key,val);
1079+ }
1080+ free(sect);
1081+ lines=strtok_r(NULL,"\n",&bar);
1082+ }
1083+
1084+ free(buffer);
1085+ return 0;
1086+}
1087+
1088+int uf_screendump_pbm(unsigned char *buffer,char *filename) {
1089+ FILE *f;
1090+ int x,y;
1091+ #define WIDTH 40
1092+ g15canvas *canvas=g15daemon_xmalloc(sizeof(g15canvas));
1093+ memcpy(canvas->buffer,buffer,LCD_BUFSIZE);
1094+ f = fopen(filename,"w+");
1095+ fprintf(f,"P1\n160 43\n");
1096+ fprintf(f,"# G15 screendump - %s\n\n",filename);
1097+ for(y=0;y<43;y++)
1098+ for(x=0;x<160;x++) {
1099+ fprintf(f,"%i",g15r_getPixel(canvas,x,y));
1100+ if(x%WIDTH==WIDTH-1)
1101+ fprintf(f,"\n");
1102+ }
1103+
1104+ fclose(f);
1105+ free(canvas);
1106+ return 0;
1107+}
1108+
1109
1110=== added directory '.pc/03-change-syslog-facility.diff'
1111=== added directory '.pc/03-change-syslog-facility.diff/g15daemon'
1112=== added file '.pc/03-change-syslog-facility.diff/g15daemon/main.c'
1113--- .pc/03-change-syslog-facility.diff/g15daemon/main.c 1970-01-01 00:00:00 +0000
1114+++ .pc/03-change-syslog-facility.diff/g15daemon/main.c 2015-05-21 10:27:39 +0000
1115@@ -0,0 +1,580 @@
1116+/*
1117+ This file is part of g15daemon.
1118+
1119+ g15daemon is free software; you can redistribute it and/or modify
1120+ it under the terms of the GNU General Public License as published by
1121+ the Free Software Foundation; either version 2 of the License, or
1122+ (at your option) any later version.
1123+
1124+ g15daemon is distributed in the hope that it will be useful,
1125+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1126+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1127+ GNU General Public License for more details.
1128+
1129+ You should have received a copy of the GNU General Public License
1130+ along with g15daemon; if not, write to the Free Software
1131+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1132+
1133+ (c) 2006-2008 Mike Lampard, Philip Lawatsch, and others
1134+
1135+ $Revision: 457 $ - $Date: 2008-01-31 15:32:46 +1030 (Thu, 31 Jan 2008) $ $Author: mlampard $
1136+
1137+ This daemon listens on localhost port 15550 for client connections,
1138+ and arbitrates LCD display. Allows for multiple simultaneous clients.
1139+ Client screens can be cycled through by pressing the 'L1' key.
1140+*/
1141+
1142+#include <pthread.h>
1143+#include <stdio.h>
1144+#include <stdlib.h>
1145+#include <signal.h>
1146+#include <errno.h>
1147+#include <string.h>
1148+#include <sys/types.h>
1149+#include <sys/socket.h>
1150+#include <sys/stat.h>
1151+#include <sys/time.h>
1152+#include <fcntl.h>
1153+#include <unistd.h>
1154+#include <pwd.h>
1155+#include <ctype.h>
1156+
1157+#include <config.h>
1158+#include <libg15.h>
1159+#include <libg15render.h>
1160+#include "g15daemon.h"
1161+
1162+#ifndef LIBG15_VERSION
1163+#define LIBG15_VERSION 1000
1164+#endif
1165+
1166+/* all threads will exit if leaving >0 */
1167+volatile int leaving = 0;
1168+int keyboard_backlight_off_onexit = 0;
1169+unsigned int g15daemon_debug = 0;
1170+unsigned int cycle_key;
1171+unsigned int client_handles_keys = 0;
1172+static unsigned int set_backlight = 0;
1173+struct lcd_t *keyhandler = NULL;
1174+
1175+static int loaded_plugins = 0;
1176+
1177+/* send event to foreground client's eventlistener */
1178+int g15daemon_send_event(void *caller, unsigned int event, unsigned long value)
1179+{
1180+ switch(event) {
1181+ case G15_EVENT_KEYPRESS: {
1182+ static unsigned long lastkeys;
1183+ if(!(value & cycle_key) && !(lastkeys & cycle_key)){
1184+ lcd_t *lcd = (lcd_t*)caller;
1185+
1186+ if(!lcd->g15plugin->info)
1187+ break;
1188+
1189+ int *(*plugin_listener)(plugin_event_t *newevent) = (void*)lcd->g15plugin->info->event_handler;
1190+ plugin_event_t *newevent=g15daemon_xmalloc(sizeof(plugin_event_t));
1191+ newevent->event = event;
1192+ newevent->value = value;
1193+ newevent->lcd = lcd;
1194+ (*plugin_listener)((void*)newevent);
1195+ /* hack - keyboard events are always sent from the foreground even when they aren't
1196+ send keypress event to the OS keyboard_handler plugin */
1197+ if(lcd->masterlist->keyboard_handler != NULL && lcd->masterlist->remote_keyhandler_sock==0) {
1198+ int *(*keyboard_handler)(plugin_event_t *newevent) = (void*)lcd->masterlist->keyboard_handler;
1199+ (*keyboard_handler)((void*)newevent);
1200+ }
1201+ // if we have a remote keyhandler, send the key. FIXME: we should do this from the net plugin
1202+ if(lcd->masterlist->remote_keyhandler_sock!=0) {
1203+ if((send(lcd->masterlist->remote_keyhandler_sock,(void *)&newevent->value,sizeof(newevent->value),0))<0)
1204+ g15daemon_log(LOG_WARNING,"Error in send: %s\n",strerror(errno));
1205+ }
1206+ if(value & G15_KEY_LIGHT){ // the backlight key was pressed - maintain user-selected state
1207+ lcd_t *displaying = lcd->masterlist->current->lcd;
1208+ lcd->masterlist->kb_backlight_state++;
1209+ lcd->masterlist->kb_backlight_state %= 3;
1210+ displaying->backlight_state++;
1211+ displaying->backlight_state %= 3; // limit to 0-2 inclusive
1212+ }
1213+ if(value & G15_KEY_M1 && value & G15_KEY_M3) {
1214+ static int scr_num=0;
1215+ char filename[128];
1216+ lcd_t *displaying = lcd->masterlist->current->lcd;
1217+ sprintf(filename,"/tmp/g15daemon-sc-%i.pbm",scr_num);
1218+ uf_screendump_pbm(displaying->buf,filename);
1219+ scr_num++;
1220+ }
1221+ free(newevent);
1222+ }else{
1223+ /* hacky attempt to double-time the use of L1, if the key is pressed less than half a second, it cycles the screens. If held for longer, the key is sent to the application for use instead */
1224+ lcd_t *lcd = (lcd_t*)caller;
1225+ g15daemon_t* masterlist = lcd->masterlist;
1226+ static unsigned int clicktime;
1227+
1228+ if(value & cycle_key) {
1229+ clicktime=g15daemon_gettime_ms();
1230+ }else{
1231+ unsigned int unclick=g15daemon_gettime_ms();
1232+ if ((unclick-clicktime)<500) {
1233+ g15daemon_lcdnode_cycle(masterlist);
1234+ }
1235+ else
1236+ {
1237+ plugin_event_t *clickevent=g15daemon_xmalloc(sizeof(plugin_event_t));
1238+ int *(*plugin_listener)(plugin_event_t *clickevent) = (void*)lcd->g15plugin->info->event_handler;
1239+ clickevent->event = event;
1240+ clickevent->value = value|cycle_key;
1241+ clickevent->lcd = lcd;
1242+ (*plugin_listener)((void*)clickevent);
1243+ clickevent->event = event;
1244+ clickevent->value = value&~cycle_key;
1245+ clickevent->lcd = lcd;
1246+ (*plugin_listener)((void*)clickevent);
1247+ free(clickevent);
1248+ }
1249+ }
1250+ }
1251+ lastkeys = value;
1252+ break;
1253+ }
1254+ case G15_EVENT_CYCLE_PRIORITY:{
1255+ lcd_t *lcd = (lcd_t*)caller;
1256+ g15daemon_t* masterlist = lcd->masterlist;
1257+ if(value)
1258+ g15daemon_lcdnode_cycle(masterlist);
1259+ break;
1260+ }
1261+ case G15_EVENT_REQ_PRIORITY: {
1262+ lcdnode_t *lcdnode=(lcdnode_t*)caller;
1263+ /* client wants to switch priorities */
1264+ pthread_mutex_lock(&lcdlist_mutex);
1265+ if(lcdnode->list->current != lcdnode){
1266+ lcdnode->last_priority = lcdnode->list->current;
1267+ lcdnode->list->current = lcdnode;
1268+ }
1269+ else {
1270+ if(lcdnode->list->current == lcdnode->last_priority){
1271+ lcdnode->list->current = lcdnode->list->current->prev;
1272+ } else{
1273+ if(lcdnode->last_priority != NULL) {
1274+ lcdnode->list->current = lcdnode->last_priority;
1275+ lcdnode->last_priority = NULL;
1276+ }
1277+ else
1278+ lcdnode->list->current = lcdnode->list->current->prev;
1279+ }
1280+ }
1281+ pthread_mutex_unlock(&lcdlist_mutex);
1282+ g15daemon_send_refresh((lcd_t*)lcdnode->list->current->lcd);
1283+ break;
1284+ }
1285+ case G15_EVENT_VISIBILITY_CHANGED:
1286+ g15daemon_send_refresh((lcd_t*)caller);
1287+ default: {
1288+ lcd_t *lcd = (lcd_t*)caller;
1289+ int *(*plugin_listener)(plugin_event_t *newevent) = (void*)lcd->g15plugin->info->event_handler;
1290+ plugin_event_t *newevent=g15daemon_xmalloc(sizeof(plugin_event_t));
1291+ newevent->event = event;
1292+ newevent->value = value;
1293+ newevent->lcd = lcd;
1294+ (*plugin_listener)((void*)newevent);
1295+ free(newevent);
1296+ }
1297+ }
1298+ return 0;
1299+}
1300+
1301+static void *keyboard_watch_thread(void *lcdlist){
1302+
1303+ g15daemon_t *masterlist = (g15daemon_t*)(lcdlist);
1304+
1305+ unsigned int keypresses = 0;
1306+ int retval = 0;
1307+ static int lastkeys = 0;
1308+
1309+ while (!leaving) {
1310+
1311+ retval = uf_read_keypresses(&keypresses, 20);
1312+ /* every 2nd packet contains the codes we want.. immediately try again */
1313+ while (retval == G15_ERROR_TRY_AGAIN){
1314+ retval = uf_read_keypresses(&keypresses, 20);
1315+ }
1316+
1317+ if(retval == G15_NO_ERROR && lastkeys != keypresses) {
1318+ g15daemon_send_event(masterlist->current->lcd,
1319+ G15_EVENT_KEYPRESS, keypresses);
1320+ lastkeys = keypresses;
1321+
1322+ }else if(retval == -ENODEV && LIBG15_VERSION>=1200) {
1323+ pthread_mutex_lock(&g15lib_mutex);
1324+ while((retval=re_initLibG15() != G15_NO_ERROR) && !leaving){
1325+ g15daemon_log(LOG_WARNING,"Keyboard has gone.. Retrying\n");
1326+ sleep(1);
1327+ }
1328+ if(!leaving) {
1329+ masterlist->current->lcd->state_changed=1;
1330+ g15daemon_send_refresh(masterlist->current->lcd);
1331+ }
1332+ pthread_mutex_unlock(&g15lib_mutex);
1333+ }
1334+ g15daemon_msleep(40);
1335+ }
1336+ return NULL;
1337+}
1338+
1339+static void *lcd_draw_thread(void *lcdlist){
1340+
1341+ g15daemon_t *masterlist = (g15daemon_t*)(lcdlist);
1342+ /* unsigned int fps = 0; */
1343+ lcd_t *displaying = masterlist->tail->lcd;
1344+ memset(displaying->buf,0,1024);
1345+ static int prev_state=0;
1346+ g15daemon_sleep(2);
1347+
1348+ while (!leaving) {
1349+ /* wait until a client has updated */
1350+ g15daemon_wait_refresh();
1351+
1352+ pthread_mutex_lock(&lcdlist_mutex);
1353+ displaying = masterlist->current->lcd;
1354+
1355+ /* monitor 'fps' - due to the TCP protocol, some frames will be bunched up.
1356+ discard excess to reduce load on the bus */
1357+ /* fps = 1000 / (g15daemon_gettime_ms() - lastscreentime); */
1358+ /* if the current screen is less than 20ms from the previous (equivelant to 50fps) delay it */
1359+ /* this allows a real-world fps of 40fps with no almost frame loss and reduces peak usb bus-load */
1360+
1361+ g15daemon_log(LOG_DEBUG,"Updating LCD");
1362+ uf_write_buf_to_g15(displaying);
1363+ g15daemon_log(LOG_DEBUG,"LCD Update Complete");
1364+
1365+ if(prev_state!=displaying->backlight_state && set_backlight!=0) {
1366+ prev_state=displaying->backlight_state;
1367+ pthread_mutex_lock(&g15lib_mutex);
1368+ setLCDBrightness(displaying->backlight_state);
1369+ usleep(5);
1370+ setLCDBrightness(displaying->backlight_state);
1371+ setKBBrightness(displaying->backlight_state);
1372+ pthread_mutex_unlock(&g15lib_mutex);
1373+ }
1374+
1375+ if(displaying->state_changed){
1376+ pthread_mutex_lock(&g15lib_mutex);
1377+ setLCDContrast(displaying->contrast_state);
1378+ if(displaying->masterlist->remote_keyhandler_sock==0) // only allow mled control if the macro recorder isnt running
1379+ setLEDs(displaying->mkey_state);
1380+ pthread_mutex_unlock(&g15lib_mutex);
1381+ displaying->state_changed = 0;
1382+ }
1383+
1384+ pthread_mutex_unlock(&lcdlist_mutex);
1385+ }
1386+ return NULL;
1387+}
1388+
1389+void g15daemon_sighandler(int sig) {
1390+ switch(sig){
1391+ case SIGUSR1:
1392+ keyboard_backlight_off_onexit = 1;
1393+ case SIGINT:
1394+ case SIGTERM:
1395+ case SIGQUIT:
1396+ leaving = 1;
1397+ break;
1398+ case SIGPIPE:
1399+ break;
1400+ }
1401+}
1402+
1403+#ifndef HAVE_DAEMON
1404+/* daemon() is not posix compliant, so we roll our own if needed.*/
1405+int daemon(int nochdir, int noclose) {
1406+ pid_t pid;
1407+
1408+ if(nochdir<1)
1409+ chdir("/");
1410+ pid = fork();
1411+
1412+ switch(pid){
1413+ case -1:
1414+ printf("Unable to daemonise!\n");
1415+ return -1;
1416+ break;
1417+ case 0: {
1418+ umask(0);
1419+ if(setsid()==-1) {
1420+ perror("setsid");
1421+ return -1;
1422+ }
1423+ if(noclose<1) {
1424+ freopen( "/dev/null", "r", stdin);
1425+ freopen( "/dev/null", "w", stdout);
1426+ freopen( "/dev/null", "w", stderr);
1427+ }
1428+ break;
1429+ }
1430+ default:
1431+ _exit(0);
1432+ }
1433+ return 0;
1434+}
1435+#endif
1436+
1437+int main (int argc, char *argv[])
1438+{
1439+ pid_t daemonpid;
1440+ int retval;
1441+ int i;
1442+ int cycle_cmdline_override=0;
1443+ struct sigaction new_action;
1444+ cycle_key = G15_KEY_L1;
1445+ unsigned char user[256];
1446+ unsigned int lcdlevel = 1;
1447+
1448+ pthread_t keyboard_thread;
1449+ pthread_t lcd_thread;
1450+ memset(user,0,256);
1451+
1452+ for (i=0;i<argc;i++) {
1453+ char daemonargs[20];
1454+ memset(daemonargs,0,20);
1455+ strncpy(daemonargs,argv[i],19);
1456+ if (!strncmp(daemonargs, "-k",2) || !strncmp(daemonargs, "--kill",6)) {
1457+ daemonpid = uf_return_running();
1458+ if(daemonpid>0) {
1459+ kill(daemonpid,SIGINT);
1460+ } else
1461+ printf("G15Daemon not running\n");
1462+ exit(0);
1463+ }
1464+ if (!strncmp(daemonargs, "-K",2) || !strncmp(daemonargs, "--KILL",6)) {
1465+ daemonpid = uf_return_running();
1466+ if(daemonpid>0) {
1467+ kill(daemonpid,SIGUSR1);
1468+ } else
1469+ printf("G15Daemon not running\n");
1470+ exit(0);
1471+ }
1472+ if (!strncmp(daemonargs, "-v",2) || !strncmp(daemonargs, "--version",9)) {
1473+ float lg15ver = LIBG15_VERSION;
1474+ printf("G15Daemon version %s - %s\n",VERSION,uf_return_running() >= 0 ?"Loaded & Running":"Not Running");
1475+ printf("compiled with libg15 version %.3f\n\n",lg15ver/1000);
1476+ exit(0);
1477+ }
1478+
1479+ if (!strncmp(daemonargs, "-h",2) || !strncmp(daemonargs, "--help",6)) {
1480+ printf("G15Daemon version %s - %s\n",VERSION,uf_return_running() >= 0 ?"Loaded & Running":"Not Running");
1481+ printf("%s -h (--help) or -k (--kill) or -s (--switch) or -d (--debug) [level] or -v (--version) or -l (--lcdlevel) [0-2] \n\n -k\twill kill a previous incarnation",argv[0]);
1482+ #ifdef LIBG15_VERSION
1483+ #if LIBG15_VERSION >= 1200
1484+ printf("\n -K\tturn off the keyboard backlight on the way out.");
1485+ #endif
1486+ #endif
1487+ printf("\n -h\tshows this help\n -s\tchanges the screen-switch key from L1 to MR (beware)\n -d\tdebug mode - stay in foreground and output all debug messages to STDERR\n -v\tshow version\n -l\tset default LCD backlight level\n");
1488+ printf(" --set-backlight sets backlight individually for currently shown screen.\n\t\tDefault is to set backlight globally (keyboard default).\n");
1489+ exit(0);
1490+ }
1491+
1492+ if (!strncmp(daemonargs, "-s",2) || !strncmp(daemonargs, "--switch",8)) {
1493+ cycle_key = G15_KEY_MR;
1494+ cycle_cmdline_override=1;
1495+ }
1496+
1497+ if (!strncmp(daemonargs, "--set-backlight",15)) {
1498+ set_backlight = 1;
1499+ }
1500+
1501+ if (!strncmp(daemonargs, "-d",2) || !strncmp(daemonargs, "--debug",7)) {
1502+ g15daemon_debug = 1;
1503+ if((argv[i+1])!=NULL)
1504+ if(isdigit(argv[i+1][0])){
1505+ g15daemon_debug = atoi(argv[i+1]);
1506+ if(g15daemon_debug==0) g15daemon_debug = 1;
1507+ }
1508+ }
1509+
1510+ if (!strncmp(daemonargs, "-u",2) || !strncmp(daemonargs, "--user",7)) {
1511+ if(argv[i+1]!=NULL){
1512+ strncpy((char*)user,argv[i+1],128);
1513+ i++;
1514+ }
1515+ }
1516+
1517+ if (!strncmp(daemonargs, "-l",2) || !strncmp(daemonargs, "--lcdlevel",7)) {
1518+ if((argv[i+1])!=NULL)
1519+ if(isdigit(argv[i+1][0])){
1520+ lcdlevel = atoi(argv[i+1]);
1521+ }
1522+ }
1523+ }
1524+ if(g15daemon_debug){
1525+ g15daemon_log(LOG_INFO, "G15Daemon %s Build Date: %s",PACKAGE_VERSION,BUILD_DATE);
1526+ g15daemon_log(LOG_DEBUG, "Build OS: %s",BUILD_OS_NAME);
1527+ g15daemon_log(LOG_DEBUG, "With compiler: %s",COMPILER_VERSION);
1528+ fprintf(stderr, "G15Daemon CMDLINE ARGS: ");
1529+ for(i=1;i<argc;i++)
1530+ fprintf(stderr, "%s ",argv[i]);
1531+ fprintf(stderr,"\n");
1532+ }
1533+ if(uf_return_running()>=0) {
1534+ g15daemon_log(LOG_ERR,"G15Daemon already running.. Exiting");
1535+ exit(0);
1536+ }
1537+
1538+ /* set libg15 debugging to our debug setting */
1539+ if(LIBG15_VERSION>=1200)
1540+ libg15Debug(g15daemon_debug);
1541+
1542+#ifdef OSTYPE_DARWIN
1543+ /* OS X: load codeless kext */
1544+ retval = system("/sbin/kextload " "/System/Library/Extensions/libusbshield.kext");
1545+
1546+ if (WIFEXITED(retval)){
1547+ if (WEXITSTATUS(retval) !=0){
1548+ g15daemon_log(LOG_ERR,"Unable to load USB shield kext...exiting");
1549+ exit(1);
1550+ }
1551+ } else {
1552+ g15daemon_log(LOG_ERR,"Unable to launch kextload...exiting");
1553+ exit(1);
1554+ }
1555+#endif
1556+
1557+ /* init stuff here.. */
1558+ if((retval=initLibG15())!=G15_NO_ERROR){
1559+ g15daemon_log(LOG_ERR,"Unable to attach to the G15 Keyboard... exiting");
1560+ exit(1);
1561+ }
1562+
1563+ if(!g15daemon_debug)
1564+ daemon(0,0);
1565+
1566+ if(uf_create_pidfile() == 0) {
1567+
1568+ g15daemon_t *lcdlist;
1569+ config_section_t *global_cfg=NULL;
1570+ pthread_attr_t attr;
1571+ struct passwd *nobody;
1572+ unsigned char location[1024];
1573+
1574+ openlog("g15daemon", LOG_PID, LOG_USER);
1575+ if(strlen((char*)user)==0){
1576+ nobody = getpwnam("nobody");
1577+ }else {
1578+ nobody = getpwnam((char*)user);
1579+ }
1580+ if (nobody==NULL)
1581+ {
1582+ nobody = getpwuid(geteuid());
1583+ g15daemon_log(LOG_WARNING,"BEWARE: running as effective uid %i\n",nobody->pw_uid);
1584+ }
1585+
1586+ /* initialise the linked list */
1587+ lcdlist = ll_lcdlist_init();
1588+ lcdlist->nobody = nobody;
1589+
1590+ setLCDContrast(1);
1591+ setLEDs(0);
1592+ lcdlist->kb_backlight_state=1;
1593+ lcdlist->current->lcd->backlight_state=lcdlevel;
1594+ setLCDBrightness(lcdlevel);
1595+
1596+#ifdef LIBG15_VERSION
1597+#if LIBG15_VERSION >= 1200
1598+ setKBBrightness(lcdlist->kb_backlight_state);
1599+#endif
1600+#endif
1601+
1602+ uf_conf_open(lcdlist, "/etc/g15daemon.conf");
1603+ global_cfg=g15daemon_cfg_load_section(lcdlist,"Global");
1604+ if(!cycle_cmdline_override){
1605+ cycle_key = 1==g15daemon_cfg_read_bool(global_cfg,"Use MR as Cycle Key",0)?G15_KEY_MR:G15_KEY_L1;
1606+ }
1607+
1608+#ifndef OSTYPE_SOLARIS
1609+ /* all other processes/threads should be seteuid nobody */
1610+ if(nobody!=NULL) {
1611+ seteuid(nobody->pw_uid);
1612+ setegid(nobody->pw_gid);
1613+ }
1614+#endif
1615+ /* initialise the pthread condition for the LCD thread */
1616+ g15daemon_init_refresh();
1617+ pthread_mutex_init(&g15lib_mutex, NULL);
1618+ pthread_attr_init(&attr);
1619+
1620+ pthread_attr_setstacksize(&attr,512*1024); /* set stack to 512k - dont need 8Mb !! */
1621+ if (pthread_create(&keyboard_thread, &attr, keyboard_watch_thread, lcdlist) != 0) {
1622+ g15daemon_log(LOG_ERR,"Unable to create keyboard listener thread. Exiting");
1623+ goto exitnow;
1624+ }
1625+
1626+ pthread_attr_setstacksize(&attr,128*1024);
1627+
1628+ if (pthread_create(&lcd_thread, &attr, lcd_draw_thread, lcdlist) != 0) {
1629+ g15daemon_log(LOG_ERR,"Unable to create display thread. Exiting");
1630+ goto exitnow;
1631+ }
1632+ g15daemon_log(LOG_INFO,"%s loaded\n",PACKAGE_STRING);
1633+
1634+ snprintf((char*)location,1024,"%s/%s",DATADIR,"g15daemon/splash/g15logo2.wbmp");
1635+ g15canvas *canvas = (g15canvas *)g15daemon_xmalloc (sizeof (g15canvas));
1636+ memset (canvas->buffer, 0, G15_BUFFER_LEN);
1637+ canvas->mode_cache = 0;
1638+ canvas->mode_reverse = 0;
1639+ canvas->mode_xor = 0;
1640+ g15r_loadWbmpSplash(canvas,(char*)location);
1641+ memcpy (lcdlist->tail->lcd->buf, canvas->buffer, G15_BUFFER_LEN);
1642+ free (canvas);
1643+ uf_write_buf_to_g15(lcdlist->tail->lcd);
1644+
1645+ snprintf((char*)location,1024,"%s",PLUGINDIR);
1646+
1647+ loaded_plugins = g15_open_all_plugins(lcdlist,(char*)location);
1648+
1649+ new_action.sa_handler = g15daemon_sighandler;
1650+ new_action.sa_flags = 0;
1651+ sigaction(SIGINT, &new_action, NULL);
1652+ sigaction(SIGQUIT, &new_action, NULL);
1653+ sigaction(SIGTERM, &new_action, NULL);
1654+ sigaction(SIGUSR1, &new_action, NULL);
1655+
1656+ do {
1657+ pause();
1658+ } while( leaving == 0);
1659+
1660+ g15daemon_log(LOG_INFO,"Leaving by request");
1661+
1662+ pthread_join(lcd_thread,NULL);
1663+ pthread_join(keyboard_thread,NULL);
1664+ /* switch off the lcd backlight */
1665+ char *blank=g15daemon_xmalloc(G15_BUFFER_LEN);
1666+ writePixmapToLCD((unsigned char*)blank);
1667+ free(blank);
1668+ setLCDBrightness(0);
1669+#ifdef LIBG15_VERSION
1670+#if LIBG15_VERSION >= 1200
1671+ /* if SIGUSR1 was sent to kill us, switch off the keyboard backlight as well */
1672+ if(keyboard_backlight_off_onexit==1)
1673+ setKBBrightness(0);
1674+#endif
1675+#endif
1676+
1677+#ifdef LIBG15_VERSION
1678+#if LIBG15_VERSION >= 1100
1679+ exitLibG15();
1680+#endif
1681+#endif
1682+ ll_lcdlist_destroy(&lcdlist);
1683+
1684+exitnow:
1685+ /* return to root privilages for the final countdown */
1686+ seteuid(0);
1687+ setegid(0);
1688+ closelog();
1689+ g15daemon_quit_refresh();
1690+ uf_conf_write(lcdlist,"/etc/g15daemon.conf");
1691+ uf_conf_free(lcdlist);
1692+ unlink("/var/run/g15daemon.pid");
1693+ }
1694+ return 0;
1695+}
1696
1697=== added directory '.pc/04-open-needs-mode.diff'
1698=== added directory '.pc/04-open-needs-mode.diff/g15daemon'
1699=== added file '.pc/04-open-needs-mode.diff/g15daemon/utility_funcs.c'
1700--- .pc/04-open-needs-mode.diff/g15daemon/utility_funcs.c 1970-01-01 00:00:00 +0000
1701+++ .pc/04-open-needs-mode.diff/g15daemon/utility_funcs.c 2015-05-21 10:27:39 +0000
1702@@ -0,0 +1,702 @@
1703+/*
1704+ This file is part of g15daemon.
1705+
1706+ g15daemon is free software; you can redistribute it and/or modify
1707+ it under the terms of the GNU General Public License as published by
1708+ the Free Software Foundation; either version 2 of the License, or
1709+ (at your option) any later version.
1710+
1711+ g15daemon is distributed in the hope that it will be useful,
1712+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1713+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1714+ GNU General Public License for more details.
1715+
1716+ You should have received a copy of the GNU General Public License
1717+ along with g15daemon; if not, write to the Free Software
1718+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1719+
1720+ (c) 2006-2008 Mike Lampard, Philip Lawatsch, and others
1721+
1722+ $Revision: 449 $ - $Date: 2008-01-24 17:42:07 +1030 (Thu, 24 Jan 2008) $ $Author: mlampard $
1723+
1724+ This daemon listens on localhost port 15550 for client connections,
1725+ and arbitrates LCD display. Allows for multiple simultaneous clients.
1726+ Client screens can be cycled through by pressing the 'L1' key.
1727+*/
1728+
1729+#include <pthread.h>
1730+#include <stdio.h>
1731+#include <stdlib.h>
1732+#include <signal.h>
1733+#include <errno.h>
1734+#include <string.h>
1735+#include <sys/types.h>
1736+#include <fcntl.h>
1737+#include <unistd.h>
1738+#include <sys/stat.h>
1739+#include <ctype.h>
1740+
1741+#include <sys/time.h>
1742+
1743+#ifdef HAVE_CONFIG_H
1744+#include <config.h>
1745+#endif
1746+#include "g15daemon.h"
1747+#include <libg15.h>
1748+#include <stdarg.h>
1749+#include <libg15render.h>
1750+
1751+extern unsigned int g15daemon_debug;
1752+extern volatile int leaving;
1753+#define G15DAEMON_PIDFILE "/var/run/g15daemon.pid"
1754+
1755+pthread_cond_t lcd_refresh = PTHREAD_COND_INITIALIZER;
1756+
1757+
1758+/* if no exitfunc or eventhandler, member should be NULL */
1759+const plugin_info_t generic_info[] = {
1760+ /* TYPE, name, initfunc, updatefreq, exitfunc, eventhandler */
1761+ {G15_PLUGIN_LCD_CLIENT, "BackwardCompatible", NULL, 0, NULL, (void*)internal_generic_eventhandler},
1762+ {G15_PLUGIN_NONE, "" , NULL, 0, NULL, NULL}
1763+};
1764+
1765+/* handy function from xine_utils.c */
1766+void *g15daemon_xmalloc(size_t size) {
1767+ void *ptr;
1768+
1769+ /* prevent xmalloc(0) of possibly returning NULL */
1770+ if( !size )
1771+ size++;
1772+
1773+ if((ptr = calloc(1, size)) == NULL) {
1774+ g15daemon_log(LOG_WARNING, "g15_xmalloc() failed: %s.\n", strerror(errno));
1775+ return NULL;
1776+ }
1777+ return ptr;
1778+}
1779+
1780+static int refresh_pending=0;
1781+void g15daemon_init_refresh() {
1782+ pthread_condattr_t attr;
1783+ pthread_cond_init(&lcd_refresh, &attr);
1784+}
1785+
1786+void g15daemon_send_refresh(lcd_t *lcd) {
1787+ if(lcd==lcd->masterlist->current->lcd||lcd->state_changed) {
1788+ pthread_cond_broadcast(&lcd_refresh);
1789+ refresh_pending++;
1790+ }
1791+}
1792+
1793+void g15daemon_wait_refresh() {
1794+ pthread_mutex_t dummy_mutex;
1795+ struct timespec timeout;
1796+ int retval;
1797+ if(refresh_pending<1) {
1798+ /* Create a dummy mutex which doesn't unlock for sure while waiting. */
1799+ pthread_mutex_init(&dummy_mutex, NULL);
1800+ pthread_mutex_lock(&dummy_mutex);
1801+start:
1802+ time(&timeout.tv_sec);
1803+ timeout.tv_sec += 1;
1804+ timeout.tv_nsec = 0L;
1805+
1806+ retval=pthread_cond_timedwait(&lcd_refresh, &dummy_mutex, &timeout);
1807+ if(!leaving && retval == ETIMEDOUT)
1808+ goto start;
1809+ pthread_mutex_unlock(&dummy_mutex);
1810+ pthread_mutex_destroy(&dummy_mutex);
1811+ }
1812+ refresh_pending--;
1813+}
1814+
1815+void g15daemon_quit_refresh() {
1816+ pthread_cond_destroy(&lcd_refresh);
1817+}
1818+
1819+int uf_return_running(){
1820+ int fd;
1821+ char pidtxt[128];
1822+ int pid;
1823+ int l;
1824+
1825+ if ((fd = open(G15DAEMON_PIDFILE, O_RDWR, 0644)) < 0) {
1826+ return -1;
1827+ }
1828+ if((l = read(fd,pidtxt,sizeof(pidtxt)-1)) < 0) {
1829+ unlink (G15DAEMON_PIDFILE);
1830+ close(fd);
1831+ return -1;
1832+ }
1833+ if((pid = atoi(pidtxt)) <= 0) {
1834+ g15daemon_log(LOG_ERR,"pidfile corrupt");
1835+ unlink(G15DAEMON_PIDFILE);
1836+ close(fd);
1837+ return -1;
1838+ }
1839+ if((kill(pid,0) != 0) && errno != EPERM ) {
1840+ g15daemon_log(LOG_ERR,"Process died - removing pidfile");
1841+ unlink(G15DAEMON_PIDFILE);
1842+ close(fd);
1843+ return -1;
1844+ }
1845+
1846+ return pid;
1847+
1848+}
1849+
1850+int uf_create_pidfile() {
1851+
1852+ char pidtxt[128];
1853+ size_t l;
1854+ int fd;
1855+
1856+ if(!uf_return_running() && (fd = open(G15DAEMON_PIDFILE, O_CREAT|O_RDWR|O_EXCL, 0644)) < 0) {
1857+ g15daemon_log(LOG_ERR,"previous G15Daemon process died. removing pidfile");
1858+ unlink(G15DAEMON_PIDFILE);
1859+ }
1860+ if ((fd = open(G15DAEMON_PIDFILE, O_CREAT|O_RDWR|O_EXCL, 0644)) < 0) {
1861+ return 1;
1862+ }
1863+
1864+ snprintf(pidtxt, sizeof(pidtxt), "%lu\n", (unsigned long) getpid());
1865+
1866+ if (write(fd, pidtxt, l = strlen(pidtxt)) != l) {
1867+ g15daemon_log(LOG_WARNING, "write(): %s", strerror(errno));
1868+ unlink(G15DAEMON_PIDFILE);
1869+ }
1870+
1871+ if(fd>0) {
1872+ close(fd);
1873+ return 0;
1874+ }
1875+ return 1;
1876+}
1877+
1878+
1879+/* syslog wrapper */
1880+int g15daemon_log (int priority, const char *fmt, ...) {
1881+ va_list argp;
1882+ va_start (argp, fmt);
1883+ int real_prio=0;
1884+
1885+ switch(g15daemon_debug) {
1886+ case 0:
1887+ case 1:
1888+ real_prio = LOG_WARNING;
1889+ break;
1890+ case 2:
1891+ real_prio = LOG_INFO;
1892+ break;
1893+ default:
1894+ real_prio = LOG_DEBUG;
1895+ }
1896+
1897+ if(real_prio>=priority) {
1898+ if(g15daemon_debug == 0) {
1899+ vsyslog(priority, fmt, argp);
1900+ } else {
1901+ vfprintf(stderr,fmt,argp);
1902+ fprintf(stderr,"\n");
1903+ }
1904+ }
1905+ va_end (argp);
1906+
1907+ return 0;
1908+}
1909+
1910+/* takes a 6880 byte (1byte==1pixel) buffer and packs it into libg15 format. */
1911+void g15daemon_convert_buf(lcd_t *lcd, unsigned char * orig_buf)
1912+{
1913+ unsigned int x,y,val;
1914+ for(x=0;x<160;x++)
1915+ for(y=0;y<43;y++)
1916+ {
1917+ unsigned int pixel_offset = y * LCD_WIDTH + x;
1918+ unsigned int byte_offset = pixel_offset / 8;
1919+ unsigned int bit_offset = 7-(pixel_offset % 8);
1920+
1921+ val = orig_buf[x+(y*160)];
1922+
1923+ if (val)
1924+ lcd->buf[byte_offset] = lcd->buf[byte_offset] | 1 << bit_offset;
1925+ else
1926+ lcd->buf[byte_offset] = lcd->buf[byte_offset] & ~(1 << bit_offset);
1927+ }
1928+}
1929+
1930+/* wrap the libg15 functions */
1931+int uf_write_buf_to_g15(lcd_t *lcd)
1932+{
1933+ int retval = 0;
1934+#ifdef LIBUSB_BLOCKS
1935+ retval = writePixmapToLCD(lcd->buf);
1936+#else
1937+ pthread_mutex_lock(&g15lib_mutex);
1938+ retval = writePixmapToLCD(lcd->buf);
1939+ pthread_mutex_unlock(&g15lib_mutex);
1940+#endif
1941+ return retval;
1942+}
1943+
1944+int uf_read_keypresses(unsigned int *keypresses, unsigned int timeout)
1945+{
1946+ int retval=0;
1947+#ifdef LIBUSB_BLOCKS
1948+ retval = getPressedKeys(keypresses, timeout);
1949+#else
1950+ pthread_mutex_lock(&g15lib_mutex);
1951+ retval = getPressedKeys(keypresses, timeout);
1952+ pthread_mutex_unlock(&g15lib_mutex);
1953+#endif
1954+ return retval;
1955+}
1956+
1957+/* Sleep routine (hackish). */
1958+void g15daemon_sleep(int seconds) {
1959+ pthread_mutex_t dummy_mutex;
1960+ static pthread_cond_t dummy_cond = PTHREAD_COND_INITIALIZER;
1961+ struct timespec timeout;
1962+
1963+ /* Create a dummy mutex which doesn't unlock for sure while waiting. */
1964+ pthread_mutex_init(&dummy_mutex, NULL);
1965+ pthread_mutex_lock(&dummy_mutex);
1966+
1967+ timeout.tv_sec = time(NULL) + seconds;
1968+ timeout.tv_nsec = 0;
1969+
1970+ pthread_cond_timedwait(&dummy_cond, &dummy_mutex, &timeout);
1971+
1972+ /* pthread_cond_destroy(&dummy_cond); */
1973+ pthread_mutex_unlock(&dummy_mutex);
1974+ pthread_mutex_destroy(&dummy_mutex);
1975+}
1976+
1977+/* microsecond sleep routine. */
1978+int g15daemon_usleep(int useconds) {
1979+
1980+ struct timeval timeout;
1981+ if(useconds < 10000)
1982+ useconds = 10000;
1983+ timeout.tv_sec = useconds / 1000000;
1984+ timeout.tv_usec = useconds % 1000000;
1985+ return select (0,0,0,0,&timeout);
1986+}
1987+
1988+/* millisecond sleep routine. */
1989+int g15daemon_msleep(int milliseconds) {
1990+
1991+ return g15daemon_usleep(milliseconds*1000);
1992+}
1993+
1994+
1995+unsigned int g15daemon_gettime_ms(){
1996+ struct timeval tv;
1997+ gettimeofday(&tv,NULL);
1998+ return (tv.tv_sec*1000+tv.tv_usec/1000);
1999+}
2000+
2001+/* generic event handler used unless overridden (only loading a plugin will override currently)*/
2002+int internal_generic_eventhandler(plugin_event_t *event) {
2003+
2004+ lcd_t *lcd = (lcd_t*) event->lcd;
2005+
2006+ switch (event->event)
2007+ {
2008+ case G15_EVENT_KEYPRESS: {
2009+ if(lcd->g15plugin->plugin_handle){ /* loadable plugin */
2010+ /* plugin had null for eventhandler therefore doesnt want events.. throw them away */
2011+ }
2012+ }
2013+ break;
2014+ case G15_EVENT_VISIBILITY_CHANGED:
2015+ break;
2016+ default:
2017+ break;
2018+ }
2019+ return G15_PLUGIN_OK;
2020+}
2021+
2022+
2023+/* free all memory used by the config subsystem */
2024+void uf_conf_free(g15daemon_t *list)
2025+{
2026+ config_section_t *section=list->config->sections;
2027+ config_items_t *tmpitem=NULL;
2028+ config_section_t *tmpsection=section;
2029+
2030+ while(tmpsection!=NULL){
2031+ tmpitem=section->items;
2032+
2033+ if(section->sectionname){
2034+ free(section->sectionname);
2035+ while(section->items!=NULL){
2036+ if(tmpitem->key!=NULL)
2037+ free(tmpitem->key);
2038+ if(tmpitem->value!=NULL)
2039+ free(tmpitem->value);
2040+ tmpitem=section->items->next;
2041+ free(section->items);
2042+ section->items=tmpitem;
2043+ }
2044+ }
2045+ tmpsection=section->next;
2046+ free(section);
2047+ section=tmpsection;
2048+ }
2049+ free(section);
2050+ free(list->config);
2051+}
2052+
2053+/* write the config file with all keys/sections */
2054+int uf_conf_write(g15daemon_t *list,char *filename)
2055+{
2056+ int config_fd=-1;
2057+ config_section_t *foo=list->config->sections;
2058+ config_items_t * item=NULL;
2059+ char line[1024];
2060+
2061+ config_fd = open(filename,O_CREAT|O_RDWR|O_TRUNC);
2062+ if(config_fd){
2063+ snprintf(line,1024,"# G15Daemon Configuration File\n# any items entered before a [section] header\n# will be in the Global config space\n# comments you wish to keep should start with a semicolon';'\n");
2064+ write(config_fd,line,strlen(line));
2065+ while(foo!=NULL){
2066+ item=foo->items;
2067+ memset(line,0,1024);
2068+ if(foo->sectionname!=NULL){
2069+ snprintf(line,1024,"\n[%s]\n",foo->sectionname);
2070+ write(config_fd,line,strlen(line));
2071+ while(item!=NULL){
2072+ memset(line,0,1024);
2073+ if(item->key!=NULL){
2074+ if(item->key[0]==';') // comment
2075+ snprintf(line,1024,"%s\n",item->key);
2076+ else
2077+ snprintf(line,1024,"%s: %s\n",item->key, item->value);
2078+ write(config_fd,line,strlen(line));
2079+ }
2080+ item=item->next;
2081+ }
2082+ }
2083+ foo=foo->next;
2084+ }
2085+ close(config_fd);
2086+ return 0;
2087+ }
2088+ return -1;
2089+}
2090+
2091+/* search the list for valid section name return pointer to section, or NULL otherwise */
2092+config_section_t* uf_search_confsection(g15daemon_t *list,char *sectionname){
2093+ config_section_t *section=list->config->sections;
2094+
2095+ while(section!=NULL){
2096+ if(0==strcmp((char*)section->sectionname,(char*)sectionname))
2097+ break;
2098+ section=section->next;
2099+ }
2100+ return section;
2101+}
2102+
2103+/* search the list for valid key called "key" in section named "section" return pointer to item or NULL */
2104+config_items_t* uf_search_confitem(config_section_t *section, char *key){
2105+
2106+ config_items_t * item=NULL;
2107+
2108+ if(section!=NULL){
2109+ item=section->items;
2110+ while(item!=NULL){
2111+ if(0==strcmp((char*)item->key,(char*)key))
2112+ break;
2113+ item=item->next;
2114+ }
2115+ }
2116+ return item;
2117+}
2118+
2119+
2120+/* return pointer to section, or create a new section if it doesnt exist */
2121+config_section_t *g15daemon_cfg_load_section(g15daemon_t *masterlist,char *name) {
2122+
2123+ config_section_t *new = NULL;
2124+ if((new=uf_search_confsection(masterlist,name))!=NULL)
2125+ return new;
2126+ new = g15daemon_xmalloc(sizeof(config_section_t));
2127+ new->head = new;
2128+ new->next = NULL;;
2129+ new->sectionname=strdup(name);
2130+ if(!masterlist->config->sections){
2131+ masterlist->config->sections=new;
2132+ masterlist->config->sections->head = new;
2133+ } else {
2134+ masterlist->config->sections->head->next=new;
2135+ masterlist->config->sections->head = new;
2136+ }
2137+ return new;
2138+}
2139+
2140+/* cleanup whitespace */
2141+char * uf_remove_whitespace(char *str){
2142+ int z=0;
2143+ if(str==NULL)
2144+ str=strdup(" ");
2145+ while(isspace(str[z])&&str[z])
2146+ z++;
2147+ str+=z;
2148+ return str;
2149+}
2150+
2151+/* add a new key, or update the value of an already existing key, or return -1 if section doesnt exist */
2152+int g15daemon_cfg_write_string(config_section_t *section, char *key, char *val){
2153+
2154+ config_items_t *new = NULL;
2155+
2156+ if(section==NULL)
2157+ return -1;
2158+
2159+ if((uf_search_confitem(section, key))){
2160+ free(new);
2161+ new=uf_search_confitem(section, key);
2162+ new->value=strdup(val);
2163+ }else{
2164+ new=g15daemon_xmalloc(sizeof(config_items_t));
2165+ new->head=new;
2166+ new->next=NULL;
2167+
2168+ new->key=strdup(key);
2169+ new->value=strdup(val);
2170+ if(!section->items){
2171+ new->prev=NULL;
2172+ section->items=new;
2173+ section->items->head=new;
2174+ }else{
2175+ new->prev=section->items->head;
2176+ section->items->head->next=new;
2177+ section->items->head=new;
2178+ }
2179+ }
2180+ return 0;
2181+}
2182+
2183+/* remoe a key/value pair from named section */
2184+int g15daemon_cfg_remove_key(config_section_t *section, char *key){
2185+
2186+ config_items_t *new = NULL;
2187+ config_items_t *next = NULL;
2188+ config_items_t *prev = NULL;
2189+ if(section==NULL)
2190+ return -1;
2191+
2192+ if((uf_search_confitem(section, key))){
2193+ new=uf_search_confitem(section, key);
2194+ prev=new->prev;
2195+ next=new->next;
2196+ if(prev){
2197+ prev->next=new->next;
2198+ }else{
2199+ if(!next) {
2200+ free(section->items);
2201+ section->items=NULL;
2202+ }
2203+ else
2204+ section->items=next;
2205+ }
2206+
2207+ if(new->head==new){
2208+ if(prev){
2209+ prev->head = prev;
2210+ section->items->head=prev;
2211+ }
2212+ if(!prev){
2213+ if(!next) {
2214+ free(section->items);
2215+ section->items=NULL;
2216+ }
2217+ }
2218+ }
2219+ if(next){
2220+ if(prev)
2221+ next->prev=prev;
2222+ else
2223+ next->prev=NULL;
2224+ }
2225+ free(new->key);
2226+ free(new->value);
2227+ free(new);
2228+ }
2229+ return 0;
2230+}
2231+
2232+int g15daemon_cfg_write_int(config_section_t *section, char *key, int val) {
2233+ char tmp[1024];
2234+ snprintf(tmp,1024,"%i",val);
2235+ return g15daemon_cfg_write_string(section, key, tmp);
2236+}
2237+
2238+int g15daemon_cfg_write_float(config_section_t *section, char *key, double val) {
2239+ char tmp[1024];
2240+ snprintf(tmp,1024,"%f",val);
2241+ return g15daemon_cfg_write_string(section, key, tmp);
2242+}
2243+
2244+/* simply write value as On or Off depending on whether val>0 */
2245+int g15daemon_cfg_write_bool(config_section_t *section, char *key, unsigned int val) {
2246+ char tmp[1024];
2247+ snprintf(tmp,1024,"%s",val?"On":"Off");
2248+ return g15daemon_cfg_write_string(section, key, tmp);
2249+}
2250+
2251+/* the config read functions will either return a value from the config file, or the default value, which will be written to the config file if the key doesnt exist */
2252+
2253+/* return bool as int from key in sectionname */
2254+int g15daemon_cfg_read_bool(config_section_t *section, char *key, int defaultval) {
2255+
2256+ int retval=0;
2257+ config_items_t *item = uf_search_confitem(section, key);
2258+ if(item){
2259+ retval = 1^retval?(strncmp(item->value,"On",2)==0):1;
2260+ return retval;
2261+ }
2262+ g15daemon_cfg_write_bool(section, key, defaultval);
2263+ return defaultval;
2264+}
2265+
2266+/* return int from key in sectionname */
2267+int g15daemon_cfg_read_int(config_section_t *section, char *key, int defaultval) {
2268+
2269+ config_items_t *item = uf_search_confitem(section, key);
2270+ if(item){
2271+ return atoi(item->value);
2272+ }
2273+ g15daemon_cfg_write_int(section, key, defaultval);
2274+ return defaultval;
2275+}
2276+
2277+/* return float from key in sectionname */
2278+double g15daemon_cfg_read_float(config_section_t *section, char *key, double defaultval) {
2279+
2280+ config_items_t *item = uf_search_confitem(section, key);
2281+ if(item){
2282+ return atof(item->value);
2283+ }
2284+ g15daemon_cfg_write_float(section, key, defaultval);
2285+ return defaultval;
2286+}
2287+
2288+/* return string value from key in sectionname */
2289+char* g15daemon_cfg_read_string(config_section_t *section, char *key, char *defaultval) {
2290+
2291+ config_items_t *item = uf_search_confitem(section, key);
2292+ if(item){
2293+ return item->value;
2294+ }
2295+ g15daemon_cfg_write_string(section, key, defaultval);
2296+ return defaultval;
2297+}
2298+
2299+
2300+int uf_conf_open(g15daemon_t *list, char *filename) {
2301+
2302+ char *buffer, *lines;
2303+ int config_fd=-1;
2304+ char *sect;
2305+ char *start;
2306+ char *bar = NULL;
2307+ int i;
2308+ struct stat stats;
2309+
2310+ list->config=g15daemon_xmalloc(sizeof(configfile_t));
2311+ list->config->sections=NULL;
2312+
2313+ if (lstat(filename, &stats) == -1)
2314+ return -1;
2315+ if (!(config_fd = open(filename, O_RDWR)))
2316+ return -1;
2317+
2318+ buffer = g15daemon_xmalloc(stats.st_size + 1);
2319+
2320+ if (read(config_fd, buffer, stats.st_size) != stats.st_size)
2321+ {
2322+ free(buffer);
2323+ close(config_fd);
2324+ return -1;
2325+ }
2326+ close(config_fd);
2327+ buffer[stats.st_size] = '\0';
2328+
2329+ lines=strtok_r(buffer,"\n",&bar);
2330+ config_section_t *section=NULL;
2331+ while(lines!=NULL){
2332+ sect=strdup(lines);
2333+
2334+ i=0;
2335+ while(isspace(sect[i])){
2336+ i++;
2337+ }
2338+ start=sect+i;
2339+ if(start[0]=='#'){
2340+ /* header - ignore */
2341+ /* comments start with ; and can be produced like so:
2342+ g15daemon_cfg_write_string(noload_cfg,"; Plugins in this section will not be loaded on start","");
2343+ the value parameter must not be used.
2344+ */
2345+ } else if(strrchr(start,']')) { /* section title */
2346+ char sectiontitle[1024];
2347+ memset(sectiontitle,0,1024);
2348+ strncpy(sectiontitle,start+1,strlen(start)-2);
2349+ section = g15daemon_cfg_load_section(list,sectiontitle);
2350+ }else{
2351+ /*section keys */
2352+ if(section==NULL){
2353+ /* create an internal section "Global" which is the default for items not under a [section] header */
2354+ section=g15daemon_cfg_load_section(list,"Global");
2355+ }
2356+ char *foo=NULL;
2357+ char *key = uf_remove_whitespace( strtok_r(start,":=",&foo) );
2358+ char *val = uf_remove_whitespace( strtok_r(NULL,":=", &foo) );
2359+
2360+ g15daemon_cfg_write_string(section,key,val);
2361+ }
2362+ free(sect);
2363+ lines=strtok_r(NULL,"\n",&bar);
2364+ }
2365+
2366+ free(buffer);
2367+ return 0;
2368+}
2369+
2370+int uf_screendump_pbm(unsigned char *buffer,char *filename) {
2371+ int fd;
2372+ FILE *f;
2373+ int x,y;
2374+ #define WIDTH 40
2375+ g15canvas *canvas=g15daemon_xmalloc(sizeof(g15canvas));
2376+ memcpy(canvas->buffer,buffer,LCD_BUFSIZE);
2377+ fd = open(filename, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
2378+ if(fd == -1) {
2379+ g15daemon_log(LOG_WARNING, "uf_screendump_pbm failed: open, %s.\n", strerror(errno));
2380+ return -1;
2381+ }
2382+ f = fdopen(fd,"w");
2383+ if(f==NULL) {
2384+ close(fd);
2385+ g15daemon_log(LOG_WARNING, "uf_screendump_pbm failed: fdopen, %s.\n", strerror(errno));
2386+ return -1;
2387+ }
2388+
2389+ fprintf(f,"P1\n160 43\n");
2390+ fprintf(f,"# G15 screendump - %s\n\n",filename);
2391+ for(y=0;y<43;y++)
2392+ for(x=0;x<160;x++) {
2393+ fprintf(f,"%i",g15r_getPixel(canvas,x,y));
2394+ if(x%WIDTH==WIDTH-1)
2395+ fprintf(f,"\n");
2396+ }
2397+
2398+ fclose(f);
2399+ fsync(fd);
2400+ close(fd);
2401+ free(canvas);
2402+ return 0;
2403+}
2404+
2405
2406=== added directory '.pc/05-send-a-sync-event-after-key-up-down.diff'
2407=== added directory '.pc/05-send-a-sync-event-after-key-up-down.diff/plugins'
2408=== added file '.pc/05-send-a-sync-event-after-key-up-down.diff/plugins/g15_plugin_uinput.c'
2409--- .pc/05-send-a-sync-event-after-key-up-down.diff/plugins/g15_plugin_uinput.c 1970-01-01 00:00:00 +0000
2410+++ .pc/05-send-a-sync-event-after-key-up-down.diff/plugins/g15_plugin_uinput.c 2015-05-21 10:27:39 +0000
2411@@ -0,0 +1,324 @@
2412+/*
2413+ This file is part of g15daemon.
2414+
2415+ g15daemon is free software; you can redistribute it and/or modify
2416+ it under the terms of the GNU General Public License as published by
2417+ the Free Software Foundation; either version 2 of the License, or
2418+ (at your option) any later version.
2419+
2420+ g15daemon is distributed in the hope that it will be useful,
2421+ but WITHOUT ANY WARRANTY; without even the implied warranty of
2422+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2423+ GNU General Public License for more details.
2424+
2425+ You should have received a copy of the GNU General Public License
2426+ along with g15daemon; if not, write to the Free Software
2427+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2428+
2429+ (c) 2006-2008 Mike Lampard, Philip Lawatsch, and others
2430+
2431+ $Revision: 388 $ - $Date: 2008-01-02 12:57:03 +1030 (Wed, 02 Jan 2008) $ $Author: mlampard $
2432+
2433+ UINPUT key processing plugin. receives events and sends keycodes to the linux kernel.
2434+*/
2435+#include <pthread.h>
2436+#include <stdio.h>
2437+#include <stdlib.h>
2438+#include <signal.h>
2439+#include <errno.h>
2440+#include <string.h>
2441+#include <sys/types.h>
2442+#include <sys/stat.h>
2443+#include <fcntl.h>
2444+#include <unistd.h>
2445+
2446+#include <config.h>
2447+#include <g15daemon.h>
2448+#include <pwd.h>
2449+
2450+#ifdef HAVE_CONFIG_H
2451+#ifdef HAVE_LINUX_UINPUT_H
2452+#include <linux/input.h>
2453+#include <linux/uinput.h>
2454+
2455+#include <libg15.h>
2456+
2457+static int uinp_fd = -1;
2458+static config_section_t *uinput_cfg=NULL;
2459+static int map_Lkeys = 0;
2460+
2461+#define GKEY_OFFSET 167
2462+#define MKEY_OFFSET 185
2463+#define LKEY_OFFSET 189
2464+
2465+#define G15KEY_DOWN 1
2466+#define G15KEY_UP 0
2467+
2468+static int g15_init_uinput(void *plugin_args) {
2469+
2470+ int i=0;
2471+ char *custom_filename;
2472+ g15daemon_t *masterlist = (g15daemon_t*) plugin_args;
2473+ struct uinput_user_dev uinp;
2474+ static const char *uinput_device_fn[] = { "/dev/uinput", "/dev/input/uinput","/dev/misc/uinput",0};
2475+
2476+ uinput_cfg = g15daemon_cfg_load_section(masterlist,"Keyboard OS Mapping (uinput)");
2477+ custom_filename = g15daemon_cfg_read_string(uinput_cfg, "device",(char*)uinput_device_fn[1]);
2478+ map_Lkeys=g15daemon_cfg_read_int(uinput_cfg, "Lkeys.mapped",0);
2479+
2480+ seteuid(0);
2481+ setegid(0);
2482+ while (uinput_device_fn[i] && (uinp_fd = open(uinput_device_fn[i],O_RDWR))<0){
2483+ ++i;
2484+ }
2485+ if(uinp_fd<0) { /* try reading the users preference in the config */
2486+ uinp_fd = open(custom_filename,O_RDWR);
2487+ }
2488+ if(uinp_fd<0){
2489+ g15daemon_log(LOG_ERR,"Unable to open UINPUT device. Please ensure the uinput driver is loaded into the kernel and that you have permission to open the device.");
2490+ return -1;
2491+ }
2492+ /* all other processes/threads should be seteuid nobody */
2493+ seteuid(masterlist->nobody->pw_uid);
2494+ setegid(masterlist->nobody->pw_gid);
2495+
2496+
2497+ memset(&uinp,0,sizeof(uinp));
2498+ strncpy(uinp.name, "G15 Extra Keys", UINPUT_MAX_NAME_SIZE);
2499+
2500+#ifdef HAVE_UINPUT_USER_DEV_ID
2501+ uinp.id.version = 4;
2502+ uinp.id.bustype = BUS_USB;
2503+#else
2504+ uinp.idversion = 4;
2505+ uinp.idbus = BUS_USB;
2506+#endif
2507+
2508+ ioctl(uinp_fd, UI_SET_EVBIT, EV_KEY);
2509+
2510+ for (i=0; i<256; ++i)
2511+ ioctl(uinp_fd, UI_SET_KEYBIT, i);
2512+
2513+ write(uinp_fd, &uinp, sizeof(uinp));
2514+
2515+ if (ioctl(uinp_fd, UI_DEV_CREATE))
2516+ {
2517+ g15daemon_log(LOG_ERR,"Unable to create UINPUT device.");
2518+ return -1;
2519+ }
2520+ return 0;
2521+}
2522+
2523+void g15_exit_uinput(void *plugin_args){
2524+ ioctl(uinp_fd, UI_DEV_DESTROY);
2525+ close(uinp_fd);
2526+}
2527+
2528+
2529+static void g15_uinput_keydown(unsigned char code)
2530+{
2531+ struct input_event event;
2532+ memset(&event, 0, sizeof(event));
2533+
2534+ event.type = EV_KEY;
2535+ event.code = code;
2536+ event.value = G15KEY_DOWN;
2537+
2538+ write (uinp_fd, &event, sizeof(event));
2539+}
2540+
2541+static void g15_uinput_keyup(unsigned char code)
2542+{
2543+ struct input_event event;
2544+ memset(&event, 0, sizeof(event));
2545+
2546+ event.type = EV_KEY;
2547+ event.code = code;
2548+ event.value = G15KEY_UP;
2549+
2550+ write (uinp_fd, &event, sizeof(event));
2551+}
2552+
2553+ void (*keyup)(unsigned char code) = &g15_uinput_keyup;
2554+ void (*keydown)(unsigned char code) = &g15_uinput_keydown;
2555+#else
2556+ void keyup(unsigned char code) { printf("Extra Keys not supported due to missing Uinput.h\n"); }
2557+ void keydown(unsigned char code) { printf("Extra Keys not supported due to missing Uinput.h\n"); }
2558+#endif
2559+#endif
2560+
2561+static void g15_process_keys(g15daemon_t *masterlist, unsigned int currentkeys, unsigned int lastkeys)
2562+{
2563+ /* 'G' keys */
2564+ if((currentkeys & G15_KEY_G1) && !(lastkeys & G15_KEY_G1))
2565+ keydown(GKEY_OFFSET);
2566+ else if(!(currentkeys & G15_KEY_G1) && (lastkeys & G15_KEY_G1))
2567+ keyup(GKEY_OFFSET);
2568+
2569+ if((currentkeys & G15_KEY_G2) && !(lastkeys & G15_KEY_G2))
2570+ keydown(GKEY_OFFSET+1);
2571+ else if(!(currentkeys & G15_KEY_G2) && (lastkeys & G15_KEY_G2))
2572+ keyup(GKEY_OFFSET+1);
2573+
2574+ if((currentkeys & G15_KEY_G3) && !(lastkeys & G15_KEY_G3))
2575+ keydown(GKEY_OFFSET+2);
2576+ else if(!(currentkeys & G15_KEY_G3) && (lastkeys & G15_KEY_G3))
2577+ keyup(GKEY_OFFSET+2);
2578+
2579+ if((currentkeys & G15_KEY_G4) && !(lastkeys & G15_KEY_G4))
2580+ keydown(GKEY_OFFSET+3);
2581+ else if(!(currentkeys & G15_KEY_G4) && (lastkeys & G15_KEY_G4))
2582+ keyup(GKEY_OFFSET+3);
2583+
2584+ if((currentkeys & G15_KEY_G5) && !(lastkeys & G15_KEY_G5))
2585+ keydown(GKEY_OFFSET+4);
2586+ else if(!(currentkeys & G15_KEY_G5) && (lastkeys & G15_KEY_G5))
2587+ keyup(GKEY_OFFSET+4);
2588+
2589+ if((currentkeys & G15_KEY_G6) && !(lastkeys & G15_KEY_G6))
2590+ keydown(GKEY_OFFSET+5);
2591+ else if(!(currentkeys & G15_KEY_G6) && (lastkeys & G15_KEY_G6))
2592+ keyup(GKEY_OFFSET+5);
2593+
2594+ if((currentkeys & G15_KEY_G7) && !(lastkeys & G15_KEY_G7))
2595+ keydown(GKEY_OFFSET+6);
2596+ else if(!(currentkeys & G15_KEY_G7) && (lastkeys & G15_KEY_G7))
2597+ keyup(GKEY_OFFSET+6);
2598+
2599+ if((currentkeys & G15_KEY_G8) && !(lastkeys & G15_KEY_G8))
2600+ keydown(GKEY_OFFSET+7);
2601+ else if(!(currentkeys & G15_KEY_G8) && (lastkeys & G15_KEY_G8))
2602+ keyup(GKEY_OFFSET+7);
2603+
2604+ if((currentkeys & G15_KEY_G9) && !(lastkeys & G15_KEY_G9))
2605+ keydown(GKEY_OFFSET+8);
2606+ else if(!(currentkeys & G15_KEY_G9) && (lastkeys & G15_KEY_G9))
2607+ keyup(GKEY_OFFSET+8);
2608+
2609+ if((currentkeys & G15_KEY_G10) && !(lastkeys & G15_KEY_G10))
2610+ keydown(GKEY_OFFSET+9);
2611+ else if(!(currentkeys & G15_KEY_G10) && (lastkeys & G15_KEY_G10))
2612+ keyup(GKEY_OFFSET+9);
2613+
2614+ if((currentkeys & G15_KEY_G11) && !(lastkeys & G15_KEY_G11))
2615+ keydown(GKEY_OFFSET+10);
2616+ else if(!(currentkeys & G15_KEY_G11) && (lastkeys & G15_KEY_G11))
2617+ keyup(GKEY_OFFSET+10);
2618+
2619+ if((currentkeys & G15_KEY_G12) && !(lastkeys & G15_KEY_G12))
2620+ keydown(GKEY_OFFSET+11);
2621+ else if(!(currentkeys & G15_KEY_G12) && (lastkeys & G15_KEY_G12))
2622+ keyup(GKEY_OFFSET+11);
2623+
2624+ if((currentkeys & G15_KEY_G13) && !(lastkeys & G15_KEY_G13))
2625+ keydown(GKEY_OFFSET+12);
2626+ else if(!(currentkeys & G15_KEY_G13) && (lastkeys & G15_KEY_G13))
2627+ keyup(GKEY_OFFSET+12);
2628+
2629+ if((currentkeys & G15_KEY_G14) && !(lastkeys & G15_KEY_G14))
2630+ keydown(GKEY_OFFSET+13);
2631+ else if(!(currentkeys & G15_KEY_G14) && (lastkeys & G15_KEY_G14))
2632+ keyup(GKEY_OFFSET+13);
2633+
2634+ if((currentkeys & G15_KEY_G15) && !(lastkeys & G15_KEY_G15))
2635+ keydown(GKEY_OFFSET+14);
2636+ else if(!(currentkeys & G15_KEY_G15) && (lastkeys & G15_KEY_G15))
2637+ keyup(GKEY_OFFSET+14);
2638+
2639+ if((currentkeys & G15_KEY_G16) && !(lastkeys & G15_KEY_G16))
2640+ keydown(GKEY_OFFSET+15);
2641+ else if(!(currentkeys & G15_KEY_G16) && (lastkeys & G15_KEY_G16))
2642+ keyup(GKEY_OFFSET+15);
2643+
2644+ if((currentkeys & G15_KEY_G17) && !(lastkeys & G15_KEY_G17))
2645+ keydown(GKEY_OFFSET+16);
2646+ else if(!(currentkeys & G15_KEY_G17) && (lastkeys & G15_KEY_G17))
2647+ keyup(GKEY_OFFSET+16);
2648+
2649+ if((currentkeys & G15_KEY_G18) && !(lastkeys & G15_KEY_G18))
2650+ keydown(GKEY_OFFSET+17);
2651+ else if(!(currentkeys & G15_KEY_G18) && (lastkeys & G15_KEY_G18))
2652+ keyup(GKEY_OFFSET+17);
2653+
2654+ /* 'M' keys */
2655+
2656+ if((currentkeys & G15_KEY_M1) && !(lastkeys & G15_KEY_M1))
2657+ keydown(MKEY_OFFSET);
2658+ else if(!(currentkeys & G15_KEY_M1) && (lastkeys & G15_KEY_M1))
2659+ keyup(MKEY_OFFSET);
2660+
2661+ if((currentkeys & G15_KEY_M2) && !(lastkeys & G15_KEY_M2))
2662+ keydown(MKEY_OFFSET+1);
2663+ else if(!(currentkeys & G15_KEY_M2) && (lastkeys & G15_KEY_M2))
2664+ keyup(MKEY_OFFSET+1);
2665+
2666+ if((currentkeys & G15_KEY_M3) && !(lastkeys & G15_KEY_M3))
2667+ keydown(MKEY_OFFSET+2);
2668+ else if(!(currentkeys & G15_KEY_M3) && (lastkeys & G15_KEY_M3))
2669+ keyup(MKEY_OFFSET+2);
2670+
2671+ if((currentkeys & G15_KEY_MR) && !(lastkeys & G15_KEY_MR))
2672+ keydown(MKEY_OFFSET+3);
2673+ else if(!(currentkeys & G15_KEY_MR) && (lastkeys & G15_KEY_MR))
2674+ keyup(MKEY_OFFSET+3);
2675+
2676+ if(map_Lkeys){
2677+ /* 'L' keys... */
2678+ if((currentkeys & G15_KEY_L1) && !(lastkeys & G15_KEY_L1))
2679+ keydown(LKEY_OFFSET);
2680+ else if(!(currentkeys & G15_KEY_L1) && (lastkeys & G15_KEY_L1))
2681+ keyup(LKEY_OFFSET);
2682+
2683+ if((currentkeys & G15_KEY_L2) && !(lastkeys & G15_KEY_L2))
2684+ keydown(LKEY_OFFSET+1);
2685+ else if(!(currentkeys & G15_KEY_L2) && (lastkeys & G15_KEY_L2))
2686+ keyup(LKEY_OFFSET+1);
2687+
2688+ if((currentkeys & G15_KEY_L3) && !(lastkeys & G15_KEY_L3))
2689+ keydown(LKEY_OFFSET+2);
2690+ else if(!(currentkeys & G15_KEY_L3) && (lastkeys & G15_KEY_L3))
2691+ keyup(LKEY_OFFSET+2);
2692+
2693+ if((currentkeys & G15_KEY_L4) && !(lastkeys & G15_KEY_L4))
2694+ keydown(LKEY_OFFSET+3);
2695+ else if(!(currentkeys & G15_KEY_L4) && (lastkeys & G15_KEY_L4))
2696+ keyup(LKEY_OFFSET+3);
2697+
2698+ if((currentkeys & G15_KEY_L5) && !(lastkeys & G15_KEY_L5))
2699+ keydown(LKEY_OFFSET+4);
2700+ else if(!(currentkeys & G15_KEY_L5) && (lastkeys & G15_KEY_L5))
2701+ keyup(LKEY_OFFSET+4);
2702+ }
2703+}
2704+
2705+
2706+static int keyevents(plugin_event_t *myevent) {
2707+ lcd_t *lcd = (lcd_t*) myevent->lcd;
2708+ static int lastkeys;
2709+ switch (myevent->event)
2710+ {
2711+ case G15_EVENT_KEYPRESS:{
2712+ g15_process_keys(lcd->masterlist, myevent->value,lastkeys);
2713+ lastkeys = myevent->value;
2714+ break;
2715+ }
2716+ case G15_EVENT_VISIBILITY_CHANGED:
2717+ case G15_EVENT_USER_FOREGROUND:
2718+ case G15_EVENT_MLED:
2719+ case G15_EVENT_BACKLIGHT:
2720+ case G15_EVENT_CONTRAST:
2721+ case G15_EVENT_REQ_PRIORITY:
2722+ case G15_EVENT_CYCLE_PRIORITY:
2723+ default:
2724+ break;
2725+ }
2726+ return G15_PLUGIN_OK;
2727+}
2728+
2729+
2730+ /* if no exitfunc or eventhandler, member should be NULL */
2731+plugin_info_t g15plugin_info[] = {
2732+ /* TYPE, name, initfunc, updatefreq, exitfunc, eventhandler, initfunc */
2733+ {G15_PLUGIN_CORE_OS_KB, "Linux UINPUT Keyboard Output" , NULL, 500, (void*)g15_exit_uinput, (void*)keyevents, (void*)g15_init_uinput},
2734+ {G15_PLUGIN_NONE, "" , NULL, 0, NULL, NULL, NULL}
2735+};
2736
2737=== added directory '.pc/06-fix-buffer-overflow.diff'
2738=== added directory '.pc/06-fix-buffer-overflow.diff/libg15daemon_client'
2739=== added file '.pc/06-fix-buffer-overflow.diff/libg15daemon_client/g15daemon_net.c'
2740--- .pc/06-fix-buffer-overflow.diff/libg15daemon_client/g15daemon_net.c 1970-01-01 00:00:00 +0000
2741+++ .pc/06-fix-buffer-overflow.diff/libg15daemon_client/g15daemon_net.c 2015-05-21 10:27:39 +0000
2742@@ -0,0 +1,297 @@
2743+/*
2744+ This file is part of g15daemon.
2745+
2746+ g15daemon is free software; you can redistribute it and/or modify
2747+ it under the terms of the GNU General Public License as published by
2748+ the Free Software Foundation; either version 2 of the License, or
2749+ (at your option) any later version.
2750+
2751+ g15daemon is distributed in the hope that it will be useful,
2752+ but WITHOUT ANY WARRANTY; without even the implied warranty of
2753+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2754+ GNU General Public License for more details.
2755+
2756+ You should have received a copy of the GNU General Public License
2757+ along with g15daemon; if not, write to the Free Software
2758+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2759+
2760+ (c) 2006-2008 Mike Lampard, Philip Lawatsch, and others
2761+
2762+ $Revision: 451 $ - $Date: 2008-01-25 15:15:04 +1030 (Fri, 25 Jan 2008) $ $Author: mlampard $
2763+
2764+ This daemon listens on localhost port 15550 for client connections,
2765+ and arbitrates LCD display. Allows for multiple simultaneous clients.
2766+ Client screens can be cycled through by pressing the 'L1' key.
2767+*/
2768+
2769+#include <string.h>
2770+#include <stdlib.h>
2771+#include <sys/socket.h>
2772+#include <sys/types.h>
2773+#include <sys/wait.h>
2774+#include <poll.h>
2775+#include <arpa/inet.h>
2776+#include <unistd.h>
2777+#include <sys/stat.h>
2778+#include <fcntl.h>
2779+#include <stdio.h>
2780+
2781+#include <config.h>
2782+
2783+#include <libg15.h>
2784+#include "g15daemon_client.h"
2785+
2786+#ifndef SO_PRIORITY
2787+#define SO_PRIORITY 12
2788+#endif
2789+
2790+#define G15SERVER_PORT 15550
2791+#define G15SERVER_ADDR "127.0.0.1"
2792+int leaving = 0;
2793+
2794+const char *g15daemon_version () {
2795+ return VERSION;
2796+}
2797+
2798+#ifdef HAVE_BACKTRACE
2799+
2800+#include <signal.h>
2801+#ifdef HAVE_EXECINFO_H
2802+#include <execinfo.h>
2803+#endif
2804+#define BACKTRACE_LEN 100
2805+_Bool segv_init = 0;
2806+
2807+/* sighandler function to print backtrace on segfault */
2808+
2809+void g15_sighandler(int sig) {
2810+ int i,nptrs;
2811+ void *buf[BACKTRACE_LEN];
2812+ char **btfuncs;
2813+
2814+ switch (sig) {
2815+ case SIGSEGV:
2816+ #ifdef HAVE_EXECINFO_H
2817+ fprintf(stderr, "The application (or it's libraries) caught a Segmentation Fault. Backtrace follows:\n");
2818+ nptrs = backtrace(buf,BACKTRACE_LEN);
2819+
2820+ btfuncs = backtrace_symbols(buf,nptrs);
2821+ if(btfuncs == NULL)
2822+ return;
2823+
2824+ for(i=0;i<nptrs;i++)
2825+ fprintf(stderr,"Backtrace: %s\n",btfuncs[i]);
2826+ fprintf(stderr,"End of Backtrace.\n");
2827+ free(btfuncs);
2828+ exit(1);
2829+ #endif
2830+ break;
2831+ }
2832+}
2833+#endif
2834+
2835+int new_g15_screen(int screentype)
2836+{
2837+ struct sigaction new_sigaction;
2838+ int g15screen_fd;
2839+ struct sockaddr_in serv_addr;
2840+ static int sighandler_init=0;
2841+ /* raise the priority of our packets */
2842+ int tos = 0x6;
2843+
2844+ char buffer[256];
2845+ if(sighandler_init==0) {
2846+#ifdef HAVE_BACKTRACE
2847+ new_sigaction.sa_handler = g15_sighandler;
2848+ new_sigaction.sa_flags = 0;
2849+ sigaction(SIGSEGV,&new_sigaction,NULL);
2850+#endif
2851+ sighandler_init=1;
2852+ }
2853+
2854+ g15screen_fd = socket(AF_INET, SOCK_STREAM, 0);
2855+ if (g15screen_fd < 0)
2856+ return -1;
2857+
2858+ memset(&serv_addr, 0, sizeof(serv_addr));
2859+ serv_addr.sin_family = AF_INET;
2860+ inet_aton (G15SERVER_ADDR, &serv_addr.sin_addr);
2861+ serv_addr.sin_port = htons(G15SERVER_PORT);
2862+
2863+ if (connect(g15screen_fd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
2864+ return -1;
2865+
2866+ setsockopt(g15screen_fd, SOL_SOCKET, SO_PRIORITY, &tos, sizeof(tos));
2867+
2868+ if (fcntl(g15screen_fd, F_SETFL, O_NONBLOCK) <0 ) {
2869+ }
2870+
2871+ memset(buffer,0,256);
2872+ if(g15_recv(g15screen_fd, buffer, 16)<0)
2873+ return -1;
2874+
2875+ /* here we check that we're really talking to the g15daemon */
2876+ if(strcmp(buffer,"G15 daemon HELLO") != 0)
2877+ return -1;
2878+ if(screentype == G15_TEXTBUF) /* txt buffer - not supported yet */
2879+ g15_send(g15screen_fd,"TBUF",4);
2880+ else if(screentype == G15_WBMPBUF) /* wbmp buffer */
2881+ g15_send(g15screen_fd,"WBUF",4);
2882+ else if(screentype == G15_G15RBUF)
2883+ g15_send(g15screen_fd,"RBUF",4);
2884+ else
2885+ g15_send(g15screen_fd,"GBUF",4);
2886+
2887+ return g15screen_fd;
2888+}
2889+
2890+int g15_close_screen(int sock)
2891+{
2892+ return close(sock);
2893+}
2894+
2895+int g15_send(int sock, char *buf, unsigned int len)
2896+{
2897+ int total = 0;
2898+ int retval = 0;
2899+ int bytesleft = len;
2900+ struct pollfd pfd[1];
2901+
2902+ while(total < len && !leaving) {
2903+ memset(pfd,0,sizeof(pfd));
2904+ pfd[0].fd = sock;
2905+ pfd[0].events = POLLOUT|POLLERR|POLLHUP|POLLNVAL;
2906+ if(poll(pfd,1,500)>=0) {
2907+ if(pfd[0].revents & POLLOUT && !(pfd[0].revents & POLLERR || pfd[0].revents & POLLHUP || pfd[0].revents & POLLNVAL) ) {
2908+ retval = send(sock, buf+total, bytesleft, MSG_DONTWAIT);
2909+ if (retval == -1) {
2910+ break;
2911+ }
2912+ bytesleft -= retval;
2913+ total += retval;
2914+ }
2915+ if((pfd[0].revents & POLLERR|| pfd[0].revents & POLLHUP || pfd[0].revents & POLLNVAL)){
2916+ retval=-1;
2917+ break;
2918+ }
2919+ }
2920+ }
2921+ return retval==-1?-1:0;
2922+}
2923+
2924+int g15_recv(int sock, char *buf, unsigned int len)
2925+{
2926+ int total = 0;
2927+ int retval = 0;
2928+ int bytesleft = len;
2929+ struct pollfd pfd[1];
2930+
2931+ while(total < len && !leaving) {
2932+ memset(pfd,0,sizeof(pfd));
2933+ pfd[0].fd = sock;
2934+ pfd[0].events = POLLIN;
2935+ if(poll(pfd,1,500)>0){
2936+ if(pfd[0].revents & POLLIN) {
2937+ retval = recv(sock, buf+total, bytesleft, 0);
2938+ if (retval < 1) {
2939+ break;
2940+ }
2941+ total += retval;
2942+ bytesleft -= retval;
2943+ }
2944+ }
2945+ }
2946+ return total;
2947+}
2948+
2949+/* receive a byte from a priority, out-of-band packet */
2950+int g15_recv_oob_answer(int sock) {
2951+ int packet[2];
2952+ int msgret = 0;
2953+ struct pollfd pfd[1];
2954+ memset(pfd,0,sizeof(pfd));
2955+ memset(packet,0,2);
2956+ pfd[0].fd = sock;
2957+ pfd[0].events = POLLPRI | POLLERR | POLLHUP | POLLNVAL;
2958+
2959+ if(poll(pfd,1,100)>0){
2960+ if(pfd[0].revents & POLLPRI && !(pfd[0].revents & POLLERR || pfd[0].revents & POLLHUP || pfd[0].revents & POLLNVAL)) {
2961+ memset(packet,0,sizeof(packet));
2962+ msgret = recv(sock, packet, 10 , MSG_OOB);
2963+ if (msgret < 1) {
2964+ return -1;
2965+ }
2966+ }
2967+ }
2968+ return packet[0];
2969+}
2970+
2971+unsigned long g15_send_cmd (int sock, unsigned char command, unsigned char value)
2972+{
2973+ int retval;
2974+ unsigned char packet[2];
2975+
2976+ switch (command) {
2977+ case G15DAEMON_KEY_HANDLER:
2978+ if (value > G15_LED_MR)
2979+ value = G15_LED_MR;
2980+ packet[0] = (unsigned char)command | (unsigned char)value;
2981+ retval = send( sock, packet, 1, MSG_OOB );
2982+ break;
2983+ case G15DAEMON_CONTRAST:
2984+ if (value > G15_CONTRAST_HIGH)
2985+ value = G15_CONTRAST_HIGH;
2986+ packet[0] = (unsigned char)command | (unsigned char)value;
2987+ send( sock, packet, 1, MSG_OOB );
2988+ retval = g15_recv_oob_answer(sock);
2989+ break;
2990+ case G15DAEMON_BACKLIGHT:
2991+ if (value > G15_BRIGHTNESS_BRIGHT)
2992+ value = G15_BRIGHTNESS_BRIGHT;
2993+ packet[0] = (unsigned char)command | (unsigned char)value;
2994+ send( sock, packet, 1, MSG_OOB );
2995+ retval = g15_recv_oob_answer(sock);
2996+ break;
2997+ case G15DAEMON_KB_BACKLIGHT:
2998+ if (value > G15_BRIGHTNESS_BRIGHT)
2999+ value = G15_BRIGHTNESS_BRIGHT;
3000+ packet[0] = (unsigned char)command | (unsigned char)value;
3001+ retval = send( sock, packet, 1, MSG_OOB );
3002+ break;
3003+ case G15DAEMON_MKEYLEDS:
3004+ packet[0] = (unsigned char)command|(unsigned char)value;
3005+ retval = send( sock, packet, 1, MSG_OOB );
3006+ break;
3007+ case G15DAEMON_SWITCH_PRIORITIES:
3008+ packet[0] = (unsigned char)command;
3009+ retval = send( sock, packet, 1, MSG_OOB );
3010+ break;
3011+ case G15DAEMON_NEVER_SELECT:
3012+ packet[0] = (unsigned char)command;
3013+ retval = send( sock, packet, 1, MSG_OOB );
3014+ break;
3015+ case G15DAEMON_GET_KEYSTATE:{
3016+ retval = 0;
3017+ unsigned long keystate = 0;
3018+ g15_recv(sock, (char*)&keystate, sizeof(keystate));
3019+ return keystate;
3020+ break;
3021+ }
3022+ case G15DAEMON_IS_FOREGROUND:{
3023+ packet[0] = (unsigned char)command;
3024+ send( sock, packet, 1, MSG_OOB );
3025+ retval = g15_recv_oob_answer(sock) - 48;
3026+ break;
3027+ }
3028+ case G15DAEMON_IS_USER_SELECTED:{
3029+ packet[0] = (unsigned char)command;
3030+ send( sock, packet, 1, MSG_OOB );
3031+ retval = g15_recv_oob_answer(sock);
3032+ break;
3033+ }
3034+ default:
3035+ return -1;
3036+ }
3037+ usleep(1000);
3038+ return retval;
3039+}
3040
3041=== added directory '.pc/07-reinit-on-any-error.diff'
3042=== added directory '.pc/07-reinit-on-any-error.diff/g15daemon'
3043=== added file '.pc/07-reinit-on-any-error.diff/g15daemon/main.c'
3044--- .pc/07-reinit-on-any-error.diff/g15daemon/main.c 1970-01-01 00:00:00 +0000
3045+++ .pc/07-reinit-on-any-error.diff/g15daemon/main.c 2015-05-21 10:27:39 +0000
3046@@ -0,0 +1,580 @@
3047+/*
3048+ This file is part of g15daemon.
3049+
3050+ g15daemon is free software; you can redistribute it and/or modify
3051+ it under the terms of the GNU General Public License as published by
3052+ the Free Software Foundation; either version 2 of the License, or
3053+ (at your option) any later version.
3054+
3055+ g15daemon is distributed in the hope that it will be useful,
3056+ but WITHOUT ANY WARRANTY; without even the implied warranty of
3057+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3058+ GNU General Public License for more details.
3059+
3060+ You should have received a copy of the GNU General Public License
3061+ along with g15daemon; if not, write to the Free Software
3062+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
3063+
3064+ (c) 2006-2008 Mike Lampard, Philip Lawatsch, and others
3065+
3066+ $Revision: 457 $ - $Date: 2008-01-31 15:32:46 +1030 (Thu, 31 Jan 2008) $ $Author: mlampard $
3067+
3068+ This daemon listens on localhost port 15550 for client connections,
3069+ and arbitrates LCD display. Allows for multiple simultaneous clients.
3070+ Client screens can be cycled through by pressing the 'L1' key.
3071+*/
3072+
3073+#include <pthread.h>
3074+#include <stdio.h>
3075+#include <stdlib.h>
3076+#include <signal.h>
3077+#include <errno.h>
3078+#include <string.h>
3079+#include <sys/types.h>
3080+#include <sys/socket.h>
3081+#include <sys/stat.h>
3082+#include <sys/time.h>
3083+#include <fcntl.h>
3084+#include <unistd.h>
3085+#include <pwd.h>
3086+#include <ctype.h>
3087+
3088+#include <config.h>
3089+#include <libg15.h>
3090+#include <libg15render.h>
3091+#include "g15daemon.h"
3092+
3093+#ifndef LIBG15_VERSION
3094+#define LIBG15_VERSION 1000
3095+#endif
3096+
3097+/* all threads will exit if leaving >0 */
3098+volatile int leaving = 0;
3099+int keyboard_backlight_off_onexit = 0;
3100+unsigned int g15daemon_debug = 0;
3101+unsigned int cycle_key;
3102+unsigned int client_handles_keys = 0;
3103+static unsigned int set_backlight = 0;
3104+struct lcd_t *keyhandler = NULL;
3105+
3106+static int loaded_plugins = 0;
3107+
3108+/* send event to foreground client's eventlistener */
3109+int g15daemon_send_event(void *caller, unsigned int event, unsigned long value)
3110+{
3111+ switch(event) {
3112+ case G15_EVENT_KEYPRESS: {
3113+ static unsigned long lastkeys;
3114+ if(!(value & cycle_key) && !(lastkeys & cycle_key)){
3115+ lcd_t *lcd = (lcd_t*)caller;
3116+
3117+ if(!lcd->g15plugin->info)
3118+ break;
3119+
3120+ int *(*plugin_listener)(plugin_event_t *newevent) = (void*)lcd->g15plugin->info->event_handler;
3121+ plugin_event_t *newevent=g15daemon_xmalloc(sizeof(plugin_event_t));
3122+ newevent->event = event;
3123+ newevent->value = value;
3124+ newevent->lcd = lcd;
3125+ (*plugin_listener)((void*)newevent);
3126+ /* hack - keyboard events are always sent from the foreground even when they aren't
3127+ send keypress event to the OS keyboard_handler plugin */
3128+ if(lcd->masterlist->keyboard_handler != NULL && lcd->masterlist->remote_keyhandler_sock==0) {
3129+ int *(*keyboard_handler)(plugin_event_t *newevent) = (void*)lcd->masterlist->keyboard_handler;
3130+ (*keyboard_handler)((void*)newevent);
3131+ }
3132+ // if we have a remote keyhandler, send the key. FIXME: we should do this from the net plugin
3133+ if(lcd->masterlist->remote_keyhandler_sock!=0) {
3134+ if((send(lcd->masterlist->remote_keyhandler_sock,(void *)&newevent->value,sizeof(newevent->value),0))<0)
3135+ g15daemon_log(LOG_WARNING,"Error in send: %s\n",strerror(errno));
3136+ }
3137+ if(value & G15_KEY_LIGHT){ // the backlight key was pressed - maintain user-selected state
3138+ lcd_t *displaying = lcd->masterlist->current->lcd;
3139+ lcd->masterlist->kb_backlight_state++;
3140+ lcd->masterlist->kb_backlight_state %= 3;
3141+ displaying->backlight_state++;
3142+ displaying->backlight_state %= 3; // limit to 0-2 inclusive
3143+ }
3144+ if(value & G15_KEY_M1 && value & G15_KEY_M3) {
3145+ static int scr_num=0;
3146+ char filename[128];
3147+ lcd_t *displaying = lcd->masterlist->current->lcd;
3148+ sprintf(filename,"/tmp/g15daemon-sc-%i.pbm",scr_num);
3149+ uf_screendump_pbm(displaying->buf,filename);
3150+ scr_num++;
3151+ }
3152+ free(newevent);
3153+ }else{
3154+ /* hacky attempt to double-time the use of L1, if the key is pressed less than half a second, it cycles the screens. If held for longer, the key is sent to the application for use instead */
3155+ lcd_t *lcd = (lcd_t*)caller;
3156+ g15daemon_t* masterlist = lcd->masterlist;
3157+ static unsigned int clicktime;
3158+
3159+ if(value & cycle_key) {
3160+ clicktime=g15daemon_gettime_ms();
3161+ }else{
3162+ unsigned int unclick=g15daemon_gettime_ms();
3163+ if ((unclick-clicktime)<500) {
3164+ g15daemon_lcdnode_cycle(masterlist);
3165+ }
3166+ else
3167+ {
3168+ plugin_event_t *clickevent=g15daemon_xmalloc(sizeof(plugin_event_t));
3169+ int *(*plugin_listener)(plugin_event_t *clickevent) = (void*)lcd->g15plugin->info->event_handler;
3170+ clickevent->event = event;
3171+ clickevent->value = value|cycle_key;
3172+ clickevent->lcd = lcd;
3173+ (*plugin_listener)((void*)clickevent);
3174+ clickevent->event = event;
3175+ clickevent->value = value&~cycle_key;
3176+ clickevent->lcd = lcd;
3177+ (*plugin_listener)((void*)clickevent);
3178+ free(clickevent);
3179+ }
3180+ }
3181+ }
3182+ lastkeys = value;
3183+ break;
3184+ }
3185+ case G15_EVENT_CYCLE_PRIORITY:{
3186+ lcd_t *lcd = (lcd_t*)caller;
3187+ g15daemon_t* masterlist = lcd->masterlist;
3188+ if(value)
3189+ g15daemon_lcdnode_cycle(masterlist);
3190+ break;
3191+ }
3192+ case G15_EVENT_REQ_PRIORITY: {
3193+ lcdnode_t *lcdnode=(lcdnode_t*)caller;
3194+ /* client wants to switch priorities */
3195+ pthread_mutex_lock(&lcdlist_mutex);
3196+ if(lcdnode->list->current != lcdnode){
3197+ lcdnode->last_priority = lcdnode->list->current;
3198+ lcdnode->list->current = lcdnode;
3199+ }
3200+ else {
3201+ if(lcdnode->list->current == lcdnode->last_priority){
3202+ lcdnode->list->current = lcdnode->list->current->prev;
3203+ } else{
3204+ if(lcdnode->last_priority != NULL) {
3205+ lcdnode->list->current = lcdnode->last_priority;
3206+ lcdnode->last_priority = NULL;
3207+ }
3208+ else
3209+ lcdnode->list->current = lcdnode->list->current->prev;
3210+ }
3211+ }
3212+ pthread_mutex_unlock(&lcdlist_mutex);
3213+ g15daemon_send_refresh((lcd_t*)lcdnode->list->current->lcd);
3214+ break;
3215+ }
3216+ case G15_EVENT_VISIBILITY_CHANGED:
3217+ g15daemon_send_refresh((lcd_t*)caller);
3218+ default: {
3219+ lcd_t *lcd = (lcd_t*)caller;
3220+ int *(*plugin_listener)(plugin_event_t *newevent) = (void*)lcd->g15plugin->info->event_handler;
3221+ plugin_event_t *newevent=g15daemon_xmalloc(sizeof(plugin_event_t));
3222+ newevent->event = event;
3223+ newevent->value = value;
3224+ newevent->lcd = lcd;
3225+ (*plugin_listener)((void*)newevent);
3226+ free(newevent);
3227+ }
3228+ }
3229+ return 0;
3230+}
3231+
3232+static void *keyboard_watch_thread(void *lcdlist){
3233+
3234+ g15daemon_t *masterlist = (g15daemon_t*)(lcdlist);
3235+
3236+ unsigned int keypresses = 0;
3237+ int retval = 0;
3238+ static int lastkeys = 0;
3239+
3240+ while (!leaving) {
3241+
3242+ retval = uf_read_keypresses(&keypresses, 20);
3243+ /* every 2nd packet contains the codes we want.. immediately try again */
3244+ while (retval == G15_ERROR_TRY_AGAIN){
3245+ retval = uf_read_keypresses(&keypresses, 20);
3246+ }
3247+
3248+ if(retval == G15_NO_ERROR && lastkeys != keypresses) {
3249+ g15daemon_send_event(masterlist->current->lcd,
3250+ G15_EVENT_KEYPRESS, keypresses);
3251+ lastkeys = keypresses;
3252+
3253+ }else if(retval == -ENODEV && LIBG15_VERSION>=1200) {
3254+ pthread_mutex_lock(&g15lib_mutex);
3255+ while((retval=re_initLibG15() != G15_NO_ERROR) && !leaving){
3256+ g15daemon_log(LOG_WARNING,"Keyboard has gone.. Retrying\n");
3257+ sleep(1);
3258+ }
3259+ if(!leaving) {
3260+ masterlist->current->lcd->state_changed=1;
3261+ g15daemon_send_refresh(masterlist->current->lcd);
3262+ }
3263+ pthread_mutex_unlock(&g15lib_mutex);
3264+ }
3265+ g15daemon_msleep(40);
3266+ }
3267+ return NULL;
3268+}
3269+
3270+static void *lcd_draw_thread(void *lcdlist){
3271+
3272+ g15daemon_t *masterlist = (g15daemon_t*)(lcdlist);
3273+ /* unsigned int fps = 0; */
3274+ lcd_t *displaying = masterlist->tail->lcd;
3275+ memset(displaying->buf,0,1024);
3276+ static int prev_state=0;
3277+ g15daemon_sleep(2);
3278+
3279+ while (!leaving) {
3280+ /* wait until a client has updated */
3281+ g15daemon_wait_refresh();
3282+
3283+ pthread_mutex_lock(&lcdlist_mutex);
3284+ displaying = masterlist->current->lcd;
3285+
3286+ /* monitor 'fps' - due to the TCP protocol, some frames will be bunched up.
3287+ discard excess to reduce load on the bus */
3288+ /* fps = 1000 / (g15daemon_gettime_ms() - lastscreentime); */
3289+ /* if the current screen is less than 20ms from the previous (equivelant to 50fps) delay it */
3290+ /* this allows a real-world fps of 40fps with no almost frame loss and reduces peak usb bus-load */
3291+
3292+ g15daemon_log(LOG_DEBUG,"Updating LCD");
3293+ uf_write_buf_to_g15(displaying);
3294+ g15daemon_log(LOG_DEBUG,"LCD Update Complete");
3295+
3296+ if(prev_state!=displaying->backlight_state && set_backlight!=0) {
3297+ prev_state=displaying->backlight_state;
3298+ pthread_mutex_lock(&g15lib_mutex);
3299+ setLCDBrightness(displaying->backlight_state);
3300+ usleep(5);
3301+ setLCDBrightness(displaying->backlight_state);
3302+ setKBBrightness(displaying->backlight_state);
3303+ pthread_mutex_unlock(&g15lib_mutex);
3304+ }
3305+
3306+ if(displaying->state_changed){
3307+ pthread_mutex_lock(&g15lib_mutex);
3308+ setLCDContrast(displaying->contrast_state);
3309+ if(displaying->masterlist->remote_keyhandler_sock==0) // only allow mled control if the macro recorder isnt running
3310+ setLEDs(displaying->mkey_state);
3311+ pthread_mutex_unlock(&g15lib_mutex);
3312+ displaying->state_changed = 0;
3313+ }
3314+
3315+ pthread_mutex_unlock(&lcdlist_mutex);
3316+ }
3317+ return NULL;
3318+}
3319+
3320+void g15daemon_sighandler(int sig) {
3321+ switch(sig){
3322+ case SIGUSR1:
3323+ keyboard_backlight_off_onexit = 1;
3324+ case SIGINT:
3325+ case SIGTERM:
3326+ case SIGQUIT:
3327+ leaving = 1;
3328+ break;
3329+ case SIGPIPE:
3330+ break;
3331+ }
3332+}
3333+
3334+#ifndef HAVE_DAEMON
3335+/* daemon() is not posix compliant, so we roll our own if needed.*/
3336+int daemon(int nochdir, int noclose) {
3337+ pid_t pid;
3338+
3339+ if(nochdir<1)
3340+ chdir("/");
3341+ pid = fork();
3342+
3343+ switch(pid){
3344+ case -1:
3345+ printf("Unable to daemonise!\n");
3346+ return -1;
3347+ break;
3348+ case 0: {
3349+ umask(0);
3350+ if(setsid()==-1) {
3351+ perror("setsid");
3352+ return -1;
3353+ }
3354+ if(noclose<1) {
3355+ freopen( "/dev/null", "r", stdin);
3356+ freopen( "/dev/null", "w", stdout);
3357+ freopen( "/dev/null", "w", stderr);
3358+ }
3359+ break;
3360+ }
3361+ default:
3362+ _exit(0);
3363+ }
3364+ return 0;
3365+}
3366+#endif
3367+
3368+int main (int argc, char *argv[])
3369+{
3370+ pid_t daemonpid;
3371+ int retval;
3372+ int i;
3373+ int cycle_cmdline_override=0;
3374+ struct sigaction new_action;
3375+ cycle_key = G15_KEY_L1;
3376+ unsigned char user[256];
3377+ unsigned int lcdlevel = 1;
3378+
3379+ pthread_t keyboard_thread;
3380+ pthread_t lcd_thread;
3381+ memset(user,0,256);
3382+
3383+ for (i=0;i<argc;i++) {
3384+ char daemonargs[20];
3385+ memset(daemonargs,0,20);
3386+ strncpy(daemonargs,argv[i],19);
3387+ if (!strncmp(daemonargs, "-k",2) || !strncmp(daemonargs, "--kill",6)) {
3388+ daemonpid = uf_return_running();
3389+ if(daemonpid>0) {
3390+ kill(daemonpid,SIGINT);
3391+ } else
3392+ printf("G15Daemon not running\n");
3393+ exit(0);
3394+ }
3395+ if (!strncmp(daemonargs, "-K",2) || !strncmp(daemonargs, "--KILL",6)) {
3396+ daemonpid = uf_return_running();
3397+ if(daemonpid>0) {
3398+ kill(daemonpid,SIGUSR1);
3399+ } else
3400+ printf("G15Daemon not running\n");
3401+ exit(0);
3402+ }
3403+ if (!strncmp(daemonargs, "-v",2) || !strncmp(daemonargs, "--version",9)) {
3404+ float lg15ver = LIBG15_VERSION;
3405+ printf("G15Daemon version %s - %s\n",VERSION,uf_return_running() >= 0 ?"Loaded & Running":"Not Running");
3406+ printf("compiled with libg15 version %.3f\n\n",lg15ver/1000);
3407+ exit(0);
3408+ }
3409+
3410+ if (!strncmp(daemonargs, "-h",2) || !strncmp(daemonargs, "--help",6)) {
3411+ printf("G15Daemon version %s - %s\n",VERSION,uf_return_running() >= 0 ?"Loaded & Running":"Not Running");
3412+ printf("%s -h (--help) or -k (--kill) or -s (--switch) or -d (--debug) [level] or -v (--version) or -l (--lcdlevel) [0-2] \n\n -k\twill kill a previous incarnation",argv[0]);
3413+ #ifdef LIBG15_VERSION
3414+ #if LIBG15_VERSION >= 1200
3415+ printf("\n -K\tturn off the keyboard backlight on the way out.");
3416+ #endif
3417+ #endif
3418+ printf("\n -h\tshows this help\n -s\tchanges the screen-switch key from L1 to MR (beware)\n -d\tdebug mode - stay in foreground and output all debug messages to STDERR\n -v\tshow version\n -l\tset default LCD backlight level\n");
3419+ printf(" --set-backlight sets backlight individually for currently shown screen.\n\t\tDefault is to set backlight globally (keyboard default).\n");
3420+ exit(0);
3421+ }
3422+
3423+ if (!strncmp(daemonargs, "-s",2) || !strncmp(daemonargs, "--switch",8)) {
3424+ cycle_key = G15_KEY_MR;
3425+ cycle_cmdline_override=1;
3426+ }
3427+
3428+ if (!strncmp(daemonargs, "--set-backlight",15)) {
3429+ set_backlight = 1;
3430+ }
3431+
3432+ if (!strncmp(daemonargs, "-d",2) || !strncmp(daemonargs, "--debug",7)) {
3433+ g15daemon_debug = 1;
3434+ if((argv[i+1])!=NULL)
3435+ if(isdigit(argv[i+1][0])){
3436+ g15daemon_debug = atoi(argv[i+1]);
3437+ if(g15daemon_debug==0) g15daemon_debug = 1;
3438+ }
3439+ }
3440+
3441+ if (!strncmp(daemonargs, "-u",2) || !strncmp(daemonargs, "--user",7)) {
3442+ if(argv[i+1]!=NULL){
3443+ strncpy((char*)user,argv[i+1],128);
3444+ i++;
3445+ }
3446+ }
3447+
3448+ if (!strncmp(daemonargs, "-l",2) || !strncmp(daemonargs, "--lcdlevel",7)) {
3449+ if((argv[i+1])!=NULL)
3450+ if(isdigit(argv[i+1][0])){
3451+ lcdlevel = atoi(argv[i+1]);
3452+ }
3453+ }
3454+ }
3455+ if(g15daemon_debug){
3456+ g15daemon_log(LOG_INFO, "G15Daemon %s Build Date: %s",PACKAGE_VERSION,BUILD_DATE);
3457+ g15daemon_log(LOG_DEBUG, "Build OS: %s",BUILD_OS_NAME);
3458+ g15daemon_log(LOG_DEBUG, "With compiler: %s",COMPILER_VERSION);
3459+ fprintf(stderr, "G15Daemon CMDLINE ARGS: ");
3460+ for(i=1;i<argc;i++)
3461+ fprintf(stderr, "%s ",argv[i]);
3462+ fprintf(stderr,"\n");
3463+ }
3464+ if(uf_return_running()>=0) {
3465+ g15daemon_log(LOG_ERR,"G15Daemon already running.. Exiting");
3466+ exit(0);
3467+ }
3468+
3469+ /* set libg15 debugging to our debug setting */
3470+ if(LIBG15_VERSION>=1200)
3471+ libg15Debug(g15daemon_debug);
3472+
3473+#ifdef OSTYPE_DARWIN
3474+ /* OS X: load codeless kext */
3475+ retval = system("/sbin/kextload " "/System/Library/Extensions/libusbshield.kext");
3476+
3477+ if (WIFEXITED(retval)){
3478+ if (WEXITSTATUS(retval) !=0){
3479+ g15daemon_log(LOG_ERR,"Unable to load USB shield kext...exiting");
3480+ exit(1);
3481+ }
3482+ } else {
3483+ g15daemon_log(LOG_ERR,"Unable to launch kextload...exiting");
3484+ exit(1);
3485+ }
3486+#endif
3487+
3488+ /* init stuff here.. */
3489+ if((retval=initLibG15())!=G15_NO_ERROR){
3490+ g15daemon_log(LOG_ERR,"Unable to attach to the G15 Keyboard... exiting");
3491+ exit(1);
3492+ }
3493+
3494+ if(!g15daemon_debug)
3495+ daemon(0,0);
3496+
3497+ if(uf_create_pidfile() == 0) {
3498+
3499+ g15daemon_t *lcdlist;
3500+ config_section_t *global_cfg=NULL;
3501+ pthread_attr_t attr;
3502+ struct passwd *nobody;
3503+ unsigned char location[1024];
3504+
3505+ openlog("g15daemon", LOG_PID, LOG_DAEMON);
3506+ if(strlen((char*)user)==0){
3507+ nobody = getpwnam("nobody");
3508+ }else {
3509+ nobody = getpwnam((char*)user);
3510+ }
3511+ if (nobody==NULL)
3512+ {
3513+ nobody = getpwuid(geteuid());
3514+ g15daemon_log(LOG_WARNING,"BEWARE: running as effective uid %i\n",nobody->pw_uid);
3515+ }
3516+
3517+ /* initialise the linked list */
3518+ lcdlist = ll_lcdlist_init();
3519+ lcdlist->nobody = nobody;
3520+
3521+ setLCDContrast(1);
3522+ setLEDs(0);
3523+ lcdlist->kb_backlight_state=1;
3524+ lcdlist->current->lcd->backlight_state=lcdlevel;
3525+ setLCDBrightness(lcdlevel);
3526+
3527+#ifdef LIBG15_VERSION
3528+#if LIBG15_VERSION >= 1200
3529+ setKBBrightness(lcdlist->kb_backlight_state);
3530+#endif
3531+#endif
3532+
3533+ uf_conf_open(lcdlist, "/etc/g15daemon.conf");
3534+ global_cfg=g15daemon_cfg_load_section(lcdlist,"Global");
3535+ if(!cycle_cmdline_override){
3536+ cycle_key = 1==g15daemon_cfg_read_bool(global_cfg,"Use MR as Cycle Key",0)?G15_KEY_MR:G15_KEY_L1;
3537+ }
3538+
3539+#ifndef OSTYPE_SOLARIS
3540+ /* all other processes/threads should be seteuid nobody */
3541+ if(nobody!=NULL) {
3542+ seteuid(nobody->pw_uid);
3543+ setegid(nobody->pw_gid);
3544+ }
3545+#endif
3546+ /* initialise the pthread condition for the LCD thread */
3547+ g15daemon_init_refresh();
3548+ pthread_mutex_init(&g15lib_mutex, NULL);
3549+ pthread_attr_init(&attr);
3550+
3551+ pthread_attr_setstacksize(&attr,512*1024); /* set stack to 512k - dont need 8Mb !! */
3552+ if (pthread_create(&keyboard_thread, &attr, keyboard_watch_thread, lcdlist) != 0) {
3553+ g15daemon_log(LOG_ERR,"Unable to create keyboard listener thread. Exiting");
3554+ goto exitnow;
3555+ }
3556+
3557+ pthread_attr_setstacksize(&attr,128*1024);
3558+
3559+ if (pthread_create(&lcd_thread, &attr, lcd_draw_thread, lcdlist) != 0) {
3560+ g15daemon_log(LOG_ERR,"Unable to create display thread. Exiting");
3561+ goto exitnow;
3562+ }
3563+ g15daemon_log(LOG_INFO,"%s loaded\n",PACKAGE_STRING);
3564+
3565+ snprintf((char*)location,1024,"%s/%s",DATADIR,"g15daemon/splash/g15logo2.wbmp");
3566+ g15canvas *canvas = (g15canvas *)g15daemon_xmalloc (sizeof (g15canvas));
3567+ memset (canvas->buffer, 0, G15_BUFFER_LEN);
3568+ canvas->mode_cache = 0;
3569+ canvas->mode_reverse = 0;
3570+ canvas->mode_xor = 0;
3571+ g15r_loadWbmpSplash(canvas,(char*)location);
3572+ memcpy (lcdlist->tail->lcd->buf, canvas->buffer, G15_BUFFER_LEN);
3573+ free (canvas);
3574+ uf_write_buf_to_g15(lcdlist->tail->lcd);
3575+
3576+ snprintf((char*)location,1024,"%s",PLUGINDIR);
3577+
3578+ loaded_plugins = g15_open_all_plugins(lcdlist,(char*)location);
3579+
3580+ new_action.sa_handler = g15daemon_sighandler;
3581+ new_action.sa_flags = 0;
3582+ sigaction(SIGINT, &new_action, NULL);
3583+ sigaction(SIGQUIT, &new_action, NULL);
3584+ sigaction(SIGTERM, &new_action, NULL);
3585+ sigaction(SIGUSR1, &new_action, NULL);
3586+
3587+ do {
3588+ pause();
3589+ } while( leaving == 0);
3590+
3591+ g15daemon_log(LOG_INFO,"Leaving by request");
3592+
3593+ pthread_join(lcd_thread,NULL);
3594+ pthread_join(keyboard_thread,NULL);
3595+ /* switch off the lcd backlight */
3596+ char *blank=g15daemon_xmalloc(G15_BUFFER_LEN);
3597+ writePixmapToLCD((unsigned char*)blank);
3598+ free(blank);
3599+ setLCDBrightness(0);
3600+#ifdef LIBG15_VERSION
3601+#if LIBG15_VERSION >= 1200
3602+ /* if SIGUSR1 was sent to kill us, switch off the keyboard backlight as well */
3603+ if(keyboard_backlight_off_onexit==1)
3604+ setKBBrightness(0);
3605+#endif
3606+#endif
3607+
3608+#ifdef LIBG15_VERSION
3609+#if LIBG15_VERSION >= 1100
3610+ exitLibG15();
3611+#endif
3612+#endif
3613+ ll_lcdlist_destroy(&lcdlist);
3614+
3615+exitnow:
3616+ /* return to root privilages for the final countdown */
3617+ seteuid(0);
3618+ setegid(0);
3619+ closelog();
3620+ g15daemon_quit_refresh();
3621+ uf_conf_write(lcdlist,"/etc/g15daemon.conf");
3622+ uf_conf_free(lcdlist);
3623+ unlink("/var/run/g15daemon.pid");
3624+ }
3625+ return 0;
3626+}
3627
3628=== added file '.pc/applied-patches'
3629--- .pc/applied-patches 1970-01-01 00:00:00 +0000
3630+++ .pc/applied-patches 2015-05-21 10:27:39 +0000
3631@@ -0,0 +1,7 @@
3632+01-remove-x11-setup-from-man.diff
3633+02-better-screenshort-creation.diff
3634+03-change-syslog-facility.diff
3635+04-open-needs-mode.diff
3636+05-send-a-sync-event-after-key-up-down.diff
3637+06-fix-buffer-overflow.diff
3638+07-reinit-on-any-error.diff
3639
3640=== modified file 'debian/changelog'
3641--- debian/changelog 2014-05-20 02:13:35 +0000
3642+++ debian/changelog 2015-05-21 10:27:39 +0000
3643@@ -1,3 +1,30 @@
3644+g15daemon (1.9.5.3-8.3ubuntu1ppa2) UNRELEASED; urgency=medium
3645+
3646+ * debian/g15daemon.service: Added documantation link.
3647+
3648+ -- Alexander Ponyatykh <lazyranma@gmail.com> Thu, 21 May 2015 12:41:54 +0300
3649+
3650+g15daemon (1.9.5.3-8.3ubuntu1ppa1) wily; urgency=medium
3651+
3652+ * Converted source to 3.0 (quilt) format.
3653+ * debian/g15daemon.init: Replaced /dev/input/uinput with /dev/uinput
3654+ (related to LP #617101).
3655+ * debian/docs: removed obsolete file.
3656+ * Do not fail package installation/removal if g15daemon fails to start/stop
3657+ (LP: #617101, LP: #1103275).
3658+ * debian/g15daemon.init: added dependency on $remote_fs
3659+ * debian/g15daemon.init: now sources /lib/lsb/init-functions
3660+ * Added debian/patches/07-reinit-on-any-error.diff: reinitialize on any
3661+ error returned by libusb to correctly recover after suspend/resume.
3662+ (LP: #1357556)
3663+ * debian/control: removed dependency on libg15daemon-client1 for g15daemon
3664+ * debian/control: changed priority of g15daemon to optional
3665+ * Added native upstart job and systemd service. (LP: #1441365)
3666+ * debian/g15daemon.default: removed SWITCH_KEY option to keep systemd and
3667+ upstart scripts simple.
3668+
3669+ -- Alexander Ponyatykh <lazyranma@gmail.com> Thu, 21 May 2015 11:16:21 +0300
3670+
3671 g15daemon (1.9.5.3-8.3ubuntu1) utopic; urgency=medium
3672
3673 * Merge from Debian unstable. Remaining changes:
3674
3675=== modified file 'debian/control'
3676--- debian/control 2014-05-20 02:13:35 +0000
3677+++ debian/control 2015-05-21 10:27:39 +0000
3678@@ -1,18 +1,19 @@
3679 Source: g15daemon
3680 Section: utils
3681-Priority: extra
3682+Priority: optional
3683 Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
3684 XSBC-Original-Maintainer: Giacomo Catenazzi <cate@debian.org>
3685 Build-Depends: cdbs, debhelper (>= 5), dh-autoreconf, libtool, chrpath,
3686 libg15-dev, libg15render-dev (>=1.2.0.svn250-2), libusb-dev, libfreetype6-dev
3687-Standards-Version: 3.8.2
3688+Standards-Version: 3.9.6
3689 Homepage: http://www.g15tools.com/
3690
3691 Package: g15daemon
3692 Section: utils
3693 Architecture: any
3694-Depends: libg15daemon-client1 (=${binary:Version}), ${shlibs:Depends}, ${misc:Depends},
3695-Recommends: xkb-data ( >= 0.9+cvs.20070428-1)
3696+Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base (>= 4.1+Debian3),
3697+ sysv-rc (>= 2.88dsf-24)
3698+Recommends: xkb-data ( >= 0.9+cvs.20070428-1), udev
3699 Description: Screen multiplexer for Logitech G15 Keyboard
3700 G15daemon provides multiple virtual screens for the LCD on the Logitech
3701 G11 and G15 keyboards.
3702@@ -22,7 +23,6 @@
3703
3704 Package: libg15daemon-client1
3705 Section: libs
3706-Priority: optional
3707 Architecture: any
3708 Depends: ${shlibs:Depends}, ${misc:Depends}
3709 Description: Development packages for libg15daemon-client
3710@@ -30,6 +30,7 @@
3711
3712 Package: libg15daemon-client-dev
3713 Section: libdevel
3714+Priority: extra
3715 Architecture: any
3716 Depends: libg15daemon-client1 (= ${binary:Version}), ${misc:Depends}
3717 Description: Development packages for libg15daemon-client
3718
3719=== removed file 'debian/docs'
3720--- debian/docs 2009-08-06 08:32:33 +0000
3721+++ debian/docs 1970-01-01 00:00:00 +0000
3722@@ -1,3 +0,0 @@
3723-NEWS
3724-README
3725-TODO
3726
3727=== modified file 'debian/g15daemon.default'
3728--- debian/g15daemon.default 2009-08-19 07:33:22 +0000
3729+++ debian/g15daemon.default 2015-05-21 10:27:39 +0000
3730@@ -1,13 +1,5 @@
3731 # Defaults for g15daemon initscript
3732
3733-# SWITCH_KEY selects the key used to switch between client screens
3734-#
3735-# SWITCH_KEY="MR" to use the MR key (on top left)
3736-# SWITCH_KEY="L1 to use the L1 key: the small round key below the LCD
3737-
3738-
3739-SWITCH_KEY="L1"
3740-
3741 # Turn on debugging of g15 init.d and udev scripts
3742 #G15DEBUG="on"
3743
3744
3745=== modified file 'debian/g15daemon.init'
3746--- debian/g15daemon.init 2009-08-19 07:33:22 +0000
3747+++ debian/g15daemon.init 2015-05-21 10:27:39 +0000
3748@@ -2,8 +2,8 @@
3749
3750 ### BEGIN INIT INFO
3751 # Provides: g15daemon
3752-# Required-Start: $syslog $local_fs
3753-# Required-Stop: $syslog $local_fs
3754+# Required-Start: $syslog $local_fs $remote_fs
3755+# Required-Stop: $syslog $local_fs $remote_fs
3756 # Should-Start: $remote_fs
3757 # Should-Stop: $remote_fs
3758 # X-Start-Before: xdm kdm gdm ldm sdm
3759@@ -21,6 +21,8 @@
3760
3761 [ -x "$DAEMON" ] || exit 0
3762
3763+. /lib/lsb/init-functions
3764+
3765 # Include g15daemon defaults if available
3766 if [ -f /etc/default/g15daemon ] ; then
3767 . /etc/default/g15daemon
3768@@ -45,8 +47,11 @@
3769
3770 fi
3771
3772-
3773-
3774+check_new_init() {
3775+ if init_is_upstart || ps -p1 | grep -q systemd ; then
3776+ exit $1
3777+ fi
3778+}
3779
3780 wait_for_file() {
3781 local file=$1
3782@@ -63,9 +68,9 @@
3783 }
3784
3785 load_uinput() {
3786- if [ ! -e /dev/input/uinput ] ; then
3787+ if [ ! -e /dev/uinput ] ; then
3788 modprobe -q uinput || true
3789- wait_for_file /dev/input/uinput 3 || return 1
3790+ wait_for_file /dev/uinput 3 || return 1
3791 fi
3792 }
3793
3794@@ -94,12 +99,14 @@
3795
3796 case "$1" in
3797 start)
3798+ check_new_init 1
3799 echo -n "Starting $DESC: "
3800- load_uinput || echo -n ".../dev/input/uinput not found ..."
3801+ load_uinput || echo -n ".../dev/uinput not found ..."
3802 do_start
3803 echo "$NAME."
3804 ;;
3805 stop)
3806+ check_new_init 0
3807 echo -n "Stopping $DESC: "
3808 do_stop
3809 echo "$NAME."
3810@@ -123,9 +130,11 @@
3811 # just the same as "restart" except that it does nothing if the
3812 # daemon isn't already running.
3813 # check wether $DAEMON is running. If so, restart
3814+ check_new_init 1
3815 is_running && $0 restart || exit 0
3816 ;;
3817 restart)
3818+ check_new_init 1
3819 echo -n "Restarting $DESC: "
3820 do_stop
3821 # the device is slow to shut-down
3822@@ -134,6 +143,7 @@
3823 echo "$NAME."
3824 ;;
3825 udev)
3826+ check_new_init 0
3827 log "calling g15 udev; action: $ACTION, product $PRODUCT"
3828 if [ "x$ACTION" = "xadd" ] ; then
3829 load_uinput || true
3830@@ -153,6 +163,7 @@
3831 shared-udev)
3832 # some devices share usb also for audio, which causes some spourios
3833 # udev messages.
3834+ check_new_init 0
3835 log "calling g15 shared-dev; action: $ACTION, product $PRODUCT"
3836 if [ "x$ACTION" = "xadd" ] ; then
3837 load_uinput || true
3838
3839=== added file 'debian/g15daemon.postinst'
3840--- debian/g15daemon.postinst 1970-01-01 00:00:00 +0000
3841+++ debian/g15daemon.postinst 2015-05-21 10:27:39 +0000
3842@@ -0,0 +1,8 @@
3843+#!/bin/sh -e
3844+
3845+#DEBHELPER#
3846+
3847+if [ "$1" = configure ] ; then
3848+ #g15daemon will fail if supported device is not present, so ignore start script errors
3849+ invoke-rc.d g15daemon start || true
3850+fi
3851
3852=== added file 'debian/g15daemon.prerm'
3853--- debian/g15daemon.prerm 1970-01-01 00:00:00 +0000
3854+++ debian/g15daemon.prerm 2015-05-21 10:27:39 +0000
3855@@ -0,0 +1,5 @@
3856+#!/bin/sh -e
3857+
3858+#DEBHELPER#
3859+
3860+invoke-rc.d g15daemon stop || true
3861
3862=== added file 'debian/g15daemon.service'
3863--- debian/g15daemon.service 1970-01-01 00:00:00 +0000
3864+++ debian/g15daemon.service 2015-05-21 10:27:39 +0000
3865@@ -0,0 +1,12 @@
3866+[Unit]
3867+Description=Daemon for Logitech G15 keyboard
3868+Documentation=man:g15daemon(1)
3869+Wants=remote-fs.target
3870+After=remote-fs.target
3871+
3872+[Service]
3873+Type=forking
3874+EnvironmentFile=-/etc/default/g15daemon
3875+ExecStartPre=-/sbin/modprobe -q uinput
3876+ExecStartPre=-/sbin/udevadm settle -t 5 -E /dev/uinput
3877+ExecStart=/usr/sbin/g15daemon $DAEMON_OPTS
3878
3879=== modified file 'debian/g15daemon.udev'
3880--- debian/g15daemon.udev 2011-05-31 07:33:52 +0000
3881+++ debian/g15daemon.udev 2015-05-21 10:27:39 +0000
3882@@ -4,17 +4,16 @@
3883 #
3884
3885 # Logitech g11 -- extra keys, no LCD
3886-ATTR{idVendor}=="046d", ATTR{idProduct}=="c225", RUN+="/etc/init.d/g15daemon udev"
3887+ATTR{idVendor}=="046d", ATTR{idProduct}=="c225", RUN+="/etc/init.d/g15daemon udev", TAG+="systemd",ENV{SYSTEMD_WANTS}+="g15daemon.service"
3888
3889 # Logitech G15 (blue) -- extra keys and LCD
3890-ATTR{idVendor}=="046d", ATTR{idProduct}=="c222", RUN+="/etc/init.d/g15daemon udev"
3891+ATTR{idVendor}=="046d", ATTR{idProduct}=="c222", RUN+="/etc/init.d/g15daemon udev", TAG+="systemd", ENV{SYSTEMD_WANTS}+="g15daemon.service"
3892
3893 # Logitech G15 v2 (orange) -- extra keys and LCD
3894-ATTR{idVendor}=="046d", ATTR{idProduct}=="c227", RUN+="/etc/init.d/g15daemon shared-udev"
3895+ATTR{idVendor}=="046d", ATTR{idProduct}=="c227", RUN+="/etc/init.d/g15daemon shared-udev", TAG+="systemd", ENV{SYSTEMD_WANTS}+="g15daemon.service"
3896
3897 # Logitech Z10 -- extra keys and LCD
3898-ATTR{idVendor}=="046d", ATTR{idProduct}=="0a07", RUN+="/etc/init.d/g15daemon udev"
3899+ATTR{idVendor}=="046d", ATTR{idProduct}=="0a07", RUN+="/etc/init.d/g15daemon udev", TAG+="systemd", ENV{SYSTEMD_WANTS}+="g15daemon.service"
3900
3901 # Logitech G15 Gamepanel -- extra keys and LCD
3902-ATTR{idVendor}=="046d", ATTR{idProduct}=="c251", RUN+="/etc/init.d/g15daemon shared-udev"
3903-
3904+ATTR{idVendor}=="046d", ATTR{idProduct}=="c251", RUN+="/etc/init.d/g15daemon shared-udev", TAG+="systemd", ENV{SYSTEMD_WANTS}+="g15daemon.service"
3905
3906=== added file 'debian/g15daemon.upstart'
3907--- debian/g15daemon.upstart 1970-01-01 00:00:00 +0000
3908+++ debian/g15daemon.upstart 2015-05-21 10:27:39 +0000
3909@@ -0,0 +1,20 @@
3910+#Daemon for Logitech G15 keyboard
3911+
3912+start on remote-filesystems and (
3913+ usb-device-added ID_VENDOR_ID=046d ID_MODEL_ID=c225 or
3914+ usb-device-added ID_VENDOR_ID=046d ID_MODEL_ID=c222 or
3915+ usb-device-added ID_VENDOR_ID=046d ID_MODEL_ID=c227 or
3916+ usb-device-added ID_VENDOR_ID=046d ID_MODEL_ID=0a07 or
3917+ usb-device-added ID_VENDOR_ID=046d ID_MODEL_ID=c251)
3918+
3919+stop on runlevel [016]
3920+
3921+expect fork
3922+
3923+pre-start script
3924+ /sbin/modprobe -q uinput || true
3925+ [ -f /etc/default/g15daemon ] && . /etc/default/g15daemon
3926+ /sbin/udevadm settle -t 5 -E /dev/uinput || true
3927+end script
3928+
3929+exec /usr/sbin/g15daemon $DAEMON_OPTS
3930
3931=== added directory 'debian/patches'
3932=== added file 'debian/patches/01-remove-x11-setup-from-man.diff'
3933--- debian/patches/01-remove-x11-setup-from-man.diff 1970-01-01 00:00:00 +0000
3934+++ debian/patches/01-remove-x11-setup-from-man.diff 2015-05-21 10:27:39 +0000
3935@@ -0,0 +1,127 @@
3936+--- a/Documentation/g15daemon.1
3937++++ b/Documentation/g15daemon.1
3938+@@ -37,113 +37,6 @@
3939+ If all required libraries are installed and in locations known to your operating system, the daemon will slip quietly into the background and a clock will appear on the LCD.
3940+ Congratulations! The linux kernel will now output keycodes for all your extra keys.
3941+
3942+-.SH "Using the keys in X11"
3943+-Current versions of the Xorg Xserver dont have support for the extra keys that g15daemon provides. This support will be available in the next release of Xorg (7.2).
3944+-
3945+-For now, if you want access to the extra keys for hotkey support in X11, you need to run the xmodmaprc script on each start of X. This script is available in the contrib folder (if g15daemon is installed in the default location, the contrib folder is in /usr/share/doc/g15daemon\-${VERSION}/contrib
3946+-
3947+-Depending on your linux distribution, copying the xmodmaprc file (or pasting the text below) into ~/.Xmodmap may be all that's required.
3948+-
3949+-.SH "Xmodmaprc file"
3950+-Copy the following into ~/.Xmodmap (depending on your distribution) for X11 to recognise all extra G15 keys:
3951+-
3952+-\-\- cut here \-\-
3953+-.br
3954+-keycode 93 = XF86Launch1
3955+-.br
3956+-keycode 129 = XF86Launch8
3957+-.br
3958+-keycode 130 = XF86Launch9
3959+-.br
3960+-keycode 131 = XF86Launch2
3961+-.br
3962+-keycode 132 = XF86Phone
3963+-.br
3964+-keycode 133 = XF86Messenger
3965+-.br
3966+-keycode 136 = XF86LaunchD
3967+-.br
3968+-keycode 137 = XF86Support
3969+-.br
3970+-keycode 138 = XF86Word
3971+-.br
3972+-keycode 143 = XF86LaunchF
3973+-.br
3974+-keycode 144 = XF86AudioPrev
3975+-.br
3976+-keycode 150 = XF86LogOff
3977+-.br
3978+-keycode 152 = XF86Launch5
3979+-.br
3980+-keycode 153 = XF86AudioNext
3981+-.br
3982+-keycode 160 = XF86AudioMute
3983+-.br
3984+-keycode 161 = XF86Travel
3985+-.br
3986+-keycode 162 = XF86AudioPlay
3987+-.br
3988+-keycode 163 = XF86Spell
3989+-.br
3990+-keycode 164 = XF86AudioStop
3991+-.br
3992+-keycode 170 = XF86VendorHome
3993+-.br
3994+-keycode 174 = XF86AudioLowerVolume
3995+-.br
3996+-keycode 176 = XF86AudioRaiseVolume
3997+-.br
3998+-keycode 177 = XF86Launch4
3999+-.br
4000+-keycode 178 = XF86HomePage
4001+-.br
4002+-keycode 182 = XF86Away
4003+-.br
4004+-keycode 183 = XF86WebCam
4005+-.br
4006+-keycode 184 = XF86Launch0
4007+-.br
4008+-keycode 188 = XF86Music
4009+-.br
4010+-keycode 190 = XF86Launch6
4011+-.br
4012+-keycode 194 = XF86Forward
4013+-.br
4014+-keycode 195 = XF86Send
4015+-.br
4016+-keycode 205 = XF86Calendar
4017+-.br
4018+-keycode 208 = XF86Launch7
4019+-.br
4020+-keycode 209 = XF86LaunchB
4021+-.br
4022+-keycode 210 = XF86LaunchC
4023+-.br
4024+-keycode 215 = XF86Save
4025+-.br
4026+-keycode 219 = XF86WWW
4027+-.br
4028+-keycode 220 = XF86LaunchE
4029+-.br
4030+-keycode 223 = XF86Sleep
4031+-.br
4032+-keycode 228 = XF86Pictures
4033+-.br
4034+-keycode 231 = XF86LaunchA
4035+-.br
4036+-keycode 236 = XF86Mail
4037+-.br
4038+-keycode 237 = XF86AudioMedia
4039+-.br
4040+-keycode 246 = XF86iTouch
4041+-.br
4042+-keycode 247 = XF86Launch3
4043+-.br
4044+-keycode 249 = XF86ToDoList
4045+-.br
4046+-keycode 251 = XF86Calculater
4047+-.br
4048+-\-\- end cutting \-\-
4049+ .SH "AUTHORS"
4050+ The latest release of g15daemon is available at
4051+ .P
4052+--- a/Documentation/g15daemon_client_devel.3
4053++++ b/Documentation/g15daemon_client_devel.3
4054+@@ -55,7 +55,7 @@
4055+ int retval = 0;
4056+ int screen_fd = new_g15_screen( G15_WBMPBUF );
4057+
4058+-... do processing and display here ...
4059++ ... do processing and display here ...
4060+
4061+ retval = g15_close_screen( screen_fd );
4062+
4063
4064=== added file 'debian/patches/02-better-screenshort-creation.diff'
4065--- debian/patches/02-better-screenshort-creation.diff 1970-01-01 00:00:00 +0000
4066+++ debian/patches/02-better-screenshort-creation.diff 2015-05-21 10:27:39 +0000
4067@@ -0,0 +1,39 @@
4068+--- a/g15daemon/utility_funcs.c
4069++++ b/g15daemon/utility_funcs.c
4070+@@ -666,12 +666,24 @@
4071+ }
4072+
4073+ int uf_screendump_pbm(unsigned char *buffer,char *filename) {
4074++ int fd;
4075+ FILE *f;
4076+ int x,y;
4077+ #define WIDTH 40
4078+ g15canvas *canvas=g15daemon_xmalloc(sizeof(g15canvas));
4079+ memcpy(canvas->buffer,buffer,LCD_BUFSIZE);
4080+- f = fopen(filename,"w+");
4081++ fd = open(filename, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
4082++ if(fd == -1) {
4083++ g15daemon_log(LOG_WARNING, "uf_screendump_pbm failed: open, %s.\n", strerror(errno));
4084++ return -1;
4085++ }
4086++ f = fdopen(fd,"w");
4087++ if(f==NULL) {
4088++ close(fd);
4089++ g15daemon_log(LOG_WARNING, "uf_screendump_pbm failed: fdopen, %s.\n", strerror(errno));
4090++ return -1;
4091++ }
4092++
4093+ fprintf(f,"P1\n160 43\n");
4094+ fprintf(f,"# G15 screendump - %s\n\n",filename);
4095+ for(y=0;y<43;y++)
4096+@@ -681,7 +693,9 @@
4097+ fprintf(f,"\n");
4098+ }
4099+
4100+- fclose(f);
4101++ fclose(f);
4102++ fsync(fd);
4103++ close(fd);
4104+ free(canvas);
4105+ return 0;
4106+ }
4107
4108=== added file 'debian/patches/03-change-syslog-facility.diff'
4109--- debian/patches/03-change-syslog-facility.diff 1970-01-01 00:00:00 +0000
4110+++ debian/patches/03-change-syslog-facility.diff 2015-05-21 10:27:39 +0000
4111@@ -0,0 +1,11 @@
4112+--- a/g15daemon/main.c
4113++++ b/g15daemon/main.c
4114+@@ -456,7 +456,7 @@
4115+ struct passwd *nobody;
4116+ unsigned char location[1024];
4117+
4118+- openlog("g15daemon", LOG_PID, LOG_USER);
4119++ openlog("g15daemon", LOG_PID, LOG_DAEMON);
4120+ if(strlen((char*)user)==0){
4121+ nobody = getpwnam("nobody");
4122+ }else {
4123
4124=== added file 'debian/patches/04-open-needs-mode.diff'
4125--- debian/patches/04-open-needs-mode.diff 1970-01-01 00:00:00 +0000
4126+++ debian/patches/04-open-needs-mode.diff 2015-05-21 10:27:39 +0000
4127@@ -0,0 +1,11 @@
4128+--- a/g15daemon/utility_funcs.c
4129++++ b/g15daemon/utility_funcs.c
4130+@@ -356,7 +356,7 @@
4131+ config_items_t * item=NULL;
4132+ char line[1024];
4133+
4134+- config_fd = open(filename,O_CREAT|O_RDWR|O_TRUNC);
4135++ config_fd = open(filename,O_CREAT|O_RDWR|O_TRUNC, 0644);
4136+ if(config_fd){
4137+ snprintf(line,1024,"# G15Daemon Configuration File\n# any items entered before a [section] header\n# will be in the Global config space\n# comments you wish to keep should start with a semicolon';'\n");
4138+ write(config_fd,line,strlen(line));
4139
4140=== added file 'debian/patches/05-send-a-sync-event-after-key-up-down.diff'
4141--- debian/patches/05-send-a-sync-event-after-key-up-down.diff 1970-01-01 00:00:00 +0000
4142+++ debian/patches/05-send-a-sync-event-after-key-up-down.diff 2015-05-21 10:27:39 +0000
4143@@ -0,0 +1,30 @@
4144+--- a/plugins/g15_plugin_uinput.c
4145++++ b/plugins/g15_plugin_uinput.c
4146+@@ -125,6 +125,13 @@
4147+ event.value = G15KEY_DOWN;
4148+
4149+ write (uinp_fd, &event, sizeof(event));
4150++
4151++ memset(&event, 0, sizeof(event));
4152++
4153++ event.type = EV_SYN;
4154++ event.code = SYN_REPORT;
4155++
4156++ write (uinp_fd, &event, sizeof(event));
4157+ }
4158+
4159+ static void g15_uinput_keyup(unsigned char code)
4160+@@ -137,6 +144,13 @@
4161+ event.value = G15KEY_UP;
4162+
4163+ write (uinp_fd, &event, sizeof(event));
4164++
4165++ memset(&event, 0, sizeof(event));
4166++
4167++ event.type = EV_SYN;
4168++ event.code = SYN_REPORT;
4169++
4170++ write (uinp_fd, &event, sizeof(event));
4171+ }
4172+
4173+ void (*keyup)(unsigned char code) = &g15_uinput_keyup;
4174
4175=== added file 'debian/patches/06-fix-buffer-overflow.diff'
4176--- debian/patches/06-fix-buffer-overflow.diff 1970-01-01 00:00:00 +0000
4177+++ debian/patches/06-fix-buffer-overflow.diff 2015-05-21 10:27:39 +0000
4178@@ -0,0 +1,11 @@
4179+--- a/libg15daemon_client/g15daemon_net.c
4180++++ b/libg15daemon_client/g15daemon_net.c
4181+@@ -217,7 +217,7 @@
4182+ if(poll(pfd,1,100)>0){
4183+ if(pfd[0].revents & POLLPRI && !(pfd[0].revents & POLLERR || pfd[0].revents & POLLHUP || pfd[0].revents & POLLNVAL)) {
4184+ memset(packet,0,sizeof(packet));
4185+- msgret = recv(sock, packet, 10 , MSG_OOB);
4186++ msgret = recv(sock, packet, sizeof(packet) , MSG_OOB);
4187+ if (msgret < 1) {
4188+ return -1;
4189+ }
4190
4191=== added file 'debian/patches/07-reinit-on-any-error.diff'
4192--- debian/patches/07-reinit-on-any-error.diff 1970-01-01 00:00:00 +0000
4193+++ debian/patches/07-reinit-on-any-error.diff 2015-05-21 10:27:39 +0000
4194@@ -0,0 +1,22 @@
4195+Description: Reinitialize on any libusb error.
4196+ This allows g15daemon to correctly recover after suspend/resume.
4197+Author: Alexander Ponyatykh <lazyranma@gmail.com>
4198+Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/libusb/+bug/1357556
4199+Forwarded: no
4200+Last-Update: 2015-05-18
4201+===================================================================
4202+--- a/g15daemon/main.c
4203++++ b/g15daemon/main.c
4204+@@ -204,10 +204,10 @@
4205+ G15_EVENT_KEYPRESS, keypresses);
4206+ lastkeys = keypresses;
4207+
4208+- }else if(retval == -ENODEV && LIBG15_VERSION>=1200) {
4209++ }else if(retval < 0 && LIBG15_VERSION>=1200) {
4210+ pthread_mutex_lock(&g15lib_mutex);
4211+ while((retval=re_initLibG15() != G15_NO_ERROR) && !leaving){
4212+- g15daemon_log(LOG_WARNING,"Keyboard has gone.. Retrying\n");
4213++ g15daemon_log(LOG_WARNING,"Keyboard error (%d).. Reinitializing\n", retval);
4214+ sleep(1);
4215+ }
4216+ if(!leaving) {
4217
4218=== added file 'debian/patches/series'
4219--- debian/patches/series 1970-01-01 00:00:00 +0000
4220+++ debian/patches/series 2015-05-21 10:27:39 +0000
4221@@ -0,0 +1,7 @@
4222+01-remove-x11-setup-from-man.diff
4223+02-better-screenshort-creation.diff
4224+03-change-syslog-facility.diff
4225+04-open-needs-mode.diff
4226+05-send-a-sync-event-after-key-up-down.diff
4227+06-fix-buffer-overflow.diff
4228+07-reinit-on-any-error.diff
4229
4230=== modified file 'debian/rules'
4231--- debian/rules 2014-01-15 03:41:51 +0000
4232+++ debian/rules 2015-05-21 10:27:39 +0000
4233@@ -27,6 +27,7 @@
4234 include /usr/share/cdbs/1/rules/autoreconf.mk
4235
4236 DEB_CONFIGURE_EXTRA_FLAGS = --quiet --disable-rpath
4237+DEB_DH_INSTALLINIT_ARGS_g15daemon = --no-start --no-restart-on-upgrade
4238
4239 install/libg15daemon-client1::
4240 chrpath --delete $(DEB_DESTDIR)/usr/lib/libg15daemon_client.so.1.0.2 $(DEB_DESTDIR)/usr/lib/g15daemon/1.9.5.3/plugins/*.so $(DEB_DESTDIR)/usr/sbin/g15daemon
4241
4242=== added directory 'debian/source'
4243=== added file 'debian/source/format'
4244--- debian/source/format 1970-01-01 00:00:00 +0000
4245+++ debian/source/format 2015-05-21 10:27:39 +0000
4246@@ -0,0 +1,1 @@
4247+3.0 (quilt)
4248
4249=== modified file 'g15daemon/main.c'
4250--- g15daemon/main.c 2009-12-18 07:52:26 +0000
4251+++ g15daemon/main.c 2015-05-21 10:27:39 +0000
4252@@ -204,10 +204,10 @@
4253 G15_EVENT_KEYPRESS, keypresses);
4254 lastkeys = keypresses;
4255
4256- }else if(retval == -ENODEV && LIBG15_VERSION>=1200) {
4257+ }else if(retval < 0 && LIBG15_VERSION>=1200) {
4258 pthread_mutex_lock(&g15lib_mutex);
4259 while((retval=re_initLibG15() != G15_NO_ERROR) && !leaving){
4260- g15daemon_log(LOG_WARNING,"Keyboard has gone.. Retrying\n");
4261+ g15daemon_log(LOG_WARNING,"Keyboard error (%d).. Reinitializing\n", retval);
4262 sleep(1);
4263 }
4264 if(!leaving) {

Subscribers

People subscribed via source and target branches