项目作者: mac-can

项目描述 :
Creation of USB User-Space Driver for CAN Interfaces under macOS®
高级语言: C
项目地址: git://github.com/mac-can/MacCAN-Core.git
创建时间: 2020-02-23T21:04:23Z
项目社区:https://github.com/mac-can/MacCAN-Core

开源协议:BSD 2-Clause "Simplified" License

下载


Creation of USB User-Space Drivers for CAN Interfaces under macOS®

Copyright © 2012-2023 Uwe Vogt, UV Software, Berlin (info@mac-can.com) \
All rights reserved.

Version $Rev$

Running CAN and CAN FD on Mac®

Running CAN and CAN FD on Mac is the mission of the MacCAN project.
The MacCAN-Core repo is not aimed at building a driver or a library.
It provides the source code of an abstraction (or rather of a wrapper) of Apple´s IOUsbKit to create USB user-space drivers for CAN interfaces from various vendors under macOS.

A Stupid Question

I´m working with the CAN bus since the late 1990th, mainly on microcontrollers
(CANopen, SAE J1939, ISO-TP, UDS, etc.), but also on PC. See my blog for the things I did.

Sometimes I tend to ask myself some stupid questions like “Is it possible to …?”.
In 2010 I asked a well known search engine if it is possible to run CAN on a Mac.
I only found the request of a student, who had to do a semester work with CAN bus.
But that poor boy only owned a Mac.

MacCAN - macOS Driver for PCAN-USB Interfaces and more

In the absence of a CAN driver for Mac, I started developing an OS X user space driver for my PEAK USB-to-CAN dongle.
Many thanks to Uwe Wilhelm, CEO of PEAK-System Technik GmbH, who had supported me with technical information and several hardware.

PCBUSB Library for PEAK´s PCAN-USB Interfaces

The PCBUSB library realizes a USB user-space driver under macOS for PCAN® USB interfaces from PEAK-System Technik.
See the MacCAN website for further information, downloads and links.

The library supports up to 8 PCAN-USB and PCAN-USB FD devices.
It offers an easy to use API that is almost compatible to PEAK´s PCANBasic DLL on Windows.
Standard CAN frames (11-bit identifier) as well as extended CAN frames (29-bit identifier) are supported.
PCAN-USB FD devices can be operated in CAN 2.0 mode and in CAN FD mode.

The library comes with an Objective-C wrapper and a demo App; see https://youtu.be/v0U_WN7s3ao/ \
Furthermore, it can be used with the Qt® Serial Bus API on a Mac; see https://doc.qt.io/qt-5/qtserialbus-index.html

The PCBUSB library is closed source, please note the copyright and license agreements.

TouCAN USB Interfaces from Rusoku

Rusoku Technologies is an innovative engineering team based in Lithuania, Europe.
They offer CAN adapter at a reasonable price.
Drivers and utilities for Windows and Linux are available as open-source.
See Rusoku´s website for the products and the services they offer.

The MacCAN-TouCAN driver for TouCAN USB interfaces from Rusoku is the first driver implementation based on MacCAN-Core.
And it is open source;
goto https://github.com/mac-can/RusokuCAN.dylib.

USB CAN Interfaces from Kvaser

The Swedish company Kvaser AB supplies advanced CAN solutions to engineers designing and deploying systems for manifold areas of applications.
They offer a wide range of CAN hardware and CAN software, mainly for applications under Windows but also under Linux.

Welcome the MacCAN-KvaserCAN driver for CAN interfaces from Kvaser as the next member of the MacCAN family.
Find its source code on GitHub;
goto https://github.com/mac-can/KvaserCAN-Library.

HowTo

