#include "buffer.h" //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 //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 //buffer status stores allocation status of each raw buffer 32Byte bank static uint8_t raw_bank_status[NUM_RAW_BANKS]; /* 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; *rlen = (spacket->wLength); break; case BUFF_PAYLOAD0 ... BUFF_PAYLOAD7: //for now just read write from designated buffer //TODO make some checks that buffer is allocated/not busy etc //determine endpoint IN/OUT if ((spacket->bmRequestType & ENDPOINT_BIT) & ENDPOINT_IN) { //read/dump from device to host rptr = called_buff->data; *rlen = (spacket->wLength); called_buff->cur_byte = 0; called_buff->status = USB_UNLOADING; } else { //write to device from host cur_usb_load_buff = called_buff; incoming_bytes_remain = (spacket->wLength); called_buff->cur_byte = 0; called_buff->status = USB_LOADING; //return USB_NO_MSG to get usbFunctionWrite //called on incoming packets *rlen = USB_NO_MSG; } 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 * 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_no_return( uint8_t opcode, buffer *buff, uint8_t oper1, uint8_t oper2, uint8_t oper3 ) { switch (opcode) { case RAW_BUFFER_RESET: raw_buffer_reset(); break; 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 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 * 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 * Post:all raw buffer ram unallocated * buffer status updated to UNALLOC * Rtn: None */ void raw_buffer_reset( ) { uint8_t i; //unallocate raw buffer space for( i=0; i NUM_RAW_BANKS ) { //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) { return ERR_BUFF_STATUS_ALREADY_ALLOC; } if ( buff->id != UNALLOC) { return ERR_BUFF_ID_ALREADY_ALLOC; } //check that raw banks aren't allocated for ( i=0; iid = new_id; buff->status = EMPTY; buff->size = num_banks * RAW_BANK_SIZE; //zero out other elements buff->cur_byte = 0; buff->reload = 0; buff->page_num = 0; buff->mem_type = 0; buff->part_num = 0; buff->multiple = 0; buff->add_mult = 0; buff->mapper = 0; buff->function = 0; //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