diff -r d866bbdd68e8 Lib/test/test_socket.py --- a/Lib/test/test_socket.py Tue Jan 15 16:49:35 2013 -0500 +++ b/Lib/test/test_socket.py Thu Jan 17 19:00:58 2013 +1300 @@ -121,6 +121,31 @@ interface = 'vcan0' bufsize = 128 + """The CAN frame structure is defined in : + + struct can_frame { + canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ + __u8 can_dlc; /* data length code: 0 .. 8 */ + __u8 data[8] __attribute__((aligned(8))); + }; + """ + can_frame_fmt = "=IB3x8s" + can_frame_size = struct.calcsize(can_frame_fmt) + + """Must use native not standard types for packing + + struct bcm_msg_head { + __u32 opcode; -> I + __u32 flags; -> I + __u32 count; -> I + struct timeval ival1, ival2; -> llll + canid_t can_id; -> I + __u32 nframes; -> I + struct can_frame frames[0]; -> IB3x8s (See above comment for CAN frame structure) + } + """ + bcm_cmd_msg_fmt = "@IIIllllII" + def setUp(self): self.s = socket.socket(socket.PF_CAN, socket.SOCK_RAW, socket.CAN_RAW) self.addCleanup(self.s.close) @@ -1290,11 +1315,18 @@ socket.AF_CAN socket.PF_CAN socket.CAN_RAW + socket.CAN_BCM def testCreateSocket(self): with socket.socket(socket.PF_CAN, socket.SOCK_RAW, socket.CAN_RAW) as s: pass + @unittest.skipUnless(hasattr(socket, "CAN_BCM"), + 'socket.CAN_BCM required for this test.') + def testCreateBCMSocket(self): + with socket.socket(socket.PF_CAN, socket.SOCK_DGRAM, socket.CAN_BCM) as s: + pass + def testBindAny(self): with socket.socket(socket.PF_CAN, socket.SOCK_RAW, socket.CAN_RAW) as s: s.bind(('', )) @@ -1327,19 +1359,8 @@ @unittest.skipUnless(HAVE_SOCKET_CAN, 'SocketCan required for this test.') -@unittest.skipUnless(thread, 'Threading required for this test.') class CANTest(ThreadedCANSocketTest): - """The CAN frame structure is defined in : - - struct can_frame { - canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */ - __u8 can_dlc; /* data length code: 0 .. 8 */ - __u8 data[8] __attribute__((aligned(8))); - }; - """ - can_frame_fmt = "=IB3x8s" - def __init__(self, methodName='runTest'): ThreadedCANSocketTest.__init__(self, methodName=methodName) @@ -1388,6 +1409,42 @@ self.cf2 = self.build_can_frame(0x12, b'\x99\x22\x33') self.cli.send(self.cf2) + def _testBCM(self): + cf, addr = self.cli.recvfrom(self.bufsize) + self.assertEqual(self.cf, cf) + can_id, can_dlc, data = self.dissect_can_frame(cf) + self.assertEqual(self.can_id, can_id) + self.assertEqual(self.data, data) + + def testBCM(self): + self.bcm = socket.socket(socket.PF_CAN, socket.SOCK_DGRAM, socket.CAN_BCM) + self.bcm.connect((self.interface,)) + self.can_id = 0x123 + self.data = bytes([0xc0, 0xff, 0xee]) + self.cf = self.build_can_frame(self.can_id, self.data) + opcode = socket.CAN_BCM_TX_SEND + flags = 0 + count = 0 + ival1_seconds = ival1_usec = ival2_seconds = ival2_usec = 0 + bcm_can_id = 0x0222 + nframes = 1 + assert len(self.cf) == 16 + header = struct.pack(self.bcm_cmd_msg_fmt, + opcode, + flags, + count, + ival1_seconds, + ival1_usec, + ival2_seconds, + ival2_usec, + bcm_can_id, + nframes, + ) + + header_plus_frame = header + self.cf + bytes_sent = self.bcm.send(header_plus_frame) + assert bytes_sent == len(header_plus_frame) + self.bcm.close() @unittest.skipUnless(HAVE_SOCKET_RDS, 'RDS sockets required for this test.') class BasicRDSTest(unittest.TestCase): diff -r d866bbdd68e8 Modules/socketmodule.c --- a/Modules/socketmodule.c Tue Jan 15 16:49:35 2013 -0500 +++ b/Modules/socketmodule.c Thu Jan 17 19:00:58 2013 +1300 @@ -1598,6 +1598,8 @@ case AF_CAN: switch (s->sock_proto) { case CAN_RAW: + /* fallthrough */ + case CAN_BCM: { struct sockaddr_can *addr; PyObject *interfaceName; @@ -6031,6 +6033,14 @@ PyModule_AddIntConstant(m, "CAN_RAW_LOOPBACK", CAN_RAW_LOOPBACK); PyModule_AddIntConstant(m, "CAN_RAW_RECV_OWN_MSGS", CAN_RAW_RECV_OWN_MSGS); #endif +#ifdef HAVE_LINUX_CAN_BCM_H + PyModule_AddIntConstant(m, "CAN_BCM", CAN_BCM); + PyModule_AddIntConstant(m, "CAN_BCM_TX_SETUP", TX_SETUP); + PyModule_AddIntConstant(m, "CAN_BCM_TX_DELETE", TX_DELETE); + PyModule_AddIntConstant(m, "CAN_BCM_TX_READ", TX_READ); + PyModule_AddIntConstant(m, "CAN_BCM_TX_SEND", TX_SEND); + +#endif #ifdef SOL_RDS PyModule_AddIntConstant(m, "SOL_RDS", SOL_RDS); #endif diff -r d866bbdd68e8 Modules/socketmodule.h --- a/Modules/socketmodule.h Tue Jan 15 16:49:35 2013 -0500 +++ b/Modules/socketmodule.h Thu Jan 17 19:00:58 2013 +1300 @@ -80,6 +80,10 @@ #include #endif +#ifdef HAVE_LINUX_CAN_BCM_H +#include +#endif + #ifdef HAVE_SYS_SYS_DOMAIN_H #include #endif diff -r d866bbdd68e8 configure.ac --- a/configure.ac Tue Jan 15 16:49:35 2013 -0500 +++ b/configure.ac Thu Jan 17 19:00:58 2013 +1300 @@ -1561,7 +1561,7 @@ ]) # On Linux, can.h and can/raw.h require sys/socket.h -AC_CHECK_HEADERS(linux/can.h linux/can/raw.h,,,[ +AC_CHECK_HEADERS(linux/can.h linux/can/raw.h linux/can/bcm.h,,,[ #ifdef HAVE_SYS_SOCKET_H #include #endif