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 Wed Jan 16 15:46:05 2013 +1300 @@ -1339,6 +1339,7 @@ }; """ can_frame_fmt = "=IB3x8s" + can_frame_size = struct.calcsize(can_frame_fmt) def __init__(self, methodName='runTest'): ThreadedCANSocketTest.__init__(self, methodName=methodName) @@ -1389,6 +1390,73 @@ self.cli.send(self.cf2) + +class BCMCANTest(CANTest): + + def clientSetUp(self): + '''create a bcm socket and connect the interface''' + + self.cli = socket.socket(socket.PF_CAN, socket.SOCK_RAW, socket.CAN_RAW) + self.bcm = socket.socket(socket.PF_CAN, socket.SOCK_DGRAM, socket.CAN_BCM) + try: + self.cli.bind((self.interface,)) + self.bcm.connect((self.interface,)) + except OSError: + # skipTest should not be called here, and will be called in the + # server instead + pass + + self.addCleanup(self.cli.close) + self.addCleanup(self.bcm.close) + + def testBCM_TX_SEND(self): + cf = self.cli.recv(self.can_frame_size) + 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_TX_SEND(self): + 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 + """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; -> iiii ... + canid_t can_id; -> I + __u32 nframes; -> I + struct can_frame frames[0]; -> IB3x8s + } + """ + bcm_cmd_msg_fmt = "@IIIllllII" + header = struct.pack(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 + self.bcm.send(header_plus_frame) + + @unittest.skipUnless(HAVE_SOCKET_RDS, 'RDS sockets required for this test.') class BasicRDSTest(unittest.TestCase): @@ -4816,7 +4884,7 @@ def test_main(): tests = [GeneralModuleTests, BasicTCPTest, TCPCloserTest, TCPTimeoutTest, TestExceptions, BufferIOTest, BasicTCPTest2, BasicUDPTest, UDPTimeoutTest ] - + """ tests.extend([ NonBlockingTCPTests, FileObjectClassTestCase, @@ -4834,6 +4902,7 @@ CloexecConstantTest, NonblockConstantTest ]) + if hasattr(socket, "socketpair"): tests.append(BasicSocketPairTest) if hasattr(socket, "AF_UNIX"): @@ -4843,8 +4912,9 @@ if isTipcAvailable(): tests.append(TIPCTest) tests.append(TIPCThreadableTest) - tests.extend([BasicCANTest, CANTest]) - tests.extend([BasicRDSTest, RDSTest]) + """ + tests.extend([BasicCANTest, CANTest, BCMCANTest]) + """tests.extend([BasicRDSTest, RDSTest]) tests.extend([ CmsgMacroTests, SendmsgUDPTest, @@ -4870,7 +4940,7 @@ InterruptedRecvTimeoutTest, InterruptedSendTimeoutTest, TestSocketSharing, - ]) + ])""" thread_info = support.threading_setup() support.run_unittest(*tests) diff -r d866bbdd68e8 Modules/socketmodule.c --- a/Modules/socketmodule.c Tue Jan 15 16:49:35 2013 -0500 +++ b/Modules/socketmodule.c Wed Jan 16 15:46:05 2013 +1300 @@ -1635,6 +1635,44 @@ Py_DECREF(interfaceName); return 1; } + case CAN_BCM: + { + struct sockaddr_can *addr; + PyObject *interfaceName; + struct ifreq ifr; + addr = (struct sockaddr_can *)addr_ret; + Py_ssize_t len; + + if (!PyArg_ParseTuple(args, "O&", PyUnicode_FSConverter, + &interfaceName)) + return 0; + + len = PyBytes_GET_SIZE(interfaceName); + + if (len == 0) { + ifr.ifr_ifindex = 0; + } else if (len < sizeof(ifr.ifr_name)) { + strcpy(ifr.ifr_name, PyBytes_AS_STRING(interfaceName)); + if (ioctl(s->sock_fd, SIOCGIFINDEX, &ifr) < 0) { + s->errorhandler(); + Py_DECREF(interfaceName); + return 0; + } + } else { + PyErr_SetString(PyExc_OSError, + "AF_CAN interface name too long"); + Py_DECREF(interfaceName); + return 0; + } + + addr->can_family = PF_CAN; + addr->can_ifindex = ifr.ifr_ifindex; + s->sock_type = SOCK_DGRAM; + + *len_ret = sizeof(*addr); + Py_DECREF(interfaceName); + return 1; + } default: PyErr_SetString(PyExc_OSError, "getsockaddrarg: unsupported CAN protocol"); @@ -6031,6 +6069,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 Wed Jan 16 15:46:05 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 --- a/configure Tue Jan 15 16:49:35 2013 -0500 +++ b/configure Wed Jan 16 15:46:05 2013 +1300 @@ -7212,7 +7212,7 @@ # On Linux, can.h and can/raw.h require sys/socket.h -for ac_header in linux/can.h linux/can/raw.h +for ac_header in linux/can.h linux/can/raw.h linux/can/bcm.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" " diff -r d866bbdd68e8 configure.ac --- a/configure.ac Tue Jan 15 16:49:35 2013 -0500 +++ b/configure.ac Wed Jan 16 15:46:05 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 diff -r d866bbdd68e8 pyconfig.h.in --- a/pyconfig.h.in Tue Jan 15 16:49:35 2013 -0500 +++ b/pyconfig.h.in Wed Jan 16 15:46:05 2013 +1300 @@ -501,6 +501,9 @@ /* Define to 1 if you have the `linkat' function. */ #undef HAVE_LINKAT +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_CAN_BCM_H + /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_CAN_H