/* * Written by Oron Peled * Copyright (C) 2008, Xorcom * * All rights reserved. * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include #include #include #include #include #include #include #include "mpptalk.h" #include "astribank.h" #define DBG_MASK 0x80 /* if enabled, adds support for resetting pre-MPP USB firmware - if we * failed opening a device and we were asked to reset it, try also the * old protocol. */ #define SUPPORT_OLD_RESET static char *progname; static void usage() { fprintf(stderr, "Usage: %s [options] -D {/proc/bus/usb|/dev/bus/usb}// [operation...]\n", progname); fprintf(stderr, "\tOptions:\n"); fprintf(stderr, "\t\t[-v] # Increase verbosity\n"); fprintf(stderr, "\t\t[-d mask] # Debug mask (0xFF for everything)\n"); fprintf(stderr, "\tOperations:\n"); fprintf(stderr, "\t\t[-n] # Renumerate device\n"); fprintf(stderr, "\t\t[-r kind] # Reset: kind = {half|full}\n"); fprintf(stderr, "\t\t[-p port] # TwinStar: USB port number [0, 1]\n"); fprintf(stderr, "\t\t[-w (0|1)] # TwinStar: Watchdog off or on guard\n"); fprintf(stderr, "\t\t[-Q] # Query device properties\n"); exit(1); } static int reset_kind(const char *arg) { static const struct { const char *name; int type_code; } reset_kinds[] = { { "half", 0 }, { "full", 1 }, }; int i; for(i = 0; i < sizeof(reset_kinds)/sizeof(reset_kinds[0]); i++) { if(strcasecmp(reset_kinds[i].name, arg) == 0) return reset_kinds[i].type_code; } ERR("Unknown reset kind '%s'\n", arg); return -1; } int main(int argc, char *argv[]) { char *devpath = NULL; struct astribank *astribank; struct mpp_device *mpp; const char options[] = "vd:D:nr:p:w:Q"; int opt_renumerate = 0; char *opt_port = NULL; char *opt_watchdog = NULL; char *opt_reset = NULL; int opt_query = 0; int ret; progname = argv[0]; while (1) { int c; c = getopt (argc, argv, options); if (c == -1) break; switch (c) { case 'D': devpath = optarg; break; case 'n': opt_renumerate++; break; case 'p': opt_port = optarg; break; case 'w': opt_watchdog = optarg; break; case 'r': opt_reset = optarg; /* * Sanity check so we can reject bad * arguments before device access. */ if(reset_kind(opt_reset) < 0) usage(); break; case 'Q': opt_query = 1; break; case 'v': verbose++; break; case 'd': debug_mask = strtoul(optarg, NULL, 0); break; case 'h': default: ERR("Unknown option '%c'\n", c); usage(); } } if(!devpath) { ERR("Missing device path\n"); usage(); } DBG("Startup %s\n", devpath); astribank = astribank_new(devpath); if(!astribank) { ERR("Failed initializing Astribank\n"); return 1; } mpp = astribank_mpp_open(astribank); /* * First process reset options. We want to be able * to reset minimal USB firmwares even if they don't * implement the full MPP protocol (e.g: EEPROM_BURN) */ if(opt_reset) { int full_reset; if((full_reset = reset_kind(opt_reset)) < 0) { ERR("Bad reset kind '%s'\n", opt_reset); return 1; } DBG("Resetting (%s)\n", opt_reset); if((ret = mpp_reset(mpp, full_reset)) < 0) { ERR("%s Resetting astribank failed: %d\n", (full_reset) ? "Full" : "Half", ret); } goto out; } show_astribank_info(astribank); if(opt_query) { show_hardware(mpp); } else if(opt_renumerate) { DBG("Renumerate\n"); if((ret = mpp_renumerate(mpp)) < 0) { ERR("Renumerating astribank failed: %d\n", ret); } } else if(opt_watchdog) { int watchdogstate = strtoul(opt_watchdog, NULL, 0); DBG("TWINSTAR: Setting watchdog %s-guard\n", (watchdogstate) ? "on" : "off"); if((ret = mpp_tws_setwatchdog(mpp, watchdogstate)) < 0) { ERR("Failed to set watchdog to %d\n", watchdogstate); return 1; } } else if(opt_port) { int new_portnum = strtoul(opt_port, NULL, 0); int tws_portnum = mpp_tws_portnum(mpp); char *msg = (new_portnum == tws_portnum) ? " Same same, never mind..." : ""; DBG("TWINSTAR: Setting portnum to %d.%s\n", new_portnum, msg); if((ret = mpp_tws_setportnum(mpp, new_portnum)) < 0) { ERR("Failed to set USB portnum to %d\n", new_portnum); return 1; } } out: astribank_destroy(astribank); return 0; }