History

can: gw: support modification of Classical CAN DLCs

Add support for data length code modifications for Classical CAN. The netlink configuration interface always allowed to pass any value that fits into a byte, therefore only the modification process had to be extended to handle the raw DLC represenation of Classical CAN frames. When a DLC value from 0 .. F is provided for Classical CAN frame modifications the 'len' value is modified as-is with the exception that potentially existing 9 .. F DLC values in the len8_dlc element are moved to the 'len' element for the modification operation by mod_retrieve_ccdlc(). After the modification the Classical CAN frame DLC information is brought back into the correct format by mod_store_ccdlc() which is filling 'len' and 'len8_dlc' accordingly.

Oliver Hartkopp committed 5 years ago

Commit 94c23091 parent 396b3ce2 files · +72 −10Browse files

Unified · Split

2 files
  1. include/uapi/linux/can/gw.h +2 −2
  2. net/can/gw.c +70 −8
include/uapi/linux/can/gw.h+2−2
@@ -98,8 +98,8 @@ enum { · 97 unmodified lines
9898
9999 /* CAN frame elements that are affected by curr. 3 CAN frame modifications */
100100 #define CGW_MOD_ID 0x01
101−#define CGW_MOD_DLC 0x02 /* contains the data length in bytes */
102−#define CGW_MOD_LEN CGW_MOD_DLC /* CAN FD length representation */
101+#define CGW_MOD_DLC 0x02 /* Classical CAN data length code */
102+#define CGW_MOD_LEN CGW_MOD_DLC /* CAN FD (plain) data length */
103103 #define CGW_MOD_DATA 0x04
104104 #define CGW_MOD_FLAGS 0x08 /* CAN FD flags */
105105
net/can/gw.c+70−8
@@ -199,6 +199,68 @@ static void mod_set_fddata(struct canfd_frame *cf, struct cf_mod *mod) · 198 unmodified lines
199199 memcpy(cf->data, mod->modframe.set.data, CANFD_MAX_DLEN);
200200 }
201201
202+/* retrieve valid CC DLC value and store it into 'len' */
203+static void mod_retrieve_ccdlc(struct canfd_frame *cf)
204+{
205+ struct can_frame *ccf = (struct can_frame *)cf;
206+
207+ /* len8_dlc is only valid if len == CAN_MAX_DLEN */
208+ if (ccf->len != CAN_MAX_DLEN)
209+ return;
210+
211+ /* do we have a valid len8_dlc value from 9 .. 15 ? */
212+ if (ccf->len8_dlc > CAN_MAX_DLEN && ccf->len8_dlc <= CAN_MAX_RAW_DLC)
213+ ccf->len = ccf->len8_dlc;
214+}
215+
216+/* convert valid CC DLC value in 'len' into struct can_frame elements */
217+static void mod_store_ccdlc(struct canfd_frame *cf)
218+{
219+ struct can_frame *ccf = (struct can_frame *)cf;
220+
221+ /* clear potential leftovers */
222+ ccf->len8_dlc = 0;
223+
224+ /* plain data length 0 .. 8 - that was easy */
225+ if (ccf->len <= CAN_MAX_DLEN)
226+ return;
227+
228+ /* potentially broken values are catched in can_can_gw_rcv() */
229+ if (ccf->len > CAN_MAX_RAW_DLC)
230+ return;
231+
232+ /* we have a valid dlc value from 9 .. 15 in ccf->len */
233+ ccf->len8_dlc = ccf->len;
234+ ccf->len = CAN_MAX_DLEN;
235+}
236+
237+static void mod_and_ccdlc(struct canfd_frame *cf, struct cf_mod *mod)
238+{
239+ mod_retrieve_ccdlc(cf);
240+ mod_and_len(cf, mod);
241+ mod_store_ccdlc(cf);
242+}
243+
244+static void mod_or_ccdlc(struct canfd_frame *cf, struct cf_mod *mod)
245+{
246+ mod_retrieve_ccdlc(cf);
247+ mod_or_len(cf, mod);
248+ mod_store_ccdlc(cf);
249+}
250+
251+static void mod_xor_ccdlc(struct canfd_frame *cf, struct cf_mod *mod)
252+{
253+ mod_retrieve_ccdlc(cf);
254+ mod_xor_len(cf, mod);
255+ mod_store_ccdlc(cf);
256+}
257+
258+static void mod_set_ccdlc(struct canfd_frame *cf, struct cf_mod *mod)
259+{
260+ mod_set_len(cf, mod);
261+ mod_store_ccdlc(cf);
262+}
263+
202264 static void canframecpy(struct canfd_frame *dst, struct can_frame *src)
203265 {
204266 /* Copy the struct members separately to ensure that no uninitialized
@@ -842,8 +904,8 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, · 637 unmodified lines
842904 if (mb.modtype & CGW_MOD_ID)
843905 mod->modfunc[modidx++] = mod_and_id;
844906
845− if (mb.modtype & CGW_MOD_LEN)
846− mod->modfunc[modidx++] = mod_and_len;
907+ if (mb.modtype & CGW_MOD_DLC)
908+ mod->modfunc[modidx++] = mod_and_ccdlc;
847909
848910 if (mb.modtype & CGW_MOD_DATA)
849911 mod->modfunc[modidx++] = mod_and_data;
@@ -858,8 +920,8 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, · 8 unmodified lines
858920 if (mb.modtype & CGW_MOD_ID)
859921 mod->modfunc[modidx++] = mod_or_id;
860922
861− if (mb.modtype & CGW_MOD_LEN)
862− mod->modfunc[modidx++] = mod_or_len;
923+ if (mb.modtype & CGW_MOD_DLC)
924+ mod->modfunc[modidx++] = mod_or_ccdlc;
863925
864926 if (mb.modtype & CGW_MOD_DATA)
865927 mod->modfunc[modidx++] = mod_or_data;
@@ -874,8 +936,8 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, · 8 unmodified lines
874936 if (mb.modtype & CGW_MOD_ID)
875937 mod->modfunc[modidx++] = mod_xor_id;
876938
877− if (mb.modtype & CGW_MOD_LEN)
878− mod->modfunc[modidx++] = mod_xor_len;
939+ if (mb.modtype & CGW_MOD_DLC)
940+ mod->modfunc[modidx++] = mod_xor_ccdlc;
879941
880942 if (mb.modtype & CGW_MOD_DATA)
881943 mod->modfunc[modidx++] = mod_xor_data;
@@ -890,8 +952,8 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, · 8 unmodified lines
890952 if (mb.modtype & CGW_MOD_ID)
891953 mod->modfunc[modidx++] = mod_set_id;
892954
893− if (mb.modtype & CGW_MOD_LEN)
894− mod->modfunc[modidx++] = mod_set_len;
955+ if (mb.modtype & CGW_MOD_DLC)
956+ mod->modfunc[modidx++] = mod_set_ccdlc;
895957
896958 if (mb.modtype & CGW_MOD_DATA)
897959 mod->modfunc[modidx++] = mod_set_data;