Infrared receiver/transmitter support


From SamyGO
Jump to: navigation, search

This wiki page is not just a description of how to do things. Although my efforts in the area of IR control have resulted in a working configuration, there's still quite some room for improvement. If you think you can help, please do so.


A few years ago I bought a B-series Samsung TV (UE40B7020). Apart from a very good display, it also has a very poor sound quality. What do you expect from a <30mm thick housing, with the speakers facing backwards. To counter this not-so-good feature, I hooked the TV up to a home theatre system, incorporating a BluRay player (HT-BD8200, also from Samsung. It has a sleek design that nicely matches my TV). Both devices need to be switched on through an IR-remote control. Once running, when the TV is switched off again, the BluRay player shuts down automatically, together with the TV, at least when the TV's software is properly configured.

Hmmm .. I want them to switch on with a single button-push as well. Since both devices only respond to IR signals when switched off, there are two possible options to tackle this problem.

  1. Buy a multi-platform, multi-protocol remote. Logitech has some, with list prices ranging from $70,- to $350,-.
    Pro: One shiny remote for a multitude of devices.
    Con: Yet another remote floating around in your living room. Price may be an issue. It's just dull and boring.
  2. Buy a small USB infrared receiver/transmitter, teach the TV how to control it, and let your TV do the switching on of the home theatre.
    Pro: Cheap (I bought one for $40,- from iguanaworks). One remote for a multitude of devices. You can still use your original remote. Yet another way to be tinkering with your TV.
    Con: Nothing!

For the SamyGO community, the second is of course the only real option.

Here's how it's done:

What you need

Before we go any futher, this wiki describes the use of the iguanaworks USB IR receiver/transmitter. For any other type and/or brand, parts of this wiki may be helpful, but it is by no means a complete guide, then.

Required hardware:

  1. USB-IR transmitter/receiver. You can order it from IguanaWorks.
    USB transmitter/receiver from iguanaworks
  2. USB A-male A-female cable, at least 0.5m in length. Without it your transmitter will be tucked away behind your TV, probably without being able to send/receive IR signals.
  3. B-series Samsung TV, with telnet access and a free USB-port. Automated startup follows through an edit of the SamyGO.sh script. The actions described in this wiki may work for other models as well, but haven't been tested.

Required software:

  1. Iguanaworks driver code
  2. libpopt source
  3. libusb-0.1 [1] or, alternatively, use the libusb source provided by Samsung. It is deeply hidden in 10_UE46B8000.zip, available from Samsung. I did the last.
  4. libusb-1.0 [2]
  5. LIRC [3]
  6. Cross-compilation toolchain for your TV, including at least the kernel headers. See SamyGO wiki for details.

What you do

Preparation of the software

In this example, the source code packages were installed side by side, in the same top-level directory:

libusb
popt-1.16
iguanaIR-1.0.1  
libusb-1.0.8  
lirc-0.9.0

Build of libpopt.so

  • Unpack the source code for libpopt.
  • cd to the popt source dir, run the configure script, define the host type for cross-compilation (mine is arm-SamyGO-linux-gnueabi):
./configure --host=arm-SamyGO-linux-gnueabi
  • run make
  • after successful completion, libpopt.so.0.0.0 resides in .libs/ in the source tree.

Build of libusb-0.1

  • Unpack the source code for libusb-0.1
  • For Samsung's libusb, edit the Makefile, to enable cross-compilation. Set the -I option to point to the right header subdir.The relevant lines should look like this:
CC = arm-SamyGO-linux-gnueabi-gcc
INC = -I./Inc
  • run make
  • After successful completion, libusb.so resides in the top-level build directory.

Build of libusb-1.0

  • Unpack the source code for libusb-1.0
  • run configure, set host and installation prefix. In my machine this is /usr/local/arm-SamyGO-linux-gnueabi, YMMV:
