AGL CAN binding アーキテクチャ

# AGL CAN binding アーキテクチャ

---

### はじめに

AGL のCANに関する個人的なメモ。

[公式ドキュメント](http://docs.automotivelinux.org/docs/apis_services/en/dev/reference/signaling/low-level-can-service-guide.html)の翻訳等。

---

### AGL CAN binding architecture

これは、CANメッセージと診断メッセージ（現在はOBD2）を記述するJSONファイルからプロジェクトに統合するためのcppファイルを生成するためのものです。

生成されたバインディングが作成されると、その結果はAGLターゲットシステム上にインストールされるウィジェットファイルになります。

> binding用のCAN通信ライブラリをJSONファイルから自動生成するためのプロジェクト?
>
> JSON -> CAN設定ジェネレータ -> 各種ベンダ性のCAN通信プログラム -> コンパイラ -> CAN低レベルBinding(共有ライブラリ)

![OpenXC_to_AGL.png](https://qiita-image-store.s3.amazonaws.com/0/210251/d37f0cd9-ec4a-3161-5159-2a676505ef8c.png)


AGLプロジェクトへのCAN管理の導入は単にCANメッセージのデコードや出力を可能とするだけでなく、多くのツール(Wireshark, CAN-util...)でそれを可能にします。

目標としては、共通APIとCANバスの抽象化を提供することで、システムにより高度な機能をもたらすことです。

CAN bindingは次の2つの部分から構成されることになるでしょう。

> 低級レイヤ、高級レイヤ、APIの三層（二層）構造？
>
> - 低級レイヤ：デコード、エンコード、暗号化等、トランザクション管理、キャッシング、デバッグ用途等のCANバスとのやり取り
> - 高級レイヤ：ロジック、集約(vehicle.doors.any.open というような)、高等なオペレーション
>
> UIから共通APIを叩くと、高級レイヤはBinderイベントを発行し、低級レイヤが発行されたBinderイベントを処理する、という形式になる

![CAN_level_mapping.png](https://qiita-image-store.s3.amazonaws.com/0/210251/cd5a38fd-16fc-53eb-0d50-ec883ae392e3.png)


- ハイレベル：<br>他のアプリケーションが接続するBinding。<br>いくつかのオリジナルから提供される新しい信号や集約信号による、CANバスへの様々なアクセス手段を提供します。<br>たとえば、どのドアであるか関係なく、ドアの開閉状況を示す信号です。<br>また、車内に誰もいないかどうかを監視しているアプリケーションが、1mか2mほどの移動を検知した際に、予期しない動作として所有者に警報を送信する、といったことは想像に難くないでしょう。<br>ハイレベルBindingは、その動作を表したイベント信号をアプリケーションに送信し、アプリケーションは電話メッセージとして、そのイベント信号を送信する、といった具合です。
- ローレベル：<br>メッセージをデコードし、アプリケーションフレームワーク経由で人間が読めるメッセージとしてサブスクライバにイベントを送信します。<br>ローレベルは、いくつかのバスへの基本的なアクセス手段といくつかの基本的な数学的、統計的な機能（前回値、最小、最大、タイムスタンプ、平均化）、そして、それと同様に識別信号のみを得るための基本的なフィルタを提供します（この部分はまだ低レベルでは実装されていません）。

![CAN_bindings_communication.png](https://qiita-image-store.s3.amazonaws.com/0/210251/38fcf7d4-10fd-1d92-af4c-ba3f329a6cfa.png)


最後に、低レベルバインディングは、OpenXCを使用したバイナリとしてのみ、出荷できます。OpenXCは[AGL低レベルCANバインディングジェネレータ](https://github.com/iotbzh/can-config-generator)(※URLが失効しています)にインスパイアされています。

### 前提条件

- AGLのバージョンはApplication frameworkバージョン0.6以上のDaring Dabの最新版である必要があります。
- AGLジェネレータのビルド。さもなければ、カスタムローレベルCAN bindingを生成することはできません。AGLジェネレータは`CAN-binder/low-can-binding/binding/`ディレクトリのソース中に貼り付ける、`application-generated.cpp`ファイルを生成します。
- SDKクイックスタートアップガイドにしたがって、AGL SDKをセットアップしてください。もしくは、AGL Developerサイトの公式ガイドを参照してください。


SDKの中にグラフィックススタックが必要な場合は、prepare_metaツールを使用してiotbzhまたはDaring Dabフレーバーを使用して環境を準備する必要があります。これを行うには、`[prepare build environment] ...：`のステップ4のDockerイメージで次のコマンドを実行します。

> **NOTE** 以下のコマンドはRenesas Porterボード用プロプライエタリグラフィックドライバが`/home/devel/share/proprietary-renesas-rcar`ディレクトリにある場合のものです。

```bash
prepare_meta -f iotbzh -o /xdt -l /home/devel/mirror -p /home/devel/share/proprietary-renesas-rcar/ -t m3ulcb -e wipeconfig -e rm_work -e cleartemp
/xdt/build/m3ulcb/agl-init-build-env
```

- (オプション) OBD2コネクタを介して実際の車に接続する場合は、[このケーブル](https://www.mouser.fr/search/ProductDetail.aspx?R=0virtualkey0virtualkeyOBD-M-DB9-F-ES)を介して[USB CANアダプタ](http://shop.8devices.com/usb2can)をコネクタに接続してください。

### Getting started

#### CAN config generator 使用法

###### ビルド要求条件

- CMake バージョン 3.3以降
- g++, clang++ またはその他のC++11準拠のコンパイラ

###### コンパイル

```bash
source /xdt/sdk/environment-setup-aarch64-agl-linux
export PATH=$PATH:/xdt/sdk/sysroots/x86_64-aglsdk-linux/usr/bin
export WD=$(pwd)
git clone --recursive https://gerrit.automotivelinux.org/gerrit/apps/low-level-can-service -b Renesas_delivery_Q2
git clone --recursive https://gerrit.automotivelinux.org/gerrit/apps/low-level-can-generator
cd ${WD}/low-level-can-generator
mkdir -p build
cd build
cmake -G "Unix Makefiles" ..
make
```

###### 命名規則

広く知られている形式である、`.`による命名規則を採用しました。

名前を分離・構造化した階層構造になっています。

左側の抽象度が最も高く、右に行くにつれ、具体的になります。

この規則に従った標準PID名の例を示します：

```
engine.load
engine.coolant.temperature
fuel.pressure
intake.manifold.pressure
engine.speed
vehicle.speed
intake.air.temperature
mass.airflow
throttle.position
running.time
EGR.error
fuel.level
barometric.pressure
commanded.throttle.position
ethanol.fuel.percentage
accelerator.pedal.position
hybrid.battery-pack.remaining.life
engine.oil.temperature
engine.torque
```

>**NOTE** この命名規則に従ってCAN信号に名前を付けることをお勧めします。
>
>サブスクリプションとアンサブスクリプションで用いるワイルドカードとして使用されているため、`*`のみは名前の中で使用できません。
>
>これについては、以下の章で説明します。

###### 利用可能なデコーダ

bindingが標準的に提供している、以下のような基本的なデコーダを使用できます。

- **`decoder_t::noopDecoder`**:指定がなかった場合のデフォルトのデコーダ。信号のビットフィールドの生の値を返します。
- **`decoder_t::booleanDecoder`**:数値をブール値に変換します。
- **`decoder_t::stateDecoder`**s:CAN信号の生の整数値に対応する文字列状態を見つけて、返します。

###### Vector CANoe データベースからのJSONの生成

> **注意** この章は、自動車用のツールを必要としないため、テストされていません。

`gold standard`CAN信号定義を保存するためにCANoeを使用する場合、JSON作成のためにOpenXC `xml_to_json.py` スクリプトを使用できます。

はじめに、CANoe .dbcファイルをXMLとしてエクスポートします - Vector CANdb++でこれを実行できます。

次に、上で定義したフォーマットに従って、JSONファイルを

CANoeを使用して標準CANシグナル定義を保存する場合は、OpenXC xml_to_json.pyスクリプトを使用してJSONを作成することができます。まず、Canoeの.dbcファイルをXMLとしてエクスポートします。これは、Vector CANdb ++で行うことができます。次に、以下の定義に加えて、上で定義したフォーマットに従ってJSONファイルを作成します。

- CANメッセージ
- メッセージ内のCAN信号名とそれらの`generic_name`
- オプション：診断メッセージの名前とその名前

OpenXCユーティリティのインストールと`xml_to_json.py`スクリプトの実行を行うには以下を実行します。

```bash
sudo pip install openxc
cd /usr/local/lib/python2.7/dist-packages/openxc/generator
```

Vectorからエクスポートされたデータがsignals.xmlにあり、最小限のマッピングファイルがmapping.jsonであると仮定して、スクリプトを実行した例が以下です。

```bash
python -m openxc.utils ./xml_to_json.py signals.xml mapping.json signals.json
```

スクリプトは`mapping.json`をスキャンし、XMLファイルから使用したいCANメッセージ、及び信号を特定します。

メッセージの必要な部分（ビット位置、ビットサイズ、オフセットなど）を取得し、結果のサブセットをJSONとして出力ファイル`signals.json`に出力します。

結果ファイルとmapping.jsonは、コード生成スクリプトへの入力として機能します。

###### 設定ファイルの生成

設定ファイルを生成するためには、ジェネレータの実行時に`-m`オプションを使用し、JSONファイルを引数として渡す必要があります。

```bash
./can-config-generator -m ../tests/basic.json -o application-generated.cpp
```

もし、`-o`オプションを省略した場合、コードは標準出力上で生成されます。

ヘッダファイルとフッタファイルを指定することもできます。

これらのファイルはそのまま挿入した場合に有効なC++の一部でなければいけません。

ヘルプを表示するには、-hオプションを使用します。

> **注意**： 各diagnostic_messageは、bindingが使用する唯一のバスと同じバスを定義する必要があります。

###### サポートされたOpenXC項目

今のところ、OpenXCリファレンスのコンプライアンスは進行中であり、can-config-generatorとCAN_signalingがすぐにそれらを実装する予定です。

`initializers`、`loopers`、`commands`、`handlers`ノードは現在無視されています。

このジェネレータは、低レベルCAN信号bindingのOpenXCサポートステータスに従います。

> **注意**：bindingは別の方法でバスの宣言と構成を行うため、バス項目はこのジェネレータでサポートされません。bindingのドキュメントを参照してください。

#### bindingのコンパイルとインストール

###### ビルド要求条件

- カーネル 4.8以上
- CMakeバージョン3.3以上
- g++, clang++ またはその他のC++11準拠コンパイラ

###### コンパイル

bindingレポジトリを複製して、更新されたgitサブモジュールと生成されたファイルをコピーします。

bindingリポジトリ上で以下のコマンドを実行してください。

```bash
cd ${WD}/low-level-can-service
cp ${WD}/low-level-can-generator/build/application-generated.cpp ../low-can-binding/binding
```

###### インストール

```bash
cd ${WD}/low-level-can-service
mkdir build
cd build
cmake ..
make
make widget
```

手動でインストールするには、`low-can-service.wgt`ファイルをターゲットマシンにコピーしてから、ターゲットマシン上で次のコマンドを実行します。

ホストマシン上で、ネットワーク経由でファイルをコピーします。

```
scp low-can-service.wgt root@<target_IP>:~
```

ターゲットマシン上で、`wgt`ファイルがrootホームディレクトリ上にある場合の例が以下です。

```bash
afm-util install low-can-service.wgt
{ "added": "low-can-service@4.0" }
```

### AGLシステムの設定

#### 仮想CANデバイス

ターゲットマシンに接続して、仮想CANデバイスドライバをロードし、新しいVCANデバイスをセットアップするには以下のようにします。

```bash
modprobe vcan
ip link add vcan0 type vcan
ip link set vcan0 up
```

Linux CANデバイスに好きな名前をつけることができます。以下に、`can0`という名前をつける場合の例を示します。

```bash
modprobe vcan
ip link add can0 type vcan
ip link set can0 up
```

#### USB CANアダプタを用いたCANデバイス

OBD2コネクタに接続されたUSB CANアダプタを用いて車のCANバスへ実際に接続する。

接続後に、`dmesg`コマンドを起動し、使用するデバイスを探します。

```bash
dmesg
[...]
[  131.871441] usb 1-3: new full-speed USB device number 4 using ohci-pci
[  161.860504] can: controller area network core (rev 20120528 abi 9)
[  161.860522] NET: Registered protocol family 29
[  177.561620] usb 1-3: USB disconnect, device number 4
[  191.061423] usb 1-2: USB disconnect, device number 3
[  196.095325] usb 1-2: new full-speed USB device number 5 using ohci-pci
[  327.568882] usb 1-2: USB disconnect, device number 5
[  428.594177] CAN device driver interface
[ 1872.551543] usb 1-2: new full-speed USB device number 6 using ohci-pci
[ 1872.809302] usb_8dev 1-2:1.0 can0: firmware: 1.7, hardware: 1.0
[ 1872.809356] usbcore: registered new interface driver usb_8dev
```

ここではデバイスの名前は`can0`です。

この例では、CANバスを500000kbpsの速度だと仮定します。

500000kbps以外にも、125000, 250000kbpsをサポートしています。

```bash
ip link set can0 type can bitrate 500000
ip link set can0 up
ip link show can0
  can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UNKNOWN qlen 10
    link/can
    can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0
    bitrate 500000 sample-point 0.875
    tq 125 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1
    sja1000: tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1
    clock 16000000
```

RCar Gen3ボード上では、`can0`はすでに組み込みデバイスとして存在しているため、CANデバイスは`can1`として認識されます。

```bash
ip link set can1 type can bitrate 500000
ip link set can1 up
ip link show can1
  can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UNKNOWN qlen 10
    link/can
    can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0
    bitrate 500000 sample-point 0.875
    tq 125 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1
    sja1000: tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1
    clock 16000000
```

#### 存在しているCANデバイスの名前を変更する

次のコマンドを用いてCANデバイスの名前の名前を変更し、既に存在している`can0`デバイスを他のものに移動して、他のデバイスを`can0`として使用することができます。

次の例はRcar Gen3ボードでの例です。

```bash
sudo ip link set can0 down
sudo ip link set can0 name bsp-can0
sudo ip link set bsp-can0 up
```

これ以降、USB CANデバイスを接続するとデフォルトで`can0`という名前が付けられます。

### bindingの設定

bindingは起動時にシステム設定ファイル`/etc/dev-mapping.conf`を読み込み、JSONファイルに記述された信号から論理的な名前をシステムによって初期化されたLinuxデバイス名にマッピングします。

ファイル`/etc/dev-mapping.conf`を編集し、`CANbus-mapping`セクションへのマッピングを追加してください。

デフォルトのbinding設定では`hs`と命名されたCANバスを使用します。なので、`hs`を実際のCANバスにマッピングする必要があります。以下はその例です。

- 前章で記述したものとしての仮想CANデバイスの使用

```bash
[CANbus-mapping]
hs="vcan0"
ls="vcan1"
```

- 実際のCANデバイスの使用(CANバストラフィックを`can0`上のものとして仮定)

```bash
[CANbus-mapping]
hs="can0"
ls="can1"
```

- Rcar Gen3ボード上には既存の`can0`組み込みデバイスではなく、OBD2コネクタに接続されたUSB CANアダプタを使用したい場合(`can1`を使用するとします）

```bash
[CANbus-mapping]
hs="can1"
```

> 重大な警告： 設定ファイルで指定したCANバスが、`CAN-config-generator`で生成されたソースファイルで指定されたものと一致していることを確認してください。

### 実行、テスト、使用

`afm-util`ツールを用いたbinding実行の古典的な方法例

```bash
afm-util run low-can-service@4.0
1
```

`afm-util`については[こちら](http://docs.iot.bzh/docs/apis_services/en/dev/reference/af-main/afm-daemons.html#using-afm-util)を参照してください、Application Frameworkのドキュメントも同様です。

しかし、アプリケーションフレームワークが起動時に取得したセキュリティトークンが分からないため、制御や相互作用はできません。

したがって、それをテストするには、bindingを手動で起動する方がよいでしょう。次の例では、ポート1234を使用し、テスト用に空のセキュリティトークンを残します。

```bash
afb-daemon --binding=/var/lib/afm/applications/low-can-service/4.0/lib/afb-low-can.so --rootdir=/var/lib/afm/applications/low-can-service/4.0/ --port=1234 --token=1
NOTICE: binding [/usr/lib/afb/afb-dbus-binding.so] calling registering function afbBindingV1Register
NOTICE: binding /usr/lib/afb/afb-dbus-binding.so loaded with API prefix dbus
NOTICE: binding [/usr/lib/afb/authLogin.so] calling registering function afbBindingV1Register
NOTICE: binding /usr/lib/afb/authLogin.so loaded with API prefix auth
NOTICE: binding [/var/lib/afm/applications/low-can-service/4.0/libs//low-can-binding.so] calling registering function afbBindingV1Register
NOTICE: binding /var/lib/afm/applications/low-can-service/4.0/libs//low-can-binding.so loaded with API prefix low-can
NOTICE: Waiting port=1234 rootdir=/var/lib/afm/applications/low-can-service/4.0/
NOTICE: Browser URL= http:/*localhost:1234
```

別のターミナルで、以前にインストールしたAFB Websocket CLIツールを使用してbindingに接続します。

```bash
afb-client-demo ws://localhost:1234/api?token=1
```

binding APIと直接通信できるインタラクティブなセッションになります。

bindingは、この時点で2つの動詞、_subscribe_および_unsubscribe_を提供します。これはJSON**event**オブジェクトによって引数を取ることができます。

引数の値は、binding用のcppファイルを生成するために使用されるJSONファイルに記述されているCANメッセージ**generic_name**です。

AFB Websocket CLIツールを使用するには、次のようにします。

```bash
<api> <verb> <arguments>
```

- API:**low-can**
- Verb: **subscribe** または **unsubscribe**
- Arguments: **{ "event": "driver.doors.open" }**

### サブスクリプションとアンサブスクリプション

選択したCANイベントをサブスクライブするには、CANメッセージ名をJSON引数にしてsubscribe API verbを呼び出します。

> 注：引数が指定されていない場合、すべてのシグナルを一度にサブスクライブします。

例：websocketセッション

```bash
low-can subscribe { "event": "doors.driver.open" }
ON-REPLY 1:low-can/subscribe: {"jtype":"afb-reply","request":{"status":"success","uuid":"a18fd375-b6fa-4c0e-a1d4-9d3955975ae8"}}
```

event変数中でワイルドカードを使用してサブスクリプション、アンサブスクリプションを設定できます。

全ドアイベントを受信する例：

```bash
low-can subscribe { "event" : "doors*" }
ON-REPLY 1:low-can/subscribe: {"jtype":"afb-reply","request":{"status":"success","uuid":"511c872e-d7f3-4f3b-89c2-aa9a3e9fbbdb"}}
```

次に、doors.driver.openという名前のイベントのCANメッセージがデコードされるたびに、イベントを受信する例です。

```bash
ON-EVENT low-can/messages.doors.driver.open({"event":"low-can\/messages.doors.driver.open","data":{"name":"messages.doors.driver.open","value":true},"jtype":"afb-event"})
```

イベントは、CANイベントの名前がmessages.doors.driver.openであることを示していますが、doors.driver.openに関するイベントを要求しています。

これは、すべてのCANメッセージまたは診断メッセージに、JSON親ノード名、CANメッセージ用の**message**、OBD2などの診断メッセージ用の**diagnostic_messages**のプリフィックスが付与されるためです。

これにより、一度にすべての信号をサブスクライブまたはアンサブスクライブすることができ、推奨されないようになり、そのタイプに基づいてサブスクリプション操作をよりよくフィルタリングできます。

例：

```bash
low-can subscribe { "event" : "*speed*" } --> will subscribe to all messages with speed in their name. Search will be make without prefix for it.
low-can subscribe { "event" : "speed*" } --> will subscribe to all messages begin by speed in their name. Search will be make without prefix for it.
low-can subscribe { "event" : "messages*speed*" } --> will subscribe to all CAN messages with speed in their name. Search will be on prefixed messages here.
low-can subscribe { "event" : "messages*speed" } --> will subscribe to all CAN messages ending with speed in their name. Search will be on prefixed messages here.
low-can subscribe { "event" : "diagnostic*speed*" } --> will subscribe to all diagnostic messages with speed in their name. Search will be on prefixed messages here.
low-can subscribe { "event" : "diagnostic*speed" } --> will subscribe to all diagnostic messages ending with speed in their name. Search will be on prefixed messages here.
```

サブスクライブと同様の方法でシグナルをアンサブスクライブすることで、イベントの受信を停止することができます

```bash
low-can unsubscribe { "event": "doors.driver.open" }
ON-REPLY 2:low-can/unsubscribe: {"jtype":"afb-reply","request":{"status":"success"}}
low-can unsubscribe { "event" : "doors*" }
ON-REPLY 3:low-can/unsubscribe: {"jtype":"afb-reply","request":{"status":"success"}}
```

###### ケイパビリティのフィルタリング

周波数を限定するのと同様に、受信したイベント通知に最小及び最大範囲を設定することができます。

利用可能なフィルターを1つ以上使用することで、引数フィルタを使用することが可能です。

- frequency:
- frequency：指定された信号の新しいCANイベントが通知される頻度をHertzで指定します。ブロックされた時間中にさらに変更されたCANメッセージが受信された場合、最後に有効なものがRX_CHANGEDでロックアウト後に転送されます。
- min：サブスクライブしたクライアントにプッシュされるデコード値の下限値
- max：サブスクライブしたクライアントにプッシュされるデコード値の上限値

順序は選択されたフィルタの数に関係なく、一度に1つ、2つ、またはすべてを使用できます。

使用例：

```bash
low-can subscribe {"event": "messages.engine.speed", "filter": { "frequency": 3, "min": 1250, "max": 3500}}
low-can subscribe {"event": "messages.engine.load", "filter": { "min": 30, "max": 100}}
low-can subscribe {"event": "messages.vehicle.speed", "filter": { "frequency": 2}}
```

#### CANアクティビティモニタリング用途にCAN utilsを使用する

AGLターゲットにプリインストールされたcan-utilsを使用することでCANのトラフィックの監視、カスタムCANメッセージの送信を行うことができます。

CANバスの監視例

```bash
candump can0
```

ポーターボードに接続されたUSB CAN アダプタの場合

```bash
candump can1
```

カスタムメッセージの送信

```bash
cansend can0 ID#DDDDAAAATTTTAAAA
```

以前にダンプされたCANログファイルをリプレイできます。

これらのログファイルはGitリポジトリ下の`can_samples`ディレクトリ内にあります。

以下の例はAuris TOYOTA車で実際の走行に用いられたものです。

トレースはCANデバイス`can0`で記録されたものなので、動作確認の際はテストシステムに正しいデバイスをマッピングすべきです。

仮想CANデバイス`vcan0`でのリプレイ

```bash
canplayer -I trip_test_with_obd2_vehicle_speed_requests vcan0=can0
```

CANデバイス`can0`でのリプレイ

```bash
canplayer -I trip_test_with_obd2_vehicle_speed_requests can0
```

CANデバイス`can1`でのリプレイ（例はポーター）

```bash
canplayer -I trip_test_with_obd2_vehicle_speed_requests can1=can0
```

---

### CANサンプル

### Gitリポジトリクローン

```
git clone https://gerrit.automotivelinux.org/gerrit/apps/low-level-can-service
```

### サンプル

`low-level-can-service/can_samples`に存在。

`init_can.sh`はCANデバイス、`init_vcan.sh`はVCANデバイスのロード等を行うスクリプト。

サンプルはTOYOTA Auris, Ford Focus, Citroenの3つがある。

### 中身

```bash
.
├── can_samples
│   ├── citroen
│   ├── ford
│   │   └── focus
│   └── toyota
│       └── auris
├── conf.d
│   ├── app-templates
│   ├── autobuild
│   │   ├── agl
│   │   └── linux
│   ├── cmake
│   └── wgt
├── docs
│   ├── _layouts
│   │   └── ebook
│   ├── images
│   └── resources
├── examples
│   ├── OBD2
│   ├── agl-vcar
│   ├── basic
│   ├── engine
│   ├── hvac
│   └── toyota
│       └── auris
├── libs
│   ├── bitfield-c
│   │   ├── src
│   │   │   ├── bitfield
│   │   │   └── canutil
│   │   └── tests
│   ├── ini-config
│   ├── isotp-c
│   │   ├── src
│   │   │   └── isotp
│   │   └── tests
│   ├── nanopb
│   │   ├── docs
│   │   │   └── logo
│   │   ├── examples
│   │   │   ├── cmake_simple
│   │   │   ├── network_server
│   │   │   ├── simple
│   │   │   ├── using_double_on_avr
│   │   │   └── using_union_messages
│   │   ├── extra
│   │   ├── generator
│   │   │   ├── nanopb
│   │   │   └── proto
│   │   │       └── google
│   │   │           └── protobuf
│   │   ├── tests
│   │   │   ├── alltypes
│   │   │   ├── alltypes_callback
│   │   │   ├── alltypes_pointer
│   │   │   ├── alltypes_proto3
│   │   │   ├── alltypes_proto3_callback
│   │   │   ├── anonymous_oneof
│   │   │   ├── backwards_compatibility
│   │   │   ├── basic_buffer
│   │   │   ├── basic_stream
│   │   │   ├── buffer_only
│   │   │   ├── callbacks
│   │   │   ├── common
│   │   │   ├── cxx_main_program
│   │   │   ├── cyclic_messages
│   │   │   ├── decode_unittests
│   │   │   ├── encode_unittests
│   │   │   ├── enum_sizes
│   │   │   ├── enum_to_string
│   │   │   ├── extensions
│   │   │   ├── extra_fields
│   │   │   ├── field_size_16
│   │   │   ├── field_size_16_proto3
│   │   │   ├── field_size_32
│   │   │   ├── fuzztest
│   │   │   │   └── sample_data
│   │   │   ├── inline
│   │   │   ├── intsizes
│   │   │   ├── io_errors
│   │   │   ├── io_errors_pointers
│   │   │   ├── mem_release
│   │   │   ├── message_sizes
│   │   │   ├── missing_fields
│   │   │   ├── multiple_files
│   │   │   │   └── subdir
│   │   │   ├── no_errmsg
│   │   │   ├── no_messages
│   │   │   ├── oneof
│   │   │   ├── options
│   │   │   ├── package_name
│   │   │   ├── regression
│   │   │   │   ├── issue_118
│   │   │   │   ├── issue_125
│   │   │   │   ├── issue_141
│   │   │   │   ├── issue_145
│   │   │   │   ├── issue_166
│   │   │   │   ├── issue_172
│   │   │   │   │   └── submessage
│   │   │   │   ├── issue_188
│   │   │   │   ├── issue_195
│   │   │   │   ├── issue_203
│   │   │   │   ├── issue_205
│   │   │   │   ├── issue_227
│   │   │   │   ├── issue_229
│   │   │   │   ├── issue_242
│   │   │   │   ├── issue_247
│   │   │   │   ├── issue_249
│   │   │   │   ├── issue_253
│   │   │   │   └── issue_256
│   │   │   ├── site_scons
│   │   │   │   └── site_tools
│   │   │   ├── special_characters
│   │   │   └── splint
│   │   └── tools
│   ├── openxc-message-format
│   │   ├── benchmark
│   │   │   └── proto
│   │   ├── gen
│   │   │   ├── cpp
│   │   │   ├── java
│   │   │   │   └── com
│   │   │   │       └── openxc
│   │   │   └── python
│   │   └── script
│   └── uds-c
│       ├── src
│       │   └── uds
│       └── tests
└── low-can-binding
    ├── binding
    ├── can
    ├── diagnostic
    └── utils
```