Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Erik Strand
lufa
Commits
a7aaa45e
Commit
a7aaa45e
authored
Feb 24, 2010
by
Dean Camera
Browse files
More AVR32 achitecture ports.
parent
3702ba1f
Changes
11
Hide whitespace changes
Inline
Side-by-side
LUFA/Drivers/Peripheral/AVR32/SPI.h
View file @
a7aaa45e
...
...
@@ -72,6 +72,12 @@
/** SPI prescaler mask for SPI_Init(). Divides the system clock by a factor of 32. */
#define SPI_SPEED_FCPU_DIV_32 AVR32_SPI_MR_FDIV_MASK
/** SPI chip selection mode for direct peripheral-to-CS pin connections. */
#define SPI_CS_4BITDECODER AVR32_SPI_MR_PSDEC_MASK
/** SPI chip selection mode for peripheral CS pin connections through a 4-bit decoder. */
#define SPI_CS_DIRECT 0
/** SPI mode mask for SPI_Init(). Indicates that the SPI interface should be initialized into slave mode. */
#define SPI_MODE_SLAVE 0
...
...
@@ -89,12 +95,15 @@
* configure these seperately to connect the SPI module to the desired GPIO pins via the
* GPIO MUX registers.
*
* \param[in] SPIOptions SPI Options, a mask consisting of one of each of the SPI_SPEED_*
* and SPI_MODE_* masks
* \param[in] SPIOptions SPI Options, a mask consisting of one of each of the SPI_SPEED_*
,
*
SPI_CS_*
and SPI_MODE_* masks
*/
static
inline
void
SPI_Init
(
const
uintN_t
SPIOptions
)
{
AVR32_SPI
.
cr
=
(
AVR32_SPI_CR_SPIEN_MASK
|
AVR32_SPI_CR_SWRST_MASK
);
AVR32_PM
.
pbamask
=
(
1
<<
5
);
AVR32_SPI
.
CR
.
swrst
=
true
;
AVR32_SPI
.
CR
.
spien
=
true
;
AVR32_SPI
.
mr
=
SPIOptions
;
}
...
...
@@ -102,6 +111,8 @@
static
inline
void
SPI_ShutDown
(
void
)
{
AVR32_SPI
.
cr
=
AVR32_SPI_CR_SPIDIS_MASK
;
AVR32_PM
.
pbamask
&=
~
(
1
<<
5
);
}
/** Sends and receives a transfer through the SPI interface, blocking until the transfer is complete.
...
...
@@ -115,9 +126,12 @@
static
inline
uint16_t
SPI_Transfer
(
const
uint16_t
Data
)
ATTR_ALWAYS_INLINE
;
static
inline
uint16_t
SPI_Transfer
(
const
uint16_t
Data
)
{
AVR32_SPI
.
TDR
.
td
=
Data
;
while
(
!
(
AVR32_SPI
.
SR
.
tdre
));
return
AVR32_SPI
.
rdr
;
AVR32_SPI
.
TDR
.
td
=
Data
;
while
((
AVR32_SPI
.
sr
&
(
AVR32_SPI_SR_RDRF_MASK
|
AVR32_SPI_SR_TXEMPTY_MASK
))
!=
(
AVR32_SPI_SR_RDRF_MASK
|
AVR32_SPI_SR_TXEMPTY_MASK
));
return
AVR32_SPI
.
RDR
.
rd
;
}
/** Sends a transfer through the SPI interface, blocking until the transfer is complete. The response
...
...
@@ -129,8 +143,8 @@
static
inline
void
SPI_Send
(
const
uint16_t
Data
)
ATTR_ALWAYS_INLINE
;
static
inline
void
SPI_Send
(
const
uint16_t
Data
)
{
AVR32_SPI
.
TDR
.
td
=
Data
;
while
(
!
(
AVR32_SPI
.
SR
.
tdre
));
AVR32_SPI
.
TDR
.
td
=
Data
;
}
/** Sends a dummy transfer through the SPI interface, blocking until the transfer is complete. The response
...
...
@@ -142,8 +156,11 @@
static
inline
uint16_t
SPI_Receive
(
void
)
ATTR_ALWAYS_INLINE
ATTR_WARN_UNUSED_RESULT
;
static
inline
uint16_t
SPI_Receive
(
void
)
{
AVR32_SPI
.
TDR
.
td
=
0x0000
;
while
(
!
(
AVR32_SPI
.
SR
.
tdre
));
AVR32_SPI
.
TDR
.
td
=
0x0000
;
while
((
AVR32_SPI
.
sr
&
(
AVR32_SPI_SR_RDRF_MASK
|
AVR32_SPI_SR_TXEMPTY_MASK
))
!=
(
AVR32_SPI_SR_RDRF_MASK
|
AVR32_SPI_SR_TXEMPTY_MASK
));
return
AVR32_SPI
.
RDR
.
rd
;
}
...
...
LUFA/Drivers/USB/Class/Device/RNDIS.c
View file @
a7aaa45e
...
...
@@ -345,7 +345,11 @@ static bool RNDIS_Device_ProcessNDISQuery(USB_ClassInfo_RNDIS_Device_t* const RN
case
OID_GEN_SUPPORTED_LIST
:
*
ResponseSize
=
sizeof
(
AdapterSupportedOIDList
);
memcpy_P
(
ResponseData
,
AdapterSupportedOIDList
,
sizeof
(
AdapterSupportedOIDList
));
#if defined(__AVR32__)
memcpy
(
ResponseData
,
AdapterSupportedOIDList
,
sizeof
(
AdapterSupportedOIDList
));
#elif defined(__AVR__)
memcpy_P
(
ResponseData
,
AdapterSupportedOIDList
,
sizeof
(
AdapterSupportedOIDList
));
#endif
return
true
;
case
OID_GEN_PHYSICAL_MEDIUM
:
...
...
LUFA/Drivers/USB/HighLevel/USBInterrupt.c
View file @
a7aaa45e
...
...
@@ -51,17 +51,24 @@ void USB_INT_DisableAllInterrupts(void)
void
USB_INT_ClearAllInterrupts
(
void
)
{
#if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
USBINT
=
0
;
#endif
#if defined(USB_CAN_BE_HOST)
UHINT
=
0
;
OTGINT
=
0
;
#endif
#if defined(USB_CAN_BE_DEVICE)
UDINT
=
0
;
#if defined(__AVR32__)
AVR32_USBB
.
USBSTACLR
=
0xFFFFFF
;
AVR32_USBB
.
UHINTCLR
=
0xFFFFFF
;
AVR32_USBB
.
UECONX
=
AVR32_USBB
.
UDINTCLR
=
0xFFFFFF
;
#elif defined(__AVR__)
#if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
USBINT
=
0
;
#endif
#if defined(USB_CAN_BE_HOST)
UHINT
=
0
;
OTGINT
=
0
;
#endif
#if defined(USB_CAN_BE_DEVICE)
UDINT
=
0
;
#endif
#endif
}
...
...
LUFA/Drivers/USB/HighLevel/USBInterrupt.h
View file @
a7aaa45e
...
...
@@ -62,17 +62,19 @@
#if defined(__AVR32__)
#define USB_INT_Enable(int) MACROS{ USB_INT_GET_EN_REG(int) |= USB_INT_GET_EN_MASK(int); }MACROE
#define USB_INT_Disable(int) MACROS{ USB_INT_GET_EN_REG(int) &= ~(USB_INT_GET_EN_MASK(int)); }MACROE
#define USB_INT_Clear(int) MACROS{ USB_INT_GET_INT_REG(int)
## CLR
|= USB_INT_GET_INT_MASK(int)
## C
; }MACROE
#define USB_INT_Clear(int) MACROS{ USB_INT_GET_INT
C
_REG(int) |=
USB_INT_GET_INT
C
_MASK(int); }MACROE
#define USB_INT_IsEnabled(int) ((USB_INT_GET_EN_REG(int) & USB_INT_GET_EN_MASK(int)) ? true : false)
#define USB_INT_HasOccurred(int) ((USB_INT_GET_INT_REG(int) & USB_INT_GET_INT_MASK(int)) ? true : false)
#define USB_INT_GET_EN_REG(a, b, c, d) *((volatile uint32_t*)AVR32_USBB_ ## a)
#define USB_INT_GET_EN_REG(a, b, c, d) *(
(volatile uint32_t*)AVR32_USBB_ ## a
)
#define USB_INT_GET_EN_MASK(a, b, c, d) AVR32_USBB_ ## b
#define USB_INT_GET_INT_REG(a, b, c, d) *((volatile uint32_t*)AVR32_USBB_ ## c)
#define USB_INT_GET_INT_REG(a, b, c, d) *(
(volatile uint32_t*)AVR32_USBB_ ## c
)
#define USB_INT_GET_INT_MASK(a, b, c, d) AVR32_USBB_ ## d
#define USB_INT_GET_INTC_REG(a, b, c, d) *( (volatile uint32_t*)AVR32_USBB_ ## c ## CLR )
#define USB_INT_GET_INTC_MASK(a, b, c, d) AVR32_USBB_ ## d ## C
#define USB_INT_VBUS USBCON, USBCON_VBUSTE_MASK, USBSTA, USBSTA_VBUSTI_MASK
#define USB_INT_IDTI USBCON, USBCON_IDTE_MASK , USB
INT
, USBCON_IDTI_MASK
#define USB_INT_IDTI USBCON, USBCON_IDTE_MASK , USB
STA
, USBCON_IDTI_MASK
#define USB_INT_WAKEUP UDIEN , UDIEN_WAKEUPE_MASK, UDINT , UDIEN_WAKEUPI_MASK
#define USB_INT_SUSPEND UDIEN , UDIEN_SUSPE_MASK , UDINT , UDIEN_SUSPI_MASK
#define USB_INT_EORSTI UDIEN , UDIEN_EORSTE_MASK , UDINT , UDIEN_EORSTI_MASK
...
...
@@ -81,10 +83,10 @@
#define USB_INT_DDISCI UHIEN , UDIEN_DDISCE_MASK , UHINT , UHIEN_DDISCI_MASK
#define USB_INT_HSOFI UHIEN, UHIEN_HSOFE_MASK , UHINT , UHIEN_HSOFI_MASK
#define USB_INT_RSTI UHIEN , UHIEN_RSTE_MASK , UHINT , UHIEN_RSTI_MASK
#define USB_INT_RXSTPI UE
IE
NX, UE
IE
NX_RXSTPE_MASK, UE
INT
X, UE
IEN
X_RXSTPI_MASK
#define USB_INT_BCERRI
OTGIEN, OTGIE
N_BCERRE_MASK,
OTGINT, OTGIEN
_BCERRI_MASK
#define USB_INT_VBERRI
OTGIEN, OTGIE
N_VBERRE_MASK,
OTGINT, OTGIEN
_VBERRI_MASK
#define USB_INT_SRPI
OTGIEN, OTGIE
N_SRPE_MASK ,
OTGINT, OTGIEN
_SRPI_MASK
#define USB_INT_RXSTPI UE
CO
NX, UE
CO
NX_RXSTPE_MASK, UE
STA
X, UE
STA
X_RXSTPI_MASK
#define USB_INT_BCERRI
USBCON, USBCO
N_BCERRE_MASK,
USBSTA, USBSTA
_BCERRI_MASK
#define USB_INT_VBERRI
USBCON, USBCO
N_VBERRE_MASK,
USBSTA, USBSTA
_VBERRI_MASK
#define USB_INT_SRPI
USBCON, USBCO
N_SRPE_MASK ,
USBSTA, USBSTA
_SRPI_MASK
#elif defined(__AVR__)
#define USB_INT_Enable(int) MACROS{ USB_INT_GET_EN_REG(int) |= USB_INT_GET_EN_MASK(int); }MACROE
#define USB_INT_Disable(int) MACROS{ USB_INT_GET_EN_REG(int) &= ~(USB_INT_GET_EN_MASK(int)); }MACROE
...
...
LUFA/Drivers/USB/HighLevel/USBTask.h
View file @
a7aaa45e
...
...
@@ -87,7 +87,7 @@
extern
USB_Request_Header_t
USB_ControlRequest
;
#if defined(USB_CAN_BE_HOST) || defined(__DOXYGEN__)
#if (!defined(__AVR32__)
&&
!defined(HOST_STATE_AS_GPIOR)) || defined(__DOXYGEN__)
#if (!defined(__AVR32__)
||
!defined(HOST_STATE_AS_GPIOR)) || defined(__DOXYGEN__)
/** Indicates the current host state machine state. When in host mode, this indicates the state
* via one of the values of the \ref USB_Host_States_t enum values.
*
...
...
@@ -116,7 +116,7 @@
#endif
#if defined(USB_CAN_BE_DEVICE) || defined(__DOXYGEN__)
#if (
!
defined(__AVR32__)
&&
!defined(DEVICE_STATE_AS_GPIOR)) || defined(__DOXYGEN__)
#if (defined(__AVR32__)
||
!defined(DEVICE_STATE_AS_GPIOR)) || defined(__DOXYGEN__)
/** Indicates the current device state machine state. When in device mode, this indicates the state
* via one of the values of the \ref USB_Device_States_t enum values.
*
...
...
LUFA/Drivers/USB/LowLevel/Device.h
View file @
a7aaa45e
...
...
@@ -223,7 +223,7 @@
#define USB_Device_SetLowSpeed() MACROS{ AVR32_USBB.UDCON.ls = true; }MACROE
#define USB_Device_SetFullSpeed() MACROS{ AVR32_USBB.UDCON.ls = false; }MACROE
#define USB_Device_SetDeviceAddress(addr) MACROS{ AVR32_USBB.UD
ADDR = (
AVR32_USBB
_
UDCON
_ADDEN_MASK | DeviceAddress)
; }MACROE
#define USB_Device_SetDeviceAddress(addr) MACROS{ AVR32_USBB.UD
CON.uadd = DeviceAddress;
AVR32_USBB
.
UDCON
.adden = true
; }MACROE
#elif defined(__AVR__)
#define USB_Device_SetLowSpeed() MACROS{ UDCON |= (1 << LSM); }MACROE
#define USB_Device_SetFullSpeed() MACROS{ UDCON &= ~(1 << LSM); }MACROE
...
...
LUFA/Drivers/USB/LowLevel/Endpoint.h
View file @
a7aaa45e
...
...
@@ -95,6 +95,10 @@
#error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
#endif
#if defined(__AVR32__) && !defined(__AVR32_EPREG_X)
#define __AVR32_EPREG_X(x) ((volatile uint32_t*)AVR32_USBB_ ## x)[USB_SelectedEPNumber]
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
#if defined(__AVR32__) || defined(__DOXYGEN__)
...
...
@@ -377,17 +381,17 @@
#if !defined(CONTROL_ONLY_DEVICE)
#define Endpoint_GetCurrentEndpoint() USB_SelectedEPNumber
#define Endpoint_SelectEndpoint(epnum) MACROS{ USB_SelectedEPNumber = (epnum); }MACROE
#define Endpoint_IsReadWriteAllowed() (__AVR32_EPREG_X(UESTA0) & AVR32_USBB_RWAL_MASK)
#define Endpoint_IsReadWriteAllowed() (__AVR32_EPREG_X(UESTA0) & AVR32_USBB_RWAL
L
_MASK)
#else
#define Endpoint_GetCurrentEndpoint() ENDPOINT_CONTROLEP
#define Endpoint_SelectEndpoint(epnum) (void)(epnum)
#endif
#define Endpoint_ResetFIFO(epnum) MACROS{ AVR32_USBB.
UERST
|= (AVR32_USBB_EPRST0_MASK << (epnum)); \
AVR32_USBB
.
UERST
&=
~
(
AVR32_USBB_EPRST0_MASK
<<
(
epnum
));
}
MACROE
#define Endpoint_EnableEndpoint() MACROS{ AVR32_USBB.
UERST
|= (AVR32_USBB_UERST_EPEN0_MASK <<
(epen)
); }MACROE
#define Endpoint_DisableEndpoint() MACROS{ AVR32_USBB.
UERST
&= ~(AVR32_USBB_UERST_EPEN0_MASK <<
(epen)
); }MACROE
#define Endpoint_IsEnabled() ((AVR32_USBB.
UERST
& (AVR32_USBB_UERST_EPEN0_MASK <<
(epen)
)) ? true : false)
#define Endpoint_ResetFIFO(epnum) MACROS{ AVR32_USBB.
uerst
|= (AVR32_USBB_EPRST0_MASK << (epnum)); \
AVR32_USBB
.
uerst
&=
~
(
AVR32_USBB_EPRST0_MASK
<<
(
epnum
));
}
MACROE
#define Endpoint_EnableEndpoint() MACROS{ AVR32_USBB.
uerst
|= (AVR32_USBB_UERST_EPEN0_MASK <<
USB_SelectedEPNumber
); }MACROE
#define Endpoint_DisableEndpoint() MACROS{ AVR32_USBB.
uerst
&= ~(AVR32_USBB_UERST_EPEN0_MASK <<
USB_SelectedEPNumber
); }MACROE
#define Endpoint_IsEnabled() ((AVR32_USBB.
uerst
& (AVR32_USBB_UERST_EPEN0_MASK <<
USB_SelectedEPNumber
)) ? true : false)
#define Endpoint_IsConfigured() ((__AVR32_EPREG_X(UESTA0) & AVR32_USBB_UESTA0_CFGOK_MASK) ? true : false)
#define Endpoint_GetEndpointInterrupts() (AVR32_USBB.UDINT >> AVR32_USBB_EP0INT)
...
...
LUFA/Drivers/USB/LowLevel/LowLevel.h
View file @
a7aaa45e
...
...
@@ -88,39 +88,43 @@
#if !defined(__INCLUDE_FROM_USB_DRIVER)
#error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
#endif
#if !defined(F_CLOCK)
#error F_CLOCK is not defined. You must define F_CLOCK to the frequency of the unprescaled input clock in your project makefile.
#endif
#if (F_CLOCK == 8000000)
#if (defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || \
defined
(
__AVR_ATmega8U2__
)
||
defined
(
__AVR_ATmega16U2__
)
||
\
defined
(
__AVR_ATmega32U2__
))
#define USB_PLL_PSC 0
#elif (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
#define USB_PLL_PSC 0
#elif (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) || defined(__AVR_ATmega32U6__))
#define USB_PLL_PSC ((1 << PLLP1) | (1 << PLLP0))
#elif (defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1287__))
#define USB_PLL_PSC ((1 << PLLP1) | (1 << PLLP0))
#endif
#elif (F_CLOCK == 16000000)
#if (defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || \
defined
(
__AVR_ATmega8U2__
)
||
defined
(
__AVR_ATmega16U2__
)
||
\
defined
(
__AVR_ATmega32U2__
))
#define USB_PLL_PSC (1 << PLLP0)
#elif (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
#define USB_PLL_PSC (1 << PINDIV)
#elif (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_ATmega32U6__))
#define USB_PLL_PSC ((1 << PLLP2) | (1 << PLLP1))
#elif (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__))
#define USB_PLL_PSC ((1 << PLLP2) | (1 << PLLP0))
#if defined(__AVR32__)
#define USB_PLL_PSC 0
#elif defined(__AVR__)
#if !defined(F_CLOCK)
#error F_CLOCK is not defined. You must define F_CLOCK to the frequency of the unprescaled input clock in your project makefile.
#endif
#endif
#if !defined(USB_PLL_PSC)
#error No PLL prescale value available for chosen F_CPU value and AVR model.
#if (F_CLOCK == 8000000)
#if (defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || \
defined
(
__AVR_ATmega8U2__
)
||
defined
(
__AVR_ATmega16U2__
)
||
\
defined
(
__AVR_ATmega32U2__
))
#define USB_PLL_PSC 0
#elif (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
#define USB_PLL_PSC 0
#elif (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) || defined(__AVR_ATmega32U6__))
#define USB_PLL_PSC ((1 << PLLP1) | (1 << PLLP0))
#elif (defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1287__))
#define USB_PLL_PSC ((1 << PLLP1) | (1 << PLLP0))
#endif
#elif (F_CLOCK == 16000000)
#if (defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || \
defined
(
__AVR_ATmega8U2__
)
||
defined
(
__AVR_ATmega16U2__
)
||
\
defined
(
__AVR_ATmega32U2__
))
#define USB_PLL_PSC (1 << PLLP0)
#elif (defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__))
#define USB_PLL_PSC (1 << PINDIV)
#elif (defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_ATmega32U6__))
#define USB_PLL_PSC ((1 << PLLP2) | (1 << PLLP1))
#elif (defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__))
#define USB_PLL_PSC ((1 << PLLP2) | (1 << PLLP0))
#endif
#endif
#if !defined(USB_PLL_PSC)
#error No PLL prescale value available for chosen F_CLOCK value and AVR model.
#endif
#endif
/* Public Interface - May be used in end-application: */
...
...
@@ -147,7 +151,7 @@
*
* \note This token is not available on AVR models which do not support both host and device modes.
*/
#define USB_MODE_UID
3
#define USB_MODE_UID 3
#endif
/** Regulator disable option mask for \ref USB_Init(). This indicates that the internal 3.3V USB data pad
...
...
@@ -206,7 +210,7 @@
*
* \note This token is not available on some AVR models which do not support hardware VBUS monitoring.
*/
#define USB_VBUS_GetStatus()
((USBSTA & (1 << VBUS)) ? true : false)
#define USB_VBUS_GetStatus() ((USBSTA & (1 << VBUS)) ? true : false)
#endif
/** Detaches the device from the USB bus. This has the effect of removing the device from any
...
...
LUFA/Drivers/USB/LowLevel/Pipe.h
View file @
a7aaa45e
...
...
@@ -103,6 +103,10 @@
#error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
#endif
#if defined(__AVR32__) && !defined(__AVR32_EPREG_X)
#define __AVR32_EPREG_X(x) ((volatile uint32_t*)AVR32_USBB_ ## x)[USB_SelectedEPNumber]
#endif
/* Public Interface - May be used in end-application: */
/* Macros: */
/** Mask for \ref Pipe_GetErrorFlags(), indicating that an overflow error occurred in the pipe on the received data. */
...
...
LUFA/Drivers/USB/USB.h
View file @
a7aaa45e
...
...
@@ -355,10 +355,6 @@
#define __INCLUDE_FROM_USB_DRIVER
#endif
#if defined(__AVR32__)
#define __AVR32_EPREG_X(x) ((volatile uint32_t*)AVR32_USBB_ ## x)[USB_SelectedEPNumber]
#endif
/* Includes: */
#include
"HighLevel/USBMode.h"
...
...
LUFA/ManPages/VIDAndPIDValues.txt
View file @
a7aaa45e
...
...
@@ -277,7 +277,7 @@
* 0x2064
* </td>
* <td>
*
<i>Currently Unallocated</i>
*
Interfaceless Control-Only LUFA Devices
* </td>
* </tr>
*
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment