diff --git a/include/net/if.h b/include/net/if.h index e54c1b81ec..0dde170c00 100644 --- a/include/net/if.h +++ b/include/net/if.h @@ -149,6 +149,20 @@ struct can_ioctl_data_s uint16_t data_samplep; /* Data phase sample point % */ }; +/* Structure passed to add or remove hardware-level CAN ID filters + * SIOCxCANSTDFILTER / SIOCxCANEXTFILTER ioctl commands. + */ + +struct can_ioctl_filter_s +{ + uint32_t fid1; /* 11- or 29-bit ID (context dependent). For dual match or + * for the lower address in a range of addresses */ + uint32_t fid2; /* 11- or 29-bit ID. For dual match, address mask or for + * upper address in address range */ + uint8_t ftype; /* See CAN_FILTER_* definitions */ + uint8_t fprio; /* See CAN_MSGPRIO_* definitions */ +}; + /* There are two forms of the I/F request structure. * One for IPv6 and one for IPv4. * Notice that they are (and must be) cast compatible and really different @@ -159,21 +173,22 @@ struct can_ioctl_data_s struct lifreq { - char lifr_name[IFNAMSIZ]; /* Network device name (e.g. "eth0") */ - int16_t lifr_ifindex; /* Interface index */ + char lifr_name[IFNAMSIZ]; /* Network device name (e.g. "eth0") */ + int16_t lifr_ifindex; /* Interface index */ union { - struct sockaddr_storage lifru_addr; /* IP Address */ - struct sockaddr_storage lifru_dstaddr; /* P-to-P Address */ - struct sockaddr_storage lifru_broadaddr; /* Broadcast address */ - struct sockaddr_storage lifru_netmask; /* Netmask */ - struct sockaddr lifru_hwaddr; /* MAC address */ - int lifru_count; /* Number of devices */ - int lifru_mtu; /* MTU size */ - uint8_t lifru_flags; /* Interface flags */ - struct mii_ioctl_notify_s llfru_mii_notify; /* PHY event notification */ - struct mii_ioctl_data_s lifru_mii_data; /* MII request data */ - struct can_ioctl_data_s lifru_can_data; /* CAN bitrate request data */ + struct sockaddr_storage lifru_addr; /* IP Address */ + struct sockaddr_storage lifru_dstaddr; /* P-to-P Address */ + struct sockaddr_storage lifru_broadaddr; /* Broadcast address */ + struct sockaddr_storage lifru_netmask; /* Netmask */ + struct sockaddr lifru_hwaddr; /* MAC address */ + int lifru_count; /* Number of devices */ + int lifru_mtu; /* MTU size */ + uint8_t lifru_flags; /* Interface flags */ + struct mii_ioctl_notify_s llfru_mii_notify; /* PHY event notification */ + struct mii_ioctl_data_s lifru_mii_data; /* MII request data */ + struct can_ioctl_data_s lifru_can_data; /* CAN bitrate request data */ + struct can_ioctl_filter_s lifru_can_filter; /* CAN filter request data */ } lifr_ifru; }; @@ -196,36 +211,37 @@ struct lifreq struct lifconf { - size_t lifc_len; /* Size of buffer */ + size_t lifc_len; /* Size of buffer */ union { - FAR char *lifcu_buf; /* Buffer address */ - FAR struct lifreq *lifcu_req; /* Array of ifreq structures */ + FAR char *lifcu_buf; /* Buffer address */ + FAR struct lifreq *lifcu_req; /* Array of ifreq structures */ } lifc_ifcu; }; -#define lifc_buf lifc_ifcu.lifcu_buf /* Buffer address */ -#define lifc_req lifc_ifcu.lifcu_req /* Array of ifreq structures */ +#define lifc_buf lifc_ifcu.lifcu_buf /* Buffer address */ +#define lifc_req lifc_ifcu.lifcu_req /* Array of ifreq structures */ /* This is the I/F request that should be used with IPv4. */ struct ifreq { - char ifr_name[IFNAMSIZ]; /* Network device name (e.g. "eth0") */ - int16_t ifr_ifindex; /* Interface index */ + char ifr_name[IFNAMSIZ]; /* Network device name (e.g. "eth0") */ + int16_t ifr_ifindex; /* Interface index */ union { - struct sockaddr ifru_addr; /* IP Address */ - struct sockaddr ifru_dstaddr; /* P-to-P Address */ - struct sockaddr ifru_broadaddr; /* Broadcast address */ - struct sockaddr ifru_netmask; /* Netmask */ - struct sockaddr ifru_hwaddr; /* MAC address */ - int ifru_count; /* Number of devices */ - int ifru_mtu; /* MTU size */ - uint8_t ifru_flags; /* Interface flags */ - struct mii_ioctl_notify_s ifru_mii_notify; /* PHY event notification */ - struct mii_ioctl_data_s ifru_mii_data; /* MII request data */ - struct can_ioctl_data_s ifru_can_data; /* CAN bitrate request data */ + struct sockaddr ifru_addr; /* IP Address */ + struct sockaddr ifru_dstaddr; /* P-to-P Address */ + struct sockaddr ifru_broadaddr; /* Broadcast address */ + struct sockaddr ifru_netmask; /* Netmask */ + struct sockaddr ifru_hwaddr; /* MAC address */ + int ifru_count; /* Number of devices */ + int ifru_mtu; /* MTU size */ + uint8_t ifru_flags; /* Interface flags */ + struct mii_ioctl_notify_s ifru_mii_notify; /* PHY event notification */ + struct mii_ioctl_data_s ifru_mii_data; /* MII request data */ + struct can_ioctl_data_s ifru_can_data; /* CAN bitrate request data */ + struct can_ioctl_filter_s ifru_can_filter; /* CAN filter request data */ } ifr_ifru; }; @@ -248,7 +264,7 @@ struct ifreq struct ifconf { - size_t ifc_len; /* Size of buffer */ + size_t ifc_len; /* Size of buffer */ union { FAR char *ifcu_buf; /* Buffer address */ diff --git a/include/netpacket/can.h b/include/netpacket/can.h index 775e0dd05f..1d1f730cdc 100644 --- a/include/netpacket/can.h +++ b/include/netpacket/can.h @@ -82,6 +82,22 @@ #define CAN_RAW_TX_DEADLINE (__SO_PROTOCOL + 6) /* Abort frame when deadline passed */ +/* CAN filter support (Hardware level filtering) ****************************/ + +/* Some CAN hardware supports a notion of prioritizing messages that match + * filters. Only two priority levels are currently supported and are encoded + * as defined below: + */ + +#define CAN_MSGPRIO_LOW 0 +#define CAN_MSGPRIO_HIGH 1 + +/* Filter type. Not all CAN hardware will support all filter types. */ + +#define CAN_FILTER_MASK 0 /* Address match under a mask */ +#define CAN_FILTER_DUAL 1 /* Dual address match */ +#define CAN_FILTER_RANGE 2 /* Match a range of addresses */ + /**************************************************************************** * Public Types ****************************************************************************/ diff --git a/include/nuttx/net/ioctl.h b/include/nuttx/net/ioctl.h index 450e7522f8..6dcec0f283 100644 --- a/include/nuttx/net/ioctl.h +++ b/include/nuttx/net/ioctl.h @@ -112,8 +112,12 @@ /* SocketCAN ****************************************************************/ -#define SIOCGCANBITRATE _SIOC(0x002C) /* Get bitrate from a CAN controller */ -#define SIOCSCANBITRATE _SIOC(0x002D) /* Set bitrate of a CAN controller */ +#define SIOCGCANBITRATE _SIOC(0x002C) /* Get bitrate from a CAN controller */ +#define SIOCSCANBITRATE _SIOC(0x002D) /* Set bitrate of a CAN controller */ +#define SIOCACANEXTFILTER _SIOC(0x002E) /* Add hardware-level exteneded ID filter */ +#define SIOCDCANEXTFILTER _SIOC(0x002F) /* Delete hardware-level exteneded ID filter */ +#define SIOCACANSTDFILTER _SIOC(0x0030) /* Add hardware-level standard ID filter */ +#define SIOCDCANSTDFILTER _SIOC(0x0031) /* Delete hardware-level standard ID filter */ /**************************************************************************** * Public Type Definitions diff --git a/net/can/Kconfig b/net/can/Kconfig index 85c77c078e..9913ba8a6c 100644 --- a/net/can/Kconfig +++ b/net/can/Kconfig @@ -31,7 +31,7 @@ config NET_CAN_HAVE_ERRORS default n config CAN_CONNS - int "Number of CAN connections" + int "Max number of CAN socket connections" default 4 ---help--- Maximum number of CAN connections (all tasks). diff --git a/net/netdev/Kconfig b/net/netdev/Kconfig index 6944f5d2e5..d04b7a38ce 100644 --- a/net/netdev/Kconfig +++ b/net/netdev/Kconfig @@ -24,6 +24,15 @@ config NETDEV_CAN_BITRATE_IOCTL ---help--- Enable support for ioctl() commands to change CAN bitrate +config NETDEV_CAN_FILTER_IOCTL + bool "Enable CAN filter ioctl()" + default n + select NETDEV_IOCTL + depends on NET_CAN + ---help--- + Enable support for ioctl() commands to add/remove CAN hardware-level + filters (NOTE: Not supported by all drivers) + config NETDEV_WIRELESS_IOCTL bool "Enable Wireless ioctl()" default n diff --git a/net/netdev/netdev_ioctl.c b/net/netdev/netdev_ioctl.c index e3243be15c..033db500a4 100644 --- a/net/netdev/netdev_ioctl.c +++ b/net/netdev/netdev_ioctl.c @@ -1072,7 +1072,7 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, if (dev && dev->d_ioctl) { struct can_ioctl_data_s *can_bitrate_data = - &req->ifr_ifru.ifru_can_data; + &req->ifr_ifru.ifru_can_data; ret = dev->d_ioctl(dev, cmd, (unsigned long)(uintptr_t)can_bitrate_data); } @@ -1080,6 +1080,24 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, break; #endif +#if defined(CONFIG_NETDEV_IOCTL) && defined(CONFIG_NETDEV_CAN_FILTER_IOCTL) + case SIOCACANEXTFILTER: /* Add an extended-ID filter */ + case SIOCDCANEXTFILTER: /* Delete an extended-ID filter */ + case SIOCACANSTDFILTER: /* Add a standard-ID filter */ + case SIOCDCANSTDFILTER: /* Delete a standard-ID filter */ + { + dev = netdev_ifr_dev(req); + if (dev && dev->d_ioctl) + { + struct can_ioctl_filter_s *can_filter = + &req->ifr_ifru.ifru_can_filter; + ret = dev->d_ioctl(dev, cmd, + (unsigned long)(uintptr_t)can_filter); + } + } + break; +#endif + #ifdef CONFIG_NETDEV_IFINDEX case SIOCGIFNAME: /* Get interface name */ {