Reputation: 21
When i write to a linux driver / device, in this case i want to put the embedded linux device to sleep:
echo "mem" > /sys/power/state
I get an error on the terminal if the above command fails
[ 2593.061030] dpm_run_callback(): elan_touch_suspend+0x0/0x114 returns 1
[ 2593.067578] PM: Device 0-0015 failed to suspend: error 1
[ 2593.072994] PM: Some devices failed to suspend, or early wake event detected
[ 2593.107845] ==== calc_soc_by_voltageMethod E60U22 ====
And i do this the same in c++:
int fd2 = open("/sys/power/state", O_RDWR);
write(fd2, "mem", 3);
close(fd2);
If the above command fails, i get the same error on the terminal. now i want to get this error as a string in c++, in shell i can do something like this:
echo "mem" > /sys/power/state 2>/tmp/sleep_error
But i cant figure this out in c++, I need to to try one more time if it fails
What I tryied:
Capturing cerr
of the whole program, with freopen
doesn't work. When I write to the device from another terminal, and do cat /dev/stderr
from another, i get the output in the second one, I tryied to use it:
char byte[1000];
int stderrdevice = open("/dev/stderr", O_RDONLY | O_NOCTTY);
int fd2 = open("/sys/power/state", O_RDWR);
write(fd2, "mem", 3);
close(fd2);
ssize_t size = read(stderrdevice, &byte, 1000);
printf("Read byte %s\n", byte);
This doesn't work too. Any resources, documentation related to this are welcome
Upvotes: 1
Views: 259
Reputation: 21
Thanks everyone for help and responding. user17732522 and Nate Eldredge were right. What i was trying to get was the kernel ring buffer, that was printing out to the serial connection. The same thing was in dmesg. I ended up using klogctl
to get the errors. I couldn't get only the last line of dmesg with other klogctl options, and the code is a bit chaotic, but here is what I finally used:
bool continueSleeping = true;
int count = 0;
while (continueSleeping == true) {
// https://linux.die.net/man/3/klogctl
klogctl(5, NULL, 0);
log("Trying sleep");
std::this_thread::sleep_for(std::chrono::milliseconds(100));
int fd2 = open("/sys/power/state", O_RDWR);
int status = write(fd2, "mem", 3);
close(fd2);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
log("After sleep");
// get dmesg, and then only lines containing <3>
char *logs_data;
ssize_t len = klogctl(10, NULL, 0);
logs_data = (char *)malloc(len);
klogctl(3, logs_data, len);
vector<string> dmesgErrorsVec;
boost::split(dmesgErrorsVec, logs_data, boost::is_any_of("\n"),
boost::token_compress_on);
// to show whole dmesg
//log("dmesg: " + (string)logs_data);
free(logs_data);
string dmesgErrors;
for (string line : dmesgErrorsVec) {
if (line.find("<3>") != std::string::npos) {
// tesdt
dmesgErrors.append(line);
dmesgErrors.append("\n");
}
}
dmesgErrorsVec.clear();
if (status == -1 or
dmesgErrors.find("PM: Some devices failed to suspend") != std::string::npos) {
log("Failed to suspend, dmesg errors:\n" + dmesgErrors);
log("status: " + to_string(status));
CEG();
count = count + 1;
if (count == 5) {
log("5 failed attemts at suspending, sleep a little longer...");
smartWait(10000);
} else if (count == 15) {
log("15 failed attempts at sleeping...");
// Write to fbink here a sad message
} else {
smartWait(3000);
}
} else {
// Exiting this sleeping hell
log("Tryied going to sleep " + to_string(count) + "times");
continueSleeping = false;
}
}
log("Sleep finished, Exiting going to sleep");
Upvotes: 1