/* $ gcc -o firewire_changer firewire_changer.c -lraw1394 -lavc1394 jwestfall@surrealistic.net */ #include #include #include #include #include #include #define AVC1394_PANEL_OPERATION_TUNE 0x67 #define AVC1394_TUNE_COMMAND_LENGTH 0x04 #define AVC1394_TUNE AVC1394_CTYPE_CONTROL | AVC1394_SUBUNIT_TYPE_PANEL | \ AVC1394_PANEL_COMMAND_PASS_THROUGH | \ AVC1394_PANEL_OPERATION_TUNE #define AVC1394_KEY_PRESS AVC1394_CTYPE_CONTROL | AVC1394_SUBUNIT_TYPE_PANEL | \ AVC1394_PANEL_COMMAND_PASS_THROUGH | \ AVC1394_PANEL_OPERATION_0 #define CHANGE_METHOD_KEY_PRESS 0 #define CHANGE_METHOD_TUNE 1 int check_device(raw1394handle_t handle, int port, int node); void method_key_press(raw1394handle_t handle, int port, int node, int channel); void method_tune(raw1394handle_t handle, int port, int node, int channel); void usage(void); int verbose = 0; int main(int argc, char **argv) { raw1394handle_t handle; int node = -1, channel = -1, port = 0; int method = CHANGE_METHOD_KEY_PRESS; int c; opterr = 0; while((c = getopt(argc, argv, "tkn:p:v")) != -1) { switch(c) { case 't': method = CHANGE_METHOD_TUNE; break; case 'k': method = CHANGE_METHOD_KEY_PRESS; break; case 'n': node = atoi(optarg); if (node < 0) { printf("invalid node: %d\n", node); exit(1); } break; case 'p': port = atoi(optarg); if (port < 0) { printf("invalid port: %d\n", port); exit(1); } break; case 'v': verbose = 1; break; default: printf("bad command line argument: %c\n", optopt); usage(); exit(1); } } if (optind != argc - 1) { usage(); exit(1); } if (node == -1) { printf("-n NODE option required\n"); usage(); exit(1); } channel = atoi(argv[optind]); if (channel < 0 || channel > 999) { printf("invalid channel: %d\n", channel); exit(1); } handle = raw1394_new_handle_on_port(port); if (!handle) { printf("Failed to get raw1394 handle, Port: %d\n", port); exit(1); } if (!check_device(handle, port, node)) { printf("Device Check FAILED, exiting\n"); exit(1); } switch (method) { case CHANGE_METHOD_KEY_PRESS: method_key_press(handle, port, node, channel); break; case CHANGE_METHOD_TUNE: method_tune(handle, port, node, channel); break; } exit(0); } void method_key_press(raw1394handle_t handle, int port, int node, int channel) { quadlet_t cmd[2], *response; int i, dig[3]; dig[2] = (channel % 10); dig[1] = (channel % 100) / 10; dig[0] = (channel % 1000) / 100; if (verbose) { printf("Method: Key Press\n"); printf("Channel: %d, Port: %d, Node: %d\n", channel, port, node); } for (i = 0; i < 3; i++) { cmd[0] = AVC1394_KEY_PRESS | dig[i]; cmd[1] = 0x0; if (verbose) printf("Sending Command (Digit: %d): 0x%08X 0x%08X\n", dig[i], cmd[0], cmd[1]); response = avc1394_transaction_block(handle, node, cmd, 2, 1); if (response) { if (AVC1394_MASK_RESPONSE(response[0]) == AVC1394_RESPONSE_ACCEPTED) { if (verbose) printf("Success, Response: 0x%08X 0x%08X\n", response[0], response[1]); } else { printf("Command Failed (Digit %d), Response: 0x%08X 0x%08X\n", dig[i], response[0], response[1]); // add retry instead of exit exit(1); } } else { printf("Command Failed (Digit %d), No Response\n", dig[i]); // add retry instead of exit exit(1); } usleep(500000); } } void method_tune(raw1394handle_t handle, int port, int node, int channel) { quadlet_t cmd[3], *response; cmd[0] = AVC1394_TUNE; cmd[1] = (AVC1394_TUNE_COMMAND_LENGTH << 24) | (channel << 8); cmd[2] = 0x0; if (verbose) { printf("Method: Tune\n"); printf("Channel: %d, Port: %d, Node: %d\n", channel, port, node); printf("Sending Command: 0x%08X 0x%08X 0x%08X\n", cmd[0], cmd[1], cmd[2]); } response = avc1394_transaction_block(handle, node, cmd, 3, 1); if (response) { if (AVC1394_MASK_RESPONSE(response[0]) == AVC1394_RESPONSE_ACCEPTED) { if (verbose) printf("Success, Response: 0x%08X 0x%08X 0x%08X\n", response[0], response[1], response[2]); } else { printf("Command Failed, Response: 0x%08X 0x%08X 0x%08X\n", response[0], response[1], response[2]); // add retry instead of exit exit(1); } } else { printf("Command Failed, No Response\n"); // add retry instead of exit exit(1); } } // verify the device looks like something we could change the channel on int check_device(raw1394handle_t handle, int port, int node) { if (verbose) printf("Checking Device, Port: %d, Node: %d\n Subunit Type Panel: ", port, node); if (!avc1394_check_subunit_type(handle, node, AVC1394_SUBUNIT_TYPE_PANEL)) { if (verbose) printf("Failed\n"); return 0; } if (verbose) printf("Passed\n Subunit Type Tuner: "); if (!avc1394_check_subunit_type(handle, node, AVC1394_SUBUNIT_TYPE_TUNER)) { if (verbose) printf("Failed\n"); return 0; } if (verbose) printf("Passed\n"); return 1; } void usage(void) { printf("Usage: firewire_changer -k|-t -n NODE [-v] [-p PORT] \n"); printf(" -k use key press method (default)\n"); printf(" -t use tune method\n"); printf(" -n NODE use node NODE, (required)\n"); printf(" -p PORT use adapter PORT, (default:0)\n"); printf(" -v be verbose\n"); }