./configure --host=arm-SamyGO-linux-gnueabi --prefix=/usr/local/arm-SamyGO-linux-gnueabi
  • run make
  • run make install. This step is needed because otherwise the build of igdaemon fails miserably.
  • after completion, the library and links reside in $prefix/lib, headers in $prefix/include/libusb-1.0

Build of igdaemon

  • Unpack the iguanaIR source package
  • Locate the file iguanaIR.h
  • Change the line reading
#define IGSOCK_NAME "/dev/iguanaIR/"

to

#define IGSOCK_NAME "/dtv/dev/iguanaIR/"
  • Configure the igdaemon build. Because some dependencies for libusb-1.0 for ARM are normally not installed on an x86-64 or x86 linux system, I set up a script for the configuration of igdaemon and libiguanaIR. Normally, I try and avoid the installation of ARM executables and libraries as much as I can, so I don't have libpopt and libusb installed. The only exception is libusb-1.0. It had to be installed to prevent interference with the native libusb (x86-64).This is the script:
BUILD_ROOT=`pwd`

# exports for headers and libraries.

export CPPFLAGS="-I/usr/local/arm-SamyGO-linux-gnueabi/include -I$BUILD_ROOT/../libusb/Inc -I../popt-1.16"
export LDFLAGS="-L/usr/local/arm-SamyGO-linux-gnueabi/lib -L$BUILD_ROOT/../libusb -L../popt-1.16/.libs" 

# exports for rpl_malloc() and rpl_realloc() macros

export ac_cv_func_malloc_0_nonnull=yes
export ac_cv_func_realloc_0_nonnull=yes
./configure --host arm-SamyGO-linux-gnueabi --disable-python
  • run make
  • After completion, the required binaries reside in the top-level build directory.
  • to be able to build LIRC, create the following link in the top-level build directory:
ln -s libiguanaIR.so.0 libiguanaIR.so

Build of LIRC with Iguanaworks support

  • Unpack the LIRC source package
  • LIRC redefines some datatypes, which during the build leads to errors.
  • Locate the file include/linux/types.h in the kernel source tree and comment out the lines described below (I know, not a very elegant way of getting things to work, but after two days of searching I got fed up and decided to do it the blunt way. This edit holds at least for kernel 2.6.18):
[marcelr@laptop46 linux]$ diff types.h.orig types.h 
21,22c21,22
< typedef __kernel_fd_set		fd_set;
< typedef __kernel_dev_t		dev_t;
---
> /*typedef __kernel_fd_set		fd_set;*/
> /*typedef __kernel_dev_t		dev_t;*/
24,25c24,25
< typedef __kernel_mode_t		mode_t;
< typedef __kernel_nlink_t	nlink_t;
---
> /*typedef __kernel_mode_t		mode_t;*/
> /*typedef __kernel_nlink_t	nlink_t;*/
51,52c51,52
< typedef __kernel_uid_t		uid_t;
< typedef __kernel_gid_t		gid_t;
---
> /*typedef __kernel_uid_t		uid_t;*/
> /*typedef __kernel_gid_t		gid_t;*/
140c140
< typedef unsigned long blkcnt_t;
---
> /*typedef unsigned long blkcnt_t;*/
  • Configure LIRC. Like for igdaemon, quite some options need to be set, so again a script is easier:
#! /bin/sh

export CPPFLAGS="-I/home/marcelr/build/iguanaworks/iguanaIR-1.0.1"
export LDFLAGS="-L/home/marcelr/build/iguanaworks/iguanaIR-1.0.1 -liguanaIR"

./configure --with-kerneldir=/home/marcelr/build/ue40b7020/toolchain/build/src/linux --host=arm-SamyGO-linux-gnueabi \
            --with-driver=iguanaIR --with-transmitter
  • You may encounter this error:
checking for Linux kernel sources... make: arm_v6_vfp_le-gcc: Command not found
/tmp/LIRCMF.tFf5zE:1404: *** mixed implicit and normal rules.  Stop.
make: arm_v6_vfp_le-gcc: Command not found
/tmp/LIRCMF.tFf5zE:1404: *** mixed implicit and normal rules.  Stop.
./configure: line 15357: test: -eq: unary operator expected

