Use RPi to change HDMI-Input to non-CEC device

10 posts
by Therket » Sat Aug 25, 2012 12:53 pm
Hi there,

I have the following setup:
0) TV
1) AVR
1.2) RPi
1.3) Satellite TV (non-CEC)
1.4) PS3 (CEC)

While the AVR does have a an option to default to HDMI 3 when in standby, it changes to HDMI 2 or HDMI 4 if I start up the RPi or the PS3 (which is all fine). The problem is, I can't change back to HDMI 3 after shutting down RPi / PS3 without starting the AVR first and use AVR's remote to change HDMI-Input. In most cases, I don't want to use the AVR for watching TV, the TV's speaker are fine for that..

So, I had the following idea "Use the RPi to send an appropriate CEC command, so the AVR switches to HDMI 3, although the RPi is still running". Basically, it works! But I got stuck to make is comfortable as I want to have it.

First, what is possible right now:
With the latest XBian-Image (Raspbmc does not work, because cec-client is not included), I can connect via ssh to the RPi and execute the one liner:
Code: Select all
echo "tx 4f 82 13 00" | cec-client -s

What it does: It starts cec-client in single execution mode (see cec-client --help for details) and passes the transmission command to it. Honestly, I don't know, what 0x4f stands for, 0x82 is the "Active Source" command and 13 the Port to change to.
This is not perfect, as it starts a new cec-client and messes up the XBMC-CEC implementation. But it's a starting point.

Basically, what I want to achieve is to have a single command in XBMC-UI that executes the command and changes AVR's input.
I think, I have two options here:
1) Execute the command above as a shell script.
2) Use libCEC-API from Python directly

The first option seemed easier for me, so I wrapped it in a simple python script (and an additional shell script, shouldn't be necessary):
Code: Select all
root@XBian:~# cat
echo "tx 4f 82 13 00" | cec-client -s

root@XBian:~# cat
import os
os.system('sh /root/')

Using the XBMC-FileBrowser, I am able to execute from my remote now, great :-) Sadly, when adding the script to the favorites, it's not executed?!

Anyway, I think, that trying to go with the second option would be better anyway. But I'm no python expert, so I'd really appreciate, if anyone could give me some hints on how to make use of the libcec api from python.


PS: The basic idea can be extended of course. It'll be great to set the RPi in a "satellite receiver mode" and pass all incoming CEC commands to the receiver via gpio. But that will be a (too) long way for me..
Posts: 12
Joined: Mon Aug 06, 2012 3:48 pm
by DMcK » Wed Sep 26, 2012 8:07 pm
Hopefully, I'll also be using CEC to change my inputs based on python scripts too. I'm waiting for raspmc to issue RC5 before I start. So it will be a couple of days or so. Hopefully by the weekend. I'm also a beginner with python, but if I figure it out, I'll post back.

In the meantime, I was doing some searching on CEC and came across this website. It allows you to either see what a CEC message should do or create a CEC message by clicking the source/destination and selecting a feature with parameters.

Your message (4F:82:13:00) shows it's Broadcast message sent from Playback 1 and changes the source. I suppose you could target the message to the TV (click TV for destination and then click the up arrow). It gives 40:82:13:00 as a CEC message.

Posts: 20
Joined: Sun Jul 01, 2012 4:51 am
by Therket » Wed Sep 26, 2012 8:46 pm
Thanks for your reply!

In the meantime, I tried to use libcec but eventually failed. While I came accross Python CTypes, I gave up. Redefining a complete C header file in Python doesn't seem the right beginner task for me.

But that CEC-O-MATIC is really interesting. With it's help, I'll try to understand, how the PS3 advertises itself to the TV. Then I'll try to emulate the advertise the sat receiver using cec-client (on RPi). If that worked, it would be even better - having the sat receiver in TV's list of known sources would be really great!

Unfourtenately, I haven't understood how the mapping between logical and physical addresses works yet. Maybe it's not a good idea to identify as "Playback 1", because it might be used by another device already. There must be something like "Is Playback 1 free? No? Ok, then I am Playback2".

I'll look into this, when I find some time.

Posts: 12
Joined: Mon Aug 06, 2012 3:48 pm
by drmouse » Tue Oct 02, 2012 3:56 pm

I have looked into this before for another project (an Arduino-based CEC dongle for a PC). One of the "problems" of CEC is it uses non-CEC mapping from the start. Basically, there is a separate line, can't remember what it's called, over which the TV & source communicate things like display modes, and it is over this line that a unique address is initially advertised. Then using the CEC protocol it sets up a mapping between this address and a CEC identifier.

