Merge lp:~lazyranma/ubuntu/wily/g15daemon/g15daemon.dev into lp:ubuntu/wily/g15daemon
- Wily (15.10)
- g15daemon.dev
- Merge into wily
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 |
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu branches | Pending | ||
Review via email: mp+259746@code.launchpad.net |
Commit message
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/
(related to LP #617101).
* debian/docs: removed obsolete file.
* Do not fail package installation/
(LP: #617101, LP: #1103275).
* debian/
* debian/
* Added debian/
error returned by libusb to correctly recover after suspend/resume.
(LP: #1357556)
* debian/control: removed dependency on libg15daemon-
* debian/control: changed priority of g15daemon to optional
* Added native upstart job and systemd service. (LP: #1441365)
* debian/
upstart scripts simple.
Sebastien Bacher (seb128) wrote : | # |
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
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) { |
Thanks, that's quite some changes. Do you think some could be forwarded to Debian?