This you can ignore, because there will be no kernel module for this particular device.

  • run make.
  • after successful completion, the required binaries reside in the daemons/ directory.

Installation of the software on the TV

To make things work the following binaries need to be transferred to the TV (I put them in /mtd_rwarea/iguanaworks/) Any place will do, as long as the filesystem you install it on supports links. RFS does. VFAT doesn't. When you decide to install stuff in other places, be aware of the fact that some source code and scripts will require editing.

# pwd
/mtd_rwarea/iguanaworks
# ls -R
.:
bin  etc  lib 

./bin:
SamyGO-IR-ctrl.sh  igdaemon           irsend             lircd
igclient           irrecord           irw                lircmd

./etc:
lirc

./etc/lirc:
Samsung_AH59-02195C.conf

./lib:
libiguanaIR.so           libpopt.so               libusb-1.0.so.0
libiguanaIR.so.0         libpopt.so.0             libusb-1.0.so.0.0.0
liblirc_client.so        libpopt.so.0.0.0         libusb.so
liblirc_client.so.0.2.1  libusb-1.0.so            libusbpre1.so

You don't really need everything in bin/, some binaries are there just for testing purposes. As soon as that's done, they will be removed. The switching on of my TV is handled by bin/SamyGO-IR-ctrl.sh:

#! /bin/sh                                                                    
#                                                                             
# SamyGO-IR-ctrl.sh                                                           
#                                                                             
# quick and dirty script to crank up lirc support for the iguanaworks         
# usb IR transmitter for Samsung B-series TV's                                
#                                                                             
# Call this script from the SamyGO.sh script.                                 
#                                                                             
# see www.iguanaworks.net for details on the transmitter                      
#                                                                             
# marcelr, 15-9-2011.                                                         
#                                                                             
                                                                              
# wait a little first                                                         
                                                                              
sleep 60                                                                      
                                                                              
VAR_LOG=/dtv/var/log                                                          
VAR_RUN=/dtv/var/run                                                          
                                                                              
# kill existing lircd and igdaemon                                            
                                                                              
if [ -f $VAR_RUN/lircd.pid ]; then                                            
                                                                              
       echo "stopping lircd"                                                 
        rm $VAR_RUN/lircd.pid                                                 
        rm $VAR_LOG/lircd.log                                                 
        killall lircd                                                         
fi                                                                            
                                                                              
if [ -f $VAR_RUN/igdaemon.pid ]; then                                         
                                                                              
        echo "stopping igdaemon"                                              
        rm $VAR_RUN/igdaemon.pid                                              
        rm $VAR_LOG/iguanaIR.log                                              
        killall igdaemon                                                      
fi                                                                            
                                                                              
# set paths for binaries and libs                                             
                                                                              
DATA_ROOT=/mtd_rwarea/iguanaworks                                             
export LD_LIBRARY_PATH=$DATA_ROOT/lib                                         
                                                                              
# create var directories in /dtv                                              
                                                                              
mkdir -p $VAR_LOG                                                             
mkdir -p $VAR_RUN/lirc                                                         
 

SOCKET=$VAR_RUN/lirc/lircd                                                    
                                                                             
# create socket directory (requires patching of iguanaIR.h, line 57)          
                                                                              
mkdir -p /dtv/dev/iguanaIR                                                    
                                                                              
# crank up iguanaIR daemon and wait                                           
                                                                              
$DATA_ROOT/bin/igdaemon \                                                     
        --no-ids  -v -v -v -v \                                               
        -p $VAR_RUN/igdaemon.pid \                                            
        -l $VAR_LOG/iguanaIR.log                                              
                                                                              
sleep 5                                                                       
                                                                              
# check if something failed ... not very elegant, but it works.               
# igdaemon fails every second time ...                                        
                                                                              
grep "ailed" $VAR_LOG/iguanaIR.log                                            
                                                                              
