+static int sprintf_error_prot(char *buf, size_t len, struct can_frame *cf)
+{
+ int n = 0;
+
+ if (len <= 0)
+ return 0;
+
+ n += snprintf(buf + n, len - n, "{{");
+ n += sprintf_error_data(buf + n, len - n, cf->data[2],
+ protocol_violation_types,
+ ARRAY_SIZE(protocol_violation_types));
+ n += snprintf(buf + n, len - n, "}{");
+ if (cf->data[3] > 0 &&
+ cf->data[3] < ARRAY_SIZE(protocol_violation_locations))
+ n += snprintf(buf + n, len - n, "%s",
+ protocol_violation_locations[cf->data[3]]);
+ n += snprintf(buf + n, len - n, "}}");
+
+ return n;
+}
+
+void snprintf_can_error_frame(char *buf, size_t len, struct can_frame *cf,
+ char* sep)
+{
+ canid_t class, mask;
+ int i, n = 0, classes = 0;
+ char *defsep = ",";
+
+ if (!(cf->can_id & CAN_ERR_FLAG))
+ return;
+
+ class = cf->can_id & CAN_EFF_MASK;
+ if (class > (1 << ARRAY_SIZE(error_classes))) {
+ fprintf(stderr, "Error class %#x is invalid\n", class);
+ return;
+ }
+
+ if (!sep)
+ sep = defsep;
+
+ for (i = 0; i < ARRAY_SIZE(error_classes); i++) {
+ mask = 1 << i;
+ if (class & mask) {
+ if (classes)
+ n += snprintf(buf + n, len - n, "%s", sep);
+ n += snprintf(buf + n, len - n, "%s", error_classes[i]);
+ if (mask == CAN_ERR_LOSTARB)
+ n += sprintf_error_lostarb(buf + n, len - n,
+ cf);
+ if (mask == CAN_ERR_CRTL)
+ n += sprintf_error_ctrl(buf + n, len - n, cf);
+ if (mask == CAN_ERR_PROT)
+ n += sprintf_error_prot(buf + n, len - n, cf);
+ classes++;
+ }
+ }
+
+ if (cf->data[6] || cf->data[7]) {
+ n += snprintf(buf + n, len - n, "%s", sep);
+ n += snprintf(buf + n, len - n, "error-counter-tx-rx{{%d}{%d}}",
+ cf->data[6], cf->data[7]);
+ }
+}