COM Configurations for automotive embedded application

Date: July 13, 2020

Author: Ninad Gajanan Naik

As complexity of the automotive embedded systems grew, there was a rising demand for an open industry standardized software architecture for development of automotive electronic control units. In a bid to address this concern a partnership between world leaders in automotive domains ensued, which resulted in the formation of AUTOSAR, which stands for Automotive Open Systems Architecture.

Figure 1. Autosar Layered Architecture

Autosar Layered Architecture

AUTOSAR architecture consists of three layers as seen in figure 1. Let us see about each layer in brief.

Basic Software Layer

This is the bottom most layer in the AUTOSAR architecture and directly interacts with the underlying hardware module and provides hardware abstraction for the upper layers.  This layer provides standardized architecture in order to implement memory stack, diagnostics services, operation system and communication stack which we will see further.

Runtime Environment Layer

RTE acts as a common interface between Application layer and BSW layer to provide means of interaction between them. It facilitates information exchange between application software components and basic software and applications.

Application Layer

This is the final layer of AUTOSAR architecture and contains application Software Components (SWC). These are completely hardware independent.

AUTOSAR Communication (COM) Stack

Figure 2. Components of AUTOSAR Layers

As seen in figure2 COM stack or Communication stack of AUTOSAR consists of Communication services, Communication Hardware Abstraction and Communication driver present in the BSW layer. Moving further, let us see different components present in each layer of COM stack.

Figure 3. Components of AUTOSAR COM stack


Autosar COM is a service layer module lying in between RTE and the PDU Router. It is used to transfer signals to and from the RTE layer.

It packs the signals to a PDU at the transmitter and unpacks received PDU to provide signal level access to the application at the receiver. Thus, signal level or PDU level communication is possible irrespective of the underlying protocol. In this module we also configure the cycle time, offset, repetition period ( for Event frame ) at PDU level. It is also used for grouping of PDUs.

PDU Router

The job of a PDU router is to provide routing paths to the I-PDUs within the communication stack. It routes the receiving I-PDUs to the upper COM module or to diagnostic services or the error detection module. For transmitting, it routes the I-PDUs to the respective bus interface. For example it receives a PDU from the AUTOSARr COM module and then routes it to CANIf module for transmission through CAN bus, LinIf module for transmission through LIN bus.


Here TP stands for Transport Protocol. This module is bus specific and its configuration depends on the underlying bus protocol. It can be CAN bus protocol, LIN bus protocol or any other communication protocol. This module facilitates segmentation of messages at transmission along with flow control and reassembling of segmented messages at reception.

Bus State Manager

The bus state manager module is responsible for the control flow of the respective bus. It also handles startup and shutdown features of com transmission and monitors signal timeouts. It interacts with the Communication Hardware abstraction layer and System Services layer. It can either have CAN State Manager (CanSM), LIN STate Manager (LinSM) based on the bus protocol.

Bus Transceiver driver / Internal us Driver

It is a part of the ECU abstraction layer. It can either have CanTrcv for CAN transceiver, EthTrcv for Ethernet transceiver, FrTrcv for Flexray transceiver, etc. This module provides hardware-independent interface of the underlying bus transceivers to the upper layers of communication stack. It provides services for initiating transmissions and callback functions for notifying receive events, independent from controller hardware.

External Bus Driver

This module is a part of the AUTOSAR MCAL layer (Ex: CanDrv, LinDrv, FrDrv).It actually interacts with the underlying hardware of the ECU and provides a hardware independent interface to its upper layer. This module is hardware dependent and the driver codes may vary according to the underlying hardware. BusIf is the only module that can access this Bus driver.

What is CAN Bus Protocol

CAN stands for Controller Area Network. It is called CAN bus protocol because it is implemented as a logical bus topology. It is widely used in Automotive Electronics. Prior to the introduction of the CAN bus, each ECU had to be connected to one another to enable communication between them resulting in a large mesh of wires. However, now each ECU has to be connected just to a single bus, thus reducing the wire length as well as overall connection complexity in an automotive system. Thus, the CAN bus protocol allows ECUs to communicate with each other without any complex dedicated wiring in between

