On 05/11/2011 11:04 PM, Kurt Van Dijck wrote:
> Oliver,
> 
> Yet another interesting general purpose tool: jdate
> It sends out the date/time PGN.

Can you add a date/time receiver to this tool, too?
Some nitpicking inline:

cheers, Marc

> Kurt
> PS: I know you can't test immediately :-)
> ---
> Signed-off-by: Kurt Van Dijck <[email protected]>
> ---
> Index: can-utils/Makefile
> ===================================================================
> --- can-utils/Makefile        (revision 1257)
> +++ can-utils/Makefile        (working copy)
> @@ -56,7 +56,7 @@
>  PROGRAMS_ISOTP = isotpdump isotprecv isotpsend isotpsniffer isotptun 
> isotpserver
>  PROGRAMS_CANGW = cangw
>  PROGRAMS_SLCAN = slcan_attach slcand
> -PROGRAMS_J1939 = jacd jspy jsr
> +PROGRAMS_J1939 = jacd jspy jsr jdate

keep/make the list sorted

>  PROGRAMS = can-calc-bit-timing candump cansniffer cansend canplayer cangen 
> canbusload\
>          log2long log2asc asc2log\
>          canlogserver bcmserver\
> @@ -107,4 +107,5 @@
>  
>  jspy: libj1939.a
>  jsr: libj1939.a
> +jdate: libj1939.a
dito
>  
> Index: can-utils/GNUmakefile.am
> ===================================================================
> --- can-utils/GNUmakefile.am  (revision 1257)
> +++ can-utils/GNUmakefile.am  (working copy)
> @@ -56,11 +56,13 @@
>  bin_PROGRAMS += \
>       jacd \
>       jsr \
> -     jspy
> +     jspy \
> +     jdate
dito
>  
>  jacd_LDADD = libj1939.la
>  jsr_LDADD = libj1939.la
>  jspy_LDADD = libj1939.la
> +jdate_LDADD = libj1939.la
>  
>  noinst_LTLIBRARIES += libj1939.la
>  
> Index: can-utils/jdate.c
> ===================================================================
> --- can-utils/jdate.c (revision 0)
> +++ can-utils/jdate.c (revision 0)
> @@ -0,0 +1,279 @@
> +/*
> + * Copyright (c) 2011 EIA Electronics
> + *
> + * Authors:
> + * Kurt Van Dijck <[email protected]>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the version 2 of the GNU General Public License
> + * as published by the Free Software Foundation
> + */
> +
> +#include <signal.h>
> +#include <time.h>
> +#include <inttypes.h>
> +#include <errno.h>
> +#include <string.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +
> +#include <unistd.h>
> +#include <getopt.h>
> +#include <error.h>
> +#include <sys/time.h>
> +#include <sys/socket.h>
> +#include <linux/can.h>
> +#include <linux/can/j1939.h>
> +#include "libj1939.h"
> +
> +static const char help_msg[] =
> +     "jdate: Send the datetime pgn, each second or on request" "\n"
> +     "Usage: jdate SOURCE" "\n"
> +     " -v, --verbose         Show info" "\n"
> +     " -l, --listen          Answer to request PGN's only" "\n"
                                                     ^
's make no sense here

> +     " -i, --iso11783                iso-11783 format" "\n"
> +     "\n"
> +     "Example:" "\n"
> +     "jdate --iso can1:20" "\n"
> +     "\n"
> +     "Specifications" "\n"
> +     " - SAE J1939-71 pgn65254" "\n"
> +     " - ISO 11783-7 Annex B.1" "\n"
> +     "\n"
> +     "Notes" "\n"
> +     "Time/Date Adjust is not yet supported" "\n"
> +     ;
> +
> +#ifdef _GNU_SOURCE
> +static struct option long_opts[] = {
> +     { "help", no_argument, NULL, '?', },
> +     { "listen", no_argument, NULL, 'l', },
> +     { "verbose", no_argument, NULL, 'v', },
> +     { "iso11783", no_argument, NULL, 'i', },
> +     { },
> +};
> +#else
> +#define getopt_long(argc, argv, optstring, longopts, longindex) \
> +     getopt((argc), (argv), (optstring))
> +#endif
> +static const char optstring[] = "liv?";
> +
> +/* global variables */
> +static struct {
> +     const char *source;
> +     int periodic;
> +     int verbose;
> +     int iso;
> +     int sig_term;
> +     int sig_alrm;
> +} s = {
> +     .source = "can0:",
> +     .periodic = 1,
> +};
> +
> +/* j1939 socket */
> +static const struct j1939_filter filt[] = {
> +     {
> +             .pgn = 0x0ea00,
> +             .pgn_mask = 0x3ff00,
> +     },
> +};
> +
> +static int open_socket(const char *source)
> +{
> +     int ret, sock;
> +     struct sockaddr_can saddr;
> +
> +     ret = libj1939_str2addr(source, 0, &saddr);
> +     if (ret < 0)
> +             error(1, 0, "source spec '%s'", source);
> +     if (saddr.can_addr.j1939.pgn != J1939_NO_PGN)
> +             error(1, 0, "no pgn allowed in '%s'", source);
> +     saddr.can_addr.j1939.pgn = 0xfee6;
> +
> +     sock = ret = socket(PF_CAN, SOCK_DGRAM, CAN_J1939);
> +     if (ret < 0)
> +             error(1, errno, "socket(j1939)");
> +
> +     ret = setsockopt(sock, SOL_CAN_J1939, SO_J1939_FILTER,
> +                     &filt, sizeof(filt));
> +     if (ret < 0)
> +             error(1, errno, "setsockopt filter");
> +
> +     ret = bind(sock, (void *)&saddr, sizeof(saddr));
> +     if (ret < 0)
> +             error(1, errno, "bind()");
> +     return sock;
> +}
> +
> +/* signa handling */
           ^l
> +static void sighandler(int sig, siginfo_t *info, void *vp)
> +{
> +     switch (sig) {
> +     case SIGINT:
> +     case SIGTERM:
> +             s.sig_term = 1;
> +             break;
> +     case SIGALRM:
> +             s.sig_alrm = 1;
> +             break;
> +     }
> +}
> +
> +static void install_signal(int sig)
> +{
> +     int ret;
> +     struct sigaction sigact = {
> +             .sa_sigaction = sighandler,
> +             .sa_flags = SA_SIGINFO,
> +     };
> +
> +     sigfillset(&sigact.sa_mask);
> +     ret = sigaction(sig, &sigact, NULL);
> +     if (ret < 0)
> +             error(1, errno, "sigaction for signal %i", sig);
> +}
> +
> +static void schedule_repeating_itimer(int msec)
> +{
> +     int ret;
> +     struct itimerval val = {};
> +
> +     val.it_value.tv_sec = msec / 1000;
> +     val.it_value.tv_usec = (msec % 1000) * 1000;
> +     val.it_interval = val.it_value;

C99 initializer?

> +
> +     s.sig_alrm = 0;
> +     do {
> +             ret = setitimer(ITIMER_REAL, &val, NULL);
> +     } while ((ret < 0) && (errno == EINTR));
> +     if (ret < 0)
> +             error(1, errno, "setitimer %i msec", msec);
> +}
> +
> +static void fill_datetime(uint8_t dat[8])
> +{
> +     struct timeval tv;
> +     struct timezone tz;
> +     struct tm tm;
> +
> +     if (gettimeofday(&tv, &tz) < 0)
> +             error(1, errno, "gettimeofday");
> +
> +     tm = *gmtime(&tv.tv_sec);
> +     dat[0] = tm.tm_sec *4;
                            ^
> +     dat[1] = tm.tm_min;
> +     dat[2] = tm.tm_hour;
> +     dat[3] = tm.tm_mon +1
                            ^
;
> +     dat[4] = tm.tm_mday *4;
                             ^

please add a whitespace, each :)
> +     dat[5] = tm.tm_year - 85;
> +     if (s.iso) {
> +             dat[6] = 0;
> +             dat[7] = (-tz.tz_minuteswest / 60) + 24;
> +     } else {
> +             dat[6] = (-tz.tz_minuteswest % 60) + 125;
> +             dat[7] = (-tz.tz_minuteswest / 60) + 125;
> +     }
> +}
> +
> +static int ratelimit_errno(int _errno)
> +{
> +     static int saved_errno;
> +     int ret;
> +
> +     ret = _errno != saved_errno;
> +     saved_errno = _errno;
> +     return ret;
> +}
> +
> +/* main */
> +int main(int argc, char *argv[])
> +{
> +     int ret, sock, pgn, opt;
> +     uint8_t dat[9];
> +     struct sockaddr_can daddr;
> +
> +#ifdef _GNU_SOURCE
> +     program_invocation_name = program_invocation_short_name;
> +#endif
> +     /* argument parsing */
> +     while ((opt = getopt_long(argc, argv, optstring, long_opts, NULL)) != 
> -1)
> +     switch (opt) {
> +     case 'l':
> +             s.periodic = 0;
> +             break;
> +     case 'i':
> +             s.iso = 1;
> +             break;
> +     case 'v':
> +             ++s.verbose;
> +             break;
> +     default:
> +             fputs(help_msg, stderr);
> +             exit(1);
> +             break;
> +     }
> +     if (argv[optind])
> +             s.source = argv[optind++];
> +     /* args done */
> +
> +     ret = sock = open_socket(s.source);
> +
> +     install_signal(SIGTERM);
> +     install_signal(SIGINT);
> +     install_signal(SIGALRM);
> +     install_signal(SIGUSR1);
> +     install_signal(SIGUSR2);
> +
> +     if (s.periodic)
> +             schedule_repeating_itimer(1000);
> +
> +     while (!s.sig_term) {
> +             if (s.sig_alrm) {
> +                     /* send datetime */
> +                     memset(&daddr, 0, sizeof(daddr));
> +
> +                     fill_datetime(dat);
> +                     ret = send(sock, dat, 8, 0);
> +                     if (ret < 0)
> +                     switch (errno) {
> +                     case EINTR:
> +                             continue;
> +                     case ENOBUFS:
> +                     case EHOSTDOWN:
> +                     case EADDRNOTAVAIL:
> +                             if (ratelimit_errno(errno))
> +                                     error(0, errno, "j1939 send");
> +                             break;
> +                     default:
> +                             error(1, errno, "j1939 send");
> +                             break;
> +                     } else if (ratelimit_errno(0))
> +                             error(0, 0, "j1939 send ok");
> +
> +                     s.sig_alrm = 0;
> +                     if (s.verbose && (ret >= 0))
> +                             error(0, 0, "send");
> +             }
> +
> +             ret = recv(sock, dat, sizeof(dat), 0);

You send 8 byte but receive 9. Is this a j1939 thing speciality?

> +             if (ret < 0) {
> +                     if (EINTR == errno)
> +                             continue;
> +                     error(1, errno, "recvfrom()");
> +             }
> +             if (ret < 3)
> +                     continue;
> +             pgn = dat[0] + (dat[1] << 8) + ((dat[2] & 0x03) << 16);
> +
> +             switch (pgn) {
> +             case 0x0fee6:

Quite unusual, I'd write:
if (pgn == 0x0fee6)

> +                     if (s.verbose)
> +                             error(0, 0, "got request");
> +                     s.sig_alrm = 1;
> +                     break;
> +             }
> +     }
> +     return 0;
> +}
> +
> 
> Property changes on: can-utils/jdate.c
> ___________________________________________________________________
> Name: svn:eol-style
>    + native
> 
> _______________________________________________
> Socketcan-core mailing list
> [email protected]
> https://lists.berlios.de/mailman/listinfo/socketcan-core


-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |

Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
Socketcan-core mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/socketcan-core

Reply via email to