//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
:imagesdir: ../../images/users/protocols
:icons: font

== CAN Bus Driver Adapter

The CAN Bus driver is a special kind of driver which does not bring any logic.
Its responsibility is to combine link:../transports/can.html[CAN transport facade] and custom application layer protocols.
In this way, the protocol can use its own "root frame" type which is not delivered from CAN bus frame.

=== More details on the driver

The `CANDriverAdapter` is a full implementation of Apache PLC4X API.
Under the hood adapter will forward all operations to delegate driver.
Work which is done by the adapter is to transform data incoming via CAN transport into frame supported by driver.
In this regard the `CANDriverAdapter` does not implement any real protocol.
All it does is transformation of incoming frames into frame desired by real driver.

Below diagram explains how driver adapter works with CANopen.
Given that this is currently biggest CAN driver implemented in Apache PLC4X we will use it as a reference.

[ditaa,apache-plc4x-can-canopen]
....
                                                     +--------------------------------------------+
                                                     |            CAN Driver Adapter              |

                                                                                    +----------------------------------------------------------+
                                                       Conversation                 |                        CANopen Driver                    |
                                       Protocol          Context                                        Protocol
       CAN Transport                  Root Frame         Wrapper               Frame Handler           Root Frame               Protocol Logic
 wire   /---------\                 /------------\                                                     /---------\            |
 -----> | receive | --------------> | SocketCAN  | -----[transform] ------> [ map to protocol ] -----> | CANopen | ---------> | receive
        |---------|                 |   Frame    |                                                     |  Frame  |            |
 <------|  write  |---------------- \------------/ <----------------------- [ map to transport] <----- \---------/ <--------- | publish
        \---------/                                                                                                           |
....

Looking at left most side of diagram we can see a CAN transport.
The transport knows how to receive and send data to the CAN bus.
Transport can create its own intermediate representation of CAN data frame.
In case of `SocketCAN` there is a dedicated type called `SocketCANFrame`.

Most of other drivers in Apache PLC4X which rely on TCP, UDP or serial transports can unify right above transport.
Yet due to variety of APIs which are possible to be used with CAN bus such early unification at API level is not possible.

Place where `CANDriverAdapter` jumps in is once transport formed the frame structure.
Then, adapter asks the transport to turn that structure into a `FrameData`.
An instance of `FrameData` is then passed to an adapter delivered by CANopen Driver.
This adapter can then create a `CANopenFrame` which is processed by desired driver logic.

The return side, when desired driver wants to publish information is a bit simplified.
Because `FrameData` does not be a real type (it is an interface) we can skip it.
With a help of a `CANFrameBuilder` provided by CAN transport driver can easily construct a structure which is supported by it.
While this makes an API asymmetric it also makes it possible to use any third party transport with `CANopenDriver`.