The reason for choosing CAN bus implementation in order to study COM configuration is that, it is very widely used in automotive electronics these days owing to its following features,

  1. Highly Robust to electronic disturbances and electromagnetic interferences which is ideal in vehicular environment.
  2. Less prone to errors as well as more efficient.
  3. CAN protocol is flexible. Each CAN-connected ECU can receive all transmitted messages. It decides relevance and acts accordingly. Thus addition or removal of ECU on the bus is easy.
  4. Based on two wires, CAN High and CAN Low, which reduces installation hassle.
  5. More importantly, it is a low cost interface.

Figure 4. Example of CAN bus in a automotive vehicle

COM configuration for CAN bus Implementation

Figure. AUTOSAR Communication Stack for CAN Bus Protocol

Now we will discuss the Autosar Communication stack with respective CAN bus protocol. Communication pstack with respect to CAN protocol consists of Autosar COM module, PDU router, CAN State Manage (CanSM) and CAN Transport Protocol (CanTp) from Service Layer, CAN Interface (CanIf) fand CAN transceiver driver from ECU abstraction layer, and CAN driver from MCAL layer. Autosar COM and PduR modules are generic and function irrespective of the underlying communication protocol.

We will further study each module involved in setting up CAN communication stack and all the import configuration parameters associated with each of them.


The underlying purpose of providing COM configurations is to establish a communication of the system between the upper RTE layer and the below PDU router irrespective of communication protocol. This is done by defining and configuring four different objects, viz.

  1. I-PDUs
  2. I-PDU contains a message received from a certain module or a message that needs to be transmitted to a certain module in the communication stack.
  1. I-PDU Groups
  2. If we have a large number of I-PDUs then we can group them in different groups.
  1. Signals
  2. A I-PDU can consist of one or more signals.
  1. Signal Groups
  2. Signals can be further formed into signal groups if several signals need to be sent to the same I-PDU.

COM module contains two main Containers ComGeneral and ComConfig.

ComGeneral (Multiplicity: 1)

It is used to provide various general configuration parameters for the COM module. Following are some important parameters of ComGeneral container:

  1. ComConfigurationUseDet: If this boolean parameter is set to ON then any error shall lead to call to API function Det_ReportError (Multiplicity: 0.1)
  2. ComCancellationSupport : It is a boolean parameter which is used to enable/disable cancellation features used for cancellation of PDU transmit requests. (Multiplicity: 0.1)
  3. ComEnableSignalGroupArrayApi: It is a boolean parameter used to activate/deactivate the signal group array access API. (Multiplicity: 1)
  4. ComSupportedIPduGroups : It is an integer parameter which tells the maximum number of supported IPDU groups. (Multiplicity: 1)
  5. ComVersionInfoApi : Boolean parameter to activate/deactivate the version information API, Com_GetVersionInfo. (Multiplicity: 1)
  6. ComRetryFailedTransmitRequests: If this Parameter is set to true, retry of failed transmission requests is enabled. (Multiplicity: 0.1)
  7. ComEnableMDTForCyclicTransmission: If this is enabled then it provides a Minimum Delay Time monitoring between cyclic and repeated transmission of I-PDUs. (Multiplicity: 0.1)

ComConfig (Multiplicity: 0.1)

It contains the four major containers ComSignals, ComIPdus, ComIPduGroups, and ComSignalGroups. It also has configuration parameters for Transmission mode configuration, Signal gateway configuration, Timebase configuration, and Filter parameter configuration.

ComIpdu (Multiplicity: 1)

This container is used to provide definition to different IPDU parameter without which no communication via the COM module is possible.The ComIPdu is also linked to PDU via the ComPduIdRef. I-PDUs contain one or more signals and / or signal groups. Following are some basic properties of ComIpdu.

  1. ComIPduHandleId: This is a numerical value assigned as the ID for this IPDU. This ID is used to refer to this IPDU in various transmitting and receiving API calls as well as respective callback APIs. (Multiplicity: 0.1)
  2. ComPduIdRef: It provides reference to the global PDU structure of the COM stack. (Multiplicity: 1)
  3. ComIPduGroupRef : It refers to the IPDU group to which this IPDU belongs to. (Multiplicity: 0...*)
  4. ComIPduSignalRef: This provides references to all the signals that are included in this IPDU.A IPDU can contain one or more individual signals.   (Multiplicity: 0...*)
  5. ComIPduSignalGroupRef: This provides references to all the signal groups that are included in this IPDU.A IPDU can signal groups where several signals need to be associated with the same IPDU. (Multiplicity: 0...*)
  6. ComIPduCallout: This parameter defines the existence and the name of a callout function for the corresponding I-PDU, that is called upon on receival of the IPDU or before transmission of the IPDU bu PDUR.             (Multiplicity: 0...1)
  7. ComIPduDirection: The direction defines if this I-PDU, and therefore its contributing signals and signal groups, are to be transmitted (SEND) or received (RECEIVE). (Multiplicity: 1)
  8. ComIPduSignalProcessing: It is used to configure when the signal indication takes place, either in IMEDIATE mode or in DEFERRED mode. (Multiplicity: 1)