So, for my implementation, I would have needed to hook into this extra line as well as the CEC line to set up the correct mapping (fortunately you can get this address from a PC via other means, so I used that and passed the info over USB in it's initialisation process).

If you want to get the device correctly set up (Sky box by any chance?) you will need to find this address. I think it's similar to an ethernet MAC address, so it wont change. Once you have that, it would take some extra code at least in the CEC client, then mappings to another control method. There is documentation out there on the CEC protocol, although it wasn't that easy to find when I was looking. Luckily it was a slow week at work....

I know I am being rather vague here, but it has been ages since I have looked at this. I eventually gave up on the project as being "not worth it".

For your simple usage as described, I would suggest looking at the XBMC/XBian sources to add a "function" to send the "Switch source" command. Maybe a small XBMC addon would do the job?
Posts: 20
Joined: Mon Sep 03, 2012 2:28 pm
by Therket » Sun Oct 07, 2012 11:32 am
Made some progress here :-)

Disclaimer: I'm a newbie to linux and most of this has been explored by try and error. While things work, they might be just wrong, have side effects and so on. Suggestions to improve things are welcome!

I focused on the "register sat tuner in TV although it's not really a cec-device" idea instead of the first approach "switch hdmi input by sending raw cec commands".

After some tests, I finally found that
Code: Select all
echo "pa 13 00" | cec-client -t t -o "Sat Tuner"
is all I need.
It starts a new cec-client process with options "type = tuner" and "osdname = Sat Tuner". There is one 'issue' with cec-client: It 'honestly' reports it's true physical address (1200 im case) to the cec channel. To workaround that, I'm issuing the "pa 13 00" command to change the physical address to 1300.

To start this command automatically, I wrapped it in a simple shell script and created a new upstart file "/etc/init/cecsat.conf" with the following content:
Code: Select all
# SAT CEC Device

description     "sat cec daemon"
author          "None"

start on (started dbus and started mountall)
stop on (runlevel [!2345])


exec /usr/bin/

This works and gives what I needed: I have a nice sat icon on my tv and can change to it, when needed. Xbmc (raspbmc) and PS3 still work fine.

Some potential issues (and possible solutions):
- cec-client first reports it's real physical address -> I think, we need to compile a patched / different version of cec-client, which accepts an additional command line argument "fake pa" and overwrites "GetPhysicalAddress()
- startup script has the very same startup conditions as xbmc itself. Maybe this causes problems, if xbmc is started before our script.

The good thing about this solution. We registered a new device and we can see key presses on TV remote being sent to exactly this instance. It responds with "sending abort", but I think, this is a starting point to pass those to lirc.

Posts: 12
Joined: Mon Aug 06, 2012 3:48 pm
by nicolas33 » Fri Nov 16, 2012 5:21 pm

Excuse me for disturbing you. I would like to ask you a question about libCEC.
I have a raspberry and I would use my TV remote to make a simple navigation on a web page or an application (top, bottom, left, right, validate) through the HDMI / CEC, after startx on my raspberry.
Is this possible with this library? Do you have any advice or give me tracks to get there, it would be very nice of you.

With thanks in advance.
Posts: 8
Joined: Fri Nov 16, 2012 5:16 pm
Location: France
by adam_t_watson » Sun Dec 02, 2012 9:15 am
did you get anywhere with this - i need a starting point with cec
what version of Linux is the pi running etc?
Posts: 1
Joined: Sun Dec 02, 2012 9:13 am
by migube » Tue Dec 25, 2012 9:56 pm
would you have a compiled version (or instructions) for Raspbmc to get the cec-client there?
Posts: 29
Joined: Tue Jul 17, 2012 7:02 am
by eth0 » Wed Dec 26, 2012 12:57 am
I've got the same issue with when I call "cec-client" it kills the XBMC CEC client and I have to restart XBMC - annoying. Have you found a solution? From looking (quickly) through the CEC code in XBMC it looks like there's no way around it. I have opened a feature request on the forums to send CEC commands via the JSON API to the built-in CEC client, feel free to bump up the thread ;)
Posts: 6
Joined: Fri Dec 21, 2012 11:41 pm
by drmouse » Thu Jan 17, 2013 6:09 pm
Therket wrote:- startup script has the very same startup conditions as xbmc itself. Maybe this causes problems, if xbmc is started before our script.

This is a simple one to fix. You just need to add a dependency to your xbmc upstart script. I believe (not being 100% familiar with upstart) you would just need change the start on line to:
Code: Select all
start on (started dbus and started mountall and started cecsat)
Posts: 20
Joined: Mon Sep 03, 2012 2:28 pm