if [ $?==0 ]; then                                                            
        echo "trying again"                                                   
        rm $VAR_RUN/igdaemon.pid                                              
#       rm $VAR_LOG/iguanaIR.log                                              
        killall igdaemon                                                      
        sleep 1                                                               
        $DATA_ROOT/bin/igdaemon \                                             
                --no-ids -v -v -v -v \                                        
                -p $VAR_RUN/igdaemon.pid \                                    
                -l $VAR_LOG/iguanaIR.log                                      
fi                                                                            
                                                                              
# crank up lirc daemon:                                                       
                                                                              
$DATA_ROOT/bin/lircd \                                                        
        -d /dtv/dev/iguanaIR/0 \                                              
        -o $SOCKET \                                                          
        -H iguanaIR \                                                         
        -P $VAR_RUN/lircd.pid \                                               
        -L $VAR_LOG/lircd.log \                                               
        $DATA_ROOT/etc/lirc/Samsung_AH59-02195C.conf                          
                                                                              
sleep 3                                                                       
                                                                              
# start transmission:                                                         
                                                                              
$DATA_ROOT/bin/irsend -d $SOCKET set_transmitters 1 2 3 4                     

# switch on BD player:
       
$DATA_ROOT/bin/irsend -d $SOCKET send_once Samsung_AH59-02195C BD_Power

The IR commands for the remote are kept in etc/lirc/Samsung_AH59-02195C.conf:

# Please make this file available to others
# by sending it to <lirc@bartelmus.de>
#
# this config file was automatically generated
# using lirc-0.9.0(iguanaIR) on Sun Sep 11 20:59:27 2011
#
# contributed by marcelru
#
# brand:                       Samsung
# model no. of remote control: AH59-02195C
# devices being controlled by this remote: HT-BD8200
#
# The remote is capable of controlling both TV and Bluray home theatre,
# by choice of "TV" or "BD receiver" buttons, who don't generate IR codes by
# themselves. This not just toggles the pre-data bits (0xE0E0 for TV, 
# 0xC2CA for Home theatre), but also changes the actual signal values ...

begin remote 

  name  Samsung_AH59-02195C
  bits           32
  flags SPACE_ENC|CONST_LENGTH
  eps            30
  aeps          100 

  header       4501  4452
  one           558  1646
  zero          558   503
  ptrail        558
  gap          107045
  min_repeat      3