If the ComIPduDirection is set as SEND we need to set additional parameters like whether the transmission is cyclic or periodic, etc. This is added by adding a ComTxIPdu object.

ComIpduGroup (Multiplicity: 1)

It contains the configuration parameters of the COM module's IPDU groups.  If there is no ComIPduGroup container included then no IPDU group is defined. In this case no communication via the COM module is possible. (Multiplicity: 1)

  1. ComIPduGroupHandleId: The numerical value used as the ID of this IPDU Group. It is required by the API calls to start and stop IPDU Groups. (Multiplicity: 1)
  2. ComIPduGroupGroupRef : It provides references to all IPDU groups that include this IPDU group. (Multiplicity: 0...* )


An IPDU can be formed of one or more than one signals. These signals coming from the different applications from the RTE layer are packed into a PDU before being transmitted to the PDU router.  This container provides various parameters to configure the signal bit position in the PDU, signal bit size and other properties.

  1. ComHandleId: This is a numerical value assigned as an ID to each signal. It is required by different API calls pertaining to operation on signals. (Multiplicity: 0...1)
  2. ComTimeoutFactor : It defines the timeout period for the deadline monitoring. (Multiplicity : 0..1 )
  3. ComTransferProperty: Following options define if this signal can trigger the transmission of the corresponding IPDU; (Multiplicity: 0...1)
    We can set one among these five options,
  4. ComBitPosition: It states the starting position of the signal in the IPDU. It will be a multiple of ComSignalType. (Multiplicity: 1)
  5. ComBitSize: It defines the size of signal in bits. (Multiplicity: 0...1)
  6. ComSignalEndianess: Defines the endianness of the signal's network representation. It can be BIG_ENDIAN, LITTLE_ENDIAN, OPAQUE. (Multiplicity: 0...1)
  7. ComSignalInitValue: It is used to set initial value or default value of signals in varied cases. (Multiplicity: 0...1)
  8. ComSignalLength: It specifies the n (in Bytes: 1...8) of the type UINT8[n]. For other types it will be ignored. (Multiplicity: 0...1)
  9. ComSignalType: It specifies the type of signal conforming to one of the different AUTOSAR types like BOOLEAN, SINT8, UINT8. (Multiplicity: 1)
  10. Commodification: If references the callback function that needs to be called on either the sender or receiver side. (Multiplicity: 0...1)
  11. ComErrorNotification: Only valid on the sender side, defines the name of the callback function to be called on the error message.  If this parameter is omitted no error notification shall take place. (Multiplicity: 0...1)
  12. ComTimeoutNotification: Defines the name of function to be called on the sender or the receiver side if timeout occurs (Multiplicity: 0...1)


When we need to send or receive several signals to the same IPDu then, these signals can be clubbed together to form a signal group.

Note: This container includes different parameters with names similar to ComSignal container and act exactly the same only on a signal group rather than individual signals. Therefore, in this section I will only mention the parameter names, to understand their behaviour please refer to the ComSignal section.

  1. ComHandleId (Multiplicity: 0...1)
  2. ComTimeoutFactor (Multiplicity: 0...1)
  3. ComFirstTimeoutFactor (Multiplicity: 0...1)
  4. ComTransferProperty (Multiplicity: 0...1)
  5. ComNotification (Multiplicity: 0...1)
  6. ComInvalidNotification (Multiplicity: 0...1)
  7. ComErrorNotification (Multiplicity: 0...1)
  8. ComTimeoutNotification (Multiplicity: 0...1)

PDU Router (PduR)

PDUR is responsible for routing the PDUs to specific bus interface. In all layers above PduR all the PDUs are protocol independent. However, all PDUs, in the layer below PDUr belong to specific protocol interface module, CanIf in thi case.PduR module provides following for main containers for parameter configurations.

