From 80943f7f622460e1dee240eb5943eb2113660f87 Mon Sep 17 00:00:00 2001 From: Paul Molloy Date: Mon, 28 Nov 2016 22:16:35 -0600 Subject: [PATCH] firmware buffer.c reorganization and some intitial testing complete. moved all buffer operations out of usb.c with new bridge function between the two files. Lots of pointing going on and lessons learned.. Thankfully everything seems to be working if you actually call the functions as I designed them.. Gotta love trouble shooting bugs that don't exist.. Helped updating allocate output to get returned as error back to the host. Moved typedef structs to firmware type.h file as seemed to cause compilation issues being contained in the files .h file when other .c files needed those types. Fixed casting warnings with usbMsgPtr ended up looking at usbdrv.c figured out how close I got, just shouldn't have been putting the * in there.. --- firmware/source/buffer.c | 210 ++++++++++++++++++++++++++++-------- firmware/source/buffer.h | 42 ++------ firmware/source/types.h | 39 +++++++ firmware/source/usb.c | 134 +++++++++-------------- firmware/source/usb.h | 11 ++ host/source/dictionary.c | 31 +++++- host/source/erase.c | 55 ++++++++-- shared/shared_dict_buffer.h | 63 ++++++++--- shared/shared_errors.h | 4 + 9 files changed, 399 insertions(+), 190 deletions(-) create mode 100644 firmware/source/types.h diff --git a/firmware/source/buffer.c b/firmware/source/buffer.c index cc1fce4..b4e7da1 100644 --- a/firmware/source/buffer.c +++ b/firmware/source/buffer.c @@ -1,40 +1,105 @@ #include "buffer.h" -//typedef struct buffer{ -// uint8_t *data; //pointer to base buffer's allocated sram -// uint8_t size; //size of buffer in bytes (max 256 bytes) -// uint8_t status; //current status of buffer USB load/unload, flashing, waiting, erase -// uint8_t cur_byte; //byte currently being loaded/unloaded/flashed/read -// uint8_t reload; //add this number to page_num for next loading -// uint8_t buff_num; //address bits between buffer size and page number -// //ie need 2x128 byte buffers making buff_num = A7 -// //ie need 4x64 byte buffers making buff_num = A7:6 -// //ie need 8x32 byte buffers making buff_num = A7:5 -// uint16_t page_num; //address bits beyond buffer's size and buff_num A23-A8 -// //MSB A23-16, LSB A15-8 -// uint8_t mem_type; //SNES ROM, SNES RAM, PRG ROM, PRG RAM, CHR ROM, CHR RAM, CPLD, SPI -// uint8_t part_num; //used to define unlock commands, sector erase, etc -// uint8_t multiple; //number of times to program this page -// uint8_t add_mult; //add this number to page_num for multiple programs -// //CHR shift LSb to A13 (max 2MByte) -// //PRG shift LSb to A14 (max 4MByte) -// //SNES add to MSB of page_num (max 16MByte) -// uint8_t mapper; //mapper number of board -// uint8_t mapvar; //mapper variant -// uint8_t function; //function "pointer" for flash/dump operation control -//}buffer; - -//max raw buffer size is 256 bytes must create multiple raw buffers for more -//or handle 16bit values for page size - +//max raw buffer size is only limited based on buffer struct //raw buffer memory to which smaller buffers will be created from //set pointers and lengths to prevent buffer conflicts -//static uint8_t raw_buffer[NUM_RAW_BANKS * RAW_BANK_SIZE]; //8 banks of 32bytes each 256Bytes total -static uint8_t raw_buffer[256]; //8 banks of 32bytes each 256Bytes total +static uint8_t raw_buffer[NUM_RAW_BANKS * RAW_BANK_SIZE]; //8 banks of 32bytes each 256Bytes total //buffer status stores allocation status of each raw buffer 32Byte bank -//static uint8_t raw_bank_status[NUM_RAW_BANKS]; -static uint8_t raw_bank_status[8]; +static uint8_t raw_bank_status[NUM_RAW_BANKS]; + +//min define of two buffers +static buffer buff0; +static buffer buff1; +#if ( defined(NUM_BUFFERS_4) || (defined(NUM_BUFFERS_8)) ) +static buffer buff2; +static buffer buff3; +#endif +#ifdef NUM_BUFFERS_8 +static buffer buff4; +static buffer buff5; +static buffer buff6; +static buffer buff7; +#endif + + +/* Desc:Bridge between usb.c and buffer.c functions + * usb.c calls this function providing setup packet info + * usb.c also provides pointer to small 'rv' return value buffer of 8bytes + * and pointer to rlen so buffer.c can decide wether to utilize the + * small 8byte generic return buffer or point usbMsgPtr to some larger buffer of sram. + * this function interprets opcode type to call proper opcode switch function + * Pre: opcode must be defined in shared_dict_buffer.h + * Post:function call complete. + * rlen updated to lenght of return data + * rv[0] contains SUCCESS/ERROR code + * rv buffer filled with return data for small data requests + * Rtn: pointer to ram buffer to be returned over USB + */ +uint8_t * buffer_usb_call( setup_packet *spacket, uint8_t *rv, uint16_t *rlen) +{ + buffer *called_buff = &buff0; //used to point to buffer that was called based on opcode + uint8_t *rptr = rv; //used for return pointer set to small rv buffer by default + + switch (spacket->opcode) { + + //opcodes which don't address a specific buffer object + case BUFF_OPCODE_NRV_MIN ... BUFF_OPCODE_NRV_MAX: + rv[RV_ERR_IDX] = buffer_opcode_no_return( spacket->opcode, NULL, + spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); + *rlen = 1; + break; + + case BUFF_OPCODE_RV_MIN ... BUFF_OPCODE_RV_MAX: + rv[RV_ERR_IDX] = buffer_opcode_return( spacket->opcode, NULL, + spacket->operandMSB, spacket->operandLSB, spacket->miscdata, &rv[1] ); + *rlen = 2; + break; + + //opcodes which include designation of which buffer is being called in lower bits + case BUFF_OPCODE_BUFN_MIN ... BUFF_OPCODE_BUFN_MAX: + //mask out last three bits to detect buffer being called based on opcode number + switch ( (spacket->opcode) & 0x07) { + //2 buffers minimum support + case 0: called_buff = &buff0; break; + case 1: called_buff = &buff1; break; +# if ( defined(NUM_BUFFERS_4) || (defined(NUM_BUFFERS_8)) ) + //4-8 buffers + case 2: called_buff = &buff2; break; + case 3: called_buff = &buff3; break; +# endif +# ifdef NUM_BUFFERS_8 + //8 buffers + case 4: called_buff = &buff4; break; + case 5: called_buff = &buff5; break; + case 6: called_buff = &buff6; break; + case 7: called_buff = &buff7; break; +# endif + default: //opcode sent for non-existent buffer + rv[RV_ERR_IDX] = ERR_BUFN_DOES_NOT_EXIST; + } + //now that we have pointer to buffer object call associated function + switch ( spacket->opcode ) { + case BUFF_OPCODE_BUFN_NRV_MIN ... BUFF_OPCODE_BUFN_NRV_MAX: + rv[RV_ERR_IDX] = buffer_opcode_buffnum_no_return( spacket->opcode, called_buff, + spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); + break; + case BUFF_OPCODE_BUFN_RV_MIN ... BUFF_OPCODE_BUFN_RV_MAX: + //returnlength = somereturn value( spacket->opcode, &called_buff, + //spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); + //return pointer to buffer's data + rptr = called_buff->data; + break; + } + break; + + default: //nes opcode min/max definition error + rv[RV_ERR_IDX] = ERR_BAD_BUFF_OP_MINMAX; + } + + return rptr; +} + /* Desc:Function takes an opcode which was transmitted via USB @@ -51,8 +116,28 @@ uint8_t buffer_opcode_no_return( uint8_t opcode, buffer *buff, uint8_t oper1, ui case RAW_BUFFER_RESET: raw_buffer_reset(); break; - case ALLOCATE_BUFFER0 ... ALLOCATE_BUFFER7: - allocate_buffer( &(*buff), oper1, oper2, oper3 ); + default: + //opcode doesn't exist + return ERR_UNKN_BUFF_OPCODE_NRV; + } + + return SUCCESS; + +} + +/* Desc:Function takes an opcode which was transmitted via USB + * then decodes it to call designated function. + * shared_dict_buffer.h is used in both host and fw to ensure opcodes/names align + * Pre: Macros must be defined in firmware pinport.h + * opcode must be defined in shared_dict_buffer.h + * Post:function call complete. + * Rtn: SUCCESS if opcode found, ERR_UNKN_BUFF_OPCODE_NRV if opcode not present. + */ +uint8_t buffer_opcode_return( uint8_t opcode, buffer *buff, uint8_t operMSB, uint8_t operLSB, uint8_t miscdata, uint8_t *rvalue ) +{ + switch (opcode) { + case RAW_BANK_STATUS: + *rvalue = raw_bank_status[operLSB]; break; default: //opcode doesn't exist @@ -63,9 +148,34 @@ uint8_t buffer_opcode_no_return( uint8_t opcode, buffer *buff, uint8_t oper1, ui } +/* Desc:Function takes an opcode which was transmitted via USB + * then decodes it to call designated function. + * shared_dict_buffer.h is used in both host and fw to ensure opcodes/names align + * This function is for opcodes which use their opcode lower bits to + * denote which buffer to be operated on. + * Pre: Macros must be defined in firmware pinport.h + * opcode must be defined in shared_dict_buffer.h + * Post:function call complete. + * Rtn: SUCCESS if opcode found, ERR_UNKN_BUFF_OPCODE_BUFN_NRV if opcode not present. + */ +uint8_t buffer_opcode_buffnum_no_return( uint8_t opcode, buffer *buff, uint8_t oper1, uint8_t oper2, uint8_t oper3 ) +{ + switch (opcode) { + case ALLOCATE_BUFFER0 ... ALLOCATE_BUFFER7: + return allocate_buffer( buff, oper1, oper2, oper3 ); + break; + default: + //opcode doesn't exist + return ERR_UNKN_BUFF_OPCODE_BUFN_NRV; + } + + return SUCCESS; + +} + /* Desc:Blindly resets all buffer allocation and values * Host instructs this to be called. - * Pre: static instantitions of raw_buffer, raw_bank_status, and buff0-7 above + * Pre: static instantitions of raw_buffer, raw_bank_status, and buff0-7 * Post:all raw buffer ram unallocated * buffer status updated to UNALLOC * Rtn: None @@ -80,23 +190,29 @@ void raw_buffer_reset( ) } //unallocate all buffer objects + //set buffer id to UNALLOC +//min 2 buffers buff0.status = UNALLOC; buff1.status = UNALLOC; + buff0.id = UNALLOC; + buff1.id = UNALLOC; +// 4-8 buffers +#if ( defined(NUM_BUFFERS_4) || (defined(NUM_BUFFERS_8)) ) buff2.status = UNALLOC; buff3.status = UNALLOC; + buff2.id = UNALLOC; + buff3.id = UNALLOC; +#endif //8 buffers +#ifdef NUM_BUFFERS_8 buff4.status = UNALLOC; buff5.status = UNALLOC; buff6.status = UNALLOC; buff7.status = UNALLOC; - //set buffer id to UNALLOC - buff0.id = UNALLOC; - buff1.id = UNALLOC; - buff2.id = UNALLOC; - buff3.id = UNALLOC; buff4.id = UNALLOC; buff5.id = UNALLOC; buff6.id = UNALLOC; buff7.id = UNALLOC; +#endif } @@ -110,6 +226,8 @@ void raw_buffer_reset( ) * another buffer or bank already allocated. * pass in pointer to buffer object to be allocated * pass base bank number and number of banks in buffer + * This function works with various sizes of raw buffer + * as it works based on NUM_RAW_BANKS and RAW_BANK_SIZE * Pre: static instantitions of raw_buffer raw_bank_status, * and buff0-7 above. * Buffer must be unallocated. @@ -122,7 +240,6 @@ void raw_buffer_reset( ) * all other buffer values cleared to zero * Rtn: SUCCESS or ERROR code if unable to allocate */ -//uint8_t allocate_buffer( struct buffer *buff, uint8_t new_id, uint8_t base_bank, uint8_t num_banks ) uint8_t allocate_buffer( buffer *buff, uint8_t new_id, uint8_t base_bank, uint8_t num_banks ) { uint8_t i; @@ -132,6 +249,10 @@ uint8_t allocate_buffer( buffer *buff, uint8_t new_id, uint8_t base_bank, uint8_ //trying to allocate SRAM past end of raw_buffer return ERR_BUFF_ALLOC_RANGE; } + if ( (num_banks) == 0 ) { + //trying to allocate buffer with zero banks + return ERR_BUFF_ALLOC_RANGE; + } //check that buffer isn't already allocated if ( buff->status != UNALLOC) { @@ -151,7 +272,9 @@ uint8_t allocate_buffer( buffer *buff, uint8_t new_id, uint8_t base_bank, uint8_ //seems that buffer and raw are free allocate them as requested buff->id = new_id; buff->status = EMPTY; - buff->data = &raw_buffer[base_bank]; + + //set buffer data pointer to base ram address + buff->data = &raw_buffer[base_bank*RAW_BANK_SIZE]; //set bank status to bank's id for ( i=0; i - - -//~16 bytes per buffer... -typedef struct buffer { - uint8_t *data; //pointer to base buffer's allocated sram - uint8_t size; //size of buffer in bytes (max 256 bytes) - uint8_t status; //current status of buffer USB load/unload, flashing, waiting, erase - uint8_t cur_byte; //byte currently being loaded/unloaded/flashed/read - uint8_t reload; //add this number to page_num for next loading - uint8_t id; //address bits between buffer size and page number - //ie need 2x128 byte buffers making buff_num = A7 - //ie need 4x64 byte buffers making buff_num = A7:6 - //ie need 8x32 byte buffers making buff_num = A7:5 - uint16_t page_num; //address bits beyond buffer's size and buff_num A23-A8 - //MSB A23-16, LSB A15-8 - uint8_t mem_type; //SNES ROM, SNES RAM, PRG ROM, PRG RAM, CHR ROM, CHR RAM, CPLD, SPI - uint8_t part_num; //used to define unlock commands, sector erase, etc - uint8_t multiple; //number of times to program this page - uint8_t add_mult; //add this number to page_num for multiple programs - //CHR shift LSb to A13 (max 2MByte) - //PRG shift LSb to A14 (max 4MByte) - //SNES add to MSB of page_num (max 16MByte) - uint8_t mapper; //mapper number of board - uint8_t mapvar; //mapper variant - uint8_t function; //function "pointer" for flash/dump operation control -}buffer; - -static buffer buff0; -static buffer buff1; -static buffer buff2; -static buffer buff3; -static buffer buff4; -static buffer buff5; -static buffer buff6; -static buffer buff7; - +#include "types.h" #include "logic.h" +#include "usb.h" #include "shared_dictionaries.h" #include "shared_errors.h" + +uint8_t * buffer_usb_call( setup_packet *spacket, uint8_t *rv, uint16_t *rlen); uint8_t buffer_opcode_no_return( uint8_t opcode, buffer *buff, uint8_t oper1, uint8_t oper2, uint8_t oper3 ); +uint8_t buffer_opcode_buffnum_no_return( uint8_t opcode, buffer *buff, uint8_t oper1, uint8_t oper2, uint8_t oper3 ); +uint8_t buffer_opcode_return( uint8_t opcode, buffer *buff, uint8_t operMSB, uint8_t operLSB, uint8_t miscdata, uint8_t *rvalue ); void raw_buffer_reset( ); uint8_t allocate_buffer( buffer *buff, uint8_t new_id, uint8_t base_bank, uint8_t num_banks ); diff --git a/firmware/source/types.h b/firmware/source/types.h new file mode 100644 index 0000000..a0bd294 --- /dev/null +++ b/firmware/source/types.h @@ -0,0 +1,39 @@ +#ifndef _types_h +#define _types_h + +typedef struct setup_packet{ + uint8_t bmRequestType; //contains endpoint + uint8_t bRequest; //designates dictionary of opcode + uint8_t opcode; //wValueLSB (little endian) + uint8_t miscdata; //wValueMSB + uint8_t operandLSB; //wIndexLSB + uint8_t operandMSB; //wIndexMSB + uint16_t wLength; +}setup_packet; + +//~16 bytes per buffer... +typedef struct buffer { + uint8_t *data; //pointer to base buffer's allocated sram + uint8_t size; //size of buffer in bytes (max 256 bytes) + uint8_t status; //current status of buffer USB load/unload, flashing, waiting, erase + uint8_t cur_byte; //byte currently being loaded/unloaded/flashed/read + uint8_t reload; //add this number to page_num for next loading + uint8_t id; //address bits between buffer size and page number + //ie need 2x128 byte buffers making buff_num = A7 + //ie need 4x64 byte buffers making buff_num = A7:6 + //ie need 8x32 byte buffers making buff_num = A7:5 + uint16_t page_num; //address bits beyond buffer's size and buff_num A23-A8 + //MSB A23-16, LSB A15-8 + uint8_t mem_type; //SNES ROM, SNES RAM, PRG ROM, PRG RAM, CHR ROM, CHR RAM, CPLD, SPI + uint8_t part_num; //used to define unlock commands, sector erase, etc + uint8_t multiple; //number of times to program this page + uint8_t add_mult; //add this number to page_num for multiple programs + //CHR shift LSb to A13 (max 2MByte) + //PRG shift LSb to A14 (max 4MByte) + //SNES add to MSB of page_num (max 16MByte) + uint8_t mapper; //mapper number of board + uint8_t mapvar; //mapper variant + uint8_t function; //function "pointer" for flash/dump operation control +}buffer; + +#endif diff --git a/firmware/source/usb.c b/firmware/source/usb.c index 19cc1e9..f466d5e 100644 --- a/firmware/source/usb.c +++ b/firmware/source/usb.c @@ -38,34 +38,43 @@ // usbWord_t wLength; //}usbRequest_t; -#define ENDPOINT_BIT 0x80 //Bit 7 of bmRequest type determines endpoint -#define ENDPOINT_IN 0x80 //In: device-to-host. -#define ENDPOINT_OUT 0x00 //Out: host-to-device. -typedef struct setup_packet{ - uint8_t bmRequestType; //contains endpoint - uint8_t bRequest; //designates dictionary of opcode - uint8_t opcode; //wValueLSB (little endian) - uint8_t miscdata; //wValueMSB - uint8_t operandLSB; //wIndexLSB - uint8_t operandMSB; //wIndexMSB - uint16_t wLength; -}setup_packet; - USB_PUBLIC usbMsgLen_t usbFunctionSetup(uchar data[8]) { //cast incoming data into the the usb setup packet it is setup_packet *spacket = (void *)data; //8 Byte buffer to be used for returning error code and return values - //must be static so driver can still access after function return - static uchar rv[8]; - //rv[0] contains opcode success/error code + //must be static so V-USB driver can still access after function return + static uint8_t rv[RETURN_BUFF_SIZE]; + //rv[RV_ERR_IDX] contains opcode success/error code //rv[1-7] available for return data, start with index 1 + //rv[RETURN_BUFF_FIRST_IDX-RETURN_BUFFER_LAST_IDX] - //number of bytes to return to host - uint8_t rlen = 0; + /* (1) Set the global pointer 'usbMsgPtr' to the base of the static RAM data + * block and return the length of the data in 'usbFunctionSetup()'. The driver + * will handle the rest. Or (2) return USB_NO_MSG in 'usbFunctionSetup()'. The + * driver will then call 'usbFunctionRead()' when data is needed. See the + */ + //by default want to return some portion of the 8 byte rv "return value" + //buffer. If no return data requested from host rlen = 0, so this wouldn't matter + //Some dictionaries/opcodes that want to return larger buffers though + //this function will set usbMsgPtr to point to that larger buffer when supported + //avr-gcc doesn't like this and gives warning + //source/usb.c:64: warning: assignment makes integer from pointer without a cast + //tried casting it to usbMsgPtr + usbMsgPtr = (usbMsgPtr_t)rv; + +//#if USB_CFG_LONG_TRANSFERS +// //number of bytes to return to host +// //16bit meets max possible 16KBytes with V-USB long transfers enabled + uint16_t rlen = 0; //just go ahead and set to 16bit to be safe + //prob not worth saving a measly byte.. +//#else +// //8bit is enough for 254 bit non-long xfrs +// uint8_t rlen = 0; +//#endif //determine endpoint IN/OUT if ( (spacket->bmRequestType & ENDPOINT_BIT) == ENDPOINT_IN ) { @@ -85,131 +94,92 @@ USB_PUBLIC usbMsgLen_t usbFunctionSetup(uchar data[8]) { case PINPORT: switch (spacket->opcode) { case PP_OPCODE_ONLY_MIN ... PP_OPCODE_ONLY_MAX: - rv[0] = pinport_opcode_only( spacket->opcode ); + rv[RV_ERR_IDX] = pinport_opcode_only( spacket->opcode ); break; case PP_OPCODE_8BOP_MIN ... PP_OPCODE_8BOP_MAX: - rv[0] = pinport_opcode_8b_operand( + rv[RV_ERR_IDX] = pinport_opcode_8b_operand( spacket->opcode, spacket->operandLSB ); break; case PP_OPCODE_16BOP_MIN ... PP_OPCODE_16BOP_MAX: - rv[0] = pinport_opcode_16b_operand( + rv[RV_ERR_IDX] = pinport_opcode_16b_operand( spacket->opcode, spacket->operandMSB, spacket->operandLSB ); break; case PP_OPCODE_24BOP_MIN ... PP_OPCODE_24BOP_MAX: - rv[0] = pinport_opcode_24b_operand( spacket->opcode, + rv[RV_ERR_IDX] = pinport_opcode_24b_operand( spacket->opcode, spacket->miscdata, spacket->operandMSB, spacket->operandLSB ); break; case PP_OPCODE_8BRV_MIN ... PP_OPCODE_8BRV_MAX: - rv[0] = pinport_opcode_8b_return( spacket->opcode, &rv[1]); + rv[RV_ERR_IDX] = pinport_opcode_8b_return( spacket->opcode, &rv[RV_DATA0_IDX]); rlen ++; break; default: //pinport opcode min/max definition error - rv[0] = ERR_BAD_PP_OP_MINMAX; + rv[RV_ERR_IDX] = ERR_BAD_PP_OP_MINMAX; } break; //end of PINPORT case IO: switch (spacket->opcode) { case IO_OPCODE_ONLY_MIN ... IO_OPCODE_ONLY_MAX: - rv[0] = io_opcode_only( spacket->opcode ); + rv[RV_ERR_IDX] = io_opcode_only( spacket->opcode ); break; case IO_OPCODE_RTN_MIN ... IO_OPCODE_RTN_MAX: - rv[0] = io_opcode_return( - spacket->opcode, &rv[1] ); + rv[RV_ERR_IDX] = io_opcode_return( + spacket->opcode, &rv[RV_DATA0_IDX] ); rlen = 8; break; default: //io opcode min/max definition error - rv[0] = ERR_BAD_IO_OP_MINMAX; + rv[RV_ERR_IDX] = ERR_BAD_IO_OP_MINMAX; } break; //end of IO case NES: switch (spacket->opcode) { case NES_OPCODE_24BOP_MIN ... NES_OPCODE_24BOP_MAX: - rv[0] = nes_opcode_24b_operand( spacket->opcode, + rv[RV_ERR_IDX] = nes_opcode_24b_operand( spacket->opcode, spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); break; case NES_OPCODE_16BOP_8BRV_MIN ... NES_OPCODE_16BOP_8BRV_MAX: - rv[0] = nes_opcode_16b_operand_8b_return( spacket->opcode, - spacket->operandMSB, spacket->operandLSB, &rv[1]); + rv[RV_ERR_IDX] = nes_opcode_16b_operand_8b_return( spacket->opcode, + spacket->operandMSB, spacket->operandLSB, &rv[RV_DATA0_IDX]); rlen++; break; default: //nes opcode min/max definition error - rv[0] = ERR_BAD_NES_OP_MINMAX; + rv[RV_ERR_IDX] = ERR_BAD_NES_OP_MINMAX; } break; //end of NES case SNES: switch (spacket->opcode) { case SNES_OPCODE_24BOP_MIN ... SNES_OPCODE_24BOP_MAX: - rv[0] = snes_opcode_24b_operand( spacket->opcode, + rv[RV_ERR_IDX] = snes_opcode_24b_operand( spacket->opcode, spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); break; case SNES_OPCODE_24BOP_8BRV_MIN ... SNES_OPCODE_24BOP_8BRV_MAX: - rv[0] = snes_opcode_24b_operand_8b_return( spacket->opcode, - spacket->miscdata, spacket->operandMSB, spacket->operandLSB, &rv[1]); + rv[RV_ERR_IDX] = snes_opcode_24b_operand_8b_return( spacket->opcode, + spacket->miscdata, spacket->operandMSB, spacket->operandLSB, &rv[RV_DATA0_IDX]); rlen++; break; default: //snes opcode min/max definition error - rv[0] = ERR_BAD_SNES_OP_MINMAX; + rv[RV_ERR_IDX] = ERR_BAD_SNES_OP_MINMAX; } break; //end of SNES case BUFFER: - switch (spacket->opcode) { - case BUFF_OPCODE_NRV_MIN ... BUFF_OPCODE_NRV_MAX: - rv[0] = buffer_opcode_no_return( spacket->opcode, NULL, - spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); - break; - case BUFF_OPCODE_BUFn_NRV_MIN ... BUFF_OPCODE_BUFn_NRV_MAX: - switch ( (spacket->opcode) & 0x07) { - case 0: - rv[0] = buffer_opcode_no_return( spacket->opcode, &buff0, - spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); - case 1: - rv[0] = buffer_opcode_no_return( spacket->opcode, &buff1, - spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); - case 2: - rv[0] = buffer_opcode_no_return( spacket->opcode, &buff2, - spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); - case 3: - rv[0] = buffer_opcode_no_return( spacket->opcode, &buff3, - spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); - case 4: - rv[0] = buffer_opcode_no_return( spacket->opcode, &buff4, - spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); - case 5: - rv[0] = buffer_opcode_no_return( spacket->opcode, &buff5, - spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); - case 6: - rv[0] = buffer_opcode_no_return( spacket->opcode, &buff6, - spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); - case 7: - rv[0] = buffer_opcode_no_return( spacket->opcode, &buff7, - spacket->operandMSB, spacket->operandLSB, spacket->miscdata ); - default: //nes opcode min/max definition error - rv[0] = ERR_BAD_BUFF_OP_MINMAX; - } - break; - default: //nes opcode min/max definition error - rv[0] = ERR_BAD_BUFF_OP_MINMAX; - } + //just give buffer.c the setup packet and let it figure things out for itself + usbMsgPtr = (usbMsgPtr_t)buffer_usb_call( spacket, rv, &rlen ); break; //end of BUFFER default: //request (aka dictionary) is unknown - rv[0] = ERR_UNKN_DICTIONARY; + rv[RV_ERR_IDX] = ERR_UNKN_DICTIONARY; } - /* (1) Set the global pointer 'usbMsgPtr' to the base of the static RAM data - * block and return the length of the data in 'usbFunctionSetup()'. The driver - * will handle the rest. Or (2) return USB_NO_MSG in 'usbFunctionSetup()'. The - * driver will then call 'usbFunctionRead()' when data is needed. See the - */ - usbMsgPtr = rv; + //TODO add check that verifies rlen == setup packet return lenght request + //current state has error checking somewhat embeded in the fact the host + //will detect when return length differs from requested return rlen; - //return USB_NO_MSG; + //return USB_NO_MSG; //if want usbFunctionRead called during IN token data packets //Don't have a use for usbFunctionRead yet.. Not expecting to anytime soon //probably easier and perhaps faster to send cart dump commands and store rom image //in a buffer to be returned here. diff --git a/firmware/source/usb.h b/firmware/source/usb.h index d21a285..b8fa0b1 100644 --- a/firmware/source/usb.h +++ b/firmware/source/usb.h @@ -5,6 +5,7 @@ #include "usbdrv.h" #include "logic.h" +#include "types.h" #include "shared_dictionaries.h" #include "shared_errors.h" #include "pinport.h" @@ -13,5 +14,15 @@ #include "snes.h" #include "buffer.h" +#define ENDPOINT_BIT 0x80 //Bit 7 of bmRequest type determines endpoint +#define ENDPOINT_IN 0x80 //In: device-to-host. +#define ENDPOINT_OUT 0x00 //Out: host-to-device. + + +//TODO these should probably be in shared so host code and utilize them on the other side +#define RETURN_BUFF_SIZE 8 //number of bytes in generic return buffer +#define RV_ERR_IDX 0 //(first) index of buffer that contains SUCCESS/ERROR# +#define RV_DATA0_IDX RV_ERR_IDX + 1 //first index of return data +#define RV_DATA_MAX_IDX RETURN_BUFF_SIZE - 1 //last index available for return data #endif diff --git a/host/source/dictionary.c b/host/source/dictionary.c index 0389177..d38296f 100644 --- a/host/source/dictionary.c +++ b/host/source/dictionary.c @@ -40,7 +40,7 @@ int dictionary_call( USBtransfer *transfer, uint8_t dictionary, uint8_t opcode, transfer->data = rbuf; - debug("dictionary call dict:%d opcode:%d/%x addr:%x data:%x", dictionary, opcode, opcode, addr, miscdata); + 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; @@ -111,6 +111,28 @@ int dictionary_call( USBtransfer *transfer, uint8_t dictionary, uint8_t opcode, } break; //end of SNES + case BUFFER: debug("dict: BUFFER"); + transfer->wLength = 1; + switch (opcode) { + case BUFF_OPCODE_NRV_MIN ... BUFF_OPCODE_NRV_MAX: + debug("BUFF_OPCODE_NRV"); + break; + case BUFF_OPCODE_RV_MIN ... BUFF_OPCODE_RV_MAX: + debug("BUFF_OPCODE_RV"); + transfer->wLength = 2; + break; + case BUFF_OPCODE_BUFN_NRV_MIN ... BUFF_OPCODE_BUFN_NRV_MAX: + debug("BUFF_OPCODE_NRV"); + break; + case BUFF_OPCODE_BUFN_RV_MIN ... BUFF_OPCODE_BUFN_RV_MAX: + debug("BUFF_OPCODE_RV"); + //TODO + break; + default: //snes opcode min/max definition error + sentinel("bad BUFFER opcode min/max err:%d",ERR_BAD_BUFF_OP_MINMAX); + } + break; //end of BUFF + default: //request (aka dictionary) is unknown sentinel("unknown DICT err:%d",ERR_UNKN_DICTIONARY); @@ -120,7 +142,12 @@ int dictionary_call( USBtransfer *transfer, uint8_t dictionary, uint8_t opcode, int xfr_cnt; xfr_cnt = usb_transfer( transfer ); - debug("xf: %d er: %d rv: %x, %x, %x, %x, %x, %x, %x",xfr_cnt, rbuf[0], rbuf[1], rbuf[2], rbuf[3], rbuf[4], rbuf[5], rbuf[6], rbuf[7]); + printf(" xf: %d er: %d rv:",xfr_cnt, rbuf[0]); + int i ; + for (i=1; i