can-j1939: add libj1939.a

libj1939 provides a parser for struct sockaddr_can with j1939 info

Signed-off-by: Kurt Van Dijck <kurt.van.dijck@eia.be>
pull/7/head
Kurt Van Dijck 2013-03-13 20:28:44 +01:00
parent e965a2a25e
commit 18da2c3f6a
5 changed files with 213 additions and 3 deletions

1
.gitignore vendored
View File

@ -39,6 +39,7 @@ GNUmakefile.in
/isotpserver /isotpserver
/isotpsniffer /isotpsniffer
/isotptun /isotptun
/libj1939.a
/log2asc /log2asc
/log2long /log2long
/slcan_attach /slcan_attach

View File

@ -61,6 +61,12 @@ bin_PROGRAMS = \
slcand \ slcand \
slcanpty slcanpty
if CONFIG_J1939
noinst_LTLIBRARIES += libj1939.la
libj1939_la_SOURCES = libj1939.c
endif
EXTRA_DIST = \ EXTRA_DIST = \
autogen.sh autogen.sh

View File

@ -60,17 +60,25 @@ PROGRAMS = can-calc-bit-timing candump cansniffer cansend canplayer cangen canbu
$(PROGRAMS_SLCAN)\ $(PROGRAMS_SLCAN)\
slcanpty canfdtest slcanpty canfdtest
all: $(PROGRAMS) LIBRARIES = libj1939.a
all: $(PROGRAMS) $(LIBRARIES)
clean: clean:
rm -f $(PROGRAMS) *.o rm -f $(PROGRAMS) *.o libj1939.a
install: install:
mkdir -p $(DESTDIR)$(PREFIX)/bin mkdir -p $(DESTDIR)$(PREFIX)/bin
cp -f $(PROGRAMS) $(DESTDIR)$(PREFIX)/bin cp -f $(PROGRAMS) $(DESTDIR)$(PREFIX)/bin
mkdir -p $(DESTDIR)$(PREFIX)/lib
cp -f $(LIBRARIES) $(DESTDIR)$(PREFIX)/lib
distclean: distclean:
rm -f $(PROGRAMS) *.o *~ rm -f $(PROGRAMS) $(LIBRARIES) *.o *~
libj1939.a: libj1939.o
ar crs $@ $<
cansend.o: lib.h cansend.o: lib.h
cangen.o: lib.h cangen.o: lib.h

176
libj1939.c 100644
View File

@ -0,0 +1,176 @@
/*
* Copyright (c) 2011 EIA Electronics
*
* Authors:
* Kurt Van Dijck <kurt.van.dijck@eia.be>
*
* 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 <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <inttypes.h>
#include <error.h>
#include <unistd.h>
#include <fcntl.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include "libj1939.h"
/* static data */
static struct if_nameindex *saved;
__attribute__((destructor))
static void libj1939_cleanup(void)
{
if (saved)
if_freenameindex(saved);
saved = 0;
}
static inline void fetch_names(void)
{
if (!saved) {
saved = if_nameindex();
if (!saved)
error(1, errno, "if_nameindex()");
}
}
/* retrieve name */
const char *libj1939_ifnam(int ifindex)
{
const struct if_nameindex *lp, *cached = saved;
fetch_names();
for (lp = saved; lp->if_index; ++lp) {
if (lp->if_index == ifindex)
return lp->if_name;
}
if (cached) {
/*
* the list was not recent
* iterate twice, but force a refresh now
* recursion stops since the 'saved' pointer is cleaned
*/
libj1939_cleanup();
return libj1939_ifnam(ifindex);
} else
return NULL;
}
/* retrieve index */
int libj1939_ifindex(const char *str)
{
const struct if_nameindex *lp, *cached = saved;
char *endp;
int ret;
ret = strtol(str, &endp, 0);
if (!*endp)
/* did some good parse */
return ret;
fetch_names();
for (lp = saved; lp->if_index; ++lp) {
if (!strcmp(lp->if_name, str))
return lp->if_index;
}
if (cached) {
libj1939_cleanup();
return libj1939_ifindex(str);
} else
return 0;
}
int libj1939_str2addr(const char *str, char **endp, struct sockaddr_can *can)
{
char *p;
const char *pstr;
uint64_t tmp64;
unsigned long tmp;
if (!endp)
endp = &p;
memset(can, 0, sizeof(*can));
can->can_family = AF_CAN;
can->can_addr.j1939.name = J1939_NO_NAME;
can->can_addr.j1939.addr = J1939_NO_ADDR;
can->can_addr.j1939.pgn = J1939_NO_PGN;
pstr = strchr(str, ':');
if (pstr) {
char tmp[IFNAMSIZ];
if ((pstr - str) >= IFNAMSIZ)
return -1;
strncpy(tmp, str, pstr - str);
tmp[pstr - str] = 0;
can->can_ifindex = libj1939_ifindex(tmp);
} else {
can->can_ifindex = libj1939_ifindex(str);
if (can->can_ifindex) {
if (endp)
*endp = (char *)&str[strlen(str)];
return 0;
}
}
if (pstr)
++pstr;
else
pstr = str;
tmp64 = strtoull(pstr, endp, 16);
if (*endp <= pstr)
return 0;
if ((*endp - pstr) == 2)
can->can_addr.j1939.addr = tmp64;
else
can->can_addr.j1939.name = tmp64;
if (!**endp)
return 0;
str = *endp + 1;
tmp = strtoul(str, endp, 16);
if (*endp > str)
can->can_addr.j1939.pgn = tmp;
return 0;
}
const char *libj1939_addr2str(const struct sockaddr_can *can)
{
char *str;
static char buf[128];
str = buf;
if (can->can_ifindex) {
const char *ifname;
ifname = libj1939_ifnam(can->can_ifindex);
if (!ifname)
str += sprintf(str, "#%i:", can->can_ifindex);
else
str += sprintf(str, "%s:", ifname);
}
if (can->can_addr.j1939.name) {
str += sprintf(str, "%016llx", (unsigned long long)can->can_addr.j1939.name);
if (can->can_addr.j1939.pgn == 0x0ee00)
str += sprintf(str, ".%02x", can->can_addr.j1939.addr);
} else if (can->can_addr.j1939.addr <= 0xfe)
str += sprintf(str, "%02x", can->can_addr.j1939.addr);
else
str += sprintf(str, "-");
if (can->can_addr.j1939.pgn <= 0x3ffff)
str += sprintf(str, ",%05x", can->can_addr.j1939.pgn);
return buf;
}

19
libj1939.h 100644
View File

@ -0,0 +1,19 @@
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/j1939.h>
#ifndef J1939_LIB_H
#define J1939_LIB_H
#ifdef __cplusplus
extern "C" {
#endif
extern int libj1939_str2addr(const char *str, char **endp, struct sockaddr_can *can);
extern const char *libj1939_addr2str(const struct sockaddr_can *can);
#ifdef __cplusplus
}
#endif
#endif