X-Git-Url: http://git.linex4red.de/pub/USBasp.git/blobdiff_plain/885170f5b456116d7c40570c36342193a30ed886..5517f96e86b9447780a3e27bb455697f9fc65eea:/Bootloaders/CDC/BootloaderCDC.c diff --git a/Bootloaders/CDC/BootloaderCDC.c b/Bootloaders/CDC/BootloaderCDC.c index da2d0b665..38f78daf3 100644 --- a/Bootloaders/CDC/BootloaderCDC.c +++ b/Bootloaders/CDC/BootloaderCDC.c @@ -1,7 +1,7 @@ /* LUFA Library Copyright (C) Dean Camera, 2010. - + dean [at] fourwalledcubicle [dot] com www.fourwalledcubicle.com */ @@ -9,13 +9,13 @@ /* Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) - Permission to use, copy, modify, distribute, and sell this + Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in + without fee, provided that the above copyright notice appear in all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the software without specific, written prior permission. The author disclaim all warranties with regard to this @@ -32,10 +32,18 @@ * * Main source file for the CDC class bootloader. This file contains the complete bootloader logic. */ - + #define INCLUDE_FROM_BOOTLOADERCDC_C #include "BootloaderCDC.h" +/** Contains the current baud rate and other settings of the first virtual serial port. This must be retained as some + * operating systems will not open the port unless the settings can be set successfully. + */ +CDC_Line_Coding_t LineEncoding = { .BaudRateBPS = 0, + .CharFormat = OneStopBit, + .ParityType = Parity_None, + .DataBits = 8 }; + /** Current address counter. This stores the current address of the FLASH or EEPROM as set by the host, * and is used when reading or writing to the AVRs memory (either FLASH or EEPROM depending on the issued * command.) @@ -49,7 +57,7 @@ uint32_t CurrAddress; bool RunBootloader = true; -/** Main program entry point. This routine configures the hardware required by the bootloader, then continuously +/** Main program entry point. This routine configures the hardware required by the bootloader, then continuously * runs the bootloader processing routine until instructed to soft-exit, or hard-reset via the watchdog to start * the loaded application code. */ @@ -66,7 +74,7 @@ int main(void) CDC_Task(); USB_USBTask(); } - + /* Disconnect from the host - USB interface will be reset later along with the AVR */ USB_Detach(); @@ -85,11 +93,11 @@ void SetupHardware(void) /* Disable clock division */ clock_prescale_set(clock_div_1); - + /* Relocate the interrupt vector table to the bootloader section */ MCUCR = (1 << IVCE); MCUCR = (1 << IVSEL); - + /* Initialize USB Subsystem */ USB_Init(); } @@ -101,18 +109,52 @@ void EVENT_USB_Device_ConfigurationChanged(void) { /* Setup CDC Notification, Rx and Tx Endpoints */ Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT, - ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE, + ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE, ENDPOINT_BANK_SINGLE); Endpoint_ConfigureEndpoint(CDC_TX_EPNUM, EP_TYPE_BULK, - ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE, + ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE, ENDPOINT_BANK_SINGLE); Endpoint_ConfigureEndpoint(CDC_RX_EPNUM, EP_TYPE_BULK, - ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE, + ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE, ENDPOINT_BANK_SINGLE); } +/** Event handler for the USB_UnhandledControlRequest event. This is used to catch standard and class specific + * control requests that are not handled internally by the USB library (including the CDC control commands, + * which are all issued via the control endpoint), so that they can be handled appropriately for the application. + */ +void EVENT_USB_Device_UnhandledControlRequest(void) +{ + /* Process CDC specific control requests */ + switch (USB_ControlRequest.bRequest) + { + case REQ_GetLineEncoding: + if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE)) + { + Endpoint_ClearSETUP(); + + /* Write the line coding data to the control endpoint */ + Endpoint_Write_Control_Stream_LE(&LineEncoding, sizeof(CDC_Line_Coding_t)); + Endpoint_ClearOUT(); + } + + break; + case REQ_SetLineEncoding: + if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) + { + Endpoint_ClearSETUP(); + + /* Read the line coding data in from the host into the global struct */ + Endpoint_Read_Control_Stream_LE(&LineEncoding, sizeof(CDC_Line_Coding_t)); + Endpoint_ClearIN(); + } + + break; + } +} + /** Reads or writes a block of EEPROM or FLASH memory to or from the appropriate CDC data endpoint, depending * on the AVR910 protocol command issued. * @@ -122,20 +164,20 @@ static void ReadWriteMemoryBlock(const uint8_t Command) { uint16_t BlockSize; char MemoryType; - + bool HighByte = false; uint8_t LowByte = 0; - + BlockSize = (FetchNextCommandByte() << 8); BlockSize |= FetchNextCommandByte(); - + MemoryType = FetchNextCommandByte(); if ((MemoryType != 'E') && (MemoryType != 'F')) { /* Send error byte back to the host */ WriteNextResponseByte('?'); - + return; } @@ -153,13 +195,13 @@ static void ReadWriteMemoryBlock(const uint8_t Command) #if (FLASHEND > 0xFFFF) WriteNextResponseByte(pgm_read_byte_far(CurrAddress | HighByte)); #else - WriteNextResponseByte(pgm_read_byte(CurrAddress | HighByte)); + WriteNextResponseByte(pgm_read_byte(CurrAddress | HighByte)); #endif - + /* If both bytes in current word have been read, increment the address counter */ if (HighByte) CurrAddress += 2; - + HighByte = !HighByte; } else @@ -169,7 +211,7 @@ static void ReadWriteMemoryBlock(const uint8_t Command) /* Increment the address counter after use */ CurrAddress += 2; - } + } } } else @@ -181,11 +223,11 @@ static void ReadWriteMemoryBlock(const uint8_t Command) boot_page_erase(PageStartAddress); boot_spm_busy_wait(); } - + while (BlockSize--) { if (MemoryType == 'F') - { + { /* If both bytes in current word have been written, increment the address counter */ if (HighByte) { @@ -200,14 +242,14 @@ static void ReadWriteMemoryBlock(const uint8_t Command) else { LowByte = FetchNextCommandByte(); - + HighByte = true; } } else { /* Write the next EEPROM byte from the endpoint */ - eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte()); + eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte()); /* Increment the address counter after use */ CurrAddress += 2; @@ -219,13 +261,13 @@ static void ReadWriteMemoryBlock(const uint8_t Command) { /* Commit the flash page to memory */ boot_page_write(PageStartAddress); - + /* Wait until write operation has completed */ boot_spm_busy_wait(); } - + /* Send response byte back to the host */ - WriteNextResponseByte('\r'); + WriteNextResponseByte('\r'); } } @@ -238,7 +280,7 @@ static uint8_t FetchNextCommandByte(void) { /* Select the OUT endpoint so that the next data byte can be read */ Endpoint_SelectEndpoint(CDC_RX_EPNUM); - + /* If OUT endpoint empty, clear it and wait for the next packet from the host */ while (!(Endpoint_IsReadWriteAllowed())) { @@ -250,7 +292,7 @@ static uint8_t FetchNextCommandByte(void) return 0; } } - + /* Fetch the next byte from the OUT endpoint */ return Endpoint_Read_Byte(); } @@ -264,19 +306,19 @@ static void WriteNextResponseByte(const uint8_t Response) { /* Select the IN endpoint so that the next data byte can be written */ Endpoint_SelectEndpoint(CDC_TX_EPNUM); - + /* If IN endpoint full, clear it and wait until ready for the next packet to the host */ if (!(Endpoint_IsReadWriteAllowed())) { Endpoint_ClearIN(); - + while (!(Endpoint_IsINReady())) { if (USB_DeviceState == DEVICE_STATE_Unattached) return; } } - + /* Write the next byte to the OUT endpoint */ Endpoint_Write_Byte(Response); } @@ -288,7 +330,7 @@ void CDC_Task(void) { /* Select the OUT endpoint */ Endpoint_SelectEndpoint(CDC_RX_EPNUM); - + /* Check if endpoint has a command in it sent from the host */ if (Endpoint_IsOUTReceived()) { @@ -303,7 +345,7 @@ void CDC_Task(void) FetchNextCommandByte(); /* Send confirmation byte back to the host */ - WriteNextResponseByte('\r'); + WriteNextResponseByte('\r'); } else if (Command == 't') { @@ -328,13 +370,13 @@ void CDC_Task(void) else if (Command == 'p') { /* Indicate serial programmer back to the host */ - WriteNextResponseByte('S'); + WriteNextResponseByte('S'); } else if (Command == 'S') { /* Write the 7-byte software identifier to the endpoint */ for (uint8_t CurrByte = 0; CurrByte < 7; CurrByte++) - WriteNextResponseByte(SOFTWARE_IDENTIFIER[CurrByte]); + WriteNextResponseByte(SOFTWARE_IDENTIFIER[CurrByte]); } else if (Command == 'V') { @@ -343,17 +385,17 @@ void CDC_Task(void) } else if (Command == 's') { - WriteNextResponseByte(AVR_SIGNATURE_3); + WriteNextResponseByte(AVR_SIGNATURE_3); WriteNextResponseByte(AVR_SIGNATURE_2); WriteNextResponseByte(AVR_SIGNATURE_1); } else if (Command == 'b') { WriteNextResponseByte('Y'); - + /* Send block size to the host */ WriteNextResponseByte(SPM_PAGESIZE >> 8); - WriteNextResponseByte(SPM_PAGESIZE & 0xFF); + WriteNextResponseByte(SPM_PAGESIZE & 0xFF); } else if (Command == 'e') { @@ -367,9 +409,9 @@ void CDC_Task(void) CurrFlashAddress += SPM_PAGESIZE; } - + /* Send confirmation byte back to the host */ - WriteNextResponseByte('\r'); + WriteNextResponseByte('\r'); } else if (Command == 'l') { @@ -381,7 +423,7 @@ void CDC_Task(void) } else if (Command == 'r') { - WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOCK_BITS)); + WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOCK_BITS)); } else if (Command == 'F') { @@ -389,41 +431,41 @@ void CDC_Task(void) } else if (Command == 'N') { - WriteNextResponseByte(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS)); + WriteNextResponseByte(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS)); } else if (Command == 'Q') { - WriteNextResponseByte(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS)); + WriteNextResponseByte(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS)); } else if (Command == 'C') - { + { /* Write the high byte to the current flash page */ boot_page_fill(CurrAddress, FetchNextCommandByte()); /* Send confirmation byte back to the host */ - WriteNextResponseByte('\r'); + WriteNextResponseByte('\r'); } else if (Command == 'c') - { + { /* Write the low byte to the current flash page */ boot_page_fill(CurrAddress | 1, FetchNextCommandByte()); - + /* Increment the address */ CurrAddress += 2; /* Send confirmation byte back to the host */ - WriteNextResponseByte('\r'); + WriteNextResponseByte('\r'); } else if (Command == 'm') { /* Commit the flash page to memory */ boot_page_write(CurrAddress); - + /* Wait until write operation has completed */ boot_spm_busy_wait(); /* Send confirmation byte back to the host */ - WriteNextResponseByte('\r'); + WriteNextResponseByte('\r'); } else if ((Command == 'B') || (Command == 'g')) { @@ -435,9 +477,9 @@ void CDC_Task(void) #if (FLASHEND > 0xFFFF) uint16_t ProgramWord = pgm_read_word_far(CurrAddress); #else - uint16_t ProgramWord = pgm_read_word(CurrAddress); + uint16_t ProgramWord = pgm_read_word(CurrAddress); #endif - + WriteNextResponseByte(ProgramWord >> 8); WriteNextResponseByte(ProgramWord & 0xFF); } @@ -445,12 +487,12 @@ void CDC_Task(void) { /* Read the byte from the endpoint and write it to the EEPROM */ eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte()); - - /* Increment the address after use */ + + /* Increment the address after use */ CurrAddress += 2; - + /* Send confirmation byte back to the host */ - WriteNextResponseByte('\r'); + WriteNextResponseByte('\r'); } else if (Command == 'd') { @@ -478,12 +520,12 @@ void CDC_Task(void) /* Send the endpoint data to the host */ Endpoint_ClearIN(); - + /* If a full endpoint's worth of data was sent, we need to send an empty packet afterwards to signal end of transfer */ if (IsEndpointFull) { while (!(Endpoint_IsINReady())) - { + { if (USB_DeviceState == DEVICE_STATE_Unattached) return; } @@ -493,11 +535,11 @@ void CDC_Task(void) /* Wait until the data has been sent to the host */ while (!(Endpoint_IsINReady())) - { + { if (USB_DeviceState == DEVICE_STATE_Unattached) return; } - + /* Select the OUT endpoint */ Endpoint_SelectEndpoint(CDC_RX_EPNUM); @@ -505,3 +547,4 @@ void CDC_Task(void) Endpoint_ClearOUT(); } } +