-
-
Save Orochimarufan/d8e42cfaa32c2cdd13640dad6a10b847 to your computer and use it in GitHub Desktop.
#include <stdlib.h> | |
#include <stdio.h> | |
#include <errno.h> | |
#include <dirent.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <sys/stat.h> | |
#include <sys/utsname.h> | |
#include <fcntl.h> | |
int gpio_offset() { | |
struct utsname ver; | |
int major, minor; | |
uname(&ver); | |
sscanf(ver.release, "%d.%d.", &major, &minor); | |
if (major == 4) { | |
// until 4.15 | |
if (minor < 16) | |
return 21; | |
} | |
// 4.16 + | |
return 27; | |
} | |
void die_usage(const char *prog) { | |
printf( "spken (c) 2018 Taeyeon Mori\n" | |
"CHUWI Hi10 Pro speaker enabler\n" | |
"\n" | |
"Usage: %s [enable:0/1]\n" | |
"\n" | |
"If omitted, speakers are enabled\n", | |
prog); | |
exit(1); | |
} | |
void die(const char *msg) { | |
perror(msg); | |
exit(errno); | |
} | |
int main(int argc, const char**argv) { | |
char pathbuf[256]; | |
int enable = 1; | |
int fd, gpio; | |
DIR *dir; | |
struct dirent *ent; | |
// Check argv | |
if (argc > 2) | |
die_usage(argv[0]); | |
else if (argc == 2) { | |
if (argv[1][0] == '1') | |
; | |
else if (argv[1][0] == '0') | |
enable = 0; | |
else | |
die_usage(argv[0]); | |
if (argv[1][1] != 0) | |
die_usage(argv[0]); | |
} | |
// find chip | |
dir = opendir("/sys/devices/platform/INT33FF:01/gpio"); | |
if (!dir) | |
die("Could not open INT33FF:01/gpio in sysfs"); | |
while (1) { | |
ent = readdir(dir); | |
if (!ent) { | |
if (errno) | |
die("Could not list INT33FF:01/gpio in sysfs"); | |
else { | |
puts("No gpiochip in INT33FF:01!"); | |
exit(2); | |
} | |
} | |
if (!strncmp(ent->d_name, "gpiochip", 8)) | |
break; | |
} | |
//printf("Found gpiochip: %s\n", ent->d_name); | |
closedir(dir); | |
// find number | |
gpio = atoi(ent->d_name + 8) + gpio_offset(); | |
printf("Using gpio %d\n", gpio); | |
if (snprintf(pathbuf, 255, "/sys/class/gpio/gpio%d/value", gpio) < 0) | |
die("Could not build path name"); | |
// Export | |
if (access(pathbuf, F_OK)) { | |
fd = open("/sys/class/gpio/export", O_WRONLY); | |
if (fd < 0) | |
die("Could not open /sys/class/gpio/export"); | |
if(dprintf(fd, "%d", gpio) < 0) | |
die("Could not export GPIO"); | |
close(fd); | |
} | |
// Open | |
fd = open(pathbuf, O_WRONLY); | |
if (fd < 0) | |
die("Could not open gpio pin"); | |
if (dprintf(fd, "%d", enable) < 0) | |
die("Could not write gpio pin"); | |
close(fd); | |
return 0; | |
} |
For some reason the pin offset changed. Code is updated to work with 4.16
Hardcoding numbers is a hack in the first place, so it's not all too surprising it broke. Unfortunately I'm not aware of a userspace solution to properly extract the pin number from the DSDT AND map it to the linux subsystem numbers...
Thank you so much for the update. I am not very deep in this pin number thing but how do you currently find it out maybe I could then try to find a way to get it from userspace. Maybe something like this could work (if you can find the correct PIN number in the output)?
Extract ACPI tables (as root)
# cat /sys/firmware/acpi/tables/DSDT > dsdt.dat
Decompile
# iasl -d dsdt.dat
Maybe the needed info is in the dsdt.dsl??
Info taken from Arch Wiki (DSDT).
Well yes, but you'll still have to somehow map it to the numbering system linux uses. I originally found out by writing a patch to the kernel driver, since driver code can get the info pretty easily; see the earlier discussion in danielotero/linux-on-hi10#8
Hi,
first of all, thanks for your efforts to make sound working. I had your solution in place runing on my Arch Linux system and it worked well. Yesterday kernel 4.16.2 arrived in Arch Linux and now enabling the speaker via GPIO pin no longer works. It is now telling
Could not write gpio pin: Operation not permitted
.As far as I could find out
/sys/class/gpio/<exported pin>/direction
has valuein
which means we can not write because write is only allowed when direction isout
as stated here:I don't know if they made something wrong with the kernel or a small rewrite of your code is needed. Anyway it would be nice if you could spend a minute of your time to take a look again what is going on. - Thanks in advance!
Here is my output of
ls -l /sys/class/gpio/
after boot.So
gpiochip341 -> ../../devices/platform/INT33FF:01/gpio/gpiochip341
is the relevant part (on this boot).Tried (as root) to switch direction from
in
toout
and could then write the value to 1 but that does not enable sound again.gpio341
was exported successfully[root@arch]# echo "out" > /sys/class/gpio/gpio341/direction
still no sound
I just wante to note that I blacklisted
snd_hdmi_lpe_audio
to enable sound at all but I think this is not relevant to the problem.Regards
Peter