commit
4df793ecb2
@ -0,0 +1,10 @@ |
||||
src/lufa-LUFA-210130 |
||||
*.bin |
||||
*.eep |
||||
*.elf |
||||
*.hex |
||||
*.lss |
||||
*.map |
||||
*.sym |
||||
obj |
||||
bin |
@ -0,0 +1,60 @@ |
||||
# https://github.com/jkent/caterina-promicro
|
||||
|
||||
VID = 0xbeef
|
||||
PID = 0x0001
|
||||
|
||||
CDEFS = -DDEVICE_VID=$(VID)UL
|
||||
CDEFS += -DDEVICE_PID=$(PID)UL
|
||||
|
||||
|
||||
MCU = atmega32u4
|
||||
F_CPU = 16000000
|
||||
ARCH = AVR8
|
||||
TARGET = App
|
||||
SRC = src/main.c src/Descriptors.c $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS)
|
||||
F_USB = $(F_CPU)
|
||||
OPTIMIZATION = s
|
||||
BOARD = USER
|
||||
|
||||
CC_FLAGS = -Isrc -DUSE_LUFA_CONFIG_HEADER -IConfig/ $(CDEFS) -I$(LUFA_PATH)/
|
||||
CC_FLAGS += -std=gnu99 -mmcu=$(MCU) -DF_CPU=$(F_CPU)UL $(CDEFS)
|
||||
CC_FLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
|
||||
CC_FLAGS += -Wall -Wno-main -Wno-strict-prototypes -Wno-comment
|
||||
CC_FLAGS += -g2 -Wextra -Wfatal-errors -Wno-unused-but-set-variable
|
||||
CC_FLAGS += -ffunction-sections -fdata-sections -Os $(LUFA_OPTS)
|
||||
|
||||
LUFA_PATH = src/lufa-LUFA-210130/LUFA
|
||||
LD_FLAGS = -Wl,--gc-sections -Wl,--relax
|
||||
|
||||
|
||||
include $(LUFA_PATH)/Build/lufa_core.mk |
||||
include $(LUFA_PATH)/Build/lufa_sources.mk |
||||
include $(LUFA_PATH)/Build/lufa_build.mk |
||||
#include $(LUFA_PATH)/Build/lufa_cppcheck.mk
|
||||
#include $(LUFA_PATH)/Build/lufa_doxygen.mk
|
||||
#include $(LUFA_PATH)/Build/lufa_dfu.mk
|
||||
#include $(LUFA_PATH)/Build/lufa_hid.mk
|
||||
#include $(LUFA_PATH)/Build/lufa_avrdude.mk
|
||||
#include $(LUFA_PATH)/Build/lufa_atprogram.mk
|
||||
|
||||
PROGRAMMER_TYPE = avr109
|
||||
PROGRAMMER_ARGS = -P /dev/ttyACM0
|
||||
AVRDUDE = avrdude
|
||||
|
||||
.PHONY: eeprom flash flashe shell |
||||
eeprom: $(TARGET).eeprom |
||||
|
||||
%.eeprom: %.elf |
||||
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
|
||||
|
||||
|
||||
flash: $(TARGET).hex |
||||
stty -F /dev/ttyACM0 speed 1200
|
||||
stty -F /dev/ttyACM0 speed 115200
|
||||
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
|
||||
|
||||
flashe: $(TARGET).eeprom |
||||
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
|
||||
|
||||
shell: |
||||
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
|
@ -0,0 +1,164 @@ |
||||
# https://github.com/jkent/caterina-promicro |
||||
|
||||
## === CPU settings === |
||||
MCU = atmega32u4 |
||||
F_CPU = 16000000 |
||||
ARCH = AVR8 |
||||
TARGET = Target |
||||
|
||||
# Input clock frequency. |
||||
# This will define a symbol, F_USB, in all source code files equal to the |
||||
# input clock frequency (before any prescaling is performed) in Hz. This value may |
||||
# differ from F_CPU if prescaling is used on the latter, and is required as the |
||||
# raw input clock is fed directly to the PLL sections of the AVR for high speed |
||||
# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL' |
||||
# at the end, this will be done automatically to create a 32-bit value in your |
||||
# source code. |
||||
# |
||||
# If no clock division is performed on the input clock inside the AVR (via the |
||||
# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU. |
||||
F_USB = $(F_CPU) |
||||
|
||||
|
||||
|
||||
## === Source files === |
||||
# Main C file |
||||
|
||||
APP = app |
||||
SRC_DIR=src |
||||
INC_DIR=src |
||||
OBJ_DIR=obj |
||||
BIN_DIR=bin |
||||
|
||||
|
||||
|
||||
# LUFA library compile-time options and predefined tokens |
||||
LUFA_OPTS = -D USB_DEVICE_ONLY |
||||
LUFA_OPTS += -D DEVICE_STATE_AS_GPIOR=0 |
||||
LUFA_OPTS += -D ORDERED_EP_CONFIG |
||||
LUFA_OPTS += -D FIXED_CONTROL_ENDPOINT_SIZE=8 |
||||
LUFA_OPTS += -D FIXED_NUM_CONFIGURATIONS=1 |
||||
LUFA_OPTS += -D USE_RAM_DESCRIPTORS |
||||
LUFA_OPTS += -D USE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)" |
||||
LUFA_OPTS += -D NO_INTERNAL_SERIAL |
||||
LUFA_OPTS += -D NO_DEVICE_SELF_POWER |
||||
LUFA_OPTS += -D NO_DEVICE_REMOTE_WAKEUP |
||||
LUFA_OPTS += -D NO_SOF_EVENTS |
||||
LUFA_OPTS += -D F_USB=$(F_USB)UL |
||||
|
||||
#LUFA_OPTS += -D NO_BLOCK_SUPPORT |
||||
#LUFA_OPTS += -D NO_EEPROM_BYTE_SUPPORT |
||||
#LUFA_OPTS += -D NO_FLASH_BYTE_SUPPORT |
||||
LUFA_OPTS += -D NO_LOCK_BYTE_WRITE_SUPPORT |
||||
|
||||
LUFA_PATH = src/lufa-LUFA-210130/LUFA |
||||
|
||||
include $(LUFA_PATH)/Build/lufa_core.mk |
||||
include $(LUFA_PATH)/Build/lufa_sources.mk |
||||
include $(LUFA_PATH)/Build/lufa_build.mk |
||||
#include $(LUFA_PATH)/Build/lufa_cppcheck.mk |
||||
#include $(LUFA_PATH)/Build/lufa_doxygen.mk |
||||
#include $(LUFA_PATH)/Build/lufa_dfu.mk |
||||
#include $(LUFA_PATH)/Build/lufa_hid.mk |
||||
#include $(LUFA_PATH)/Build/lufa_avrdude.mk |
||||
#include $(LUFA_PATH)/Build/lufa_atprogram.mk |
||||
|
||||
## === Programmer === |
||||
#PROGRAMMER_TYPE = arduino |
||||
PROGRAMMER_TYPE = avr109 |
||||
PROGRAMMER_ARGS = -P /dev/ttyACM0 |
||||
|
||||
# USB vendor ID (VID) |
||||
# SparkFun |
||||
VID = 0xbeef |
||||
# USB product ID (PID) |
||||
PID = 0x0001 |
||||
|
||||
CDEFS = -DDEVICE_VID=$(VID)UL |
||||
CDEFS += -DDEVICE_PID=$(PID)UL |
||||
|
||||
## === C flags === |
||||
|
||||
INCFLAGS += -I$(INC_DIR) -I$(LUFA_PATH)/ |
||||
|
||||
CFLAGS = -std=gnu99 -mmcu=$(MCU) -DF_CPU=$(F_CPU)UL $(CDEFS) |
||||
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums |
||||
CFLAGS += -Wall -Wno-main -Wno-strict-prototypes -Wno-comment |
||||
CFLAGS += -g2 -Wextra -Wfatal-errors -Wno-unused-but-set-variable |
||||
CFLAGS += -ffunction-sections -fdata-sections -Os $(LUFA_OPTS) |
||||
|
||||
LFLAGS = -Wl,--gc-sections -Wl,--relax |
||||
|
||||
# CFLAGS += -lm ## Math |
||||
# CFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf |
||||
# CFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf |
||||
|
||||
|
||||
# --------------------------------------------------------------------------- |
||||
|
||||
## Defined programs / locations |
||||
CC = avr-gcc |
||||
LD = avr-gcc |
||||
OBJCOPY = avr-objcopy |
||||
OBJDUMP = avr-objdump |
||||
AVRSIZE = avr-size |
||||
AVRDUDE = avrdude |
||||
|
||||
#$(wildcard $(SRC_DIR)/*.c) |
||||
SOURCES=src/main.c src/Descriptors.c $(LUFA_SRC_ALL_FILES) |
||||
OBJECTS=$(SOURCES:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) |
||||
DEPENDS=$(OBJ_DIR)/.depends |
||||
|
||||
TARGET=$(BIN_DIR)/$(APP) |
||||
|
||||
|
||||
.PHONY: all clean eeprom size |
||||
|
||||
|
||||
all: $(TARGET).hex size |
||||
|
||||
debug: |
||||
@echo "SOURCES $(SOURCES)" |
||||
@echo "OBJECTS $(OBJECTS)" |
||||
@echo "TARGET $(TARGET)" |
||||
|
||||
eeprom: $(TARGET).eeprom |
||||
|
||||
size: $(TARGET).elf |
||||
$(AVRSIZE) -C --mcu=$(MCU) $< |
||||
|
||||
$(TARGET).elf: $(OBJECTS) | $(BIN_DIR) |
||||
$(LD) $(CFLAGS) $(LFLGAS) -o $@ $^ |
||||
|
||||
%.hex: %.elf |
||||
$(OBJCOPY) -R .eeprom -O ihex $< $@ |
||||
|
||||
%.eeprom: %.elf |
||||
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@ |
||||
|
||||
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR) |
||||
$(CC) -c $(CFLAGS) $(INCFLAGS) -o $@ $< |
||||
|
||||
$(DEPENDS): $(SOURCES) | $(OBJ_DIR) |
||||
$(CC) $(INCFLAGS) -MM $(SOURCES) | sed -e 's!^!$(OBJ_DIR)/!' >$@ |
||||
|
||||
$(BIN_DIR): |
||||
mkdir -p $@ |
||||
$(OBJ_DIR): |
||||
mkdir -p $@ |
||||
|
||||
clean: |
||||
rm -rf $(BIN_DIR) $(OBJ_DIR) |
||||
|
||||
## === avrdude === |
||||
|
||||
flash: $(TARGET).hex |
||||
stty -F /dev/ttyACM0 speed 1200 |
||||
stty -F /dev/ttyACM0 speed 115200 |
||||
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$< |
||||
|
||||
flashe: $(TARGET).eeprom |
||||
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$< |
||||
|
||||
shell: |
||||
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt |
@ -0,0 +1,251 @@ |
||||
/*
|
||||
LUFA Library |
||||
Copyright (C) Dean Camera, 2011. |
||||
|
||||
dean [at] fourwalledcubicle [dot] com |
||||
www.lufa-lib.org |
||||
*/ |
||||
|
||||
/*
|
||||
Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) |
||||
|
||||
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 |
||||
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 |
||||
software without specific, written prior permission. |
||||
|
||||
The author disclaim all warranties with regard to this |
||||
software, including all implied warranties of merchantability |
||||
and fitness. In no event shall the author be liable for any |
||||
special, indirect or consequential damages or any damages |
||||
whatsoever resulting from loss of use, data or profits, whether |
||||
in an action of contract, negligence or other tortious action, |
||||
arising out of or in connection with the use or performance of |
||||
this software. |
||||
*/ |
||||
|
||||
/** \file
|
||||
* |
||||
* USB Device Descriptors, for library use when in USB device mode. Descriptors are special |
||||
* computer-readable structures which the host requests upon device enumeration, to determine |
||||
* the device's capabilities and functions. |
||||
*/ |
||||
|
||||
#include "Descriptors.h" |
||||
|
||||
/** Device descriptor structure. This descriptor, located in SRAM memory, describes the overall
|
||||
* device characteristics, including the supported USB version, control endpoint size and the |
||||
* number of device configurations. The descriptor is read out by the USB host when the enumeration |
||||
* process begins. |
||||
*/ |
||||
const USB_Descriptor_Device_t DeviceDescriptor = |
||||
{ |
||||
.Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device}, |
||||
|
||||
.USBSpecification = VERSION_BCD(1,1,0), |
||||
.Class = CDC_CSCP_CDCClass, |
||||
.SubClass = CDC_CSCP_NoSpecificSubclass, |
||||
.Protocol = CDC_CSCP_NoSpecificProtocol, |
||||
|
||||
.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE, |
||||
|
||||
.VendorID = DEVICE_VID, |
||||
.ProductID = DEVICE_PID, |
||||
.ReleaseNumber = VERSION_BCD(0,0,1), |
||||
|
||||
.ManufacturerStrIndex = 0x02, |
||||
.ProductStrIndex = 0x01, |
||||
.SerialNumStrIndex = NO_DESCRIPTOR, |
||||
|
||||
.NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS |
||||
}; |
||||
|
||||
/** Configuration descriptor structure. This descriptor, located in SRAM memory, describes the usage
|
||||
* of the device in one of its supported configurations, including information about any device interfaces |
||||
* and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting |
||||
* a configuration so that the host may correctly communicate with the USB device. |
||||
*/ |
||||
const USB_Descriptor_Configuration_t ConfigurationDescriptor = |
||||
{ |
||||
.Config = |
||||
{ |
||||
.Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration}, |
||||
|
||||
.TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t), |
||||
.TotalInterfaces = 2, |
||||
|
||||
.ConfigurationNumber = 1, |
||||
.ConfigurationStrIndex = NO_DESCRIPTOR, |
||||
|
||||
.ConfigAttributes = 0, // USB_CONFIG_ATTR_BUSPOWERED
|
||||
|
||||
.MaxPowerConsumption = USB_CONFIG_POWER_MA(100) |
||||
}, |
||||
|
||||
.CDC_CCI_Interface = |
||||
{ |
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, |
||||
|
||||
.InterfaceNumber = 0, |
||||
.AlternateSetting = 0, |
||||
|
||||
.TotalEndpoints = 1, |
||||
|
||||
.Class = CDC_CSCP_CDCClass, |
||||
.SubClass = CDC_CSCP_ACMSubclass, |
||||
.Protocol = CDC_CSCP_ATCommandProtocol, |
||||
|
||||
.InterfaceStrIndex = NO_DESCRIPTOR |
||||
}, |
||||
|
||||
.CDC_Functional_Header = |
||||
{ |
||||
.Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t), .Type = CDC_DTYPE_CSInterface}, |
||||
.Subtype = 0x00, |
||||
|
||||
.CDCSpecification = VERSION_BCD(1,1,0), |
||||
}, |
||||
|
||||
.CDC_Functional_ACM = |
||||
{ |
||||
.Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type = CDC_DTYPE_CSInterface}, |
||||
.Subtype = 0x02, |
||||
|
||||
.Capabilities = 0x04, |
||||
}, |
||||
|
||||
.CDC_Functional_Union = |
||||
{ |
||||
.Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t), .Type = CDC_DTYPE_CSInterface}, |
||||
.Subtype = 0x06, |
||||
|
||||
.MasterInterfaceNumber = 0, |
||||
.SlaveInterfaceNumber = 1, |
||||
}, |
||||
|
||||
.CDC_NotificationEndpoint = |
||||
{ |
||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, |
||||
|
||||
.EndpointAddress = (ENDPOINT_DIR_IN | CDC_NOTIFICATION_EPNUM), |
||||
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), |
||||
.EndpointSize = CDC_NOTIFICATION_EPSIZE, |
||||
.PollingIntervalMS = 0xFF |
||||
}, |
||||
|
||||
.CDC_DCI_Interface = |
||||
{ |
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface}, |
||||
|
||||
.InterfaceNumber = 1, |
||||
.AlternateSetting = 0, |
||||
|
||||
.TotalEndpoints = 2, |
||||
|
||||
.Class = CDC_CSCP_CDCDataClass, |
||||
.SubClass = CDC_CSCP_NoDataSubclass, |
||||
.Protocol = CDC_CSCP_NoDataProtocol, |
||||
|
||||
.InterfaceStrIndex = NO_DESCRIPTOR |
||||
}, |
||||
|
||||
.CDC_DataOutEndpoint = |
||||
{ |
||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, |
||||
|
||||
.EndpointAddress = (ENDPOINT_DIR_OUT | CDC_RX_EPNUM), |
||||
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), |
||||
.EndpointSize = CDC_TXRX_EPSIZE, |
||||
.PollingIntervalMS = 0x01 |
||||
}, |
||||
|
||||
.CDC_DataInEndpoint = |
||||
{ |
||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint}, |
||||
|
||||
.EndpointAddress = (ENDPOINT_DIR_IN | CDC_TX_EPNUM), |
||||
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA), |
||||
.EndpointSize = CDC_TXRX_EPSIZE, |
||||
.PollingIntervalMS = 0x01 |
||||
} |
||||
}; |
||||
|
||||
/** Language descriptor structure. This descriptor, located in SRAM memory, is returned when the host requests
|
||||
* the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate |
||||
* via the language ID table available at USB.org what languages the device supports for its string descriptors. |
||||
*/ |
||||
const USB_Descriptor_String_t LanguageString = |
||||
{ |
||||
.Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String}, |
||||
|
||||
.UnicodeString = {LANGUAGE_ID_ENG} |
||||
}; |
||||
|
||||
/** Product descriptor string. This is a Unicode string containing the product's details in human readable form,
|
||||
* and is read out upon request by the host when the appropriate string ID is requested, listed in the Device |
||||
* Descriptor. |
||||
*/ |
||||
const USB_Descriptor_String_t ProductString = |
||||
{ |
||||
.Header = {.Size = USB_STRING_LEN(5), .Type = DTYPE_String}, |
||||
.UnicodeString = L"Relay" |
||||
}; |
||||
|
||||
const USB_Descriptor_String_t ManufNameString = |
||||
{ |
||||
.Header = {.Size = USB_STRING_LEN(10), .Type = DTYPE_String}, |
||||
.UnicodeString = L"MightyPork" |
||||
}; |
||||
|
||||
/** This function is called by the library when in device mode, and must be overridden (see LUFA library "USB Descriptors"
|
||||
* documentation) by the application code so that the address and size of a requested descriptor can be given |
||||
* to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function |
||||
* is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the |
||||
* USB host. |
||||
*/ |
||||
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, |
||||
const uint16_t wIndex, |
||||
const void** const DescriptorAddress) |
||||
{ |
||||
const uint8_t DescriptorType = (wValue >> 8); |
||||
const uint8_t DescriptorNumber = (wValue & 0xFF); |
||||
|
||||
const void* Address = NULL; |
||||
uint16_t Size = NO_DESCRIPTOR; |
||||
|
||||
switch (DescriptorType) |
||||
{ |
||||
case DTYPE_Device: |
||||
Address = &DeviceDescriptor; |
||||
Size = sizeof(USB_Descriptor_Device_t); |
||||
break; |
||||
case DTYPE_Configuration: |
||||
Address = &ConfigurationDescriptor; |
||||
Size = sizeof(USB_Descriptor_Configuration_t); |
||||
break; |
||||
case DTYPE_String: |
||||
if (!(DescriptorNumber)) |
||||
{ |
||||
Address = &LanguageString; |
||||
Size = LanguageString.Header.Size; |
||||
} |
||||
else if (DescriptorNumber == DeviceDescriptor.ProductStrIndex) |
||||
{ |
||||
Address = &ProductString; |
||||
Size = ProductString.Header.Size; |
||||
} else if (DescriptorNumber == DeviceDescriptor.ManufacturerStrIndex) |
||||
{ |
||||
Address = &ManufNameString; |
||||
Size = ManufNameString.Header.Size; |
||||
} |
||||
|
||||
break; |
||||
} |
||||
|
||||
*DescriptorAddress = Address; |
||||
return Size; |
||||
} |
@ -0,0 +1,138 @@ |
||||
/*
|
||||
LUFA Library |
||||
Copyright (C) Dean Camera, 2011. |
||||
|
||||
dean [at] fourwalledcubicle [dot] com |
||||
www.lufa-lib.org |
||||
*/ |
||||
|
||||
/*
|
||||
Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) |
||||
|
||||
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 |
||||
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 |
||||
software without specific, written prior permission. |
||||
|
||||
The author disclaim all warranties with regard to this |
||||
software, including all implied warranties of merchantability |
||||
and fitness. In no event shall the author be liable for any |
||||
special, indirect or consequential damages or any damages |
||||
whatsoever resulting from loss of use, data or profits, whether |
||||
in an action of contract, negligence or other tortious action, |
||||
arising out of or in connection with the use or performance of |
||||
this software. |
||||
*/ |
||||
|
||||
/** \file
|
||||
* |
||||
* Header file for Descriptors.c. |
||||
*/ |
||||
|
||||
#ifndef _DESCRIPTORS_H_ |
||||
#define _DESCRIPTORS_H_ |
||||
|
||||
/* Includes: */ |
||||
#include <LUFA/Drivers/USB/USB.h> |
||||
|
||||
/* Macros: */ |
||||
#if defined(__AVR_AT90USB1287__) |
||||
#define AVR_SIGNATURE_1 0x1E |
||||
#define AVR_SIGNATURE_2 0x97 |
||||
#define AVR_SIGNATURE_3 0x82 |
||||
#elif defined(__AVR_AT90USB647__) |
||||
#define AVR_SIGNATURE_1 0x1E |
||||
#define AVR_SIGNATURE_2 0x96 |
||||
#define AVR_SIGNATURE_3 0x82 |
||||
#elif defined(__AVR_AT90USB1286__) |
||||
#define AVR_SIGNATURE_1 0x1E |
||||
#define AVR_SIGNATURE_2 0x97 |
||||
#define AVR_SIGNATURE_3 0x82 |
||||
#elif defined(__AVR_AT90USB646__) |
||||
#define AVR_SIGNATURE_1 0x1E |
||||
#define AVR_SIGNATURE_2 0x96 |
||||
#define AVR_SIGNATURE_3 0x82 |
||||
#elif defined(__AVR_ATmega32U6__) |
||||
#define AVR_SIGNATURE_1 0x1E |
||||
#define AVR_SIGNATURE_2 0x95 |
||||
#define AVR_SIGNATURE_3 0x88 |
||||
#elif defined(__AVR_ATmega32U4__) |
||||
#define AVR_SIGNATURE_1 0x1E |
||||
#define AVR_SIGNATURE_2 0x95 |
||||
#define AVR_SIGNATURE_3 0x87 |
||||
#elif defined(__AVR_ATmega16U4__) |
||||
#define AVR_SIGNATURE_1 0x1E |
||||
#define AVR_SIGNATURE_2 0x94 |
||||
#define AVR_SIGNATURE_3 0x88 |
||||
#elif defined(__AVR_ATmega32U2__) |
||||
#define AVR_SIGNATURE_1 0x1E |
||||
#define AVR_SIGNATURE_2 0x95 |
||||
#define AVR_SIGNATURE_3 0x8A |
||||
#elif defined(__AVR_ATmega16U2__) |
||||
#define AVR_SIGNATURE_1 0x1E |
||||
#define AVR_SIGNATURE_2 0x94 |
||||
#define AVR_SIGNATURE_3 0x89 |
||||
#elif defined(__AVR_AT90USB162__) |
||||
#define AVR_SIGNATURE_1 0x1E |
||||
#define AVR_SIGNATURE_2 0x94 |
||||
#define AVR_SIGNATURE_3 0x82 |
||||
#elif defined(__AVR_ATmega8U2__) |
||||
#define AVR_SIGNATURE_1 0x1E |
||||
#define AVR_SIGNATURE_2 0x93 |
||||
#define AVR_SIGNATURE_3 0x89 |
||||
#elif defined(__AVR_AT90USB82__) |
||||
#define AVR_SIGNATURE_1 0x1E |
||||
#define AVR_SIGNATURE_2 0x94 |
||||
#define AVR_SIGNATURE_3 0x82 |
||||
#else |
||||
#error The selected AVR part is not currently supported by this bootloader. |
||||
#endif |
||||
|
||||
/** Endpoint number for the CDC control interface event notification endpoint. */ |
||||
#define CDC_NOTIFICATION_EPNUM 2 |
||||
|
||||
/** Endpoint number for the CDC data interface TX (data IN) endpoint. */ |
||||
#define CDC_TX_EPNUM 3 |
||||
|
||||
/** Endpoint number for the CDC data interface RX (data OUT) endpoint. */ |
||||
#define CDC_RX_EPNUM 4 |
||||
|
||||
/** Size of the CDC data interface TX and RX data endpoint banks, in bytes. */ |
||||
#define CDC_TXRX_EPSIZE 16 |
||||
|
||||
/** Size of the CDC control interface notification endpoint bank, in bytes. */ |
||||
#define CDC_NOTIFICATION_EPSIZE 8 |
||||
|
||||
/* Type Defines: */ |
||||
/** Type define for the device configuration descriptor structure. This must be defined in the
|
||||
* application code, as the configuration descriptor contains several sub-descriptors which |
||||
* vary between devices, and which describe the device's usage to the host. |
||||
*/ |
||||
typedef struct |
||||
{ |
||||
USB_Descriptor_Configuration_Header_t Config; |
||||
|
||||
// CDC Control Interface
|
||||
USB_Descriptor_Interface_t CDC_CCI_Interface; |
||||
USB_CDC_Descriptor_FunctionalHeader_t CDC_Functional_Header; |
||||
USB_CDC_Descriptor_FunctionalACM_t CDC_Functional_ACM; |
||||
USB_CDC_Descriptor_FunctionalUnion_t CDC_Functional_Union; |
||||
USB_Descriptor_Endpoint_t CDC_NotificationEndpoint; |
||||
|
||||
// CDC Data Interface
|
||||
USB_Descriptor_Interface_t CDC_DCI_Interface; |
||||
USB_Descriptor_Endpoint_t CDC_DataOutEndpoint; |
||||
USB_Descriptor_Endpoint_t CDC_DataInEndpoint; |
||||
} USB_Descriptor_Configuration_t; |
||||
|
||||
/* Function Prototypes: */ |
||||
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, |
||||
const uint16_t wIndex, |
||||
const void** const DescriptorAddress) |
||||
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3); |
||||
|
||||
#endif |
@ -0,0 +1,166 @@ |
||||
/*
|
||||
LUFA Library |
||||
Copyright (C) Dean Camera, 2021. |
||||
|
||||
dean [at] fourwalledcubicle [dot] com |
||||
www.lufa-lib.org |
||||
*/ |
||||
|
||||
/*
|
||||
Copyright 2021 Dean Camera (dean [at] fourwalledcubicle [dot] com) |
||||
|
||||
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 |
||||
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 |
||||
software without specific, written prior permission. |
||||
|
||||
The author disclaims all warranties with regard to this |
||||
software, including all implied warranties of merchantability |
||||
and fitness. In no event shall the author be liable for any |
||||
special, indirect or consequential damages or any damages |
||||
whatsoever resulting from loss of use, data or profits, whether |
||||
in an action of contract, negligence or other tortious action, |
||||
arising out of or in connection with the use or performance of |
||||
this software. |
||||
*/ |
||||
|
||||
/** \file
|
||||
* \brief LUFA Library Configuration Header File (Template) |
||||
* |
||||
* This is a header file which can be used to configure LUFA's |
||||
* compile time options, as an alternative to the compile time |
||||
* constants supplied through a makefile. To use this configuration |
||||
* header, copy this into your project's root directory and supply |
||||
* the \c USE_LUFA_CONFIG_HEADER token to the compiler so that it is |
||||
* defined in all compiled source files. |
||||
* |
||||
* For information on what each token does, refer to the LUFA |
||||
* manual section "Summary of Compile Tokens". |
||||
*/ |
||||
|
||||
#ifndef __LUFA_CONFIG_H__ |
||||
#define __LUFA_CONFIG_H__ |
||||
|
||||
#if (ARCH == ARCH_AVR8) |
||||
|
||||
/* Non-USB Related Configuration Tokens: */ |
||||
// #define DISABLE_TERMINAL_CODES
|
||||
|
||||
/* USB Class Driver Related Tokens: */ |
||||
// #define HID_HOST_BOOT_PROTOCOL_ONLY
|
||||
// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
|
||||
// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
|
||||
// #define HID_MAX_COLLECTIONS {Insert Value Here}
|
||||
// #define HID_MAX_REPORTITEMS {Insert Value Here}
|
||||
// #define HID_MAX_REPORT_IDS {Insert Value Here}
|
||||
// #define NO_CLASS_DRIVER_AUTOFLUSH
|
||||
|
||||
/* General USB Driver Related Tokens: */ |
||||
#define ORDERED_EP_CONFIG |
||||
#define USE_STATIC_OPTIONS (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL) |
||||
#define USB_DEVICE_ONLY |
||||
// #define USB_HOST_ONLY
|
||||
// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
|
||||
// #define NO_LIMITED_CONTROLLER_CONNECT
|
||||
#define NO_SOF_EVENTS |
||||
|
||||
/* USB Device Mode Driver Related Tokens: */ |
||||
#define USE_RAM_DESCRIPTORS |
||||
// #define USE_FLASH_DESCRIPTORS
|
||||
// #define USE_EEPROM_DESCRIPTORS
|
||||
// #define NO_INTERNAL_SERIAL
|
||||
#define FIXED_CONTROL_ENDPOINT_SIZE 8 |
||||
#define DEVICE_STATE_AS_GPIOR 0 |
||||
#define FIXED_NUM_CONFIGURATIONS 1 |
||||
// #define CONTROL_ONLY_DEVICE
|
||||
// #define INTERRUPT_CONTROL_ENDPOINT
|
||||
#define NO_DEVICE_REMOTE_WAKEUP |
||||
#define NO_DEVICE_SELF_POWER |
||||
|
||||
/* USB Host Mode Driver Related Tokens: */ |
||||
// #define HOST_STATE_AS_GPIOR {Insert Value Here}
|
||||
// #define USB_HOST_TIMEOUT_MS {Insert Value Here}
|
||||
// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here}
|
||||
// #define NO_AUTO_VBUS_MANAGEMENT
|
||||
// #define INVERTED_VBUS_ENABLE_LINE
|
||||
|
||||
#elif (ARCH == ARCH_XMEGA) |
||||
|
||||
/* Non-USB Related Configuration Tokens: */ |
||||
// #define DISABLE_TERMINAL_CODES
|
||||
|
||||
/* USB Class Driver Related Tokens: */ |
||||
// #define HID_HOST_BOOT_PROTOCOL_ONLY
|
||||
// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
|
||||
// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
|
||||
// #define HID_MAX_COLLECTIONS {Insert Value Here}
|
||||
// #define HID_MAX_REPORTITEMS {Insert Value Here}
|
||||
// #define HID_MAX_REPORT_IDS {Insert Value Here}
|
||||
// #define NO_CLASS_DRIVER_AUTOFLUSH
|
||||
|
||||
/* General USB Driver Related Tokens: */ |
||||
// #define USE_STATIC_OPTIONS {Insert Value Here}
|
||||
// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
|
||||
// #define NO_LIMITED_CONTROLLER_CONNECT
|
||||
// #define NO_SOF_EVENTS
|
||||
|
||||
/* USB Device Mode Driver Related Tokens: */ |
||||
// #define USE_RAM_DESCRIPTORS
|
||||
// #define USE_FLASH_DESCRIPTORS
|
||||
// #define USE_EEPROM_DESCRIPTORS
|
||||
// #define NO_INTERNAL_SERIAL
|
||||
// #define FIXED_CONTROL_ENDPOINT_SIZE {Insert Value Here}
|
||||
// #define DEVICE_STATE_AS_GPIOR {Insert Value Here}
|
||||
// #define FIXED_NUM_CONFIGURATIONS {Insert Value Here}
|
||||
// #define CONTROL_ONLY_DEVICE
|
||||
// #define MAX_ENDPOINT_INDEX {Insert Value Here}
|
||||
// #define NO_DEVICE_REMOTE_WAKEUP
|
||||
// #define NO_DEVICE_SELF_POWER
|
||||
|
||||
#elif (ARCH == ARCH_UC3) |
||||
|
||||
/* Non-USB Related Configuration Tokens: */ |
||||
// #define DISABLE_TERMINAL_CODES
|
||||
|
||||
/* USB Class Driver Related Tokens: */ |
||||
// #define HID_HOST_BOOT_PROTOCOL_ONLY
|
||||
// #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
|
||||
// #define HID_USAGE_STACK_DEPTH {Insert Value Here}
|
||||
// #define HID_MAX_COLLECTIONS {Insert Value Here}
|
||||
// #define HID_MAX_REPORTITEMS {Insert Value Here}
|
||||
// #define HID_MAX_REPORT_IDS {Insert Value Here}
|
||||
// #define NO_CLASS_DRIVER_AUTOFLUSH
|
||||
|
||||
/* General USB Driver Related Tokens: */ |
||||
// #define ORDERED_EP_CONFIG
|
||||
// #define USE_STATIC_OPTIONS {Insert Value Here}
|
||||
// #define USB_DEVICE_ONLY
|
||||
// #define USB_HOST_ONLY
|
||||
// #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
|
||||
// #define NO_SOF_EVENTS
|
||||
|
||||
/* USB Device Mode Driver Related Tokens: */ |
||||
// #define NO_INTERNAL_SERIAL
|
||||
// #define FIXED_CONTROL_ENDPOINT_SIZE {Insert Value Here}
|
||||
// #define FIXED_NUM_CONFIGURATIONS {Insert Value Here}
|
||||
// #define CONTROL_ONLY_DEVICE
|
||||
// #define INTERRUPT_CONTROL_ENDPOINT
|
||||
// #define NO_DEVICE_REMOTE_WAKEUP
|
||||
// #define NO_DEVICE_SELF_POWER
|
||||
|
||||
/* USB Host Mode Driver Related Tokens: */ |
||||
// #define USB_HOST_TIMEOUT_MS {Insert Value Here}
|
||||
// #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here}
|
||||
// #define NO_AUTO_VBUS_MANAGEMENT
|
||||
// #define INVERTED_VBUS_ENABLE_LINE
|
||||
|
||||
#else |
||||
|
||||
#error Unsupported architecture for this LUFA configuration file. |
||||
|
||||
#endif |
||||
#endif |
@ -0,0 +1,242 @@ |
||||
#include <util/delay.h> |
||||
#include <avr/io.h> |
||||
|
||||
|
||||
#include <LUFA/Drivers/USB/USB.h> |
||||
|
||||
|
||||
#include "Descriptors.h" |
||||
|
||||
#define LED_SETUP() DDRB |= (1<<0); DDRD |= (1<<5); |
||||
#define L_LED_OFF() PORTD |= (1<<5) |
||||
#define L_LED_ON() PORTD &= ~(1<<5) |
||||
#define L_LED_TOGGLE() PORTD ^= (1<<5) |
||||
#define DATA_LED_OFF() PORTB |= (1<<0) |
||||
#define DATA_LED_ON() PORTB &= ~(1<<0) |
||||
|
||||
|
||||
|
||||
/** Endpoint address for the CDC control interface event notification endpoint. */ |
||||
#define CDC_NOTIFICATION_EPADDR (ENDPOINT_DIR_IN | CDC_NOTIFICATION_EPNUM) |
||||
|
||||
/** Endpoint address for the CDC data interface TX (data IN) endpoint. */ |
||||
#define CDC_TX_EPADDR (ENDPOINT_DIR_IN | CDC_TX_EPNUM) |
||||
|
||||
/** Endpoint address for the CDC data interface RX (data OUT) endpoint. */ |
||||
#define CDC_RX_EPADDR (ENDPOINT_DIR_OUT | CDC_RX_EPNUM) |
||||
|
||||
|
||||
/** Retrieves the next byte from the host in the CDC data OUT endpoint, and clears the endpoint bank if needed
|
||||
* to allow reception of the next data packet from the host. |
||||
* |
||||
* \return Next received byte from the host in the CDC data OUT endpoint |
||||
*/ |
||||
static uint8_t FetchNextCommandByte(void) |
||||
{ |
||||
/* Select the OUT endpoint so that the next data byte can be read */ |
||||
Endpoint_SelectEndpoint(CDC_RX_EPADDR); |
||||
|
||||
/* If OUT endpoint empty, clear it and wait for the next packet from the host */ |
||||
while (!(Endpoint_IsReadWriteAllowed())) |
||||
{ |
||||
Endpoint_ClearOUT(); |
||||
|
||||
while (!(Endpoint_IsOUTReceived())) |
||||
{ |
||||
if (USB_DeviceState == DEVICE_STATE_Unattached) |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
/* Fetch the next byte from the OUT endpoint */ |
||||
return Endpoint_Read_8(); |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
/** Writes the next response byte to the CDC data IN endpoint, and sends the endpoint back if needed to free up the
|
||||
* bank when full ready for the next byte in the packet to the host. |
||||
* |
||||
* \param[in] Response Next response byte to send to the host |
||||
*/ |
||||
static void WriteNextResponseByte(const uint8_t Response) |
||||
{ |
||||
/* Select the IN endpoint so that the next data byte can be written */ |
||||
Endpoint_SelectEndpoint(CDC_TX_EPADDR); |
||||
|
||||
/* 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 IN endpoint */ |
||||
Endpoint_Write_8(Response); |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void CDC_Task(void); |
||||
|
||||
/* Pulse generation counters to keep track of the time remaining for each pulse type */ |
||||
#define DATA_LED_PULSE_PERIOD 100 |
||||
uint16_t DataLEDPulse = 0; // time remaining for Data LED pulse
|
||||
|
||||
uint16_t LLEDPulse; |
||||
void LEDPulse(void) |
||||
{ |
||||
LLEDPulse++; |
||||
uint8_t p = LLEDPulse >> 8; |
||||
if (p > 127) |
||||
p = 254-p; |
||||
p += p; |
||||
if (((uint8_t)LLEDPulse) > p) |
||||
L_LED_OFF(); |
||||
else |
||||
L_LED_ON(); |
||||
} |
||||
|
||||
|
||||
|
||||
void main () { |
||||
LED_SETUP(); |
||||
|
||||
/* Initialize USB Subsystem */ |
||||
USB_Init(); |
||||
|
||||
/* Enable global interrupts so that the USB stack can function */ |
||||
sei(); |
||||
|
||||
for(;;) { |
||||
CDC_Task(); |
||||
USB_USBTask(); |
||||
LEDPulse(); |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
/*
|
||||
* some parts of this code are from LUFA. |
||||
* |
||||
* |
||||
Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) |
||||
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 |
||||
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 |
||||
software without specific, written prior permission. |
||||
The author disclaim all warranties with regard to this |
||||
software, including all implied warranties of merchantability |
||||
and fitness. In no event shall the author be liable for any |
||||
special, indirect or consequential damages or any damages |
||||
whatsoever resulting from loss of use, data or profits, whether |
||||
in an action of contract, negligence or other tortious action, |
||||
arising out of or in connection with the use or performance of |
||||
this software. |
||||
*/ |
||||
|
||||
// /*
|
||||
//
|
||||
// /** Retrieves the next byte from the host in the CDC data OUT endpoint, and clears the endpoint bank if needed
|
||||
// * to allow reception of the next data packet from the host.
|
||||
// *
|
||||
// * \return Next received byte from the host in the CDC data OUT endpoint
|
||||
// */
|
||||
// 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()))
|
||||
// {
|
||||
// Endpoint_ClearOUT();
|
||||
//
|
||||
// while (!(Endpoint_IsOUTReceived()))
|
||||
// {
|
||||
// if (USB_DeviceState == DEVICE_STATE_Unattached)
|
||||
// return 0;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /* Fetch the next byte from the OUT endpoint */
|
||||
// return Endpoint_Read_8();
|
||||
// }
|
||||
// */
|
||||
|
||||
|
||||
/** Task to read in AVR910 commands from the CDC data OUT endpoint, process them, perform the required actions
|
||||
* and send the appropriate response back to the host. |
||||
*/ |
||||
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())) |
||||
return; |
||||
|
||||
DATA_LED_ON(); |
||||
DataLEDPulse = DATA_LED_PULSE_PERIOD; |
||||
|
||||
/* Read in the bootloader command (first byte sent from host) */ |
||||
uint8_t Command = FetchNextCommandByte(); |
||||
|
||||
// COMMAND PROCESSING
|
||||
if (Command == 'a') |
||||
{ |
||||
WriteNextResponseByte('b'); |
||||
WriteNextResponseByte('\r'); |
||||
WriteNextResponseByte('\n'); |
||||
} |
||||
|
||||
|
||||
/* Select the IN endpoint */ |
||||
Endpoint_SelectEndpoint(CDC_TX_EPNUM); |
||||
|
||||
/* Remember if the endpoint is completely full before clearing it */ |
||||
bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed()); |
||||
|
||||
/* 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; |
||||
} |
||||
|
||||
Endpoint_ClearIN(); |
||||
} |
||||
|
||||
/* 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); |
||||
|
||||
/* Acknowledge the command from the host */ |
||||
Endpoint_ClearOUT(); |
||||
} |
Loading…
Reference in new issue