Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: UAVCAN UAVCAN_Subscriber
libuavcan_drivers/linux/apps/test_socket.cpp@0:dfe6edabb8ec, 2018-04-14 (annotated)
- Committer:
- RuslanUrya
- Date:
- Sat Apr 14 10:25:32 2018 +0000
- Revision:
- 0:dfe6edabb8ec
Initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
RuslanUrya | 0:dfe6edabb8ec | 1 | /* |
RuslanUrya | 0:dfe6edabb8ec | 2 | * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com> |
RuslanUrya | 0:dfe6edabb8ec | 3 | */ |
RuslanUrya | 0:dfe6edabb8ec | 4 | |
RuslanUrya | 0:dfe6edabb8ec | 5 | #include <iostream> |
RuslanUrya | 0:dfe6edabb8ec | 6 | #include <vector> |
RuslanUrya | 0:dfe6edabb8ec | 7 | #include <cerrno> |
RuslanUrya | 0:dfe6edabb8ec | 8 | #include <uavcan_linux/uavcan_linux.hpp> |
RuslanUrya | 0:dfe6edabb8ec | 9 | #include "debug.hpp" |
RuslanUrya | 0:dfe6edabb8ec | 10 | |
RuslanUrya | 0:dfe6edabb8ec | 11 | static uavcan::CanFrame makeFrame(std::uint32_t id, const std::string& data) |
RuslanUrya | 0:dfe6edabb8ec | 12 | { |
RuslanUrya | 0:dfe6edabb8ec | 13 | return uavcan::CanFrame(id, reinterpret_cast<const std::uint8_t*>(data.c_str()), data.length()); |
RuslanUrya | 0:dfe6edabb8ec | 14 | } |
RuslanUrya | 0:dfe6edabb8ec | 15 | |
RuslanUrya | 0:dfe6edabb8ec | 16 | static uavcan::MonotonicTime tsMonoOffsetMs(std::int64_t ms) |
RuslanUrya | 0:dfe6edabb8ec | 17 | { |
RuslanUrya | 0:dfe6edabb8ec | 18 | return uavcan_linux::SystemClock().getMonotonic() + uavcan::MonotonicDuration::fromMSec(ms); |
RuslanUrya | 0:dfe6edabb8ec | 19 | } |
RuslanUrya | 0:dfe6edabb8ec | 20 | |
RuslanUrya | 0:dfe6edabb8ec | 21 | static void testNonexistentIface() |
RuslanUrya | 0:dfe6edabb8ec | 22 | { |
RuslanUrya | 0:dfe6edabb8ec | 23 | const int sock1 = uavcan_linux::SocketCanIface::openSocket("noif9"); |
RuslanUrya | 0:dfe6edabb8ec | 24 | ENFORCE(sock1 < 0); |
RuslanUrya | 0:dfe6edabb8ec | 25 | const int sock2 = uavcan_linux::SocketCanIface::openSocket("verylongifacenameverylongifacenameverylongifacename"); |
RuslanUrya | 0:dfe6edabb8ec | 26 | ENFORCE(sock2 < 0); |
RuslanUrya | 0:dfe6edabb8ec | 27 | } |
RuslanUrya | 0:dfe6edabb8ec | 28 | |
RuslanUrya | 0:dfe6edabb8ec | 29 | static void testSocketRxTx(const std::string& iface_name) |
RuslanUrya | 0:dfe6edabb8ec | 30 | { |
RuslanUrya | 0:dfe6edabb8ec | 31 | const int sock1 = uavcan_linux::SocketCanIface::openSocket(iface_name); |
RuslanUrya | 0:dfe6edabb8ec | 32 | const int sock2 = uavcan_linux::SocketCanIface::openSocket(iface_name); |
RuslanUrya | 0:dfe6edabb8ec | 33 | ENFORCE(sock1 >= 0 && sock2 >= 0); |
RuslanUrya | 0:dfe6edabb8ec | 34 | |
RuslanUrya | 0:dfe6edabb8ec | 35 | /* |
RuslanUrya | 0:dfe6edabb8ec | 36 | * Clocks will have some offset from the true system time |
RuslanUrya | 0:dfe6edabb8ec | 37 | * SocketCAN driver must handle this correctly |
RuslanUrya | 0:dfe6edabb8ec | 38 | */ |
RuslanUrya | 0:dfe6edabb8ec | 39 | uavcan_linux::SystemClock clock_impl(uavcan_linux::ClockAdjustmentMode::PerDriverPrivate); |
RuslanUrya | 0:dfe6edabb8ec | 40 | clock_impl.adjustUtc(uavcan::UtcDuration::fromMSec(100000)); |
RuslanUrya | 0:dfe6edabb8ec | 41 | const uavcan_linux::SystemClock& clock = clock_impl; |
RuslanUrya | 0:dfe6edabb8ec | 42 | |
RuslanUrya | 0:dfe6edabb8ec | 43 | uavcan_linux::SocketCanIface if1(clock, sock1); |
RuslanUrya | 0:dfe6edabb8ec | 44 | uavcan_linux::SocketCanIface if2(clock, sock2); |
RuslanUrya | 0:dfe6edabb8ec | 45 | |
RuslanUrya | 0:dfe6edabb8ec | 46 | /* |
RuslanUrya | 0:dfe6edabb8ec | 47 | * Sending two frames, one of which must be returned back |
RuslanUrya | 0:dfe6edabb8ec | 48 | */ |
RuslanUrya | 0:dfe6edabb8ec | 49 | ENFORCE(1 == if1.send(makeFrame(123, "if1-1"), tsMonoOffsetMs(100), 0)); |
RuslanUrya | 0:dfe6edabb8ec | 50 | ENFORCE(1 == if1.send(makeFrame(456, "if1-2"), tsMonoOffsetMs(100), uavcan::CanIOFlagLoopback)); |
RuslanUrya | 0:dfe6edabb8ec | 51 | if1.poll(true, true); |
RuslanUrya | 0:dfe6edabb8ec | 52 | if1.poll(true, true); |
RuslanUrya | 0:dfe6edabb8ec | 53 | ENFORCE(0 == if1.getErrorCount()); |
RuslanUrya | 0:dfe6edabb8ec | 54 | ENFORCE(!if1.hasReadyTx()); |
RuslanUrya | 0:dfe6edabb8ec | 55 | ENFORCE(if1.hasReadyRx()); // Second loopback |
RuslanUrya | 0:dfe6edabb8ec | 56 | |
RuslanUrya | 0:dfe6edabb8ec | 57 | /* |
RuslanUrya | 0:dfe6edabb8ec | 58 | * Second iface, same thing |
RuslanUrya | 0:dfe6edabb8ec | 59 | */ |
RuslanUrya | 0:dfe6edabb8ec | 60 | ENFORCE(1 == if2.send(makeFrame(321, "if2-1"), tsMonoOffsetMs(100), 0)); |
RuslanUrya | 0:dfe6edabb8ec | 61 | ENFORCE(1 == if2.send(makeFrame(654, "if2-2"), tsMonoOffsetMs(100), uavcan::CanIOFlagLoopback)); |
RuslanUrya | 0:dfe6edabb8ec | 62 | ENFORCE(1 == if2.send(makeFrame(1, "discard"), tsMonoOffsetMs(-1), uavcan::CanIOFlagLoopback)); // Will timeout |
RuslanUrya | 0:dfe6edabb8ec | 63 | if2.poll(true, true); |
RuslanUrya | 0:dfe6edabb8ec | 64 | if2.poll(true, true); |
RuslanUrya | 0:dfe6edabb8ec | 65 | ENFORCE(1 == if2.getErrorCount()); // One timed out |
RuslanUrya | 0:dfe6edabb8ec | 66 | ENFORCE(!if2.hasReadyTx()); |
RuslanUrya | 0:dfe6edabb8ec | 67 | ENFORCE(if2.hasReadyRx()); |
RuslanUrya | 0:dfe6edabb8ec | 68 | |
RuslanUrya | 0:dfe6edabb8ec | 69 | /* |
RuslanUrya | 0:dfe6edabb8ec | 70 | * No-op |
RuslanUrya | 0:dfe6edabb8ec | 71 | */ |
RuslanUrya | 0:dfe6edabb8ec | 72 | if1.poll(true, true); |
RuslanUrya | 0:dfe6edabb8ec | 73 | if2.poll(true, true); |
RuslanUrya | 0:dfe6edabb8ec | 74 | |
RuslanUrya | 0:dfe6edabb8ec | 75 | uavcan::CanFrame frame; |
RuslanUrya | 0:dfe6edabb8ec | 76 | uavcan::MonotonicTime ts_mono; |
RuslanUrya | 0:dfe6edabb8ec | 77 | uavcan::UtcTime ts_utc; |
RuslanUrya | 0:dfe6edabb8ec | 78 | uavcan::CanIOFlags flags = 0; |
RuslanUrya | 0:dfe6edabb8ec | 79 | |
RuslanUrya | 0:dfe6edabb8ec | 80 | /* |
RuslanUrya | 0:dfe6edabb8ec | 81 | * Read first |
RuslanUrya | 0:dfe6edabb8ec | 82 | */ |
RuslanUrya | 0:dfe6edabb8ec | 83 | ENFORCE(1 == if1.receive(frame, ts_mono, ts_utc, flags)); |
RuslanUrya | 0:dfe6edabb8ec | 84 | ENFORCE(frame == makeFrame(456, "if1-2")); |
RuslanUrya | 0:dfe6edabb8ec | 85 | ENFORCE(flags == uavcan::CanIOFlagLoopback); |
RuslanUrya | 0:dfe6edabb8ec | 86 | ENFORCE((clock.getMonotonic() - ts_mono).getAbs().toMSec() < 10); |
RuslanUrya | 0:dfe6edabb8ec | 87 | ENFORCE((clock.getUtc() - ts_utc).getAbs().toMSec() < 10); |
RuslanUrya | 0:dfe6edabb8ec | 88 | |
RuslanUrya | 0:dfe6edabb8ec | 89 | ENFORCE(1 == if1.receive(frame, ts_mono, ts_utc, flags)); |
RuslanUrya | 0:dfe6edabb8ec | 90 | ENFORCE(frame == makeFrame(321, "if2-1")); |
RuslanUrya | 0:dfe6edabb8ec | 91 | ENFORCE(flags == 0); |
RuslanUrya | 0:dfe6edabb8ec | 92 | ENFORCE(!ts_mono.isZero()); |
RuslanUrya | 0:dfe6edabb8ec | 93 | ENFORCE(!ts_utc.isZero()); |
RuslanUrya | 0:dfe6edabb8ec | 94 | ENFORCE((clock.getMonotonic() - ts_mono).getAbs().toMSec() < 10); |
RuslanUrya | 0:dfe6edabb8ec | 95 | ENFORCE((clock.getUtc() - ts_utc).getAbs().toMSec() < 10); |
RuslanUrya | 0:dfe6edabb8ec | 96 | |
RuslanUrya | 0:dfe6edabb8ec | 97 | ENFORCE(1 == if1.receive(frame, ts_mono, ts_utc, flags)); |
RuslanUrya | 0:dfe6edabb8ec | 98 | ENFORCE(frame == makeFrame(654, "if2-2")); |
RuslanUrya | 0:dfe6edabb8ec | 99 | ENFORCE(flags == 0); |
RuslanUrya | 0:dfe6edabb8ec | 100 | ENFORCE((clock.getMonotonic() - ts_mono).getAbs().toMSec() < 10); |
RuslanUrya | 0:dfe6edabb8ec | 101 | ENFORCE((clock.getUtc() - ts_utc).getAbs().toMSec() < 10); |
RuslanUrya | 0:dfe6edabb8ec | 102 | |
RuslanUrya | 0:dfe6edabb8ec | 103 | ENFORCE(0 == if1.receive(frame, ts_mono, ts_utc, flags)); |
RuslanUrya | 0:dfe6edabb8ec | 104 | ENFORCE(!if1.hasReadyTx()); |
RuslanUrya | 0:dfe6edabb8ec | 105 | ENFORCE(!if1.hasReadyRx()); |
RuslanUrya | 0:dfe6edabb8ec | 106 | |
RuslanUrya | 0:dfe6edabb8ec | 107 | /* |
RuslanUrya | 0:dfe6edabb8ec | 108 | * Read second |
RuslanUrya | 0:dfe6edabb8ec | 109 | */ |
RuslanUrya | 0:dfe6edabb8ec | 110 | ENFORCE(1 == if2.receive(frame, ts_mono, ts_utc, flags)); |
RuslanUrya | 0:dfe6edabb8ec | 111 | ENFORCE(frame == makeFrame(123, "if1-1")); |
RuslanUrya | 0:dfe6edabb8ec | 112 | ENFORCE(flags == 0); |
RuslanUrya | 0:dfe6edabb8ec | 113 | ENFORCE((clock.getMonotonic() - ts_mono).getAbs().toMSec() < 10); |
RuslanUrya | 0:dfe6edabb8ec | 114 | ENFORCE((clock.getUtc() - ts_utc).getAbs().toMSec() < 10); |
RuslanUrya | 0:dfe6edabb8ec | 115 | |
RuslanUrya | 0:dfe6edabb8ec | 116 | ENFORCE(1 == if2.receive(frame, ts_mono, ts_utc, flags)); |
RuslanUrya | 0:dfe6edabb8ec | 117 | ENFORCE(frame == makeFrame(456, "if1-2")); |
RuslanUrya | 0:dfe6edabb8ec | 118 | ENFORCE(flags == 0); |
RuslanUrya | 0:dfe6edabb8ec | 119 | ENFORCE((clock.getMonotonic() - ts_mono).getAbs().toMSec() < 10); |
RuslanUrya | 0:dfe6edabb8ec | 120 | ENFORCE((clock.getUtc() - ts_utc).getAbs().toMSec() < 10); |
RuslanUrya | 0:dfe6edabb8ec | 121 | |
RuslanUrya | 0:dfe6edabb8ec | 122 | ENFORCE(1 == if2.receive(frame, ts_mono, ts_utc, flags)); |
RuslanUrya | 0:dfe6edabb8ec | 123 | ENFORCE(frame == makeFrame(654, "if2-2")); |
RuslanUrya | 0:dfe6edabb8ec | 124 | ENFORCE(flags == uavcan::CanIOFlagLoopback); |
RuslanUrya | 0:dfe6edabb8ec | 125 | ENFORCE((clock.getMonotonic() - ts_mono).getAbs().toMSec() < 10); |
RuslanUrya | 0:dfe6edabb8ec | 126 | ENFORCE((clock.getUtc() - ts_utc).getAbs().toMSec() < 10); |
RuslanUrya | 0:dfe6edabb8ec | 127 | |
RuslanUrya | 0:dfe6edabb8ec | 128 | ENFORCE(0 == if2.receive(frame, ts_mono, ts_utc, flags)); |
RuslanUrya | 0:dfe6edabb8ec | 129 | ENFORCE(!if2.hasReadyTx()); |
RuslanUrya | 0:dfe6edabb8ec | 130 | ENFORCE(!if2.hasReadyRx()); |
RuslanUrya | 0:dfe6edabb8ec | 131 | } |
RuslanUrya | 0:dfe6edabb8ec | 132 | |
RuslanUrya | 0:dfe6edabb8ec | 133 | static void testSocketFilters(const std::string& iface_name) |
RuslanUrya | 0:dfe6edabb8ec | 134 | { |
RuslanUrya | 0:dfe6edabb8ec | 135 | using uavcan::CanFrame; |
RuslanUrya | 0:dfe6edabb8ec | 136 | |
RuslanUrya | 0:dfe6edabb8ec | 137 | const int sock1 = uavcan_linux::SocketCanIface::openSocket(iface_name); |
RuslanUrya | 0:dfe6edabb8ec | 138 | const int sock2 = uavcan_linux::SocketCanIface::openSocket(iface_name); |
RuslanUrya | 0:dfe6edabb8ec | 139 | ENFORCE(sock1 >= 0 && sock2 >= 0); |
RuslanUrya | 0:dfe6edabb8ec | 140 | |
RuslanUrya | 0:dfe6edabb8ec | 141 | /* |
RuslanUrya | 0:dfe6edabb8ec | 142 | * Clocks will have some offset from the true system time |
RuslanUrya | 0:dfe6edabb8ec | 143 | * SocketCAN driver must handle this correctly |
RuslanUrya | 0:dfe6edabb8ec | 144 | */ |
RuslanUrya | 0:dfe6edabb8ec | 145 | uavcan_linux::SystemClock clock_impl(uavcan_linux::ClockAdjustmentMode::PerDriverPrivate); |
RuslanUrya | 0:dfe6edabb8ec | 146 | clock_impl.adjustUtc(uavcan::UtcDuration::fromMSec(-1000)); |
RuslanUrya | 0:dfe6edabb8ec | 147 | const uavcan_linux::SystemClock& clock = clock_impl; |
RuslanUrya | 0:dfe6edabb8ec | 148 | |
RuslanUrya | 0:dfe6edabb8ec | 149 | uavcan_linux::SocketCanIface if1(clock, sock1); |
RuslanUrya | 0:dfe6edabb8ec | 150 | uavcan_linux::SocketCanIface if2(clock, sock2); |
RuslanUrya | 0:dfe6edabb8ec | 151 | |
RuslanUrya | 0:dfe6edabb8ec | 152 | /* |
RuslanUrya | 0:dfe6edabb8ec | 153 | * Configuring filters |
RuslanUrya | 0:dfe6edabb8ec | 154 | */ |
RuslanUrya | 0:dfe6edabb8ec | 155 | uavcan::CanFilterConfig fcs[3]; |
RuslanUrya | 0:dfe6edabb8ec | 156 | // STD/EXT 123 |
RuslanUrya | 0:dfe6edabb8ec | 157 | fcs[0].id = 123; |
RuslanUrya | 0:dfe6edabb8ec | 158 | fcs[0].mask = CanFrame::MaskExtID; |
RuslanUrya | 0:dfe6edabb8ec | 159 | // Only EXT 456789 |
RuslanUrya | 0:dfe6edabb8ec | 160 | fcs[1].id = 456789 | CanFrame::FlagEFF; |
RuslanUrya | 0:dfe6edabb8ec | 161 | fcs[1].mask = CanFrame::MaskExtID | CanFrame::FlagEFF; |
RuslanUrya | 0:dfe6edabb8ec | 162 | // Only STD 0 |
RuslanUrya | 0:dfe6edabb8ec | 163 | fcs[2].id = 0; |
RuslanUrya | 0:dfe6edabb8ec | 164 | fcs[2].mask = CanFrame::MaskExtID | CanFrame::FlagEFF; |
RuslanUrya | 0:dfe6edabb8ec | 165 | |
RuslanUrya | 0:dfe6edabb8ec | 166 | ENFORCE(0 == if2.configureFilters(fcs, 3)); |
RuslanUrya | 0:dfe6edabb8ec | 167 | |
RuslanUrya | 0:dfe6edabb8ec | 168 | /* |
RuslanUrya | 0:dfe6edabb8ec | 169 | * Sending data from 1 to 2, making sure only filtered data will be accepted |
RuslanUrya | 0:dfe6edabb8ec | 170 | */ |
RuslanUrya | 0:dfe6edabb8ec | 171 | const auto EFF = CanFrame::FlagEFF; |
RuslanUrya | 0:dfe6edabb8ec | 172 | ENFORCE(1 == if1.send(makeFrame(123, "1"), tsMonoOffsetMs(100), 0)); // Accept 0 |
RuslanUrya | 0:dfe6edabb8ec | 173 | ENFORCE(1 == if1.send(makeFrame(123 | EFF, "2"), tsMonoOffsetMs(100), 0)); // Accept 0 |
RuslanUrya | 0:dfe6edabb8ec | 174 | ENFORCE(1 == if1.send(makeFrame(456, "3"), tsMonoOffsetMs(100), 0)); // Drop |
RuslanUrya | 0:dfe6edabb8ec | 175 | ENFORCE(1 == if1.send(makeFrame(456789, "4"), tsMonoOffsetMs(100), 0)); // Drop |
RuslanUrya | 0:dfe6edabb8ec | 176 | ENFORCE(1 == if1.send(makeFrame(456789 | EFF, "5"), tsMonoOffsetMs(100), 0)); // Accept 1 |
RuslanUrya | 0:dfe6edabb8ec | 177 | ENFORCE(1 == if1.send(makeFrame(0, "6"), tsMonoOffsetMs(100), 0)); // Accept 2 |
RuslanUrya | 0:dfe6edabb8ec | 178 | ENFORCE(1 == if1.send(makeFrame(EFF, "7"), tsMonoOffsetMs(100), 0)); // Drop |
RuslanUrya | 0:dfe6edabb8ec | 179 | |
RuslanUrya | 0:dfe6edabb8ec | 180 | for (int i = 0; i < 7; i++) |
RuslanUrya | 0:dfe6edabb8ec | 181 | { |
RuslanUrya | 0:dfe6edabb8ec | 182 | if1.poll(true, true); |
RuslanUrya | 0:dfe6edabb8ec | 183 | if2.poll(true, false); |
RuslanUrya | 0:dfe6edabb8ec | 184 | } |
RuslanUrya | 0:dfe6edabb8ec | 185 | ENFORCE(!if1.hasReadyTx()); |
RuslanUrya | 0:dfe6edabb8ec | 186 | ENFORCE(!if1.hasReadyRx()); |
RuslanUrya | 0:dfe6edabb8ec | 187 | ENFORCE(0 == if1.getErrorCount()); |
RuslanUrya | 0:dfe6edabb8ec | 188 | ENFORCE(if2.hasReadyRx()); |
RuslanUrya | 0:dfe6edabb8ec | 189 | |
RuslanUrya | 0:dfe6edabb8ec | 190 | /* |
RuslanUrya | 0:dfe6edabb8ec | 191 | * Checking RX on 2 |
RuslanUrya | 0:dfe6edabb8ec | 192 | */ |
RuslanUrya | 0:dfe6edabb8ec | 193 | uavcan::CanFrame frame; |
RuslanUrya | 0:dfe6edabb8ec | 194 | uavcan::MonotonicTime ts_mono; |
RuslanUrya | 0:dfe6edabb8ec | 195 | uavcan::UtcTime ts_utc; |
RuslanUrya | 0:dfe6edabb8ec | 196 | uavcan::CanIOFlags flags = 0; |
RuslanUrya | 0:dfe6edabb8ec | 197 | |
RuslanUrya | 0:dfe6edabb8ec | 198 | ENFORCE(1 == if2.receive(frame, ts_mono, ts_utc, flags)); |
RuslanUrya | 0:dfe6edabb8ec | 199 | ENFORCE(frame == makeFrame(123, "1")); |
RuslanUrya | 0:dfe6edabb8ec | 200 | |
RuslanUrya | 0:dfe6edabb8ec | 201 | ENFORCE(1 == if2.receive(frame, ts_mono, ts_utc, flags)); |
RuslanUrya | 0:dfe6edabb8ec | 202 | ENFORCE(frame == makeFrame(123 | EFF, "2")); |
RuslanUrya | 0:dfe6edabb8ec | 203 | |
RuslanUrya | 0:dfe6edabb8ec | 204 | ENFORCE(1 == if2.receive(frame, ts_mono, ts_utc, flags)); |
RuslanUrya | 0:dfe6edabb8ec | 205 | ENFORCE(frame == makeFrame(456789 | EFF, "5")); |
RuslanUrya | 0:dfe6edabb8ec | 206 | |
RuslanUrya | 0:dfe6edabb8ec | 207 | ENFORCE(1 == if2.receive(frame, ts_mono, ts_utc, flags)); |
RuslanUrya | 0:dfe6edabb8ec | 208 | ENFORCE(frame == makeFrame(0, "6")); |
RuslanUrya | 0:dfe6edabb8ec | 209 | ENFORCE(flags == 0); |
RuslanUrya | 0:dfe6edabb8ec | 210 | |
RuslanUrya | 0:dfe6edabb8ec | 211 | ENFORCE(!if2.hasReadyRx()); |
RuslanUrya | 0:dfe6edabb8ec | 212 | } |
RuslanUrya | 0:dfe6edabb8ec | 213 | |
RuslanUrya | 0:dfe6edabb8ec | 214 | static void testDriver(const std::vector<std::string>& iface_names) |
RuslanUrya | 0:dfe6edabb8ec | 215 | { |
RuslanUrya | 0:dfe6edabb8ec | 216 | /* |
RuslanUrya | 0:dfe6edabb8ec | 217 | * Clocks will have some offset from the true system time |
RuslanUrya | 0:dfe6edabb8ec | 218 | * SocketCAN driver must handle this correctly |
RuslanUrya | 0:dfe6edabb8ec | 219 | */ |
RuslanUrya | 0:dfe6edabb8ec | 220 | uavcan_linux::SystemClock clock_impl(uavcan_linux::ClockAdjustmentMode::PerDriverPrivate); |
RuslanUrya | 0:dfe6edabb8ec | 221 | clock_impl.adjustUtc(uavcan::UtcDuration::fromMSec(9000000)); |
RuslanUrya | 0:dfe6edabb8ec | 222 | const uavcan_linux::SystemClock& clock = clock_impl; |
RuslanUrya | 0:dfe6edabb8ec | 223 | |
RuslanUrya | 0:dfe6edabb8ec | 224 | uavcan_linux::SocketCanDriver driver(clock); |
RuslanUrya | 0:dfe6edabb8ec | 225 | for (auto ifn : iface_names) |
RuslanUrya | 0:dfe6edabb8ec | 226 | { |
RuslanUrya | 0:dfe6edabb8ec | 227 | std::cout << "Adding iface " << ifn << std::endl; |
RuslanUrya | 0:dfe6edabb8ec | 228 | ENFORCE(0 == driver.addIface(ifn)); |
RuslanUrya | 0:dfe6edabb8ec | 229 | } |
RuslanUrya | 0:dfe6edabb8ec | 230 | |
RuslanUrya | 0:dfe6edabb8ec | 231 | ENFORCE(-1 == driver.addIface("noif9")); |
RuslanUrya | 0:dfe6edabb8ec | 232 | ENFORCE(-1 == driver.addIface("noif9")); |
RuslanUrya | 0:dfe6edabb8ec | 233 | ENFORCE(-1 == driver.addIface("noif9")); |
RuslanUrya | 0:dfe6edabb8ec | 234 | |
RuslanUrya | 0:dfe6edabb8ec | 235 | ENFORCE(driver.getNumIfaces() == iface_names.size()); |
RuslanUrya | 0:dfe6edabb8ec | 236 | ENFORCE(nullptr == driver.getIface(255)); |
RuslanUrya | 0:dfe6edabb8ec | 237 | ENFORCE(nullptr == driver.getIface(driver.getNumIfaces())); |
RuslanUrya | 0:dfe6edabb8ec | 238 | |
RuslanUrya | 0:dfe6edabb8ec | 239 | const uavcan::CanFrame* pending_tx[uavcan::MaxCanIfaces] = {}; |
RuslanUrya | 0:dfe6edabb8ec | 240 | |
RuslanUrya | 0:dfe6edabb8ec | 241 | const unsigned AllIfacesMask = (1 << driver.getNumIfaces()) - 1; |
RuslanUrya | 0:dfe6edabb8ec | 242 | |
RuslanUrya | 0:dfe6edabb8ec | 243 | /* |
RuslanUrya | 0:dfe6edabb8ec | 244 | * Send, no loopback |
RuslanUrya | 0:dfe6edabb8ec | 245 | */ |
RuslanUrya | 0:dfe6edabb8ec | 246 | std::cout << "select() 1" << std::endl; |
RuslanUrya | 0:dfe6edabb8ec | 247 | uavcan::CanSelectMasks masks; // Driver provides masks for all available events |
RuslanUrya | 0:dfe6edabb8ec | 248 | ENFORCE(driver.getNumIfaces() == driver.select(masks, pending_tx, tsMonoOffsetMs(1000))); |
RuslanUrya | 0:dfe6edabb8ec | 249 | ENFORCE(masks.read == 0); |
RuslanUrya | 0:dfe6edabb8ec | 250 | ENFORCE(masks.write == AllIfacesMask); |
RuslanUrya | 0:dfe6edabb8ec | 251 | |
RuslanUrya | 0:dfe6edabb8ec | 252 | for (int i = 0; i < driver.getNumIfaces(); i++) |
RuslanUrya | 0:dfe6edabb8ec | 253 | { |
RuslanUrya | 0:dfe6edabb8ec | 254 | ENFORCE(1 == driver.getIface(i)->send(makeFrame(123, std::to_string(i)), tsMonoOffsetMs(10), 0)); |
RuslanUrya | 0:dfe6edabb8ec | 255 | } |
RuslanUrya | 0:dfe6edabb8ec | 256 | |
RuslanUrya | 0:dfe6edabb8ec | 257 | std::cout << "select() 2" << std::endl; |
RuslanUrya | 0:dfe6edabb8ec | 258 | ENFORCE(driver.getNumIfaces() == driver.select(masks, pending_tx, tsMonoOffsetMs(1000))); |
RuslanUrya | 0:dfe6edabb8ec | 259 | ENFORCE(masks.read == 0); |
RuslanUrya | 0:dfe6edabb8ec | 260 | ENFORCE(masks.write == AllIfacesMask); |
RuslanUrya | 0:dfe6edabb8ec | 261 | |
RuslanUrya | 0:dfe6edabb8ec | 262 | /* |
RuslanUrya | 0:dfe6edabb8ec | 263 | * Send with loopback |
RuslanUrya | 0:dfe6edabb8ec | 264 | */ |
RuslanUrya | 0:dfe6edabb8ec | 265 | for (int i = 0; i < driver.getNumIfaces(); i++) |
RuslanUrya | 0:dfe6edabb8ec | 266 | { |
RuslanUrya | 0:dfe6edabb8ec | 267 | ENFORCE(1 == driver.getIface(i)->send(makeFrame(456, std::to_string(i)), tsMonoOffsetMs(10), |
RuslanUrya | 0:dfe6edabb8ec | 268 | uavcan::CanIOFlagLoopback)); |
RuslanUrya | 0:dfe6edabb8ec | 269 | ENFORCE(1 == driver.getIface(i)->send(makeFrame(789, std::to_string(i)), tsMonoOffsetMs(-1), // Will timeout |
RuslanUrya | 0:dfe6edabb8ec | 270 | uavcan::CanIOFlagLoopback)); |
RuslanUrya | 0:dfe6edabb8ec | 271 | } |
RuslanUrya | 0:dfe6edabb8ec | 272 | |
RuslanUrya | 0:dfe6edabb8ec | 273 | std::cout << "select() 3" << std::endl; |
RuslanUrya | 0:dfe6edabb8ec | 274 | ENFORCE(driver.getNumIfaces() == driver.select(masks, pending_tx, tsMonoOffsetMs(1000))); |
RuslanUrya | 0:dfe6edabb8ec | 275 | ENFORCE(masks.read == AllIfacesMask); |
RuslanUrya | 0:dfe6edabb8ec | 276 | ENFORCE(masks.write == AllIfacesMask); |
RuslanUrya | 0:dfe6edabb8ec | 277 | |
RuslanUrya | 0:dfe6edabb8ec | 278 | /* |
RuslanUrya | 0:dfe6edabb8ec | 279 | * Receive loopback |
RuslanUrya | 0:dfe6edabb8ec | 280 | */ |
RuslanUrya | 0:dfe6edabb8ec | 281 | for (int i = 0; i < driver.getNumIfaces(); i++) |
RuslanUrya | 0:dfe6edabb8ec | 282 | { |
RuslanUrya | 0:dfe6edabb8ec | 283 | uavcan::CanFrame frame; |
RuslanUrya | 0:dfe6edabb8ec | 284 | uavcan::MonotonicTime ts_mono; |
RuslanUrya | 0:dfe6edabb8ec | 285 | uavcan::UtcTime ts_utc; |
RuslanUrya | 0:dfe6edabb8ec | 286 | uavcan::CanIOFlags flags = 0; |
RuslanUrya | 0:dfe6edabb8ec | 287 | ENFORCE(1 == driver.getIface(i)->receive(frame, ts_mono, ts_utc, flags)); |
RuslanUrya | 0:dfe6edabb8ec | 288 | ENFORCE(frame == makeFrame(456, std::to_string(i))); |
RuslanUrya | 0:dfe6edabb8ec | 289 | ENFORCE(flags == uavcan::CanIOFlagLoopback); |
RuslanUrya | 0:dfe6edabb8ec | 290 | ENFORCE((clock.getMonotonic() - ts_mono).getAbs().toMSec() < 10); |
RuslanUrya | 0:dfe6edabb8ec | 291 | ENFORCE((clock.getUtc() - ts_utc).getAbs().toMSec() < 10); |
RuslanUrya | 0:dfe6edabb8ec | 292 | |
RuslanUrya | 0:dfe6edabb8ec | 293 | ENFORCE(!driver.getIface(i)->hasReadyTx()); |
RuslanUrya | 0:dfe6edabb8ec | 294 | ENFORCE(!driver.getIface(i)->hasReadyRx()); |
RuslanUrya | 0:dfe6edabb8ec | 295 | } |
RuslanUrya | 0:dfe6edabb8ec | 296 | |
RuslanUrya | 0:dfe6edabb8ec | 297 | std::cout << "select() 4" << std::endl; |
RuslanUrya | 0:dfe6edabb8ec | 298 | masks.write = 0; |
RuslanUrya | 0:dfe6edabb8ec | 299 | ENFORCE(driver.getNumIfaces() == driver.select(masks, pending_tx, tsMonoOffsetMs(1000))); |
RuslanUrya | 0:dfe6edabb8ec | 300 | ENFORCE(masks.read == 0); |
RuslanUrya | 0:dfe6edabb8ec | 301 | ENFORCE(masks.write == AllIfacesMask); |
RuslanUrya | 0:dfe6edabb8ec | 302 | |
RuslanUrya | 0:dfe6edabb8ec | 303 | std::cout << "exit" << std::endl; |
RuslanUrya | 0:dfe6edabb8ec | 304 | |
RuslanUrya | 0:dfe6edabb8ec | 305 | /* |
RuslanUrya | 0:dfe6edabb8ec | 306 | * Error checks |
RuslanUrya | 0:dfe6edabb8ec | 307 | */ |
RuslanUrya | 0:dfe6edabb8ec | 308 | for (int i = 0; i < driver.getNumIfaces(); i++) |
RuslanUrya | 0:dfe6edabb8ec | 309 | { |
RuslanUrya | 0:dfe6edabb8ec | 310 | for (auto kv : driver.getIface(i)->getErrors()) |
RuslanUrya | 0:dfe6edabb8ec | 311 | { |
RuslanUrya | 0:dfe6edabb8ec | 312 | switch (kv.first) |
RuslanUrya | 0:dfe6edabb8ec | 313 | { |
RuslanUrya | 0:dfe6edabb8ec | 314 | case uavcan_linux::SocketCanError::SocketReadFailure: |
RuslanUrya | 0:dfe6edabb8ec | 315 | case uavcan_linux::SocketCanError::SocketWriteFailure: |
RuslanUrya | 0:dfe6edabb8ec | 316 | { |
RuslanUrya | 0:dfe6edabb8ec | 317 | ENFORCE(kv.second == 0); |
RuslanUrya | 0:dfe6edabb8ec | 318 | break; |
RuslanUrya | 0:dfe6edabb8ec | 319 | } |
RuslanUrya | 0:dfe6edabb8ec | 320 | case uavcan_linux::SocketCanError::TxTimeout: |
RuslanUrya | 0:dfe6edabb8ec | 321 | { |
RuslanUrya | 0:dfe6edabb8ec | 322 | ENFORCE(kv.second == 1); // One timed out frame from the above |
RuslanUrya | 0:dfe6edabb8ec | 323 | break; |
RuslanUrya | 0:dfe6edabb8ec | 324 | } |
RuslanUrya | 0:dfe6edabb8ec | 325 | default: |
RuslanUrya | 0:dfe6edabb8ec | 326 | { |
RuslanUrya | 0:dfe6edabb8ec | 327 | ENFORCE(false); |
RuslanUrya | 0:dfe6edabb8ec | 328 | break; |
RuslanUrya | 0:dfe6edabb8ec | 329 | } |
RuslanUrya | 0:dfe6edabb8ec | 330 | } |
RuslanUrya | 0:dfe6edabb8ec | 331 | } |
RuslanUrya | 0:dfe6edabb8ec | 332 | } |
RuslanUrya | 0:dfe6edabb8ec | 333 | } |
RuslanUrya | 0:dfe6edabb8ec | 334 | |
RuslanUrya | 0:dfe6edabb8ec | 335 | int main(int argc, const char** argv) |
RuslanUrya | 0:dfe6edabb8ec | 336 | { |
RuslanUrya | 0:dfe6edabb8ec | 337 | try |
RuslanUrya | 0:dfe6edabb8ec | 338 | { |
RuslanUrya | 0:dfe6edabb8ec | 339 | if (argc < 2) |
RuslanUrya | 0:dfe6edabb8ec | 340 | { |
RuslanUrya | 0:dfe6edabb8ec | 341 | std::cerr << "Usage:\n\t" << argv[0] << " <can-iface-name-1> [can-iface-name-N...]" << std::endl; |
RuslanUrya | 0:dfe6edabb8ec | 342 | return 1; |
RuslanUrya | 0:dfe6edabb8ec | 343 | } |
RuslanUrya | 0:dfe6edabb8ec | 344 | |
RuslanUrya | 0:dfe6edabb8ec | 345 | std::vector<std::string> iface_names; |
RuslanUrya | 0:dfe6edabb8ec | 346 | for (int i = 1; i < argc; i++) |
RuslanUrya | 0:dfe6edabb8ec | 347 | { |
RuslanUrya | 0:dfe6edabb8ec | 348 | iface_names.emplace_back(argv[i]); |
RuslanUrya | 0:dfe6edabb8ec | 349 | } |
RuslanUrya | 0:dfe6edabb8ec | 350 | |
RuslanUrya | 0:dfe6edabb8ec | 351 | testNonexistentIface(); |
RuslanUrya | 0:dfe6edabb8ec | 352 | testSocketRxTx(iface_names[0]); |
RuslanUrya | 0:dfe6edabb8ec | 353 | testSocketFilters(iface_names[0]); |
RuslanUrya | 0:dfe6edabb8ec | 354 | |
RuslanUrya | 0:dfe6edabb8ec | 355 | testDriver(iface_names); |
RuslanUrya | 0:dfe6edabb8ec | 356 | |
RuslanUrya | 0:dfe6edabb8ec | 357 | return 0; |
RuslanUrya | 0:dfe6edabb8ec | 358 | } |
RuslanUrya | 0:dfe6edabb8ec | 359 | catch (const std::exception& ex) |
RuslanUrya | 0:dfe6edabb8ec | 360 | { |
RuslanUrya | 0:dfe6edabb8ec | 361 | std::cerr << "Exception: " << ex.what() << std::endl; |
RuslanUrya | 0:dfe6edabb8ec | 362 | return 1; |
RuslanUrya | 0:dfe6edabb8ec | 363 | } |
RuslanUrya | 0:dfe6edabb8ec | 364 | } |