#  suppress_repeat 3
#  uncomment to suppress unwanted repeats
  toggle_bit_mask 0x0 

      begin codes
          BD_Power                 0xC2CA807F
          BD_Eject                 0xC2CA0CF3
          BD_Dimmer                0xC2CA18E7
          BD_BD                    0xC2CA9867
          BD_Tuner                 0xC2CA906F
          BD_Aux                   0xC2CA8877
          BD_1                     0xC2CA827D
          BD_2                     0xC2CA42BD
          BD_3                     0xC2CAC23D
          BD_4                     0xC2CA22DD
          BD_5                     0xC2CAA25D
          BD_6                     0xC2CA629D
          BD_7                     0xC2CAE21D
          BD_8                     0xC2CAFC03
          BD_9                     0xC2CAEC13
          BD_0                     0xC2CAF40B
          BD_Audio                 0xC2CA609F
          BD_Subtitle              0xC2CA708F
          BD_Previous              0xC2CAD827
          BD_Step                  0xC2CABC43
          BD_Pause                 0xC2CABE41
          BD_Next                  0xC2CAC837
          BD_Rewind                0xC2CA2ED1
          BD_Stop                  0xC2CAD02F
          BD_Play                  0xC2CAC03F
          BD_Fastforward           0xC2CAAE51
          BD_Vol+                  0xC2CACC33
          BD_Vol-                  0xC2CADC23
          BD_Mute                  0xC2CA9C63
          BD_V-sound               0xC2CA24DB
          BD_Chan_up               0xC2CAC43B
          BD_Chan_down             0xC2CAD42B
          BD_Menu                  0xC2CA6C93
          BD_Return                0xC2CA38C7
          BD_Arrow_up              0xC2CAB04F
          BD_Arrow_down            0xC2CAA857
          BD_Arrow_left            0xC2CAA45B
          BD_Arrow_right           0xC2CAB847
          BD_Enter                 0xC2CAA05F
          BD_Info                  0xC2CA649B
          BD_Exit                  0xC2CA7E81
          BD_Red                   0xC2CADA25
          BD_Green                 0xC2CA2AD5
          BD_Yellow                0xC2CAAA55
          BD_Blue                  0xC2CAEE11
          BD_Popup/title_menu      0xC2CACA35
          BD_Disc_menu             0xC2CA5AA5
          BD_Zoom                  0xC2CAF00F
          BD_Pip                   0xC2CA10EF
          BD_Tuner_memory          0xC2CAB44B
          BD_MO/ST                 0xC2CA6A95
          BD_Repeat_A/B            0xC2CA8A75
          BD_Repeat                0xC2CA6699
          BD_Cancel                0xC2CAE817
          BD_Sleep                 0xC2CA847B
          BD_Slow                  0xC2CAAC53
          BD_Dsp                   0xC2CA5EA1
          TV_Power                 0xE0E040BF
          TV_Source                0xE0E0807F
          TV_1                     0xE0E020DF
          TV_2                     0xE0E0A05F
          TV_3                     0xE0E0609F
          TV_4                     0xE0E010EF
          TV_5                     0xE0E0906F
          TV_6                     0xE0E050AF
          TV_7                     0xE0E030CF
          TV_8                     0xE0E0B04F
          TV_9                     0xE0E0708F
          TV_0                     0xE0E08877
          TV_Pause                 0xE0E052AD
          TV_Rewind                0xE0E0A25D
          TV_Stop                  0xE0E0629D
          TV_Play                  0xE0E0E21D
          TV_Fastforward           0xE0E012ED
          TV_Vol+                  0xE0E0E01F
          TV_Vol-                  0xE0E0D02F
          TV_Mute                  0xE0E0F00F
          TV_Chan_up               0xE0E048B7
          TV_Chan_down             0xE0E008F7
          TV_Menu                  0xE0E058A7
          TV_Return                0xE0E01AE5
          TV_Info                  0xE0E0F807
          TV_Exit                  0xE0E0B44B
          TV_Arrow_up              0xE0E006F9
          TV_Arrow_down            0xE0E08679
          TV_Arrow_left            0xE0E0A659
          TV_Arrow_right           0xE0E046B9
          TV_Enter                 0xE0E016E9
          TV_Red                   0xE0E036C9
          TV_Green                 0xE0E028D7
          TV_Yellow                0xE0E0A857
          TV_Blue                  0xE0E06897
          TV_Sleep                 0xE0E0C03F
      end codes

end remote

For another remote, consult the remotes/ directory in the LIRC package, otherwise, you can record your own remote with the irrecord program, which is part of the LIRC package. In this example just a single switch-on of the HT is demonstrated. With some more programming many other options are possible.

Installation of the hardware

That's the easiest part. I just mounted the receiver/transmitter at the back of my TV.(see picture):

USB transmitter/receiver mounted at the back of the TV

Just make sure that the device you want to control has a straight line of sight from its IR receiver to the transmitter.

Issues

  • The fact that the kernel code needs patching for LIRC to compile is not very satisfactory. This obviously needs some work.
  • The iguanaIR daemon fails every second time it gets started on the TV, complaining about time-outs. Needs to be fixed as well.
  • When embedded in the TVs startup scripts, there's quite some waiting time needed before the daemons can be started. At startup, the TV (at least mine) is quite busy with all kinds of SamyGO additions, so time-critical devices like this transmitter can only be started successfully when most of the actions at startup have been completed. That's the main reason for the 60 second delay in the startup script.
  • In case anyone's interested in precompiled binaries, PM me, and I'll get them to you. Don't know how to upload to the download area of SamyGO (yet).

marcelr, 26-9-2011.