6

So I can use "tvservice -o" to turn off the HDMI on the raspberry Pi, and "tvservice -p" to turn it back on. After turning it back on I apparently need to do "fbset -depth 8 && fbset -depth 16" to re-enable the frame buffer and then force an X11 redraw.

My question is, how do I do this in C? I have an X11 application and I can manage the X11 redraw no problem, but how do I disable/re-enable HDMI in C, and how do I re-enable the frame buffer after re-enabling HDMI?

To give background, I have a headless application running as a sort of media server, controlled by an Android app. Currently I am permanently disabling the turning off of HDMI after a timeout. However to save energy I would like to disable the HDMI when the app is not in use, and then turn it back on and display the RPi application on screen using libcec to determine when the TV is using the RPi's HDMI connection to turn HDMI on and off.

Christophe Vu-Brugier
  • 2,645
  • 26
  • 21
AlastairG
  • 4,119
  • 5
  • 26
  • 41

5 Answers5

7

If you want to go for pure C, look at the source code for tvservice, which is a C program. It can be found at github. It appears to be using the vc_tv_hdmi_power_on_preferred(); function defined in #include "interface/vmcs_host/vc_tvservice.h"

If you decide to call the tvservice program like in @moffeltje's answer, you could use the execl() it's a little safer - you have to give full path to the binary. (With execlp you can also have control over environment variables):

pid_t pid;


pid = fork();
if (0 == pid) {
    execl("/opt/vc/bin/tvservice", "-p", NULL);
}
if (-1 == pid) {
    // Handle error here, close program?
}
Prof. Falken
  • 24,226
  • 19
  • 100
  • 173
  • Lovely, thanks. Any idea where to find the source code for fbset? I suspect it uses ioctls and without the documentation or example code on the frame buffer device I'm a bit stuck. – AlastairG Mar 30 '15 at 16:16
  • @AlastairG, yes, it *should* be in util-linux package: https://www.kernel.org/pub/linux/utils/util-linux/ but if not, just google for it, there is a busybox implementation too out there. – Prof. Falken Mar 30 '15 at 18:10
2

You can use the system() command to use those commands you described.

int main(){

   //some code before disable hdmi
   system("tvservice -o");

   //do somethings when HDMI is disabled

   //turn HDMI back on
   system("tvservice -p");
   system("fbset -depth 8 && fbset -depth 16");

   return 0;

}
moffeltje
  • 4,521
  • 4
  • 33
  • 57
  • As a general rule I avoid system. I prefer execl() etc., but for preference I'd rather embed the functionality in my own program. – AlastairG Mar 30 '15 at 16:18
2

From https://gist.github.com/AGWA/9874925 I found the usefulness of chvt. So I suggest calling the shell commands

hdmioff() { tvservice -o; }
hdmion() { tvservice -p; sudo chvt 1; sudo chvt 7; }

with system().

Frank Breitling
  • 942
  • 1
  • 10
  • 27
  • 1
    In my current configuration I need to change the chvt commands: hdmion() { tvservice -p; sudo chvt 7; sudo chvt 1; } – alvaropg Oct 10 '18 at 12:46
0

I've found

xset dpms force on

to refresh the xorg stuff after doing a tvservice -o and bringing it back with tvservice -p. Doing it fbset way didn't work for me very well.

Entrabiter
  • 752
  • 7
  • 13
-1

I had the best results with cec-client.

sudo apt install cec-utils

Turn monitor off:

echo "standby 0" | cec-client -s -d 1

Turn monitor on:

echo "on 0" | cec-client -s -d 1

  • I asked how to do it in C, not scripting/command line. Moreover this just sends CEC commands and doesn't actually change the physical HDMI port status (AFAIK). – AlastairG Aug 10 '16 at 08:02