mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-17 10:46:33 +00:00
can: ucan: add driver for Theobroma Systems UCAN devices
The UCAN driver supports the microcontroller-based USB/CAN adapters from Theobroma Systems. There are two form-factors that run essentially the same firmware: * Seal: standalone USB stick ( https://www.theobroma-systems.com/seal ) * Mule: integrated on the PCB of various System-on-Modules from Theobroma Systems like the A31-µQ7 and the RK3399-Q7 ( https://www.theobroma-systems.com/rk3399-q7 ) The USB wire protocol has been designed to be as generic and hardware-indendent as possible in the hope of being useful for implementation on other microcontrollers. Signed-off-by: Martin Elshuber <martin.elshuber@theobroma-systems.com> Signed-off-by: Jakob Unterwurzacher <jakob.unterwurzacher@theobroma-systems.com> Signed-off-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com> Acked-by: Wolfgang Grandegger <wg@grandegger.com> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
This commit is contained in:
parent
ffbdd9172e
commit
9f2d3eae88
332
Documentation/networking/can_ucan_protocol.rst
Normal file
332
Documentation/networking/can_ucan_protocol.rst
Normal file
@ -0,0 +1,332 @@
|
|||||||
|
=================
|
||||||
|
The UCAN Protocol
|
||||||
|
=================
|
||||||
|
|
||||||
|
UCAN is the protocol used by the microcontroller-based USB-CAN
|
||||||
|
adapter that is integrated on System-on-Modules from Theobroma Systems
|
||||||
|
and that is also available as a standalone USB stick.
|
||||||
|
|
||||||
|
The UCAN protocol has been designed to be hardware-independent.
|
||||||
|
It is modeled closely after how Linux represents CAN devices
|
||||||
|
internally. All multi-byte integers are encoded as Little Endian.
|
||||||
|
|
||||||
|
All structures mentioned in this document are defined in
|
||||||
|
``drivers/net/can/usb/ucan.c``.
|
||||||
|
|
||||||
|
USB Endpoints
|
||||||
|
=============
|
||||||
|
|
||||||
|
UCAN devices use three USB endpoints:
|
||||||
|
|
||||||
|
CONTROL endpoint
|
||||||
|
The driver sends device management commands on this endpoint
|
||||||
|
|
||||||
|
IN endpoint
|
||||||
|
The device sends CAN data frames and CAN error frames
|
||||||
|
|
||||||
|
OUT endpoint
|
||||||
|
The driver sends CAN data frames on the out endpoint
|
||||||
|
|
||||||
|
|
||||||
|
CONTROL Messages
|
||||||
|
================
|
||||||
|
|
||||||
|
UCAN devices are configured using vendor requests on the control pipe.
|
||||||
|
|
||||||
|
To support multiple CAN interfaces in a single USB device all
|
||||||
|
configuration commands target the corresponding interface in the USB
|
||||||
|
descriptor.
|
||||||
|
|
||||||
|
The driver uses ``ucan_ctrl_command_in/out`` and
|
||||||
|
``ucan_device_request_in`` to deliver commands to the device.
|
||||||
|
|
||||||
|
Setup Packet
|
||||||
|
------------
|
||||||
|
|
||||||
|
================= =====================================================
|
||||||
|
``bmRequestType`` Direction | Vendor | (Interface or Device)
|
||||||
|
``bRequest`` Command Number
|
||||||
|
``wValue`` Subcommand Number (16 Bit) or 0 if not used
|
||||||
|
``wIndex`` USB Interface Index (0 for device commands)
|
||||||
|
``wLength`` * Host to Device - Number of bytes to transmit
|
||||||
|
* Device to Host - Maximum Number of bytes to
|
||||||
|
receive. If the device send less. Commom ZLP
|
||||||
|
semantics are used.
|
||||||
|
================= =====================================================
|
||||||
|
|
||||||
|
Error Handling
|
||||||
|
--------------
|
||||||
|
|
||||||
|
The device indicates failed control commands by stalling the
|
||||||
|
pipe.
|
||||||
|
|
||||||
|
Device Commands
|
||||||
|
---------------
|
||||||
|
|
||||||
|
UCAN_DEVICE_GET_FW_STRING
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
*Dev2Host; optional*
|
||||||
|
|
||||||
|
Request the device firmware string.
|
||||||
|
|
||||||
|
|
||||||
|
Interface Commands
|
||||||
|
------------------
|
||||||
|
|
||||||
|
UCAN_COMMAND_START
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
*Host2Dev; mandatory*
|
||||||
|
|
||||||
|
Bring the CAN interface up.
|
||||||
|
|
||||||
|
Payload Format
|
||||||
|
``ucan_ctl_payload_t.cmd_start``
|
||||||
|
|
||||||
|
==== ============================
|
||||||
|
mode or mask of ``UCAN_MODE_*``
|
||||||
|
==== ============================
|
||||||
|
|
||||||
|
UCAN_COMMAND_STOP
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
*Host2Dev; mandatory*
|
||||||
|
|
||||||
|
Stop the CAN interface
|
||||||
|
|
||||||
|
Payload Format
|
||||||
|
*empty*
|
||||||
|
|
||||||
|
UCAN_COMMAND_RESET
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
*Host2Dev; mandatory*
|
||||||
|
|
||||||
|
Reset the CAN controller (including error counters)
|
||||||
|
|
||||||
|
Payload Format
|
||||||
|
*empty*
|
||||||
|
|
||||||
|
UCAN_COMMAND_GET
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
*Host2Dev; mandatory*
|
||||||
|
|
||||||
|
Get Information from the Device
|
||||||
|
|
||||||
|
Subcommands
|
||||||
|
^^^^^^^^^^^
|
||||||
|
|
||||||
|
UCAN_COMMAND_GET_INFO
|
||||||
|
Request the device information structure ``ucan_ctl_payload_t.device_info``.
|
||||||
|
|
||||||
|
See the ``device_info`` field for details, and
|
||||||
|
``uapi/linux/can/netlink.h`` for an explanation of the
|
||||||
|
``can_bittiming fields``.
|
||||||
|
|
||||||
|
Payload Format
|
||||||
|
``ucan_ctl_payload_t.device_info``
|
||||||
|
|
||||||
|
UCAN_COMMAND_GET_PROTOCOL_VERSION
|
||||||
|
|
||||||
|
Request the device protocol version
|
||||||
|
``ucan_ctl_payload_t.protocol_version``. The current protocol version is 3.
|
||||||
|
|
||||||
|
Payload Format
|
||||||
|
``ucan_ctl_payload_t.protocol_version``
|
||||||
|
|
||||||
|
.. note:: Devices that do not implement this command use the old
|
||||||
|
protocol version 1
|
||||||
|
|
||||||
|
UCAN_COMMAND_SET_BITTIMING
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
*Host2Dev; mandatory*
|
||||||
|
|
||||||
|
Setup bittiming by sending the the structure
|
||||||
|
``ucan_ctl_payload_t.cmd_set_bittiming`` (see ``struct bittiming`` for
|
||||||
|
details)
|
||||||
|
|
||||||
|
Payload Format
|
||||||
|
``ucan_ctl_payload_t.cmd_set_bittiming``.
|
||||||
|
|
||||||
|
UCAN_SLEEP/WAKE
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
*Host2Dev; optional*
|
||||||
|
|
||||||
|
Configure sleep and wake modes. Not yet supported by the driver.
|
||||||
|
|
||||||
|
UCAN_FILTER
|
||||||
|
~~~~~~~~~~~
|
||||||
|
|
||||||
|
*Host2Dev; optional*
|
||||||
|
|
||||||
|
Setup hardware CAN filters. Not yet supported by the driver.
|
||||||
|
|
||||||
|
Allowed interface commands
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
================== =================== ==================
|
||||||
|
Legal Device State Command New Device State
|
||||||
|
================== =================== ==================
|
||||||
|
stopped SET_BITTIMING stopped
|
||||||
|
stopped START started
|
||||||
|
started STOP or RESET stopped
|
||||||
|
stopped STOP or RESET stopped
|
||||||
|
started RESTART started
|
||||||
|
any GET *no change*
|
||||||
|
================== =================== ==================
|
||||||
|
|
||||||
|
IN Message Format
|
||||||
|
=================
|
||||||
|
|
||||||
|
A data packet on the USB IN endpoint contains one or more
|
||||||
|
``ucan_message_in`` values. If multiple messages are batched in a USB
|
||||||
|
data packet, the ``len`` field can be used to jump to the next
|
||||||
|
``ucan_message_in`` value (take care to sanity-check the ``len`` value
|
||||||
|
against the actual data size).
|
||||||
|
|
||||||
|
.. _can_ucan_in_message_len:
|
||||||
|
|
||||||
|
``len`` field
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Each ``ucan_message_in`` must be aligned to a 4-byte boundary (relative
|
||||||
|
to the start of the start of the data buffer). That means that there
|
||||||
|
may be padding bytes between multiple ``ucan_message_in`` values:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
+----------------------------+ < 0
|
||||||
|
| |
|
||||||
|
| struct ucan_message_in |
|
||||||
|
| |
|
||||||
|
+----------------------------+ < len
|
||||||
|
[padding]
|
||||||
|
+----------------------------+ < round_up(len, 4)
|
||||||
|
| |
|
||||||
|
| struct ucan_message_in |
|
||||||
|
| |
|
||||||
|
+----------------------------+
|
||||||
|
[...]
|
||||||
|
|
||||||
|
``type`` field
|
||||||
|
--------------
|
||||||
|
|
||||||
|
The ``type`` field specifies the type of the message.
|
||||||
|
|
||||||
|
UCAN_IN_RX
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
``subtype``
|
||||||
|
zero
|
||||||
|
|
||||||
|
Data received from the CAN bus (ID + payload).
|
||||||
|
|
||||||
|
UCAN_IN_TX_COMPLETE
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
``subtype``
|
||||||
|
zero
|
||||||
|
|
||||||
|
The CAN device has sent a message to the CAN bus. It answers with a
|
||||||
|
list of of tuples <echo-ids, flags>.
|
||||||
|
|
||||||
|
The echo-id identifies the frame from (echos the id from a previous
|
||||||
|
UCAN_OUT_TX message). The flag indicates the result of the
|
||||||
|
transmission. Whereas a set Bit 0 indicates success. All other bits
|
||||||
|
are reserved and set to zero.
|
||||||
|
|
||||||
|
Flow Control
|
||||||
|
------------
|
||||||
|
|
||||||
|
When receiving CAN messages there is no flow control on the USB
|
||||||
|
buffer. The driver has to handle inbound message quickly enough to
|
||||||
|
avoid drops. I case the device buffer overflow the condition is
|
||||||
|
reported by sending corresponding error frames (see
|
||||||
|
:ref:`can_ucan_error_handling`)
|
||||||
|
|
||||||
|
|
||||||
|
OUT Message Format
|
||||||
|
==================
|
||||||
|
|
||||||
|
A data packet on the USB OUT endpoint contains one or more ``struct
|
||||||
|
ucan_message_out`` values. If multiple messages are batched into one
|
||||||
|
data packet, the device uses the ``len`` field to jump to the next
|
||||||
|
ucan_message_out value. Each ucan_message_out must be aligned to 4
|
||||||
|
bytes (relative to the start of the data buffer). The mechanism is
|
||||||
|
same as described in :ref:`can_ucan_in_message_len`.
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
+----------------------------+ < 0
|
||||||
|
| |
|
||||||
|
| struct ucan_message_out |
|
||||||
|
| |
|
||||||
|
+----------------------------+ < len
|
||||||
|
[padding]
|
||||||
|
+----------------------------+ < round_up(len, 4)
|
||||||
|
| |
|
||||||
|
| struct ucan_message_out |
|
||||||
|
| |
|
||||||
|
+----------------------------+
|
||||||
|
[...]
|
||||||
|
|
||||||
|
``type`` field
|
||||||
|
--------------
|
||||||
|
|
||||||
|
In protocol version 3 only ``UCAN_OUT_TX`` is defined, others are used
|
||||||
|
only by legacy devices (protocol version 1).
|
||||||
|
|
||||||
|
UCAN_OUT_TX
|
||||||
|
~~~~~~~~~~~
|
||||||
|
``subtype``
|
||||||
|
echo id to be replied within a CAN_IN_TX_COMPLETE message
|
||||||
|
|
||||||
|
Transmit a CAN frame. (parameters: ``id``, ``data``)
|
||||||
|
|
||||||
|
Flow Control
|
||||||
|
------------
|
||||||
|
|
||||||
|
When the device outbound buffers are full it starts sending *NAKs* on
|
||||||
|
the *OUT* pipe until more buffers are available. The driver stops the
|
||||||
|
queue when a certain threshold of out packets are incomplete.
|
||||||
|
|
||||||
|
.. _can_ucan_error_handling:
|
||||||
|
|
||||||
|
CAN Error Handling
|
||||||
|
==================
|
||||||
|
|
||||||
|
If error reporting is turned on the device encodes errors into CAN
|
||||||
|
error frames (see ``uapi/linux/can/error.h``) and sends it using the
|
||||||
|
IN endpoint. The driver updates its error statistics and forwards
|
||||||
|
it.
|
||||||
|
|
||||||
|
Although UCAN devices can suppress error frames completely, in Linux
|
||||||
|
the driver is always interested. Hence, the device is always started with
|
||||||
|
the ``UCAN_MODE_BERR_REPORT`` set. Filtering those messages for the
|
||||||
|
user space is done by the driver.
|
||||||
|
|
||||||
|
Bus OFF
|
||||||
|
-------
|
||||||
|
|
||||||
|
- The device does not recover from bus of automatically.
|
||||||
|
- Bus OFF is indicated by an error frame (see ``uapi/linux/can/error.h``)
|
||||||
|
- Bus OFF recovery is started by ``UCAN_COMMAND_RESTART``
|
||||||
|
- Once Bus OFF recover is completed the device sends an error frame
|
||||||
|
indicating that it is on ERROR-ACTIVE state.
|
||||||
|
- During Bus OFF no frames are sent by the device.
|
||||||
|
- During Bus OFF transmission requests from the host are completed
|
||||||
|
immediately with the success bit left unset.
|
||||||
|
|
||||||
|
Example Conversation
|
||||||
|
====================
|
||||||
|
|
||||||
|
#) Device is connected to USB
|
||||||
|
#) Host sends command ``UCAN_COMMAND_RESET``, subcmd 0
|
||||||
|
#) Host sends command ``UCAN_COMMAND_GET``, subcmd ``UCAN_COMMAND_GET_INFO``
|
||||||
|
#) Device sends ``UCAN_IN_DEVICE_INFO``
|
||||||
|
#) Host sends command ``UCAN_OUT_SET_BITTIMING``
|
||||||
|
#) Host sends command ``UCAN_COMMAND_START``, subcmd 0, mode ``UCAN_MODE_BERR_REPORT``
|
@ -10,6 +10,7 @@ Contents:
|
|||||||
af_xdp
|
af_xdp
|
||||||
batman-adv
|
batman-adv
|
||||||
can
|
can
|
||||||
|
can_ucan_protocol
|
||||||
dpaa2/index
|
dpaa2/index
|
||||||
e100
|
e100
|
||||||
e1000
|
e1000
|
||||||
|
@ -95,4 +95,20 @@ config CAN_MCBA_USB
|
|||||||
This driver supports the CAN BUS Analyzer interface
|
This driver supports the CAN BUS Analyzer interface
|
||||||
from Microchip (http://www.microchip.com/development-tools/).
|
from Microchip (http://www.microchip.com/development-tools/).
|
||||||
|
|
||||||
|
config CAN_UCAN
|
||||||
|
tristate "Theobroma Systems UCAN interface"
|
||||||
|
---help---
|
||||||
|
This driver supports the Theobroma Systems
|
||||||
|
UCAN USB-CAN interface.
|
||||||
|
|
||||||
|
The UCAN driver supports the microcontroller-based USB/CAN
|
||||||
|
adapters from Theobroma Systems. There are two form-factors
|
||||||
|
that run essentially the same firmware:
|
||||||
|
|
||||||
|
* Seal: standalone USB stick
|
||||||
|
https://www.theobroma-systems.com/seal)
|
||||||
|
* Mule: integrated on the PCB of various System-on-Modules
|
||||||
|
from Theobroma Systems like the A31-µQ7 and the RK3399-Q7
|
||||||
|
(https://www.theobroma-systems.com/rk3399-q7)
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
@ -10,3 +10,4 @@ obj-$(CONFIG_CAN_GS_USB) += gs_usb.o
|
|||||||
obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb.o
|
obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb.o
|
||||||
obj-$(CONFIG_CAN_MCBA_USB) += mcba_usb.o
|
obj-$(CONFIG_CAN_MCBA_USB) += mcba_usb.o
|
||||||
obj-$(CONFIG_CAN_PEAK_USB) += peak_usb/
|
obj-$(CONFIG_CAN_PEAK_USB) += peak_usb/
|
||||||
|
obj-$(CONFIG_CAN_UCAN) += ucan.o
|
||||||
|
1613
drivers/net/can/usb/ucan.c
Normal file
1613
drivers/net/can/usb/ucan.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user