PduRBswModules (Multiplicity: 0...*)

Each container describes a specific BSW module (upper/CDD/lower/IpduM) that the PDU Router shall interface to. While adding a PduRBswModule, the shortname of the container must match the name of the Bsw module, e.g. CanIf.

PdurGeneral (Multiplicity: 1)

This is a subcontainer of PduR module and it specifies the general configuration parameters of the PDU Router. Following are few basic configuration parameters.

  1. PduRDevErrorDetect: If enabled it switches the Default Error Tracer (Det) detection and notification ON. (Multiplicity: 1)
  2. PduRZeroCostOperation: If this parameter is set then the PduR configuration generator will report an error if zero-costoperation cannot be fulfilled. (Multiplicity: 1)
  3. PduRVersionInfoApi: If it is set to true, PduR_GetVersionInfo API is made available. (Multiplicity: 1)

PduRRoutingTables (Multiplicity: 1)

It represents a table of routing paths. This routing table allows multiple configurations that are used to create several routing tables in the same configuration.

  1. PduRConfigurationId: It provides i dentification of the configuration of the PduR configuration which is read using the PduR API. (Multiplicity: 1)
  2. PduRMaxRoutingPathCnt: It gives the maximum number of RoutingPaths in all RoutingTables. (Multiplicity: 1)
  3. PduRMaxRoutingTableCnt: It gives the maximum number of RoutingTables. (Multiplicity: 1)


This is a subcontainer of PduRRoutingPath container and it specifies the source of the PDU to be routed.

  1. PduRSourcePduHandleId: This is the PDU identifier assigned by PDU Router. (Multiplicity: 1)
  2. PduRSrcPduRef: This parameter provides reference to a unique PDU identifier which shall be used for the requested PDU Router operation. (Multiplicity: 1)


This is a subcontainer of PduRRoutingPath container and specifies one destination for the PDU to be routed.

  1. PduRDestPduHandleId : PDU identifier assigned by PDU Router that is used by communication interface and transport protocol modules for confirmation. (Multiplicity: 0...1)
  2. PduRDestPduDataProvision : This parameter specifies how data are provided,
    PDU_DIRECT or by PDUR_TRIGGERTRANSMIT. (Multiplicity: 0...1)
  3. PduRDestPduRef: It provides reference a unique PDU identifier which shall be used by the PDU Router when calling functions of the destination module. (Multiplicity : 1)
  4. PduRDestTxBufferRef: Provides reference to a buffer that is required for communication interface gatewaying and transport protocol gatewaying for single frame routing. (Multiplicity: 0...1)

CAN State Manager (CanSM)

The CAN State Manager (CanSM) is a member of the Communication Service layer which interacts with the Communication Hardware Abstraction Layer and the System Service Layer.The CanSM module is responsible for the control flow abstraction of CAN networks. It can also change the communication modes of the configured CAN networks. CanSM module has following container for its configuration

CanSMGeneral (Multiplicity: 1)

It contains module wide general-purpose pre-compile parameters of the CanSM module.

  1. CanSMDevErrorDetect: Toggle used to switch the development error detection and notification on or off. (Multiplicity : 1)
  2. CanSMMainFunctionTimePeriod: It defines the cycle time of the function CanSM_MainFunction in seconds. (Multiplicity: 1)
  3. CanSMVersionInfoApi: It is used to allow the version information API, CanSM_GetVersionInfo.  (Multiplicity: 1)

CanSMManagerNetwork (Multiplicity: 1...*)

This container contains the CAN network specific parameters for determining handling of underlaying CanControllers i.e. each CAN network.

  1. CanSMModeRequestRepetitionTime : It determines time duration the CanSM module shall repeat mode change requests by using the API of the CanIf module. (Multiplicity: 1)
  2. CanSMModeRequestRepetitionMax : It determines the maximum amount of mode request repetitions without a respective mode indication from the CanIf module until the CanSM module reports a Development Error to the Det and tries to go back to no communication. (Multiplicity: 1)

The CanSMConfiguration container has one CanSMManagerNetwork per CAN network.

CanSMManagerNetwork (Multiplicity: 1...*)

