CAN-BUS SocketCAN lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- rampinia · 2018-01-28 09:20 Hello to all does anyone did programming socket in the class PF_CAN for accessing CAN-BUS in Linux? On the wiki side I have seen there are not current constant declaration for such network protocoll. If the pfsocket and others call are just wrapper for standard BSD socket call I think it is enaugh to declare the constant just porting from the standard linux header. Any info? Thanks ---------------------------------------------------------------------- marcov · 2018-01-28 09:43 Yes, the sockets unit are just wrappers. Best is if somebody finds the constants, tests it, and then submits a patch. ---------------------------------------------------------------------- rampinia · 2018-01-28 17:30 Yes got PF_CAN = 29 and CAN_RAW = 1 from sys/if.h already run some tests with PF_CAN = 29 and CAN_RAW = 1 and it works. I'm working a minimal porting from C header. ---------------------------------------------------------------------- RM · 2019-03-11 07:50 Hello at all, i am new here... I try to establish a CAN connection on the raspberry pi (stretch), using free pascal. I successfully created a raw socket with PF_CAN=29 and CAN_RAW=1. And now i have to bind the socket to the hardware address, but i don't know how? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i class procedure TSysBus.OpenSocket;var  s:Tsocket;  sa:TSockAddr;begin     s:=fpsocket(29, SOCK_RAW, 1);     sa.sa_family:=29;     sa.sa_data[0]:=???;     fpbind(s,@sa,SizeOf(sa));     FpClose(s);end;  Can somebody give me an example, how i have to go on? Thanks ---------------------------------------------------------------------- jcdammeyer · 2020-08-21 03:00 Anyone been able to create the equivalent of a simple the socketCAN utilities  candump using Lazarus Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i debian@ebb:~$ sudo /sbin/ip link set can1 up type can bitrate 250000debian@ebb:~$ candump can1  can1  721   [1]  05  can1  1A1   [8]  20 00 FF 0F A8 FD A8 FD  No one answered RM and rampinia didn't post any other solutions. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TSocketForm.Button1Click(Sender: TObject);var    i : integer;begin  // open socket  socket_result := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);  if (socket_result < 0) then begin        // perror("socket");    Edit1.text := 'Error #' + IntToStr(socket_result) + ' creating socket';  end  else begin    SAddr.sin_family := PF_CAN;    if fpconnect(socket_result, @SAddr, 0) = -1 then begin      Edit1.text := 'Socket can''t connect: ' + strerror(socketerror);    end;  end;end;  The error is 'Operation not supported on Endpoint' The C language candump doesn't use fpconnect() and the 'connect()' is deprecated and doesn't work either.  So although this is the document for fpconnect it uses deprecated functions rather than fpconnect(). https://www.freepascal.org/docs- html/current/rtl/sockets/fpconnect.html Plus it's more targeted at internet protocol sockets. Ideas? ---------------------------------------------------------------------- trev · 2020-08-21 03:17 What about this. The Windows/Linux SDK for Delphi is free. ---------------------------------------------------------------------- jcdammeyer · 2020-08-23 07:55 Quote from: trev on August 21, 2020, 05:17:22 amWhat about this. The Windows/Linux SDK for Delphi is free. Unfortunately from what I can see it doesn't address socketcan. What I've found out so far is that socketcan and the utilities like candump work with the USB based CANUSB from Lawicel along with the internal BeagleBone Black CAN device and on a Pi, an SPI based MCP2515. Further research shows that as simple as including 'can' in python programs brings in support for either the BBB or Pi.  This is what I want to see for Lazarus.  I'd like to be able to plug in any device that has socketCAN support and have the application compile on that platform, or cross compile for that platform and just plain work. What I've discovered is that this doesn't work for Lazarus yet.   So I need to find out where the sockets source code lives for the Pi and the Beagle and figure out why the fpconnect() returns an error.  Clearly it's broken or not properly documented. ---------------------------------------------------------------------- Laksen · 2020-08-23 09:10 Why are you calling connect and not bind? ---------------------------------------------------------------------- jcdammeyer · 2020-10-22 04:10 I think I have some time to dive back into this project.  Quote from: Laksen on August 23, 2020, 11:10:19 amWhy are you calling connect and not bind? Even if I call bind (or fpbind) the issue is that the sockets code seems to be oriented towards ip and port numbers.  Referencing this document http://www.linuxhowtos.org/C_C++/socket.htm I believe the socketCAN has to address the unix domain via the Linux File system.  Recall my example from a previous post. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i         debian@ebb:~$ sudo /sbin/ip link set can1 up type can bitrate 250000  debian@ebb:~$ candump can1      can1  721   [1]  05      can1  1A1   [8]  20 00 FF 0F A8 FD A8 FD The can1 is the device which in the above example is a USB based CAN dongle.  On a Pi I can just as easily specify the SPI based MCP2515 CAN device in place of the USB device.  For example from this tutorial https://www.raspberrypi.org/forums/viewtopic.php?t=141052 Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i pi@piv2:~ $ ls /sys/bus/spi/devices/spi0.0/net/can0 pi@piv2:~ $ sudo ip link set can0 up type can bitrate 125000 pi@piv2:~ $ sudo ifconfigcan0   Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00        UP RUNNING NOARP  MTU:16  Metric:1          RX packets:0 errors:0 dropped:0 overruns:0 frame:0          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0          collisions:0 txqueuelen:10        RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)  So from the OS perspective the fact that one device is USB based and can be plugged into a WIN-PC MAC or Linux system while the other one is SPI based on the Pi the access via Linux is the same. And the C Program candump.c creates identical output regardless of the hardware type.  (BTW, it's the same with the embedded inside the processor CAN device in a BeagleBone Black). Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i pi@piv2:~ $ candump can0  can0  001   [8]  11 22 33 44 55 66 77 88  can0  00003456   [8]  EF FE DD AD CB 67 98 AA  Now in the C world, candump.c or cansend.c can be used as a template for a customized program to do whatever...  One might cut and paste parts into their application.    That's because the sockets library in C handles the parameters PF_CAN and SOCK_RAW, CAN_RAW. The FPC sockets does not.  And yes I can define those but tunnel down into sockets.pp and and the system's ...sockh.inc we don't have a PF_CAN.  And without a PF_CAN and AF_CAN in the socket()  the connection aborts because it doesn't know what to do with it. In order to cut and paste more of the code I'll have to continue this in another message from the Pi3 so I can post the Lazarus program I've used to discover this but I don't think the FPC code will matter at this point. Search for candump.c and we find in https://github.com/linux-can/can-utils/blob/master/candump.c Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW); Later we bind to the socket Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {                      perror("bind");                        return 1;              }  Eventually after all the CAN_FD and filter handling we end up Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i nbytes = recvmsg(s[i], &msg, 0); So in general I get the feeling that to add socketCAN support to FPC will require a fairly extensive modification of the base sockets library.  Is there any interest in this?  Who's allowed to change it.  The project I started in Lazarus works fine with the USB based CAN dongle by treating it as a serial port which generates strings of characters representing the messages.  But I can't access the CAN devices built into the BeagleBone nor the Pi which is a cakewalk with Python or C.  And I'd like to be able to demonstrate CAN bus access from a USB dongle or the embedded hardware.  What's the next step? ---------------------------------------------------------------------- avra · 2020-10-22 07:41 Quote from: jcdammeyer on October 22, 2020, 06:10:48 amSo in general I get the feeling that to add socketCAN support to FPC will require a fairly extensive modification of the base sockets library.PF_CAN is just a number. In linux sources you can find it defined as AF_CAN, which is defined as 29. So why don't you try that first? You could also take a look at https://github.com/linux-can/socketcand if you wish to access CAN via CAN-ETH gateway daemon. You can install https://github.com/dschanoeh/Kayak as a handy GUI application that can access SocketCAN (and serial slcan through it) using socketcand. Instead of using real slcan device as you do, maybe it would be easier if you use vcan instead and simulate CAN traffic for testing purposes. Once you get everything working you can then switch to a real device. If you wish I can give you several simple scripts to bring up VCAN environment, generate CAN traffic, and use SocketCAN directly or through socketcand and Kayak. EDIT: I see now that you are looking at sources of candump. It will be much easier if you use simpler example from here: https://www.beyondlogic.org/example-c-socketcan-code/ ---------------------------------------------------------------------- MarkMLl · 2020-10-22 07:44 Quote from: jcdammeyer on October 22, 2020, 06:10:48 amI believe the socketCAN has to address the unix domain via the Linux File system.  Presumably you mean unix domain *socket* here. If so I agree that it's normally accessed via the filesystem, but otherwise the API is fairly similar to an inet datagram socket. Code: [Select]      if fpSelect(maxHandle + 1, @readSet, nil, nil, nil) >= 0 then begin (* A message received on the inet domain socket must have a recognisable sender *) (* since it might be needed for authentication purposes. A unix domain socket   *) (* can be assumed to be protected by local permissions and capabilities.        *)         if (UnixDomainSocket() >= 0) and (fpFD_ISSET(UnixDomainSocket(), readSet) = 1) then           dispatchMessage(UnixDomainSocket(), false);         if (InetDomainSocket() >= 0) and (fpFD_ISSET(InetDomainSocket(), readSet) = 1) then           dispatchMessage(InetDomainSocket(), true)       end ... begin // dispatchMessage(), invoked as above, 2nd param is hasFrom   FillByte(recvBuffer, SizeOf(recvBuffer), 0);   if hasFrom then begin                 (* Inet domain socket                 *)     FillByte(sa, SizeOf(sa), 0);     saLength := SizeOf(sa);     messageLength := fpRecvFrom(socket, @recvBuffer, SizeOf(recvBuffer), 0, @sa, @saLength)   end else begin                        (* Unix domain socket                 *)     saLength := -1;     messageLength := fpRecv(socket, @recvBuffer, SizeOf(recvBuffer), 0)   end; (* There is no provision here for concatenated or fragmented messages, which we *) (* of course shouldn't see since it's a datagram socket. Elsewhere, we try to   *) (* work out the MTU by looking at padded backbone messages.                   *) ... (* The result of this may be subsequently retrieved using UnixDomainSocket().   If a .pid file indicates that an existing socket was created by an instance   of this program that no longer exists then delete it. Create a fresh Unix   Domain socket and save the handle, on failure save an error code. Both success   and failure are silent. *) procedure CreateUnixDomainSocket(socketName: string); var   oldPid: longInt= -1;   pidName: string;   pidFile: text;   uid: TUid;   gid: TGid; begin   if socketName[1] = '~' then begin     Delete(socketName, 1, 1);     socketName := UserHome() + socketName   end;   pidName := socketName + '.pid';   if FileExists(pidName) then     try       Write(StdErr, 'Opening old PID file... ');       Assign(pidFile, pidName);       Reset(pidFile);       try         Read(pidFile, oldPid);         WriteLn(StdErr, 'OK, ' + IntToStr(oldPid))       finally         Close(pidFile)       end     except       WriteLn(StdErr, 'failed');       oldPid := -1     end; (* If we have managed to read a process ID file then check whether the relevant *) (* process (an older instance of this program) still exists. If it does then we *) (* shouldn't be trying to run this program, if it does not and a unix domain    *) (* socket exists then try to delete it.                                       *)   if (oldPid >= 0) and FileExists('/proc/' + IntToStr(oldPid)) then begin     WriteLn(StdErr, 'WatchP0x already running, terminating.');     Halt(9)   end;   if oldPid >= 0 then begin     WriteLn(StdErr, 'Process ', oldPid, ' is not running');     try       if FileExists(socketName) then begin         Write(StdErr, 'Deleting old unix domain socket ', socketName, '... ');         DeleteFile(socketName);         if not FileExists(socketName) then           WriteLn(StdErr, 'OK')         else           WriteLn(StdErr, 'ineffective (critical error)')       end else         WriteLn(StdErr, 'No old socket')     except       WriteLn(StdErr, 'failed');       unixDomainSocketHandle := -Abs(ErrNo) (* Probably ESysEACCESS           *)     end   end; (* Delete old PID file since it might be owned by a different user.           *)   if FileExists(pidName) then begin     Write(StdErr, 'Deleting old PID file... ');     try         DeleteFile(pidName);         if not FileExists(pidName) then           WriteLn(StdErr, 'OK')         else           WriteLn(StdErr, 'ineffective (critical error)')     except       WriteLn(StdErr, 'failed');       unixDomainSocketHandle := -Abs(ErrNo) (* Probably ESysEACCESS           *)     end   end; (* Create a new PID file.                                                     *)   try     Write(StdErr, 'Creating new PID file... ');     Assign(pidFile, pidName);     Rewrite(pidFile);     try       WriteLn(pidFile, IntToStr(GetProcessID()));       WriteLn(StdErr, 'OK, ', GetProcessID())     finally       Close(pidFile)     end   except     WriteLn(StdErr, 'failed (critical error)');     unixDomainSocketHandle := -Abs(ErrNo) (* Probably ESysEACCESS             *)   end; (* Create the socket. Note that there is no suitable fpBind() for this.         *)   Write(StdErr, 'Creating new unix domain socket... ');   unixDomainSocketHandle := fpSocket(AF_UNIX, SOCK_DGRAM, 0);   if Bind(unixDomainSocketHandle, socketName) then     WriteLn(StdErr, 'OK')   else begin     WriteLn(StdErr, 'failed (continuing)');     unixDomainSocketHandle := -Abs(ErrNo) (* Probably ESysEACCESS             *)   end; (* Change socket owner and group to be the same as the executable, on the       *) (* assumption that this is the user that will be executing all programs.        *) // TODO : Bad assumption if setuid.   Write(StdErr, 'Changing socket''s ownership... ');   getOwner(ParamStr(0), uid, gid);   if fpChown(socketName, uid, gid) = 0 then     WriteLn(StdErr, 'OK')   else begin     WriteLn(StdErr, 'failed (continuing)'); //    unixDomainSocketHandle := -Abs(ErrNo) (* Probably ESysEACCESS           *)   end; (* Set the socket to be writable by its owner (i.e. any cooperating program)    *) (* and readable by its group (this program). I don't think very much of doing   *) (* this but the computer on which this is running can be assumed to be          *) (* physically secure leaving the major risk being that somebody unauthorised    *) (* logs into it and runs one of this suite of programs.                       *)   Write(StdErr, 'Relaxing socket''s read/write permissions... ');   if fpChMod(socketName, &766) = 0 then     WriteLn(StdErr, 'OK')   else begin     WriteLn(StdErr, 'failed (continuing), might need CAP_DAC_OVERRIDE,CAP_NET_BIND_SERVICE,CAP_NET_RAW=p+e');     unixDomainSocketHandle := -Abs(ErrNo) (* Probably ESysEACCESS             *)   end (* Since we're about to reliquish admin capabilities we won't be able to delete *) (* the socket at program termination.                                         *) end { CreateUnixDomainSocket } ; (* The result of this may be subsequently retrieved using InetDomainSocket().   Assume that any existing socket was deleted when its owner terminated. Create   a fresh Inet Domain socket and save the handle, on failure save an error code.   Both success and failure are silent. *) procedure CreateInetDomainSocket(port: integer); var   sockAddr: TSockAddr; begin   Write(StdErr, 'Creating new Internet domain socket (UDP, port ', port, ')... ');   inetDomainSocketHandle := fpSocket(PF_INET, SOCK_DGRAM, 0);   try     sockAddr.sin_family:= AF_INET;     sockAddr.sin_port:= hToNS(port);     sockAddr.sin_addr.s_addr:= 0;     FillChar(sockAddr.sin_zero[0], SIZEOF(sockAddr.sin_zero), #0);     if fpBind(inetDomainSocketHandle, @sockAddr, SIZEOF(sockAddr)) = 0 then       WriteLn(StdErr, 'OK')     else begin       WriteLn(StdErr, 'failed, might need CAP_DAC_OVERRIDE,CAP_NET_BIND_SERVICE,CAP_NET_RAW=p+e');       inetDomainSocketHandle := -Abs(ErrNo)     end   except     WriteLn(StdErr, 'failed, might need CAP_DAC_OVERRIDE,CAP_NET_BIND_SERVICE,CAP_NET_RAW=p+e');     inetDomainSocketHandle := -Abs(ErrNo)   end (* Assume that this will be deleted automatically at program termination.       *) end { CreateInetDomainSocket } ; QuoteRecall my example from a previous post. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i         debian@ebb:~$ sudo /sbin/ip link set can1 up type can bitrate 250000  debian@ebb:~$ candump can1      can1  721   [1]  05      can1  1A1   [8]  20 00 FF 0F A8 FD A8 FD  ... So in general I get the feeling that to add socketCAN support to FPC will require a fairly extensive modification of the base sockets library.  Is there any interest in this?  Who's allowed to change it.  Noting that you seem to have demonstrated that the "plug-in" nature of the Linux network stack functionality is working properly... are you saying that this is purely an FPC issue rather than a kernel one? At that point I'd expect that a patch via Mantis would be appropriate, particularly since this appears to move FPC and possibly Lazarus into an area that it's not previously supported. MarkMLl ---------------------------------------------------------------------- jcdammeyer · 2020-10-22 08:07 Quote from: MarkMLl on October 22, 2020, 09:44:51 am Noting that you seem to have demonstrated that the "plug-in" nature of the Linux network stack functionality is working properly... are you saying that this is purely an FPC issue rather than a kernel one? At that point I'd expect that a patch via Mantis would be appropriate, particularly since this appears to move FPC and possibly Lazarus into an area that it's not previously supported. MarkMLl Yes for both the BeagleBone and Pi and as I understand pretty well all Linux systems the socketCAN capability works well.  As the attached screen shot generated by the return result from the socket call with PF_CAN as the parameter shows.  PF_CAN doesn't exist so of course it fails.  The PF_CAN with a value of 29 doesn't exist in the definitions for socket.pp or whatever code is ultimately executed.  And the PF can is required so the system knows where to go for the data during a read. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i const  PF_CAN = 29;  CAN_RAW = 1;  Trouble is, GitHub and the associated read me files are so convoluted that I have no idea where to even start much less what to compile (if at all) to be able to duplicate the operation of the C programs.    I could make the changes but I don't know where to start. Here's the example.  I realize bind should probably be used but it doesn't make it past the socket call. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit socketunit; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Sockets, errors; const  PF_CAN = 29;  CAN_RAW = 1; type   { TSocketForm }   TSocketForm = class(TForm)    Button1: TButton;    Edit1: TEdit;    procedure Button1Click(Sender: TObject);  private   public    socket_result : LongInt;    SAddr : TInetSockAddr;    Slen : TSockLen;    sin, sout : text;   end; var  SocketForm: TSocketForm; implementation {$R *.lfm} { TSocketForm } procedure TSocketForm.Button1Click(Sender: TObject);var    i : integer;begin  // open socket  socket_result := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);  if (socket_result < 0) then begin        // perror("socket");    Edit1.text := 'Error #' + IntToStr(socket_result) + ' creating socket';  end  else begin    SAddr.sin_family := PF_CAN;    SAddr.xpad := 'can0';    if fpconnect(socket_result, @SAddr, 0) = -1 then begin      Edit1.text := 'Socket can''t connect: ' + strerror(socketerror);    end;  end;end; end. ---------------------------------------------------------------------- MarkMLl · 2020-10-22 08:45 At the very least I suggest getting a bug report in  suggesting that FPC's definition of PF_INET (and possibly AF_INET?) should be accompanied by one for PF_CAN. However I think that you'd need to make sure that you could provide (links to) the appropriate numeric values for different OSes, since I don't think the numeric values can be relied upon to be constant... you're basically telling the OS how to populate an internal table. MarkMLl ---------------------------------------------------------------------- avra · 2020-10-22 09:15 Quote from: jcdammeyer on October 22, 2020, 10:07:36 amHere's the example.  I realize bind should probably be used but it doesn't make it past the socket call.Because you are trying to use "SAddr : TInetSockAddr;" (C sockaddr) with SocketCAN, while you need to use C sockaddr_can. CAN C headers have not yet been translated to FPC. You will at least need sockaddr_can, ifreq and can_frame structures. You can find ifreq structure in \fpcsrc\packages\libc\src\nifh.inc, but the rest only in /usr/src/linux-source-5.8/include/uapi/linux/can.h and /usr/src/linux-source-5.8/include/uapi/linux/can/ (raw.h, bcm.h, error.h ...) waiting for translation. Btw.1 You do not need CAN_FD for slcan devices since none of them implements faster CAN_FD yet (although CAN_FD is backwards compatible with slow CAN). Btw.2 Did you read my previous message? I still think that socketcand path would be easier for you... ---------------------------------------------------------------------- tetrastes · 2020-10-22 10:39 Quote from: jcdammeyer on October 22, 2020, 10:07:36 amCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     if fpconnect(socket_result, @SAddr, 0) = -1 then begin  Why the third parameter of fpconnect is zero? ---------------------------------------------------------------------- MarkMLl · 2020-10-22 11:29 Quote from: tetrastes on October 22, 2020, 12:39:40 pmQuote from: jcdammeyer on October 22, 2020, 10:07:36 amCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     if fpconnect(socket_result, @SAddr, 0) = -1 then begin  Why the third parameter of fpconnect is zero? Well spotted ;-) For that matter, I have a lot of trouble tying https://www.freepascal.org/docs-html/rtl/sockets/fpconnect.html to anything remotely relevant. MarkMLl ---------------------------------------------------------------------- jcdammeyer · 2020-10-22 17:06 Quote from: avra on October 22, 2020, 09:41:43 amQuote from: jcdammeyer on October 22, 2020, 06:10:48 amSo in general I get the feeling that to add socketCAN support to FPC will require a fairly extensive modification of the base sockets library.PF_CAN is just a number. In linux sources you can find it defined as AF_CAN, which is defined as 29. So why don't you try that first? EDIT: I see now that you are looking at sources of candump. It will be much easier if you use simpler example from here: https://www.beyondlogic.org/example-c-socketcan-code/ True.  And in my example I assigned 29 to PF_CAN.  The beyondlogic example in C translated to pascal still suffers from the same issue that it's not handled in the socket library.  Thank you for that link.  It does simplify the code.  The candump.c has become more complicated with CAN_FD support which I'm not interested in looking at right now.  Especially since it's not supported by the MCP2515 and the BeagleBone internal CAN device nor many of the other existing CANopen modules out there. I don't really want to add what appears to be an extra layer with TCP if I don't have to.  I'll download and compile socketcand to see if it fits in with what I want to do. BTW, under winsock2.pp 29 is allocated to Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   AF_TCNPROCESS   = 29;  AF_TCNMESSAGE   = 30;  AF_ICLFXBM      = 31;   AF_MAX          = 32;  My goal is to make something that runs on Windows, Pi and BeagleBones and other small modules running Linux.  Even LinuxCNC.  Not that concerned about Linux Desktop PCs.  The PC doesn't have the SPI or embedded CAN device so the CANUSB from Lawicel (or equivalent module with identical protocol) is what I'm currently targeting. ---------------------------------------------------------------------- jcdammeyer · 2020-10-22 17:08 Quote from: MarkMLl on October 22, 2020, 01:29:16 pmQuote from: tetrastes on October 22, 2020, 12:39:40 pmQuote from: jcdammeyer on October 22, 2020, 10:07:36 amCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     if fpconnect(socket_result, @SAddr, 0) = -1 then begin  Why the third parameter of fpconnect is zero? Well spotted ;-) For that matter, I have a lot of trouble tying https://www.freepascal.org/docs-html/rtl/sockets/fpconnect.html to anything remotely relevant. MarkMLl Because I never got past the socket call and had not used bind which is what should be used.  Wasn't even worried about fpconnect or the Saddr once I dove down into the socket library and saw that AF_CAN  or PF_CAN equal to 29 was not supported which essentially means the socketCAN library working in C or Python also won't work. ---------------------------------------------------------------------- jcdammeyer · 2020-10-22 17:25 Quote from: tetrastes on October 22, 2020, 12:39:40 pmQuote from: jcdammeyer on October 22, 2020, 10:07:36 amCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     if fpconnect(socket_result, @SAddr, 0) = -1 then begin  Why the third parameter of fpconnect is zero? Awe Crap!  That's what I get for leaving a project for 2 months and then jumping back in not remembering where I stopped.  In fact both you and Mark are correct that I'm using fpconnect incorrectly. My mistake is that I though I didn't make it past the socket call which I do and returns 11 and not a value < 0.  OK.  Some steps backwards and then I'll report what I've discovered.  Sheesh. Newbie type mistake... ---------------------------------------------------------------------- avra · 2021-02-22 14:41 For a start, I would like to update fpc's linux kernel header translations with missing AF_CAN, PF_CAN and some other constants. Needed kernel header is at Quote/usr/src/linux- headers-5.10.0-0.bpo.3-common/include/linux/socket.hand I want to update file Quotefpcsrc/packages/rtl-extra/src/linux/unxsockh.inc Should I also update Quotefpcsrc/packages/rtl-extra/src/android/unxsockh.incas well? I only intend to test linux... ---------------------------------------------------------------------- MarkMLl · 2021-02-22 14:56 Quote from: avra on February 22, 2021, 03:41:43 pmFor a start, I would like to update fpc's linux kernel header translations with missing AF_CAN, PF_CAN and some other constants. ... I only intend to test linux... Noting that the AF_ and PF_ constants are used by user and/or kernel code to express an interest in a particular protocol facet, and that there aren't helpers to extend enumerations and subranges, I think that as a matter of policy they're worth getting into header files etc. as soon as they are standardised by the IETF or whoever's authoritative. MarkMLl ---------------------------------------------------------------------- jcdammeyer · 2021-02-23 02:44 For now this project is on hold for while I catch up on a few others.  I'm working on a project that uses the TI TMS320F28379D and the CAN bus and Quadrature encoder interface.  Also not quite finished a CNC mill conversion.  https://youtu.be/I6lvnYhlez4 When I get a few of these other projects out of the way I'll come back to Lazarus and see about the sockets and socketCAN. ---------------------------------------------------------------------- avra · 2021-02-23 07:19 Quote from: MarkMLl on February 22, 2021, 03:56:43 pmQuote from: avra on February 22, 2021, 03:41:43 pmFor a start, I would like to update fpc's linux kernel header translations with missing AF_CAN, PF_CAN and some other constants. ... I only intend to test linux... Noting that the AF_ and PF_ constants are used by user and/or kernel code to express an interest in a particular protocol facet, and that there aren't helpers to extend enumerations and subranges, I think that as a matter of policy they're worth getting into header files etc. as soon as they are standardised by the IETF or whoever's authoritative.Those constants are only a start. I searched FPC files for them, and found where they are and what should be updated. I need a little guiding since it is not simple 1:1 header translation and there is a split into several files - probably because of cross platforming. Only when this work is finished, can and j1939 can build on them. As for the standardization... well, I don't know what to say. Try to search in sources for AF_BLUETOOTH and you will see that in some operating systems it is defined as 31 and in some as 36. It seams to be OS dependent and not tied to some standard... ---------------------------------------------------------------------- MarkMLl · 2021-02-23 07:33 Quote from: avra on February 23, 2021, 08:19:58 amAs for the standardization... well, I don't know what to say. Try to search in sources for AF_BLUETOOTH and you will see that in some operating systems it is defined as 31 and in some as 36. It seams to be OS dependent and not tied to some standard... Hmmm. Another of those things like the data returned by a stat() call, where OSes varied and Linux tried to follow the dominant OS on each platform. I obviously knew that the numerical value of AF_ and PF_ couldn't be trusted to be the same, but I'd assumed that ultimately they were traceable to IETF or similar... I was obviously wrong. MarkMLl ---------------------------------------------------------------------- jcdammeyer · 2021-02-23 07:41 The issue isn't only the AF_CAN and PF_CAN.  The lower levels need to deal with the socketCAN infrastructure.  The best way to do this is to research what happens with AF_CAN and PF_CAN in sockets.c.  The socketCAN interface has been usable in Linux now for almost 10 years.  In fact the newest code I was looking at now also supports CANFD which is an enhancement to the original CAN protocol that supports larger messages at higher data rates for the data part. Even if CANFD was not supported initially I suspect the best thing to do is to port the socketCAN section from the C code to the pascal side.  Then rewrite, again without the CANFD support, the command line applications that are written in C like candump. The candump application is clever enough to know the difference between a Lawicel CANUSB dongle and say the SPI based Pi MCP2515 or the Beagle embledded CAN device.  In both cases those devices show up as files that can be opened. To do most of this one doesn't have to actually know much about CAN, although it's useful, but mostly about how Linux handles devices that are files and how the socket communications deals with them.  It's on my do list. John ---------------------------------------------------------------------- avra · 2021-02-23 13:48 Quote from: jcdammeyer on February 23, 2021, 08:41:44 amThe issue isn't only the AF_CAN and PF_CAN...That's why I said that updating socket wrapper with new constants is just a first step. Next step would be CAN through SocketCAN (not via socketcand daemon which already allows us to connect to CAN using ethernet), and after that SAE J1939 which is a layer on top of CAN. That's what I'm after. CAN FD is not in my focus, but I will probably add it, too. ---------------------------------------------------------------------- jcdammeyer · 2021-02-23 17:23 Quote from: avra on February 23, 2021, 02:48:05 pmQuote from: jcdammeyer on February 23, 2021, 08:41:44 amThe issue isn't only the AF_CAN and PF_CAN...That's why I said that updating socket wrapper with new constants is just a first step. Next step would be CAN through SocketCAN (not via socketcand daemon which already allows us to connect to CAN using ethernet), and after that SAE J1939 which is a layer on top of CAN. That's what I'm after. CAN FD is not in my focus, but I will probably add it, too. My focus will be CANopen with a monitor program that runs equally well on PCs with Windows, LinuxCNC, Pi and Beagles.  But I've worked with all sorts of CAN protocols.. http://www.autoartisans.com/rings/9S12-Controller.jpg  This M9S12 has 5 CAN channels and I've used it on one project that had a proprietary protocol on one channel, CANopen on two more actiing as bridge and two J1939, one to servo motors and one to the vehicle for engine RPM and transmission status.   Software on the PC to interface to this was done with Delphi to the USB port This module here http://www.autoartisans.com/CAN/STU-2.jpg runs a PiZeroW and includes a PIC32 for the high speed CAN buffering and then SPI.  C software with pipes etc. to log CAN messages from an electric vehicle into Pi Linux.  I had to use C for that.  Would have been nice to be able to use Lazarus. Both those projects are for clients so I can't disclose details.  But there are lots of other projects on the go that will be published for playing with CAN and Pi or BBB. ---------------------------------------------------------------------- avra · 2021-03-02 12:55 CAN constants have been added to FPC 48867: https://svn.freepascal.org/svn/fpc/trunk/packages/rtl- extra/src/linux/unxsockh.inc Also other stuff not related to CAN has been added from .../include/linux/socket.h in Linux 5.10 headers. Proceeding further steps... UPDATE: Upon user's request here is a working link to this file in new gitlab repo: https://gitlab.com/freepascal.org/fpc/source/-/blob/main/packages/rtl- extra/src/linux/unxsockh.inc ---------------------------------------------------------------------- jcdammeyer · 2021-03-02 17:25 Awesome.  You've probably already seen this but for convenience here's the link: https://www.beyondlogic.org/example-c-socketcan-code I guess for example one would take the C code and create a Lazarus command line version of candump called pcandump to avoid mixing things up.  But it needs that sockets.pp (I think that was the file) modified to understand the AF_CAN and PF_CAN constants. https://elinux.org/Can-utils The above link is to an example which has a link to the source which has a link to the doc. ---------------------------------------------------------------------- avra · 2021-03-03 08:54 Quote from: jcdammeyer on March 02, 2021, 06:25:31 pmAwesome.  You've probably already seen this but for convenience here's the link: https://www.beyondlogic.org/example-c-socketcan-codeThat is the link I gave in my first reply to this topic.  Quote from: jcdammeyer on March 02, 2021, 06:25:31 pmI guess for example one would take the C code and create a Lazarus command line version of candump called pcandump to avoid mixing things up.My initial goal would be to make pascal versions of cantransmit, canreceive and canfilter from https://github.com/craigpeacock/CAN- Examples. Then I would probably move to J1939. Quote from: jcdammeyer on March 02, 2021, 06:25:31 pmBut it needs that sockets.pp (I think that was the file) modified to understand the AF_CAN and PF_CAN constants.Already done. With latest trunk you simply include sockets and those constants are available. Quote from: jcdammeyer on March 02, 2021, 06:25:31 pmhttps://elinux.org/Can-utils The above link is to an example which has a link to the source which has a link to the doc.I am familiar with that, too. I am the author of https://github.com/linux-can/can-utils/blob/master/can-j1939-install- kernel-module.md ---------------------------------------------------------------------- jcdammeyer · 2021-03-03 18:11 Quote from: avra on March 03, 2021, 09:54:10 amQuote from: jcdammeyer on March 02, 2021, 06:25:31 pmhttps://elinux.org/Can-utils The above link is to an example which has a link to the source which has a link to the doc. I am familiar with that, too. I am the author of https://github.com/linux-can/can-utils/blob/master/can-j1939-install- kernel-module.md  Nice write-up on the install of can-J1939.  I like the fact that you explain how to fix it when it goes wrong.  So many people leave that out of their description. ---------------------------------------------------------------------- avra · 2021-03-04 11:05 Quote from: jcdammeyer on March 03, 2021, 07:11:19 pmNice write-up on the install of can-J1939.  I like the fact that you explain how to fix it when it goes wrong.  So many people leave that out of their description. Thanks, you're very kind. I'm glad you like it. ---------------------------------------------------------------------- avra · 2021-03-08 10:12 Here is Linux SocketCAN wrapper. Not a full one yet, but enough to be able to compile 1:1 pascal version of https://github.com/craigpeacock/CAN- Examples/blob/master/cantransmit.c. It compiles, however something is wrong since with pascal version during runtime binding: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     if fpbind(s, @addr, sizeof(addr)) < 0 then I get socket error 88 (ESysENOTSOCK - Socket operation on non-socket). C version of cantransmit example binds without problems and sends good data to canreceive, and I can also see with other sniffing tools that SocketCAN messaging is working. Could someone please take a closer look at this "Socket operation on non-socket" problem? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program cantransmit; {$mode delphi} {$H+} uses  cthreads, classes, sysutils, sockets, unixtype, baseunix, can; procedure PError(const S : string);begin  WriteLn(S, ', SocketError = ', SocketError);end; var  s:     cint = 0;  addr:  sockaddr_can;  ifr:   ifreq;  frame: can_frame;begin  try    Writeln('CAN Sockets Demo');    if fpsocket(PF_CAN, SOCK_RAW, CAN_RAW) < 0 then    begin      perror('Socket');      Exit;    end;     ifr.ifr_name := 'vcan0' ;    fpioctl(s, SIOCGIFINDEX, @ifr);     memset(@addr, 0, sizeof(addr));  addr.can_family := AF_CAN;    addr.can_ifindex := ifr.ifr_ifindex;   if fpbind(s, @addr, sizeof(addr)) < 0 then    //if fpbind(s, Psockaddr(@addr), sizeof(addr)) < 0 then    begin      perror('Bind');      Exit;    end;     frame.can_id   := $555;    frame.can_dlc  := 5;    frame.datatext := 'Hello'; // datatext field is a variant record of chars overlaying data field     if fpwrite(s, frame, sizeof(can_frame)) <> sizeof(can_frame) then    begin      perror('Write');      Exit;    end;     if fpclose(s) < 0 then    begin      perror('Close');      Exit;    end;   except    on e:Exception do      WriteLn(e.Message);  end;end.  Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i #include #include #include #include  #include #include #include  #include #include  int main(int argc, char **argv){        int s;         struct sockaddr_can addr;        struct ifreq ifr;        struct can_frame frame;         printf("CAN Sockets Demo\r\n");         if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {                perror("Socket");              return 1;        }         strcpy(ifr.ifr_name, "vcan0" );        ioctl(s, SIOCGIFINDEX, &ifr);         memset(&addr, 0, sizeof(addr));        addr.can_family = AF_CAN;        addr.can_ifindex = ifr.ifr_ifindex;         if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {                perror("Bind");                return 1;        }         frame.can_id = 0x555;        frame.can_dlc = 5;        sprintf(frame.data, "Hello");         if (write(s, &frame, sizeof(struct can_frame)) != sizeof(struct can_frame)) {              perror("Write");                return 1;        }         if (close(s) < 0) {                perror("Close");                return 1;        }         return 0;} As you can see in code, I am using virtual vcan0 which you can create yourself if you follow instructions from https://www.elinux.org/Bringing_CAN_interface_up. If needed sniffing tools can be found at https://www.elinux.org/Can- utils. p.s. You need either trunk FPC, or you need to define missing CAN constants yourself as explained earlier in this thread. UPDATE: The problem remains even when doing one of these: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     memset(@ifr, 0, sizeof(ifr));Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     ifr.ifr_name := 'vcan0' + #0; ---------------------------------------------------------------------- avra · 2021-03-08 11:15 It looks like the problem is in fpioctl() call since this modified code: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     strcopy(ifr.ifr_name, 'vcan0');    WriteLn('before fpioctl: ifr.ifr_ifindex = ', ifr.ifr_ifindex);    if fpioctl(s, SIOCGIFINDEX, @ifr) < 0 then // SIOCGIFINDEX = $8933;    begin      WriteLn('after fpioctl: ifr.ifr_ifindex = ', ifr.ifr_ifindex);      WriteLn('fpGetErrno = ', fpGetErrno);      perror('IOctl');      Exit;    end;exits with fpGetErrno = 25 and I can see that ifr.ifr_ifindex = 0 which tells me that vcan0 was not found at all, while this modified part of C code: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   strcpy(ifr.ifr_name, "vcan0" );  int i;  i = ioctl(s, SIOCGIFINDEX, &ifr);  if (i < 0){    perror("ioctl");    return 1;  };  printf("ioctl() = %d\n", i);  printf("ifr.ifr_ifindex = %d\n", ifr.ifr_ifindex);  works well with ioctl() = 0 and ifr.ifr_ifindex = 3 which tells me that vcan0 was found properly. So, is this a bug related to fpioctl() ??? UPDATE: No, it was not a bug in fpioctl(). Silly me, I forgot to get a handle in the first place.  I will provide working cantransmit a little later... ---------------------------------------------------------------------- avra · 2021-03-08 13:44 Here is a fully working SocketCAN transmit demo. First ever with FreePascal.  Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program cantransmit; {$mode delphi} {$H+} uses  cthreads, classes, sysutils, sockets, unixtype, baseunix, can; procedure PError(const S : string);begin  WriteLn(S, ', SocketError = ', SocketError);end; var  s:     cint = 0;  addr:  sockaddr_can;  ifr:   ifreq;  frame: can_frame;begin  try    Writeln('CAN Sockets Transmit Demo');    s := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);    if s < 0 then    begin      perror('Socket');      Exit;    end;     strcopy(ifr.ifr_name, 'vcan0'); // ifr.ifr_name := 'vcan0' + #0;     if fpioctl(s, SIOCGIFINDEX, @ifr) < 0 then    begin      perror('IOctl');      Exit;    end;     memset(@addr, 0, sizeof(addr));    addr.can_family := AF_CAN;    addr.can_ifindex := ifr.ifr_ifindex;     if fpbind(s, @addr, sizeof(addr)) < 0 then // equals to: if fpbind(s, Psockaddr(@addr), sizeof(addr)) < 0 then    begin      perror('Bind');      Exit;    end;     frame.can_id   := $555;    frame.can_dlc  := 5;    frame.datatext := 'Hello'; // datatext field is a variant record of chars overlaying data field     if fpwrite(s, frame, sizeof(can_frame)) <> sizeof(can_frame) then    begin      perror('Write');      Exit;    end;     if fpclose(s) < 0 then    begin      perror('Close');      Exit;    end;   except    on e:Exception do      WriteLn(e.Message);  end;end. ---------------------------------------------------------------------- avra · 2021-03-08 14:34 Also fully working SocketCAN receive demo. Enjoy!  Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program canreceive; {$mode delphi} {$H+} uses  cthreads, classes, sysutils, sockets, unixtype, baseunix, can; procedure PError(const S : string);begin  WriteLn(S, ', SocketError = ', SocketError);end; var  s, i, nbytes: cint;  addr:  sockaddr_can;  ifr:   ifreq;  frame: can_frame;begin  try    Writeln('CAN Sockets Receive  Demo');    s := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);    if s < 0 then    begin      perror('Socket');      Exit;    end;     strcopy(ifr.ifr_name, 'vcan0'); // ifr.ifr_name := 'vcan0' + #0;     if fpioctl(s, SIOCGIFINDEX, @ifr) < 0 then    begin      perror('IOctl');      Exit;    end;     memset(@addr, 0, sizeof(addr));    addr.can_family := AF_CAN;    addr.can_ifindex := ifr.ifr_ifindex;     if fpbind(s, @addr, sizeof(addr)) < 0 then // equals to: if fpbind(s, Psockaddr(@addr), sizeof(addr)) < 0 then    begin      perror('Bind');      Exit;    end;     nbytes := fpread(s, frame, sizeof(can_frame));    if nbytes < 0 then begin      perror('Read');    Exit;    end;     Write(format('0x%03X [%d] ', [frame.can_id, frame.can_dlc]));    for i := 0 to frame.can_dlc - 1 do      Write(Format('%02X ', [frame.data[i]]));    WriteLn('');     if fpclose(s) < 0 then    begin      perror('Close');      Exit;    end;   except    on e:Exception do      WriteLn(e.Message);  end;end. ---------------------------------------------------------------------- avra · 2021-03-09 12:48 SocketCAN filter demo:  Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program canfilter; {$mode delphi} {$H+} uses  cthreads, classes, sysutils, sockets, unixtype, baseunix, can, can.raw; procedure PError(const S : string);begin  WriteLn(S, ', SocketError = ', SocketError);end; var  s, i, nbytes: cint;  addr:         sockaddr_can;  ifr:          ifreq;  frame:        can_frame;  rfilter:      array[0..1] of can_filter;begin  try    Writeln('CAN Sockets Filter Demo');    s := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);    if s < 0 then    begin      perror('Socket');      Exit;    end;     strcopy(ifr.ifr_name, 'vcan0'); // ifr.ifr_name := 'vcan0' + #0;    if fpioctl(s, SIOCGIFINDEX, @ifr) < 0 then    begin      perror('IOctl');      Exit;    end;     memset(@addr, 0, sizeof(addr));    addr.can_family  := AF_CAN;    addr.can_ifindex := ifr.ifr_ifindex;     if fpbind(s, @addr, sizeof(addr)) < 0 then // if fpbind(s, Psockaddr(@addr), sizeof(addr)) < 0 then    begin      perror('Bind');      Exit;    end;     rfilter[0].can_id   := $550; // 1st CAN ID    rfilter[0].can_mask := $7F0; // 1st CAN MASK matches all frames with identifiers from $550 to $55F    rfilter[1].can_id   := $200; // 2nd CAN ID    rfilter[1].can_mask := $7FF; // 2nd CAN MASK matches only frames with identifier equal to $200 and nothing else     fpsetsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, @rfilter, sizeof(rfilter));     nbytes := fpread(s, frame, sizeof(can_frame));  if nbytes < 0 then begin      perror('Read');      Exit;    end;     Write(format('0x%03X [%d] ', [frame.can_id, frame.can_dlc]));    for i := 0 to frame.can_dlc - 1 do      Write(Format('%02X ', [frame.data[i]]));    WriteLn('');     if fpclose(s) < 0 then    begin      perror('Close');      Exit;    end;   except    on e:Exception do      WriteLn(e.Message);  end;end. ---------------------------------------------------------------------- avra · 2021-03-11 08:53 Finished conversion of all linux CAN headers (can, can.bcm, can.error, can.gw, can.isotp, can.j1939, can.netlink, can.raw and can.vxcan). I will see if I can shape it a little bit more, add some more demos, and prepare a patch for bug tracker. Demos for can and can.raw are already given, so I will probably add can.bcm and can.j1939 demos. If anyone is interested to contribute some other demos send me a PM and I will provide all header translations. I guess that CAN support should be shaped as a FP package. That way it shall work out of the box with FP, as it already does with Python and C. I should have done this a long time ago. Python and C are fine but there is no fun in that. ---------------------------------------------------------------------- ThomasK · 2021-03-11 14:01 Hi, can you tell me where I can finde the required can and can.raw units you use in your solutions (Send ,receive, filter)? Thanks and Best Regards, Thomas ---------------------------------------------------------------------- avra · 2021-03-11 14:11 Quote from: ThomasK on March 11, 2021, 03:01:32 pmHi, can you tell me where I can finde the required can and can.raw units you use in your solutions (Send ,receive, filter)?Translated headers can be found in cantransmit.zip attached to message: https://forum.lazarus.freepascal. org/index.php/topic,39858.msg396883.html#msg396883. In just few days there have been almost 200 downloads.  Since I have updated them a little, I have attached latest version of demos and all translated headers to this message. Quote from: ThomasK on March 11, 2021, 03:01:32 pmThanks and Best RegardsYou're most welcome. ---------------------------------------------------------------------- avra · 2021-03-11 14:12 @jcdammeyer: CAN FD receive and transmit demos are here.  It was not trivial to find info of what exactly to change when compared to legacy CAN but it works now. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i /////////// ////////////////////////////////////////////////////////////////////// ///                                                                            ////  This is a SocketCAN demo converted from C to Pascal by Zeljko Avramovic.    ////  Original code has GNU General Public License v3.0 and can be found at       ////  https://github.com/craigpeacock/CAN-Examples                              ////                                                                            ////  Virtual CAN adapter vcan0 is hard coded and you can bring it up like this:  ////  sudo modprobe vcan                                                        ////  sudo ip link add dev vcan0 type vcan                                        ////  sudo ip link set vcan0 mtu 72            # needed for CAN FD                ////  sudo ip link set vcan0 up                                                 ////                                                                            /////////////////////////////////////////////// ///////////////////////////////////// program canfdtransmit; {$mode delphi} {$H+} uses  cthreads, classes, sysutils, sockets, baseunix, can, can.raw; procedure perror(const S : string);begin  WriteLn(S, ', SocketError = ', SocketError);end; var  s, err: cint;  addr:   sockaddr_can;  ifr:    ifreq;  frame:  canfd_frame;begin  try    Writeln('CAN FD Sockets Transmit Demo');    s := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);    if s < 0 then    begin      if s = ESysENOPROTOOPT then        Writeln('CAN_RAW_FD_FRAMES socket option is not supported. Your kernel is probably too old.');      perror('Socket');      Exit;    end;     strcopy(ifr.ifr_name, 'vcan0');    if fpioctl(s, SIOCGIFINDEX, @ifr) < 0 then    begin      perror('IOctl');      Exit;    end;     memset(@addr, 0, sizeof(addr));    addr.can_family  := AF_CAN;    addr.can_ifindex := ifr.ifr_ifindex;     if fpbind(s, @addr, sizeof(addr)) < 0 then    begin      perror('Bind');      Exit;    end;     frame.can_id := $444;    // CAN FD message ID    frame.len    := 20;      // payload length will be 20 bytes    frame.data   := [$01, $02, $03, $04, $05, $06, $07, $08, $09, $0A, $0B, $0C, $0D, $0E, $0F, $10,                   $11, $12, $13, $14, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,                     $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,                     $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00];                     // shows as '0x444 [40] 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14' in canfdreceive    {    frame.data[0]  := $01; // alternative for the above    frame.data[1]  := $02; // shows as '0x444 [40] 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14' in canfdreceive    frame.data[2]  := $03;    frame.data[3]  := $04;    frame.data[4]  := $05;    frame.data[5]  := $06;    frame.data[6]  := $07;    frame.data[7]  := $08;    frame.data[8]  := $09;    frame.data[9]  := $0A;    frame.data[10] := $0B;    frame.data[11] := $0C;    frame.data[12] := $0D;    frame.data[13] := $0E;    frame.data[14] := $0F;    frame.data[15] := $10;    frame.data[16] := $11;    frame.data[17] := $12;    frame.data[18] := $13;    frame.data[19] := $14;    }     err := fpsetsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, @ENABLE_CAN_OPTION, sizeof(ENABLE_CAN_OPTION));    if err <> 0 then    begin      if err = ESysENOPROTOOPT then        WriteLn('CAN FD Protocol not available. Try newer kernel');      perror('SetSockopt');      Exit;    end;     if fpwrite(s, frame, sizeof(canfd_frame)) <> sizeof(canfd_frame) then    begin      perror('Write');      Exit;    end;     if fpclose(s) < 0 then    begin      perror('Close');      Exit;    end;   except    on e:Exception do      WriteLn(e.Message);  end;end. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i /////////// ////////////////////////////////////////////////////////////////////// ///                                                                            ////  This is a SocketCAN demo converted from C to Pascal by Zeljko Avramovic.    ////  Original code has GNU General Public License v3.0 and can be found at       ////  https://github.com/craigpeacock/CAN-Examples                              ////                                                                            ////  Virtual CAN adapter vcan0 is hard coded and you can bring it up like this:  ////  sudo modprobe vcan                                                        ////  sudo ip link add dev vcan0 type vcan                                        ////  sudo ip link set vcan0 mtu 72            # needed for CAN FD                ////  sudo ip link set vcan0 up                                                 ////                                                                            /////////////////////////////////////////////// ///////////////////////////////////// program canfdreceive; {$mode delphi} {$H+} uses  cthreads, classes, sysutils, sockets, unixtype, baseunix, can, can.raw; procedure perror(const S : string);begin  WriteLn(S, ', SocketError = ', SocketError);end; var  s, i, nbytes, err: cint;  addr:              sockaddr_can;  ifr:               ifreq;  frame:             canfd_frame;begin  try    Writeln('CAN FD Sockets Receive Demo');    s := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);  if s < 0 then    begin      perror('Socket');      Exit;    end;     strcopy(ifr.ifr_name, 'vcan0'); // ifr.ifr_name := 'vcan0' + #0;    if fpioctl(s, SIOCGIFINDEX, @ifr) < 0 then    begin      perror('IOctl');      Exit;    end;     memset(@addr, 0, sizeof(addr));    addr.can_family  := AF_CAN;    addr.can_ifindex := ifr.ifr_ifindex;     if fpbind(s, @addr, sizeof(addr)) < 0 then    begin      perror('Bind');      Exit;    end;     err := fpsetsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, @ENABLE_CAN_OPTION, sizeof(ENABLE_CAN_OPTION));    if err <> 0 then    begin      if err = ESysENOPROTOOPT then        WriteLn('CAN FD Protocol not available. Try newer kernel');      perror('SetSockopt');      Exit;    end;     nbytes := fpread(s, frame, sizeof(canfd_frame));    if nbytes < 0 then    begin      perror('Read');      Exit;    end;    if nbytes < sizeof(can_frame) then // paranoid check    begin      perror('Read: Incomplete CAN frame');      Exit;    end;     if nbytes = CANFD_MTU then      WriteLn('CAN FD frame received with length ', IntToStr(frame.len))    else if nbytes = CAN_MTU then      WriteLn('CAN legacy frame received with length ', IntToStr(frame.len))    else      WriteLn('Invalid CAN(FD) frame received');     Write(format('0x%03X [%d] ', [frame.can_id, frame.len]));    for i := 0 to frame.len - 1 do      Write(Format('%02.2X ', [frame.data[i]]));    WriteLn('');     if fpclose(s) < 0 then    begin      perror('Close');      Exit;    end;   except    on e:Exception do      WriteLn(e.Message);  end;end. ---------------------------------------------------------------------- ThomasK · 2021-03-11 14:26 Quote from: avra on March 11, 2021, 03:11:35 pm You're most welcome.  Thanks a lot. I recently started progamming Pascal again. I started in 1977 on a Siemens 4004/151 with punch cards..... My first application runs on a Pi. ---------------------------------------------------------------------- Fred vS · 2021-03-11 14:33 @Avra: Wonderful! (like always with you  ) Many thanks. Fre;D ---------------------------------------------------------------------- avra · 2021-03-11 14:41 Quote from: Fred vS on March 11, 2021, 03:33:57 pm@Avra: Wonderful! (like always with you  ) Many thanks.You're very kind and you're most welcome.  You can test canfdreceive either with provided canfdtransmit, or you can use can-utils like this: for legacy CAN: Quotecansend vcan0 456#DEADBEEF for CAN FD: Quotecansend vcan0 123##1112233445566778899AABBCC for CAN XL: QuoteJust kidding  . CAN XL is in testing phase and linux is not ready for it yet. But according to specification it should be compatible to CAN FD so we do not have to worry for now... ---------------------------------------------------------------------- sstvmaster · 2021-03-11 16:08 @Avra: Many thanks. Wouldn't it be better to upload your work to Bitbucket, Github, ..., and make an own repo for that? Rgr Maik ---------------------------------------------------------------------- avra · 2021-03-12 06:53 Quote from: sstvmaster on March 11, 2021, 05:08:33 pm@Avra: Many thanks.You're most welcome. I'm glad it's of use to others.  Quote from: sstvmaster on March 11, 2021, 05:08:33 pmWouldn't it be better to upload your work to Bitbucket, Github, ..., and make an own repo for that?This is just a temporary public playground. My final goal is to make SocketCAN header translations and demos integral part of FreePascal, so that CAN works out of the box without downloading anything additional. Like Python and C already have. So far my development and testing is on Debian x86-64 via vcan, using can-utils and Kayak. I will probably also test it on Manjaro x86-64. While I do intend to test it with real hardware on Raspbery Pi and PocketBeagle in the future, I would appreciate any testing feedback I can get now. Especially on 32 and 64 bit ARM - even with just vcan. ---------------------------------------------------------------------- avra · 2021-03-15 13:43 Here is SocketCAN BCM cyclic demo where you let kernel take care of sending interval. Enjoy!  Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i /////////// ////////////////////////////////////////////////////////////////////// ///                                                                            ////  This is a SocketCAN BCM cyclic demo created by Zeljko Avramovic             ////  FPC modified LGPL licence: https://wiki.freepascal.org/FPC_modified_LGPL    ////                                                                            ////  Virtual CAN adapter vcan0 is hard coded and you can bring it up like this:  ////  sudo modprobe vcan                                                        ////  sudo ip link add dev vcan0 type vcan                                      ////  sudo ip link set vcan0 mtu 72          # needed for CAN FD                ////  sudo ip link set vcan0 up                                                   ////                                                                            ////// ////////////////////////////////////////////////////////////////////// //////// program cancyclic; {$mode delphi} {$H+} uses  cthreads, classes, sysutils, sockets, baseunix, crt, can, can.bcm; type  bcm_msg = record    head: bcm_msg_head_without_frames; // we shall use more then 1 frame so bcm_msg_head is not enough    frame: array[0..2] of can_frame;   // and we add here space for our 3 frames  end; procedure perror(const S : string);begin  WriteLn(S, ', SocketError = ', SocketError);end; var  s, i: cint;  addr: sockaddr_can;  ifr:  ifreq;  msg:  bcm_msg;begin  try    Writeln('CAN Sockets BCM Cyclic Demo');  s := fpsocket(PF_CAN, SOCK_DGRAM, CAN_BCM);    if s < 0 then    begin      perror('Socket');      Exit;    end;     strcopy(ifr.ifr_name, 'vcan0'); // ifr.ifr_name := 'vcan0' + #0;    if fpioctl(s, SIOCGIFINDEX, @ifr) < 0 then    begin      perror('IOctl');      Exit;    end;     memset(@addr, 0, sizeof(addr));    addr.can_family  := AF_CAN;    addr.can_ifindex := ifr.ifr_ifindex;     if fpconnect(s, @addr, sizeof(addr)) < 0 then    begin      perror('Connect');      Exit;    end;     msg.head.opcode        := TX_SETUP;    msg.head.can_id        := $567; // if TX_CP_CAN_ID flag is set then all messages shall have this CAN ID    msg.head.flags       := SETTIMER OR STARTTIMER OR TX_ANNOUNCE {OR TX_CP_CAN_ID} {OR TX_RESET_MULTI_IDX};    msg.head.nframes       := 3;    msg.head.count         := 0; // single interval (use only ival2)    msg.head.ival1.tv_sec  := 0;    msg.head.ival1.tv_usec := 0;    msg.head.ival2.tv_sec  := 0;    msg.head.ival2.tv_usec := 250000; // 250 ms interval between CAN messages    msg.frame[0].can_id    := $550; // not used if TX_CP_CAN_ID falg is set    msg.frame[0].can_dlc := 2;    msg.frame[0].data      := [$01,$02,$03,$04,$05,$06,$07,$08];    msg.frame[1].can_id    := $551; // not used if TX_CP_CAN_ID falg is set    msg.frame[1].can_dlc   := 4;    msg.frame[1].data      := [$11,$12,$13,$14,$15,$16,$17,$18];    msg.frame[2].can_id    := $552; // not used if TX_CP_CAN_ID falg is set    msg.frame[2].can_dlc   := 8;    msg.frame[2].data      := [$21,$22,$23,$24,$25,$26,$27,$28];     if fpwrite(s, msg, sizeof(msg)) <> sizeof(msg) then    begin      perror('Write');      Exit;    end;     repeat      WriteLn('Press any key to stop...');      msg.frame[2].DataByte[0] := msg.frame[2].DataByte[0] + 1;      for i := 0 to msg.frame[2].can_dlc - 1 do        Write(Format('%02.2X ', [msg.frame[2].data[i]]));      WriteLn('');      WriteLn('');      fpwrite(s, msg, sizeof(msg)); // comment out this line if you do not want to publish changed frame[2]      Delay(2000); // loop every 2 seconds    until KeyPressed;     if fpclose(s) < 0 then    begin      perror('Close');      Exit;    end;   except    on e:Exception do    WriteLn(e.Message);  end;end. ---------------------------------------------------------------------- radek · 2021-03-16 00:01 Hi, I apologize in advance for my English, I am also interested in the implementation of CAN for Lazarus. I wonder what the performance difference will be if I use: 1) This solution via SocketCAN 2) Direct control of IC MCP2518 via SPI bus using Lazarus 3) Direct control of IC MCP2518 via USB using IC MCP2210 (USB to SPI driver) libusb I'm interested because I want the application to work under both Windows and Linux. When I use MCP2210 and MCP2518, I can control the CAN driver via SPI directly in Windows and Linux. If I use SocketCAN, then I have to implement another solution for Windows. ---------------------------------------------------------------------- avra · 2021-03-16 07:35 Quote from: radek on March 16, 2021, 01:01:29 amI am also interested in the implementation of CAN for Lazarus.Nice to hear  Quote from: radek on March 16, 2021, 01:01:29 amI wonder what the performance difference will be if I use: 1) This solution via SocketCAN 2) Direct control of IC MCP2518 via SPI bus using Lazarus 3) Direct control of IC MCP2518 via USB using IC MCP2210 (USB to SPI driver) libusbAny modern PC or SBC CPU is capable of handling CAN without problems. Bottleneck is communication channel. In case of Lawicel/SLCAN/CAN232 it is serial communication - if you use classic AVR ATMEGA328 based Arduino it is 115200 (STM32 or ESP32 based ones may use speeds higher then that so they do not have that problem), you don't use filters and want to see all of high speed CAN traffic then expect to miss frames here and there. Using MCP2518 direct via SPI on Raspberry Pi or PocketBeagle for CAN and CAN FD is solid and comfortable. I haven't used MCP2518 over MCP2210 but I guess that might also skip frames. SocketCAN is just a Berkeley sockets abstraction layer over any Linux CAN hardware, and you use it the same with both SPI MCP2518 and Lawicel/SLCAN/CAN232 (there is no driver for MCP2518 over MCP2210). So, performance does not suffer if you use SocketCAN. Quote from: radek on March 16, 2021, 01:01:29 amI'm interested because I want the application to work under both Windows and Linux. When I use MCP2210 and MCP2518, I can control the CAN driver via SPI directly in Windows and Linux. If I use SocketCAN, then I have to implement another solution for Windows.Well, you said it all. Since you want your app to be used on both Windows and Linux, unfortunately you need to give up SocketCAN (unless someone implements it under Windows). Your best bet would be to use some STM32 or ESP32 Lawicel/SLCAN/CAN232 using higher serial speeds, which would probably avoid frame dropping unless you use it on a very, very high traffic 1Mbit CAN. Also take a look at this discussion: https://forum.lazarus.freepascal. org/index.php/topic,51477.msg377993.html#msg377993 ---------------------------------------------------------------------- radek · 2021-03-16 11:19 Just to add, the MCP2210 is a High Speed USB HID driver for the SPI bus with speeds from 1500bps to 12Mbps, so there will be no bottleneck. The only problem is that I need to constantly read the 64 byte register to see if the MCP2518 has received any data, this may cause some CPU usage. ---------------------------------------------------------------------- avra · 2021-03-16 13:08 Quote from: radek on March 16, 2021, 12:19:30 pmJust to add, the MCP2210 is a High Speed USB HID driver for the SPI bus with speeds from 1500bps to 12Mbps, so there will be no bottleneck. The only problem is that I need to constantly read the 64 byte register to see if the MCP2518 has received any data, this may cause some CPU usage.It doesn't matter how fast you set it's SPI to talk to CAN chip. It seams to use USB HID, which is limited to 1000 messages per second where each message can have up to 64 bytes. You do the math. Ah yes, and while you are transferring data over USB you can not get new CAN messages. https://github.com/daniel-santos/mcp2210-linux/issues/11 ---------------------------------------------------------------------- joelucsd · 2021-03-23 21:23 Thank you for the work to get the CANsocket working.  I pulled in the files from can.zip and it worked.  I am using an older version of FPC on the raspberry Pi.  The example worked.  I used that code as a template for my Lazarus project. I needed an Extended ID.  Will look at that tomorrow.  Might just need to set the extended ID manually before stuffing the value into the frame field. Regards, Joel ---------------------------------------------------------------------- avra · 2021-03-25 07:28 Quote from: joelucsd on March 23, 2021, 10:23:02 pmThank you for the work to get the CANsocket working.You're most welcome.  Quote from: joelucsd on March 23, 2021, 10:23:02 pmI pulled in the files from can.zip and it worked.  I am using an older version of FPC on the raspberry Pi.  The example worked.  I used that code as a template for my Lazarus project.Thank you for the report. I didn't catch time to test on Pi and PocketBeagle yet, so I'm glad to hear it works on Pi. Just for info, could you tell me what CAN hardware did you use during testing? Quote from: joelucsd on March 23, 2021, 10:23:02 pmI needed an Extended ID.  Will look at that tomorrow.  Might just need to set the extended ID manually before stuffing the value into the frame field.So far I have attached enough for 1:1 translation of various C examples you can find on the net. Right now I am working on bit packed overlays which would allow easy access to individual bits, and some higher level helper methods. After that I will probably add SAE J1939 (for trucks, buses, tractors, boats and heavy machinery) where Extended ID is used, and at the end provide a FPC patch so that we can all use SocketCAN out of the box. ---------------------------------------------------------------------- joelucsd · 2021-03-25 17:00 I am running on a Raspberry Pi 4. Raspbian GNU/Linux 10 FPC version is: 3.0.4+dfsg-22+rpi1 Lazarus: 2.0.0+dfsg-2   2019-03-01 I am using a USB to CAN adapter from www.inno-maker.com.  It is a nice cheap solution. http://wiki.inno-maker.com/display/HOMEPAGE/usb2can I got mine through Amazon You do have to enable it with a couple of commands: 'sudo ip link set can0 type can bitrate 250000' 'sudo ifconfig can0 up' I did get extended addressing to work.  Like I suggested, I just had to set bit 31 to select it before writing the ID into the frame structure.  Then it came out on the bus.  The Python library has an additional parameter in the call to say it is the 29 bit version of the ID.  Setting the bit manually before works fine.  You just need to know to do it.  (And I don't like the Python syntax.  So would rather use Pascal or C) ---------------------------------------------------------------------- avra · 2021-03-26 09:18 Quote from: joelucsd on March 25, 2021, 06:00:16 pmI am running on a Raspberry Pi 4. Raspbian GNU/Linux 10 FPC version is: 3.0.4+dfsg-22+rpi1 Lazarus: 2.0.0+dfsg-2   2019-03-01 I am using a USB to CAN adapter from www.inno-maker.com.Thanks for the report. I guess with 3.0.4 you had to manually add missing CAN constants. Quote from: joelucsd on March 25, 2021, 06:00:16 pmYou do have to enable it with a couple of commands: 'sudo ip link set can0 type can bitrate 250000' 'sudo ifconfig can0 up'That's pretty standard for a CAN device that kernel can recognize. Quote from: joelucsd on March 25, 2021, 06:00:16 pmI did get extended addressing to work.  Like I suggested, I just had to set bit 31 to select it before writing the ID into the frame structure.I know. That's why I said "I am working on bit packed overlays which would allow easy access to individual bits". ---------------------------------------------------------------------- avra · 2021-03-31 09:14 I have implemented high level CAN access in can.hl unit. So, if you do your own code from scratch it is recommended to use this unit. Old low level C-like access will stay for easier future upgrades, and you will probably use it only when you want 1:1 translation of some C example from the net. In the attachment you will find new CAN examples hlcancyclic, hlcanfdreceive, hlcanfdtransmit, hlcanfilter, hlcanreceive and hlcantransmit. These are all "high level" versions of previous examples using can.hl unit (if you can give "high level" name to pascalish renaming, bit packed overlays and some helpers). I hope you will find CAN usage more pleasant now. @joelucsd: Take a look at hlcanfdtransmit which uses extended 29-bit CAN ID addressing now. It is as simple as this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     CanFDFrame.ID.Value := $444444; // CAN FD message extended ID    CanFDFrame.ID.EFF   := true;    // confirm that we have 29-bit CAN ID Talk is cheap. Here is what CAN code looks like now: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program hlcanfdtransmit; // higher level pascalized version of canfdtransmit demo {$mode delphi} {$H+} uses  cthreads, sysutils, sockets, baseunix, can, can.hl, can.raw; procedure perror(const S : string);begin  WriteLn(S, ', SocketError = ', SocketError);end; var  Err:          integer;  CanHandle:    TCanHandle;  CanAddr:      TCanSockAddr;  CanInterface: TCanIfreq;  CanFDFrame:   TCanFDFrame;begin  try    Writeln('CAN FD Sockets Transmit Demo');    CanHandle := CanSocket(SOCK_RAW, CAN_RAW);    if CanHandle < 0 then    begin      perror('Socket');      Exit;    end;     CanInterface.Name := 'vcan0' + #0;    if CanIOCtl(CanHandle, SIOCGIFINDEX, CanInterface) < 0 then  begin      perror('IOctl');      Exit;    end;     CanAddr.Clear;    CanAddr.CanFamily  := AF_CAN;    CanAddr.CanIfIndex := CanInterface.IfIndex;     if CanBind(CanHandle, CanAddr) < 0 then    begin      perror('Bind');      Exit;    end;     CanFDFrame.ID.Value := $444444; // CAN FD message extended ID    CanFDFrame.ID.EFF   := true;    // confirm that we have 29-bit CAN ID    CanFDFrame.Len      := 20;      // payload length will be 20 bytes    CanFDFrame.Data   := [$01, $02, $03, $04, $05, $06, $07, $08, $09, $0A, $0B, $0C, $0D, $0E, $0F, $10,                            $11, $12, $13, $14, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,                          $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00,                            $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00];                          // shows as '0x444444 [40] 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14' in canfdreceive    {    CanFDFrame.Data[0]  := $01; // alternative for the above    CanFDFrame.Data[1]  := $02; // shows as '0x444444 [40] 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14' in canfdreceive    CanFDFrame.Data[2]  := $03;    CanFDFrame.Data[3]  := $04;    CanFDFrame.Data[4]  := $05;    CanFDFrame.Data[5]  := $06;    CanFDFrame.Data[6]  := $07;    CanFDFrame.Data[7]  := $08;    CanFDFrame.Data[8]  := $09;    CanFDFrame.Data[9]  := $0A;    CanFDFrame.Data[10] := $0B;    CanFDFrame.Data[11] := $0C;    CanFDFrame.Data[12] := $0D;    CanFDFrame.Data[13] := $0E;    CanFDFrame.Data[14] := $0F;    CanFDFrame.Data[15] := $10;    CanFDFrame.Data[16] := $11;    CanFDFrame.Data[17] := $12;    CanFDFrame.Data[18] := $13;    CanFDFrame.Data[19] := $14;    }     Err := CanSetSockOpt(CanHandle, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, ENABLE_CAN_OPTION, SizeOf(ENABLE_CAN_OPTION));    if Err <> 0 then    begin      if Err = ESysENOPROTOOPT then        WriteLn('CAN FD Protocol not available. Try newer kernel');      perror('SetSockopt');      Exit;    end;     if CanWrite(CanHandle, CanFDFrame) <> SizeOf(CanFDFrame) then    begin      perror('Write');      Exit;    end;     if CanClose(CanHandle) < 0 then    begin      perror('Close');      Exit;    end;   except    on e: Exception do    WriteLn(e.Message);  end;end.  Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program hlcanfdreceive; // higher level pascalized version of canfdreceive demo {$mode delphi} {$H+} uses  cthreads, sysutils, sockets, baseunix, can, can.hl, can.raw; procedure perror(const S : string);begin  WriteLn(S, ', SocketError = ', SocketError);end; var  i, BytesNo:   byte;  Err:          integer;  CanHandle:    TCanHandle;  CanAddr:    TCanSockAddr;  CanInterface: TCanIfreq;  CanFDFrame:   TCanFDFrame;begin  try    Writeln('CAN FD Sockets Receive Demo');    CanHandle := CanSocket(SOCK_RAW, CAN_RAW);    if CanHandle < 0 then  begin      perror('Socket');      Exit;    end;     CanInterface.Name := 'vcan0' + #0;    if CanIOCtl(CanHandle, SIOCGIFINDEX, CanInterface) < 0 then    begin      perror('IOctl');      Exit;    end;     CanAddr.Clear;    CanAddr.CanFamily  := AF_CAN;    CanAddr.CanIfIndex := CanInterface.IfIndex;     if CanBind(CanHandle, CanAddr) < 0 then  begin      perror('Bind');      Exit;    end;     Err := CanSetSockOpt(CanHandle, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, ENABLE_CAN_OPTION, SizeOf(ENABLE_CAN_OPTION));    if Err <> 0 then    begin      if Err = ESysENOPROTOOPT then        WriteLn('CAN FD Protocol not available. Try newer kernel.');      perror('SetSockopt');      Exit;    end;     BytesNo := CanRead(CanHandle, CanFDFrame);    if BytesNo < 0 then    begin      perror('Read');      Exit;    end;     if BytesNo = CANFD_MTU then    // test CAN FD with 'cansend vcan0 123##1223344556677889900'      WriteLn('CAN FD frame received with length ', IntToStr(CanFDFrame.Len))    else if BytesNo = CAN_MTU then // test legacy CAN with 'cansend vcan0 456#DEADBEEF'      WriteLn('CAN legacy frame received with length ', IntToStr(CanFDFrame.Len))    else      WriteLn('Invalid CAN(FD) frame received');     Write(format('0x%03X [%d] ', [CanFDFrame.ID.Value, CanFDFrame.Len]));    for i := 0 to CanFDFrame.Len - 1 do      Write(Format('%02.2X ', [CanFDFrame.Data[i]]));    WriteLn('');     if CanClose(CanHandle) < 0 then    begin      perror('Close');      Exit;    end;   except    on e: Exception do      WriteLn(e.Message);  end;end.  Hopefully, J1939 examples are next. Remember, this is all still a playground and things may change until I include SocketCAN support into FP trunk. ---------------------------------------------------------------------- avra · 2021-04-16 12:20 I've been thinking about creating some unique CAN tools. There are so many tools for sniffing, dumping and hacking your car CAN communication, but very few touch showing CAN error message details. The ones which do, show just a few selected messages, and there is none that shows all CAN error messages with their finest details in human readable form. So, I have created hlcanerrdump. Quite a unique tool created with FreePascal. Enjoy! Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i /////////// ////////////////////////////////////////////////////////////////////// /////////////////////                                                                                              ////  hlcanerrdump utility to display SocketCAN error messages, by Zeljko Avramovic (c) 2021        ////                                                                                              ////  Dual license:                                                                               ////  1. FPC modified LGPL (chosen for compatibility with FreePascal and Lazarus)                   ////  2. BSD3              (chosen for compatibility with everything else)                          ////                                                                                            ////  Virtual CAN adapter vcan0 is hard coded and you can bring it up like this:                    ////  sudo modprobe vcan                                                                          ////  sudo ip link add dev vcan0 type vcan                                                        ////  sudo ip link set vcan0 mtu 72              # needed for CAN FD                                ////  sudo ip link set vcan0 up                                                                   ////                                                                                              ////  To simulate error messages use hlcanerrsim utility like this:                               ////  ./hlcanerrsim LostArbitrationBit=09 TX BusOff Data7=AA Data6=BB                               ////                                                                                            ////  That should show in hlcanerrdump utility as:                                                ////  0x04A [8] 16 00 80 00 00 00 BB AA  ERR=LostArbitrationBit09,BusOff,Prot(Type(TX),Loc(Unspec)) ////                                                                                            ////  Alternatively, you could use candump from can- utils to check error messages like this:        ////  candump -s -c -c -x -a any,0~0,#FFFFFFFF                                                    ////                                                                                              /////////////////////////////////// /////////////////////////////////////////////////////////////////// pr ogram hlcanerrdump; // dump CAN error messages {$mode delphi} {$H+} uses  classes, sysutils, strutils, sockets, baseunix, can, can.hl, can.raw, can.error, crt; procedure perror(const S : string);begin  WriteLn(S, ', SocketError = ', SocketError);end; var  i, BytesNo:   integer;  CanHandle:    TCanHandle;  CanAddress:   TCanSockAddress;  CanInterface: TCanIFreq;  CanFrame:     TCanFrame;  CanMask:      TCanErrMask;  CanFilter:    TCanFilter;  SockOpt:      cint;  ErrFlagStr:   string;  Errors:       TStringList;begin  try  try      WriteLn('CAN Sockets Error Messages Dump. Waiting for errors...');      Errors    := TStringList.Create;      CanHandle := CanSocket(SOCK_RAW, CAN_RAW);      if CanHandle < 0 then      begin      perror('Socket');        Exit;      end;       CanInterface.Name := 'vcan0';      if CanIOCtl(CanHandle, SIOCGIFINDEX, CanInterface) < 0 then      begin        perror('IOctl');        Exit;      end;     CanAddress.Clear;      CanAddress.CanFamily  := AF_CAN;      CanAddress.CanIfIndex := CanInterface.IfIndex;       if CanBind(CanHandle, CanAddress) < 0 then      begin        perror('Bind');        Exit;      end;       CanFilter.ID.InverseFilter              := true; // no normal CAN frames      CanFilter.Mask.Full                     := 0;    // inverting nothing gives us everything      // CanFilter.Mask.Error.LostArbitration := true; // you might want to exclude arbitration errors      CanSetSockOpt(CanHandle, SOL_CAN_RAW, CAN_RAW_FILTER, CanFilter, SizeOf(CanFilter));       CanMask.ERR := true;                // only error frames      CanSetSockOpt(CanHandle, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, CanMask, SizeOf(CanMask));       SockOpt := CanFcntl(CanHandle, F_GETFL);                      // get socket options      if SockOpt < 0 then      begin        perror('CanFcntl: Error = ' + CanGetErrNo.ToString);      Exit;      end;       if CanFcntl(CanHandle, F_SETFL, SockOpt or O_NONBLOCK) < 0 then // set nonblock socket (to be able to exit after key press)      begin        perror('NonBlock: Error = ' + CanGetErrNo.ToString);        Exit;      end;       repeat        BytesNo := CanRead(CanHandle, CanFrame);        if BytesNo = SizeOf(CanFrame) then        begin          Write(Format(IfThen(CanFrame.ID.EFF, '0x%08.8X [%d] ', '     0x%03.3X [%d] '), [CanFrame.ID.Value, CanFrame.DLC])); // extended or standard frame          for i := 0 to CanFrame.DLC - 1 do            Write(Format('%02.2X ', [CanFrame.Data[i]]));           Errors.Clear;          if CanFrame.ID.Mask.Error.TxTimeout       then Errors.Add('TxTimeout');          if CanFrame.ID.Mask.Error.LostArbitration then Errors.Add('LostArbitrationBit' + Format('%.*d', [2, CanFrame.DataError.LostArbitration.BitNumber]));          if CanFrame.ID.Mask.Error.NoAck           then Errors.Add('NoAck');        if CanFrame.ID.Mask.Error.BusOff          then Errors.Add('BusOff');          if CanFrame.ID.Mask.Error.BusError      then Errors.Add('BusError');          if CanFrame.ID.Mask.Error.Restarted       then Errors.Add('Restarted');        if CanFrame.ID.Mask.Error.Controller      then          begin          ErrFlagStr := '';            if CanFrame.DataError.Controller.OverflowRX then ErrFlagStr := ErrFlagStr + 'OverflowRX,';            if CanFrame.DataError.Controller.OverflowTX then ErrFlagStr := ErrFlagStr + 'OverflowTX,';            if CanFrame.DataError.Controller.WarningRX  then ErrFlagStr := ErrFlagStr + 'WarningRX,';            if CanFrame.DataError.Controller.WarningTX  then ErrFlagStr := ErrFlagStr + 'WarningTX,';            if CanFrame.DataError.Controller.PassiveRX  then ErrFlagStr := ErrFlagStr + 'PassiveRX,';            if CanFrame.DataError.Controller.PassiveTX  then ErrFlagStr := ErrFlagStr + 'PassiveTX,';            if CanFrame.DataError.Controller.Active   then ErrFlagStr := ErrFlagStr + 'Active';            if ErrFlagStr.EndsWith(',') then SetLength(ErrFlagStr, ErrFlagStr.Length - 1);            Errors.Add('Ctrl(' + ErrFlagStr + ')');          end;          if CanFrame.ID.Mask.Error.Protocol        then          begin            ErrFlagStr := 'Type(';            if CanFrame.DataError.Protocol.Category.SingleBit          then ErrFlagStr := ErrFlagStr + 'SingleBit,';            if CanFrame.DataError.Protocol.Category.FrameFormat        then ErrFlagStr := ErrFlagStr + 'FrameFormat,';            if CanFrame.DataError.Protocol.Category.BitStuffing        then ErrFlagStr := ErrFlagStr + 'BitStuffing,';            if CanFrame.DataError.Protocol.Category.Bit0               then ErrFlagStr := ErrFlagStr + 'Bit0,';            if CanFrame.DataError.Protocol.Category.Bit1               then ErrFlagStr := ErrFlagStr + 'Bit1,';            if CanFrame.DataError.Protocol.Category.BusOverload        then ErrFlagStr := ErrFlagStr + 'BusOverload,';            if CanFrame.DataError.Protocol.Category.ActiveAnnouncement then ErrFlagStr := ErrFlagStr + 'ActiveAnnouncement,';            if CanFrame.DataError.Protocol.Category.TX                 then ErrFlagStr := ErrFlagStr + 'TX';            if ErrFlagStr.EndsWith(',') then SetLength(ErrFlagStr, ErrFlagStr.Length - 1);            ErrFlagStr := ErrFlagStr + '),Loc(';            case CanFrame.DataError.Protocol.Location of              CAN_ERR_PROT_LOC_UNSPEC:     ErrFlagStr := ErrFlagStr + 'Unspec';  // zero              CAN_ERR_PROT_LOC_SOF:        ErrFlagStr := ErrFlagStr + 'SOF';     // start of frame              CAN_ERR_PROT_LOC_ID28_21:    ErrFlagStr := ErrFlagStr + 'ID28_21'; // ID bits 28 - 21 (SFF: 10 - 3)              CAN_ERR_PROT_LOC_ID20_18:  ErrFlagStr := ErrFlagStr + 'ID20_18'; // ID bits 20 - 18 (SFF: 2 - 0 )              CAN_ERR_PROT_LOC_SRTR:       ErrFlagStr := ErrFlagStr + 'SRTR';    // substitute RTR (SFF: RTR)              CAN_ERR_PROT_LOC_IDE:        ErrFlagStr := ErrFlagStr + 'IDE';     // identifier extension              CAN_ERR_PROT_LOC_ID17_13:    ErrFlagStr := ErrFlagStr + 'ID17_13'; // ID bits 17-13              CAN_ERR_PROT_LOC_ID12_05:    ErrFlagStr := ErrFlagStr + 'ID12_05'; // ID bits 12-5              CAN_ERR_PROT_LOC_ID04_00:    ErrFlagStr := ErrFlagStr + 'ID04_00'; // ID bits 4-0              CAN_ERR_PROT_LOC_RTR:        ErrFlagStr := ErrFlagStr + 'RTR';     // RTR              CAN_ERR_PROT_LOC_RES1:       ErrFlagStr := ErrFlagStr + 'RES1';    // reserved bit 1              CAN_ERR_PROT_LOC_RES0:     ErrFlagStr := ErrFlagStr + 'RES0';    // reserved bit 0            CAN_ERR_PROT_LOC_DLC:        ErrFlagStr := ErrFlagStr + 'DLC';     // data length code              CAN_ERR_PROT_LOC_DATA:       ErrFlagStr := ErrFlagStr + 'DATA';    // data section              CAN_ERR_PROT_LOC_CRC_SEQ:    ErrFlagStr := ErrFlagStr + 'CRC_SEQ'; // CRC sequence              CAN_ERR_PROT_LOC_CRC_DEL:    ErrFlagStr := ErrFlagStr + 'CRC_DEL'; // CRC delimiter              CAN_ERR_PROT_LOC_ACK:        ErrFlagStr := ErrFlagStr + 'ACK';     // ACK slot              CAN_ERR_PROT_LOC_ACK_DEL:    ErrFlagStr := ErrFlagStr + 'ACK_DEL'; // ACK delimiter              CAN_ERR_PROT_LOC_EOF:        ErrFlagStr := ErrFlagStr + 'EOF';     // end of frame              CAN_ERR_PROT_LOC_INTERM:     ErrFlagStr := ErrFlagStr + 'INTERM';  // intermission            otherwise            ErrFlagStr := ErrFlagStr + 'Unknown';   // protocol location not recognized            end;            Errors.Add('Prot(' + ErrFlagStr + '))');          end;          if CanFrame.ID.Mask.Error.Transceiver then          begin            ErrFlagStr := '';            case CanFrame.DataError.Transceiver of              CAN_ERR_TRX_UNSPEC:            ErrFlagStr := ErrFlagStr + 'Unspec';            // $00, 0000 0000              CAN_ERR_TRX_CANH_NO_WIRE:        ErrFlagStr := ErrFlagStr + 'CanHiNoWire';       // $04, 0000 0100              CAN_ERR_TRX_CANH_SHORT_TO_BAT:   ErrFlagStr := ErrFlagStr + 'CanHiShortToBAT';   // $05, 0000 0101              CAN_ERR_TRX_CANH_SHORT_TO_VCC:   ErrFlagStr := ErrFlagStr + 'CanHiShortToVCC';   // $06, 0000 0110              CAN_ERR_TRX_CANH_SHORT_TO_GND:   ErrFlagStr := ErrFlagStr + 'CanHiShortToGND';   // $07, 0000 0111              CAN_ERR_TRX_CANL_NO_WIRE:        ErrFlagStr := ErrFlagStr + 'CanLoNoWire';       // $40, 0100 0000              CAN_ERR_TRX_CANL_SHORT_TO_BAT:   ErrFlagStr := ErrFlagStr + 'CanLoShortToBAT';   // $50, 0101 0000              CAN_ERR_TRX_CANL_SHORT_TO_VCC:   ErrFlagStr := ErrFlagStr + 'CanLoShortToVCC';   // $60, 0110 0000              CAN_ERR_TRX_CANL_SHORT_TO_GND:   ErrFlagStr := ErrFlagStr + 'CanLoShortToGND';   // $70, 0111 0000              CAN_ERR_TRX_CANL_SHORT_TO_CANH:  ErrFlagStr := ErrFlagStr + 'CanLoShortToCanHi'; // $80, 1000 0000            otherwise            ErrFlagStr := ErrFlagStr + 'Unknown'; // transceiver error not recognized            end;            Errors.Add('Trans(' + ErrFlagStr + ')');          end;           if Errors.Count > 0 then            Write(' ERR=');           for i := 0 to Errors.Count - 1 do          begin            Write(Errors.Strings[i]);            if i <> (Errors.Count - 1) then              Write(',');          end;        WriteLn('');        end;        Sleep(5);      until KeyPressed;     if CanClose(CanHandle) < 0 then      begin        perror('Close');      Exit;      end;    except      on e: Exception do        WriteLn(e.Message);    end;  finally    Errors.Free;  end;end.  Beta version attached here is tied to vcan0. Before I put it into FPC trunk I will make it accept CAN interface as a parameter. ---------------------------------------------------------------------- avra · 2021-04-16 12:29 I have searched all the net and I could not find a single open source tool for simulating CAN error messages. None. Zero. So, I have created hlcanerrsim. A unique tool created with FreePascal. Enjoy! UPDATE: Source exceeds single message limit, so you can find it in can.zip archive in previous message. ---------------------------------------------------------------------- avra · 2021-04-28 08:33 hlcanerrdump now accepts CAN interface as first parameter and CAN filter for error messages as further parameters. Especially useful example is to use IgnoreNoAck parameter for filtering NoAck messages. Code: [Select]avra@vm-debian:/mnt/e/can$ ./hlcanerrdump CAN Sockets Error Messages Dump Usage: hlcanerrdump [options] CAN interface:                   ( CAN interface is case sensitive )     can1                         ( or can2, can3 or virtual ones like vcan0, vcan1... Options:                         ( options are not case sensitive )                                  ( ERROR CLASS (MASK) IN CAN ID: )     IgnoreTxTimeout              ( filter TX timeout by netdevice driver error messages )     IgnoreLostArbitration        ( filter lost arbitration error messages )     IgnoreController             ( filter controller problem error messages )     IgnoreProtocol               ( filter protocol error messages )     IgnoreTransceiver            ( filter transceiver status error messages )     IgnoreNoAck                  ( filter no ACK on transmission error messages )     IgnoreBusOff                 ( filter bus off error messages )     IgnoreBusError               ( filter bus error messages )     IgnoreRestarted              ( filter controller restarted messages )                                  ( DEBUG HELPERS: )     ShowFilterAndMaskBits        ( display all filtering bits ) Examples:     ./hlcanerrdump can1     ( dump all CAN error messages from CAN interface can1 )     ./hlcanerrdump vcan0 IgnoreNoAck IgnoreBusOff     ( dump all CAN error messages from virtual CAN interface vcan0 except NoACk and BusOff) hlcanerrsim now accepts CAN interface as first parameter. It still accepts error message types as parameters for forming simulated error messages. Code: [Select]avra@vm-debian:/mnt/e/can$ ./hlcanerrsim CAN Sockets Error Messages Simulator Usage: hlcanerrsim [options] CAN interface:                   ( CAN interface is case sensitive )     can1                         ( or can2, can3 or virtual ones like vcan0, vcan1... Options:                         ( options are not case sensitive )                                  ( ERROR CLASS (MASK) IN CAN ID: )     TxTimeout                    ( TX timeout by netdevice driver )     NoAck                        ( received no ACK on transmission )     BusOff                       ( bus off )     BusError                     ( bus error, may flood! )     Restarted                    ( controller restarted )                                  ( ARBITRATIONLOST IN CAN ID + BIT NUMBER IN DATA[0]: )     LostArbitrationBit=<00..29>  ( decimal bit number in bitstream )                                  ( CONTROLLER IN CAN ID + ERROR STATUS IN DATA[1]: )     OverflowRX                   ( RX buffer overflow )     OverflowTX                   ( TX buffer overflow )     WarningRX                    ( reached warning level for RX errors )     WarningTX                    ( reached warning level for TX errors )     PassiveRX                    ( reached error passive status RX, errors > 127 )     PassiveTX                    ( reached error passive status TX, errors > 127 )     Active                       ( recovered to error active state )                                  ( PROTOCOL ERROR IN CAN ID + TYPE IN DATA[2]: )     SingleBit                    ( single bit error )     FrameFormat                  ( frame format error )     BitStuffing                  ( bit stuffing error )     Bit0                         ( unable to send dominant bit )     Bit1                         ( unable to send recessive bit )     BusOverload                  ( bus overload )     ActiveAnnouncement           ( active error announcement )     TX                           ( error occurred on transmission )                                  ( PROTOCOL ERROR IN CAN ID + LOCATION IN DATA[3]: )     SOF                          ( start of frame )     ID28_21                      ( ID bits 21..28, SFF: 3..10 )     ID20_18                      ( ID bits 18..20, SFF: 0..2 )     SRTR                         ( substitute RTR, SFF: RTR )     IDE                          ( identifier extension )     ID17_13                      ( ID bits 13..17 )     ID12_05                      ( ID bits 5..12 )     ID04_00                      ( ID bits 0..4 )     RTR                          ( RTR )     RES1                         ( reserved bit 1 )     RES0                         ( reserved bit 0 )     DLC                          ( data length code )     DATA                         ( data section )     CRC_SEQ                      ( CRC sequence )     CRC_DEL                      ( CRC delimiter )     ACK                          ( ACK slot )     ACK_DEL                      ( ACK delimiter )     EOF                          ( end of frame )     INTERM                       ( intermission )                                  ( TRANSCEIVER ERROR IN CAN ID + STATUS IN DATA[4]: )                                  ( CANH CANL )     TransUnspec                  ( 0000 0000 )     CanHiNoWire                  ( 0000 0100 )     CanHiShortToBAT              ( 0000 0101 )     CanHiShortToVCC              ( 0000 0110 )     CanHiShortToGND              ( 0000 0111 )     CanLoNoWire                  ( 0100 0000 )     CanLoShortToBAT              ( 0101 0000 )     CanLoShortToVCC              ( 0110 0000 )     CanLoShortToGND              ( 0111 0000 )     CanLoShortToCanHi            ( 1000 0000 )                                  ( CUSTOM BYTE TO DATA[0..7]: )     Data<0..7>=<00..FF>          ( write hex number to one of 8 payload bytes ) Examples:     ./hlcanerrsim can1 LostArbitrationBit=09 TX BusOff Data7=AA Data6=BB     ( can1: 9th arb. bit lost, transmission, bus off, controller specific info in Data[6] and Data[7] )     ./hlcanerrsim vcan0 NoAck TxTimeout Active     ( vcan0: received no ACK on transmission, driver timeout, protocol type active error announcement )     ./hlcanerrsim vcan0 BusError CanHiNoWire Restarted INTERM     ( vcan0: bus error, lost CANH wiring, controller restarted, protocol location intermission ) ---------------------------------------------------------------------- ThomasK · 2021-05-15 12:40 Hello Avra, is there already a way to perform the actions which the 'ip' command does in pascal? like "sudo ip link set can0 type can bitrate 125000 sample-point 0.875" and "sudo ip link set can0 up" and "sudo ip link set can0 down"? I got the Inno-Maker CAN RS485 HAT to work with my test gear from PEAK and don't want to do work which is already done..... Cheers, Thomas ---------------------------------------------------------------------- avra · 2021-05-16 00:35 Quote from: ThomasK on May 15, 2021, 02:40:45 pmis there already a way to perform the actions which the 'ip' command does in pascal? like "sudo ip link set can0 type can bitrate 125000 sample-point 0.875" and "sudo ip link set can0 up" and "sudo ip link set can0 down"?Calling ip command from your pascal application and parsing the output would be the simplest solution. If you are not satisfied with that, you would have to use NETLINK sockets, since that is what ip command uses. Alternatively, you could use libsocketcan (a wrapper around netlink sockets for CAN) or libnl, but you would need to make your own wrapper. https://lalten.github.io/libsocketcan/Documentation/html/group__extern .html#gaa01e52bcb6f4b873da7ce32cab38332d https://github.com/jmore-reachtech/can- utils/blob/master/src/canconfig.c https://www.infradead.org/~tgr/libnl/doc/api/group__can.html#gab6de57c db6c42d48df432636e266700b ---------------------------------------------------------------------- ThomasK · 2021-05-16 08:45 Thanks. Well, it seems that due to the 'C' in CAN most code is written in C ---------------------------------------------------------------------- ThomasK · 2021-05-16 13:03 Hi, I installed the library and am trying to call it. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit LibSockCAN; {$mode objfpc}{$H+} interface //lib/arm-linux- gnueabihf/libsocketcan.so//libsocketcan.h {$linklib c}{$linklib libsocketcan} //function can_do_restart                   : longint; cdecl; external;function can_do_stop(const pchar)           : longint; cdecl; external;function can_do_start(const pchar)          : longint; cdecl; external;//function can_set_bitrate                  : longint; cdecl; external;//function can_set_bitrate_samplepoint      : longint; cdecl; external; //uses implementation  end.  The call is done as reaction to a Button: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  procedure TForm1.B_StartCan0Click(Sender: TObject);var  ifr_name : PChar;  myresult : integer;begin  ifr_name:= 'can0';  myresult:=can_do_start(ifr_name);  Label_StartResult.caption:=InttoStr(myresult);end; No errors during compilation, but return code is -1. Where is my error? btw. the CAN-UTILS and the ip commands work ---------------------------------------------------------------------- avra · 2021-05-16 13:32 Quote from: ThomasK on May 16, 2021, 10:45:20 amThanks.You're welcome.  Quote from: ThomasK on May 16, 2021, 10:45:20 amit seems that due to the 'C' in CAN most code is written in C Well, Linux kernel 2.6.25 with first SocketCAN implementation was donated by Volkswagen in 2008, so besides much wider user base C also has about 13 years advantage - although we already have some unique and pretty useful error dump and error simulation tools. With FreePascal wrapper all SocketCAN code can be easily transferred with almost 1:1 translation. Just take a look at demos which do not start with hl prefix in their name. They are in Pascal but they look almost identical to their C roots. If you take a look at canconfig.c that I mentioned in previous post, you will see that besides SocketCAN (that is already part of the kernel) only libsocketcan is used additionally. So, if you create a libsocketcan wrapper then it should not be too hard to do an almost 1:1 translation, or extract just parts which you need for CAN setup in code. If that is too much, then you can always run ip command in a process and parse the output. According to my free time, plan is to support J1939 (trucks, buses, heavy machinery, marine, military and agriculture), OBD-II (cars) and DBC file parsing (for automatic conversion of CAN messages to human readable form). If in the mean time I get some CANopen (plc, industrial automation, embedded) freelance work then I might consider supporting CANopen as well. For now, there is no plan to support libsocketcan. UPDATE: Quote from: ThomasK on May 16, 2021, 03:03:41 pmNo errors during compilation, but return code is -1. Where is my error?I am not familiar with internals of libsocketcan so I can not tell. If I had to guess then I would first try to replace Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i ifr_name:= 'can0';with Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i ifr_name:= 'can0' + #0;If that doesn't work, then I would try to create the most simplest code in C which does the job, and then try to convert that to FreePascal with already mentioned 1:1 conversion method. That would eliminate a lot of unknowns of what works and what doesn't. Ah, yes... You should also try to start your app as root, and check if can0 is not already started. ---------------------------------------------------------------------- ThomasK · 2021-05-16 14:25 Adding the #0 to the devince name changed nothing. ---------------------------------------------------------------------- dseligo · 2021-05-16 21:40 Quote from: avra on May 16, 2021, 03:32:39 pmAccording to my free time, plan is to support J1939 (trucks, buses, heavy machinery, marine, military and agriculture), OBD-II (cars) and DBC file parsing (for automatic conversion of CAN messages to human readable form). If in the mean time I get some CANopen (plc, industrial automation, embedded) freelance work then I might consider supporting CANopen as well. For now, there is no plan to support libsocketcan. What device(s) do you use to interface with CAN bus? ---------------------------------------------------------------------- avra · 2021-05-16 22:44 Quote from: dseligo on May 16, 2021, 11:40:48 pmWhat device(s) do you use to interface with CAN bus?Pi, PocketBeagle and Arduino (AVR, STM32, ESP32) ---------------------------------------------------------------------- dseligo · 2021-05-17 12:54 Quote from: avra on May 17, 2021, 12:44:51 amQuote from: dseligo on May 16, 2021, 11:40:48 pmWhat device(s) do you use to interface with CAN bus?Pi, PocketBeagle and Arduino (AVR, STM32, ESP32) Does Arduino (AVR) has to be some specific type (e.g. AT90CAN128) or any will do? What do you use between 'controller' and CAN bus? ---------------------------------------------------------------------- Blade · 2021-05-17 13:23 This thread mentions C to Pascal translation several times.  I'm wondering if this is not also an opportunity to test out some of the automatic C to Pascal or C to Delphi translators.  Probably wouldn't be as good as being done manually by someone very fluent in both, but perhaps the automatic software could be useful in various cases. ---------------------------------------------------------------------- avra · 2021-05-17 22:58 Quote from: dseligo on May 17, 2021, 02:54:14 pmQuote from: avra on May 17, 2021, 12:44:51 amQuote from: dseligo on May 16, 2021, 11:40:48 pmWhat device(s) do you use to interface with CAN bus?Pi, PocketBeagle and Arduino (AVR, STM32, ESP32) Does Arduino (AVR) has to be some specific type (e.g. AT90CAN128) or any will do? What do you use between 'controller' and CAN bus? You can use some CAN based AVR as AT90CAN128 with just a TJA1050 or similar CAN transceiver, but it is more common to use simpler AVR (like ATMEGA328P) with MCP2515 and some CAN transceiver chip as MCP is much better supported. Using MCP2515 also means that besides using CAN directly from AVR, you can also use it from Linux as Lawicel/SLCAN based CAN gateway for SocketCAN with something like this: https://github.com/latonita/arduino-canbus-monitor, https://github.com/autowp/can-usb or https://github.com/mintynet/nano- can. You are limited with serial to USB chip speed on your Arduino so with speeds of 500kbps and higher expect dropped frames (and even with 250kbps if your CAN bus load is high). Although MCP2515 is the most supported CAN 2.0B chip on the planet, if you need CAN FD then it will not be enough and you will have to use MCP2518 and similar with a proper lib. Although ESP32 is much more capable then standard AVRs, there is also a serial to USB chip so there is the same speed limit. It has internal CAN so there are libs which do not need MCP2515 to implement Lawicel/SLCAN which can be used from Linux SocketCAN. I have seen versions which use Bluetooth instead of serial to USB, but I have never tested them (https://github.com/michey/esp32_can and https://github.com/mintynet/esp32-slcan). There are also versions which support CAN FD and create a WiFi UDP tunnel to Linux SocketCAN via cannelloni protocol (https://github.com/PhilippFux/ESP32_CAN_Interface and https://github.com/epozzobon/lasagne), but I haven't tested them either. STM32 has many microcontrollers (like STM32F103C8T6 BluePill for example) which support CAN out of the box and do not need MCP2515. They also have USB but unfortunately USB and CAN can not work at the same time, so some serial to USB must also be used. Look at https://github.com/kolyandex/CAN-to-USB-lawicel-for-stm32, https://github.com/GBert/misc/tree/master/stm32-slcan, https://github.com/geier99/STM32-CAN_CubeMX_Tests, https://github.com/darauble/lawicel-slcan, http://randomport.com/pages/usb-to-can.html and https://ucandevices.github.io. Most of the mentioned devices can be used as very cheap Lawicel/SLCAN compatible protocol CAN gateways for Linux SocketCAN, but I personally do not use them for that. I use them as embedded devices when Linux SBC is an overkill or when long booting can not be tolerated. What is good about such Lawicel/SLCAN protocol compatible devices is that there is a lot of software for Windows that can use them, so that will be your CAN path if you are not a Linux fan. However, Linux SocketCAN path is much more powerful and standardized so unlike with Windows various software can work together using data simultaneously from the same CAN adapter. Raspberry Pi needs a HAT with MCP2515/2517/2518. PocketBeagle and BeagleBone can also use MCP, but if you do not need CAN FD then built in CAN with some transceiver will be enough. There is no speed limit or dropped frames problem with Linux boards, so you can use SocketCAN at it's full glory. SocketCAN also supports virtual CAN channels so you can play and learn even if you have no CAN adapter at all. For a simple introduction to CAN, CAN FD, OBD-II, CANopen and J1939 take a look at these links: https://www.csselectronics.com/screen/page/simple-intro-to-can-bus https://www.csselectronics.com/screen/page/can-fd-flexible-data-rate- intro https://www.csselectronics.com/screen/page/simple-intro-obd2-explained https://www.csselectronics.com/screen/page/simple- intro-j1939-explained https://www.csselectronics.com/screen/page/canopen-tutorial-simple- intro Here is also a little old but still relevant Car Hacker's Handbook: http://www.opengarages.org/handbook/ Quote from: Blade on May 17, 2021, 03:23:15 pmThis thread mentions C to Pascal translation several times.  I'm wondering if this is not also an opportunity to test out some of the automatic C to Pascal or C to Delphi translators.  Probably wouldn't be as good as being done manually by someone very fluent in both, but perhaps the automatic software could be useful in various cases.I use these all the time. They are good, but not perfect and I usually have to combine them. They can save you a lot of time, but can not save you from manual work completelly. https://forum.lazarus.freepascal.org/index.php/topic,12763.msg66330.ht ml#msg66330 https://forum.lazarus.freepascal.org/index.php/topic,53389.msg395085.h tml#msg395085 https://wiki.freepascal.org/C_to_Pascal ---------------------------------------------------------------------- dseligo · 2021-05-18 02:38 Thanks  I will need some time to process this ---------------------------------------------------------------------- ThomasK · 2021-05-19 11:24 Quote from: avra on May 16, 2021, 03:32:39 pm For now, there is no plan to support libsocketcan. I see. Anyway for my point of view it is better if an application takes care itself of all relevant initialisation and parameterisation tasks. At least I am used to that working with an automation system for automotive test beds. Customers always complained to if they need more than one program to get an interface working. I also found a fork of can-utils containing canconfig.c with a more recent date than 2009. . I will try to get short snippets to work, as you proposed and migrate then. I tested my short app by starting it with admin rights, it failed too. Didn't find the file, it said in the console. ---------------------------------------------------------------------- ThomasK · 2021-05-30 20:07 Have you intentions to implement this: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i num_events = epoll_wait(fd_epoll, events_pending, currmax, timeout_ms);              if (num_events == -1) {                        if (errno != EINTR)                                running = 0;                      continue;                }  This would allow a read process not to wait until data is available. I found that in the recent can-utils. ---------------------------------------------------------------------- avra · 2021-05-30 23:30 Quote from: ThomasK on May 30, 2021, 10:07:21 pmI found that in the recent can-utils.Not everything is related to CAN. If you take a look at candump.c from can-utils you will see that it includes sys/epoll.h which is a standard linux header for which there is a man page https://linux.die.net/man/2/epoll_wait. As such, you could also search your fpc directory and find that translation for epoll_wait can already be found in your existing \fpcsrc\rtl\linux\linux.pp, so you already have everything needed. You need to improve your source search fu a little, if you want the source to be with you. ---------------------------------------------------------------------- ThomasK · 2021-05-31 12:46 I know that this is not only CAN related. But this code snippet is from the latest https://github.com/linux- can/can-utils candump.c. I try to get this to work. ---------------------------------------------------------------------- ThomasK · 2021-06-03 11:20 @avra, I have put yor sent & transmit code together with the epoll routines from the latest candump.c into a GUI app for Lazarus. It works principally, I can send, receive, see that there is data after calling epoll_wait. But the num_events is always either 0 or 1 even if more than 1 message was sent to the port. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit mainunit; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, sockets, baseunix, can, linux; type   { TFCANTest }   TFCANTest = class(TForm)    bInitcan0: TButton;    bSendData: TButton;    bReceiveData: TButton;    BClosecan0: TButton;    bEpollCreate: TButton;    bEpollQuery: TButton;    mLog: TMemo;    mLogTest: TMemo;    STnum_events: TStaticText;    STevents_pending: TStaticText;    StaticText3: TStaticText;    StaticText4: TStaticText;    procedure BClosecan0Click(Sender: TObject);    procedure bEpollCreateClick(Sender: TObject);    procedure bEpollQueryClick(Sender: TObject);    procedure bInitcan0Click(Sender: TObject);    procedure bReceiveDataClick(Sender: TObject);    procedure bSendDataClick(Sender: TObject);    procedure FormCreate(Sender: TObject);   private    procedure Addmessages(mess2show: string);   public   end;  const  AF_CAN = 29;  PF_CAN = 29;  CANDevice ='can0';typeif_info = record  s            : integer;  cmdlinename  : ^byte;  dropcnt,  last_dropcnt : uint32;end;{type  EPoll_Data = record    case integer of      0: (ptr: pointer);      1: (fd: cint);      2: (u32: cuint);      3: (u64: cuint64);  end;  TEPoll_Data =  Epoll_Data;  PEPoll_Data = ^Epoll_Data;  EPoll_Event = record    Events: cuint32;    Data  : TEpoll_Data;  end;   TEPoll_Event =  Epoll_Event;  PEpoll_Event = ^Epoll_Event;}var  FCANTest       : TFCANTest;  sock_info      : if_info;  events_pending : EPoll_Event;  event_setup    : EPoll_Event;  Pevent_Setup   : PEPoll_Event;  PPoll_Event    : PEPoll_Event;  fd_epoll,  num_events,  currmax        : integer;  s:   cint;  addr:  sockaddr_can;  ifr:   ifreq;  frame: can_frame;  timeout_ms : integer; //* default to no timeout */ implementation {$R *.lfm} { TFCANTest }procedure TFCANTest.Addmessages(mess2show: string);begin  mLogtest.Lines.BeginUpdate;  mLogtest.Lines.Add(mess2show);  mLogtest.Lines.EndUpdate;  mLogtest.SelStart := Length(mLogtest.Lines.Text)-1;  mLogtest.SelLength:=0;end; procedure TFCANTest.FormCreate(Sender: TObject);begin  currmax            :=16;                                                     // number of CAN devices  event_setup.events :=EPOLLIN;  Pevent_Setup       :=@(event_setup);  PPoll_event        :=@(events_pending);  timeout_ms         :=10;  bInitcan0.caption  :=bInitcan0.caption + ' ' + CANDevice;  bClosecan0.caption  :=bclosecan0.caption + ' ' + CANDevice;end; procedure TFCANTest.bInitcan0Click(Sender: TObject);var  perror : string;begin  s := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);  if s < 0 then  begin    perror:='socket creation error';    mLog.Lines.Add(perror);    Addmessages(perror);    Exit;  end else begin     mLog.Lines.Add('Socket: '+inttostr(s));     Addmessages('Socket: '+inttostr(s));  end;  strcopy(ifr.ifr_name, CANDevice);  if fpioctl(s, SIOCGIFINDEX, @ifr) < 0 then  begin    perror:='error IOctl';    mLog.Lines.Add(perror);    Addmessages(perror);    Exit;  end;  memset(@addr, 0, sizeof(addr));  addr.can_family  := AF_CAN;  addr.can_ifindex := ifr.ifr_ifindex;  if fpbind(s, @addr, sizeof(addr)) < 0 then // if fpbind(s, Psockaddr(@addr), sizeof(addr)) < 0 then  begin    perror:='error bind';    mLog.Lines.Add(perror);  Addmessages(perror);    Exit;  end;end; procedure TFCANTest.bReceiveDataClick(Sender: TObject);var  nbytes,  i      : integer;  perror : string;begin    nbytes := fpread(s, frame, sizeof(can_frame));    if nbytes < 0 then    begin      perror:='Error during Read';      mLog.Lines.Add(perror);      Addmessages(perror);    Exit;    end;    if nbytes < sizeof(can_frame) then // paranoid check    begin      perror:='Read: Incomplete CAN frame';      mLog.Lines.Add(perror);      Addmessages(perror);      Exit;    end;  Perror:=Format('0x%03X [%d] ', [frame.can_id and CAN_SFF_MASK, frame.can_dlc]);    for i := 0 to frame.can_dlc - 1 do      Perror:=Perror + Format('%02.2X ', [frame.data[i]]);    mLog.Lines.Add(perror);    Addmessages(perror);end; procedure TFCANTest.bSendDataClick(Sender: TObject);var  perror : string;  psizef : integer;begin  frame.can_id   := $020;    // CAN message ID  frame.can_dlc  := 8;       // payload length will be 8 bytes  frame.data[0]  := $10;  frame.data[1]  := $11;  frame.data[2]  := $12;  frame.data[3]  := $13;  frame.data[4]  := $14;  frame.data[5]  := $15;  frame.data[6]  := $16;  frame.data[7]  := $17; psizef:= fpwrite(s, frame, sizeof(can_frame));if psizef <> sizeof(can_frame) then  begin    perror:='error write ' + InttoStr(psizef);    mLog.Lines.Add(perror);    Addmessages(perror);    Exit;  end else begin    mLog.Lines.Add(InttoStr(psizef) + ' bytes written');    Addmessages(InttoStr(psizef) + ' bytes written');  end;end; procedure TFCANTest.BClosecan0Click(Sender: TObject);var  perror : string;begin  if fpclose(s) < 0 then    begin      perror:='error close socket ';    mLog.Lines.Add(perror);      Addmessages(perror);      Exit;    end;  if fpclose(fd_epoll) < 0 then    begin      perror:='error close epoll ';      mLog.Lines.Add(perror);      Addmessages(perror);      Exit;    end;end; procedure TFCANTest.bEpollCreateClick(Sender: TObject);var  pepollerr : integer;begin  fd_epoll := epoll_create(1);  if fd_epoll < 0 then begin    mLog.Lines.Add('epoll create error');  Addmessages('epoll create error');    Exit;  end;  pepollerr:= epoll_ctl(fd_epoll, EPOLL_CTL_ADD, s, pevent_setup);  if pepollerr< 0 then begin    mLog.Lines.Add(IntTostr(pepollerr)+ ' epoll add to socket error');    Addmessages(IntTostr(pepollerr)+ ' epoll add to socket error');    Exit;  end;end; procedure TFCANTest.bEpollQueryClick(Sender: TObject);begin  num_events := epoll_wait(fd_epoll, PPoll_event, currmax, timeout_ms);  STnum_events.caption:= IntToStr(num_events);  STevents_pending.caption:=IntToStr(PPoll_event^.Events);end;  end. This would be sufficient, because it can prevent that the read routine gets stuck if there is nothing to read. But the candump repeats the reads as often as num_events.... may be not, because when it is fast enough it sees only one telegram. ---------------------------------------------------------------------- ThomasK · 2021-06-04 11:23 update. ip commands added {$i can.ioctl.inc} {$i can.if.inc} {$i can.sockios.inc}   included in zip. epoll_wait delivers a '1' if the file descriptor has an EPOLLIN event. After all data is read, this returns to 0. btw. runs on a Raspberry Pi 4 with inno maker dual RS485 and CAN Module, both isolated. Other CAN device is attached to a W10 laptop. (Peak USB) Maybe I try to get the USB-CAN running with a virtual machine on the laptop. ---------------------------------------------------------------------- avra · 2021-06-05 15:19 Quote from: ThomasK on June 03, 2021, 01:20:16 pmBut the num_events is always either 0 or 1 even if more than 1 message was sent to the port.I am in the middle of industrial plant commissioning, so I will not be able to take a look at this before next week. ---------------------------------------------------------------------- ThomasK · 2021-06-06 06:48 Quote from: avra on June 05, 2021, 05:19:46 pmI am in the middle of industrial plant commissioning, so I will not be able to take a look at this before next week. Thanks. But I think the num_events as result of epoll_wait is not increased with number of events per input, but with number of inputs having an event. If only one input is polled it can simply be seen as „true“ for having data to read, if the only event type is EPOLLIN. ---------------------------------------------------------------------- ThomasK · 2021-06-08 08:19 I converted the LibSocketCAN library into a Pascal Unit. beside the 'set' functions, which require root rights, the 'get' functions work as normal user. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit LibSockCAN; {$mode objfpc}{$H+} interface //lib/arm-linux- gnueabihf/libsocketcan.so//libsocketcan.huses can.netlink, ctypes, if_linkpart;   // a short version of the linux/if_link.h {$linklib c}{$linklib libsocketcan}type pdword   = ^dword; p_mybt   = ^can_bittiming; p_mycm   = ^can_ctrlmode; p_myclk  = ^can_clock; p_mybtc  = ^can_bittiming_const; p_mybcs  = ^can_berr_counter; p_mycds  = ^can_device_stats; p_myrls  = ^rtnl_link_stats64;  //defined in if_linkpart derived from   rx_packets = qword;  //These functions work only with root rights function can_do_restart(myifname : ansistring) : longint; cdecl; external;function can_set_restart_ms(myifname : ansistring; restart_ms : dword) : longint; cdecl; external;function can_do_stop(myifname : ansistring) : longint; cdecl; external;function can_do_start(myifname : ansistring) : longint; cdecl; external;function can_set_bitrate(myifname : ansistring; bitrate : dword) : longint; cdecl; external;function can_set_bitrate_samplepoint(myifname : ansistring; bitrate, samplepoint : dword) : longint; cdecl; external;function can_set_bittiming(myifname : ansistring; mybt : p_mybt) : longint; cdecl; external;function can_set_ctrlmode(myifname : ansistring; mycm : p_mycm ) : longint; cdecl; external; //These functions work with user rights function can_get_restart_ms(myifname : ansistring; myrms : pdword)  :longint; cdecl; external;function can_get_bittiming(myifname : ansistring; mybt : p_mybt ) : longint; cdecl; external;function can_get_ctrlmode(myifname : ansistring; mycm : p_mycm) :longint; cdecl; external;function can_get_state(myifname : ansistring; mystate : pdword): longint; cdecl; external;function can_get_clock(myifname : ansistring; myclock : p_myclk) :longint; cdecl; external;function can_get_bittiming_const(myifname : ansistring; mybtc : p_mybtc) :longint; cdecl; external;function can_get_berr_counter(myifname : ansistring; mybcs : p_mybcs):longint; cdecl; external;function can_get_device_stats(myifname : ansistring; mycds : p_mycds):longint; cdecl; external;function can_get_link_stats(myifname : ansistring; myrls : p_myrls):longint; cdecl; external;  implementation  end.  I have tested all the 'get' and from the 'set' the ones I would need. Doing that, was easier than using ip commands and parsing the text returns for the desired value. ---------------------------------------------------------------------- avra · 2021-06-09 11:51 Quote from: ThomasK on June 03, 2021, 01:20:16 pmBut the num_events is always either 0 or 1 even if more than 1 message was sent to the port.Based on a quick look, it seams to me that instead of a single PEPoll_event you should try to create an array of PEPoll_event, pass number of elements to epoll_create(), and pass PEPoll_event array to epoll_wait(). Exactly аs in C demo that you can find at https://linux.die.net/man/7/epoll. I know that epoll_create() with kernels newer then 2.6.8 should not care for size parameter (as long as it's positive), but C demo thinks that it does matter so you should probably listen to it (at least until you make it work). Quote from: ThomasK on June 08, 2021, 10:19:01 amI converted the LibSocketCAN library into a Pascal Unit.Very nice and thank you! If you agree to put the same license as in my CAN wrapper and demos, then I can add your wrapper also - if you add some simple console demo (of course, it will be clear who is the author of which file). What I would probably do is rename LibSockCAN.pas to can.lib.pas, and rename if_linkpart.pas (which is missing, btw) to can.if.linkpart.inc and include it from can.lib unit. What do you think? ---------------------------------------------------------------------- ThomasK · 2021-06-09 12:50 Quote from: avra on June 09, 2021, 01:51:33 pm (at least until you make it work). I actually don't care how many events occur, because the epoll is fixed to the event EPOLLIN. As long as the query returns '1' there is data to read, if  it is '0' then not. Quote from: avra on June 09, 2021, 01:51:33 pmVery nice and thank you! If you agree to put the same license as in my CAN wrapper and demos, then I can add your wrapper also - if you add some simple console demo (of course, it will be clear who is the author of which file). I can rework the whole stuff, no problem Is really a console application required? A GUI exists, which I left out of the .zip due to its size and in case of a console app I would have to do a cmd parser...... Quote from: avra on June 09, 2021, 01:51:33 pmWhat I would probably do is rename LibSockCAN.pas to can.lib.pas, and rename if_linkpart.pas (which is missing, btw) to can.if.linkpart.inc and include it from can.lib unit. What do you think? I can do the renaming, the licensing stuff and and check if all is available, no problem.  I am working on another topic : https://forum.lazarus.freepascal.org/i ndex.php/topic,54944.msg408418.html#msg408418 and want to solve that too. Pic of the GUI attached. ---------------------------------------------------------------------- avra · 2021-06-09 16:45 Quote from: ThomasK on June 09, 2021, 02:50:44 pmIs really a console application required? A GUI exists, which I left out of the .zip due to its size and in case of a console app I would have to do a cmd parser......Although you can find basic cmd parsers in hlcanerrdump and hlcanerrsim, there is really no need to go that far. Just fix interface name and other needed parameters in code and that shall be fine. GUI advanced demos are nice, but SocketCAN package will be part of FPC and there is a good chance that it will run on a headless SBC without Lazarus, so simple console demos are more important. Quote from: ThomasK on June 09, 2021, 02:50:44 pmQuote from: avra on June 09, 2021, 01:51:33 pmWhat I would probably do is rename LibSockCAN.pas to can.lib.pas, and rename if_linkpart.pas (which is missing, btw) to can.if.linkpart.inc and include it from can.lib unit. What do you think?I can do the renaming, the licensing stuff and and check if all is available, no problem.Thanks! It would be great if you could use license templates from my demos and wrappers. Quote from: ThomasK on June 09, 2021, 02:50:44 pmI am working on another topic : https://forum.lazarus.freepascal.org/index.php/topic,5 4944.msg408418.html#msg408418 and want to solve that too. Pic of the GUI attached.Nice. I wrote a solution proposal there. ---------------------------------------------------------------------- ThomasK · 2021-06-10 09:17 Hello Avra, I have reworked the library and included the definition for Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i rtnl_link_stats64  =   record in can.lib.pas library itself, like in libsocketcan.h. Explanations of this data type can be found for example here https://github.com/torval ds/linux/blob/master/include/uapi/linux/if_link.h. I updated the license disclaimer of the original libsocketcan.h and added it to the library. Besides the can.lib.pas, only can.netlink.pas is required to use libsocketcan. A demo GUI application for Lazarus is included, it does not exercise all functions with all parameters set, but the use becomes clear. If you want to use "set" commands it must be started with root rights, otherwise they fail. Feel free to use the lib.can.pas together with your code. rgds, Thomas ---------------------------------------------------------------------- avra · 2021-06-10 13:31 Thanks Thomas, very nice! I will take a look as soon as I get some free time. ---------------------------------------------------------------------- avra · 2021-07-01 13:45 @Thomas: I have made small changes needed for your LibSocketCAN wrapper and demo to fit the rest of the project. Please review and comment if needed. @Everyone: I am also thinking about making a high level pascal like interface to avoid ugly c naming in LibSocketCAN, like I already did for SocketCAN. However, I do not know if I should add it to can.hl.pas where the rest of the high level stuff is, or to a separate unit? I am in doubt since LibSocketCAN wrapper in can.lib.pas has {$linklib libsocketcan} which is a dependency that needs installation (from source or package manager), and I don't want to force that dependency to all SocketCAN users. Is lib dependency forced on everyone as soon as we include lib with $linklib, or we need to call something from that lib first? I do not know this so I ask if someone else knows? ---------------------------------------------------------------------- ThomasK · 2021-07-28 08:48 @Avra, sorry for the late reply, I changed job so my days are very busy.... I will review the new demo and come back. About integration of LibSocketCAN into can.hl my two cents are keep it as an tool on top, because  it is not always needed but a grip to do some diagnostics. Chers! ---------------------------------------------------------------------- avra · 2021-07-28 10:43 Quote from: ThomasK on July 28, 2021, 10:48:34 amsorry for the late reply, I changed job so my days are very busy.... I will review the new demo and come back.Take your time. No rush. Quote from: ThomasK on July 28, 2021, 10:48:34 amAbout integration of LibSocketCAN into can.hl my two cents are keep it as an tool on top, because it is not always needed but a grip to do some diagnostics.Your wrapper will stay as can.lib unit, and future pascalish thin wrapper will be a separate can.lib.hl unit. That way we will still be able to easily convert C demos when needed, while having more eye pleasing pascalish named access as with the rest of the high level CAN. I wish you well on your new job! ---------------------------------------------------------------------- jcdammeyer · 2021-09-24 08:04 Quote from: avra on March 11, 2021, 03:12:31 pm@jcdammeyer: CAN FD receive and transmit demos are here.  It was not trivial to find info of what exactly to change when compared to legacy CAN but it works now. Oh my gosh.  I've finally finished a fairly large work-work project this summer and was thinking about getting back to this and I must have missed an email that the thread had been updated.  Wow!  Time for me to dig back into this since it's part of a larger project on CANopen Lite I'd like to do with Lazarus. In fact I'm using one of my dsPIC modules with very simple CANopen messaging from LinuxCNC to run a power drawbar.  The LinuxCNC code is python interfaced with the AXIS user interface but the connection is via the Lawicel CANUSB dongle and serial port commands.  I'll go through the entire thread and do some testing as soon as I finish a CNC conversion to new AC Servos.  I really do want to get back to this. John ---------------------------------------------------------------------- avra · 2021-09-24 10:24 Quote from: jcdammeyer on September 24, 2021, 10:04:17 amOh my gosh.  I've finally finished a fairly large work-work project this summer and was thinking about getting back to this and I must have missed an email that the thread had been updated.  Wow!I'm glad you like the progress.  I'm waiting for my bithelpers (actually new name as agreed with devs is syshelpers) FPC patch to become fully accepted (direct bit/nibble/byte/word/dword array like access already works in trunk as can be seen at https://gitlab.com/freepascal.org/fpc/source/-/issues/39268), and then I will need to write syshelpers documentation. After that gets completed, plan is to polish SocketCAN a little more and make an official FPC patch so it can be used out of the box. Good news for you is that Lawicel works with SocketCAN. Bad news is that while J1939 base support exists (demos not included yet), CANopen support is not comming any time soon. Right now I need plain CAN and J1939 for some of my freelance work so that's in focus, but since I do CAN a lot it is possible that at some moment I will deal with CANopen, too. No promisses and no schedule, but tiny possibility is there. If you need CANopen now, then you will have to implement it on your own. Patches are welcome. ---------------------------------------------------------------------- jcdammeyer · 2021-09-24 17:30 Quote from: avra on September 24, 2021, 12:24:45 pmI'm glad you like the progress.  If you need CANopen now, then you will have to implement it on your own. Patches are welcome. The problem with CANopen is it's huge and for 99% of the projects (IMHO) doesn't need to be.  For example, a big deal is made over the support of the configuration files.  Useful for the non-programmer mechanical engineer or installer but for someone who writes in Delphi or Lazarus not so much.  Building up the object dictionary (OD) to show the size of variables pointless and just takes up a lot of code/data space.  Creating a be all end all installation would be nice but also overkill and hard to understand and maintain. So I'm proposing a CANopen Lite.  That can deal with COTS (Commercial Off The Shelf) devices but might require a bit of programming to interface with.  To start with I've started with a simple monitoring program that at the moment uses the CANUSB.  So far this software has run on WIN-PC, BeagleBone and Pi.  To migrate to socketCAN it will need a level of abstraction built in so we can open a device like the internal processor built in CAN on a BeagleBone or a Pi3 HAT that uses the MCP2515 SPI to CAN device and of course the socketCAN version of CANUSB.  I have two HATs for the Pi, a cape for the Beagle and lots of CANUSB plus a few expensive commercial USB dongles. I will of course make the entire program open source. ---------------------------------------------------------------------- avra · 2021-09-24 23:02 Quote from: jcdammeyer on September 24, 2021, 07:30:21 pmTo migrate to socketCAN it will need a level of abstraction built in so we can open a device like the internal processor built in CAN on a BeagleBone or a Pi3 HAT that uses the MCP2515 SPI to CAN device and of course the socketCAN version of CANUSB.Step-by-step guide on using Lawicel CANUSB via SocketCAN: https://pascal-walter.blogspot.com/2015/08/installing- lawicel-canusb-on-linux.html ---------------------------------------------------------------------- jcdammeyer · 2021-09-24 23:10 Quote from: avra on September 25, 2021, 01:02:20 amQuote from: jcdammeyer on September 24, 2021, 07:30:21 pmTo migrate to socketCAN it will need a level of abstraction built in so we can open a device like the internal processor built in CAN on a BeagleBone or a Pi3 HAT that uses the MCP2515 SPI to CAN device and of course the socketCAN version of CANUSB.Step-by-step guide on using Lawicel CANUSB via SocketCAN: https://pascal-walter.blogspot.com/2015/08/installing- lawicel-canusb-on-linux.html Yes.  Thank you.  That's not an issue.  I've dumped CAN packets from working systems using socketCAN with the CANUSB on the PI3/4.  But that's using the C language command line programs.  A couple of years ago now I had to record Hydrogen powered vehicle CAN messages from ignition key on and the Pi wasn't capable of booting in under 14 seconds.   So instead I put together a small PIC32 with CAN module that logged/timestamped all CAN messages along with GPS information and sent them up via SPI to the PiZero once it was awake. On the Pi they were saved in files and another application would grab them and put them on the cloud for the engineers to use for diagnostics. Really looking forward to playing with your socketCAN stuff. John ---------------------------------------------------------------------- avra · 2021-09-25 09:02 Quote from: jcdammeyer on September 25, 2021, 01:10:02 amI've dumped CAN packets from working systems using socketCAN with the CANUSB on the PI3/4.  But that's using the C language command line programs.As you progress through pascal SocketCAN demos, you will see that low level units will help when you want to convert C examples from the net since it will mostly be 1:1 translation as far as SocketCAN part is concerned. Once you get a feeling, you will quickly advance to more natural pascalish high level unit. Quote from: jcdammeyer on September 25, 2021, 01:10:02 amReally looking forward to playing with your socketCAN stuff.I wish you as much fun as I have! ---------------------------------------------------------------------- jcdammeyer · 2021-09-26 03:49 Quote from: avra on September 25, 2021, 11:02:03 amI wish you as much fun as I have!  Not quite yet. Under Lazarus I can create a console project, add this writeln('Hello World from my Console Application');  in the appropriate spot and then either run it from the IDE or from the console with that output. Opening the canreceive project from the can.zip file compiles but doesn't generate an executable on the Beaglebone as shown in the attached screen shot. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     s := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);And the BBB sockets.pp doesn't have PF_CAN so the can.zip file by itself isn't enough to compile and test.  ie. if I add this along with the perror function it complains about the missing PF_CAN Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     s := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);    if s < 0 then    begin      perror('Socket');      Exit;    end;  Would you be able to create a canreceive.zip with a console application who's sole purpose is to open say slcan0 and just dump out messages like your canreceive.  For example the 3 attachments show that the CANUSB on /dev/ttyUSB0 can be accessed as a serial port via the CANopenLite application but can also be configured as slcan0 as shown in the other photo working with the socketCAN candump application. So my hardware works.  Now the software. ---------------------------------------------------------------------- avra · 2021-09-26 15:00 Quote from: jcdammeyer on September 26, 2021, 05:49:40 amBBB sockets.pp doesn't have PF_CANAs mentioned at https://forum.lazarus.fr eepascal.org/index.php/topic,39858.msg396135.html#msg396135 you need newer FPC so getting trunk would be a good idea. If that is not for you, then instead you could simply define missing constants PF_CAN and AF_CAN as 29 somewhere in your code. After that, it would be good to create vcan0 virtual adapter and go through demos since they should all work out of the box. Quote from: jcdammeyer on September 26, 2021, 05:49:40 amWould you be able to create a canreceive.zip with a console application who's sole purpose is to open say slcan0 and just dump out messages like your canreceive.Once you have demos working with vcan0, making them work with slcan0 should be trivial. For example, in canreceive.lpr or hlcanreceive.lpr, all you need is to replace 'vcan0' with 'slcan0' at one place in code (as shown in your 3rd attachment). ---------------------------------------------------------------------- jcdammeyer · 2021-09-26 17:22 Quote from: avra on September 26, 2021, 05:00:21 pmQuote from: jcdammeyer on September 26, 2021, 05:49:40 amBBB sockets.pp doesn't have PF_CANAs mentioned at https://forum.lazarus.freepascal.org/index. php/topic,39858.msg396135.html#msg396135 you need newer FPC so getting trunk would be a good idea. If that is not for you, then instead you could simply define missing constants PF_CAN and AF_CAN as 29 somewhere in your code. After that, it would be good to create vcan0 virtual adapter and go through demos since they should all work out of the box. Sadly this link doesn't work anymore which is why I posted the question. QuoteCAN constants have been added to FPC 48867: https://svn.freepascal.org/svn/fpc/trunk/packages/rtl- extra/src/linux/unxsockh.inc In fact I can't even access https://svn.freepasccal.org ---------------------------------------------------------------------- dsiders · 2021-09-26 18:07 Quote from: jcdammeyer on September 26, 2021, 07:22:11 pmQuoteCAN constants have been added to FPC 48867: https://svn.freepascal.org/svn/fpc/trunk/packages/rtl- extra/src/linux/unxsockh.inc In fact I can't even access https://svn.freepasccal.org You have two issues: The URL was https://svn.freepascal.org and not https://svn.freepasccal.org. They moved to GitLab a few months back and the svn server no longer exists. There is a GitHub SVN mirror at: https://github.com/fpc/FPCSource, but the vcs of record is git located at: https://gitlab.com/freepascal.org/fpc/source. ---------------------------------------------------------------------- jcdammeyer · 2021-09-26 18:45 Incorrect spelling.  Sorry about that.  If possible then the link way back should be edited to point to the correct location. What I did is add the PF_CAN and AF_CAN definitions into my code.  I also did put them into unxsockh.inc but it didn't have any effect.  Perhaps there's another copy being used instead. Here's the results of the code below where I cut and pasted the canreceive.lpr section: Code: [Select]debian@ebb:~/lazarus/AvraCAN$ ./ConsoleApplication Hello World from Console Application CAN Sockets Receive Demo Rev 0.01 fpsocket call fpioctl call fpbind call fpread call Standard CAN frame received with length 1 0x718 [1] 05 debian@ebb:~/lazarus/AvraCAN$ Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program ConsoleApplication; {$mode delphi}{$H+} uses  {$IFDEF UNIX}{$IFDEF UseCThreads}  cthreads,  {$ENDIF}{$ENDIF}  Classes, SysUtils, CustApp,  { you can add units after this }  sockets, baseunix, can; const         PF_CAN = 29;         AF_CAN = 29; type   { TMyApplication }   TMyApplication = class(TCustomApplication)  protected    procedure DoRun; override;  public    constructor Create(TheOwner: TComponent); override;    destructor Destroy; override;    procedure WriteHelp; virtual;    procedure perror(const S : string);    procedure MyApplicationMain;  end; { TMyApplication }procedure TMyApplication.perror(const S : string);begin  WriteLn(S, ', SocketError = ', SocketError);end;  procedure TMyApplication.MyApplicationMain;var  s, i, nbytes, err: cint;  addr:            sockaddr_can;  ifr:               ifreq;  frame:           canfd_frame;begin  Writeln('Hello World from Console Application');  WriteLn('CAN Sockets Receive Demo Rev 0.01');  writeln('fpsocket call');  s := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);  if s < 0 then  begin    perror('Socket');    Exit;  end;   writeln('fpioctl call');  strcopy(ifr.ifr_name, 'slcan0'); // ifr.ifr_name := 'vcan0' + #0;  if fpioctl(s, SIOCGIFINDEX, @ifr) < 0 then  begin    perror('IOctl');    Exit;  end;   writeln('fpbind call');  memset(@addr, 0, sizeof(addr));  addr.can_family  := AF_CAN;  addr.can_ifindex := ifr.ifr_ifindex;   if fpbind(s, @addr, sizeof(addr)) < 0 then  begin  perror('Bind');    Exit;  end;   writeln('fpread call');  nbytes := fpread(s, frame, sizeof(frame));  if nbytes < 0 then  begin    perror('Read');    Exit;  end;   if nbytes = CANFD_MTU then    // test CAN FD with 'cansend vcan0 123##1223344556677889900'    WriteLn('CAN FD frame received with length ', IntToStr(frame.len))  else if nbytes = CAN_MTU then // test legacy CAN with 'cansend vcan0 456#DEADBEEF'  WriteLn('Standard CAN frame received with length ', IntToStr(frame.len))  else    WriteLn('Invalid CAN(FD) frame received');   Write(Format('0x%03X [%d] ', [frame.can_id and CAN_EFF_MASK, frame.len]));  for i := 0 to frame.len - 1 do    Write(Format('%02.2X ', [frame.data[i]]));  WriteLn('');   if fpclose(s) < 0 then  begin    perror('Close');    Exit;  end; end; procedure TMyApplication.DoRun;var  ErrorMsg: String;begin  // quick check parameters  ErrorMsg:=CheckOptions('h', 'help');  if ErrorMsg<>'' then begin    ShowException(Exception.Create(ErrorMsg));    Terminate;    Exit;  end;   // parse parameters  if HasOption('h', 'help') then begin    WriteHelp;    Terminate;    Exit;  end;   { add your program here }  MyApplicationMain;   // stop program loop  Terminate;end; constructor TMyApplication.Create(TheOwner: TComponent);begin  inherited Create(TheOwner);  StopOnException:=True;end; destructor TMyApplication.Destroy;begin  inherited Destroy;end; procedure TMyApplication.WriteHelp;begin  { add your help code here }  writeln('Usage: ', ExeName, ' -h');end; var  Application: TMyApplication;begin  Application:=TMyApplication.Create(nil);  Application.Title:='My Application';  Application.Run;  Application.Free;end.   No idea why canreceive.lpr won't compile into an executable. ---------------------------------------------------------------------- jcdammeyer · 2021-09-26 20:32 I've updated the program and formatted it to match the socketCAN candump program.  Only does standard IDs, no Extended ID or CANFD.  CANFD likely won't happen as I have absolutely no CANFD units here and no desire to actually use it.  99.9% of everything I have in stock in drivers, devices, dongles are all non-CANFD. Quotedebian@ebb:~/lazarus/AvraCAN$ ./ConsoleApplication CAN Sockets Receive Demo Rev 0.1 Build 5 slcan0  298   [7]  00 00 00 00 01 00 00 slcan0  718   [1]  05 slcan0  298   [7]  00 00 00 00 01 00 00 slcan0  298   [7]  00 00 00 00 01 00 00 slcan0  718   [1]  05 slcan0  298   [7]  00 00 00 00 01 00 00 slcan0  298   [7]  00 00 00 00 01 00 00 slcan0  718   [1]  05 slcan0  298   [7]  00 00 00 00 01 00 00 slcan0  298   [7]  00 00 00 00 01 00 00 slcan0  718   [1]  05 debian@ebb:~/lazarus/AvraCAN$ And here's the updated console application.  I'll hang a module on that generates Extended 29 bit ID messages and add support for that to match candump.  I'll also add a command line parameter that allows defining which CAN device is to be used.  Since this test is on a Beagle I'll put the CAN cape on it, verify with the socketCAN candump that it works and then test it with the Lazarus program. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program ConsoleApplication; {$mode delphi}{$H+} uses  {$IFDEF UNIX}{$IFDEF UseCThreads}  cthreads,  {$ENDIF}{$ENDIF}  Classes, SysUtils, CustApp,  { you can add units after this }  crt,  { for the keypressed function }  sockets, baseunix, can;  { for socketCAN support } const       PF_CAN = 29;  // Not defined in libraries yet.         AF_CAN = 29; type   { TMyApplication }   TMyApplication = class(TCustomApplication)  protected    procedure DoRun; override;  public    constructor Create(TheOwner: TComponent); override;    destructor Destroy; override;    procedure WriteHelp; virtual;    procedure perror(const S : string);    procedure MyApplicationMain;  end; { TMyApplication }procedure TMyApplication.perror(const S : string);begin  WriteLn(S, ', SocketError = ', SocketError);end;  procedure TMyApplication.MyApplicationMain;var  s, i, nbytes, err: cint;  addr:              sockaddr_can;  ifr:             ifreq;  frame:             canfd_frame; begin//  Writeln('Hello World from Console Application');  WriteLn('CAN Sockets Receive Demo Rev 0.1 Build 5');//  writeln('fpsocket call');  s := fpsocket(PF_CAN, SOCK_RAW, CAN_RAW);  if s < 0 then  begin    perror('Socket');    Exit;  end; //  writeln('fpioctl call');  strcopy(ifr.ifr_name, 'slcan0'); // ifr.ifr_name := 'vcan0' + #0;  if fpioctl(s, SIOCGIFINDEX, @ifr) < 0 then  begin    perror('IOctl');    Exit;  end; //  writeln('fpbind call');  memset(@addr, 0, sizeof(addr));  addr.can_family  := AF_CAN;  addr.can_ifindex := ifr.ifr_ifindex;   if fpbind(s, @addr, sizeof(addr)) < 0 then  begin    perror('Bind');    Exit;  end;   while (not keypressed) do begin    //  writeln('fpread call');      nbytes := fpread(s, frame, sizeof(frame));      if nbytes < 0 then      begin        perror('Read');        Exit;      end;     if nbytes = CANFD_MTU then    // test CAN FD with 'cansend vcan0 123##1223344556677889900'        WriteLn('CAN FD frame received with length ', IntToStr(frame.len))      else if nbytes = CAN_MTU then // test Standard CAN with 'cansend vcan0 456#DEADBEEF'    //    WriteLn('Standard CAN frame received with length ', IntToStr(frame.len))          write(ifr.ifr_name, '  ')      else      WriteLn('Invalid CAN(FD) frame received');       Write(Format('%03X [%d]  ', [frame.can_id and CAN_EFF_MASK, frame.len]));      for i := 0 to frame.len - 1 do        Write(Format('%02.2X ', [frame.data[i]]));      WriteLn('');  end;   if fpclose(s) < 0 then  begin    perror('Close');    Exit;  end; end; procedure TMyApplication.DoRun;var  ErrorMsg: String;begin  // quick check parameters  ErrorMsg:=CheckOptions('h', 'help');  if ErrorMsg<>'' then begin    ShowException(Exception.Create(ErrorMsg));    Terminate;    Exit;  end;   // parse parameters  if HasOption('h', 'help') then begin    WriteHelp;    Terminate;    Exit;  end;   { add your program here }  MyApplicationMain;   // stop program loop  Terminate;end; constructor TMyApplication.Create(TheOwner: TComponent);begin  inherited Create(TheOwner);  StopOnException:=True;end; destructor TMyApplication.Destroy;begin  inherited Destroy;end; procedure TMyApplication.WriteHelp;begin  { add your help code here }  writeln('Usage: ', ExeName, ' -h');end; var  Application: TMyApplication;begin  Application:=TMyApplication.Create(nil);  Application.Title:='My Application';  Application.Run;  Application.Free;end.   John ---------------------------------------------------------------------- jcdammeyer · 2021-09-26 20:47 Oh and the messages you see are generated by the module in the photo.  The buttons enable an air cylinder and butterfly impact wrench to act as a power drawbar and are displayed on the Pi4 LinuxCNC display.  The Mist Coolant has been turned on so the 0x44 represents that output command and in the high nibble the output status.   You can see the bits in the PDO message changing as I press the button and the drawbar state machine is activated with one other output also switched ON.  The Pi4 LinuxCNC talks to the CAN bus via another Lawicel CANUSB.  QuoteCAN Sockets Receive Demo Rev 0.1 Build 5 slcan0  298   [7]  00 44 00 00 01 00 00 slcan0  718   [1]  05 slcan0  298   [7]  00 44 00 00 01 00 00 slcan0  298   [7]  00 44 00 00 01 00 00 slcan0  718   [1]  05 slcan0  298   [7]  00 44 00 00 01 00 00 slcan0  298   [7]  00 44 00 00 01 00 00 slcan0  718   [1]  05 slcan0  298   [7]  00 44 00 00 01 00 00 slcan0  298   [7]  00 44 00 00 01 00 00 slcan0  298   [7]  02 44 00 00 01 00 02 slcan0  298   [7]  00 66 00 00 06 00 00 slcan0  718   [1]  05 slcan0  298   [7]  00 66 00 00 06 00 00 slcan0  298   [7]  00 66 00 00 06 00 00 slcan0  718   [1]  05 slcan0  298   [7]  00 66 00 00 06 00 00 slcan0  298   [7]  00 66 00 00 06 00 00 slcan0  718   [1]  05 slcan0  298   [7]  00 44 00 00 01 00 00 slcan0  298   [7]  00 44 00 00 01 00 00 slcan0  718   [1]  05 It's not yet mounted on the machine.  I only just learned about postings from avra on this.  For some reason I missed the email that things were being done.  Been a busy summer.  And yes.  Now I'm having fun again. ---------------------------------------------------------------------- jcdammeyer · 2021-09-26 23:04 This link had me confused for a bit, especially since I was referencing CAN0 in my notes too.  https://github.com/BlueAndi/beaglebone_black_socketcan However, that same cape does say CAN1 on it so when I switched to setting it up as CAN1 candump now works. I recompiled the ConsoleApplication again to use can1 and then slcan0 and the Beagle now has two functional CAN bus channels; Lawicel CANUSB and the internal Beagle bone CAN1 Quotedebian@ebb:~$ candump can1   can1  298   [7]  00 44 00 00 01 00 00   can1  718   [1]  05   can1  298   [7]  00 44 00 00 01 00 00   can1  298   [7]  00 44 00 00 01 00 00   can1  718   [1]  05   can1  298   [7]  00 44 00 00 01 00 00 ^Cdebian@ebb:~$ cd lazarus/AvraCAN/ debian@ebb:~/lazarus/AvraCAN$ ./ConsoleApplication CAN Sockets Receive Demo Rev 0.1 Build 6 can1  298   [7]  00 44 00 00 01 00 00 can1  718   [1]  05 can1  298   [7]  00 44 00 00 01 00 00 can1  298   [7]  00 44 00 00 01 00 00 can1  718   [1]  05 can1  298   [7]  00 44 00 00 01 00 00 can1  298   [7]  00 44 00 00 01 00 00 can1  718   [1]  05 debian@ebb:~/lazarus/AvraCAN$ sudo ifconfig slcan0 up [sudo] password for debian: debian@ebb:~/lazarus/AvraCAN$ ./ConsoleApplication CAN Sockets Receive Demo Rev 0.1 Build 7 slcan0  298   [7]  00 44 00 00 01 00 00 slcan0  718   [1]  05 slcan0  298   [7]  00 44 00 00 01 00 00 slcan0  298   [7]  00 44 00 00 01 00 00 slcan0  718   [1]  05 debian@ebb:~/lazarus/AvraCAN$ ---------------------------------------------------------------------- jcdammeyer · 2021-09-27 06:59 BTW, if anyone wants more of a write-up on socketCAN this link might be useful.  The link is also in the can.pas application provided by avra: https://www.kernel.org/doc/html/v5.10/networking/can.html Also back in 2013 when I attended the CANopen Conference in Germany the attached pdf was one of the presentations.  This presentation goes over the Volkswagon contribution by Oliver Hartkopp who is also referenced in the can.pas document. Just a bit of history... ---------------------------------------------------------------------- avra · 2021-09-28 11:47 Quote from: jcdammeyer on September 26, 2021, 08:45:45 pmI also did put them into unxsockh.inc but it didn't have any effect.That would have also worked after FPC rebuilding. Quote from: jcdammeyer on September 26, 2021, 08:45:45 pmNo idea why canreceive.lpr won't compile into an executable.What is the compilation error message? What FPC/LAZ/OS/ARCH/Bitness combo was used? Did you manage to compile other demos? Quote from: jcdammeyer on September 27, 2021, 08:59:05 amAlso back in 2013 when I attended the CANopen Conference in Germany the attached pdf was one of the presentations.Nice and simple bridge and ISO examples. ---------------------------------------------------------------------- jcdammeyer · 2021-09-28 17:14 Quote from: avra on September 28, 2021, 01:47:04 pmQuote from: jcdammeyer on September 26, 2021, 08:45:45 pmI also did put them into unxsockh.inc but it didn't have any effect.That would have also worked after FPC rebuilding. Unfortunately at this point you lose me on what to do there.  I ran fpcupdeluxe to install the same version on the PC, Pi3/4 and BBB.  I would need the simpleton step by step procedure to do the 'FPC rebuilding' along with a "why I am doing what I'm doing" QuoteQuote from: jcdammeyer on September 26, 2021, 08:45:45 pmNo idea why canreceive.lpr won't compile into an executable.What is the compilation error message? What FPC/LAZ/OS/ARCH/Bitness combo was used? Did you manage to compile other demos? I opened up the .lpi project from Lazarus and did a build.  The screen capture I posted earlier and again here shows the result.  I tried a number of options with no success in creating an executable.  That's when I used the lazarus 'new' and selected console application program to create my stock application.  Then coppied and pasted the key parts that were needed to duplicate the basic functionality of candump. Last night I created a new folder 'lazcandump' and copied over the initial files that appeared to be needed based on the uses clause and the {$i lines.  And then a bunch more that I'm not sure where were {$i when the compiler complained.  {It was late.  Easier to copy over than figure out why} It now accepts 'can1' or 'slcan0' on the command line and then dumps the messages in the same way as the socketCAN candump.  I plugged a mcp2515 CAN hat into a Pi4 running LinuxCNC.  I think I still have to install Lazarus on that Pi4 but the socketCAN candump shows the messages created by the CANUSB when a checkbox is clicked on the LinuxCNC AXIS display.  More on that by the end of the day if all goes well. QuoteQuote from: jcdammeyer on September 27, 2021, 08:59:05 amAlso back in 2013 when I attended the CANopen Conference in Germany the attached pdf was one of the presentations.Nice and simple bridge and ISO examples. I do have a zip of the entire conference proceedings (47MB) including my presentation (1.4MB) all too big to post here. ---------------------------------------------------------------------- jcdammeyer · 2021-09-28 17:58 There we go.  The 29 bit Extended IDs in addition to 11 bit Standard IDs are now also supported in the lazcandump.  The Extended ID message is only sent on change of one of the two checkboxes in LinuxCNC with a single byte of null data.  ie.  No important information.  Just the message to show it works.  The captured data here from the CANUSB  was done with puTTY into the BBB while lazcandump was also running on a terminal screen on the BBB working with the internal CAN1. Oh and via puTTY I can run lazcandump can1 while it's also running on the BBB terminal session so it's sharing nicely. Next step, make lazcandump  work on the Pi4 Quoteslcan0       298 [7]  00 00 00 00 01 00 00 slcan0       298 [7]  00 00 00 00 01 00 00 slcan0       318 [1]  04 slcan0  12345678 [1]  00 slcan0       718 [1]  05 slcan0       298 [7]  00 44 00 00 01 00 00 slcan0       298 [7]  00 44 00 00 01 00 00 slcan0       718 [1]  05 slcan0       298 [7]  00 44 00 00 01 00 00 slcan0       318 [1]  00 slcan0  12345678 [1]  00 slcan0       298 [7]  00 00 00 00 01 00 00 ---------------------------------------------------------------------- jcdammeyer · 2021-09-29 03:29 I'm ready to try it on the Raspberry Pi4.  However something odd and this may not be the right thread to ask the question. The Pi4 has the folder fcpupdeluxe as shown in the attached photo.  However there's no shortcut to it on the desktop.  I don't remember at what point I stopped with the installation or if I even installed it. The BBB has this as the desktop link: Quote[Desktop Entry] Version=1.0 Encoding=UTF-8 Type=Application Icon=/home/debian/fpcupdeluxe/lazarus/images/icons/lazarus.ico Exec=/home/debian/fpcupdeluxe/lazarus/lazarus --pcp="/home/debian/fpcupdeluxe/config_lazarus" %f Name=Lazarus_fpcupdeluxe GenericName=Lazarus IDE with Free Pascal Compiler Category=Application;IDE;Development;GUIDesigner;Programming; Categories=Application;IDE;Development;GUIDesigner;Programming; Keywords=editor;Pascal;IDE;FreePascal;fpc;Design;Designer; Suggestions? Thanks John ---------------------------------------------------------------------- avra · 2021-09-29 07:32 Quote from: jcdammeyer on September 28, 2021, 07:14:33 pmQuote from: avra on September 28, 2021, 01:47:04 pmQuote from: jcdammeyer on September 26, 2021, 08:45:45 pmI also did put them into unxsockh.inc but it didn't have any effect.That would have also worked after FPC rebuilding. Unfortunately at this point you lose me on what to do there.  I ran fpcupdeluxe to install the same version on the PC, Pi3/4 and BBB.  I would need the simpleton step by step procedure to do the 'FPC rebuilding' along with a "why I am doing what I'm doing"FPC rebuild steps for Windows: https://forum.lazarus.freepascal.org/index.php/topi c,55358.msg411825.html. Shouldn't be too difficult to adapt for Linux. Ah, yes... do not forget to rebuild Lazarus as well, so IDE can be aware of FPC changes. Quote from: jcdammeyer on September 28, 2021, 07:14:33 pmQuoteQuote from: jcdammeyer on September 26, 2021, 08:45:45 pmNo idea why canreceive.lpr won't compile into an executable.What is the compilation error message? What FPC/LAZ/OS/ARCH/Bitness combo was used? Did you manage to compile other demos? I opened up the .lpi project from Lazarus and did a build.  The screen capture I posted earlier and again here shows the result.  I tried a number of options with no success in creating an executable.I can see on the screenshot that compilation was a success, so canreceive file should be created. It also seams that you tried to run it from IDE, which I do not recommend. Better try to run it from the terminal. If file canreceive exists, then maybe you just need to manually flag it as an executable? What about other demos? Could you compile them and run, or not? Quote from: jcdammeyer on September 26, 2021, 08:45:45 pmI do have a zip of the entire conference proceedings (47MB) including my presentation (1.4MB) all too big to post here.What was the topic of your presentation? Quote from: jcdammeyer on September 29, 2021, 05:29:31 amThe Pi4 has the folder fcpupdeluxe as shown in the attached photo.  However there's no shortcut to it on the desktop.  I don't remember at what point I stopped with the installation or if I even installed it. The BBB has this as the desktop link:Excluding path difference, I have identical desktop shortcut on my Debian XFCE system so you should be good to copy and use yours in another system. I'm so glad to see your progress. ---------------------------------------------------------------------- jcdammeyer · 2021-09-29 08:06 1. Really.  It didn't compile it.  Very strange. Quotedebian@ebb:/$ sudo find / -name canreceive* [sudo] password for debian: /home/debian/lazarus/AvraCAN/canreceive.lpi /home/debian/lazarus/AvraCAN/canreceive.lpr /home/debian/lazarus/AvraCAN/backup/canreceive.lpi /home/debian/lazarus/AvraCAN/backup/canreceive.lpr /home/debian/lazarus/AvraCAN/backup/canreceive.lps /home/debian/lazarus/AvraCAN/canreceive.lps debian@ebb:/$ 2. The paper was titled "A large scale CAN bus system".  I put the document here:  http://www.autoartisans.com/rings/ALargeScaleCANbusSystem.pdf 3. I'll try creating a shortcut.  I have no worries about both the CANUSB and SPI MCP2515 working as they both work with the C language candump. ---------------------------------------------------------------------- avra · 2021-09-30 09:33 Quote from: jcdammeyer on September 29, 2021, 10:06:15 am1. Really.  It didn't compile it.  Very strange.Do you have problems generating executable only with canreceive demo, or you have problems with all demos (hlcanreceive...)? If all demos suffer the same problem, then it might be dir/file access rights problem and you could try another directory or fix access rights. ---------------------------------------------------------------------- jcdammeyer · 2021-09-30 16:47 Quote from: avra on September 30, 2021, 11:33:57 amQuote from: jcdammeyer on September 29, 2021, 10:06:15 am1. Really.  It didn't compile it.  Very strange.Do you have problems generating executable only with canreceive demo, or you have problems with all demos (hlcanreceive...)? If all demos suffer the same problem, then it might be dir/file access rights problem and you could try another directory or fix access rights. Haven't had a chance to try that yet.  Yesterday was a battle to get fpcupdeluxe installed on the Pi4 LinuxCNC.  Each time a failure near the end.  Google on the error and others have had the same and the support statement was closing this issue it's a Lazarus problem... But eventually I did get it running and have the same version of Lazarus installed on the Pi4.  Now to make sure that LED sample works.  Probably have to add the same changes we did in the spring to the library. Then on BBB finally after much feedback from Robert Nelson got Buster and a Buster kernel installed on the BBB.  So today I'll take another look at your examples.  Are you compiling them from within Lazarus or just using FPC and command line? ---------------------------------------------------------------------- jcdammeyer · 2021-09-30 19:34 Quote from: jcdammeyer on September 30, 2021, 06:47:00 pmQuote from: avra on September 30, 2021, 11:33:57 amQuote from: jcdammeyer on September 29, 2021, 10:06:15 am1. Really.  It didn't compile it.  Very strange.Do you have problems generating executable only with canreceive demo, or you have problems with all demos (hlcanreceive...)? If all demos suffer the same problem, then it might be dir/file access rights problem and you could try another directory or fix access rights. Haven't had a chance to try that yet.  Yesterday was a battle to get fpcupdeluxe installed on the Pi4 LinuxCNC.  So today I'll take another look at your examples.  Are you compiling them from within Lazarus or just using FPC and command line? Alright.  My project loads and compiles correctly on the Pi4 with Lazarus. I load yours, say hlcanreceive.lpi and the screen shot says it all I think. Your canreceive.lpi does have files because I added them on the beagle and then dragged that folder over to the Pi. As you can see on the screen shot I'm using Lazarus IDE v2.0.10  since that's what's on the Beagle.  Also it's the only one that would actually install without lazarus compile failures on the Pi4.  On the WIN-PC with 2.0.8 r62944 it behaves the same.  The source code file doesn't appear. So let's look at the .lpi file for the simple console application I made from within Lazarus and had the key elements of your receive code cut and pasted.  Using the now 30 year old CodeWright from Borland with the side by side compare perhaps you can see why mine loads the lpr file.  In the Project inspector mine shows ConsoleApplication.pas. Hopefully this helps? ---------------------------------------------------------------------- jcdammeyer · 2021-09-30 19:37 Here's a zip of the console application ---------------------------------------------------------------------- avra · 2021-10-01 10:19 After seeing that your project inspector is empty, and that when comparing LPIs - one XML file has and the other one has just , it is clear that all LPI files have been saved in new Lazarus 2.1+ XML file format, and that was the reason why you have not been able to load project properly, because you have old Lazarus 2.0. For a quick fix you can use this tool: https://sourceforge.net/p/lazarus- ccr/svn/HEAD/tree/applications/fixlp/, but as a permanent solution I will change all project files to be saved in old compatibility mode. ---------------------------------------------------------------------- avra · 2021-10-01 11:23 Attached latest SocketCAN with fixed example projects LPIs. Old Lazarus is now able to open all projects. ---------------------------------------------------------------------- jcdammeyer · 2021-10-01 16:22 Quote from: avra on October 01, 2021, 01:23:36 pmAttached latest SocketCAN with fixed example projects LPIs. Old Lazarus is now able to open all projects. I'll try it today.    At the moment I have to stay with the old Lazarus.  After the 4th try with Stable, Trunk and a mix of those I finally went Trunk and 2.0.10 for Lazarus on the Debian Pi4 LinuxCNC install.   That's the only one that actually would build to completion and put the icon on the desktop.  And at that point I was able to build my code along with that LED 7 segment display program that had the paint issue.  I've forgotten exactly what that was.  Will have to look through the old posts although the code seems to work. ---------------------------------------------------------------------- jcdammeyer · 2021-10-01 16:28 Quote from: avra on October 01, 2021, 12:19:34 pmAfter seeing that your project inspector is empty, and that when comparing LPIs - one XML file has and the other one has just , it is clear that all LPI files have been saved in new Lazarus 2.1+ XML file format, and that was the reason why you have not been able to load project properly, because you have old Lazarus 2.0. For a quick fix you can use this tool: https://sourceforge.net/p/lazarus- ccr/svn/HEAD/tree/applications/fixlp/, but as a permanent solution I will change all project files to be saved in old compatibility mode. I've downloaded it to my PC and then dragged and dropped onto the Pi and the Beagle via windows explorer.  Since I'm running 2.0.10 on the Windows systems too I'll also try it there. What was the reasoning to cripple all old versions of Lazarus with a change to the project format?  Would it not have been better to leave the old and add a replacement for Buildmodes that would be ignored?  For backward compatibility? ---------------------------------------------------------------------- jcdammeyer · 2021-10-01 16:37 Quote from: jcdammeyer on October 01, 2021, 06:28:41 pmQuote from: avra on October 01, 2021, 12:19:34 pmAfter seeing that your project inspector is empty, and that when comparing LPIs - one XML file has and the other one has just , it is clear that all LPI files have been saved in new Lazarus 2.1+ XML file format, and that was the reason why you have not been able to load project properly, because you have old Lazarus 2.0. For a quick fix you can use this tool: https://sourceforge.net/p/lazarus- ccr/svn/HEAD/tree/applications/fixlp/, but as a permanent solution I will change all project files to be saved in old compatibility mode. I've downloaded it to my PC and then dragged and dropped onto the Pi and the Beagle via windows explorer.  Since I'm running 2.0.10 on the Windows systems too I'll also try it there. As the screen shot shows, it went from no files in the project to the list with the members.pas missing and of course won't compile because termio is missing but then this project was never meant to be compatible with windows lazarus so that's no real surprise. More when I get to the Linux systems. ---------------------------------------------------------------------- jcdammeyer · 2021-10-01 21:22 Amazing how much time this eats up. Although the fixlp program compiled and ran and modified the lpi programs it did not create a workable solution.  At least not with 2.0.10 I downloaded the can.zip and that one did work with canreceive.lpi and after modifying to use slcan0 I was able to capture a CAN message.  However compiling hlcanreceive.lpi created a list of 5 files as shown in the screen capture but it breaks. The one I converted had 7 files including members.pas and sockios.pas which also doesn't compile. So there are still some path issues. the -canzip is from the latest can.zip posted.  The -fixlp is the older one that was 'fixed' by fixlp. ---------------------------------------------------------------------- jcdammeyer · 2021-10-02 00:05 Loaded the LinuxCNC MicroSD into the Pi4. Created fixlp folder and compiled fixlp ran from AvraCAN ./fixlp/fixlp hlcanreceive.lpi which created the new .lpi and .lpi.bak Check with file compare and only the expected changes were there.  As the screen shot shows, the members.pas file is not to be found but there are 7 files there. Added the PC_CAN and AF_CAN constants and compiled for slcan0. Then first ran it with slcan0 and saw a real CAN message from the Lawicel CANUSB. Next recompiled with can0 and saw a real CAN message from the MCP2515 HAT. No idea why the other Pi Linux system is having trouble. Next I'll try this on the BeagleBone Black. ---------------------------------------------------------------------- jcdammeyer · 2021-10-02 00:12 Here's the difference between the LinuxCNC Pi4 and the regular Pi4 Linux. Version Value is different and both MainUnit Value and Modes Count don't exist in the fixlp file that doesn't work. I wonder why. ---------------------------------------------------------------------- avra · 2021-10-04 14:53 @jcdammeyer: SocketCAN was never meant to be used with older FPC like 3.0.4. Even newer 3.2.x does not have needed constants. I use it with trunk since there is a plan for SocketCAN to end up in FPC 3.4 or 4.0, whichever comes first. Lazarus version should not matter at all, but it did since I used Lazarus trunk which introduced new LPI format. I fixed that in latest can.zip so use that instead. While constants like AF_CAN, PF_CAN and PF_RDS can be added manually, whole units like termio certainly can't, so I wouldn't bother with such old FPC. Sorry, I do not provide support for that. When I see that you still have members.pas in your LPI file, that tells me that you did not use latest can.zip where I fixed that (fixlp is also not needed with this latest archive). Btw, not having members.pas file in directory does not stop compilation at all. It just notifies you that it could not be found, and since it was not used at all - it didn't matter anyway. I'm glad you somehow managed to compile at all, even with old FPC. ---------------------------------------------------------------------- jcdammeyer · 2021-10-04 16:16 I probably get confused at times too with which system is which.  I'm running a Pi Linux version on one MicroSD and a LinuxCNC on the other.  Add to that a Debian system on the Beagle which was no longer supported so with the help of Robert Nelson was able to upgrade the kernel and the OS to the latest version.  I've only stayed with 2.0.10 because that worked on WIN-10, WIN-7, Linux, LinuxCNC, Pi3/4 and Beagle.  Upgrading one of those to a newer version means it has to be done on everything which is a lot of work.  I've found in the past that it's best to not be on the bleeding edge but I guess trying out socketCAN for Lazarus is really still working on the bleeding edge. I recall from looking at older Delphi libraries that I thought I saw {$ifdef... statements that tested versions of the compiler.  Should that not then be in socketCAN libraries so if one tries to compile applications that require > 3.2.x that the compiler complains and stops.  If sample applications are dependent on that then should that not also exist in those samples? But if it's time to upgrade then so be it. ---------------------------------------------------------------------- avra · 2021-10-04 23:15 Quote from: jcdammeyer on October 04, 2021, 06:16:30 pmI recall from looking at older Delphi libraries that I thought I saw {$ifdef... statements that tested versions of the compiler.  Should that not then be in socketCAN libraries so if one tries to compile applications that require > 3.2.x that the compiler complains and stops.  If sample applications are dependent on that then should that not also exist in those samples?It was never meant to make SocketCAN a library that works with any FPC version. It can be forced but it would be a mine field which I do not recommend. In one of the old messages in this thread you can find exact FPC revision that I added missing constants to, and which has everything else needed - but if you do not feel like hunting it down, then current trunk FPC will do. This is just a playground and SocketCAN will be part of FPC, so there will be no need for ifdefs in code. As for Lazarus, my last can.zip does not depend on Lazarus 2.1+ any more and should work with any Lazarus 2.0.x and maybe even older. ---------------------------------------------------------------------- jcdammeyer · 2021-10-04 23:34 Thanks, The two windows systems (WIN-7 and WIN-10) have been upgraded to trunk and trunk.  The reason for maintaining windows compatibility isn't just for socketCAN but also for that graphical issue a few months back.  Now I have to find out where I put all the packages.  Sloppy on my part. And therein lies the problem with constantly updating.  All the lpk packages have to be rebuilt and installed into the IDE.  It was always the worst part of upgrading Delphi too. Then I'll upgrade my Linux systems. ---------------------------------------------------------------------- avra · 2021-10-06 09:09 Quote from: jcdammeyer on October 05, 2021, 01:34:41 amThe two windows systems (WIN-7 and WIN-10) have been upgraded to trunk and trunk.Since projects can now be opened in older Lazarus, there was no real need to use Lazarus trunk, but it will not hurt. In case you want to be able to open your own projects saved with Lazarus 2.1+ in Lazarus 2.0.x and older, you can go to Project Options / Misellaneous and check Maximize compatibility of project files (LPI and LPS). That's all I did in latest can.zip, so fixlp is not needed any more. If you use fpcupdeluxe, then it would be wise to write down exact revision of FPC and LAZ combo you used at one place, and then tell fpcupdeluxe to download that exact combo on each system you use for SocketCAN. That would eliminate a lot of ifs in case of problems. Quote from: jcdammeyer on October 05, 2021, 01:34:41 amAnd therein lies the problem with constantly updating.  All the lpk packages have to be rebuilt and installed into the IDE.  It was always the worst part of upgrading Delphi too.If you use fpcupdeluxe, then once you install it in one OS/CPU combo, you can simply copy whole dir and desktop shortcut to another machine with the same (or compatible) OS/CPU combo. That's all. No need for reinstallation all over again. And sometimes cross compilation can also save the day... ---------------------------------------------------------------------- jcdammeyer · 2021-10-06 17:02 Quote from: avra on October 06, 2021, 11:09:17 amSince projects can now be opened in older Lazarus, there was no real need to use Lazarus trunk, but it will not hurt. In case you want to be able to open your own projects saved with Lazarus 2.1+ in Lazarus 2.0.x and older, you can go to Project Options / Misellaneous and check Maximize compatibility of project files (LPI and LPS). That's all I did in latest can.zip, so fixlp is not needed any more. For some reason, even after 3 tries I couldn't get the trunk/trunk version to install on the Pi4 LinuxCNC version.  What finally worked was the trunk fpc which then built your examples correctly.   The 2.0.10 Lazarus did install and that's what I was running on the others.  And that created the same problem from 6 months ago. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i     if (DevCtx.IsNullPen and (DevCtx.IsNullBrush or Winding)) thenHad to go back through all my postings to find that solution and now the sample 7 segment programs work on all three systems.  The Pi is using FPC 3.3.1 and Laz 10.0.2.  The Beagle is using Laz 10.0.2 and I think 3.3.1 but for some reason the compiler version isn't showing up on the messages.  The same boxes appear to be checked in the Project Options verbosity.  I only updated the FPC on the Beagle.  PCs are both running 3.3.1 and Laz 2.3.0 but then Windows never had the issue with the "Winding". QuoteIf you use fpcupdeluxe, then it would be wise to write down exact revision of FPC and LAZ combo you used at one place, and then tell fpcupdeluxe to download that exact combo on each system you use for SocketCAN. That would eliminate a lot of ifs in case of problems. Quote from: jcdammeyer on October 05, 2021, 01:34:41 amAnd therein lies the problem with constantly updating.  All the lpk packages have to be rebuilt and installed into the IDE.  It was always the worst part of upgrading Delphi too.If you use fpcupdeluxe, then once you install it in one OS/CPU combo, you can simply copy whole dir and desktop shortcut to another machine with the same (or compatible) OS/CPU combo. That's all. No need for reinstallation all over again. And sometimes cross compilation can also save the day... In either case, updating to 3.3.1 allows all your examples to compile.  Thanks for all your help.  Now I have to chase the usual BBB kernal and OS update issues.  Seems now the paths to the SPI devices have changed so once again Derek Molloy's book has sections now that are wrong.    And where I used to be able to read a 1-Wire device on the BBB it no longer shows up.  Probably something in the cape EEROM.  Constant upgrades that break old programs are such a pain. ---------------------------------------------------------------------- avra · 2021-10-06 18:56 Quote from: jcdammeyer on October 06, 2021, 07:02:35 pm...that created the same problem from 6 months ago... Had to go back through all my postings to find that solution and now the sample 7 segment programs work on all three systems.Well, LCL evolves so from time to time you need to check your projects for compatibility. SocketCAN should work with your old Lazarus, but your project which uses some GUI features that changed in newer Lazarus was the reason for incompatibility. Glad you fixed that after all. Quote from: jcdammeyer on October 06, 2021, 07:02:35 pmIn either case, updating to 3.3.1 allows all your examples to compile.  Thanks for all your help.You're most welcome. I'm glad that you can finally compile all SocketCAN demos. ---------------------------------------------------------------------- jcdammeyer · 2021-10-06 20:21 I had already started my own CANopen unit which included a CAN message data structure.  I'll see if I can't convert that over to use the socketCAN data structures and add {$ifdef for WIN or LINUX so I can still run with the CANUSB on the windows systems but switch over to socketCAN on the Linux ones.  That will allow me to use the MCP2515 devices on the Pi and the internal CAN device on the Beagle. When that's all done and working I'll post the Lazarus source code for the project. ---------------------------------------------------------------------- MarkMLl · 2021-10-19 10:02 Noting that this is the dominant Canbus thread: what interface hardware are people using for general development on a PC? I might need to prod at a vehicle subsystem with Canbus as one (fortunately not the only one) of the interfaces. MarkMLl ---------------------------------------------------------------------- jcdammeyer · 2021-10-19 17:29 Quote from: MarkMLl on October 19, 2021, 12:02:03 pmNoting that this is the dominant Canbus thread: what interface hardware are people using for general development on a PC? I might need to prod at a vehicle subsystem with Canbus as one (fortunately not the only one) of the interfaces. MarkMLl It's because I have four of the CANUSB from Lawicel in Sweden that it is one of the first tools I grab but the software support for monitoring isn't the best.  I think there are clones from China for even less. For some monitoring on my car before a friend loaned me a Code Monitor I built up an Arduino with the add on SPI based CAN board.  It would be easy enough to clone the basic serial side of the CANUSB protocol on it. I also have a dongle from RM Michaelides with their software that is very good but over $500.  It's that user software that I'm sort of cloning onto Lazarus.   The Lazarus software works with the serial port (COMx: on windows, /dev/ttyUSBx on Linux). I also have a KVaser Lief USB dongle.  Rarely use it.  They are even more money. For the Beagle I have a cape with the CAN and RS485 driver.  For the Pi I have a single and dual CAN cape both using SPI. The Lazarus software has a long way to go.  I've been side tracked by other projects but I can zip up what I have if you want it. John ---------------------------------------------------------------------- MarkMLl · 2021-10-19 18:27 Quote from: jcdammeyer on October 19, 2021, 07:29:42 pmIt's because I have four of the CANUSB from Lawicel in Sweden that it is one of the first tools I grab but the software support for monitoring isn't the best.  I think there are clones from China for even less. Thanks for that. I see http://www.can232.com/?page_id=16 and note that that's described as having an FTDI interface, so I've got a fair degree of confidence that Linux will see it (as remarked elsewhere, I've bought lots of stuff over the last year or so that has an embedded serial chip). Is the clone you're thinking about something like https://www.ebay.co.uk/itm/143099880796 ? I can see the various SPI interfaces, but at least initially I want to be able to exercise some kit from my desk. MarkMLl ---------------------------------------------------------------------- avra · 2021-10-19 18:32 Quote from: MarkMLl on October 19, 2021, 12:02:03 pmNoting that this is the dominant Canbus thread: what interface hardware are people using for general development on a PC? I might need to prod at a vehicle subsystem with Canbus as one (fortunately not the only one) of the interfaces. Linux has best tools and allows greatest hacking capability, so you could use these (Pi based on MCP2515): Quote from: jcdammeyer on October 19, 2021, 07:29:42 pmFor the Beagle I have a cape with the CAN and RS485 driver.  For the Pi I have a single and dual CAN cape both using SPI. Lawicel based ones work with both Windows and Linux (and can occasionally drop frames on very congested 1Mbit networks), but above ones are my favorites (especially if you have proper DBC files for automatic data decoding). For software/hardware specifics read my older messages. ---------------------------------------------------------------------- MarkMLl · 2021-10-19 18:44 Quote from: avra on October 19, 2021, 08:32:51 pmQuote from: MarkMLl on October 19, 2021, 12:02:03 pmNoting that this is the dominant Canbus thread: what interface hardware are people using for general development on a PC? I might need to prod at a vehicle subsystem with Canbus as one (fortunately not the only one) of the interfaces. Linux has best tools and allows greatest hacking capability, so you could use these (Pi based on MCP2515): Quote from: jcdammeyer on October 19, 2021, 07:29:42 pmFor the Beagle I have a cape with the CAN and RS485 driver.  For the Pi I have a single and dual CAN cape both using SPI. Lawicel based ones work with both Windows and Linux (and can occasionally drop frames on very congested 1Mbit networks), but above ones are my favorites (especially if you have proper DBC files for automatic data decoding). For software/hardware specifics read my older messages. Thanks Avra, noted. It's all extremely tentative at the moment, I anticipate it would be entirely point-to-point and low-speed. MarkMLl ---------------------------------------------------------------------- jcdammeyer · 2021-10-19 18:44 Quote from: MarkMLl on October 19, 2021, 08:27:10 pm Thanks for that. I see http://www.can232.com/?page_id=16 and note that that's described as having an FTDI interface, so I've got a fair degree of confidence that Linux will see it (as remarked elsewhere, I've bought lots of stuff over the last year or so that has an embedded serial chip). Is the clone you're thinking about something like https://www.ebay.co.uk/itm/143099880796 ? I can see the various SPI interfaces, but at least initially I want to be able to exercise some kit from my desk. MarkMLl The biggest problem with that one and most of the crap coming from China is that the CAN bus is designed for 3 wires, not two.  Ground is a fundamental part of the circuit and it's find if you have an arduino or Pi which is also powered from the vehicle 12V power system as at some point the arduino power ground matches up with the vehicle CAN bus ground . The late Steve Corrigan at TI (he designed TI's CAN driver chips) and I had a long discussion about that.  I even set up two 82C250 CAN transceivers both run from 9V batteries into 78L05 regulators.  I coupled only the two CAN signals so no physical ground connection.  There was no problem sending with only two wires so you'd think it would be fine.  Which is why you see the crap out there not supplying a ground assuming the vehicle ground is on both.  But here's the reason you need the ground. Ultimately it's possible for the ground from one device to be connected to the ground from the other through some peculiar way.  Now the two CAN signals which are referenced to ground (2.5V is recessive relative to their own ground) could have more than 7V between the two grounds.  This results in a common mode voltage that is higher than the transceiver and it pops.  Or worse you don't exceed it but you get a lot of bus faults that are sporadic and non-deterministic.   The error counters go up and down and you can't pinpoint the reason.  As soon as you put the scope on it the errors  go away. So watch out for dongles that don't provide the standard DB-9 CANopen pin format.  Notice on this link they don't make the ground pin optional. https://www.kvaser.com/about-can/the-can-protocol/can-connectors/ ---------------------------------------------------------------------- MarkMLl · 2021-10-19 18:54 Thanks for the reminder about grounding and the extra link, I actually had much of that stuff drummed into me when I was hooking up an early not-quite-PC LAN in about 1984 :-) For the moment this is strictly desktop-experimentation (well, desktop plus a cable to my antenna mast) and if anything production comes of it cost will be little object (you ought to see the cost of the traditional opposition...) MarkMLl ---------------------------------------------------------------------- jcdammeyer · 2021-10-19 18:55 Quote from: avra on October 19, 2021, 08:32:51 pmQuote from: MarkMLl on October 19, 2021, 12:02:03 pmNoting that this is the dominant Canbus thread: what interface hardware are people using for general development on a PC? I might need to prod at a vehicle subsystem with Canbus as one (fortunately not the only one) of the interfaces. Linux has best tools and allows greatest hacking capability, so you could use these (Pi based on MCP2515): Quote from: jcdammeyer on October 19, 2021, 07:29:42 pmFor the Beagle I have a cape with the CAN and RS485 driver.  For the Pi I have a single and dual CAN cape both using SPI. Lawicel based ones work with both Windows and Linux (and can occasionally drop frames on very congested 1Mbit networks), but above ones are my favorites (especially if you have proper DBC files for automatic data decoding). For software/hardware specifics read my older messages. Yes the problem with the Lawicel using the COMx: on windows is more to do with the USB side of things.  The CANUSB buffers a fair number of messages and uses the 8bit bus based SJA1000 CAN device.  But if the USB can't get them out fast enough (the serial port driver is the issue) then at really high bus speeds with 100% utilized bus there can be problems.  There is a DLL based driver that doesn't have the overhead of the serial port.  However I don't think that's supported on Linux. If you are using 29 bit Extended IDs then you can use 135 bits as a general rule for largest message size including stuff bits.  So at 1MBps we're talking 135uS per message with the bus at 100%.  That's only about 7.5kHz with the largest messages.  But if you are running standard IDs with only one or two bytes in the messages now you can go back to back about 64 bits and double the message rate just over 15kHz.    A 10Mhz SPI bus has no trouble with this.  But it's hard to do that with a PC unless it's USB with a dedicated driver, not the serial port. For example:  15kHz for a Lawicel message might be t12325566  which is 10 characters.  That's 150 kbaud and most USB interfaces start to break down above 115Kbaud.  Although DMX512A for light shows are 250kbaud. ---------------------------------------------------------------------- MarkMLl · 2021-10-19 18:59 Quote from: jcdammeyer on October 19, 2021, 08:55:13 pmmost USB interfaces start to break down above 115Kbaud.  Although DMX512A for light shows are 250kbaud. Particularly if they use a counterfeit chip. I'm amassing a photo collection... As a slight aside, if deciding on a default "Baud rate" ** for a serial link it's worth considering that some Arduino-like devices (e.g. ESP32) don't support below 38k4. MarkMLl ** I know, that's why I put it in quotes. ---------------------------------------------------------------------- jcdammeyer · 2021-10-19 19:01 Quote from: MarkMLl on October 19, 2021, 08:54:22 pmThanks for the reminder about grounding and the extra link, I actually had much of that stuff drummed into me when I was hooking up an early not-quite-PC LAN in about 1984 :-) For the moment this is strictly desktop-experimentation (well, desktop plus a cable to my antenna mast) and if anything production comes of it cost will be little object (you ought to see the cost of the traditional opposition...) MarkMLl I started working with CAN and the 82C200 in 1992.  Before there were CAN drivers.  The 82C200 (now SJA1000) had drivers on board for resistive termination and was rated at max 100kbps.  We were using it at 333kbps only because the original author made a config mistake aiming for 500kbps.  By the time I figured that out there were too many systems in the field. A year later Philips came out with the 82C250 and we were given 250 to play with.  A bunch of machines went out with those and only later when we started having problems did we learn they were pre-production prototypes never meant for distribution in the field.  They had a serious issue with returning to recessive state and floated all over the place. My solution was a resistor array that pulled the CAN_H to 2.4V and the CAN_L to 2.6V during the recessive state.  During dominant the device would still go 4.0V for CAN_H and 1.0V for CAN_L and all was good.  Good times.... ---------------------------------------------------------------------- jcdammeyer · 2021-10-19 19:04 Quote from: MarkMLl on October 19, 2021, 08:59:52 pmQuote from: jcdammeyer on October 19, 2021, 08:55:13 pmmost USB interfaces start to break down above 115Kbaud.  Although DMX512A for light shows are 250kbaud. Particularly if they use a counterfeit chip. I'm amassing a photo collection... As a slight aside, if deciding on a default "Baud rate" ** for a serial link it's worth considering that some Arduino-like devices (e.g. ESP32) don't support below 38k4. MarkMLl ** I know, that's why I put it in quotes. Just remember that UARTs have 'BAUD' rates and CAN has BitRates.  BAUD is derived from Baudot and 5 bits of data with a start bit and two stop bits.  Now of course we tend to use 8 bits with one start and one stop.  So a Baud rate of 9600 baud means exactly 960 characters per second.  Calling CAN rate a baud rate tells you nothing.  Pet peeve of mine.  Sorry.... ---------------------------------------------------------------------- MarkMLl · 2021-10-19 19:04 A colleague at Lowbrow had had his PhD (possibly at Liverpool) paid for by Ripaults designing a vehicle data bus. He joined at the same time as I did- late '83- which gives some idea of the timeframe... there must have been many companies working on the same thing. MarkMLl ---------------------------------------------------------------------- jcdammeyer · 2021-10-19 19:06 Quote from: MarkMLl on October 19, 2021, 09:04:23 pmA colleague at Lowbrow had had his PhD (possibly at Liverpool) paid for by Ripaults designing a vehicle data bus. He joined at the same time as I did- late '83- which gives some idea of the timeframe... there must have been many companies working on the same thing. MarkMLl I think that's why you see so many busses on the OBD-II connector.  Now I think it's all standardized on CAN and for heavy vehicles J1939.  For the military stuff I worked on it was MilCAN which is still standard J1939 but with some 'rules' of behavior for the messaging. ---------------------------------------------------------------------- MarkMLl · 2021-10-19 19:07 Yes, I've also seen RS232 on it. Range Rover suspension... (Later:) I've ordered one of those cheap interfaces and will report back. My suspicion is that that jumper probably ties one side of the data to (USB) ground... At a pinch I should be able to monitor the bus with my logic analyser, which is good for +-40V :-) MarkMLl ---------------------------------------------------------------------- avra · 2021-10-20 12:04 Quote from: jcdammeyer on October 19, 2021, 08:44:54 pmGround is a fundamental part of the circuit and it's find if you have an arduino or Pi which is also powered from the vehicle 12V power system as at some point the arduino power ground matches up with the vehicle CAN bus ground.There are galvanic isolated Pi shields like https://www.sg- electronic-systems.com/can-bus-dual-iso-v2-1-shield-for-raspberry/ which help when you must have separate power supply for your equipment. I solve that problem simply by powering Pi from the vehicle (Pi Zero is sufficient for CAN hacking), and then ssh or vnc to Pi from my laptop via WiFi. I even have a 4.3" display and small wireless keyboard for the Pi, but I find laptop access more convenient in 90% of the cases. ---------------------------------------------------------------------- avra · 2021-10-20 12:18 Quote from: MarkMLl on October 19, 2021, 09:07:58 pm(Later:) I've ordered one of those cheap interfaces and will report back.There are AVR, ESP32 and STM32 projects which implement Lawicel protocol, so if at the end you become unsatisfied with your device then you can go DIY path. ---------------------------------------------------------------------- MarkMLl · 2021-10-20 12:24 Quote from: avra on October 20, 2021, 02:18:46 pmQuote from: MarkMLl on October 19, 2021, 09:07:58 pm(Later:) I've ordered one of those cheap interfaces and will report back.There are AVR, ESP32 and STM32 projects which implement Lawicel protocol, so if at the end you become unsatisfied with your device then you can go DIY path. Understood, and the transceiver boards are available cheaply in this country from the usual suspects... unlike cheap USB-connected interfaces. So I'm just trying to think ahead... MarkMLl ---------------------------------------------------------------------- avra · 2021-10-28 17:12 Quote from: avra on October 20, 2021, 02:04:59 pm... I solve that problem simply by powering Pi from the vehicle (Pi Zero is sufficient for CAN hacking), and then ssh or vnc to Pi from my laptop via WiFi.Happy me just ordered 2 of these new toys: https://www.raspberrypi.com/products/raspberry-pi-zero-2-w/ ---------------------------------------------------------------------- MarkMLl · 2021-11-16 10:44 Quote from: MarkMLl on October 19, 2021, 09:07:58 pm(Later:) I've ordered one of those cheap interfaces and will report back. My suspicion is that that jumper probably ties one side of the data to (USB) ground... The cheap interface (little black box with a blue/white label) has a jumper which controls whether a resistor is across the lines, but neither line is tied to ground unless there's provision for that in the interface chip (SIT1050). The markings on the main chip are obliterated but plugged into an unconfigured Linux system is identified as 10c4:ea60 CP210x (/dev/ttyUSBx). Spurious rules in 60-gpsd.rules aliased this as a GPS device, I chopped those since I've got several things with one of those chips in it and I don't want anything getting in the way (now all I need to do is re-enable all the gpsd stuff before I forget about it). I find I need to load a custom module and bring a link up manually, after which I can see an interface: # modprobe slcan # slcand -o -c -f -s4 /dev/ttyUSB2 can0 # ip link set can0 up 6: can0: mtu 16 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 10     link/can At this point I need to do more research. I'm attached on a one-to-one basis to a device with documented addresses, and I need to read and possibly write some of those. Any suggestions would be appreciated, and I'll post any updates I work out myself. MarkMLl ---------------------------------------------------------------------- avra · 2021-11-23 23:33 Quote from: MarkMLl on November 16, 2021, 11:44:31 amI need to load a custom module and bring a link up manuallyThat is normal. See https://pascal-walter.blogspot.com/2015/08/installing-lawicel-canusb- on-linux.html Quote from: MarkMLl on November 16, 2021, 11:44:31 amI'm attached on a one-to-one basis to a device with documented addresses, and I need to read and possibly write some of those. Any suggestions would be appreciatedInstall can-utils. Although there are other tools you can find if you search through my older messages in this thread, everything needed is already there. It is best if you have CAN messaging docs for your devices, but CAN hacking is not that hard, either. In hacking you try to physically change something on your device and while spying CAN network you try to interpret data changes you see in the messages (CAN data messages are usually heavily bit packed records with no bits wasted and no byte alignment). Without docs it will be hard to guess how to send data to device, so it might be helpful to already have a device which writes to target device. Then all you need is to spy those messages and simply replicate them or try to guess the message data structure when you need to have a variable parameter. Here is some real life example. Let's say that you're lucky and in your car you have a button without any function attached to it, and you are not satisfied with just 2 speeds for your rain wiper blades. You need to spy the vehicle CAN network (usually there are more CAN networks then just one you access through OBD-II interface), and then look for new messages, or changes in existing messages when you press that button. Then you spy for message which shows when you press button for a single manual rain wiper blade cycle. Now, you should have everything needed to write a program which waits for a single, double, or long click on unused button to set custom interval which will be used for commanding rain wiper blades, and increase or decrease it in case of a need. When everything works the way you want on your Pi, you can program some Arduino like board and leave your custom device permanently in the car. Happy you, problem solved!  Now imagine other ideas like protecting your vehicle start up with morse like taps on a button. Sky is the limit.... Have fun!  PS: If you do not have unused button in your car, you will probably be able to find a button to which you can safely add double, triple or long click. There are even cheap wireless bluetooth multimedia buttons which you can attach to your wheel or on your dashboard. They can be used as custom additional buttons for your bluetooth Arduino (all ESP microcontrollers have BT) when you can not find any unused button in your car. ---------------------------------------------------------------------- MarkMLl · 2021-11-24 07:25 Current situation is that I've been looking through dumps that various other people have captured, but they don't interact with the specific device I've got standalone. I'm in the middle of making a T-cable to tap into a live system, which needs a couple of moderately-expensive connectors: until then I can't be 100% sure that slcan etc. is working properly. MarkMLl ---------------------------------------------------------------------- avra · 2021-11-24 07:49 Quote from: MarkMLl on November 24, 2021, 08:25:13 amI'm in the middle of making a T-cable to tap into a live system, which needs a couple of moderately-expensive connectorsThere are contactless crocodile clips which can be used if you only need to spy data without sending anything (like just spying J1939): https://copperhilltech.com/cancrocodile-contactless-can- bus-j1708-reader/ or tap into cable system without connectors using intrusive T splitters: https://www.aliexpress.com/item/4001147302536.html You might also use thin needles hack to tap into the system without a need for an expensive connector. Of course, nothing like a real thing. But these days receiving products from online ordering can take forever. ---------------------------------------------------------------------- MarkMLl · 2021-11-24 08:11 I've got the connectors, just need steel myself for the crimping... it's a one-time assembly with environmental seals etc. £20 for a pair isn't too bad, considering. But in principle it should be possible to have a stock of "close enough" pins and receptacles and 3D-print the housings on demand. MarkMLl ---------------------------------------------------------------------- unoAchtung · 2022-10-20 13:13 Impressive work! How do I do if I want to find out which channels that are available on the device (can0, can1, etc.)? ---------------------------------------------------------------------- jcdammeyer · 2022-10-20 16:26 Boy it's been over a year since I did anything with this.  Work-work and COVID shutdows got in the way.  In a few months I should be able to get back to this project.  I've pretty well abandoned the BeagleBone Black.  The OS just keeps changing with respect to I/O breaking existing code. ---------------------------------------------------------------------- avra · 2022-10-22 11:40 Quote from: unoAchtung on October 20, 2022, 03:13:13 pmImpressive work!Thanks!  Quote from: unoAchtung on October 20, 2022, 03:13:13 pmHow do I do if I want to find out which channels that are available on the device (can0, can1, etc.)?Using ifconfig from net-tools package can show CAN device interfaces that you have already brought up: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i ifconfig | grep canbut beware that out of the box linux does not bring any interfaces automatically. You have to do it on your own if there is no vendor script for that purpose. You can find relevant tutorials in my initial posts. ---------------------------------------------------------------------- unoAchtung · 2022-10-24 07:55 If I want to list the devices in my FPC application, how can I get the devices through FPC code? ---------------------------------------------------------------------- avra · 2022-10-24 09:17 Quote from: unoAchtung on October 24, 2022, 09:55:16 amIf I want to list the devices in my FPC application, how can I get the devices through FPC code?Either asume that ifconfig is installed and each CAN interface has CAN word in it's name so you can use output of this command line: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i avra@vm- debian:~$ ifconfig | grep can | sed -r 's#:.*##'vcan0vcan1or analyze source code of ifconfig and try to replicate part of it's functionality in pascal: https://github.com/giftnuss/net-tools/blob/master/ifconfig.c EDIT: Ok, I was playing a little so here is version 2 which still depends on net-tools package and CAN substring in interface name: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i avra@vm- debian:~$ netstat -i | grep can | sed -r 's# .*##'vcan0vcan1and version 3 which lists all can, vcan and vxcan interfaces without depending on net-tools package or CAN substring in their name: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i avra@vm- debian:~$ ip link show type can | grep : | sed -r 's#: <.*##' | sed -r 's#.* ##' && ip link show type vcan | grep : | sed -r 's#: <.*##' | sed -r 's#.* ##' && ip link show type vxcan | grep : | sed -r 's#: <.*##' | sed -r 's#.* ##'vcan0vcan1 As you can guess, of all command lines version 3 is the best since ip command exists in most modern distros (iproute2 package). However, you should not asume anything and always do the checking on your own. ---------------------------------------------------------------------- avra · 2025-03-10 12:32 canerrsim (son of hlcanerrsim) is now officially part of can-utils (#1 collection of tools used by socketcan users): https://github.com/linux-can/can-utils https://github.com/zeljkoavramovic/canerrsim If you need to use CAN error simulation then please consider giving canerrsim repo a star.