lib.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. /*
  2. * lib.c - library for command line tools
  3. *
  4. * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of Volkswagen nor the names of its contributors
  16. * may be used to endorse or promote products derived from this software
  17. * without specific prior written permission.
  18. *
  19. * Alternatively, provided that this notice is retained in full, this
  20. * software may be distributed under the terms of the GNU General
  21. * Public License ("GPL") version 2, in which case the provisions of the
  22. * GPL apply INSTEAD OF those given above.
  23. *
  24. * The provided data structures and external interfaces from this code
  25. * are not restricted to be used by modules with a GPL compatible license.
  26. *
  27. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  28. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  29. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  30. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  31. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  32. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  33. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  34. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  35. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  36. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  37. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  38. * DAMAGE.
  39. *
  40. * Send feedback to <linux-can@vger.kernel.org>
  41. *
  42. */
  43. #include <stdio.h>
  44. #include <string.h>
  45. #include <stdint.h>
  46. #include <sys/socket.h> /* for sa_family_t */
  47. #include <linux/can.h>
  48. #include <linux/can/error.h>
  49. #include "lib.h"
  50. #define CANID_DELIM '#'
  51. #define DATA_SEPERATOR '.'
  52. const char hex_asc_upper[] = "0123456789ABCDEF";
  53. #define hex_asc_upper_lo(x) hex_asc_upper[((x) & 0x0F)]
  54. #define hex_asc_upper_hi(x) hex_asc_upper[((x) & 0xF0) >> 4]
  55. static inline void put_hex_byte(char *buf, __u8 byte)
  56. {
  57. buf[0] = hex_asc_upper_hi(byte);
  58. buf[1] = hex_asc_upper_lo(byte);
  59. }
  60. static inline void _put_id(char *buf, int end_offset, canid_t id)
  61. {
  62. /* build 3 (SFF) or 8 (EFF) digit CAN identifier */
  63. while (end_offset >= 0) {
  64. buf[end_offset--] = hex_asc_upper_lo(id);
  65. id >>= 4;
  66. }
  67. }
  68. #define put_sff_id(buf, id) _put_id(buf, 2, id)
  69. #define put_eff_id(buf, id) _put_id(buf, 7, id)
  70. /* CAN DLC to real data length conversion helpers */
  71. static const unsigned char dlc2len[] = {0, 1, 2, 3, 4, 5, 6, 7,
  72. 8, 12, 16, 20, 24, 32, 48, 64};
  73. /* get data length from can_dlc with sanitized can_dlc */
  74. unsigned char can_dlc2len(unsigned char can_dlc)
  75. {
  76. return dlc2len[can_dlc & 0x0F];
  77. }
  78. static const unsigned char len2dlc[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, /* 0 - 8 */
  79. 9, 9, 9, 9, /* 9 - 12 */
  80. 10, 10, 10, 10, /* 13 - 16 */
  81. 11, 11, 11, 11, /* 17 - 20 */
  82. 12, 12, 12, 12, /* 21 - 24 */
  83. 13, 13, 13, 13, 13, 13, 13, 13, /* 25 - 32 */
  84. 14, 14, 14, 14, 14, 14, 14, 14, /* 33 - 40 */
  85. 14, 14, 14, 14, 14, 14, 14, 14, /* 41 - 48 */
  86. 15, 15, 15, 15, 15, 15, 15, 15, /* 49 - 56 */
  87. 15, 15, 15, 15, 15, 15, 15, 15}; /* 57 - 64 */
  88. /* map the sanitized data length to an appropriate data length code */
  89. unsigned char can_len2dlc(unsigned char len)
  90. {
  91. if (len > 64)
  92. return 0xF;
  93. return len2dlc[len];
  94. }
  95. unsigned char asc2nibble(char c) {
  96. if ((c >= '0') && (c <= '9'))
  97. return c - '0';
  98. if ((c >= 'A') && (c <= 'F'))
  99. return c - 'A' + 10;
  100. if ((c >= 'a') && (c <= 'f'))
  101. return c - 'a' + 10;
  102. return 16; /* error */
  103. }
  104. int hexstring2data(char *arg, unsigned char *data, int maxdlen) {
  105. int len = strlen(arg);
  106. int i;
  107. unsigned char tmp;
  108. if (!len || len%2 || len > maxdlen*2)
  109. return 1;
  110. memset(data, 0, maxdlen);
  111. for (i=0; i < len/2; i++) {
  112. tmp = asc2nibble(*(arg+(2*i)));
  113. if (tmp > 0x0F)
  114. return 1;
  115. data[i] = (tmp << 4);
  116. tmp = asc2nibble(*(arg+(2*i)+1));
  117. if (tmp > 0x0F)
  118. return 1;
  119. data[i] |= tmp;
  120. }
  121. return 0;
  122. }
  123. int parse_canframe(char *cs, struct canfd_frame *cf) {
  124. /* documentation see lib.h */
  125. int i, idx, dlen, len;
  126. int maxdlen = CAN_MAX_DLEN;
  127. int ret = CAN_MTU;
  128. unsigned char tmp;
  129. len = strlen(cs);
  130. //printf("'%s' len %d\n", cs, len);
  131. memset(cf, 0, sizeof(*cf)); /* init CAN FD frame, e.g. LEN = 0 */
  132. if (len < 4)
  133. return 0;
  134. if (cs[3] == CANID_DELIM) { /* 3 digits */
  135. idx = 4;
  136. for (i=0; i<3; i++){
  137. if ((tmp = asc2nibble(cs[i])) > 0x0F)
  138. return 0;
  139. cf->can_id |= (tmp << (2-i)*4);
  140. }
  141. } else if (cs[8] == CANID_DELIM) { /* 8 digits */
  142. idx = 9;
  143. for (i=0; i<8; i++){
  144. if ((tmp = asc2nibble(cs[i])) > 0x0F)
  145. return 0;
  146. cf->can_id |= (tmp << (7-i)*4);
  147. }
  148. if (!(cf->can_id & CAN_ERR_FLAG)) /* 8 digits but no errorframe? */
  149. cf->can_id |= CAN_EFF_FLAG; /* then it is an extended frame */
  150. } else
  151. return 0;
  152. if((cs[idx] == 'R') || (cs[idx] == 'r')){ /* RTR frame */
  153. cf->can_id |= CAN_RTR_FLAG;
  154. /* check for optional DLC value for CAN 2.0B frames */
  155. if(cs[++idx] && (tmp = asc2nibble(cs[idx])) <= CAN_MAX_DLC)
  156. cf->len = tmp;
  157. return ret;
  158. }
  159. if (cs[idx] == CANID_DELIM) { /* CAN FD frame escape char '##' */
  160. maxdlen = CANFD_MAX_DLEN;
  161. ret = CANFD_MTU;
  162. /* CAN FD frame <canid>##<flags><data>* */
  163. if ((tmp = asc2nibble(cs[idx+1])) > 0x0F)
  164. return 0;
  165. cf->flags = tmp;
  166. idx += 2;
  167. }
  168. for (i=0, dlen=0; i < maxdlen; i++){
  169. if(cs[idx] == DATA_SEPERATOR) /* skip (optional) separator */
  170. idx++;
  171. if(idx >= len) /* end of string => end of data */
  172. break;
  173. if ((tmp = asc2nibble(cs[idx++])) > 0x0F)
  174. return 0;
  175. cf->data[i] = (tmp << 4);
  176. if ((tmp = asc2nibble(cs[idx++])) > 0x0F)
  177. return 0;
  178. cf->data[i] |= tmp;
  179. dlen++;
  180. }
  181. cf->len = dlen;
  182. return ret;
  183. }
  184. void fprint_canframe(FILE *stream , struct canfd_frame *cf, char *eol, int sep, int maxdlen) {
  185. /* documentation see lib.h */
  186. char buf[CL_CFSZ]; /* max length */
  187. sprint_canframe(buf, cf, sep, maxdlen);
  188. fprintf(stream, "%s", buf);
  189. if (eol)
  190. fprintf(stream, "%s", eol);
  191. }
  192. void sprint_canframe(char *buf , struct canfd_frame *cf, int sep, int maxdlen) {
  193. /* documentation see lib.h */
  194. int i,offset;
  195. int len = (cf->len > maxdlen) ? maxdlen : cf->len;
  196. if (cf->can_id & CAN_ERR_FLAG) {
  197. put_eff_id(buf, cf->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG));
  198. buf[8] = '#';
  199. offset = 9;
  200. } else if (cf->can_id & CAN_EFF_FLAG) {
  201. put_eff_id(buf, cf->can_id & CAN_EFF_MASK);
  202. buf[8] = '#';
  203. offset = 9;
  204. } else {
  205. put_sff_id(buf, cf->can_id & CAN_SFF_MASK);
  206. buf[3] = '#';
  207. offset = 4;
  208. }
  209. /* standard CAN frames may have RTR enabled. There are no ERR frames with RTR */
  210. if (maxdlen == CAN_MAX_DLEN && cf->can_id & CAN_RTR_FLAG) {
  211. buf[offset++] = 'R';
  212. /* print a given CAN 2.0B DLC if it's not zero */
  213. if (cf->len && cf->len <= CAN_MAX_DLC)
  214. buf[offset++] = hex_asc_upper_lo(cf->len);
  215. buf[offset] = 0;
  216. return;
  217. }
  218. if (maxdlen == CANFD_MAX_DLEN) {
  219. /* add CAN FD specific escape char and flags */
  220. buf[offset++] = '#';
  221. buf[offset++] = hex_asc_upper_lo(cf->flags);
  222. if (sep && len)
  223. buf[offset++] = '.';
  224. }
  225. for (i = 0; i < len; i++) {
  226. put_hex_byte(buf + offset, cf->data[i]);
  227. offset += 2;
  228. if (sep && (i+1 < len))
  229. buf[offset++] = '.';
  230. }
  231. buf[offset] = 0;
  232. }
  233. void fprint_long_canframe(FILE *stream , struct canfd_frame *cf, char *eol, int view, int maxdlen) {
  234. /* documentation see lib.h */
  235. char buf[CL_LONGCFSZ];
  236. sprint_long_canframe(buf, cf, view, maxdlen);
  237. fprintf(stream, "%s", buf);
  238. if ((view & CANLIB_VIEW_ERROR) && (cf->can_id & CAN_ERR_FLAG)) {
  239. snprintf_can_error_frame(buf, sizeof(buf), cf, "\n\t");
  240. fprintf(stream, "\n\t%s", buf);
  241. }
  242. if (eol)
  243. fprintf(stream, "%s", eol);
  244. }
  245. void sprint_long_canframe(char *buf , struct canfd_frame *cf, int view, int maxdlen) {
  246. /* documentation see lib.h */
  247. int i, j, dlen, offset;
  248. int len = (cf->len > maxdlen)? maxdlen : cf->len;
  249. /* initialize space for CAN-ID and length information */
  250. memset(buf, ' ', 15);
  251. if (cf->can_id & CAN_ERR_FLAG) {
  252. put_eff_id(buf, cf->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG));
  253. offset = 10;
  254. } else if (cf->can_id & CAN_EFF_FLAG) {
  255. put_eff_id(buf, cf->can_id & CAN_EFF_MASK);
  256. offset = 10;
  257. } else {
  258. if (view & CANLIB_VIEW_INDENT_SFF) {
  259. put_sff_id(buf + 5, cf->can_id & CAN_SFF_MASK);
  260. offset = 10;
  261. } else {
  262. put_sff_id(buf, cf->can_id & CAN_SFF_MASK);
  263. offset = 5;
  264. }
  265. }
  266. /* The len value is sanitized by maxdlen (see above) */
  267. if (maxdlen == CAN_MAX_DLEN) {
  268. buf[offset + 1] = '[';
  269. buf[offset + 2] = len + '0';
  270. buf[offset + 3] = ']';
  271. /* standard CAN frames may have RTR enabled */
  272. if (cf->can_id & CAN_RTR_FLAG) {
  273. sprintf(buf+offset+5, " remote request");
  274. return;
  275. }
  276. } else {
  277. buf[offset] = '[';
  278. buf[offset + 1] = (len/10) + '0';
  279. buf[offset + 2] = (len%10) + '0';
  280. buf[offset + 3] = ']';
  281. }
  282. offset += 5;
  283. if (view & CANLIB_VIEW_BINARY) {
  284. dlen = 9; /* _10101010 */
  285. if (view & CANLIB_VIEW_SWAP) {
  286. for (i = len - 1; i >= 0; i--) {
  287. buf[offset++] = (i == len-1)?' ':SWAP_DELIMITER;
  288. for (j = 7; j >= 0; j--)
  289. buf[offset++] = (1<<j & cf->data[i])?'1':'0';
  290. }
  291. } else {
  292. for (i = 0; i < len; i++) {
  293. buf[offset++] = ' ';
  294. for (j = 7; j >= 0; j--)
  295. buf[offset++] = (1<<j & cf->data[i])?'1':'0';
  296. }
  297. }
  298. } else {
  299. dlen = 3; /* _AA */
  300. if (view & CANLIB_VIEW_SWAP) {
  301. for (i = len - 1; i >= 0; i--) {
  302. if (i == len-1)
  303. buf[offset++] = ' ';
  304. else
  305. buf[offset++] = SWAP_DELIMITER;
  306. put_hex_byte(buf + offset, cf->data[i]);
  307. offset += 2;
  308. }
  309. } else {
  310. for (i = 0; i < len; i++) {
  311. buf[offset++] = ' ';
  312. put_hex_byte(buf + offset, cf->data[i]);
  313. offset += 2;
  314. }
  315. }
  316. }
  317. buf[offset] = 0; /* terminate string */
  318. /*
  319. * The ASCII & ERRORFRAME output is put at a fixed len behind the data.
  320. * For now we support ASCII output only for payload length up to 8 bytes.
  321. * Does it make sense to write 64 ASCII byte behind 64 ASCII HEX data on the console?
  322. */
  323. if (len > CAN_MAX_DLEN)
  324. return;
  325. if (cf->can_id & CAN_ERR_FLAG)
  326. sprintf(buf+offset, "%*s", dlen*(8-len)+13, "ERRORFRAME");
  327. else if (view & CANLIB_VIEW_ASCII) {
  328. j = dlen*(8-len)+4;
  329. if (view & CANLIB_VIEW_SWAP) {
  330. sprintf(buf+offset, "%*s", j, "`");
  331. offset += j;
  332. for (i = len - 1; i >= 0; i--)
  333. if ((cf->data[i] > 0x1F) && (cf->data[i] < 0x7F))
  334. buf[offset++] = cf->data[i];
  335. else
  336. buf[offset++] = '.';
  337. sprintf(buf+offset, "`");
  338. } else {
  339. sprintf(buf+offset, "%*s", j, "'");
  340. offset += j;
  341. for (i = 0; i < len; i++)
  342. if ((cf->data[i] > 0x1F) && (cf->data[i] < 0x7F))
  343. buf[offset++] = cf->data[i];
  344. else
  345. buf[offset++] = '.';
  346. sprintf(buf+offset, "'");
  347. }
  348. }
  349. }
  350. static const char *error_classes[] = {
  351. "tx-timeout",
  352. "lost-arbitration",
  353. "controller-problem",
  354. "protocol-violation",
  355. "transceiver-status",
  356. "no-acknowledgement-on-tx",
  357. "bus-off",
  358. "bus-error",
  359. "restarted-after-bus-off",
  360. };
  361. static const char *controller_problems[] = {
  362. "rx-overflow",
  363. "tx-overflow",
  364. "rx-error-warning",
  365. "tx-error-warning",
  366. "rx-error-passive",
  367. "tx-error-passive",
  368. "back-to-error-active",
  369. };
  370. static const char *protocol_violation_types[] = {
  371. "single-bit-error",
  372. "frame-format-error",
  373. "bit-stuffing-error",
  374. "tx-dominant-bit-error",
  375. "tx-recessive-bit-error",
  376. "bus-overload",
  377. "active-error",
  378. "error-on-tx",
  379. };
  380. static const char *protocol_violation_locations[] = {
  381. "unspecified",
  382. "unspecified",
  383. "id.28-to-id.21",
  384. "start-of-frame",
  385. "bit-srtr",
  386. "bit-ide",
  387. "id.20-to-id.18",
  388. "id.17-to-id.13",
  389. "crc-sequence",
  390. "reserved-bit-0",
  391. "data-field",
  392. "data-length-code",
  393. "bit-rtr",
  394. "reserved-bit-1",
  395. "id.4-to-id.0",
  396. "id.12-to-id.5",
  397. "unspecified",
  398. "active-error-flag",
  399. "intermission",
  400. "tolerate-dominant-bits",
  401. "unspecified",
  402. "unspecified",
  403. "passive-error-flag",
  404. "error-delimiter",
  405. "crc-delimiter",
  406. "acknowledge-slot",
  407. "end-of-frame",
  408. "acknowledge-delimiter",
  409. "overload-flag",
  410. "unspecified",
  411. "unspecified",
  412. "unspecified",
  413. };
  414. #ifndef ARRAY_SIZE
  415. #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
  416. #endif
  417. static int snprintf_error_data(char *buf, size_t len, uint8_t err,
  418. const char **arr, int arr_len)
  419. {
  420. int i, n = 0, count = 0;
  421. if (!err || len <= 0)
  422. return 0;
  423. for (i = 0; i < arr_len; i++) {
  424. if (err & (1 << i)) {
  425. if (count)
  426. n += snprintf(buf + n, len - n, ",");
  427. n += snprintf(buf + n, len - n, "%s", arr[i]);
  428. count++;
  429. }
  430. }
  431. return n;
  432. }
  433. static int snprintf_error_lostarb(char *buf, size_t len, const struct canfd_frame *cf)
  434. {
  435. if (len <= 0)
  436. return 0;
  437. return snprintf(buf, len, "{at bit %d}", cf->data[0]);
  438. }
  439. static int snprintf_error_ctrl(char *buf, size_t len, const struct canfd_frame *cf)
  440. {
  441. int n = 0;
  442. if (len <= 0)
  443. return 0;
  444. n += snprintf(buf + n, len - n, "{");
  445. n += snprintf_error_data(buf + n, len - n, cf->data[1],
  446. controller_problems,
  447. ARRAY_SIZE(controller_problems));
  448. n += snprintf(buf + n, len - n, "}");
  449. return n;
  450. }
  451. static int snprintf_error_prot(char *buf, size_t len, const struct canfd_frame *cf)
  452. {
  453. int n = 0;
  454. if (len <= 0)
  455. return 0;
  456. n += snprintf(buf + n, len - n, "{{");
  457. n += snprintf_error_data(buf + n, len - n, cf->data[2],
  458. protocol_violation_types,
  459. ARRAY_SIZE(protocol_violation_types));
  460. n += snprintf(buf + n, len - n, "}{");
  461. if (cf->data[3] > 0 &&
  462. cf->data[3] < ARRAY_SIZE(protocol_violation_locations))
  463. n += snprintf(buf + n, len - n, "%s",
  464. protocol_violation_locations[cf->data[3]]);
  465. n += snprintf(buf + n, len - n, "}}");
  466. return n;
  467. }
  468. void snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *cf,
  469. const char* sep)
  470. {
  471. canid_t class, mask;
  472. int i, n = 0, classes = 0;
  473. char *defsep = ",";
  474. if (!(cf->can_id & CAN_ERR_FLAG))
  475. return;
  476. class = cf->can_id & CAN_EFF_MASK;
  477. if (class > (1 << ARRAY_SIZE(error_classes))) {
  478. fprintf(stderr, "Error class %#x is invalid\n", class);
  479. return;
  480. }
  481. if (!sep)
  482. sep = defsep;
  483. for (i = 0; i < ARRAY_SIZE(error_classes); i++) {
  484. mask = 1 << i;
  485. if (class & mask) {
  486. if (classes)
  487. n += snprintf(buf + n, len - n, "%s", sep);
  488. n += snprintf(buf + n, len - n, "%s", error_classes[i]);
  489. if (mask == CAN_ERR_LOSTARB)
  490. n += snprintf_error_lostarb(buf + n, len - n,
  491. cf);
  492. if (mask == CAN_ERR_CRTL)
  493. n += snprintf_error_ctrl(buf + n, len - n, cf);
  494. if (mask == CAN_ERR_PROT)
  495. n += snprintf_error_prot(buf + n, len - n, cf);
  496. classes++;
  497. }
  498. }
  499. if (cf->data[6] || cf->data[7]) {
  500. n += snprintf(buf + n, len - n, "%s", sep);
  501. n += snprintf(buf + n, len - n, "error-counter-tx-rx{{%d}{%d}}",
  502. cf->data[6], cf->data[7]);
  503. }
  504. }