Re: [RFC PATCH v5 3/5] can: dev: add CAN XL support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri. 22 Jul. 2022 at 05:26, Oliver Hartkopp <socketcan@xxxxxxxxxxxx> wrote:
> On 21.07.22 05:13, Vincent Mailhol wrote:
> > On Thu. 21 juil. 2022 at 11:37, Vincent Mailhol
> > <vincent.mailhol@xxxxxxxxx> wrote:
> >> On Wed. 21 Jul. 2022 at 01:43, Oliver Hartkopp <socketcan@xxxxxxxxxxxx> wrote:
>
>
> >>> And even the user space side to handle a mix of CAN frame types is
> >>> pretty simple IMO:
> >>>
> >>> union {
> >>>           struct can_frame cc;
> >>>           struct canfd_frame fd;
> >>>           struct canxl_frame xl;
> >>> } can;
> >>
> >> Do you want to add this union in the kernel uapi or is it just a
> >> userland example?
> >
> > More brainstorming. If we want to introduce a generic can structure in
> > linux/can.h, we could  do:
> >
> > struct canxl_frame {
> >          canid_t prio;  /* 11 bit priority for arbitration (canid_t) */
> >          __u8    xl_flags; /* additional flags for CAN XL */
> >          __u8    fd_flags; /* CAN(-FD) flags */
> >          __u16   len;   /* frame payload length in byte */
> >          __u32   af;    /* acceptance field */
> >          __u8    sdt;   /* SDU (service data unit) type */
> >          __u8    __res0;  /* reserved / padding */
> >          __u8    __res1;  /* reserved / padding */
> >          __u8    __res2;  /* reserved / padding */
> >          __u8    data[CANXL_MAX_DLEN] __attribute__((aligned(8)));
> > };
> >
> > union can_generic_frame {
> >           struct {
> >                  union {
> >                         canid_t can_id;
> >                         canid_t prio;
> >                  };
> >                  union {
> >                          __u16 type;
> >                           struct {
> >                                  __u8 xl_flags;
> >                                  __u8 fd_flags;
> >                          } __attribute__((packed));
> >                  } __attribute__((packed));
> >           };
> >           struct can_frame cc;
> >           struct canfd_frame fd;
> >           struct canxl_frame xl;
> > };
> >
> > #define CANXL_XLF 0x80 /* apply to canxl_frame::xl_flags */
> >
> > #define CAN_TYPE_CC 0
> > #ifdef __LITTLE_ENDIAN
> > #define CAN_TYPE_FD (CANFD_FDF << 8)
> > #define CAN_TYPE_XL (CANXL_XLF)
> > #else /* __BIG_ENDIAN */
> > #define CAN_TYPE_FD (CANFD_FDF)
> > #define CAN_TYPE_XL (CANXL_XLF << 8)
> > #endif
> >
> > #define CAN_TYPE_MASK (CAN_TYPE_FD | CAN_TYPE_XL)
> >
> > Because can_generic_frame::type overlaps with the can(fd)_frame::len,
> > it will contain garbage and thus it is necessary to mask it with
> > CAN_TYPE_MASK.
> > The CANFD_FDF is only set in the rx path. In the tx path it is simply
> > ignored. This done, we can use it as below when *receiving* can
> > frames:
>
> No problem to set CANFD_FDF in raw_sendmsg() when we process a CAN FD
> frame in the tx path ...

ACK.

> >
> > int foo()
> > {
> >    union can_generic_frame can;
> >
> >    /* receive a frame */
> >
> >    switch (can.type & CAN_TYPE_MASK) {
> >    case CAN_TYPE_CC:
> >      printf("Received classical CAN Frame\n");
> >      break;
> >
> >    case CAN_TYPE_FD:
> >      printf("Received CAN FD Frame\n");
> >      break;
> >
> >    case CAN_TYPE_XL:
> >      printf("Received CAN XL Frame\n");
> >      break;
> >
> >    default:
> >      fprintf(stderr, "Unknown type: %x\n", can.type & CAN_TYPE_MASK);
> >    }
> >
> >    return EXIT_SUCCESS;
> > }
> >
>
> If you just want to get rid of the nbytes checking and we make sure
> CANFD_FDF is properly set in the future we are not far from such an easy
> check - even without moving the sdt element or endian magic:

ACK. I did not like the mix between the CANXL_XLF and the CAN*_MTU
checks. Would be great to have a consistent method to check the type.

>
> if (can.xl_flags & CANXL_XLF) {
>      printf("Received CAN XL Frame\n");
> } else if (can.fd_flags & CANFD_FDF) {
>      printf("Received CAN FD Frame\n");
> } else {
>      printf("Received classical CAN Frame\n");
> }

ACK. I like this approach :)



[Index of Archives]     [Automotive Discussions]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]     [CAN Bus]

  Powered by Linux