Sa3250ch

From MythTV Official Wiki
Jump to: navigation, search

Important.png Note: The correct title of this article is sa3250ch. It appears incorrectly here due to technical restrictions.


Author unknown
Description Channel-change script for use with the Scientific Atlanta SA3250HD cable box
Supports


sa3250ch is a small program that changes channels on a Scientific Atlanta SA3250HD cable box via a 1394 (aka. Firewire) connection. It is based off of 6200ch by Stacey Son ( mythdev a son d org ).

To use this with mythtv do the following:

(1) Make sure you have 1394/Firewire drivers installed in your kernel.

(2) Install libraw1394, librom1394 and libavc1394.

(3) Compile and install "sa3250ch":

     # cc -o sa3250ch sa3250ch.c -lrom1394 -lavc1394 -lraw1394
     # cp sa3250ch /usr/local/bin

(4) Connect a 1394/Firewire cable from your computer to your SA3250HD and test:

     # sa3250ch <your_favorite_channel_number>

(5) Configure Mythtv to use the channel changer by running the "setup" program and adding to "/usr/local/bin/sa3250ch" to the "External channel change command" field under "Connect source to Input".

I'm curious if this works for anybody on other SciAtl boxes when the proper model IDs are added.

Matt Porter ( mporter a kernel d crashing d org


Script.png sa3250ch.c

/*
 * sa3250ch - an external channel changer for SA3250HD Tuner
 * Based off 6200ch.c by Stacey D. Son
 *
 * Copyright 2004,2005 by Stacey D. Son <mythdev@son.org>
 * Copyright 2005 Matt Porter <mporter@kernel.crashing.org>
 * Portions Copyright 2006 Chris Ingrassia <chris@spicecoffee.org> (SA4200 and Single-digit command mode)
 * R.D. Vaughan <r.d.vaughan@rogers.com> (Cisco 4642HD and Single-digit two commands mode)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include <libavc1394/rom1394.h>
#include <libavc1394/avc1394.h>
#include <libraw1394/raw1394.h>
#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>

/* SA3250HD IDs */
/* WARNING: Please update firewiredevice.cpp when adding to this list. */

#define SA_VENDOR_ID1           0x00000a73
#define SA_VENDOR_ID2           0x00000f21
#define SA_VENDOR_ID3           0x000011e6
#define SA_VENDOR_ID4           0x000014f8
#define SA_VENDOR_ID5           0x00001692
#define SA_VENDOR_ID6           0x00001868
#define SA_VENDOR_ID7           0x00001947
#define SA_VENDOR_ID8           0x00001ac3
#define SA_VENDOR_ID9           0x00001bd7
#define SA_VENDOR_ID10          0x00001cea
#define SA_VENDOR_ID11          0x00001e6b
#define SA_VENDOR_ID12          0x000021be
#define SA_VENDOR_ID13          0x0000223a
#define SA_VENDOR_ID14          0x000022ce
#define SA_VENDOR_ID15          0x000023be
#define SA_VENDOR_ID16          0x0000252e
#define CISCO_VENDOR_ID17       0x00484487

#define SA3250HD_MODEL_ID1      0x00000be0
#define SA4200HD_MODEL_ID1      0x00001072
#define SA4250HDC_MODEL_ID1     0x000010cc
#define SA8300HD_MODEL_ID1      0x000022ce
#define CISCO4642_MODEL_ID1     0x00001222

#define AVC1394_SA3250_COMMAND_CHANNEL 0x000007c00   /* subunit command */
#define AVC1394_SA3250_OPERAND_KEY_PRESS 0xe7
#define AVC1394_SA3250_OPERAND_KEY_RELEASE 0x67

#define CTL_CMD0 AVC1394_CTYPE_CONTROL | AVC1394_SUBUNIT_TYPE_PANEL | \
        AVC1394_SUBUNIT_ID_0 | AVC1394_SA3250_COMMAND_CHANNEL
#define CTL_CMD1 (0x04 << 24)
#define CTL_CMD2 0xff000000

#define STARTING_NODE 0

void usage()
{
   fprintf(stderr, "Usage: sa3250ch [-v] [-s] <channel_num>\n");
   fprintf(stderr, "  -v : Verbose Mode\n");
   fprintf(stderr, "  -s : Send command as single digit "
           "(for SA4200 and some SA3250s and SA4200HD's)\n");
   fprintf(stderr, "  -2 : Send command as single digit through two commands "
           "(for Cisco 4642HD)\n");
   exit(1);
}

int main (int argc, char *argv[])
{
   rom1394_directory dir;
   int device = -1;
   int single = 0;
   int single_two = 0;
   int i;
   int verbose = 0;
   quadlet_t cmd[3];
   int dig[3];
   int chn = 708;

   if (argc < 2)
      usage();

  for(i = 1; i < argc; ++i) {
      if ((argv[i][0] == '-') && (strlen(argv[i]) > 1)) {
        switch(argv[i][1]) {
            case 'v':
                verbose = 1;
                break;
            case 's':
                single = 1;
                break;
            case '2':
                single_two = 1;
                break;
            default:
                fprintf(stderr, "WARNING: Unknown option \'%c\', ignoring", argv[i][1]);
        }
      }
      else {
          chn = atoi(argv[i]);
      }
  }

#ifdef RAW1394_V_0_8
   raw1394handle_t handle = raw1394_get_handle();
#else
   raw1394handle_t handle = raw1394_new_handle();
#endif

   if (!handle) {
      if (!errno) {
         fprintf(stderr, "Not Compatible!\n");
      } else {
         perror("Couldn't get 1394 handle");
         fprintf(stderr, "Is ieee1394, driver, and raw1394 loaded?\n");
      }
      exit(1);
   }

   if (raw1394_set_port(handle, 0) < 0) {
      perror("couldn't set port");
      raw1394_destroy_handle(handle);
      exit(1);
   }

   int nc = raw1394_get_nodecount(handle);
   for (i=STARTING_NODE; i < nc; ++i) {
      if (rom1394_get_directory(handle, i, &dir) < 0) {
         fprintf(stderr,"error reading config rom directory for node %d\n", i);
         raw1394_destroy_handle(handle);
    	 exit(1);
      }

      if (verbose)
         printf("node %d: vendor_id = 0x%08x model_id = 0x%08x\n",
                 i, dir.vendor_id, dir.model_id);

      /* WARNING: Please update firewiredevice.cpp when adding to this list. */
      if (((dir.vendor_id == SA_VENDOR_ID1)  ||
           (dir.vendor_id == SA_VENDOR_ID2)  ||
           (dir.vendor_id == SA_VENDOR_ID3)  ||
           (dir.vendor_id == SA_VENDOR_ID4)  ||
           (dir.vendor_id == SA_VENDOR_ID5)  ||
           (dir.vendor_id == SA_VENDOR_ID6)  ||
           (dir.vendor_id == SA_VENDOR_ID7)  ||
           (dir.vendor_id == SA_VENDOR_ID8)  ||
           (dir.vendor_id == SA_VENDOR_ID9)  ||
           (dir.vendor_id == SA_VENDOR_ID10) ||
           (dir.vendor_id == SA_VENDOR_ID11) ||
           (dir.vendor_id == SA_VENDOR_ID12) ||
           (dir.vendor_id == SA_VENDOR_ID13) ||
           (dir.vendor_id == SA_VENDOR_ID14) ||
           (dir.vendor_id == SA_VENDOR_ID15) ||
           (dir.vendor_id == SA_VENDOR_ID16) ||
           (dir.vendor_id == CISCO_VENDOR_ID17)) &&
          ((dir.model_id == SA3250HD_MODEL_ID1)  ||
           (dir.model_id == SA4200HD_MODEL_ID1)  ||
           (dir.model_id == SA4250HDC_MODEL_ID1) ||
           (dir.model_id == SA8300HD_MODEL_ID1)  ||
           (dir.model_id == CISCO4642_MODEL_ID1)))
      {
          if (dir.model_id == SA4250HDC_MODEL_ID1)
          {
              fprintf(stderr, "Ignoring SA 4250HDC on node %d -- "
                      "sorry not supported yet\n", i);
          }
          else
          {
              device = i;
              break;
          }
      }
   }

   if (device == -1)
   {
        fprintf(stderr, "Could not find SA3250HD, SA4200HD, SA8300HD or Cisco 4642HD "
                "on the IEEE 1394 bus.\n");

        raw1394_destroy_handle(handle);
        exit(1);
   }

   if (single) {
       /* Send channel as single number for SA4200 and some SA3250s */
       if (verbose)
        printf("Using single number channel change command method\n");

       cmd[0] = CTL_CMD0 | AVC1394_SA3250_OPERAND_KEY_PRESS;
       cmd[1] = CTL_CMD1 | (chn << 8);
       cmd[2] = 0x0;

       if (verbose)
            printf("AV/C Command: cmd0=0x%08x cmd1=0x%08x cmd2=0x%08x\n",
                   cmd[0], cmd[1], cmd[2]);
       avc1394_transaction_block(handle, device, cmd, 3, 1);
   } else if( single_two ) {
       /* Single digits but two commands for Cisco 4642HD */
       dig[2] = 0x00 | (chn % 10);
       dig[1] = 0x00 | ((chn % 100)  / 10);
       dig[0] = 0x00 | ((chn % 1000) / 100);

       cmd[0] = CTL_CMD0 | AVC1394_SA3250_OPERAND_KEY_PRESS;
       cmd[1] = CTL_CMD1 | (chn << 8);
       cmd[2] = CTL_CMD2;

       if (verbose)
          printf("AV/C Command: %d%d%d = cmd0=0x%08x cmd2=0x%08x cmd3=0x%08x\n",
                dig[0] & 0xf, dig[1] & 0xf, dig[2] & 0xf, cmd[0], cmd[1], cmd[2]);

       avc1394_transaction_block(handle, device, cmd, 3, 1);
       cmd[0] = CTL_CMD0 | AVC1394_SA3250_OPERAND_KEY_RELEASE;

       if (verbose)
          printf("AV/C Command: %d%d%d = cmd0=0x%08x cmd2=0x%08x cmd3=0x%08x\n",
                dig[0] & 0xf, dig[1] & 0xf, dig[2] & 0xf, cmd[0], cmd[1], cmd[2]);

       avc1394_transaction_block(handle, device, cmd, 3, 1);
   } else {
       /* Default method sending three separate digits */
       dig[2] = 0x30 | (chn % 10);
       dig[1] = 0x30 | ((chn % 100)  / 10);
       dig[0] = 0x30 | ((chn % 1000) / 100);

       cmd[0] = CTL_CMD0 | AVC1394_SA3250_OPERAND_KEY_PRESS;
       cmd[1] = CTL_CMD1 | (dig[2] << 16) | (dig[1] << 8) | dig[0];
       cmd[2] = CTL_CMD2;

       if (verbose)
          printf("AV/C Command: %d%d%d = cmd0=0x%08x cmd2=0x%08x cmd3=0x%08x\n",
                dig[0] & 0xf, dig[1] & 0xf, dig[2] & 0xf, cmd[0], cmd[1], cmd[2]);

       avc1394_transaction_block(handle, device, cmd, 3, 1);
       cmd[0] = CTL_CMD0 | AVC1394_SA3250_OPERAND_KEY_RELEASE;
       cmd[1] = CTL_CMD1 | (dig[0] << 16) | (dig[1] << 8) | dig[2];
       cmd[2] = CTL_CMD2;

       if (verbose)
          printf("AV/C Command: %d%d%d = cmd0=0x%08x cmd2=0x%08x cmd3=0x%08x\n",
                dig[0] & 0xf, dig[1] & 0xf, dig[2] & 0xf, cmd[0], cmd[1], cmd[2]);

       avc1394_transaction_block(handle, device, cmd, 3, 1);
   }

   raw1394_destroy_handle(handle);

   exit(0);
}


Script.png Makefile

TARGET=sa3250ch
CFLAGS = -Wall -std=gnu99 
PREFIX = /usr/local
BINPATH = ${PREFIX}/bin

all: $(TARGET)

$(TARGET): $(TARGET).c
	$(CC) $(CFLAGS) -o $(TARGET) $(TARGET).c -lavc1394 -lrom1394 -lraw1394

install: $(TARGET)
	install -m 0755 $(TARGET) ${BINPATH}

uninstall:
	rm -f ${BINPATH}/$(TARGET)

clean:
	rm -f $(TARGET)

distclean: clean


Support for the CISCO Explorer 4642HD box has been added with the addition of a new command line option "-2". In the MythTV channel change setting specify:

./sa3250ch -2

For the CISCO Explorer 4642HD the existing "sa3250cmd" still works for checking the current status of the STB and powering the box on or off. The configuration of the 4642HDs output resolution requires two steps.
(1) Press "Guide" and "Info" on panel then follow the on screen instructions
(2) When the STB is powered on using the remote press "Settings->Settings" scroll to "Set:Picture Format" and select "Pass Through"
Note: The "Fixed" setting in the "Settings->Set:Picture Format" overrides any resolution you select during step #1 above.

--Need1e 10:47, 11 December 2010 (UTC): Fixed a bug that would cause the program to fail with error message

rom1394_0 warning: read failed
error reading config rom directory for node 0

, when the STB was on any node other than 0.

--Phlegm Broken! After the Rogers program guide update the Cisco 4642 no longer works for channels above 100. Sometimes it changes channels but not to the correct ones. If anybody can help with this I would be glad to test. daveshome @ gmail.com