~increscent/sxmo-utils

26d0027307701a8c7eb3d6c0fb5d54430da1e6ed — Robert Williams 4 months ago 0cb3e1e master
added audio handling to suspend
2 files changed, 114 insertions(+), 102 deletions(-)

M configs/openrc/sxmo-pinephone
M programs/sxmo_suspend.c
M configs/openrc/sxmo-pinephone => configs/openrc/sxmo-pinephone +1 -1
@@ 3,4 3,4 @@
description="Enable user access to pinephone hardware kernel interface"

command="chmod"
command_args="a+rw /sys/module/8723cs/parameters/rtw_scan_interval_thr /sys/devices/platform/backlight/backlight/backlight/brightness /sys/power/state /sys/devices/platform/soc/1f00000.rtc/power/wakeup /sys/power/mem_sleep /sys/bus/usb/drivers/usb/unbind /sys/bus/usb/drivers/usb/bind /sys/class/leds/red:indicator/brightness /sys/class/leds/blue:indicator/brightness /sys/class/leds/green:indicator/brightness /sys/class/leds/white:flash/brightness /dev/rtc0 /sys/devices/platform/soc/1f03400.rsb/sunxi-rsb-3a3/axp221-pek/power/wakeup"
command_args="a+rw /sys/module/8723cs/parameters/rtw_scan_interval_thr /sys/devices/platform/backlight/backlight/backlight/brightness /sys/power/state /sys/devices/platform/soc/1f00000.rtc/power/wakeup /sys/power/mem_sleep /sys/bus/usb/drivers/usb/unbind /sys/bus/usb/drivers/usb/bind /sys/class/leds/red:indicator/brightness /sys/class/leds/blue:indicator/brightness /sys/class/leds/green:indicator/brightness /sys/class/leds/white:flash/brightness /dev/rtc0 /sys/devices/platform/soc/1f03400.rsb/sunxi-rsb-3a3/axp221-pek/power/wakeup /sys/devices/platform/gpio-keys/power/wakeup"

M programs/sxmo_suspend.c => programs/sxmo_suspend.c +113 -101
@@ 17,6 17,7 @@
#include <linux/rtc.h>

const int WAKE_INTERVAL = 60; // wake every 60 seconds
const char *AUDIO_STATE_FILE = "/proc/asound/card0/pcm0p/sub0/status";
const char *POWER_STATE_FILE = "/sys/power/state";
const char *RTC_DEVICE = "/dev/rtc0";



@@ 35,12 36,14 @@ struct fbuf {
};

// Fn declarations
int     audio_playing();
time_t  convert_rtc_time(struct rtc_time *rtc);
void    die(const char *err, ...);
int     hook_post_suspend();
int     hook_pre_suspend();
int     hook_rtc_wake(time_t waketime);
void    lock_touch(Display *dpy, int screen);
int     read_file(char *filepath, struct fbuf *buf);
int     rtc_check_wake(time_t waketime);
void    rtc_close();
int     rtc_init();


@@ 53,7 56,7 @@ int     setup_rtc_wakeup();
void    suspend();
void    suspend_init();
void    suspend_reset();
void    writefile(char *filepath, char *str);
void    write_file(char *filepath, char *str);

// Variables
int rtc_fd = 0;


@@ 109,6 112,17 @@ time_t rtc_set_alarm() {
    return waketime;
}

int audio_playing() {
    struct fbuf buf;

    if (read_file((char *)AUDIO_STATE_FILE, &buf) == -1) {
        fprintf(stderr, "Could not read audio state\n");
        return 0;
    }

    return !(buf.len >= 6 && strncmp("closed", buf.buf, 6) == 0);
}