MacCAN API Specification

  1. /// \name MacCAN API
  2. /// \brief MacCAN API based on CAN Interface API Version 3 (CAN API V3).
  3. /// \note To implement a MacCAN driver derive a class from abstract class
  4. /// CMacCAN, and override all pure virtual functions and optionally
  5. /// the static function 'ProbeChannel'.
  6. /// \{
  7. class CMacCAN {
  8. public:
  9. /// \brief CAN channel states
  10. enum EChannelState {
  11. ChannelOccupied = CANBRD_OCCUPIED, ///< channel is available, but occupied
  12. ChannelAvailable = CANBRD_PRESENT, ///< channel is available and can be used
  13. ChannelNotAvailable = CANBRD_NOT_PRESENT, ///< channel is not available
  14. ChannelNotTestable = CANBRD_NOT_TESTABLE ///< channel is not testable
  15. };
  16. /// \brief Common error codes (CAN API V3 compatible)
  17. enum EErrorCodes {
  18. NoError = CANERR_NOERROR, ///< no error!
  19. BusOFF = CANERR_BOFF, ///< busoff status
  20. ErrorWarning = CANERR_EWRN, ///< error warning status
  21. BusError = CANERR_BERR, ///< bus error
  22. ControllerOffline = CANERR_OFFLINE, ///< not started
  23. ControllerOnline = CANERR_ONLINE, ///< already started
  24. MessageLost = CANERR_MSG_LST, ///< message lost
  25. TransmitterBusy = CANERR_TX_BUSY, ///< transmitter busy
  26. ReceiverEmpty = CANERR_RX_EMPTY, ///< receiver empty
  27. ErrorFrame = CANERR_ERR_FRAME, ///< error frame
  28. Timeout = CANERR_TIMEOUT, ///< timed out
  29. ResourceError = CANERR_RESOURCE, ///< resource allocation
  30. InvalidBaudrate = CANERR_BAUDRATE, ///< illegal baudrate
  31. IllegalParameter = CANERR_ILLPARA, ///< illegal parameter
  32. NullPointer = CANERR_NULLPTR, ///< null-pointer assignment
  33. NotInitialized = CANERR_NOTINIT, ///< not initialized
  34. AlreadyInitialized = CANERR_YETINIT, ///< already initialized
  35. InvalidLibrary = CANERR_LIBRARY, ///< illegal library
  36. NotSupported = CANERR_NOTSUPP, ///< not supported
  37. FatalError = CANERR_FATAL, ///< fatal error
  38. VendorSpecific = CANERR_VENDOR ///< offset for vendor-specific error code
  39. };
  40. /// \name MacCAN Driver Interface
  41. /// \brief Methods to be overridden by a MacCAN driver implementation.
  42. /// \{
  43. public:
  44. /// \brief probes if the CAN interface (hardware and driver) given by
  45. /// the argument 'channel' is present, and if the requested
  46. /// operation mode is supported by the CAN controller.
  47. //
  48. /// \note When a requested operation mode is not supported by the
  49. /// CAN controller, error CANERR_ILLPARA will be returned.
  50. //
  51. /// \param[in] channel - channel number of the CAN interface
  52. /// \param[in] opMode - operation mode to be checked
  53. /// \param[in] param - pointer to channel-specific parameters
  54. /// \param[out] state - state of the CAN channel:
  55. /// < 0 - channel is not present,
  56. /// = 0 - channel is present,
  57. /// > 0 - channel is present, but in use
  58. //
  59. /// \returns 0 if successful, or a negative value on error.
  60. //
  61. static MacCAN_Return_t ProbeChannel(int32_t channel, MacCAN_OpMode_t opMode, const void *param, EChannelState &state);
  62. static MacCAN_Return_t ProbeChannel(int32_t channel, MacCAN_OpMode_t opMode, EChannelState &state);
  63. /// \brief initializes the CAN interface (hardware and driver) given by
  64. /// the argument 'channel'.
  65. /// The operation state of the CAN controller is set to 'stopped';
  66. /// no communication is possible in this state.
  67. //
  68. /// \param[in] channel - channel number of the CAN interface
  69. /// \param[in] opMode - operation mode of the CAN controller
  70. /// \param[in] param - pointer to channel-specific parameters
  71. //
  72. /// \returns handle of the CAN interface if successful,
  73. /// or a negative value on error.
  74. //
  75. virtual MacCAN_Return_t InitializeChannel(int32_t channel, MacCAN_OpMode_t opMode, const void *param = NULL) = 0;
  76. /// \brief stops any operation of the CAN interface and sets the operation
  77. /// state of the CAN controller to 'stopped'.
  78. //
  79. /// \returns 0 if successful, or a negative value on error.
  80. ///
  81. virtual MacCAN_Return_t TeardownChannel() = 0;
  82. /// \brief signals waiting event objects of the CAN interface. This can
  83. /// be used to terminate blocking operations in progress
  84. /// (e.g. by means of a Ctrl-C handler or similar).
  85. //
  86. /// \remarks Some drivers are using waitable objects to realize blocking
  87. /// operations by a call to WaitForSingleObject (Windows) or
  88. /// pthread_cond_wait (POSIX), but these waitable objects are
  89. /// no cancellation points. This means that they cannot be
  90. /// terminated by Ctrl-C (SIGINT).
  91. //
  92. /// \note Even though this is not the case with Darwin, we support
  93. /// this feature for compatibility reasons..
  94. //
  95. /// \returns 0 if successful, or a negative value on error.
  96. ///
  97. virtual MacCAN_Return_t SignalChannel() = 0;
  98. /// \brief initializes the operation mode and the bit-rate settings of the
  99. /// CAN interface and sets the operation state of the CAN controller
  100. /// to 'running'.
  101. //
  102. /// \note All statistical counters (tx/rx/err) will be reset by this.
  103. //
  104. /// \param[in] bitrate - bit-rate as btr register or baud rate index
  105. //
  106. /// \returns 0 if successful, or a negative value on error.
  107. //
  108. virtual MacCAN_Return_t StartController(MacCAN_Bitrate_t bitrate) = 0;
  109. /// \brief stops any operation of the CAN interface and sets the operation
  110. /// state of the CAN controller to 'stopped'; no communication is
  111. /// possible in this state.
  112. //
  113. /// \returns 0 if successful, or a negative value on error.
  114. //
  115. virtual MacCAN_Return_t ResetController() = 0;
  116. /// \brief transmits one message over the CAN bus. The CAN controller must
  117. /// be in operation state 'running'.
  118. //
  119. /// \param[in] message - the message to send
  120. /// \param[in] timeout - time to wait for the transmission of the message:
  121. /// 0 means the function returns immediately,
  122. /// 65535 means blocking read, and any other
  123. /// value means the time to wait in milliseconds
  124. //
  125. /// \returns 0 if successful, or a negative value on error.
  126. //
  127. virtual MacCAN_Return_t WriteMessage(MacCAN_Message_t message, uint16_t timeout = 0U) = 0;
  128. /// \brief read one message from the message queue of the CAN interface, if
  129. /// any message was received. The CAN controller must be in operation
  130. /// state 'running'.
  131. //
  132. /// \param[out] message - the message read from the message queue, if any
  133. /// \param[in] timeout - time to wait for the reception of a message:
  134. /// 0 means the function returns immediately,
  135. /// 65535 means blocking read, and any other
  136. /// value means the time to wait in milliseconds
  137. //
  138. /// \returns 0 if successful, or a negative value on error.
  139. //
  140. virtual MacCAN_Return_t ReadMessage(MacCAN_Message_t &message, uint16_t timeout = CANREAD_INFINITE) = 0;
  141. /// \brief retrieves the status register of the CAN interface.
  142. //
  143. /// \param[out] status - 8-bit status register.
  144. //
  145. /// \returns 0 if successful, or a negative value on error.
  146. //
  147. virtual MacCAN_Return_t GetStatus(MacCAN_Status_t &status) = 0;
  148. /// \brief retrieves the bus-load (in percent) of the CAN interface.
  149. //
  150. /// \param[out] load - bus-load in [%]
  151. //
  152. /// \returns 0 if successful, or a negative value on error.
  153. //
  154. virtual MacCAN_Return_t GetBusLoad(uint8_t &load) = 0;
  155. /// \brief retrieves the bit-rate setting of the CAN interface. The
  156. /// CAN controller must be in operation state 'running'.
  157. //
  158. /// \param[out] bitrate - bit-rate setting
  159. //
  160. /// \returns 0 if successful, or a negative value on error.
  161. //
  162. virtual MacCAN_Return_t GetBitrate(MacCAN_Bitrate_t &bitrate) = 0;
  163. /// \brief retrieves the transmission rate of the CAN interface. The
  164. /// CAN controller must be in operation state 'running'.
  165. //
  166. /// \param[out] speed - transmission rate
  167. //
  168. /// \returns 0 if successful, or a negative value on error.
  169. //
  170. virtual MacCAN_Return_t GetBusSpeed(MacCAN_BusSpeed_t &speed) = 0;
  171. /// \brief retrieves a property value of the CAN interface.
  172. //
  173. /// \param[in] param - property id to be read
  174. /// \param[out] value - pointer to a buffer for the value to be read
  175. /// \param[in] nbytes - size of the given buffer in bytes
  176. //
  177. /// \returns 0 if successful, or a negative value on error.
  178. //
  179. virtual MacCAN_Return_t GetProperty(uint16_t param, void *value, uint32_t nbytes) = 0;
  180. /// \brief modifies a property value of the CAN interface.
  181. //
  182. /// \param[in] param - property id to be written
  183. /// \param[in] value - pointer to a buffer with the value to be written
  184. /// \param[in] nbytes - size of the given buffer in bytes
  185. //
  186. /// \returns 0 if successful, or a negative value on error.
  187. //
  188. virtual MacCAN_Return_t SetProperty(uint16_t param, const void *value, uint32_t nbytes) = 0;
  189. /// \brief retrieves the hardware version of the CAN controller
  190. /// board as a zero-terminated string.
  191. //
  192. /// \returns pointer to a zero-terminated string, or NULL on error.
  193. //
  194. virtual char *GetHardwareVersion() = 0;
  195. /// \brief retrieves the firmware version of the CAN controller
  196. /// board as a zero-terminated string.
  197. //
  198. /// \returns pointer to a zero-terminated string, or NULL on error.
  199. //
  200. virtual char *GetFirmwareVersion() = 0;
  201. /// \}
  202. /// \name MacCAN Bit-rate converstion
  203. /// \brief Methods for bit-rate conversion.
  204. /// \note To be overridden when required.
  205. /// \{
  206. public:
  207. static MacCAN_Return_t MapIndex2Bitrate(int32_t index, MacCAN_Bitrate_t &bitrate);
  208. static MacCAN_Return_t MapString2Bitrate(const char *string, MacCAN_Bitrate_t &bitrate);
  209. static MacCAN_Return_t MapBitrate2String(MacCAN_Bitrate_t bitrate, char *string, size_t length);
  210. static MacCAN_Return_t MapBitrate2Speed(MacCAN_Bitrate_t bitrate, MacCAN_BusSpeed_t &speed);
  211. /// \}
  212. /// \name CAN FD Data Length Code
  213. /// \brief Methods for DLC conversion.
  214. /// \{
  215. public:
  216. static uint8_t Dlc2Len(uint8_t dlc);
  217. static uint8_t Len2Dlc(uint8_t len);
  218. /// \}
  219. };
  220. /// \}

MacCAN Driver Implementation

[To Be Continued]

This and That

SVN Repo

The MacCAN-Core sources are maintained in a SVN repo to synchronized them between the different MacCAN driver repos.

Dual-License

This work is dual-licensed under the terms of the BSD 2-Clause “Simplified” License and under the terms of the GNU General Public License v3.0 (or any later version).
You can choose between one of them if you use this work in whole or in part.

SPDX-License-Identifier: BSD-2-Clause OR GPL-3.0-or-later

Trademarks

Mac and macOS are trademarks of Apple Inc., registered in the U.S. and other countries. \
PCAN is a registered trademark of PEAK-System Technik GmbH, Darmstadt, Germany. \
Qt is a registered trademark of The Qt Company Ltd. and its subsidiaries. \
All other company, product and service names mentioned herein are trademarks, registered trademarks or service marks of their respective owners.

Contact

E-Mail: mailto://info@mac.can.com \
Internet: https://www.mac-can.net