├── README.md ├── include ├── linux │ ├── can.h │ └── can │ │ ├── bcm.h │ │ ├── dev.h │ │ ├── gw.h │ │ ├── raw.h │ │ ├── core.h │ │ ├── error.h │ │ ├── isotp.h │ │ └── netlink.h └── socketcan │ ├── can │ ├── raw.h │ ├── ioctl.h │ ├── bcm.h │ ├── netlink.h │ ├── isotp.h │ ├── error.h │ └── gw.h │ └── can.h ├── .gitignore ├── META-INF └── MANIFEST.MF ├── .classpath ├── LICENSE ├── Makefile ├── src.test └── de │ └── entropia │ └── can │ └── CanSocketTest.java ├── jni └── cansocket.cpp └── src └── de └── entropia └── can └── CanSocket.java /README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /include/linux/can.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/linux/can/bcm.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/linux/can/dev.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/linux/can/gw.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/linux/can/raw.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/linux/can/core.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/linux/can/error.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/linux/can/isotp.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /include/linux/can/netlink.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | *.orig 3 | *~ 4 | \#*# 5 | 6 | !.gitignore 7 | !/.classpath 8 | 9 | /classes 10 | /classes.test 11 | /dist 12 | /lib 13 | /stamps 14 | /jni/*.h 15 | -------------------------------------------------------------------------------- /META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Bundle-ManifestVersion: 2 3 | Bundle-Name: libsocket-can-java 4 | Bundle-SymbolicName: libsocket-can-java 5 | Bundle-Description: SocketCAN JNI wrapper 6 | Bundle-Version: 0.1.0 7 | Export-Package: de.entropia.can 8 | Import-Package: de.entropia.can 9 | -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /include/socketcan/can/raw.h: -------------------------------------------------------------------------------- 1 | /* 2 | * socketcan/can/raw.h 3 | * 4 | * Definitions for raw CAN sockets 5 | * 6 | * Authors: Oliver Hartkopp 7 | * Urs Thuermann 8 | * Copyright (c) 2002-2007 Volkswagen Group Electronic Research 9 | * All rights reserved. 10 | * 11 | */ 12 | 13 | #ifndef CAN_RAW_H 14 | #define CAN_RAW_H 15 | 16 | #include 17 | 18 | #define SOL_CAN_RAW (SOL_CAN_BASE + CAN_RAW) 19 | 20 | /* for socket options affecting the socket (not the global system) */ 21 | 22 | enum { 23 | CAN_RAW_FILTER = 1, /* set 0 .. n can_filter(s) */ 24 | CAN_RAW_ERR_FILTER, /* set filter for error frames */ 25 | CAN_RAW_LOOPBACK, /* local loopback (default:on) */ 26 | CAN_RAW_RECV_OWN_MSGS, /* receive my own msgs (default:off) */ 27 | CAN_RAW_FD_FRAMES /* allow CAN FD frames (default:off) */ 28 | }; 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2012 Hannes Frederic Sowa 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a 5 | copy of this software and associated documentation files (the "Software"), 6 | to deal in the Software without restriction, including without limitation 7 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | and/or sell copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included 12 | in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 | OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | -------------------------------------------------------------------------------- /include/socketcan/can/ioctl.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * socketcan/can/ioctl.h 4 | * 5 | * Definitions for CAN controller setup (work in progress) 6 | * 7 | * $Id$ 8 | * 9 | * Send feedback to 10 | * 11 | */ 12 | 13 | #ifndef CAN_IOCTL_H 14 | #define CAN_IOCTL_H 15 | 16 | #include 17 | 18 | /* 19 | * CAN bitrate 20 | */ 21 | #define CAN_BITRATE_UNCONFIGURED ((__u32) 0xFFFFFFFFU) 22 | #define CAN_BITRATE_UNKNOWN 0 23 | #define CAN_BITRATE_DEFAULT 500000 24 | 25 | /* 26 | * CAN custom bit time 27 | */ 28 | enum can_bittimes { 29 | CAN_BITTIME_STD, 30 | CAN_BITTIME_BTR 31 | }; 32 | 33 | /* TSEG1 of controllers usually is a sum of synch_seg (always 1), 34 | * prop_seg and phase_seg1, TSEG2 = phase_seg2 */ 35 | 36 | struct can_bittime_std { 37 | __u32 brp; /* baud rate prescaler */ 38 | __u8 prop_seg; /* from 1 to 8 */ 39 | __u8 phase_seg1; /* from 1 to 8 */ 40 | __u8 phase_seg2; /* from 1 to 8 */ 41 | __u8 sjw:7; /* from 1 to 4 */ 42 | __u8 sam:1; /* 1 - enable triple sampling */ 43 | }; 44 | 45 | struct can_bittime_btr { 46 | __u8 btr0; 47 | __u8 btr1; 48 | }; 49 | 50 | struct can_bittime { 51 | enum can_bittimes type; 52 | union { 53 | struct can_bittime_std std; 54 | struct can_bittime_btr btr; 55 | }; 56 | }; 57 | 58 | /* 59 | * CAN mode 60 | */ 61 | enum can_mode { 62 | CAN_MODE_STOP = 0, 63 | CAN_MODE_START, 64 | CAN_MODE_SLEEP 65 | }; 66 | 67 | /* 68 | * CAN controller mode 69 | */ 70 | #define CAN_CTRLMODE_LOOPBACK 0x1 71 | #define CAN_CTRLMODE_LISTENONLY 0x2 72 | 73 | /* 74 | * CAN operational and error states 75 | */ 76 | enum can_state { 77 | CAN_STATE_ACTIVE = 0, 78 | CAN_STATE_BUS_WARNING, 79 | CAN_STATE_BUS_PASSIVE, 80 | CAN_STATE_BUS_OFF, 81 | CAN_STATE_STOPPED, 82 | CAN_STATE_SLEEPING 83 | }; 84 | 85 | /* 86 | * CAN device statistics 87 | */ 88 | struct can_device_stats { 89 | int error_warning; 90 | int data_overrun; 91 | int wakeup; 92 | int bus_error; 93 | int error_passive; 94 | int arbitration_lost; 95 | int restarts; 96 | int bus_error_at_init; 97 | }; 98 | 99 | #endif /* CAN_IOCTL_H */ 100 | -------------------------------------------------------------------------------- /include/socketcan/can/bcm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * socketcan/can/bcm.h 3 | * 4 | * Definitions for CAN Broadcast Manager (BCM) 5 | * 6 | * Author: Oliver Hartkopp 7 | * Copyright (c) 2002-2007 Volkswagen Group Electronic Research 8 | * All rights reserved. 9 | * 10 | */ 11 | 12 | #ifndef CAN_BCM_H 13 | #define CAN_BCM_H 14 | 15 | #include 16 | #include 17 | 18 | /** 19 | * struct bcm_msg_head - head of messages to/from the broadcast manager 20 | * @opcode: opcode, see enum below. 21 | * @flags: special flags, see below. 22 | * @count: number of frames to send before changing interval. 23 | * @ival1: interval for the first @count frames. 24 | * @ival2: interval for the following frames. 25 | * @can_id: CAN ID of frames to be sent or received. 26 | * @nframes: number of frames appended to the message head. 27 | * @frames: array of CAN frames. 28 | */ 29 | struct bcm_msg_head { 30 | __u32 opcode; 31 | __u32 flags; 32 | __u32 count; 33 | struct timeval ival1, ival2; 34 | canid_t can_id; 35 | __u32 nframes; 36 | struct can_frame frames[0]; 37 | }; 38 | 39 | enum { 40 | TX_SETUP = 1, /* create (cyclic) transmission task */ 41 | TX_DELETE, /* remove (cyclic) transmission task */ 42 | TX_READ, /* read properties of (cyclic) transmission task */ 43 | TX_SEND, /* send one CAN frame */ 44 | RX_SETUP, /* create RX content filter subscription */ 45 | RX_DELETE, /* remove RX content filter subscription */ 46 | RX_READ, /* read properties of RX content filter subscription */ 47 | TX_STATUS, /* reply to TX_READ request */ 48 | TX_EXPIRED, /* notification on performed transmissions (count=0) */ 49 | RX_STATUS, /* reply to RX_READ request */ 50 | RX_TIMEOUT, /* cyclic message is absent */ 51 | RX_CHANGED /* updated CAN frame (detected content change) */ 52 | }; 53 | 54 | #define SETTIMER 0x0001 55 | #define STARTTIMER 0x0002 56 | #define TX_COUNTEVT 0x0004 57 | #define TX_ANNOUNCE 0x0008 58 | #define TX_CP_CAN_ID 0x0010 59 | #define RX_FILTER_ID 0x0020 60 | #define RX_CHECK_DLC 0x0040 61 | #define RX_NO_AUTOTIMER 0x0080 62 | #define RX_ANNOUNCE_RESUME 0x0100 63 | #define TX_RESET_MULTI_IDX 0x0200 64 | #define RX_RTR_FRAME 0x0400 65 | 66 | #endif /* CAN_BCM_H */ 67 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL=/bin/bash 2 | CXX=g++ 3 | NAME:=libsocket-can-java 4 | 5 | ### JAVA_HOME 6 | ifndef JAVA_HOME 7 | JAVA_HOME=$(shell readlink -f /usr/bin/javac | sed "s:bin/javac::") 8 | endif 9 | 10 | JAVA_INCLUDES=-I$(JAVA_HOME)/include/linux -I$(JAVA_HOME)/include 11 | JAVA=$(JAVA_HOME)/bin/java 12 | JAVAC=$(JAVA_HOME)/bin/javac 13 | JAVAH=$(JAVA_HOME)/bin/javah 14 | JAR=$(JAVA_HOME)/bin/jar 15 | JAVA_SRC:=$(shell find src -type f -and -name '*.java') 16 | JAVA_TEST_SRC:=$(shell find src.test -type f -and -name '*.java') 17 | JNI_SRC:=$(shell find jni -type f -and -regex '^.*\.\(cpp\|h\)$$') 18 | JAVA_DEST=classes 19 | JAVA_TEST_DEST=classes.test 20 | LIB_DEST=lib 21 | JAR_DEST=dist 22 | JAR_DEST_FILE=$(JAR_DEST)/$(NAME).jar 23 | JAR_MANIFEST_FILE=META-INF/MANIFEST.MF 24 | DIRS=stamps obj $(JAVA_DEST) $(JAVA_TEST_DEST) $(LIB_DEST) $(JAR_DEST) 25 | JNI_DIR=jni 26 | JNI_CLASSES=de.entropia.can.CanSocket 27 | JAVAC_FLAGS=-g -Xlint:all 28 | CXXFLAGS=-I./include -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions \ 29 | -fstack-protector --param=ssp-buffer-size=4 -fPIC -Wno-unused-parameter \ 30 | -pedantic -D_REENTRANT -D_GNU_SOURCE \ 31 | $(JAVA_INCLUDES) 32 | SONAME=jni_socketcan 33 | LDFLAGS=-Wl,-soname,$(SONAME) 34 | 35 | .DEFAULT_GOAL := all 36 | .LIBPATTERNS := 37 | .SUFFIXES: 38 | 39 | .PHONY: all 40 | all: stamps/create-jar stamps/compile-test 41 | 42 | .PHONY: clean 43 | clean: 44 | $(RM) -r $(DIRS) $(STAMPS) $(filter %.h,$(JNI_SRC)) 45 | 46 | stamps/dirs: 47 | mkdir $(DIRS) 48 | @touch $@ 49 | 50 | stamps/compile-src: stamps/dirs $(JAVA_SRC) 51 | $(JAVAC) $(JAVAC_FLAGS) -d $(JAVA_DEST) $(sort $(JAVA_SRC)) 52 | @touch $@ 53 | 54 | stamps/compile-test: stamps/compile-src $(JAVA_TEST_SRC) 55 | $(JAVAC) $(JAVAC_FLAGS) -cp $(JAVA_DEST) -d $(JAVA_TEST_DEST) \ 56 | $(sort $(JAVA_TEST_SRC)) 57 | @touch $@ 58 | 59 | stamps/generate-jni-h: stamps/compile-src 60 | $(JAVAH) -jni -d $(JNI_DIR) -classpath $(JAVA_DEST) \ 61 | $(JNI_CLASSES) 62 | @touch $@ 63 | 64 | stamps/compile-jni: stamps/generate-jni-h $(JNI_SRC) 65 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -o $(LIB_DEST)/lib$(SONAME).so \ 66 | $(sort $(filter %.cpp,$(JNI_SRC))) 67 | @touch $@ 68 | 69 | stamps/create-jar: stamps/compile-jni $(JAR_MANIFEST_FILE) 70 | $(JAR) cMf $(JAR_DEST_FILE) $(JAR_MANIFEST_FILE) lib -C $(JAVA_DEST) . 71 | @touch $@ 72 | 73 | .PHONY: check 74 | check: stamps/create-jar stamps/compile-test 75 | $(JAVA) -ea -cp $(JAR_DEST_FILE):$(JAVA_TEST_DEST) \ 76 | -Xcheck:jni \ 77 | de.entropia.can.CanSocketTest 78 | -------------------------------------------------------------------------------- /include/socketcan/can/netlink.h: -------------------------------------------------------------------------------- 1 | /* 2 | * socketcan/can/netlink.h 3 | * 4 | * Definitions for the CAN netlink interface 5 | * 6 | * Copyright (c) 2009 Wolfgang Grandegger 7 | * 8 | */ 9 | 10 | #ifndef CAN_NETLINK_H 11 | #define CAN_NETLINK_H 12 | 13 | #include 14 | 15 | /* 16 | * CAN bit-timing parameters 17 | * 18 | * For further information, please read chapter "8 BIT TIMING 19 | * REQUIREMENTS" of the "Bosch CAN Specification version 2.0" 20 | * at http://www.semiconductors.bosch.de/pdf/can2spec.pdf. 21 | */ 22 | struct can_bittiming { 23 | __u32 bitrate; /* Bit-rate in bits/second */ 24 | __u32 sample_point; /* Sample point in one-tenth of a percent */ 25 | __u32 tq; /* Time quanta (TQ) in nanoseconds */ 26 | __u32 prop_seg; /* Propagation segment in TQs */ 27 | __u32 phase_seg1; /* Phase buffer segment 1 in TQs */ 28 | __u32 phase_seg2; /* Phase buffer segment 2 in TQs */ 29 | __u32 sjw; /* Synchronisation jump width in TQs */ 30 | __u32 brp; /* Bit-rate prescaler */ 31 | }; 32 | 33 | /* 34 | * CAN harware-dependent bit-timing constant 35 | * 36 | * Used for calculating and checking bit-timing parameters 37 | */ 38 | struct can_bittiming_const { 39 | char name[16]; /* Name of the CAN controller hardware */ 40 | __u32 tseg1_min; /* Time segement 1 = prop_seg + phase_seg1 */ 41 | __u32 tseg1_max; 42 | __u32 tseg2_min; /* Time segement 2 = phase_seg2 */ 43 | __u32 tseg2_max; 44 | __u32 sjw_max; /* Synchronisation jump width */ 45 | __u32 brp_min; /* Bit-rate prescaler */ 46 | __u32 brp_max; 47 | __u32 brp_inc; 48 | }; 49 | 50 | /* 51 | * CAN clock parameters 52 | */ 53 | struct can_clock { 54 | __u32 freq; /* CAN system clock frequency in Hz */ 55 | }; 56 | 57 | /* 58 | * CAN operational and error states 59 | */ 60 | enum can_state { 61 | CAN_STATE_ERROR_ACTIVE = 0, /* RX/TX error count < 96 */ 62 | CAN_STATE_ERROR_WARNING, /* RX/TX error count < 128 */ 63 | CAN_STATE_ERROR_PASSIVE, /* RX/TX error count < 256 */ 64 | CAN_STATE_BUS_OFF, /* RX/TX error count >= 256 */ 65 | CAN_STATE_STOPPED, /* Device is stopped */ 66 | CAN_STATE_SLEEPING, /* Device is sleeping */ 67 | CAN_STATE_MAX 68 | }; 69 | 70 | /* 71 | * CAN bus error counters 72 | */ 73 | struct can_berr_counter { 74 | __u16 txerr; 75 | __u16 rxerr; 76 | }; 77 | 78 | /* 79 | * CAN controller mode 80 | */ 81 | struct can_ctrlmode { 82 | __u32 mask; 83 | __u32 flags; 84 | }; 85 | 86 | #define CAN_CTRLMODE_LOOPBACK 0x01 /* Loopback mode */ 87 | #define CAN_CTRLMODE_LISTENONLY 0x02 /* Listen-only mode */ 88 | #define CAN_CTRLMODE_3_SAMPLES 0x04 /* Triple sampling mode */ 89 | #define CAN_CTRLMODE_ONE_SHOT 0x08 /* One-Shot mode */ 90 | #define CAN_CTRLMODE_BERR_REPORTING 0x10 /* Bus-error reporting */ 91 | 92 | /* 93 | * CAN device statistics 94 | */ 95 | struct can_device_stats { 96 | __u32 bus_error; /* Bus errors */ 97 | __u32 error_warning; /* Changes to error warning state */ 98 | __u32 error_passive; /* Changes to error passive state */ 99 | __u32 bus_off; /* Changes to bus off state */ 100 | __u32 arbitration_lost; /* Arbitration lost errors */ 101 | __u32 restarts; /* CAN controller re-starts */ 102 | }; 103 | 104 | /* 105 | * CAN netlink interface 106 | */ 107 | enum { 108 | IFLA_CAN_UNSPEC, 109 | IFLA_CAN_BITTIMING, 110 | IFLA_CAN_BITTIMING_CONST, 111 | IFLA_CAN_CLOCK, 112 | IFLA_CAN_STATE, 113 | IFLA_CAN_CTRLMODE, 114 | IFLA_CAN_RESTART_MS, 115 | IFLA_CAN_RESTART, 116 | IFLA_CAN_BERR_COUNTER, 117 | __IFLA_CAN_MAX 118 | }; 119 | 120 | #define IFLA_CAN_MAX (__IFLA_CAN_MAX - 1) 121 | 122 | #endif /* CAN_NETLINK_H */ 123 | -------------------------------------------------------------------------------- /include/socketcan/can/isotp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * socketcan/can/isotp.h 3 | * 4 | * Definitions for isotp CAN sockets 5 | * 6 | * $Id$ 7 | * 8 | * Author: Oliver Hartkopp 9 | * Copyright (c) 2008 Volkswagen Group Electronic Research 10 | * All rights reserved. 11 | * 12 | * Send feedback to 13 | * 14 | */ 15 | 16 | #ifndef CAN_ISOTP_H 17 | #define CAN_ISOTP_H 18 | 19 | #include 20 | 21 | #define SOL_CAN_ISOTP (SOL_CAN_BASE + CAN_ISOTP) 22 | 23 | /* for socket options affecting the socket (not the global system) */ 24 | 25 | #define CAN_ISOTP_OPTS 1 /* pass struct can_isotp_options */ 26 | 27 | #define CAN_ISOTP_RECV_FC 2 /* pass struct can_isotp_fc_options */ 28 | 29 | /* sockopts to force stmin timer values for protocol regression tests */ 30 | 31 | #define CAN_ISOTP_TX_STMIN 3 /* pass __u32 value in nano secs */ 32 | /* use this time instead of value */ 33 | /* provided in FC from the receiver */ 34 | 35 | #define CAN_ISOTP_RX_STMIN 4 /* pass __u32 value in nano secs */ 36 | /* ignore received CF frames which */ 37 | /* timestamps differ less than val */ 38 | 39 | struct can_isotp_options { 40 | 41 | __u32 flags; /* set flags for isotp behaviour. */ 42 | /* __u32 value : flags see below */ 43 | 44 | __u32 frame_txtime; /* frame transmission time (N_As/N_Ar) */ 45 | /* __u32 value : time in nano secs */ 46 | 47 | __u8 ext_address; /* set address for extended addressing */ 48 | /* __u8 value : extended address */ 49 | 50 | __u8 txpad_content; /* set content of padding byte (tx) */ 51 | /* __u8 value : content on tx path */ 52 | 53 | __u8 rxpad_content; /* set content of padding byte (rx) */ 54 | /* __u8 value : content on rx path */ 55 | }; 56 | 57 | struct can_isotp_fc_options { 58 | 59 | __u8 bs; /* blocksize provided in FC frame */ 60 | /* __u8 value : blocksize. 0 = off */ 61 | 62 | __u8 stmin; /* separation time provided in FC frame */ 63 | /* __u8 value : */ 64 | /* 0x00 - 0x7F : 0 - 127 ms */ 65 | /* 0x80 - 0xF0 : reserved */ 66 | /* 0xF1 - 0xF9 : 100 us - 900 us */ 67 | /* 0xFA - 0xFF : reserved */ 68 | 69 | __u8 wftmax; /* max. number of wait frame transmiss. */ 70 | /* __u8 value : 0 = omit FC N_PDU WT */ 71 | }; 72 | 73 | 74 | /* flags for isotp behaviour */ 75 | 76 | #define CAN_ISOTP_LISTEN_MODE 0x001 /* listen only (do not send FC) */ 77 | #define CAN_ISOTP_EXTEND_ADDR 0x002 /* enable extended addressing */ 78 | #define CAN_ISOTP_TX_PADDING 0x004 /* enable CAN frame padding tx path */ 79 | #define CAN_ISOTP_RX_PADDING 0x008 /* enable CAN frame padding rx path */ 80 | #define CAN_ISOTP_CHK_PAD_LEN 0x010 /* check received CAN frame padding */ 81 | #define CAN_ISOTP_CHK_PAD_DATA 0x020 /* check received CAN frame padding */ 82 | #define CAN_ISOTP_HALF_DUPLEX 0x040 /* half duplex error state handling */ 83 | #define CAN_ISOTP_FORCE_TXSTMIN 0x080 /* ignore stmin from received FC */ 84 | #define CAN_ISOTP_FORCE_RXSTMIN 0x100 /* ignore CFs depending on rx stmin */ 85 | 86 | 87 | /* default values */ 88 | 89 | #define CAN_ISOTP_DEFAULT_FLAGS 0 90 | #define CAN_ISOTP_DEFAULT_EXT_ADDRESS 0x00 91 | #define CAN_ISOTP_DEFAULT_RXPAD_CONTENT 0x00 92 | #define CAN_ISOTP_DEFAULT_TXPAD_CONTENT 0x00 93 | #define CAN_ISOTP_DEFAULT_FRAME_TXTIME 0 94 | #define CAN_ISOTP_DEFAULT_RECV_BS 0 95 | #define CAN_ISOTP_DEFAULT_RECV_STMIN 0x00 96 | #define CAN_ISOTP_DEFAULT_RECV_WFTMAX 0 97 | 98 | /* 99 | * Remark on CAN_ISOTP_DEFAULT_RECV_* values: 100 | * 101 | * We can strongly assume, that the Linux Kernel implementation of 102 | * CAN_ISOTP is capable to run with BS=0, STmin=0 and WFTmax=0. 103 | * But as we like to be able to behave as a commonly available ECU, 104 | * these default settings can be changed via sockopts. 105 | * For that reason the STmin value is intentionally _not_ checked for 106 | * consistency and copied directly into the flow control (FC) frame. 107 | * 108 | */ 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /include/socketcan/can/error.h: -------------------------------------------------------------------------------- 1 | /* 2 | * socketcan/can/error.h 3 | * 4 | * Definitions of the CAN error messages to be filtered and passed to the user. 5 | * 6 | * Author: Oliver Hartkopp 7 | * Copyright (c) 2002-2007 Volkswagen Group Electronic Research 8 | * All rights reserved. 9 | * 10 | */ 11 | 12 | #ifndef CAN_ERROR_H 13 | #define CAN_ERROR_H 14 | 15 | #define CAN_ERR_DLC 8 /* dlc for error message frames */ 16 | 17 | /* error class (mask) in can_id */ 18 | #define CAN_ERR_TX_TIMEOUT 0x00000001U /* TX timeout (by netdevice driver) */ 19 | #define CAN_ERR_LOSTARB 0x00000002U /* lost arbitration / data[0] */ 20 | #define CAN_ERR_CRTL 0x00000004U /* controller problems / data[1] */ 21 | #define CAN_ERR_PROT 0x00000008U /* protocol violations / data[2..3] */ 22 | #define CAN_ERR_TRX 0x00000010U /* transceiver status / data[4] */ 23 | #define CAN_ERR_ACK 0x00000020U /* received no ACK on transmission */ 24 | #define CAN_ERR_BUSOFF 0x00000040U /* bus off */ 25 | #define CAN_ERR_BUSERROR 0x00000080U /* bus error (may flood!) */ 26 | #define CAN_ERR_RESTARTED 0x00000100U /* controller restarted */ 27 | 28 | /* arbitration lost in bit ... / data[0] */ 29 | #define CAN_ERR_LOSTARB_UNSPEC 0x00 /* unspecified */ 30 | /* else bit number in bitstream */ 31 | 32 | /* error status of CAN-controller / data[1] */ 33 | #define CAN_ERR_CRTL_UNSPEC 0x00 /* unspecified */ 34 | #define CAN_ERR_CRTL_RX_OVERFLOW 0x01 /* RX buffer overflow */ 35 | #define CAN_ERR_CRTL_TX_OVERFLOW 0x02 /* TX buffer overflow */ 36 | #define CAN_ERR_CRTL_RX_WARNING 0x04 /* reached warning level for RX errors */ 37 | #define CAN_ERR_CRTL_TX_WARNING 0x08 /* reached warning level for TX errors */ 38 | #define CAN_ERR_CRTL_RX_PASSIVE 0x10 /* reached error passive status RX */ 39 | #define CAN_ERR_CRTL_TX_PASSIVE 0x20 /* reached error passive status TX */ 40 | /* (at least one error counter exceeds */ 41 | /* the protocol-defined level of 127) */ 42 | 43 | /* error in CAN protocol (type) / data[2] */ 44 | #define CAN_ERR_PROT_UNSPEC 0x00 /* unspecified */ 45 | #define CAN_ERR_PROT_BIT 0x01 /* single bit error */ 46 | #define CAN_ERR_PROT_FORM 0x02 /* frame format error */ 47 | #define CAN_ERR_PROT_STUFF 0x04 /* bit stuffing error */ 48 | #define CAN_ERR_PROT_BIT0 0x08 /* unable to send dominant bit */ 49 | #define CAN_ERR_PROT_BIT1 0x10 /* unable to send recessive bit */ 50 | #define CAN_ERR_PROT_OVERLOAD 0x20 /* bus overload */ 51 | #define CAN_ERR_PROT_ACTIVE 0x40 /* active error announcement */ 52 | #define CAN_ERR_PROT_TX 0x80 /* error occurred on transmission */ 53 | 54 | /* error in CAN protocol (location) / data[3] */ 55 | #define CAN_ERR_PROT_LOC_UNSPEC 0x00 /* unspecified */ 56 | #define CAN_ERR_PROT_LOC_SOF 0x03 /* start of frame */ 57 | #define CAN_ERR_PROT_LOC_ID28_21 0x02 /* ID bits 28 - 21 (SFF: 10 - 3) */ 58 | #define CAN_ERR_PROT_LOC_ID20_18 0x06 /* ID bits 20 - 18 (SFF: 2 - 0 )*/ 59 | #define CAN_ERR_PROT_LOC_SRTR 0x04 /* substitute RTR (SFF: RTR) */ 60 | #define CAN_ERR_PROT_LOC_IDE 0x05 /* identifier extension */ 61 | #define CAN_ERR_PROT_LOC_ID17_13 0x07 /* ID bits 17-13 */ 62 | #define CAN_ERR_PROT_LOC_ID12_05 0x0F /* ID bits 12-5 */ 63 | #define CAN_ERR_PROT_LOC_ID04_00 0x0E /* ID bits 4-0 */ 64 | #define CAN_ERR_PROT_LOC_RTR 0x0C /* RTR */ 65 | #define CAN_ERR_PROT_LOC_RES1 0x0D /* reserved bit 1 */ 66 | #define CAN_ERR_PROT_LOC_RES0 0x09 /* reserved bit 0 */ 67 | #define CAN_ERR_PROT_LOC_DLC 0x0B /* data length code */ 68 | #define CAN_ERR_PROT_LOC_DATA 0x0A /* data section */ 69 | #define CAN_ERR_PROT_LOC_CRC_SEQ 0x08 /* CRC sequence */ 70 | #define CAN_ERR_PROT_LOC_CRC_DEL 0x18 /* CRC delimiter */ 71 | #define CAN_ERR_PROT_LOC_ACK 0x19 /* ACK slot */ 72 | #define CAN_ERR_PROT_LOC_ACK_DEL 0x1B /* ACK delimiter */ 73 | #define CAN_ERR_PROT_LOC_EOF 0x1A /* end of frame */ 74 | #define CAN_ERR_PROT_LOC_INTERM 0x12 /* intermission */ 75 | 76 | /* error status of CAN-transceiver / data[4] */ 77 | /* CANH CANL */ 78 | #define CAN_ERR_TRX_UNSPEC 0x00 /* 0000 0000 */ 79 | #define CAN_ERR_TRX_CANH_NO_WIRE 0x04 /* 0000 0100 */ 80 | #define CAN_ERR_TRX_CANH_SHORT_TO_BAT 0x05 /* 0000 0101 */ 81 | #define CAN_ERR_TRX_CANH_SHORT_TO_VCC 0x06 /* 0000 0110 */ 82 | #define CAN_ERR_TRX_CANH_SHORT_TO_GND 0x07 /* 0000 0111 */ 83 | #define CAN_ERR_TRX_CANL_NO_WIRE 0x40 /* 0100 0000 */ 84 | #define CAN_ERR_TRX_CANL_SHORT_TO_BAT 0x50 /* 0101 0000 */ 85 | #define CAN_ERR_TRX_CANL_SHORT_TO_VCC 0x60 /* 0110 0000 */ 86 | #define CAN_ERR_TRX_CANL_SHORT_TO_GND 0x70 /* 0111 0000 */ 87 | #define CAN_ERR_TRX_CANL_SHORT_TO_CANH 0x80 /* 1000 0000 */ 88 | 89 | /* controller specific additional information / data[5..7] */ 90 | 91 | #endif /* CAN_ERROR_H */ 92 | -------------------------------------------------------------------------------- /include/socketcan/can/gw.h: -------------------------------------------------------------------------------- 1 | /* 2 | * socketcan/can/gw.h 3 | * 4 | * Definitions for CAN frame Gateway/Router/Bridge 5 | * 6 | * Author: Oliver Hartkopp 7 | * Copyright (c) 2011 Volkswagen Group Electronic Research 8 | * All rights reserved. 9 | * 10 | */ 11 | 12 | #ifndef CAN_GW_H 13 | #define CAN_GW_H 14 | 15 | #include 16 | #include 17 | 18 | struct rtcanmsg { 19 | __u8 can_family; 20 | __u8 gwtype; 21 | __u16 flags; 22 | }; 23 | 24 | /* CAN gateway types */ 25 | enum { 26 | CGW_TYPE_UNSPEC, 27 | CGW_TYPE_CAN_CAN, /* CAN->CAN routing */ 28 | __CGW_TYPE_MAX 29 | }; 30 | 31 | #define CGW_TYPE_MAX (__CGW_TYPE_MAX - 1) 32 | 33 | /* CAN rtnetlink attribute definitions */ 34 | enum { 35 | CGW_UNSPEC, 36 | CGW_MOD_AND, /* CAN frame modification binary AND */ 37 | CGW_MOD_OR, /* CAN frame modification binary OR */ 38 | CGW_MOD_XOR, /* CAN frame modification binary XOR */ 39 | CGW_MOD_SET, /* CAN frame modification set alternate values */ 40 | CGW_CS_XOR, /* set data[] XOR checksum into data[index] */ 41 | CGW_CS_CRC8, /* set data[] CRC8 checksum into data[index] */ 42 | CGW_HANDLED, /* number of handled CAN frames */ 43 | CGW_DROPPED, /* number of dropped CAN frames */ 44 | CGW_SRC_IF, /* ifindex of source network interface */ 45 | CGW_DST_IF, /* ifindex of destination network interface */ 46 | CGW_FILTER, /* specify struct can_filter on source CAN device */ 47 | CGW_DELETED, /* number of deleted CAN frames (see max_hops param) */ 48 | __CGW_MAX 49 | }; 50 | 51 | #define CGW_MAX (__CGW_MAX - 1) 52 | 53 | #define CGW_FLAGS_CAN_ECHO 0x01 54 | #define CGW_FLAGS_CAN_SRC_TSTAMP 0x02 55 | #define CGW_FLAGS_CAN_IIF_TX_OK 0x04 56 | 57 | #define CGW_MOD_FUNCS 4 /* AND OR XOR SET */ 58 | 59 | /* CAN frame elements that are affected by curr. 3 CAN frame modifications */ 60 | #define CGW_MOD_ID 0x01 61 | #define CGW_MOD_DLC 0x02 62 | #define CGW_MOD_DATA 0x04 63 | 64 | #define CGW_FRAME_MODS 3 /* ID DLC DATA */ 65 | 66 | #define MAX_MODFUNCTIONS (CGW_MOD_FUNCS * CGW_FRAME_MODS) 67 | 68 | struct cgw_frame_mod { 69 | struct can_frame cf; 70 | __u8 modtype; 71 | } __attribute__((packed)); 72 | 73 | #define CGW_MODATTR_LEN sizeof(struct cgw_frame_mod) 74 | 75 | struct cgw_csum_xor { 76 | __s8 from_idx; 77 | __s8 to_idx; 78 | __s8 result_idx; 79 | __u8 init_xor_val; 80 | } __attribute__((packed)); 81 | 82 | struct cgw_csum_crc8 { 83 | __s8 from_idx; 84 | __s8 to_idx; 85 | __s8 result_idx; 86 | __u8 init_crc_val; 87 | __u8 final_xor_val; 88 | __u8 crctab[256]; 89 | __u8 profile; 90 | __u8 profile_data[20]; 91 | } __attribute__((packed)); 92 | 93 | /* length of checksum operation parameters. idx = index in CAN frame data[] */ 94 | #define CGW_CS_XOR_LEN sizeof(struct cgw_csum_xor) 95 | #define CGW_CS_CRC8_LEN sizeof(struct cgw_csum_crc8) 96 | 97 | /* CRC8 profiles (compute CRC for additional data elements - see below) */ 98 | enum { 99 | CGW_CRC8PRF_UNSPEC, 100 | CGW_CRC8PRF_1U8, /* compute one additional u8 value */ 101 | CGW_CRC8PRF_16U8, /* u8 value table indexed by data[1] & 0xF */ 102 | CGW_CRC8PRF_SFFID_XOR, /* (can_id & 0xFF) ^ (can_id >> 8 & 0xFF) */ 103 | __CGW_CRC8PRF_MAX 104 | }; 105 | 106 | #define CGW_CRC8PRF_MAX (__CGW_CRC8PRF_MAX - 1) 107 | 108 | /* 109 | * CAN rtnetlink attribute contents in detail 110 | * 111 | * CGW_XXX_IF (length 4 bytes): 112 | * Sets an interface index for source/destination network interfaces. 113 | * For the CAN->CAN gwtype the indices of _two_ CAN interfaces are mandatory. 114 | * 115 | * CGW_FILTER (length 8 bytes): 116 | * Sets a CAN receive filter for the gateway job specified by the 117 | * struct can_filter described in include/linux/can.h 118 | * 119 | * CGW_MOD_XXX (length 17 bytes): 120 | * Specifies a modification that's done to a received CAN frame before it is 121 | * send out to the destination interface. 122 | * 123 | * data used as operator 124 | * affected CAN frame elements 125 | * 126 | * CGW_CS_XOR (length 4 bytes): 127 | * Set a simple XOR checksum starting with an initial value into 128 | * data[result-idx] using data[start-idx] .. data[end-idx] 129 | * 130 | * The XOR checksum is calculated like this: 131 | * 132 | * xor = init_xor_val 133 | * 134 | * for (i = from_idx .. to_idx) 135 | * xor ^= can_frame.data[i] 136 | * 137 | * can_frame.data[ result_idx ] = xor 138 | * 139 | * CGW_CS_CRC8 (length 282 bytes): 140 | * Set a CRC8 value into data[result-idx] using a given 256 byte CRC8 table, 141 | * a given initial value and a defined input data[start-idx] .. data[end-idx]. 142 | * Finally the result value is XOR'ed with the final_xor_val. 143 | * 144 | * The CRC8 checksum is calculated like this: 145 | * 146 | * crc = init_crc_val 147 | * 148 | * for (i = from_idx .. to_idx) 149 | * crc = crctab[ crc ^ can_frame.data[i] ] 150 | * 151 | * can_frame.data[ result_idx ] = crc ^ final_xor_val 152 | * 153 | * The calculated CRC may contain additional source data elements that can be 154 | * defined in the handling of 'checksum profiles' e.g. shown in AUTOSAR specs 155 | * like http://www.autosar.org/download/R4.0/AUTOSAR_SWS_E2ELibrary.pdf 156 | * E.g. the profile_data[] may contain additional u8 values (called DATA_IDs) 157 | * that are used depending on counter values inside the CAN frame data[]. 158 | * So far only three profiles have been implemented for illustration. 159 | * 160 | * Remark: In general the attribute data is a linear buffer. 161 | * Beware of sending unpacked or aligned structs! 162 | */ 163 | 164 | #endif 165 | -------------------------------------------------------------------------------- /src.test/de/entropia/can/CanSocketTest.java: -------------------------------------------------------------------------------- 1 | package de.entropia.can; 2 | 3 | import java.io.IOException; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | import java.lang.reflect.Method; 9 | 10 | import de.entropia.can.CanSocket.CanFrame; 11 | import de.entropia.can.CanSocket.CanId; 12 | import de.entropia.can.CanSocket.CanInterface; 13 | import de.entropia.can.CanSocket.Mode; 14 | 15 | public class CanSocketTest { 16 | 17 | private static final String CAN_INTERFACE = "vcan0"; 18 | 19 | @Retention(RetentionPolicy.RUNTIME) 20 | @Target({ElementType.METHOD}) 21 | @interface Test { /* EMPTY */ } 22 | 23 | public static void main(String[] args) throws IOException { 24 | startTests(); 25 | // miscTests(); 26 | } 27 | 28 | @SuppressWarnings("unused") 29 | private static void miscTests() throws IOException { 30 | final CanId id = new CanId(0x30001).setEFFSFF(); 31 | try (final CanSocket s = new CanSocket(Mode.RAW)) { 32 | final CanInterface canif = new CanInterface(s, "slcan0"); 33 | s.bind(canif); 34 | s.send(new CanFrame(canif, id, new byte[] {0, 35 | (byte) 0x91})); 36 | System.out.println(s.recv()); 37 | } 38 | } 39 | 40 | private static void startTests() { 41 | final CanSocketTest dummy = new CanSocketTest(); 42 | boolean succeeded = true; 43 | for (Method testMethod : CanSocketTest.class.getMethods()) { 44 | if (testMethod.getAnnotation(Test.class) != null) { 45 | System.out.print("Test: " + testMethod.getName()); 46 | try { 47 | testMethod.invoke(dummy); 48 | System.out.println(" OK"); 49 | } catch (final Exception e) { 50 | System.out.println(" FAILED"); 51 | e.printStackTrace(); 52 | succeeded = false; 53 | } 54 | } 55 | } 56 | if (!succeeded) { 57 | System.out.println("unit tests went wrong".toUpperCase()); 58 | System.exit(-1); 59 | } 60 | } 61 | 62 | @Test 63 | public void testSocketCanRawCreate() throws IOException { 64 | new CanSocket(Mode.RAW).close(); 65 | } 66 | 67 | @Test 68 | public void testSocketCanBcmCreate() throws IOException { 69 | new CanSocket(Mode.BCM).close(); 70 | } 71 | 72 | @Test 73 | public void testFlags() { 74 | final CanId id_0 = new CanId(0); 75 | final CanId id_f = new CanId(0xffffffff); 76 | assert !id_0.isSetEFFSFF(); 77 | assert !id_0.isSetRTR(); 78 | assert !id_0.isSetERR(); 79 | 80 | assert id_f.isSetEFFSFF(); 81 | assert id_f.isSetRTR(); 82 | assert id_f.isSetERR(); 83 | 84 | id_0.setEFFSFF(); 85 | assert id_0.isSetEFFSFF(); 86 | id_0.clearEFFSFF(); 87 | assert !id_0.isSetEFFSFF(); 88 | 89 | id_0.setRTR(); 90 | assert id_0.isSetRTR(); 91 | id_0.clearRTR(); 92 | assert !id_0.isSetRTR(); 93 | 94 | id_0.setERR(); 95 | assert id_0.isSetERR(); 96 | id_0.clearERR(); 97 | assert !id_0.isSetERR(); 98 | 99 | assert id_0.getCanId_EFF() == 0x0; 100 | } 101 | 102 | @Test 103 | public void testInterface() throws IOException { 104 | try (final CanSocket socket = new CanSocket(Mode.RAW)) { 105 | new CanInterface(socket, CAN_INTERFACE); 106 | } 107 | } 108 | 109 | @Test 110 | public void testBindInterface() throws IOException { 111 | try (final CanSocket socket = new CanSocket(Mode.RAW)) { 112 | final CanInterface canIf = new CanInterface(socket, CAN_INTERFACE); 113 | socket.bind(canIf); 114 | } 115 | } 116 | 117 | @Test 118 | public void testBind2Interface() throws IOException { 119 | try (final CanSocket socket = new CanSocket(Mode.RAW)) { 120 | final CanInterface canIf = new CanInterface(socket, CAN_INTERFACE); 121 | socket.bind(CanSocket.CAN_ALL_INTERFACES); 122 | socket.bind(canIf); 123 | } 124 | } 125 | 126 | @Test 127 | public void testSend() throws IOException { 128 | try (final CanSocket socket = new CanSocket(Mode.RAW)) { 129 | final CanInterface canif = new CanInterface(socket, CAN_INTERFACE); 130 | socket.bind(canif); 131 | socket.send(new CanFrame(canif, 132 | new CanId(0x5), new byte[] {0,0,0,0,0,0,0,0})); 133 | } 134 | } 135 | 136 | // @Test 137 | public void testRecv() throws IOException { 138 | try (final CanSocket socket = new CanSocket(Mode.RAW)) { 139 | socket.bind(CanSocket.CAN_ALL_INTERFACES); 140 | socket.recv(); 141 | } 142 | } 143 | 144 | @Test 145 | public void testMtu() throws IOException { 146 | try (final CanSocket socket = new CanSocket(Mode.RAW)) { 147 | final CanInterface canInterface = 148 | new CanInterface(socket, CAN_INTERFACE); 149 | socket.bind(canInterface); 150 | final int mtu = socket.getMtu(CAN_INTERFACE); 151 | if (!(mtu == CanSocket.CAN_MTU) && !(mtu == CanSocket.CAN_FD_MTU)) { 152 | throw new IOException("illegal interface mtu: " + mtu); 153 | } 154 | } 155 | } 156 | 157 | @Test 158 | public void testSockOpts() throws IOException { 159 | try (final CanSocket socket = new CanSocket(Mode.RAW)) { 160 | socket.setLoopbackMode(true); 161 | assert socket.getLoopbackMode(); 162 | socket.setRecvOwnMsgsMode(true); 163 | assert socket.getRecvOwnMsgsMode(); 164 | socket.setRecvOwnMsgsMode(false); 165 | assert !socket.getRecvOwnMsgsMode(); 166 | socket.setLoopbackMode(false); 167 | assert !socket.getLoopbackMode(); 168 | } 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /include/socketcan/can.h: -------------------------------------------------------------------------------- 1 | /* 2 | * socketcan/can.h 3 | * 4 | * Definitions for CAN network layer (socket addr / CAN frame / CAN filter) 5 | * 6 | * Authors: Oliver Hartkopp 7 | * Urs Thuermann 8 | * Copyright (c) 2002-2007 Volkswagen Group Electronic Research 9 | * All rights reserved. 10 | * 11 | */ 12 | 13 | #ifndef CAN_H 14 | #define CAN_H 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | /* controller area network (CAN) kernel definitions */ 21 | 22 | /* special address description flags for the CAN_ID */ 23 | #define CAN_EFF_FLAG 0x80000000U /* EFF/SFF is set in the MSB */ 24 | #define CAN_RTR_FLAG 0x40000000U /* remote transmission request */ 25 | #define CAN_ERR_FLAG 0x20000000U /* error message frame */ 26 | 27 | /* valid bits in CAN ID for frame formats */ 28 | #define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */ 29 | #define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */ 30 | #define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */ 31 | 32 | /* 33 | * Controller Area Network Identifier structure 34 | * 35 | * bit 0-28 : CAN identifier (11/29 bit) 36 | * bit 29 : error message frame flag (0 = data frame, 1 = error message) 37 | * bit 30 : remote transmission request flag (1 = rtr frame) 38 | * bit 31 : frame format flag (0 = standard 11 bit, 1 = extended 29 bit) 39 | */ 40 | typedef __u32 canid_t; 41 | 42 | #define CAN_SFF_ID_BITS 11 43 | #define CAN_EFF_ID_BITS 29 44 | 45 | /* 46 | * Controller Area Network Error Message Frame Mask structure 47 | * 48 | * bit 0-28 : error class mask (see include/socketcan/can/error.h) 49 | * bit 29-31 : set to zero 50 | */ 51 | typedef __u32 can_err_mask_t; 52 | 53 | /* CAN payload length and DLC definitions according to ISO 11898-1 */ 54 | #define CAN_MAX_DLC 8 55 | #define CAN_MAX_DLEN 8 56 | 57 | /* CAN FD payload length and DLC definitions according to ISO 11898-7 */ 58 | #define CANFD_MAX_DLC 15 59 | #define CANFD_MAX_DLEN 64 60 | 61 | /** 62 | * struct can_frame - basic CAN frame structure 63 | * @can_id: CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition 64 | * @can_dlc: frame payload length in byte (0 .. 8) aka data length code 65 | * N.B. the DLC field from ISO 11898-1 Chapter 8.4.2.3 has a 1:1 66 | * mapping of the 'data length code' to the real payload length 67 | * @data: CAN frame payload (up to 8 byte) 68 | */ 69 | struct can_frame { 70 | canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ 71 | __u8 can_dlc; /* frame payload length in byte (0 .. CAN_MAX_DLEN) */ 72 | __u8 data[CAN_MAX_DLEN] __attribute__((aligned(8))); 73 | }; 74 | 75 | /* 76 | * defined bits for canfd_frame.flags 77 | * 78 | * The use of struct canfd_frame implies the Extended Data Length (EDL) bit to 79 | * be set in the CAN frame bitstream on the wire. The EDL bit switch turns 80 | * the CAN controllers bitstream processor into the CAN FD mode which creates 81 | * two new options within the CAN FD frame specification: 82 | * 83 | * Bit Rate Switch - to indicate a second bitrate is/was used for the payload 84 | * Error State Indicator - represents the error state of the transmitting node 85 | * 86 | * As the CANFD_ESI bit is internally generated by the transmitting CAN 87 | * controller only the CANFD_BRS bit is relevant for real CAN controllers when 88 | * building a CAN FD frame for transmission. Setting the CANFD_ESI bit can make 89 | * sense for virtual CAN interfaces to test applications with echoed frames. 90 | */ 91 | #define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */ 92 | #define CANFD_ESI 0x02 /* error state indicator of the transmitting node */ 93 | 94 | /** 95 | * struct canfd_frame - CAN flexible data rate frame structure 96 | * @can_id: CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition 97 | * @len: frame payload length in byte (0 .. CANFD_MAX_DLEN) 98 | * @flags: additional flags for CAN FD 99 | * @__res0: reserved / padding 100 | * @__res1: reserved / padding 101 | * @data: CAN FD frame payload (up to CANFD_MAX_DLEN byte) 102 | */ 103 | struct canfd_frame { 104 | canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ 105 | __u8 len; /* frame payload length in byte */ 106 | __u8 flags; /* additional flags for CAN FD */ 107 | __u8 __res0; /* reserved / padding */ 108 | __u8 __res1; /* reserved / padding */ 109 | __u8 data[CANFD_MAX_DLEN] __attribute__((aligned(8))); 110 | }; 111 | 112 | #define CAN_MTU (sizeof(struct can_frame)) 113 | #define CANFD_MTU (sizeof(struct canfd_frame)) 114 | 115 | /* particular protocols of the protocol family PF_CAN */ 116 | #define CAN_RAW 1 /* RAW sockets */ 117 | #define CAN_BCM 2 /* Broadcast Manager */ 118 | #define CAN_TP16 3 /* VAG Transport Protocol v1.6 */ 119 | #define CAN_TP20 4 /* VAG Transport Protocol v2.0 */ 120 | #define CAN_MCNET 5 /* Bosch MCNet */ 121 | #define CAN_ISOTP 6 /* ISO 15765-2 Transport Protocol */ 122 | #define CAN_NPROTO 7 123 | 124 | #define SOL_CAN_BASE 100 125 | 126 | // typedef unsigned short __kernel_sa_family_t; 127 | // introduced in Linux 3.2 commit 6602a4baf4d1a73cc4685a39ef859e1c5ddf654c 128 | 129 | /** 130 | * struct sockaddr_can - the sockaddr structure for CAN sockets 131 | * @can_family: address family number AF_CAN. 132 | * @can_ifindex: CAN network interface index. 133 | * @can_addr: protocol specific address information 134 | */ 135 | struct sockaddr_can { 136 | sa_family_t can_family; 137 | // __kernel_sa_family_t can_family; 138 | int can_ifindex; 139 | union { 140 | /* transport protocol class address information (e.g. ISOTP) */ 141 | struct { canid_t rx_id, tx_id; } tp; 142 | 143 | /* reserved for future CAN protocols address information */ 144 | } can_addr; 145 | }; 146 | 147 | /** 148 | * struct can_filter - CAN ID based filter in can_register(). 149 | * @can_id: relevant bits of CAN ID which are not masked out. 150 | * @can_mask: CAN mask (see description) 151 | * 152 | * Description: 153 | * A filter matches, when 154 | * 155 | * & mask == can_id & mask 156 | * 157 | * The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can 158 | * filter for error message frames (CAN_ERR_FLAG bit set in mask). 159 | */ 160 | struct can_filter { 161 | canid_t can_id; 162 | canid_t can_mask; 163 | }; 164 | 165 | #define CAN_INV_FILTER 0x20000000U /* to be set in can_filter.can_id */ 166 | 167 | #endif /* CAN_H */ 168 | -------------------------------------------------------------------------------- /jni/cansocket.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | extern "C" { 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | } 19 | 20 | #if defined(ANDROID) || defined(__ANDROID__) 21 | #include "jni.h" 22 | #else 23 | #include "de_entropia_can_CanSocket.h" 24 | #endif 25 | 26 | static const int ERRNO_BUFFER_LEN = 1024; 27 | 28 | static void throwException(JNIEnv *env, const std::string& exception_name, 29 | const std::string& msg) 30 | { 31 | const jclass exception = env->FindClass(exception_name.c_str()); 32 | if (exception == NULL) { 33 | return; 34 | } 35 | env->ThrowNew(exception, msg.c_str()); 36 | } 37 | 38 | static void throwIOExceptionMsg(JNIEnv *env, const std::string& msg) 39 | { 40 | throwException(env, "java/io/IOException", msg); 41 | } 42 | 43 | static void throwIOExceptionErrno(JNIEnv *env, const int exc_errno) 44 | { 45 | char message[ERRNO_BUFFER_LEN]; 46 | const char *const msg = (char *) strerror_r(exc_errno, message, ERRNO_BUFFER_LEN); 47 | if (((long)msg) == 0) { 48 | // POSIX strerror_r, success 49 | throwIOExceptionMsg(env, std::string(message)); 50 | } else if (((long)msg) == -1) { 51 | // POSIX strerror_r, failure 52 | // (Strictly, POSIX only guarantees a value other than 0. The safest 53 | // way to implement this function is to use C++ and overload on the 54 | // type of strerror_r to accurately distinguish GNU from POSIX. But 55 | // realistic implementations will always return -1.) 56 | snprintf(message, ERRNO_BUFFER_LEN, "errno %d", exc_errno); 57 | throwIOExceptionMsg(env, std::string(message)); 58 | } else { 59 | // glibc strerror_r returning a string 60 | throwIOExceptionMsg(env, std::string(msg)); 61 | } 62 | } 63 | 64 | static void throwIllegalArgumentException(JNIEnv *env, const std::string& message) 65 | { 66 | throwException(env, "java/lang/IllegalArgumentException", message); 67 | } 68 | 69 | static void throwOutOfMemoryError(JNIEnv *env, const std::string& message) 70 | { 71 | throwException(env, "java/lang/OutOfMemoryError", message); 72 | } 73 | 74 | static jint newCanSocket(JNIEnv *env, int socket_type, int protocol) 75 | { 76 | const int fd = socket(PF_CAN, socket_type, protocol); 77 | if (fd != -1) { 78 | return fd; 79 | } 80 | throwIOExceptionErrno(env, errno); 81 | return -1; 82 | } 83 | 84 | JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1openSocketRAW 85 | (JNIEnv *env, jclass obj) 86 | { 87 | return newCanSocket(env, SOCK_RAW, CAN_RAW); 88 | } 89 | 90 | 91 | JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1openSocketBCM 92 | (JNIEnv *env, jclass obj) 93 | { 94 | return newCanSocket(env, SOCK_DGRAM, CAN_BCM); 95 | } 96 | 97 | JNIEXPORT void JNICALL Java_de_entropia_can_CanSocket__1close 98 | (JNIEnv *env, jclass obj, jint fd) 99 | { 100 | if (close(fd) == -1) { 101 | throwIOExceptionErrno(env, errno); 102 | } 103 | } 104 | 105 | JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1discoverInterfaceIndex 106 | (JNIEnv *env, jclass clazz, jint socketFd, jstring ifName) 107 | { 108 | struct ifreq ifreq; 109 | const jsize ifNameSize = env->GetStringUTFLength(ifName); 110 | if (ifNameSize > IFNAMSIZ-1) { 111 | throwIllegalArgumentException(env, "illegal interface name"); 112 | return -1; 113 | } 114 | 115 | /* fetch interface name */ 116 | memset(&ifreq, 0x0, sizeof(ifreq)); 117 | env->GetStringUTFRegion(ifName, 0, ifNameSize, 118 | ifreq.ifr_name); 119 | if (env->ExceptionCheck() == JNI_TRUE) { 120 | return -1; 121 | } 122 | /* discover interface id */ 123 | const int err = ioctl(socketFd, SIOCGIFINDEX, &ifreq); 124 | if (err == -1) { 125 | throwIOExceptionErrno(env, errno); 126 | return -1; 127 | } else { 128 | return ifreq.ifr_ifindex; 129 | } 130 | } 131 | 132 | JNIEXPORT jstring JNICALL Java_de_entropia_can_CanSocket__1discoverInterfaceName 133 | (JNIEnv *env, jclass obj, jint fd, jint ifIdx) 134 | { 135 | struct ifreq ifreq; 136 | memset(&ifreq, 0x0, sizeof(ifreq)); 137 | ifreq.ifr_ifindex = ifIdx; 138 | if (ioctl(fd, SIOCGIFNAME, &ifreq) == -1) { 139 | throwIOExceptionErrno(env, errno); 140 | return NULL; 141 | } 142 | const jstring ifname = env->NewStringUTF(ifreq.ifr_name); 143 | return ifname; 144 | } 145 | 146 | 147 | JNIEXPORT void JNICALL Java_de_entropia_can_CanSocket__1bindToSocket 148 | (JNIEnv *env, jclass obj, jint fd, jint ifIndex) 149 | { 150 | struct sockaddr_can addr; 151 | addr.can_family = AF_CAN; 152 | addr.can_ifindex = ifIndex; 153 | if (bind(fd, reinterpret_cast(&addr), sizeof(addr)) != 0) { 154 | throwIOExceptionErrno(env, errno); 155 | } 156 | } 157 | 158 | JNIEXPORT void JNICALL Java_de_entropia_can_CanSocket__1sendFrame 159 | (JNIEnv *env, jclass obj, jint fd, jint if_idx, jint canid, jbyteArray data) 160 | { 161 | const int flags = 0; 162 | ssize_t nbytes; 163 | struct sockaddr_can addr; 164 | struct can_frame frame; 165 | memset(&addr, 0, sizeof(addr)); 166 | memset(&frame, 0, sizeof(frame)); 167 | addr.can_family = AF_CAN; 168 | addr.can_ifindex = if_idx; 169 | const jsize len = env->GetArrayLength(data); 170 | if (env->ExceptionCheck() == JNI_TRUE) { 171 | return; 172 | } 173 | frame.can_id = canid; 174 | frame.can_dlc = static_cast<__u8>(len); 175 | env->GetByteArrayRegion(data, 0, len, reinterpret_cast(&frame.data)); 176 | if (env->ExceptionCheck() == JNI_TRUE) { 177 | return; 178 | } 179 | nbytes = sendto(fd, &frame, sizeof(frame), flags, 180 | reinterpret_cast(&addr), 181 | sizeof(addr)); 182 | if (nbytes == -1) { 183 | throwIOExceptionErrno(env, errno); 184 | } else if (nbytes != sizeof(frame)) { 185 | throwIOExceptionMsg(env, "send partial frame"); 186 | } 187 | } 188 | 189 | JNIEXPORT jobject JNICALL Java_de_entropia_can_CanSocket__1recvFrame 190 | (JNIEnv *env, jclass obj, jint fd) 191 | { 192 | const int flags = 0; 193 | ssize_t nbytes; 194 | struct sockaddr_can addr; 195 | socklen_t len = sizeof(addr); 196 | struct can_frame frame; 197 | 198 | memset(&addr, 0, sizeof(addr)); 199 | memset(&frame, 0, sizeof(frame)); 200 | nbytes = recvfrom(fd, &frame, sizeof(frame), flags, 201 | reinterpret_cast(&addr), &len); 202 | if (len != sizeof(addr)) { 203 | throwIllegalArgumentException(env, "illegal AF_CAN address"); 204 | return NULL; 205 | } 206 | if (nbytes == -1) { 207 | throwIOExceptionErrno(env, errno); 208 | return NULL; 209 | } else if (nbytes != sizeof(frame)) { 210 | throwIOExceptionMsg(env, "invalid length of received frame"); 211 | return NULL; 212 | } 213 | const jsize fsize = static_cast(std::min(static_cast(frame.can_dlc), 214 | static_cast(nbytes - offsetof(struct can_frame, data)))); 215 | const jclass can_frame_clazz = env->FindClass("de/entropia/can/" 216 | "CanSocket$CanFrame"); 217 | if (can_frame_clazz == NULL) { 218 | return NULL; 219 | } 220 | const jmethodID can_frame_cstr = env->GetMethodID(can_frame_clazz, 221 | "", "(II[B)V"); 222 | if (can_frame_cstr == NULL) { 223 | return NULL; 224 | } 225 | const jbyteArray data = env->NewByteArray(fsize); 226 | if (data == NULL) { 227 | if (env->ExceptionCheck() != JNI_TRUE) { 228 | throwOutOfMemoryError(env, "could not allocate ByteArray"); 229 | } 230 | return NULL; 231 | } 232 | env->SetByteArrayRegion(data, 0, fsize, reinterpret_cast(&frame.data)); 233 | if (env->ExceptionCheck() == JNI_TRUE) { 234 | return NULL; 235 | } 236 | const jobject ret = env->NewObject(can_frame_clazz, can_frame_cstr, 237 | addr.can_ifindex, frame.can_id, 238 | data); 239 | return ret; 240 | } 241 | 242 | JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1fetchInterfaceMtu 243 | (JNIEnv *env, jclass obj, jint fd, jstring ifName) 244 | { 245 | struct ifreq ifreq; 246 | 247 | const jsize ifNameSize = env->GetStringUTFLength(ifName); 248 | if (ifNameSize > IFNAMSIZ-1) { 249 | throwIllegalArgumentException(env, "illegal interface name"); 250 | return -1; 251 | } 252 | memset(&ifreq, 0x0, sizeof(ifreq)); 253 | env->GetStringUTFRegion(ifName, 0, ifNameSize, ifreq.ifr_name); 254 | if (env->ExceptionCheck() == JNI_TRUE) { 255 | return -1; 256 | } 257 | if (ioctl(fd, SIOCGIFMTU, &ifreq) == -1) { 258 | throwIOExceptionErrno(env, errno); 259 | return -1; 260 | } else { 261 | return ifreq.ifr_mtu; 262 | } 263 | } 264 | 265 | JNIEXPORT void JNICALL Java_de_entropia_can_CanSocket__1setsockopt 266 | (JNIEnv *env, jclass obj, jint fd, jint op, jint stat) 267 | { 268 | const int _stat = stat; 269 | if (setsockopt(fd, SOL_CAN_RAW, op, &_stat, sizeof(_stat)) == -1) { 270 | throwIOExceptionErrno(env, errno); 271 | } 272 | } 273 | 274 | JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1getsockopt 275 | (JNIEnv *env, jclass obj, jint fd, jint op) 276 | { 277 | int _stat = 0; 278 | socklen_t len = sizeof(_stat); 279 | if (getsockopt(fd, SOL_CAN_RAW, op, &_stat, &len) == -1) { 280 | throwIOExceptionErrno(env, errno); 281 | } 282 | if (len != sizeof(_stat)) { 283 | throwIllegalArgumentException(env, "setsockopt return size is different"); 284 | return -1; 285 | } 286 | return _stat; 287 | } 288 | 289 | 290 | /*** constants ***/ 291 | 292 | JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1fetch_1CAN_1MTU 293 | (JNIEnv *env, jclass obj) 294 | { 295 | return CAN_MTU; 296 | } 297 | 298 | JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1fetch_1CAN_1FD_1MTU 299 | (JNIEnv *env, jclass obj) 300 | { 301 | return CANFD_MTU; 302 | } 303 | 304 | /*** ioctls ***/ 305 | JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1fetch_1CAN_1RAW_1FILTER 306 | (JNIEnv *env, jclass obj) 307 | { 308 | return CAN_RAW_FILTER; 309 | } 310 | 311 | JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1fetch_1CAN_1RAW_1ERR_1FILTER 312 | (JNIEnv *env, jclass obj) 313 | { 314 | return CAN_RAW_ERR_FILTER; 315 | } 316 | 317 | JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1fetch_1CAN_1RAW_1LOOPBACK 318 | (JNIEnv *env, jclass obj) 319 | { 320 | return CAN_RAW_LOOPBACK; 321 | } 322 | 323 | JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1fetch_1CAN_1RAW_1RECV_1OWN_1MSGS 324 | (JNIEnv *env, jclass obj) 325 | { 326 | return CAN_RAW_RECV_OWN_MSGS; 327 | } 328 | 329 | JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1fetch_1CAN_1RAW_1FD_1FRAMES 330 | (JNIEnv *env, jclass obj) 331 | { 332 | return CAN_RAW_FD_FRAMES; 333 | } 334 | 335 | /*** ADR MANIPULATION FUNCTIONS ***/ 336 | 337 | JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1getCANID_1SFF 338 | (JNIEnv *env, jclass obj, jint canid) 339 | { 340 | return canid & CAN_SFF_MASK; 341 | } 342 | 343 | JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1getCANID_1EFF 344 | (JNIEnv *env, jclass obj, jint canid) 345 | { 346 | return canid & CAN_EFF_MASK; 347 | } 348 | 349 | JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1getCANID_1ERR 350 | (JNIEnv *env, jclass obj, jint canid) 351 | { 352 | return canid & CAN_ERR_MASK; 353 | } 354 | 355 | JNIEXPORT jboolean JNICALL Java_de_entropia_can_CanSocket__1isSetEFFSFF 356 | (JNIEnv *env, jclass obj, jint canid) 357 | { 358 | return (canid & CAN_EFF_FLAG) != 0 ? JNI_TRUE : JNI_FALSE; 359 | } 360 | 361 | JNIEXPORT jboolean JNICALL Java_de_entropia_can_CanSocket__1isSetRTR 362 | (JNIEnv *env, jclass obj, jint canid) 363 | { 364 | return (canid & CAN_RTR_FLAG) != 0 ? JNI_TRUE : JNI_FALSE; 365 | } 366 | 367 | JNIEXPORT jboolean JNICALL Java_de_entropia_can_CanSocket__1isSetERR 368 | (JNIEnv *env, jclass obj, jint canid) 369 | { 370 | return (canid & CAN_ERR_FLAG) != 0 ? JNI_TRUE : JNI_FALSE; 371 | } 372 | 373 | JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1setEFFSFF 374 | (JNIEnv *env, jclass obj, jint canid) 375 | { 376 | return canid | CAN_EFF_FLAG; 377 | } 378 | 379 | JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1setRTR 380 | (JNIEnv *env, jclass obj, jint canid) 381 | { 382 | return canid | CAN_RTR_FLAG; 383 | } 384 | 385 | JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1setERR 386 | (JNIEnv *env, jclass obj, jint canid) 387 | { 388 | return canid | CAN_ERR_FLAG; 389 | } 390 | 391 | JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1clearEFFSFF 392 | (JNIEnv *env, jclass obj, jint canid) 393 | { 394 | return canid & ~CAN_EFF_FLAG; 395 | } 396 | 397 | JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1clearRTR 398 | (JNIEnv *env, jclass obj, jint canid) 399 | { 400 | return canid & ~CAN_RTR_FLAG; 401 | } 402 | 403 | JNIEXPORT jint JNICALL Java_de_entropia_can_CanSocket__1clearERR 404 | (JNIEnv *env, jclass obj, jint canid) 405 | { 406 | return canid & ~CAN_ERR_FLAG; 407 | } 408 | -------------------------------------------------------------------------------- /src/de/entropia/can/CanSocket.java: -------------------------------------------------------------------------------- 1 | package de.entropia.can; 2 | 3 | import java.io.Closeable; 4 | import java.io.FileNotFoundException; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.io.OutputStream; 8 | import java.nio.file.Files; 9 | import java.nio.file.Path; 10 | import java.nio.file.StandardOpenOption; 11 | import java.nio.file.attribute.FileAttribute; 12 | import java.nio.file.attribute.PosixFilePermission; 13 | import java.nio.file.attribute.PosixFilePermissions; 14 | import java.util.Arrays; 15 | import java.util.Collections; 16 | import java.util.EnumSet; 17 | import java.util.Objects; 18 | import java.util.Set; 19 | 20 | public final class CanSocket implements Closeable { 21 | static { 22 | final String LIB_JNI_SOCKETCAN = "jni_socketcan"; 23 | try { 24 | System.loadLibrary(LIB_JNI_SOCKETCAN); 25 | } catch (final UnsatisfiedLinkError e) { 26 | try { 27 | loadLibFromJar(LIB_JNI_SOCKETCAN); 28 | } catch (final IOException _e) { 29 | throw new UnsatisfiedLinkError(LIB_JNI_SOCKETCAN); 30 | } 31 | } 32 | } 33 | 34 | private static void copyStream(final InputStream in, 35 | final OutputStream out) throws IOException { 36 | final int BYTE_BUFFER_SIZE = 0x1000; 37 | final byte[] buffer = new byte[BYTE_BUFFER_SIZE]; 38 | for (int len; (len = in.read(buffer)) != -1;) { 39 | out.write(buffer, 0, len); 40 | } 41 | } 42 | 43 | private static void loadLibFromJar(final String libName) 44 | throws IOException { 45 | Objects.requireNonNull(libName); 46 | final String fileName = "/lib/lib" + libName + ".so"; 47 | final FileAttribute> permissions = 48 | PosixFilePermissions.asFileAttribute( 49 | PosixFilePermissions.fromString("rw-------")); 50 | final Path tempSo = Files.createTempFile(CanSocket.class.getName(), 51 | ".so", permissions); 52 | try { 53 | try (final InputStream libstream = 54 | CanSocket.class.getResourceAsStream(fileName)) { 55 | if (libstream == null) { 56 | throw new FileNotFoundException("jar:*!" + fileName); 57 | } 58 | try (final OutputStream fout = Files.newOutputStream(tempSo, 59 | StandardOpenOption.WRITE, 60 | StandardOpenOption.TRUNCATE_EXISTING)) { 61 | copyStream(libstream, fout); 62 | } 63 | } 64 | System.load(tempSo.toString()); 65 | } finally { 66 | Files.delete(tempSo); 67 | } 68 | } 69 | 70 | public static final CanInterface CAN_ALL_INTERFACES = new CanInterface(0); 71 | 72 | private static native int _getCANID_SFF(final int canid); 73 | private static native int _getCANID_EFF(final int canid); 74 | private static native int _getCANID_ERR(final int canid); 75 | 76 | private static native boolean _isSetEFFSFF(final int canid); 77 | private static native boolean _isSetRTR(final int canid); 78 | private static native boolean _isSetERR(final int canid); 79 | 80 | private static native int _setEFFSFF(final int canid); 81 | private static native int _setRTR(final int canid); 82 | private static native int _setERR(final int canid); 83 | 84 | private static native int _clearEFFSFF(final int canid); 85 | private static native int _clearRTR(final int canid); 86 | private static native int _clearERR(final int canid); 87 | 88 | private static native int _openSocketRAW() throws IOException; 89 | private static native int _openSocketBCM() throws IOException; 90 | private static native void _close(final int fd) throws IOException; 91 | 92 | private static native int _fetchInterfaceMtu(final int fd, 93 | final String ifName) throws IOException; 94 | private static native int _fetch_CAN_MTU(); 95 | private static native int _fetch_CAN_FD_MTU(); 96 | 97 | private static native int _discoverInterfaceIndex(final int fd, 98 | final String ifName) throws IOException; 99 | private static native String _discoverInterfaceName(final int fd, 100 | final int ifIndex) throws IOException; 101 | 102 | private static native void _bindToSocket(final int fd, 103 | final int ifId) throws IOException; 104 | 105 | private static native CanFrame _recvFrame(final int fd) throws IOException; 106 | private static native void _sendFrame(final int fd, final int canif, 107 | final int canid, final byte[] data) throws IOException; 108 | 109 | public static final int CAN_MTU = _fetch_CAN_MTU(); 110 | public static final int CAN_FD_MTU = _fetch_CAN_FD_MTU(); 111 | 112 | private static native int _fetch_CAN_RAW_FILTER(); 113 | private static native int _fetch_CAN_RAW_ERR_FILTER(); 114 | private static native int _fetch_CAN_RAW_LOOPBACK(); 115 | private static native int _fetch_CAN_RAW_RECV_OWN_MSGS(); 116 | private static native int _fetch_CAN_RAW_FD_FRAMES(); 117 | 118 | private static final int CAN_RAW_FILTER = _fetch_CAN_RAW_FILTER(); 119 | private static final int CAN_RAW_ERR_FILTER = _fetch_CAN_RAW_ERR_FILTER(); 120 | private static final int CAN_RAW_LOOPBACK = _fetch_CAN_RAW_LOOPBACK(); 121 | private static final int CAN_RAW_RECV_OWN_MSGS = _fetch_CAN_RAW_RECV_OWN_MSGS(); 122 | private static final int CAN_RAW_FD_FRAMES = _fetch_CAN_RAW_FD_FRAMES(); 123 | 124 | private static native void _setsockopt(final int fd, final int op, 125 | final int stat) throws IOException; 126 | private static native int _getsockopt(final int fd, final int op) 127 | throws IOException; 128 | 129 | public final static class CanId implements Cloneable { 130 | private int _canId = 0; 131 | 132 | public static enum StatusBits { 133 | ERR, EFFSFF, RTR 134 | } 135 | 136 | public CanId(final int address) { 137 | _canId = address; 138 | } 139 | 140 | public boolean isSetEFFSFF() { 141 | return _isSetEFFSFF(_canId); 142 | } 143 | 144 | public boolean isSetRTR() { 145 | return _isSetRTR(_canId); 146 | } 147 | 148 | public boolean isSetERR() { 149 | return _isSetERR(_canId); 150 | } 151 | 152 | public CanId setEFFSFF() { 153 | _canId = _setEFFSFF(_canId); 154 | return this; 155 | } 156 | 157 | public CanId setRTR() { 158 | _canId = _setRTR(_canId); 159 | return this; 160 | } 161 | 162 | public CanId setERR() { 163 | _canId = _setERR(_canId); 164 | return this; 165 | } 166 | 167 | public CanId clearEFFSFF() { 168 | _canId = _clearEFFSFF(_canId); 169 | return this; 170 | } 171 | 172 | public CanId clearRTR() { 173 | _canId = _clearRTR(_canId); 174 | return this; 175 | } 176 | 177 | public CanId clearERR() { 178 | _canId = _clearERR(_canId); 179 | return this; 180 | } 181 | 182 | public int getCanId_SFF() { 183 | return _getCANID_SFF(_canId); 184 | } 185 | 186 | public int getCanId_EFF() { 187 | return _getCANID_EFF(_canId); 188 | } 189 | 190 | public int getCanId_ERR() { 191 | return _getCANID_ERR(_canId); 192 | } 193 | 194 | @Override 195 | protected Object clone() { 196 | return new CanId(_canId); 197 | } 198 | 199 | private Set _inferStatusBits() { 200 | final EnumSet bits = EnumSet.noneOf(StatusBits.class); 201 | if (isSetERR()) { 202 | bits.add(StatusBits.ERR); 203 | } 204 | if (isSetEFFSFF()) { 205 | bits.add(StatusBits.EFFSFF); 206 | } 207 | if (isSetRTR()) { 208 | bits.add(StatusBits.RTR); 209 | } 210 | return Collections.unmodifiableSet(bits); 211 | } 212 | 213 | @Override 214 | public String toString() { 215 | return "CanId [canId=" + (isSetEFFSFF() 216 | ? getCanId_EFF() : getCanId_SFF()) 217 | + "flags=" + _inferStatusBits() + "]"; 218 | } 219 | 220 | @Override 221 | public int hashCode() { 222 | final int prime = 31; 223 | int result = 1; 224 | result = prime * result + _canId; 225 | return result; 226 | } 227 | 228 | @Override 229 | public boolean equals(Object obj) { 230 | if (this == obj) 231 | return true; 232 | if (obj == null) 233 | return false; 234 | if (getClass() != obj.getClass()) 235 | return false; 236 | CanId other = (CanId) obj; 237 | if (_canId != other._canId) 238 | return false; 239 | return true; 240 | } 241 | } 242 | 243 | public final static class CanInterface implements Cloneable { 244 | private final int _ifIndex; 245 | private String _ifName; 246 | 247 | public CanInterface(final CanSocket socket, final String ifName) 248 | throws IOException { 249 | this._ifIndex = _discoverInterfaceIndex(socket._fd, ifName); 250 | this._ifName = ifName; 251 | } 252 | 253 | private CanInterface(int ifIndex, String ifName) { 254 | this._ifIndex = ifIndex; 255 | this._ifName = ifName; 256 | } 257 | 258 | private CanInterface(int ifIndex) { 259 | this(ifIndex, null); 260 | } 261 | 262 | public int getInterfaceIndex() { 263 | return _ifIndex; 264 | } 265 | 266 | @Override 267 | public String toString() { 268 | return "CanInterface [_ifIndex=" + _ifIndex + ", _ifName=" 269 | + _ifName + "]"; 270 | } 271 | 272 | public String getIfName() { 273 | return _ifName; 274 | } 275 | 276 | public String resolveIfName(final CanSocket socket) { 277 | if (_ifName == null) { 278 | try { 279 | _ifName = _discoverInterfaceName(socket._fd, _ifIndex); 280 | } catch (IOException e) { /* EMPTY */ } 281 | } 282 | return _ifName; 283 | } 284 | 285 | @Override 286 | public int hashCode() { 287 | final int prime = 31; 288 | int result = 1; 289 | result = prime * result + _ifIndex; 290 | result = prime * result 291 | + ((_ifName == null) ? 0 : _ifName.hashCode()); 292 | return result; 293 | } 294 | 295 | @Override 296 | public boolean equals(Object obj) { 297 | if (this == obj) 298 | return true; 299 | if (obj == null) 300 | return false; 301 | if (getClass() != obj.getClass()) 302 | return false; 303 | CanInterface other = (CanInterface) obj; 304 | if (_ifIndex != other._ifIndex) 305 | return false; 306 | if (_ifName == null) { 307 | if (other._ifName != null) 308 | return false; 309 | } else if (!_ifName.equals(other._ifName)) 310 | return false; 311 | return true; 312 | } 313 | 314 | @Override 315 | protected Object clone() { 316 | return new CanInterface(_ifIndex, _ifName); 317 | } 318 | } 319 | 320 | public final static class CanFrame implements Cloneable { 321 | private final CanInterface canIf; 322 | private final CanId canId; 323 | private final byte[] data; 324 | 325 | public CanFrame(final CanInterface canIf, final CanId canId, 326 | byte[] data) { 327 | this.canIf = canIf; 328 | this.canId = canId; 329 | this.data = data; 330 | } 331 | 332 | /* this constructor is used in native code */ 333 | @SuppressWarnings("unused") 334 | private CanFrame(int canIf, int canid, byte[] data) { 335 | if (data.length > 8) { 336 | throw new IllegalArgumentException(); 337 | } 338 | this.canIf = new CanInterface(canIf); 339 | this.canId = new CanId(canid); 340 | this.data = data; 341 | } 342 | 343 | public CanId getCanId() { 344 | return canId; 345 | } 346 | 347 | public byte[] getData() { 348 | return data; 349 | } 350 | 351 | public CanInterface getCanInterfacae() { 352 | return canIf; 353 | } 354 | 355 | @Override 356 | public String toString() { 357 | return "CanFrame [canIf=" + canIf + ", canId=" + canId + ", data=" 358 | + Arrays.toString(data) + "]"; 359 | } 360 | 361 | @Override 362 | protected Object clone() { 363 | return new CanFrame(canIf, (CanId)canId.clone(), 364 | Arrays.copyOf(data, data.length)); 365 | } 366 | } 367 | 368 | public static enum Mode { 369 | RAW, BCM 370 | } 371 | 372 | private final int _fd; 373 | private final Mode _mode; 374 | private CanInterface _boundTo; 375 | 376 | public CanSocket(Mode mode) throws IOException { 377 | switch (mode) { 378 | case BCM: 379 | _fd = _openSocketBCM(); 380 | break; 381 | case RAW: 382 | _fd = _openSocketRAW(); 383 | break; 384 | default: 385 | throw new IllegalStateException("unkown mode " + mode); 386 | } 387 | this._mode = mode; 388 | } 389 | 390 | public void bind(CanInterface canInterface) throws IOException { 391 | _bindToSocket(_fd, canInterface._ifIndex); 392 | this._boundTo = canInterface; 393 | } 394 | 395 | public void send(CanFrame frame) throws IOException { 396 | _sendFrame(_fd, frame.canIf._ifIndex, frame.canId._canId, frame.data); 397 | } 398 | 399 | public CanFrame recv() throws IOException { 400 | return _recvFrame(_fd); 401 | } 402 | 403 | @Override 404 | public void close() throws IOException { 405 | _close(_fd); 406 | } 407 | 408 | public int getMtu(final String canif) throws IOException { 409 | return _fetchInterfaceMtu(_fd, canif); 410 | } 411 | 412 | public void setLoopbackMode(final boolean on) throws IOException { 413 | _setsockopt(_fd, CAN_RAW_LOOPBACK, on ? 1 : 0); 414 | } 415 | 416 | public boolean getLoopbackMode() throws IOException { 417 | return _getsockopt(_fd, CAN_RAW_LOOPBACK) == 1; 418 | } 419 | 420 | public void setRecvOwnMsgsMode(final boolean on) throws IOException { 421 | _setsockopt(_fd, CAN_RAW_RECV_OWN_MSGS, on ? 1 : 0); 422 | } 423 | 424 | public boolean getRecvOwnMsgsMode() throws IOException { 425 | return _getsockopt(_fd, CAN_RAW_RECV_OWN_MSGS) == 1; 426 | } 427 | } 428 | --------------------------------------------------------------------------------