#include #include #include #include #include // DEVICE-RELATED DEFINES #define USBDEV_SHARED_VENDOR 0x16C0 /* VOTI */ #define USBDEV_SHARED_PRODUCT 0x03e8 /* Obdev's free shared PID */ /* Use obdev's generic shared VID/PID pair and follow the rules outlined * in firmware/usbdrv/USBID-License.txt. */ // COMMANDS: #define CMD_PING 0 #define CMD_SWVERSION 1 #define CMD_EEWRITE 2 #define CMD_EEREAD 3 #define CMD_EEOPEN 4 // Can be used if errors occour while writing to the device. #define CMD_RESET 5 // WDT RESET // OTHER DEFS: #define IDENTIFY_NAME 0 #define IDENTIFY_VERSION 1 struct usb_dev_handle *dev; // functions int sendMessage(int command, int var1, int var2, char *buffer); bool sendMessage(int command, int var1, int var2); //shell void help (QStringList *cmd); using namespace std; int main() //int argc, char *argv[] { // USB-Variables struct usb_bus *bus; struct usb_device *devs; char iMan[256]; // Manufacturer name char iProd[256]; // Product name // Some other vars bool break_loop = false; // Init usb_init(); // Init USB usb_set_debug(3); // Debug on usb_find_busses(); usb_find_devices(); // Scan for device for (bus = usb_busses; bus; bus = bus->next) { // Cycle through all busses for (devs = bus->devices; devs; devs = devs->next) { // Cycle through all devices on that bus. cout << "Checking device: \n\tBUS:" << bus->dirname << "\\" << devs->filename << "\n\tIDV:" << devs->descriptor.idVendor << "\n\tIDP:" << devs->descriptor.idProduct << endl; if (devs->descriptor.idVendor == USBDEV_SHARED_VENDOR && devs->descriptor.idProduct == USBDEV_SHARED_PRODUCT) { cout << "FOUND DEVICE! " << endl; break_loop = true; // Tell the second loop to exit as well. break; // Exit loop } } if (break_loop) break; // Break if dev was found } // Check whether a device was found if (!break_loop) { // If we didn't leave the loop on purpose the device wasn't found cout << "!!! ERROR: Device couldn't be found !!!" << endl; return 1; } // If the device was found we try to open it. dev = usb_open(devs); // Since we left the loop when the right device was active we may still use it now. if (dev) { // We were able to open it :) // query basic info usb_get_string_simple(dev,devs->descriptor.iManufacturer,iMan, sizeof(iMan)); usb_get_string_simple(dev,devs->descriptor.iProduct,iProd, sizeof(iProd)); } else { cout << "!!! ERROR: Device could not be opened !!!" << endl; return 1; } // Create the shell QStringList command; string temp; bool exit = false; while (!exit) { cout << iMan << "@" << iProd << "# " << ends; getline(cin, temp); command = QString::fromStdString(temp).split(" "); if (command.at(0) == "exit" || command.at(0) == "quit") exit = true; else if (command.at(0) == "reset") { cout << "Triggering a watchdog-reset..." << endl; sendMessage(CMD_RESET,0,0); } else if (command.at(0) == "raw") { if (command.count() < 2) help(&command); int p1 = 0, p2 = 0; if (command.count() >= 4) { p1 = command.at(2).toInt(); p2 = command.at(3).toInt(); } else if (command.count() >= 3) { p1 = command.at(2).toInt(); } char buf[16]; int retVal = sendMessage(command.at(1).toInt(), p1, p2, buf); if (retVal > 0) { buf[retVal] = 0; cout << "Answer (" << QString::number(retVal).toStdString().data() << "B): " << buf << endl; } else if (retVal == 0) { cout << "This command has no response." << endl; } else { cout << "ERROR: " << retVal << endl; } } else if (command.at(0) == "rawnum") { if (command.count() < 2) help(&command); int p1 = 0, p2 = 0; if (command.count() >= 4) { p1 = command.at(2).toInt(); p2 = command.at(3).toInt(); } else if (command.count() >= 3) { p1 = command.at(2).toInt(); } char buf[16]; int retVal = sendMessage(command.at(1).toInt(), p1, p2, buf); if (retVal > 0) { buf[retVal] = 0; cout << "Answer (" << QString::number(retVal).toStdString().data() << "B): "; for (int y = 0; y < retVal; y++) { cout << " 0x" << QString::number(buf[y], 16).toStdString().data() << "(" << QString::number((unsigned char) buf[y],10).toStdString().data() << ")"; } cout << endl; } else if (retVal == 0) { cout << "This command has no response." << endl; } else { cout << "ERROR: " << retVal << endl; } } else if (command.at(0) == "ping") { if (command.count() != 2) help(&command); else { char buf[1]; int retVal = sendMessage(CMD_PING, command.at(1).at(0).toAscii(),0, buf); if (retVal > 0) { buf[retVal] = 0; cout << "PING returned (" << QString::number(retVal).toStdString().data() << "B): " << buf << endl; } else { cout << "ERROR: Received no data!" << endl; } } } else if (command.at(0) == "dump") { int memSize = 512*16; char buf[16]; if (command.count() != 2) help(&command); else { ofstream file(command.at(1).toStdString().c_str()); if (!file.is_open()) { cerr << "ERROR: Couldn't open file!" << endl; } else { cout << "Dumping memory..." << endl; for (int addr=0; addr < memSize; ++addr) { cout << "\r" << addr+1 << "\r\t / " << memSize << " Bytes (" << (int)((float)(addr+1)/memSize*100) << "%) " << ends; int retVal = sendMessage(3, addr, 0, buf); file << buf[0]; } cout << endl << "done." << endl; } } } else if (command.at(0) == "backup") { sendMessage(4, 0, 0); unsigned int memSize = 512*16; char buf[16]; if (command.count() != 2) help(&command); else { ifstream file(command.at(1).toStdString().c_str()); if (!file.is_open()) { cerr << "ERROR: Couldn't open file!" << endl; } else { cout << "Writing memory..." << endl; for (unsigned int addr=0; addr < memSize; ++addr) { cout << "\r" << addr+1 << "\r\t / " << memSize << " Bytes (" << (int)((float)(addr+1)/memSize*100) << "%) " << ends; unsigned int value, errs; errs=0; if ((value = file.get()) == -1) value=255; // If file end too early, fill up with 255s while (errs < 3) { int retVal = sendMessage(2, addr, value, buf); if (false && buf[0] != value) { // Disabled due to an error in the fw? errs++; cerr << endl << "ERROR writing to address " << addr <<". Read back " << (int)buf[0] << " instead of " << (int)value << ". Try " << errs << endl; } else { errs = 255; } } } cout << endl << "done." << endl; } } } else if (command.at(0) == "" || command.at(0) == " "); else if (command.at(0) == "help") { help(&command); } else { cout << command.at(0).toStdString().data() << ": Command not found!" << endl; } // Ping dev to mke sure it's still alive char buf[1]; int8_t retVal = sendMessage(CMD_PING, command.at(0).at(0).toAscii(),0, buf); // instead of creating a random number we use the first letter of our alst command if (retVal <= 0) { cout << "ERROR: LOST CONNECTION!" << endl; exit = 1; } } cout << "Closing device..." << endl; usb_close(dev); return 0; } int sendMessage(int command, int var1, int var2, char *buffer) { return (usb_control_msg(dev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, command, var1, var2, (char *)buffer, sizeof(buffer), 5000)); } bool sendMessage(int command, int var1, int var2) { if (usb_control_msg(dev, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, command, var1, var2, NULL, 0, 5000) < 0) return false; return true; } // SHELL-RELATED functions void help (QStringList *cmd) { char pos=1; if (cmd->count() == 1) pos = 0; if (cmd->at(pos) == "ping") { cout << "Syntax: ping [AnyChar]\nPing will simply return the character you entered." << endl; } else if (cmd->at(pos) == "raw") { cout << "Syntax: raw [command] ([Param1]) ([Param2])\nThis will send the raw data to the device. All parameters will be converted to numbers. (65->A)\nExample: raw\t42\t13\t37\n\t\t^cmd\t^param1\t^param2" << endl; } else if (cmd->at(pos) == "dump") { cout << "Syntax: dump [filename]\nDumps the full eeprom memory as bytecode into filename." << endl; } else if (cmd->at(pos) == "backup") { cout << "Syntax: backup [filename]\nCopies the content of filename into the eeprom memory. Filename has to be a binary file." << endl; } else if (cmd->at(pos) == "help") { cout << "List of commands: raw, rawnum, ping, help, dump, backup" << endl; } else { cout << cmd->at(pos).toStdString().data() << ": Help not found!" << endl; } return; }