G15DAEMON_CLIENT_DEVEL(3)
π NAME π
g15daemon_client β G15Daemon Server / Client communication for g15daemon π«Ά
okay so you opened the G15daemon Client Development page and you're like "what is this" β bestie, it's the whole manual for talking to g15daemon from your own code. grab a snack, we're going in π
β¨ SYNOPSIS β¨
#include <libg15.h>
#include <g15daemon_client.h>
link with
-lg15daemon_client
int new_g15_screen(int screentype);
int g15_close_screen(int sock);
int g15_send(int sock, char *buf, unsigned int len);
int g15_recv(int sock, char *buf, unsigned int len);
int g15_send_cmd (int sock, unsigned char command, unsigned char value);
π¦ G15Daemon Server / Client communication π¦
so the tea is: G15Daemon talks to its clients over INET sockets, and it's sitting there listening on localhost port 15550 waiting for connection requests π
the second you connect, the server sends you the text string "G15 daemon HELLO" β that's it confirming to you that it really is a valid g15daemon process, no catfish here π β then it creates a new screen and just waits for LCD buffers or commands to show up from you.
and the way you get multiple screens? iconic. you literally just open more socket connections to the server process. that's it. that's the trick π
if the socket gets closed, or your client just dips and exits, all the LCD buffers and the screen tied to that socket get automatically destroyed. no cleanup chores, the daemon handles it β¨
clients that wanna display stuff on the LCD must send entire screens, in whatever format they like. and lowkey important: partial screen updates (icons, etc.) are not supported right now π
commands go to the daemon via the OOB (out-of-band) messagetype, and the replies come back inband to the client. remember that, it matters later.
πΈ int new_g15_screen(int screentype) πΈ
opens a new connection and hands you back a network socket to use π
it also creates a screen, and the pixel format you get depends on which of these (defined in g15daemon_client.h) you pass:
G15_PIXELBUFβ this buffer has to be exactly6880bytes, and it uses 1 byte per pixel. no more, no less, don't try it.G15_TEXTBUFβ currently ignored by the daemon. yeah. it's giving ghosted πG15_WBMPBUFβ a packed pixel buffer in WBMP format with 8 pixels per byte. super handy for perl programmers using theGD::andG15Daemon.pmperl modules (check thelang_bindingsdirectory, iykyk).G15_G15RBUFβ another packed pixel buffer type, also 8 pixels/byte, and it's the nativelibg15renderformat. the real one β
example of use:
int screen_fd = new_g15_screen( G15_WBMPBUF );
π int g15_close_screen (int screen_fd) π
does exactly what it says bestie β it just closes a socket you previously opened with new_g15_screen(). then the daemon automatically cleans up any buffers and removes the LCD screen from the display list. it's giving "you don't have to do anything, I got you" π«Ά
returns 0 if it worked, or errno if there was an error.
example:
int retval = 0; int screen_fd = new_g15_screen( G15_WBMPBUF );
... do processing and display here ...
retval = g15_close_screen( screen_fd );
π₯ int g15_send (int sock, char *buf, unsigned int len) π₯
a lil wrapper around send() whose whole personality is "make sure all len bytes of data actually get to the daemon". it just uses poll() to block until the entire message is sent. no half-sends, no drama β¨
returns 0 on success, -1 if the send failed because of a timeout or a socket error π
π int g15_recv (int sock, char *buf, unsigned int len) π
same energy, opposite direction: a wrapper around recv() that makes sure all len bytes of data are received from the daemon. again, poll() blocks until the whole message is in π
returns 0 on success, -1 if the recv failed due to a timeout or socket error.
β int g15_send_cmd ( int sock, unsigned char command, unsigned char value) β
sends a command to the daemon (all the possible commands are listed right below, don't scroll past them π).
returns 0 or the return value of the command on success, and -1 on failure.
see examples for usage.
π G15Daemon Command Types π
commands and requests to the daemon are sent via OOB data packets. heads up: changes to the backlight and mkey state only affect the calling client β nobody else's screen is catching strays π
the following commands are supported as defined in g15daemon_client.h:
G15DAEMON_KEY_HANDLER
requests that all M and G key presses get sent to this client. all the keys are packed into an unsigned int, and sent to the client inband when a key is pressed. main character privileges, honestly π
G15DAEMON_MKEYLEDS
sets the M key LED state. to change LED state, each LED that's supposed to be turned on gets OR'd with the command byte. see libg15.h for values. for examples see the end of this document β¨
G15DAEMON_BACKLIGHT
sets the LCD Backlight brightness. the brightness level (0|1|2) is OR'd with the command byte. for examples see the end of this document πΈ
G15DAEMON_CONTRAST
sets the LCD contrast. the contrast level (0|1|2) is OR'd with the command byte. for examples see the end of this document π
G15DAEMON_GET_KEYSTATE
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 π
G15DAEMON_SWITCH_PRIORITIES
toggles the client's LCD screen to/from the front. clients can check their foreground/background state with the following:
G15DAEMON_IS_FOREGROUND
on receipt of this command, G15Daemon will send a 1 byte packet back with the value 1 if the client is foreground, or 0 if not. simple as π
G15DAEMON_IS_USER_SELECTED
on receipt of this command, G15daemon will return a byte indicating if the user selected the client be foreground or background. (yes, the user is the one deciding your fate, not the daemon π)
π EXAMPLES π
below is a completely nonsensical client which (poorly) demonstrates the usage of most of the commands. it's not good. it is educational. both things are true π
--- Cut here ---
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <poll.h>
#include <g15daemon_client.h>
#include <libg15.h>
/* #define TEST_KEYHANDLER */
int main(int argc, char *argv[]) {
int g15screen_fd, retval;
char lcdbuffer[6880];
unsigned int keystate;
char msgbuf[256];
int foo = 0;
if((g15screen_fd = new_g15_screen(G15_PIXELBUF))<0){
printf("Sorry, cant connect to the G15daemon0);
return 5;
}else
printf("Connected to g15daemon. sending image0);
if(argc<2)
retval = g15_send(g15screen_fd,(char*)logo_data,6880);
else {
memset(lcdbuffer,0,6880);
memset(lcdbuffer,1,6880/2);
retval = g15_send(g15screen_fd,(char*)lcdbuffer,6880);
}
printf("checking key status - press G1 to exit0,retval);
while(1){
keystate = 0;
int foo;
keystate = g15_send_cmd (g15screen_fd,
G15DAEMON_GET_KEYSTATE, foo);
if(keystate)
printf("keystate = %i0,keystate);
if(keystate & G15_KEY_G1) //G1 key. See libg15.h for
details on key values.
break;
/* G2,G3 & G4 change LCD backlight */
if(keystate & G15_KEY_G2){
retval = g15_send_cmd (g15screen_fd,
G15DAEMON_BACKLIGHT, G15_BRIGHTNESS_DARK);
}
if(keystate & G15_KEY_G3){
retval = g15_send_cmd (g15screen_fd,
G15DAEMON_BACKLIGHT, G15_BRIGHTNESS_MEDIUM);
}
if(keystate & G15_KEY_G4){
retval = g15_send_cmd (g15screen_fd,
G15DAEMON_BACKLIGHT, G15_BRIGHTNESS_BRIGHT);
}
/* is this client in the foreground?? */
retval = g15_send_cmd (g15screen_fd,
G15DAEMON_IS_FOREGROUND, foo);
if(retval)
printf("Hey, we are in the foreground, Doc0);
else
printf("What dastardly wabbit put me in the background?0);
retval = g15_send_cmd (g15screen_fd,
G15DAEMON_IS_USER_SELECTED, foo);
if(retval)
printf("You wanted me in the foreground, right Doc?0);
else
printf("You dastardly wabbit !0);
if(retval){ /* we've been backgrounded! */
sleep(2); /* remain in the background for a bit */
retval = g15_send_cmd (g15screen_fd,
G15DAEMON_SWITCH_PRIORITIES, foo);
sleep(2); /* switch to foreground */
retval = g15_send_cmd (g15screen_fd,
G15DAEMON_SWITCH_PRIORITIES, foo);
}
usleep(500); #ifdef TEST_KEYHANDLER
/* ok.. request that all G&M keys are passed to us.. */
retval = g15_send_cmd (g15screen_fd, G15DAEMON_KEY_HANDLER,
foo);
while(1){
printf("waiting on keystate0);
keystate=0;
retval = recv(g15screen_fd, &keystate ,
sizeof(keystate),0);
if(keystate)
printf("Recieved %i as keystate",keystate);
} #endif
}
g15_close_screen(g15screen_fd);
return 0; }
--- end cutting ---
and that's the whole page bestie π this one comes from G15Daemon, version 1.0, and the date slot is literally just G15daemon Client Development() β which is a whole vibe. go forth and talk to your daemon, you're gonna slay β¨ππ¦
π¦ where this page comes from
- debian bookworm: libg15daemon-client1 1.9.5.3-12
- debian trixie: libg15daemon-client1t64 1.9.5.3-14.1+b1
- ubuntu jammy: libg15daemon-client1 1.9.5.3-12
- ubuntu noble: libg15daemon-client1t64 1.9.5.3-14.1build1
- ubuntu questing: libg15daemon-client1t64 1.9.5.3-14.1build1
- ubuntu resolute: libg15daemon-client1t64 1.9.5.3-14.1build2
- ubuntu stonking: libg15daemon-client1t64 1.9.5.3-14.1build2
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms