]> rtime.felk.cvut.cz Git - socketcan-devel.git/commitdiff
Added CRC8 profiles to handle additional data for checksum generation.
authorhartkopp <hartkopp@030b6a49-0b11-0410-94ab-b0dab22257f2>
Fri, 16 Apr 2010 08:46:17 +0000 (08:46 +0000)
committerhartkopp <hartkopp@030b6a49-0b11-0410-94ab-b0dab22257f2>
Fri, 16 Apr 2010 08:46:17 +0000 (08:46 +0000)
git-svn-id: svn://svn.berlios.de//socketcan/trunk@1167 030b6a49-0b11-0410-94ab-b0dab22257f2

can-utils/cangw.c
kernel/2.6/include/socketcan/can/gw.h
kernel/2.6/net/can/gw.c

index 8f99f9b6b4eb0d006ba10bade552cba8c6f3c0d1..4c7140ce0417cea432766cb594ef9b7fd7dea340 100644 (file)
@@ -138,6 +138,35 @@ void print_cs_xor(struct cgw_csum_xor *cs_xor)
               cs_xor->result_idx, cs_xor->init_xor_val);
 }
 
+void print_cs_crc8_profile(struct cgw_csum_crc8 *cs_crc8)
+{
+       int i;
+
+       printf("-p %d:", cs_crc8->profile);
+
+       switch (cs_crc8->profile) {
+
+       case  CGW_CRC8PRF_1U8:
+
+               printf("%02X", cs_crc8->profile_data[0]);
+               break;
+
+       case  CGW_CRC8PRF_16U8:
+
+               for (i = 0; i < 16; i++)
+                       printf("%02X", cs_crc8->profile_data[i]);
+               break;
+
+       case  CGW_CRC8PRF_SFFID_XOR:
+               break;
+
+       default:
+               printf("<unknown profile #%d>", cs_crc8->profile);
+       }
+
+       printf(" ");
+}
+
 void print_cs_crc8(struct cgw_csum_crc8 *cs_crc8)
 {
        int i;
@@ -151,6 +180,9 @@ void print_cs_crc8(struct cgw_csum_crc8 *cs_crc8)
                printf("%02X", cs_crc8->crctab[i]);
 
        printf(" ");
+
+       if (cs_crc8->profile != CGW_CRC8PRF_UNSPEC)
+               print_cs_crc8_profile(cs_crc8);
 }
 
 void print_usage(char *prg)
@@ -166,6 +198,9 @@ void print_usage(char *prg)
        fprintf(stderr, "           -e (echo sent frames - recommended on vcanx)\n");
        fprintf(stderr, "           -f <filter> (set CAN filter)\n");
        fprintf(stderr, "           -m <mod> (set frame modifications)\n");
+       fprintf(stderr, "           -x <from_idx>:<to_idx>:<result_idx>:<init_xor_val> (XOR checksum)\n");
+       fprintf(stderr, "           -c <from>:<to>:<result>:<init_val>:<xor_val>:<crctab[256]> (CRC8 cs)\n");
+       fprintf(stderr, "           -p <profile>:[<profile_data>] (CRC8 checksum profile & parameters)\n");
        fprintf(stderr, "\nValues are given and expected in hexadecimal values. Leading 0s can be omitted.\n");
        fprintf(stderr, "\n");
        fprintf(stderr, "<filter> is a <value>:<mask> CAN identifier filter\n");
@@ -182,6 +217,11 @@ void print_usage(char *prg)
        fprintf(stderr, "Example:\n");
        fprintf(stderr, "%s -A -s can0 -d vcan3 -e -f 123:C00007FF -m SET:IL:333.4.1122334455667788\n", prg);
        fprintf(stderr, "\n");
+       fprintf(stderr, "Supported CRC 8 profiles:\n");
+       fprintf(stderr, "Profile '%d' (1U8)       - add one additional u8 value\n", CGW_CRC8PRF_1U8);
+       fprintf(stderr, "Profile '%d' (16U8)      - add u8 value from table[16] indexed by (data[1] & 0xF)\n", CGW_CRC8PRF_16U8);
+       fprintf(stderr, "Profile '%d' (SFFID_XOR) - add u8 value (can_id & 0xFF) ^ (can_id >> 8 & 0xFF)\n", CGW_CRC8PRF_SFFID_XOR);
+       fprintf(stderr, "\n");
 }
 
 int b64hex(char *asc, unsigned char *bin, int len)
@@ -195,6 +235,45 @@ int b64hex(char *asc, unsigned char *bin, int len)
        return 0;
 }
 
+int parse_crc8_profile(char *optarg, struct cgw_csum_crc8 *crc8)
+{
+       int ret = 1;
+       char *ptr;
+
+       if (sscanf(optarg, "%hhd:", &crc8->profile) != 1)
+               return ret;
+
+       switch (crc8->profile) {
+
+       case  CGW_CRC8PRF_1U8:
+
+               if (sscanf(optarg, "%hhd:%2hhx", &crc8->profile, &crc8->profile_data[0]) == 2)
+                       ret = 0;
+
+               break;
+
+       case  CGW_CRC8PRF_16U8:
+
+               ptr = strchr(optarg, ':');
+
+               /* check if length contains 16 base64 hex values */
+               if (ptr != NULL &&
+                   strlen(ptr) == strlen(":00112233445566778899AABBCCDDEEFF") &&
+                   b64hex(ptr+1, (unsigned char *)&crc8->profile_data[0], 16) == 0)
+                       ret = 0;
+
+               break;
+
+       case  CGW_CRC8PRF_SFFID_XOR:
+
+               /* no additional parameters needed */
+               ret = 0;
+               break;
+       }
+
+       return ret;
+}
+
 int parse_mod(char *optarg, struct modattr *modmsg)
 {
        char *ptr, *nptr;
@@ -469,8 +548,10 @@ int main(int argc, char **argv)
        int i;
 
        memset(&req, 0, sizeof(req));
+       memset(&cs_xor, 0, sizeof(cs_xor));
+       memset(&cs_crc8, 0, sizeof(cs_crc8));
 
-       while ((opt = getopt(argc, argv, "ADFLs:d:tef:c:x:m:?")) != -1) {
+       while ((opt = getopt(argc, argv, "ADFLs:d:tef:c:p:x:m:?")) != -1) {
                switch (opt) {
 
                case 'A':
@@ -545,6 +626,13 @@ int main(int argc, char **argv)
                        }
                        break;
 
+               case 'p':
+                       if (parse_crc8_profile(optarg, &cs_crc8)) {
+                               printf("Bad CRC8 profile definition '%s'.\n", optarg);
+                               exit(1);
+                       }
+                       break;
+
                case 'm':
                        /* may be triggered by each of the CGW_MOD_FUNCS functions */
                        if ((modidx < CGW_MOD_FUNCS) && (err = parse_mod(optarg, &modmsg[modidx++]))) {
index 2cf3fb7280f63e4d3466536547800ef8379bfaf3..d5d22fa5d47b438af97ff6f4cdddb94b7a53dec5 100644 (file)
@@ -87,12 +87,25 @@ struct cgw_csum_crc8 {
        __u8 init_crc_val;
        __u8 final_xor_val;
        __u8 crctab[256];
+       __u8 profile;
+       __u8 profile_data[20];
 } __attribute__ ((packed));
 
 /* length of checksum operation parameters. idx = index in CAN frame data[] */
 #define CGW_CS_XOR_LEN  sizeof(struct cgw_csum_xor)
 #define CGW_CS_CRC8_LEN  sizeof(struct cgw_csum_crc8)
 
+/* CRC8 profiles (compute CRC for additional data elements - see below) */
+enum {
+       CGW_CRC8PRF_UNSPEC,
+       CGW_CRC8PRF_1U8,        /* compute one additional u8 value */
+       CGW_CRC8PRF_16U8,       /* u8 value table indexed by data[1] & 0xF */
+       CGW_CRC8PRF_SFFID_XOR,  /* (can_id & 0xFF) ^ (can_id >> 8 & 0xFF) */
+       __CGW_CRC8PRF_MAX
+};
+
+#define CGW_CRC8PRF_MAX (__CGW_CRC8PRF_MAX - 1)
+
 /*
  * CAN rtnetlink attribute contents in detail
  *
@@ -124,7 +137,7 @@ struct cgw_csum_crc8 {
  *
  * can_frame.data[ result_idx ] = xor
  *
- * CGW_CS_CRC8 (length 261 bytes):
+ * CGW_CS_CRC8 (length 282 bytes):
  * Set a CRC8 value into data[result-idx] using a given 256 byte CRC8 table,
  * a given initial value and a defined input data[start-idx] .. data[end-idx].
  * Finally the result value is XOR'ed with the final_xor_val.
@@ -138,6 +151,13 @@ struct cgw_csum_crc8 {
  *
  * can_frame.data[ result_idx ] = crc ^ final_xor_val
  *
+ * The calculated CRC may contain additional source data elements that can be
+ * defined in the handling of 'checksum profiles' e.g. shown in AUTOSAR specs
+ * like http://www.autosar.org/download/R4.0/AUTOSAR_SWS_E2ELibrary.pdf
+ * E.g. the profile_data[] may contain additional u8 values (called DATA_IDs)
+ * that are used depending on counter values inside the CAN frame data[].
+ * So far only three profiles have been implemented for illustration.
+ *
  * Remark: In general the attribute data is a linear buffer.
  *         Beware of sending unpacked or aligned structs!
  */
index 5ec8fa8f51af9c67d35ab526b0e8590dc4515ccd..74d51f5cb5e1f88b4700b9984d3a9eb979d51aae 100644 (file)
@@ -264,6 +264,23 @@ static void cgw_csum_crc8_rel(struct can_frame *cf, struct cgw_csum_crc8 *crc8)
                        crc = crc8->crctab[crc^cf->data[i]];
        }
 
+       switch (crc8->profile) {
+
+       case CGW_CRC8PRF_1U8:
+               crc = crc8->crctab[crc^crc8->profile_data[0]];
+               break;
+
+       case  CGW_CRC8PRF_16U8:
+               crc = crc8->crctab[crc^crc8->profile_data[cf->data[1] & 0xF]];
+               break;
+
+       case CGW_CRC8PRF_SFFID_XOR:
+               crc = crc8->crctab[crc^(cf->can_id & 0xFF)^
+                                  (cf->can_id >> 8 & 0xFF)];
+               break;
+
+       }
+
        cf->data[crc8->result_idx] = crc^crc8->final_xor_val;
 }
 
@@ -275,6 +292,22 @@ static void cgw_csum_crc8_pos(struct can_frame *cf, struct cgw_csum_crc8 *crc8)
        for (i = crc8->from_idx; i <= crc8->to_idx; i++)
                crc = crc8->crctab[crc^cf->data[i]];
 
+       switch (crc8->profile) {
+
+       case CGW_CRC8PRF_1U8:
+               crc = crc8->crctab[crc^crc8->profile_data[0]];
+               break;
+
+       case  CGW_CRC8PRF_16U8:
+               crc = crc8->crctab[crc^crc8->profile_data[cf->data[1] & 0xF]];
+               break;
+
+       case CGW_CRC8PRF_SFFID_XOR:
+               crc = crc8->crctab[crc^(cf->can_id & 0xFF)^
+                                  (cf->can_id >> 8 & 0xFF)];
+               break;
+       }
+
        cf->data[crc8->result_idx] = crc^crc8->final_xor_val;
 }
 
@@ -286,6 +319,22 @@ static void cgw_csum_crc8_neg(struct can_frame *cf, struct cgw_csum_crc8 *crc8)
        for (i = crc8->from_idx; i >= crc8->to_idx; i--)
                crc = crc8->crctab[crc^cf->data[i]];
 
+       switch (crc8->profile) {
+
+       case CGW_CRC8PRF_1U8:
+               crc = crc8->crctab[crc^crc8->profile_data[0]];
+               break;
+
+       case  CGW_CRC8PRF_16U8:
+               crc = crc8->crctab[crc^crc8->profile_data[cf->data[1] & 0xF]];
+               break;
+
+       case CGW_CRC8PRF_SFFID_XOR:
+               crc = crc8->crctab[crc^(cf->can_id & 0xFF)^
+                                  (cf->can_id >> 8 & 0xFF)];
+               break;
+       }
+
        cf->data[crc8->result_idx] = crc^crc8->final_xor_val;
 }