void set_wakeup_sources() {
    // None of the following files can be opened right now
//    // Disable all wakeup sources


@@ 126,42 140,42 @@ void set_wakeup_sources() {
//            wakeupsource->d_name
//        );
//        fprintf(stderr, "Disabling wakeup source: %s", wakeupsource->d_name);
//        writefile(wakeuppath, "disabled");
//        write_file(wakeuppath, "disabled");
//        fprintf(stderr, ".. ok\n");
//    }
//    closedir(wakeupsources);
//
    // Enable powerbutton wakeup source
    fprintf(stderr, "Enable powerbutton wakeup source\n");
    writefile(
    write_file(
        "/sys/devices/platform/soc/1f03400.rsb/sunxi-rsb-3a3/axp221-pek/power/wakeup",
        "enabled"
    );
//
//    // Enable IRQ wakeup source (incoming call) 5.8
//    fprintf(stderr, "Enable 5.8 IRQ wakeup source\n");
//    writefile(
//        "/sys/devices/platform/gpio-keys/power/wakeup",
//        "enabled"
//     );

    // Enable IRQ wakeup source (incoming call) 5.8
    fprintf(stderr, "Enable 5.8 IRQ wakeup source\n");
    write_file(
        "/sys/devices/platform/gpio-keys/power/wakeup",
        "enabled"
     );
//
//     // Enable IRQ wakeup source (incoming call) 5.9
//    fprintf(stderr, "Enable 5.9 IRQ wakeup source\n");
//    writefile(
//    write_file(
//        "/sys/devices/platform/soc/1c28c00.serial/serial1/serial1-0/power/wakeup",
//        "enabled"
//     );

    // Enable rtc wakeup source
    fprintf(stderr, "Enable rtc wakeup source\n");
    writefile(
    write_file(
        "/sys/devices/platform/soc/1f00000.rtc/power/wakeup",
        "enabled"
    );

    // E.g. make sure we're using CRUST
    fprintf(stderr, "Flip mem_sleep setting to use crust\n");
    writefile("/sys/power/mem_sleep", "deep");
    write_file("/sys/power/mem_sleep", "deep");
}

void die(const char *err, ...) {


@@ 207,87 221,61 @@ void screen_on() {
    system("xset dpms force on");
}

//void readinputloop(Display *dpy, int screen) {
//    KeySym keysym;
//    XEvent ev;
//    char buf[32];
//    fd_set fdset;
//    int xfd;
//    int selectresult;
//    struct timeval xeventtimeout = {1, 0};
//    xfd = ConnectionNumber(dpy);
//
//    for (;;) {
//        FD_ZERO(&fdset);
//        FD_SET(xfd, &fdset);
//        if (state == StateSuspendPending)
//            selectresult = select(FD_SETSIZE, &fdset, NULL, NULL, &xeventtimeout);
//        else
//            selectresult = select(FD_SETSIZE, &fdset, NULL, NULL, NULL);
//
//        if (FD_ISSET(xfd, &fdset) && XPending(dpy)) {
//            XNextEvent(dpy, &ev);
//            if (ev.type == KeyRelease) {
//                XLookupString(&ev.xkey, buf, sizeof(buf), &keysym, 0);
//                if (lastkeysym == keysym) {
//                    lastkeyn++;
//                } else {
//                    lastkeysym = keysym;
//                    lastkeyn = 1;
//                }
//
//// Commented out because I want the phone to wake immediately
////                if (lastkeyn < 3)
////                    continue;
//
//                lastkeyn = 0;
//                lastkeysym = XK_Cancel;
//                if (slept) postwake();
//                switch (keysym) {
//                    case XF86XK_AudioRaiseVolume:
//                        suspendpendingsceenon = state == StateNoInput;
//                        suspendpendingtimeouts = 0;
//                        state = StateSuspend;
//                        break;
//                    case XF86XK_AudioLowerVolume:
//                        if (state == StateNoInput) state = StateNoInputNoScreen;
//                        else if (state == StateNoInputNoScreen) state = StateNoInput;
//                        else if (state == StateSuspendPending && suspendpendingsceenon) state = StateNoInputNoScreen;
//                        else state = StateNoInput;
//                        break;
//                    case XF86XK_PowerOff:
//                        waketime = 0;
//                        state = StateDead;
//                        break;
//                }
//                syncstate();
//            }
//        } else if (state == StateSuspendPending) {
//            suspendpendingtimeouts++;
//            // # E.g. after suspendtimeouts seconds kick back into suspend
//            if (suspendpendingtimeouts > suspendtimeouts) state = StateSuspend;
//            syncstate();
//        }
//
//
//        if (state == StateDead) break;
//    }
//}
void read_input_loop(Display *dpy, int screen) {
    KeySym keysym;
    XEvent ev;
    fd_set fdset;
    char buf[512];
    int xfd;
    int selectresult;
    struct timeval xeventtimeout = {1, 0};
    xfd = ConnectionNumber(dpy);

    for (;;) {
        FD_ZERO(&fdset);
        FD_SET(xfd, &fdset);

        selectresult = select(FD_SETSIZE, &fdset, NULL, NULL, &xeventtimeout);

        if (FD_ISSET(xfd, &fdset) && XPending(dpy)) {
            fprintf(stderr, "selected...\n");
            XNextEvent(dpy, &ev);
            if (ev.type == KeyRelease) {
                XLookupString(&ev.xkey, buf, sizeof(buf), &keysym, 0);

                switch (keysym) {
                    case XF86XK_AudioRaiseVolume:
                        system("sxmo_vol.sh up");
                        break;
                    case XF86XK_AudioLowerVolume:
                        system("sxmo_vol.sh down");
                        break;
                    case XF86XK_PowerOff:
                        fprintf(stderr, "power button pressed\n");
                        // Done sleeping
                        return;
                }
            }
        }

//        screen_off();
    }
}

void set_pine_led(enum Color c) {
    writefile("/sys/class/leds/red:indicator/brightness", "0");
    writefile("/sys/class/leds/blue:indicator/brightness", "0");
    writefile("/sys/class/leds/green:indicator/brightness", "0");
    write_file("/sys/class/leds/red:indicator/brightness", "0");
    write_file("/sys/class/leds/blue:indicator/brightness", "0");
    write_file("/sys/class/leds/green:indicator/brightness", "0");

    if (c == Red) {
        writefile("/sys/class/leds/red:indicator/brightness", "1");
        write_file("/sys/class/leds/red:indicator/brightness", "1");
    } else if (c == Blue) {
        writefile("/sys/class/leds/blue:indicator/brightness", "1");
        write_file("/sys/class/leds/blue:indicator/brightness", "1");
    } else if (c == Purple) {
        writefile("/sys/class/leds/red:indicator/brightness", "1");
        writefile("/sys/class/leds/blue:indicator/brightness", "1");
        write_file("/sys/class/leds/red:indicator/brightness", "1");
        write_file("/sys/class/leds/blue:indicator/brightness", "1");
    } else if (c == Green) {
        writefile("/sys/class/leds/green:indicator/brightness", "1");
        write_file("/sys/class/leds/green:indicator/brightness", "1");
    }
}



@@ 328,16 316,16 @@ void suspend() {
        time_t waketime = rtc_set_alarm();

//        die("don't sleep :)");
        writefile((char *)POWER_STATE_FILE, "mem");
        write_file((char *)POWER_STATE_FILE, "mem");

        //---- program blocks here due to sleep ----- //
        // Just woke up again
        fprintf(stderr, "Suspend woke up\n");
        fprintf(stderr, "Resetting usb connection to the modem\n");
        writefile("/sys/bus/usb/drivers/usb/unbind", "3-1");
        writefile("/sys/bus/usb/drivers/usb/bind", "3-1");
        write_file("/sys/bus/usb/drivers/usb/unbind", "3-1");
        write_file("/sys/bus/usb/drivers/usb/bind", "3-1");
        fprintf(stderr, "Lower scan interval for quicker reconnection to wireless network\n");
        writefile("/sys/module/8723cs/parameters/rtw_scan_interval_thr", "1200"); //ms
        write_file("/sys/module/8723cs/parameters/rtw_scan_interval_thr", "1200"); //ms
        //^-- this will be undone again by a networkmanager hook after connection has been established
        //    or by a delayed script if no connection can be established after a while (to conserve battery)



@@ 356,7 344,25 @@ void suspend() {

}

void writefile(char *filepath, char *str) {
// Returns -1 on error, 0 on success
int read_file(char *filepath, struct fbuf *buf) {
    FILE* f = fopen(filepath, "r");
    if (!f)
        return -1;

    buf->buf = malloc(4096);
    buf->len = 0;

    int nread = 0;
    while ((nread = fread(buf->buf + buf->len, 1, 4096, f)) > 0) {
        buf->len += nread;
        buf->buf = realloc(buf->buf, buf->len + 4096);
    }

    return 0;
}

void write_file(char *filepath, char *str) {
    int f;
    f = open(filepath, O_WRONLY);
    if (f != -1) {


@@ 405,16 411,22 @@ int main(int argc, char **argv) {
    XSync(dpy, 0);
    lock_touch(dpy, screen);

    hook_pre_suspend();

    suspend_init();

    suspend();
//    readinputloop(dpy, screen);
    set_pine_led(Off);

    suspend_reset();

    hook_post_suspend();
    if (audio_playing()) {
        // Don't suspend if audio is playing
        set_pine_led(Blue);
        screen_off();
        read_input_loop(dpy, screen);
        screen_on();
        set_pine_led(Off);
    } else {
        hook_pre_suspend();
        suspend_init();
        suspend();
        suspend_reset();
        hook_post_suspend();
    }

    fprintf(stderr, "Suspend terminating normally\n");
    return 0;