mirror of
https://github.com/intrepidcs/libicsneo.git
synced 2026-09-20 07:58:39 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb892bfd9b | ||
|
|
8801e949da | ||
|
|
d95a17b360 | ||
|
|
3a6501d116 | ||
|
|
34875129ee | ||
|
|
236c6ad089 | ||
|
|
cf58f819cb | ||
|
|
07e4eca14a | ||
|
|
936566170f | ||
|
|
3aaacb6cc8 | ||
|
|
1dda9f5412 | ||
|
|
78c2e3ff89 | ||
|
|
afedd4bb1f | ||
|
|
9b01e488da | ||
|
|
77a886bbe0 | ||
|
|
aff547b738 | ||
|
|
7a5c8c2879 | ||
|
|
0dd8dbfb64 | ||
|
|
d708f8081a | ||
|
|
743246e813 | ||
|
|
4ed29b4a5e | ||
|
|
55d69246b0 | ||
|
|
19232def41 | ||
|
|
9d91524dc0 | ||
|
|
d86e3164af | ||
|
|
3d99898598 | ||
|
|
4b9cf1a37f | ||
|
|
40d83f3b7c | ||
|
|
60918c4b6d | ||
|
|
749552e443 | ||
|
|
8af6d5f2a8 | ||
|
|
54fb89b675 | ||
|
|
299766403f | ||
|
|
2d0b0c63ed | ||
|
|
30606be7a8 | ||
|
|
4dd97f734a | ||
|
|
44d0e3de64 | ||
|
|
023f5aa089 | ||
|
|
bb711ae7e2 | ||
|
|
476b5ff35c | ||
|
|
99792a0ee1 | ||
|
|
d42c51d772 | ||
|
|
3ab06199c3 | ||
|
|
49e578a657 | ||
|
|
0bf279c7b9 | ||
|
|
9de0cf688c | ||
|
|
eded388b83 | ||
|
|
00b7b4a6de | ||
|
|
0ecb360195 | ||
|
|
b3bb033ecb | ||
|
|
c3762bbf22 | ||
|
|
e926e10dc5 | ||
|
|
5620c98eda | ||
|
|
c466d75dae | ||
|
|
d7fc7ffa47 | ||
|
|
70ad76771e | ||
|
|
87c10410e8 | ||
|
|
7cca96dcfb | ||
|
|
d45b72ef68 | ||
|
|
da02927da7 | ||
|
|
b5a6f6ace6 | ||
|
|
0d2bbed7d5 | ||
|
|
a68b64c641 | ||
|
|
9abd9389f4 | ||
|
|
d682627b40 | ||
|
|
9ae3e115fc | ||
|
|
87f45e060e | ||
|
|
0cb30cfc5b | ||
|
|
79ff19015a | ||
|
|
9c4323987f | ||
|
|
f5f6d0828b | ||
|
|
6dc005fcea | ||
|
|
5b553b63d3 | ||
|
|
97a6b4a04f | ||
|
|
67929a19bc | ||
|
|
e7c2c07947 | ||
|
|
146ddaf23c | ||
|
|
6f2ad54adc | ||
|
|
87e2a65b71 | ||
|
|
26e8a2c3d9 | ||
|
|
0ef26fec63 | ||
|
|
682299cb8c | ||
|
|
294e707924 | ||
|
|
22d2b7c984 | ||
|
|
5a4a1489a8 | ||
|
|
b0b7623b4c | ||
|
|
171422d8e1 | ||
|
|
81769db025 | ||
|
|
0e60f8f459 | ||
|
|
0aa7d338fd | ||
|
|
224e840841 | ||
|
|
174c0b80d4 | ||
|
|
19092bceb6 | ||
|
|
25b673075f | ||
|
|
1a7bc4df47 | ||
|
|
20a2474508 | ||
|
|
d18ca9e6eb | ||
|
|
6cda765fe0 | ||
|
|
730aaf5fed | ||
|
|
1f10adb760 | ||
|
|
6a32823a0f | ||
|
|
5f16adc103 | ||
|
|
f6926cbb22 | ||
|
|
4c7b8e107a | ||
|
|
0e55101a16 | ||
|
|
68ebb6dae4 | ||
|
|
8cb62c2cae | ||
|
|
d74051f57e | ||
|
|
530a99d264 | ||
|
|
5ee450353b | ||
|
|
516bca682c | ||
|
|
3f5150bef3 | ||
|
|
2a2d55f20d | ||
|
|
977677e3af | ||
|
|
000036f745 | ||
|
|
be6a15c017 | ||
|
|
5288385495 | ||
|
|
d6d9fc16ef | ||
|
|
dbab92b25c | ||
|
|
579160f6d4 | ||
|
|
737d5ceb3b | ||
|
|
95521a5548 | ||
|
|
16cd476c01 | ||
|
|
d328d314b6 | ||
|
|
7b5b94d980 | ||
|
|
fedb4b88f3 | ||
|
|
5cac3a4600 | ||
|
|
9ff4bf7d0d | ||
|
|
30c009fe8f | ||
|
|
51e4fdc6d9 | ||
|
|
39b54d8c4e | ||
|
|
615b7d8d56 | ||
|
|
e3f4bbdc73 | ||
|
|
563c444def | ||
|
|
3f3300d677 | ||
|
|
b9e3542bcf | ||
|
|
7f192a0cea | ||
|
|
3b60bfc986 | ||
|
|
d51f88d023 | ||
|
|
f3cb41d60b | ||
|
|
1b00c6a05b | ||
|
|
ebf9409c18 | ||
|
|
83ab65b062 | ||
|
|
7f1668a55b | ||
|
|
10ffd756a1 | ||
|
|
c2f1022858 | ||
|
|
bf311ebe30 | ||
|
|
5cdaeb1edc | ||
|
|
deabc2cff4 | ||
|
|
b48160286b | ||
|
|
5d672d48d4 | ||
|
|
495632ddb7 | ||
|
|
3668b86f37 | ||
|
|
0bd733bc5d | ||
|
|
99a2ca4f0d | ||
|
|
ec350b522a | ||
|
|
895cd0792c | ||
|
|
a5ec9a2d20 | ||
|
|
b9d3dde8d5 | ||
|
|
11643e2281 | ||
|
|
f22d666f94 | ||
|
|
58b22da09b | ||
|
|
88d32128c9 | ||
|
|
6d82289864 | ||
|
|
674e905340 | ||
|
|
8b7e2556a0 | ||
|
|
fbdab1e998 | ||
|
|
f53bc2e920 | ||
|
|
a9e1f24f67 | ||
|
|
b10e29b8f5 | ||
|
|
3c0c0dd44c | ||
|
|
cf2cf3e28b | ||
|
|
6926ca8199 | ||
|
|
29dc7b345f | ||
|
|
17285389e3 | ||
|
|
328563b7e6 | ||
|
|
6b60804174 | ||
|
|
c5bce795c6 | ||
|
|
1e5e714f5b | ||
|
|
d70defbf8a | ||
|
|
10efacf91e | ||
|
|
6d985ca873 | ||
|
|
19df557b4a | ||
|
|
7afa41bf2a | ||
|
|
c056e8dc2e | ||
|
|
d5ae1cdb03 | ||
|
|
5795791eac | ||
|
|
c91db6355c | ||
|
|
f37b88d616 | ||
|
|
33dea748f7 | ||
|
|
245073f9d5 | ||
|
|
c4e858d346 | ||
|
|
b3d47f2ae5 | ||
|
|
b94ade1ef6 | ||
|
|
d9ea5e085e | ||
|
|
5125520e76 | ||
|
|
4dcb944d35 | ||
|
|
7eeb1b6c38 | ||
|
|
b1e875980c | ||
|
|
8b680f2b64 | ||
|
|
e88cd244c8 | ||
|
|
70733b3d96 | ||
|
|
f743f32e63 | ||
|
|
830fe1af59 | ||
|
|
2209e348a3 | ||
|
|
52e98af9fd | ||
|
|
e1a0ca056a | ||
|
|
538d6ec0c8 | ||
|
|
1ba3eded09 | ||
|
|
89047447a6 | ||
|
|
f97fd75b8d | ||
|
|
ea5f11268c | ||
|
|
759cb2436d | ||
|
|
771d82826f | ||
|
|
b7330a2cea | ||
|
|
fb3778f91b | ||
|
|
a0c8cc62df | ||
|
|
77b3564677 | ||
|
|
051063e684 | ||
|
|
7c1cfde6a0 | ||
|
|
d4995fa2a9 | ||
|
|
fb5c4babce | ||
|
|
4ba1a1e1dd | ||
|
|
6b9a687ff9 | ||
|
|
02b5dafca9 | ||
|
|
f04cd16bee | ||
|
|
c5ba2d8d32 | ||
|
|
a22791c9e0 | ||
|
|
dc2a364afb | ||
|
|
114b664d78 | ||
|
|
2acf248583 | ||
|
|
f18aa00322 | ||
|
|
87baa97c3f | ||
|
|
8dcbbe0d72 | ||
|
|
b624d06ca0 | ||
|
|
c249df8756 | ||
|
|
b2161211c5 | ||
|
|
0ee8a990a7 | ||
|
|
dc0f16b1d2 | ||
|
|
c4ce803d62 | ||
|
|
34cacf4cf2 | ||
|
|
4157558e84 | ||
|
|
40b85488dc | ||
|
|
7584563002 | ||
|
|
4f83614037 | ||
|
|
38a4af8062 | ||
|
|
3b95b41be4 | ||
|
|
3da31a29b4 | ||
|
|
d0f3e593df | ||
|
|
90268a4f04 | ||
|
|
dbe19a5616 | ||
|
|
e5d7a38160 | ||
|
|
d714b620c4 | ||
|
|
10d2625cb6 | ||
|
|
b9cfa85009 | ||
|
|
776d14bb3e | ||
|
|
648fb2502f | ||
|
|
008a0e4057 | ||
|
|
3787bc27a2 | ||
|
|
e73f61bfcc | ||
|
|
f552df372b | ||
|
|
80904dd84c | ||
|
|
e2bd0b5a3e | ||
|
|
24f291dc83 | ||
|
|
ee7b66625a | ||
|
|
99183a89f9 | ||
|
|
7f30179cc4 | ||
|
|
39bcef0230 | ||
|
|
ca370a1310 | ||
|
|
564933cb41 | ||
|
|
cac8d760b0 | ||
|
|
75af3220b0 | ||
|
|
f25a0a4a81 | ||
|
|
387c39d3a0 | ||
|
|
4476bd8b71 | ||
|
|
14588591e5 | ||
|
|
cbcbcbdc5d | ||
|
|
cf1b4778a1 | ||
|
|
77928dc93d | ||
|
|
659fcf633c | ||
|
|
9a1cd1124d | ||
|
|
3782e12ef6 | ||
|
|
bc6f5eca9c | ||
|
|
53ba297a44 | ||
|
|
d9bf4f423e | ||
|
|
ba3bceaee0 | ||
|
|
31d47613e7 | ||
|
|
9c830a91a2 | ||
|
|
46e244fbab | ||
|
|
63f0516318 | ||
|
|
7d2d12c5cd | ||
|
|
bcf9d62be9 | ||
|
|
a01aa90740 | ||
|
|
85178368d7 | ||
|
|
16b60d5ca0 | ||
|
|
cb22e622b3 | ||
|
|
06f6861130 | ||
|
|
219a5edbd8 | ||
|
|
05888e5c20 | ||
|
|
e37d939699 | ||
|
|
2a94b4566b | ||
|
|
4782e26bed | ||
|
|
3264a1ecbe | ||
|
|
1dfed4c9c4 | ||
|
|
a44952be13 | ||
|
|
75e9319c32 | ||
|
|
9df4aed19f | ||
|
|
d56e66afd3 | ||
|
|
26b52237e4 | ||
|
|
28ba94fa25 | ||
|
|
e56c714a0c | ||
|
|
58f53edea8 | ||
|
|
3d2d3cb43d | ||
|
|
bddbcfcf6d | ||
|
|
0497b361ef | ||
|
|
02f1b4592e | ||
|
|
4248c1a538 | ||
|
|
ec51393dfc | ||
|
|
90e1aa223d | ||
|
|
e0cef880f0 | ||
|
|
cc7cffe068 | ||
|
|
e97b307c4d | ||
|
|
0c436621a0 | ||
|
|
508013baf4 | ||
|
|
8d704b1bbb | ||
|
|
018f1fac8e | ||
|
|
188a087c51 | ||
|
|
53e66b8772 | ||
|
|
41d6927496 | ||
|
|
237bed1b72 | ||
|
|
6c93fc839b | ||
|
|
4cf35acf6c | ||
|
|
9ef93eb73e | ||
|
|
5b3e21fa7c | ||
|
|
a36d114e1f | ||
|
|
ee9cf26eb2 | ||
|
|
d7d98855ea | ||
|
|
245f5089da | ||
|
|
d9c12bffe7 | ||
|
|
f907d6759f | ||
|
|
1e773ba9ab | ||
|
|
f5096b879c | ||
|
|
0de23f2817 | ||
|
|
32900ae263 | ||
|
|
b6d9ef4c7e | ||
|
|
2f7c3a2dda | ||
|
|
bbf348a6ab | ||
|
|
73744bf6d9 | ||
|
|
6b0c588a46 | ||
|
|
b3bbf91e8c | ||
|
|
af31aa23ad | ||
|
|
83f6c611fe | ||
|
|
4fa813ccbc | ||
|
|
3ddb832708 | ||
|
|
63c81b1c3d | ||
|
|
0fa7494eab | ||
|
|
cd7b0b0a7b | ||
|
|
d9cdd03618 | ||
|
|
832cf9c84b | ||
|
|
bf6a059820 | ||
|
|
9b46d486cb | ||
|
|
ddee1254a0 | ||
|
|
539cfa511b | ||
|
|
4229d8b66a | ||
|
|
dc1c4ede9d | ||
|
|
9e7d442e83 | ||
|
|
41a569fc2d | ||
|
|
f4e4a103ad | ||
|
|
78465e0f20 | ||
|
|
ed1632c652 | ||
|
|
c97db0f35f | ||
|
|
c9d8a4f0a9 | ||
|
|
96fe8895fc | ||
|
|
e46755f120 | ||
|
|
0619c37a90 | ||
|
|
de58b2d639 | ||
|
|
5ff1707c47 | ||
|
|
4c0d49f09a | ||
|
|
b32f58da38 | ||
|
|
0101467154 | ||
|
|
17b3018499 | ||
|
|
0fc676e576 | ||
|
|
7b2544864b | ||
|
|
7f22286838 | ||
|
|
643768fb6a | ||
|
|
9817887523 | ||
|
|
13ec2bca98 | ||
|
|
711976cce0 | ||
|
|
e02203a974 | ||
|
|
5b14ec7246 | ||
|
|
3b80746fb8 | ||
|
|
3b9a31ef51 | ||
|
|
124bd3b310 | ||
|
|
9871430288 | ||
|
|
2e296dc8d3 | ||
|
|
b35fab754c | ||
|
|
9ef01e2d3d | ||
|
|
1bb33156f7 | ||
|
|
a0f73755e8 | ||
|
|
ab54697745 | ||
|
|
0d0b7f00bd | ||
|
|
1a28fbf5ad | ||
|
|
b50706846c | ||
|
|
d6d34eb7bc | ||
|
|
a928a1d879 | ||
|
|
de3d8bf870 | ||
|
|
407ccccedd | ||
|
|
00024990e9 | ||
|
|
cb47065a47 | ||
|
|
2b819065ad | ||
|
|
58700afc73 | ||
|
|
55d7d5bf17 | ||
|
|
c08c0dd893 | ||
|
|
44ad06d4bb | ||
|
|
c2de1dfdf1 | ||
|
|
a2cfc50b7c | ||
|
|
c398afc4e3 | ||
|
|
8d495aa916 | ||
|
|
91abf378f8 | ||
|
|
2e3b738e76 | ||
|
|
103f938d69 | ||
|
|
d45d708446 | ||
|
|
5d4ed0f4cd | ||
|
|
2dd91325e6 | ||
|
|
008a1620c8 | ||
|
|
781fc2c034 | ||
|
|
0ff12300f3 | ||
|
|
f4e16025c1 | ||
|
|
fef6f363f1 | ||
|
|
f367fcecca | ||
|
|
f05fd5e201 | ||
|
|
adad9b3761 | ||
|
|
0a15adbe91 | ||
|
|
1118428250 | ||
|
|
8c774228bc | ||
|
|
478dfb3cb8 | ||
|
|
8aa5bef7dc | ||
|
|
453d3366af | ||
|
|
caf5cca42f | ||
|
|
ae1b8d342e | ||
|
|
c314417277 | ||
|
|
1fadb85206 | ||
|
|
6bcd8e5637 | ||
|
|
4c9d6c5ee7 | ||
|
|
4ef8fe8794 | ||
|
|
f8a46b7196 | ||
|
|
0b27e88da1 | ||
|
|
241502c2a2 | ||
|
|
242c7259ac | ||
|
|
9d2d94d22b | ||
|
|
bb49ce039e | ||
|
|
e52073c518 | ||
|
|
0dcd950092 | ||
|
|
80cd4ae052 | ||
|
|
f8bfb243fa | ||
|
|
fe4d5e0c15 | ||
|
|
9e6970fd39 | ||
|
|
f1d9be1a81 | ||
|
|
6cd821be2c | ||
|
|
6cc0f08e2b | ||
|
|
80362e7f81 | ||
|
|
d7d9c15a9f | ||
|
|
c326397bea | ||
|
|
af152fe54a | ||
|
|
d051d20db6 | ||
|
|
d0d279fdad | ||
|
|
2c282fe396 | ||
|
|
95de93aa84 | ||
|
|
733312628c | ||
|
|
b177617940 | ||
|
|
28d3730375 | ||
|
|
c32d027b2d | ||
|
|
ac7b2d5106 | ||
|
|
4dbb8f3956 | ||
|
|
eace014494 | ||
|
|
159c54b756 | ||
|
|
416996b31d | ||
|
|
f37669139f | ||
|
|
7aedb673fd | ||
|
|
52c7b5aaca | ||
|
|
0f9bf83c89 | ||
|
|
dfd8768bbf | ||
|
|
94e0ea1fe0 | ||
|
|
58944a2523 | ||
|
|
be666e810d | ||
|
|
c451fc2b7c | ||
|
|
c620b2ee8b | ||
|
|
111d377d4a | ||
|
|
c3469f5fb6 | ||
|
|
0219eccc94 | ||
|
|
e22f70a35a | ||
|
|
b019c20ad0 | ||
|
|
6fa469de5f | ||
|
|
be219288dc | ||
|
|
d35653e3d0 | ||
|
|
0ce7326b83 | ||
|
|
44e48182bf | ||
|
|
4fd65d85c8 | ||
|
|
0ded5508c1 | ||
|
|
6d92b7a03a | ||
|
|
2d1bb381f6 | ||
|
|
890eb1e1bc | ||
|
|
96f18dcfd6 | ||
|
|
d5087c1ba5 | ||
|
|
f8b5710a6c | ||
|
|
78747aa899 | ||
|
|
2d6004bed1 | ||
|
|
574530978c | ||
|
|
988289afc1 | ||
|
|
714db03a05 | ||
|
|
d097fb9a74 | ||
|
|
9d5bad94d4 | ||
|
|
181223375a | ||
|
|
51626b9e63 | ||
|
|
a1a544045b | ||
|
|
719dbcefc8 | ||
|
|
ac77fe2b56 | ||
|
|
1aa3828688 | ||
|
|
0656cb568e | ||
|
|
6b37acf471 | ||
|
|
df9827fb2c | ||
|
|
f129be34b5 | ||
|
|
38f0022bb6 | ||
|
|
67c8e6a952 | ||
|
|
80c6816a54 | ||
|
|
c5314884ce | ||
|
|
82954d9190 | ||
|
|
1b13e2d6a4 | ||
|
|
c847d68f3c | ||
|
|
3764a2e814 | ||
|
|
5f44986c1b | ||
|
|
68715d515d | ||
|
|
27184a203f | ||
|
|
c7e7222140 | ||
|
|
6241996a58 | ||
|
|
84c6b202c7 | ||
|
|
16b88b7787 | ||
|
|
0c67cdf078 | ||
|
|
bb65e37841 | ||
|
|
02c14aeb35 | ||
|
|
ca83d7c4f2 | ||
|
|
4da5f63e57 | ||
|
|
37d06807e4 | ||
|
|
b13a33f0be | ||
|
|
af2c30885b | ||
|
|
3cff831c6b | ||
|
|
a8562aca60 | ||
|
|
e5bf87ba7d | ||
|
|
da4ab6ef62 | ||
|
|
a9840028ff | ||
|
|
4b7cb28bdf | ||
|
|
c888aad5ae | ||
|
|
8c9d3a5e6a | ||
|
|
4588cb55fa | ||
|
|
9b2eae4a6c | ||
|
|
45c879c2b6 | ||
|
|
a43c0117d6 | ||
|
|
f3e456e7ea | ||
|
|
843fa92564 | ||
|
|
34f7bfabd2 | ||
|
|
d82a069842 | ||
|
|
9e70a9d51f | ||
|
|
4095f23ded | ||
|
|
1b7db51a45 | ||
|
|
165eb0f8a2 | ||
|
|
ed94012046 | ||
|
|
7b7320bc27 | ||
|
|
19aabdfacf | ||
|
|
b340d167dc | ||
|
|
d4f6c12394 | ||
|
|
4e901676d2 | ||
|
|
ffe2d34799 | ||
|
|
71fc039689 | ||
|
|
496a007da3 | ||
|
|
cf8bcd1d63 | ||
|
|
bda37e31f3 | ||
|
|
c12330eec4 | ||
|
|
04e7bfd1af | ||
|
|
ed5132e852 | ||
|
|
76b6ecbf04 | ||
|
|
ad07af160c | ||
|
|
21bc4eeff2 | ||
|
|
21e93d1f73 | ||
|
|
b97f358a0f | ||
|
|
6f8e073fd1 | ||
|
|
07afbebc6d | ||
|
|
9ba7320fd3 | ||
|
|
f752924a36 | ||
|
|
295ba490aa | ||
|
|
1bb114004e | ||
|
|
e99107c1bc | ||
|
|
82113f1a67 | ||
|
|
0006f31844 | ||
|
|
595cc36545 | ||
|
|
8be3bbaee5 | ||
|
|
72bc5914a6 | ||
|
|
eca1110305 | ||
|
|
b104b34919 | ||
|
|
805ff4f549 | ||
|
|
78e3eb18df | ||
|
|
6d22b1e001 | ||
|
|
b7c7d4349a | ||
|
|
3d4e0a27e3 | ||
|
|
0ce52f064b | ||
|
|
f629125e67 | ||
|
|
a63d701839 | ||
|
|
622c5ee57a | ||
|
|
5733300de6 | ||
|
|
65a6fadd1d | ||
|
|
8e2883bca9 | ||
|
|
f8355df770 | ||
|
|
218648ae5a | ||
|
|
4cd7bafca7 | ||
|
|
6c1cbc9db8 | ||
|
|
b7ce9819bd | ||
|
|
55ca6adee6 | ||
|
|
bb7719d185 | ||
|
|
4b12d3aa4d | ||
|
|
bb322ad190 | ||
|
|
92589c2ce7 | ||
|
|
3b6b4f0541 | ||
|
|
40be68e744 | ||
|
|
e29d63b08c | ||
|
|
d79f735df8 | ||
|
|
e82b5d15e0 | ||
|
|
c8bf1f26da | ||
|
|
9ba21d5dc7 | ||
|
|
eb5a84132a | ||
|
|
66b0c91cea | ||
|
|
7fdae15aed | ||
|
|
adb972b1f7 | ||
|
|
441b16e9a1 | ||
|
|
cf8c5a31c7 | ||
|
|
a6c8acd8e9 | ||
|
|
4e245db94e | ||
|
|
4a1d0382f2 | ||
|
|
18394d0cfb | ||
|
|
4bca43028c | ||
|
|
92790330f1 | ||
|
|
7f27b30954 | ||
|
|
f63c187ed3 | ||
|
|
4d655da69d | ||
|
|
09a02ff420 | ||
|
|
33a84bf8ce | ||
|
|
7c1d44bc4f | ||
|
|
cfaf677263 | ||
|
|
ffbb5e20c5 | ||
|
|
e5920417ff | ||
|
|
a5b27a15b0 | ||
|
|
dfe2d23d85 | ||
|
|
66d7c2f390 | ||
|
|
7e714abfd1 | ||
|
|
2cd074cf13 | ||
|
|
90b04f4578 | ||
|
|
6f0654c336 | ||
|
|
76619e2496 | ||
|
|
2c55584962 | ||
|
|
1f4358af4b | ||
|
|
28b35a8243 | ||
|
|
5c18bedf70 | ||
|
|
eda4a30dcd | ||
|
|
211f844f77 | ||
|
|
8843ace87e | ||
|
|
d2676afa11 | ||
|
|
c48efe8e5b | ||
|
|
9dc4b302ef | ||
|
|
a460e27657 | ||
|
|
eaa1409af0 | ||
|
|
de0c16a461 | ||
|
|
3f8ed840ba | ||
|
|
12463ea2f4 | ||
|
|
8e999a0fb8 | ||
|
|
a325d8a12b | ||
|
|
046e2bae9d | ||
|
|
c48995520f | ||
|
|
aceea6dc5b | ||
|
|
1bb1ab7a82 | ||
|
|
044c2bb86f | ||
|
|
5db07102aa | ||
|
|
b5c9443fc8 | ||
|
|
4c2cd918de | ||
|
|
7cd008a003 | ||
|
|
dfe5845b3c | ||
|
|
b6692d3762 | ||
|
|
3e4b595fe4 | ||
|
|
4cd897badd | ||
|
|
afda617894 | ||
|
|
1d286be1e4 | ||
|
|
6638cf05ae | ||
|
|
d58202dfc0 | ||
|
|
08928c36e3 | ||
|
|
4b218b3f9a | ||
|
|
07e99515fa | ||
|
|
3123cbb54b | ||
|
|
17ebba3c57 | ||
|
|
7b3782cbe7 | ||
|
|
f9ff4049f2 | ||
|
|
154eab4b1b |
+8
-1
@@ -8,4 +8,11 @@ CMakeSettings.json
|
||||
third-party/concurrentqueue/benchmarks
|
||||
third-party/concurrentqueue/tests
|
||||
*.bak
|
||||
.vs
|
||||
.vs
|
||||
.cache
|
||||
*.wav
|
||||
*.orig
|
||||
examples/csharp/bin
|
||||
examples/csharp/obj
|
||||
test/system
|
||||
.env
|
||||
|
||||
+380
@@ -0,0 +1,380 @@
|
||||
default:
|
||||
interruptible: true
|
||||
|
||||
variables:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
LIBICSNEO_ICSPB_REPO: https://gitlab-ci-token:${CI_JOB_TOKEN}@${LIBICSNEO_ICSPB_GIT}
|
||||
|
||||
stages:
|
||||
- build
|
||||
- unit_test
|
||||
- deploy
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Windows
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
build windows/x64:
|
||||
stage: build
|
||||
script:
|
||||
- cmd /C ci\build-windows64.bat
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- build
|
||||
expire_in: 3 days
|
||||
tags:
|
||||
- libicsneo-win-x64
|
||||
|
||||
unit_test windows/x64:
|
||||
stage: unit_test
|
||||
script:
|
||||
- build\libicsneo-unit-tests.exe
|
||||
dependencies:
|
||||
- build windows/x64
|
||||
needs:
|
||||
- build windows/x64
|
||||
tags:
|
||||
- libicsneo-win-x64
|
||||
timeout: 5m
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Ubuntu
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
.build_linux_ubuntu_gcc: &build_linux_ubuntu_gcc
|
||||
stage: build
|
||||
script:
|
||||
- apt update -y
|
||||
- apt upgrade -y
|
||||
- apt install -y g++ ninja-build cmake libpcap-dev git ca-certificates
|
||||
- echo "$ICS_IPA_CA_CRT" >/usr/local/share/ca-certificates/ica-ipa-ca.crt
|
||||
- update-ca-certificates --fresh
|
||||
- sh ci/build-posix.sh
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- build
|
||||
expire_in: 3 days
|
||||
tags:
|
||||
- linux-build
|
||||
|
||||
.test_linux_ubuntu_gcc: &test_linux_ubuntu_gcc
|
||||
stage: unit_test
|
||||
script:
|
||||
- apt update -y
|
||||
- apt upgrade -y
|
||||
- apt install -y libpcap-dev
|
||||
- build/libicsneo-unit-tests
|
||||
tags:
|
||||
- linux-build
|
||||
timeout: 5m
|
||||
|
||||
.build_linux_ubuntu_clang: &build_linux_ubuntu_clang
|
||||
stage: build
|
||||
script:
|
||||
- apt update -y
|
||||
- apt upgrade -y
|
||||
- apt install -y clang lld ninja-build cmake libpcap-dev git ca-certificates
|
||||
- echo "$ICS_IPA_CA_CRT" >/usr/local/share/ca-certificates/ica-ipa-ca.crt
|
||||
- update-ca-certificates --fresh
|
||||
- CC=clang CXX=clang++ LDFLAGS=-fuse-ld=lld sh ci/build-posix.sh
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- build
|
||||
expire_in: 3 days
|
||||
tags:
|
||||
- linux-build
|
||||
|
||||
.test_linux_ubuntu_clang: &test_linux_ubuntu_clang
|
||||
stage: unit_test
|
||||
script:
|
||||
- apt update -y
|
||||
- apt upgrade -y
|
||||
- apt install -y libpcap-dev
|
||||
- build/libicsneo-unit-tests
|
||||
tags:
|
||||
- linux-build
|
||||
timeout: 5m
|
||||
|
||||
build linux/ubuntu/2404/amd64/gcc:
|
||||
<<: *build_linux_ubuntu_gcc
|
||||
image: ubuntu:24.04
|
||||
|
||||
unit_test linux/ubuntu/2404/amd64/gcc:
|
||||
<<: *test_linux_ubuntu_gcc
|
||||
image: ubuntu:24.04
|
||||
dependencies:
|
||||
- build linux/ubuntu/2404/amd64/gcc
|
||||
needs:
|
||||
- build linux/ubuntu/2404/amd64/gcc
|
||||
|
||||
build linux/ubuntu/2404/amd64/clang:
|
||||
<<: *build_linux_ubuntu_clang
|
||||
image: ubuntu:24.04
|
||||
|
||||
unit_test linux/ubuntu/2404/amd64/clang:
|
||||
<<: *test_linux_ubuntu_clang
|
||||
image: ubuntu:24.04
|
||||
dependencies:
|
||||
- build linux/ubuntu/2404/amd64/clang
|
||||
needs:
|
||||
- build linux/ubuntu/2404/amd64/clang
|
||||
|
||||
build linux/ubuntu/2604/amd64/gcc:
|
||||
<<: *build_linux_ubuntu_gcc
|
||||
image: ubuntu:26.04
|
||||
|
||||
unit_test linux/ubuntu/2604/amd64/gcc:
|
||||
<<: *test_linux_ubuntu_gcc
|
||||
image: ubuntu:26.04
|
||||
dependencies:
|
||||
- build linux/ubuntu/2604/amd64/gcc
|
||||
needs:
|
||||
- build linux/ubuntu/2604/amd64/gcc
|
||||
|
||||
build linux/ubuntu/2604/amd64/clang:
|
||||
<<: *build_linux_ubuntu_clang
|
||||
image: ubuntu:26.04
|
||||
|
||||
unit_test linux/ubuntu/2604/amd64/clang:
|
||||
<<: *test_linux_ubuntu_clang
|
||||
image: ubuntu:26.04
|
||||
dependencies:
|
||||
- build linux/ubuntu/2604/amd64/clang
|
||||
needs:
|
||||
- build linux/ubuntu/2604/amd64/clang
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Fedora
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
.build_linux_fedora_gcc: &build_linux_fedora_gcc
|
||||
stage: build
|
||||
cache:
|
||||
paths:
|
||||
- /var/cache/dnf
|
||||
script:
|
||||
- echo max_parallel_downloads=10 >>/etc/dnf/dnf.conf
|
||||
- echo fastestmirror=True >>/etc/dnf/dnf.conf
|
||||
- dnf upgrade -y
|
||||
- dnf install -y g++ libpcap-devel cmake ninja-build git ca-certificates
|
||||
- echo "$ICS_IPA_CA_CRT" >/etc/pki/ca-trust/source/anchors/ica-ipa-ca.crt
|
||||
- update-ca-trust
|
||||
- sh ci/build-posix.sh
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- build
|
||||
expire_in: 3 days
|
||||
tags:
|
||||
- linux-build
|
||||
|
||||
.test_linux_fedora_gcc: &test_linux_fedora_gcc
|
||||
stage: unit_test
|
||||
cache:
|
||||
paths:
|
||||
- /var/cache/dnf
|
||||
script:
|
||||
- echo max_parallel_downloads=10 >>/etc/dnf/dnf.conf
|
||||
- echo fastestmirror=True >>/etc/dnf/dnf.conf
|
||||
- dnf upgrade -y
|
||||
- dnf install -y libpcap-devel
|
||||
- build/libicsneo-unit-tests
|
||||
tags:
|
||||
- linux-build
|
||||
timeout: 5m
|
||||
|
||||
.build_linux_fedora_clang: &build_linux_fedora_clang
|
||||
stage: build
|
||||
cache:
|
||||
paths:
|
||||
- /var/cache/dnf
|
||||
script:
|
||||
- echo max_parallel_downloads=10 >>/etc/dnf/dnf.conf
|
||||
- echo fastestmirror=True >>/etc/dnf/dnf.conf
|
||||
- dnf upgrade -y
|
||||
- dnf install -y clang lld libpcap-devel cmake ninja-build git ca-certificates
|
||||
- echo "$ICS_IPA_CA_CRT" >/etc/pki/ca-trust/source/anchors/ica-ipa-ca.crt
|
||||
- update-ca-trust
|
||||
- CC=clang CXX=clang++ LDFLAGS=-fuse-ld=lld sh ci/build-posix.sh
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- build
|
||||
expire_in: 3 days
|
||||
tags:
|
||||
- linux-build
|
||||
|
||||
.test_linux_fedora_clang: &test_linux_fedora_clang
|
||||
stage: unit_test
|
||||
cache:
|
||||
paths:
|
||||
- /var/cache/dnf
|
||||
script:
|
||||
- echo max_parallel_downloads=10 >>/etc/dnf/dnf.conf
|
||||
- echo fastestmirror=True >>/etc/dnf/dnf.conf
|
||||
- dnf upgrade -y
|
||||
- dnf install -y libpcap-devel
|
||||
- build/libicsneo-unit-tests
|
||||
tags:
|
||||
- linux-build
|
||||
timeout: 5m
|
||||
|
||||
build linux/fedora/43/amd64/gcc:
|
||||
<<: *build_linux_fedora_gcc
|
||||
image: fedora:43
|
||||
|
||||
unit_test linux/fedora/43/amd64/gcc:
|
||||
<<: *test_linux_fedora_gcc
|
||||
image: fedora:43
|
||||
dependencies:
|
||||
- build linux/fedora/43/amd64/gcc
|
||||
needs:
|
||||
- build linux/fedora/43/amd64/gcc
|
||||
|
||||
build linux/fedora/43/amd64/clang:
|
||||
<<: *build_linux_fedora_clang
|
||||
image: fedora:43
|
||||
|
||||
unit_test linux/fedora/43/amd64/clang:
|
||||
<<: *test_linux_fedora_clang
|
||||
image: fedora:43
|
||||
dependencies:
|
||||
- build linux/fedora/43/amd64/clang
|
||||
needs:
|
||||
- build linux/fedora/43/amd64/clang
|
||||
|
||||
build linux/fedora/44/amd64/gcc:
|
||||
<<: *build_linux_fedora_gcc
|
||||
image: fedora:44
|
||||
|
||||
unit_test linux/fedora/44/amd64/gcc:
|
||||
<<: *test_linux_fedora_gcc
|
||||
image: fedora:44
|
||||
dependencies:
|
||||
- build linux/fedora/44/amd64/gcc
|
||||
needs:
|
||||
- build linux/fedora/44/amd64/gcc
|
||||
|
||||
build linux/fedora/44/amd64/clang:
|
||||
<<: *build_linux_fedora_clang
|
||||
image: fedora:44
|
||||
|
||||
unit_test linux/fedora/44/amd64/clang:
|
||||
<<: *test_linux_fedora_clang
|
||||
image: fedora:44
|
||||
dependencies:
|
||||
- build linux/fedora/44/amd64/clang
|
||||
needs:
|
||||
- build linux/fedora/44/amd64/clang
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Python Module
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
build python/linux/amd64:
|
||||
stage: build
|
||||
tags:
|
||||
- linux-native-amd64
|
||||
variables:
|
||||
CIBW_BEFORE_ALL: sh ci/bootstrap-cibuildwheel.sh && sh ci/bootstrap-libpcap.sh
|
||||
CIBW_BUILD: "*manylinux*" # no musl
|
||||
CIBW_ARCHS: x86_64
|
||||
CIBW_ENVIRONMENT: PCAP_ROOT=/project/libpcap/install
|
||||
SKBUILD_CMAKE_DEFINE: ICSPB_BOOTSTRAP_DIR=/project/icspb
|
||||
script:
|
||||
- sh ci/build-wheel-posix.sh
|
||||
artifacts:
|
||||
paths:
|
||||
- wheelhouse
|
||||
|
||||
build python/linux/arm64:
|
||||
stage: build
|
||||
tags:
|
||||
- arm64-linux-build
|
||||
variables:
|
||||
CIBW_BEFORE_ALL: sh ci/bootstrap-cibuildwheel.sh && sh ci/bootstrap-libpcap.sh
|
||||
CIBW_BUILD: "*manylinux*" # no musl
|
||||
CIBW_ARCHS: aarch64
|
||||
CIBW_ENVIRONMENT: PCAP_ROOT=/project/libpcap/install
|
||||
SKBUILD_CMAKE_DEFINE: ICSPB_BOOTSTRAP_DIR=/project/icspb
|
||||
script:
|
||||
- sh ci/build-wheel-posix.sh
|
||||
artifacts:
|
||||
paths:
|
||||
- wheelhouse
|
||||
|
||||
build python/macos:
|
||||
stage: build
|
||||
tags:
|
||||
- macos-arm64
|
||||
variables:
|
||||
CIBW_BEFORE_ALL: sh ci/bootstrap-libpcap.sh
|
||||
CIBW_ARCHS: arm64
|
||||
CIBW_ENVIRONMENT: PCAP_ROOT=$CI_PROJECT_DIR/libpcap/install
|
||||
SKBUILD_CMAKE_DEFINE: ICSPB_BOOTSTRAP_DIR=$CI_PROJECT_DIR/icspb
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.14
|
||||
script:
|
||||
- sh ci/build-wheel-posix.sh
|
||||
artifacts:
|
||||
paths:
|
||||
- wheelhouse
|
||||
|
||||
build python/windows:
|
||||
stage: build
|
||||
tags:
|
||||
- libicsneo-win-x64
|
||||
variables:
|
||||
CIBW_ARCHS: AMD64
|
||||
CIBW_ENVIRONMENT: CMAKE_GENERATOR=Ninja
|
||||
SKBUILD_CMAKE_DEFINE: ICSPB_BOOTSTRAP_DIR=$CI_PROJECT_DIR/icspb
|
||||
script:
|
||||
- cmd /c ci\build-wheel-windows.bat
|
||||
artifacts:
|
||||
paths:
|
||||
- wheelhouse
|
||||
|
||||
deploy python/pypi:
|
||||
stage: deploy
|
||||
interruptible: false
|
||||
variables:
|
||||
TWINE_USERNAME: __token__
|
||||
TWINE_PASSWORD: $PYPI_TOKEN
|
||||
tags:
|
||||
- linux-build
|
||||
image: python:3.13
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||
script:
|
||||
- python3 -m pip install -U twine
|
||||
- twine upload wheelhouse/*
|
||||
dependencies:
|
||||
- build python/linux/amd64
|
||||
- build python/linux/arm64
|
||||
- build python/macos
|
||||
- build python/windows
|
||||
needs:
|
||||
- build python/linux/amd64
|
||||
- build python/linux/arm64
|
||||
- build python/macos
|
||||
- build python/windows
|
||||
|
||||
push github:
|
||||
stage: deploy
|
||||
interruptible: false
|
||||
tags:
|
||||
- linux-build
|
||||
image: alpine:latest
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||
when: delayed
|
||||
start_in: 10 minutes
|
||||
dependencies:
|
||||
- deploy python/pypi
|
||||
needs:
|
||||
- deploy python/pypi
|
||||
script:
|
||||
- apk add git
|
||||
- git push https://$LIBICSNEO_GITHUB_USERNAME:$LIBICSNEO_GITHUB_TOKEN@github.com/intrepidcs/libicsneo.git HEAD:master
|
||||
@@ -0,0 +1,15 @@
|
||||
version: 2
|
||||
|
||||
build:
|
||||
os: "ubuntu-24.04"
|
||||
tools:
|
||||
python: "3.12"
|
||||
apt_packages:
|
||||
- doxygen
|
||||
|
||||
python:
|
||||
install:
|
||||
- requirements: docs/requirements.txt
|
||||
|
||||
sphinx:
|
||||
configuration: docs/conf.py
|
||||
+5
-21
@@ -3,24 +3,8 @@ SUBSYSTEM=="usb", ATTRS{idVendor}=="093c", GROUP="users", MODE="0666"
|
||||
KERNEL=="ttyUSB?", ATTRS{idVendor}=="093c", GROUP="users", MODE="0666"
|
||||
KERNEL=="ttyACM?", ATTRS{idVendor}=="093c", GROUP="users", MODE="0666"
|
||||
|
||||
# neoVI ION/PLASMA PIDs are not in the latest ftdi_sio driver so lets make a
|
||||
# rule to add it when we see a new unclaimed device.
|
||||
# PLASMA = 0x0801, ION = 0x0901
|
||||
ACTION=="add", SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_interface", \
|
||||
ATTRS{idVendor}=="093c", ATTRS{idProduct}=="0801", \
|
||||
DRIVER=="", \
|
||||
RUN+="/sbin/modprobe -b ftdi_sio"
|
||||
ACTION=="add", SUBSYSTEM=="drivers", \
|
||||
ENV{DEVPATH}=="/bus/usb-serial/drivers/ftdi_sio", \
|
||||
ATTR{new_id}="093c 0801"
|
||||
ACTION=="add", SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_interface", \
|
||||
ATTRS{idVendor}=="093c", ATTRS{idProduct}=="0901", \
|
||||
DRIVER=="", \
|
||||
RUN+="/sbin/modprobe -b ftdi_sio"
|
||||
ACTION=="add", SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_interface", \
|
||||
ATTRS{idVendor}=="093c", ATTRS{idProduct}=="1000", \
|
||||
DRIVER=="", \
|
||||
RUN+="/sbin/modprobe -b ftdi_sio"
|
||||
ACTION=="add", SUBSYSTEM=="drivers", \
|
||||
ENV{DEVPATH}=="/bus/usb-serial/drivers/ftdi_sio", \
|
||||
ATTR{new_id}="093c 0901"
|
||||
ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="093c", KERNEL=="ttyUSB*", \
|
||||
RUN+="/bin/sh -c 'echo $id:1.0>/sys/bus/usb/drivers/ftdi_sio/unbind'"
|
||||
|
||||
ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="093c", DRIVER=="usbhid", \
|
||||
RUN+="/bin/sh -c 'echo $id:1.0>/sys/bus/usb/drivers/usbhid/unbind'"
|
||||
|
||||
+399
-83
@@ -1,15 +1,74 @@
|
||||
cmake_minimum_required(VERSION 3.2)
|
||||
project(libicsneo VERSION 0.2.0)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
option(LIBICSNEO_BUILD_TESTS "Build all tests." OFF)
|
||||
function(git_tag_version VERSION_RESULT)
|
||||
set(${VERSION_RESULT} "0.0.0.0" PARENT_SCOPE)
|
||||
find_package(Git)
|
||||
if(NOT Git_FOUND)
|
||||
return()
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} describe --tags --abbrev=0
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE LAST_TAG
|
||||
RESULT_VARIABLE RESULT
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
if(NOT RESULT EQUAL 0)
|
||||
return()
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND ${GIT_EXECUTABLE} rev-list ${LAST_TAG}..HEAD --count
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE COMMIT_COUNT_SINCE_TAG
|
||||
RESULT_VARIABLE RESULT
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
if(NOT RESULT EQUAL 0)
|
||||
return()
|
||||
endif()
|
||||
set(${VERSION_RESULT} "${LAST_TAG}.${COMMIT_COUNT_SINCE_TAG}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
git_tag_version(LIBICSNEO_VERSION)
|
||||
|
||||
if(LIBICSNEO_VERSION STREQUAL "0.0.0.0")
|
||||
message(WARNING "Unable to parse version from git history")
|
||||
endif()
|
||||
|
||||
project(libicsneo VERSION ${LIBICSNEO_VERSION})
|
||||
|
||||
cmake_policy(SET CMP0074 NEW)
|
||||
if(POLICY CMP0135)
|
||||
cmake_policy(SET CMP0135 NEW)
|
||||
endif()
|
||||
|
||||
option(LIBICSNEO_BUILD_UNIT_TESTS "Build unit tests." OFF)
|
||||
option(LIBICSNEO_BUILD_DOCS "Build documentation. Don't use in Visual Studio." OFF)
|
||||
option(LIBICSNEO_BUILD_EXAMPLES "Build examples." ON)
|
||||
option(LIBICSNEO_BUILD_ICSNEOC "Build dynamic C library" ON)
|
||||
option(LIBICSNEO_BUILD_ICSNEOC_STATIC "Build static C library" ON)
|
||||
option(LIBICSNEO_BUILD_ICSNEOC2 "Build dynamic C2 library" ON)
|
||||
option(LIBICSNEO_BUILD_ICSNEOC2_STATIC "Build static C2 library" ON)
|
||||
option(LIBICSNEO_BUILD_ICSNEOLEGACY "Build icsnVC40 compatibility library" ON)
|
||||
option(LIBICSNEO_BUILD_ICSNEOLEGACY_STATIC "Build static icsnVC40 compatibility library" ON)
|
||||
set(LIBICSNEO_NPCAP_INCLUDE_DIR "" CACHE STRING "Npcap include directory; set to build with Npcap")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
# Device Drivers
|
||||
# You almost certainly don't want firmio for your build,
|
||||
# it is only relevant for communication between Linux and
|
||||
# CoreMini from the onboard processor of the device.
|
||||
option(LIBICSNEO_ENABLE_FIRMIO "Enable communication between Linux and CoreMini within the same device" OFF)
|
||||
option(LIBICSNEO_ENABLE_RAW_ETHERNET "Enable devices which communicate over raw ethernet" ON)
|
||||
option(LIBICSNEO_ENABLE_CDCACM "Enable devices which communicate over USB CDC ACM" ON)
|
||||
option(LIBICSNEO_ENABLE_TCP "Enable devices which communicate over TCP" OFF)
|
||||
option(LIBICSNEO_ENABLE_DXX "Enable devices which communicate over D2XX/D3XX via libredxx" ON)
|
||||
|
||||
option(LIBICSNEO_ENABLE_BINDINGS_PYTHON "Enable Python library" OFF)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded")
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
@@ -17,16 +76,17 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
# Enable Warnings
|
||||
if(MSVC)
|
||||
# Force to always compile with W4
|
||||
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
|
||||
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
|
||||
endif()
|
||||
set(LIBICSNEO_COMPILER_WARNINGS /W4)
|
||||
# http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0618r0.html
|
||||
# Still supported until a suitable replacement is standardized
|
||||
add_definitions(-D_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING)
|
||||
add_definitions(-D_ITERATOR_DEBUG_LEVEL=0)
|
||||
else() #if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-switch -Wno-unknown-pragmas")
|
||||
set(LIBICSNEO_COMPILER_WARNINGS -Wall -Wno-unknown-pragmas)
|
||||
endif()
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
# doxygen
|
||||
find_package(Doxygen)
|
||||
if(DOXYGEN_FOUND)
|
||||
@@ -82,51 +142,170 @@ if(LIBICSNEO_BUILD_DOCS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||
file(GLOB PLATFORM_SRC_EXTERNAL ${CMAKE_CURRENT_SOURCE_DIR}/platform/windows/*.cpp)
|
||||
file(GLOB PLATFORM_SRC_INTERNAL ${CMAKE_CURRENT_SOURCE_DIR}/platform/windows/internal/*.cpp)
|
||||
set(PLATFORM_SRC ${PLATFORM_SRC_EXTERNAL} ${PLATFORM_SRC_INTERNAL})
|
||||
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
|
||||
file(GLOB PLATFORM_SRC_DARWIN ${CMAKE_CURRENT_SOURCE_DIR}/platform/posix/darwin/*.cpp)
|
||||
file(GLOB PLATFORM_SRC_POSIX ${CMAKE_CURRENT_SOURCE_DIR}/platform/posix/*.cpp)
|
||||
set(PLATFORM_SRC ${PLATFORM_SRC_POSIX} ${PLATFORM_SRC_DARWIN})
|
||||
else() # elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
file(GLOB PLATFORM_SRC_LINUX ${CMAKE_CURRENT_SOURCE_DIR}/platform/posix/linux/*.cpp)
|
||||
file(GLOB PLATFORM_SRC_POSIX ${CMAKE_CURRENT_SOURCE_DIR}/platform/posix/*.cpp)
|
||||
set(PLATFORM_SRC ${PLATFORM_SRC_POSIX} ${PLATFORM_SRC_LINUX})
|
||||
if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
message(WARNING
|
||||
"There is no platform port defined for ${CMAKE_SYSTEM_NAME}!\n"
|
||||
"The Linux platform code will be used, as it will generally allow building, but some devices may not enumerate properly."
|
||||
if(WIN32)
|
||||
set(PLATFORM_SRC
|
||||
platform/windows/strings.cpp
|
||||
platform/windows/registry.cpp
|
||||
)
|
||||
|
||||
if(LIBICSNEO_ENABLE_RAW_ETHERNET)
|
||||
list(APPEND PLATFORM_SRC
|
||||
platform/windows/pcap.cpp
|
||||
platform/windows/internal/pcapdll.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(LIBICSNEO_ENABLE_CDCACM)
|
||||
list(APPEND PLATFORM_SRC
|
||||
platform/windows/cdcacm.cpp
|
||||
)
|
||||
endif()
|
||||
else() # Darwin or Linux
|
||||
set(PLATFORM_SRC)
|
||||
|
||||
if(LIBICSNEO_ENABLE_FIRMIO)
|
||||
list(APPEND PLATFORM_SRC
|
||||
platform/posix/firmio.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(LIBICSNEO_ENABLE_RAW_ETHERNET)
|
||||
list(APPEND PLATFORM_SRC
|
||||
platform/posix/pcap.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(LIBICSNEO_ENABLE_CDCACM)
|
||||
list(APPEND PLATFORM_SRC
|
||||
platform/posix/cdcacm.cpp
|
||||
)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
|
||||
list(APPEND PLATFORM_SRC
|
||||
platform/posix/darwin/cdcacmdarwin.cpp
|
||||
)
|
||||
else() # Linux or other
|
||||
list(APPEND PLATFORM_SRC
|
||||
platform/posix/linux/cdcacmlinux.cpp
|
||||
)
|
||||
if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
message(WARNING
|
||||
"There is no CDCACM platform port defined for ${CMAKE_SYSTEM_NAME}!\n"
|
||||
"The Linux platform code will be used, as it will generally allow building, but some devices may not enumerate properly."
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(LIBICSNEO_BUILD_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
if(LIBICSNEO_ENABLE_DXX)
|
||||
list(APPEND PLATFORM_SRC
|
||||
platform/dxx.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
set(COMMON_SRC
|
||||
if(LIBICSNEO_ENABLE_TCP)
|
||||
list(APPEND PLATFORM_SRC
|
||||
platform/tcp.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
# Extensions
|
||||
set(LIBICSNEO_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
foreach(EXT_PATH ${LIBICSNEO_EXTENSION_DIRS})
|
||||
get_filename_component(EXT_DIR ${EXT_PATH} NAME)
|
||||
message("Adding extension " ${EXT_DIR})
|
||||
add_subdirectory(${EXT_PATH} ${CMAKE_CURRENT_BINARY_DIR}/${EXT_DIR})
|
||||
endforeach()
|
||||
|
||||
set(SRC_FILES
|
||||
communication/message/flexray/control/flexraycontrolmessage.cpp
|
||||
communication/message/callback/streamoutput/a2bwavoutput.cpp
|
||||
communication/message/a2bmessage.cpp
|
||||
communication/message/apperrormessage.cpp
|
||||
communication/message/neomessage.cpp
|
||||
communication/message/ethphymessage.cpp
|
||||
communication/message/linmessage.cpp
|
||||
communication/message/livedatamessage.cpp
|
||||
communication/message/logdatamessage.cpp
|
||||
communication/message/tc10statusmessage.cpp
|
||||
communication/message/gptpstatusmessage.cpp
|
||||
communication/message/allmacaddressesmessage.cpp
|
||||
communication/message/ethernetstatusmessage.cpp
|
||||
communication/message/networkmutexmessage.cpp
|
||||
communication/message/clientidmessage.cpp
|
||||
communication/message/mfgconfigmessage.cpp
|
||||
communication/message/transmitmessage.cpp
|
||||
|
||||
|
||||
communication/message/spiportkeymessage.cpp
|
||||
communication/message/genericapidatamessage.cpp
|
||||
communication/message/genericapistatusmessage.cpp
|
||||
communication/message/iso15765message.cpp
|
||||
communication/packet/flexraypacket.cpp
|
||||
communication/packet/canpacket.cpp
|
||||
communication/packet/a2bpacket.cpp
|
||||
communication/packet/spipacket.cpp
|
||||
communication/packet/ethernetpacket.cpp
|
||||
communication/packet/versionpacket.cpp
|
||||
communication/packet/iso9141packet.cpp
|
||||
communication/packet/ethphyregpacket.cpp
|
||||
communication/packet/livedatapacket.cpp
|
||||
communication/packet/logicaldiskinfopacket.cpp
|
||||
communication/packet/wivicommandpacket.cpp
|
||||
communication/packet/i2cpacket.cpp
|
||||
communication/packet/linpacket.cpp
|
||||
communication/packet/mdiopacket.cpp
|
||||
communication/packet/scriptstatuspacket.cpp
|
||||
communication/packet/componentversionpacket.cpp
|
||||
communication/packet/supportedfeaturespacket.cpp
|
||||
communication/packet/genericbinarystatuspacket.cpp
|
||||
communication/packet/hardwareinfopacket.cpp
|
||||
communication/decoder.cpp
|
||||
communication/encoder.cpp
|
||||
communication/ethernetpacketizer.cpp
|
||||
communication/packetizer.cpp
|
||||
communication/multichannelcommunication.cpp
|
||||
communication/communication.cpp
|
||||
communication/driver.cpp
|
||||
communication/livedata.cpp
|
||||
core/ringbuffer.cpp
|
||||
core/crc32.cpp
|
||||
core/macseccfg.cpp
|
||||
device/extensions/flexray/extension.cpp
|
||||
device/extensions/flexray/controller.cpp
|
||||
device/idevicesettings.cpp
|
||||
device/devicefinder.cpp
|
||||
device/device.cpp
|
||||
device/neodevice.cpp
|
||||
disk/diskreaddriver.cpp
|
||||
disk/diskwritedriver.cpp
|
||||
disk/nulldiskdriver.cpp
|
||||
disk/neomemorydiskdriver.cpp
|
||||
disk/plasiondiskreaddriver.cpp
|
||||
disk/extextractordiskreaddriver.cpp
|
||||
disk/fat.cpp
|
||||
disk/diskdetails.cpp
|
||||
disk/vsa/vsa.cpp
|
||||
disk/vsa/vsa02.cpp
|
||||
disk/vsa/vsa03.cpp
|
||||
disk/vsa/vsa04.cpp
|
||||
disk/vsa/vsa05.cpp
|
||||
disk/vsa/vsa06.cpp
|
||||
disk/vsa/vsa07.cpp
|
||||
disk/vsa/vsa08.cpp
|
||||
disk/vsa/vsa09.cpp
|
||||
disk/vsa/vsa0b.cpp
|
||||
disk/vsa/vsa0c.cpp
|
||||
disk/vsa/vsa0d.cpp
|
||||
disk/vsa/vsa0e.cpp
|
||||
disk/vsa/vsa0f.cpp
|
||||
disk/vsa/vsa6a.cpp
|
||||
disk/vsa/vsaparser.cpp
|
||||
platform/servd.cpp
|
||||
${PLATFORM_SRC}
|
||||
)
|
||||
|
||||
set(SRC_FILES ${COMMON_SRC} ${PLATFORM_SRC})
|
||||
|
||||
# Generate build info header
|
||||
execute_process(
|
||||
COMMAND git rev-parse --abbrev-ref HEAD
|
||||
@@ -154,48 +333,115 @@ endif()
|
||||
|
||||
configure_file(api/icsneocpp/buildinfo.h.template ${CMAKE_CURRENT_BINARY_DIR}/generated/buildinfo.h)
|
||||
configure_file(api/icsneoc/version.rc.template ${CMAKE_CURRENT_BINARY_DIR}/generated/icsneoc/version.rc)
|
||||
configure_file(api/icsneoc2/version.rc.template ${CMAKE_CURRENT_BINARY_DIR}/generated/icsneoc2/version.rc)
|
||||
|
||||
foreach(EXTINC ${LIBICSNEO_EXTENSION_INCLUDES})
|
||||
message("Including " ${EXTINC})
|
||||
list(APPEND LIBICSNEO_EXT_CODE_INCS_LIST "#include \"${EXTINC}\"")
|
||||
endforeach()
|
||||
list(JOIN LIBICSNEO_EXT_CODE_INCS_LIST "\n" LIBICSNEO_EXT_CODE_INCS)
|
||||
foreach(EXTCLASS ${LIBICSNEO_EXTENSION_CLASSES})
|
||||
list(APPEND LIBICSNEO_EXT_CODE_LIST "device->addExtension(std::make_shared<${EXTCLASS}>(*device))\;")
|
||||
endforeach()
|
||||
list(JOIN LIBICSNEO_EXT_CODE_LIST "\n\t" LIBICSNEO_EXT_CODE)
|
||||
configure_file(include/icsneo/device/extensions/builtin.h.template ${CMAKE_CURRENT_BINARY_DIR}/generated/extensions/builtin.h)
|
||||
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
add_library(icsneocpp
|
||||
api/icsneocpp/icsneocpp.cpp
|
||||
api/icsneocpp/event.cpp
|
||||
api/icsneocpp/eventmanager.cpp
|
||||
api/icsneocpp/heartbeat.cpp
|
||||
api/icsneocpp/version.cpp
|
||||
${SRC_FILES}
|
||||
)
|
||||
message("Include paths " ${LIBICSNEO_EXTENSION_INCLUDE_PATHS})
|
||||
target_include_directories(icsneocpp
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:>
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
${LIBICSNEO_EXTENSION_INCLUDE_PATHS}
|
||||
)
|
||||
target_link_libraries(icsneocpp PUBLIC Threads::Threads $<$<BOOL:${WIN32}>:ws2_32 iphlpapi>)
|
||||
set_property(TARGET icsneocpp PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
target_compile_features(icsneocpp PUBLIC cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums)
|
||||
|
||||
# libftdi
|
||||
if(NOT WIN32)
|
||||
target_include_directories(icsneocpp PUBLIC third-party/libftdi/src)
|
||||
set(LIBFTDI_DOCUMENTATION OFF CACHE INTERNAL "")
|
||||
set(LIBFTDI_BUILD_TESTS OFF CACHE INTERNAL "")
|
||||
set(LIBFTDI_INSTALL OFF CACHE INTERNAL "")
|
||||
set(LIBFTDI_PYTHON_BINDINGS OFF CACHE INTERNAL "")
|
||||
set(LIBFTDI_LINK_PYTHON_LIBRARY OFF CACHE INTERNAL "")
|
||||
set(FTDIPP OFF CACHE INTERNAL "")
|
||||
set(FTDI_EEPROM OFF CACHE INTERNAL "")
|
||||
add_subdirectory(third-party/libftdi)
|
||||
endif(NOT WIN32)
|
||||
|
||||
# winpcap
|
||||
if(WIN32)
|
||||
if(LIBICSNEO_NPCAP_INCLUDE_DIR STREQUAL "")
|
||||
target_include_directories(icsneocpp PUBLIC AFTER third-party/winpcap/include)
|
||||
add_definitions(-DWPCAP -DHAVE_REMOTE -DWIN32_LEAN_AND_MEAN)
|
||||
else()
|
||||
target_include_directories(icsneocpp PUBLIC AFTER ${LIBICSNEO_NPCAP_INCLUDE_DIR})
|
||||
add_definitions(-DNPCAP -DWIN32_LEAN_AND_MEAN)
|
||||
target_compile_options(icsneocpp PRIVATE ${LIBICSNEO_COMPILER_WARNINGS})
|
||||
message("Loaded extensions: " ${LIBICSNEO_EXTENSION_TARGETS})
|
||||
target_link_libraries(icsneocpp PUBLIC ${LIBICSNEO_EXTENSION_TARGETS})
|
||||
if(LIBICSNEO_ENABLE_FIRMIO)
|
||||
target_compile_definitions(icsneocpp PRIVATE ICSNEO_ENABLE_FIRMIO)
|
||||
endif()
|
||||
if(LIBICSNEO_ENABLE_RAW_ETHERNET)
|
||||
target_compile_definitions(icsneocpp PRIVATE ICSNEO_ENABLE_RAW_ETHERNET)
|
||||
endif()
|
||||
if(LIBICSNEO_ENABLE_CDCACM)
|
||||
target_compile_definitions(icsneocpp PRIVATE ICSNEO_ENABLE_CDCACM)
|
||||
if(APPLE)
|
||||
find_library(CORE_FOUNDATION_FRAMEWORK CoreFoundation REQUIRED)
|
||||
find_library(IO_KIT_FRAMEWORK IOKit REQUIRED)
|
||||
target_link_libraries(icsneocpp PRIVATE ${CORE_FOUNDATION_FRAMEWORK} ${IO_KIT_FRAMEWORK})
|
||||
endif()
|
||||
endif(WIN32)
|
||||
endif()
|
||||
if(LIBICSNEO_ENABLE_DXX)
|
||||
target_compile_definitions(icsneocpp PRIVATE ICSNEO_ENABLE_DXX)
|
||||
target_link_libraries(icsneocpp PRIVATE libredxx::libredxx)
|
||||
endif()
|
||||
if(LIBICSNEO_ENABLE_TCP)
|
||||
target_compile_definitions(icsneocpp PRIVATE ICSNEO_ENABLE_TCP)
|
||||
if(WIN32)
|
||||
target_link_libraries(icsneocpp PRIVATE ws2_32 iphlpapi)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# fatfs
|
||||
add_subdirectory(third-party/fatfs)
|
||||
set_property(TARGET fatfs PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
target_link_libraries(icsneocpp PRIVATE fatfs)
|
||||
|
||||
# dxx
|
||||
if(LIBICSNEO_ENABLE_DXX)
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(libredxx
|
||||
GIT_REPOSITORY https://github.com/Zeranoe/libredxx.git
|
||||
GIT_TAG e823a96c39a64ab41b7d1632dbe8f86bb854df83
|
||||
)
|
||||
set(LIBREDXX_DISABLE_INSTALL ON)
|
||||
FetchContent_MakeAvailable(libredxx)
|
||||
endif()
|
||||
|
||||
# pcap
|
||||
if(LIBICSNEO_ENABLE_RAW_ETHERNET)
|
||||
if(WIN32)
|
||||
if(LIBICSNEO_NPCAP_INCLUDE_DIR STREQUAL "")
|
||||
target_include_directories(icsneocpp PUBLIC AFTER third-party/winpcap/include)
|
||||
add_definitions(-DWPCAP -DHAVE_REMOTE)
|
||||
else()
|
||||
target_include_directories(icsneocpp PUBLIC AFTER ${LIBICSNEO_NPCAP_INCLUDE_DIR})
|
||||
endif()
|
||||
else()
|
||||
find_package(PCAP REQUIRED)
|
||||
target_include_directories(icsneocpp PUBLIC ${PCAP_INCLUDE_DIR})
|
||||
target_link_libraries(icsneocpp PUBLIC ${PCAP_LIBRARY})
|
||||
endif(WIN32)
|
||||
endif(LIBICSNEO_ENABLE_RAW_ETHERNET)
|
||||
|
||||
# protobuf
|
||||
if(DEFINED ENV{LIBICSNEO_ICSPB_REPO})
|
||||
set(LIBICSNEO_ICSPB_REPO "$ENV{LIBICSNEO_ICSPB_REPO}")
|
||||
endif()
|
||||
if(NOT LIBICSNEO_ICSPB_REPO)
|
||||
set(LIBICSNEO_ICSPB_REPO https://github.com/intrepidcs/icspb.git)
|
||||
endif()
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(icspb
|
||||
GIT_REPOSITORY ${LIBICSNEO_ICSPB_REPO}
|
||||
GIT_TAG 3339fa6b83a6b3e7704d41f5c2f2175cfc761a1f
|
||||
)
|
||||
FetchContent_MakeAvailable(icspb)
|
||||
target_link_libraries(icsneocpp PRIVATE icspb::icspb)
|
||||
|
||||
if(LIBICSNEO_BUILD_ICSNEOC)
|
||||
add_library(icsneoc SHARED api/icsneoc/icsneoc.cpp ${CMAKE_CURRENT_BINARY_DIR}/generated/icsneoc/version.rc)
|
||||
@@ -208,6 +454,7 @@ if(LIBICSNEO_BUILD_ICSNEOC)
|
||||
)
|
||||
target_link_libraries(icsneoc PRIVATE icsneocpp)
|
||||
target_compile_features(icsneoc PRIVATE cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums)
|
||||
target_compile_options(icsneoc PRIVATE ${LIBICSNEO_COMPILER_WARNINGS})
|
||||
endif()
|
||||
|
||||
if(LIBICSNEO_BUILD_ICSNEOC_STATIC)
|
||||
@@ -221,6 +468,40 @@ if(LIBICSNEO_BUILD_ICSNEOC_STATIC)
|
||||
)
|
||||
target_link_libraries(icsneoc-static PUBLIC icsneocpp)
|
||||
target_compile_features(icsneoc-static PUBLIC cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums)
|
||||
target_compile_definitions(icsneoc-static PUBLIC ICSNEOC_BUILD_STATIC)
|
||||
target_compile_options(icsneoc-static PRIVATE ${LIBICSNEO_COMPILER_WARNINGS})
|
||||
endif()
|
||||
|
||||
if(LIBICSNEO_BUILD_ICSNEOC2)
|
||||
add_library(icsneoc2 SHARED api/icsneoc2/icsneoc2.cpp api/icsneoc2/icsneoc2settings.cpp api/icsneoc2/icsneoc2messages.cpp ${CMAKE_CURRENT_BINARY_DIR}/generated/icsneoc2/version.rc)
|
||||
target_include_directories(icsneoc2
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:>
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
)
|
||||
target_link_libraries(icsneoc2 PRIVATE icsneocpp)
|
||||
target_compile_features(icsneoc2 PRIVATE cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums)
|
||||
target_compile_options(icsneoc2 PRIVATE ${LIBICSNEO_COMPILER_WARNINGS})
|
||||
if(WIN32)
|
||||
set_target_properties(icsneoc2 PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(LIBICSNEO_BUILD_ICSNEOC2_STATIC)
|
||||
add_library(icsneoc2-static STATIC api/icsneoc2/icsneoc2.cpp api/icsneoc2/icsneoc2settings.cpp api/icsneoc2/icsneoc2messages.cpp)
|
||||
target_include_directories(icsneoc2-static
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:>
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
)
|
||||
target_link_libraries(icsneoc2-static PUBLIC icsneocpp)
|
||||
target_compile_features(icsneoc2-static PUBLIC cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums)
|
||||
target_compile_definitions(icsneoc2-static PUBLIC ICSNEOC2_BUILD_STATIC)
|
||||
target_compile_options(icsneoc2-static PRIVATE ${LIBICSNEO_COMPILER_WARNINGS})
|
||||
endif()
|
||||
|
||||
if(LIBICSNEO_BUILD_ICSNEOLEGACY)
|
||||
@@ -228,6 +509,7 @@ if(LIBICSNEO_BUILD_ICSNEOLEGACY)
|
||||
api/icsneolegacy/icsneolegacy.cpp
|
||||
api/icsneolegacy/icsneolegacyextra.cpp
|
||||
api/icsneoc/icsneoc.cpp
|
||||
platform/windows/icsneolegacy.def
|
||||
)
|
||||
target_include_directories(icsneolegacy
|
||||
PUBLIC
|
||||
@@ -238,42 +520,76 @@ if(LIBICSNEO_BUILD_ICSNEOLEGACY)
|
||||
)
|
||||
target_link_libraries(icsneolegacy PRIVATE icsneocpp)
|
||||
target_compile_features(icsneolegacy PRIVATE cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums)
|
||||
target_compile_options(icsneolegacy PRIVATE ${LIBICSNEO_COMPILER_WARNINGS})
|
||||
endif()
|
||||
|
||||
# libftdi
|
||||
if(NOT WIN32)
|
||||
find_package(Threads)
|
||||
set_property(TARGET ftdi1-static PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
target_link_libraries(icsneocpp PUBLIC ftdi1-static)
|
||||
target_link_libraries(icsneocpp PUBLIC ${CMAKE_THREAD_LIBS_INIT})
|
||||
find_package(PCAP REQUIRED)
|
||||
target_link_libraries(icsneocpp PUBLIC ${PCAP_LIBRARY})
|
||||
if(LIBICSNEO_BUILD_ICSNEOLEGACY_STATIC)
|
||||
add_library(icsneolegacy-static STATIC
|
||||
api/icsneolegacy/icsneolegacy.cpp
|
||||
api/icsneolegacy/icsneolegacyextra.cpp
|
||||
api/icsneoc/icsneoc.cpp
|
||||
)
|
||||
|
||||
target_include_directories(icsneolegacy-static
|
||||
PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:>
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
)
|
||||
target_link_libraries(icsneolegacy-static PUBLIC icsneocpp)
|
||||
target_compile_features(icsneolegacy-static PUBLIC cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums)
|
||||
target_compile_definitions(icsneolegacy-static PUBLIC ICSNEOC_BUILD_STATIC)
|
||||
target_compile_options(icsneolegacy-static PRIVATE ${LIBICSNEO_COMPILER_WARNINGS})
|
||||
endif()
|
||||
|
||||
add_subdirectory(bindings)
|
||||
|
||||
if(LIBICSNEO_BUILD_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif()
|
||||
|
||||
# googletest
|
||||
if(LIBICSNEO_BUILD_TESTS)
|
||||
if(WIN32)
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
if(LIBICSNEO_BUILD_UNIT_TESTS)
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(googletest
|
||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||
GIT_TAG 6986c2b575f77135401a4e1c65a7a42f20e18fef
|
||||
)
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
include(GoogleTest)
|
||||
|
||||
add_executable(libicsneo-unit-tests
|
||||
test/unit/main.cpp
|
||||
test/unit/diskdriverreadtest.cpp
|
||||
test/unit/diskdriverwritetest.cpp
|
||||
test/unit/eventmanagertest.cpp
|
||||
test/unit/ethernetpacketizertest.cpp
|
||||
test/unit/i2cencoderdecodertest.cpp
|
||||
test/unit/linencoderdecodertest.cpp
|
||||
test/unit/a2bencoderdecodertest.cpp
|
||||
test/unit/mdioencoderdecodertest.cpp
|
||||
test/unit/livedataencoderdecodertest.cpp
|
||||
test/unit/ringbuffertest.cpp
|
||||
test/unit/apperrordecodertest.cpp
|
||||
test/unit/icsneoc2.cpp
|
||||
test/unit/windowsstrings.cpp
|
||||
test/unit/periodictest.cpp
|
||||
)
|
||||
|
||||
target_compile_options(libicsneo-unit-tests PRIVATE ${LIBICSNEO_COMPILER_WARNINGS})
|
||||
|
||||
target_link_libraries(libicsneo-unit-tests gtest gtest_main)
|
||||
target_link_libraries(libicsneo-unit-tests icsneocpp)
|
||||
target_link_libraries(libicsneo-unit-tests icsneoc2-static)
|
||||
|
||||
target_include_directories(libicsneo-unit-tests PUBLIC ${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
|
||||
|
||||
add_subdirectory(third-party/googletest-master)
|
||||
|
||||
if (CMAKE_VERSION VERSION_LESS 2.8.11)
|
||||
include_directories("${gtest_SOURCE_DIR}/include")
|
||||
endif()
|
||||
|
||||
add_executable(runTests test/main.cpp test/eventmanagertest.cpp)
|
||||
|
||||
target_link_libraries(runTests gtest gtest_main)
|
||||
target_link_libraries(runTests icsneocpp)
|
||||
|
||||
target_include_directories(runTests PUBLIC ${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
|
||||
|
||||
enable_testing()
|
||||
|
||||
add_test(NAME testSuite COMMAND runTests)
|
||||
|
||||
gtest_discover_tests(libicsneo-unit-tests TEST_PREFIX "unit/" PROPERTIES LABELS "unit")
|
||||
endif()
|
||||
|
||||
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
|
||||
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
|
||||
include(CPack)
|
||||
include(CPack)
|
||||
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
# Hardware Support
|
||||
|
||||
- Connecting over Ethernet
|
||||
- neoVI FIRE 2
|
||||
- CAN works
|
||||
- CAN FD works
|
||||
- ValueCAN 4-2EL
|
||||
- CAN works
|
||||
- CAN FD works
|
||||
- Ethernet works
|
||||
- RADGalaxy
|
||||
- CAN works
|
||||
- Ethernet works
|
||||
- RADStar 2
|
||||
- CAN works
|
||||
- Ethernet works
|
||||
|
||||
- Connecting over USB
|
||||
- ValueCAN 4 series
|
||||
- CAN works
|
||||
- CAN FD works
|
||||
- Ethernet works (on 4-2EL)
|
||||
- neoOBD2 PRO
|
||||
- CAN works
|
||||
- neoVI FIRE
|
||||
- CAN works
|
||||
- neoVI FIRE 2
|
||||
- CAN works
|
||||
- CAN FD works
|
||||
- Ethernet works
|
||||
- ValueCAN 3
|
||||
- CAN works
|
||||
- RADStar 2
|
||||
- CAN works
|
||||
- Ethernet works
|
||||
- neoVI PLASMA
|
||||
- CAN works
|
||||
- neoVI ION
|
||||
- CAN works
|
||||
@@ -1,13 +1,29 @@
|
||||
Copyright 2018-2020 Intrepid Control Systems, Inc.
|
||||
Copyright (c) 2018-2026 Intrepid Control Systems, Inc.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
4. It is forbidden to use this library or derivatives to interface with vehicle networking hardware not produced by Intrepid Control Systems, Inc.
|
||||
4. It is forbidden to use this library or derivatives to interface with vehicle
|
||||
networking hardware not produced by Intrepid Control Systems, Inc.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
@@ -1,130 +1,55 @@
|
||||
# libicsneo
|
||||
### The Intrepid Control Systems Open Source Cross-Platform Device Communication API
|
||||
|
||||
An open source solution to integrate Intrepid Control Systems vehicle networking hardware with your application.
|
||||
libicsneo is the [Intrepid Control Systems](https://intrepidcs.com/) device
|
||||
communication library. Installation and usage documentation can be found within
|
||||
each of the respective APIs.
|
||||
|
||||
[Read the Full Documentation](https://libicsneo.readthedocs.io/)
|
||||
## Installation
|
||||
|
||||
## Getting Started
|
||||
There are two major ways to write a new application using libicsneo. You can use the C++ interface, which will be compiled with your project and statically linked, or you can use the C interface, which can be either statically or dynamically linked.
|
||||
### Integration with CMake (Static Linking)
|
||||
Integrating the library with your current CMake project is extremely easy.
|
||||
1. Checkout the library (or add as a submodule) into a subdirectory of your project.
|
||||
2. Within your `CMakeLists.txt` you can add the line `add_subdirectory("third-party/libicsneo")` to bring in the libicsneo targets. Replace `third-party` with any subdirectory you choose.
|
||||
3. The libicsneo library include paths should automatically be added to your include path.
|
||||
4. Link the library with your target by adding `target_link_libraries(libicsneocpp-example icsneocpp)` after your target, substituting `libicsneocpp-example` with your target application.
|
||||
libicsneo relies on Servd, IntrepidCS's device communication server.
|
||||
|
||||
You can now include either the C++ API with `#include <icsneo/icsneocpp.h>` or the C API with `#include <icsneo/icsneoc.h>`
|
||||
Servd can be installed for all platforms from https://cdn.intrepidcs.net/servd/.
|
||||
|
||||
### DLL / SO / DYLIB Releases (Dynamic Linking)
|
||||
It is also possible to use the precompiled binaries with runtime linking. It is not recommended or supported to attempt to use the C++ interface with dynamic linking due to the complexities of C++ compilers.
|
||||
1. Add this repository's `/include` to your include path
|
||||
2. Add `#define ICSNEOC_DYNAMICLOAD` to the top of your source file
|
||||
2. Add `#import <icsneo/icsneoc.h>` below that line
|
||||
3. Call `icsneo_init();` to import the library before using any other libicsneo functions.
|
||||
4. Use the library as normal.
|
||||
5. Call `icsneo_close();` to unload the library.
|
||||
Instructions for installing each API can be found in its respective documentation.
|
||||
|
||||
## Usage
|
||||
### Using the C++ API
|
||||
The C++ API is designed to be modern and easy to use. All library functions and classes are in the namespace `icsneo`. Most applications will start by calling `icsneo::FindAllDevices()`. This will return an `std::vector` of `std::shared_ptr<icsneo::Device>` objects. You will want to keep a copy of the `shared_ptr` to any devices you want to use, as allowing it to go out of scope will automatically close the device and free all memory associated with it.
|
||||
## Documentation
|
||||
|
||||
Any time you get bus traffic from the API, you will receive it as an `std::shared_ptr<icsneo::Message>`. The message will be valid as long as the `shared_ptr` stays in scope. Checking the type of the message allows you to cast it accordingly and access extra data for certain protocols. For instance, casting an `icsneo::Message` to an `icsneo::CANMessage` allows you to access the arbitration ID.
|
||||
- [C++](https://libicsneo.readthedocs.io/en/latest/icsneocpp/)
|
||||
- [Python](https://libicsneo.readthedocs.io/en/latest/icsneopy/)
|
||||
- [C](https://libicsneo.readthedocs.io/en/latest/icsneoc/) (deprecated, use C2)
|
||||
- [C2](https://libicsneo.readthedocs.io/en/latest/icsneoc2/)
|
||||
|
||||
A barebones example is provided. For a more complete example, check [intrepidcs/libicsneo-examples](https://github.com/intrepidcs/libicsneo-examples).
|
||||
``` c++
|
||||
std::vector<std::shared_ptr<icsneo::Device>> devices = icsneo::FindAllDevices();
|
||||
std::cout << devices.size() << " found!" << std::endl;
|
||||
for(auto& device : devices)
|
||||
std::cout << "Found " << device->describe() << std::endl; // "Found neoVI FIRE 2 CY2345"
|
||||
std::shared_ptr<icsneo::Device> myDevice = devices[0];
|
||||
## Hardware Support
|
||||
|
||||
if(!myDevice->open()) // Device tried and failed to open, print the last error
|
||||
std::cout << icsneo::GetLastError() << std::endl;
|
||||
- EtherBADGE
|
||||
- neoVI Connect
|
||||
- neoVI FIRE
|
||||
- neoVI FIRE 2
|
||||
- neoVI FIRE 3
|
||||
- neoVI ION
|
||||
- neoVI PLASMA
|
||||
- neoVI RED 2
|
||||
- RAD-A2B
|
||||
- RAD-Comet 2
|
||||
- RAD-Comet 3
|
||||
- RAD-Epsilon
|
||||
- RAD-EpsilonXL
|
||||
- RAD-Galaxy
|
||||
- RAD-Galaxy 2
|
||||
- RAD-Gemini
|
||||
- RAD-Gigastar
|
||||
- RAD-Gigastar 2
|
||||
- RAD-Moon 2
|
||||
- RAD-Moon 3
|
||||
- RAD-Moon T1S
|
||||
- RAD-Pluto
|
||||
- RAD-Star 2
|
||||
- RAD-SuperMoon
|
||||
- RAD-wBMS
|
||||
- ValueCAN 3
|
||||
- ValueCAN 4
|
||||
|
||||
myDevice->goOnline(); // Start receiving messages
|
||||
myDevice->enableMessagePolling(); // Allow the use of myDevice->getMessages() later
|
||||
// Alternatively, assign a callback for new messages
|
||||
std::this_thread::wait_for(std::chrono::seconds(5));
|
||||
std::vector<std::shared_ptr<icsneo::Message>> messages = myDevice->getMessages();
|
||||
std::cout << "We got " << messages.size() << " messages!" << std::endl;
|
||||
for(auto& msg : messages) {
|
||||
switch(msg->network.getType()) {
|
||||
case icsneo::Network::Type::CAN:
|
||||
case icsneo::Network::Type::SWCAN:
|
||||
case icsneo::Network::Type::LSFTCAN: {
|
||||
// A message of type CAN is guaranteed to be a CANMessage, so we can static cast safely
|
||||
auto canmsg = std::static_pointer_cast<icsneo::CANMessage>(msg);
|
||||
// canmsg->arbid is valid here
|
||||
// canmsg->data is an std::vector<uint8_t>, you can check .size() for the DLC of the message
|
||||
// canmsg->timestamp is the time recorded by the hardware in nanoseconds since (1/1/2007 12:00:00 GMT)
|
||||
}
|
||||
default:
|
||||
// Handle others
|
||||
}
|
||||
}
|
||||
myDevice->close();
|
||||
```
|
||||
## License
|
||||
|
||||
### Using the C API
|
||||
The C API is designed to be a robust and fault tolerant interface which allows easy integration with other languages as well as existing C applications. When calling `icsneo_findAllDevices()` you will provide a buffer of `neodevice_t` structures, which will be written with the found devices. These `neodevice_t` structures can be uses to interface with the API from then on. Once you call `icsneo_close()` with a device, that device and all associated memory will be freed. You will need to run `icsneo_findAllDevices()` again to reconnect.
|
||||
|
||||
Messages are passed in the form of `neomessage_t` structures when calling `icsneo_getMessages()`. These structures contain a `uint8_t*` to the payload data, and this pointer will be valid until the next call to `icsneo_getMessages()` or the device is closed.
|
||||
|
||||
A barebones example is provided. For a more complete example, check [intrepidcs/libicsneo-examples](https://github.com/intrepidcs/libicsneo-examples).
|
||||
``` c
|
||||
size_t deviceCount = 10; // Pre-set to the size of your buffer before the icsneo_findAllDevices() call
|
||||
neodevice_t devices[10];
|
||||
icsneo_findAllDevices(devices, &deviceCount);
|
||||
printf("We found %ull devices\n", deviceCount);
|
||||
for(size_t i = 0; i < deviceCount; i++) {
|
||||
neodevice_t* myDevice = &devices[i];
|
||||
char desc[ICSNEO_DEVICETYPE_LONGEST_DESCRIPTION];
|
||||
size_t sz = ICSNEO_DEVICETYPE_LONGEST_DESCRIPTION;
|
||||
icsneo_describeDevice(myDevice, desc, &sz);
|
||||
printf("Found %s\n", desc); // "Found neoVI FIRE 2 CY2345"
|
||||
}
|
||||
|
||||
neodevice_t* myDevice = &devices[0];
|
||||
if(!icsneo_openDevice(myDevice)) {
|
||||
neoevent_t error;
|
||||
if(icsneo_getLastError(&error))
|
||||
printf("Error! %s\n", error.description);
|
||||
}
|
||||
icsneo_goOnline(myDevice); // Start receiving messages
|
||||
icsneo_enableMessagePolling(myDevice); // Allow the use of icsneo_getMessages() later
|
||||
sleep(5);
|
||||
neomessage_t messages[50];
|
||||
size_t messageCount = 50;
|
||||
icsneo_getMessages(myDevice, messages, &messageCount, 0 /* non-blocking */);
|
||||
printf("We got %ull messages!\n", messageCount);
|
||||
for(size_t i = 0; i < messageCount; i++) {
|
||||
if(messages[i].type == ICSNEO_NETWORK_TYPE_CAN) {
|
||||
// A message of type CAN should be interperated a neomessage_can_t, so we can cast safely
|
||||
neomessage_can_t* canmsg = (neomessage_can_t*)&messages[i];
|
||||
// canmsg->arbid is valid here
|
||||
// canmsg->data is an uint8_t*, you can check canmsg->length for the length of the payload
|
||||
// canmsg->timestamp is the time recorded by the hardware in nanoseconds since (1/1/2007 12:00:00 GMT)
|
||||
}
|
||||
}
|
||||
icsneo_closeDevice(myDevice);
|
||||
```
|
||||
|
||||
## Building from Source
|
||||
### Windows
|
||||
Building will require Microsoft Visual Studio 2017+ and CMake to be installed.
|
||||
### macOS
|
||||
Getting the dependencies is easiest with the Homebrew package manager. You will also need XCode installed. You can then install CMake, an up-to-date version of GCC or Clang, and `libusb-1.0`.
|
||||
### Linux
|
||||
The dependencies are as follows
|
||||
- CMake 3.2 or above
|
||||
- GCC 4.7 or above, 4.8+ recommended
|
||||
- `libusb-1.0-0-dev`
|
||||
- `libpcap0.8-dev`
|
||||
- `build-essential` is recommended
|
||||
|
||||
If you'd like to be able to run programs that use this library without being root, consider using the included udev rules
|
||||
|
||||
```
|
||||
$ sudo cp 99-intrepidcs.rules /etc/udev/rules.d/
|
||||
```
|
||||
libicsneo is licensed as BSD-3 with an extra clause, see [LICENSE](LICENSE)
|
||||
for more details.
|
||||
|
||||
+789
-622
File diff suppressed because it is too large
Load Diff
@@ -29,7 +29,7 @@ BEGIN
|
||||
VALUE "FileDescription", "Intrepid Control Systems Open Device Communication C API"
|
||||
VALUE "FileVersion", VER_FILEVERSION_STR
|
||||
VALUE "InternalName", "icsneoc.dll"
|
||||
VALUE "LegalCopyright", "Intrepid Control Systems, Inc. (C) 2018-2019"
|
||||
VALUE "LegalCopyright", "Intrepid Control Systems, Inc. (C) 2018-2026"
|
||||
VALUE "OriginalFilename", "icsneoc.dll"
|
||||
VALUE "ProductName", "libicsneo"
|
||||
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,74 @@
|
||||
// This header is for internal icsneoc2 use only, it should not be included by users of the API.
|
||||
#pragma once
|
||||
|
||||
#include "icsneo/icsneoc2.h"
|
||||
#include "icsneo/device/device.h"
|
||||
#include "icsneo/communication/message/message.h"
|
||||
#include "icsneo/communication/message/scriptstatusmessage.h"
|
||||
#include "icsneo/api/event.h"
|
||||
#include "icsneo/disk/diskdetails.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
typedef struct icsneoc2_supported_device_t {
|
||||
DeviceType device_type;
|
||||
icsneoc2_supported_device_t* next;
|
||||
} icsneoc2_supported_device_t;
|
||||
|
||||
typedef struct icsneoc2_message_t {
|
||||
std::shared_ptr<Message> message;
|
||||
} icsneoc2_message_t;
|
||||
|
||||
typedef struct icsneoc2_event_t {
|
||||
APIEvent event;
|
||||
} icsneoc2_event_t;
|
||||
|
||||
typedef struct icsneoc2_device_info_t {
|
||||
std::shared_ptr<Device> device;
|
||||
icsneoc2_device_info_t* next;
|
||||
} icsneoc2_device_info_t;
|
||||
|
||||
typedef struct icsneoc2_device_t {
|
||||
std::shared_ptr<Device> device;
|
||||
} icsneoc2_device_t;
|
||||
|
||||
typedef struct icsneoc2_disk_details_t {
|
||||
std::shared_ptr<DiskDetails> details;
|
||||
} icsneoc2_disk_details_t;
|
||||
|
||||
typedef struct icsneoc2_script_status_t {
|
||||
std::shared_ptr<ScriptStatusMessage> status;
|
||||
} icsneoc2_script_status_t;
|
||||
|
||||
typedef struct icsneoc2_chip_versions_t {
|
||||
VersionReport version_report;
|
||||
icsneoc2_chip_versions_t* next;
|
||||
} icsneoc2_chip_versions_t;
|
||||
|
||||
typedef struct icsneoc2_termination_group_t {
|
||||
std::vector<icsneoc2_netid_t> netids;
|
||||
icsneoc2_termination_group_t* next;
|
||||
} icsneoc2_termination_group_t;
|
||||
|
||||
typedef struct icsneoc2_mac_addr_entry_t {
|
||||
uint16_t network_id;
|
||||
uint8_t address[ICSNEO_MAC_ADDRESS_LEN];
|
||||
icsneoc2_mac_addr_entry_t* next;
|
||||
} icsneoc2_mac_addr_entry_t;
|
||||
|
||||
/**
|
||||
* Safely copies a std::string to a char array.
|
||||
*
|
||||
* @param dest The buffer to copy the string into
|
||||
* @param dest_size* The size of the buffer. Will be modified to the length of the string without the null terminator.
|
||||
* @param src The string to copy
|
||||
*
|
||||
* @return true if the string was successfully copied, false otherwise
|
||||
*
|
||||
* @note This function always null terminates the buffer, even if the string is too long.
|
||||
* In the case of truncation, dest_size will reflect the truncated length (not including the null terminator).
|
||||
*/
|
||||
bool safe_str_copy(char* dest, size_t* dest_size, std::string_view src);
|
||||
@@ -0,0 +1,711 @@
|
||||
#include "icsneo/icsneoc2messages.h" // TODO: Remove this after the complete refactor
|
||||
|
||||
#include "icsneo/icsneoc2.h"
|
||||
#include "icsneoc2_internal.h"
|
||||
|
||||
#include "icsneo/icsneocpp.h"
|
||||
#include "icsneo/communication/message/message.h"
|
||||
#include "icsneo/communication/message/canmessage.h"
|
||||
#include "icsneo/communication/message/canerrormessage.h"
|
||||
#include "icsneo/communication/message/apperrormessage.h"
|
||||
#include "icsneo/communication/message/linmessage.h"
|
||||
#include "icsneo/communication/message/ethernetmessage.h"
|
||||
#include "icsneo/communication/message/ethernetstatusmessage.h"
|
||||
#include "icsneo/communication/packet/canpacket.h"
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_is_valid(icsneoc2_message_t* message, bool* is_valid) {
|
||||
if(!message || !is_valid) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
|
||||
*is_valid = (bool)message->message;
|
||||
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_is_transmit(icsneoc2_message_t* message, bool* value) {
|
||||
if(!message || !value) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
// We can static cast here because we are relying on the type being correct at this point
|
||||
auto frame = std::dynamic_pointer_cast<Frame>(message->message);
|
||||
if(!frame) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
*value = frame->transmitted;
|
||||
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_is_error(icsneoc2_message_t* message, bool* value) {
|
||||
if(!message || !value) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
auto frame = std::dynamic_pointer_cast<Frame>(message->message);
|
||||
if(!frame) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
*value = frame->error;
|
||||
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_netid_get(icsneoc2_message_t* message, icsneoc2_netid_t* netid) {
|
||||
if(!message || !netid) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
auto raw = std::dynamic_pointer_cast<RawMessage>(message->message);
|
||||
if(!raw) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
*netid = static_cast<icsneoc2_netid_t>(raw->network.getNetID());
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_netid_name_get(icsneoc2_netid_t netid, char* value, size_t* value_length) {
|
||||
if(!value || !value_length) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
auto netid_str = std::string(Network::GetNetIDString(static_cast<Network::NetID>(netid), true));
|
||||
// Copy the string into value
|
||||
return safe_str_copy(value, value_length, netid_str) ? icsneoc2_error_success : icsneoc2_error_string_copy_failed;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_netid_network_type_get(icsneoc2_netid_t netid, icsneoc2_network_type_t* network_type) {
|
||||
if(!network_type) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
*network_type = static_cast<icsneoc2_network_type_t>(Network::GetTypeOfNetID(static_cast<Network::NetID>(netid), true));
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_netid_set(icsneoc2_message_t* message, icsneoc2_netid_t netid) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
auto raw = std::dynamic_pointer_cast<RawMessage>(message->message);
|
||||
if(!raw) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
raw->network = Network(static_cast<neonetid_t>(netid), true);
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_data_set(icsneoc2_message_t* message, uint8_t* data, size_t data_length) {
|
||||
if(!message || !data) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
// Make sure the message has the data field (RawMessage or Frame)
|
||||
auto raw_message = std::dynamic_pointer_cast<RawMessage>(message->message);
|
||||
if(!raw_message) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
raw_message->data.resize(data_length);
|
||||
std::copy(data, data + data_length, raw_message->data.begin());
|
||||
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_data_get(icsneoc2_message_t* message, uint8_t* data, size_t* data_length) {
|
||||
if(!message || !data_length) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
// Make sure the message has the data field (RawMessage or Frame)
|
||||
auto raw_message = std::dynamic_pointer_cast<RawMessage>(message->message);
|
||||
if(!raw_message) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
if(!data) {
|
||||
*data_length = raw_message->data.size();
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
if(*data_length < raw_message->data.size()) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
std::copy(raw_message->data.begin(), raw_message->data.begin() + raw_message->data.size(), data);
|
||||
*data_length = raw_message->data.size();
|
||||
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_timestamp_set(icsneoc2_message_t* message, uint64_t timestamp) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
if(!message->message) {
|
||||
return icsneoc2_error_invalid_message;
|
||||
}
|
||||
message->message->timestamp = timestamp;
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_timestamp_get(icsneoc2_message_t* message, uint64_t* timestamp) {
|
||||
if(!message || !timestamp) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
if(!message->message) {
|
||||
return icsneoc2_error_invalid_message;
|
||||
}
|
||||
*timestamp = message->message->timestamp;
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_can_create(icsneoc2_message_t** message) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
try {
|
||||
*message = new icsneoc2_message_t;
|
||||
// Initialize the internal message as a CANMessage so that all icsneoc2_message_can_*_set
|
||||
// functions work correctly on user-created transmit messages.
|
||||
(*message)->message = std::make_shared<CANMessage>();
|
||||
} catch(const std::bad_alloc&) {
|
||||
return icsneoc2_error_out_of_memory;
|
||||
}
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_free(icsneoc2_message_t* message) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
delete message;
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_can_props_set(icsneoc2_message_t* message, const uint64_t* arb_id, const uint64_t* flags) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
auto can_msg = std::dynamic_pointer_cast<CANMessage>(message->message);
|
||||
if(!can_msg) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
if(arb_id) {
|
||||
can_msg->arbid = static_cast<uint32_t>(*arb_id);
|
||||
}
|
||||
if(flags) {
|
||||
can_msg->isRemote = (*flags & ICSNEOC2_MESSAGE_CAN_FLAGS_RTR);
|
||||
can_msg->isExtended = (*flags & ICSNEOC2_MESSAGE_CAN_FLAGS_IDE);
|
||||
can_msg->isCANFD = (*flags & ICSNEOC2_MESSAGE_CAN_FLAGS_FDF);
|
||||
can_msg->baudrateSwitch = (*flags & ICSNEOC2_MESSAGE_CAN_FLAGS_BRS);
|
||||
can_msg->errorStateIndicator = (*flags & ICSNEOC2_MESSAGE_CAN_FLAGS_ESI);
|
||||
}
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_can_props_get(icsneoc2_message_t* message, uint64_t* arb_id, uint64_t* flags) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
auto can_msg = std::dynamic_pointer_cast<CANMessage>(message->message);
|
||||
if(!can_msg) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
if(arb_id) {
|
||||
*arb_id = can_msg->arbid;
|
||||
}
|
||||
if(flags) {
|
||||
*flags = 0;
|
||||
if(can_msg->isRemote) {
|
||||
*flags |= ICSNEOC2_MESSAGE_CAN_FLAGS_RTR;
|
||||
}
|
||||
if(can_msg->isExtended) {
|
||||
*flags |= ICSNEOC2_MESSAGE_CAN_FLAGS_IDE;
|
||||
}
|
||||
if(can_msg->isCANFD) {
|
||||
*flags |= ICSNEOC2_MESSAGE_CAN_FLAGS_FDF;
|
||||
}
|
||||
if(can_msg->baudrateSwitch) {
|
||||
*flags |= ICSNEOC2_MESSAGE_CAN_FLAGS_BRS;
|
||||
}
|
||||
if(can_msg->errorStateIndicator) {
|
||||
*flags |= ICSNEOC2_MESSAGE_CAN_FLAGS_ESI;
|
||||
}
|
||||
if(can_msg->txAborted) {
|
||||
*flags |= ICSNEOC2_MESSAGE_CAN_FLAGS_TX_ABORTED;
|
||||
}
|
||||
if(can_msg->txLostArb) {
|
||||
*flags |= ICSNEOC2_MESSAGE_CAN_FLAGS_TX_LOST_ARB;
|
||||
}
|
||||
if(can_msg->txError) {
|
||||
*flags |= ICSNEOC2_MESSAGE_CAN_FLAGS_TX_ERROR;
|
||||
}
|
||||
}
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_network_type_get(icsneoc2_message_t* message, icsneoc2_network_type_t* network_type) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
auto raw = std::dynamic_pointer_cast<RawMessage>(message->message);
|
||||
if(!raw) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
*network_type = (icsneoc2_network_type_t)raw->network.getType();
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_is_raw(icsneoc2_message_t* message, bool* is_raw) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
*is_raw = std::dynamic_pointer_cast<RawMessage>(message->message) != nullptr;
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_is_frame(icsneoc2_message_t* message, bool* is_frame) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
*is_frame = std::dynamic_pointer_cast<Frame>(message->message) != nullptr;
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_is_can(icsneoc2_message_t* message, bool* is_can) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
*is_can = std::dynamic_pointer_cast<CANMessage>(message->message) != nullptr;
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_is_can_error(icsneoc2_message_t* message, bool* is_can_error) {
|
||||
if(!message || !is_can_error) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
*is_can_error = std::dynamic_pointer_cast<CANErrorMessage>(message->message) != nullptr;
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_can_error_props_get(
|
||||
icsneoc2_message_t *message, uint8_t *tx_err_count, uint8_t *rx_err_count,
|
||||
icsneoc2_can_error_code_t *error_code,
|
||||
icsneoc2_can_error_code_t *data_error_code,
|
||||
icsneoc2_message_can_error_flags_t *flags) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
auto can_err = std::dynamic_pointer_cast<CANErrorMessage>(message->message);
|
||||
if(!can_err) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
if(tx_err_count) {
|
||||
*tx_err_count = can_err->transmitErrorCount;
|
||||
}
|
||||
if(rx_err_count) {
|
||||
*rx_err_count = can_err->receiveErrorCount;
|
||||
}
|
||||
if(error_code) {
|
||||
*error_code = static_cast<icsneoc2_can_error_code_t>(can_err->errorCode);
|
||||
}
|
||||
if(data_error_code) {
|
||||
*data_error_code = static_cast<icsneoc2_can_error_code_t>(can_err->dataErrorCode);
|
||||
}
|
||||
if(flags) {
|
||||
*flags = 0;
|
||||
if(can_err->busOff) {
|
||||
*flags |= ICSNEOC2_MESSAGE_CAN_ERROR_FLAGS_BUS_OFF;
|
||||
}
|
||||
if(can_err->errorPassive) {
|
||||
*flags |= ICSNEOC2_MESSAGE_CAN_ERROR_FLAGS_ERROR_PASSIVE;
|
||||
}
|
||||
if(can_err->errorWarn) {
|
||||
*flags |= ICSNEOC2_MESSAGE_CAN_ERROR_FLAGS_ERROR_WARN;
|
||||
}
|
||||
}
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_is_app_error(icsneoc2_message_t* message, bool* is_app_error) {
|
||||
if(!message || !is_app_error) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
*is_app_error = std::dynamic_pointer_cast<AppErrorMessage>(message->message) != nullptr;
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_app_error_props_get(icsneoc2_message_t* message,
|
||||
icsneoc2_app_error_type_t* error_type, icsneoc2_netid_t* error_netid) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
auto app_err = std::dynamic_pointer_cast<AppErrorMessage>(message->message);
|
||||
if(!app_err) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
if(error_type) {
|
||||
*error_type = static_cast<icsneoc2_app_error_type_t>(app_err->getAppErrorType());
|
||||
}
|
||||
if(error_netid) {
|
||||
*error_netid = static_cast<icsneoc2_netid_t>(app_err->errorNetID);
|
||||
}
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_app_error_string_get(icsneoc2_message_t* message,
|
||||
char* value, size_t* value_length) {
|
||||
if(!message || !value_length) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
auto app_err = std::dynamic_pointer_cast<AppErrorMessage>(message->message);
|
||||
if(!app_err) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
return safe_str_copy(value, value_length, app_err->getAppErrorString()) ? icsneoc2_error_success : icsneoc2_error_string_copy_failed;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_is_lin(icsneoc2_message_t* message, bool* is_lin) {
|
||||
if(!message || !is_lin) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
*is_lin = std::dynamic_pointer_cast<LINMessage>(message->message) != nullptr;
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_lin_create(icsneoc2_message_t** message, uint8_t id) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
try {
|
||||
*message = new icsneoc2_message_t;
|
||||
(*message)->message = std::make_shared<LINMessage>(id);
|
||||
} catch(const std::bad_alloc&) {
|
||||
return icsneoc2_error_out_of_memory;
|
||||
}
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_lin_props_get(const icsneoc2_message_t* message,
|
||||
uint8_t* id, uint8_t* protected_id, uint8_t* checksum,
|
||||
icsneoc2_lin_msg_type_t* msg_type, bool* is_enhanced_checksum) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
auto lin_msg = std::dynamic_pointer_cast<LINMessage>(message->message);
|
||||
if(!lin_msg) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
if(id) {
|
||||
*id = lin_msg->ID;
|
||||
}
|
||||
if(protected_id) {
|
||||
*protected_id = lin_msg->protectedID;
|
||||
}
|
||||
if(checksum) {
|
||||
*checksum = lin_msg->checksum;
|
||||
}
|
||||
if(msg_type) {
|
||||
*msg_type = static_cast<icsneoc2_lin_msg_type_t>(lin_msg->linMsgType);
|
||||
}
|
||||
if(is_enhanced_checksum) {
|
||||
*is_enhanced_checksum = lin_msg->isEnhancedChecksum;
|
||||
}
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_lin_props_set(icsneoc2_message_t* message,
|
||||
const uint8_t* id, const uint8_t* checksum,
|
||||
const icsneoc2_lin_msg_type_t* msg_type, const bool* is_enhanced_checksum) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
auto lin_msg = std::dynamic_pointer_cast<LINMessage>(message->message);
|
||||
if(!lin_msg) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
if(id) {
|
||||
lin_msg->ID = *id & 0x3Fu;
|
||||
lin_msg->protectedID = lin_msg->calcProtectedID(lin_msg->ID);
|
||||
}
|
||||
if(checksum) {
|
||||
lin_msg->checksum = *checksum;
|
||||
}
|
||||
if(msg_type) {
|
||||
lin_msg->linMsgType = static_cast<LINMessage::Type>(*msg_type);
|
||||
}
|
||||
if(is_enhanced_checksum) {
|
||||
lin_msg->isEnhancedChecksum = *is_enhanced_checksum;
|
||||
}
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_lin_err_flags_get(const icsneoc2_message_t* message, icsneoc2_lin_err_flags_t* err_flags) {
|
||||
if(!message || !err_flags) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
auto lin_msg = std::dynamic_pointer_cast<LINMessage>(message->message);
|
||||
if(!lin_msg) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
*err_flags = 0;
|
||||
if(lin_msg->errFlags.ErrRxBreakOnly) *err_flags |= ICSNEOC2_LIN_ERR_RX_BREAK_ONLY;
|
||||
if(lin_msg->errFlags.ErrRxBreakSyncOnly) *err_flags |= ICSNEOC2_LIN_ERR_RX_BREAK_SYNC_ONLY;
|
||||
if(lin_msg->errFlags.ErrTxRxMismatch) *err_flags |= ICSNEOC2_LIN_ERR_TX_RX_MISMATCH;
|
||||
if(lin_msg->errFlags.ErrRxBreakNotZero) *err_flags |= ICSNEOC2_LIN_ERR_RX_BREAK_NOT_ZERO;
|
||||
if(lin_msg->errFlags.ErrRxBreakTooShort) *err_flags |= ICSNEOC2_LIN_ERR_RX_BREAK_TOO_SHORT;
|
||||
if(lin_msg->errFlags.ErrRxSyncNot55) *err_flags |= ICSNEOC2_LIN_ERR_RX_SYNC_NOT_55;
|
||||
if(lin_msg->errFlags.ErrRxDataLenOver8) *err_flags |= ICSNEOC2_LIN_ERR_RX_DATA_LEN_OVER_8;
|
||||
if(lin_msg->errFlags.ErrFrameSync) *err_flags |= ICSNEOC2_LIN_ERR_FRAME_SYNC;
|
||||
if(lin_msg->errFlags.ErrFrameMessageID) *err_flags |= ICSNEOC2_LIN_ERR_FRAME_MESSAGE_ID;
|
||||
if(lin_msg->errFlags.ErrFrameResponderData) *err_flags |= ICSNEOC2_LIN_ERR_FRAME_RESPONDER_DATA;
|
||||
if(lin_msg->errFlags.ErrChecksumMatch) *err_flags |= ICSNEOC2_LIN_ERR_CHECKSUM_MATCH;
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_lin_status_flags_get(const icsneoc2_message_t* message, icsneoc2_lin_status_flags_t* status_flags) {
|
||||
if(!message || !status_flags) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
auto lin_msg = std::dynamic_pointer_cast<LINMessage>(message->message);
|
||||
if(!lin_msg) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
*status_flags = 0;
|
||||
if(lin_msg->statusFlags.TxChecksumEnhanced) *status_flags |= ICSNEOC2_LIN_STATUS_TX_CHECKSUM_ENHANCED;
|
||||
if(lin_msg->statusFlags.TxCommander) *status_flags |= ICSNEOC2_LIN_STATUS_TX_COMMANDER;
|
||||
if(lin_msg->statusFlags.TxResponder) *status_flags |= ICSNEOC2_LIN_STATUS_TX_RESPONDER;
|
||||
if(lin_msg->statusFlags.TxAborted) *status_flags |= ICSNEOC2_LIN_STATUS_TX_ABORTED;
|
||||
if(lin_msg->statusFlags.UpdateResponderOnce) *status_flags |= ICSNEOC2_LIN_STATUS_UPDATE_RESPONDER_ONCE;
|
||||
if(lin_msg->statusFlags.HasUpdatedResponderOnce) *status_flags |= ICSNEOC2_LIN_STATUS_HAS_UPDATED_RESPONDER_ONCE;
|
||||
if(lin_msg->statusFlags.BusRecovered) *status_flags |= ICSNEOC2_LIN_STATUS_BUS_RECOVERED;
|
||||
if(lin_msg->statusFlags.BreakOnly) *status_flags |= ICSNEOC2_LIN_STATUS_BREAK_ONLY;
|
||||
if(lin_msg->statusFlags.WakeupRequest) *status_flags |= ICSNEOC2_LIN_STATUS_WAKEUP_REQUEST;
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_lin_calc_checksum(icsneoc2_message_t* message) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
auto lin_msg = std::dynamic_pointer_cast<LINMessage>(message->message);
|
||||
if(!lin_msg) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
LINMessage::calcChecksum(*lin_msg);
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_eth_create(icsneoc2_message_t** message) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
try {
|
||||
*message = new icsneoc2_message_t;
|
||||
(*message)->message = std::make_shared<EthernetMessage>();
|
||||
} catch(const std::bad_alloc&) {
|
||||
return icsneoc2_error_out_of_memory;
|
||||
}
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_eth_props_set(icsneoc2_message_t* message, const icsneoc2_message_eth_flags_t* flags, const bool* has_fcs, const uint32_t* fcs) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
auto eth_msg = std::dynamic_pointer_cast<EthernetMessage>(message->message);
|
||||
if(!eth_msg) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
if(flags) {
|
||||
eth_msg->frameTooShort = (*flags & ICSNEOC2_MESSAGE_ETH_FLAGS_FRAME_TOO_SHORT);
|
||||
eth_msg->noPadding = (*flags & ICSNEOC2_MESSAGE_ETH_FLAGS_NO_PADDING);
|
||||
eth_msg->fcsVerified = (*flags & ICSNEOC2_MESSAGE_ETH_FLAGS_FCS_VERIFIED);
|
||||
eth_msg->txAborted = (*flags & ICSNEOC2_MESSAGE_ETH_FLAGS_TX_ABORTED);
|
||||
eth_msg->crcError = (*flags & ICSNEOC2_MESSAGE_ETH_FLAGS_CRC_ERROR);
|
||||
}
|
||||
if(has_fcs && !*has_fcs) {
|
||||
eth_msg->fcs = std::nullopt;
|
||||
} else if(has_fcs && *has_fcs) {
|
||||
// I'm pretty sure we can leave this alone, setting fcs below will take care of the behavior,
|
||||
// otherwise we get into a weird state where we have to set fcs to zero if fcs is null but has_fcs is true.
|
||||
}
|
||||
if (fcs) {
|
||||
eth_msg->fcs = *fcs;
|
||||
}
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_eth_props_get(icsneoc2_message_t* message, icsneoc2_message_eth_flags_t* flags, bool* has_fcs, uint32_t* fcs) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
auto eth_msg = std::dynamic_pointer_cast<EthernetMessage>(message->message);
|
||||
if(!eth_msg) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
if(flags) {
|
||||
*flags = 0;
|
||||
if(eth_msg->noPadding)
|
||||
*flags |= ICSNEOC2_MESSAGE_ETH_FLAGS_NO_PADDING;
|
||||
if(eth_msg->fcsVerified)
|
||||
*flags |= ICSNEOC2_MESSAGE_ETH_FLAGS_FCS_VERIFIED;
|
||||
if(eth_msg->txAborted)
|
||||
*flags |= ICSNEOC2_MESSAGE_ETH_FLAGS_TX_ABORTED;
|
||||
if(eth_msg->crcError)
|
||||
*flags |= ICSNEOC2_MESSAGE_ETH_FLAGS_CRC_ERROR;
|
||||
if(eth_msg->frameTooShort)
|
||||
*flags |= ICSNEOC2_MESSAGE_ETH_FLAGS_FRAME_TOO_SHORT;
|
||||
}
|
||||
if(has_fcs) {
|
||||
*has_fcs = eth_msg->fcs.has_value();
|
||||
}
|
||||
if(fcs) {
|
||||
if(eth_msg->fcs) {
|
||||
*fcs = eth_msg->fcs.value();
|
||||
} else {
|
||||
*fcs = 0;
|
||||
}
|
||||
}
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_eth_mac_get(icsneoc2_message_t* message, uint8_t* dst_mac, uint8_t* src_mac) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
auto eth_msg = std::dynamic_pointer_cast<EthernetMessage>(message->message);
|
||||
if(!eth_msg) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
if(dst_mac) {
|
||||
if(auto mac = eth_msg->getDestinationMAC(); mac.has_value()) {
|
||||
const auto& mac_value = mac.value();
|
||||
std::memcpy(dst_mac, mac_value.data(), mac_value.size());
|
||||
} else {
|
||||
return icsneoc2_error_invalid_data;
|
||||
}
|
||||
}
|
||||
if(src_mac) {
|
||||
if(auto mac = eth_msg->getSourceMAC(); mac.has_value()) {
|
||||
const auto& mac_value = mac.value();
|
||||
std::memcpy(src_mac, mac_value.data(), mac_value.size());
|
||||
} else {
|
||||
return icsneoc2_error_invalid_data;
|
||||
}
|
||||
}
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_eth_ether_type_get(icsneoc2_message_t* message, uint16_t* ether_type) {
|
||||
if(!message || !ether_type) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
auto eth_msg = std::dynamic_pointer_cast<EthernetMessage>(message->message);
|
||||
if(!eth_msg) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
if (auto et = eth_msg->getEtherType(); et.has_value()) {
|
||||
*ether_type = et.value();
|
||||
} else {
|
||||
return icsneoc2_error_invalid_data;
|
||||
}
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_eth_t1s_props_set(icsneoc2_message_t* message, const icsneoc2_message_eth_t1s_flags_t* flags, const uint8_t* node_id, const uint8_t* burst_count, const uint8_t* symbol_type) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
auto eth_msg = std::dynamic_pointer_cast<EthernetMessage>(message->message);
|
||||
if(!eth_msg) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
// If all parameters are null/zero, clear the T1S state. Otherwise, if any parameters are set and we don't have a T1S state, create it.
|
||||
if(!flags && !node_id && !burst_count && !symbol_type) {
|
||||
eth_msg->t1s = std::nullopt;
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
if((flags || node_id || burst_count || symbol_type) && !eth_msg->t1s.has_value()) {
|
||||
eth_msg->t1s.emplace();
|
||||
}
|
||||
if(flags) {
|
||||
eth_msg->t1s->isSymbol = (*flags & ICSNEOC2_MESSAGE_ETH_T1S_FLAGS_IS_T1S_SYMBOL);
|
||||
eth_msg->t1s->isBurst = (*flags & ICSNEOC2_MESSAGE_ETH_T1S_FLAGS_IS_T1S_BURST);
|
||||
eth_msg->t1s->txCollision = (*flags & ICSNEOC2_MESSAGE_ETH_T1S_FLAGS_TX_COLLISION);
|
||||
eth_msg->t1s->isWake = (*flags & ICSNEOC2_MESSAGE_ETH_T1S_FLAGS_IS_T1S_WAKE);
|
||||
}
|
||||
if(node_id) {
|
||||
eth_msg->t1s->nodeId = *node_id;
|
||||
}
|
||||
if(burst_count) {
|
||||
eth_msg->t1s->burstCount = *burst_count;
|
||||
}
|
||||
if(symbol_type) {
|
||||
eth_msg->t1s->symbolType = *symbol_type;
|
||||
}
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_eth_t1s_props_get(icsneoc2_message_t* message, icsneoc2_message_eth_t1s_flags_t* flags, uint8_t* node_id, uint8_t* burst_count, uint8_t* symbol_type) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
auto eth_msg = std::dynamic_pointer_cast<EthernetMessage>(message->message);
|
||||
if(!eth_msg) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
if(flags) {
|
||||
*flags = 0;
|
||||
if(eth_msg->t1s.has_value()) {
|
||||
if(eth_msg->t1s->isSymbol)
|
||||
*flags |= ICSNEOC2_MESSAGE_ETH_T1S_FLAGS_IS_T1S_SYMBOL;
|
||||
if(eth_msg->t1s->isBurst)
|
||||
*flags |= ICSNEOC2_MESSAGE_ETH_T1S_FLAGS_IS_T1S_BURST;
|
||||
if(eth_msg->t1s->txCollision)
|
||||
*flags |= ICSNEOC2_MESSAGE_ETH_T1S_FLAGS_TX_COLLISION;
|
||||
if(eth_msg->t1s->isWake)
|
||||
*flags |= ICSNEOC2_MESSAGE_ETH_T1S_FLAGS_IS_T1S_WAKE;
|
||||
}
|
||||
}
|
||||
if(node_id) {
|
||||
*node_id = eth_msg->t1s.has_value() ? eth_msg->t1s->nodeId : 0;
|
||||
}
|
||||
if(burst_count) {
|
||||
*burst_count = eth_msg->t1s.has_value() ? eth_msg->t1s->burstCount : 0;
|
||||
}
|
||||
if(symbol_type) {
|
||||
*symbol_type = eth_msg->t1s.has_value() ? eth_msg->t1s->symbolType : 0;
|
||||
}
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_is_ethernet(icsneoc2_message_t* message, bool* is_ethernet) {
|
||||
if(!message || !is_ethernet) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
*is_ethernet = std::dynamic_pointer_cast<EthernetMessage>(message->message) != nullptr;
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_is_ethernet_status(icsneoc2_message_t* message, bool* is_ethernet_status) {
|
||||
if(!message || !is_ethernet_status) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
*is_ethernet_status = std::dynamic_pointer_cast<EthernetStatusMessage>(message->message) != nullptr;
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
|
||||
icsneoc2_error_t icsneoc2_message_eth_status_props_get(icsneoc2_message_t* message, bool* link_state, bool* duplex, icsneoc2_link_speed_t* link_speed, icsneoc2_link_mode_t* link_mode) {
|
||||
if(!message) {
|
||||
return icsneoc2_error_invalid_parameters;
|
||||
}
|
||||
auto msg = std::dynamic_pointer_cast<EthernetStatusMessage>(message->message);
|
||||
if(!msg) {
|
||||
return icsneoc2_error_invalid_type;
|
||||
}
|
||||
if(link_state) {
|
||||
*link_state = msg->state;
|
||||
}
|
||||
if(duplex) {
|
||||
*duplex = msg->duplex;
|
||||
}
|
||||
if(link_speed) {
|
||||
*link_speed = static_cast<icsneoc2_link_speed_t>(msg->speed);
|
||||
}
|
||||
if(link_mode) {
|
||||
*link_mode = static_cast<icsneoc2_link_mode_t>(msg->mode);
|
||||
}
|
||||
return icsneoc2_error_success;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,51 @@
|
||||
#define VER_FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@
|
||||
#define VER_FILEVERSION_STR "v@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@@BUILD_METADATA_PLUS@ @BUILD_GIT_INFO@"
|
||||
|
||||
#define VER_PRODUCTVERSION VER_FILEVERSION
|
||||
#define VER_PRODUCTVERSION_STR VER_FILEVERSION_STR
|
||||
|
||||
#ifndef DEBUG
|
||||
#define VER_DEBUG 0
|
||||
#else
|
||||
#define VER_DEBUG VS_FF_DEBUG
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VER_FILEVERSION
|
||||
PRODUCTVERSION VER_PRODUCTVERSION
|
||||
FILEFLAGSMASK (VS_FF_DEBUG)
|
||||
FILEFLAGS (VER_DEBUG)
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904E4"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Intrepid Control Systems, Inc."
|
||||
VALUE "FileDescription", "Intrepid Control Systems Open Device Communication C API"
|
||||
VALUE "FileVersion", VER_FILEVERSION_STR
|
||||
VALUE "InternalName", "icsneoc2.dll"
|
||||
VALUE "LegalCopyright", "Intrepid Control Systems, Inc. (C) 2018-2026"
|
||||
VALUE "OriginalFilename", "icsneoc2.dll"
|
||||
VALUE "ProductName", "libicsneo"
|
||||
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
|
||||
END
|
||||
END
|
||||
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
/* The following line should only be modified for localized versions. */
|
||||
/* It consists of any number of WORD,WORD pairs, with each pair */
|
||||
/* describing a language,codepage combination supported by the file. */
|
||||
/* */
|
||||
/* For example, a file might have values "0x409,1252" indicating that it */
|
||||
/* supports English language (0x409) in the Windows ANSI codepage (1252). */
|
||||
|
||||
VALUE "Translation", 0x409, 1252
|
||||
|
||||
END
|
||||
END
|
||||
+317
-38
@@ -4,10 +4,10 @@
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
APIEvent::APIEvent(Type type, APIEvent::Severity severity, const Device* device) : eventStruct({}) {
|
||||
this->device = device;
|
||||
if(device) {
|
||||
serial = device->getSerial();
|
||||
APIEvent::APIEvent(Type type, APIEvent::Severity severity, std::weak_ptr<Device> device) : eventStruct({}), device(device) {
|
||||
auto shared = device.lock();
|
||||
if(shared) {
|
||||
serial = shared->getSerial();
|
||||
eventStruct.serial[serial.copy(eventStruct.serial, sizeof(eventStruct.serial))] = '\0';
|
||||
}
|
||||
|
||||
@@ -22,37 +22,15 @@ void APIEvent::init(Type event, APIEvent::Severity severity) {
|
||||
eventStruct.timestamp = EventClock::to_time_t(timepoint);
|
||||
}
|
||||
|
||||
std::string APIEvent::describe() const noexcept {
|
||||
std::stringstream ss;
|
||||
if(device)
|
||||
ss << *device; // Makes use of device.describe()
|
||||
else
|
||||
ss << "API";
|
||||
|
||||
Severity severity = getSeverity();
|
||||
if(severity == Severity::EventInfo) {
|
||||
ss << " Info: ";
|
||||
} else if(severity == Severity::EventWarning) {
|
||||
ss << " Warning: ";
|
||||
} else if(severity == Severity::Error) {
|
||||
ss << " Error: ";
|
||||
} else {
|
||||
// Should never get here, since Severity::Any should only be used for filtering
|
||||
ss << " Any: ";
|
||||
}
|
||||
|
||||
ss << getDescription();
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void APIEvent::downgradeFromError() noexcept {
|
||||
eventStruct.severity = (uint8_t) APIEvent::Severity::EventWarning;
|
||||
}
|
||||
|
||||
bool APIEvent::isForDevice(std::string filterSerial) const noexcept {
|
||||
if(!device || filterSerial.length() == 0)
|
||||
auto shared = device.lock();
|
||||
if(!shared || filterSerial.length() == 0)
|
||||
return false;
|
||||
return device->getSerial() == filterSerial;
|
||||
return shared->getSerial() == filterSerial;
|
||||
}
|
||||
|
||||
// API Errors
|
||||
@@ -69,14 +47,25 @@ static constexpr const char* DEVICE_CURRENTLY_POLLING = "The device is currently
|
||||
static constexpr const char* DEVICE_NOT_CURRENTLY_POLLING = "The device is not currently polling for messages.";
|
||||
static constexpr const char* UNSUPPORTED_TX_NETWORK = "Message network is not a supported TX network.";
|
||||
static constexpr const char* MESSAGE_MAX_LENGTH_EXCEEDED = "The message was too long.";
|
||||
static constexpr const char* VALUE_NOT_YET_PRESENT = "The value is not yet present.";
|
||||
static constexpr const char* TIMEOUT = "The timeout was reached.";
|
||||
static constexpr const char* WIVI_NOT_SUPPORTED = "Wireless neoVI functions are not supported on this device.";
|
||||
static constexpr const char* RESTRICTED_ENTRY_FLAG = "Attempted to set a restricted flag in a Root Directory entry.";
|
||||
static constexpr const char* NOT_SUPPORTED = "The requested feature is not supported.";
|
||||
static constexpr const char* FIXED_POINT_OVERFLOW = "Value is too large to convert to fixed point.";
|
||||
static constexpr const char* FIXED_POINT_PRECISION = "Value is too small for fixed point precision.";
|
||||
static constexpr const char* SYSCALL_ERROR = "Error returned from syscall, check errno/GetLastError().";
|
||||
|
||||
// Device Errors
|
||||
static constexpr const char* POLLING_MESSAGE_OVERFLOW = "Too many messages have been recieved for the polling message buffer, some have been lost!";
|
||||
static constexpr const char* NO_SERIAL_NUMBER = "Communication could not be established with the device. Perhaps it is not powered with 12 volts?";
|
||||
static constexpr const char* NO_SERIAL_NUMBER_FW_12V = "Communication could not be established with the device. Perhaps it is not powered with 12 volts?";
|
||||
static constexpr const char* NO_SERIAL_NUMBER_FW = "Communication could not be established with the device. Perhaps it is not powered?";
|
||||
static constexpr const char* NO_SERIAL_NUMBER_12V = "Communication could not be established with the device. Perhaps it is not powered with 12 volts or requires a firmware update using Vehicle Spy.";
|
||||
static constexpr const char* NO_SERIAL_NUMBER = "Communication could not be established with the device. Perhaps it is not powered or requires a firmware update using Vehicle Spy.";
|
||||
static constexpr const char* INCORRECT_SERIAL_NUMBER = "The device did not return the expected serial number!";
|
||||
static constexpr const char* SETTINGS_READ = "The device settings could not be read.";
|
||||
static constexpr const char* SETTINGS_VERSION = "The settings version is incorrect, please update your firmware with neoVI Explorer.";
|
||||
static constexpr const char* SETTINGS_LENGTH = "The settings length is incorrect, please update your firmware with neoVI Explorer.";
|
||||
static constexpr const char* SETTINGS_VERSION = "The settings version is incorrect, please update your firmware with ICS Device Manager.";
|
||||
static constexpr const char* SETTINGS_LENGTH = "The settings length is incorrect, please update your firmware with ICS Device Manager.";
|
||||
static constexpr const char* SETTINGS_CHECKSUM = "The settings checksum is incorrect, attempting to set defaults may remedy this issue.";
|
||||
static constexpr const char* SETTINGS_NOT_AVAILABLE = "Settings are not available for this device.";
|
||||
static constexpr const char* SETTINGS_READONLY = "Settings are read-only for this device.";
|
||||
@@ -93,6 +82,41 @@ static constexpr const char* NO_DEVICE_RESPONSE = "Expected a response from the
|
||||
static constexpr const char* MESSAGE_FORMATTING = "The message was not properly formed.";
|
||||
static constexpr const char* CANFD_NOT_SUPPORTED = "This device does not support CANFD.";
|
||||
static constexpr const char* RTR_NOT_SUPPORTED = "RTR is not supported with CANFD.";
|
||||
static constexpr const char* DEVICE_DISCONNECTED = "The device was disconnected.";
|
||||
static constexpr const char* ONLINE_NOT_SUPPORTED = "This device does not support going online.";
|
||||
static constexpr const char* TERMINATION_NOT_SUPPORTED_DEVICE = "This device does not support software selectable termination.";
|
||||
static constexpr const char* TERMINATION_NOT_SUPPORTED_NETWORK = "This network does not support software selectable termination on this device.";
|
||||
static constexpr const char* ANOTHER_IN_TERMINATION_GROUP_ENABLED = "A mutually exclusive network already has termination enabled.";
|
||||
static constexpr const char* ETH_PHY_REGISTER_CONTROL_NOT_AVAILABLE = "Ethernet PHY register control is not available for this device.";
|
||||
static constexpr const char* DISK_NOT_SUPPORTED = "This device does not support accessing the specified disk.";
|
||||
static constexpr const char* EOF_REACHED = "The requested length exceeds the available data from this disk.";
|
||||
static constexpr const char* SETTINGS_DEFAULTS_USED = "The device settings could not be loaded, the default settings have been applied.";
|
||||
static constexpr const char* ATOMIC_OPERATION_RETRIED = "An operation failed to be atomically completed, but will be retried.";
|
||||
static constexpr const char* ATOMIC_OPERATION_COMPLETED_NONATOMICALLY = "An ideally-atomic operation was completed nonatomically.";
|
||||
static constexpr const char* WIVI_STACK_REFRESH_FAILED = "The Wireless neoVI stack encountered a communication error.";
|
||||
static constexpr const char* WIVI_UPLOAD_STACK_OVERFLOW = "The Wireless neoVI upload stack has encountered an overflow condition.";
|
||||
static constexpr const char* A2B_MESSAGE_INCOMPLETE_FRAME = "At least one of the frames of the A2B message does not contain samples for each channel and stream.";
|
||||
static constexpr const char* I2C_MESSAGE_EXCEED_MAX_LENGTH = "The I2C message was too long.";
|
||||
static constexpr const char* COREMINI_UPLOAD_VERSION_MISMATCH = "The version of the coremini engine on the device and the script uploaded are not the same.";
|
||||
static constexpr const char* DISK_NOT_CONNECTED = "The program tried to access a disk that is not connected.";
|
||||
static constexpr const char* UNEXPECTED_RESPONSE = "Received an unexpected or invalid response from the device.";
|
||||
static constexpr const char* LIVE_DATA_INVALID_HANDLE = "The live data handle was invalid.";
|
||||
static constexpr const char* LIVE_DATA_INVALID_COMMAND = "The live data command was invalid.";
|
||||
static constexpr const char* LIVE_DATA_INVALID_ARGUMENT = "The live data argument was invalid.";
|
||||
static constexpr const char* LIVE_DATA_VERSION_MISMATCH = "The live data version between libicsneo and firmware are not the same.";
|
||||
static constexpr const char* LIVE_DATA_NO_DEVICE_RESPONSE = "Expected a response from the device for live data but none were found.";
|
||||
static constexpr const char* LIVE_DATA_MAX_SIGNALS_REACHED = "The max amound of signals to subscribe to for live data has been reached.";
|
||||
static constexpr const char* LIVE_DATA_COMMAND_FAILED = "The live data command failed.";
|
||||
static constexpr const char* LIVE_DATA_ENCODER_ERROR = "Failure to encode live data message.";
|
||||
static constexpr const char* LIVE_DATA_DECODER_ERROR = "Failure to decode live data message.";
|
||||
static constexpr const char* LIVE_DATA_NOT_SUPPORTED = "Live data is not supported on this device.";
|
||||
static constexpr const char* LIN_SETTINGS_NOT_AVAILABLE = "LIN settings are not available for this device.";
|
||||
static constexpr const char* MODE_NOT_FOUND = "The mode was not found.";
|
||||
static constexpr const char* APP_ERROR_PARSING_FAILED = "Failure to decode app error message.";
|
||||
static constexpr const char* GPTP_NOT_SUPPORTED = "GPTP clock synchronization is not supported on this device.";
|
||||
static constexpr const char* SETTING_NOT_AVAILABLE = "Requested a setting that is not available on this device";
|
||||
static constexpr const char* DISK_FORMAT_NOT_SUPPORTED = "Disk formatting is not supported on this device.";
|
||||
static constexpr const char* DISK_FORMAT_INVALID_COUNT = "Disk format config disk count is mismatched with device disk count.";
|
||||
|
||||
// Transport Errors
|
||||
static constexpr const char* FAILED_TO_READ = "A read operation failed.";
|
||||
@@ -104,11 +128,59 @@ static constexpr const char* TRANSMIT_BUFFER_FULL = "The transmit buffer is full
|
||||
static constexpr const char* DEVICE_IN_USE = "The device is currently in use by another program.";
|
||||
static constexpr const char* PCAP_COULD_NOT_START = "The PCAP driver could not be started. Ethernet devices will not be found.";
|
||||
static constexpr const char* PCAP_COULD_NOT_FIND_DEVICES = "The PCAP driver failed to find devices. Ethernet devices will not be found.";
|
||||
static constexpr const char* PACKET_DECODING = "The packet could not be decoded.";
|
||||
static constexpr const char* PACKET_DECODING = "There was an error decoding a packet from the device.";
|
||||
static constexpr const char* SOCKET_FAILED_TO_OPEN = "Unable to open new socket.";
|
||||
static constexpr const char* FAILED_TO_BIND = "Unable to bind socket.";
|
||||
static constexpr const char* ERROR_SETTING_SOCKET_OPTION = "A call to setsockopt() failed.";
|
||||
static constexpr const char* GETIFADDRS_ERROR = "A call to getifaddrs() failed.";
|
||||
static constexpr const char* SEND_TO_ERROR = "A call to sendto() failed.";
|
||||
static constexpr const char* MDIO_MESSAGE_EXCEED_MAX_LENGTH = "The MDIO message was too long.";
|
||||
|
||||
// VSA
|
||||
static constexpr const char* VSA_BUFFER_CORRUPTED = "VSA data in record buffer is corrupted.";
|
||||
static constexpr const char* VSA_TIMESTAMP_NOT_FOUND = "Unable to find a VSA record with a valid timestamp.";
|
||||
static constexpr const char* VSA_BUFFER_FORMAT_ERROR = "VSA record buffer is formatted incorrectly.";
|
||||
static constexpr const char* VSA_MAX_READ_ATTEMPTS_REACHED = "Reached max attempts to read VSA records before exit.";
|
||||
static constexpr const char* VSA_BYTE_PARSE_FAILURE = "Failure to parse record bytes from VSA buffer.";
|
||||
static constexpr const char* VSA_EXTENDED_MESSAGE_ERROR = "Failure to parse extended message record sequence";
|
||||
static constexpr const char* VSA_OTHER_ERROR = "Unknown error in VSA read API.";
|
||||
|
||||
// MACSEC
|
||||
static constexpr const char* MACSEC_SECY_LIMIT = "Attempted to exceed the limit of SecY additions to this port";
|
||||
static constexpr const char* MACSEC_RULE_LIMIT = "Attempted to exceed the limit of rule additions to this port";
|
||||
static constexpr const char* MACSEC_SA_LIMIT = "Attempted to exceed the limit of SA additions to this port";
|
||||
static constexpr const char* MACSEC_INVALID_SECY_INDEX = "Attempted to access an invalid SecY index";
|
||||
static constexpr const char* MACSEC_INVALID_SA_INDEX = "Attempted to access an invalid SA index";
|
||||
static constexpr const char* MACSEC_INVALID_RULE_INDEX = "Attempted to access an invalid rule index";
|
||||
static constexpr const char* MACSEC_REKEY_NOT_ENABLED = "Attempted to set rekey SA when rekey was not enabled";
|
||||
static constexpr const char* MACSEC_NOT_SUPPORTED = "MACsec is not supported on this device";
|
||||
static constexpr const char* MACSEC_CONFIG_MISMATCH = "Attempted to configure device with a macsec configuration for a different device";
|
||||
// Servd
|
||||
static constexpr const char* SERVD_BIND_ERROR = "Error binding socket for Servd communication";
|
||||
static constexpr const char* SERVD_NONBLOCK_ERROR = "Error setting non-blocking mode for Servd socket";
|
||||
static constexpr const char* SERVD_TRANSCEIVE_ERROR = "Error while sending to or receiving from Servd";
|
||||
static constexpr const char* SERVD_OUTDATED_ERROR = "Servd version is lower than client (libicsneo) version, update Servd";
|
||||
static constexpr const char* SERVD_INVALID_RESPONSE_ERROR = "Unexpected response from Servd";
|
||||
static constexpr const char* SERVD_LOCK_ERROR = "Error locking Servd mutex";
|
||||
static constexpr const char* SERVD_SEND_ERROR = "Error sending to Servd";
|
||||
static constexpr const char* SERVD_RECV_ERROR = "Error receiving from Servd";
|
||||
static constexpr const char* SERVD_POLL_ERROR = "Error polling on Servd socket";
|
||||
static constexpr const char* SERVD_NODATA_ERROR = "No data received from Servd";
|
||||
static constexpr const char* SERVD_JOIN_MULTICAST_ERROR = "Error joining Servd multicast group";
|
||||
static constexpr const char* SERVD_NOT_REACHABLE = "Could not reach Servd; ensure it is installed and running";
|
||||
|
||||
// DXX
|
||||
static constexpr const char* DXX_ERROR_SYS = "System error, check errno/GetLastError()";
|
||||
static constexpr const char* DXX_ERROR_INT = "DXX interrupt called";
|
||||
static constexpr const char* DXX_ERROR_OVERFLOW = "Overflow in DXX";
|
||||
static constexpr const char* DXX_ERROR_IO = "I/O failure in DXX";
|
||||
static constexpr const char* DXX_ERROR_ARG = "Invalid arg passed to DXX";
|
||||
|
||||
static constexpr const char* NO_ERROR_FOUND = "No errors were found.";
|
||||
static constexpr const char* TOO_MANY_EVENTS = "Too many events have occurred. The list has been truncated.";
|
||||
static constexpr const char* UNKNOWN = "An unknown internal error occurred.";
|
||||
static constexpr const char* INVALID = "An invalid internal error occurred.";
|
||||
|
||||
const char* APIEvent::DescriptionForType(Type type) {
|
||||
switch(type) {
|
||||
// API Errors
|
||||
@@ -138,6 +210,22 @@ const char* APIEvent::DescriptionForType(Type type) {
|
||||
return UNSUPPORTED_TX_NETWORK;
|
||||
case Type::MessageMaxLengthExceeded:
|
||||
return MESSAGE_MAX_LENGTH_EXCEEDED;
|
||||
case Type::ValueNotYetPresent:
|
||||
return VALUE_NOT_YET_PRESENT;
|
||||
case Type::Timeout:
|
||||
return TIMEOUT;
|
||||
case Type::WiVINotSupported:
|
||||
return WIVI_NOT_SUPPORTED;
|
||||
case Type::RestrictedEntryFlag:
|
||||
return RESTRICTED_ENTRY_FLAG;
|
||||
case Type::NotSupported:
|
||||
return NOT_SUPPORTED;
|
||||
case Type::FixedPointOverflow:
|
||||
return FIXED_POINT_OVERFLOW;
|
||||
case Type::FixedPointPrecision:
|
||||
return FIXED_POINT_PRECISION;
|
||||
case Type::SyscallError:
|
||||
return SYSCALL_ERROR;
|
||||
|
||||
// Device Errors
|
||||
case Type::PollingMessageOverflow:
|
||||
@@ -184,7 +272,76 @@ const char* APIEvent::DescriptionForType(Type type) {
|
||||
return CANFD_NOT_SUPPORTED;
|
||||
case Type::RTRNotSupported:
|
||||
return RTR_NOT_SUPPORTED;
|
||||
|
||||
case Type::DeviceDisconnected:
|
||||
return DEVICE_DISCONNECTED;
|
||||
case Type::OnlineNotSupported:
|
||||
return ONLINE_NOT_SUPPORTED;
|
||||
case Type::TerminationNotSupportedDevice:
|
||||
return TERMINATION_NOT_SUPPORTED_DEVICE;
|
||||
case Type::TerminationNotSupportedNetwork:
|
||||
return TERMINATION_NOT_SUPPORTED_NETWORK;
|
||||
case Type::AnotherInTerminationGroupEnabled:
|
||||
return ANOTHER_IN_TERMINATION_GROUP_ENABLED;
|
||||
case Type::NoSerialNumberFW:
|
||||
return NO_SERIAL_NUMBER_FW;
|
||||
case Type::NoSerialNumber12V:
|
||||
return NO_SERIAL_NUMBER_12V;
|
||||
case Type::NoSerialNumberFW12V:
|
||||
return NO_SERIAL_NUMBER_FW_12V;
|
||||
case Type::EthPhyRegisterControlNotAvailable:
|
||||
return ETH_PHY_REGISTER_CONTROL_NOT_AVAILABLE;
|
||||
case Type::DiskNotSupported:
|
||||
return DISK_NOT_SUPPORTED;
|
||||
case Type::EOFReached:
|
||||
return EOF_REACHED;
|
||||
case Type::SettingsDefaultsUsed:
|
||||
return SETTINGS_DEFAULTS_USED;
|
||||
case Type::AtomicOperationRetried:
|
||||
return ATOMIC_OPERATION_RETRIED;
|
||||
case Type::AtomicOperationCompletedNonatomically:
|
||||
return ATOMIC_OPERATION_COMPLETED_NONATOMICALLY;
|
||||
case Type::WiVIStackRefreshFailed:
|
||||
return WIVI_STACK_REFRESH_FAILED;
|
||||
case Type::WiVIUploadStackOverflow:
|
||||
return WIVI_UPLOAD_STACK_OVERFLOW;
|
||||
case Type::I2CMessageExceedsMaxLength:
|
||||
return I2C_MESSAGE_EXCEED_MAX_LENGTH;
|
||||
case Type::A2BMessageIncompleteFrame:
|
||||
return A2B_MESSAGE_INCOMPLETE_FRAME;
|
||||
case Type::CoreminiUploadVersionMismatch:
|
||||
return COREMINI_UPLOAD_VERSION_MISMATCH;
|
||||
case Type::DiskNotConnected:
|
||||
return DISK_NOT_CONNECTED;
|
||||
case Type::UnexpectedResponse:
|
||||
return UNEXPECTED_RESPONSE;
|
||||
case Type::LiveDataInvalidHandle:
|
||||
return LIVE_DATA_INVALID_HANDLE;
|
||||
case Type::LiveDataInvalidCommand:
|
||||
return LIVE_DATA_INVALID_COMMAND;
|
||||
case Type::LiveDataInvalidArgument:
|
||||
return LIVE_DATA_INVALID_ARGUMENT;
|
||||
case Type::LiveDataVersionMismatch:
|
||||
return LIVE_DATA_VERSION_MISMATCH;
|
||||
case Type::LiveDataNoDeviceResponse:
|
||||
return LIVE_DATA_NO_DEVICE_RESPONSE;
|
||||
case Type::LiveDataMaxSignalsReached:
|
||||
return LIVE_DATA_MAX_SIGNALS_REACHED;
|
||||
case Type::LiveDataCommandFailed:
|
||||
return LIVE_DATA_COMMAND_FAILED;
|
||||
case Type::LiveDataEncoderError:
|
||||
return LIVE_DATA_ENCODER_ERROR;
|
||||
case Type::LiveDataDecoderError:
|
||||
return LIVE_DATA_DECODER_ERROR;
|
||||
case Type::LiveDataNotSupported:
|
||||
return LIVE_DATA_NOT_SUPPORTED;
|
||||
case Type::LINSettingsNotAvailable:
|
||||
return LIN_SETTINGS_NOT_AVAILABLE;
|
||||
case Type::ModeNotFound:
|
||||
return MODE_NOT_FOUND;
|
||||
case Type::AppErrorParsingFailed:
|
||||
return APP_ERROR_PARSING_FAILED;
|
||||
case Type::SettingNotAvaiableDevice:
|
||||
return SETTING_NOT_AVAILABLE;
|
||||
// Transport Errors
|
||||
case Type::FailedToRead:
|
||||
return FAILED_TO_READ;
|
||||
@@ -206,21 +363,143 @@ const char* APIEvent::DescriptionForType(Type type) {
|
||||
return PCAP_COULD_NOT_FIND_DEVICES;
|
||||
case Type::PacketDecodingError:
|
||||
return PACKET_DECODING;
|
||||
|
||||
case Type::SocketFailedToOpen:
|
||||
return SOCKET_FAILED_TO_OPEN;
|
||||
case Type::FailedToBind:
|
||||
return FAILED_TO_BIND;
|
||||
case Type::ErrorSettingSocketOption:
|
||||
return ERROR_SETTING_SOCKET_OPTION;
|
||||
case Type::GetIfAddrsError:
|
||||
return GETIFADDRS_ERROR;
|
||||
case Type::SendToError:
|
||||
return SEND_TO_ERROR;
|
||||
case Type::MDIOMessageExceedsMaxLength:
|
||||
return MDIO_MESSAGE_EXCEED_MAX_LENGTH;
|
||||
case Type::GPTPNotSupported:
|
||||
return GPTP_NOT_SUPPORTED;
|
||||
case Type::DiskFormatNotSupported:
|
||||
return DISK_FORMAT_NOT_SUPPORTED;
|
||||
case Type::DiskFormatInvalidCount:
|
||||
return DISK_FORMAT_INVALID_COUNT;
|
||||
|
||||
// VSA
|
||||
case Type::VSABufferCorrupted:
|
||||
return VSA_BUFFER_CORRUPTED;
|
||||
case Type::VSATimestampNotFound:
|
||||
return VSA_TIMESTAMP_NOT_FOUND;
|
||||
case Type::VSABufferFormatError:
|
||||
return VSA_BUFFER_FORMAT_ERROR;
|
||||
case Type::VSAMaxReadAttemptsReached:
|
||||
return VSA_MAX_READ_ATTEMPTS_REACHED;
|
||||
case Type::VSAByteParseFailure:
|
||||
return VSA_BYTE_PARSE_FAILURE;
|
||||
case Type::VSAExtendedMessageError:
|
||||
return VSA_EXTENDED_MESSAGE_ERROR;
|
||||
case Type::VSAOtherError:
|
||||
return VSA_OTHER_ERROR;
|
||||
|
||||
// MACSEC
|
||||
case Type::MACsecSecYLimit:
|
||||
return MACSEC_SECY_LIMIT;
|
||||
case Type::MACsecSaLimit:
|
||||
return MACSEC_SA_LIMIT;
|
||||
case Type::MACsecRuleLimit:
|
||||
return MACSEC_RULE_LIMIT;
|
||||
case Type::MACsecInvalidSecYIndex:
|
||||
return MACSEC_INVALID_SECY_INDEX;
|
||||
case Type::MACsecInvalidSaIndex:
|
||||
return MACSEC_INVALID_SA_INDEX;
|
||||
case Type::MACsecInvalidRuleIndex:
|
||||
return MACSEC_INVALID_RULE_INDEX;
|
||||
case Type::MACsecRekeyNotEnabled:
|
||||
return MACSEC_REKEY_NOT_ENABLED;
|
||||
case Type::MACsecNotSupported:
|
||||
return MACSEC_NOT_SUPPORTED;
|
||||
case Type::MACsecConfigMismatch:
|
||||
return MACSEC_CONFIG_MISMATCH;
|
||||
// Servd
|
||||
case Type::ServdBindError:
|
||||
return SERVD_BIND_ERROR;
|
||||
case Type::ServdNonblockError:
|
||||
return SERVD_NONBLOCK_ERROR;
|
||||
case Type::ServdTransceiveError:
|
||||
return SERVD_TRANSCEIVE_ERROR;
|
||||
case Type::ServdOutdatedError:
|
||||
return SERVD_OUTDATED_ERROR;
|
||||
case Type::ServdInvalidResponseError:
|
||||
return SERVD_INVALID_RESPONSE_ERROR;
|
||||
case Type::ServdLockError:
|
||||
return SERVD_LOCK_ERROR;
|
||||
case Type::ServdSendError:
|
||||
return SERVD_SEND_ERROR;
|
||||
case Type::ServdRecvError:
|
||||
return SERVD_RECV_ERROR;
|
||||
case Type::ServdPollError:
|
||||
return SERVD_POLL_ERROR;
|
||||
case Type::ServdNoDataError:
|
||||
return SERVD_NODATA_ERROR;
|
||||
case Type::ServdJoinMulticastError:
|
||||
return SERVD_JOIN_MULTICAST_ERROR;
|
||||
case Type::ServdNotReachable:
|
||||
return SERVD_NOT_REACHABLE;
|
||||
|
||||
// DXX
|
||||
case Type::DXXErrorSys:
|
||||
return DXX_ERROR_SYS;
|
||||
case Type::DXXErrorInt:
|
||||
return DXX_ERROR_INT;
|
||||
case Type::DXXErrorOverflow:
|
||||
return DXX_ERROR_OVERFLOW;
|
||||
case Type::DXXErrorIO:
|
||||
return DXX_ERROR_IO;
|
||||
case Type::DXXErrorArg:
|
||||
return DXX_ERROR_ARG;
|
||||
|
||||
// Other Errors
|
||||
case Type::NoErrorFound:
|
||||
return NO_ERROR_FOUND;
|
||||
case Type::TooManyEvents:
|
||||
return TOO_MANY_EVENTS;
|
||||
case Type::Unknown:
|
||||
return UNKNOWN;
|
||||
default:
|
||||
return INVALID;
|
||||
case Type::Any:
|
||||
break;
|
||||
}
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
std::string APIEvent::describe() const noexcept {
|
||||
std::stringstream ss;
|
||||
auto shared = device.lock();
|
||||
if(shared)
|
||||
ss << *shared; // Makes use of device.describe()
|
||||
else
|
||||
ss << "API";
|
||||
|
||||
Severity severity = getSeverity();
|
||||
if(severity == Severity::EventInfo) {
|
||||
ss << " Info: ";
|
||||
} else if(severity == Severity::EventWarning) {
|
||||
ss << " Warning: ";
|
||||
} else if(severity == Severity::Error) {
|
||||
ss << " Error: ";
|
||||
} else {
|
||||
// Should never get here, since Severity::Any should only be used for filtering
|
||||
ss << " Any: ";
|
||||
}
|
||||
|
||||
const char* description = DescriptionForType(getType());
|
||||
if(description == INVALID)
|
||||
ss << description << " (0x" << std::hex << eventStruct.eventNumber << ")";
|
||||
else
|
||||
ss << description;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
bool EventFilter::match(const APIEvent& event) const noexcept {
|
||||
if(type != APIEvent::Type::Any && type != event.getType())
|
||||
return false;
|
||||
|
||||
|
||||
if(matchOnDevicePtr && !event.isForDevice(device))
|
||||
return false;
|
||||
|
||||
|
||||
@@ -1,11 +1,126 @@
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
EventManager& EventManager::GetInstance() {
|
||||
static EventManager inst;
|
||||
return inst;
|
||||
static EventManager* inst = new EventManager();
|
||||
return *inst;
|
||||
}
|
||||
|
||||
void EventManager::downgradeErrorsOnCurrentThread() {
|
||||
if(destructing)
|
||||
return;
|
||||
std::lock_guard<std::mutex> lk(downgradedThreadsMutex);
|
||||
auto i = downgradedThreads.find(std::this_thread::get_id());
|
||||
if(i != downgradedThreads.end()) {
|
||||
i->second = true;
|
||||
} else {
|
||||
downgradedThreads.insert({std::this_thread::get_id(), true});
|
||||
}
|
||||
}
|
||||
|
||||
void EventManager::cancelErrorDowngradingOnCurrentThread() {
|
||||
if(destructing)
|
||||
return;
|
||||
std::lock_guard<std::mutex> lk(downgradedThreadsMutex);
|
||||
auto i = downgradedThreads.find(std::this_thread::get_id());
|
||||
if(i != downgradedThreads.end()) {
|
||||
i->second = false;
|
||||
}
|
||||
}
|
||||
|
||||
void EventManager::add(APIEvent event) {
|
||||
if(destructing)
|
||||
return;
|
||||
static const auto printLevel = []() -> std::optional<uint8_t> {
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
const auto level = std::getenv("LIBICSNEO_PRINT_EVENTS");
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
if(!level)
|
||||
return std::nullopt;
|
||||
try {
|
||||
return (uint8_t)std::stoi(level);
|
||||
} catch (std::invalid_argument const&) {
|
||||
return std::nullopt;
|
||||
}
|
||||
}();
|
||||
if(printLevel && (uint8_t)event.getSeverity() >= *printLevel)
|
||||
std::cerr << event.describe() << std::endl;
|
||||
if(event.getSeverity() == APIEvent::Severity::Error) {
|
||||
// if the error was added on a thread that downgrades errors (non-user thread)
|
||||
std::lock_guard<std::mutex> lk(downgradedThreadsMutex);
|
||||
auto i = downgradedThreads.find(std::this_thread::get_id());
|
||||
if(i != downgradedThreads.end() && i->second) {
|
||||
event.downgradeFromError();
|
||||
{
|
||||
std::lock_guard<std::mutex> eventsLock(eventsMutex);
|
||||
addEventInternal(event);
|
||||
} // free the lock so that callbacks may modify events
|
||||
runCallbacks(event);
|
||||
} else {
|
||||
std::lock_guard<std::mutex> errorsLock(errorsMutex);
|
||||
lastUserErrors[std::this_thread::get_id()] = event;
|
||||
}
|
||||
} else {
|
||||
{
|
||||
std::lock_guard<std::mutex> eventsLock(eventsMutex);
|
||||
addEventInternal(event);
|
||||
} // free the lock so that callbacks may modify events
|
||||
runCallbacks(event);
|
||||
}
|
||||
}
|
||||
|
||||
void EventManager::addEventInternal(APIEvent event) {
|
||||
// Ensure the event list is at most exactly full (size of eventLimit - 1, leaving room for a potential APIEvent::TooManyEvents)
|
||||
// Removes any events of type TooManyEvents from the end before checking to avoid duplicates.
|
||||
enforceLimit();
|
||||
|
||||
// We are exactly full, either because the list was truncated or because we were simply full before
|
||||
if(events.size() == eventLimit - 1) {
|
||||
// If the event is worth adding
|
||||
if(event.getType() != APIEvent::Type::TooManyEvents) {
|
||||
discardOldest(1);
|
||||
events.push_back(event);
|
||||
}
|
||||
|
||||
events.push_back(APIEvent(APIEvent::Type::TooManyEvents, APIEvent::Severity::EventWarning));
|
||||
} else {
|
||||
if (event.getType() != APIEvent::Type::TooManyEvents)
|
||||
events.push_back(event);
|
||||
}
|
||||
}
|
||||
|
||||
void EventManager::runCallbacks(APIEvent event) {
|
||||
std::lock_guard<std::mutex> lk(callbacksMutex);
|
||||
for(auto& i : callbacks)
|
||||
i.second.callIfMatch(std::make_shared<APIEvent>(event));
|
||||
}
|
||||
|
||||
void EventManager::setEventLimit(size_t newLimit) {
|
||||
std::lock_guard<std::mutex> eventLimitLock(eventLimitMutex);
|
||||
|
||||
if(newLimit == eventLimit)
|
||||
return;
|
||||
|
||||
if(newLimit < 10) {
|
||||
add(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
|
||||
return;
|
||||
}
|
||||
|
||||
eventLimit = newLimit;
|
||||
|
||||
std::lock_guard<std::mutex> eventsLock(eventsMutex);
|
||||
if(enforceLimit())
|
||||
addEventInternal(APIEvent(APIEvent::Type::TooManyEvents, APIEvent::Severity::EventWarning));
|
||||
}
|
||||
|
||||
void EventManager::ResetInstance() {
|
||||
@@ -21,7 +136,7 @@ void EventManager::ResetInstance() {
|
||||
lastUserErrors.clear();
|
||||
downgradedThreads.clear();
|
||||
callbacks.clear();
|
||||
|
||||
|
||||
callbackID = 0;
|
||||
eventLimit = 10000;
|
||||
}
|
||||
@@ -55,7 +170,7 @@ bool EventManager::isDowngradingErrorsOnCurrentThread() const {
|
||||
|
||||
void EventManager::get(std::vector<APIEvent>& eventOutput, size_t max, EventFilter filter) {
|
||||
std::lock_guard<std::mutex> lk(eventsMutex);
|
||||
|
||||
|
||||
if(max == 0) // A limit of 0 indicates no limit
|
||||
max = (size_t)-1;
|
||||
|
||||
@@ -98,7 +213,7 @@ void EventManager::discard(EventFilter filter) {
|
||||
});
|
||||
}
|
||||
|
||||
size_t EventManager::count_internal(EventFilter filter) const {
|
||||
size_t EventManager::countInternal(EventFilter filter) const {
|
||||
size_t ret = 0;
|
||||
for(auto& event : events)
|
||||
if(filter.match(event))
|
||||
@@ -117,7 +232,7 @@ bool EventManager::enforceLimit() {
|
||||
while(it != events.rend() && filter.match(*it)) {
|
||||
it = decltype(it){events.erase( std::next(it).base() )};
|
||||
}
|
||||
|
||||
|
||||
// We are not overflowing
|
||||
if(events.size() < eventLimit)
|
||||
return false;
|
||||
@@ -137,6 +252,6 @@ void EventManager::discardOldest(size_t count) {
|
||||
while(it != events.end()) {
|
||||
it = events.erase(it);
|
||||
if(--count == 0)
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
#include "icsneo/api/heartbeat.h"
|
||||
#include "icsneo/api/lifetime.h"
|
||||
#include "icsneo/device/device.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
Heartbeat::Heartbeat(Device& device) :
|
||||
device(device), mode(device.isOnline() ? Mode::Passive : Mode::Active), thread(&Heartbeat::run, this) {
|
||||
}
|
||||
|
||||
Heartbeat::~Heartbeat() {
|
||||
{
|
||||
std::lock_guard lk(mutex);
|
||||
stop = true;
|
||||
}
|
||||
cv.notify_one();
|
||||
thread.join();
|
||||
}
|
||||
|
||||
void Heartbeat::run() {
|
||||
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
|
||||
|
||||
auto filter = std::make_shared<MessageFilter>();
|
||||
filter->includeInternalInAny = true;
|
||||
bool status = false;
|
||||
auto cbHandle = device.com->addMessageCallback(std::make_shared<MessageCallback>(filter, [&](std::shared_ptr<Message> msg) {
|
||||
// TODO: remove DeviceStatus after 2027-08-17, as ResetStatus should be widely supported
|
||||
const bool isHeartbeat =
|
||||
(msg->type == Message::Type::ResetStatus) ||
|
||||
(msg->type == Message::Type::RawMessage && std::static_pointer_cast<RawMessage>(msg)->network == Network::NetID::DeviceStatus);
|
||||
if(!isHeartbeat)
|
||||
return;
|
||||
{
|
||||
std::lock_guard lk(mutex);
|
||||
status = true;
|
||||
}
|
||||
cv.notify_one();
|
||||
}));
|
||||
Lifetime cbLifetime([&] {
|
||||
device.com->removeMessageCallback(cbHandle);
|
||||
});
|
||||
while(true) {
|
||||
std::unique_lock lk(mutex);
|
||||
if(mode == Mode::Active) {
|
||||
if(cv.wait_for(lk, std::chrono::milliseconds(100), [&] { return stop; })) {
|
||||
break;
|
||||
}
|
||||
device.com->sendCommand(Command::RequestStatusUpdate);
|
||||
}
|
||||
if(!cv.wait_for(lk, std::chrono::seconds(2), [&] { return status || stop; })) {
|
||||
// we disconnect instead of close because it indicates to the user that a cleanup is still required (our thread join)
|
||||
device.report(APIEvent::Type::DeviceDisconnected, APIEvent::Severity::Error);
|
||||
device.com->driver->setIsDisconnected(true);
|
||||
break;
|
||||
}
|
||||
if(stop)
|
||||
break;
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
+47
-47
@@ -1,48 +1,48 @@
|
||||
#include "icsneo/icsneocpp.h"
|
||||
#include "icsneo/device/devicefinder.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
std::vector<std::shared_ptr<Device>> icsneo::FindAllDevices() {
|
||||
return DeviceFinder::FindAll();
|
||||
}
|
||||
|
||||
std::vector<DeviceType> icsneo::GetSupportedDevices() {
|
||||
return DeviceFinder::GetSupportedDevices();
|
||||
}
|
||||
|
||||
size_t icsneo::EventCount(EventFilter filter) {
|
||||
return EventManager::GetInstance().eventCount(filter);
|
||||
}
|
||||
|
||||
std::vector<APIEvent> icsneo::GetEvents(EventFilter filter, size_t max) {
|
||||
return EventManager::GetInstance().get(filter, max);
|
||||
}
|
||||
|
||||
std::vector<APIEvent> icsneo::GetEvents(size_t max, EventFilter filter) {
|
||||
return EventManager::GetInstance().get(max, filter);
|
||||
}
|
||||
|
||||
void icsneo::GetEvents(std::vector<APIEvent>& events, EventFilter filter, size_t max) {
|
||||
EventManager::GetInstance().get(events, filter, max);
|
||||
}
|
||||
|
||||
void icsneo::GetEvents(std::vector<APIEvent>& events, size_t max, EventFilter filter) {
|
||||
EventManager::GetInstance().get(events, max, filter);
|
||||
}
|
||||
|
||||
APIEvent icsneo::GetLastError() {
|
||||
return EventManager::GetInstance().getLastError();
|
||||
}
|
||||
|
||||
void icsneo::DiscardEvents(EventFilter filter) {
|
||||
EventManager::GetInstance().discard(filter);
|
||||
}
|
||||
|
||||
void icsneo::SetEventLimit(size_t newLimit) {
|
||||
EventManager::GetInstance().setEventLimit(newLimit);
|
||||
}
|
||||
|
||||
size_t icsneo::GetEventLimit() {
|
||||
return EventManager::GetInstance().getEventLimit();
|
||||
#include "icsneo/icsneocpp.h"
|
||||
#include "icsneo/device/devicefinder.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
std::vector<std::shared_ptr<Device>> icsneo::FindAllDevices() {
|
||||
return DeviceFinder::FindAll();
|
||||
}
|
||||
|
||||
std::vector<DeviceType> icsneo::GetSupportedDevices() {
|
||||
return DeviceFinder::GetSupportedDevices();
|
||||
}
|
||||
|
||||
size_t icsneo::EventCount(EventFilter filter) {
|
||||
return EventManager::GetInstance().eventCount(filter);
|
||||
}
|
||||
|
||||
std::vector<APIEvent> icsneo::GetEvents(EventFilter filter, size_t max) {
|
||||
return EventManager::GetInstance().get(filter, max);
|
||||
}
|
||||
|
||||
std::vector<APIEvent> icsneo::GetEvents(size_t max, EventFilter filter) {
|
||||
return EventManager::GetInstance().get(max, filter);
|
||||
}
|
||||
|
||||
void icsneo::GetEvents(std::vector<APIEvent>& events, EventFilter filter, size_t max) {
|
||||
EventManager::GetInstance().get(events, filter, max);
|
||||
}
|
||||
|
||||
void icsneo::GetEvents(std::vector<APIEvent>& events, size_t max, EventFilter filter) {
|
||||
EventManager::GetInstance().get(events, max, filter);
|
||||
}
|
||||
|
||||
APIEvent icsneo::GetLastError() {
|
||||
return EventManager::GetInstance().getLastError();
|
||||
}
|
||||
|
||||
void icsneo::DiscardEvents(EventFilter filter) {
|
||||
EventManager::GetInstance().discard(filter);
|
||||
}
|
||||
|
||||
void icsneo::SetEventLimit(size_t newLimit) {
|
||||
EventManager::GetInstance().setEventLimit(newLimit);
|
||||
}
|
||||
|
||||
size_t icsneo::GetEventLimit() {
|
||||
return EventManager::GetInstance().getEventLimit();
|
||||
}
|
||||
@@ -3,8 +3,7 @@
|
||||
#include <Tchar.h>
|
||||
|
||||
//Basic Functions
|
||||
FINDNEODEVICES icsneoFindNeoDevices;
|
||||
OPENNEODEVICE icsneoOpenNeoDevice;
|
||||
OPENDEVICE icsneoOpenDevice;
|
||||
CLOSEPORT icsneoClosePort;
|
||||
FREEOBJECT icsneoFreeObject;
|
||||
////OPENPORTEX icsneoOpenPortEx;
|
||||
@@ -45,6 +44,7 @@ SETVCAN412SETTINGS icsneoSetVCAN412Settings;
|
||||
SETBITRATE icsneoSetBitRate;
|
||||
GETDEVICEPARMS icsneoGetDeviceParameters;
|
||||
SETDEVICEPARMS icsneoSetDeviceParameters;
|
||||
ENABLEDOIPACTIVATIONLINE icsneoEnableDOIPLine;
|
||||
|
||||
//Error Functions
|
||||
GETLASTAPIERROR icsneoGetLastAPIError;
|
||||
@@ -81,17 +81,17 @@ SCRIPTWRITEAPPSIGNAL icsneoScriptWriteAppSignal;
|
||||
//SCRIPTWRITETXMESSAGE icsneoScriptWriteTxMessage;
|
||||
|
||||
|
||||
//The following are valid strings for setting parameters on devices
|
||||
//The following are valid strings for setting parameters on devices
|
||||
//using the icsneoGetDeviceParameters() and icsneoSetDeviceParameters() functions
|
||||
char *FireParameters[] =
|
||||
{
|
||||
"can1", "can2", "can3", "can4", "swcan", "lsftcan", "lin1", "lin2",
|
||||
"lin3", "lin4", "cgi_baud", "cgi_tx_ifs_bit_times",
|
||||
"cgi_rx_ifs_bit_times", "cgi_chksum_enable", "network_enables",
|
||||
"network_enabled_on_boot", "pwm_man_timeout", "pwr_man_enable",
|
||||
"misc_io_initial_ddr", "misc_io_initial_latch", "misc_io_analog_enable",
|
||||
"misc_io_report_period", "misc_io_on_report_events", "ain_sample_period",
|
||||
"ain_threshold", "iso15765_separation_time_offset", "iso9141_kwp_settings",
|
||||
"cgi_rx_ifs_bit_times", "cgi_chksum_enable", "network_enables",
|
||||
"network_enabled_on_boot", "pwm_man_timeout", "pwr_man_enable",
|
||||
"misc_io_initial_ddr", "misc_io_initial_latch", "misc_io_analog_enable",
|
||||
"misc_io_report_period", "misc_io_on_report_events", "ain_sample_period",
|
||||
"ain_threshold", "iso15765_separation_time_offset", "iso9141_kwp_settings",
|
||||
"perf_en", "iso_parity", "iso_msg_termination", "network_enables_2"
|
||||
};
|
||||
|
||||
@@ -99,30 +99,30 @@ char *FireParameters[] =
|
||||
char *VCAN3Parameters[] =
|
||||
{
|
||||
"can1", "can2", "network_enables", "network_enabled_on_boot", "iso15765_separation_time_offset",
|
||||
"perf_en", "misc_io_initial_ddr", "misc_io_initial_latch", "misc_io_report_period",
|
||||
"perf_en", "misc_io_initial_ddr", "misc_io_initial_latch", "misc_io_report_period",
|
||||
"misc_io_on_report_events"
|
||||
};
|
||||
|
||||
char *CANParameters[] =
|
||||
char *CANParameters[] =
|
||||
{
|
||||
"Mode", "SetBaudrate", "Baudrate", "NetworkType", "TqSeg1",
|
||||
"TqSeg2", "TqProp", "TqSync", "BRP", "auto_baud"
|
||||
};
|
||||
|
||||
char *SWCANParameters[] =
|
||||
char *SWCANParameters[] =
|
||||
{
|
||||
"Mode", "SetBaudrate", "Baudrate", "NetworkType", "TqSeg1", "TqSeg2",
|
||||
"Mode", "SetBaudrate", "Baudrate", "NetworkType", "TqSeg1", "TqSeg2",
|
||||
"TqProp", "TqSync", "BRP", "high_speed_auto_switch", "auto_baud"
|
||||
};
|
||||
|
||||
char *LINParameters[] =
|
||||
char *LINParameters[] =
|
||||
{
|
||||
"Baudrate", "spbrg", "brgh", "MasterResistor", "Mode"
|
||||
};
|
||||
|
||||
char *ISOKWPParms[] =
|
||||
{
|
||||
"Baudrate", "spbrg", "brgh", "init_steps", "init_step_count",
|
||||
"Baudrate", "spbrg", "brgh", "init_steps", "init_step_count",
|
||||
"p2_500us", "p3_500us", "p4_500us", "chksum_enabled"
|
||||
};
|
||||
|
||||
@@ -132,10 +132,7 @@ bool LoadDLLAPI(HINSTANCE &hAPIDLL)
|
||||
if((hAPIDLL = LoadLibrary(_T("icsneo40.dll"))) == NULL)
|
||||
return false;
|
||||
|
||||
|
||||
|
||||
icsneoFindNeoDevices = (FINDNEODEVICES) GetProcAddress(hAPIDLL, "icsneoFindNeoDevices");
|
||||
icsneoOpenNeoDevice = (OPENNEODEVICE) GetProcAddress(hAPIDLL, "icsneoOpenNeoDevice");
|
||||
icsneoOpenDevice = (OPENDEVICE) GetProcAddress(hAPIDLL, "icsneoOpenDevice");
|
||||
icsneoClosePort = (CLOSEPORT) GetProcAddress(hAPIDLL, "icsneoClosePort");
|
||||
icsneoFreeObject = (FREEOBJECT) GetProcAddress(hAPIDLL, "icsneoFreeObject");
|
||||
//// icsneoOpenPortEx = (OPENPORTEX) GetProcAddress(hAPIDLL, "icsneoOpenPortEx");
|
||||
@@ -201,22 +198,22 @@ bool LoadDLLAPI(HINSTANCE &hAPIDLL)
|
||||
icsneoScriptReadAppSignal = (SCRIPTREADAPPSIGNAL) GetProcAddress(hAPIDLL, "icsneoScriptReadAppSignal");
|
||||
icsneoScriptWriteAppSignal = (SCRIPTWRITEAPPSIGNAL) GetProcAddress(hAPIDLL, "icsneoScriptWriteAppSignal");
|
||||
|
||||
|
||||
icsneoEnableDOIPLine = (ENABLEDOIPACTIVATIONLINE)GetProcAddress(hAPIDLL, "icsneoEnableDOIPLine");
|
||||
|
||||
if(!icsneoFindNeoDevices || !icsneoOpenNeoDevice || !icsneoClosePort || !icsneoFreeObject ||
|
||||
if(!icsneoOpenDevice || !icsneoClosePort || !icsneoFreeObject ||
|
||||
!icsneoTxMessages || !icsneoGetMessages || !icsneoWaitForRxMessagesWithTimeOut ||
|
||||
!icsneoGetTimeStampForMsg || !icsneoEnableNetworkRXQueue || !icsneoGetISO15765Status || !icsneoTxMessagesEx ||
|
||||
!icsneoSetISO15765RxParameters || !icsneoGetConfiguration || !icsneoSendConfiguration ||
|
||||
!icsneoGetFireSettings || !icsneoSetFireSettings || !icsneoGetVCAN3Settings ||
|
||||
!icsneoSetVCAN3Settings || !icsneoGetVCANRFSettings || !icsneoSetVCANRFSettings || !icsneoGetFire2Settings ||
|
||||
!icsneoGetVCAN412Settings || !icsneoSetVCAN412Settings ||
|
||||
!icsneoSetFire2Settings || !icsneoGetRADGalaxySettings || !icsneoSetRADGalaxySettings ||
|
||||
!icsneoSetFire2Settings || !icsneoGetRADGalaxySettings || !icsneoSetRADGalaxySettings ||
|
||||
!icsneoSetBitRate || !icsneoGetDeviceParameters || !icsneoSerialNumberToString ||
|
||||
!icsneoSetDeviceParameters || !icsneoGetLastAPIError || !icsneoGetErrorMessages ||
|
||||
!icsneoGetErrorInfo || !icsneoScriptLoad || !icsneoScriptStart || !icsneoScriptStop ||
|
||||
!icsneoScriptClear || !icsneoScriptStartFBlock || !icsneoScriptStopFBlock ||
|
||||
!icsneoScriptGetFBlockStatus || !icsneoScriptGetScriptStatus || !icsneoScriptReadAppSignal ||
|
||||
!icsneoScriptWriteAppSignal || !icsneoGetDLLVersion)
|
||||
!icsneoScriptWriteAppSignal || !icsneoGetDLLVersion || !icsneoEnableDOIPLine)
|
||||
{
|
||||
FreeLibrary(hAPIDLL);
|
||||
return false;
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
//FILE: icsneo40DLLAPI.H
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
#include "icsneo/icsnVC40.h"
|
||||
|
||||
// Vehicle Spy 3.26.3.9 removed these legacy settings structure definitions from
|
||||
// icsnVC40.h. The corresponding functions only ever treat them as opaque
|
||||
// buffers, so forward declarations keep the existing API/ABI intact.
|
||||
typedef struct _SFireSettings SFireSettings;
|
||||
typedef struct _SVCAN3Settings SVCAN3Settings;
|
||||
typedef struct _SVCANRFSettings SVCANRFSettings;
|
||||
|
||||
|
||||
|
||||
bool LoadDLLAPI(HINSTANCE &hAPIDLL);
|
||||
@@ -11,23 +20,24 @@ void UnloadDLLAPI(HINSTANCE &hAPIDLL);
|
||||
//Basic Functions
|
||||
typedef int (__stdcall *FINDNEODEVICES)(unsigned long DeviceTypes, NeoDevice *pNeoDevice, int *pNumDevices);
|
||||
typedef int (__stdcall *OPENNEODEVICE)(NeoDevice *pNeoDevice, void * hObject, unsigned char *bNetworkIDs, int bConfigRead, int bSyncToPC);
|
||||
typedef int (__stdcall *CLOSEPORT)(void * hObject, int *pNumberOfErrors);
|
||||
typedef int (__stdcall *OPENDEVICE)(NeoDeviceEx* pNeoDeviceEx, void** hObject, unsigned char* bNetworkIDs, int bConfigRead, int iOptions, OptionsOpenNeoEx* stOptionsOpenNeoEx, unsigned long reserved);
|
||||
typedef int (__stdcall *CLOSEPORT)(void * hObject, int *pNumberOfErrors);
|
||||
typedef void (__stdcall *FREEOBJECT)(void * hObject);
|
||||
typedef int (__stdcall *OPENPORTEX)(void * lPortNumber, int lPortType, int lDriverType, int lIPAddressMSB, int lIPAddressLSBOrBaudRate,
|
||||
typedef int (__stdcall *OPENPORTEX)(void * lPortNumber, int lPortType, int lDriverType, int lIPAddressMSB, int lIPAddressLSBOrBaudRate,
|
||||
int bConfigRead, unsigned char *bNetworkID, int * hObject);
|
||||
typedef int (__stdcall *SERIALNUMBERTOSTRING) (unsigned long serial, char *data,unsigned long data_size);
|
||||
|
||||
//Message Functions
|
||||
typedef int (__stdcall *GETMESSAGES)(void * hObject, icsSpyMessage *pMsg, int * pNumberOfMessages, int * pNumberOfErrors);
|
||||
typedef int (__stdcall *TXMESSAGES)(void * hObject, icsSpyMessage *pMsg, int lNetworkID, int lNumMessages);
|
||||
typedef int (__stdcall *GETMESSAGES)(void * hObject, icsSpyMessage *pMsg, int * pNumberOfMessages, int * pNumberOfErrors);
|
||||
typedef int (__stdcall *TXMESSAGES)(void * hObject, icsSpyMessage *pMsg, int lNetworkID, int lNumMessages);
|
||||
typedef int (__stdcall *TXMESSAGESEX)(void * hObject,icsSpyMessage *pMsg, unsigned int lNetworkID,unsigned int lNumMessages,unsigned int *NumTxed, unsigned int zero2);
|
||||
typedef int (__stdcall *WAITFORRXMSGS)(void * hObject, unsigned int iTimeOut);
|
||||
typedef int (__stdcall *ENABLERXQUEUE)(void * hObject, int iEnable);
|
||||
typedef int (__stdcall *GETTSFORMSG)(void * hObject, icsSpyMessage *pMsg, double *pTimeStamp);
|
||||
typedef void (__stdcall *GETISO15765STATUS)(void * hObject, int lNetwork, int lClearTxStatus,
|
||||
typedef void (__stdcall *GETISO15765STATUS)(void * hObject, int lNetwork, int lClearTxStatus,
|
||||
int lClearRxStatus, int *lTxStatus, int *lRxStatus);
|
||||
typedef void (__stdcall *SETISO15765RXPARMS)(void * hObject, int lNetwork, int lEnable,
|
||||
spyFilterLong *pFF_CFMsgFilter, icsSpyMessage *pTxMsg,
|
||||
typedef void (__stdcall *SETISO15765RXPARMS)(void * hObject, int lNetwork, int lEnable,
|
||||
spyFilterLong *pFF_CFMsgFilter, icsSpyMessage *pTxMsg,
|
||||
int lCFTimeOutMs, int lFlowCBlockSize,
|
||||
int lUsesExtendedAddressing, int lUseHardwareIfPresent);
|
||||
typedef int (__stdcall *DOWNLOADISO15765_2_TXSCRIPT)(void * hObject, unsigned int NetworkID);
|
||||
@@ -36,7 +46,7 @@ typedef int (__stdcall *TXISO15765_2_MESSAGE)(void * hObject, stCM_ISO157652_TxM
|
||||
|
||||
//Device Functions
|
||||
typedef int (__stdcall *GETCONFIG)(void * hObject, unsigned char * pData, int * lNumBytes);
|
||||
typedef int (__stdcall *SENDCONFIG)(void * hObject, unsigned char * pData, int lNumBytes);
|
||||
typedef int (__stdcall *SENDCONFIG)(void * hObject, unsigned char * pData, int lNumBytes);
|
||||
typedef int (__stdcall *GETFIRESETTINGS)(void * hObject, SFireSettings *pSettings, int iNumBytes);
|
||||
typedef int (__stdcall *SETFIRESETTINGS)(void * hObject, SFireSettings *pSettings, int iNumBytes, int bSaveToEEPROM);
|
||||
|
||||
@@ -62,11 +72,12 @@ typedef int (__stdcall *SETRADSTAR2SETTINGS)(void * hObject, SRADStar2Settings *
|
||||
typedef int (__stdcall *SETBITRATE)(void * hObject, int BitRate, int NetworkID);
|
||||
typedef int (__stdcall *GETDEVICEPARMS)(void * hObject, char *pParameter, char *pValues, short ValuesLength);
|
||||
typedef int (__stdcall *SETDEVICEPARMS)(void * hObject, char *pParmValue, int *pErrorIndex, int bSaveToEEPROM);
|
||||
typedef int(__stdcall *ENABLEDOIPACTIVATIONLINE)(void * hObject, bool Val);
|
||||
|
||||
//Error Functions
|
||||
typedef int (__stdcall *GETLASTAPIERROR)(void * hObject, unsigned long *pErrorNumber);
|
||||
typedef int (__stdcall *GETERRMSGS)(void * hObject, int * pErrorMsgs, int * pNumberOfErrors);
|
||||
typedef int (__stdcall *GETERRORINFO)(int lErrorNumber, TCHAR *szErrorDescriptionShort,
|
||||
typedef int (__stdcall *GETERRORINFO)(int lErrorNumber, TCHAR *szErrorDescriptionShort,
|
||||
TCHAR *szErrorDescriptionLong, int * lMaxLengthShort,
|
||||
int * lMaxLengthLong,int * lErrorSeverity,int * lRestartNeeded);
|
||||
|
||||
@@ -84,8 +95,8 @@ typedef int (__stdcall *STARTSOCKSERVER)(void * hObject, int iPort);
|
||||
typedef int (__stdcall *STOPSOCKSERVER)(void * hObject);
|
||||
|
||||
//CoreMini Script functions
|
||||
typedef int (__stdcall *SCRIPTSTART)(void * hObject, int iLocation);
|
||||
typedef int (__stdcall *SCRIPTSTOP)(void * hObject);
|
||||
typedef int (__stdcall *SCRIPTSTART)(void * hObject, int iLocation);
|
||||
typedef int (__stdcall *SCRIPTSTOP)(void * hObject);
|
||||
typedef int (__stdcall *SCRIPTLOAD)(void * hObject, const unsigned char * bin, unsigned long len_bytes, int iLocation);
|
||||
typedef int (__stdcall *SCRIPTCLEAR)(void * hObject, int iLocation);
|
||||
typedef int (__stdcall *SCRIPTSTARTFBLOCK)(void * hObject,unsigned int fb_index);
|
||||
@@ -99,21 +110,20 @@ typedef int (__stdcall *SCRIPTWRITEISO15765TXMESSAGE)(void * hObject, unsigned
|
||||
|
||||
|
||||
//Deprecated (but still suppored in the DLL)
|
||||
//////typedef int (__stdcall *OPENPORTEX)(int lPortSerialNumber, int lPortType, int lDriverType,
|
||||
////// int lIPAddressMSB, int lIPAddressLSBOrBaudRate,int bConfigRead,
|
||||
//////typedef int (__stdcall *OPENPORTEX)(int lPortSerialNumber, int lPortType, int lDriverType,
|
||||
////// int lIPAddressMSB, int lIPAddressLSBOrBaudRate,int bConfigRead,
|
||||
////// unsigned char * bNetworkID, int * hObject);
|
||||
//////
|
||||
//////typedef int (__stdcall *OPENPORT)(int lPortNumber, int lPortType, int lDriverType,
|
||||
//////typedef int (__stdcall *OPENPORT)(int lPortNumber, int lPortType, int lDriverType,
|
||||
////// unsigned char *bNetworkID, unsigned char *bSCPIDs, int * hObject);
|
||||
//////typedef int (__stdcall *ENABLENETWORKCOM)(void * hObject, int Enable);
|
||||
//////typedef int (__stdcall *FINDCOMDEVICES)(int lDriverType, int lGetSerialNumbers, int lStopAtFirst, int lUSBCommOnly,
|
||||
////// int *p_lDeviceTypes, int *p_lComPorts, int *p_lSerialNumbers, int *lNumDevices);
|
||||
////// int *p_lDeviceTypes, int *p_lComPorts, int *p_lSerialNumbers, int *lNumDevices);
|
||||
|
||||
|
||||
|
||||
//Basic Functions
|
||||
extern FINDNEODEVICES icsneoFindNeoDevices;
|
||||
extern OPENNEODEVICE icsneoOpenNeoDevice;
|
||||
extern OPENDEVICE icsneoOpenDevice;
|
||||
extern CLOSEPORT icsneoClosePort;
|
||||
extern FREEOBJECT icsneoFreeObject;
|
||||
extern SERIALNUMBERTOSTRING icsneoSerialNumberToString;
|
||||
@@ -157,6 +167,7 @@ extern SETVCAN412SETTINGS icsneoSetVCAN412Settings;
|
||||
extern SETBITRATE icsneoSetBitRate;
|
||||
extern GETDEVICEPARMS icsneoGetDeviceParameters;
|
||||
extern SETDEVICEPARMS icsneoSetDeviceParameters;
|
||||
extern ENABLEDOIPACTIVATIONLINE icsneoEnableDOIPLine;
|
||||
|
||||
//Error Functions
|
||||
extern GETLASTAPIERROR icsneoGetLastAPIError;
|
||||
|
||||
+1178
-270
File diff suppressed because it is too large
Load Diff
@@ -14,15 +14,15 @@
|
||||
using namespace icsneo;
|
||||
|
||||
extern "C" {
|
||||
extern int DLLExport icsneoValidateHObject(void* hObject);
|
||||
extern int DLLExport icsneoWaitForRxMessagesWithTimeOut(void* hObject, unsigned int iTimeOut);
|
||||
extern int LegacyDLLExport icsneoValidateHObject(void* hObject);
|
||||
extern int LegacyDLLExport icsneoWaitForRxMessagesWithTimeOut(void* hObject, unsigned int iTimeOut);
|
||||
}
|
||||
|
||||
int icsneoWaitForRxMessagesWithTimeOut(void* hObject, unsigned int iTimeOut) {
|
||||
int LegacyDLLExport icsneoWaitForRxMessagesWithTimeOut(void* hObject, unsigned int iTimeOut) {
|
||||
if(!icsneoValidateHObject(hObject))
|
||||
return false;
|
||||
neodevice_t* device = (neodevice_t*)hObject;
|
||||
if(device->device->getCurrentMessageCount() != 0)
|
||||
return true;
|
||||
return bool(device->device->com->waitForMessageSync(MessageFilter(), std::chrono::milliseconds(iTimeOut)));
|
||||
return bool(device->device->com->waitForMessageSync({}, std::chrono::milliseconds(iTimeOut)));
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
if(LIBICSNEO_ENABLE_BINDINGS_PYTHON)
|
||||
add_subdirectory(python)
|
||||
endif()
|
||||
@@ -0,0 +1,71 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
set(PYBIND11_FINDPYTHON ON)
|
||||
|
||||
if(PYBIND11_ROOT)
|
||||
find_package(pybind11 CONFIG REQUIRED)
|
||||
else()
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
pybind11
|
||||
GIT_REPOSITORY https://github.com/pybind/pybind11.git
|
||||
GIT_TAG v3.0.3
|
||||
)
|
||||
FetchContent_MakeAvailable(pybind11)
|
||||
endif()
|
||||
|
||||
pybind11_add_module(icsneopy
|
||||
icsneopy/api/event.cpp
|
||||
icsneopy/api/eventcallback.cpp
|
||||
icsneopy/api/eventmanager.cpp
|
||||
icsneopy/api/version.cpp
|
||||
icsneopy/device/devicetype.cpp
|
||||
icsneopy/communication/network.cpp
|
||||
icsneopy/communication/io.cpp
|
||||
icsneopy/communication/livedata.cpp
|
||||
icsneopy/communication/message/message.cpp
|
||||
icsneopy/communication/message/canmessage.cpp
|
||||
icsneopy/communication/message/canerrormessage.cpp
|
||||
icsneopy/communication/message/ethernetmessage.cpp
|
||||
icsneopy/communication/message/linmessage.cpp
|
||||
icsneopy/communication/message/tc10statusmessage.cpp
|
||||
icsneopy/communication/message/mdiomessage.cpp
|
||||
icsneopy/communication/message/gptpstatusmessage.cpp
|
||||
icsneopy/communication/message/allmacaddressesmessage.cpp
|
||||
icsneopy/communication/message/apperrormessage.cpp
|
||||
icsneopy/communication/message/ethernetstatusmessage.cpp
|
||||
icsneopy/communication/message/spimessage.cpp
|
||||
icsneopy/communication/message/scriptstatusmessage.cpp
|
||||
icsneopy/communication/message/ethphymessage.cpp
|
||||
icsneopy/communication/message/livedatamessage.cpp
|
||||
icsneopy/communication/message/callback/messagecallback.cpp
|
||||
icsneopy/communication/message/filter/messagefilter.cpp
|
||||
icsneopy/core/macseccfg.cpp
|
||||
icsneopy/flexray/flexray.cpp
|
||||
icsneopy/disk/diskdriver.cpp
|
||||
icsneopy/disk/diskdetails.cpp
|
||||
icsneopy/device/chipid.cpp
|
||||
icsneopy/device/versionreport.cpp
|
||||
icsneopy/device/device.cpp
|
||||
icsneopy/device/extensions/deviceextension.cpp
|
||||
icsneopy/device/idevicesettings.cpp
|
||||
icsneopy/icsneocpp.cpp
|
||||
)
|
||||
target_link_libraries(icsneopy PRIVATE icsneocpp)
|
||||
|
||||
install(TARGETS icsneopy LIBRARY DESTINATION icsneopy)
|
||||
|
||||
find_program(STUBGEN_EXE stubgen)
|
||||
if(STUBGEN_EXE)
|
||||
# Multi-config generators put the extension in Release/ or Debug/. Import
|
||||
# that freshly built module, not a globally installed older icsneopy.
|
||||
add_custom_command(TARGET icsneopy POST_BUILD
|
||||
COMMAND "${CMAKE_COMMAND}" -E rm -f "${CMAKE_CURRENT_BINARY_DIR}/icsneopy.pyi"
|
||||
COMMAND "${STUBGEN_EXE}" -v -p icsneopy -o "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
WORKING_DIRECTORY "$<TARGET_FILE_DIR:icsneopy>"
|
||||
VERBATIM
|
||||
)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/icsneopy.pyi py.typed DESTINATION icsneopy)
|
||||
endif()
|
||||
|
||||
install(FILES __init__.py DESTINATION icsneopy)
|
||||
@@ -0,0 +1 @@
|
||||
from .icsneopy import *
|
||||
@@ -0,0 +1,164 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
#include <pybind11/native_enum.h>
|
||||
|
||||
#include "icsneo/api/event.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_event(pybind11::module_& m) {
|
||||
pybind11::classh<APIEvent> apiEvent(m, "APIEvent");
|
||||
pybind11::native_enum<APIEvent::Type>(apiEvent, "Type", "enum.IntEnum")
|
||||
.value("Any", APIEvent::Type::Any)
|
||||
.value("InvalidNeoDevice", APIEvent::Type::InvalidNeoDevice)
|
||||
.value("RequiredParameterNull", APIEvent::Type::RequiredParameterNull)
|
||||
.value("BufferInsufficient", APIEvent::Type::BufferInsufficient)
|
||||
.value("OutputTruncated", APIEvent::Type::OutputTruncated)
|
||||
.value("ParameterOutOfRange", APIEvent::Type::ParameterOutOfRange)
|
||||
.value("DeviceCurrentlyOpen", APIEvent::Type::DeviceCurrentlyOpen)
|
||||
.value("DeviceCurrentlyClosed", APIEvent::Type::DeviceCurrentlyClosed)
|
||||
.value("DeviceCurrentlyOnline", APIEvent::Type::DeviceCurrentlyOnline)
|
||||
.value("DeviceCurrentlyOffline", APIEvent::Type::DeviceCurrentlyOffline)
|
||||
.value("DeviceCurrentlyPolling", APIEvent::Type::DeviceCurrentlyPolling)
|
||||
.value("DeviceNotCurrentlyPolling", APIEvent::Type::DeviceNotCurrentlyPolling)
|
||||
.value("UnsupportedTXNetwork", APIEvent::Type::UnsupportedTXNetwork)
|
||||
.value("MessageMaxLengthExceeded", APIEvent::Type::MessageMaxLengthExceeded)
|
||||
.value("ValueNotYetPresent", APIEvent::Type::ValueNotYetPresent)
|
||||
.value("Timeout", APIEvent::Type::Timeout)
|
||||
.value("WiVINotSupported", APIEvent::Type::WiVINotSupported)
|
||||
.value("RestrictedEntryFlag", APIEvent::Type::RestrictedEntryFlag)
|
||||
.value("NotSupported", APIEvent::Type::NotSupported)
|
||||
.value("FixedPointOverflow", APIEvent::Type::FixedPointOverflow)
|
||||
.value("FixedPointPrecision", APIEvent::Type::FixedPointPrecision)
|
||||
.value("SyscallError", APIEvent::Type::SyscallError)
|
||||
.value("PollingMessageOverflow", APIEvent::Type::PollingMessageOverflow)
|
||||
.value("NoSerialNumber", APIEvent::Type::NoSerialNumber)
|
||||
.value("IncorrectSerialNumber", APIEvent::Type::IncorrectSerialNumber)
|
||||
.value("SettingsReadError", APIEvent::Type::SettingsReadError)
|
||||
.value("SettingsVersionError", APIEvent::Type::SettingsVersionError)
|
||||
.value("SettingsLengthError", APIEvent::Type::SettingsLengthError)
|
||||
.value("SettingsChecksumError", APIEvent::Type::SettingsChecksumError)
|
||||
.value("SettingsNotAvailable", APIEvent::Type::SettingsNotAvailable)
|
||||
.value("SettingsReadOnly", APIEvent::Type::SettingsReadOnly)
|
||||
.value("CANSettingsNotAvailable", APIEvent::Type::CANSettingsNotAvailable)
|
||||
.value("CANFDSettingsNotAvailable", APIEvent::Type::CANFDSettingsNotAvailable)
|
||||
.value("LSFTCANSettingsNotAvailable", APIEvent::Type::LSFTCANSettingsNotAvailable)
|
||||
.value("SWCANSettingsNotAvailable", APIEvent::Type::SWCANSettingsNotAvailable)
|
||||
.value("BaudrateNotFound", APIEvent::Type::BaudrateNotFound)
|
||||
.value("UnexpectedNetworkType", APIEvent::Type::UnexpectedNetworkType)
|
||||
.value("DeviceFirmwareOutOfDate", APIEvent::Type::DeviceFirmwareOutOfDate)
|
||||
.value("SettingsStructureMismatch", APIEvent::Type::SettingsStructureMismatch)
|
||||
.value("SettingsStructureTruncated", APIEvent::Type::SettingsStructureTruncated)
|
||||
.value("NoDeviceResponse", APIEvent::Type::NoDeviceResponse)
|
||||
.value("MessageFormattingError", APIEvent::Type::MessageFormattingError)
|
||||
.value("CANFDNotSupported", APIEvent::Type::CANFDNotSupported)
|
||||
.value("RTRNotSupported", APIEvent::Type::RTRNotSupported)
|
||||
.value("DeviceDisconnected", APIEvent::Type::DeviceDisconnected)
|
||||
.value("OnlineNotSupported", APIEvent::Type::OnlineNotSupported)
|
||||
.value("TerminationNotSupportedDevice", APIEvent::Type::TerminationNotSupportedDevice)
|
||||
.value("TerminationNotSupportedNetwork", APIEvent::Type::TerminationNotSupportedNetwork)
|
||||
.value("AnotherInTerminationGroupEnabled", APIEvent::Type::AnotherInTerminationGroupEnabled)
|
||||
.value("NoSerialNumberFW", APIEvent::Type::NoSerialNumberFW)
|
||||
.value("NoSerialNumber12V", APIEvent::Type::NoSerialNumber12V)
|
||||
.value("NoSerialNumberFW12V", APIEvent::Type::NoSerialNumberFW12V)
|
||||
.value("EthPhyRegisterControlNotAvailable", APIEvent::Type::EthPhyRegisterControlNotAvailable)
|
||||
.value("DiskNotSupported", APIEvent::Type::DiskNotSupported)
|
||||
.value("EOFReached", APIEvent::Type::EOFReached)
|
||||
.value("SettingsDefaultsUsed", APIEvent::Type::SettingsDefaultsUsed)
|
||||
.value("AtomicOperationRetried", APIEvent::Type::AtomicOperationRetried)
|
||||
.value("AtomicOperationCompletedNonatomically", APIEvent::Type::AtomicOperationCompletedNonatomically)
|
||||
.value("WiVIStackRefreshFailed", APIEvent::Type::WiVIStackRefreshFailed)
|
||||
.value("WiVIUploadStackOverflow", APIEvent::Type::WiVIUploadStackOverflow)
|
||||
.value("I2CMessageExceedsMaxLength", APIEvent::Type::I2CMessageExceedsMaxLength)
|
||||
.value("A2BMessageIncompleteFrame", APIEvent::Type::A2BMessageIncompleteFrame)
|
||||
.value("CoreminiUploadVersionMismatch", APIEvent::Type::CoreminiUploadVersionMismatch)
|
||||
.value("DiskNotConnected", APIEvent::Type::DiskNotConnected)
|
||||
.value("UnexpectedResponse", APIEvent::Type::UnexpectedResponse)
|
||||
.value("LiveDataInvalidHandle", APIEvent::Type::LiveDataInvalidHandle)
|
||||
.value("LiveDataInvalidCommand", APIEvent::Type::LiveDataInvalidCommand)
|
||||
.value("LiveDataInvalidArgument", APIEvent::Type::LiveDataInvalidArgument)
|
||||
.value("LiveDataVersionMismatch", APIEvent::Type::LiveDataVersionMismatch)
|
||||
.value("LiveDataNoDeviceResponse", APIEvent::Type::LiveDataNoDeviceResponse)
|
||||
.value("LiveDataMaxSignalsReached", APIEvent::Type::LiveDataMaxSignalsReached)
|
||||
.value("LiveDataCommandFailed", APIEvent::Type::LiveDataCommandFailed)
|
||||
.value("LiveDataEncoderError", APIEvent::Type::LiveDataEncoderError)
|
||||
.value("LiveDataDecoderError", APIEvent::Type::LiveDataDecoderError)
|
||||
.value("LiveDataNotSupported", APIEvent::Type::LiveDataNotSupported)
|
||||
.value("LINSettingsNotAvailable", APIEvent::Type::LINSettingsNotAvailable)
|
||||
.value("ModeNotFound", APIEvent::Type::ModeNotFound)
|
||||
.value("AppErrorParsingFailed", APIEvent::Type::AppErrorParsingFailed)
|
||||
.value("GPTPNotSupported", APIEvent::Type::GPTPNotSupported)
|
||||
.value("SettingNotAvaiableDevice", APIEvent::Type::SettingNotAvaiableDevice)
|
||||
.value("DiskFormatNotSupported", APIEvent::Type::DiskFormatNotSupported)
|
||||
.value("DiskFormatInvalidCount", APIEvent::Type::DiskFormatInvalidCount)
|
||||
.value("FailedToRead", APIEvent::Type::FailedToRead)
|
||||
.value("FailedToWrite", APIEvent::Type::FailedToWrite)
|
||||
.value("DriverFailedToOpen", APIEvent::Type::DriverFailedToOpen)
|
||||
.value("DriverFailedToClose", APIEvent::Type::DriverFailedToClose)
|
||||
.value("PacketChecksumError", APIEvent::Type::PacketChecksumError)
|
||||
.value("TransmitBufferFull", APIEvent::Type::TransmitBufferFull)
|
||||
.value("DeviceInUse", APIEvent::Type::DeviceInUse)
|
||||
.value("PCAPCouldNotStart", APIEvent::Type::PCAPCouldNotStart)
|
||||
.value("PCAPCouldNotFindDevices", APIEvent::Type::PCAPCouldNotFindDevices)
|
||||
.value("PacketDecodingError", APIEvent::Type::PacketDecodingError)
|
||||
.value("SocketFailedToOpen", APIEvent::Type::SocketFailedToOpen)
|
||||
.value("FailedToBind", APIEvent::Type::FailedToBind)
|
||||
.value("ErrorSettingSocketOption", APIEvent::Type::ErrorSettingSocketOption)
|
||||
.value("GetIfAddrsError", APIEvent::Type::GetIfAddrsError)
|
||||
.value("SendToError", APIEvent::Type::SendToError)
|
||||
.value("MDIOMessageExceedsMaxLength", APIEvent::Type::MDIOMessageExceedsMaxLength)
|
||||
.value("VSABufferCorrupted", APIEvent::Type::VSABufferCorrupted)
|
||||
.value("VSATimestampNotFound", APIEvent::Type::VSATimestampNotFound)
|
||||
.value("VSABufferFormatError", APIEvent::Type::VSABufferFormatError)
|
||||
.value("VSAMaxReadAttemptsReached", APIEvent::Type::VSAMaxReadAttemptsReached)
|
||||
.value("VSAByteParseFailure", APIEvent::Type::VSAByteParseFailure)
|
||||
.value("VSAExtendedMessageError", APIEvent::Type::VSAExtendedMessageError)
|
||||
.value("VSAOtherError", APIEvent::Type::VSAOtherError)
|
||||
.value("ServdBindError", APIEvent::Type::ServdBindError)
|
||||
.value("ServdNonblockError", APIEvent::Type::ServdNonblockError)
|
||||
.value("ServdTransceiveError", APIEvent::Type::ServdTransceiveError)
|
||||
.value("ServdOutdatedError", APIEvent::Type::ServdOutdatedError)
|
||||
.value("ServdInvalidResponseError", APIEvent::Type::ServdInvalidResponseError)
|
||||
.value("ServdLockError", APIEvent::Type::ServdLockError)
|
||||
.value("ServdSendError", APIEvent::Type::ServdSendError)
|
||||
.value("ServdRecvError", APIEvent::Type::ServdRecvError)
|
||||
.value("ServdPollError", APIEvent::Type::ServdPollError)
|
||||
.value("ServdNoDataError", APIEvent::Type::ServdNoDataError)
|
||||
.value("ServdJoinMulticastError", APIEvent::Type::ServdJoinMulticastError)
|
||||
.value("ServdNotReachable", APIEvent::Type::ServdNotReachable)
|
||||
.value("DXXErrorSys", APIEvent::Type::DXXErrorSys)
|
||||
.value("DXXErrorInt", APIEvent::Type::DXXErrorInt)
|
||||
.value("DXXErrorOverflow", APIEvent::Type::DXXErrorOverflow)
|
||||
.value("DXXErrorIO", APIEvent::Type::DXXErrorIO)
|
||||
.value("DXXErrorArg", APIEvent::Type::DXXErrorArg)
|
||||
.value("NoErrorFound", APIEvent::Type::NoErrorFound)
|
||||
.value("TooManyEvents", APIEvent::Type::TooManyEvents)
|
||||
.value("Unknown", APIEvent::Type::Unknown)
|
||||
.finalize();
|
||||
|
||||
pybind11::native_enum<APIEvent::Severity>(apiEvent, "Severity", "enum.IntEnum")
|
||||
.value("Any", APIEvent::Severity::Any)
|
||||
.value("EventInfo", APIEvent::Severity::EventInfo)
|
||||
.value("EventWarning", APIEvent::Severity::EventWarning)
|
||||
.value("Error", APIEvent::Severity::Error)
|
||||
.finalize();
|
||||
|
||||
apiEvent
|
||||
.def("get_type", &APIEvent::getType)
|
||||
.def("get_severity", &APIEvent::getSeverity)
|
||||
.def("get_description", &APIEvent::getDescription)
|
||||
.def("describe", &APIEvent::describe)
|
||||
.def("__repr__", &APIEvent::describe);
|
||||
|
||||
pybind11::classh<EventFilter>(m, "EventFilter")
|
||||
.def(pybind11::init())
|
||||
.def(pybind11::init<APIEvent::Type>())
|
||||
.def(pybind11::init<APIEvent::Severity>())
|
||||
.def_readwrite("type", &EventFilter::type)
|
||||
.def_readwrite("severity", &EventFilter::severity)
|
||||
.def_readwrite("serial", &EventFilter::serial);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/api/eventcallback.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_eventcallback(pybind11::module_& m) {
|
||||
pybind11::classh<EventCallback>(m, "EventCallback")
|
||||
.def(pybind11::init<EventCallback::fn_eventCallback, EventFilter>())
|
||||
.def(pybind11::init<EventCallback::fn_eventCallback>());
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_eventmanager(pybind11::module_& m) {
|
||||
pybind11::classh<EventManager>(m, "EventManager")
|
||||
.def_static("get_instance", &EventManager::GetInstance, pybind11::return_value_policy::reference)
|
||||
.def("add_event_callback", &EventManager::addEventCallback)
|
||||
.def("remove_event_callback", &EventManager::removeEventCallback)
|
||||
.def("get_last_error", &EventManager::getLastError);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/api/version.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_version(pybind11::module_& m) {
|
||||
pybind11::classh<neoversion_t>(m, "NeoVersion")
|
||||
.def_readonly("major", &neoversion_t::major)
|
||||
.def_readonly("minor", &neoversion_t::minor)
|
||||
.def_readonly("patch", &neoversion_t::patch)
|
||||
.def_readonly("metadata", &neoversion_t::metadata)
|
||||
.def_readonly("buildBranch", &neoversion_t::buildBranch)
|
||||
.def_readonly("buildTag", &neoversion_t::buildTag)
|
||||
.def("__repr__", [](const neoversion_t& self) -> std::string {
|
||||
std::stringstream ss;
|
||||
ss << self;
|
||||
return ss.str();
|
||||
});
|
||||
m.def("get_version", &GetVersion);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/communication/io.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_io(pybind11::module_& m) {
|
||||
pybind11::enum_<IO>(m, "IO")
|
||||
.value("EthernetActivation", IO::EthernetActivation)
|
||||
.value("USBHostPower", IO::USBHostPower)
|
||||
.value("BackupPowerEnabled", IO::BackupPowerEnabled)
|
||||
.value("BackupPowerGood", IO::BackupPowerGood)
|
||||
.value("Misc", IO::Misc)
|
||||
.value("EMisc", IO::EMisc);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
@@ -0,0 +1,79 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
#include <pybind11/native_enum.h>
|
||||
|
||||
#include "icsneo/communication/livedata.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_livedata(pybind11::module_& m) {
|
||||
// LiveDataValue struct
|
||||
pybind11::classh<LiveDataValue>(m, "LiveDataValue")
|
||||
.def(pybind11::init<>())
|
||||
.def_readwrite("value", &LiveDataValue::value);
|
||||
|
||||
// LiveDataArgument struct
|
||||
pybind11::classh<LiveDataArgument>(m, "LiveDataArgument")
|
||||
.def(pybind11::init<>())
|
||||
.def_readwrite("object_type", &LiveDataArgument::objectType)
|
||||
.def_readwrite("object_index", &LiveDataArgument::objectIndex)
|
||||
.def_readwrite("signal_index", &LiveDataArgument::signalIndex)
|
||||
.def_readwrite("value_type", &LiveDataArgument::valueType);
|
||||
|
||||
// LiveDataCommand enum
|
||||
pybind11::native_enum<LiveDataCommand>(m, "LiveDataCommand", "enum.IntEnum")
|
||||
.value("STATUS", LiveDataCommand::STATUS)
|
||||
.value("SUBSCRIBE", LiveDataCommand::SUBSCRIBE)
|
||||
.value("UNSUBSCRIBE", LiveDataCommand::UNSUBSCRIBE)
|
||||
.value("RESPONSE", LiveDataCommand::RESPONSE)
|
||||
.value("CLEAR_ALL", LiveDataCommand::CLEAR_ALL)
|
||||
.value("SET_VALUE", LiveDataCommand::SET_VALUE)
|
||||
.finalize();
|
||||
|
||||
// LiveDataStatus enum
|
||||
pybind11::native_enum<LiveDataStatus>(m, "LiveDataStatus", "enum.IntEnum")
|
||||
.value("SUCCESS", LiveDataStatus::SUCCESS)
|
||||
.value("ERR_UNKNOWN_COMMAND", LiveDataStatus::ERR_UNKNOWN_COMMAND)
|
||||
.value("ERR_HANDLE", LiveDataStatus::ERR_HANDLE)
|
||||
.value("ERR_DUPLICATE", LiveDataStatus::ERR_DUPLICATE)
|
||||
.value("ERR_FULL", LiveDataStatus::ERR_FULL)
|
||||
.finalize();
|
||||
|
||||
// LiveDataObjectType enum
|
||||
pybind11::enum_<LiveDataObjectType>(m, "LiveDataObjectType")
|
||||
.value("MISC", LiveDataObjectType::MISC)
|
||||
.value("SNA", LiveDataObjectType::SNA)
|
||||
.export_values();
|
||||
|
||||
// LiveDataValueType enum
|
||||
pybind11::native_enum<LiveDataValueType>(m, "LiveDataValueType", "enum.IntEnum")
|
||||
.value("GPS_LATITUDE", LiveDataValueType::GPS_LATITUDE)
|
||||
.value("GPS_LONGITUDE", LiveDataValueType::GPS_LONGITUDE)
|
||||
.value("GPS_ALTITUDE", LiveDataValueType::GPS_ALTITUDE)
|
||||
.value("GPS_SPEED", LiveDataValueType::GPS_SPEED)
|
||||
.value("GPS_VALID", LiveDataValueType::GPS_VALID)
|
||||
.value("GPS_ENABLE", LiveDataValueType::GPS_ENABLE)
|
||||
.value("MANUAL_TRIGGER", LiveDataValueType::MANUAL_TRIGGER)
|
||||
.value("TIME_SINCE_MSG", LiveDataValueType::TIME_SINCE_MSG)
|
||||
.value("GPS_ACCURACY", LiveDataValueType::GPS_ACCURACY)
|
||||
.value("GPS_BEARING", LiveDataValueType::GPS_BEARING)
|
||||
.value("GPS_TIME", LiveDataValueType::GPS_TIME)
|
||||
.value("GPS_TIME_VALID", LiveDataValueType::GPS_TIME_VALID)
|
||||
.value("DAQ_ENABLE", LiveDataValueType::DAQ_ENABLE)
|
||||
.finalize();
|
||||
|
||||
// LiveDataUtil namespace functions
|
||||
m.def("get_new_handle", &LiveDataUtil::getNewHandle,
|
||||
"Generate a new unique LiveData handle");
|
||||
|
||||
m.def("livedata_value_to_double", &LiveDataUtil::liveDataValueToDouble,
|
||||
pybind11::arg("val"),
|
||||
"Convert LiveDataValue to double (32.32 fixed-point to floating-point)");
|
||||
|
||||
m.def("livedata_double_to_value", &LiveDataUtil::liveDataDoubleToValue,
|
||||
pybind11::arg("d"),
|
||||
"Convert double to LiveDataValue (32.32 fixed-point format). Returns LiveDataValue or None on failure.");
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
@@ -0,0 +1,13 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
|
||||
#include "icsneo/communication/message/allmacaddressesmessage.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_allmacaddressesmessage(pybind11::module_& m) {
|
||||
pybind11::classh<AllMACAddressesMessage, Message>(m, "AllMACAddressesMessage")
|
||||
.def_readonly("addresses", &AllMACAddressesMessage::addresses);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
@@ -0,0 +1,71 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/native_enum.h>
|
||||
|
||||
#include "icsneo/communication/message/apperrormessage.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_errortypes(pybind11::module_& m) {
|
||||
pybind11::native_enum<AppErrorType>(m, "AppErrorType", "enum.IntEnum")
|
||||
.value("RxMessagesFull", AppErrorType::AppErrorRxMessagesFull)
|
||||
.value("TxMessagesFull", AppErrorType::AppErrorTxMessagesFull)
|
||||
.value("TxReportMessagesFull", AppErrorType::AppErrorTxReportMessagesFull)
|
||||
.value("BadCommWithDspIC", AppErrorType::AppErrorBadCommWithDspIC)
|
||||
.value("DriverOverflow", AppErrorType::AppErrorDriverOverflow)
|
||||
.value("PCBuffOverflow", AppErrorType::AppErrorPCBuffOverflow)
|
||||
.value("PCChksumError", AppErrorType::AppErrorPCChksumError)
|
||||
.value("PCMissedByte", AppErrorType::AppErrorPCMissedByte)
|
||||
.value("PCOverrunError", AppErrorType::AppErrorPCOverrunError)
|
||||
.value("SettingFailure", AppErrorType::AppErrorSettingFailure)
|
||||
.value("TooManySelectedNetworks", AppErrorType::AppErrorTooManySelectedNetworks)
|
||||
.value("NetworkNotEnabled", AppErrorType::AppErrorNetworkNotEnabled)
|
||||
.value("RtcNotCorrect", AppErrorType::AppErrorRtcNotCorrect)
|
||||
.value("LoadedDefaultSettings", AppErrorType::AppErrorLoadedDefaultSettings)
|
||||
.value("FeatureNotUnlocked", AppErrorType::AppErrorFeatureNotUnlocked)
|
||||
.value("FeatureRtcCmdDropped", AppErrorType::AppErrorFeatureRtcCmdDropped)
|
||||
.value("TxMessagesFlushed", AppErrorType::AppErrorTxMessagesFlushed)
|
||||
.value("TxMessagesHalfFull", AppErrorType::AppErrorTxMessagesHalfFull)
|
||||
.value("NetworkNotValid", AppErrorType::AppErrorNetworkNotValid)
|
||||
.value("TxInterfaceNotImplemented", AppErrorType::AppErrorTxInterfaceNotImplemented)
|
||||
.value("TxMessagesCommEnableIsOff", AppErrorType::AppErrorTxMessagesCommEnableIsOff)
|
||||
.value("RxFilterMatchCountExceeded", AppErrorType::AppErrorRxFilterMatchCountExceeded)
|
||||
.value("EthPreemptionNotEnabled", AppErrorType::AppErrorEthPreemptionNotEnabled)
|
||||
.value("TxNotSupportedInMode", AppErrorType::AppErrorTxNotSupportedInMode)
|
||||
.value("JumboFramesNotSupported", AppErrorType::AppErrorJumboFramesNotSupported)
|
||||
.value("EthernetIpFragment", AppErrorType::AppErrorEthernetIpFragment)
|
||||
.value("TxMessagesUnderrun", AppErrorType::AppErrorTxMessagesUnderrun)
|
||||
.value("DeviceFanFailure", AppErrorType::AppErrorDeviceFanFailure)
|
||||
.value("DeviceOvertemperature", AppErrorType::AppErrorDeviceOvertemperature)
|
||||
.value("TxMessageIndexOutOfRange", AppErrorType::AppErrorTxMessageIndexOutOfRange)
|
||||
.value("UndersizedFrameDropped", AppErrorType::AppErrorUndersizedFrameDropped)
|
||||
.value("OversizedFrameDropped", AppErrorType::AppErrorOversizedFrameDropped)
|
||||
.value("WatchdogEvent", AppErrorType::AppErrorWatchdogEvent)
|
||||
.value("SystemClockFailure", AppErrorType::AppErrorSystemClockFailure)
|
||||
.value("SystemClockRecovered", AppErrorType::AppErrorSystemClockRecovered)
|
||||
.value("SystemPeripheralReset", AppErrorType::AppErrorSystemPeripheralReset)
|
||||
.value("SystemCommunicationFailure", AppErrorType::AppErrorSystemCommunicationFailure)
|
||||
.value("TxMessagesUnsupportedSourceOrPacketId", AppErrorType::AppErrorTxMessagesUnsupportedSourceOrPacketId)
|
||||
.value("WbmsManagerConnectFailed", AppErrorType::AppErrorWbmsManagerConnectFailed)
|
||||
.value("WbmsManagerConnectBadState", AppErrorType::AppErrorWbmsManagerConnectBadState)
|
||||
.value("WbmsManagerConnectTimeout", AppErrorType::AppErrorWbmsManagerConnectTimeout)
|
||||
.value("FailedToInitializeLoggerDisk", AppErrorType::AppErrorFailedToInitializeLoggerDisk)
|
||||
.value("InvalidSetting", AppErrorType::AppErrorInvalidSetting)
|
||||
.value("SystemFailureRequestedReset", AppErrorType::AppErrorSystemFailureRequestedReset)
|
||||
.value("PortKeyMistmatch", AppErrorType::AppErrorPortKeyMistmatch)
|
||||
.value("BusFailure", AppErrorType::AppErrorBusFailure)
|
||||
.value("TapOverflow", AppErrorType::AppErrorTapOverflow)
|
||||
.value("EthTxNoLink", AppErrorType::AppErrorEthTxNoLink)
|
||||
.value("ErrorBufferOverflow", AppErrorType::AppErrorErrorBufferOverflow)
|
||||
.value("NoError", AppErrorType::AppNoError)
|
||||
.finalize();
|
||||
}
|
||||
|
||||
void init_apperrormessage(pybind11::module_& m) {
|
||||
init_errortypes(m);
|
||||
pybind11::classh<AppErrorMessage, Message>(m, "AppErrorMessage")
|
||||
.def("get_app_error_type", &AppErrorMessage::getAppErrorType)
|
||||
.def("get_app_error_string", &AppErrorMessage::getAppErrorString);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
@@ -0,0 +1,15 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/communication/message/callback/messagecallback.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_messagecallback(pybind11::module_& m) {
|
||||
pybind11::classh<MessageCallback>(m, "MessageCallback")
|
||||
.def(pybind11::init<MessageCallback::fn_messageCallback, std::shared_ptr<MessageFilter>>());
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
#include <pybind11/native_enum.h>
|
||||
|
||||
#include "icsneo/communication/message/canerrormessage.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_errorcodes(pybind11::module_& m) {
|
||||
pybind11::native_enum<CANErrorCode>(m, "CANErrorCode", "enum.IntEnum")
|
||||
.value("NoError", CANErrorCode::NoError)
|
||||
.value("StuffError", CANErrorCode::StuffError)
|
||||
.value("FormError", CANErrorCode::FormError)
|
||||
.value("AckError", CANErrorCode::AckError)
|
||||
.value("Bit1Error", CANErrorCode::Bit1Error)
|
||||
.value("Bit0Error", CANErrorCode::Bit0Error)
|
||||
.value("CRCError", CANErrorCode::CRCError)
|
||||
.value("NoChange", CANErrorCode::NoChange)
|
||||
.finalize();
|
||||
}
|
||||
|
||||
void init_canerrormessage(pybind11::module_& m) {
|
||||
init_errorcodes(m);
|
||||
pybind11::classh<CANErrorMessage, Message>(m, "CANErrorMessage")
|
||||
.def_readonly("network", &CANErrorMessage::network)
|
||||
.def_readonly("transmitErrorCount", &CANErrorMessage::transmitErrorCount)
|
||||
.def_readonly("receiveErrorCount", &CANErrorMessage::receiveErrorCount)
|
||||
.def_readonly("busOff", &CANErrorMessage::busOff)
|
||||
.def_readonly("errorPassive", &CANErrorMessage::errorPassive)
|
||||
.def_readonly("errorWarn", &CANErrorMessage::errorWarn)
|
||||
.def_readonly("dataErrorCode", &CANErrorMessage::dataErrorCode)
|
||||
.def_readonly("errorCode", &CANErrorMessage::errorCode);
|
||||
|
||||
|
||||
m.attr("CANErrorCountMessage") = m.attr("CANErrorMessage");
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/communication/message/canmessage.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_canmessage(pybind11::module_& m) {
|
||||
pybind11::classh<CANMessage, Frame>(m, "CANMessage")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("arbid", &CANMessage::arbid)
|
||||
.def_readwrite("dlcOnWire", &CANMessage::dlcOnWire)
|
||||
.def_readwrite("isRemote", &CANMessage::isRemote)
|
||||
.def_readwrite("isExtended", &CANMessage::isExtended)
|
||||
.def_readwrite("isCANFD", &CANMessage::isCANFD)
|
||||
.def_readwrite("baudrateSwitch", &CANMessage::baudrateSwitch)
|
||||
.def_readwrite("errorStateIndicator", &CANMessage::errorStateIndicator)
|
||||
.def_readwrite("txAborted", &CANMessage::txAborted)
|
||||
.def_readwrite("txLostArb", &CANMessage::txLostArb)
|
||||
.def_readwrite("txError", &CANMessage::txError);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/communication/message/ethernetmessage.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_ethernetmessage(pybind11::module_& m) {
|
||||
pybind11::classh<EthernetMessage::T1S>(m, "EthernetMessageT1S")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("isSymbol", &EthernetMessage::T1S::isSymbol)
|
||||
.def_readwrite("isBurst", &EthernetMessage::T1S::isBurst)
|
||||
.def_readwrite("txCollision", &EthernetMessage::T1S::txCollision)
|
||||
.def_readwrite("isWake", &EthernetMessage::T1S::isWake)
|
||||
.def_readwrite("nodeId", &EthernetMessage::T1S::nodeId)
|
||||
.def_readwrite("burstCount", &EthernetMessage::T1S::burstCount)
|
||||
.def_readwrite("symbolType", &EthernetMessage::T1S::symbolType);
|
||||
|
||||
pybind11::classh<EthernetMessage, Frame>(m, "EthernetMessage")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("fcs", &EthernetMessage::fcs)
|
||||
.def_readwrite("frameTooShort", &EthernetMessage::frameTooShort)
|
||||
.def_readwrite("noPadding", &EthernetMessage::noPadding)
|
||||
.def_readwrite("fcsVerified", &EthernetMessage::fcsVerified)
|
||||
.def_readwrite("txAborted", &EthernetMessage::txAborted)
|
||||
.def_readwrite("crcError", &EthernetMessage::crcError)
|
||||
.def_readwrite("t1s", &EthernetMessage::t1s)
|
||||
.def_readwrite("preemptionFlags", &EthernetMessage::preemptionFlags)
|
||||
.def("get_destination_mac", &EthernetMessage::getDestinationMAC)
|
||||
.def("get_source_mac", &EthernetMessage::getSourceMAC)
|
||||
.def("get_ether_type", &EthernetMessage::getEtherType);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
@@ -0,0 +1,36 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/communication/message/ethernetstatusmessage.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_ethernetstatusmessage(pybind11::module_& m) {
|
||||
pybind11::classh<EthernetStatusMessage, RawMessage> ethernetStatusMessage(m, "EthernetStatusMessage");
|
||||
|
||||
pybind11::enum_<EthernetStatusMessage::LinkSpeed>(ethernetStatusMessage, "LinkSpeed")
|
||||
.value("LinkSpeedAuto", EthernetStatusMessage::LinkSpeed::LinkSpeedAuto)
|
||||
.value("LinkSpeed10", EthernetStatusMessage::LinkSpeed::LinkSpeed10)
|
||||
.value("LinkSpeed100", EthernetStatusMessage::LinkSpeed::LinkSpeed100)
|
||||
.value("LinkSpeed1000", EthernetStatusMessage::LinkSpeed::LinkSpeed1000)
|
||||
.value("LinkSpeed2500", EthernetStatusMessage::LinkSpeed::LinkSpeed2500)
|
||||
.value("LinkSpeed5000", EthernetStatusMessage::LinkSpeed::LinkSpeed5000)
|
||||
.value("LinkSpeed10000", EthernetStatusMessage::LinkSpeed::LinkSpeed10000);
|
||||
|
||||
pybind11::enum_<EthernetStatusMessage::LinkMode>(ethernetStatusMessage, "LinkMode")
|
||||
.value("LinkModeAuto", EthernetStatusMessage::LinkMode::LinkModeAuto)
|
||||
.value("LinkModeMaster", EthernetStatusMessage::LinkMode::LinkModeMaster)
|
||||
.value("LinkModeSlave", EthernetStatusMessage::LinkMode::LinkModeSlave)
|
||||
.value("LinkModeInvalid", EthernetStatusMessage::LinkMode::LinkModeInvalid)
|
||||
.value("LinkModeNone", EthernetStatusMessage::LinkMode::LinkModeNone);
|
||||
|
||||
ethernetStatusMessage
|
||||
.def_readonly("network", &EthernetStatusMessage::network)
|
||||
.def_readonly("state", &EthernetStatusMessage::state)
|
||||
.def_readonly("speed", &EthernetStatusMessage::speed)
|
||||
.def_readonly("duplex", &EthernetStatusMessage::duplex)
|
||||
.def_readonly("mode", &EthernetStatusMessage::mode);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
@@ -0,0 +1,34 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/communication/message/ethphymessage.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_ethphymessage(pybind11::module_& m) {
|
||||
pybind11::classh<Clause22Message>(m, "Clause22Message")
|
||||
.def_readwrite("phyAddr", &Clause22Message::phyAddr)
|
||||
.def_readwrite("page", &Clause22Message::page)
|
||||
.def_readwrite("regAddr", &Clause22Message::regAddr)
|
||||
.def_readwrite("regVal", &Clause22Message::regVal);
|
||||
pybind11::classh<Clause45Message>(m, "Clause45Message")
|
||||
.def_readwrite("port", &Clause45Message::port)
|
||||
.def_readwrite("device", &Clause45Message::device)
|
||||
.def_readwrite("regAddr", &Clause45Message::regAddr)
|
||||
.def_readwrite("regVal", &Clause45Message::regVal);
|
||||
pybind11::classh<PhyMessage>(m, "PhyMessage")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("Enabled", &PhyMessage::Enabled)
|
||||
.def_readwrite("WriteEnable", &PhyMessage::WriteEnable)
|
||||
.def_readwrite("Clause45Enable", &PhyMessage::Clause45Enable)
|
||||
.def_readwrite("Version", &PhyMessage::Version)
|
||||
.def_readwrite("BusIndex", &PhyMessage::BusIndex)
|
||||
.def_readwrite("Clause22", &PhyMessage::Clause22)
|
||||
.def_readwrite("Clause45", &PhyMessage::Clause45);
|
||||
pybind11::classh<EthPhyMessage, Message>(m, "EthPhyMessage")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("messages", &EthPhyMessage::messages);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
@@ -0,0 +1,17 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/communication/message/filter/messagefilter.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_messagefilter(pybind11::module_& m) {
|
||||
pybind11::classh<MessageFilter>(m, "MessageFilter")
|
||||
.def(pybind11::init())
|
||||
.def(pybind11::init<Message::Type>())
|
||||
.def(pybind11::init<Network::NetID>());
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/communication/message/gptpstatusmessage.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_gptpstatusmessage(pybind11::module_& m) {
|
||||
pybind11::classh<GPTPStatus, Message> gptpStatus(m, "GPTPStatus");
|
||||
|
||||
pybind11::classh<GPTPStatus::Timestamp>(gptpStatus, "Timestamp")
|
||||
.def_readonly("seconds", &GPTPStatus::Timestamp::seconds)
|
||||
.def_readonly("nanoseconds", &GPTPStatus::Timestamp::nanoseconds)
|
||||
.def("to_seconds", &GPTPStatus::Timestamp::toSeconds, pybind11::call_guard<pybind11::gil_scoped_release>());
|
||||
|
||||
pybind11::classh<GPTPStatus::ScaledNanoSeconds>(gptpStatus, "ScaledNanoSeconds")
|
||||
.def_readonly("nanoseconds_msb", &GPTPStatus::ScaledNanoSeconds::nanosecondsMSB)
|
||||
.def_readonly("nanoseconds_lsb", &GPTPStatus::ScaledNanoSeconds::nanosecondsLSB)
|
||||
.def_readonly("fractional_nanoseconds", &GPTPStatus::ScaledNanoSeconds::fractionalNanoseconds);
|
||||
|
||||
pybind11::classh<GPTPStatus::PortID>(gptpStatus, "PortID")
|
||||
.def_readonly("clock_identity", &GPTPStatus::PortID::clockIdentity)
|
||||
.def_readonly("port_number", &GPTPStatus::PortID::portNumber);
|
||||
|
||||
pybind11::classh<GPTPStatus::ClockQuality>(gptpStatus, "ClockQuality")
|
||||
.def_readonly("clock_class", &GPTPStatus::ClockQuality::clockClass)
|
||||
.def_readonly("clock_accuracy", &GPTPStatus::ClockQuality::clockAccuracy)
|
||||
.def_readonly("offset_scaled_log_variance", &GPTPStatus::ClockQuality::offsetScaledLogVariance);
|
||||
|
||||
pybind11::classh<GPTPStatus::SystemID>(gptpStatus, "SystemID")
|
||||
.def_readonly("priority1", &GPTPStatus::SystemID::priority1)
|
||||
.def_readonly("clock_quality", &GPTPStatus::SystemID::clockQuality)
|
||||
.def_readonly("priority2", &GPTPStatus::SystemID::priority2)
|
||||
.def_readonly("clock_id", &GPTPStatus::SystemID::clockID);
|
||||
|
||||
pybind11::classh<GPTPStatus::PriorityVector>(gptpStatus, "PriorityVector")
|
||||
.def_readonly("sys_id", &GPTPStatus::PriorityVector::sysID)
|
||||
.def_readonly("steps_removed", &GPTPStatus::PriorityVector::stepsRemoved)
|
||||
.def_readonly("port_id", &GPTPStatus::PriorityVector::portID)
|
||||
.def_readonly("port_number", &GPTPStatus::PriorityVector::portNumber);
|
||||
|
||||
pybind11::classh<GPTPStatus::ParentDS>(gptpStatus, "ParentDS")
|
||||
.def_readonly("parent_port_identity", &GPTPStatus::ParentDS::parentPortIdentity)
|
||||
.def_readonly("cumulative_rate_ratio", &GPTPStatus::ParentDS::cumulativeRateRatio)
|
||||
.def_readonly("grandmaster_identity", &GPTPStatus::ParentDS::grandmasterIdentity)
|
||||
.def_readonly("gm_clock_quality_clock_class", &GPTPStatus::ParentDS::gmClockQualityClockClass)
|
||||
.def_readonly("gm_clock_quality_clock_accuracy", &GPTPStatus::ParentDS::gmClockQualityClockAccuracy)
|
||||
.def_readonly("gm_clock_quality_offset_scaled_log_variance", &GPTPStatus::ParentDS::gmClockQualityOffsetScaledLogVariance)
|
||||
.def_readonly("gm_priority1", &GPTPStatus::ParentDS::gmPriority1)
|
||||
.def_readonly("gm_priority2", &GPTPStatus::ParentDS::gmPriority2);
|
||||
|
||||
pybind11::classh<GPTPStatus::CurrentDS>(gptpStatus, "CurrentDS")
|
||||
.def_readonly("steps_removed", &GPTPStatus::CurrentDS::stepsRemoved)
|
||||
.def_readonly("offset_from_master", &GPTPStatus::CurrentDS::offsetFromMaster)
|
||||
.def_readonly("lastgm_phase_change", &GPTPStatus::CurrentDS::lastgmPhaseChange)
|
||||
.def_readonly("lastgm_freq_change", &GPTPStatus::CurrentDS::lastgmFreqChange)
|
||||
.def_readonly("gm_time_base_indicator", &GPTPStatus::CurrentDS::gmTimeBaseIndicator)
|
||||
.def_readonly("gm_change_count", &GPTPStatus::CurrentDS::gmChangeCount)
|
||||
.def_readonly("time_of_lastgm_change_event", &GPTPStatus::CurrentDS::timeOfLastgmChangeEvent)
|
||||
.def_readonly("time_of_lastgm_phase_change_event", &GPTPStatus::CurrentDS::timeOfLastgmPhaseChangeEvent)
|
||||
.def_readonly("time_of_lastgm_freq_change_event", &GPTPStatus::CurrentDS::timeOfLastgmFreqChangeEvent);
|
||||
|
||||
gptpStatus.def_readonly("current_time", &GPTPStatus::currentTime)
|
||||
.def_readonly("gm_priority", &GPTPStatus::gmPriority)
|
||||
.def_readonly("ms_offset_ns", &GPTPStatus::msOffsetNs)
|
||||
.def_readonly("is_sync", &GPTPStatus::isSync)
|
||||
.def_readonly("link_status", &GPTPStatus::linkStatus)
|
||||
.def_readonly("link_delay_ns", &GPTPStatus::linkDelayNS)
|
||||
.def_readonly("selected_role", &GPTPStatus::selectedRole)
|
||||
.def_readonly("as_capable", &GPTPStatus::asCapable)
|
||||
.def_readonly("is_syntonized", &GPTPStatus::isSyntonized)
|
||||
.def_readonly("last_rx_sync_ts", &GPTPStatus::lastRXSyncTS)
|
||||
.def_readonly("current_ds", &GPTPStatus::currentDS)
|
||||
.def_readonly("parent_ds", &GPTPStatus::parentDS)
|
||||
.def_readonly("short_format", &GPTPStatus::shortFormat);
|
||||
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
@@ -0,0 +1,61 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/communication/message/linmessage.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_linmessage(pybind11::module_& m) {
|
||||
pybind11::classh<LINErrorFlags>(m, "LINErrorFlags")
|
||||
.def_readwrite("ErrRxBreakOnly", &LINErrorFlags::ErrRxBreakOnly)
|
||||
.def_readwrite("ErrRxBreakSyncOnly", &LINErrorFlags::ErrRxBreakSyncOnly)
|
||||
.def_readwrite("ErrTxRxMismatch", &LINErrorFlags::ErrTxRxMismatch)
|
||||
.def_readwrite("ErrRxBreakNotZero", &LINErrorFlags::ErrRxBreakNotZero)
|
||||
.def_readwrite("ErrRxBreakTooShort", &LINErrorFlags::ErrRxBreakTooShort)
|
||||
.def_readwrite("ErrRxSyncNot55", &LINErrorFlags::ErrRxSyncNot55)
|
||||
.def_readwrite("ErrRxDataLenOver8", &LINErrorFlags::ErrRxDataLenOver8)
|
||||
.def_readwrite("ErrFrameSync", &LINErrorFlags::ErrFrameSync)
|
||||
.def_readwrite("ErrFrameMessageID", &LINErrorFlags::ErrFrameMessageID)
|
||||
.def_readwrite("ErrFrameResponderData", &LINErrorFlags::ErrFrameResponderData)
|
||||
.def_readwrite("ErrChecksumMatch", &LINErrorFlags::ErrChecksumMatch);
|
||||
|
||||
pybind11::classh<LINStatusFlags>(m, "LINStatusFlags")
|
||||
.def_readwrite("TxChecksumEnhanced", &LINStatusFlags::TxChecksumEnhanced)
|
||||
.def_readwrite("TxCommander", &LINStatusFlags::TxCommander)
|
||||
.def_readwrite("TxResponder", &LINStatusFlags::TxResponder)
|
||||
.def_readwrite("TxAborted", &LINStatusFlags::TxAborted)
|
||||
.def_readwrite("UpdateResponderOnce", &LINStatusFlags::UpdateResponderOnce)
|
||||
.def_readwrite("HasUpdatedResponderOnce", &LINStatusFlags::HasUpdatedResponderOnce)
|
||||
.def_readwrite("BusRecovered", &LINStatusFlags::BusRecovered)
|
||||
.def_readwrite("BreakOnly", &LINStatusFlags::BreakOnly)
|
||||
.def_readwrite("WakeupRequest", &LINStatusFlags::WakeupRequest);
|
||||
|
||||
pybind11::classh<LINMessage, Frame> linMessage(m, "LINMessage");
|
||||
|
||||
pybind11::enum_<LINMessage::Type>(linMessage, "Type")
|
||||
.value("NOT_SET", LINMessage::Type::NOT_SET)
|
||||
.value("LIN_COMMANDER_MSG", LINMessage::Type::LIN_COMMANDER_MSG)
|
||||
.value("LIN_HEADER_ONLY", LINMessage::Type::LIN_HEADER_ONLY)
|
||||
.value("LIN_BREAK_ONLY", LINMessage::Type::LIN_BREAK_ONLY)
|
||||
.value("LIN_SYNC_ONLY", LINMessage::Type::LIN_SYNC_ONLY)
|
||||
.value("LIN_UPDATE_RESPONDER", LINMessage::Type::LIN_UPDATE_RESPONDER)
|
||||
.value("LIN_ERROR", LINMessage::Type::LIN_ERROR)
|
||||
.value("LIN_WAKEUP_REQUEST", LINMessage::Type::LIN_WAKEUP_REQUEST);
|
||||
|
||||
linMessage
|
||||
.def(pybind11::init<>())
|
||||
.def(pybind11::init<uint8_t>())
|
||||
.def_static("calc_checksum", &LINMessage::calcChecksum)
|
||||
.def("calc_protected_id", &LINMessage::calcProtectedID)
|
||||
.def_readwrite("ID", &LINMessage::ID)
|
||||
.def_readwrite("protectedID", &LINMessage::protectedID)
|
||||
.def_readwrite("checksum", &LINMessage::checksum)
|
||||
.def_readwrite("linMsgType", &LINMessage::linMsgType)
|
||||
.def_readwrite("isEnhancedChecksum", &LINMessage::isEnhancedChecksum)
|
||||
.def_readwrite("errFlags", &LINMessage::errFlags)
|
||||
.def_readwrite("statusFlags", &LINMessage::statusFlags);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
#include <pybind11/chrono.h>
|
||||
|
||||
#include "icsneo/communication/message/livedatamessage.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_livedatamessage(pybind11::module_& m) {
|
||||
// LiveDataMessage base class
|
||||
pybind11::classh<LiveDataMessage, RawMessage>(m, "LiveDataMessage")
|
||||
.def(pybind11::init<>())
|
||||
.def_readwrite("handle", &LiveDataMessage::handle)
|
||||
.def_readwrite("cmd", &LiveDataMessage::cmd);
|
||||
|
||||
// LiveDataCommandMessage (for subscribe/unsubscribe)
|
||||
pybind11::classh<LiveDataCommandMessage, LiveDataMessage>(m, "LiveDataCommandMessage")
|
||||
.def(pybind11::init<>())
|
||||
.def_readwrite("update_period", &LiveDataCommandMessage::updatePeriod)
|
||||
.def_readwrite("expiration_time", &LiveDataCommandMessage::expirationTime)
|
||||
.def_readwrite("args", &LiveDataCommandMessage::args)
|
||||
.def("append_signal_arg", &LiveDataCommandMessage::appendSignalArg,
|
||||
pybind11::arg("value_type"),
|
||||
"Append a signal argument to the command message");
|
||||
|
||||
// LiveDataValueMessage (received values)
|
||||
pybind11::classh<LiveDataValueMessage, LiveDataMessage>(m, "LiveDataValueMessage")
|
||||
.def(pybind11::init<>())
|
||||
.def_readwrite("num_args", &LiveDataValueMessage::numArgs)
|
||||
.def_readwrite("values", &LiveDataValueMessage::values);
|
||||
|
||||
// LiveDataStatusMessage (status responses)
|
||||
pybind11::classh<LiveDataStatusMessage, LiveDataMessage>(m, "LiveDataStatusMessage")
|
||||
.def(pybind11::init<>())
|
||||
.def_readwrite("requested_command", &LiveDataStatusMessage::requestedCommand)
|
||||
.def_readwrite("status", &LiveDataStatusMessage::status);
|
||||
|
||||
// LiveDataSetValueMessage (for setting values)
|
||||
pybind11::classh<LiveDataSetValueMessage, LiveDataMessage>(m, "LiveDataSetValueMessage")
|
||||
.def(pybind11::init<>())
|
||||
.def_readwrite("args", &LiveDataSetValueMessage::args)
|
||||
.def_readwrite("values", &LiveDataSetValueMessage::values)
|
||||
.def("append_set_value", &LiveDataSetValueMessage::appendSetValue,
|
||||
pybind11::arg("value_type"),
|
||||
pybind11::arg("value"),
|
||||
"Append a value to set in the message");
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
@@ -0,0 +1,35 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/communication/message/mdiomessage.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_mdiomessage(pybind11::module_& m) {
|
||||
pybind11::classh<MDIOMessage, Frame> mdioMessage(m, "MDIOMessage");
|
||||
pybind11::enum_<MDIOMessage::Clause>(mdioMessage, "Clause")
|
||||
.value("Clause45", MDIOMessage::Clause::Clause45)
|
||||
.value("Clause22", MDIOMessage::Clause::Clause22);
|
||||
pybind11::enum_<MDIOMessage::Direction>(mdioMessage, "Direction")
|
||||
.value("Write", MDIOMessage::Direction::Write)
|
||||
.value("Read", MDIOMessage::Direction::Read);
|
||||
mdioMessage
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("isTXMsg", &MDIOMessage::isTXMsg)
|
||||
.def_readwrite("txTimeout", &MDIOMessage::txTimeout)
|
||||
.def_readwrite("txAborted", &MDIOMessage::txAborted)
|
||||
.def_readwrite("txInvalidBus", &MDIOMessage::txInvalidBus)
|
||||
.def_readwrite("txInvalidPhyAddr", &MDIOMessage::txInvalidPhyAddr)
|
||||
.def_readwrite("txInvalidRegAddr", &MDIOMessage::txInvalidRegAddr)
|
||||
.def_readwrite("txInvalidClause", &MDIOMessage::txInvalidClause)
|
||||
.def_readwrite("txInvalidOpcode", &MDIOMessage::txInvalidOpcode)
|
||||
.def_readwrite("phyAddress", &MDIOMessage::phyAddress)
|
||||
.def_readwrite("devAddress", &MDIOMessage::devAddress)
|
||||
.def_readwrite("regAddress", &MDIOMessage::regAddress)
|
||||
.def_readwrite("direction", &MDIOMessage::direction)
|
||||
.def_readwrite("clause", &MDIOMessage::clause);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
#include <pybind11/native_enum.h>
|
||||
|
||||
#include "icsneo/communication/message/message.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_message(pybind11::module_& m) {
|
||||
// Using py::smart_holder for safer lifetime management
|
||||
pybind11::classh<Message> message(m, "Message");
|
||||
pybind11::native_enum<Message::Type>(message, "Type", "enum.IntEnum")
|
||||
.value("Frame", Message::Type::Frame)
|
||||
.value("CANErrorCount", Message::Type::CANErrorCount)
|
||||
.value("CANError", Message::Type::CANError)
|
||||
.value("LINHeaderOnly", Message::Type::LINHeaderOnly)
|
||||
.value("LINBreak", Message::Type::LINBreak)
|
||||
.value("Invalid", Message::Type::Invalid)
|
||||
.value("RawMessage", Message::Type::RawMessage)
|
||||
.value("ReadSettings", Message::Type::ReadSettings)
|
||||
.value("ResetStatus", Message::Type::ResetStatus)
|
||||
.value("DeviceVersion", Message::Type::DeviceVersion)
|
||||
.value("Main51", Message::Type::Main51)
|
||||
.value("FlexRayControl", Message::Type::FlexRayControl)
|
||||
.value("EthernetPhyRegister", Message::Type::EthernetPhyRegister)
|
||||
.value("LogicalDiskInfo", Message::Type::LogicalDiskInfo)
|
||||
.value("ExtendedResponse", Message::Type::ExtendedResponse)
|
||||
.value("WiVICommandResponse", Message::Type::WiVICommandResponse)
|
||||
.value("ScriptStatus", Message::Type::ScriptStatus)
|
||||
.value("ComponentVersions", Message::Type::ComponentVersions)
|
||||
.value("SupportedFeatures", Message::Type::SupportedFeatures)
|
||||
.value("GenericBinaryStatus", Message::Type::GenericBinaryStatus)
|
||||
.value("LiveData", Message::Type::LiveData)
|
||||
.value("HardwareInfo", Message::Type::HardwareInfo)
|
||||
.value("TC10Status", Message::Type::TC10Status)
|
||||
.value("AppError", Message::Type::AppError)
|
||||
.value("GPTPStatus", Message::Type::GPTPStatus)
|
||||
.value("EthernetStatus", Message::Type::EthernetStatus)
|
||||
.finalize();
|
||||
|
||||
message.def(pybind11::init<Message::Type>());
|
||||
message.def_readonly("type", &Message::type);
|
||||
message.def_readwrite("timestamp", &Message::timestamp);
|
||||
|
||||
pybind11::classh<RawMessage, Message>(m, "RawMessage")
|
||||
.def_readwrite("network", &RawMessage::network)
|
||||
.def_readwrite("data", &RawMessage::data);
|
||||
|
||||
pybind11::classh<Frame, RawMessage>(m, "Frame")
|
||||
.def_readwrite("description", &Frame::description)
|
||||
.def_readwrite("transmitted", &Frame::transmitted)
|
||||
.def_readwrite("error", &Frame::error);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/communication/message/scriptstatusmessage.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_scriptstatusmessage(pybind11::module_& m) {
|
||||
pybind11::classh<ScriptStatusMessage, Message>(m, "ScriptStatusMessage")
|
||||
.def_readonly("isEncrypted", &ScriptStatusMessage::isEncrypted)
|
||||
.def_readonly("isCoreminiRunning", &ScriptStatusMessage::isCoreminiRunning)
|
||||
.def_readonly("sectorOverflows", &ScriptStatusMessage::sectorOverflows)
|
||||
.def_readonly("numRemainingSectorBuffers", &ScriptStatusMessage::numRemainingSectorBuffers)
|
||||
.def_readonly("lastSector", &ScriptStatusMessage::lastSector)
|
||||
.def_readonly("readBinSize", &ScriptStatusMessage::readBinSize)
|
||||
.def_readonly("minSector", &ScriptStatusMessage::minSector)
|
||||
.def_readonly("maxSector", &ScriptStatusMessage::maxSector)
|
||||
.def_readonly("currentSector", &ScriptStatusMessage::currentSector)
|
||||
.def_readonly("coreminiCreateTime", &ScriptStatusMessage::coreminiCreateTime)
|
||||
.def_readonly("fileChecksum", &ScriptStatusMessage::fileChecksum)
|
||||
.def_readonly("coreminiVersion", &ScriptStatusMessage::coreminiVersion)
|
||||
.def_readonly("coreminiHeaderSize", &ScriptStatusMessage::coreminiHeaderSize)
|
||||
.def_readonly("diagnosticErrorCode", &ScriptStatusMessage::diagnosticErrorCode)
|
||||
.def_readonly("diagnosticErrorCodeCount", &ScriptStatusMessage::diagnosticErrorCodeCount)
|
||||
.def_readonly("maxCoreminiSizeKB", &ScriptStatusMessage::maxCoreminiSizeKB);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/communication/message/spimessage.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_spimessage(pybind11::module_& m) {
|
||||
pybind11::classh<SPIMessage, Frame> spiMessage(m, "SPIMessage");
|
||||
pybind11::enum_<SPIMessage::Direction>(spiMessage, "Direction")
|
||||
.value("Write", SPIMessage::Direction::Write)
|
||||
.value("Read", SPIMessage::Direction::Read);
|
||||
spiMessage
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("direction", &SPIMessage::direction)
|
||||
.def_readwrite("address", &SPIMessage::address)
|
||||
.def_readwrite("mms", &SPIMessage::mms)
|
||||
.def_readwrite("stats", &SPIMessage::stats)
|
||||
.def_readwrite("payload", &SPIMessage::payload);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/communication/message/tc10statusmessage.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_tc10statusmessage(pybind11::module_& m) {
|
||||
pybind11::enum_<TC10WakeStatus>(m, "TC10WakeStatus")
|
||||
.value("NoWakeReceived", TC10WakeStatus::NoWakeReceived)
|
||||
.value("WakeReceived", TC10WakeStatus::WakeReceived);
|
||||
|
||||
pybind11::enum_<TC10SleepStatus>(m, "TC10SleepStatus")
|
||||
.value("NoSleepReceived", TC10SleepStatus::NoSleepReceived)
|
||||
.value("SleepReceived", TC10SleepStatus::SleepReceived)
|
||||
.value("SleepFailed", TC10SleepStatus::SleepFailed)
|
||||
.value("SleepAborted", TC10SleepStatus::SleepAborted);
|
||||
|
||||
pybind11::classh<TC10StatusMessage, Message>(m, "TC10StatusMessage")
|
||||
.def_readonly("wakeStatus", &TC10StatusMessage::wakeStatus)
|
||||
.def_readonly("sleepStatus", &TC10StatusMessage::sleepStatus);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
@@ -0,0 +1,202 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
#include <pybind11/native_enum.h>
|
||||
|
||||
#include "icsneo/communication/network.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_network(pybind11::module_& m) {
|
||||
pybind11::classh<Network> network(m, "Network");
|
||||
|
||||
pybind11::native_enum<Network::NetID>(network, "NetID", "enum.IntEnum")
|
||||
.value("Device", Network::NetID::Device)
|
||||
.value("DWCAN_01", Network::NetID::DWCAN_01)
|
||||
.value("DWCAN_08", Network::NetID::DWCAN_08)
|
||||
.value("SWCAN_01", Network::NetID::SWCAN_01)
|
||||
.value("LSFTCAN_01", Network::NetID::LSFTCAN_01)
|
||||
.value("FordSCP", Network::NetID::FordSCP)
|
||||
.value("J1708", Network::NetID::J1708)
|
||||
.value("Aux", Network::NetID::Aux)
|
||||
.value("J1850VPW", Network::NetID::J1850VPW)
|
||||
.value("ISO9141_01", Network::NetID::ISO9141_01)
|
||||
.value("DiskData", Network::NetID::DiskData)
|
||||
.value("Main51", Network::NetID::Main51)
|
||||
.value("RED", Network::NetID::RED)
|
||||
.value("SCI", Network::NetID::SCI)
|
||||
.value("ISO9141_02", Network::NetID::ISO9141_02)
|
||||
.value("ISO14230", Network::NetID::ISO14230)
|
||||
.value("LIN_01", Network::NetID::LIN_01)
|
||||
.value("AE_01", Network::NetID::AE_01)
|
||||
.value("AE_02", Network::NetID::AE_02)
|
||||
.value("AE_03", Network::NetID::AE_03)
|
||||
.value("RED_EXT_MEMORYREAD", Network::NetID::RED_EXT_MEMORYREAD)
|
||||
.value("RED_INT_MEMORYREAD", Network::NetID::RED_INT_MEMORYREAD)
|
||||
.value("RED_DFLASH_READ", Network::NetID::RED_DFLASH_READ)
|
||||
.value("NeoMemorySDRead", Network::NetID::NeoMemorySDRead)
|
||||
.value("CAN_ERRBITS", Network::NetID::CAN_ERRBITS)
|
||||
.value("NeoMemoryWriteDone", Network::NetID::NeoMemoryWriteDone)
|
||||
.value("RED_WAVE_CAN1_LOGICAL", Network::NetID::RED_WAVE_CAN1_LOGICAL)
|
||||
.value("RED_WAVE_CAN2_LOGICAL", Network::NetID::RED_WAVE_CAN2_LOGICAL)
|
||||
.value("RED_WAVE_LIN1_LOGICAL", Network::NetID::RED_WAVE_LIN1_LOGICAL)
|
||||
.value("RED_WAVE_LIN2_LOGICAL", Network::NetID::RED_WAVE_LIN2_LOGICAL)
|
||||
.value("RED_WAVE_LIN1_ANALOG", Network::NetID::RED_WAVE_LIN1_ANALOG)
|
||||
.value("RED_WAVE_LIN2_ANALOG", Network::NetID::RED_WAVE_LIN2_ANALOG)
|
||||
.value("RED_WAVE_MISC_ANALOG", Network::NetID::RED_WAVE_MISC_ANALOG)
|
||||
.value("RED_WAVE_MISCDIO2_LOGICAL", Network::NetID::RED_WAVE_MISCDIO2_LOGICAL)
|
||||
.value("RED_NETWORK_COM_ENABLE_EX", Network::NetID::RED_NETWORK_COM_ENABLE_EX)
|
||||
.value("RED_NEOVI_NETWORK", Network::NetID::RED_NEOVI_NETWORK)
|
||||
.value("RED_READ_BAUD_SETTINGS", Network::NetID::RED_READ_BAUD_SETTINGS)
|
||||
.value("RED_OLDFORMAT", Network::NetID::RED_OLDFORMAT)
|
||||
.value("RED_SCOPE_CAPTURE", Network::NetID::RED_SCOPE_CAPTURE)
|
||||
.value("RED_HARDWARE_EXCEP", Network::NetID::RED_HARDWARE_EXCEP)
|
||||
.value("RED_GET_RTC", Network::NetID::RED_GET_RTC)
|
||||
.value("ISO9141_03", Network::NetID::ISO9141_03)
|
||||
.value("DWCAN_02", Network::NetID::DWCAN_02)
|
||||
.value("DWCAN_03", Network::NetID::DWCAN_03)
|
||||
.value("AE_04", Network::NetID::AE_04)
|
||||
.value("AE_05", Network::NetID::AE_05)
|
||||
.value("ISO9141_04", Network::NetID::ISO9141_04)
|
||||
.value("LIN_02", Network::NetID::LIN_02)
|
||||
.value("LIN_03", Network::NetID::LIN_03)
|
||||
.value("LIN_04", Network::NetID::LIN_04)
|
||||
.value("RED_App_Error", Network::NetID::RED_App_Error)
|
||||
.value("CGI", Network::NetID::CGI)
|
||||
.value("Reset_Status", Network::NetID::Reset_Status)
|
||||
.value("FB_Status", Network::NetID::FB_Status)
|
||||
.value("App_Signal_Status", Network::NetID::App_Signal_Status)
|
||||
.value("Read_Datalink_Cm_Tx_Msg", Network::NetID::Read_Datalink_Cm_Tx_Msg)
|
||||
.value("Read_Datalink_Cm_Rx_Msg", Network::NetID::Read_Datalink_Cm_Rx_Msg)
|
||||
.value("Logging_Overflow", Network::NetID::Logging_Overflow)
|
||||
.value("ReadSettings", Network::NetID::ReadSettings)
|
||||
.value("DWCAN_04", Network::NetID::DWCAN_04)
|
||||
.value("DWCAN_05", Network::NetID::DWCAN_05)
|
||||
.value("RS232", Network::NetID::RS232)
|
||||
.value("UART_01", Network::NetID::UART_01)
|
||||
.value("UART_02", Network::NetID::UART_02)
|
||||
.value("UART_03", Network::NetID::UART_03)
|
||||
.value("UART_04", Network::NetID::UART_04)
|
||||
.value("SWCAN_02", Network::NetID::SWCAN_02)
|
||||
.value("ETHERNET_DAQ", Network::NetID::ETHERNET_DAQ)
|
||||
.value("Data_To_Host", Network::NetID::Data_To_Host)
|
||||
.value("TextAPI_To_Host", Network::NetID::TextAPI_To_Host)
|
||||
.value("SPI_01", Network::NetID::SPI_01)
|
||||
.value("AE_06", Network::NetID::AE_06)
|
||||
.value("Red_VBat", Network::NetID::Red_VBat)
|
||||
.value("AE_07", Network::NetID::AE_07)
|
||||
.value("AE_08", Network::NetID::AE_08)
|
||||
.value("AE_09", Network::NetID::AE_09)
|
||||
.value("AE_10", Network::NetID::AE_10)
|
||||
.value("AE_11", Network::NetID::AE_11)
|
||||
.value("FLEXRAY_01A", Network::NetID::FLEXRAY_01A)
|
||||
.value("FLEXRAY_01B", Network::NetID::FLEXRAY_01B)
|
||||
.value("FLEXRAY_02A", Network::NetID::FLEXRAY_02A)
|
||||
.value("FLEXRAY_02B", Network::NetID::FLEXRAY_02B)
|
||||
.value("LIN_05", Network::NetID::LIN_05)
|
||||
.value("FLEXRAY_01", Network::NetID::FLEXRAY_01)
|
||||
.value("FLEXRAY_02", Network::NetID::FLEXRAY_02)
|
||||
.value("AE_12", Network::NetID::AE_12)
|
||||
.value("I2C_01", Network::NetID::I2C_01)
|
||||
.value("MOST_25", Network::NetID::MOST_25)
|
||||
.value("MOST_50", Network::NetID::MOST_50)
|
||||
.value("MOST_150", Network::NetID::MOST_150)
|
||||
.value("ETHERNET_01", Network::NetID::ETHERNET_01)
|
||||
.value("GMFSA", Network::NetID::GMFSA)
|
||||
.value("TCP", Network::NetID::TCP)
|
||||
.value("DWCAN_06", Network::NetID::DWCAN_06)
|
||||
.value("DWCAN_07", Network::NetID::DWCAN_07)
|
||||
.value("LIN_06", Network::NetID::LIN_06)
|
||||
.value("LSFTCAN_02", Network::NetID::LSFTCAN_02)
|
||||
.value("LogicalDiskInfo", Network::NetID::LogicalDiskInfo)
|
||||
.value("WiVICommand", Network::NetID::WiVICommand)
|
||||
.value("ScriptStatus", Network::NetID::ScriptStatus)
|
||||
.value("EthPHYControl", Network::NetID::EthPHYControl)
|
||||
.value("ExtendedCommand", Network::NetID::ExtendedCommand)
|
||||
.value("ExtendedData", Network::NetID::ExtendedData)
|
||||
.value("FlexRayControl", Network::NetID::FlexRayControl)
|
||||
.value("CoreMiniPreLoad", Network::NetID::CoreMiniPreLoad)
|
||||
.value("HW_COM_Latency_Test", Network::NetID::HW_COM_Latency_Test)
|
||||
.value("DeviceStatus", Network::NetID::DeviceStatus)
|
||||
.value("UDP", Network::NetID::UDP)
|
||||
.value("ForwardedMessage", Network::NetID::ForwardedMessage)
|
||||
.value("I2C_02", Network::NetID::I2C_02)
|
||||
.value("I2C_03", Network::NetID::I2C_03)
|
||||
.value("I2C_04", Network::NetID::I2C_04)
|
||||
.value("ETHERNET_02", Network::NetID::ETHERNET_02)
|
||||
.value("ETHERNET_TX_WRAP", Network::NetID::ETHERNET_TX_WRAP)
|
||||
.value("A2B_01", Network::NetID::A2B_01)
|
||||
.value("A2B_02", Network::NetID::A2B_02)
|
||||
.value("ETHERNET_03", Network::NetID::ETHERNET_03)
|
||||
.value("WBMS_01", Network::NetID::WBMS_01)
|
||||
.value("DWCAN_09", Network::NetID::DWCAN_09)
|
||||
.value("DWCAN_10", Network::NetID::DWCAN_10)
|
||||
.value("DWCAN_11", Network::NetID::DWCAN_11)
|
||||
.value("DWCAN_12", Network::NetID::DWCAN_12)
|
||||
.value("DWCAN_13", Network::NetID::DWCAN_13)
|
||||
.value("DWCAN_14", Network::NetID::DWCAN_14)
|
||||
.value("DWCAN_15", Network::NetID::DWCAN_15)
|
||||
.value("DWCAN_16", Network::NetID::DWCAN_16)
|
||||
.value("LIN_07", Network::NetID::LIN_07)
|
||||
.value("LIN_08", Network::NetID::LIN_08)
|
||||
.value("SPI_02", Network::NetID::SPI_02)
|
||||
.value("MDIO_01", Network::NetID::MDIO_01)
|
||||
.value("MDIO_02", Network::NetID::MDIO_02)
|
||||
.value("MDIO_03", Network::NetID::MDIO_03)
|
||||
.value("MDIO_04", Network::NetID::MDIO_04)
|
||||
.value("MDIO_05", Network::NetID::MDIO_05)
|
||||
.value("MDIO_06", Network::NetID::MDIO_06)
|
||||
.value("MDIO_07", Network::NetID::MDIO_07)
|
||||
.value("MDIO_08", Network::NetID::MDIO_08)
|
||||
.value("AE_13", Network::NetID::AE_13)
|
||||
.value("AE_14", Network::NetID::AE_14)
|
||||
.value("AE_15", Network::NetID::AE_15)
|
||||
.value("AE_16", Network::NetID::AE_16)
|
||||
.value("SPI_03", Network::NetID::SPI_03)
|
||||
.value("SPI_04", Network::NetID::SPI_04)
|
||||
.value("SPI_05", Network::NetID::SPI_05)
|
||||
.value("SPI_06", Network::NetID::SPI_06)
|
||||
.value("SPI_07", Network::NetID::SPI_07)
|
||||
.value("SPI_08", Network::NetID::SPI_08)
|
||||
.value("LIN_09", Network::NetID::LIN_09)
|
||||
.value("LIN_10", Network::NetID::LIN_10)
|
||||
.value("LIN_11", Network::NetID::LIN_11)
|
||||
.value("LIN_12", Network::NetID::LIN_12)
|
||||
.value("LIN_13", Network::NetID::LIN_13)
|
||||
.value("LIN_14", Network::NetID::LIN_14)
|
||||
.value("LIN_15", Network::NetID::LIN_15)
|
||||
.value("LIN_16", Network::NetID::LIN_16)
|
||||
.value("Any", Network::NetID::Any)
|
||||
.value("Invalid", Network::NetID::Invalid)
|
||||
.finalize();
|
||||
|
||||
pybind11::native_enum<Network::Type>(network, "Type", "enum.Enum")
|
||||
.value("Invalid", Network::Type::Invalid)
|
||||
.value("Internal", Network::Type::Internal)
|
||||
.value("CAN", Network::Type::CAN)
|
||||
.value("LIN", Network::Type::LIN)
|
||||
.value("FlexRay", Network::Type::FlexRay)
|
||||
.value("MOST", Network::Type::MOST)
|
||||
.value("Ethernet", Network::Type::Ethernet)
|
||||
.value("LSFTCAN", Network::Type::LSFTCAN)
|
||||
.value("SWCAN", Network::Type::SWCAN)
|
||||
.value("ISO9141", Network::Type::ISO9141)
|
||||
.value("I2C", Network::Type::I2C)
|
||||
.value("A2B", Network::Type::A2B)
|
||||
.value("SPI", Network::Type::SPI)
|
||||
.value("MDIO", Network::Type::MDIO)
|
||||
.value("AutomotiveEthernet", Network::Type::AutomotiveEthernet)
|
||||
.value("Any", Network::Type::Any)
|
||||
.value("Other", Network::Type::Other)
|
||||
.finalize();
|
||||
|
||||
network
|
||||
.def(pybind11::init<Network::NetID>())
|
||||
.def("__repr__", [](Network& self) { return Network::GetNetIDString(self.getNetID()); })
|
||||
.def_static("get_net_id_string", &Network::GetNetIDString, pybind11::arg("netid"), pybind11::arg("expand") = true)
|
||||
.def("get_net_id", &Network::getNetID)
|
||||
.def("get_type", &Network::getType);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/core/macseccfg.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_macsecconfig(pybind11::module_ & m)
|
||||
{
|
||||
pybind11::enum_<MACsecPacketType>(m, "MACsecPacketType")
|
||||
.value("DEFAULT", MACsecPacketType::Default)
|
||||
.value("SINGLE_VLAN", MACsecPacketType::SingleVLAN)
|
||||
.value("DUAL_VLAN", MACsecPacketType::DualVLAN)
|
||||
.value("MPLS", MACsecPacketType::MPLS)
|
||||
.value("SINGLE_VLAN_FOLLOWED_BY_MPLS", MACsecPacketType::SingleVLANFollowedByMPLS)
|
||||
.value("DUAL_VLAN_FOLLOWED_BY_MPLS", MACsecPacketType::DualVLANFollowedByMPLS)
|
||||
.value("UNSUPPORTED", MACsecPacketType::Unsupported);
|
||||
|
||||
pybind11::enum_<MACsecValidation>(m, "MACsecValidation")
|
||||
.value("DISABLED", MACsecValidation::Disabled)
|
||||
.value("CHECK", MACsecValidation::Check)
|
||||
.value("STRICT", MACsecValidation::Strict)
|
||||
.value("NA", MACsecValidation::NA);
|
||||
|
||||
pybind11::enum_<MACsecStrip>(m, "MACsecStrip")
|
||||
.value("STRIP_SECTAG_AND_ICV", MACsecStrip::StripSecTagAndIcv)
|
||||
.value("STRIP_SECTAG_PRESERVE_ICV", MACsecStrip::StripSecTagPreserveICV)
|
||||
.value("PRESERVE_SECTAG_STRIP_ICV", MACsecStrip::PreserveSecTagStripICV)
|
||||
.value("NO_STRIP", MACsecStrip::NoStrip);
|
||||
|
||||
pybind11::enum_<MACsecCipherSuite>(m, "MACsecCipherSuite")
|
||||
.value("GCM_AES_128", MACsecCipherSuite::GcmAes128)
|
||||
.value("GCM_AES_256", MACsecCipherSuite::GcmAes256)
|
||||
.value("GCM_AES_128_XPN", MACsecCipherSuite::GcmAes128Xpn)
|
||||
.value("GCM_AES_256_XPN", MACsecCipherSuite::GcmAes256Xpn);
|
||||
|
||||
pybind11::classh<MACsecVLANTag>(m, "MACsecVLANTag")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("vid", &MACsecVLANTag::vid)
|
||||
.def_readwrite("pri_cfi", &MACsecVLANTag::priCfi);
|
||||
|
||||
pybind11::classh<MACsecMPLSOuter>(m, "MACsecMPLSOuter")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("mpls_label", &MACsecMPLSOuter::mplsLabel)
|
||||
.def_readwrite("exp", &MACsecMPLSOuter::exp);
|
||||
|
||||
pybind11::classh<MACsecTci>(m, "MACsecTci")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("es", &MACsecTci::es)
|
||||
.def_readwrite("sc", &MACsecTci::sc)
|
||||
.def_readwrite("scb", &MACsecTci::scb)
|
||||
.def_readwrite("e", &MACsecTci::e)
|
||||
.def_readwrite("c", &MACsecTci::c);
|
||||
|
||||
pybind11::classh<MACsecRxRule>(m, "MACsecRxRule")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("key_mac_da", &MACsecRxRule::keyMacDa)
|
||||
.def_readwrite("mask_mac_da", &MACsecRxRule::maskMacDa)
|
||||
.def_readwrite("key_mask_sa", &MACsecRxRule::keyMacSa)
|
||||
.def_readwrite("mask_mac_sa", &MACsecRxRule::maskMacSa)
|
||||
.def_readwrite("key_ether_type", &MACsecRxRule::keyEthertype)
|
||||
.def_readwrite("mask_ether_type", &MACsecRxRule::maskEthertype)
|
||||
.def_readwrite("key_vlan_tag_outer1", &MACsecRxRule::keyVlanTagOuter1)
|
||||
.def_readwrite("key_mpls_outer1", &MACsecRxRule::keyMplsOuter1)
|
||||
.def_readwrite("mask_vlan_tag_outer1", &MACsecRxRule::maskVlanTagOuter1)
|
||||
.def_readwrite("mask_mpls_outer1", &MACsecRxRule::maskMplsOuter1)
|
||||
.def_readwrite("key_vlan_tag_outer2", &MACsecRxRule::keyVlanTagOuter2)
|
||||
.def_readwrite("key_mpls_outer2", &MACsecRxRule::keyMplsOuter2)
|
||||
.def_readwrite("mask_vlan_tag_outer2", &MACsecRxRule::maskVlanTagOuter2)
|
||||
.def_readwrite("mask_mpls_outer2", &MACsecRxRule::maskMplsOuter2)
|
||||
.def_readwrite("key_bonus_data", &MACsecRxRule::keyBonusData)
|
||||
.def_readwrite("mask_bonus_data", &MACsecRxRule::maskBonusData)
|
||||
.def_readwrite("key_tag_match_bitmap", &MACsecRxRule::keyTagMatchBitmap)
|
||||
.def_readwrite("mask_tag_match_bitmap", &MACsecRxRule::maskTagMatchBitmap)
|
||||
.def_readwrite("key_packet_type", &MACsecRxRule::keyPacketType)
|
||||
.def_readwrite("mask_packet_type", &MACsecRxRule::maskPacketType)
|
||||
.def_readwrite("key_inner_vlan_type", &MACsecRxRule::keyInnerVlanType)
|
||||
.def_readwrite("mask_inner_vlan_type", &MACsecRxRule::maskInnerVlanType)
|
||||
.def_readwrite("key_outer_vlan_type", &MACsecRxRule::keyOuterVlanType)
|
||||
.def_readwrite("mask_outer_vlan_type", &MACsecRxRule::maskOuterVlanType)
|
||||
.def_readwrite("key_num_tags", &MACsecRxRule::keyNumTags)
|
||||
.def_readwrite("mask_num_tags", &MACsecRxRule::maskNumTags)
|
||||
.def_readwrite("key_express", &MACsecRxRule::keyExpress)
|
||||
.def_readwrite("mask_express", &MACsecRxRule::maskExpress)
|
||||
.def_readwrite("is_mpls", &MACsecRxRule::isMpls);
|
||||
|
||||
pybind11::classh<MACsecTxSecY>(m, "MACsecTxSecY")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("enable_control_port", &MACsecTxSecY::enableControlPort)
|
||||
.def_readwrite("cipher", &MACsecTxSecY::cipher)
|
||||
.def_readwrite("confidentiality_offset", &MACsecTxSecY::confidentialityOffset)
|
||||
.def_readwrite("icv_includes_da_sa", &MACsecTxSecY::icvIncludesDaSa)
|
||||
.def_readwrite("protect_frames", &MACsecTxSecY::protectFrames)
|
||||
.def_readwrite("sec_tag_offset", &MACsecTxSecY::secTagOffset)
|
||||
.def_readwrite("sec_tag_tci", &MACsecTxSecY::tci)
|
||||
.def_readwrite("mtu", &MACsecTxSecY::mtu)
|
||||
.def_readwrite("is_control_packet", &MACsecTxSecY::isControlPacket)
|
||||
.def_readwrite("auxiliary_policy", &MACsecTxSecY::auxiliaryPolicy)
|
||||
.def_readwrite("sci", &MACsecTxSecY::sci);
|
||||
|
||||
pybind11::classh<MACsecRxSecY>(m, "MACsecRxSecY")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("enable_control_port", &MACsecRxSecY::enableControlPort)
|
||||
.def_readwrite("frame_validation", &MACsecRxSecY::frameValidation)
|
||||
.def_readwrite("frame_strip", &MACsecRxSecY::frameStrip)
|
||||
.def_readwrite("cipher", &MACsecRxSecY::cipher)
|
||||
.def_readwrite("confidentiality_offset", &MACsecRxSecY::confidentialityOffset)
|
||||
.def_readwrite("icv_includes_da_sa", &MACsecRxSecY::icvIncludesDaSa)
|
||||
.def_readwrite("replay_protect", &MACsecRxSecY::replayProtect)
|
||||
.def_readwrite("replay_window", &MACsecRxSecY::replayWindow)
|
||||
.def_readwrite("is_control_packet", &MACsecRxSecY::isControlPacket)
|
||||
.def_readwrite("sci", &MACsecRxSecY::sci);
|
||||
|
||||
pybind11::classh<MACsecTxSa>(m, "MACsecTxSa")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("sak", &MACsecTxSa::sak)
|
||||
.def_readwrite("hash_key", &MACsecTxSa::hashKey)
|
||||
.def_readwrite("salt", &MACsecTxSa::salt)
|
||||
.def_readwrite("ssci", &MACsecTxSa::ssci)
|
||||
.def_readwrite("next_pn", &MACsecTxSa::nextPn)
|
||||
.def_readwrite("an", &MACsecTxSa::an);
|
||||
|
||||
pybind11::classh<MACsecRxSa>(m, "MACsecRxSa")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("sak", &MACsecRxSa::sak)
|
||||
.def_readwrite("hash_key", &MACsecRxSa::hashKey)
|
||||
.def_readwrite("salt", &MACsecRxSa::salt)
|
||||
.def_readwrite("ssci", &MACsecRxSa::ssci)
|
||||
.def_readwrite("next_pn", &MACsecRxSa::nextPn);
|
||||
|
||||
pybind11::classh<MACsecConfig>(m, "MACsecConfig")
|
||||
.def(pybind11::init<icsneo::DeviceType>())
|
||||
.def("add_rx_secy", &MACsecConfig::addRxSecY, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("add_tx_secY", &MACsecConfig::addTxSecY, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("add_rx_rule", &MACsecConfig::addRxRule, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("add_rx_sa", &MACsecConfig::addRxSa, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("add_tx_sa", &MACsecConfig::addTxSa, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_rx_secy", [](MACsecConfig& cfg, uint8_t index) -> MACsecRxSecY& { return cfg.getRxSecY(index); }, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_tx_secy", [](MACsecConfig& cfg, uint8_t index) -> MACsecTxSecY& { return cfg.getTxSecY(index); }, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_rx_sa", [](MACsecConfig& cfg, uint8_t index) -> MACsecRxSa& { return cfg.getRxSa(index); }, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_tx_sa", [](MACsecConfig& cfg, uint8_t index) -> MACsecTxSa& { return cfg.getTxSa(index); }, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_rx_rule", [](MACsecConfig& cfg, uint8_t index) -> MACsecRxRule& { return cfg.getRxRule(index); }, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_tx_sa_index", &MACsecConfig::setTxSaIndex, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("enable_tx_rekey", &MACsecConfig::enableTxRekey, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_tx_sa_rekey_index", &MACsecConfig::setTxSaRekeyIndex, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("disable_tx_rekey", &MACsecConfig::disableTxRekey, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_rx_sa_index", &MACsecConfig::setRxSaIndex, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("enable_rx_rekey", &MACsecConfig::enableRxRekey, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_rx_sa_rekey_index", &MACsecConfig::setRxSaRekeyIndex, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("disable_rx_rekey", &MACsecConfig::disableRxRekey, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_rx_enable", &MACsecConfig::setRxEnable, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_tx_enable", &MACsecConfig::setTxEnable, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_storage", &MACsecConfig::setStorage, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("clear", &MACsecConfig::clear, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("serialize", &MACsecConfig::serialize, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_bin_index", &MACsecConfig::getBinIndex, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_type", &MACsecConfig::getType, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_max_num_rule", &MACsecConfig::getMaxNumRule, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_max_num_secy", &MACsecConfig::getMaxNumSecY, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_max_num_sa", &MACsecConfig::getMaxNumSa, pybind11::call_guard<pybind11::gil_scoped_release>());
|
||||
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
#include <pybind11/native_enum.h>
|
||||
|
||||
#include "icsneo/device/chipid.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_chipid(pybind11::module_& m) {
|
||||
pybind11::native_enum<ChipID>(m, "ChipID", "enum.IntEnum")
|
||||
.value("neoVIFIRE_MCHIP", ChipID::neoVIFIRE_MCHIP)
|
||||
.value("neoVIFIRE_LCHIP", ChipID::neoVIFIRE_LCHIP)
|
||||
.value("neoVIFIRE_UCHIP", ChipID::neoVIFIRE_UCHIP)
|
||||
.value("neoVIFIRE_JCHIP", ChipID::neoVIFIRE_JCHIP)
|
||||
.value("ValueCAN3_MCHIP", ChipID::ValueCAN3_MCHIP)
|
||||
.value("neoVIECU_MPIC", ChipID::neoVIECU_MPIC)
|
||||
.value("neoVIIEVB_MPIC", ChipID::neoVIIEVB_MPIC)
|
||||
.value("neoVIPENDANT_MPIC", ChipID::neoVIPENDANT_MPIC)
|
||||
.value("neoVIFIRE_VNET_MCHIP", ChipID::neoVIFIRE_VNET_MCHIP)
|
||||
.value("neoVIFIRE_VNET_LCHIP", ChipID::neoVIFIRE_VNET_LCHIP)
|
||||
.value("neoVIPLASMA_Core", ChipID::neoVIPLASMA_Core)
|
||||
.value("neoVIPLASMA_HID", ChipID::neoVIPLASMA_HID)
|
||||
.value("neoVIANALOG_MPIC", ChipID::neoVIANALOG_MPIC)
|
||||
.value("neoVIPLASMA_ANALOG_Core", ChipID::neoVIPLASMA_ANALOG_Core)
|
||||
.value("neoVIPLASMA_FlexRay_Core", ChipID::neoVIPLASMA_FlexRay_Core)
|
||||
.value("neoVIPLASMA_Core_1_12", ChipID::neoVIPLASMA_Core_1_12)
|
||||
.value("neoVIFIRE_Slave_VNET_MCHIP", ChipID::neoVIFIRE_Slave_VNET_MCHIP)
|
||||
.value("neoVIFIRE_Slave_VNET_LCHIP", ChipID::neoVIFIRE_Slave_VNET_LCHIP)
|
||||
.value("neoVIION_Core", ChipID::neoVIION_Core)
|
||||
.value("neoVIION_HID", ChipID::neoVIION_HID)
|
||||
.value("neoVIION_Core_Loader", ChipID::neoVIION_Core_Loader)
|
||||
.value("neoVIION_HID_Loader", ChipID::neoVIION_HID_Loader)
|
||||
.value("neoVIION_FPGA_BIT", ChipID::neoVIION_FPGA_BIT)
|
||||
.value("neoVIFIRE_VNET_EP_MCHIP", ChipID::neoVIFIRE_VNET_EP_MCHIP)
|
||||
.value("neoVIFIRE_VNET_EP_LCHIP", ChipID::neoVIFIRE_VNET_EP_LCHIP)
|
||||
.value("neoVIAnalogOut_MCHIP", ChipID::neoVIAnalogOut_MCHIP)
|
||||
.value("neoVIMOST25_MCHIP", ChipID::neoVIMOST25_MCHIP)
|
||||
.value("neoVIMOST50_MCHIP", ChipID::neoVIMOST50_MCHIP)
|
||||
.value("neoVIMOST150_MCHIP", ChipID::neoVIMOST150_MCHIP)
|
||||
.value("ValueCAN4_4_MCHIP", ChipID::ValueCAN4_4_MCHIP)
|
||||
.value("ValueCAN4_4_SCHIP", ChipID::ValueCAN4_4_SCHIP)
|
||||
.value("cmProbe_ZYNQ", ChipID::cmProbe_ZYNQ)
|
||||
.value("EEVB_STM32", ChipID::EEVB_STM32)
|
||||
.value("neoVIFIRE_Slave_VNET_EP_MCHIP", ChipID::neoVIFIRE_Slave_VNET_EP_MCHIP)
|
||||
.value("neoVIFIRE_Slave_VNET_EP_LCHIP", ChipID::neoVIFIRE_Slave_VNET_EP_LCHIP)
|
||||
.value("RADStar_MCHIP", ChipID::RADStar_MCHIP)
|
||||
.value("ValueCANrf_MCHIP", ChipID::ValueCANrf_MCHIP)
|
||||
.value("neoVIFIRE2_MCHIP", ChipID::neoVIFIRE2_MCHIP)
|
||||
.value("neoVIFIRE2_CCHIP", ChipID::neoVIFIRE2_CCHIP)
|
||||
.value("neoVIFIRE2_Core", ChipID::neoVIFIRE2_Core)
|
||||
.value("neoVIFIRE2_BLECHIP", ChipID::neoVIFIRE2_BLECHIP)
|
||||
.value("neoVIFIRE2_ZYNQ", ChipID::neoVIFIRE2_ZYNQ)
|
||||
.value("neoVIFIRE2_SECURITYCHIP", ChipID::neoVIFIRE2_SECURITYCHIP)
|
||||
.value("RADGalaxy_ZYNQ", ChipID::RADGalaxy_ZYNQ)
|
||||
.value("neoVIFIRE2_VNET_MCHIP", ChipID::neoVIFIRE2_VNET_MCHIP)
|
||||
.value("neoVIFIRE2_Slave_VNET_A_MCHIP", ChipID::neoVIFIRE2_Slave_VNET_A_MCHIP)
|
||||
.value("neoVIFIRE2_Slave_VNET_A_CCHIP", ChipID::neoVIFIRE2_Slave_VNET_A_CCHIP)
|
||||
.value("neoVIFIRE2_VNET_CCHIP", ChipID::neoVIFIRE2_VNET_CCHIP)
|
||||
.value("neoVIFIRE2_VNET_Core", ChipID::neoVIFIRE2_VNET_Core)
|
||||
.value("RADStar2_ZYNQ", ChipID::RADStar2_ZYNQ)
|
||||
.value("VividCAN_MCHIP", ChipID::VividCAN_MCHIP)
|
||||
.value("neoOBD2SIM_MCHIP", ChipID::neoOBD2SIM_MCHIP)
|
||||
.value("neoVIFIRE2_VNETZ_MCHIP", ChipID::neoVIFIRE2_VNETZ_MCHIP)
|
||||
.value("neoVIFIRE2_VNETZ_ZYNQ", ChipID::neoVIFIRE2_VNETZ_ZYNQ)
|
||||
.value("neoVIFIRE2_Slave_VNETZ_A_MCHIP", ChipID::neoVIFIRE2_Slave_VNETZ_A_MCHIP)
|
||||
.value("neoVIFIRE2_Slave_VNETZ_A_ZYNQ", ChipID::neoVIFIRE2_Slave_VNETZ_A_ZYNQ)
|
||||
.value("VividCAN_EXT_FLASH", ChipID::VividCAN_EXT_FLASH)
|
||||
.value("VividCAN_NRF52", ChipID::VividCAN_NRF52)
|
||||
.value("cmProbe_ZYNQ_Unused", ChipID::cmProbe_ZYNQ_Unused)
|
||||
.value("neoOBD2PRO_MCHIP", ChipID::neoOBD2PRO_MCHIP)
|
||||
.value("ValueCAN4_1_MCHIP", ChipID::ValueCAN4_1_MCHIP)
|
||||
.value("ValueCAN4_2_MCHIP", ChipID::ValueCAN4_2_MCHIP)
|
||||
.value("ValueCAN4_4_2EL_Core", ChipID::ValueCAN4_4_2EL_Core)
|
||||
.value("neoOBD2PRO_SCHIP", ChipID::neoOBD2PRO_SCHIP)
|
||||
.value("ValueCAN4_2EL_MCHIP", ChipID::ValueCAN4_2EL_MCHIP)
|
||||
.value("neoECUAVBTSN_MCHIP", ChipID::neoECUAVBTSN_MCHIP)
|
||||
.value("neoOBD2PRO_Core", ChipID::neoOBD2PRO_Core)
|
||||
.value("RADSupermoon_ZYNQ", ChipID::RADSupermoon_ZYNQ)
|
||||
.value("RADMoon2_ZYNQ", ChipID::RADMoon2_ZYNQ)
|
||||
.value("VividCANPRO_MCHIP", ChipID::VividCANPRO_MCHIP)
|
||||
.value("VividCANPRO_EXT_FLASH", ChipID::VividCANPRO_EXT_FLASH)
|
||||
.value("RADPluto_MCHIP", ChipID::RADPluto_MCHIP)
|
||||
.value("RADMars_ZYNQ", ChipID::RADMars_ZYNQ)
|
||||
.value("neoECU12_MCHIP", ChipID::neoECU12_MCHIP)
|
||||
.value("RADIOCANHUB_MCHIP", ChipID::RADIOCANHUB_MCHIP)
|
||||
.value("FlexRay_VNETZ_ZCHIP", ChipID::FlexRay_VNETZ_ZCHIP)
|
||||
.value("neoOBD2_LCBADGE_MCHIP", ChipID::neoOBD2_LCBADGE_MCHIP)
|
||||
.value("neoOBD2_LCBADGE_SCHIP", ChipID::neoOBD2_LCBADGE_SCHIP)
|
||||
.value("RADMoonDuo_MCHIP", ChipID::RADMoonDuo_MCHIP)
|
||||
.value("neoVIFIRE3_ZCHIP", ChipID::neoVIFIRE3_ZCHIP)
|
||||
.value("FlexRay_VNETZ_FCHIP", ChipID::FlexRay_VNETZ_FCHIP)
|
||||
.value("RADJupiter_MCHIP", ChipID::RADJupiter_MCHIP)
|
||||
.value("ValueCAN4Industrial_MCHIP", ChipID::ValueCAN4Industrial_MCHIP)
|
||||
.value("EtherBADGE_MCHIP", ChipID::EtherBADGE_MCHIP)
|
||||
.value("RADMars_3_ZYNQ", ChipID::RADMars_3_ZYNQ)
|
||||
.value("RADGigastar_USBZ_ZYNQ", ChipID::RADGigastar_USBZ_ZYNQ)
|
||||
.value("RADGigastar_ZYNQ", ChipID::RADGigastar_ZYNQ)
|
||||
.value("RAD4G_MCHIP", ChipID::RAD4G_MCHIP)
|
||||
.value("neoVIFIRE3_SCHIP", ChipID::neoVIFIRE3_SCHIP)
|
||||
.value("RADEpsilon_MCHIP", ChipID::RADEpsilon_MCHIP)
|
||||
.value("RADA2B_ZCHIP", ChipID::RADA2B_ZCHIP)
|
||||
.value("neoOBD2Dev_MCHIP", ChipID::neoOBD2Dev_MCHIP)
|
||||
.value("neoOBD2Dev_SCHIP", ChipID::neoOBD2Dev_SCHIP)
|
||||
.value("neoOBD2SIMDoIP_MCHIP", ChipID::neoOBD2SIMDoIP_MCHIP)
|
||||
.value("SFPModule_88q2112_MCHIP", ChipID::SFPModule_88q2112_MCHIP)
|
||||
.value("RADEpsilonT_MCHIP", ChipID::RADEpsilonT_MCHIP)
|
||||
.value("RADEpsilonExpress_MCHIP", ChipID::RADEpsilonExpress_MCHIP)
|
||||
.value("RADProxima_MCHIP", ChipID::RADProxima_MCHIP)
|
||||
.value("NewDevice57_ZCHIP", ChipID::NewDevice57_ZCHIP)
|
||||
.value("RAD_GALAXY_2_ZMPCHIP_ID", ChipID::RAD_GALAXY_2_ZMPCHIP_ID)
|
||||
.value("NewDevice59_MCHIP", ChipID::NewDevice59_MCHIP)
|
||||
.value("RADMoon2_Z7010_ZYNQ", ChipID::RADMoon2_Z7010_ZYNQ)
|
||||
.value("neoVIFIRE2_Core_SG4", ChipID::neoVIFIRE2_Core_SG4)
|
||||
.value("RADBMS_MCHIP", ChipID::RADBMS_MCHIP)
|
||||
.value("RADMoon2_ZL_MCHIP", ChipID::RADMoon2_ZL_MCHIP)
|
||||
.value("RADGigastar_USBZ_Z7010_ZYNQ", ChipID::RADGigastar_USBZ_Z7010_ZYNQ)
|
||||
.value("neoVIFIRE3_LINUX", ChipID::neoVIFIRE3_LINUX)
|
||||
.value("RADGigastar_USBZ_Z7007S_ZYNQ", ChipID::RADGigastar_USBZ_Z7007S_ZYNQ)
|
||||
.value("VEM_01_8DW_ZCHIP", ChipID::VEM_01_8DW_ZCHIP)
|
||||
.value("RADGalaxy_FFG_Zynq", ChipID::RADGalaxy_FFG_Zynq)
|
||||
.value("RADMoon3_MCHIP", ChipID::RADMoon3_MCHIP)
|
||||
.value("RADComet2_ZYNQ", ChipID::RADComet2_ZYNQ)
|
||||
.value("VEM_02_FR_ZCHIP", ChipID::VEM_02_FR_ZCHIP)
|
||||
.value("RADA2B_REVB_ZCHIP", ChipID::RADA2B_REVB_ZCHIP)
|
||||
.value("RADGigastar_FFG_ZYNQ", ChipID::RADGigastar_FFG_ZYNQ)
|
||||
.value("VEM_02_FR_FCHIP", ChipID::VEM_02_FR_FCHIP)
|
||||
.value("Connect_ZCHIP", ChipID::Connect_ZCHIP)
|
||||
.value("SFPModule_88q2221_MCHIP", ChipID::SFPModule_88q2221_MCHIP)
|
||||
.value("RADGALAXY2_SYSMON_CHIP", ChipID::RADGALAXY2_SYSMON_CHIP)
|
||||
.value("SFPModule_88q3244_MCHIP", ChipID::SFPModule_88q3244_MCHIP)
|
||||
.value("RADCOMET3_ZCHIP", ChipID::RADCOMET3_ZCHIP)
|
||||
.value("Connect_LINUX", ChipID::Connect_LINUX)
|
||||
.value("SFPModule_lan8670_MCHIP", ChipID::SFPModule_lan8670_MCHIP)
|
||||
.value("RADGigastar2_ZYNQ", ChipID::RADGigastar2_ZYNQ)
|
||||
.value("SFPModule_ent11100_MCHIP", ChipID::SFPModule_ent11100_MCHIP)
|
||||
.value("RADGemini_MCHIP", ChipID::RADGemini_MCHIP)
|
||||
.value("Invalid", ChipID::Invalid)
|
||||
.finalize();
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
@@ -0,0 +1,79 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
#include <pybind11/chrono.h>
|
||||
|
||||
#include "icsneo/device/device.h"
|
||||
#include "icsneo/device/extensions/deviceextension.h"
|
||||
#include "icsneo/disk/diskdetails.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_device(pybind11::module_& m) {
|
||||
pybind11::classh<Device>(m, "Device")
|
||||
.def("__repr__", &Device::describe)
|
||||
.def("add_message_callback", &Device::addMessageCallback, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("clear_script", &Device::clearScript, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("close", &Device::close, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("describe", &Device::describe)
|
||||
.def("disable_message_polling", &Device::disableMessagePolling, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("enable_message_polling", &Device::enableMessagePolling, pybind11::arg("filter") = std::nullopt, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_current_message_count", &Device::getCurrentMessageCount)
|
||||
.def("get_digital_io", &Device::getDigitalIO, pybind11::arg("type"), pybind11::arg("number"), pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_extension", static_cast<std::shared_ptr<DeviceExtension>(Device::*)(const std::string&) const>(&Device::getExtension)) // This has to be static_casted rather than overload_casted because DeviceExtension is forward declared in device.h
|
||||
.def("get_flexray_controllers", &Device::getFlexRayControllers)
|
||||
.def("get_gptp_status", &Device::getGPTPStatus, pybind11::arg("timeout") = std::chrono::milliseconds(100), pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_messages", [](Device& device) { return device.getMessages(); }, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_polling_message_limit", &Device::getPollingMessageLimit)
|
||||
.def("get_product_name", &Device::getProductName)
|
||||
.def("get_rtc", &Device::getRTC, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_script_status", &Device::getScriptStatus, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_serial_number", &Device::getSerialNumber)
|
||||
.def("get_serial", &Device::getSerial)
|
||||
.def("get_pcb_serial", &Device::getPCBSerial, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_mac_addresses", &Device::getMACAddresses, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_supported_rx_networks", &Device::getSupportedRXNetworks, pybind11::return_value_policy::reference)
|
||||
.def("get_supported_tx_networks", &Device::getSupportedTXNetworks, pybind11::return_value_policy::reference)
|
||||
.def("get_tc10_status", &Device::getTC10Status, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_type", &Device::getType)
|
||||
.def("go_offline", &Device::goOffline, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("go_online", &Device::goOnline, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("is_message_polling_enabled", &Device::isMessagePollingEnabled)
|
||||
.def("is_online_supported", &Device::isOnlineSupported)
|
||||
.def("is_online", &Device::isOnline)
|
||||
.def("is_open", &Device::isOpen)
|
||||
.def("open", [](Device& device) { return device.open(); }, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("prepare_script_load", &Device::prepareScriptLoad, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("remove_message_callback", &Device::removeMessageCallback, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("request_tc10_sleep", &Device::requestTC10Sleep, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("request_tc10_wake", &Device::requestTC10Wake, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_digital_io", pybind11::overload_cast<IO, size_t, bool>(&Device::setDigitalIO), pybind11::arg("type"), pybind11::arg("number"), pybind11::arg("value"), pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_polling_message_limit", &Device::setPollingMessageLimit)
|
||||
.def("set_rtc", &Device::setRTC, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("reboot", &Device::reboot, pybind11::arg("safe") = false, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("start_script", &Device::startScript, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("stop_script", &Device::stopScript, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("supports_tc10", &Device::supportsTC10)
|
||||
.def("supports_reboot", &Device::supportsReboot)
|
||||
.def("supports_live_data", &Device::supportsLiveData)
|
||||
.def("subscribe_live_data", &Device::subscribeLiveData, pybind11::arg("message"), pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("unsubscribe_live_data", &Device::unsubscribeLiveData, pybind11::arg("handle"), pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("clear_all_live_data", &Device::clearAllLiveData, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_value_live_data", &Device::setValueLiveData, pybind11::arg("message"), pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("transmit", pybind11::overload_cast<std::shared_ptr<Frame>>(&Device::transmit), pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("upload_coremini", [](Device& device, std::string& path, Disk::MemoryType memType) { std::ifstream ifs(path, std::ios::binary); return device.uploadCoremini(ifs, memType); }, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("write_macsec_config", &Device::writeMACsecConfig, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("send_eth_phy_msg", &Device::sendEthPhyMsg, pybind11::arg("message"), pybind11::arg("timeout") = std::chrono::milliseconds(50), pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_chip_versions", &Device::getChipVersions, pybind11::arg("refreshComponents") = true, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("supports_disk_formatting", &Device::supportsDiskFormatting, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_disk_count", &Device::getDiskCount, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_disk_details", &Device::getDiskDetails, pybind11::arg("timeout") = std::chrono::milliseconds(100), pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("force_disk_config_update", &Device::forceDiskConfigUpdate, pybind11::arg("config"), pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("format_disk", [](Device& device, const DiskDetails& config) -> bool { return device.formatDisk(config); }, pybind11::arg("config"), pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def_readonly("settings", &Device::settings);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
#include <pybind11/native_enum.h>
|
||||
|
||||
#include "icsneo/device/devicetype.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_devicetype(pybind11::module_& m) {
|
||||
pybind11::classh<DeviceType> deviceType(m, "DeviceType");
|
||||
pybind11::native_enum<DeviceType::Enum>(deviceType, "Enum", "enum.IntEnum")
|
||||
.value("Unknown", DeviceType::Enum::Unknown)
|
||||
.value("BLUE", DeviceType::Enum::BLUE)
|
||||
.value("ECU_AVB", DeviceType::Enum::ECU_AVB)
|
||||
.value("RADSupermoon", DeviceType::Enum::RADSupermoon)
|
||||
.value("DW_VCAN", DeviceType::Enum::DW_VCAN)
|
||||
.value("RADMoon2", DeviceType::Enum::RADMoon2)
|
||||
.value("RADMars", DeviceType::Enum::RADMars)
|
||||
.value("VCAN4_1", DeviceType::Enum::VCAN4_1)
|
||||
.value("FIRE", DeviceType::Enum::FIRE)
|
||||
.value("RADPluto", DeviceType::Enum::RADPluto)
|
||||
.value("VCAN4_2EL", DeviceType::Enum::VCAN4_2EL)
|
||||
.value("RADIO_CANHUB", DeviceType::Enum::RADIO_CANHUB)
|
||||
.value("NEOECU12", DeviceType::Enum::NEOECU12)
|
||||
.value("OBD2_LCBADGE", DeviceType::Enum::OBD2_LCBADGE)
|
||||
.value("RADMoonDuo", DeviceType::Enum::RADMoonDuo)
|
||||
.value("FIRE3", DeviceType::Enum::FIRE3)
|
||||
.value("VCAN3", DeviceType::Enum::VCAN3)
|
||||
.value("RADJupiter", DeviceType::Enum::RADJupiter)
|
||||
.value("VCAN4_IND", DeviceType::Enum::VCAN4_IND)
|
||||
.value("RADGigastar", DeviceType::Enum::RADGigastar)
|
||||
.value("RED2", DeviceType::Enum::RED2)
|
||||
.value("EtherBADGE", DeviceType::Enum::EtherBADGE)
|
||||
.value("RAD_A2B", DeviceType::Enum::RAD_A2B)
|
||||
.value("RADEpsilon", DeviceType::Enum::RADEpsilon)
|
||||
.value("RADEpsilonXL", DeviceType::Enum::RADEpsilonXL)
|
||||
.value("RADGalaxy2", DeviceType::Enum::RADGalaxy2)
|
||||
.value("RADwBMS", DeviceType::Enum::RADwBMS)
|
||||
.value("RADMoon3", DeviceType::Enum::RADMoon3)
|
||||
.value("RADGemini", DeviceType::Enum::RADGemini)
|
||||
.value("RADComet2", DeviceType::Enum::RADComet2)
|
||||
.value("FIRE3_FlexRay", DeviceType::Enum::FIRE3_FlexRay)
|
||||
.value("FIRE3_T1S_LIN", DeviceType::Enum::FIRE3_T1S_LIN)
|
||||
.value("FIRE3_T1S_SENT", DeviceType::Enum::FIRE3_T1S_SENT)
|
||||
.value("Connect", DeviceType::Enum::Connect)
|
||||
.value("RADComet3", DeviceType::Enum::RADComet3)
|
||||
.value("RADMoonT1S", DeviceType::Enum::RADMoonT1S)
|
||||
.value("RADGigastar2", DeviceType::Enum::RADGigastar2)
|
||||
.value("RED", DeviceType::Enum::RED)
|
||||
.value("ECU", DeviceType::Enum::ECU)
|
||||
.value("IEVB", DeviceType::Enum::IEVB)
|
||||
.value("Pendant", DeviceType::Enum::Pendant)
|
||||
.value("OBD2_PRO", DeviceType::Enum::OBD2_PRO)
|
||||
.value("ECUChip_UART", DeviceType::Enum::ECUChip_UART)
|
||||
.value("PLASMA", DeviceType::Enum::PLASMA)
|
||||
.value("DONT_REUSE0", DeviceType::Enum::DONT_REUSE0)
|
||||
.value("NEOAnalog", DeviceType::Enum::NEOAnalog)
|
||||
.value("CT_OBD", DeviceType::Enum::CT_OBD)
|
||||
.value("DONT_REUSE1", DeviceType::Enum::DONT_REUSE1)
|
||||
.value("DONT_REUSE2", DeviceType::Enum::DONT_REUSE2)
|
||||
.value("ION", DeviceType::Enum::ION)
|
||||
.value("RADStar", DeviceType::Enum::RADStar)
|
||||
.value("DONT_REUSE3", DeviceType::Enum::DONT_REUSE3)
|
||||
.value("VCAN4_4", DeviceType::Enum::VCAN4_4)
|
||||
.value("VCAN4_2", DeviceType::Enum::VCAN4_2)
|
||||
.value("CMProbe", DeviceType::Enum::CMProbe)
|
||||
.value("EEVB", DeviceType::Enum::EEVB)
|
||||
.value("VCANrf", DeviceType::Enum::VCANrf)
|
||||
.value("FIRE2", DeviceType::Enum::FIRE2)
|
||||
.value("Flex", DeviceType::Enum::Flex)
|
||||
.value("RADGalaxy", DeviceType::Enum::RADGalaxy)
|
||||
.value("RADStar2", DeviceType::Enum::RADStar2)
|
||||
.value("VividCAN", DeviceType::Enum::VividCAN)
|
||||
.value("OBD2_SIM", DeviceType::Enum::OBD2_SIM)
|
||||
.finalize();
|
||||
deviceType.def(pybind11::init<DeviceType::Enum>());
|
||||
deviceType.def("get_device_type", &DeviceType::getDeviceType);
|
||||
deviceType.def("get_generic_product_name", &DeviceType::getGenericProductName);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/device/extensions/deviceextension.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_deviceextension(pybind11::module_& m) {
|
||||
pybind11::classh<DeviceExtension>(m, "DeviceExtension")
|
||||
.def("get_name", &DeviceExtension::getName);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
@@ -0,0 +1,164 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/stl_bind.h>
|
||||
#include <pybind11/functional.h>
|
||||
#include <pybind11/chrono.h>
|
||||
|
||||
#include "icsneo/device/idevicesettings.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
struct DeviceSettingsNamespace {
|
||||
using EthLinkMode = AELinkMode;
|
||||
};
|
||||
|
||||
void init_idevicesettings(pybind11::module_& m) {
|
||||
pybind11::classh<DeviceSettingsNamespace> settings(m, "Settings");
|
||||
|
||||
pybind11::enum_<DeviceSettingsNamespace::EthLinkMode>(settings, "EthernetLinkMode")
|
||||
.value("Auto", DeviceSettingsNamespace::EthLinkMode::AE_LINK_AUTO)
|
||||
.value("Slave", DeviceSettingsNamespace::EthLinkMode::AE_LINK_SLAVE)
|
||||
.value("Master", DeviceSettingsNamespace::EthLinkMode::AE_LINK_MASTER);
|
||||
|
||||
pybind11::enum_<EthPhyLinkMode>(settings, "PhyLinkMode")
|
||||
.value("ETH_LINK_MODE_AUTO_NEGOTIATION", ETH_LINK_MODE_AUTO_NEGOTIATION)
|
||||
.value("ETH_LINK_MODE_10MBPS_HALFDUPLEX", ETH_LINK_MODE_10MBPS_HALFDUPLEX)
|
||||
.value("ETH_LINK_MODE_10MBPS_FULLDUPLEX", ETH_LINK_MODE_10MBPS_FULLDUPLEX)
|
||||
.value("ETH_LINK_MODE_100MBPS_HALFDUPLEX", ETH_LINK_MODE_100MBPS_HALFDUPLEX)
|
||||
.value("ETH_LINK_MODE_100MBPS_FULLDUPLEX", ETH_LINK_MODE_100MBPS_FULLDUPLEX)
|
||||
.value("ETH_LINK_MODE_1GBPS_HALFDUPLEX", ETH_LINK_MODE_1GBPS_HALFDUPLEX)
|
||||
.value("ETH_LINK_MODE_1GBPS_FULLDUPLEX", ETH_LINK_MODE_1GBPS_FULLDUPLEX)
|
||||
.value("ETH_LINK_MODE_2_5GBPS_FULLDUPLEX", ETH_LINK_MODE_2_5GBPS_FULLDUPLEX)
|
||||
.value("ETH_LINK_MODE_5GBPS_FULLDUPLEX", ETH_LINK_MODE_5GBPS_FULLDUPLEX)
|
||||
.value("ETH_LINK_MODE_10GBPS_FULLDUPLEX", ETH_LINK_MODE_10GBPS_FULLDUPLEX);
|
||||
|
||||
pybind11::enum_<LINMode>(settings, "LINMode")
|
||||
.value("Sleep", LINMode::SLEEP_MODE)
|
||||
.value("Slow", LINMode::SLOW_MODE)
|
||||
.value("Normal", LINMode::NORMAL_MODE)
|
||||
.value("Fast", LINMode::FAST_MODE);
|
||||
|
||||
pybind11::enum_<RADGPTPProfile>(settings, "GPTPProfile")
|
||||
.value("Standard", RADGPTPProfile::RAD_GPTP_PROFILE_STANDARD)
|
||||
.value("Automotive", RADGPTPProfile::RAD_GPTP_PROFILE_AUTOMOTIVE);
|
||||
|
||||
pybind11::enum_<RADGPTPRole>(settings, "GPTPRole")
|
||||
.value("Disabled", RADGPTPRole::RAD_GPTP_ROLE_DISABLED)
|
||||
.value("Passive", RADGPTPRole::RAD_GPTP_ROLE_PASSIVE)
|
||||
.value("Master", RADGPTPRole::RAD_GPTP_ROLE_MASTER)
|
||||
.value("Slave", RADGPTPRole::RAD_GPTP_ROLE_SLAVE);
|
||||
|
||||
pybind11::enum_<MiscIOAnalogVoltage>(settings, "MiscIOAnalogVoltage")
|
||||
.value("V0", MiscIOAnalogVoltage::V0)
|
||||
.value("V1", MiscIOAnalogVoltage::V1)
|
||||
.value("V2", MiscIOAnalogVoltage::V2)
|
||||
.value("V3", MiscIOAnalogVoltage::V3)
|
||||
.value("V4", MiscIOAnalogVoltage::V4)
|
||||
.value("V5", MiscIOAnalogVoltage::V5);
|
||||
|
||||
pybind11::enum_<LinuxConfigurationPort>(settings, "LinuxConfigurationPort")
|
||||
.value("USB", LinuxConfigurationPort::USB)
|
||||
.value("ETH01", LinuxConfigurationPort::ETH01);
|
||||
|
||||
pybind11::classh<IDeviceSettings>(m, "IDeviceSettings")
|
||||
.def("apply", &IDeviceSettings::apply, pybind11::arg("temporary") = 0, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("apply_defaults", &IDeviceSettings::applyDefaults, pybind11::arg("temporary") = 0, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("refresh", &IDeviceSettings::refresh, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
|
||||
// Baudrate methods
|
||||
.def("get_baudrate", &IDeviceSettings::getBaudrateFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_baudrate", &IDeviceSettings::setBaudrateFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_fd_baudrate", &IDeviceSettings::getFDBaudrateFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_fd_baudrate", &IDeviceSettings::setFDBaudrateFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
|
||||
// Termination methods
|
||||
.def("is_termination_supported", &IDeviceSettings::isTerminationSupportedFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("can_termination_be_enabled", &IDeviceSettings::canTerminationBeEnabledFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("is_termination_enabled", &IDeviceSettings::isTerminationEnabledFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_termination", &IDeviceSettings::setTerminationFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_termination_groups", &IDeviceSettings::getTerminationGroups, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
|
||||
// LIN methods
|
||||
.def("is_commander_resistor_enabled", &IDeviceSettings::isCommanderResistorEnabledFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_commander_resistor", &IDeviceSettings::setCommanderResistorFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_lin_mode", &IDeviceSettings::getLINModeFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_lin_mode", &IDeviceSettings::setLINModeFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_lin_commander_response_time", &IDeviceSettings::getLINCommanderResponseTimeFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_lin_commander_response_time", &IDeviceSettings::setLINCommanderResponseTimeFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
|
||||
// Ethernet PHY methods (index-based for switch devices)
|
||||
.def("get_phy_enable", &IDeviceSettings::getPhyEnable, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_phy_mode", &IDeviceSettings::getPhyMode, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_phy_speed", &IDeviceSettings::getPhySpeed, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_phy_enable", &IDeviceSettings::setPhyEnable, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_phy_mode", &IDeviceSettings::setPhyMode, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_phy_speed", &IDeviceSettings::setPhySpeed, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
|
||||
// Ethernet PHY methods (network-based for multi-interface devices)
|
||||
.def("get_phy_enable_for", &IDeviceSettings::getPhyEnableFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_phy_role_for", &IDeviceSettings::getPhyRoleFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_phy_link_mode_for", &IDeviceSettings::getPhyLinkModeFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_phy_enable_for", &IDeviceSettings::setPhyEnableFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_phy_role_for", &IDeviceSettings::setPhyRoleFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_phy_link_mode_for", &IDeviceSettings::setPhyLinkModeFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_supported_phy_link_modes_for", &IDeviceSettings::getSupportedPhyLinkModesFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
|
||||
// 10BASE-T1S methods
|
||||
.def("is_t1s_plca_enabled", &IDeviceSettings::isT1SPLCAEnabledFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_t1s_plca", &IDeviceSettings::setT1SPLCAFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_t1s_local_id", &IDeviceSettings::getT1SLocalIDFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_t1s_local_id", &IDeviceSettings::setT1SLocalIDFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_t1s_max_nodes", &IDeviceSettings::getT1SMaxNodesFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_t1s_max_nodes", &IDeviceSettings::setT1SMaxNodesFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_t1s_tx_opp_timer", &IDeviceSettings::getT1STxOppTimerFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_t1s_tx_opp_timer", &IDeviceSettings::setT1STxOppTimerFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_t1s_max_burst", &IDeviceSettings::getT1SMaxBurstFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_t1s_max_burst", &IDeviceSettings::setT1SMaxBurstFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_t1s_burst_timer", &IDeviceSettings::getT1SBurstTimerFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_t1s_burst_timer", &IDeviceSettings::setT1SBurstTimerFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_t1s_local_id_alternate", &IDeviceSettings::getT1SLocalIDAlternateFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_t1s_local_id_alternate", &IDeviceSettings::setT1SLocalIDAlternateFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("is_t1s_termination_enabled", &IDeviceSettings::isT1STerminationEnabledFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_t1s_termination", &IDeviceSettings::setT1STerminationFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("is_t1s_bus_decoding_beacons_enabled", &IDeviceSettings::isT1SBusDecodingBeaconsEnabledFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_t1s_bus_decoding_beacons", &IDeviceSettings::setT1SBusDecodingBeaconsFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("is_t1s_bus_decoding_all_enabled", &IDeviceSettings::isT1SBusDecodingAllEnabledFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_t1s_bus_decoding_all", &IDeviceSettings::setT1SBusDecodingAllFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_t1s_multi_id_enable_mask", &IDeviceSettings::getT1SMultiIDEnableMaskFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_t1s_multi_id_enable_mask", &IDeviceSettings::setT1SMultiIDEnableMaskFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_t1s_multi_id", &IDeviceSettings::getT1SMultiIDFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_t1s_multi_id", &IDeviceSettings::setT1SMultiIDFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
|
||||
.def("set_misc_io_analog_output_enabled", &IDeviceSettings::setMiscIOAnalogOutputEnabled, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_misc_io_analog_output", &IDeviceSettings::setMiscIOAnalogOutput, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
|
||||
// Performance blast
|
||||
.def("is_perf_test_enabled", &IDeviceSettings::isPerfTestEnabled, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_perf_test_enable", &IDeviceSettings::setPerfTestEnable, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
// gPTP methods
|
||||
.def("get_gptp_profile", &IDeviceSettings::getGPTPProfile, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_gptp_profile", &IDeviceSettings::setGPTPProfile, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_gptp_role", &IDeviceSettings::getGPTPRole, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_gptp_role", &IDeviceSettings::setGPTPRole, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_gptp_enabled_port", &IDeviceSettings::getGPTPEnabledPort, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_gptp_enabled_port", &IDeviceSettings::setGPTPEnabledPort, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("is_gptp_clock_syntonization_enabled", &IDeviceSettings::isGPTPClockSyntonizationEnabled, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_gptp_clock_syntonization_enabled", &IDeviceSettings::setGPTPClockSyntonizationEnabled, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
|
||||
// Linux operating-system settings (Fire3 family devices)
|
||||
.def("get_linux_boot_enabled", &IDeviceSettings::getLinuxBootEnabled, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_linux_boot_enabled", &IDeviceSettings::setLinuxBootEnabled, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_external_wifi_antenna_enabled", &IDeviceSettings::getExternalWifiAntennaEnabled, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_external_wifi_antenna_enabled", &IDeviceSettings::setExternalWifiAntennaEnabled, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("get_linux_configuration_port", &IDeviceSettings::getLinuxConfigurationPort, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
.def("set_linux_configuration_port", &IDeviceSettings::setLinuxConfigurationPort, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||
|
||||
// Status properties
|
||||
.def_readonly("disabled", &IDeviceSettings::disabled)
|
||||
.def_readonly("readonly", &IDeviceSettings::readonly);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/device/versionreport.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_versionreport(pybind11::module_& m) {
|
||||
pybind11::classh<VersionReport>(m, "VersionReport")
|
||||
.def_readonly("id", &VersionReport::id)
|
||||
.def_readonly("name", &VersionReport::name)
|
||||
.def_readonly("major", &VersionReport::major)
|
||||
.def_readonly("minor", &VersionReport::minor)
|
||||
.def_readonly("maintenance", &VersionReport::maintenance)
|
||||
.def_readonly("build", &VersionReport::build);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
@@ -0,0 +1,29 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
|
||||
#include "icsneo/disk/diskdetails.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_diskdetails(pybind11::module_& m) {
|
||||
pybind11::enum_<DiskLayout>(m, "DiskLayout")
|
||||
.value("Spanned", DiskLayout::Spanned)
|
||||
.value("RAID0", DiskLayout::RAID0);
|
||||
|
||||
pybind11::classh<DiskInfo>(m, "DiskInfo")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("present", &DiskInfo::present)
|
||||
.def_readwrite("initialized", &DiskInfo::initialized)
|
||||
.def_readwrite("formatted", &DiskInfo::formatted)
|
||||
.def_readwrite("sectors", &DiskInfo::sectors)
|
||||
.def_readwrite("bytes_per_sector", &DiskInfo::bytesPerSector)
|
||||
.def("size", &DiskInfo::size);
|
||||
|
||||
pybind11::classh<DiskDetails>(m, "DiskDetails")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("layout", &DiskDetails::layout)
|
||||
.def_readwrite("full_format", &DiskDetails::fullFormat)
|
||||
.def_readwrite("disks", &DiskDetails::disks);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
@@ -0,0 +1,26 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/disk/diskdriver.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
// binding namespace workaround to avoid submodules
|
||||
struct DiskNamespace {
|
||||
using Access = icsneo::Disk::Access;
|
||||
using MemoryType = icsneo::Disk::MemoryType;
|
||||
};
|
||||
|
||||
void init_diskdriver(pybind11::module_& m) {
|
||||
pybind11::classh<DiskNamespace> disk(m, "Disk");
|
||||
pybind11::enum_<Disk::Access>(disk, "Access")
|
||||
.value("None", Disk::Access::None)
|
||||
.value("EntireCard", Disk::Access::EntireCard)
|
||||
.value("VSA", Disk::Access::VSA);
|
||||
pybind11::enum_<Disk::MemoryType>(disk, "MemoryType")
|
||||
.value("Flash", Disk::MemoryType::Flash)
|
||||
.value("SD", Disk::MemoryType::SD);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
@@ -0,0 +1,195 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/communication/message/flexray/flexraymessage.h"
|
||||
#include "icsneo/device/extensions/flexray/symbol.h"
|
||||
#include "icsneo/device/extensions/flexray/channel.h"
|
||||
#include "icsneo/device/extensions/flexray/crcstatus.h"
|
||||
#include "icsneo/device/extensions/flexray/controller.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
struct FlexRayNamespace {
|
||||
using Symbol = icsneo::FlexRay::Symbol;
|
||||
using CRCStatus = icsneo::FlexRay::CRCStatus;
|
||||
using Channel = icsneo::FlexRay::Channel;
|
||||
};
|
||||
|
||||
namespace FlexRay {
|
||||
|
||||
struct ClusterNamespace {
|
||||
using SpeedType = icsneo::FlexRay::Cluster::SpeedType;
|
||||
using SPPType = icsneo::FlexRay::Cluster::SPPType;
|
||||
};
|
||||
|
||||
void init_extension(pybind11::classh<FlexRayNamespace>& c) {
|
||||
pybind11::classh<MessageBuffer>(c, "MessageBuffer")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("is_dynamic", &MessageBuffer::isDynamic)
|
||||
.def_readwrite("is_sync", &MessageBuffer::isSync)
|
||||
.def_readwrite("is_startup", &MessageBuffer::isStartup)
|
||||
.def_readwrite("is_network_management_frame", &MessageBuffer::isNetworkManagementFrame)
|
||||
.def_readwrite("is_transmit", &MessageBuffer::isTransmit)
|
||||
.def_readwrite("frame_id", &MessageBuffer::frameID)
|
||||
.def_readwrite("channel_a", &MessageBuffer::channelA)
|
||||
.def_readwrite("channel_b", &MessageBuffer::channelB)
|
||||
.def_readwrite("frame_length_bytes", &MessageBuffer::frameLengthBytes)
|
||||
.def_readwrite("base_cycle", &MessageBuffer::baseCycle)
|
||||
.def_readwrite("cycle_repetition", &MessageBuffer::cycleRepetition)
|
||||
.def_readwrite("continuous_mode", &MessageBuffer::continuousMode);
|
||||
|
||||
auto controller = pybind11::classh<Controller>(c, "Controller")
|
||||
.def("get_network", &Controller::getNetwork)
|
||||
.def("get_configuration", &Controller::getConfiguration)
|
||||
.def("set_configuration", &Controller::setConfiguration)
|
||||
.def("get_start_when_going_online", &Controller::getStartWhenGoingOnline)
|
||||
.def("set_start_when_going_online", &Controller::setStartWhenGoingOnline)
|
||||
.def("get_allow_coldstart", &Controller::getAllowColdstart)
|
||||
.def("set_allow_coldstart", &Controller::setAllowColdstart)
|
||||
.def("get_wakeup_before_start", &Controller::getWakeupBeforeStart)
|
||||
.def("set_wakeup_before_start", &Controller::setWakeupBeforeStart)
|
||||
.def("add_message_buffer", &Controller::addMessageBuffer)
|
||||
.def("clear_message_buffers", &Controller::clearMessageBuffers)
|
||||
.def("wakeup", &Controller::wakeup)
|
||||
.def("configure", &Controller::getReady)
|
||||
.def("start", &Controller::start)
|
||||
.def("transmit", &Controller::transmit)
|
||||
.def("halt", &Controller::halt)
|
||||
.def("freeze", &Controller::freeze)
|
||||
.def("trigger_mts", &Controller::triggerMTS);
|
||||
|
||||
pybind11::classh<Controller::Configuration>(controller, "Configuration")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("accept_startup_range_microticks", &Controller::Configuration::AcceptStartupRangeMicroticks)
|
||||
.def_readwrite("allow_passive_to_active_cycle_pairs", &Controller::Configuration::AllowPassiveToActiveCyclePairs)
|
||||
.def_readwrite("cluster_drift_damping", &Controller::Configuration::ClusterDriftDamping)
|
||||
.def_readwrite("allow_halt_due_to_clock", &Controller::Configuration::AllowHaltDueToClock)
|
||||
.def_readwrite("channel_a", &Controller::Configuration::ChannelA)
|
||||
.def_readwrite("channel_b", &Controller::Configuration::ChannelB)
|
||||
.def_readwrite("decoding_correction_microticks", &Controller::Configuration::DecodingCorrectionMicroticks)
|
||||
.def_readwrite("delay_compensation_a_microticks", &Controller::Configuration::DelayCompensationAMicroticks)
|
||||
.def_readwrite("delay_compensation_b_microticks", &Controller::Configuration::DelayCompensationBMicroticks)
|
||||
.def_readwrite("extern_offset_correction_control", &Controller::Configuration::ExternOffsetCorrectionControl)
|
||||
.def_readwrite("extern_rate_correction_control", &Controller::Configuration::ExternRateCorrectionControl)
|
||||
.def_readwrite("extern_offset_correction_microticks", &Controller::Configuration::ExternOffsetCorrectionMicroticks)
|
||||
.def_readwrite("extern_rate_correction_microticks", &Controller::Configuration::ExternRateCorrectionMicroticks)
|
||||
.def_readwrite("key_slot_id", &Controller::Configuration::KeySlotID)
|
||||
.def_readwrite("key_slot_only_enabled", &Controller::Configuration::KeySlotOnlyEnabled)
|
||||
.def_readwrite("key_slot_used_for_startup", &Controller::Configuration::KeySlotUsedForStartup)
|
||||
.def_readwrite("key_slot_used_for_sync", &Controller::Configuration::KeySlotUsedForSync)
|
||||
.def_readwrite("latest_tx_minislot", &Controller::Configuration::LatestTxMinislot)
|
||||
.def_readwrite("listen_timeout", &Controller::Configuration::ListenTimeout)
|
||||
.def_readwrite("macro_initial_offset_a", &Controller::Configuration::MacroInitialOffsetA)
|
||||
.def_readwrite("macro_initial_offset_b", &Controller::Configuration::MacroInitialOffsetB)
|
||||
.def_readwrite("micro_initial_offset_a", &Controller::Configuration::MicroInitialOffsetA)
|
||||
.def_readwrite("micro_initial_offset_b", &Controller::Configuration::MicroInitialOffsetB)
|
||||
.def_readwrite("micro_per_cycle", &Controller::Configuration::MicroPerCycle)
|
||||
.def_readwrite("mts_on_a", &Controller::Configuration::MTSOnA)
|
||||
.def_readwrite("mts_on_b", &Controller::Configuration::MTSOnB)
|
||||
.def_readwrite("offset_correction_out_microticks", &Controller::Configuration::OffsetCorrectionOutMicroticks)
|
||||
.def_readwrite("rate_correction_out_microticks", &Controller::Configuration::RateCorrectionOutMicroticks)
|
||||
.def_readwrite("second_key_slot_id", &Controller::Configuration::SecondKeySlotID)
|
||||
.def_readwrite("two_key_slot_mode", &Controller::Configuration::TwoKeySlotMode)
|
||||
.def_readwrite("wakeup_pattern", &Controller::Configuration::WakeupPattern)
|
||||
.def_readwrite("wakeup_on_channel_b", &Controller::Configuration::WakeupOnChannelB);
|
||||
|
||||
// Dummy class for cluster namespace
|
||||
pybind11::classh<ClusterNamespace> cluster(c, "Cluster");
|
||||
|
||||
pybind11::enum_<Cluster::SpeedType>(cluster, "SpeedType")
|
||||
.value("FLEXRAY_BAUDRATE_10M", Cluster::SpeedType::FLEXRAY_BAUDRATE_10M)
|
||||
.value("FLEXRAY_BAUDRATE_5M", Cluster::SpeedType::FLEXRAY_BAUDRATE_5M)
|
||||
.value("FLEXRAY_BAUDRATE_2M5", Cluster::SpeedType::FLEXRAY_BAUDRATE_2M5)
|
||||
.value("FLEXRAY_BAUDRATE_2M5_ALT", Cluster::SpeedType::FLEXRAY_BAUDRATE_2M5_ALT);
|
||||
|
||||
pybind11::enum_<Cluster::SPPType>(cluster, "SPPType")
|
||||
.value("FLEXRAY_SPP_5", Cluster::SPPType::FLEXRAY_SPP_5)
|
||||
.value("FLEXRAY_SPP_4", Cluster::SPPType::FLEXRAY_SPP_4)
|
||||
.value("FLEXRAY_SPP_6", Cluster::SPPType::FLEXRAY_SPP_6)
|
||||
.value("FLEXRAY_SPP_5_ALT", Cluster::SPPType::FLEXRAY_SPP_5_ALT);
|
||||
|
||||
pybind11::classh<Cluster::Configuration>(cluster, "Configuration")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("speed", &Cluster::Configuration::Speed)
|
||||
.def_readwrite("strobe_point_position", &Cluster::Configuration::StrobePointPosition)
|
||||
.def_readwrite("action_point_offset", &Cluster::Configuration::ActionPointOffset)
|
||||
.def_readwrite("casr_x_low_max", &Cluster::Configuration::CASRxLowMax)
|
||||
.def_readwrite("cold_start_attempts", &Cluster::Configuration::ColdStartAttempts)
|
||||
.def_readwrite("cycle_duration_micro_sec", &Cluster::Configuration::CycleDurationMicroSec)
|
||||
.def_readwrite("dynamic_slot_idle_phase_minislots", &Cluster::Configuration::DynamicSlotIdlePhaseMinislots)
|
||||
.def_readwrite("listen_noise_macroticks", &Cluster::Configuration::ListenNoiseMacroticks)
|
||||
.def_readwrite("macroticks_per_cycle", &Cluster::Configuration::MacroticksPerCycle)
|
||||
.def_readwrite("macrotick_duration_micro_sec", &Cluster::Configuration::MacrotickDurationMicroSec)
|
||||
.def_readwrite("max_without_clock_correction_fatal", &Cluster::Configuration::MaxWithoutClockCorrectionFatal)
|
||||
.def_readwrite("max_without_clock_correction_passive", &Cluster::Configuration::MaxWithoutClockCorrectionPassive)
|
||||
.def_readwrite("minislot_action_point_offset_macroticks", &Cluster::Configuration::MinislotActionPointOffsetMacroticks)
|
||||
.def_readwrite("minislot_duration_macroticks", &Cluster::Configuration::MinislotDurationMacroticks)
|
||||
.def_readwrite("network_idle_time_macroticks", &Cluster::Configuration::NetworkIdleTimeMacroticks)
|
||||
.def_readwrite("network_management_vector_length_bytes", &Cluster::Configuration::NetworkManagementVectorLengthBytes)
|
||||
.def_readwrite("number_of_minislots", &Cluster::Configuration::NumberOfMinislots)
|
||||
.def_readwrite("number_of_static_slots", &Cluster::Configuration::NumberOfStaticSlots)
|
||||
.def_readwrite("offset_correction_start_macroticks", &Cluster::Configuration::OffsetCorrectionStartMacroticks)
|
||||
.def_readwrite("payload_length_of_static_slot_in_words", &Cluster::Configuration::PayloadLengthOfStaticSlotInWords)
|
||||
.def_readwrite("static_slot_macroticks", &Cluster::Configuration::StaticSlotMacroticks)
|
||||
.def_readwrite("symbol_window_macroticks", &Cluster::Configuration::SymbolWindowMacroticks)
|
||||
.def_readwrite("symbol_window_action_point_offset_macroticks", &Cluster::Configuration::SymbolWindowActionPointOffsetMacroticks)
|
||||
.def_readwrite("sync_frame_id_count_max", &Cluster::Configuration::SyncFrameIDCountMax)
|
||||
.def_readwrite("transmission_start_sequence_duration_bits", &Cluster::Configuration::TransmissionStartSequenceDurationBits)
|
||||
.def_readwrite("wakeup_rx_idle_bits", &Cluster::Configuration::WakeupRxIdleBits)
|
||||
.def_readwrite("wakeup_rx_low_bits", &Cluster::Configuration::WakeupRxLowBits)
|
||||
.def_readwrite("wakeup_rx_window_bits", &Cluster::Configuration::WakeupRxWindowBits)
|
||||
.def_readwrite("wakeup_tx_active_bits", &Cluster::Configuration::WakeupTxActiveBits)
|
||||
.def_readwrite("wakeup_tx_idle_bits", &Cluster::Configuration::WakeupTxIdleBits);
|
||||
}
|
||||
|
||||
} // namespace FlexRay
|
||||
|
||||
void init_flexraymessage(pybind11::module_& m) {
|
||||
pybind11::classh<FlexRayMessage, Frame>(m, "FlexRayMessage")
|
||||
.def(pybind11::init())
|
||||
.def_readwrite("slotid", &FlexRayMessage::slotid)
|
||||
.def_readwrite("tsslen", &FlexRayMessage::tsslen)
|
||||
.def_readwrite("framelen", &FlexRayMessage::framelen)
|
||||
.def_readwrite("symbol", &FlexRayMessage::symbol)
|
||||
.def_readwrite("header_crc_status", &FlexRayMessage::headerCRCStatus)
|
||||
.def_readwrite("header_crc", &FlexRayMessage::headerCRC)
|
||||
.def_readwrite("frame_crc_status", &FlexRayMessage::crcStatus)
|
||||
.def_readwrite("frame_crc", &FlexRayMessage::frameCRC)
|
||||
.def_readwrite("channel", &FlexRayMessage::channel)
|
||||
.def_readwrite("null_frame", &FlexRayMessage::nullFrame)
|
||||
.def_readwrite("payload_preamble", &FlexRayMessage::payloadPreamble)
|
||||
.def_readwrite("sync_frame", &FlexRayMessage::sync)
|
||||
.def_readwrite("startup_frame", &FlexRayMessage::startup)
|
||||
.def_readwrite("dynamic_frame", &FlexRayMessage::dynamic)
|
||||
.def_readwrite("cycle", &FlexRayMessage::cycle)
|
||||
.def_readwrite("cycle_repetition", &FlexRayMessage::cycleRepetition);
|
||||
|
||||
//// TODO: Eliminate FlexRayControlMessage class references in controller class and eliminate getStatus function in bindings
|
||||
}
|
||||
|
||||
void init_flexray(pybind11::module_& m) {
|
||||
// Dummy class to act as FlexRay namespace
|
||||
pybind11::classh<FlexRayNamespace> flexray(m, "FlexRay");
|
||||
|
||||
pybind11::enum_<FlexRayNamespace::Symbol>(flexray, "Symbol")
|
||||
.value("None", FlexRayNamespace::Symbol::None)
|
||||
.value("Unknown", FlexRayNamespace::Symbol::Unknown)
|
||||
.value("Wakeup", FlexRayNamespace::Symbol::Wakeup)
|
||||
.value("CAS", FlexRayNamespace::Symbol::CAS);
|
||||
pybind11::enum_<FlexRayNamespace::CRCStatus>(flexray, "CRCStatus")
|
||||
.value("OK", FlexRayNamespace::CRCStatus::OK)
|
||||
.value("Error", FlexRayNamespace::CRCStatus::Error)
|
||||
.value("NoCRC", FlexRayNamespace::CRCStatus::NoCRC);
|
||||
pybind11::enum_<FlexRayNamespace::Channel>(flexray, "Channel")
|
||||
.value("None", FlexRayNamespace::Channel::None)
|
||||
.value("A", FlexRayNamespace::Channel::A)
|
||||
.value("B", FlexRayNamespace::Channel::B)
|
||||
.value("AB", FlexRayNamespace::Channel::AB);
|
||||
|
||||
init_flexraymessage(m);
|
||||
FlexRay::init_extension(flexray);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/functional.h>
|
||||
|
||||
#include "icsneo/icsneocpp.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void init_event(pybind11::module_&);
|
||||
void init_eventcallback(pybind11::module_&);
|
||||
void init_eventmanager(pybind11::module_&);
|
||||
void init_network(pybind11::module_&);
|
||||
void init_io(pybind11::module_&);
|
||||
void init_devicetype(pybind11::module_&);
|
||||
void init_message(pybind11::module_&);
|
||||
void init_canmessage(pybind11::module_&);
|
||||
void init_canerrormessage(pybind11::module_&);
|
||||
void init_ethernetmessage(pybind11::module_&);
|
||||
void init_linmessage(pybind11::module_&);
|
||||
void init_tc10statusmessage(pybind11::module_&);
|
||||
void init_gptpstatusmessage(pybind11::module_&);
|
||||
void init_allmacaddressesmessage(pybind11::module_&);
|
||||
void init_apperrormessage(pybind11::module_&);
|
||||
void init_mdiomessage(pybind11::module_&);
|
||||
void init_spimessage(pybind11::module_&);
|
||||
void init_ethernetstatusmessage(pybind11::module_&);
|
||||
void init_macsecconfig(pybind11::module_&);
|
||||
void init_scriptstatusmessage(pybind11::module_&);
|
||||
void init_diskdriver(pybind11::module_&);
|
||||
void init_diskdetails(pybind11::module_&);
|
||||
void init_deviceextension(pybind11::module_&);
|
||||
void init_chipid(pybind11::module_&);
|
||||
void init_versionreport(pybind11::module_&);
|
||||
void init_device(pybind11::module_&);
|
||||
void init_messagefilter(pybind11::module_&);
|
||||
void init_messagecallback(pybind11::module_&);
|
||||
void init_version(pybind11::module_&);
|
||||
void init_flexray(pybind11::module_& m);
|
||||
void init_idevicesettings(pybind11::module_&);
|
||||
void init_ethphymessage(pybind11::module_&);
|
||||
void init_livedata(pybind11::module_&);
|
||||
void init_livedatamessage(pybind11::module_&);
|
||||
|
||||
PYBIND11_MODULE(icsneopy, m) {
|
||||
pybind11::options options;
|
||||
options.disable_enum_members_docstring();
|
||||
m.doc() = "libicsneo Python module";
|
||||
|
||||
init_event(m);
|
||||
init_eventcallback(m);
|
||||
init_eventmanager(m);
|
||||
init_version(m);
|
||||
init_devicetype(m);
|
||||
init_network(m);
|
||||
init_io(m);
|
||||
init_livedata(m);
|
||||
init_message(m);
|
||||
init_canmessage(m);
|
||||
init_canerrormessage(m);
|
||||
init_ethernetmessage(m);
|
||||
init_linmessage(m);
|
||||
init_tc10statusmessage(m);
|
||||
init_gptpstatusmessage(m);
|
||||
init_allmacaddressesmessage(m);
|
||||
init_apperrormessage(m);
|
||||
init_mdiomessage(m);
|
||||
init_ethernetstatusmessage(m);
|
||||
init_macsecconfig(m);
|
||||
init_scriptstatusmessage(m);
|
||||
init_spimessage(m);
|
||||
init_livedatamessage(m);
|
||||
init_messagefilter(m);
|
||||
init_messagecallback(m);
|
||||
init_diskdriver(m);
|
||||
init_diskdetails(m);
|
||||
init_flexray(m);
|
||||
init_ethphymessage(m);
|
||||
init_chipid(m);
|
||||
init_versionreport(m);
|
||||
init_device(m);
|
||||
init_deviceextension(m);
|
||||
init_idevicesettings(m);
|
||||
|
||||
m.def("find_all_devices", &FindAllDevices);
|
||||
m.def("get_supported_devices", &GetSupportedDevices);
|
||||
m.def("get_last_error", &GetLastError);
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
yum install -y flex ca-certificates || exit 1
|
||||
|
||||
echo "$ICS_IPA_CA_CRT" >/etc/pki/ca-trust/source/anchors/ica-ipa-ca.crt
|
||||
|
||||
update-ca-trust || exit 1
|
||||
@@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
|
||||
VERSION="1.10.5"
|
||||
ROOT="$PWD/libpcap"
|
||||
SOURCE="$ROOT/source"
|
||||
BUILD="$ROOT/build"
|
||||
INSTALL="$ROOT/install"
|
||||
|
||||
mkdir -p "$ROOT"
|
||||
cd "$ROOT" || exit 1
|
||||
|
||||
curl -LO "https://www.tcpdump.org/release/libpcap-$VERSION.tar.xz" || exit 1
|
||||
tar -xf "libpcap-$VERSION.tar.xz" || exit 1
|
||||
mv "libpcap-$VERSION" "$SOURCE" || exit 1
|
||||
|
||||
cmake -D CMAKE_POSITION_INDEPENDENT_CODE=ON -D CMAKE_INSTALL_PREFIX="$INSTALL" -D BUILD_SHARED_LIBS=OFF -D BUILD_WITH_LIBNL=OFF -D DISABLE_DBUS=ON -D DISABLE_LINUX_USBMON=ON -D DISABLE_BLUETOOTH=ON -D DISABLE_NETMAP=ON -D DISABLE_DPDK=ON -D DISABLE_RDMA=ON -D DISABLE_DAG=ON -D DISABLE_SEPTEL=ON -D DISABLE_SNF=ON -D DISABLE_TC=ON -B "$BUILD" -S "$SOURCE" || exit 1
|
||||
cmake --build "$BUILD" || exit 1
|
||||
cmake --install "$BUILD" || exit 1
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Release -DLIBICSNEO_BUILD_EXAMPLES=ON -DLIBICSNEO_BUILD_UNIT_TESTS=ON -DLIBICSNEO_ENABLE_TCP=OFF || exit 1
|
||||
|
||||
cmake --build build || exit 1
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
python3 -m venv env || exit 1
|
||||
. env/bin/activate || exit 1
|
||||
python3 -m pip install cibuildwheel || exit 1
|
||||
python3 -m cibuildwheel --output-dir wheelhouse || exit 1
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
@setlocal
|
||||
@echo off
|
||||
|
||||
call "%VCVARS64_2022%"
|
||||
|
||||
python.exe -m venv env || exit /b 1
|
||||
call env\Scripts\Activate.bat || exit /b 1
|
||||
python.exe -m pip install cibuildwheel || exit /b 1
|
||||
python.exe -m cibuildwheel --output-dir wheelhouse --platform windows || exit /b 1
|
||||
@@ -0,0 +1,8 @@
|
||||
@setlocal
|
||||
@echo off
|
||||
|
||||
mkdir build >nul 2>&1
|
||||
|
||||
cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Release -DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DLIBICSNEO_BUILD_UNIT_TESTS=ON-DLIBICSNEO_ENABLE_TCP=ON || exit /b 1
|
||||
|
||||
cmake --build build || exit /b 1
|
||||
@@ -0,0 +1,2 @@
|
||||
call "%VCVARS32_2022%"
|
||||
call "ci\build-windows.bat"
|
||||
@@ -0,0 +1,2 @@
|
||||
call "%VCVARS64_2022%"
|
||||
call "ci\build-windows.bat"
|
||||
+193
-34
@@ -12,17 +12,30 @@
|
||||
#include "icsneo/communication/message/serialnumbermessage.h"
|
||||
#include "icsneo/communication/message/filter/main51messagefilter.h"
|
||||
#include "icsneo/communication/message/readsettingsmessage.h"
|
||||
#include "icsneo/communication/message/versionmessage.h"
|
||||
#include "icsneo/communication/message/componentversionsmessage.h"
|
||||
#include "icsneo/communication/message/filter/extendedresponsefilter.h"
|
||||
#include "icsneo/communication/message/clientidmessage.h"
|
||||
#include "icsneo/communication/icspb.h"
|
||||
|
||||
#include <commands/generic/v1/client_id.pb.h>
|
||||
#include <commands/network/v1/mutex.pb.h>
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
int Communication::messageCallbackIDCounter = 1;
|
||||
|
||||
Communication::~Communication() {
|
||||
if(isOpen())
|
||||
close();
|
||||
}
|
||||
|
||||
bool Communication::open() {
|
||||
if(isOpen()) {
|
||||
report(APIEvent::Type::DeviceCurrentlyOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if(!driver->open())
|
||||
return false;
|
||||
spawnThreads();
|
||||
@@ -30,24 +43,28 @@ bool Communication::open() {
|
||||
}
|
||||
|
||||
void Communication::spawnThreads() {
|
||||
closing = false;
|
||||
readTaskThread = std::thread(&Communication::readTask, this);
|
||||
}
|
||||
|
||||
void Communication::joinThreads() {
|
||||
if(pauseReadTask) {
|
||||
resumeReads();
|
||||
}
|
||||
|
||||
closing = true;
|
||||
if(readTaskThread.joinable())
|
||||
readTaskThread.join();
|
||||
closing = false;
|
||||
}
|
||||
|
||||
bool Communication::close() {
|
||||
joinThreads();
|
||||
|
||||
if(!isOpen()) {
|
||||
if(!isOpen() && !isDisconnected()) {
|
||||
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
joinThreads();
|
||||
|
||||
return driver->close();
|
||||
}
|
||||
|
||||
@@ -55,6 +72,10 @@ bool Communication::isOpen() {
|
||||
return driver->isOpen();
|
||||
}
|
||||
|
||||
bool Communication::isDisconnected() {
|
||||
return driver->isDisconnected();
|
||||
}
|
||||
|
||||
bool Communication::sendPacket(std::vector<uint8_t>& bytes) {
|
||||
// This is here so that other communication types (like multichannel) can override it
|
||||
return rawWrite(bytes);
|
||||
@@ -68,10 +89,26 @@ bool Communication::sendCommand(Command cmd, std::vector<uint8_t> arguments) {
|
||||
return sendPacket(packet);
|
||||
}
|
||||
|
||||
bool Communication::sendCommand(ExtendedCommand cmd, std::vector<uint8_t> arguments) {
|
||||
const auto size = arguments.size();
|
||||
if (size > std::numeric_limits<uint16_t>::max())
|
||||
return false;
|
||||
|
||||
arguments.insert(arguments.begin(), {
|
||||
uint8_t(uint16_t(cmd) & 0xff),
|
||||
uint8_t((uint16_t(cmd) >> 8) & 0xff),
|
||||
uint8_t(size & 0xff),
|
||||
uint8_t((size >> 8) & 0xff)
|
||||
});
|
||||
|
||||
return sendCommand(Command::Extended, arguments);
|
||||
}
|
||||
|
||||
bool Communication::getSettingsSync(std::vector<uint8_t>& data, std::chrono::milliseconds timeout) {
|
||||
static const std::shared_ptr<MessageFilter> filter = std::make_shared<MessageFilter>(Network::NetID::ReadSettings);
|
||||
std::shared_ptr<Message> msg = waitForMessageSync([this]() {
|
||||
return sendCommand(Command::ReadSettings, { 0, 0, 0, 1 /* Get Global Settings */, 0, 1 /* Subversion 1 */ });
|
||||
}, MessageFilter(Network::NetID::ReadSettings), timeout);
|
||||
}, filter, timeout);
|
||||
if(!msg)
|
||||
return false;
|
||||
|
||||
@@ -81,31 +118,75 @@ bool Communication::getSettingsSync(std::vector<uint8_t>& data, std::chrono::mil
|
||||
return false;
|
||||
}
|
||||
|
||||
if(gsmsg->response != ReadSettingsMessage::Response::OK) {
|
||||
report(APIEvent::Type::Unknown, APIEvent::Severity::Error);
|
||||
if(gsmsg->response == ReadSettingsMessage::Response::OKDefaultsUsed) {
|
||||
report(APIEvent::Type::SettingsDefaultsUsed, APIEvent::Severity::EventInfo);
|
||||
} else if(gsmsg->response != ReadSettingsMessage::Response::OK) {
|
||||
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
data = std::move(msg->data);
|
||||
data = std::move(gsmsg->data);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::shared_ptr<SerialNumberMessage> Communication::getSerialNumberSync(std::chrono::milliseconds timeout) {
|
||||
sendCommand(Command::RequestSerialNumber);
|
||||
static const std::shared_ptr<MessageFilter> filter = std::make_shared<Main51MessageFilter>(Command::RequestSerialNumber);
|
||||
std::shared_ptr<Message> msg = waitForMessageSync([this]() {
|
||||
return sendCommand(Command::RequestSerialNumber);
|
||||
}, Main51MessageFilter(Command::RequestSerialNumber), timeout);
|
||||
}, filter, timeout);
|
||||
if(!msg) // Did not receive a message
|
||||
return std::shared_ptr<SerialNumberMessage>();
|
||||
|
||||
auto m51 = std::dynamic_pointer_cast<Main51Message>(msg);
|
||||
if(!m51) // Could not upcast for some reason
|
||||
return std::shared_ptr<SerialNumberMessage>();
|
||||
|
||||
return std::dynamic_pointer_cast<SerialNumberMessage>(m51);
|
||||
}
|
||||
|
||||
int Communication::addMessageCallback(const MessageCallback& cb) {
|
||||
std::optional< std::vector< std::optional<DeviceAppVersion> > > Communication::getVersionsSync(std::chrono::milliseconds timeout) {
|
||||
static const std::shared_ptr<MessageFilter> filter = std::make_shared<MessageFilter>(Message::Type::DeviceVersion);
|
||||
std::vector< std::optional<DeviceAppVersion> > ret;
|
||||
|
||||
std::shared_ptr<Message> msg = waitForMessageSync([this]() {
|
||||
return sendCommand(Command::GetMainVersion);
|
||||
}, filter, timeout);
|
||||
if(!msg) // Did not receive a message
|
||||
return std::nullopt;
|
||||
|
||||
auto ver = std::dynamic_pointer_cast<VersionMessage>(msg);
|
||||
if(!ver) // Could not upcast for some reason
|
||||
return std::nullopt;
|
||||
|
||||
if(ver->ForChip != VersionMessage::MainChip || ver->Versions.size() != 1)
|
||||
return std::nullopt;
|
||||
|
||||
ret.push_back(ver->Versions.front());
|
||||
|
||||
msg = waitForMessageSync([this]() {
|
||||
return sendCommand(Command::GetSecondaryVersions);
|
||||
}, filter, timeout);
|
||||
if(msg) { // This one is allowed to fail
|
||||
ver = std::dynamic_pointer_cast<VersionMessage>(msg);
|
||||
if(ver && ver->ForChip != VersionMessage::MainChip)
|
||||
ret.insert(ret.end(), ver->Versions.begin(), ver->Versions.end());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::shared_ptr<LogicalDiskInfoMessage> Communication::getLogicalDiskInfoSync(std::chrono::milliseconds timeout) {
|
||||
static const std::shared_ptr<MessageFilter> filter = std::make_shared<MessageFilter>(Message::Type::LogicalDiskInfo);
|
||||
|
||||
std::shared_ptr<Message> msg = waitForMessageSync([this]() {
|
||||
return sendCommand(Command::GetLogicalDiskInfo);
|
||||
}, filter, timeout);
|
||||
if(!msg) // Did not receive a message
|
||||
return {};
|
||||
|
||||
return std::dynamic_pointer_cast<LogicalDiskInfoMessage>(msg);
|
||||
}
|
||||
|
||||
int Communication::addMessageCallback(const std::shared_ptr<MessageCallback>& cb) {
|
||||
std::lock_guard<std::mutex> lk(messageCallbacksLock);
|
||||
messageCallbacks.insert(std::make_pair(messageCallbackIDCounter, cb));
|
||||
return messageCallbackIDCounter++;
|
||||
@@ -122,15 +203,17 @@ bool Communication::removeMessageCallback(int id) {
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Message> Communication::waitForMessageSync(std::function<bool(void)> onceWaitingDo, MessageFilter f, std::chrono::milliseconds timeout) {
|
||||
std::mutex m;
|
||||
std::shared_ptr<Message> Communication::waitForMessageSync(std::function<bool(void)> onceWaitingDo,
|
||||
const std::shared_ptr<MessageFilter>& f, std::chrono::milliseconds timeout) {
|
||||
std::mutex cvMutex;
|
||||
std::condition_variable cv;
|
||||
std::shared_ptr<Message> returnedMessage;
|
||||
|
||||
std::unique_lock<std::mutex> lk(m); // Don't let the callback fire until we're waiting for it
|
||||
int cb = addMessageCallback(MessageCallback([&m, &returnedMessage, &cv](std::shared_ptr<Message> message) {
|
||||
std::unique_lock<std::mutex> fnLk(syncMessageMutex); // Only allow for one sync message at a time
|
||||
std::unique_lock<std::mutex> cvLk(cvMutex); // Don't let the callback fire until we're waiting for it
|
||||
int cb = addMessageCallback(std::make_shared<MessageCallback>([&cvMutex, &returnedMessage, &cv](std::shared_ptr<Message> message) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(m);
|
||||
std::lock_guard<std::mutex> lk(cvMutex);
|
||||
returnedMessage = message;
|
||||
}
|
||||
cv.notify_all();
|
||||
@@ -139,8 +222,8 @@ std::shared_ptr<Message> Communication::waitForMessageSync(std::function<bool(vo
|
||||
// We have now added the callback, do whatever the caller wanted to do
|
||||
bool fail = !onceWaitingDo();
|
||||
if(!fail)
|
||||
cv.wait_for(lk, timeout, [&returnedMessage] { return !!returnedMessage; }); // `!!shared_ptr` checks if the ptr has a value
|
||||
lk.unlock(); // Ensure callbacks can complete even if we didn't wait for them
|
||||
cv.wait_for(cvLk, timeout, [&returnedMessage] { return !!returnedMessage; }); // `!!shared_ptr` checks if the ptr has a value
|
||||
cvLk.unlock(); // Ensure callbacks can complete even if we didn't wait for them
|
||||
|
||||
// We don't actually check that we got a message, because either way we want to remove the callback (since it should only happen once)
|
||||
removeMessageCallback(cb);
|
||||
@@ -162,30 +245,106 @@ void Communication::dispatchMessage(const std::shared_ptr<Message>& msg) {
|
||||
EventManager::GetInstance().cancelErrorDowngradingOnCurrentThread();
|
||||
for(auto& cb : messageCallbacks) {
|
||||
if(!closing) { // We might have closed while reading or processing
|
||||
cb.second.callIfMatch(msg);
|
||||
cb.second->callIfMatch(msg);
|
||||
}
|
||||
}
|
||||
if(downgrade)
|
||||
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
|
||||
}
|
||||
|
||||
void Communication::pauseReads() {
|
||||
std::unique_lock<std::mutex> lk(pauseReadTaskMutex);
|
||||
pauseReadTask = true;
|
||||
}
|
||||
|
||||
void Communication::resumeReads() {
|
||||
std::unique_lock<std::mutex> lk(pauseReadTaskMutex);
|
||||
if(!pauseReadTask) {
|
||||
return;
|
||||
}
|
||||
pauseReadTask = false;
|
||||
lk.unlock();
|
||||
|
||||
pauseReadTaskCv.notify_one();
|
||||
}
|
||||
|
||||
bool Communication::readsArePaused() {
|
||||
std::unique_lock<std::mutex> lk(pauseReadTaskMutex);
|
||||
return pauseReadTask;
|
||||
}
|
||||
|
||||
void Communication::readTask() {
|
||||
std::vector<uint8_t> readBytes;
|
||||
|
||||
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
|
||||
|
||||
while(!closing) {
|
||||
readBytes.clear();
|
||||
if(driver->readWait(readBytes)) {
|
||||
if(packetizer->input(readBytes)) {
|
||||
for(const auto& packet : packetizer->output()) {
|
||||
std::shared_ptr<Message> msg;
|
||||
if(!decoder->decode(msg, packet))
|
||||
continue;
|
||||
|
||||
dispatchMessage(msg);
|
||||
}
|
||||
while(!closing) {
|
||||
if(pauseReadTask) {
|
||||
std::unique_lock<std::mutex> lk(pauseReadTaskMutex);
|
||||
pauseReadTaskCv.wait(lk, [this]() { return !pauseReadTask; });
|
||||
}
|
||||
if(driver->waitForRx(readTaskWakeLimit, readTaskWakeTimeout)) {
|
||||
if(pauseReadTask) {
|
||||
/**
|
||||
* Reads could have paused while the driver was not available
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
handleInput(*packetizer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Communication::handleInput(Packetizer& p) {
|
||||
if(p.input(driver->getReadBuffer())) {
|
||||
for(const auto& packet : p.output()) {
|
||||
std::shared_ptr<Message> msg;
|
||||
if(!decoder->decode(msg, packet))
|
||||
continue;
|
||||
|
||||
dispatchMessage(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::optional< std::vector<ComponentVersion> > Communication::getComponentVersionsSync(std::chrono::milliseconds timeout) {
|
||||
static const std::shared_ptr<MessageFilter> filter = std::make_shared<MessageFilter>(Message::Type::ComponentVersions);
|
||||
std::shared_ptr<Message> msg = waitForMessageSync([this]() {
|
||||
return sendCommand(ExtendedCommand::GetComponentVersions, {});
|
||||
}, filter, timeout);
|
||||
if(!msg) // Did not receive a message
|
||||
return std::nullopt;
|
||||
|
||||
auto ver = std::dynamic_pointer_cast<ComponentVersionsMessage>(msg);
|
||||
if(!ver) // Could not upcast for some reason
|
||||
return std::nullopt;
|
||||
|
||||
return std::make_optional< std::vector<ComponentVersion> >(std::move(ver->versions));
|
||||
}
|
||||
|
||||
std::optional<uint32_t> Communication::getClientIDSync() {
|
||||
constexpr auto timeout = std::chrono::milliseconds(250);
|
||||
commands::generic::v1::ClientId msg;
|
||||
msg.Clear();
|
||||
|
||||
std::vector<uint8_t> payload = protoapi::getPayload(protoapi::Command::GET, msg);
|
||||
|
||||
std::shared_ptr<Message> response = waitForMessageSync(
|
||||
[this, payload](){
|
||||
return sendCommand(ExtendedCommand::ProtobufAPI, payload);
|
||||
},
|
||||
std::make_shared<MessageFilter>(Message::Type::ClientId),
|
||||
timeout
|
||||
);
|
||||
|
||||
if(!response) {
|
||||
report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto clientIdMessage = std::dynamic_pointer_cast<ClientIdMessage>(response);
|
||||
if(!clientIdMessage) {
|
||||
report(APIEvent::Type::UnexpectedResponse, APIEvent::Severity::Error);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return clientIdMessage->clientId;
|
||||
}
|
||||
|
||||
+436
-26
@@ -3,26 +3,73 @@
|
||||
#include "icsneo/communication/message/serialnumbermessage.h"
|
||||
#include "icsneo/communication/message/resetstatusmessage.h"
|
||||
#include "icsneo/communication/message/readsettingsmessage.h"
|
||||
#include "icsneo/communication/message/canerrormessage.h"
|
||||
#include "icsneo/communication/message/neoreadmemorysdmessage.h"
|
||||
#include "icsneo/communication/message/flashmemorymessage.h"
|
||||
#include "icsneo/communication/message/extendedresponsemessage.h"
|
||||
#include "icsneo/communication/message/wiviresponsemessage.h"
|
||||
#include "icsneo/communication/message/scriptstatusmessage.h"
|
||||
#include "icsneo/communication/message/a2bmessage.h"
|
||||
#include "icsneo/communication/message/flexray/control/flexraycontrolmessage.h"
|
||||
#include "icsneo/communication/message/i2cmessage.h"
|
||||
#include "icsneo/communication/message/linmessage.h"
|
||||
#include "icsneo/communication/message/mdiomessage.h"
|
||||
#include "icsneo/communication/message/extendeddatamessage.h"
|
||||
#include "icsneo/communication/message/livedatamessage.h"
|
||||
#include "icsneo/communication/message/logdatamessage.h"
|
||||
#include "icsneo/communication/message/diskdatamessage.h"
|
||||
#include "icsneo/communication/message/hardwareinfo.h"
|
||||
#include "icsneo/communication/message/tc10statusmessage.h"
|
||||
#include "icsneo/communication/message/gptpstatusmessage.h"
|
||||
#include "icsneo/communication/message/allmacaddressesmessage.h"
|
||||
#include "icsneo/communication/message/apperrormessage.h"
|
||||
#include "icsneo/communication/message/ethernetstatusmessage.h"
|
||||
#include "icsneo/communication/message/networkmutexmessage.h"
|
||||
#include "icsneo/communication/message/clientidmessage.h"
|
||||
#include "icsneo/communication/message/mfgconfigmessage.h"
|
||||
#include "icsneo/communication/message/spiportkeymessage.h"
|
||||
#include "icsneo/communication/message/genericapidatamessage.h"
|
||||
#include "icsneo/communication/message/genericapistatusmessage.h"
|
||||
#include "icsneo/communication/command.h"
|
||||
#include "icsneo/device/device.h"
|
||||
#include "icsneo/communication/packet/canpacket.h"
|
||||
#include "icsneo/communication/packet/a2bpacket.h"
|
||||
#include "icsneo/communication/packet/ethernetpacket.h"
|
||||
#include "icsneo/communication/packet/flexraypacket.h"
|
||||
#include "icsneo/communication/packet/iso9141packet.h"
|
||||
#include "icsneo/communication/packet/versionpacket.h"
|
||||
#include "icsneo/communication/packet/ethphyregpacket.h"
|
||||
#include "icsneo/communication/packet/logicaldiskinfopacket.h"
|
||||
#include "icsneo/communication/packet/wivicommandpacket.h"
|
||||
#include "icsneo/communication/packet/i2cpacket.h"
|
||||
#include "icsneo/communication/packet/scriptstatuspacket.h"
|
||||
#include "icsneo/communication/packet/linpacket.h"
|
||||
#include "icsneo/communication/message/iso15765message.h"
|
||||
#include "icsneo/communication/packet/componentversionpacket.h"
|
||||
#include "icsneo/communication/packet/supportedfeaturespacket.h"
|
||||
#include "icsneo/communication/packet/mdiopacket.h"
|
||||
#include "icsneo/communication/packet/genericbinarystatuspacket.h"
|
||||
#include "icsneo/communication/packet/livedatapacket.h"
|
||||
#include "icsneo/communication/packet/hardwareinfopacket.h"
|
||||
#include "icsneo/communication/packet/spipacket.h"
|
||||
#include "icsneo/communication/icspb.h"
|
||||
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
uint64_t Decoder::GetUInt64FromLEBytes(uint8_t* bytes) {
|
||||
uint64_t Decoder::GetUInt64FromLEBytes(const uint8_t* bytes) {
|
||||
uint64_t ret = 0;
|
||||
for(int i = 0; i < 8; i++)
|
||||
ret |= (bytes[i] << (i * 8));
|
||||
ret |= (uint64_t(bytes[i]) << (i * 8));
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Packet>& packet) {
|
||||
switch(packet->network.getType()) {
|
||||
case Network::Type::Ethernet:
|
||||
case Network::Type::AutomotiveEthernet: {
|
||||
result = HardwareEthernetPacket::DecodeToMessage(packet->data);
|
||||
if(!result) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
@@ -31,9 +78,11 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||
|
||||
// Timestamps are in (resolution) ns increments since 1/1/2007 GMT 00:00:00.0000
|
||||
// The resolution depends on the device
|
||||
result->timestamp *= timestampResolution;
|
||||
result->network = packet->network;
|
||||
EthernetMessage& eth = *static_cast<EthernetMessage*>(result.get());
|
||||
eth.timestamp *= timestampResolution;
|
||||
eth.network = packet->network;
|
||||
return true;
|
||||
}
|
||||
case Network::Type::CAN:
|
||||
case Network::Type::SWCAN:
|
||||
case Network::Type::LSFTCAN: {
|
||||
@@ -47,10 +96,28 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false; // A nullptr was returned, the packet was malformed
|
||||
}
|
||||
|
||||
// Timestamps are in (resolution) ns increments since 1/1/2007 GMT 00:00:00.0000
|
||||
// The resolution depends on the device
|
||||
result->timestamp *= timestampResolution;
|
||||
result->network = packet->network;
|
||||
|
||||
switch(result->type) {
|
||||
case Message::Type::Frame: {
|
||||
CANMessage& can = *static_cast<CANMessage*>(result.get());
|
||||
can.network = packet->network;
|
||||
break;
|
||||
}
|
||||
case Message::Type::CANErrorCount: {
|
||||
CANErrorMessage& can = *static_cast<CANErrorMessage*>(result.get());
|
||||
can.network = packet->network;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false; // An unknown type was returned, the packet was malformed
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
case Network::Type::FlexRay: {
|
||||
@@ -64,27 +131,109 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false; // A nullptr was returned, the packet was malformed
|
||||
}
|
||||
|
||||
// Timestamps are in (resolution) ns increments since 1/1/2007 GMT 00:00:00.0000
|
||||
// The resolution depends on the device
|
||||
result->timestamp *= timestampResolution;
|
||||
result->network = packet->network;
|
||||
FlexRayMessage& fr = *static_cast<FlexRayMessage*>(result.get());
|
||||
fr.timestamp *= timestampResolution;
|
||||
fr.network = packet->network;
|
||||
return true;
|
||||
}
|
||||
case Network::Type::ISO9141: {
|
||||
if(packet->data.size() < sizeof(HardwareISO9141Packet)) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
result = iso9141decoder.decodeToMessage(packet->data);
|
||||
if(!result)
|
||||
return false; // A nullptr was returned, more data is required to decode this packet
|
||||
|
||||
// Timestamps are in (resolution) ns increments since 1/1/2007 GMT 00:00:00.0000
|
||||
// The resolution depends on the device
|
||||
ISO9141Message& iso = *static_cast<ISO9141Message*>(result.get());
|
||||
iso.timestamp *= timestampResolution;
|
||||
iso.network = packet->network;
|
||||
return true;
|
||||
}
|
||||
case Network::Type::I2C: {
|
||||
if(packet->data.size() < sizeof(HardwareI2CPacket)) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
result = HardwareI2CPacket::DecodeToMessage(packet->data);
|
||||
if(!result) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false; //malformed packet indicated by a nullptr return
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
case Network::Type::A2B: {
|
||||
result = HardwareA2BPacket::DecodeToMessage(packet->data);
|
||||
|
||||
if(!result) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false; // A nullptr was returned, the packet was not long enough to decode
|
||||
}
|
||||
|
||||
A2BMessage& msg = *static_cast<A2BMessage*>(result.get());
|
||||
msg.network = packet->network;
|
||||
msg.timestamp *= timestampResolution;
|
||||
return true;
|
||||
}
|
||||
case Network::Type::LIN: {
|
||||
result = HardwareLINPacket::DecodeToMessage(packet->data);
|
||||
|
||||
if(!result) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false; // A nullptr was returned, the packet was not long enough to decode
|
||||
}
|
||||
|
||||
LINMessage& msg = *static_cast<LINMessage*>(result.get());
|
||||
msg.network = packet->network;
|
||||
msg.timestamp *= timestampResolution;
|
||||
return true;
|
||||
}
|
||||
case Network::Type::SPI: {
|
||||
result = HardwareSPIPacket::DecodeToMessage(packet->data);
|
||||
|
||||
if(!result) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false; // A nullptr was returned, the packet was not long enough to decode
|
||||
}
|
||||
|
||||
SPIMessage& msg = *static_cast<SPIMessage*>(result.get());
|
||||
msg.network = packet->network;
|
||||
msg.timestamp *= timestampResolution;
|
||||
return true;
|
||||
}
|
||||
case Network::Type::MDIO: {
|
||||
result = HardwareMDIOPacket::DecodeToMessage(packet->data);
|
||||
|
||||
if(!result) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false; // A nullptr was returned, the packet was not long enough to decode
|
||||
}
|
||||
|
||||
MDIOMessage& msg = *static_cast<MDIOMessage*>(result.get());
|
||||
msg.network = packet->network;
|
||||
return true;
|
||||
}
|
||||
case Network::Type::Internal: {
|
||||
switch(packet->network.getNetID()) {
|
||||
case Network::NetID::Reset_Status: {
|
||||
if(packet->data.size() < sizeof(HardwareResetStatusPacket)) {
|
||||
// We can deal with not having the last two fields (voltage and temperature)
|
||||
if(packet->data.size() < (sizeof(HardwareResetStatusPacket) - (sizeof(uint16_t) * 2))) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
HardwareResetStatusPacket* data = (HardwareResetStatusPacket*)packet->data.data();
|
||||
auto msg = std::make_shared<ResetStatusMessage>();
|
||||
msg->network = packet->network;
|
||||
msg->mainLoopTime = data->main_loop_time_25ns * 25;
|
||||
msg->maxMainLoopTime = data->max_main_loop_time_25ns * 25;
|
||||
msg->busVoltage = data->busVoltage;
|
||||
msg->deviceTemperature = data->deviceTemperature;
|
||||
msg->justReset = data->status.just_reset;
|
||||
msg->comEnabled = data->status.com_enabled;
|
||||
msg->cmRunning = data->status.cm_is_running;
|
||||
@@ -98,9 +247,186 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||
msg->cmTooBig = data->status.cm_too_big;
|
||||
msg->hidUsbState = data->status.hidUsbState;
|
||||
msg->fpgaUsbState = data->status.fpgaUsbState;
|
||||
if(packet->data.size() >= sizeof(HardwareResetStatusPacket)) {
|
||||
msg->busVoltage = data->busVoltage;
|
||||
msg->deviceTemperature = data->deviceTemperature;
|
||||
}
|
||||
result = msg;
|
||||
return true;
|
||||
}
|
||||
case Network::NetID::Device: {
|
||||
// These are neoVI network messages
|
||||
// They come in as CAN but we will handle them in the device rather than
|
||||
// passing them onto the user.
|
||||
if(packet->data.size() < 24) {
|
||||
auto rawmsg = std::make_shared<RawMessage>(Network::NetID::Device);
|
||||
result = rawmsg;
|
||||
rawmsg->data = packet->data;
|
||||
return true;
|
||||
}
|
||||
|
||||
const auto can = std::dynamic_pointer_cast<CANMessage>(HardwareCANPacket::DecodeToMessage(packet->data));
|
||||
if(!can) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(can->arbid == 0x162) {
|
||||
result = EthernetStatusMessage::DecodeToMessage(can->data);
|
||||
|
||||
if(!result) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// TODO: move more handleNeoVIMessage handling here, the Decoder layer will parse the message and the Device layer can cache the values
|
||||
can->network = packet->network;
|
||||
result = can;
|
||||
}
|
||||
|
||||
result->timestamp = can->timestamp * timestampResolution;
|
||||
return true;
|
||||
}
|
||||
case Network::NetID::DeviceStatus: {
|
||||
// Just pass along the data, the device needs to handle this itself
|
||||
result = std::make_shared<RawMessage>(packet->network, packet->data);
|
||||
return true;
|
||||
}
|
||||
case Network::NetID::RED_INT_MEMORYREAD: {
|
||||
if(packet->data.size() != 512 + sizeof(uint16_t)) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false; // Should get enough data for a start address and sector
|
||||
}
|
||||
|
||||
const auto msg = std::make_shared<FlashMemoryMessage>();
|
||||
result = msg;
|
||||
msg->startAddress = *reinterpret_cast<uint16_t*>(packet->data.data());
|
||||
msg->data.insert(msg->data.end(), packet->data.begin() + 2, packet->data.end());
|
||||
return true;
|
||||
}
|
||||
case Network::NetID::NeoMemorySDRead: {
|
||||
if(packet->data.size() != 512 + sizeof(uint32_t)) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false; // Should get enough data for a start address and sector
|
||||
}
|
||||
|
||||
const auto msg = std::make_shared<NeoReadMemorySDMessage>();
|
||||
result = msg;
|
||||
msg->startAddress = *reinterpret_cast<uint32_t*>(packet->data.data());
|
||||
msg->data.insert(msg->data.end(), packet->data.begin() + 4, packet->data.end());
|
||||
return true;
|
||||
}
|
||||
case Network::NetID::ExtendedCommand: {
|
||||
|
||||
if(packet->data.size() < sizeof(ExtendedResponseMessage::ResponseHeader))
|
||||
break; // Handle as a raw message, might not be a generic response
|
||||
|
||||
const auto& resp = *reinterpret_cast<ExtendedResponseMessage::ResponseHeader*>(packet->data.data());
|
||||
switch(resp.command) {
|
||||
case ExtendedCommand::GetComponentVersions:
|
||||
result = ComponentVersionPacket::DecodeToMessage(packet->data);
|
||||
return true;
|
||||
case ExtendedCommand::GetSupportedFeatures:
|
||||
result = SupportedFeaturesPacket::DecodeToMessage(packet->data);
|
||||
return true;
|
||||
case ExtendedCommand::GenericBinaryInfo:
|
||||
result = GenericBinaryStatusPacket::DecodeToMessage(packet->data);
|
||||
return true;
|
||||
case ExtendedCommand::SoftwareUpdate: {
|
||||
result = std::make_shared<ExtendedResponseMessage>(ExtendedCommand::SoftwareUpdate, ExtendedResponse::OperationPending, packet->data);
|
||||
return true;
|
||||
}
|
||||
case ExtendedCommand::GenericReturn: {
|
||||
if(packet->data.size() < sizeof(ExtendedResponseMessage::PackedGenericResponse))
|
||||
break;
|
||||
const auto& packedResp = *reinterpret_cast<ExtendedResponseMessage::PackedGenericResponse*>(packet->data.data());
|
||||
result = std::make_shared<ExtendedResponseMessage>(packedResp.command, packedResp.returnCode, packet->data);
|
||||
return true;
|
||||
}
|
||||
case ExtendedCommand::LiveData:
|
||||
result = HardwareLiveDataPacket::DecodeToMessage(packet->data, report);
|
||||
return true;
|
||||
case ExtendedCommand::ExecuteSPIPortKeyOperation:
|
||||
result = SPIPortKeyMessage::DecodeToMessage(packet->data);
|
||||
return true;
|
||||
case ExtendedCommand::ReadGenericAPIData:
|
||||
result = GenericAPIDataMessage::DecodeToMessage(packet->data);
|
||||
return true;
|
||||
case ExtendedCommand::ReadGenericAPIStatus:
|
||||
result = GenericAPIStatusMessage::DecodeToMessage(packet->data);
|
||||
return true;
|
||||
case ExtendedCommand::GetTC10Status:
|
||||
result = TC10StatusMessage::DecodeToMessage(packet->data);
|
||||
return true;
|
||||
case ExtendedCommand::GetAllMACAddresses:
|
||||
result = AllMACAddressesMessage::DecodeToMessage(packet->data);
|
||||
return true;
|
||||
case ExtendedCommand::GetGPTPStatus: {
|
||||
result = GPTPStatus::DecodeToMessage(packet->data, report);
|
||||
return true;
|
||||
}
|
||||
case ExtendedCommand::ProtobufAPI: {
|
||||
// get the proto id
|
||||
std::vector<uint8_t> responseBody(
|
||||
packet->data.begin() + sizeof(ExtendedResponseMessage::ResponseHeader),
|
||||
packet->data.end()
|
||||
);
|
||||
protoapi::Id protoId = protoapi::getProtoId(responseBody.data(), responseBody.size());
|
||||
switch(protoId) {
|
||||
case protoapi::Id::MfgConfig:
|
||||
result = MfgConfigMessage::DecodeToMessage(responseBody);
|
||||
return true;
|
||||
case protoapi::Id::NetworkMutex:
|
||||
result = NetworkMutexMessage::DecodeToMessage(responseBody);
|
||||
return true;
|
||||
case protoapi::Id::ClientId:
|
||||
result = ClientIdMessage::DecodeToMessage(responseBody);
|
||||
return true;
|
||||
default:
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
case ExtendedCommand::GetDiskDetails:
|
||||
case ExtendedCommand::DiskFormatProgress: {
|
||||
std::vector<uint8_t> responseBody(
|
||||
packet->data.begin() + sizeof(ExtendedResponseMessage::ResponseHeader),
|
||||
packet->data.end()
|
||||
);
|
||||
auto response = std::make_shared<ExtendedResponseMessage>(resp.command);
|
||||
response->data = std::move(responseBody);
|
||||
result = response;
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
// No defined handler, treat this as a RawMessage
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Network::NetID::ExtendedData: {
|
||||
if(packet->data.size() < sizeof(ExtendedDataMessage::ExtendedDataHeader))
|
||||
break;
|
||||
const auto& header = *reinterpret_cast<ExtendedDataMessage::ExtendedDataHeader*>(packet->data.data());
|
||||
|
||||
switch(header.subCommand) {
|
||||
case ExtendedDataSubCommand::GenericBinaryRead: {
|
||||
result = std::make_shared<ExtendedDataMessage>(header);
|
||||
auto extDataMsg = std::static_pointer_cast<ExtendedDataMessage>(result);
|
||||
|
||||
size_t numRead = std::min(ExtendedDataMessage::MaxExtendedDataBufferSize, (size_t)header.length);
|
||||
extDataMsg->data.resize(numRead);
|
||||
|
||||
std::copy(packet->data.begin() + sizeof(header), packet->data.begin() + sizeof(header) + numRead, extDataMsg->data.begin());
|
||||
|
||||
extDataMsg->network = Network(static_cast<uint16_t>(Network::NetID::ExtendedData), false);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Network::NetID::FlexRayControl: {
|
||||
auto frResult = std::make_shared<FlexRayControlMessage>(*packet);
|
||||
if(!frResult->decoded) {
|
||||
@@ -110,17 +436,10 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||
result = frResult;
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
break;//return false;
|
||||
}
|
||||
}
|
||||
default:
|
||||
switch(packet->network.getNetID()) {
|
||||
case Network::NetID::Main51: {
|
||||
switch((Command)packet->data[0]) {
|
||||
case Command::RequestSerialNumber: {
|
||||
auto msg = std::make_shared<SerialNumberMessage>();
|
||||
msg->network = packet->network;
|
||||
uint64_t serial = GetUInt64FromLEBytes(packet->data.data() + 1);
|
||||
// The device sends 64-bits of serial number, but we never use more than 32-bits.
|
||||
msg->deviceSerial = Device::SerialNumToString((uint32_t)serial);
|
||||
@@ -133,9 +452,44 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||
result = msg;
|
||||
return true;
|
||||
}
|
||||
case Command::GetMainVersion: {
|
||||
result = HardwareVersionPacket::DecodeMainToMessage(packet->data);
|
||||
if(!result) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
case Command::GetSecondaryVersions: {
|
||||
result = HardwareVersionPacket::DecodeSecondaryToMessage(packet->data);
|
||||
if(!result) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
case Command::GetHardwareInfo: {
|
||||
result = HardwareInfoPacket::DecodeToMessage(packet->data);
|
||||
|
||||
if(!result) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
case Command::J2534Command: {
|
||||
result = J2534CommandMessage::decodeToMessage(packet->data);
|
||||
if(!result) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
auto msg = std::make_shared<Main51Message>();
|
||||
msg->network = packet->network;
|
||||
msg->command = Command(packet->data[0]);
|
||||
msg->data.insert(msg->data.begin(), packet->data.begin() + 1, packet->data.end());
|
||||
result = msg;
|
||||
@@ -157,11 +511,18 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||
packet->data.resize(length);
|
||||
return decode(result, packet);
|
||||
}
|
||||
case Network::NetID::RED_App_Error: {
|
||||
result = AppErrorMessage::DecodeToMessage(packet->data, report);
|
||||
if(!result) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::EventWarning);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case Network::NetID::ReadSettings: {
|
||||
auto msg = std::make_shared<ReadSettingsMessage>();
|
||||
msg->network = packet->network;
|
||||
msg->response = ReadSettingsMessage::Response(packet->data[0]);
|
||||
|
||||
|
||||
if(msg->response == ReadSettingsMessage::Response::OK) {
|
||||
// The global settings structure is the payload of the message in this case
|
||||
msg->data.insert(msg->data.begin(), packet->data.begin() + 10, packet->data.end());
|
||||
@@ -177,13 +538,62 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||
result = msg;
|
||||
return true;
|
||||
}
|
||||
case Network::NetID::LogicalDiskInfo: {
|
||||
result = LogicalDiskInfoPacket::DecodeToMessage(packet->data);
|
||||
if(!result) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::EventWarning);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case Network::NetID::WiVICommand: {
|
||||
result = WiVI::CommandPacket::DecodeToMessage(packet->data);
|
||||
if(!result) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::EventWarning);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case Network::NetID::EthPHYControl: {
|
||||
result = HardwareEthernetPhyRegisterPacket::DecodeToMessage(packet->data, report);
|
||||
if(!result) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::EventWarning);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case Network::NetID::ScriptStatus: {
|
||||
result = ScriptStatus::DecodeToMessage(packet->data);
|
||||
if(!result) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::EventWarning);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case Network::NetID::DiskData: {
|
||||
result = std::make_shared<DiskDataMessage>(std::move(packet->data));
|
||||
return true;
|
||||
}
|
||||
case Network::NetID::Data_To_Host: {
|
||||
result = LogDataMessage::DecodeToMessage(packet->data);
|
||||
if(!result) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::EventWarning);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
// For the moment other types of messages will automatically be decoded as raw messages
|
||||
auto msg = std::make_shared<Message>();
|
||||
msg->network = packet->network;
|
||||
msg->data = packet->data;
|
||||
result = msg;
|
||||
result = std::make_shared<RawMessage>(packet->network, packet->data);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+58
-28
@@ -1,40 +1,65 @@
|
||||
#include "icsneo/communication/driver.h"
|
||||
|
||||
//#define ICSNEO_DRIVER_DEBUG_PRINTS
|
||||
#ifdef ICSNEO_DRIVER_DEBUG_PRINTS
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#endif
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
bool Driver::read(std::vector<uint8_t>& bytes, size_t limit) {
|
||||
// A limit of zero indicates no limit
|
||||
if(limit == 0)
|
||||
limit = (size_t)-1;
|
||||
bool Driver::pushRx(const uint8_t* buf, size_t numReceived) {
|
||||
bool ret = readBuffer.write(buf, numReceived);
|
||||
|
||||
if(limit > (readQueue.size_approx() + 4))
|
||||
limit = (readQueue.size_approx() + 4);
|
||||
rxWaitCv.notify_all();
|
||||
|
||||
if(bytes.capacity() < limit)
|
||||
bytes.resize(limit);
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t actuallyRead = readQueue.try_dequeue_bulk(bytes.data(), limit);
|
||||
void Driver::clearBuffers()
|
||||
{
|
||||
WriteOperation flushop;
|
||||
|
||||
if(bytes.size() > actuallyRead)
|
||||
bytes.resize(actuallyRead);
|
||||
readBuffer.clear();
|
||||
rxWaitCv.notify_all();
|
||||
|
||||
return true;
|
||||
while (writeQueue.try_dequeue(flushop)) {}
|
||||
}
|
||||
|
||||
bool Driver::waitForRx(size_t limit, std::chrono::milliseconds timeout) {
|
||||
return waitForRx([limit, this]() {
|
||||
return readBuffer.size() >= limit;
|
||||
}, timeout);
|
||||
}
|
||||
|
||||
bool Driver::waitForRx(std::function<bool()> predicate, std::chrono::milliseconds timeout) {
|
||||
std::unique_lock<std::mutex> lk(rxWaitMutex);
|
||||
return rxWaitCv.wait_for(lk, timeout, predicate);
|
||||
}
|
||||
|
||||
bool Driver::readWait(std::vector<uint8_t>& bytes, std::chrono::milliseconds timeout, size_t limit) {
|
||||
// A limit of zero indicates no limit
|
||||
if(limit == 0)
|
||||
limit = (size_t)-1;
|
||||
|
||||
if(limit > (readQueue.size_approx() + 4))
|
||||
limit = (readQueue.size_approx() + 4);
|
||||
|
||||
bytes.resize(limit);
|
||||
|
||||
size_t actuallyRead = readQueue.wait_dequeue_bulk_timed(bytes.data(), limit, timeout);
|
||||
// wait until we have enough data, or the timeout occurs
|
||||
waitForRx(limit, timeout);
|
||||
|
||||
size_t actuallyRead = readBuffer.size();
|
||||
bytes.resize(actuallyRead);
|
||||
|
||||
readBuffer.read(bytes.data(), 0, actuallyRead);
|
||||
readBuffer.pop(actuallyRead);
|
||||
bytes.resize(actuallyRead);
|
||||
|
||||
#ifdef ICSNEO_DRIVER_DEBUG_PRINTS
|
||||
if(actuallyRead > 0) {
|
||||
std::cout << "Read data: (" << actuallyRead << ')' << std::hex << std::endl;
|
||||
for(int i = 0; i < actuallyRead; i += 16) {
|
||||
for(int j = 0; j < std::min<int>(actuallyRead - i, 16); j++)
|
||||
std::cout << std::setw(2) << std::setfill('0') << uint32_t(bytes[i+j]) << ' ';
|
||||
std::cout << std::endl;
|
||||
}
|
||||
std::cout << std::dec << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
return actuallyRead > 0;
|
||||
}
|
||||
|
||||
@@ -45,19 +70,24 @@ bool Driver::write(const std::vector<uint8_t>& bytes) {
|
||||
}
|
||||
|
||||
if(writeBlocks) {
|
||||
std::unique_lock<std::mutex> lk(writeMutex);
|
||||
if(writeQueue.size_approx() > writeQueueSize)
|
||||
writeCV.wait(lk);
|
||||
if(writeQueueFull()) {
|
||||
while(writeQueueAlmostFull() && !isDisconnected() && !isClosing()) // Wait until we have some decent amount of space
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
|
||||
if(isDisconnected() || isClosing()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(writeQueue.size_approx() > writeQueueSize) {
|
||||
if(writeQueueFull()) {
|
||||
report(APIEvent::Type::TransmitBufferFull, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ret = writeQueue.enqueue(WriteOperation(bytes));
|
||||
const bool ret = writeInternal(bytes);
|
||||
if(!ret)
|
||||
report(APIEvent::Type::Unknown, APIEvent::Severity::Error);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
+235
-81
@@ -1,114 +1,262 @@
|
||||
#include "icsneo/communication/encoder.h"
|
||||
#include "icsneo/communication/message/ethernetmessage.h"
|
||||
#include "icsneo/communication/message/livedatamessage.h"
|
||||
#include "icsneo/communication/message/main51message.h"
|
||||
#include "icsneo/communication/packet/livedatapacket.h"
|
||||
#include "icsneo/communication/packet/ethernetpacket.h"
|
||||
#include "icsneo/communication/packet/iso9141packet.h"
|
||||
#include "icsneo/communication/packet/canpacket.h"
|
||||
#include "icsneo/communication/packet/ethphyregpacket.h"
|
||||
#include "icsneo/communication/message/ethphymessage.h"
|
||||
#include "icsneo/communication/packet/i2cpacket.h"
|
||||
#include "icsneo/communication/message/i2cmessage.h"
|
||||
#include "icsneo/communication/packet/a2bpacket.h"
|
||||
#include "icsneo/communication/packet/linpacket.h"
|
||||
#include "icsneo/communication/packet/mdiopacket.h"
|
||||
#include "icsneo/communication/packet/spipacket.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
bool Encoder::encode(const Packetizer& packetizer, std::vector<uint8_t>& result, const std::shared_ptr<Message>& message) {
|
||||
bool shortFormat = false;
|
||||
bool useResultAsBuffer = false; // Otherwise it's expected that we use message->data
|
||||
std::vector<uint8_t>* buffer = &result;
|
||||
uint16_t netid = 0;
|
||||
result.clear();
|
||||
|
||||
switch(message->network.getType()) {
|
||||
case Network::Type::Ethernet: {
|
||||
auto ethmsg = std::dynamic_pointer_cast<EthernetMessage>(message);
|
||||
if(!ethmsg) {
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false; // The message was not a properly formed EthernetMessage
|
||||
}
|
||||
switch(message->type) {
|
||||
case Message::Type::Frame: {
|
||||
auto frame = std::dynamic_pointer_cast<Frame>(message);
|
||||
|
||||
useResultAsBuffer = true;
|
||||
if(!HardwareEthernetPacket::EncodeFromMessage(*ethmsg, result, report))
|
||||
return false;
|
||||
// Frame uses frame->data as the buffer unless directed otherwise
|
||||
buffer = &frame->data;
|
||||
netid = uint16_t(frame->network.getNetID());
|
||||
|
||||
switch(frame->network.getType()) {
|
||||
case Network::Type::Ethernet:
|
||||
case Network::Type::AutomotiveEthernet: {
|
||||
auto ethmsg = std::dynamic_pointer_cast<EthernetMessage>(message);
|
||||
if(!ethmsg) {
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
shortFormat = false; // Ensure long-format RED header is added
|
||||
netid = static_cast<uint16_t>(Network::NetID::ETHERNET_TX_WRAP);
|
||||
buffer = &result;
|
||||
|
||||
if(!HardwareEthernetPacket::EncodeFromMessage(*ethmsg, result, report)) {
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(result.empty()) {
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case Network::Type::Internal:
|
||||
case Network::Type::CAN:
|
||||
case Network::Type::SWCAN:
|
||||
case Network::Type::LSFTCAN: {
|
||||
auto canmsg = std::dynamic_pointer_cast<CANMessage>(message);
|
||||
if(!canmsg) {
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false; // The message was not a properly formed CANMessage
|
||||
}
|
||||
|
||||
if(!supportCANFD && canmsg->isCANFD) {
|
||||
report(APIEvent::Type::CANFDNotSupported, APIEvent::Severity::Error);
|
||||
return false; // This device does not support CAN FD
|
||||
}
|
||||
|
||||
buffer = &result;
|
||||
if(!HardwareCANPacket::EncodeFromMessage(*canmsg, result, report))
|
||||
return false; // The CANMessage was malformed
|
||||
|
||||
break;
|
||||
} // End of Network::Type::CAN
|
||||
case Network::Type::ISO9141: {
|
||||
auto isomsg = std::dynamic_pointer_cast<ISO9141Message>(message);
|
||||
if(!isomsg) {
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false; // The message was not a properly formed ISO9141Message
|
||||
}
|
||||
|
||||
// Skip the normal message wrapping at the bottom since we need to send multiple
|
||||
// packets to the device. This function just encodes them back to back into `result`
|
||||
return HardwareISO9141Packet::EncodeFromMessage(*isomsg, result, report, packetizer);
|
||||
} // End of Network::Type::ISO9141
|
||||
case Network::Type::A2B: {
|
||||
auto a2bmsg = std::dynamic_pointer_cast<A2BMessage>(message);
|
||||
if(!a2bmsg) {
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
buffer = &result;
|
||||
if(!HardwareA2BPacket::EncodeFromMessage(*a2bmsg, result, report)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
} // End of Network::Type::A2B
|
||||
case Network::Type::I2C: {
|
||||
auto i2cmsg = std::dynamic_pointer_cast<I2CMessage>(message);
|
||||
if(!i2cmsg) {
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
buffer = &result;
|
||||
if(!HardwareI2CPacket::EncodeFromMessage(*i2cmsg, result, report)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
} // End of Network::Type::I2C
|
||||
case Network::Type::LIN: {
|
||||
auto linmsg = std::dynamic_pointer_cast<LINMessage>(message);
|
||||
if(!linmsg) {
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
buffer = &result;
|
||||
if(!HardwareLINPacket::EncodeFromMessage(*linmsg, result, report)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
} // End of Network::Type::LIN
|
||||
case Network::Type::MDIO: {
|
||||
auto mdiomsg = std::dynamic_pointer_cast<MDIOMessage>(message);
|
||||
if(!mdiomsg) {
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
buffer = &result;
|
||||
if(!HardwareMDIOPacket::EncodeFromMessage(*mdiomsg, result, report)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
} // End of Network::Type::MDIO
|
||||
case Network::Type::SPI: {
|
||||
auto msg = std::dynamic_pointer_cast<SPIMessage>(message);
|
||||
if(!msg) {
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false; // The message was not a properly formed LiveDataMessage
|
||||
}
|
||||
if(!HardwareSPIPacket::EncodeFromMessage(*msg, result, report))
|
||||
return false;
|
||||
result = packetizer.packetWrap(result, false);
|
||||
return true;
|
||||
} // End of Network::Type::SPI
|
||||
default:
|
||||
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
} // End of Network::Type::Ethernet
|
||||
case Network::Type::CAN:
|
||||
case Network::Type::SWCAN:
|
||||
case Network::Type::LSFTCAN: {
|
||||
auto canmsg = std::dynamic_pointer_cast<CANMessage>(message);
|
||||
if(!canmsg) {
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false; // The message was not a properly formed CANMessage
|
||||
}
|
||||
}
|
||||
case Message::Type::RawMessage: {
|
||||
auto raw = std::dynamic_pointer_cast<RawMessage>(message);
|
||||
|
||||
if(!supportCANFD && canmsg->isCANFD) {
|
||||
report(APIEvent::Type::CANFDNotSupported, APIEvent::Severity::Error);
|
||||
return false; // This device does not support CAN FD
|
||||
}
|
||||
|
||||
useResultAsBuffer = true;
|
||||
if(!HardwareCANPacket::EncodeFromMessage(*canmsg, result, report))
|
||||
return false; // The CANMessage was malformed
|
||||
// Raw message uses raw->data as the buffer unless directed otherwise
|
||||
buffer = &raw->data;
|
||||
netid = uint16_t(raw->network.getNetID());
|
||||
|
||||
break;
|
||||
} // End of Network::Type::CAN
|
||||
default:
|
||||
switch(message->network.getNetID()) {
|
||||
switch(raw->network.getNetID()) {
|
||||
case Network::NetID::Device:
|
||||
shortFormat = true;
|
||||
break;
|
||||
case Network::NetID::Main51: {
|
||||
auto m51msg = std::dynamic_pointer_cast<Main51Message>(message);
|
||||
if(!m51msg) {
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false; // The message was not a properly formed Main51Message
|
||||
}
|
||||
|
||||
if(!m51msg->forceShortFormat) {
|
||||
// Main51 can be sent as a long message without setting the NetID to RED first
|
||||
// Size in long format is the size of the entire packet
|
||||
// So +1 for AA header, +1 for short format header, and +2 for long format size
|
||||
uint16_t size = uint16_t(message->data.size()) + 1 + 1 + 2;
|
||||
size += 1; // Even though we are not including the NetID bytes, the device expects them to be counted in the length
|
||||
size += 1; // Main51 Command
|
||||
message->data.insert(message->data.begin(), {
|
||||
(uint8_t)Network::NetID::Main51, // 0x0B for long message
|
||||
(uint8_t)size, // Size, little endian 16-bit
|
||||
(uint8_t)(size >> 8),
|
||||
(uint8_t)m51msg->command
|
||||
});
|
||||
result = packetizer.packetWrap(message->data, shortFormat);
|
||||
return true;
|
||||
} else {
|
||||
message->data.insert(message->data.begin(), { uint8_t(m51msg->command) });
|
||||
shortFormat = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Network::NetID::RED_OLDFORMAT: {
|
||||
// See the decoder for an explanation
|
||||
// We expect the network byte to be populated already in data, but not the length
|
||||
uint16_t length = uint16_t(message->data.size()) - 1;
|
||||
message->data.insert(message->data.begin(), {(uint8_t)length, (uint8_t)(length >> 8)});
|
||||
uint16_t length = uint16_t(raw->data.size()) - 1;
|
||||
raw->data.insert(raw->data.begin(), {(uint8_t)length, (uint8_t)(length >> 8)});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Message::Type::Main51: {
|
||||
auto m51msg = std::dynamic_pointer_cast<Main51Message>(message);
|
||||
if(!m51msg) {
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false; // The message was not a properly formed Main51Message
|
||||
}
|
||||
|
||||
buffer = &m51msg->data;
|
||||
netid = uint16_t(Network::NetID::Main51);
|
||||
|
||||
if(!m51msg->forceShortFormat) {
|
||||
// Main51 can be sent as a long message without setting the NetID to RED first
|
||||
// Size in long format is the size of the entire packet
|
||||
// So +1 for AA header, +1 for short format header, and +2 for long format size
|
||||
uint16_t size = uint16_t(m51msg->data.size()) + 1 + 1 + 2;
|
||||
size += 1; // Even though we are not including the NetID bytes, the device expects them to be counted in the length
|
||||
size += 1; // Main51 Command
|
||||
m51msg->data.insert(m51msg->data.begin(), {
|
||||
(uint8_t)Network::NetID::Main51, // 0x0B for long message
|
||||
(uint8_t)size, // Size, little endian 16-bit
|
||||
(uint8_t)(size >> 8),
|
||||
(uint8_t)m51msg->command
|
||||
});
|
||||
result = packetizer.packetWrap(m51msg->data, shortFormat);
|
||||
return true;
|
||||
} else {
|
||||
m51msg->data.insert(m51msg->data.begin(), { uint8_t(m51msg->command) });
|
||||
shortFormat = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Message::Type::EthernetPhyRegister: {
|
||||
if(!supportEthPhy) {
|
||||
report(APIEvent::Type::EthPhyRegisterControlNotAvailable, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
auto ethPhyMessage = std::dynamic_pointer_cast<EthPhyMessage>(message);
|
||||
if(!ethPhyMessage) {
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
if(!HardwareEthernetPhyRegisterPacket::EncodeFromMessage(*ethPhyMessage, result, report))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case Message::Type::LiveData: {
|
||||
auto liveDataMsg = std::dynamic_pointer_cast<LiveDataMessage>(message);
|
||||
if(!liveDataMsg) {
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false; // The message was not a properly formed LiveDataMessage
|
||||
}
|
||||
if(!HardwareLiveDataPacket::EncodeFromMessage(*liveDataMsg, result, report))
|
||||
return false;
|
||||
result = packetizer.packetWrap(result, false);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false; // The message was not a properly formed Message
|
||||
}
|
||||
|
||||
auto& buffer = useResultAsBuffer ? result : message->data;
|
||||
|
||||
// Early returns may mean we don't reach this far, check the type you're concerned with
|
||||
if(shortFormat) {
|
||||
buffer.insert(buffer.begin(), (uint8_t(buffer.size()) << 4) | uint8_t(message->network.getNetID()));
|
||||
buffer->insert(buffer->begin(), (uint8_t(buffer->size()) << 4) | uint8_t(netid));
|
||||
} else {
|
||||
// Size in long format is the size of the entire packet
|
||||
// Size for the host-to-device long format is the size of the entire packet + 1
|
||||
// So +1 for AA header, +1 for short format header, +2 for long format size, and +2 for long format NetID
|
||||
uint16_t size = uint16_t(buffer.size()) + 1 + 1 + 2 + 2;
|
||||
buffer.insert(buffer.begin(), {
|
||||
// Then an extra +1, due to a firmware idiosyncrasy
|
||||
uint16_t size = static_cast<uint16_t>(buffer->size()) + 1 + 1 + 2 + 2 + 1;
|
||||
|
||||
buffer->insert(buffer->begin(), {
|
||||
(uint8_t)Network::NetID::RED, // 0x0C for long message
|
||||
(uint8_t)size, // Size, little endian 16-bit
|
||||
(uint8_t)(size >> 8),
|
||||
(uint8_t)message->network.getNetID(), // NetID, little endian 16-bit
|
||||
(uint8_t)(uint16_t(message->network.getNetID()) >> 8)
|
||||
(uint8_t)netid, // NetID, little endian 16-bit
|
||||
(uint8_t)(netid >> 8)
|
||||
});
|
||||
}
|
||||
|
||||
result = packetizer.packetWrap(buffer, shortFormat);
|
||||
result = packetizer.packetWrap(*buffer, shortFormat);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -120,33 +268,39 @@ bool Encoder::encode(const Packetizer& packetizer, std::vector<uint8_t>& result,
|
||||
* In this case, command 0x06 is SetLEDState.
|
||||
* This old command type is not really used anywhere else.
|
||||
*/
|
||||
msg = std::make_shared<Message>();
|
||||
auto canmsg = std::make_shared<RawMessage>(Network::NetID::Device);
|
||||
msg = canmsg;
|
||||
if(arguments.empty()) {
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
msg->network = Network::NetID::Device;
|
||||
msg->data.reserve(3);
|
||||
msg->data.push_back(0x00);
|
||||
msg->data.push_back(0x06); // SetLEDState
|
||||
msg->data.push_back(arguments.at(0)); // See Device::LEDState
|
||||
canmsg->data.reserve(3);
|
||||
canmsg->data.push_back(0x00);
|
||||
canmsg->data.push_back(0x06); // SetLEDState
|
||||
canmsg->data.push_back(arguments.at(0)); // See Device::LEDState
|
||||
} else {
|
||||
auto m51msg = std::make_shared<Main51Message>();
|
||||
msg = m51msg;
|
||||
msg->network = Network::NetID::Main51;
|
||||
m51msg->command = cmd;
|
||||
switch(cmd) {
|
||||
case Command::ReadSettings:
|
||||
case Command::RequestSerialNumber:
|
||||
case Command::EnableNetworkCommunication:
|
||||
case Command::EnableNetworkCommunicationEx:
|
||||
case Command::KeepAlive:
|
||||
case Command::GetMainVersion:
|
||||
case Command::GetSecondaryVersions:
|
||||
case Command::NeoReadMemory:
|
||||
case Command::ClearCoreMini:
|
||||
case Command::LoadCoreMini:
|
||||
// There is a firmware handling idiosyncrasy with these commands
|
||||
// They must be encoded in the short format
|
||||
m51msg->forceShortFormat = true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
msg->data.insert(msg->data.end(), std::make_move_iterator(arguments.begin()), std::make_move_iterator(arguments.end()));
|
||||
m51msg->data.insert(m51msg->data.end(), std::make_move_iterator(arguments.begin()), std::make_move_iterator(arguments.end()));
|
||||
}
|
||||
|
||||
|
||||
return encode(packetizer, result, msg);
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
#include "icsneo/communication/ethernetpacketizer.h"
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
const size_t EthernetPacketizer::MaxPacketLength = 1490; // MTU - overhead
|
||||
static const uint8_t BROADCAST_MAC[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
|
||||
EthernetPacketizer::EthernetPacket& EthernetPacketizer::newSendPacket(bool first) {
|
||||
processedDownPackets.emplace_back();
|
||||
EthernetPacket& ret = processedDownPackets.back();
|
||||
if(first) {
|
||||
ret.packetNumber = sequenceDown++;
|
||||
} else {
|
||||
ret.firstPiece = false;
|
||||
if(processedDownPackets.size() > 1)
|
||||
ret.packetNumber = (processedDownPackets.rbegin() + 1)->packetNumber;
|
||||
else
|
||||
assert(false); // This should never be called with !first if there are no packets in the queue
|
||||
}
|
||||
std::copy(std::begin(hostMAC), std::end(hostMAC), std::begin(ret.srcMAC));
|
||||
std::copy(std::begin(deviceMAC), std::end(deviceMAC), std::begin(ret.destMAC));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void EthernetPacketizer::inputDown(std::vector<uint8_t> bytes, bool first) {
|
||||
EthernetPacket* sendPacket = nullptr;
|
||||
if(first && !processedDownPackets.empty()) {
|
||||
// We have some packets already, let's see if we can add this to the last one
|
||||
if(processedDownPackets.back().payload.size() + bytes.size() <= MaxPacketLength)
|
||||
sendPacket = &processedDownPackets.back();
|
||||
}
|
||||
|
||||
if(sendPacket == nullptr)
|
||||
sendPacket = &newSendPacket(first);
|
||||
|
||||
if(sendPacket->payload.empty())
|
||||
sendPacket->payload = std::move(bytes);
|
||||
else
|
||||
sendPacket->payload.insert(sendPacket->payload.end(), bytes.begin(), bytes.end());
|
||||
|
||||
// Split packets larger than MTU
|
||||
std::vector<uint8_t> extraData;
|
||||
if(sendPacket->payload.size() > MaxPacketLength) {
|
||||
extraData.insert(extraData.end(), sendPacket->payload.begin() + MaxPacketLength, sendPacket->payload.end());
|
||||
sendPacket->payload.resize(MaxPacketLength);
|
||||
sendPacket->lastPiece = false;
|
||||
inputDown(std::move(extraData), false);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector< std::vector<uint8_t> > EthernetPacketizer::outputDown() {
|
||||
std::vector< std::vector<uint8_t> > ret;
|
||||
ret.reserve(processedDownPackets.size());
|
||||
for(auto&& packet : std::move(processedDownPackets))
|
||||
ret.push_back(packet.getBytestream());
|
||||
processedDownPackets.clear();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool EthernetPacketizer::inputUp(std::vector<uint8_t> bytes) {
|
||||
EthernetPacket packet(bytes);
|
||||
|
||||
if(packet.errorWhileDecodingFromBytestream)
|
||||
return false; // Bad packet
|
||||
|
||||
if(packet.etherType != 0xCAB2)
|
||||
return false; // Not a packet to host
|
||||
|
||||
if(memcmp(packet.destMAC, hostMAC, sizeof(packet.destMAC)) != 0 &&
|
||||
memcmp(packet.destMAC, BROADCAST_MAC, sizeof(packet.destMAC)) != 0)
|
||||
return false; // Packet is not addressed to us or broadcast
|
||||
|
||||
if(!allowInPacketsFromAnyMAC && memcmp(packet.srcMAC, deviceMAC, sizeof(deviceMAC)) != 0)
|
||||
return false; // Not a packet from the device we're concerned with
|
||||
|
||||
// Handle single packets
|
||||
if(packet.firstPiece && packet.lastPiece) {
|
||||
// Could ensure no out-of-order reassembly by checking reassembing here,
|
||||
// not doing that here because it should be harmless if it ever happened.
|
||||
processedUpBytes.insert(processedUpBytes.end(), std::make_move_iterator(packet.payload.begin()), std::make_move_iterator(packet.payload.end()));
|
||||
return true;
|
||||
}
|
||||
|
||||
if(packet.firstPiece) {
|
||||
if(reassembling) {
|
||||
//report(APIEvent::Type::FailedToRead, APIEvent::Severity::EventWarning);
|
||||
reassemblingData.clear();
|
||||
}
|
||||
|
||||
reassembling = true;
|
||||
reassemblingId = packet.packetNumber;
|
||||
reassemblingData = std::move(packet.payload);
|
||||
return !processedUpBytes.empty(); // If there are other packets in the pipe
|
||||
}
|
||||
|
||||
if(!reassembling || reassemblingId != packet.packetNumber) {
|
||||
//report(APIEvent::Type::FailedToRead, APIEvent::Severity::EventWarning);
|
||||
reassembling = false;
|
||||
reassemblingData.clear();
|
||||
return !processedUpBytes.empty(); // If there are other packets in the pipe
|
||||
}
|
||||
|
||||
if(packet.lastPiece) {
|
||||
processedUpBytes.insert(processedUpBytes.end(), std::make_move_iterator(reassemblingData.begin()), std::make_move_iterator(reassemblingData.end()));
|
||||
reassemblingData.clear();
|
||||
reassembling = false;
|
||||
processedUpBytes.insert(processedUpBytes.end(), std::make_move_iterator(packet.payload.begin()), std::make_move_iterator(packet.payload.end()));
|
||||
return true;
|
||||
}
|
||||
|
||||
reassemblingData.insert(reassemblingData.end(), std::make_move_iterator(packet.payload.begin()), std::make_move_iterator(packet.payload.end()));
|
||||
return !processedUpBytes.empty(); // If there are other packets in the pipe
|
||||
}
|
||||
|
||||
std::vector<uint8_t> EthernetPacketizer::outputUp() {
|
||||
std::vector<uint8_t> ret = std::move(processedUpBytes);
|
||||
processedUpBytes.clear();
|
||||
return ret;
|
||||
}
|
||||
|
||||
EthernetPacketizer::EthernetPacket::EthernetPacket(const std::vector<uint8_t>& bytestream) {
|
||||
loadBytestream(bytestream);
|
||||
}
|
||||
|
||||
EthernetPacketizer::EthernetPacket::EthernetPacket(const uint8_t* data, size_t size) {
|
||||
std::vector<uint8_t> bs(data, data + size);
|
||||
loadBytestream(bs);
|
||||
}
|
||||
|
||||
int EthernetPacketizer::EthernetPacket::loadBytestream(const std::vector<uint8_t>& bytestream) {
|
||||
errorWhileDecodingFromBytestream = 0;
|
||||
for(size_t i = 0; i < 6; i++)
|
||||
destMAC[i] = bytestream[i];
|
||||
for(size_t i = 0; i < 6; i++)
|
||||
srcMAC[i] = bytestream[i + 6];
|
||||
etherType = (bytestream[12] << 8) | bytestream[13];
|
||||
icsEthernetHeader = (bytestream[14] << 24) | (bytestream[15] << 16) | (bytestream[16] << 8) | bytestream[17];
|
||||
payloadSize = bytestream[18] | (bytestream[19] << 8);
|
||||
packetNumber = bytestream[20] | (bytestream[21] << 8);
|
||||
uint16_t packetInfo = bytestream[22] | (bytestream[23] << 8);
|
||||
firstPiece = packetInfo & 1;
|
||||
lastPiece = (packetInfo >> 1) & 1;
|
||||
bufferHalfFull = (packetInfo >> 2) & 2;
|
||||
payload = std::vector<uint8_t>(bytestream.begin() + 24, bytestream.end());
|
||||
size_t payloadActualSize = payload.size();
|
||||
if(payloadActualSize > payloadSize)
|
||||
payload.resize(payloadSize);
|
||||
return errorWhileDecodingFromBytestream;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> EthernetPacketizer::EthernetPacket::getBytestream() const {
|
||||
uint16_t actualPayloadSize = uint16_t(payload.size());
|
||||
std::vector<uint8_t> bytestream;
|
||||
bytestream.reserve(6 + 6 + 2 + 4 + 2 + 2 + 2 + actualPayloadSize);
|
||||
for(size_t i = 0; i < 6; i++)
|
||||
bytestream.push_back(destMAC[i]);
|
||||
for(size_t i = 0; i < 6; i++)
|
||||
bytestream.push_back(srcMAC[i]);
|
||||
// EtherType should be put into the bytestream as big endian
|
||||
bytestream.push_back((uint8_t)(etherType >> 8));
|
||||
bytestream.push_back((uint8_t)(etherType));
|
||||
// Our Ethernet header should be put into the bytestream as big endian
|
||||
bytestream.push_back((uint8_t)(icsEthernetHeader >> 24));
|
||||
bytestream.push_back((uint8_t)(icsEthernetHeader >> 16));
|
||||
bytestream.push_back((uint8_t)(icsEthernetHeader >> 8));
|
||||
bytestream.push_back((uint8_t)(icsEthernetHeader));
|
||||
uint16_t declaredPayloadSize = payloadSize ? payloadSize : actualPayloadSize;
|
||||
// The payload size comes next, it's little endian
|
||||
bytestream.push_back((uint8_t)(declaredPayloadSize));
|
||||
bytestream.push_back((uint8_t)(declaredPayloadSize >> 8));
|
||||
// Packet number is little endian
|
||||
bytestream.push_back((uint8_t)(packetNumber));
|
||||
bytestream.push_back((uint8_t)(packetNumber >> 8));
|
||||
// Packet info gets assembled into a bitfield
|
||||
uint16_t packetInfo = 0;
|
||||
packetInfo |= firstPiece & 1;
|
||||
packetInfo |= (lastPiece & 1) << 1;
|
||||
packetInfo |= (bufferHalfFull & 1) << 2;
|
||||
packetInfo |= 1 << 8; // Protocol version 1
|
||||
bytestream.push_back((uint8_t)(packetInfo));
|
||||
bytestream.push_back((uint8_t)(packetInfo >> 8));
|
||||
bytestream.insert(bytestream.end(), payload.begin(), payload.end());
|
||||
return bytestream;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
#include "icsneo/communication/livedata.h"
|
||||
#include <cmath>
|
||||
namespace icsneo {
|
||||
|
||||
namespace LiveDataUtil {
|
||||
|
||||
LiveDataHandle getNewHandle() {
|
||||
static LiveDataHandle currentHandle = 0;
|
||||
++currentHandle;
|
||||
if(currentHandle == std::numeric_limits<LiveDataHandle>::max()) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::LiveDataInvalidHandle, APIEvent::Severity::Error);
|
||||
currentHandle = 1;
|
||||
}
|
||||
return currentHandle;
|
||||
}
|
||||
|
||||
double liveDataValueToDouble(const LiveDataValue& val) {
|
||||
constexpr double liveDataFixedPointToDouble = 0.00000000023283064365386962890625;
|
||||
return val.value * liveDataFixedPointToDouble;
|
||||
}
|
||||
|
||||
std::optional<LiveDataValue> liveDataDoubleToValue(const double& dFloat) {
|
||||
LiveDataValue value;
|
||||
union {
|
||||
struct
|
||||
{
|
||||
uint32_t ValueFractionPart;
|
||||
int32_t ValueInt32;
|
||||
} parts;
|
||||
int64_t ValueLarge;
|
||||
} CminiFixedPt;
|
||||
constexpr double CM_FIXED_POINT_TO_DOUBLEVALUE = (1.0 / (double)(1ULL << 32)); // 2^-32
|
||||
constexpr double CM_DOUBLEVALUE_TO_FIXED_POINT = ((double)(1ULL << 32)); // 2^32
|
||||
// Use const for limits (C++98 compatible)
|
||||
const double INT32_MAX_DOUBLE =
|
||||
static_cast<double>(std::numeric_limits<int32_t>::max()) + (1.0 - std::numeric_limits<double>::epsilon());
|
||||
const double INT32_MIN_DOUBLE = static_cast<double>(std::numeric_limits<int32_t>::min());
|
||||
const double MIN_FIXED_POINT_DOUBLE = (double)(1ull * CM_FIXED_POINT_TO_DOUBLEVALUE);
|
||||
|
||||
// This needs to be assigned separately, otherwise, for dFloat >= 2^31,
|
||||
// long double dBigFloat = dFloat * CM_DOUBLEVALUE_TO_FIXED_POINT overflows
|
||||
// long long (value is >= 2^63) and so the assignment ValueLarge = dBigFloat is undefined
|
||||
|
||||
int32_t intPart; //creating temp variable due to static analysis warning about writing and reading to different union members
|
||||
if(dFloat < 0.0)
|
||||
intPart = (int32_t)std::floor(dFloat);
|
||||
else
|
||||
intPart = (int32_t)dFloat;
|
||||
|
||||
//using temp varialbes to avoid static analysis warning about read/write to different union members
|
||||
double frac = dFloat - (double)(intPart);
|
||||
uint32_t fracPart = (uint32_t)std::floor((frac * CM_DOUBLEVALUE_TO_FIXED_POINT) + 0.5);
|
||||
|
||||
//write temp vars back into the union
|
||||
CminiFixedPt.parts.ValueInt32 = intPart;
|
||||
CminiFixedPt.parts.ValueFractionPart = fracPart;
|
||||
value.value = CminiFixedPt.ValueLarge;
|
||||
|
||||
if(dFloat == (double)0.0)
|
||||
return value;
|
||||
|
||||
//check if double can be stored as 32.32
|
||||
// 0x1 0000 0000 0000 0000 * CM_FIXED_POINT_TO_DOUBLEVALUE = 0x1 0000 0000
|
||||
if(dFloat > INT32_MAX_DOUBLE || dFloat < INT32_MIN_DOUBLE) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::FixedPointOverflow, APIEvent::Severity::Error);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Use absolute value for minimum fixed point check
|
||||
double absFloat = (dFloat < 0.0) ? -dFloat : dFloat;
|
||||
if(absFloat < MIN_FIXED_POINT_DOUBLE) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::FixedPointPrecision, APIEvent::Severity::Error);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
} // namespace LiveDataUtil
|
||||
} // namespace icsneo
|
||||
@@ -0,0 +1,259 @@
|
||||
#include "icsneo/communication/message/a2bmessage.h"
|
||||
#include "icsneo/communication/message/callback/streamoutput/streamoutput.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
// Read a 16 bit sample from the audio buffer, which is stored as little endian
|
||||
#define SAMPLE_FROM_BYTES_16(audioData) (((audioData)[0]) | ((audioData)[1] << 8))
|
||||
|
||||
// Read a 32 bit sample from the audio buffer
|
||||
#define SAMPLE_FROM_BYTES_32(audioData) (((audioData)[0]) | ((audioData)[1] << 8) | ((audioData)[2] << 16) | ((audioData)[3] << 24))
|
||||
|
||||
// Read the most significant bytes of a sample stored in a 32 bit unsigned integer into audioData
|
||||
#define SAMPLE_TO_BYTES_16(audioData, offset, sample) {\
|
||||
(audioData)[(offset)++] = static_cast<uint8_t>(((sample) & 0x00FF0000u) >> 16);\
|
||||
(audioData)[(offset)++] = static_cast<uint8_t>(((sample) & 0xFF000000u) >> 24);\
|
||||
}
|
||||
|
||||
// Read little endian a 32 bit unsigned integer into audioData
|
||||
#define SAMPLE_TO_BYTES_32(audioData, offset, sample) {\
|
||||
(audioData)[(offset)++] = static_cast<uint8_t>(((sample) & 0x000000FFu));\
|
||||
(audioData)[(offset)++] = static_cast<uint8_t>(((sample) & 0x0000FF00u) >> 8);\
|
||||
(audioData)[(offset)++] = static_cast<uint8_t>(((sample) & 0x00FF0000u) >> 16);\
|
||||
(audioData)[(offset)++] = static_cast<uint8_t>(((sample) & 0xFF000000u) >> 24);\
|
||||
}
|
||||
|
||||
uint8_t A2BMessage::tdmToChannelNum(TDMMode tdm) {
|
||||
switch(tdm) {
|
||||
case TDMMode::TDM2:
|
||||
return 4;
|
||||
case TDMMode::TDM4:
|
||||
return 8;
|
||||
case TDMMode::TDM8:
|
||||
return 16;
|
||||
case TDMMode::TDM12:
|
||||
return 24;
|
||||
case TDMMode::TDM16:
|
||||
return 32;
|
||||
case TDMMode::TDM20:
|
||||
return 40;
|
||||
case TDMMode::TDM24:
|
||||
return 48;
|
||||
case TDMMode::TDM32:
|
||||
return 64;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint8_t A2BMessage::getBytesPerChannel() const {
|
||||
return channelSize16 ? 2u : 4u;
|
||||
}
|
||||
size_t A2BMessage::getFrameSize() const {
|
||||
return static_cast<size_t>(2 * numChannels * getBytesPerChannel());
|
||||
}
|
||||
|
||||
size_t A2BMessage::getSampleOffset(Direction dir, uint8_t channel, size_t frame) const {
|
||||
size_t frameSize = getFrameSize();
|
||||
size_t sampleOffset = static_cast<size_t>(frameSize * frame + 2 * channel * getBytesPerChannel());
|
||||
|
||||
if(dir == Direction::Upstream) {
|
||||
sampleOffset += getBytesPerChannel();
|
||||
}
|
||||
|
||||
return sampleOffset;
|
||||
}
|
||||
|
||||
size_t A2BMessage::getNumFrames() const {
|
||||
size_t frameSize = getFrameSize();
|
||||
if(frameSize == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return data.size() / frameSize;
|
||||
}
|
||||
|
||||
A2BMessage::A2BMessage(size_t numFrames, TDMMode tdm, bool chSize16) : channelSize16(chSize16) {
|
||||
numChannels = static_cast<uint8_t>(tdmToChannelNum(tdm) / 2);
|
||||
|
||||
size_t frameSize = static_cast<size_t>(2 * numChannels * (chSize16 ? 2u : 4u));
|
||||
size_t audioBufferSize = frameSize * numFrames;
|
||||
if(audioBufferSize > maxAudioBufferSize) {
|
||||
size_t maxNumFrames = maxAudioBufferSize / frameSize;
|
||||
audioBufferSize = maxNumFrames * frameSize;
|
||||
}
|
||||
|
||||
data.resize(std::min<size_t>(maxAudioBufferSize, audioBufferSize), 0);
|
||||
}
|
||||
|
||||
A2BMessage::A2BMessage(TDMMode tdm, bool chSize16) : channelSize16(chSize16) {
|
||||
numChannels = static_cast<uint8_t>(tdmToChannelNum(tdm) / 2);
|
||||
size_t frameSize = static_cast<size_t>(2 * numChannels * (chSize16 ? 2u : 4u));
|
||||
|
||||
size_t maxNumFrames = maxAudioBufferSize / frameSize;
|
||||
size_t audioBufferSize = maxNumFrames * frameSize;
|
||||
|
||||
data.resize(audioBufferSize, 0);
|
||||
}
|
||||
|
||||
PCMSample A2BMessage::getChannelSample(Direction dir, uint8_t channel, size_t frame, PCMType pcmType) const {
|
||||
size_t sampleOffset = getSampleOffset(dir, channel, frame);
|
||||
const uint8_t* audioData = &data[sampleOffset];
|
||||
PCMSample result = 0;
|
||||
|
||||
// Samples coming from the device will either come from a 16 bit channel or 32 bit channel
|
||||
if(channelSize16) {
|
||||
int16_t sample16 = 0;
|
||||
uint16_t& uSample16 = *reinterpret_cast<uint16_t*>(&sample16);
|
||||
|
||||
// Read little endian from the audio buffer
|
||||
uSample16 = SAMPLE_FROM_BYTES_16(audioData);
|
||||
|
||||
// Scale the sample up according to the desired PCM size by
|
||||
// multiplying using logical shifting
|
||||
switch(pcmType) {
|
||||
case PCMType::L16:
|
||||
result = static_cast<PCMSample>(sample16);
|
||||
break;
|
||||
case PCMType::L24:
|
||||
result = static_cast<PCMSample>(sample16) << 8;
|
||||
break;
|
||||
case PCMType::L32:
|
||||
result = static_cast<PCMSample>(sample16) << 16;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
PCMSample sample32 = 0;
|
||||
uint32_t& uSample32 = *reinterpret_cast<uint32_t*>(&sample32);
|
||||
|
||||
// Read little endian
|
||||
uSample32 = SAMPLE_FROM_BYTES_32(audioData);
|
||||
|
||||
// Scale the sample down according to the desired PCM size by dividing using
|
||||
// logical shifting, if the A2B network was set up with the desired pcmType
|
||||
// there should be a clean division and no loss in PCM resolution.
|
||||
switch(pcmType) {
|
||||
case PCMType::L16:
|
||||
result = sample32 >> 16;
|
||||
break;
|
||||
case PCMType::L24:
|
||||
result = sample32 >> 8;
|
||||
break;
|
||||
case PCMType::L32:
|
||||
result = sample32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void A2BMessage::setChannelSample(Direction dir, uint8_t channel, size_t frame, PCMSample sampleToSet, PCMType pcmType) {
|
||||
|
||||
size_t sampleOffset = getSampleOffset(dir, channel, frame);
|
||||
uint32_t& uSample = *reinterpret_cast<uint32_t*>(&sampleToSet);
|
||||
|
||||
// Align the bytes towards the most significant bit by multiplying using
|
||||
// left shifts
|
||||
switch(pcmType) {
|
||||
case PCMType::L16:
|
||||
sampleToSet = sampleToSet << 16;
|
||||
break;
|
||||
case PCMType::L24:
|
||||
sampleToSet = sampleToSet << 8;
|
||||
break;
|
||||
case PCMType::L32:
|
||||
break;
|
||||
}
|
||||
|
||||
if(channelSize16) {
|
||||
// Read the 2 most significant bytes of the sample
|
||||
SAMPLE_TO_BYTES_16(data, sampleOffset, uSample)
|
||||
} else {
|
||||
// Read the entire sample
|
||||
SAMPLE_TO_BYTES_32(data, sampleOffset, uSample);
|
||||
}
|
||||
}
|
||||
|
||||
bool A2BMessage::loadAudioBuffer(IWAVStream& wavStream, const ChannelMap& channelMap) {
|
||||
if(!wavStream) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t totalMessageChannels = numChannels * 2; // Multiply by two inorder to include both down and upstream channels
|
||||
size_t bytesPerChannel = static_cast<size_t>(getBytesPerChannel()); // Number of bytes per message channel
|
||||
size_t frameSize = getFrameSize();
|
||||
size_t numFrames = getNumFrames();
|
||||
|
||||
size_t bytesPerSampleWAV = static_cast<size_t>(wavStream.header.bitsPerSample / 8); // Number of bytes per sample in the WAV data-stream
|
||||
size_t numWAVChannels = static_cast<size_t>(wavStream.header.numChannels);
|
||||
size_t wavFrameSize = numWAVChannels * bytesPerSampleWAV;
|
||||
|
||||
if(bytesPerSampleWAV != 2 && bytesPerSampleWAV != 3 && bytesPerSampleWAV != 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(numFrames == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t* audioBuffer = data.data();
|
||||
|
||||
std::vector<uint8_t> wavFrame(wavFrameSize, 0);
|
||||
for(size_t frame = 0; frame < numFrames; frame++) {
|
||||
|
||||
// Read one frame of data from the input stream
|
||||
if(!wavStream.read(reinterpret_cast<char*>(wavFrame.data()), wavFrame.size())) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Iterate through each mapping and set a message channel to a channel in the WAV frame above
|
||||
for(const auto& [messageChannel, wavChannel] : channelMap) {
|
||||
if(messageChannel >= totalMessageChannels || wavChannel >= numWAVChannels) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t frameOffset = wavChannel * bytesPerSampleWAV; // Offset in the read WAV frame
|
||||
size_t audioBufferOffset = frame * frameSize + messageChannel * bytesPerChannel; // Offset in the message audio buffer
|
||||
|
||||
if(bytesPerChannel < bytesPerSampleWAV) {
|
||||
// In this case, the message channels are smaller than the samples in the input WAV
|
||||
// samples in both the message channel and WAV are little endian, so we write only the
|
||||
// most significant bytes of the WAV
|
||||
|
||||
// Align to most significant bytes of wav frame
|
||||
size_t align = bytesPerSampleWAV - bytesPerChannel;
|
||||
|
||||
for(
|
||||
size_t frameByte = frameOffset + align;
|
||||
frameByte < frameOffset + bytesPerSampleWAV;
|
||||
frameByte++,
|
||||
audioBufferOffset++
|
||||
) {
|
||||
audioBuffer[audioBufferOffset] = wavFrame[frameByte];
|
||||
}
|
||||
} else {
|
||||
// The message channel is greater than or equal to the sample in the WAV
|
||||
// I2S specifies that the sample in this case is right aligned to the most significant
|
||||
// byte of the message channel
|
||||
|
||||
// Align to most significant byte of audio buffer channel
|
||||
size_t align = bytesPerChannel - bytesPerSampleWAV;
|
||||
|
||||
for(
|
||||
size_t audioByte = audioBufferOffset + align;
|
||||
audioByte < audioBufferOffset + bytesPerChannel;
|
||||
audioByte++,
|
||||
frameOffset++
|
||||
) {
|
||||
audioBuffer[audioByte] = wavFrame[frameOffset];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#include "icsneo/communication/message/allmacaddressesmessage.h"
|
||||
#include "icsneo/communication/command.h"
|
||||
#include "icsneo/communication/network.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
#pragma pack(push, 2)
|
||||
struct ResponseHeader {
|
||||
ExtendedCommand command;
|
||||
uint16_t length;
|
||||
uint16_t count;
|
||||
};
|
||||
|
||||
struct MacAddrEntryPacket {
|
||||
uint16_t networkId;
|
||||
uint8_t address[MACAddressLength];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
std::shared_ptr<AllMACAddressesMessage> AllMACAddressesMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||
if(bytestream.size() < sizeof(ResponseHeader))
|
||||
return nullptr;
|
||||
|
||||
const auto* hdr = reinterpret_cast<const ResponseHeader*>(bytestream.data());
|
||||
|
||||
if(hdr->command != ExtendedCommand::GetAllMACAddresses)
|
||||
return nullptr;
|
||||
|
||||
if(hdr->count > MaxMACAddressCount)
|
||||
return nullptr;
|
||||
|
||||
const size_t required = sizeof(ResponseHeader) + hdr->count * sizeof(MacAddrEntryPacket);
|
||||
if(bytestream.size() < required)
|
||||
return nullptr;
|
||||
|
||||
auto msg = std::make_shared<AllMACAddressesMessage>();
|
||||
|
||||
const auto* entries = reinterpret_cast<const MacAddrEntryPacket*>(bytestream.data() + sizeof(ResponseHeader));
|
||||
for(uint16_t i = 0; i < hdr->count; ++i) {
|
||||
// The firmware sends CoreMini network IDs — convert to NetID for consistent use in libicsneo
|
||||
Network::NetID netId = Network::GetNetIDFromCoreMiniNetwork(static_cast<Network::CoreMini>(entries[i].networkId));
|
||||
auto addr = entries[i].address;
|
||||
MACAddress arrAddr;
|
||||
std::copy(addr, addr + MACAddressLength, arrAddr.begin());
|
||||
msg->addresses.emplace(std::make_pair(netId, arrAddr));
|
||||
}
|
||||
|
||||
return msg;
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
#include <icsneo/communication/message/apperrormessage.h>
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
#pragma pack(push, 2)
|
||||
|
||||
typedef struct {
|
||||
uint16_t error_type;
|
||||
uint16_t network_id;
|
||||
uint32_t uiTimeStamp10uS;
|
||||
uint32_t uiTimeStamp10uSMSB;
|
||||
} AppErrorData;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
std::shared_ptr<Message> AppErrorMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream, const device_eventhandler_t& report) {
|
||||
const AppErrorData* data = reinterpret_cast<const AppErrorData*>(bytestream.data());
|
||||
if(!data) {
|
||||
report(APIEvent::Type::AppErrorParsingFailed, APIEvent::Severity::Error);
|
||||
return nullptr;
|
||||
}
|
||||
auto appErr = std::make_shared<AppErrorMessage>();
|
||||
appErr->errorType = data->error_type;
|
||||
appErr->errorNetID = static_cast<Network::NetID>(data->network_id);
|
||||
appErr->timestamp10us = data->uiTimeStamp10uS;
|
||||
appErr->timestamp10usMSB = data->uiTimeStamp10uSMSB;
|
||||
appErr->network = Network::NetID::RED_App_Error;
|
||||
return appErr;
|
||||
}
|
||||
|
||||
AppErrorType AppErrorMessage::getAppErrorType() {
|
||||
AppErrorType errType = static_cast<AppErrorType>(errorType);
|
||||
if(errType > AppErrorType::AppNoError) {
|
||||
return AppErrorType::AppNoError;
|
||||
}
|
||||
return errType;
|
||||
}
|
||||
|
||||
std::string AppErrorMessage::getAppErrorString() {
|
||||
auto netIDString = Network::GetNetIDString(errorNetID);
|
||||
AppErrorType errType = static_cast<AppErrorType>(errorType);
|
||||
switch (errType) {
|
||||
case AppErrorType::AppErrorRxMessagesFull:
|
||||
return std::string(netIDString) + ": RX message buffer full";
|
||||
case AppErrorType::AppErrorTxMessagesFull:
|
||||
return std::string(netIDString) + ": TX message buffer full";
|
||||
case AppErrorType::AppErrorTxReportMessagesFull:
|
||||
return std::string(netIDString) + ": TX report buffer full";
|
||||
case AppErrorType::AppErrorBadCommWithDspIC:
|
||||
return "Received bad packet from DSP IC";
|
||||
case AppErrorType::AppErrorDriverOverflow:
|
||||
return std::string(netIDString) + ": Driver overflow";
|
||||
case AppErrorType::AppErrorPCBuffOverflow:
|
||||
return "PC buffer overflow";
|
||||
case AppErrorType::AppErrorPCChksumError:
|
||||
return "PC checksum error";
|
||||
case AppErrorType::AppErrorPCMissedByte:
|
||||
return "PC missed byte";
|
||||
case AppErrorType::AppErrorPCOverrunError:
|
||||
return "PC overrun error";
|
||||
case AppErrorType::AppErrorSettingFailure:
|
||||
return std::string(netIDString) + ": Settings incorrectly set";
|
||||
case AppErrorType::AppErrorTooManySelectedNetworks:
|
||||
return "Too many selected networks";
|
||||
case AppErrorType::AppErrorNetworkNotEnabled:
|
||||
return std::string(netIDString) + ": Network not enabled";
|
||||
case AppErrorType::AppErrorRtcNotCorrect:
|
||||
return "RTC not correct";
|
||||
case AppErrorType::AppErrorLoadedDefaultSettings:
|
||||
return "Loaded default settings";
|
||||
case AppErrorType::AppErrorFeatureNotUnlocked:
|
||||
return "Feature not unlocked";
|
||||
case AppErrorType::AppErrorFeatureRtcCmdDropped:
|
||||
return "RTC command dropped";
|
||||
case AppErrorType::AppErrorTxMessagesFlushed:
|
||||
return "TX message buffer flushed";
|
||||
case AppErrorType::AppErrorTxMessagesHalfFull:
|
||||
return "TX message buffer half full";
|
||||
case AppErrorType::AppErrorNetworkNotValid:
|
||||
return "Network is not valid";
|
||||
case AppErrorType::AppErrorTxInterfaceNotImplemented:
|
||||
return "TX interface is not implemented";
|
||||
case AppErrorType::AppErrorTxMessagesCommEnableIsOff:
|
||||
return "TX message communication is disabled";
|
||||
case AppErrorType::AppErrorRxFilterMatchCountExceeded:
|
||||
return "RX filter match count exceeded";
|
||||
case AppErrorType::AppErrorEthPreemptionNotEnabled:
|
||||
return std::string(netIDString) + ": Ethernet preemption not enabled";
|
||||
case AppErrorType::AppErrorTxNotSupportedInMode:
|
||||
return std::string(netIDString) + ": Transmit is not supported in this mode";
|
||||
case AppErrorType::AppErrorJumboFramesNotSupported:
|
||||
return std::string(netIDString) + ": Jumbo frames not supported";
|
||||
case AppErrorType::AppErrorEthernetIpFragment:
|
||||
return "Ethernet IP fragment received";
|
||||
case AppErrorType::AppErrorTxMessagesUnderrun:
|
||||
return std::string(netIDString) + ": Transmit buffer underrun";
|
||||
case AppErrorType::AppErrorDeviceFanFailure:
|
||||
return "Device fan failure";
|
||||
case AppErrorType::AppErrorDeviceOvertemperature:
|
||||
return "Device overtemperature";
|
||||
case AppErrorType::AppErrorTxMessageIndexOutOfRange:
|
||||
return "Transmit message index out of range";
|
||||
case AppErrorType::AppErrorUndersizedFrameDropped:
|
||||
return std::string(netIDString) + ": Undersized frame dropped";
|
||||
case AppErrorType::AppErrorOversizedFrameDropped:
|
||||
return std::string(netIDString) + ": Oversized frame dropped";
|
||||
case AppErrorType::AppErrorWatchdogEvent:
|
||||
return "Watchdog event occured";
|
||||
case AppErrorType::AppErrorSystemClockFailure:
|
||||
return "Device clock failed";
|
||||
case AppErrorType::AppErrorSystemClockRecovered:
|
||||
return "Device clock recovered";
|
||||
case AppErrorType::AppErrorSystemPeripheralReset:
|
||||
return "Device peripheral reset";
|
||||
case AppErrorType::AppErrorSystemCommunicationFailure:
|
||||
return "Device communication failure";
|
||||
case AppErrorType::AppErrorTxMessagesUnsupportedSourceOrPacketId:
|
||||
return std::string(netIDString) + ": Transmit unsupported source or packet ID";
|
||||
case AppErrorType::AppErrorWbmsManagerConnectFailed:
|
||||
return std::string(netIDString) + ": Failed to connect to managers with settings";
|
||||
case AppErrorType::AppErrorWbmsManagerConnectBadState:
|
||||
return std::string(netIDString) + ": Connected to managers in a invalid state";
|
||||
case AppErrorType::AppErrorWbmsManagerConnectTimeout:
|
||||
return std::string(netIDString) + ": Timeout while attempting to connect to managers";
|
||||
case AppErrorType::AppErrorFailedToInitializeLoggerDisk:
|
||||
return "Device failed to initialize storage disk";
|
||||
case AppErrorType::AppErrorInvalidSetting:
|
||||
return std::string(netIDString) + ": Invalid settings";
|
||||
case AppErrorType::AppErrorSystemFailureRequestedReset:
|
||||
return "Device rebooted to recover from an unexpected error condition";
|
||||
case AppErrorType::AppErrorPortKeyMistmatch:
|
||||
return std::string(netIDString) + ": Mismatch between key in manager and stored key";
|
||||
case AppErrorType::AppErrorBusFailure:
|
||||
return std::string(netIDString) + ": Bus failure";
|
||||
case AppErrorType::AppErrorTapOverflow:
|
||||
return std::string(netIDString) + ": Tap overflow";
|
||||
case AppErrorType::AppErrorEthTxNoLink:
|
||||
return std::string(netIDString) + ": Attempted Ethernet transmit without link";
|
||||
case AppErrorType::AppErrorErrorBufferOverflow:
|
||||
return "Device error buffer overflow";
|
||||
case AppErrorType::AppNoError:
|
||||
return "No error";
|
||||
default:
|
||||
return "Unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
@@ -0,0 +1,234 @@
|
||||
#include "icsneo/communication/message/callback/streamoutput/a2bwavoutput.h"
|
||||
#include "icsneo/device/tree/rada2b/rada2b.h"
|
||||
#include "icsneo/icsneocpp.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
A2BWAVOutput::A2BWAVOutput(
|
||||
const char* filename,
|
||||
const ChannelMap& channelMap,
|
||||
PCMType bitDepth,
|
||||
size_t numWAVChannels,
|
||||
uint32_t sampleRate
|
||||
)
|
||||
: StreamOutput(filename), wavSampleRate(sampleRate), numChannelsWAV(numWAVChannels), chMap(channelMap) {
|
||||
switch(bitDepth) {
|
||||
case PCMType::L16:
|
||||
bytesPerSampleWAV = 2;
|
||||
break;
|
||||
case PCMType::L24:
|
||||
bytesPerSampleWAV = 3;
|
||||
break;
|
||||
case PCMType::L32:
|
||||
bytesPerSampleWAV = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
if(initialize()) {
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
A2BWAVOutput::A2BWAVOutput(
|
||||
std::ostream& os,
|
||||
const ChannelMap& channelMap,
|
||||
PCMType bitDepth,
|
||||
size_t numWAVChannels,
|
||||
uint32_t sampleRate
|
||||
)
|
||||
: StreamOutput(os), wavSampleRate(sampleRate), numChannelsWAV(numWAVChannels), chMap(channelMap) {
|
||||
switch(bitDepth) {
|
||||
case PCMType::L16:
|
||||
bytesPerSampleWAV = 2;
|
||||
break;
|
||||
case PCMType::L24:
|
||||
bytesPerSampleWAV = 3;
|
||||
break;
|
||||
case PCMType::L32:
|
||||
bytesPerSampleWAV = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
if(initialize()) {
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
A2BWAVOutput::~A2BWAVOutput() {
|
||||
if(!closed) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
bool A2BWAVOutput::initialize() {
|
||||
static constexpr size_t maxWAVChannels = 256;
|
||||
|
||||
if(numChannelsWAV > maxWAVChannels) {
|
||||
return false;
|
||||
}
|
||||
|
||||
maxMessageChannel = 0;
|
||||
|
||||
// Check if the inputted channel map has invalid mappings and compute maxMessageChannel
|
||||
for(auto [wavChannel, messageChannel] : chMap) {
|
||||
maxMessageChannel = std::max<size_t>(maxMessageChannel, messageChannel);
|
||||
if(wavChannel >= numChannelsWAV) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
WAVHeader header = WAVHeader(
|
||||
static_cast<uint16_t>(chMap.size()),
|
||||
wavSampleRate,
|
||||
static_cast<uint16_t>(bytesPerSampleWAV * 8)
|
||||
);
|
||||
|
||||
if(!stream->write(reinterpret_cast<const char*>(&header), sizeof(WAVHeader))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
streamStartPos = static_cast<uint32_t>(stream->tellp());
|
||||
wavBuffer = std::vector<uint8_t>(wavBufferSize, 0);
|
||||
wavBufferOffset = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool A2BWAVOutput::callIfMatch(const std::shared_ptr<Message>& message) const {
|
||||
if(!initialized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(closed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(message->type != Message::Type::Frame) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& frameMsg = std::dynamic_pointer_cast<Frame>(message);
|
||||
|
||||
if(!frameMsg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(frameMsg->network.getType() != Network::Type::A2B)
|
||||
return false;
|
||||
|
||||
const auto& a2bMsg = std::dynamic_pointer_cast<A2BMessage>(frameMsg);
|
||||
|
||||
if(!a2bMsg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t frameSize = a2bMsg->getFrameSize();
|
||||
size_t wavFrameSize = numChannelsWAV * bytesPerSampleWAV;
|
||||
size_t bytesPerChannel = static_cast<size_t>(a2bMsg->getBytesPerChannel());
|
||||
size_t numMessageChannels = 2 * a2bMsg->numChannels;
|
||||
size_t numFrames = a2bMsg->getNumFrames();
|
||||
|
||||
const uint8_t* audioBuffer = a2bMsg->data.data();
|
||||
|
||||
if(maxMessageChannel >= numMessageChannels) {
|
||||
// The max message channel in our channel map is larger than the number of channels in this message
|
||||
// this is likely due to the user inputting incorrect settings
|
||||
return false;
|
||||
}
|
||||
|
||||
for(size_t frame = 0; frame < numFrames; frame++) {
|
||||
// Check to see if we can read another frame in wavBuffer, otherwise write and clear the buffer
|
||||
if(wavBufferOffset + wavFrameSize >= wavBufferSize) {
|
||||
if(!writeCurrentBuffer()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for(size_t wavChannel = 0; wavChannel < numChannelsWAV; wavChannel++) {
|
||||
if(auto iter = chMap.find(static_cast<uint8_t>(wavChannel)); iter != chMap.end()) {
|
||||
auto messageChannel = iter->second;
|
||||
size_t messageChannelOffset = messageChannel * bytesPerChannel + frameSize* frame;
|
||||
|
||||
// Samples in the WAV are little endian signed integers
|
||||
// Samples in the message channels are little endian signed integers that are
|
||||
// most significant bit aligned
|
||||
if(a2bMsg->channelSize16) {
|
||||
// In this case, the channel size will be less than or equal to the sample we are writing
|
||||
// so we zero out any of the least significant bytes which won't be occupied by a sample byte
|
||||
|
||||
for(size_t zeroByte = 0; zeroByte < bytesPerSampleWAV - bytesPerChannel; zeroByte++) {
|
||||
wavBuffer[wavBufferOffset++] = 0;
|
||||
}
|
||||
|
||||
// Write the channel data in the most signifant bytes of the wav sample, this effectively
|
||||
// writes a sample which is scaled up.
|
||||
for(size_t channelByte = 0; channelByte < bytesPerChannel; channelByte++) {
|
||||
wavBuffer[wavBufferOffset++] = audioBuffer[messageChannelOffset + channelByte];
|
||||
}
|
||||
} else {
|
||||
// In this case, the channel size will be greater than or equal to the sample we are reading
|
||||
|
||||
// Align the wav sample with the most significant bytes of the channel
|
||||
size_t channelByte = messageChannelOffset + (bytesPerChannel - bytesPerSampleWAV);
|
||||
|
||||
// Read the most significant bytes of the channel into the wavBuffer
|
||||
for(size_t sampleByte = 0; sampleByte < bytesPerSampleWAV; sampleByte++, channelByte++) {
|
||||
wavBuffer[wavBufferOffset++] = audioBuffer[channelByte];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If this channel wasn't specified in the channel map, set a zero sample
|
||||
for(
|
||||
size_t sampleByte = 0;
|
||||
sampleByte < bytesPerSampleWAV;
|
||||
sampleByte++
|
||||
) {
|
||||
wavBuffer[wavBufferOffset++] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void A2BWAVOutput::close() const {
|
||||
if(closed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Write any left over data in the buffer
|
||||
if(wavBufferOffset > 0) {
|
||||
writeCurrentBuffer();
|
||||
}
|
||||
|
||||
// Seek back in the output stream and write the WAV chunk sizes
|
||||
uint32_t streamEndPos = static_cast<uint32_t>(stream->tellp());
|
||||
|
||||
uint32_t subChunk2Size = streamEndPos - streamStartPos;
|
||||
uint32_t chunkSize = streamEndPos - 8;
|
||||
|
||||
stream->seekp(streamStartPos - 4);
|
||||
stream->write(reinterpret_cast<const char*>(&subChunk2Size), 4);
|
||||
stream->seekp(4, std::ios::beg);
|
||||
stream->write(reinterpret_cast<const char*>(&chunkSize), 4);
|
||||
|
||||
closed = true;
|
||||
}
|
||||
|
||||
bool A2BWAVOutput::writeCurrentBuffer() const {
|
||||
|
||||
if(!stream->write(reinterpret_cast<const char*>(wavBuffer.data()), wavBufferOffset)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
wavBufferOffset = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#include "icsneo/communication/message/clientidmessage.h"
|
||||
#include "icsneo/communication/icspb.h"
|
||||
#include "icsneo/communication/command.h"
|
||||
#include "icsneo/communication/message/extendedresponsemessage.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
std::shared_ptr<ClientIdMessage> ClientIdMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||
ClientIdMessage decoded;
|
||||
commands::generic::v1::ClientId msg;
|
||||
|
||||
if(!protoapi::processResponse(bytestream.data(), bytestream.size(), msg)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(msg.has_client_id()) {
|
||||
decoded.clientId.emplace(msg.client_id());
|
||||
}
|
||||
|
||||
return std::make_shared<ClientIdMessage>(decoded);
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
#include "icsneo/communication/message/ethernetstatusmessage.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
enum LinkSpeed {
|
||||
ethSpeed10,
|
||||
ethSpeed100,
|
||||
ethSpeed1000,
|
||||
ethSpeedAutoNeg,
|
||||
ethSpeed2500,
|
||||
ethSpeed5000,
|
||||
ethSpeed10000,
|
||||
};
|
||||
|
||||
enum TLinkMode {
|
||||
T_LINK_NONE,
|
||||
T_LINK_MASTER,
|
||||
T_LINK_SLAVE,
|
||||
T_LINK_AUTO,
|
||||
T_LINK_INVALID = 255,
|
||||
};
|
||||
|
||||
enum AELinkMode {
|
||||
AE_LINK_AUTO,
|
||||
AE_LINK_MASTER,
|
||||
AE_LINK_SLAVE,
|
||||
AE_LINK_INVALID = 255,
|
||||
};
|
||||
|
||||
struct Packet {
|
||||
uint8_t state;
|
||||
uint8_t speed;
|
||||
uint8_t duplex;
|
||||
uint16_t network;
|
||||
uint8_t mode;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
std::shared_ptr<RawMessage> EthernetStatusMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||
if(bytestream.size() < sizeof(Packet)) {
|
||||
return nullptr;
|
||||
}
|
||||
Packet* packet = (Packet*)bytestream.data();
|
||||
LinkSpeed speed;
|
||||
switch(packet->speed) {
|
||||
case ethSpeed10: speed = EthernetStatusMessage::LinkSpeed::LinkSpeed10; break;
|
||||
case ethSpeed100: speed = EthernetStatusMessage::LinkSpeed::LinkSpeed100; break;
|
||||
case ethSpeed1000: speed = EthernetStatusMessage::LinkSpeed::LinkSpeed1000; break;
|
||||
case ethSpeedAutoNeg: speed = EthernetStatusMessage::LinkSpeed::LinkSpeedAuto; break;
|
||||
case ethSpeed2500: speed = EthernetStatusMessage::LinkSpeed::LinkSpeed2500; break;
|
||||
case ethSpeed5000: speed = EthernetStatusMessage::LinkSpeed::LinkSpeed5000; break;
|
||||
case ethSpeed10000: speed = EthernetStatusMessage::LinkSpeed::LinkSpeed10000; break;
|
||||
default: return nullptr;
|
||||
}
|
||||
LinkMode mode;
|
||||
switch(Network::GetTypeOfNetID((Network::NetID)packet->network, false)) {
|
||||
case Network::Type::Ethernet:
|
||||
switch(packet->mode) {
|
||||
case T_LINK_NONE: mode = EthernetStatusMessage::LinkMode::LinkModeNone; break;
|
||||
case T_LINK_MASTER: mode = EthernetStatusMessage::LinkMode::LinkModeMaster; break;
|
||||
case T_LINK_SLAVE: mode = EthernetStatusMessage::LinkMode::LinkModeSlave; break;
|
||||
case T_LINK_AUTO: mode = EthernetStatusMessage::LinkMode::LinkModeAuto; break;
|
||||
case T_LINK_INVALID: mode = EthernetStatusMessage::LinkMode::LinkModeInvalid; break;
|
||||
default: return nullptr;
|
||||
}
|
||||
break;
|
||||
case Network::Type::AutomotiveEthernet:
|
||||
switch(packet->mode) {
|
||||
case AE_LINK_AUTO: mode = EthernetStatusMessage::LinkMode::LinkModeAuto; break;
|
||||
case AE_LINK_MASTER: mode = EthernetStatusMessage::LinkMode::LinkModeMaster; break;
|
||||
case AE_LINK_SLAVE: mode = EthernetStatusMessage::LinkMode::LinkModeSlave; break;
|
||||
case AE_LINK_INVALID: mode = EthernetStatusMessage::LinkMode::LinkModeInvalid; break;
|
||||
default: return nullptr;
|
||||
}
|
||||
break;
|
||||
default: return nullptr;
|
||||
}
|
||||
return std::make_shared<EthernetStatusMessage>(packet->network, packet->state != 0, speed, packet->duplex != 0, mode);
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#include "icsneo/communication/message/ethphymessage.h"
|
||||
|
||||
namespace icsneo
|
||||
{
|
||||
bool EthPhyMessage::appendPhyMessage(bool writeEnable, bool clause45, uint8_t phyAddrOrPort, uint8_t pageOrDevice, uint16_t regAddr, uint16_t regVal, bool enabled)
|
||||
{
|
||||
auto msg = std::make_shared<PhyMessage>();
|
||||
msg->Clause45Enable = clause45;
|
||||
msg->Enabled = enabled;
|
||||
msg->WriteEnable = writeEnable;
|
||||
msg->Version = 1u;
|
||||
if( (FiveBits < phyAddrOrPort) ||
|
||||
(clause45 && (FiveBits < pageOrDevice)) ||
|
||||
(!clause45 && (FiveBits < regAddr)) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(clause45)
|
||||
{
|
||||
msg->Clause45.port = phyAddrOrPort;
|
||||
msg->Clause45.device = pageOrDevice;
|
||||
msg->Clause45.regAddr = regAddr;
|
||||
msg->Clause45.regVal = regVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
msg->Clause22.phyAddr = phyAddrOrPort;
|
||||
msg->Clause22.page = pageOrDevice;
|
||||
msg->Clause22.regAddr = regAddr;
|
||||
msg->Clause22.regVal = regVal;
|
||||
}
|
||||
return appendPhyMessage(msg);
|
||||
}
|
||||
|
||||
bool EthPhyMessage::appendPhyMessage(std::shared_ptr<PhyMessage> message)
|
||||
{
|
||||
if(message)
|
||||
{
|
||||
messages.push_back(message);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t EthPhyMessage::getMessageCount() const
|
||||
{
|
||||
return messages.size();
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,8 @@ using namespace icsneo;
|
||||
|
||||
std::vector<uint8_t> FlexRayControlMessage::BuildBaseControlArgs(uint8_t controller, FlexRay::Opcode op, const std::vector<uint8_t>& args) {
|
||||
std::vector<uint8_t> ret;
|
||||
ret.reserve(args.size() + 4);
|
||||
ret.push_back(controller);
|
||||
const uint16_t size = uint16_t((std::min)(args.size() + 1, size_t(std::numeric_limits<uint16_t>::max()))); // Add 1 for the opcode
|
||||
const uint16_t size = static_cast<uint16_t>(std::min(args.size() + 1, size_t(std::numeric_limits<uint16_t>::max()))); // Add 1 for the opcode
|
||||
ret.push_back(uint8_t(size));
|
||||
ret.push_back(uint8_t(size >> 8));
|
||||
ret.push_back(uint8_t(op));
|
||||
@@ -59,14 +58,12 @@ std::vector<uint8_t> FlexRayControlMessage::BuildWriteMessageBufferArgs(
|
||||
uint8_t(desiredSize / 4)
|
||||
};
|
||||
args.insert(args.end(), data.begin(), data.end());
|
||||
if(args.size() != desiredSize + 2)
|
||||
if((int)args.size() != desiredSize + 2)
|
||||
args.resize(desiredSize + 2);
|
||||
return BuildBaseControlArgs(controller, FlexRay::Opcode::WriteMessageBuffer, args);
|
||||
}
|
||||
|
||||
FlexRayControlMessage::FlexRayControlMessage(const Packet& packet) : Message() {
|
||||
network = Network::NetID::FlexRayControl;
|
||||
|
||||
FlexRayControlMessage::FlexRayControlMessage(const Packet& packet) : Message(Message::Type::FlexRayControl) {
|
||||
if(packet.data.size() < 2)
|
||||
return; // huh?
|
||||
controller = packet.data[0];
|
||||
@@ -77,7 +74,7 @@ FlexRayControlMessage::FlexRayControlMessage(const Packet& packet) : Message() {
|
||||
opcode = FlexRay::Opcode(packet.data[1]);
|
||||
if(opcode != FlexRay::Opcode::ReadCCRegs && opcode != FlexRay::Opcode::ReadCCStatus)
|
||||
return;
|
||||
|
||||
|
||||
// Read out registers
|
||||
size_t bytes = packet.data.size() - 2;
|
||||
const size_t count = bytes / sizeof(uint32_t);
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#include "icsneo/communication/message/genericapidatamessage.h"
|
||||
#include "icsneo/communication/message/extendedresponsemessage.h"
|
||||
#include "icsneo/communication/command.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
std::shared_ptr<GenericAPIDataMessage> GenericAPIDataMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||
if(bytestream.size() < sizeof(ExtendedResponseMessage::ResponseHeader))
|
||||
return nullptr;
|
||||
|
||||
const auto* hdr = reinterpret_cast<const ExtendedResponseMessage::ResponseHeader*>(bytestream.data());
|
||||
|
||||
if(hdr->command != ExtendedCommand::ReadGenericAPIData)
|
||||
return nullptr;
|
||||
|
||||
const size_t required = sizeof(ExtendedResponseMessage::ResponseHeader) + sizeof(GenericAPIDataHeader);
|
||||
if(bytestream.size() < required)
|
||||
return nullptr;
|
||||
|
||||
auto msg = std::make_shared<GenericAPIDataMessage>();
|
||||
|
||||
const auto* packet = reinterpret_cast<const GenericAPIDataPacket*>(bytestream.data() + sizeof(ExtendedResponseMessage::ResponseHeader));
|
||||
|
||||
msg->functionId = packet->header.functionId;
|
||||
msg->buffer.resize(packet->header.bufferLength);
|
||||
std::copy(packet->buffer, packet->buffer + packet->header.bufferLength, msg->buffer.data());
|
||||
return msg;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#include "icsneo/communication/message/genericapistatusmessage.h"
|
||||
#include "icsneo/communication/message/extendedresponsemessage.h"
|
||||
#include "icsneo/communication/command.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
std::shared_ptr<GenericAPIStatusMessage> GenericAPIStatusMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||
if(bytestream.size() < sizeof(ExtendedResponseMessage::ResponseHeader))
|
||||
return nullptr;
|
||||
|
||||
const auto* hdr = reinterpret_cast<const ExtendedResponseMessage::ResponseHeader*>(bytestream.data());
|
||||
|
||||
if(hdr->command != ExtendedCommand::ReadGenericAPIStatus)
|
||||
return nullptr;
|
||||
|
||||
const size_t required = sizeof(ExtendedResponseMessage::ResponseHeader) + sizeof(GenericAPIStatusResponsePacket);
|
||||
if(bytestream.size() < required)
|
||||
return nullptr;
|
||||
|
||||
auto msg = std::make_shared<GenericAPIStatusMessage>();
|
||||
|
||||
const auto* packet = reinterpret_cast<const GenericAPIStatusResponsePacket*>(bytestream.data() + sizeof(ExtendedResponseMessage::ResponseHeader));
|
||||
|
||||
msg->functionId = packet->functionId;
|
||||
msg->finishedProcessing = static_cast<bool>(packet->finishedProcessing);
|
||||
msg->functionError = packet->functionError;
|
||||
msg->callbackError = packet->callbackError;
|
||||
return msg;
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
#include <icsneo/communication/message/gptpstatusmessage.h>
|
||||
#include <icsneo/communication/message/extendedresponsemessage.h>
|
||||
#include <cstring>
|
||||
|
||||
namespace icsneo {
|
||||
typedef double float64;
|
||||
typedef int64_t time_interval;
|
||||
typedef uint64_t _clock_identity;
|
||||
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct port_identity {
|
||||
_clock_identity clock_identity;
|
||||
uint16_t port_number;
|
||||
};
|
||||
|
||||
struct _scaled_ns {
|
||||
int16_t nanoseconds_msb;
|
||||
int64_t nanoseconds_lsb;
|
||||
int16_t fractional_nanoseconds;
|
||||
};
|
||||
|
||||
struct _clock_quality {
|
||||
uint8_t clock_class;
|
||||
uint8_t clock_accuracy;
|
||||
uint16_t offset_scaled_log_variance;
|
||||
};
|
||||
|
||||
struct system_identity {
|
||||
uint8_t priority_1;
|
||||
struct _clock_quality clock_quality;
|
||||
uint8_t priority_2;
|
||||
_clock_identity clock_identity;
|
||||
};
|
||||
|
||||
struct _timestamp {
|
||||
uint16_t seconds_msb;
|
||||
uint32_t seconds_lsb;
|
||||
uint32_t nanoseconds;
|
||||
};
|
||||
|
||||
struct priority_vector {
|
||||
struct system_identity sysid;
|
||||
uint16_t steps_removed;
|
||||
struct port_identity portid;
|
||||
uint16_t port_number;
|
||||
};
|
||||
|
||||
|
||||
// IEEE 802.1AS-2020 14.3
|
||||
// This is a read-only data structure
|
||||
struct _current_ds {
|
||||
uint16_t steps_removed;
|
||||
time_interval offset_from_master;
|
||||
struct _scaled_ns last_gm_phase_change;
|
||||
float64 last_gm_freq_change;
|
||||
uint16_t gm_time_base_indicator;
|
||||
uint32_t gm_change_count;
|
||||
uint32_t time_of_last_gm_change_event;
|
||||
uint32_t time_of_last_gm_phase_change_event;
|
||||
uint32_t time_of_last_gm_freq_change_event;
|
||||
};
|
||||
|
||||
// IEEE 802.1AS-2020 14.4
|
||||
// This is a read-only data structure
|
||||
struct _parent_ds {
|
||||
struct port_identity parent_port_identity;
|
||||
int32_t cumulative_rate_ratio;
|
||||
_clock_identity grandmaster_identity;
|
||||
uint8_t gm_clock_quality_clock_class;
|
||||
uint8_t gm_clock_quality_clock_accuracy;
|
||||
uint16_t gm_clock_quality_offset_scaled_log_variance;
|
||||
uint8_t gm_priority1;
|
||||
uint8_t gm_priority2;
|
||||
};
|
||||
|
||||
struct _GPTPStatus
|
||||
{
|
||||
struct _timestamp current_time;
|
||||
struct priority_vector gm_priority;
|
||||
int64_t ms_offset_ns;
|
||||
uint8_t is_sync;
|
||||
uint8_t link_status;
|
||||
int64_t link_delay_ns;
|
||||
uint8_t selected_role;
|
||||
uint8_t as_capable;
|
||||
uint8_t is_syntonized;
|
||||
struct _timestamp last_rx_sync_ts; // t2 in IEEE 1588-2019 Figure-16
|
||||
struct _current_ds current_ds;
|
||||
struct _parent_ds parent_ds;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
static void SetField(GPTPStatus::Timestamp& output, const _timestamp& input) {
|
||||
output.seconds = ((uint64_t)(input.seconds_msb) << 32) | ((uint64_t)input.seconds_lsb);
|
||||
output.nanoseconds = input.nanoseconds;
|
||||
}
|
||||
|
||||
static void SetField(GPTPStatus::PortID& output, const port_identity& input) {
|
||||
output.clockIdentity = input.clock_identity;
|
||||
output.portNumber = input.port_number;
|
||||
}
|
||||
static void SetField(GPTPStatus::ClockQuality& output, const _clock_quality& input) {
|
||||
output.clockClass = input.clock_class;
|
||||
output.clockAccuracy = input.clock_accuracy;
|
||||
output.offsetScaledLogVariance = input.offset_scaled_log_variance;
|
||||
}
|
||||
|
||||
static void SetField(GPTPStatus::SystemID& output, const system_identity& input) {
|
||||
output.priority1 = input.priority_1;
|
||||
SetField(output.clockQuality, input.clock_quality);
|
||||
output.priority2 = input.priority_2;
|
||||
output.clockID = input.clock_identity;
|
||||
}
|
||||
|
||||
static void SetField(GPTPStatus::ScaledNanoSeconds& output, const _scaled_ns& input) {
|
||||
output.nanosecondsMSB = input.nanoseconds_msb;
|
||||
output.nanosecondsLSB = input.nanoseconds_lsb;
|
||||
output.fractionalNanoseconds = input.fractional_nanoseconds;
|
||||
}
|
||||
|
||||
static void SetField(GPTPStatus::PriorityVector& output, const priority_vector& input) {
|
||||
SetField(output.sysID, input.sysid);
|
||||
output.stepsRemoved = input.steps_removed;
|
||||
SetField(output.portID, input.portid);
|
||||
output.portNumber = input.port_number;
|
||||
}
|
||||
|
||||
static void SetField(GPTPStatus::CurrentDS& output, const _current_ds& input) {
|
||||
output.stepsRemoved = input.steps_removed;
|
||||
output.offsetFromMaster = input.offset_from_master;
|
||||
SetField(output.lastgmPhaseChange, input.last_gm_phase_change);
|
||||
output.lastgmFreqChange = input.last_gm_freq_change;
|
||||
output.gmTimeBaseIndicator = input.gm_time_base_indicator;
|
||||
output.gmChangeCount = input.gm_change_count;
|
||||
output.timeOfLastgmChangeEvent = input.time_of_last_gm_change_event;
|
||||
output.timeOfLastgmPhaseChangeEvent = input.time_of_last_gm_phase_change_event;
|
||||
output.timeOfLastgmFreqChangeEvent = input.time_of_last_gm_freq_change_event;
|
||||
}
|
||||
|
||||
static void SetField(GPTPStatus::ParentDS& output, const _parent_ds& input) {
|
||||
SetField(output.parentPortIdentity, input.parent_port_identity);
|
||||
output.cumulativeRateRatio = input.cumulative_rate_ratio;
|
||||
output.grandmasterIdentity = input.grandmaster_identity;
|
||||
output.gmClockQualityClockClass = input.gm_clock_quality_clock_class;
|
||||
output.gmClockQualityClockAccuracy = input.gm_clock_quality_clock_accuracy;
|
||||
output.gmClockQualityOffsetScaledLogVariance = input.gm_clock_quality_offset_scaled_log_variance;
|
||||
output.gmPriority1 = input.gm_priority1;
|
||||
output.gmPriority2 = input.gm_priority2;
|
||||
}
|
||||
|
||||
[[maybe_unused]] static void SetField(uint8_t& output, const uint8_t& input) {
|
||||
output = input;
|
||||
}
|
||||
|
||||
[[maybe_unused]] static void SetField(uint16_t& output, const uint16_t& input) {
|
||||
output = input;
|
||||
}
|
||||
|
||||
[[maybe_unused]] static void SetField(uint32_t& output, const uint32_t& input) {
|
||||
output = input;
|
||||
}
|
||||
|
||||
[[maybe_unused]] static void SetField(uint64_t& output, const uint64_t& input) {
|
||||
output = input;
|
||||
}
|
||||
|
||||
[[maybe_unused]] static void SetField(int8_t& output, const int8_t& input) {
|
||||
output = input;
|
||||
}
|
||||
|
||||
[[maybe_unused]] static void SetField(int16_t& output, const int16_t& input) {
|
||||
output = input;
|
||||
}
|
||||
|
||||
[[maybe_unused]] static void SetField(int32_t& output, const int32_t& input) {
|
||||
output = input;
|
||||
}
|
||||
|
||||
[[maybe_unused]] static void SetField(int64_t& output, const int64_t& input) {
|
||||
output = input;
|
||||
}
|
||||
|
||||
std::shared_ptr<GPTPStatus> GPTPStatus::DecodeToMessage(std::vector<uint8_t>& bytes, const device_eventhandler_t&) {
|
||||
|
||||
// The following does not lead to overflow since we only call this function if it has at least ResponseHeader length bytes
|
||||
std::shared_ptr<GPTPStatus> res = std::make_shared<GPTPStatus>();
|
||||
auto* header = reinterpret_cast<ExtendedResponseMessage::ResponseHeader*>(bytes.data());
|
||||
uint16_t length = header->length;
|
||||
_GPTPStatus* input = reinterpret_cast<_GPTPStatus*>(bytes.data() + sizeof(ExtendedResponseMessage::ResponseHeader));
|
||||
|
||||
#define CheckLengthAndSet(output, input) if(length >= sizeof(decltype(input))) { \
|
||||
SetField(output, input); \
|
||||
length -= sizeof(decltype(input)); \
|
||||
} else {\
|
||||
memset(&output, 0, sizeof(decltype(output))); \
|
||||
length = 0; \
|
||||
res->shortFormat = true; \
|
||||
}
|
||||
|
||||
CheckLengthAndSet(res->currentTime, input->current_time);
|
||||
CheckLengthAndSet(res->gmPriority, input->gm_priority);
|
||||
CheckLengthAndSet(res->msOffsetNs, input->ms_offset_ns);
|
||||
CheckLengthAndSet(res->isSync, input->is_sync);
|
||||
CheckLengthAndSet(res->linkStatus, input->link_status);
|
||||
CheckLengthAndSet(res->linkDelayNS, input->link_delay_ns);
|
||||
CheckLengthAndSet(res->selectedRole, input->selected_role);
|
||||
CheckLengthAndSet(res->asCapable, input->as_capable);
|
||||
CheckLengthAndSet(res->isSyntonized, input->is_syntonized);
|
||||
CheckLengthAndSet(res->lastRXSyncTS, input->last_rx_sync_ts);
|
||||
CheckLengthAndSet(res->currentDS, input->current_ds);
|
||||
CheckLengthAndSet(res->parentDS, input->parent_ds);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,337 @@
|
||||
#include "icsneo/communication/message/iso15765message.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
std::shared_ptr<J2534CommandMessage> J2534CommandMessage::decodeToMessage(const std::vector<uint8_t>& data) {
|
||||
if(data.size() < 2)
|
||||
return nullptr;
|
||||
|
||||
auto msg = std::make_shared<J2534CommandMessage>((J2534Command)data[1]);
|
||||
if(data.size() > 2)
|
||||
msg->setArgumentData(std::vector<uint8_t>(data.begin() + 2, data.end()));
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
uint16_t J2534CommandMessage::read16LE(size_t o) const {
|
||||
return (uint16_t)((uint16_t)argumentData[o] | ((uint16_t)argumentData[o + 1] << 8));
|
||||
}
|
||||
|
||||
void J2534CommandMessage::write16LE(size_t o, uint16_t v) {
|
||||
argumentData[o] = (uint8_t)(v & 0xFF);
|
||||
argumentData[o + 1] = (uint8_t)((v >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
uint16_t J2534CommandMessage::read16BE(size_t o) const {
|
||||
return (uint16_t)(((uint16_t)argumentData[o] << 8) | argumentData[o + 1]);
|
||||
}
|
||||
|
||||
void J2534CommandMessage::write16BE(size_t o, uint16_t v) {
|
||||
argumentData[o] = (uint8_t)((v >> 8) & 0xFF);
|
||||
argumentData[o + 1] = (uint8_t)(v & 0xFF);
|
||||
}
|
||||
|
||||
void J2534CommandMessage::writeBits16LE(size_t o, unsigned bitPos, unsigned bitCount, uint32_t value) {
|
||||
const uint16_t mask = (uint16_t)(((1u << bitCount) - 1u) << bitPos);
|
||||
uint16_t word = read16LE(o);
|
||||
word = (uint16_t)((word & ~mask) | (((value << bitPos) & mask)));
|
||||
write16LE(o, word);
|
||||
}
|
||||
|
||||
uint32_t J2534CommandMessage::read32LE(size_t o) const {
|
||||
return (uint32_t)argumentData[o]
|
||||
| ((uint32_t)argumentData[o + 1] << 8)
|
||||
| ((uint32_t)argumentData[o + 2] << 16)
|
||||
| ((uint32_t)argumentData[o + 3] << 24);
|
||||
}
|
||||
|
||||
void J2534CommandMessage::write32LE(size_t o, uint32_t v) {
|
||||
argumentData[o] = (uint8_t)(v & 0xFF);
|
||||
argumentData[o + 1] = (uint8_t)((v >> 8) & 0xFF);
|
||||
argumentData[o + 2] = (uint8_t)((v >> 16) & 0xFF);
|
||||
argumentData[o + 3] = (uint8_t)((v >> 24) & 0xFF);
|
||||
}
|
||||
|
||||
uint32_t J2534CommandMessage::read32BE(size_t o) const {
|
||||
return ((uint32_t)argumentData[o] << 24) | ((uint32_t)argumentData[o + 1] << 16)
|
||||
| ((uint32_t)argumentData[o + 2] << 8) | (uint32_t)argumentData[o + 3];
|
||||
}
|
||||
|
||||
void J2534CommandMessage::write32BE(size_t o, uint32_t v) {
|
||||
argumentData[o] = (uint8_t)((v >> 24) & 0xFF);
|
||||
argumentData[o + 1] = (uint8_t)((v >> 16) & 0xFF);
|
||||
argumentData[o + 2] = (uint8_t)((v >> 8) & 0xFF);
|
||||
argumentData[o + 3] = (uint8_t)(v & 0xFF);
|
||||
}
|
||||
|
||||
J2534_RxCanFilter J2534SetupCanRxFilteringMessage::getRxCanFilter() const {
|
||||
constexpr size_t filterSize = sizeof(J2534_RxCanFilter::fb);
|
||||
J2534_RxCanFilter filter = {};
|
||||
if(argumentData.size() >= (10 + filterSize))
|
||||
{
|
||||
filter.idx = (argumentData[2] << 8) | argumentData[3];
|
||||
filter.enabled = (argumentData[4] << 8) | argumentData[5];
|
||||
filter.filterCount = (argumentData[6] << 8) | argumentData[7];
|
||||
filter.fb = *((MessageFilterBytes*)(argumentData.data() + 8));
|
||||
filter.networkId = (argumentData[8 + filterSize] << 8) | argumentData[9 + filterSize];
|
||||
}
|
||||
return filter;
|
||||
}
|
||||
|
||||
void J2534SetupCanRxFilteringMessage::setRxCanFilter(const J2534_RxCanFilter& filter) {
|
||||
argumentData.resize(10 + sizeof(filter.fb));
|
||||
argumentData[2] = (filter.idx >> 8) & 0xFF;
|
||||
argumentData[3] = filter.idx & 0xFF;
|
||||
argumentData[4] = (filter.enabled >> 8) & 0xFF;
|
||||
argumentData[5] = filter.enabled & 0xFF;
|
||||
argumentData[6] = (filter.filterCount >> 8) & 0xFF;
|
||||
argumentData[7] = filter.filterCount & 0xFF;
|
||||
*((MessageFilterBytes*)(argumentData.data() + 8)) = filter.fb;
|
||||
argumentData[8 + sizeof(filter.fb)] = (filter.networkId >> 8) & 0xFF;
|
||||
argumentData[9 + sizeof(filter.fb)] = filter.networkId & 0xFF;
|
||||
}
|
||||
|
||||
|
||||
J2534SetupIso15765FlowControlMessage::J2534SetupIso15765FlowControlMessage()
|
||||
: J2534CommandMessage(J2534Command::SetupIso15765RxFilter) {
|
||||
argumentData.resize(MessageSize);
|
||||
// Bytes [0..1] were populated by the base constructor. Everything else starts at zero
|
||||
// (matches the previous behavior which zeroed the flt region and left the rest of the
|
||||
// caller-supplied struct as-is; typical callers value-initialized their struct too).
|
||||
for(size_t i = 2; i < MessageSize; ++i)
|
||||
argumentData[i] = 0;
|
||||
}
|
||||
|
||||
void J2534SetupIso15765FlowControlMessage::rebuildFilterBytes(void) {
|
||||
// Zero the 28-byte flt region.
|
||||
for(size_t i = 0; i < FltSize; ++i)
|
||||
argumentData[FltOffset + i] = 0;
|
||||
|
||||
const uint32_t id = read32LE(IdOffset);
|
||||
const uint32_t idMask = read32LE(IdMaskOffset);
|
||||
const bool is29Bit = getFlagBit(FlagId29BitEnable);
|
||||
const bool extAddr = getFlagBit(FlagExtAddressEnable);
|
||||
const uint8_t extAddrByte = argumentData[ExtAddrOffset];
|
||||
|
||||
// CoreMiniMessageFilterBytes has an interleaved layout:
|
||||
// uiFilterMask0 at flt+0, uiFilterID0 at flt+2
|
||||
// uiFilterMask1 at flt+4, uiFilterID1 at flt+6
|
||||
// uiFilterMask2 at flt+8, uiFilterID2 at flt+10
|
||||
// datalink.uiFilterMask3 at flt+12, datalink.uiFilterID3 at flt+14
|
||||
//
|
||||
// CoreMiniMsgBitsCAN bit layout within each 16-bit unit:
|
||||
// unit0: IDE(bit0), SRR(bit1), SID(bits2-12), NETWORKINDEX(bits13-15)
|
||||
// unit1: EID(bits0-11), TXMSG(bit12), ...
|
||||
// unit2: DLC(bits0-3), ..., RTR(bit9), EID2(bits10-15)
|
||||
const size_t MaskUnit0 = FltOffset + 0;
|
||||
const size_t MaskUnit1 = FltOffset + 4;
|
||||
const size_t MaskUnit2 = FltOffset + 8;
|
||||
const size_t ValueUnit0 = FltOffset + 2;
|
||||
const size_t ValueUnit1 = FltOffset + 6;
|
||||
const size_t ValueUnit2 = FltOffset + 10;
|
||||
|
||||
// filter arbid: pMask->IDE = 1
|
||||
writeBits16LE(MaskUnit0, /*bit*/0, /*width*/1, 1);
|
||||
|
||||
if(is29Bit) {
|
||||
// pValue->IDE = 1; pValue->SID = (id >> 18) & 0x7FF
|
||||
writeBits16LE(ValueUnit0, 0, 1, 1);
|
||||
writeBits16LE(ValueUnit0, 2, 11, (id >> 18) & 0x7FF);
|
||||
// pValue->EID = (id >> 6) & 0xFFF
|
||||
writeBits16LE(ValueUnit1, 0, 12, (id >> 6) & 0xFFF);
|
||||
// pValue->EID2 = id & 0x3F
|
||||
writeBits16LE(ValueUnit2, 10, 6, id & 0x3F);
|
||||
// pMask->SID = (id_mask >> 18) & 0x7FF
|
||||
writeBits16LE(MaskUnit0, 2, 11, (idMask >> 18) & 0x7FF);
|
||||
// pMask->EID = (id_mask >> 6) & 0xFFF (overlaps pValue->{IDE,SID} storage)
|
||||
writeBits16LE(MaskUnit1, 0, 12, (idMask >> 6) & 0xFFF);
|
||||
// pMask->EID2 = id_mask & 0x3F (overlaps pValue->EID storage)
|
||||
writeBits16LE(MaskUnit2, 10, 6, idMask & 0x3F);
|
||||
} else {
|
||||
// pValue->IDE = 0 (already zero); pValue->SID = id
|
||||
writeBits16LE(ValueUnit0, 2, 11, id & 0x7FF);
|
||||
// pMask->SID = id_mask
|
||||
writeBits16LE(MaskUnit0, 2, 11, idMask & 0x7FF);
|
||||
}
|
||||
|
||||
// Extended-address filter: writes into the datalink.uiFilterID3 / uiFilterMask3 bytes.
|
||||
// uiFilterMask3 = flt[12..13] = wire[37..38]
|
||||
// uiFilterID3 = flt[14..15] = wire[39..40]
|
||||
if(extAddr) {
|
||||
const size_t kValueBytes = FltOffset + 14; // uiFilterID3
|
||||
const size_t kMaskBytes = FltOffset + 12; // uiFilterMask3
|
||||
argumentData[kValueBytes + 0] = extAddrByte;
|
||||
argumentData[kMaskBytes + 0] = 0xFF;
|
||||
argumentData[kValueBytes + 1] = 0;
|
||||
argumentData[kMaskBytes + 1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t J2534SetupIso15765FlowControlMessage::getIdx(void) const { return read16LE(IdxOffset); }
|
||||
void J2534SetupIso15765FlowControlMessage::setIdx(uint16_t idx) { write16LE(IdxOffset, idx); }
|
||||
|
||||
uint16_t J2534SetupIso15765FlowControlMessage::getCoreMiniId(void) const { return read16LE(CoreMiniOffset); }
|
||||
void J2534SetupIso15765FlowControlMessage::setCoreMiniId(uint16_t coreMiniId) { write16LE(CoreMiniOffset, coreMiniId); }
|
||||
|
||||
uint8_t J2534SetupIso15765FlowControlMessage::getPadding(void) const { return argumentData[PaddingOffset]; }
|
||||
void J2534SetupIso15765FlowControlMessage::setPadding(uint8_t padding) { argumentData[PaddingOffset] = padding; }
|
||||
|
||||
uint32_t J2534SetupIso15765FlowControlMessage::getId(void) const { return read32LE(IdOffset); }
|
||||
void J2534SetupIso15765FlowControlMessage::setId(uint32_t id) { write32LE(IdOffset, id); rebuildFilterBytes(); }
|
||||
|
||||
uint32_t J2534SetupIso15765FlowControlMessage::getIdMask(void) const { return read32LE(IdMaskOffset); }
|
||||
void J2534SetupIso15765FlowControlMessage::setIdMask(uint32_t idMask) { write32LE(IdMaskOffset, idMask); rebuildFilterBytes(); }
|
||||
|
||||
uint32_t J2534SetupIso15765FlowControlMessage::getFcId(void) const { return read32LE(FcIdOffset); }
|
||||
void J2534SetupIso15765FlowControlMessage::setFcId(uint32_t fcId) { write32LE(FcIdOffset, fcId); }
|
||||
|
||||
uint8_t J2534SetupIso15765FlowControlMessage::getFlowControlExtendedAddress(void) const { return argumentData[FcExtAddrOffset]; }
|
||||
void J2534SetupIso15765FlowControlMessage::setFlowControlExtendedAddress(uint8_t addr) { argumentData[FcExtAddrOffset] = addr; }
|
||||
|
||||
uint8_t J2534SetupIso15765FlowControlMessage::getExtendedAddress(void) const { return argumentData[ExtAddrOffset]; }
|
||||
void J2534SetupIso15765FlowControlMessage::setExtendedAddress(uint8_t addr) { argumentData[ExtAddrOffset] = addr; rebuildFilterBytes(); }
|
||||
|
||||
uint8_t J2534SetupIso15765FlowControlMessage::getBlockSize(void) const { return argumentData[BlockSizeOffset]; }
|
||||
void J2534SetupIso15765FlowControlMessage::setBlockSize(uint8_t blockSize) { argumentData[BlockSizeOffset] = blockSize; }
|
||||
|
||||
uint8_t J2534SetupIso15765FlowControlMessage::getStMin(void) const { return argumentData[StMinOffset]; }
|
||||
void J2534SetupIso15765FlowControlMessage::setStMin(uint8_t stMin) { argumentData[StMinOffset] = stMin; }
|
||||
|
||||
uint16_t J2534SetupIso15765FlowControlMessage::getCfTimeout(void) const { return read16LE(CfTimeoutOffset); }
|
||||
void J2534SetupIso15765FlowControlMessage::setCfTimeout(uint16_t cfTimeout) { write16LE(CfTimeoutOffset, cfTimeout); }
|
||||
|
||||
uint32_t J2534SetupIso15765FlowControlMessage::getFlags(void) const { return read32LE(FlagsOffset); }
|
||||
void J2534SetupIso15765FlowControlMessage::setFlags(uint32_t flags) { write32LE(FlagsOffset, flags); rebuildFilterBytes(); }
|
||||
|
||||
bool J2534SetupIso15765FlowControlMessage::getEnable(void) const { return getFlagBit(FlagEnable); }
|
||||
void J2534SetupIso15765FlowControlMessage::setEnable(bool enable) { setFlagBit(FlagEnable, enable); }
|
||||
|
||||
bool J2534SetupIso15765FlowControlMessage::getIs29BitEnabled(void) const { return getFlagBit(FlagId29BitEnable); }
|
||||
void J2534SetupIso15765FlowControlMessage::setIs29BitEnabled(bool enable) { setFlagBit(FlagId29BitEnable, enable); rebuildFilterBytes(); }
|
||||
|
||||
bool J2534SetupIso15765FlowControlMessage::getIsFc29BitEnabled(void) const { return getFlagBit(FlagFcId29BitEnable); }
|
||||
void J2534SetupIso15765FlowControlMessage::setIsFc29BitEnabled(bool enable) { setFlagBit(FlagFcId29BitEnable, enable); }
|
||||
|
||||
bool J2534SetupIso15765FlowControlMessage::getExtAddressEnabled(void) const { return getFlagBit(FlagExtAddressEnable); }
|
||||
void J2534SetupIso15765FlowControlMessage::setExtAddressEnabled(bool enable) { setFlagBit(FlagExtAddressEnable, enable); rebuildFilterBytes(); }
|
||||
|
||||
bool J2534SetupIso15765FlowControlMessage::getFcExtAddressEnabled(void) const { return getFlagBit(FlagFcExtAddressEnable); }
|
||||
void J2534SetupIso15765FlowControlMessage::setFcExtAddressEnabled(bool enable) { setFlagBit(FlagFcExtAddressEnable, enable); }
|
||||
|
||||
bool J2534SetupIso15765FlowControlMessage::getFlowControlTransmissionEnabled(void) const { return getFlagBit(FlagEnableFlowControlTransmit); }
|
||||
void J2534SetupIso15765FlowControlMessage::setFlowControlTransmissionEnabled(bool enable) { setFlagBit(FlagEnableFlowControlTransmit, enable); }
|
||||
|
||||
bool J2534SetupIso15765FlowControlMessage::getPaddingEnabled(void) const { return getFlagBit(FlagPaddingEnable); }
|
||||
void J2534SetupIso15765FlowControlMessage::setPaddingEnabled(bool enable) { setFlagBit(FlagPaddingEnable, enable); }
|
||||
|
||||
bool J2534SetupIso15765FlowControlMessage::getIsCanFd(void) const { return getFlagBit(FlagIsCanFd); }
|
||||
void J2534SetupIso15765FlowControlMessage::setIsCanFd(bool enable) { setFlagBit(FlagIsCanFd, enable); }
|
||||
|
||||
bool J2534SetupIso15765FlowControlMessage::getIsBrsEnabled(void) const { return getFlagBit(FlagIsBrsEnabled); }
|
||||
void J2534SetupIso15765FlowControlMessage::setIsBrsEnabled(bool enable) { setFlagBit(FlagIsBrsEnabled, enable); }
|
||||
|
||||
void J2534SetupIso15765FlowControlMessage::setFlagBit(uint32_t mask, bool enable) {
|
||||
uint32_t f = read32LE(FlagsOffset);
|
||||
if(enable) f |= mask;
|
||||
else f &= ~mask;
|
||||
write32LE(FlagsOffset, f);
|
||||
}
|
||||
|
||||
bool J2534SetupIso15765FlowControlMessage::getFlagBit(uint32_t mask) const {
|
||||
return (read32LE(FlagsOffset) & mask) != 0;
|
||||
}
|
||||
|
||||
uint16_t Iso15765TxSetupMessage::getIdx(void) const { return read16LE(SetupIdxOffset); }
|
||||
void Iso15765TxSetupMessage::setIdx(uint16_t idx) { write16LE(SetupIdxOffset, idx); }
|
||||
|
||||
uint16_t Iso15765TxSetupMessage::getCoreMiniId(void) const { return read16LE(SetupCoreMiniOffset); }
|
||||
void Iso15765TxSetupMessage::setCoreMiniId(uint16_t coreMiniId) { write16LE(SetupCoreMiniOffset, coreMiniId); }
|
||||
|
||||
uint32_t Iso15765TxSetupMessage::getMessageLength(void) const { return read32LE(SetupMsgLenOffset); }
|
||||
void Iso15765TxSetupMessage::setMessageLength(uint32_t messageLength) { write32LE(SetupMsgLenOffset, messageLength); }
|
||||
|
||||
uint8_t Iso15765TxSetupMessage::getPadding(void) const { return argumentData[SetupPaddingOffset]; }
|
||||
void Iso15765TxSetupMessage::setPadding(uint8_t padding) { argumentData[SetupPaddingOffset] = padding; }
|
||||
|
||||
uint8_t Iso15765TxSetupMessage::getTxDl(void) const { return argumentData[SetupTxDlOffset]; }
|
||||
void Iso15765TxSetupMessage::setTxDl(uint8_t txDl) { argumentData[SetupTxDlOffset] = txDl; }
|
||||
|
||||
uint32_t Iso15765TxSetupMessage::getId(void) const { return read32LE(SetupIdOffset); }
|
||||
void Iso15765TxSetupMessage::setId(uint32_t id) { write32LE(SetupIdOffset, id); }
|
||||
|
||||
uint32_t Iso15765TxSetupMessage::getFcId(void) const { return read32LE(SetupFcIdOffset); }
|
||||
void Iso15765TxSetupMessage::setFcId(uint32_t fcId) { write32LE(SetupFcIdOffset, fcId); }
|
||||
|
||||
uint32_t Iso15765TxSetupMessage::getFcIdMask(void) const { return read32LE(SetupFcIdMaskOffset); }
|
||||
void Iso15765TxSetupMessage::setFcIdMask(uint32_t fcIdMask) { write32LE(SetupFcIdMaskOffset, fcIdMask); }
|
||||
|
||||
uint8_t Iso15765TxSetupMessage::getFlowControlExtendedAddress(void) const { return argumentData[SetupFcExtAddrOffset]; }
|
||||
void Iso15765TxSetupMessage::setFlowControlExtendedAddress(uint8_t addr) { argumentData[SetupFcExtAddrOffset] = addr; }
|
||||
|
||||
uint8_t Iso15765TxSetupMessage::getExtendedAddress(void) const { return argumentData[SetupExtAddrOffset]; }
|
||||
void Iso15765TxSetupMessage::setExtendedAddress(uint8_t addr) { argumentData[SetupExtAddrOffset] = addr; }
|
||||
|
||||
uint16_t Iso15765TxSetupMessage::getFsTimeout(void) const { return read16LE(SetupFsTimeoutOffset); }
|
||||
void Iso15765TxSetupMessage::setFsTimeout(uint16_t timeout) { write16LE(SetupFsTimeoutOffset, timeout); }
|
||||
|
||||
uint16_t Iso15765TxSetupMessage::getFsWait(void) const { return read16LE(SetupFsWaitOffset); }
|
||||
void Iso15765TxSetupMessage::setFsWait(uint16_t wait) { write16LE(SetupFsWaitOffset, wait); }
|
||||
|
||||
uint32_t Iso15765TxSetupMessage::getFlags(void) const { return read32LE(SetupFlagsOffset); }
|
||||
void Iso15765TxSetupMessage::setFlags(uint32_t flags) { write32LE(SetupFlagsOffset, flags); }
|
||||
|
||||
uint8_t Iso15765TxSetupMessage::getStMin(void) const { return argumentData[SetupStMinOffset]; }
|
||||
void Iso15765TxSetupMessage::setStMin(uint8_t stMin) { argumentData[SetupStMinOffset] = stMin; }
|
||||
|
||||
uint8_t Iso15765TxSetupMessage::getBlockSize(void) const { return argumentData[SetupBlockSizeOffset]; }
|
||||
void Iso15765TxSetupMessage::setBlockSize(uint8_t blockSize) { argumentData[SetupBlockSizeOffset] = blockSize; }
|
||||
|
||||
bool Iso15765TxSetupMessage::getIs29BitEnabled(void) const { return getFlagBit(FlagId29BitEnable); }
|
||||
void Iso15765TxSetupMessage::setIs29BitEnabled(bool enable) { setFlagBit(FlagId29BitEnable, enable); }
|
||||
bool Iso15765TxSetupMessage::getIsFc29BitEnabled(void) const { return getFlagBit(FlagFcId29BitEnable); }
|
||||
void Iso15765TxSetupMessage::setIsFc29BitEnabled(bool enable) { setFlagBit(FlagFcId29BitEnable, enable); }
|
||||
bool Iso15765TxSetupMessage::getExtAddressEnabled(void) const { return getFlagBit(FlagExtAddressEnable); }
|
||||
void Iso15765TxSetupMessage::setExtAddressEnabled(bool enable) { setFlagBit(FlagExtAddressEnable, enable); }
|
||||
bool Iso15765TxSetupMessage::getFcExtAddressEnabled(void) const { return getFlagBit(FlagFcExtAddressEnable); }
|
||||
void Iso15765TxSetupMessage::setFcExtAddressEnabled(bool enable) { setFlagBit(FlagFcExtAddressEnable, enable); }
|
||||
bool Iso15765TxSetupMessage::getOverrideStMin(void) const { return getFlagBit(FlagOverrideStMin); }
|
||||
void Iso15765TxSetupMessage::setOverrideStMin(bool enable) { setFlagBit(FlagOverrideStMin, enable); }
|
||||
bool Iso15765TxSetupMessage::getOverrideBlockSize(void) const { return getFlagBit(FlagOverrideBlockSize); }
|
||||
void Iso15765TxSetupMessage::setOverrideBlockSize(bool enable) { setFlagBit(FlagOverrideBlockSize, enable); }
|
||||
bool Iso15765TxSetupMessage::getPaddingEnabled(void) const { return getFlagBit(FlagPaddingEnable); }
|
||||
void Iso15765TxSetupMessage::setPaddingEnabled(bool enable) { setFlagBit(FlagPaddingEnable, enable); }
|
||||
bool Iso15765TxSetupMessage::getIsCanFd(void) const { return getFlagBit(FlagIsCanFd); }
|
||||
void Iso15765TxSetupMessage::setIsCanFd(bool enable) { setFlagBit(FlagIsCanFd, enable); }
|
||||
bool Iso15765TxSetupMessage::getIsBrsEnabled(void) const { return getFlagBit(FlagIsBrsEnabled); }
|
||||
void Iso15765TxSetupMessage::setIsBrsEnabled(bool enable) { setFlagBit(FlagIsBrsEnabled, enable); }
|
||||
|
||||
bool Iso15765TxSetupMessage::getFlagBit(uint32_t mask) const {
|
||||
return (getFlags() & mask) != 0;
|
||||
}
|
||||
|
||||
void Iso15765TxSetupMessage::setFlagBit(uint32_t mask, bool enable) {
|
||||
uint32_t f = getFlags();
|
||||
if(enable) f |= mask;
|
||||
else f &= ~mask;
|
||||
setFlags(f);
|
||||
}
|
||||
|
||||
uint16_t Iso15765TxDataMessage::getIdx(void) const { return read16LE(DataIdxOffset); }
|
||||
void Iso15765TxDataMessage::setIdx(uint16_t idx) { write16LE(DataIdxOffset, idx); }
|
||||
|
||||
uint32_t Iso15765TxDataMessage::getOffset(void) const { return read32LE(DataOffsetOffset); }
|
||||
void Iso15765TxDataMessage::setOffset(uint32_t offset) { write32LE(DataOffsetOffset, offset); }
|
||||
|
||||
uint16_t Iso15765TxDataMessage::getLen(void) const { return read16LE(DataLenOffset); }
|
||||
|
||||
const uint8_t* Iso15765TxDataMessage::getData(void) const { return argumentData.data() + DataPayloadOffset; }
|
||||
|
||||
void Iso15765TxDataMessage::setData(const uint8_t* sourceData, uint16_t len) {
|
||||
len = std::min(len, (uint16_t)MaxDataLength);
|
||||
argumentData.resize(DataPayloadOffset + len);
|
||||
write16LE(DataLenOffset, len);
|
||||
if(len > 0 && sourceData != nullptr)
|
||||
std::copy(sourceData, sourceData + len, argumentData.begin() + DataPayloadOffset);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "icsneo/communication/message/linmessage.h"
|
||||
#include <numeric>
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
void LINMessage::calcChecksum(LINMessage& message) {
|
||||
uint16_t sum = 0;
|
||||
auto limitFunc = [](uint16_t x, uint16_t y) -> uint16_t {
|
||||
if ((x + y) > 0xFFu)
|
||||
return ((x + y) - 0xFFu);
|
||||
else
|
||||
return (x + y);
|
||||
};
|
||||
|
||||
message.checksum = static_cast<uint8_t>(std::accumulate(message.data.begin(), message.data.end(), sum, limitFunc));
|
||||
if(message.isEnhancedChecksum)
|
||||
message.checksum = static_cast<uint8_t>(limitFunc(message.checksum, message.protectedID));
|
||||
|
||||
message.checksum ^= 0xFFu;
|
||||
}
|
||||
|
||||
uint8_t LINMessage::calcProtectedID(uint8_t& id) {
|
||||
uint8_t protID = id;
|
||||
auto bit = [&](uint8_t pos)->uint8_t { return ((protID >> pos) & 0x1u); };
|
||||
protID |= (~(bit(1) ^ bit(3) ^ bit(4) ^ bit(5)) << 7);
|
||||
protID |= ((bit(0) ^ bit(1) ^ bit(2) ^ bit(4)) << 6);
|
||||
return protID;
|
||||
}
|
||||
|
||||
} //namespace icsneo
|
||||
@@ -0,0 +1,25 @@
|
||||
#include "icsneo/communication/message/livedatamessage.h"
|
||||
#include "icsneo/communication/livedata.h"
|
||||
|
||||
namespace icsneo
|
||||
{
|
||||
|
||||
void LiveDataCommandMessage::appendSignalArg(LiveDataValueType valueType) {
|
||||
auto& arg = args.emplace_back(std::make_shared<LiveDataArgument>());
|
||||
arg->objectType = LiveDataObjectType::MISC;
|
||||
arg->objectIndex = 0u;
|
||||
arg->signalIndex = 0u;
|
||||
arg->valueType = valueType;
|
||||
}
|
||||
|
||||
void LiveDataSetValueMessage::appendSetValue(LiveDataValueType valueType, const LiveDataValue& value) {
|
||||
auto& arg = args.emplace_back(std::make_shared<LiveDataArgument>());
|
||||
arg->objectType = LiveDataObjectType::MISC;
|
||||
arg->objectIndex = 0u;
|
||||
arg->signalIndex = 0u;
|
||||
arg->valueType = valueType;
|
||||
|
||||
values.push_back(std::make_shared<LiveDataValue>(value));
|
||||
}
|
||||
|
||||
} // namespace icsneo
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "icsneo/communication/message/logdatamessage.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
std::shared_ptr<LogDataMessage> LogDataMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||
if(bytestream.size() % 2 != 0)
|
||||
return nullptr;
|
||||
const auto* begin = (char16_t*)bytestream.data();
|
||||
const auto* end = begin + (bytestream.size() / sizeof(char16_t));
|
||||
return std::make_shared<LogDataMessage>(std::wstring(begin,end));
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
#include "icsneo/communication/message/mfgconfigmessage.h"
|
||||
#include "icsneo/communication/icspb.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
static MfgConfigMessage::VersionNumber versionFromProto(const settings::common::v1::VersionNumber& version) {
|
||||
MfgConfigMessage::VersionNumber decoded;
|
||||
decoded.major = version.major();
|
||||
decoded.minor = version.minor();
|
||||
if(version.has_release())
|
||||
decoded.release = version.release();
|
||||
if(version.has_build())
|
||||
decoded.build = version.build();
|
||||
return decoded;
|
||||
}
|
||||
|
||||
std::shared_ptr<MfgConfigMessage> MfgConfigMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||
MfgConfigMessage decoded;
|
||||
settings::manufacturing::v1::MfgConfig msg;
|
||||
|
||||
if(!protoapi::processResponse(bytestream.data(), bytestream.size(), msg)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(msg.has_serial_number()) {
|
||||
decoded.serialNumber = msg.serial_number();
|
||||
}
|
||||
if(msg.has_manufacture_date()) {
|
||||
const auto& date = msg.manufacture_date();
|
||||
decoded.manufactureDate = MfgDate{date.manufacture_day(), date.manufacture_month(), date.manufacture_year()};
|
||||
}
|
||||
if(msg.has_hardware_rev()) {
|
||||
decoded.hardwareRev = versionFromProto(msg.hardware_rev());
|
||||
}
|
||||
if(msg.has_product_id()) {
|
||||
decoded.productId = static_cast<uint8_t>(msg.product_id());
|
||||
}
|
||||
if(msg.has_bootloader_rev()) {
|
||||
decoded.bootloaderRev = versionFromProto(msg.bootloader_rev());
|
||||
}
|
||||
if(msg.has_usb_descriptor()) {
|
||||
decoded.usbDescriptor = msg.usb_descriptor();
|
||||
}
|
||||
for(const auto& mac : msg.mac_addresses()) {
|
||||
const auto& bytes = mac.mac_addr();
|
||||
if(bytes.size() < MACAddressLength)
|
||||
continue;
|
||||
MACAddress address{};
|
||||
std::copy_n(bytes.begin(), MACAddressLength, address.begin());
|
||||
decoded.macAddresses.push_back(address);
|
||||
}
|
||||
if(msg.has_pcb_serial()) {
|
||||
decoded.pcbSerial = msg.pcb_serial().pcb_serial();
|
||||
}
|
||||
if(msg.has_chip_id()) {
|
||||
decoded.chipId = static_cast<ChipID>(msg.chip_id());
|
||||
}
|
||||
if(msg.has_imei()) {
|
||||
decoded.imei = msg.imei();
|
||||
}
|
||||
if(msg.has_parent_product_id()) {
|
||||
decoded.parentProductId = static_cast<uint8_t>(msg.parent_product_id());
|
||||
}
|
||||
if(msg.has_software_version_lock()) {
|
||||
decoded.softwareVersionLock = versionFromProto(msg.software_version_lock());
|
||||
}
|
||||
|
||||
return std::make_shared<MfgConfigMessage>(decoded);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> MfgConfigMessage::EncodeArgumentsForGet() {
|
||||
settings::manufacturing::v1::MfgConfig msg;
|
||||
msg.Clear();
|
||||
return protoapi::getPayload(protoapi::Command::GET, msg);
|
||||
}
|
||||
@@ -1,84 +1,210 @@
|
||||
#include "icsneo/communication/message/neomessage.h"
|
||||
#include "icsneo/communication/message/canmessage.h"
|
||||
#include "icsneo/communication/message/ethernetmessage.h"
|
||||
#include "icsneo/communication/message/canerrormessage.h"
|
||||
#include "icsneo/communication/message/linmessage.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
neomessage_t icsneo::CreateNeoMessage(const std::shared_ptr<Message> message) {
|
||||
// This function is not responsible for storing the message!
|
||||
// Keep the shared_ptr around for the lifetime of the data access
|
||||
const auto type = message->network.getType();
|
||||
neomessage_t neomsg = {}; // Clear out the memory
|
||||
neomsg.netid = (uint32_t)message->network.getNetID();
|
||||
neomsg.type = (uint8_t)type;
|
||||
neomsg.length = message->data.size();
|
||||
neomsg.data = message->data.data();
|
||||
neomsg.messageType = (neomessagetype_t)message->type;
|
||||
neomsg.timestamp = message->timestamp;
|
||||
neomsg.status.globalError = message->error;
|
||||
neomsg.status.transmitMessage = message->transmitted;
|
||||
switch (message->type)
|
||||
{
|
||||
case Message::Type::Frame: {
|
||||
neomessage_frame_t& frame = *(neomessage_frame_t*)&neomsg;
|
||||
auto framemsg = std::static_pointer_cast<Frame>(message);
|
||||
const auto netType = framemsg->network.getType();
|
||||
|
||||
switch(type) {
|
||||
case Network::Type::CAN:
|
||||
case Network::Type::SWCAN:
|
||||
case Network::Type::LSFTCAN: {
|
||||
neomessage_can_t& can = *(neomessage_can_t*)&neomsg;
|
||||
auto canmsg = std::static_pointer_cast<CANMessage>(message);
|
||||
can.arbid = canmsg->arbid;
|
||||
can.dlcOnWire = canmsg->dlcOnWire;
|
||||
can.status.extendedFrame = canmsg->isExtended;
|
||||
can.status.remoteFrame = canmsg->isRemote;
|
||||
can.status.canfdRTR = canmsg->isRemote;
|
||||
can.status.canfdFDF = canmsg->isCANFD;
|
||||
can.status.canfdBRS = canmsg->baudrateSwitch;
|
||||
can.status.canfdESI = canmsg->errorStateIndicator;
|
||||
break;
|
||||
frame.netid = (neonetid_t)framemsg->network.getNetID();
|
||||
frame.type = (neonettype_t)netType;
|
||||
frame.description = framemsg->description;
|
||||
frame.length = framemsg->data.size();
|
||||
frame.data = framemsg->data.data();
|
||||
frame.timestamp = framemsg->timestamp;
|
||||
frame.status.globalError = framemsg->error;
|
||||
frame.status.transmitMessage = framemsg->transmitted;
|
||||
|
||||
switch(netType) {
|
||||
case Network::Type::CAN:
|
||||
case Network::Type::SWCAN:
|
||||
case Network::Type::LSFTCAN: {
|
||||
neomessage_can_t& can = *(neomessage_can_t*)&neomsg;
|
||||
auto canmsg = std::static_pointer_cast<CANMessage>(message);
|
||||
can.arbid = canmsg->arbid;
|
||||
can.dlcOnWire = canmsg->dlcOnWire;
|
||||
can.status.extendedFrame = canmsg->isExtended;
|
||||
can.status.remoteFrame = canmsg->isRemote;
|
||||
can.status.canfdRTR = canmsg->isRemote;
|
||||
can.status.canfdFDF = canmsg->isCANFD;
|
||||
can.status.canfdBRS = canmsg->baudrateSwitch;
|
||||
can.status.canfdESI = canmsg->errorStateIndicator;
|
||||
break;
|
||||
}
|
||||
case Network::Type::Ethernet:
|
||||
case Network::Type::AutomotiveEthernet: {
|
||||
neomessage_eth_t& eth = *(neomessage_eth_t*)&neomsg;
|
||||
auto ethmsg = std::static_pointer_cast<EthernetMessage>(message);
|
||||
eth.preemptionFlags = ethmsg->preemptionFlags.value_or(0);
|
||||
eth.status.incompleteFrame = ethmsg->frameTooShort;
|
||||
// TODO Fill in extra status bits
|
||||
//eth.status.xyz = ethmsg->preemptionEnabled;
|
||||
//eth.status.xyz = ethmsg->fcs;
|
||||
//eth.status.xyz = ethmsg->noPadding;
|
||||
break;
|
||||
}
|
||||
case Network::Type::LIN: {
|
||||
neomessage_lin_t& lin = *(neomessage_lin_t*)&neomsg;
|
||||
auto linmsg = std::static_pointer_cast<LINMessage>(message);
|
||||
if(!linmsg) { break; }
|
||||
const auto linHdrBytes = std::min(linmsg->data.size(), static_cast<size_t>(2));
|
||||
lin.header[0] = linmsg->protectedID;
|
||||
std::copy(linmsg->data.begin(), linmsg->data.begin() + linHdrBytes, lin.header + 1);
|
||||
linmsg->calcChecksum(*linmsg);
|
||||
lin.checksum = linmsg->checksum;
|
||||
lin.data = linmsg->data.data() + linHdrBytes;
|
||||
if(linmsg->isEnhancedChecksum != linmsg->statusFlags.TxChecksumEnhanced) {
|
||||
linmsg->isEnhancedChecksum = true;
|
||||
linmsg->statusFlags.TxChecksumEnhanced = true;
|
||||
}
|
||||
if(linmsg->data.size())
|
||||
lin.length = linmsg->data.size() + 2;
|
||||
else
|
||||
lin.length = 1;
|
||||
|
||||
lin.linStatus = {
|
||||
linmsg->statusFlags.TxChecksumEnhanced, // .txChecksumEnhanced
|
||||
linmsg->statusFlags.TxCommander, // .txCommander
|
||||
linmsg->statusFlags.TxResponder, // .txResponder
|
||||
0, // .txAborted
|
||||
linmsg->statusFlags.UpdateResponderOnce, // .updateResponderOnce
|
||||
linmsg->statusFlags.HasUpdatedResponderOnce, // .hasUpdatedResponderOnce
|
||||
linmsg->statusFlags.BusRecovered, // .busRecovered
|
||||
linmsg->statusFlags.BreakOnly // .breakOnly
|
||||
|
||||
};
|
||||
|
||||
lin.status.linJustBreakSync = linmsg->errFlags.ErrRxBreakSyncOnly;
|
||||
lin.status.linErrorTXRXMismatch = linmsg->errFlags.ErrTxRxMismatch;
|
||||
lin.status.linErrorRXBreakNotZero = linmsg->errFlags.ErrRxBreakNotZero;
|
||||
lin.status.linErrorRXBreakTooShort = linmsg->errFlags.ErrRxBreakTooShort;
|
||||
lin.status.linErrorRXSyncNot55 = linmsg->errFlags.ErrRxSyncNot55;
|
||||
lin.status.linErrorRXDataGreaterEight = linmsg->errFlags.ErrRxDataLenOver8;
|
||||
lin.status.linSyncFrameError = linmsg->errFlags.ErrFrameSync;
|
||||
lin.status.linIDFrameError = linmsg->errFlags.ErrFrameMessageID;
|
||||
lin.status.linSlaveByteError = linmsg->errFlags.ErrFrameResponderData;
|
||||
lin.status.checksumError = linmsg->errFlags.ErrChecksumMatch;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// TODO Implement others
|
||||
break;
|
||||
}
|
||||
case Network::Type::Ethernet: {
|
||||
neomessage_eth_t& eth = *(neomessage_eth_t*)&neomsg;
|
||||
auto ethmsg = std::static_pointer_cast<EthernetMessage>(message);
|
||||
eth.preemptionFlags = ethmsg->preemptionFlags;
|
||||
eth.status.incompleteFrame = ethmsg->frameTooShort;
|
||||
// TODO Fill in extra status bits
|
||||
//eth.status.xyz = ethmsg->preemptionEnabled;
|
||||
//eth.status.xyz = ethmsg->fcsAvailable;
|
||||
//eth.status.xyz = ethmsg->noPadding;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// TODO Implement others
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case Message::Type::CANErrorCount: {
|
||||
neomessage_can_error_t& canerror = *(neomessage_can_error_t*)&neomsg;
|
||||
auto canerrormsg = std::static_pointer_cast<CANErrorMessage>(message);
|
||||
canerror.transmitErrorCount = canerrormsg->transmitErrorCount;
|
||||
canerror.receiveErrorCount = canerrormsg->receiveErrorCount;
|
||||
canerror.status.canBusOff = canerrormsg->busOff;
|
||||
canerror.netid = (neonetid_t)canerrormsg->network.getNetID();
|
||||
canerror.type = (neonettype_t)canerrormsg->network.getType();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return neomsg;
|
||||
}
|
||||
|
||||
std::shared_ptr<Message> icsneo::CreateMessageFromNeoMessage(const neomessage_t* neomessage) {
|
||||
const Network network = neomessage->netid;
|
||||
switch(network.getType()) {
|
||||
case Network::Type::CAN:
|
||||
case Network::Type::SWCAN:
|
||||
case Network::Type::LSFTCAN: {
|
||||
neomessage_can_t& can = *(neomessage_can_t*)neomessage;
|
||||
auto canmsg = std::make_shared<CANMessage>();
|
||||
canmsg->network = network;
|
||||
canmsg->data.insert(canmsg->data.end(), can.data, can.data + can.length);
|
||||
canmsg->arbid = can.arbid;
|
||||
canmsg->isExtended = can.status.extendedFrame;
|
||||
canmsg->isRemote = can.status.remoteFrame | can.status.canfdRTR;
|
||||
canmsg->isCANFD = can.status.canfdFDF;
|
||||
canmsg->baudrateSwitch = can.status.canfdBRS;
|
||||
canmsg->errorStateIndicator = can.status.canfdESI;
|
||||
return canmsg;
|
||||
switch((Message::Type)neomessage->messageType) {
|
||||
case Message::Type::Frame: {
|
||||
const Network network = ((neomessage_frame_t*)neomessage)->netid;
|
||||
switch(network.getType()) {
|
||||
case Network::Type::CAN:
|
||||
case Network::Type::SWCAN:
|
||||
case Network::Type::LSFTCAN: {
|
||||
neomessage_can_t& can = *(neomessage_can_t*)neomessage;
|
||||
auto canmsg = std::make_shared<CANMessage>();
|
||||
canmsg->network = network;
|
||||
canmsg->description = can.description;
|
||||
canmsg->data.insert(canmsg->data.end(), can.data, can.data + can.length);
|
||||
canmsg->arbid = can.arbid;
|
||||
canmsg->dlcOnWire = can.dlcOnWire;
|
||||
canmsg->isExtended = can.status.extendedFrame;
|
||||
canmsg->isRemote = can.status.remoteFrame | can.status.canfdRTR;
|
||||
canmsg->isCANFD = can.status.canfdFDF;
|
||||
canmsg->baudrateSwitch = can.status.canfdBRS;
|
||||
canmsg->errorStateIndicator = can.status.canfdESI;
|
||||
return canmsg;
|
||||
}
|
||||
case Network::Type::Ethernet:
|
||||
case Network::Type::AutomotiveEthernet: {
|
||||
neomessage_eth_t& eth = *(neomessage_eth_t*)neomessage;
|
||||
auto ethmsg = std::make_shared<EthernetMessage>();
|
||||
ethmsg->network = network;
|
||||
ethmsg->description = eth.description;
|
||||
ethmsg->data.insert(ethmsg->data.end(), eth.data, eth.data + eth.length);
|
||||
return ethmsg;
|
||||
}
|
||||
case Network::Type::LIN: {
|
||||
neomessage_lin_t& lin = *(neomessage_lin_t*)neomessage;
|
||||
auto linmsg = std::make_shared<LINMessage>();
|
||||
linmsg->network = network;
|
||||
linmsg->description = lin.description;
|
||||
linmsg->protectedID = lin.header[0];
|
||||
linmsg->ID = linmsg->protectedID & 0x3F;
|
||||
linmsg->statusFlags = {
|
||||
static_cast<bool>(lin.linStatus.txChecksumEnhanced),
|
||||
static_cast<bool>(lin.linStatus.txCommander),
|
||||
static_cast<bool>(lin.linStatus.txResponder),
|
||||
static_cast<bool>(lin.linStatus.updateResponderOnce),
|
||||
static_cast<bool>(lin.linStatus.hasUpdatedResponderOnce),
|
||||
static_cast<bool>(lin.linStatus.busRecovered),
|
||||
static_cast<bool>(lin.linStatus.breakOnly)
|
||||
};
|
||||
linmsg->isEnhancedChecksum = linmsg->statusFlags.TxChecksumEnhanced;
|
||||
linmsg->errFlags = {
|
||||
static_cast<bool>(lin.linStatus.breakOnly),
|
||||
static_cast<bool>(lin.status.linJustBreakSync),
|
||||
static_cast<bool>(lin.status.linErrorTXRXMismatch),
|
||||
static_cast<bool>(lin.status.linErrorRXBreakNotZero),
|
||||
static_cast<bool>(lin.status.linErrorRXBreakTooShort),
|
||||
static_cast<bool>(lin.status.linErrorRXSyncNot55),
|
||||
static_cast<bool>(lin.status.linErrorRXDataGreaterEight),
|
||||
static_cast<bool>(lin.status.linSyncFrameError),
|
||||
static_cast<bool>(lin.status.linIDFrameError),
|
||||
static_cast<bool>(lin.status.linSlaveByteError),
|
||||
static_cast<bool>(lin.status.checksumError)
|
||||
};
|
||||
if(lin.length > 1) {
|
||||
auto numHeaderBytes = std::min(lin.length, static_cast<size_t>(3));
|
||||
linmsg->data.insert(linmsg->data.end(), (lin.header + 1), (lin.header + numHeaderBytes));
|
||||
linmsg->data.insert(linmsg->data.end(), lin.data, (lin.data + (lin.length - numHeaderBytes)));
|
||||
linmsg->checksum = linmsg->data.back();
|
||||
linmsg->data.pop_back();
|
||||
}
|
||||
if (linmsg->statusFlags.TxCommander) {
|
||||
if (linmsg->data.size())
|
||||
linmsg->linMsgType = icsneo::LINMessage::Type::LIN_COMMANDER_MSG;
|
||||
else
|
||||
linmsg->linMsgType = icsneo::LINMessage::Type::LIN_HEADER_ONLY;
|
||||
} else if (linmsg->statusFlags.TxResponder) {
|
||||
linmsg->linMsgType = icsneo::LINMessage::Type::LIN_UPDATE_RESPONDER;
|
||||
}
|
||||
return linmsg;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Network::Type::Ethernet: {
|
||||
neomessage_eth_t& eth = *(neomessage_eth_t*)neomessage;
|
||||
auto ethmsg = std::make_shared<EthernetMessage>();
|
||||
ethmsg->network = network;
|
||||
ethmsg->data.insert(ethmsg->data.end(), eth.data, eth.data + eth.length);
|
||||
return ethmsg;
|
||||
}
|
||||
default:
|
||||
// TODO Implement others
|
||||
return std::shared_ptr<Message>();
|
||||
default: break;
|
||||
}
|
||||
return std::shared_ptr<Message>();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
#include "icsneo/communication/message/networkmutexmessage.h"
|
||||
#include "icsneo/communication/icspb.h"
|
||||
#include "icsneo/communication/command.h"
|
||||
#include "icsneo/communication/message/extendedresponsemessage.h"
|
||||
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
std::shared_ptr<NetworkMutexMessage> NetworkMutexMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||
NetworkMutexMessage decoded;
|
||||
commands::network::v1::NetworkMutex msg;
|
||||
|
||||
if(!protoapi::processResponse(bytestream.data(), bytestream.size(), msg)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(msg.has_client_id()) {
|
||||
decoded.owner_id.emplace(msg.client_id());
|
||||
}
|
||||
if(msg.has_type()) {
|
||||
decoded.type.emplace(static_cast<NetworkMutexType>(msg.type()));
|
||||
}
|
||||
if(msg.has_priority()) {
|
||||
decoded.priority.emplace(msg.priority());
|
||||
}
|
||||
if(msg.has_ttl()){
|
||||
decoded.ttlMs.emplace(msg.ttl());
|
||||
}
|
||||
if(msg.has_event()){
|
||||
decoded.event.emplace(static_cast<NetworkMutexEvent>(msg.event()));
|
||||
}
|
||||
for(int i = 0 ; i < msg.network_ids_size(); ++i){
|
||||
decoded.networks.emplace(static_cast<Network::NetID>(msg.network_ids(i)));
|
||||
}
|
||||
return std::make_shared<NetworkMutexMessage>(decoded);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> NetworkMutexMessage::EncodeArgumentsForLock(uint32_t client_id, NetworkMutexType type, uint32_t priority, uint32_t ttlMs, const std::set<Network::NetID>& networks, const device_eventhandler_t& /* report */) {
|
||||
commands::network::v1::NetworkMutex msg;
|
||||
for(auto&& network_id : networks) {
|
||||
msg.add_network_ids(static_cast<commands::network::v1::NetworkId>(network_id));
|
||||
}
|
||||
msg.set_client_id(client_id);
|
||||
msg.set_priority(priority);
|
||||
msg.set_ttl(ttlMs);
|
||||
msg.set_type(static_cast<commands::network::v1::MutexType>(type));
|
||||
|
||||
return protoapi::getPayload(protoapi::Command::PUT, msg);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> NetworkMutexMessage::EncodeArgumentsForLockAll(uint32_t client_id, NetworkMutexType type, uint32_t priority, uint32_t ttlMs, const device_eventhandler_t& /* report */) {
|
||||
commands::network::v1::NetworkMutex msg;
|
||||
msg.set_client_id(client_id);
|
||||
msg.set_priority(priority);
|
||||
msg.set_ttl(ttlMs);
|
||||
msg.set_type(static_cast<commands::network::v1::MutexType>(type));
|
||||
msg.set_global(true);
|
||||
|
||||
return protoapi::getPayload(protoapi::Command::PUT, msg);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> NetworkMutexMessage::EncodeArgumentsForUnlock(uint32_t client_id, const std::set<Network::NetID>& networks, const device_eventhandler_t& /* report */) {
|
||||
commands::network::v1::NetworkMutex msg;
|
||||
msg.Clear();
|
||||
for(auto&& network_id : networks)
|
||||
{
|
||||
msg.add_network_ids(static_cast<commands::network::v1::NetworkId>(network_id));
|
||||
}
|
||||
msg.set_client_id(client_id);
|
||||
msg.set_release(true);
|
||||
|
||||
return protoapi::getPayload(protoapi::Command::PUT, msg);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> NetworkMutexMessage::EncodeArgumentsForUnlockAll(uint32_t client_id, const device_eventhandler_t& /* report */) {
|
||||
commands::network::v1::NetworkMutex msg;
|
||||
msg.Clear();
|
||||
msg.set_client_id(client_id);
|
||||
msg.set_release(true);
|
||||
msg.set_global(true);
|
||||
|
||||
return protoapi::getPayload(protoapi::Command::PUT, msg);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> NetworkMutexMessage::EncodeArgumentsForStatus(Network::NetID network, const device_eventhandler_t& /* report */) {
|
||||
commands::network::v1::NetworkMutex msg;
|
||||
msg.add_network_ids(static_cast<commands::network::v1::NetworkId>(network));
|
||||
return protoapi::getPayload(protoapi::Command::GET, msg);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "icsneo/communication/message/spiportkeymessage.h"
|
||||
#include "icsneo/communication/message/extendedresponsemessage.h"
|
||||
#include "icsneo/communication/command.h"
|
||||
#include "icsneo/communication/network.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
std::shared_ptr<SPIPortKeyMessage> SPIPortKeyMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||
if(bytestream.size() < sizeof(ExtendedResponseMessage::ResponseHeader))
|
||||
return nullptr;
|
||||
|
||||
const auto* hdr = reinterpret_cast<const ExtendedResponseMessage::ResponseHeader*>(bytestream.data());
|
||||
|
||||
if(hdr->command != ExtendedCommand::ExecuteSPIPortKeyOperation)
|
||||
return nullptr;
|
||||
|
||||
const size_t required = sizeof(ExtendedResponseMessage::ResponseHeader) + sizeof(SPIPortKeyPacket);
|
||||
if(bytestream.size() < required)
|
||||
return nullptr;
|
||||
|
||||
auto msg = std::make_shared<SPIPortKeyMessage>();
|
||||
|
||||
const auto* packet = reinterpret_cast<const SPIPortKeyPacket*>(bytestream.data() + sizeof(ExtendedResponseMessage::ResponseHeader));
|
||||
msg->isKeyLoaded = packet->isKeyLoaded;
|
||||
|
||||
return msg;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "icsneo/communication/message/tc10statusmessage.h"
|
||||
#include "icsneo/communication/command.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
#pragma pack(push, 2)
|
||||
struct Header {
|
||||
ExtendedCommand command;
|
||||
uint16_t length;
|
||||
};
|
||||
|
||||
struct Packet {
|
||||
Header header;
|
||||
TC10WakeStatus wakeStatus;
|
||||
TC10SleepStatus sleepStatus;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
std::shared_ptr<TC10StatusMessage> TC10StatusMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||
if(bytestream.size() < sizeof(Packet)) {
|
||||
return nullptr;
|
||||
}
|
||||
const Packet* packet = (Packet*)bytestream.data();
|
||||
if (packet->header.command != ExtendedCommand::GetTC10Status) {
|
||||
return nullptr;
|
||||
}
|
||||
if (packet->header.length < sizeof(Packet) - sizeof(Header)) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::make_shared<TC10StatusMessage>(packet->wakeStatus, packet->sleepStatus);
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
#include "icsneo/communication/message/transmitmessage.h"
|
||||
|
||||
// packet defs
|
||||
#include "icsneo/communication/packet/ethernetpacket.h"
|
||||
#include "icsneo/communication/packet/canpacket.h"
|
||||
#include "icsneo/communication/packet/linpacket.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
static std::vector<uint8_t> EncodeFromMessageEthernet(std::shared_ptr<Frame> frame, const device_eventhandler_t& report) {
|
||||
auto ethmsg = std::dynamic_pointer_cast<EthernetMessage>(frame);
|
||||
if(!ethmsg) {
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return {};
|
||||
}
|
||||
std::vector<uint8_t> encoded;
|
||||
size_t messageLen = ethmsg->data.size();
|
||||
encoded.resize(sizeof(TransmitMessage) + messageLen);
|
||||
|
||||
TransmitMessage* const msg = (TransmitMessage*)encoded.data();
|
||||
HardwareEthernetPacket* const ethpacket = (HardwareEthernetPacket*)(msg->commonHeader);
|
||||
uint8_t* const payload = encoded.data() + sizeof(TransmitMessage);
|
||||
|
||||
ethpacket->header.ENABLE_PADDING = ethmsg->noPadding ? 0 : 1;
|
||||
ethpacket->header.FCS_OVERRIDE = ethmsg->fcs ? 1 : 0;
|
||||
ethpacket->eid.txlen = static_cast<uint16_t>(messageLen);
|
||||
ethpacket->Length = static_cast<uint16_t>(messageLen);
|
||||
ethpacket->stats = ethmsg->description;
|
||||
ethpacket->NetworkID = static_cast<uint16_t>(ethmsg->network.getNetID());
|
||||
std::copy(ethmsg->data.begin(), ethmsg->data.end(), payload);
|
||||
return encoded;
|
||||
}
|
||||
|
||||
static std::vector<uint8_t> EncodeFromMessageCAN(std::shared_ptr<Frame> frame, const device_eventhandler_t& report) {
|
||||
auto canmsg = std::dynamic_pointer_cast<CANMessage>(frame);
|
||||
if(!canmsg) {
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return {};
|
||||
}
|
||||
if(canmsg->isCANFD && canmsg->isRemote) {
|
||||
report(APIEvent::Type::RTRNotSupported, APIEvent::Severity::Error);
|
||||
return {}; // RTR frames can not be used with CAN FD
|
||||
}
|
||||
std::vector<uint8_t> encoded;
|
||||
size_t messageLen = canmsg->data.size();
|
||||
size_t extraLen = 0;
|
||||
if(messageLen > 8) {
|
||||
extraLen = messageLen - 8;
|
||||
}
|
||||
encoded.resize(sizeof(TransmitMessage) + extraLen);
|
||||
|
||||
TransmitMessage* const msg = (TransmitMessage*)encoded.data();
|
||||
HardwareCANPacket* const canpacket = (HardwareCANPacket*)(msg->commonHeader);
|
||||
uint8_t* const extra_payload = encoded.data() + sizeof(TransmitMessage);
|
||||
|
||||
const size_t dataSize = canmsg->data.size();
|
||||
std::optional<uint8_t> dlc = CAN_LengthToDLC(dataSize, canmsg->isCANFD);
|
||||
if(!dlc.has_value()) {
|
||||
report(APIEvent::Type::MessageMaxLengthExceeded, APIEvent::Severity::Error);
|
||||
return {}; // Too much data for the protocol
|
||||
}
|
||||
// arb id
|
||||
if(canmsg->isExtended) {
|
||||
canpacket->header.IDE = 1;
|
||||
canpacket->header.SID = (canmsg->arbid >> 18) & 0x7FF;
|
||||
canpacket->eid.EID = (canmsg->arbid >> 6) & 0xfff;
|
||||
canpacket->dlc.EID2 = canmsg->arbid & 0x3f;
|
||||
} else {
|
||||
canpacket->header.IDE = 0;
|
||||
canpacket->header.SID = canmsg->arbid & 0x7FF;
|
||||
}
|
||||
|
||||
// DLC
|
||||
canpacket->dlc.DLC = dlc.value();
|
||||
|
||||
// FDF/BRS or remote frames
|
||||
if(canmsg->isCANFD) {
|
||||
canpacket->header.EDL = 1;
|
||||
canpacket->header.BRS = canmsg->baudrateSwitch ? 1 : 0;
|
||||
canpacket->header.ESI = canmsg->errorStateIndicator ? 1 : 0;
|
||||
canpacket->dlc.RTR = 0;
|
||||
canpacket->timestamp.IsExtended = 1;
|
||||
|
||||
} else {
|
||||
canpacket->header.EDL = 0;
|
||||
canpacket->header.BRS = 0;
|
||||
canpacket->header.ESI = 0;
|
||||
canpacket->dlc.RTR = canmsg->isRemote ? 1 : 0;
|
||||
}
|
||||
// network
|
||||
canpacket->NetworkID = static_cast<uint16_t>(canmsg->network.getNetID());
|
||||
canpacket->Length = static_cast<uint16_t>(extraLen);
|
||||
// description id
|
||||
canpacket->stats = canmsg->description;
|
||||
// first 8 bytes
|
||||
std::copy(canmsg->data.begin(), canmsg->data.begin() + (messageLen > 8 ? 8 : messageLen), canpacket->data);
|
||||
// extra bytes
|
||||
if(extraLen > 0) {
|
||||
// copy extra data after the can packet
|
||||
std::copy(canmsg->data.begin() + 8, canmsg->data.end(), extra_payload);
|
||||
}
|
||||
return encoded;
|
||||
}
|
||||
|
||||
static std::vector<uint8_t> EncodeFromMessageLIN(std::shared_ptr<Frame> frame, const device_eventhandler_t& report) {
|
||||
auto linmsg = std::dynamic_pointer_cast<LINMessage>(frame);
|
||||
if(!linmsg) {
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return {};
|
||||
}
|
||||
if(linmsg->linMsgType == LINMessage::Type::NOT_SET) {
|
||||
report(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
|
||||
return {};
|
||||
}
|
||||
|
||||
size_t dataLen = std::min<size_t>(8, linmsg->data.size());
|
||||
std::vector<uint8_t> encoded;
|
||||
encoded.resize(sizeof(TransmitMessage));
|
||||
|
||||
TransmitMessage* const msg = (TransmitMessage*)encoded.data();
|
||||
HardwareLINPacket* const linpacket = (HardwareLINPacket*)(msg->commonHeader);
|
||||
memset(linpacket, 0, sizeof(HardwareLINPacket));
|
||||
|
||||
// Protected ID and ID
|
||||
linmsg->protectedID = linmsg->calcProtectedID(linmsg->ID);
|
||||
linpacket->CoreMiniBitsLIN.ID = linmsg->protectedID & 0x3F;
|
||||
|
||||
// LIN message type flags
|
||||
switch(linmsg->linMsgType) {
|
||||
case LINMessage::Type::LIN_COMMANDER_MSG:
|
||||
linpacket->CoreMiniBitsLIN.TXCommander = 1;
|
||||
break;
|
||||
case LINMessage::Type::LIN_HEADER_ONLY:
|
||||
linpacket->CoreMiniBitsLIN.TXCommander = 1;
|
||||
break;
|
||||
case LINMessage::Type::LIN_UPDATE_RESPONDER:
|
||||
linpacket->CoreMiniBitsLIN.TXResponder = 1;
|
||||
break;
|
||||
case LINMessage::Type::LIN_BREAK_ONLY:
|
||||
linpacket->CoreMiniBitsLIN.TXCommander = 1;
|
||||
linpacket->CoreMiniBitsLIN.BreakOnly = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Enhanced checksum
|
||||
linpacket->CoreMiniBitsLIN.TxChkSumEnhanced = linmsg->isEnhancedChecksum ? 1 : 0;
|
||||
|
||||
// Data and checksum
|
||||
bool hasData = (linmsg->linMsgType == LINMessage::Type::LIN_COMMANDER_MSG ||
|
||||
linmsg->linMsgType == LINMessage::Type::LIN_UPDATE_RESPONDER) && dataLen > 0;
|
||||
|
||||
if(hasData) {
|
||||
// len includes data bytes + 1 checksum byte
|
||||
linpacket->CoreMiniBitsLIN.len = static_cast<uint16_t>(dataLen + 1);
|
||||
std::copy(linmsg->data.begin(), linmsg->data.begin() + dataLen, linpacket->data);
|
||||
// Checksum goes after data: in data[dataLen] if < 8, otherwise in LINByte9
|
||||
if(dataLen < 8)
|
||||
linpacket->data[dataLen] = linmsg->checksum;
|
||||
else
|
||||
linpacket->CoreMiniBitsLIN.LINByte9 = linmsg->checksum;
|
||||
} else {
|
||||
linpacket->CoreMiniBitsLIN.len = 0;
|
||||
}
|
||||
|
||||
// Description/stats and network
|
||||
linpacket->stats = linmsg->description;
|
||||
|
||||
return encoded;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> TransmitMessage::EncodeFromMessage(std::shared_ptr<Frame> frame, uint32_t client_id, const device_eventhandler_t& report) {
|
||||
std::vector<uint8_t> result;
|
||||
switch(frame->network.getType()) {
|
||||
case Network::Type::Ethernet:
|
||||
case Network::Type::AutomotiveEthernet:
|
||||
result = EncodeFromMessageEthernet(frame, report);
|
||||
break;
|
||||
case Network::Type::Internal:
|
||||
case Network::Type::CAN:
|
||||
result = EncodeFromMessageCAN(frame, report);
|
||||
break;
|
||||
case Network::Type::LIN:
|
||||
result = EncodeFromMessageLIN(frame, report);
|
||||
break;
|
||||
default:
|
||||
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
|
||||
return result;
|
||||
}
|
||||
// common fields
|
||||
if(result.empty())
|
||||
return result;
|
||||
TransmitMessage* const msg = (TransmitMessage*)result.data();
|
||||
msg->options.clientId = client_id;
|
||||
msg->options.networkId = static_cast<uint32_t>(frame->network.getNetID());
|
||||
msg->options.reserved[0] = 0;
|
||||
msg->options.reserved[1] = 0;
|
||||
msg->options.reserved[2] = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -2,11 +2,20 @@
|
||||
#include "icsneo/communication/command.h"
|
||||
#include "icsneo/communication/decoder.h"
|
||||
#include "icsneo/communication/packetizer.h"
|
||||
#include "icsneo/communication/message/neoreadmemorysdmessage.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
MultiChannelCommunication::MultiChannelCommunication(device_eventhandler_t err, std::unique_ptr<Driver> com,
|
||||
std::function<std::unique_ptr<Packetizer>()> makeConfiguredPacketizer, std::unique_ptr<Encoder> e,
|
||||
std::unique_ptr<Decoder> md, size_t vnetCount) :
|
||||
Communication(err, std::move(com), makeConfiguredPacketizer, std::move(e), std::move(md)), numVnets(vnetCount), packetRB(2048) {
|
||||
vnetThreads.resize(numVnets);
|
||||
vnetQueues.resize(numVnets);
|
||||
}
|
||||
|
||||
void MultiChannelCommunication::spawnThreads() {
|
||||
for(size_t i = 0; i < NUM_SUPPORTED_VNETS; i++) {
|
||||
for(size_t i = 0; i < numVnets; i++) {
|
||||
while(vnetQueues[i].pop()) {} // Ensure the queue is empty
|
||||
vnetThreads[i] = std::thread(&MultiChannelCommunication::vnetReadTask, this, i);
|
||||
}
|
||||
@@ -15,6 +24,7 @@ void MultiChannelCommunication::spawnThreads() {
|
||||
|
||||
void MultiChannelCommunication::joinThreads() {
|
||||
closing = true;
|
||||
ringBufCV.notify_all();
|
||||
if(hidReadThread.joinable())
|
||||
hidReadThread.join();
|
||||
for(auto& thread : vnetThreads) {
|
||||
@@ -119,13 +129,21 @@ void MultiChannelCommunication::hidReadTask() {
|
||||
currentQueue = &vnetQueues[0];
|
||||
break;
|
||||
case CommandType::Vnet2_to_HostPC:
|
||||
if(NUM_SUPPORTED_VNETS >= 2)
|
||||
if(numVnets >= 2)
|
||||
currentQueue = &vnetQueues[1];
|
||||
break;
|
||||
case CommandType::Vnet3_to_HostPC:
|
||||
if(NUM_SUPPORTED_VNETS >= 3)
|
||||
if(numVnets >= 3)
|
||||
currentQueue = &vnetQueues[2];
|
||||
break;
|
||||
case CommandType::SDCC1_to_HostPC: {
|
||||
auto msg = std::make_shared<NeoReadMemorySDMessage>();
|
||||
std::swap(msg->data, payloadBytes);
|
||||
dispatchMessage(msg);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(currentQueue == nullptr) {
|
||||
@@ -133,9 +151,13 @@ void MultiChannelCommunication::hidReadTask() {
|
||||
break;
|
||||
}
|
||||
|
||||
if(!currentQueue->enqueue(std::move(payloadBytes)) && gotPacket)
|
||||
EventManager::GetInstance().add(APIEvent(APIEvent::Type::FailedToRead, APIEvent::Severity::Error));
|
||||
payloadBytes.clear();
|
||||
{
|
||||
std::unique_lock lk(ringBufMutex);
|
||||
if(!packetRB.write(std::move(payloadBytes)) && gotPacket)
|
||||
EventManager::GetInstance().add(APIEvent(APIEvent::Type::FailedToRead, APIEvent::Severity::Error));
|
||||
payloadBytes.clear();
|
||||
}
|
||||
ringBufCV.notify_all();
|
||||
gotPacket = true;
|
||||
state = PreprocessState::SearchForCommand;
|
||||
break;
|
||||
@@ -145,7 +167,6 @@ void MultiChannelCommunication::hidReadTask() {
|
||||
}
|
||||
|
||||
void MultiChannelCommunication::vnetReadTask(size_t vnetIndex) {
|
||||
moodycamel::BlockingReaderWriterQueue< std::vector<uint8_t> >& queue = vnetQueues[vnetIndex];
|
||||
std::vector<uint8_t> payloadBytes;
|
||||
std::unique_ptr<Packetizer> packetizerLifetime;
|
||||
Packetizer* vnetPacketizer;
|
||||
@@ -159,18 +180,19 @@ void MultiChannelCommunication::vnetReadTask(size_t vnetIndex) {
|
||||
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
|
||||
|
||||
while(!closing) {
|
||||
if(queue.wait_dequeue_timed(payloadBytes, std::chrono::milliseconds(250))) {
|
||||
if(closing)
|
||||
break;
|
||||
|
||||
if(vnetPacketizer->input(payloadBytes)) {
|
||||
for(const auto& packet : vnetPacketizer->output()) {
|
||||
std::shared_ptr<Message> msg;
|
||||
if(!decoder->decode(msg, packet))
|
||||
continue; // Error will have been reported from within decoder
|
||||
dispatchMessage(msg);
|
||||
}
|
||||
}
|
||||
std::unique_lock lk(ringBufMutex);
|
||||
ringBufCV.wait(lk);
|
||||
if(closing) {
|
||||
break;
|
||||
}
|
||||
if(vnetPacketizer->input(packetRB)) {
|
||||
for(const auto& packet : vnetPacketizer->output()) {
|
||||
std::shared_ptr<Message> msg;
|
||||
if(!decoder->decode(msg, packet))
|
||||
continue;
|
||||
|
||||
dispatchMessage(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
#include "icsneo/communication/packet/a2bpacket.h"
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
const size_t HardwareA2BPacket::a2bMessageMaxLength = sizeof(HardwareA2BPacket) + 1024;
|
||||
|
||||
std::shared_ptr<Message> HardwareA2BPacket::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||
|
||||
if(bytestream.size() < sizeof(HardwareA2BPacket))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const HardwareA2BPacket* data = (const HardwareA2BPacket*)bytestream.data();
|
||||
|
||||
size_t totalPackedLength = static_cast<size_t>(bytestream.size()) - sizeof(HardwareA2BPacket); // First 28 bytes are message header.
|
||||
|
||||
if(totalPackedLength == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<A2BMessage> msg = std::make_shared<A2BMessage>();
|
||||
|
||||
msg->numChannels = data->header.channelNum;
|
||||
msg->channelSize16 = data->header.channelSize16;
|
||||
msg->monitor = data->header.monitor;
|
||||
msg->txmsg = data->header.txmsg;
|
||||
msg->errIndicator = data->header.errIndicator;
|
||||
msg->syncFrame = data->header.syncFrame;
|
||||
msg->rfu2 = data->header.rfu2;
|
||||
msg->timestamp = data->timestamp.TS;
|
||||
|
||||
msg->data = std::vector(bytestream.begin() + sizeof(HardwareA2BPacket), bytestream.end());
|
||||
return msg;
|
||||
}
|
||||
|
||||
bool HardwareA2BPacket::EncodeFromMessage(const A2BMessage& message, std::vector<uint8_t>& bytestream, const device_eventhandler_t& /*report*/) {
|
||||
constexpr size_t a2btxMessageHeaderSize = 6;
|
||||
|
||||
size_t audioBufferSize = message.data.size();
|
||||
size_t totalSize = a2btxMessageHeaderSize + audioBufferSize;
|
||||
|
||||
bytestream.resize(totalSize, 0);
|
||||
uint32_t offset = 0;
|
||||
|
||||
bytestream[offset++] = 0;
|
||||
bytestream[offset++] = 0;
|
||||
bytestream[offset++] = (uint8_t)(audioBufferSize & 0xFF);
|
||||
bytestream[offset++] = (uint8_t)((audioBufferSize >> 8) & 0xFF);
|
||||
bytestream[offset++] = (uint8_t)((message.description >> 8) & 0xFF);
|
||||
bytestream[offset++] = (uint8_t)(message.description & 0xFF);
|
||||
|
||||
std::copy(message.data.begin(), message.data.end(), bytestream.begin() + offset);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
+145
-153
@@ -1,86 +1,134 @@
|
||||
#include "icsneo/communication/packet/canpacket.h"
|
||||
#include "icsneo/communication/message/canerrormessage.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
std::shared_ptr<CANMessage> HardwareCANPacket::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||
const HardwareCANPacket* data = (const HardwareCANPacket*)bytestream.data();
|
||||
static std::optional<uint8_t> CAN_DLCToLength(uint8_t length, bool fd) {
|
||||
if (length <= 8)
|
||||
return length;
|
||||
|
||||
auto msg = std::make_shared<CANMessage>();
|
||||
|
||||
// Arb ID
|
||||
if(data->header.IDE) { // Extended 29-bit ID
|
||||
msg->arbid = (data->header.SID & 0x7ff) << 18;
|
||||
msg->arbid |= (data->eid.EID & 0xfff) << 6;
|
||||
msg->arbid |= (data->dlc.EID2 & 0x3f);
|
||||
msg->isExtended = true;
|
||||
} else { // Standard 11-bit ID
|
||||
msg->arbid = data->header.SID;
|
||||
if (fd) {
|
||||
switch(length) {
|
||||
case 0x9:
|
||||
return uint8_t(12);
|
||||
case 0xa:
|
||||
return uint8_t(16);
|
||||
case 0xb:
|
||||
return uint8_t(20);
|
||||
case 0xc:
|
||||
return uint8_t(24);
|
||||
case 0xd:
|
||||
return uint8_t(32);
|
||||
case 0xe:
|
||||
return uint8_t(48);
|
||||
case 0xf:
|
||||
return uint8_t(64);
|
||||
}
|
||||
}
|
||||
|
||||
// This timestamp is raw off the device (in timestampResolution increments)
|
||||
// Decoder will fix as it has information about the timestampResolution increments
|
||||
msg->timestamp = data->timestamp.TS;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// DLC
|
||||
uint8_t length = data->dlc.DLC;
|
||||
msg->dlcOnWire = length; // This will hold the real DLC on wire 0x0 - 0xF
|
||||
if(data->header.EDL && data->timestamp.IsExtended) { // CAN FD
|
||||
msg->isCANFD = true;
|
||||
msg->baudrateSwitch = data->header.BRS; // CAN FD Baudrate Switch
|
||||
msg->errorStateIndicator = data->header.ESI;
|
||||
if(length > 8) {
|
||||
switch(length) { // CAN FD Length Decoding
|
||||
case 0x9:
|
||||
length = 12;
|
||||
break;
|
||||
case 0xa:
|
||||
length = 16;
|
||||
break;
|
||||
case 0xb:
|
||||
length = 20;
|
||||
break;
|
||||
case 0xc:
|
||||
length = 24;
|
||||
break;
|
||||
case 0xd:
|
||||
length = 32;
|
||||
break;
|
||||
case 0xe:
|
||||
length = 48;
|
||||
break;
|
||||
case 0xf:
|
||||
length = 64;
|
||||
break;
|
||||
default:
|
||||
return nullptr;
|
||||
std::optional<uint8_t> icsneo::CAN_LengthToDLC(size_t dataLength, bool fd) {
|
||||
if (dataLength <= 8)
|
||||
return uint8_t(dataLength);
|
||||
|
||||
if (fd) {
|
||||
if (dataLength <= 12)
|
||||
return uint8_t(0x9);
|
||||
else if (dataLength <= 16)
|
||||
return uint8_t(0xA);
|
||||
else if (dataLength <= 20)
|
||||
return uint8_t(0xB);
|
||||
else if (dataLength <= 24)
|
||||
return uint8_t(0xC);
|
||||
else if (dataLength <= 32)
|
||||
return uint8_t(0xD);
|
||||
else if (dataLength <= 48)
|
||||
return uint8_t(0xE);
|
||||
else if (dataLength <= 64)
|
||||
return uint8_t(0xF);
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
std::shared_ptr<Message> HardwareCANPacket::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||
const HardwareCANPacket* data = (const HardwareCANPacket*)bytestream.data();
|
||||
const HardwareCANErrorPacket* errPacket = (const HardwareCANErrorPacket*)bytestream.data();
|
||||
if(errPacket->ERROR_INDICATOR) {
|
||||
auto msg = std::make_shared<CANErrorMessage>();
|
||||
msg->receiveErrorCount = errPacket->REC;
|
||||
msg->transmitErrorCount = errPacket->TEC;
|
||||
msg->errorWarn = HardwareCANErrorPacket::GetErrorWarn(errPacket->flags);
|
||||
msg->errorPassive = HardwareCANErrorPacket::GetErrorPassive(errPacket->flags);
|
||||
msg->busOff = HardwareCANErrorPacket::GetBusOff(errPacket->flags);
|
||||
msg->errorCode = (CANErrorCode)errPacket->error_code;
|
||||
msg->dataErrorCode = (CANErrorCode)errPacket->brs_data_error_code;
|
||||
// This timestamp is raw off the device (in timestampResolution increments)
|
||||
// Decoder will fix as it has information about the timestampResolution increments
|
||||
msg->timestamp = data->timestamp.TS;
|
||||
|
||||
return msg;
|
||||
|
||||
} else { // CAN Frame
|
||||
auto msg = std::make_shared<CANMessage>();
|
||||
|
||||
// Arb ID
|
||||
if(data->header.IDE) { // Extended 29-bit ID
|
||||
msg->arbid = (data->header.SID & 0x7ff) << 18;
|
||||
msg->arbid |= (data->eid.EID & 0xfff) << 6;
|
||||
msg->arbid |= (data->dlc.EID2 & 0x3f);
|
||||
msg->isExtended = true;
|
||||
} else { // Standard 11-bit ID
|
||||
msg->arbid = data->header.SID;
|
||||
}
|
||||
|
||||
// This timestamp is raw off the device (in timestampResolution increments)
|
||||
// Decoder will fix as it has information about the timestampResolution increments
|
||||
msg->timestamp = data->timestamp.TS;
|
||||
|
||||
// DLC
|
||||
uint8_t length = data->dlc.DLC;
|
||||
msg->dlcOnWire = length; // This will hold the real DLC on wire 0x0 - 0xF
|
||||
if(data->header.EDL && data->timestamp.IsExtended) { // CAN FD
|
||||
msg->isCANFD = true;
|
||||
msg->baudrateSwitch = data->header.BRS; // CAN FD Baudrate Switch
|
||||
msg->errorStateIndicator = data->header.ESI;
|
||||
const std::optional<uint8_t> lenFromDLC = CAN_DLCToLength(length, true);
|
||||
if (lenFromDLC)
|
||||
length = *lenFromDLC;
|
||||
} else if(length > 8) { // This is a standard CAN frame with a length of more than 8
|
||||
// Yes, this is possible. On the wire, the length field is a nibble, and we do want to return an accurate value
|
||||
// We don't want to overread our buffer, though, so make sure we cap the length
|
||||
length = 8;
|
||||
}
|
||||
|
||||
// Data
|
||||
// The first 8 bytes are always in the standard place
|
||||
if((data->dlc.RTR && data->header.IDE) || (!data->header.IDE && data->header.SRR)) { // Remote Request Frame
|
||||
msg->data.resize(length); // This data will be all zeros, but the length will be set
|
||||
msg->isRemote = true;
|
||||
} else {
|
||||
msg->data.reserve(length);
|
||||
msg->data.insert(msg->data.end(), data->data, data->data + (length > 8 ? 8 : length));
|
||||
if(length > 8) { // If there are more than 8 bytes, they come at the end of the message
|
||||
// Messages with extra data are formatted as message, then uint16_t netid, then uint16_t length, then extra data
|
||||
const auto extraDataStart = bytestream.begin() + sizeof(HardwareCANPacket);
|
||||
msg->data.insert(msg->data.end(), extraDataStart, extraDataStart + (length - 8));
|
||||
}
|
||||
}
|
||||
} else if(length > 8) { // This is a standard CAN frame with a length of more than 8
|
||||
// Yes, this is possible. On the wire, the length field is a nibble, and we do want to return an accurate value
|
||||
// We don't want to overread our buffer, though, so make sure we cap the length
|
||||
length = 8;
|
||||
}
|
||||
|
||||
// Data
|
||||
// The first 8 bytes are always in the standard place
|
||||
if((data->dlc.RTR && data->header.IDE) || (!data->header.IDE && data->header.SRR)) { // Remote Request Frame
|
||||
msg->data.resize(length); // This data will be all zeros, but the length will be set
|
||||
msg->isRemote = true;
|
||||
} else {
|
||||
msg->data.reserve(length);
|
||||
msg->data.insert(msg->data.end(), data->data, data->data + (length > 8 ? 8 : length));
|
||||
if(length > 8) { // If there are more than 8 bytes, they come at the end of the message
|
||||
// Messages with extra data are formatted as message, then uint16_t netid, then uint16_t length, then extra data
|
||||
const auto extraDataStart = bytestream.begin() + sizeof(HardwareCANPacket) + 2 + 2;
|
||||
msg->data.insert(msg->data.end(), extraDataStart, extraDataStart + (length - 8));
|
||||
}
|
||||
}
|
||||
|
||||
msg->transmitted = data->eid.TXMSG;
|
||||
msg->error = data->eid.TXAborted || data->eid.TXError || data->eid.TXLostArb;
|
||||
msg->description = data->stats;
|
||||
msg->transmitted = data->eid.TXMSG;
|
||||
// Set the generic frame error state
|
||||
msg->error = data->eid.TXAborted || data->eid.TXError || data->eid.TXLostArb;
|
||||
// Set specific error states for CANError
|
||||
msg->txAborted = data->eid.TXAborted;
|
||||
msg->txLostArb = data->eid.TXLostArb;
|
||||
msg->txError = data->eid.TXError;
|
||||
msg->description = data->stats;
|
||||
|
||||
return msg;
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
||||
bool HardwareCANPacket::EncodeFromMessage(const CANMessage& message, std::vector<uint8_t>& result, const device_eventhandler_t& report) {
|
||||
@@ -90,93 +138,38 @@ bool HardwareCANPacket::EncodeFromMessage(const CANMessage& message, std::vector
|
||||
}
|
||||
|
||||
const size_t dataSize = message.data.size();
|
||||
if(dataSize > 64 || (dataSize > 8 && !message.isCANFD)) {
|
||||
std::optional<uint8_t> dlc = CAN_LengthToDLC(dataSize, message.isCANFD);
|
||||
if (!dlc.has_value()) {
|
||||
report(APIEvent::Type::MessageMaxLengthExceeded, APIEvent::Severity::Error);
|
||||
return false; // Too much data for the protocol
|
||||
}
|
||||
|
||||
uint8_t lengthNibble = uint8_t(message.data.size());
|
||||
uint8_t paddingBytes = 0;
|
||||
if(lengthNibble > 8) {
|
||||
switch(lengthNibble) {
|
||||
case 9: paddingBytes++;
|
||||
case 10: paddingBytes++;
|
||||
case 11: paddingBytes++;
|
||||
case 12:
|
||||
lengthNibble = 0x9;
|
||||
break;
|
||||
case 13: paddingBytes++;
|
||||
case 14: paddingBytes++;
|
||||
case 15: paddingBytes++;
|
||||
case 16:
|
||||
lengthNibble = 0xA;
|
||||
break;
|
||||
case 17: paddingBytes++;
|
||||
case 18: paddingBytes++;
|
||||
case 19: paddingBytes++;
|
||||
case 20:
|
||||
lengthNibble = 0xB;
|
||||
break;
|
||||
case 21: paddingBytes++;
|
||||
case 22: paddingBytes++;
|
||||
case 23: paddingBytes++;
|
||||
case 24:
|
||||
lengthNibble = 0xC;
|
||||
break;
|
||||
case 25: paddingBytes++;
|
||||
case 26: paddingBytes++;
|
||||
case 27: paddingBytes++;
|
||||
case 28: paddingBytes++;
|
||||
case 29: paddingBytes++;
|
||||
case 30: paddingBytes++;
|
||||
case 31: paddingBytes++;
|
||||
case 32:
|
||||
lengthNibble = 0xD;
|
||||
break;
|
||||
case 33: paddingBytes++;
|
||||
case 34: paddingBytes++;
|
||||
case 35: paddingBytes++;
|
||||
case 36: paddingBytes++;
|
||||
case 37: paddingBytes++;
|
||||
case 38: paddingBytes++;
|
||||
case 39: paddingBytes++;
|
||||
case 40: paddingBytes++;
|
||||
case 41: paddingBytes++;
|
||||
case 42: paddingBytes++;
|
||||
case 43: paddingBytes++;
|
||||
case 44: paddingBytes++;
|
||||
case 45: paddingBytes++;
|
||||
case 46: paddingBytes++;
|
||||
case 47: paddingBytes++;
|
||||
case 48:
|
||||
lengthNibble = 0xE;
|
||||
break;
|
||||
case 49: paddingBytes++;
|
||||
case 50: paddingBytes++;
|
||||
case 51: paddingBytes++;
|
||||
case 52: paddingBytes++;
|
||||
case 53: paddingBytes++;
|
||||
case 54: paddingBytes++;
|
||||
case 55: paddingBytes++;
|
||||
case 56: paddingBytes++;
|
||||
case 57: paddingBytes++;
|
||||
case 58: paddingBytes++;
|
||||
case 59: paddingBytes++;
|
||||
case 60: paddingBytes++;
|
||||
case 61: paddingBytes++;
|
||||
case 62: paddingBytes++;
|
||||
case 63: paddingBytes++;
|
||||
case 64:
|
||||
lengthNibble = 0xF;
|
||||
break;
|
||||
default:
|
||||
report(APIEvent::Type::MessageMaxLengthExceeded, APIEvent::Severity::Error);
|
||||
return false; // CAN FD frame may have had an incorrect byte count
|
||||
if (message.dlcOnWire != 0) {
|
||||
if(message.dlcOnWire > 0xf) {
|
||||
// The DLC is only a nibble
|
||||
// It is actually possible to transmit a standard CAN frame with a DLC > 8
|
||||
// While it is invalid, most controllers will still pass along the received
|
||||
// frame and 8 bytes of data, so it may be desirable to test behavior with
|
||||
// these frames. We let you do it if you set `message.dlcOnWire` for transmit.
|
||||
report(APIEvent::Type::MessageMaxLengthExceeded, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (message.dlcOnWire < *dlc) {
|
||||
report(APIEvent::Type::MessageMaxLengthExceeded, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (message.dlcOnWire > *dlc)
|
||||
dlc = message.dlcOnWire;
|
||||
}
|
||||
|
||||
// The only way this fails is if we're transmitting a DLC > 8 on standard CAN
|
||||
const uint8_t paddedLength = CAN_DLCToLength(*dlc, message.isCANFD).value_or(8);
|
||||
const uint8_t paddingBytes = uint8_t(paddedLength - dataSize);
|
||||
|
||||
// Pre-allocate as much memory as we will possibly need for speed
|
||||
result.reserve(17 + dataSize + paddingBytes);
|
||||
result.reserve(16 + dataSize + paddingBytes);
|
||||
|
||||
result.push_back(0 /* byte count here later */ << 4 | (uint8_t(message.network.getNetID()) & 0xF));
|
||||
|
||||
@@ -211,7 +204,7 @@ bool HardwareCANPacket::EncodeFromMessage(const CANMessage& message, std::vector
|
||||
// Status and DLC bits
|
||||
if(message.isCANFD) {
|
||||
result.push_back(0x0F); // FD Frame
|
||||
uint8_t fdStatusByte = lengthNibble;
|
||||
uint8_t fdStatusByte = *dlc;
|
||||
if(message.baudrateSwitch)
|
||||
fdStatusByte |= 0x80; // BRS status bit
|
||||
// The firmware does not yet support transmitting ESI
|
||||
@@ -219,13 +212,12 @@ bool HardwareCANPacket::EncodeFromMessage(const CANMessage& message, std::vector
|
||||
} else {
|
||||
// TODO Support high voltage wakeup, bitwise-or in 0x8 here to enable
|
||||
uint8_t statusNibble = message.isRemote ? 0x4 : 0x0;
|
||||
result.push_back((statusNibble << 4) | lengthNibble);
|
||||
result.push_back((statusNibble << 4) | *dlc);
|
||||
}
|
||||
|
||||
// Now finally the payload
|
||||
result.insert(result.end(), message.data.begin(), message.data.end());
|
||||
result.resize(result.size() + paddingBytes);
|
||||
result.push_back(0);
|
||||
|
||||
// Fill in the length byte from earlier
|
||||
result[0] |= result.size() << 4;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user