Various progess on calling & texting; reorganize scripts dirs by category
This commit is contained in:
parent
334c74ad39
commit
ae983ef8c8
35 changed files with 1002 additions and 221 deletions
391
programs/sxmo_megiaudioroute.c
Normal file
391
programs/sxmo_megiaudioroute.c
Normal file
|
@ -0,0 +1,391 @@
|
|||
/*
|
||||
* Voice call audio setup tool
|
||||
*
|
||||
* Copyright (C) 2020 Ondřej Jirman <megous@megous.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <inttypes.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <sound/asound.h>
|
||||
#include <sound/tlv.h>
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0]))
|
||||
|
||||
void syscall_error(int is_err, const char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (!is_err)
|
||||
return;
|
||||
|
||||
printf("ERROR: ");
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
printf(": %s\n", strerror(errno));
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void error(const char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
printf("ERROR: ");
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
printf("\n");
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct audio_control_state {
|
||||
char name[128];
|
||||
union {
|
||||
int64_t i[4];
|
||||
const char* e[4];
|
||||
} vals;
|
||||
bool used;
|
||||
};
|
||||
|
||||
static bool audio_restore_state(struct audio_control_state* controls, int n_controls)
|
||||
{
|
||||
int fd;
|
||||
int ret;
|
||||
|
||||
fd = open("/dev/snd/controlC0", O_CLOEXEC | O_NONBLOCK);
|
||||
if (fd < 0)
|
||||
error("failed to open card\n");
|
||||
|
||||
struct snd_ctl_elem_list el = {
|
||||
.offset = 0,
|
||||
.space = 0,
|
||||
};
|
||||
ret = ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &el);
|
||||
syscall_error(ret < 0, "SNDRV_CTL_IOCTL_ELEM_LIST failed");
|
||||
|
||||
struct snd_ctl_elem_id ids[el.count];
|
||||
el.pids = ids;
|
||||
el.space = el.count;
|
||||
ret = ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &el);
|
||||
syscall_error(ret < 0, "SNDRV_CTL_IOCTL_ELEM_LIST failed");
|
||||
|
||||
for (int i = 0; i < el.used; i++) {
|
||||
struct snd_ctl_elem_info inf = {
|
||||
.id = ids[i],
|
||||
};
|
||||
|
||||
ret = ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, &inf);
|
||||
syscall_error(ret < 0, "SNDRV_CTL_IOCTL_ELEM_INFO failed");
|
||||
|
||||
if ((inf.access & SNDRV_CTL_ELEM_ACCESS_READ) && (inf.access & SNDRV_CTL_ELEM_ACCESS_WRITE)) {
|
||||
struct snd_ctl_elem_value val = {
|
||||
.id = ids[i],
|
||||
};
|
||||
int64_t cval = 0;
|
||||
|
||||
ret = ioctl(fd, SNDRV_CTL_IOCTL_ELEM_READ, &val);
|
||||
syscall_error(ret < 0, "SNDRV_CTL_IOCTL_ELEM_READ failed");
|
||||
|
||||
struct audio_control_state* cs = NULL;
|
||||
for (int j = 0; j < n_controls; j++) {
|
||||
if (!strcmp(controls[j].name, ids[i].name)) {
|
||||
cs = &controls[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cs) {
|
||||
printf("Control \"%s\" si not defined in the controls state\n", ids[i].name);
|
||||
continue;
|
||||
}
|
||||
|
||||
cs->used = 1;
|
||||
|
||||
// check if value needs changing
|
||||
|
||||
switch (inf.type) {
|
||||
case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
|
||||
case SNDRV_CTL_ELEM_TYPE_INTEGER:
|
||||
for (int j = 0; j < inf.count; j++) {
|
||||
if (cs->vals.i[j] != val.value.integer.value[j]) {
|
||||
// update
|
||||
//printf("%s <=[%d]= %"PRIi64"\n", ids[i].name, j, cs->vals.i[j]);
|
||||
|
||||
val.value.integer.value[j] = cs->vals.i[j];
|
||||
ret = ioctl(fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &val);
|
||||
syscall_error(ret < 0, "SNDRV_CTL_IOCTL_ELEM_WRITE failed");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case SNDRV_CTL_ELEM_TYPE_INTEGER64:
|
||||
for (int j = 0; j < inf.count; j++) {
|
||||
if (cs->vals.i[j] != val.value.integer64.value[j]) {
|
||||
// update
|
||||
//printf("%s <=[%d]= %"PRIi64"\n", ids[i].name, j, cs->vals.i[j]);
|
||||
|
||||
val.value.integer64.value[j] = cs->vals.i[j];
|
||||
ret = ioctl(fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &val);
|
||||
syscall_error(ret < 0, "SNDRV_CTL_IOCTL_ELEM_WRITE failed");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SNDRV_CTL_ELEM_TYPE_ENUMERATED: {
|
||||
for (int k = 0; k < inf.count; k++) {
|
||||
int eval = -1;
|
||||
for (int j = 0; j < inf.value.enumerated.items; j++) {
|
||||
inf.value.enumerated.item = j;
|
||||
|
||||
ret = ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, &inf);
|
||||
syscall_error(ret < 0, "SNDRV_CTL_IOCTL_ELEM_INFO failed");
|
||||
|
||||
if (!strcmp(cs->vals.e[k], inf.value.enumerated.name)) {
|
||||
eval = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (eval < 0)
|
||||
error("enum value %s not found\n", cs->vals.e[k]);
|
||||
|
||||
if (eval != val.value.enumerated.item[k]) {
|
||||
// update
|
||||
//printf("%s <=%d= %s\n", ids[i].name, k, cs->vals.e[k]);
|
||||
|
||||
val.value.enumerated.item[k] = eval;
|
||||
ret = ioctl(fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &val);
|
||||
syscall_error(ret < 0, "SNDRV_CTL_IOCTL_ELEM_WRITE failed");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < n_controls; j++)
|
||||
if (!controls[j].used)
|
||||
printf("Control \"%s\" is defined in state but not present on the card\n", controls[j].name);
|
||||
|
||||
close(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
struct audio_setup {
|
||||
bool mic_on;
|
||||
bool spk_on;
|
||||
bool hp_on;
|
||||
bool ear_on;
|
||||
|
||||
// when sending audio to modem from AIF1 R, also play that back
|
||||
// to me locally (just like AIF1 L plays just to me)
|
||||
//
|
||||
// this is to monitor what SW is playing to the modem (so that
|
||||
// I can hear my robocaller talking)
|
||||
bool modem_playback_monitor;
|
||||
|
||||
// enable modem routes to DAC/from ADC (spk/mic)
|
||||
// digital paths to AIF1 are always on
|
||||
bool to_modem_on;
|
||||
bool from_modem_on;
|
||||
|
||||
// shut off/enable all digital paths to the modem:
|
||||
// keep this off until the call starts, then turn it on
|
||||
bool dai2_en;
|
||||
|
||||
int mic_gain;
|
||||
int spk_vol;
|
||||
int ear_vol;
|
||||
int hp_vol;
|
||||
};
|
||||
|
||||
static void audio_set_controls(struct audio_setup* s)
|
||||
{
|
||||
struct audio_control_state controls[] = {
|
||||
//
|
||||
// Analog input:
|
||||
//
|
||||
|
||||
// Mic 1 (daughterboard)
|
||||
{ .name = "Mic1 Boost Volume", .vals.i = { s->mic_gain } },
|
||||
|
||||
// Mic 2 (headphones)
|
||||
{ .name = "Mic2 Boost Volume", .vals.i = { 0 } },
|
||||
|
||||
// Line in (unused on PP)
|
||||
// no controls yet
|
||||
|
||||
// Input mixers before ADC
|
||||
|
||||
{ .name = "Mic1 Capture Switch", .vals.i = { !!s->mic_on, !!s->mic_on } },
|
||||
{ .name = "Mic2 Capture Switch", .vals.i = { 0, 0 } },
|
||||
{ .name = "Line In Capture Switch", .vals.i = { 0, 0 } }, // Out Mix -> In Mix
|
||||
{ .name = "Mixer Capture Switch", .vals.i = { 0, 0 } },
|
||||
{ .name = "Mixer Reversed Capture Switch", .vals.i = { 0, 0 } },
|
||||
|
||||
// ADC
|
||||
{ .name = "ADC Gain Capture Volume", .vals.i = { 0 } },
|
||||
{ .name = "ADC Capture Volume", .vals.i = { 160, 160 } }, // digital gain
|
||||
|
||||
//
|
||||
// Digital paths:
|
||||
//
|
||||
|
||||
// AIF1 (SoC)
|
||||
|
||||
// AIF1 slot0 capture mixer sources
|
||||
{ .name = "AIF1 AD0 Mixer ADC Capture Switch", .vals.i = { 1, 0 } },
|
||||
{ .name = "AIF1 AD0 Mixer AIF1 DA0 Capture Switch", .vals.i = { 0, 0 } },
|
||||
{ .name = "AIF1 AD0 Mixer AIF2 DAC Capture Switch", .vals.i = { 0, 1 } },
|
||||
{ .name = "AIF1 AD0 Mixer AIF2 DAC Rev Capture Switch", .vals.i = { 0, 0 } }, //XXX: capture right from the left AIF2?
|
||||
{ .name = "AIF1 Loopback Switch", .vals.i = { 0 } },
|
||||
|
||||
// AIF1 slot0 capture/playback mono mixing/digital volume
|
||||
{ .name = "AIF1 AD0 Capture Volume", .vals.i = { 160, 160 } },
|
||||
{ .name = "AIF1 AD0 Stereo Capture Route", .vals.e = { "Stereo", "Stereo" } },
|
||||
{ .name = "AIF1 DA0 Playback Volume", .vals.i = { 160, 160 } },
|
||||
{ .name = "AIF1 DA0 Stereo Playback Route", .vals.e = { "Stereo", "Stereo" } },
|
||||
|
||||
// AIF2 (modem)
|
||||
|
||||
// AIF2 capture mixer sources
|
||||
{ .name = "AIF2 ADC Mixer ADC Capture Switch", .vals.i = { !!s->to_modem_on && !!s->dai2_en, 0 } }, // from adc/mic
|
||||
{ .name = "AIF2 ADC Mixer AIF1 DA0 Capture Switch", .vals.i = { 0, 1 } }, // from aif1 R
|
||||
{ .name = "AIF2 ADC Mixer AIF2 DAC Rev Capture Switch", .vals.i = { 0, 0 } },
|
||||
{ .name = "AIF2 Loopback Switch", .vals.i = { 0 } },
|
||||
|
||||
// AIF2 capture/playback mono mixing/digital volume
|
||||
{ .name = "AIF2 ADC Capture Volume", .vals.i = { 160, 160 } },
|
||||
{ .name = "AIF2 DAC Playback Volume", .vals.i = { 160, 160 } },
|
||||
{ .name = "AIF2 ADC Stereo Capture Route", .vals.e = { "Mix Mono", "Mix Mono" } }, // we mix because we're sending two channels (from mic and AIF1 R)
|
||||
{ .name = "AIF2 DAC Stereo Playback Route", .vals.e = { "Sum Mono", "Sum Mono" } }, // we sum because modem is sending a single channel
|
||||
|
||||
// AIF3 (bluetooth)
|
||||
|
||||
{ .name = "AIF3 Loopback Switch", .vals.i = { 0 } },
|
||||
{ .name = "AIF3 ADC Capture Route", .vals.e = { "None" } },
|
||||
{ .name = "AIF3 DAC Playback Route", .vals.e = { "None" } },
|
||||
|
||||
// DAC
|
||||
|
||||
// DAC input mixers (sources from ADC, and AIF1/2)
|
||||
{ .name = "DAC Mixer ADC Playback Switch", .vals.i = { 0, 0 } }, // we don't play our mic to ourselves
|
||||
{ .name = "DAC Mixer AIF1 DA0 Playback Switch", .vals.i = { 1, !!s->modem_playback_monitor } },
|
||||
{ .name = "DAC Mixer AIF2 DAC Playback Switch", .vals.i = { 0, !!s->dai2_en && !!s->from_modem_on } },
|
||||
|
||||
//
|
||||
// Analog output:
|
||||
//
|
||||
|
||||
// Output mixer after DAC
|
||||
|
||||
{ .name = "DAC Playback Switch", .vals.i = { 1, 1 } },
|
||||
{ .name = "DAC Reversed Playback Switch", .vals.i = { 1, 1 } },
|
||||
{ .name = "DAC Playback Volume", .vals.i = { 160, 160 } },
|
||||
{ .name = "Mic1 Playback Switch", .vals.i = { 0, 0 } },
|
||||
{ .name = "Mic1 Playback Volume", .vals.i = { 0 } },
|
||||
{ .name = "Mic2 Playback Switch", .vals.i = { 0, 0 } },
|
||||
{ .name = "Mic2 Playback Volume", .vals.i = { 0 } },
|
||||
{ .name = "Line In Playback Switch", .vals.i = { 0, 0 } },
|
||||
{ .name = "Line In Playback Volume", .vals.i = { 0 } },
|
||||
|
||||
// Outputs
|
||||
|
||||
{ .name = "Earpiece Source Playback Route", .vals.e = { "Left Mixer" } },
|
||||
{ .name = "Earpiece Playback Switch", .vals.i = { !!s->ear_on } },
|
||||
{ .name = "Earpiece Playback Volume", .vals.i = { s->ear_vol } },
|
||||
|
||||
{ .name = "Headphone Source Playback Route", .vals.e = { "Mixer", "Mixer" } },
|
||||
{ .name = "Headphone Playback Switch", .vals.i = { !!s->hp_on, !!s->hp_on } },
|
||||
{ .name = "Headphone Playback Volume", .vals.i = { s->hp_vol } },
|
||||
|
||||
// Loudspeaker
|
||||
{ .name = "Line Out Source Playback Route", .vals.e = { "Mono Differential", "Mono Differential" } },
|
||||
{ .name = "Line Out Playback Switch", .vals.i = { !!s->spk_on, !!s->spk_on } },
|
||||
{ .name = "Line Out Playback Volume", .vals.i = { s->spk_vol } },
|
||||
};
|
||||
|
||||
audio_restore_state(controls, ARRAY_SIZE(controls));
|
||||
}
|
||||
|
||||
static struct audio_setup audio_setup = {
|
||||
.mic_on = false,
|
||||
.ear_on = false,
|
||||
.spk_on = false,
|
||||
.hp_on = false,
|
||||
|
||||
.from_modem_on = true,
|
||||
.to_modem_on = true,
|
||||
.modem_playback_monitor = false,
|
||||
|
||||
.dai2_en = false,
|
||||
|
||||
.hp_vol = 15,
|
||||
.spk_vol = 15,
|
||||
.ear_vol = 31,
|
||||
.mic_gain = 1,
|
||||
};
|
||||
|
||||
int main(int ac, char* av[])
|
||||
{
|
||||
int opt;
|
||||
|
||||
while ((opt = getopt(ac, av, "smhe2")) != -1) {
|
||||
switch (opt) {
|
||||
case 's':
|
||||
audio_setup.spk_on = 1;
|
||||
break;
|
||||
case 'm':
|
||||
audio_setup.mic_on = 1;
|
||||
break;
|
||||
case 'h':
|
||||
audio_setup.hp_on = 1;
|
||||
break;
|
||||
case 'e':
|
||||
audio_setup.ear_on = 1;
|
||||
break;
|
||||
case 'z':
|
||||
audio_setup.modem_playback_monitor = 1;
|
||||
break;
|
||||
case '2':
|
||||
audio_setup.dai2_en = 1;
|
||||
break;
|
||||
default: /* '?' */
|
||||
fprintf(stderr, "Usage: %s [-s] [-m] [-h] [-e] [-2]\n", av[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
audio_set_controls(&audio_setup);
|
||||
return 0;
|
||||
}
|
||||
|
26
programs/sxmo_pdudecode.c
Normal file
26
programs/sxmo_pdudecode.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
#include <gammu.h>
|
||||
#include <gammu-message.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
GSM_SMSMessage m;
|
||||
GSM_Error err;
|
||||
int i;
|
||||
char timestamp[50];
|
||||
char * hexstring;
|
||||
|
||||
hexstring = malloc(strlen(argv[1]) / 2);
|
||||
for (i = 0; i < strlen(argv[1]) / 2; i++) {
|
||||
sscanf(argv[1] + i*2, "%2hhx", &hexstring[i]);
|
||||
}
|
||||
err = GSM_DecodePDUFrame(NULL, &m, hexstring, strlen(argv[1]) / 2, NULL, 1);
|
||||
if (err != ERR_NONE) {
|
||||
fprintf(stderr, "Failure to parse string: %s\n", GSM_ErrorString(err));
|
||||
}
|
||||
GSM_DateTimeToTimestamp(&m.DateTime, timestamp);
|
||||
|
||||
printf("Date: %s\n", timestamp);
|
||||
printf("Number: %s\n", DecodeUnicodeConsole(m.Number));
|
||||
printf("Message:\n%s\n", DecodeUnicodeConsole(m.Text));
|
||||
}
|
|
@ -11,36 +11,38 @@ static int lastkeyn = 0;
|
|||
static int oldbrightness = 10;
|
||||
static int screenon = 1;
|
||||
static char screentogglecommand[100];
|
||||
static char pineledcommand[100];
|
||||
static char * brightnessfile = "/sys/devices/platform/backlight/backlight/backlight/brightness";
|
||||
|
||||
|
||||
void
|
||||
updatescreen() {
|
||||
sprintf(
|
||||
screentogglecommand,
|
||||
"sh -c 'echo %d > /sys/devices/platform/backlight/backlight/backlight/brightness'",
|
||||
screenon ? oldbrightness : 0
|
||||
);
|
||||
if (screenon) {
|
||||
system("sh -c 'echo 1 > /sys/devices/platform/leds/leds/pinephone:blue:user/brightness'");
|
||||
system("sh -c 'echo 0 > /sys/devices/platform/leds/leds/pinephone:red:user/brightness'");
|
||||
} else {
|
||||
system("sh -c 'echo 0 > /sys/devices/platform/leds/leds/pinephone:blue:user/brightness'");
|
||||
system("sh -c 'echo 1 > /sys/devices/platform/leds/leds/pinephone:red:user/brightness'");
|
||||
}
|
||||
system(screentogglecommand);
|
||||
|
||||
void updatepineled(int red, int brightness) {
|
||||
sprintf(
|
||||
pineledcommand,
|
||||
"sh -c 'echo %d > /sys/devices/platform/leds/leds/pinephone:%s:user/brightness'",
|
||||
brightness,
|
||||
red ? "red" : "blue"
|
||||
);
|
||||
system(pineledcommand);
|
||||
}
|
||||
|
||||
void
|
||||
cleanupscreen() {
|
||||
screenon = 1;
|
||||
updatescreen();
|
||||
system("sh -c 'echo 0 > /sys/devices/platform/leds/leds/pinephone:red:user/brightness'");
|
||||
system("sh -c 'echo 0 > /sys/devices/platform/leds/leds/pinephone:blue:user/brightness'");
|
||||
void updatescreenon(int on) {
|
||||
int b = on ? oldbrightness : 0;
|
||||
sprintf(screentogglecommand, "sh -c 'echo %d > %s'", b, brightnessfile);
|
||||
system(screentogglecommand);
|
||||
updatepineled(0, b ? 1 : 0);
|
||||
updatepineled(1, b ? 0 : 1);
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
updatescreenon(1);
|
||||
updatepineled(1, 0);
|
||||
updatepineled(0, 0);
|
||||
}
|
||||
|
||||
static void die(const char *err, ...) {
|
||||
fprintf(stderr, "Error: %s", err);
|
||||
cleanupscreen();
|
||||
cleanup();
|
||||
exit(1);
|
||||
}
|
||||
static void usage(void) {
|
||||
|
@ -109,16 +111,12 @@ readinputloop(Display *dpy, int screen) {
|
|||
|
||||
switch (keysym) {
|
||||
case XF86XK_AudioRaiseVolume:
|
||||
screenon = !screenon;
|
||||
updatescreen();
|
||||
|
||||
break;
|
||||
case XF86XK_AudioLowerVolume:
|
||||
screenon = !screenon;
|
||||
updatescreen();
|
||||
break;
|
||||
updatescreenon(screenon);
|
||||
break;
|
||||
case XF86XK_PowerOff:
|
||||
cleanupscreen();
|
||||
cleanup();
|
||||
running = 0;
|
||||
break;
|
||||
}
|
||||
|
@ -127,20 +125,42 @@ readinputloop(Display *dpy, int screen) {
|
|||
|
||||
}
|
||||
|
||||
int
|
||||
getoldbrightness() {
|
||||
char * buffer = 0;
|
||||
long length;
|
||||
FILE * f = fopen(brightnessfile, "rb");
|
||||
if (f) {
|
||||
fseek(f, 0, SEEK_END);
|
||||
length = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
buffer = malloc(length);
|
||||
if (buffer) {
|
||||
fread(buffer, 1, length, f);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
if (buffer) {
|
||||
oldbrightness = atoi(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv) {
|
||||
Display *dpy;
|
||||
Screen *screen;
|
||||
|
||||
|
||||
|
||||
if (setuid(0))
|
||||
die("setuid(0) failed\n");
|
||||
if (!(dpy = XOpenDisplay(NULL)))
|
||||
die("Cannot open display\n");
|
||||
|
||||
updatescreen();
|
||||
screen = XDefaultScreen(dpy);
|
||||
XSync(dpy, 0);
|
||||
getoldbrightness();
|
||||
updatescreenon(1);
|
||||
lockscreen(dpy, screen);
|
||||
XSync(dpy, 0);
|
||||
readinputloop(dpy, screen);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue