Not really an issue: Workflow of TP -> incorrect PGN response in CM-Message
Hello everyone,
i got a quesition about the workflow of the J1939 TP. I'm about writing a script which is automatically responding a message > 8 Bytes after reading the 0xEA00 (RequestPGN). If i read the J1939 Documentation correctly the Request-PGN must have the requested PGN in the data-field.
So if responding some dummy data with "sendto" the TP seems to work correctly but the connection management message doesn't contain the requested PGN
Skript flow:
-
Initalize struct sockaddr_can (sockname/peername)
-
open socket
-
setsockopt(->Broadcast)
-
bind(->sockname)
-
Recvfrom() IF PGN==0xEA00 read requested pgn close(sock) 5.5 generate dummy data
-
Reinitalize struct sockaddr_can (sockname/peername)
-
open socket
-
setsockopt(->Broadcast)
-
bind(->sockname)
-
sendto( dummy-Data)
My questions: why the CM-Message doesn't contain the requested PGN? why the CM-Message was sended three times?
source-code:
`
sockname.can_ifindex = 4;
sockname.can_addr.j1939.addr = 0x00;
sockname.can_addr.j1939.pgn = J1939_NO_PGN;
sockname.can_addr.j1939.name = J1939_NO_NAME;
peername.can_ifindex = 4;
peername.can_addr.j1939.addr = 0x00;
peername.can_addr.j1939.pgn = J1939_NO_PGN;
peername.can_addr.j1939.name = J1939_NO_NAME;
/*SOCKET OPEN*/
sock = ret = socket(PF_CAN, SOCK_DGRAM, CAN_J1939);
printf("SOCKET:OPEN() %d\n",sock);
if (ret < 0)
err(1, "socket(j1939)");
/*SOCKET SET SOCKOPT*/
ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
&todo_broadcast, sizeof(todo_broadcast));
printf("SOCKET:SETSOCKETOPT() %d\n",sock);
if (ret < 0)
err(1, "setsockopt: filed to set broadcast");
/*SOCKET BIND*/
ret = bind(sock, (void *)&sockname, sizeof(sockname));
printf("SOCKET:BIND() %d\n",ret);
if (ret < 0 )
err(1, "bind(): failed to bind socket");
pgn_filt = 0xEA00;
if (peername.can_addr.j1939.pgn == pgn_filt){
printf("REQUEST : %d Byte\n", ret);
dp = dat;
req_pgn = *(dp+2);
req_pgn = req_pgn << 8;
req_pgn |= *(dp+2-1);
req_pgn = req_pgn << 8;
req_pgn |= *(dp+2-2);
printf("%06x\n",req_pgn);
close(sock);
sockname.can_ifindex = 4;
sockname.can_addr.j1939.addr = 0x00;
sockname.can_addr.j1939.pgn = J1939_NO_PGN;
sockname.can_addr.j1939.name = J1939_NO_NAME;
peername.can_ifindex = 4;
peername.can_addr.j1939.addr = 0x00;
peername.can_addr.j1939.pgn = req_pgn;
peername.can_addr.j1939.name = J1939_NO_NAME;
/*SOCKET OPEN*/
sock = ret = socket(PF_CAN, SOCK_DGRAM, CAN_J1939);
printf("SOCKET:OPEN() %d\n",sock);
if (ret < 0)
err(1, "socket(j1939)");
/*SOCKET SET SOCKOPT*/
ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
&todo_broadcast, sizeof(todo_broadcast));
printf("SOCKET:SETSOCKETOPT() %d\n",sock);
if (ret < 0)
err(1, "setsockopt: filed to set broadcast");
/*SOCKET BIND*/
ret = bind(sock, (void *)&sockname, sizeof(sockname));
printf("SOCKET:BIND() %d\n",ret);
if (ret < 0 )
err(1, "bind(): failed to bind socket");
memset(&dat, 0xFF, sizeof(dat));
dat[0] = 87;
dat[1] = 65;
dat[2] = 85;
dat[3] = 90;
dat[4] = 90;
dat[5] = 90;
dat[6] = 56;
dat[7] = 80;
dat[8] = 51;
dat[9] = 53;
dat[10] = 65;
dat[11] = 49;
dat[12] = 55;
dat[13] = 49;
dat[14] = 49;
dat[15] = 53;
dat[16] = 48;
/*sendto*/
ret = sendto(sock, dat, 16, 0,
(void *)&peername, sizeof(peername));
`
candump: `
can0 18EA0000 [8] 00 EC FE FF FF FF FF FF
can0 18EC0000 [8] 10 10 00 03 03 00 00 04
can0 18EC0000 [8] 11 03 01 FF FF 00 00 04
can0 18EB0000 [8] 01 57 41 55 5A 5A 5A 38
can0 18EB0000 [8] 02 50 33 35 41 31 37 31
can0 18EB0000 [8] 03 31 35 FF FF FF FF FF
can0 18EC0000 [8] 13 10 00 03 FF 00 00 04
`
hope someone can help me out :)
Hi @TSsimon , please take a look at this topic https://github.com/linux-can/can-utils/issues/228 I hope it answers your question
Thanks for your Attention @olerem ! If I understand correctly the implemented Type of SAE J1939 Transport Protocol is the RTS/CTS Type ? Is there a setting to receive TP.DT Messages without handshake?
thanks!
On the top level (from socket point of view) you do not deal with TP/ETPs at all. If you send() 8byte, the stack will send simple message. if you send more than 8 byte, the stack will send TP (all what for TP is needed) or if it is more than max TP size, it will send ETP message. See: https://github.com/linux-can/can-utils/blob/master/can-j1939-kickstart.md#larger-packets
With this tool, you can send any supported amount of data over CAN: https://github.com/linux-can/can-utils/blob/master/j1939cat.c