Exemplo n.º 1
0
/// Handle USB control requests
bool EVENT_USB_Device_ControlRequest(USB_Request_Header_t* req){
	if ((req->bmRequestType & CONTROL_REQTYPE_TYPE) == REQTYPE_VENDOR){
		switch (req->bRequest){
			case REQ_INFO:
				fillInfoStruct();
				USB_ep0_send(sizeof(BootloaderInfo));
				return true;
			case REQ_ERASE:
				SP_EraseApplicationSection();
				USB_ep0_send(0);
				return true;
			case REQ_START_WRITE:
				page = req->wIndex;
				pageOffs = 0;
				USB_ep_out_start(1, pageBuf);
				USB_ep0_send(0);
				return true;
			case REQ_CRC_APP:
				*(uint32_t*)ep0_buf_in = SP_ApplicationCRC();
				USB_ep0_send(sizeof(uint32_t));
				return true;
			case REQ_CRC_BOOT:
				*(uint32_t*)ep0_buf_in = SP_BootCRC();
				USB_ep0_send(sizeof(uint32_t));
				return true;
			case REQ_RESET:
				USB_ep0_send(0);
				USB_ep0_wait_for_complete();
				_delay_us(10000);
				USB_Detach();
				bootloaderflag = 0;
				
				cli();
				_delay_us(100000); // 0.1s
				CCP = CCP_IOREG_gc;
				RST.CTRL = RST_SWRST_bm;
				while(1){};
				
				return true;
		}
	}
	
	return false;
}
Exemplo n.º 2
0
/**************************************************************************************************
* Handle received HID set feature reports
*/
void HID_set_feature_report_out(uint8_t *report)
{
	uint8_t		response[UDI_HID_REPORT_OUT_SIZE];
	response[0] = report[0] | 0x80;
	response[1] = report[1];
	response[2] = report[2];
	
	uint16_t	addr;
	addr = *(uint16_t *)(report+1);

	switch(report[0])
	{
		// no-op
		case CMD_NOP:
			break;
		
		// write to RAM page buffer
		case CMD_RESET_POINTER:
			page_ptr = 0;
			return;

		// read from RAM page buffer
		case CMD_READ_BUFFER:
			memcpy(response, &page_buffer[page_ptr], UDI_HID_REPORT_OUT_SIZE);
			page_ptr += UDI_HID_REPORT_OUT_SIZE;
			page_ptr &= APP_SECTION_PAGE_SIZE-1;
			break;

		// erase entire application section
		case CMD_ERASE_APP_SECTION:
			SP_WaitForSPM();
			SP_EraseApplicationSection();
			return;

		// calculate application and bootloader section CRCs
		case CMD_READ_FLASH_CRCS:
			SP_WaitForSPM();
			*(uint32_t *)&response[3] = SP_ApplicationCRC();
			*(uint32_t *)&response[7] = SP_BootCRC();
			break;

		// read MCU IDs
		case CMD_READ_MCU_IDS:
			response[3] = MCU.DEVID0;
			response[4] = MCU.DEVID1;
			response[5] = MCU.DEVID2;
			response[6] = MCU.REVID;
			break;
		
		// read fuses
		case CMD_READ_FUSES:
			response[3] = SP_ReadFuseByte(0);
			response[4] = SP_ReadFuseByte(1);
			response[5] = SP_ReadFuseByte(2);
			response[6] = 0xFF;
			response[7] = SP_ReadFuseByte(4);
			response[8] = SP_ReadFuseByte(5);
			break;
		
		// write RAM page buffer to application section page
		case CMD_WRITE_PAGE:
			if (addr > (APP_SECTION_SIZE / APP_SECTION_PAGE_SIZE))	// out of range
			{
				response[1] = 0xFF;
				response[2] = 0xFF;
				break;
			}
			SP_WaitForSPM();
			SP_LoadFlashPage(page_buffer);
			SP_WriteApplicationPage(APP_SECTION_START + ((uint32_t)addr * APP_SECTION_PAGE_SIZE));
			page_ptr = 0;
			break;

		// read application page to RAM buffer and return first 32 bytes
		case CMD_READ_PAGE:
			if (addr > (APP_SECTION_SIZE / APP_SECTION_PAGE_SIZE))	// out of range
			{
				response[1] = 0xFF;
				response[2] = 0xFF;
			}
			else
			{
				memcpy_P(page_buffer, (const void *)(APP_SECTION_START + (APP_SECTION_PAGE_SIZE * addr)), APP_SECTION_PAGE_SIZE);
				memcpy(&response[3], page_buffer, 32);
				page_ptr = 0;
			}
			break;
		
		// erase user signature row
		case CMD_ERASE_USER_SIG_ROW:
			SP_WaitForSPM();
			SP_EraseUserSignatureRow();
			break;
		
		// write RAM buffer to user signature row
		case CMD_WRITE_USER_SIG_ROW:
			SP_WaitForSPM();
			SP_LoadFlashPage(page_buffer);
			SP_WriteUserSignatureRow();
			break;

		// read user signature row to RAM buffer and return first 32 bytes
		case CMD_READ_USER_SIG_ROW:
			if (addr > (USER_SIGNATURES_PAGE_SIZE - 32))
			{
				response[1] = 0xFF;
				response[2] = 0xFF;
			}
			else
			{
				memcpy_P(page_buffer, (const void *)(USER_SIGNATURES_START + addr), USER_SIGNATURES_SIZE);
				memcpy(&response[3], page_buffer, 32);
				page_ptr = 0;
			}
			break;

		case CMD_READ_SERIAL:
			{
				uint8_t	i;
				uint8_t	j = 3;
				uint8_t b;
	
				for (i = 0; i < 6; i++)
				{
					b = SP_ReadCalibrationByte(offsetof(NVM_PROD_SIGNATURES_t, LOTNUM0) + i);
					response[j++] = hex_to_char(b >> 4);
					response[j++] = hex_to_char(b & 0x0F);
				}
				response[j++] = '-';
				b = SP_ReadCalibrationByte(offsetof(NVM_PROD_SIGNATURES_t, LOTNUM0) + 6);
				response[j++] = hex_to_char(b >> 4);
				response[j++] = hex_to_char(b & 0x0F);
				response[j++] = '-';

				for (i = 7; i < 11; i++)
				{
					b = SP_ReadCalibrationByte(offsetof(NVM_PROD_SIGNATURES_t, LOTNUM0) + i);
					response[j++] = hex_to_char(b >> 4);
					response[j++] = hex_to_char(b & 0x0F);
				}

				response[j] = '\0';
				break;
			}
		
		case CMD_READ_BOOTLOADER_VERSION:
			response[3] = BOOTLOADER_VERSION;
			break;
		
		case CMD_RESET_MCU:
			reset_do_soft_reset();
			response[1] = 0xFF;	// failed
			break;
		
		case CMD_READ_EEPROM:
			if (addr > (EEPROM_SIZE - 32))
			{
				response[1] = 0xFF;
				response[2] = 0xFF;
			}
			else
			{
				EEP_EnableMapping();
				memcpy_P(page_buffer, (const void *)(MAPPED_EEPROM_START + addr), APP_SECTION_PAGE_SIZE);
				EEP_DisableMapping();
				memcpy(&response[3], page_buffer, 32);
				page_ptr = 0;
			}
			break;

		case CMD_WRITE_EEPROM:
			if (addr > (EEPROM_SIZE / EEPROM_PAGE_SIZE))
			{
				response[1] = 0xFF;
				response[2] = 0xFF;
			}
			else
			{
				EEP_LoadPageBuffer(&report[3], EEPROM_PAGE_SIZE);
				EEP_AtomicWritePage(addr);
			}
			break;
		
		// unknown command
		default:
			response[0] = 0xFF;
			break;
	}

	udi_hid_generic_send_report_in(response);
}