@@ -121,6 +121,36 @@ class SocketCANTest(unittest.TestCase):
121121 interface = 'vcan0'
122122 bufsize = 128
123123
124+ """The CAN frame structure is defined in <linux/can.h>:
125+
126+ struct can_frame {
127+ canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
128+ __u8 can_dlc; /* data length code: 0 .. 8 */
129+ __u8 data[8] __attribute__((aligned(8)));
130+ };
131+ """
132+ can_frame_fmt = "=IB3x8s"
133+ can_frame_size = struct .calcsize (can_frame_fmt )
134+
135+ """The Broadcast Management Command frame structure is defined
136+ in <linux/can/bcm.h>:
137+
138+ struct bcm_msg_head {
139+ __u32 opcode;
140+ __u32 flags;
141+ __u32 count;
142+ struct timeval ival1, ival2;
143+ canid_t can_id;
144+ __u32 nframes;
145+ struct can_frame frames[0];
146+ }
147+
148+ `bcm_msg_head` must be 8 bytes aligned because of the `frames` member (see
149+ `struct can_frame` definition). Must use native not standard types for packing.
150+ """
151+ bcm_cmd_msg_fmt = "@3I4l2I"
152+ bcm_cmd_msg_fmt += "x" * (struct .calcsize (bcm_cmd_msg_fmt ) % 8 )
153+
124154 def setUp (self ):
125155 self .s = socket .socket (socket .PF_CAN , socket .SOCK_RAW , socket .CAN_RAW )
126156 self .addCleanup (self .s .close )
@@ -1291,10 +1321,35 @@ def testCrucialConstants(self):
12911321 socket .PF_CAN
12921322 socket .CAN_RAW
12931323
1324+ @unittest .skipUnless (hasattr (socket , "CAN_BCM" ),
1325+ 'socket.CAN_BCM required for this test.' )
1326+ def testBCMConstants (self ):
1327+ socket .CAN_BCM
1328+
1329+ # opcodes
1330+ socket .CAN_BCM_TX_SETUP # create (cyclic) transmission task
1331+ socket .CAN_BCM_TX_DELETE # remove (cyclic) transmission task
1332+ socket .CAN_BCM_TX_READ # read properties of (cyclic) transmission task
1333+ socket .CAN_BCM_TX_SEND # send one CAN frame
1334+ socket .CAN_BCM_RX_SETUP # create RX content filter subscription
1335+ socket .CAN_BCM_RX_DELETE # remove RX content filter subscription
1336+ socket .CAN_BCM_RX_READ # read properties of RX content filter subscription
1337+ socket .CAN_BCM_TX_STATUS # reply to TX_READ request
1338+ socket .CAN_BCM_TX_EXPIRED # notification on performed transmissions (count=0)
1339+ socket .CAN_BCM_RX_STATUS # reply to RX_READ request
1340+ socket .CAN_BCM_RX_TIMEOUT # cyclic message is absent
1341+ socket .CAN_BCM_RX_CHANGED # updated CAN frame (detected content change)
1342+
12941343 def testCreateSocket (self ):
12951344 with socket .socket (socket .PF_CAN , socket .SOCK_RAW , socket .CAN_RAW ) as s :
12961345 pass
12971346
1347+ @unittest .skipUnless (hasattr (socket , "CAN_BCM" ),
1348+ 'socket.CAN_BCM required for this test.' )
1349+ def testCreateBCMSocket (self ):
1350+ with socket .socket (socket .PF_CAN , socket .SOCK_DGRAM , socket .CAN_BCM ) as s :
1351+ pass
1352+
12981353 def testBindAny (self ):
12991354 with socket .socket (socket .PF_CAN , socket .SOCK_RAW , socket .CAN_RAW ) as s :
13001355 s .bind (('' , ))
@@ -1327,19 +1382,8 @@ def testFilter(self):
13271382
13281383
13291384@unittest .skipUnless (HAVE_SOCKET_CAN , 'SocketCan required for this test.' )
1330- @unittest .skipUnless (thread , 'Threading required for this test.' )
13311385class CANTest (ThreadedCANSocketTest ):
13321386
1333- """The CAN frame structure is defined in <linux/can.h>:
1334-
1335- struct can_frame {
1336- canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
1337- __u8 can_dlc; /* data length code: 0 .. 8 */
1338- __u8 data[8] __attribute__((aligned(8)));
1339- };
1340- """
1341- can_frame_fmt = "=IB3x8s"
1342-
13431387 def __init__ (self , methodName = 'runTest' ):
13441388 ThreadedCANSocketTest .__init__ (self , methodName = methodName )
13451389
@@ -1388,6 +1432,46 @@ def _testSendMultiFrames(self):
13881432 self .cf2 = self .build_can_frame (0x12 , b'\x99 \x22 \x33 ' )
13891433 self .cli .send (self .cf2 )
13901434
1435+ @unittest .skipUnless (hasattr (socket , "CAN_BCM" ),
1436+ 'socket.CAN_BCM required for this test.' )
1437+ def _testBCM (self ):
1438+ cf , addr = self .cli .recvfrom (self .bufsize )
1439+ self .assertEqual (self .cf , cf )
1440+ can_id , can_dlc , data = self .dissect_can_frame (cf )
1441+ self .assertEqual (self .can_id , can_id )
1442+ self .assertEqual (self .data , data )
1443+
1444+ @unittest .skipUnless (hasattr (socket , "CAN_BCM" ),
1445+ 'socket.CAN_BCM required for this test.' )
1446+ def testBCM (self ):
1447+ bcm = socket .socket (socket .PF_CAN , socket .SOCK_DGRAM , socket .CAN_BCM )
1448+ self .addCleanup (bcm .close )
1449+ bcm .connect ((self .interface ,))
1450+ self .can_id = 0x123
1451+ self .data = bytes ([0xc0 , 0xff , 0xee ])
1452+ self .cf = self .build_can_frame (self .can_id , self .data )
1453+ opcode = socket .CAN_BCM_TX_SEND
1454+ flags = 0
1455+ count = 0
1456+ ival1_seconds = ival1_usec = ival2_seconds = ival2_usec = 0
1457+ bcm_can_id = 0x0222
1458+ nframes = 1
1459+ assert len (self .cf ) == 16
1460+ header = struct .pack (self .bcm_cmd_msg_fmt ,
1461+ opcode ,
1462+ flags ,
1463+ count ,
1464+ ival1_seconds ,
1465+ ival1_usec ,
1466+ ival2_seconds ,
1467+ ival2_usec ,
1468+ bcm_can_id ,
1469+ nframes ,
1470+ )
1471+ header_plus_frame = header + self .cf
1472+ bytes_sent = bcm .send (header_plus_frame )
1473+ self .assertEqual (bytes_sent , len (header_plus_frame ))
1474+
13911475
13921476@unittest .skipUnless (HAVE_SOCKET_RDS , 'RDS sockets required for this test.' )
13931477class BasicRDSTest (unittest .TestCase ):
0 commit comments