It contains the CAN network specific parameters of each CAN network.

  1. CanSMBorCounterL1ToL2:  It defines the count of bus-offs errors until the bus-off recovery switches from level 1 (short recovery time) to level 2 (long recovery time). (Multiplicity: 1)
  2. CanSMBorTimeL1: It defines in seconds thetime duration of the bus-off recovery time in level 1. (Multiplicity: 1)
  3. CanSMBorTimeL2:  It defines in seconds thetime duration of the bus-off recovery time in level 2. (Multiplicity: 1)

CanSMController (Multiplicity: 1...*)

Each container references a unique CAN controller

  1. CanSMControllerId: Unique identifier to refer to one certain CAN controller. (Multiplicity: 1)

CAN Bus Interface (CanIf)

The CANIf module is located between the Communication Services Layer and the Communication Drivers Layer in the communication stack. It is responsible for controlling the initialization of the CAN driver module and also provides the CAN driver module with notification services, on reception (CanIf_RxIndication) or transmission (CanIf_TxConfirmation) of messages.The CANIf module is independent of hardware, since the it does not access hardware functionality directly, but instead uses the CAN Driver module.Thus it abstracts from the location of CAN controllers, the ECU hardware layout and the number of CAN drivers. The upper layer hence addresses CAN channels rather than CAN controller.

CanIfPublicCfg (Multiplicity: 1)

This container contains the public configuration parameters of the CAN Interface.

  1. CanIfDevErrorDetect: If set to true, it switches the development error detection and notification on. And off if set to false. (Multiplicity: 1)
  2. CanIfPublicVersionInfoAp: It either enables or disables the API for reading the gversion information about the CAN Interface. (Multiplicity: 1)

CanIfPrivateCfg (Multiplicity: 1)

This container contains the private configuration parameters of the CAN Interface.

  1. CanIfPrivateDlcCheck : Selects whether the DLC check is supported or not.  If enabled, a frame will not be forwarded to the upper layer if the DLC of the frame is less than the configured DLC. If the DLC of a received frame is greater or equal to the configured DLC the frame is forwarded to the upper layer.

CanIfCtrlDrvCfg (Multiplicity: 1...*)

It provides configuration parameters for the underlying CAN driver module. One CanIfDrvCfg refers to one Can Driver module.

CanIfInitCfg (Multiplicity:)

It contains all the init parameters of the CAN Interface. At least one (if only on CanIf with one possible Configuration) or more than one (CanIf with different Configurations) instances of this container are possible. It defines all the PDU related configurations.

CanIfBufferCfg (Multiplicity: 0...*)

It is a sub-container of CanIfInitCfg.This container contains transmission buffer configuration. One instance of this containe must be added for each CanController that will be used for transmitting frames.

CanIfTxPduCfg (Multiplicity: 0...*)

It is a sub-container of CanIfInitCfg. It contains the configuration parameters of a transmit CAN L PDU. It is configured each time a transmit CAN L-PDU is needed. The SHORT-NAME of ‘CanIfTxPduConfig’ container represents the symbolic name of the transmit L-PDU. It must be added for each CAN frame that will be sent. It defines basic properties like frame id, frame type and frame length.

  1. CanIfTxPduCanId : It defines CAN Identifier of transmit CAN L-PDUs used by the CAN Driver for CAN L-PDU transmission. Range: 11 Bit for Standard CAN Identifier ... 29 Bit for Extended CAN identifier. (Multiplicity: 1)
  2. CanIfTxPduCanIdType: Defines the type of CAN Identifier of the transmit CAN L-PDU used by the CAN Driver module, whether it is Standard format (11 bit) or Extended format (29 bit). (Multiplicity: 1)
  3. CanIfTxPduDlc: It defines the Data length code (in bytes) of transmit CAN L-PDUs used by the CAN Driver for CAN L-PDU transmission. It has range from 0 to 8 bytes. (Multiplicity: 1)
  4. CanIfTxPduId: It defines an ECU wide unique, symbolic handle for transmit CAN LPDUs. (Multiplicity: 1)
  5. CanIfTxPduType: It defines the type of each transmit CAN L-PDU, whether it is Static or Dynamic. (Multiplicity: 1)

CanIfTxPduCfg (Multiplicity: 0...*)

