diff --git a/config.c b/config.c index 8010d55..0f3b8b4 100644 --- a/config.c +++ b/config.c @@ -10,10 +10,15 @@ struct eeprom_data_struct g_eeprom_data; * values. */ void eeprom_app_write_defaults(void) { + int i; const char default_serial[SERIAL_NUM_LEN] = { '0','0','0','0','0','1' }; memcpy(g_eeprom_data.cfg.serial, default_serial, SERIAL_NUM_LEN); g_eeprom_data.cfg.mode = CFG_MODE_STANDARD; + + for (i=0; i 1 + case CFG_PARAM_POLL_INTERVAL1: + *value = g_eeprom_data.cfg.poll_interval[1]; + return 1; +#endif +#if NUM_CHANNELS > 2 + case CFG_PARAM_POLL_INTERVAL2: + *value = g_eeprom_data.cfg.poll_interval[2]; + return 1; +#endif +#if NUM_CHANNELS > 3 + case CFG_PARAM_POLL_INTERVAL3: + *value = g_eeprom_data.cfg.poll_interval[3]; + return 1; +#endif } return 0; @@ -50,6 +73,24 @@ unsigned char config_setParam(unsigned char param, const unsigned char *value) case CFG_PARAM_SERIAL: config_set_serial((char*)value); return 1; + case CFG_PARAM_POLL_INTERVAL0: + g_eeprom_data.cfg.poll_interval[0] = value[0]; + return 1; +#if NUM_CHANNELS > 1 + case CFG_PARAM_POLL_INTERVAL1: + g_eeprom_data.cfg.poll_interval[1] = value[0]; + return 1; +#endif +#if NUM_CHANNELS > 2 + case CFG_PARAM_POLL_INTERVAL2: + g_eeprom_data.cfg.poll_interval[2] = value[0]; + return 1; +#endif +#if NUM_CHANNELS > 3 + case CFG_PARAM_POLL_INTERVAL3: + g_eeprom_data.cfg.poll_interval[3] = value[0]; + return 1; +#endif } return 0; diff --git a/config.h b/config.h index 8ac7efa..03ede3d 100644 --- a/config.h +++ b/config.h @@ -1,10 +1,12 @@ #ifndef _config_h__ #define _config_h__ +#define NUM_CHANNELS 4 #define SERIAL_NUM_LEN 6 struct eeprom_cfg { uint8_t serial[SERIAL_NUM_LEN]; uint8_t mode; + uint8_t poll_interval[NUM_CHANNELS]; }; void eeprom_app_write_defaults(void); diff --git a/hiddata.c b/hiddata.c index 891c872..d115dc5 100644 --- a/hiddata.c +++ b/hiddata.c @@ -38,9 +38,8 @@ uint16_t hiddata_get_report(struct usb_request *rq, const uint8_t **dat) /*** Get/Set report called from interrupt context! */ uint8_t hiddata_set_report(const struct usb_request *rq, const uint8_t *dat, uint16_t len) { - int i; - #ifdef DEBUG + int i; printf("Set data %d\n", len); for (i=0; i +#include "gcn64lib.h" +#include "../requests.h" + +int gcn64lib_getConfig(gcn64_hdl_t hdl, unsigned char param, unsigned char *rx, unsigned char rx_max) +{ + unsigned char cmd[2]; + int n; + + cmd[0] = RQ_GCN64_GET_CONFIG_PARAM; + cmd[1] = param; + + n = gcn64_exchange(hdl, cmd, 2, rx, rx_max); + if (n<2) + return n; + + n -= 2; + + // Drop the leading CMD and PARAM + if (n) { + memmove(rx, rx+2, n); + } + + return n; +} +int gcn64lib_setConfig(gcn64_hdl_t hdl, unsigned char param, unsigned char *data, unsigned char len) +{ + unsigned char cmd[2 + len]; + int n; + + cmd[0] = RQ_GCN64_SET_CONFIG_PARAM; + cmd[1] = param; + memcpy(cmd + 2, data, len); + + n = gcn64_exchange(hdl, cmd, 2 + len, cmd, sizeof(cmd)); + if (n<0) + return n; + + return 0; +} + +int gcn64lib_suspendPolling(gcn64_hdl_t hdl, unsigned char suspend) +{ + unsigned char cmd[2]; + int n; + + cmd[0] = RQ_GCN64_SUSPEND_POLLING; + cmd[1] = suspend; + + n = gcn64_exchange(hdl, cmd, 2, cmd, sizeof(cmd)); + if (n<0) + return n; + + return 0; +} + +int gcn64lib_rawSiCommand(gcn64_hdl_t hdl, unsigned char channel, unsigned char *tx, unsigned char tx_len, unsigned char *rx, unsigned char max_rx) +{ + unsigned char cmd[3 + tx_len]; + int cmdlen, rx_len, n; + + cmd[0] = RQ_GCN64_RAW_SI_COMMAND; + cmd[1] = channel; + cmd[2] = tx_len; + memcpy(cmd+3, tx, tx_len); + cmdlen = 3 + tx_len; + + n = gcn64_exchange(hdl, cmd, cmdlen, rx, max_rx); + if (n<0) + return n; + + rx_len = rx[2]; + + memmove(rx, rx + 3, rx_len); + + return rx_len; +} diff --git a/tool/gcn64lib.h b/tool/gcn64lib.h new file mode 100644 index 0000000..54d89a8 --- /dev/null +++ b/tool/gcn64lib.h @@ -0,0 +1,11 @@ +#ifndef _gcn64_lib_h__ +#define _gcn64_lib_h__ + +#include "gcn64.h" + +int gcn64lib_suspendPolling(gcn64_hdl_t hdl, unsigned char suspend); +int gcn64lib_setConfig(gcn64_hdl_t hdl, unsigned char param, unsigned char *data, unsigned char len); +int gcn64lib_getConfig(gcn64_hdl_t hdl, unsigned char param, unsigned char *rx, unsigned char rx_max); +int gcn64lib_rawSiCommand(gcn64_hdl_t hdl, unsigned char channel, unsigned char *tx, unsigned char tx_len, unsigned char *rx, unsigned char max_rx); + +#endif // _gcn64_lib_h__ diff --git a/tool/gcn64utils.h b/tool/gcn64utils.h new file mode 100644 index 0000000..ab714fb --- /dev/null +++ b/tool/gcn64utils.h @@ -0,0 +1,5 @@ +#ifndef _gcn64_utils_h__ +#define _gcn64_utils_h__ + +#endif // _gcn64_utils_h__ + diff --git a/tool/main.c b/tool/main.c index ae9cb8a..5475b9b 100644 --- a/tool/main.c +++ b/tool/main.c @@ -26,6 +26,7 @@ #include "version.h" #include "gcn64.h" +#include "gcn64lib.h" #include "mempak.h" #include "../requests.h" #include "../gcn64_protocol.h" @@ -36,19 +37,22 @@ static void printUsage(void) printf("Control tool for WUSBmote adapter. Version %s\n", VERSION_STR); printf("\n"); printf("Options:\n"); - printf(" -h, --help Print help\n"); - printf(" -l, --list List devices\n"); - printf(" -s serial Operate on specified device (required unless -f is specified)\n"); - printf(" -f, --force If no serial is specified, use first device detected.\n"); - printf(" -o, --outfile Output file for read operations (eg: --n64-mempak-dump)\n"); + printf(" -h, --help Print help\n"); + printf(" -l, --list List devices\n"); + printf(" -s serial Operate on specified device (required unless -f is specified)\n"); + printf(" -f, --force If no serial is specified, use first device detected.\n"); + printf(" -o, --outfile file Output file for read operations (eg: --n64-mempak-dump)\n"); printf("\n"); printf("Configuration commands:\n"); printf(" --set_serial serial Assign a new device serial number\n"); printf(" --get_serial Read serial from eeprom\n"); + printf(" --set_poll_rate ms Set time between controller polls in milliseconds\n"); + printf(" --get_poll_rate Read configured poll rate\n"); printf("\n"); printf("Advanced commands:\n"); printf(" --bootloader Re-enumerate in bootloader mode\n"); - printf(" --suspend_polling Stop polling controller\n"); + printf(" --suspend_polling Stop polling the controller\n"); + printf(" --resume_polling Re-start polling the controller\n"); printf("\n"); printf("Raw controller commands:\n"); printf(" --n64_getstatus Read N64 controller status now\n"); @@ -58,6 +62,17 @@ static void printUsage(void) printf(" --n64_mempak_dump Dump N64 mempak contents (Use with --outfile to write to file)\n"); } +static void printHexBuf(unsigned char *buf, int n) +{ + int i; + + for (i=0; i= 0) { + printf("N64 Get status[%d]: ", n); + printHexBuf(cmd, n); + } break; case OPT_GC_GETSTATUS_RUMBLE: - cmd[0] = RQ_GCN64_RAW_SI_COMMAND; - cmd[1] = 0x03; // Length of SI command - cmd[2] = GC_GETSTATUS1; - cmd[3] = GC_GETSTATUS2; - cmd[4] = GC_GETSTATUS3(0); - cmdlen = 5; + case OPT_GC_GETSTATUS: + cmd[0] = GC_GETSTATUS1; + cmd[1] = GC_GETSTATUS2; + cmd[2] = GC_GETSTATUS3(opt == OPT_GC_GETSTATUS_RUMBLE); + n = gcn64lib_rawSiCommand(hdl, 0, cmd, 3, cmd, sizeof(cmd)); + if (n >= 0) { + printf("GC Get status[%d]: ", n); + printHexBuf(cmd, n); + } break; case OPT_N64_GETCAPS: - cmd[0] = RQ_GCN64_RAW_SI_COMMAND; - cmd[1] = 0x01; // Length of SI command - cmd[2] = N64_GET_CAPABILITIES; // N64 GET status - cmdlen = 3; + cmd[0] = N64_GET_CAPABILITIES; + n = gcn64lib_rawSiCommand(hdl, 0, cmd, 1, cmd, sizeof(cmd)); + if (n >= 0) { + printf("N64 Get caps[%d]: ", n); + printHexBuf(cmd, n); + } break; case OPT_N64_MEMPAK_DUMP: @@ -282,7 +318,7 @@ int main(int argc, char **argv) break; } - if (cmd[0]) { + if (do_exchange) { int i; n = gcn64_exchange(hdl, cmd, cmdlen, cmd, sizeof(cmd)); if (n<0) diff --git a/tool/mempak.c b/tool/mempak.c index 66d087f..554bb76 100644 --- a/tool/mempak.c +++ b/tool/mempak.c @@ -3,6 +3,7 @@ #include #include #include "gcn64.h" +#include "gcn64lib.h" #include "mempak.h" #include "../gcn64_protocol.h" #include "../requests.h" @@ -122,30 +123,42 @@ int mempak_writeBlock(gcn64_hdl_t hdl, unsigned short addr, unsigned char data[3 int mempak_readBlock(gcn64_hdl_t hdl, unsigned short addr, unsigned char dst[32]) { unsigned char cmd[64]; - int cmdlen; + //int cmdlen; int n; uint16_t addr_crc; unsigned char crc; addr_crc = __calc_address_crc(addr); + cmd[0] = N64_EXPANSION_READ; + cmd[1] = addr_crc>>8; // Address high byte + cmd[2] = addr_crc&0xff; // Address low byte + +/* cmd[0] = RQ_GCN64_RAW_SI_COMMAND; cmd[1] = 3; cmd[2] = N64_EXPANSION_READ; cmd[3] = addr_crc>>8; // Address high byte cmd[4] = addr_crc&0xff; // Address low byte cmdlen = 5; - +*/ //printf("Addr 0x%04x with crc -> 0x%04x\n", addr, addr_crc); - n = gcn64_exchange(hdl, cmd, cmdlen, cmd, sizeof(cmd)); - if (n != 35) + n = gcn64lib_rawSiCommand(hdl, 0, cmd, 3, cmd, sizeof(cmd)); + if (n != 33) { + printf("Hey! %d\n", n); return -1; + } - memcpy(dst, cmd + 2, 0x20); +// n = gcn64_exchange(hdl, cmd, cmdlen, cmd, sizeof(cmd)); +// if (n != 35) +// return -1; + + //memcpy(dst, cmd + 2, 0x20); + memcpy(dst, cmd, 0x20); crc = __calc_data_crc(dst); - if (crc != cmd[34]) { + if (crc != cmd[32]) { fprintf(stderr, "Bad CRC reading address 0x%04x\n", addr); return -1; } @@ -184,7 +197,7 @@ int mempak_readAll(gcn64_hdl_t hdl, unsigned char dstbuf[0x8000]) return 0; } -void mempak_dump(gcn64_hdl_t hdl) +int mempak_dump(gcn64_hdl_t hdl) { unsigned char cardbuf[0x8000]; int i,j; @@ -193,7 +206,10 @@ void mempak_dump(gcn64_hdl_t hdl) mempak_init(hdl); printf("Reading card...\n"); - mempak_readAll(hdl, cardbuf); + i = mempak_readAll(hdl, cardbuf); + if (i<0) { + return i; + } for (i=0; i