@@ -123,12 +123,11 @@ def start(self, handler: Media.ReceivedFramesHandler, no_automatic_retransmissio
123123 def configure_acceptance_filters (self , configuration : typing .Sequence [FilterConfiguration ]) -> None :
124124 if self ._closed :
125125 raise pycyphal .transport .ResourceClosedError (repr (self ))
126- _logger .info (
127- "%s FIXME: acceptance filter configuration is not yet implemented; please submit patches! "
128- "Requested configuration: %s" ,
129- self ,
130- ", " .join (map (str , configuration )),
131- )
126+
127+ try :
128+ self ._sock .setsockopt (socket .SOL_CAN_RAW , socket .CAN_RAW_FILTER , _pack_filters (configuration )) # type: ignore
129+ except OSError as error :
130+ _logger .error ("Setting CAN filters failed: %s" , error )
132131
133132 async def send (self , frames : typing .Iterable [Envelope ], monotonic_deadline : float ) -> int :
134133 num_sent = 0
@@ -366,3 +365,28 @@ def _make_socket(iface_name: str, can_fd: bool, native_frame_size: int) -> socke
366365 raise
367366
368367 return s
368+
369+
370+ def _pack_filters (configuration : typing .Sequence [FilterConfiguration ]) -> bytes :
371+ """Convert a list of filters into a packed structure suitable for setsockopt().
372+ Inspired by python-can sources.
373+ :param configuration: list of CAN filters
374+ :type configuration: typing.Sequence[FilterConfiguration]
375+ :return: packed structure suitable for setsockopt()
376+ :rtype: bytes
377+ """
378+
379+ can_filter_fmt = f"={ 2 * len (configuration )} I"
380+ filter_data = []
381+ for can_filter in configuration :
382+ can_id = can_filter .identifier
383+ can_mask = can_filter .mask
384+ if can_filter .format is not None :
385+ # Match on either 11-bit OR 29-bit messages instead of both
386+ can_mask |= _CAN_EFF_FLAG # Not using socket.CAN_EFF_FLAG because it is negative on 32 bit platforms
387+ if can_filter .format == FrameFormat .EXTENDED :
388+ can_id |= _CAN_EFF_FLAG
389+ filter_data .append (can_id )
390+ filter_data .append (can_mask )
391+
392+ return struct .pack (can_filter_fmt , * filter_data )
0 commit comments