It is a sub-container of CanIfInitCfg. It contains the configuration parameters of each receive CAN L PDU. The SHORT-NAME of ‘CanIfRxPduConfig’ container represents the symbolic name of the receive L-PDU. The CanIfRxPduCfg is very similar to the CanIfTxPduCfg. It defines basic properties like frame id, frame type and frame length for the receive L-PDUs.

  1. CanIfRxPduCanId: It defines CAN Identifier of receive CAN L-PDUs. Range: 11 Bit for Standard CAN Identifier ... 29 Bit for Extended CAN identifier. (Multiplicity: 1)
  2. CanIfRxPduCanIdType : Defines the type of CAN Identifier of the receiveCAN L-PDU used by the CAN Driver module, whether it is Standard format (11 bit)  or Extended format (29 bit). (Multiplicity: 1)
  3. CanIfRxPduDlc: It defines the Data length code (in bytes) of receive CAN L-PDUs used by the CAN Driver for transmission. It has range from 0 to 8 bytes. (Multiplicity: 1)
  4. CanIfRxPduId: It defines an ECU wide unique, symbolic handle for receive CAN LPDUs. (Multiplicity: 1)
  5. CanIfRxPduType: It defines the type of each receive CAN L-PDU, whether it is Static or Dynamic. (Multiplicity: 1)

CAN Driver

This container holds the configuration parameters of a single CAN Driver.

CanGeneral (Multiplicity: 1)

Provides Module wide configuration containing the usual CanDevErrorDetection and CanVersionInfoApi.

  1. CanDevErrorDetectio: Enables/disables the Development Error Detection and Notification. (Multiplicity: 1)
  2. CanVersionInfoApi:  Enables/disables the API for version info. (Multiplicity: 1)

CanConfigSet (Multiplicity: 1)

It contains configurations of CAN controllers and CAN hardware objects. It is a multiple configuration set container for CAN Driver.

CanController (Multiplicity: 1)

It contains configuration parameters of the CAN controller.

  1. CanBusoffProcessing: Enables / disables API Can_MainFunction_BusOff() for handling bus off events in polling mode.  (Multiplicity: 1)
  2. CanControllerActivation: Defines if a CAN controller is active for configuration. (Multiplicity: 1)
  3. CanControllerId: It provides the controller ID which is unique to each CAN Driver. (Multiplicity: 1)
  4.  CanRxProcessing: Enables / disables API for handling PDU reception events in polling mode. (Multiplicity: 1)
  5. CanTxProcessing: Enables / disables API for handling PDU transmission events in polling mode. (Multiplicity: 1)
  6. CanWakeupProcessing: Enables / disables API for handling wakeup events in polling mode.  (Multiplicity: 1)
  7. CanControllerDefaultBaudrate: It provides a reference to baud rate configuration container for the Can Controller.

CanControllerBaudrateConfig (Multiplicity: 1...*)

This container contains bit timing related configuration parameters of each CAN controller.

  1. CanControllerBaudRate: It sets the baudrate of the controller in kbps. (Multiplicity: 1)
  2. CanControllerPropSeg: It defines the propagation delay in time quantas. (Multiplicity: 1)
  3. CanControllerSeg1: It defines the phase segment 1 in time quantas. (Multiplicity: 1)
  4. CanControllerSeg2: It defines the phase segment 2 in time quantas. (Multiplicity: 1)
  5. CanControllerSyncJumpWidth:  It defines the synchronization jump width for the controller in time quantas. (Multiplicity: 1).

CanFilterMask (Multiplicity: 0...*)

This container contains the configuration parameters of the CAN Filter mask. A filter mask is set for a CAN controller to filter out receiving CAN messages based upon the CAN id field. All the ECUs on the bus receive all the CAN packets travelling on the bus, however it filters out the irrelevant packets according to its filter mask.

  1. CanFilterMaskValue: It Describes a mask value for hardware-based filtering of CAN identifiers. The CAN identifiers of incoming messages are masked with the appropriate filter mask value. The mask shall be built by filling with leading 0. In case of CAN frame of type EXTENDED or MIXED a 29-bit mask is used and in case of STANDARD CAN frame type a 11-bit mask is used. (Multiplicity: 1)

Further reading

By submitting this form, you authorize PathPartner to contact you with further information about our relevant content, products and services. You may unsubscribe any time. We are committed to your privacy. For more details, refer our Privacy Policy

Notify of
Inline Feedbacks
View all comments
Back to Top