Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions epoll/src/main/java/tel/schich/javacan/util/CanBroker.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import tel.schich.javacan.select.SelectorRegistration;

import static java.time.Duration.ofMinutes;
import static tel.schich.javacan.CanSocketOptions.FD_FRAMES;
import static tel.schich.javacan.CanSocketOptions.FILTER;
import static tel.schich.javacan.CanSocketOptions.LOOPBACK;

Expand All @@ -73,6 +74,7 @@ public class CanBroker extends EventLoop<UnixFileDescriptor, RawCanChannel> {
private final Object filterLock = new Object();

private volatile boolean loopback = true;
private volatile boolean fdFrames = false;

public CanBroker(ThreadFactory threadFactory, IOSelector<UnixFileDescriptor> selector) {
this(threadFactory, selector, DEFAULT_TIMEOUT);
Expand Down Expand Up @@ -134,6 +136,26 @@ public boolean isLoopback() {
return loopback;
}

/**
* Sets whether all known devices accept and send CAN FD frames.
*
* @param enable whether to enable CAN FD frames
* @throws IOException if the native call fails
*/
public synchronized void setFdFrames(boolean enable) throws IOException {
this.fdFrames = enable;
this.updateOption(FD_FRAMES, enable);
}

/**
* Checks if the devices of this broker accept and send CAN FD frames.
*
* @return true if the devices accept and send CAN FD frames
*/
public boolean isFdFrames() {
return fdFrames;
}

/**
* Adds a filter that will be added to all underlying channels.
*
Expand Down Expand Up @@ -228,6 +250,7 @@ public void addDevice(NetworkDevice device, FrameHandler handler) throws IOExcep
ch.configureBlocking(false);
ch.setOption(FILTER, filterArray);
ch.setOption(LOOPBACK, loopback);
ch.setOption(FD_FRAMES, fdFrames);
register(ch, EnumSet.of(SelectorRegistration.Operation.READ));
this.handlerMap.put(ch, handler);
this.channelMap.put(device, ch);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,59 @@ void testExternal() throws Exception {
assertNotNull(actual, "CAN frame should have been captured!");
assertEquals(expected, actual, "What goes in should come out!");
}

@Test
void testFdFrames() throws Exception {
final int id = 0x7E1;
byte[] data = {0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22};
CanFrame expected = CanFrame.create(id, CanFrame.FD_FLAG_FD_FRAME, data);
CanFilter filter = new CanFilter(id);

CanBroker brokerA = new CanBroker(FACTORY, EPollSelector.open());
CanBroker brokerB = new CanBroker(FACTORY, EPollSelector.open());

brokerA.setFdFrames(true);
brokerB.setFdFrames(true);
brokerA.addFilter(filter);
brokerB.addFilter(filter);

CompletableFuture<CanFrame> f = new CompletableFuture<>();
brokerA.addDevice(CanTestHelper.CAN_INTERFACE, (dev, frame) -> {
f.complete(frame);
try {
brokerA.removeDevice(CanTestHelper.CAN_INTERFACE);
} catch (IOException e) {
fail("Removing the device from brokerA should not fail: " + e.getLocalizedMessage());
}
});

brokerB.addDevice(CanTestHelper.CAN_INTERFACE, (d, frame) -> LOGGER.debug(String.valueOf(frame)));
brokerB.send(expected);

CanFrame actual = f.get(2, SECONDS);
assertNotNull(actual, "CAN FD frame should have been captured!");
assertTrue(actual.isFDFrame(), "Captured frame should be an FD frame");
assertEquals(expected, actual, "What goes in should come out!");
}

@Test
void testExternalFdFrame() throws Exception {
final int id = 0x7E2;
byte[] data = {0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22};
CanFrame expected = CanFrame.create(id, CanFrame.FD_FLAG_FD_FRAME, data);
CompletableFuture<CanFrame> f = new CompletableFuture<>();

CanBroker can = new CanBroker(FACTORY, EPollSelector.open());
can.setFdFrames(true);
can.addFilter(new CanFilter(id));
can.addDevice(CanTestHelper.CAN_INTERFACE, (ch, frame) -> f.complete(frame));

CanTestHelper.sendFrameViaUtils(CanTestHelper.CAN_INTERFACE, expected);

CanFrame actual = f.get(2, SECONDS);

assertNotNull(actual, "CAN FD frame should have been captured!");
assertTrue(actual.isFDFrame(), "Captured frame should be an FD frame");
assertEquals(expected, actual, "What goes in should come out!");
}
}
Loading