Updating main command line input args, and libusb logging/debug messages.
now able to accept LIBUSB_LOG_LEVEL from commandline to turn on/off error messges at runtime. Also setting level > 0 will print messages during device discovery and connection. Still need to permit kazzo firmware version to be provided on commandline to support K flag. fixing dictionary call typo with semicolon and setting buffer length to always be provided with function call instead of dictionary call deciding what it should be based on the opcode. Adding some speed notes and other speed related discussions to buffer dictionary.
This commit is contained in:
parent
2f8823053e
commit
132360f305
|
|
@ -16,18 +16,21 @@
|
|||
*/
|
||||
|
||||
//default call dictionary without print option
|
||||
int dictionary_call( USBtransfer *transfer, uint8_t dictionary, uint8_t opcode, uint16_t addr, uint8_t miscdata, uint8_t endpoint, uint8_t *buffer, uint16_t length)
|
||||
int dictionary_call( USBtransfer *transfer, uint8_t dictionary, uint8_t opcode, uint16_t addr, uint8_t miscdata,
|
||||
uint8_t endpoint, uint8_t *buffer, uint16_t length)
|
||||
{
|
||||
return dictionary_call_print_option( ~TRUE, transfer, dictionary, opcode, addr, miscdata, endpoint, buffer, length);
|
||||
}
|
||||
|
||||
//debug call dictionary without print option
|
||||
int dictionary_call_debug( USBtransfer *transfer, uint8_t dictionary, uint8_t opcode, uint16_t addr, uint8_t miscdata, uint8_t endpoint, uint8_t *buffer, uint16_t length)
|
||||
int dictionary_call_debug( USBtransfer *transfer, uint8_t dictionary, uint8_t opcode, uint16_t addr, uint8_t miscdata,
|
||||
uint8_t endpoint, uint8_t *buffer, uint16_t length)
|
||||
{
|
||||
return dictionary_call_print_option( TRUE, transfer, dictionary, opcode, addr, miscdata, endpoint, buffer, length);
|
||||
}
|
||||
|
||||
int dictionary_call_print_option( int print_debug; USBtransfer *transfer, uint8_t dictionary, uint8_t opcode, uint16_t addr, uint8_t miscdata, uint8_t endpoint, uint8_t *buffer, uint16_t length)
|
||||
int dictionary_call_print_option( int print_debug, USBtransfer *transfer, uint8_t dictionary, uint8_t opcode, uint16_t addr, uint8_t miscdata,
|
||||
uint8_t endpoint, uint8_t *buffer, uint16_t length)
|
||||
{
|
||||
transfer->request = dictionary;
|
||||
transfer->wValueMSB = miscdata;
|
||||
|
|
@ -37,26 +40,32 @@ int dictionary_call_print_option( int print_debug; USBtransfer *transfer, uint8_
|
|||
|
||||
//default IN for now reading back error codes from short commands
|
||||
transfer->endpoint = endpoint;
|
||||
transfer->wLength = length;
|
||||
//default length of zero
|
||||
transfer->wLength = 0;
|
||||
// transfer->wLength = 0;
|
||||
|
||||
//return data buffer big enough for one data packet
|
||||
uint8_t rbuf[8];
|
||||
rbuf[0] = 0xA5;
|
||||
rbuf[1] = 0xC3;
|
||||
rbuf[2] = 0xA5;
|
||||
rbuf[3] = 0xC3;
|
||||
rbuf[4] = 0xA5;
|
||||
rbuf[5] = 0xC3;
|
||||
rbuf[6] = 0xA5;
|
||||
rbuf[7] = 0xC3;
|
||||
transfer->data = rbuf;
|
||||
|
||||
if ( buffer == NULL ) {
|
||||
rbuf[0] = 0xA5;
|
||||
rbuf[1] = 0xC3;
|
||||
rbuf[2] = 0xA5;
|
||||
rbuf[3] = 0xC3;
|
||||
rbuf[4] = 0xA5;
|
||||
rbuf[5] = 0xC3;
|
||||
rbuf[6] = 0xA5;
|
||||
rbuf[7] = 0xC3;
|
||||
transfer->data = rbuf;
|
||||
} else {
|
||||
transfer->data = buffer;
|
||||
}
|
||||
|
||||
|
||||
debug("\ndictionary call dict:%d opcode:%d/%x addr:%x data:%x", dictionary, opcode, opcode, addr, miscdata);
|
||||
switch (dictionary) {
|
||||
case PINPORT: debug("dict: PINPORT");
|
||||
transfer->wLength = 1;
|
||||
//transfer->wLength = 1;
|
||||
switch (opcode) {
|
||||
case PP_OPCODE_ONLY_MIN ... PP_OPCODE_ONLY_MAX:
|
||||
debug("PP_OPCODE_ONLY");
|
||||
|
|
@ -72,7 +81,7 @@ int dictionary_call_print_option( int print_debug; USBtransfer *transfer, uint8_
|
|||
break;
|
||||
case PP_OPCODE_8BRV_MIN ... PP_OPCODE_8BRV_MAX:
|
||||
debug("PP_OPCODE_8BRV");
|
||||
transfer->wLength = 2;
|
||||
// transfer->wLength = 2;
|
||||
break;
|
||||
default: //pinport opcode min/max definition error
|
||||
sentinel("bad PP opcode min/max err:%d",ERR_BAD_PP_OP_MINMAX);
|
||||
|
|
@ -80,14 +89,14 @@ int dictionary_call_print_option( int print_debug; USBtransfer *transfer, uint8_
|
|||
break; //end of PINPORT
|
||||
|
||||
case IO: debug("dict: IO");
|
||||
transfer->wLength = 1;
|
||||
// transfer->wLength = 1;
|
||||
switch (opcode) {
|
||||
case IO_OPCODE_ONLY_MIN ... IO_OPCODE_ONLY_MAX:
|
||||
debug("IO_OPCODE_ONLY");
|
||||
break;
|
||||
case IO_OPCODE_RTN_MIN ... IO_OPCODE_RTN_MAX:
|
||||
debug("IO_OPCODE_RTN");
|
||||
transfer->wLength = 8;
|
||||
// transfer->wLength = 8;
|
||||
break;
|
||||
default: //io opcode min/max definition error
|
||||
sentinel("bad IO opcode min/max err:%d",ERR_BAD_IO_OP_MINMAX);
|
||||
|
|
@ -95,14 +104,14 @@ int dictionary_call_print_option( int print_debug; USBtransfer *transfer, uint8_
|
|||
break; //end of IO
|
||||
|
||||
case NES: debug("dict: NES");
|
||||
transfer->wLength = 1;
|
||||
// transfer->wLength = 1;
|
||||
switch (opcode) {
|
||||
case NES_OPCODE_24BOP_MIN ... NES_OPCODE_24BOP_MAX:
|
||||
debug("NES_OPCODE_24BOP");
|
||||
break;
|
||||
case NES_OPCODE_16BOP_8BRV_MIN ... NES_OPCODE_16BOP_8BRV_MAX:
|
||||
debug("NES_OPCODE_16BOP_8BRV");
|
||||
transfer->wLength = 2;
|
||||
// transfer->wLength = 2;
|
||||
break;
|
||||
default: //nes opcode min/max definition error
|
||||
sentinel("bad NES opcode min/max err:%d",ERR_BAD_NES_OP_MINMAX);
|
||||
|
|
@ -110,14 +119,14 @@ int dictionary_call_print_option( int print_debug; USBtransfer *transfer, uint8_
|
|||
break; //end of NES
|
||||
|
||||
case SNES: debug("dict: SNES");
|
||||
transfer->wLength = 1;
|
||||
// transfer->wLength = 1;
|
||||
switch (opcode) {
|
||||
case SNES_OPCODE_24BOP_MIN ... SNES_OPCODE_24BOP_MAX:
|
||||
debug("SNES_OPCODE_24BOP");
|
||||
break;
|
||||
case SNES_OPCODE_24BOP_8BRV_MIN ... SNES_OPCODE_24BOP_8BRV_MAX:
|
||||
debug("SNES_OPCODE_24BOP_8BRV");
|
||||
transfer->wLength = 2;
|
||||
// transfer->wLength = 2;
|
||||
break;
|
||||
default: //snes opcode min/max definition error
|
||||
sentinel("bad SNES opcode min/max err:%d",ERR_BAD_SNES_OP_MINMAX);
|
||||
|
|
@ -125,14 +134,14 @@ int dictionary_call_print_option( int print_debug; USBtransfer *transfer, uint8_
|
|||
break; //end of SNES
|
||||
|
||||
case BUFFER: debug("dict: BUFFER");
|
||||
transfer->wLength = length;
|
||||
// transfer->wLength = length;
|
||||
if (buffer != NULL) {
|
||||
transfer->data = (unsigned char *)buffer;
|
||||
}
|
||||
break; //end of BUFF
|
||||
|
||||
case USB: debug("dict: USB");
|
||||
transfer->wLength = length;
|
||||
// transfer->wLength = length;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -19,13 +19,15 @@
|
|||
#include "shared_errors.h"
|
||||
#include "shared_dictionaries.h"
|
||||
|
||||
//default call dictionary without print option
|
||||
int dictionary_call( USBtransfer *transfer, uint8_t dictionary, uint8_t opcode, uint16_t addr, uint8_t miscdata,
|
||||
uint8_t endpoint, uint8_t *buffer, uint16_t length);
|
||||
|
||||
//dictionary call with debug prints
|
||||
int dictionary_call_debug( USBtransfer *transfer, uint8_t dictionary, uint8_t opcode, uint16_t addr, uint8_t miscdata, uint8_t endpoint, uint8_t *buffer, uint16_t length);
|
||||
//debug call dictionary without print option
|
||||
int dictionary_call_debug( USBtransfer *transfer, uint8_t dictionary, uint8_t opcode, uint16_t addr, uint8_t miscdata,
|
||||
uint8_t endpoint, uint8_t *buffer, uint16_t length);
|
||||
|
||||
//dictionary call without printing output
|
||||
int dictionary_call( USBtransfer *transfer, uint8_t dictionary, uint8_t opcode, uint16_t addr, uint8_t miscdata, uint8_t endpoint, uint8_t *buffer, uint16_t length);
|
||||
|
||||
int dictionary_call_print_option( int print_debug, USBtransfer *transfer, uint8_t dictionary, uint8_t opcode, uint16_t addr, uint8_t miscdata, uint8_t endpoint, uint8_t *buffer, uint16_t length);
|
||||
int dictionary_call_print_option( int print_debug, USBtransfer *transfer, uint8_t dictionary, uint8_t opcode, uint16_t addr, uint8_t miscdata,
|
||||
uint8_t endpoint, uint8_t *buffer, uint16_t length);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -21,18 +21,38 @@
|
|||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
check(argc > 1, "USAGE: inlretro <action o/f>");
|
||||
|
||||
//lower case flags suggested for average user
|
||||
int e_flag = 0; //FORCE ERASE
|
||||
int f_flag = 0; //FORCE ALL CHECKS PASSING
|
||||
int h_flag = 0; //HELP MESSAGE
|
||||
int i_flag = 0; //input file is interlaced
|
||||
int n_flag = 0; //LED OFF
|
||||
int o_flag = 0; //LED ON
|
||||
int f_flag = 0; //LED OFF
|
||||
int e_flag = 0; //ERASE
|
||||
int m_flag = 0; //MIRROR
|
||||
int t_flag = 0; //TEST
|
||||
char *w_value = NULL; //WRITE FILE
|
||||
char *d_value = NULL; //DUMP FILE
|
||||
char *s_value = NULL; //SAVE FILE
|
||||
char *i_value = NULL; //iNES MAPPER
|
||||
char *b_value = NULL; //BOARD
|
||||
int t_flag = 0; //test all SRAMs found
|
||||
int x_flag = 0; //disable all auto detecting
|
||||
int y_flag = 0; //diable all auto doubling
|
||||
|
||||
char *b_value = NULL; //SUBMAPPER #
|
||||
char *c_value = NULL; //CONSOLE NAME
|
||||
char *d_value = NULL; //DUMP TO FILE
|
||||
char *m_value = NULL; //MAPPER #
|
||||
char *p_value = NULL; //PROGRAM FILE
|
||||
char *s_value = NULL; //SCRIPT FILE
|
||||
char *v_value = NULL; //MAPPER VARIANT
|
||||
|
||||
|
||||
//upper case flags suggested for ADVANCED users
|
||||
int T_flag = 0; //TEST
|
||||
|
||||
char *C_value = NULL; //program chr file
|
||||
char *L_value = NULL; //LIBUSB debugging value
|
||||
char *K_value = NULL; //connect to kazzo firmware version #
|
||||
char *O_value = NULL; //start programming at offset base value
|
||||
char *P_value = NULL; //program prg file
|
||||
char *S_value = NULL; //program SNES binary file
|
||||
char *W_value = NULL; //program WRAM/SRAM file
|
||||
|
||||
|
||||
int index = 0;
|
||||
int rv = 0;
|
||||
|
|
@ -41,53 +61,88 @@ int main(int argc, char *argv[])
|
|||
//getopt returns args till done then returns -1
|
||||
//string of possible args : denotes 1 required additional arg
|
||||
//:: denotes optional additional arg follows
|
||||
while( (rv = getopt( argc, argv, "ofemtw:d:s:i:b:")) != -1) {
|
||||
while( (rv = getopt( argc, argv, "onefhitxyTb:c:d:m:p:s:v:C:L:K:O:P:S:W:")) != -1) {
|
||||
|
||||
switch(rv) {
|
||||
case 'o': o_flag = 1; break;
|
||||
case 'f': f_flag = 1; break;
|
||||
case 'n': n_flag = 1; break;
|
||||
case 'e': e_flag = 1; break;
|
||||
case 'm': m_flag = 1; break;
|
||||
case 'f': f_flag = 1; break;
|
||||
case 'h': h_flag = 1; break;
|
||||
case 'i': i_flag = 1; break;
|
||||
case 't': t_flag = 1; break;
|
||||
case 'w': w_value = optarg; break;
|
||||
case 'd': d_value = optarg; break;
|
||||
case 's': s_value = optarg; break;
|
||||
case 'i': i_value = optarg; break;
|
||||
case 'x': x_flag = 1; break;
|
||||
case 'y': y_flag = 1; break;
|
||||
case 'T': T_flag = 1; break;
|
||||
|
||||
case 'b': b_value = optarg; break;
|
||||
case 'c': c_value = optarg; break;
|
||||
case 'd': d_value = optarg; break;
|
||||
case 'm': m_value = optarg; break;
|
||||
case 'p': p_value = optarg; break;
|
||||
case 's': s_value = optarg; break;
|
||||
case 'v': v_value = optarg; break;
|
||||
case 'C': C_value = optarg; break;
|
||||
case 'L': L_value = optarg; break;
|
||||
case 'K': K_value = optarg; break;
|
||||
case 'O': O_value = optarg; break;
|
||||
case 'P': P_value = optarg; break;
|
||||
case 'S': S_value = optarg; break;
|
||||
case 'W': W_value = optarg; break;
|
||||
|
||||
case '?':
|
||||
if ( optopt == 'w' ) {
|
||||
log_err("Option -%c requires an argument.", optopt);
|
||||
} else if ( optopt == 'd' ) {
|
||||
log_err("Option -%c requires an argument.", optopt);
|
||||
} else if ( optopt == 's' ) {
|
||||
log_err("Option -%c requires an argument.", optopt);
|
||||
} else if ( optopt == 'i' ) {
|
||||
log_err("Option -%c requires an argument.", optopt);
|
||||
} else if ( optopt == 'b' ) {
|
||||
if(( optopt == 'b' )
|
||||
|| ( optopt == 'c' )
|
||||
|| ( optopt == 'd' )
|
||||
|| ( optopt == 'm' )
|
||||
|| ( optopt == 'p' )
|
||||
|| ( optopt == 's' )
|
||||
|| ( optopt == 'v' )
|
||||
|| ( optopt == 'C' )
|
||||
|| ( optopt == 'L' )
|
||||
|| ( optopt == 'K' )
|
||||
|| ( optopt == 'O' )
|
||||
|| ( optopt == 'P' )
|
||||
|| ( optopt == 'S' )
|
||||
|| ( optopt == 'W' )){
|
||||
log_err("Option -%c requires an argument.", optopt);
|
||||
goto error;
|
||||
|
||||
} else if ( isprint(optopt)) {
|
||||
log_err("Unknown option -%c .", optopt);
|
||||
goto error;
|
||||
} else {
|
||||
log_err("Unknown option character '\\x%x'", optopt);
|
||||
goto error;
|
||||
}
|
||||
log_err("Improper arguements passed");
|
||||
goto error;
|
||||
break;
|
||||
default:
|
||||
sentinel("getopt failed to catch all arg cases");
|
||||
}
|
||||
|
||||
}
|
||||
debug("flags= o:%d f:%d e:%d m:%d t:%d", o_flag, f_flag, e_flag, m_flag, t_flag);
|
||||
debug("args= w:%s d:%s s:%s i:%s b:%s", w_value, d_value, s_value, i_value, b_value);
|
||||
|
||||
debug("flags= o:%d n:%d e:%d f:%d h:%d i:%d t:%d x:%d y:%d T:%d",
|
||||
o_flag, n_flag, e_flag, f_flag, h_flag, i_flag, t_flag, x_flag, y_flag, T_flag );
|
||||
debug("args= b:%s c:%s d:%s m:%s p:%s", b_value, c_value, d_value, m_value, p_value);
|
||||
debug("args= s:%s v:%s C:%s L:%s K:%s", s_value, v_value, C_value, L_value, K_value);
|
||||
debug("args= O:%s P:%s S:%s W:%s", O_value, P_value, S_value, W_value);
|
||||
|
||||
for( index = optind; index < argc; index++) {
|
||||
log_err("Non-option arguement: %s \n", argv[index]);
|
||||
}
|
||||
|
||||
//TODO display better help message
|
||||
if (h_flag) {
|
||||
printf("you've asked for help but the help message still needs created...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//context set to NULL since only acting as single user of libusb
|
||||
libusb_context *context = NULL;
|
||||
|
||||
|
||||
//create USBtransfer struct to hold all transfer info
|
||||
USBtransfer *transfer = malloc( sizeof(USBtransfer));
|
||||
check_mem(transfer);
|
||||
|
|
@ -96,21 +151,54 @@ int main(int argc, char *argv[])
|
|||
//libusb_device_handle *rprog_handle = NULL;
|
||||
transfer->handle = NULL;
|
||||
|
||||
|
||||
//open INL retro prog with firmware version 2.0 or greater
|
||||
transfer->handle = open_usb_device( context );
|
||||
//command line arg L_value to set different LIBUSB debugging options
|
||||
//any value > 0 also prints debug statements in open_usb_device function
|
||||
int libusb_log = LIBUSB_LOG_LEVEL_NONE; // 0: default no msgs ever printed
|
||||
if (L_value != NULL) {
|
||||
check( isdigit(L_value[0]), "Invalid LIBUSB_LOG_LEVEL: %s, only single digit allowed", L_value);
|
||||
check( strlen(L_value) == 1, "Invalid LIBUSB_LOG_LEVEL: %s, only single digit allowed", L_value);
|
||||
libusb_log = atoi(L_value);
|
||||
check( ((libusb_log >= LIBUSB_LOG_LEVEL_NONE) && (libusb_log <=LIBUSB_LOG_LEVEL_DEBUG)),
|
||||
"Invalid LIBUSB_LOG_LEVEL: %d, must be from 0 to 4", libusb_log );
|
||||
printf("setting LIBUSB_LOG_LEVEL to: %d\n", libusb_log);
|
||||
if (libusb_log == 0) { printf("\tNONE: default no messages ever printed by library\n"); }
|
||||
if (libusb_log == 1) { printf("\tERROR: error messages are printed to stderr\n"); }
|
||||
if (libusb_log == 2) { printf("\tWARNING: warning and error messages are printed to stderr\n"); }
|
||||
if (libusb_log == 3) { printf("\tINFO: informational, warning, & error messages are printed to stdout\n"); }
|
||||
if (libusb_log == 4) { printf("\tDEBUG: debug, info, warning, & error messages are printed to stdout\n"); }
|
||||
}
|
||||
if (K_value != NULL) {
|
||||
//TODO take K_value option to connect to different version kazzo
|
||||
}
|
||||
transfer->handle = open_usb_device( context, libusb_log );
|
||||
check( transfer->handle != NULL, "Unable to open INL retro-prog usb device handle.");
|
||||
|
||||
//report successful connection to INL retro-prog
|
||||
printf("Successfully found and connected to INL retro-prog with firmware version 2.0\n");
|
||||
|
||||
//create board object/struct
|
||||
|
||||
//attempt to detect board inserted in device
|
||||
// -x flag turns off all autodection
|
||||
if (!x_flag) {
|
||||
printf("attempting to detect cartridge...\n");
|
||||
} else {
|
||||
printf("auto-detection turned off\n");
|
||||
}
|
||||
|
||||
if (e_flag) erase_nes( transfer );
|
||||
if (T_flag) test_function( transfer );
|
||||
|
||||
|
||||
//handle simple LED ON/OFF within main for now
|
||||
//TODO cut this newbie code out of here
|
||||
int xfr_cnt = 0;
|
||||
uint8_t rbuf[8];
|
||||
|
||||
int i;
|
||||
|
||||
if (e_flag) erase_nes( transfer );
|
||||
if (t_flag) test_function( transfer );
|
||||
|
||||
//handle simple LED ON/OFF within main for now
|
||||
if (o_flag | f_flag) {
|
||||
if (o_flag | n_flag) {
|
||||
printf("before return buffer: ");
|
||||
for (i = 0; i < 8; i++) {
|
||||
rbuf[i] = 7;
|
||||
|
|
@ -120,7 +208,7 @@ int main(int argc, char *argv[])
|
|||
transfer->endpoint = USB_IN;
|
||||
transfer->request = PINPORT;
|
||||
if (o_flag) transfer->wValueLSB = LED_ON;
|
||||
if (f_flag) transfer->wValueLSB = LED_OFF;
|
||||
if (n_flag) transfer->wValueLSB = LED_OFF;
|
||||
transfer->data = rbuf;
|
||||
transfer->wLength = 1;
|
||||
|
||||
|
|
@ -137,24 +225,6 @@ int main(int argc, char *argv[])
|
|||
|
||||
|
||||
|
||||
//if (o_flag) { //ON send REQ_LED_ON
|
||||
// xfr_cnt = usb_transfer( transfer.handle,
|
||||
// REQ_LED_ON,
|
||||
// (unsigned char *)buffer254, sizeof(buffer254) );
|
||||
// printf("total bytes xfrd: %d \n", xfr_cnt);
|
||||
//}
|
||||
//if (f_flag) { //OFF send REQ_LED_OFF
|
||||
// xfr_cnt = usb_write_to_device( transfer.handle,
|
||||
// REQ_LED_OFF, (unsigned char *)buffer254, sizeof(buffer254) );
|
||||
// printf("total bytes xfrd: %d \n", xfr_cnt);
|
||||
//}
|
||||
|
||||
//if (w_value) { //OFF send REQ_LED_OFF
|
||||
// check( write_file( transfer.handle, w_value, i_value, b_value) == SUCCESS,
|
||||
// "Failed to write file: %s", w_value);
|
||||
//}
|
||||
|
||||
|
||||
close_usb( context, transfer->handle);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
//LIBUSB_ENDPOINT_IN In: device-to-host.
|
||||
//LIBUSB_ENDPOINT_OUT Out: host-to-device.
|
||||
|
||||
libusb_device_handle * open_usb_device( libusb_context *context )
|
||||
libusb_device_handle * open_usb_device( libusb_context *context, int log_level )
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
|
|
@ -28,23 +28,16 @@ libusb_device_handle * open_usb_device( libusb_context *context )
|
|||
//libusb_context *context = NULL;
|
||||
//passed in from main
|
||||
|
||||
debug("Initalizing libusb");
|
||||
if (log_level>0) printf("Initalizing libusb\n");
|
||||
//initialize libusb must be called prior to any other libusb function
|
||||
//returns 0 on success LIBUSB_ERROR code on failure
|
||||
//int libusb_init ( libusb_context ** context)
|
||||
int usb_init = libusb_init(&context);
|
||||
debug("Initalized libusb");
|
||||
check( usb_init == LIBUSB_SUCCESS, "Failed to initialize libusb: %s", libusb_strerror(usb_init));
|
||||
if (log_level>0) printf("Successfully initalized libusb\n");
|
||||
|
||||
//void libusb_set_debug ( libusb_context * ctx, int level )
|
||||
libusb_set_debug(context, LIBUSB_LOG_LEVEL_ERROR);
|
||||
//LIBUSB_LOG_LEVEL_NONE (0) : no messages ever printed by the library (default)
|
||||
//LIBUSB_LOG_LEVEL_ERROR (1) : error messages are printed to stderr
|
||||
//LIBUSB_LOG_LEVEL_WARNING (2) : warning and error messages are printed to stderr
|
||||
//LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to stdout,
|
||||
// warning and error messages are printed to stderr
|
||||
//LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are printed to stdout,
|
||||
// warnings and errors to stderr
|
||||
libusb_set_debug(context, log_level);
|
||||
|
||||
//discover all usb devices
|
||||
libusb_device **device_list = NULL;
|
||||
|
|
@ -52,10 +45,10 @@ libusb_device_handle * open_usb_device( libusb_context *context )
|
|||
// Returns a list of USB devices currently attached to the system.
|
||||
// return value is number of devices plus one as list is null terminated, or LIBUSB_ERROR if negative.
|
||||
// Must free device list after done with it
|
||||
debug("getting device list");
|
||||
if (log_level>0) printf("Getting USB device list\n");
|
||||
ssize_t dev_count = libusb_get_device_list( context, &device_list);
|
||||
debug("got device list");
|
||||
check( dev_count >= 0, "libusb unable to find any devices: %s", libusb_strerror(dev_count));
|
||||
if (log_level>0) printf("Successfully retrieved USB device list\n");
|
||||
|
||||
ssize_t i = 0;
|
||||
|
||||
|
|
@ -77,34 +70,35 @@ libusb_device_handle * open_usb_device( libusb_context *context )
|
|||
const char *rprog_prod = "INL Retro-Prog";
|
||||
uint16_t min_fw_ver = 0x200;
|
||||
|
||||
debug("searching %d total devices", dev_count-1);
|
||||
if (log_level>0) printf("Searching %d total devices\n", dev_count-1);
|
||||
for( i=0; i<dev_count; i++) {
|
||||
device = device_list[i];
|
||||
debug("getting dev desc %d", i);
|
||||
if (log_level>0) printf("getting dev desc #%d ", i);
|
||||
rv = libusb_get_device_descriptor( device, &desc);
|
||||
check( rv == LIBUSB_SUCCESS, "Unable to get device #%d descriptor: %s", i, libusb_strerror(rv));
|
||||
|
||||
debug("checking %x vendor", desc.idVendor);
|
||||
debug("checking %x product", desc.idProduct);
|
||||
if (log_level>0) printf("checking %x vendor ", desc.idVendor);
|
||||
if (log_level>0) printf("checking %x product\n", desc.idProduct);
|
||||
if ((desc.idVendor == 0x16C0) && (desc.idProduct == 0x05DC)) {
|
||||
//Found a V-USB device with default VID/PID now see if it's actually a kazzo
|
||||
debug("found vend %x prod %x\n", desc.idVendor, desc.idProduct);
|
||||
debug("manf: %d prod: %d\n", desc.iManufacturer, desc.iProduct);
|
||||
if (log_level>0) printf("found vend ID:%x prod ID:%x ", desc.idVendor, desc.idProduct);
|
||||
if (log_level>0) printf("manf: %d prod: %d\n", desc.iManufacturer, desc.iProduct);
|
||||
|
||||
//opening device allows performing I/O via USB with device
|
||||
rv = libusb_open( device, &handle );
|
||||
check( rv == LIBUSB_SUCCESS, "Unable to open USB device: %s", libusb_strerror(rv));
|
||||
if (log_level>0) printf("device opened successfully\n");
|
||||
|
||||
if (desc.iManufacturer) {
|
||||
if ( libusb_get_string_descriptor_ascii( handle,
|
||||
desc.iManufacturer, (unsigned char *)manf, sizeof(manf) ) > LIBUSB_SUCCESS) {
|
||||
debug("manf_ascii: %s\n",manf);
|
||||
if (log_level>0) printf("manf_ascii: %s\n",manf);
|
||||
}
|
||||
}
|
||||
if (desc.iProduct) {
|
||||
if ( libusb_get_string_descriptor_ascii( handle,
|
||||
desc.iProduct, (unsigned char *)prod, sizeof(prod) ) > LIBUSB_SUCCESS) {
|
||||
debug("prod_ascii: %s\n",prod);
|
||||
if (log_level>0) printf("prod_ascii: %s\n",prod);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -116,11 +110,10 @@ libusb_device_handle * open_usb_device( libusb_context *context )
|
|||
}
|
||||
|
||||
if ( strcmp( manf, inl_manf) == 0) {
|
||||
debug("INL manufactured device found.");
|
||||
if (log_level>0) printf("INL manufactured device found\n");
|
||||
if ( strcmp( prod, rprog_prod) == 0) {
|
||||
debug("INL Retro-Prog found.");
|
||||
debug("bcd Device fw version: %x required: %x",
|
||||
desc.bcdDevice, min_fw_ver);
|
||||
if (log_level>0) printf("INL Retro-Prog found\n");
|
||||
if (log_level>0) printf("bcd Device fw version: %x required: %x\n", desc.bcdDevice, min_fw_ver);
|
||||
if (desc.bcdDevice < min_fw_ver) {
|
||||
//close device since can't use it
|
||||
log_warn("INL Retro-Prog found, but firmware is too old, see Readme for instructions to update firmware.");
|
||||
|
|
@ -134,15 +127,18 @@ libusb_device_handle * open_usb_device( libusb_context *context )
|
|||
//Getting here means the device was opened because it matched V-USB
|
||||
//VID/PID, but it wasn't a compatible device.
|
||||
//Can't use this device, so close it
|
||||
if (log_level>0) printf("VID/PID matched, but manf/prod didn't match, closing device\n");
|
||||
libusb_close(handle);
|
||||
handle = NULL; //Don't want to try and reclose
|
||||
}
|
||||
}
|
||||
//looped through all devices retroprog will be assigned if it was found.
|
||||
check( retroprog != NULL, "Could not find INL retro-prog USB device");
|
||||
if (log_level>0) printf("INL retro-prog USB device successfully found\n");
|
||||
|
||||
//free device list now that INL retro-prog was found and opened
|
||||
//void libusb_free_device_list ( libusb_device ** list, int unref_devices )
|
||||
if (log_level>0) printf("Freeing USB device list\n");
|
||||
libusb_free_device_list( device_list, 1); //don't completely understand the unref_devices = 1...
|
||||
device_list = NULL; //denote that device list is free if end up in error
|
||||
//Guess this is what you're supposed to do..
|
||||
|
|
@ -166,6 +162,7 @@ libusb_device_handle * open_usb_device( libusb_context *context )
|
|||
libusb_free_device_list( device_list, 1);
|
||||
}
|
||||
|
||||
if (log_level>0) printf("Returning device handle to main\n");
|
||||
return handle;
|
||||
|
||||
error:
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ typedef struct USBtransfer {
|
|||
unsigned char *data;
|
||||
} USBtransfer;
|
||||
|
||||
libusb_device_handle * open_usb_device( libusb_context *context );
|
||||
libusb_device_handle * open_usb_device( libusb_context *context, int log_level );
|
||||
|
||||
void close_usb(libusb_context *context, libusb_device_handle *handle);
|
||||
|
||||
|
|
|
|||
|
|
@ -387,6 +387,11 @@
|
|||
// 1% greater bus util compared to 254byte xfr
|
||||
// 2.2% speedup compared to 256 in 254
|
||||
|
||||
// USB 1.1 Low speed 1.5Mbps
|
||||
// maximum theoretical bus utiliation with transfers styles above
|
||||
// 1.5Mbps * 33% utilization = 495Kbps = 61.8KBps
|
||||
// Will never get to this maximum, as this assumes that bus is in use 100% of the time with no
|
||||
// delays waiting for responses etc. But gives sense of scale for what's possible
|
||||
|
||||
// Probably decent overall speedup by eliminating multiple status packets. Not sure how many
|
||||
// NAK's the old firmware was sending while the device programmed the entire 256byte buffer.
|
||||
|
|
@ -399,7 +404,7 @@
|
|||
// start programming mid usb transfer once it's full. Want to make effor to hide flash programming
|
||||
// wait time behind usb transfer time.
|
||||
|
||||
// some speed testing:
|
||||
// some speed testing with 16bit return length variable:
|
||||
// 128Byte OUT (write) transfers with long transfers DISABLED: 20.04sec/512KByte = 25.55KBps
|
||||
// 128Byte OUT (write) transfers with long transfers ENABLED: 20.7 sec/512KByte = 24.7 KBps
|
||||
// 256Byte OUT (write) transfers with long transfers ENABLED: 18.56sec/512KByte = 27.6 KBps
|
||||
|
|
@ -407,11 +412,24 @@
|
|||
// 128Byte IN (read) with long xfr DISABLED, w/o usbFuncRd: 30.5 sec/512KByte = 16.8 KBps
|
||||
// 128Byte IN (read) with long xfr DISABLED, w/usbFuncRd: 34.9 sec/512KByte = 14.7 KBps
|
||||
// 1033*254Byte IN (read) long xfr DISABLED, w/o usbFuncRd: 28.35sec/512KByte = 18.1 KBps
|
||||
//
|
||||
//
|
||||
// after concluding that would not be using long transfers, the return length variable
|
||||
// was reduced to 8bits (single byte unsigned int) and slight improvement was found:
|
||||
// 254Byte OUT (write) transfers with long transfers DISABLED: 17.5 sec/512KByte = 29.2 KBps (assuming 2 bytes stuffed in setup packet)
|
||||
//
|
||||
// adding a few checks to usbFunctionWrite to ensure buffer is proper status and not won't be overflowed
|
||||
// presented small reduction in speed:
|
||||
// 254Byte OUT (write) transfers with long transfers DISABLED: 18.1 sec/512KByte = 28.4 KBps (assuming 2 bytes stuffed in setup packet)
|
||||
//
|
||||
// These tests did nothing with payload once it arrived, so these are practical maximums of V-usb.
|
||||
// Conclusion:
|
||||
// -enabling long transfers slows writes (and probably reads)
|
||||
// -reads are much slower than writes.
|
||||
// found a vusb forum thread quoting 22KBps reads at transfer size of 200bytes
|
||||
// he was using atmega16 with 12Mhz clock, so doesn't look like we can
|
||||
// replicate this even with our 'better' conditions. But our
|
||||
// writes are exceeding his 24KBps transfer speeds so we'll take it..
|
||||
// https://forums.obdev.at/viewtopic.php?t=3059
|
||||
// -enabling usbFunctionRead is slower compared to using usbFunctionSetup alone.
|
||||
// -using 254B xfrs with 2 bytes stuffed in setup packet gives decent boost for writes.
|
||||
// this is primarily due to speed up of not having long transfers enabled.
|
||||
|
|
@ -422,6 +440,34 @@
|
|||
// separate buffer and sent separately once full.
|
||||
// Only other way without complicating dump algo would be to implement usbFuncRd
|
||||
// but that would slow things down and negate the speed boost..
|
||||
//
|
||||
// Speed testing with old firmware and app:
|
||||
// fairly certain these were long transfers of 256 bytes each
|
||||
// 512KB write 30.2sec = 16.7KBps
|
||||
// 512KB read 34.2sec = 15.0KBps
|
||||
//
|
||||
// Haven't tested for comparison's sake, but original anago/unagi firmware/app was even slower I believe
|
||||
// Found quote of Memblers finding ~19sec for 128KB PRG-ROM = 6.7KBps for reads...
|
||||
// So shouldn't be hard to beat those speeds
|
||||
//
|
||||
// Checking SST 39SF040 datasheet, the byte program time is max 20usec * 256B page = 5.12usec per page
|
||||
// We have some additional CPU execution time overhead above that 5.12usec per page
|
||||
// but that shouldn't be significant in comparison, still lots of margin to meet 50usec usbPoll requirement
|
||||
// if slow down is noticed during flashing/dumping may be helpful to call usbPoll mid page so
|
||||
// the next data packet doesn't have to wait for the last page to complete before it can be accepted/sent
|
||||
// to/from the driver.
|
||||
//
|
||||
// Sector erases are maximum of 25usec however which should probably be avoided or used with caution
|
||||
// between usbPoll. However exiting back to main and continuing to poll USB and erasure should be fine
|
||||
// as erasing doesn't have to be monitored.
|
||||
//
|
||||
// Chip erasure is max of 100usec which will most certainly violate 50usec usbPoll req't so make sure
|
||||
// we don't sit and spin waiting for chip to erase without calling usbPoll...
|
||||
//
|
||||
// SNES 4-8MB chip erasure is on the order of 30sec so certainly need to be considerate of flash timing
|
||||
// depending on the chip in use. Avoiding SNES chip erasure when possible presents large chance for
|
||||
// speedup!
|
||||
//
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue