/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2012 by Amaury Pouly * * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include "hwstub.h" #include #include #include #include #include #include #include #include #include #include "soc_desc.hpp" #if LUA_VERSION_NUM < 502 #warning You need at least lua 5.2 #endif /** * Global variables */ bool g_quiet = false; bool g_exit = false; struct hwstub_device_t *g_hwdev; struct hwstub_version_desc_t g_hwdev_ver; struct hwstub_layout_desc_t g_hwdev_layout; struct hwstub_target_desc_t g_hwdev_target; struct hwstub_stmp_desc_t g_hwdev_stmp; struct hwstub_pp_desc_t g_hwdev_pp; lua_State *g_lua; /** * hw specific */ void print_log(struct hwstub_device_t *hwdev) { do { char buffer[128]; int length = hwstub_get_log(hwdev, buffer, sizeof(buffer) - 1); if(length <= 0) break; buffer[length] = 0; printf("%s", buffer); }while(1); } /** * Lua specific */ int my_lua_help(lua_State *state) { bool has_sub = false; // implement help() in C so that we do not rely on the init to implement it // help can take optional arguments int n = lua_gettop(state); lua_getglobal(state, "hwstub"); if(!lua_istable(state, -1)) goto Lerr; lua_getfield(state, -1, "help"); if(!lua_istable(state, -1)) goto Lerr; for(int i = 1; i <= n; i++) { lua_pushvalue(state, i); lua_gettable(state, -2); if(lua_isnil(state, -1)) { printf("I don't know subtopic '%s'!\n", lua_tostring(state, i)); return 0; } if(!lua_istable(state, -1)) { printf("Subtopic '%s' is not a table!\n", lua_tostring(state, i)); return 0; } } printf("================[ HELP "); for(int i = 1; i <= n; i++) printf("> %s ", lua_tostring(state, i)); printf("]================\n"); lua_pushnil(state); while(lua_next(state, -2)) { // key is at -2 and value at -1 if(lua_isstring(state, -1)) printf("%s\n", lua_tostring(state, -1)); else if(lua_istable(state, -1)) has_sub = true; // pop value but keep key lua_pop(state, 1); } if(has_sub) { printf("\n"); printf("You can get more information on the following subtopics:\n"); lua_pushnil(state); while(lua_next(state, -2)) { // key is at -2 and value at -1 if(lua_istable(state, -1)) printf("* %s\n", lua_tostring(state, -2)); // pop value but keep key lua_pop(state, 1); } } printf("================[ STOP ]================\n"); return 0; Lerr: printf("There is a problem with the Lua context. Help is expected to be in hwstub.help\n"); printf("You must have messed badly the environment.\n"); return 0; } typedef soc_word_t (*hw_readn_fn_t)(lua_State *state, soc_addr_t addr); typedef void (*hw_writen_fn_t)(lua_State *state, soc_addr_t addr, soc_word_t val); soc_word_t hw_read8(lua_State *state, soc_addr_t addr) { uint8_t u; if(hwstub_rw_mem(g_hwdev, 1, addr, &u, sizeof(u)) != sizeof(u)) luaL_error(state, "fail to read8 @ %p", addr); return u; } soc_word_t hw_read16(lua_State *state, soc_addr_t addr) { uint16_t u; if(hwstub_rw_mem(g_hwdev, 1, addr, &u, sizeof(u)) != sizeof(u)) luaL_error(state, "fail to read16 @ %p", addr); return u; } soc_word_t hw_read32(lua_State *state, soc_addr_t addr) { uint32_t u; if(hwstub_rw_mem(g_hwdev, 1, addr, &u, sizeof(u)) != sizeof(u)) luaL_error(state, "fail to read32 @ %p", addr); return u; } void hw_write8(lua_State *state, soc_addr_t addr, soc_word_t val) { uint8_t u = val; if(hwstub_rw_mem(g_hwdev, 0, addr, &u, sizeof(u)) != sizeof(u)) luaL_error(state, "fail to write8 @ %p", addr); } void hw_write16(lua_State *state, soc_addr_t addr, soc_word_t val) { uint16_t u = val; if(hwstub_rw_mem(g_hwdev, 0, addr, &u, sizeof(u)) != sizeof(u)) luaL_error(state, "fail to write16 @ %p", addr); } void hw_write32(lua_State *state, soc_addr_t addr, soc_word_t val) { uint32_t u = val; if(hwstub_rw_mem(g_hwdev, 0, addr, &u, sizeof(u)) != sizeof(u)) luaL_error(state, "fail to write32 @ %p", addr); } int my_lua_readn(lua_State *state) { hw_readn_fn_t fn = (hw_readn_fn_t)lua_touserdata(state, lua_upvalueindex(1)); int n = lua_gettop(state); if(n != 1) luaL_error(state, "readn takes a single argument"); lua_pushunsigned(state, fn(state, luaL_checkunsigned(state, 1))); return 1; } int my_lua_writen(lua_State *state) { hw_writen_fn_t fn = (hw_writen_fn_t)lua_touserdata(state, lua_upvalueindex(1)); int n = lua_gettop(state); if(n != 2) luaL_error(state, "writen takes two arguments"); fn(state, luaL_checkunsigned(state, 1), luaL_checkunsigned(state, 2)); return 0; } int my_lua_printlog(lua_State *state) { print_log(g_hwdev); return 0; } int my_lua_quit(lua_State *state) { g_exit = true; return 0; } int my_lua_udelay(lua_State *state) { int n = lua_gettop(state); if(n != 1) luaL_error(state, "udelay takes one argument"); long usec = lua_tointeger(state, -1); usleep(usec); return 0; } bool my_lua_import_hwstub() { int oldtop = lua_gettop(g_lua); lua_newtable(g_lua); // hwstub lua_newtable(g_lua); // options lua_pushboolean(g_lua, g_quiet); lua_setfield(g_lua, -2, "quiet"); lua_setfield(g_lua, -2, "options"); lua_newtable(g_lua); // dev lua_newtable(g_lua); // version lua_pushinteger(g_lua, g_hwdev_ver.bMajor); lua_setfield(g_lua, -2, "major"); lua_pushinteger(g_lua, g_hwdev_ver.bMinor); lua_setfield(g_lua, -2, "minor"); lua_pushinteger(g_lua, g_hwdev_ver.bRevision); lua_setfield(g_lua, -2, "revision"); lua_setfield(g_lua, -2, "version"); lua_newtable(g_lua); // layout lua_newtable(g_lua); // code lua_pushinteger(g_lua, g_hwdev_layout.dCodeStart); lua_setfield(g_lua, -2, "start"); lua_pushinteger(g_lua, g_hwdev_layout.dCodeSize); lua_setfield(g_lua, -2, "size"); lua_setfield(g_lua, -2, "code"); lua_newtable(g_lua); // stack lua_pushinteger(g_lua, g_hwdev_layout.dStackStart); lua_setfield(g_lua, -2, "start"); lua_pushinteger(g_lua, g_hwdev_layout.dStackSize); lua_setfield(g_lua, -2, "size"); lua_setfield(g_lua, -2, "stack"); lua_newtable(g_lua); // buffer lua_pushinteger(g_lua, g_hwdev_layout.dBufferStart); lua_setfield(g_lua, -2, "start"); lua_pushinteger(g_lua, g_hwdev_layout.dBufferSize); lua_setfield(g_lua, -2, "size"); lua_setfield(g_lua, -2, "buffer"); lua_setfield(g_lua, -2, "layout"); lua_newtable(g_lua); // target lua_pushstring(g_lua, g_hwdev_target.bName); lua_setfield(g_lua, -2, "name"); lua_pushinteger(g_lua, g_hwdev_target.dID); lua_setfield(g_lua, -2, "id"); lua_pushinteger(g_lua, HWSTUB_TARGET_UNK); lua_setfield(g_lua, -2, "UNK"); lua_pushinteger(g_lua, HWSTUB_TARGET_STMP); lua_setfield(g_lua, -2, "STMP"); lua_pushinteger(g_lua, HWSTUB_TARGET_PP); lua_setfield(g_lua, -2, "PP"); lua_pushinteger(g_lua, HWSTUB_TARGET_RK27); lua_setfield(g_lua, -2, "RK27"); lua_setfield(g_lua, -2, "target"); if(g_hwdev_target.dID == HWSTUB_TARGET_STMP) { lua_newtable(g_lua); // stmp lua_pushinteger(g_lua, g_hwdev_stmp.wChipID); lua_setfield(g_lua, -2, "chipid"); lua_pushinteger(g_lua, g_hwdev_stmp.bRevision); lua_setfield(g_lua, -2, "rev"); lua_pushinteger(g_lua, g_hwdev_stmp.bPackage); lua_setfield(g_lua, -2, "package"); lua_setfield(g_lua, -2, "stmp"); } else if(g_hwdev_target.dID == HWSTUB_TARGET_PP) { lua_newtable(g_lua); // pp lua_pushinteger(g_lua, g_hwdev_pp.wChipID); lua_setfield(g_lua, -2, "chipid"); lua_pushlstring(g_lua, (const char *)g_hwdev_pp.bRevision, 2); lua_setfield(g_lua, -2, "rev"); lua_setfield(g_lua, -2, "pp"); } lua_pushlightuserdata(g_lua, (void *)&hw_read8); lua_pushcclosure(g_lua, my_lua_readn, 1); lua_setfield(g_lua, -2, "read8"); lua_pushlightuserdata(g_lua, (void *)&hw_read16); lua_pushcclosure(g_lua, my_lua_readn, 1); lua_setfield(g_lua, -2, "read16"); lua_pushlightuserdata(g_lua, (void *)&hw_read32); lua_pushcclosure(g_lua, my_lua_readn, 1); lua_setfield(g_lua, -2, "read32"); lua_pushlightuserdata(g_lua, (void *)&hw_write8); lua_pushcclosure(g_lua, my_lua_writen, 1); lua_setfield(g_lua, -2, "write8"); lua_pushlightuserdata(g_lua, (void *)&hw_write16); lua_pushcclosure(g_lua, my_lua_writen, 1); lua_setfield(g_lua, -2, "write16"); lua_pushlightuserdata(g_lua, (void *)&hw_write32); lua_pushcclosure(g_lua, my_lua_writen, 1); lua_setfield(g_lua, -2, "write32"); lua_pushcclosure(g_lua, my_lua_printlog, 0); lua_setfield(g_lua, -2, "print_log"); lua_setfield(g_lua, -2, "dev"); lua_newtable(g_lua); // host lua_newtable(g_lua); // version lua_pushinteger(g_lua, HWSTUB_VERSION_MAJOR); lua_setfield(g_lua, -2, "major"); lua_pushinteger(g_lua, HWSTUB_VERSION_MINOR); lua_setfield(g_lua, -2, "minor"); lua_setfield(g_lua, -2, "version"); lua_setfield(g_lua, -2, "host"); lua_newtable(g_lua); // soc lua_setfield(g_lua, -2, "soc"); lua_newtable(g_lua); // help lua_pushinteger(g_lua, 1); lua_pushstring(g_lua, "This is the help for hwstub_tool. This tools uses Lua to interpret commands."); lua_settable(g_lua, -3); lua_pushinteger(g_lua, 2); lua_pushstring(g_lua, "You can get help by running help(). Help is organised in topics and subtopics and so on."); lua_settable(g_lua, -3); lua_pushinteger(g_lua, 3); lua_pushstring(g_lua, "If you want to access the help of topic x, subtopic y, subsubtopic z, type help(x,y,z)."); lua_settable(g_lua, -3); lua_pushinteger(g_lua, 4); lua_pushstring(g_lua, "Example: help(\"hwstub\")."); lua_settable(g_lua, -3); lua_setfield(g_lua, -2, "help"); lua_pushcclosure(g_lua, my_lua_udelay, 0); lua_setfield(g_lua, -2, "udelay"); lua_setglobal(g_lua, "hwstub"); lua_pushcfunction(g_lua, my_lua_help); lua_setglobal(g_lua, "help"); lua_pushcfunction(g_lua, my_lua_quit); lua_setglobal(g_lua, "exit"); lua_pushcfunction(g_lua, my_lua_quit); lua_setglobal(g_lua, "quit"); if(lua_gettop(g_lua) != oldtop) { printf("internal error: unbalanced my_lua_import_soc\n"); return false; } return true; } int my_lua_read_reg(lua_State *state) { int n = lua_gettop(state); if(n != 0) luaL_error(state, "read() takes no argument"); soc_addr_t addr = lua_tounsigned(state, lua_upvalueindex(1)); lua_pushunsigned(state, hw_read32(state, addr)); return 1; } int my_lua_write_reg(lua_State *state) { int n = lua_gettop(state); if(n != 1) luaL_error(state, "write() takes one argument"); soc_word_t val = luaL_checkunsigned(state, 1); soc_addr_t addr = lua_tounsigned(state, lua_upvalueindex(1)); hw_write32(state, addr, val); return 0; } int my_lua_read_field(lua_State *state) { int n = lua_gettop(state); if(n != 0) luaL_error(state, "read() takes no argument"); soc_addr_t addr = lua_tounsigned(state, lua_upvalueindex(1)); soc_word_t shift = lua_tounsigned(state, lua_upvalueindex(2)); soc_word_t mask = lua_tounsigned(state, lua_upvalueindex(3)); lua_pushunsigned(state, (hw_read32(state, addr) >> shift) & mask); return 1; } int my_lua_write_field(lua_State *state) { int n = lua_gettop(state); if(n != 0 && n!= 1) luaL_error(state, "write() takes one or no argument"); soc_addr_t addr = lua_tounsigned(state, lua_upvalueindex(1)); soc_word_t shift = lua_tounsigned(state, lua_upvalueindex(2)); soc_word_t mask = lua_tounsigned(state, lua_upvalueindex(3)); bool is_sct = lua_toboolean(state, lua_upvalueindex(5)); soc_word_t value = mask; if(n == 1) { if(!lua_isnumber(state, 1) && lua_isstring(state, 1)) { lua_pushvalue(state, lua_upvalueindex(4)); lua_pushvalue(state, 1); lua_gettable(state, -2); if(lua_isnil(state, -1)) luaL_error(state, "field has no value %s", lua_tostring(state, 1)); value = luaL_checkunsigned(state, -1); lua_pop(state, 2); } else value = luaL_checkunsigned(state, 1); value &= mask; } if(!is_sct) value = value << shift | (hw_read32(state, addr) & ~(mask << shift)); else value <<= shift; hw_write32(state, addr, value); return 0; } int my_lua_sct_reg(lua_State *state) { int n = lua_gettop(state); if(n != 1) luaL_error(state, "sct() takes one argument"); soc_addr_t addr = lua_tounsigned(state, lua_upvalueindex(1)); char op = lua_tounsigned(state, lua_upvalueindex(2)); soc_word_t mask = luaL_checkunsigned(state, 1); soc_word_t value = hw_read32(state, addr); if(op == 's') value |= mask; else if(op == 'c') value &= ~mask; else if(op == 't') value ^= mask; else luaL_error(state, "sct() internal error"); hw_write32(state, addr, value); return 0; } void my_lua_create_field(soc_addr_t addr, const soc_reg_field_t& field, bool sct) { lua_newtable(g_lua); lua_pushstring(g_lua, field.name.c_str()); lua_setfield(g_lua, -2, "name"); lua_pushunsigned(g_lua, addr); lua_setfield(g_lua, -2, "addr"); lua_pushboolean(g_lua, sct); lua_setfield(g_lua, -2, "sct"); lua_pushunsigned(g_lua, field.first_bit); lua_setfield(g_lua, -2, "first_bit"); lua_pushunsigned(g_lua, field.last_bit); lua_setfield(g_lua, -2, "last_bit"); lua_pushunsigned(g_lua, field.bitmask()); lua_setfield(g_lua, -2, "bitmask"); soc_word_t local_bitmask = field.bitmask() >> field.first_bit; lua_pushunsigned(g_lua, local_bitmask); lua_setfield(g_lua, -2, "local_bitmask"); lua_pushunsigned(g_lua, addr); lua_pushunsigned(g_lua, field.first_bit); lua_pushunsigned(g_lua, local_bitmask); lua_pushcclosure(g_lua, my_lua_read_field, 3); lua_setfield(g_lua, -2, "read"); lua_pushunsigned(g_lua, addr); lua_pushunsigned(g_lua, field.first_bit); lua_pushunsigned(g_lua, local_bitmask); lua_pushvalue(g_lua, -4); lua_pushboolean(g_lua, false); lua_pushcclosure(g_lua, my_lua_write_field, 5); lua_setfield(g_lua, -2, "write"); if(sct) { lua_pushunsigned(g_lua, addr + 4); lua_pushunsigned(g_lua, field.first_bit); lua_pushunsigned(g_lua, local_bitmask); lua_pushvalue(g_lua, -4); lua_pushboolean(g_lua, true); lua_pushcclosure(g_lua, my_lua_write_field, 5); lua_setfield(g_lua, -2, "set"); lua_pushunsigned(g_lua, addr + 8); lua_pushunsigned(g_lua, field.first_bit); lua_pushunsigned(g_lua, local_bitmask); lua_pushvalue(g_lua, -4); lua_pushboolean(g_lua, true); lua_pushcclosure(g_lua, my_lua_write_field, 5); lua_setfield(g_lua, -2, "clr"); lua_pushunsigned(g_lua, addr + 12); lua_pushunsigned(g_lua, field.first_bit); lua_pushunsigned(g_lua, local_bitmask); lua_pushvalue(g_lua, -4); lua_pushboolean(g_lua, true); lua_pushcclosure(g_lua, my_lua_write_field, 5); lua_setfield(g_lua, -2, "tog"); } for(size_t i = 0; i < field.value.size(); i++) { lua_pushunsigned(g_lua, field.value[i].value); lua_setfield(g_lua, -2, field.value[i].name.c_str()); } } void my_lua_create_reg(soc_addr_t addr, size_t index, const soc_reg_t& reg) { lua_newtable(g_lua); lua_pushstring(g_lua, reg.addr[index].name.c_str()); lua_setfield(g_lua, -2, "name"); lua_pushunsigned(g_lua, addr + reg.addr[index].addr); lua_setfield(g_lua, -2, "addr"); lua_pushboolean(g_lua, !!(reg.flags & REG_HAS_SCT)); lua_setfield(g_lua, -2, "sct"); lua_pushunsigned(g_lua, addr + reg.addr[index].addr); lua_pushcclosure(g_lua, my_lua_read_reg, 1); lua_setfield(g_lua, -2, "read"); lua_pushunsigned(g_lua, addr + reg.addr[index].addr); lua_pushcclosure(g_lua, my_lua_write_reg, 1); lua_setfield(g_lua, -2, "write"); if(reg.flags & REG_HAS_SCT) { lua_pushunsigned(g_lua, addr + reg.addr[index].addr + 4); lua_pushcclosure(g_lua, my_lua_write_reg, 1); lua_setfield(g_lua, -2, "set"); lua_pushunsigned(g_lua, addr + reg.addr[index].addr + 8); lua_pushcclosure(g_lua, my_lua_write_reg, 1); lua_setfield(g_lua, -2, "clr"); lua_pushunsigned(g_lua, addr + reg.addr[index].addr + 12); lua_pushcclosure(g_lua, my_lua_write_reg, 1); lua_setfield(g_lua, -2, "tog"); } else { lua_pushunsigned(g_lua, addr + reg.addr[index].addr); lua_pushunsigned(g_lua, 's'); lua_pushcclosure(g_lua, my_lua_sct_reg, 2); lua_setfield(g_lua, -2, "set"); lua_pushunsigned(g_lua, addr + reg.addr[index].addr); lua_pushunsigned(g_lua, 'c'); lua_pushcclosure(g_lua, my_lua_sct_reg, 2); lua_setfield(g_lua, -2, "clr"); lua_pushunsigned(g_lua, addr + reg.addr[index].addr); lua_pushunsigned(g_lua, 't'); lua_pushcclosure(g_lua, my_lua_sct_reg, 2); lua_setfield(g_lua, -2, "tog"); } for(size_t i = 0; i < reg.field.size(); i++) { my_lua_create_field(addr + reg.addr[index].addr, reg.field[i], reg.flags & REG_HAS_SCT); lua_setfield(g_lua, -2, reg.field[i].name.c_str()); } } void my_lua_create_dev(size_t index, const soc_dev_t& dev) { lua_newtable(g_lua); lua_pushstring(g_lua, dev.addr[index].name.c_str()); lua_setfield(g_lua, -2, "name"); lua_pushunsigned(g_lua, dev.addr[index].addr); lua_setfield(g_lua, -2, "addr"); for(size_t i = 0; i < dev.reg.size(); i++) { bool table = dev.reg[i].addr.size() > 1; if(table) lua_newtable(g_lua); else lua_pushnil(g_lua); for(size_t k = 0; k < dev.reg[i].addr.size(); k++) { my_lua_create_reg(dev.addr[index].addr, k, dev.reg[i]); if(table) { lua_pushinteger(g_lua, k); lua_pushvalue(g_lua, -2); lua_settable(g_lua, -4); } lua_setfield(g_lua, -3, dev.reg[i].addr[k].name.c_str()); } if(table) lua_setfield(g_lua, -2, dev.reg[i].name.c_str()); else lua_pop(g_lua, 1); } } bool my_lua_import_soc(const soc_t& soc) { int oldtop = lua_gettop(g_lua); lua_getglobal(g_lua, "hwstub"); lua_getfield(g_lua, -1, "soc"); lua_newtable(g_lua); lua_pushstring(g_lua, soc.name.c_str()); lua_setfield(g_lua, -2, "name"); lua_pushstring(g_lua, soc.desc.c_str()); lua_setfield(g_lua, -2, "desc"); for(size_t i = 0; i < soc.dev.size(); i++) { bool table = soc.dev[i].addr.size() > 1; if(table) lua_newtable(g_lua); else lua_pushnil(g_lua); for(size_t k = 0; k < soc.dev[i].addr.size(); k++) { my_lua_create_dev(k, soc.dev[i]); if(table) { lua_pushinteger(g_lua, k + 1); lua_pushvalue(g_lua, -2); lua_settable(g_lua, -4); } lua_setfield(g_lua, -3, soc.dev[i].addr[k].name.c_str()); } if(table) lua_setfield(g_lua, -2, soc.dev[i].name.c_str()); else lua_pop(g_lua, 1); } lua_setfield(g_lua, -2, soc.name.c_str()); lua_pop(g_lua, 2); if(lua_gettop(g_lua) != oldtop) { printf("internal error: unbalanced my_lua_import_soc\n"); return false; } return true; } bool my_lua_import_soc(const std::vector< soc_t >& socs) { for(size_t i = 0; i < socs.size(); i++) { if(!g_quiet) printf("importing %s...\n", socs[i].name.c_str()); if(!my_lua_import_soc(socs[i])) return false; } return true; } /** * glue */ void usage(void) { printf("hwstub_tool, compiled with hwstub protocol %d.%d\n", HWSTUB_VERSION_MAJOR, HWSTUB_VERSION_MINOR); printf("\n"); printf("usage: hwstub_tool [options] \n"); printf("options:\n"); printf(" --help/-? Display this help\n"); printf(" --quiet/-q Quiet non-command messages\n"); printf(" -i Set lua init file (default is init.lua)\n"); printf(" -e Execute at startup\n"); printf(" -f Execute at startup\n"); printf("Relative order of -e and -f commands are preserved.\n"); printf("They are executed after init file.\n"); exit(1); } enum exec_type { exec_cmd, exec_file }; int main(int argc, char **argv) { const char *lua_init = "init.lua"; std::vector< std::pair< exec_type, std::string > > startup_cmds; // parse command line while(1) { static struct option long_options[] = { {"help", no_argument, 0, '?'}, {"quiet", no_argument, 0, 'q'}, {0, 0, 0, 0} }; int c = getopt_long(argc, argv, "?qi:e:f:", long_options, NULL); if(c == -1) break; switch(c) { case -1: break; case 'q': g_quiet = true; break; case '?': usage(); break; case 'i': lua_init = optarg; break; case 'e': startup_cmds.push_back(std::make_pair(exec_cmd, std::string(optarg))); break; case 'f': startup_cmds.push_back(std::make_pair(exec_file, std::string(optarg))); break; default: abort(); } } // load register descriptions std::vector< soc_t > socs; for(int i = optind; i < argc; i++) { socs.push_back(soc_t()); if(!soc_desc_parse_xml(argv[i], socs[socs.size() - 1])) { printf("Cannot load description '%s'\n", argv[i]); return 2; } } // create usb context libusb_context *ctx; libusb_init(&ctx); libusb_set_debug(ctx, 3); // look for device if(!g_quiet) printf("Looking for hwstub device ...\n"); // open first device libusb_device **list; ssize_t cnt = hwstub_get_device_list(ctx, &list); if(cnt <= 0) { printf("No device found\n"); return 1; } libusb_device_handle *handle; if(libusb_open(list[0], &handle) != 0) { printf("Cannot open device\n"); return 1; } libusb_free_device_list(list, 1); // admin stuff libusb_device *mydev = libusb_get_device(handle); if(!g_quiet) { printf("device found at %d:%d\n", libusb_get_bus_number(mydev), libusb_get_device_address(mydev)); } g_hwdev = hwstub_open(handle); if(g_hwdev == NULL) { printf("Cannot open device!\n"); return 1; } // get hwstub information int ret = hwstub_get_desc(g_hwdev, HWSTUB_DT_VERSION, &g_hwdev_ver, sizeof(g_hwdev_ver)); if(ret != sizeof(g_hwdev_ver)) { printf("Cannot get version!\n"); goto Lerr; } if(g_hwdev_ver.bMajor != HWSTUB_VERSION_MAJOR || g_hwdev_ver.bMinor < HWSTUB_VERSION_MINOR) { printf("Warning: this tool is possibly incompatible with your device:\n"); printf("Device version: %d.%d.%d\n", g_hwdev_ver.bMajor, g_hwdev_ver.bMinor, g_hwdev_ver.bRevision); printf("Host version: %d.%d\n", HWSTUB_VERSION_MAJOR, HWSTUB_VERSION_MINOR); } // get memory layout information ret = hwstub_get_desc(g_hwdev, HWSTUB_DT_LAYOUT, &g_hwdev_layout, sizeof(g_hwdev_layout)); if(ret != sizeof(g_hwdev_layout)) { printf("Cannot get layout: %d\n", ret); goto Lerr; } // get target ret = hwstub_get_desc(g_hwdev, HWSTUB_DT_TARGET, &g_hwdev_target, sizeof(g_hwdev_target)); if(ret != sizeof(g_hwdev_target)) { printf("Cannot get target: %d\n", ret); goto Lerr; } // get STMP specific information if(g_hwdev_target.dID == HWSTUB_TARGET_STMP) { ret = hwstub_get_desc(g_hwdev, HWSTUB_DT_STMP, &g_hwdev_stmp, sizeof(g_hwdev_stmp)); if(ret != sizeof(g_hwdev_stmp)) { printf("Cannot get stmp: %d\n", ret); goto Lerr; } } // get PP specific information if(g_hwdev_target.dID == HWSTUB_TARGET_PP) { ret = hwstub_get_desc(g_hwdev, HWSTUB_DT_PP, &g_hwdev_pp, sizeof(g_hwdev_pp)); if(ret != sizeof(g_hwdev_pp)) { printf("Cannot get pp: %d\n", ret); goto Lerr; } } /** Init lua */ // create lua state g_lua = luaL_newstate(); if(g_lua == NULL) { printf("Cannot create lua state\n"); return 1; } // import hwstub if(!my_lua_import_hwstub()) printf("Cannot import hwstub description into Lua context\n"); // open all standard libraires luaL_openlibs(g_lua); // import socs if(!my_lua_import_soc(socs)) printf("Cannot import SoC descriptions into Lua context\n"); if(luaL_dofile(g_lua, lua_init)) printf("error in init: %s\n", lua_tostring(g_lua, -1)); lua_pop(g_lua, lua_gettop(g_lua)); /** start interactive mode */ if(!g_quiet) printf("Starting interactive lua session. Type 'help()' to get some help\n"); /** run startup commands */ for(size_t i = 0; i < startup_cmds.size(); i++) { bool ret = false; if(!g_quiet) printf("Running '%s'...\n", startup_cmds[i].second.c_str()); if(startup_cmds[i].first == exec_file) ret = luaL_dofile(g_lua, startup_cmds[i].second.c_str()); else if(startup_cmds[i].first == exec_cmd) ret = luaL_dostring(g_lua, startup_cmds[i].second.c_str()); if(ret) printf("error: %s\n", lua_tostring(g_lua, -1)); } // use readline to provide some history and completion rl_bind_key('\t', rl_complete); while(!g_exit) { char *input = readline("> "); if(!input) break; add_history(input); // evaluate string if(luaL_dostring(g_lua, input)) printf("error: %s\n", lua_tostring(g_lua, -1)); // pop everything to start from a clean stack lua_pop(g_lua, lua_gettop(g_lua)); free(input); } Lerr: // display log if handled if(!g_quiet) printf("Device log:\n"); print_log(g_hwdev); hwstub_release(g_hwdev); return 1; }