Ticket #2059: sa3250.patch
File sa3250.patch, 13.6 KB (added by , 18 years ago) |
---|
-
sa3250ch.c
2 2 * sa3250ch - an external channel changer for SA3250HD Tuner 3 3 * Based off 6200ch.c by Stacey D. Son 4 4 * 5 * Additional enhancements and alternate SA3250 and SA4200 channel change 6 * method added for the MythTV project by Chris Ingrassia <chris@spicecoffee.org> 7 * 5 8 * Copyright 2004,2005 by Stacey D. Son <mythdev@son.org> 6 9 * Copyright 2005 Matt Porter <mporter@kernel.crashing.org> 7 10 * … … 20 23 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 24 */ 22 25 23 #include <libavc1394/rom1394.h> 24 #include <libavc1394/avc1394.h> 25 #include <libraw1394/raw1394.h> 26 #include <unistd.h> 26 27 #include <sys/types.h> 27 28 #include <stdio.h> 28 29 #include <errno.h> 29 30 #include <stdlib.h> 30 31 32 #include <libavc1394/rom1394.h> 33 #include <libavc1394/avc1394.h> 34 #include <libraw1394/raw1394.h> 35 36 37 int verbose = 0; 38 39 #ifdef RAW1394_V_0_8 40 # define GET_1394HANDLE(h) (h = raw1394_get_handle()) 41 #else 42 # define GET_1394HANDLE(h) (h = raw1394_new_handle()) 43 #endif 44 45 #define MAX_PORTS 4 /* Maximum number of 1394 ports to check for devices */ 46 31 47 /* SA3250HD IDs */ 32 48 #define SA3250HD_VENDOR_ID 0x000011e6 33 #define SA3250HD_VENDOR_ID2 0x00001 4f849 #define SA3250HD_VENDOR_ID2 0x00001692 34 50 #define SA3250HD_MODEL_ID 0x00000be0 35 51 36 52 #define AVC1394_SA3250_COMMAND_CHANNEL 0x000007c00 /* subunit command */ … … 40 56 #define CTL_CMD0 AVC1394_CTYPE_CONTROL | AVC1394_SUBUNIT_TYPE_PANEL | \ 41 57 AVC1394_SUBUNIT_ID_0 | AVC1394_SA3250_COMMAND_CHANNEL 42 58 #define CTL_CMD1 (0x04 << 24) 43 #define CTL_CMD2 0x ff00000059 #define CTL_CMD2 0x00000000 44 60 45 61 #define STARTING_NODE 0 46 62 47 63 void usage() 48 64 { 49 fprintf(stderr, "Usage: sa3250ch [-v] <channel_num>\n"); 65 fprintf(stderr, "Usage: sa3250ch [-vsh] [-p <port>] [-n <node>] <channel>\n"); 66 fprintf(stderr, "Available Options:\n"); 67 fprintf(stderr, "\t-v: Be verbose (useful for debugging)\n"); 68 fprintf(stderr, "\t-f: Force sending command even if compatible device is not detected\n"); 69 fprintf(stderr, "\t-a: Just attempt autodetection of device and exit\n"); 70 fprintf(stderr, "\t-s: Send channel as single command (for SA4200, and some SA3250 models)\n"); 71 fprintf(stderr, "\t-p: Use port <port> (Default: autodetect)\n"); 72 fprintf(stderr, "\t-n: Use node <node> (Default: autodetect)\n"); 73 fprintf(stderr, "\t-h: Print this usage message\n"); 50 74 exit(1); 51 75 } 52 76 53 77 int main (int argc, char *argv[]) 54 78 { 55 rom1394_directory dir; 56 int device = -1; 57 int i; 58 int verbose = 0; 59 quadlet_t cmd[3]; 79 int device = -1, i = 0, chn = 708, st = EXIT_SUCCESS, arg = 0; 80 int single = 0, port = -1, node = -1, report = 0, force = 0; 60 81 int dig[3]; 61 int chn = 708; 62 82 quadlet_t cmd[3], *response = NULL; 83 raw1394handle_t handle; 84 63 85 if (argc < 2) 64 86 usage(); 65 87 66 if (argc == 3 && argv[1][0] == '-' && argv[1][1] == 'v') { 67 verbose = 1; 68 chn = atoi(argv[2]); 69 } else { 70 chn = atoi(argv[1]); 88 while((arg = getopt(argc, argv, "vsafhp:n:")) != -1) { 89 switch(arg) { 90 case 'v': 91 verbose = 1; 92 printf("Verbose mode on\n"); 93 break; 94 case 's': 95 single = 1; 96 break; 97 case 'p': 98 port = atoi(optarg); 99 break; 100 case 'n': 101 node = atoi(optarg); 102 break; 103 case 'f': 104 if(verbose) printf("Force mode on\n"); 105 force = 1; 106 break; 107 case 'a': 108 report = 1; 109 break; 110 case 'h': 111 usage(); 112 goto cleanup; 113 break; 114 } 71 115 } 72 116 73 #ifdef RAW1394_V_0_8 74 raw1394handle_t handle = raw1394_get_handle(); 75 #else 76 raw1394handle_t handle = raw1394_new_handle(); 77 #endif 117 argc -= optind; 118 argv += optind; 119 120 if((argc != 1) && !report) { 121 if(verbose) printf("No channel number specified?\n"); 122 usage(); 123 st = EXIT_FAILURE; 124 goto cleanup; 125 } 126 127 if(!report) chn = atoi(*argv); 128 129 GET_1394HANDLE(handle); 78 130 79 131 if (!handle) { 80 132 if (!errno) { … … 83 135 perror("Couldn't get 1394 handle"); 84 136 fprintf(stderr, "Is ieee1394, driver, and raw1394 loaded?\n"); 85 137 } 86 exit(1); 138 st = EXIT_FAILURE; 139 goto cleanup; 87 140 } 88 141 89 if (raw1394_set_port(handle, 0) < 0) { 90 perror("couldn't set port"); 91 raw1394_destroy_handle(handle); 92 exit(1); 142 if(!locate_device(handle, &port, &node)) { 143 if(force) { 144 if(verbose) printf("Compatible AV/C device not found, continuing anyway\n"); 145 } else { 146 fprintf(stderr, "Unable to locate AV/C 1394 Panel Device\n"); 147 st = EXIT_FAILURE; 148 goto cleanup; 149 } 93 150 } 94 151 95 int nc = raw1394_get_nodecount(handle); 96 for (i=STARTING_NODE; i < nc; ++i) { 97 if (rom1394_get_directory(handle, i, &dir) < 0) { 98 fprintf(stderr,"error reading config rom directory for node %d\n", i); 99 raw1394_destroy_handle(handle); 100 exit(1); 101 } 102 103 if (verbose) 104 printf("node %d: vendor_id = 0x%08x model_id = 0x%08x\n", 105 i, dir.vendor_id, dir.model_id); 106 107 if ((dir.vendor_id == SA3250HD_VENDOR_ID || 108 dir.vendor_id == SA3250HD_VENDOR_ID2) && 109 (dir.model_id == SA3250HD_MODEL_ID)) { 110 device = i; 111 break; 112 } 152 if(report) { 153 printf("Detected compatible device at port %d and node %d\n", 154 port, node); 155 st = EXIT_SUCCESS; 156 goto cleanup; 113 157 } 114 115 if (device == -1) {116 fprintf(stderr, "Could not find SA3250HD on the 1394 bus.\n");117 raw1394_destroy_handle(handle);118 exit(1);119 }120 158 121 dig[2] = 0x30 | (chn % 10); 122 dig[1] = 0x30 | ((chn % 100) / 10); 123 dig[0] = 0x30 | ((chn % 1000) / 100); 159 raw1394_set_port(handle, port); 160 161 if(single) { 162 if(verbose) 163 printf("Tuning to channel %d using single command\n", chn); 124 164 125 cmd[0] = CTL_CMD0 | AVC1394_SA3250_OPERAND_KEY_PRESS;126 cmd[1] = CTL_CMD1 | (dig[2] << 16) | (dig[1] << 8) | dig[0];127 cmd[2] = CTL_CMD2;165 cmd[0] = CTL_CMD0 | AVC1394_SA3250_OPERAND_KEY_PRESS; 166 cmd[1] = CTL_CMD1 | (chn << 8); 167 cmd[2] = 0x0; 128 168 129 if(verbose)130 printf("AV/C Command: %d%d%d = cmd0=0x%08x cmd2=0x%08x cmd3=0x%08x\n",131 dig[0] & 0xf, dig[1] & 0xf, dig[2] & 0xf, cmd[0], cmd[1], cmd[2]);169 if(verbose) 170 printf("Sending command channel change: 0x%08X 0x%08X\n", 171 cmd[0], cmd[1]); 132 172 133 avc1394_transaction_block(handle, 0, cmd, 3, 1); 134 cmd[0] = CTL_CMD0 | AVC1394_SA3250_OPERAND_KEY_RELEASE; 135 cmd[1] = CTL_CMD1 | (dig[0] << 16) | (dig[1] << 8) | dig[2]; 136 cmd[2] = CTL_CMD2; 173 response = avc1394_transaction_block(handle, 0, cmd, 3, 1); 174 if(AVC1394_MASK_RESPONSE(response[0]) == AVC1394_RESPONSE_ACCEPTED) { 175 if(verbose) 176 printf("Channel change command success: Response: 0x%08X 0x%08X\n", 177 response[0], response[1]); 178 } 179 else { 180 fprintf(stderr, "Channel change command failed: Response: 0x%08X 0x%08X\n", 181 response[0], response[1]); 182 } 183 } 184 else { 185 /* Original sa3250ch channel change method */ 186 dig[2] = 0x30 | (chn % 10); 187 dig[1] = 0x30 | ((chn % 100) / 10); 188 dig[0] = 0x30 | ((chn % 1000) / 100); 137 189 138 if (verbose) 139 printf("AV/C Command: %d%d%d = cmd0=0x%08x cmd2=0x%08x cmd3=0x%08x\n", 140 dig[0] & 0xf, dig[1] & 0xf, dig[2] & 0xf, cmd[0], cmd[1], cmd[2]); 190 if (verbose) { 191 printf("Digits : [0] : %d [1]: %d [2]: %d\n", 192 dig[0], dig[1], dig[2]); 193 } 194 cmd[0] = CTL_CMD0 | AVC1394_SA3250_OPERAND_KEY_PRESS; 195 cmd[1] = CTL_CMD1 | (dig[0] << 16) | (dig[1] << 8) | dig[2]; 196 cmd[2] = CTL_CMD2; 197 if(verbose) 198 printf("AV/C Command: %d%d%d = cmd0=0x%08x cmd2=0x%08x cmd3=0x%08x\n", 199 dig[0] & 0xf, dig[1] & 0xf, dig[2] & 0xf, cmd[0], cmd[1], cmd[2]); 200 avc1394_transaction_block(handle, 0, cmd, 3, 1); 201 cmd[0] = CTL_CMD0 | AVC1394_SA3250_OPERAND_KEY_RELEASE; 202 if(verbose) 203 printf("AV/C Command: %d%d%d = cmd0=0x%08x cmd2=0x%08x cmd3=0x%08x\n", 204 dig[0] & 0xf, dig[1] & 0xf, dig[2] & 0xf, cmd[0], cmd[1], cmd[2]); 205 avc1394_transaction_block(handle, 0, cmd, 3, 1); 206 } 141 207 142 avc1394_transaction_block(handle, 0, cmd, 3, 1); 208 cleanup: 209 if(handle) raw1394_destroy_handle(handle); 210 211 if(verbose) { 212 printf("%s attempt %s\n", 213 report ? "Autodetection" : "Channel change", 214 st ? "failed" : "suceeded"); 215 } 216 217 exit(st); 218 } 143 219 144 raw1394_destroy_handle(handle); 220 /** 221 * locate_device - Attempt to locate a compatible AV/C panel device on the 1394 222 * bus 223 * @handle: libraw1394 handle 224 * @port: pointer to detected port number 225 * @node: pointer to detected node number 226 * 227 * Setting the value pointed to by @port or @node to a value >= 0 will limit detection 228 * to those ports, and this function will simply verify that it thinks a compatible 229 * device is at that location 230 * 231 * Returns: 1 on succesful detection, and sets the value at the locations 232 * pointed to be @port and @node to the detected ieee1394 port and node, respectively. 233 * Returns 0 on failure 234 */ 235 int locate_device(raw1394handle_t handle, int *port, int *node) { 236 int st = 0, nports = 0, i = 0, j = 0; 237 int found_port = -1, found_node = -1; 238 struct raw1394_portinfo pinfo[MAX_PORTS]; 239 240 if((port && (*port >= 0))) { 241 found_port = *port; 242 if(verbose) printf("Using user specified port %d\n", found_port); 243 } 244 245 if((node && (*node >= 0))) { 246 found_node = *node; 247 if(verbose) printf("Using user specified node %d\n", found_node); 248 } 249 250 if((found_port >= 0) && (found_node >= 0)) { 251 /* Just verify device type at this port/node combination */ 252 st = verify_device(found_port, found_node); 253 goto cleanup; 254 } 255 /* XXX: I think you have to give raw1394_get_port_info() a nonzero 256 * maxports argument. I figure the default in MAX_PORTS should be more 257 * than sufficient, and you can always specify the port manually, but 258 * I could be wrong 259 */ 260 if(found_port < 0) { 261 if(!(nports = raw1394_get_port_info(handle, pinfo, MAX_PORTS))) { 262 fprintf(stderr, "Could not find any IEEE 1394 ports!\n"); 263 st = 0; 264 goto cleanup; 265 } 266 } else { 267 nports = 1; 268 raw1394_set_port(handle, found_port); 269 pinfo[0].nodes = raw1394_get_nodecount(handle); 270 strncpy(pinfo[0].name, "Pre-set port", sizeof(pinfo[0].name)); 271 } 272 273 if(verbose) { 274 printf("Found %d ports on 1394 Bus\n", nports); 275 } 276 277 for(i = 0; i < nports; ++i) { 278 if(verbose) { 279 printf("Checking port #%d - \'%s\'\n", i, pinfo[i].name); 280 } 281 for(j = 0; (j < pinfo[i].nodes) && (found_node < 0); ++j) { 282 if(verbose) printf("\t Node %d ... ", j); 283 if(verify_device(i, j)) { 284 found_node = j; 285 if(verbose) printf("AV/C Panel/Tuner Device Found\n"); 286 break; 287 } 288 if(verbose) printf("\n"); 289 } 290 if(found_node >= 0) { 291 found_port = i; 292 st = 1; 293 break; 294 } 295 } 296 297 cleanup: 298 if(found_port >= 0) *port = found_port; 299 if(found_node >= 0) *node = found_node; 300 return st; 301 } 145 302 146 exit(0); 303 int verify_device(int port, int node) { 304 raw1394handle_t handle; 305 int panel = 0, tuner = 0; 306 307 GET_1394HANDLE(handle); 308 raw1394_set_port(handle, port); 309 panel = avc1394_check_subunit_type(handle, node, AVC1394_SUBUNIT_TYPE_PANEL); 310 tuner = avc1394_check_subunit_type(handle, node, AVC1394_SUBUNIT_TYPE_TUNER); 311 raw1394_destroy_handle(handle); 312 return (panel && tuner); 147 313 } -
sa3250ch-README
1 1 sa3250ch is a small program that changes channels on a Scientific Atlanta 2 SA3250HD cable boxvia a 1394 (aka. Firewire) connection. It is based off2 SA3250HD, and SA4200 cable boxes via a 1394 (aka. Firewire) connection. It is based off 3 3 of 6200ch by Stacey Son (mythdev@son.org). 4 4 5 5 To use this with mythtv do the following: … … 21 21 program and adding to "/usr/local/bin/sa3250ch" to the "External channel 22 22 change command" field under "Connect source to Input". 23 23 24 I'm curious if this works for anybody on other SciAtl boxes when the proper 25 model IDs are added. 24 Troubleshooting: 25 ---------------- 26 26 27 (1) Try running the program with the "-v" (verbose) argument first to see if anything 28 obvious is wrong 29 (2) If for some reason auto-detection of the device fails or you want to circumvent it, 30 manually specify the port and node with the "-p" and "-n" arguments, respectively. 31 (3) If the channel changes, but is incorrect or you have problems recording or watching LiveTV 32 after a channel change, try using the alternate method of channel changing by sending 33 a single command to the box with the "-s" option. 34 35 If you're still having problems, please include the output of the failed command with the "-v" 36 argument specified when reporting problems. 37 27 38 Matt Porter <mporter@kernel.crashing.org> 39 Chris Ingrassia <chris@spicecoffee.org> (sa3250ch enhancements, "-s" support) 40 No newline at end of file