Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // control charging of battery on apple M1
- // tested on macbook pro 2021 model
- // works on linux
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include <errno.h>
- #include <syslog.h>
- #include <string.h>
- #include <liburing.h>
- enum charge_mode {
- CHARGE_AUTO,
- CHARGE_INHIBIT_CHARGE,
- CHARGE_FORCE_DISCHARGE,
- };
- static const char *chargemodes[] = {
- "auto",
- "inhibit-charge",
- "force-discharge",
- };
- #define CAPACITY_FILE \
- "/sys/class/power_supply/macsmc-battery/capacity"
- #define CHARGE_BEHAVIOR_FILE \
- "/sys/class/power_supply/macsmc-battery/charge_behaviour"
- #define LOWER_CHARGE 70
- #define UPPER_CHARGE 90
- #define LOGNAME "charge-ctl"
- static enum charge_mode last_mode = -1;
- static int write_file(struct io_uring *ring, const char *filename,
- const char *cap)
- {
- struct io_uring_sqe *sqe;
- struct io_uring_cqe *cqe;
- int ret;
- sqe = io_uring_get_sqe(ring);
- io_uring_prep_openat_direct(sqe, -1, filename, O_WRONLY, 0, 0);
- sqe->flags |= IOSQE_IO_LINK | IOSQE_CQE_SKIP_SUCCESS;
- sqe = io_uring_get_sqe(ring);
- io_uring_prep_write(sqe, 0, cap, strlen(cap), 0);
- sqe->flags |= IOSQE_IO_HARDLINK | IOSQE_FIXED_FILE;
- sqe = io_uring_get_sqe(ring);
- io_uring_prep_close_direct(sqe, 0);
- sqe->flags |= IOSQE_CQE_SKIP_SUCCESS;
- ret = io_uring_submit(ring);
- if (ret != 3)
- return 1;
- ret = io_uring_wait_cqe(ring, &cqe);
- if (ret)
- return 1;
- if (cqe->res < 0)
- return 1;
- io_uring_cqe_seen(ring, cqe);
- return 0;
- }
- static int read_file(struct io_uring *ring, const char *filename,
- char *cap, size_t size)
- {
- struct io_uring_sqe *sqe;
- struct io_uring_cqe *cqe;
- int ret;
- sqe = io_uring_get_sqe(ring);
- io_uring_prep_openat_direct(sqe, -1, filename, O_RDONLY, 0, 0);
- sqe->flags |= IOSQE_IO_LINK | IOSQE_CQE_SKIP_SUCCESS;
- sqe = io_uring_get_sqe(ring);
- io_uring_prep_read(sqe, 0, cap, size, 0);
- sqe->flags |= IOSQE_IO_HARDLINK | IOSQE_FIXED_FILE;
- sqe = io_uring_get_sqe(ring);
- io_uring_prep_close_direct(sqe, 0);
- sqe->flags |= IOSQE_CQE_SKIP_SUCCESS;
- ret = io_uring_submit(ring);
- if (ret != 3)
- return 1;
- ret = io_uring_wait_cqe(ring, &cqe);
- if (ret)
- return 1;
- if (cqe->res < 0)
- return 1;
- io_uring_cqe_seen(ring, cqe);
- return 0;
- }
- static void set_charge_mode(struct io_uring *ring, enum charge_mode mode)
- {
- if (mode == last_mode)
- return;
- if (write_file(ring, CHARGE_BEHAVIOR_FILE, chargemodes[mode]))
- exit(EXIT_FAILURE);
- last_mode = mode;
- openlog(LOGNAME, LOG_PID, LOG_USER);
- syslog(LOG_USER | LOG_INFO, chargemodes[mode]);
- closelog();
- }
- int main(int argc, char **argv)
- {
- int ret, option, limit = UPPER_CHARGE;
- struct io_uring ring;
- pid_t pid, sid;
- while ((option = getopt(argc, argv, "l:uh")) != -1) {
- switch (option) {
- case 'h':
- puts("help");
- puts("-l limit capacity");
- exit(EXIT_SUCCESS);
- case 'l':
- limit = atoi(optarg);
- printf("limit: %d\n", limit);
- break;
- default: /* '?' */
- puts("unknown option");
- exit(EXIT_FAILURE);
- }
- }
- pid = fork();
- if (pid < 0)
- exit(EXIT_FAILURE);
- if (pid > 0)
- exit(EXIT_SUCCESS);
- umask(0);
- sid = setsid();
- if (sid < 0)
- exit(EXIT_FAILURE);
- if ((chdir("/")) < 0)
- exit(EXIT_FAILURE);
- close(STDIN_FILENO);
- close(STDOUT_FILENO);
- close(STDERR_FILENO);
- ret = io_uring_queue_init(4, &ring, 0);
- if (ret) {
- fprintf(stderr, "Queue init failed: %d\n", ret);
- exit(EXIT_FAILURE);
- }
- ret = io_uring_register_files_sparse(&ring, 1);
- if (ret) {
- fprintf(stderr, "File table register failed: %d\n", ret);
- exit(EXIT_FAILURE);
- }
- while (1) {
- char cap[6];
- int icap;
- if (read_file(&ring, CAPACITY_FILE, cap, sizeof(cap) - 1))
- break;
- icap = atoi(cap);
- if (icap < LOWER_CHARGE)
- set_charge_mode(&ring, CHARGE_AUTO);
- else if (icap > limit)
- set_charge_mode(&ring, CHARGE_FORCE_DISCHARGE);
- else
- set_charge_mode(&ring, CHARGE_INHIBIT_CHARGE);
- sleep(30);
- }
- exit(EXIT_SUCCESS);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement