All of lore.kernel.org
 help / color / mirror / Atom feed
* libsocketcan proposal for upstream (get typekind vcan or can, etc.)
@ 2016-09-23  6:16 aj neu
  2016-09-23  6:19 ` aj neu
  0 siblings, 1 reply; 4+ messages in thread
From: aj neu @ 2016-09-23  6:16 UTC (permalink / raw)
  To: linux-can

Hello,

below, please find a patch which adds the following functions to libsocketcan

    device_exists, device_is_up, can_get_typekind

    int device_exists(const char *name);
     // determine if device is libsocketcan-compatible and exists

    int device_is_up(const char *name);
     // determine if device is up (also usable for vcan)

    int can_get_typekind(const char *name, char *buf, size_t buflen);
     // determine if typekind is "can" or "vcan"


The patch can be applied to
https://git.platon.pengutronix.de/cgit/tools/libsocketcan
as follows:
   git apply diff.patch


Can this be applied to upstream?

Thanks.
ajneu


diff --git a/include/libsocketcan.h b/include/libsocketcan.h
index dc52053..16fd60a 100644
--- a/include/libsocketcan.h
+++ b/include/libsocketcan.h
@@ -27,11 +27,15 @@
  */

 #include <can_netlink.h>
+#include <stddef.h>

 #ifdef __cplusplus
 extern "C" {
 #endif

+int device_exists(const char *name);
+int device_is_up(const char *name);
+
 int can_do_restart(const char *name);
 int can_do_stop(const char *name);
 int can_do_start(const char *name);
@@ -46,6 +50,7 @@ int can_get_restart_ms(const char *name, __u32 *restart_ms);
 int can_get_bittiming(const char *name, struct can_bittiming *bt);
 int can_get_ctrlmode(const char *name, struct can_ctrlmode *cm);
 int can_get_state(const char *name, int *state);
+int can_get_typekind(const char *name, char *buf, size_t buflen);
 int can_get_clock(const char *name, struct can_clock *clock);
 int can_get_bittiming_const(const char *name, struct can_bittiming_const *btc);
 int can_get_berr_counter(const char *name, struct can_berr_counter *bc);
diff --git a/src/libsocketcan.c b/src/libsocketcan.c
index c97a28c..7c7f9bb 100644
--- a/src/libsocketcan.c
+++ b/src/libsocketcan.c
@@ -46,6 +46,10 @@
 #define IF_UP 1
 #define IF_DOWN 2

+#ifndef IFF_UP
+#define IFF_UP IF_UP
+#endif
+
 #define GET_STATE 1
 #define GET_RESTART_MS 2
 #define GET_BITTIMING 3
@@ -54,6 +58,9 @@
 #define GET_BITTIMING_CONST 6
 #define GET_BERR_COUNTER 7
 #define GET_XSTATS 8
+#define GET_TYPEKIND 9
+#define GET_DEVICEEXISTS 10
+#define GET_DEVICE_UP 11

 struct get_req {
     struct nlmsghdr n;
@@ -74,6 +81,11 @@ struct req_info {
     struct can_bittiming *bittiming;
 };

+struct str_buf {
+    char * buf;
+    const size_t capacity; // storage capacity of buf: number of bytes
+};
+
 static void
 parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, int len)
 {
@@ -389,7 +401,8 @@ static int do_get_nl_link(int fd, __u8 acquire,
const char *name, void *res)
             else
                 continue;

-            if (acquire == GET_XSTATS) {
+            switch (acquire) {
+            case GET_XSTATS:
                 if (!linkinfo[IFLA_INFO_XSTATS])
                     fprintf(stderr, "no can statistics found\n");
                 else {
@@ -398,6 +411,30 @@ static int do_get_nl_link(int fd, __u8 acquire,
const char *name, void *res)
                     ret = 0;
                 }
                 continue;
+
+            case GET_TYPEKIND:
+                if (!linkinfo[IFLA_INFO_KIND])
+                    fprintf(stderr, "no type-kind found\n");
+                else {
+                    const size_t buflen = ((struct str_buf *)res)->capacity;
+                    if (buflen) {
+                        char * const buf = ((struct str_buf *)res)->buf;
+                        *buf = '\0';
+                        strncat(buf,
RTA_DATA(linkinfo[IFLA_INFO_KIND]), buflen-1);
+                    }
+                    ret = 0;
+                }
+                continue;
+
+            case GET_DEVICEEXISTS:
+                ret = 0;
+                continue;
+
+            case GET_DEVICE_UP:
+                if ((ifi->ifi_flags & IFF_UP) == IFF_UP) {
+                    ret = 0;
+                }
+                continue;
             }

             if (!linkinfo[IFLA_INFO_DATA]) {
@@ -652,6 +689,38 @@ static int set_link(const char *name, __u8
if_state, struct req_info *req_info)

 /**
  * @ingroup extern
+ * device_exists - return non-zero if the device exists
+ *
+ * @param name name of the device. This is the netdev name, as
ifconfig -a shows
+ * in your system. usually it contains prefix "can" and the numer of the can
+ * line. e.g. "can0"
+ *
+ * @return 1 if device exists
+ * @return 0 if device does not exist
+ */
+int device_exists(const char *name)
+{
+    return !get_link(name, GET_DEVICEEXISTS, NULL);
+}
+
+/**
+ * @ingroup extern
+ * device_is_up - return non-zero if the device is up
+ *
+ * @param name name of the device. This is the netdev name, as
ifconfig -a shows
+ * in your system. usually it contains prefix "can" and the numer of the can
+ * line. e.g. "can0"
+ *
+ * @return 1 if device is up
+ * @return 0 if device is not up
+ */
+int device_is_up(const char *name)
+{
+    return !get_link(name, GET_DEVICE_UP, NULL);
+}
+
+/**
+ * @ingroup extern
  * can_do_start - start the can interface
  * @param name name of the can device. This is the netdev name, as
ifconfig -a shows
  * in your system. usually it contains prefix "can" and the numer of the can
@@ -961,6 +1030,25 @@ int can_get_state(const char *name, int *state)

 /**
  * @ingroup extern
+ * can_get_typekind - get the type (kind) of the netlink, i.e. can or vcan
+ *
+ * @param name name of the can device. This is the netdev name, as
ifconfig -a shows
+ * in your system. usually it contains prefix "can" and the numer of the can
+ * line. e.g. "can0"
+ * @param buf pointer to the first element of a string buffer, to
store the kind
+ * @param buflen length of the string buffer (at most buflen-1 chars
will be written)
+ *
+ * @return 0 if success
+ * @return -1 if failed
+ */
+int can_get_typekind(const char *name, char *buf, size_t buflen)
+{
+    struct str_buf sbuf = { buf, buflen };
+    return get_link(name, GET_TYPEKIND, &sbuf);
+}
+
+/**
+ * @ingroup extern
  * can_get_restart_ms - get the current interval of auto restarting.
  *
  * @param name name of the can device. This is the netdev name, as
ifconfig -a shows

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: libsocketcan proposal for upstream (get typekind vcan or can, etc.)
  2016-09-23  6:16 libsocketcan proposal for upstream (get typekind vcan or can, etc.) aj neu
@ 2016-09-23  6:19 ` aj neu
  2016-09-23 10:19   ` André Hartmann
  2016-09-23 12:15   ` André Hartmann
  0 siblings, 2 replies; 4+ messages in thread
From: aj neu @ 2016-09-23  6:19 UTC (permalink / raw)
  To: linux-can

[-- Attachment #1: Type: text/plain, Size: 759 bytes --]

On Fri, Sep 23, 2016 at 8:16 AM, aj neu wrote:
> Hello,
>
> below, please find a patch which adds the following functions to libsocketcan
>
>     device_exists, device_is_up, can_get_typekind
>
>     int device_exists(const char *name);
>      // determine if device is libsocketcan-compatible and exists
>
>     int device_is_up(const char *name);
>      // determine if device is up (also usable for vcan)
>
>     int can_get_typekind(const char *name, char *buf, size_t buflen);
>      // determine if typekind is "can" or "vcan"
>
>
> The patch can be applied to
> https://git.platon.pengutronix.de/cgit/tools/libsocketcan
> as follows:
>    git apply diff.patch
>
>
> Can this be applied to upstream?
>
> Thanks.
> ajneu

Here's the patch as attachment.

[-- Attachment #2: diff.patch --]
[-- Type: text/x-patch, Size: 4994 bytes --]

diff --git a/include/libsocketcan.h b/include/libsocketcan.h
index dc52053..16fd60a 100644
--- a/include/libsocketcan.h
+++ b/include/libsocketcan.h
@@ -27,11 +27,15 @@
  */
 
 #include <can_netlink.h>
+#include <stddef.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+int device_exists(const char *name);
+int device_is_up(const char *name);
+
 int can_do_restart(const char *name);
 int can_do_stop(const char *name);
 int can_do_start(const char *name);
@@ -46,6 +50,7 @@ int can_get_restart_ms(const char *name, __u32 *restart_ms);
 int can_get_bittiming(const char *name, struct can_bittiming *bt);
 int can_get_ctrlmode(const char *name, struct can_ctrlmode *cm);
 int can_get_state(const char *name, int *state);
+int can_get_typekind(const char *name, char *buf, size_t buflen);
 int can_get_clock(const char *name, struct can_clock *clock);
 int can_get_bittiming_const(const char *name, struct can_bittiming_const *btc);
 int can_get_berr_counter(const char *name, struct can_berr_counter *bc);
diff --git a/src/libsocketcan.c b/src/libsocketcan.c
index c97a28c..7c7f9bb 100644
--- a/src/libsocketcan.c
+++ b/src/libsocketcan.c
@@ -46,6 +46,10 @@
 #define IF_UP 1
 #define IF_DOWN 2
 
+#ifndef IFF_UP
+#define IFF_UP IF_UP
+#endif
+
 #define GET_STATE 1
 #define GET_RESTART_MS 2
 #define GET_BITTIMING 3
@@ -54,6 +58,9 @@
 #define GET_BITTIMING_CONST 6
 #define GET_BERR_COUNTER 7
 #define GET_XSTATS 8
+#define GET_TYPEKIND 9
+#define GET_DEVICEEXISTS 10
+#define GET_DEVICE_UP 11
 
 struct get_req {
 	struct nlmsghdr n;
@@ -74,6 +81,11 @@ struct req_info {
 	struct can_bittiming *bittiming;
 };
 
+struct str_buf {
+	char * buf;
+	const size_t capacity; // storage capacity of buf: number of bytes
+};
+
 static void
 parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, int len)
 {
@@ -389,7 +401,8 @@ static int do_get_nl_link(int fd, __u8 acquire, const char *name, void *res)
 			else
 				continue;
 
-			if (acquire == GET_XSTATS) {
+			switch (acquire) {
+			case GET_XSTATS:
 				if (!linkinfo[IFLA_INFO_XSTATS])
 					fprintf(stderr, "no can statistics found\n");
 				else {
@@ -398,6 +411,30 @@ static int do_get_nl_link(int fd, __u8 acquire, const char *name, void *res)
 					ret = 0;
 				}
 				continue;
+
+			case GET_TYPEKIND:
+				if (!linkinfo[IFLA_INFO_KIND])
+					fprintf(stderr, "no type-kind found\n");
+				else {
+					const size_t buflen = ((struct str_buf *)res)->capacity;
+					if (buflen) {
+						char * const buf = ((struct str_buf *)res)->buf;
+						*buf = '\0';
+						strncat(buf, RTA_DATA(linkinfo[IFLA_INFO_KIND]), buflen-1);
+					}
+					ret = 0;
+				}
+				continue;
+
+			case GET_DEVICEEXISTS:
+				ret = 0;
+				continue;
+
+			case GET_DEVICE_UP:
+				if ((ifi->ifi_flags & IFF_UP) == IFF_UP) {
+					ret = 0;
+				}
+				continue;
 			}
 
 			if (!linkinfo[IFLA_INFO_DATA]) {
@@ -652,6 +689,38 @@ static int set_link(const char *name, __u8 if_state, struct req_info *req_info)
 
 /**
  * @ingroup extern
+ * device_exists - return non-zero if the device exists
+ *
+ * @param name name of the device. This is the netdev name, as ifconfig -a shows
+ * in your system. usually it contains prefix "can" and the numer of the can
+ * line. e.g. "can0"
+ *
+ * @return 1 if device exists
+ * @return 0 if device does not exist
+ */
+int device_exists(const char *name)
+{
+	return !get_link(name, GET_DEVICEEXISTS, NULL);
+}
+
+/**
+ * @ingroup extern
+ * device_is_up - return non-zero if the device is up
+ *
+ * @param name name of the device. This is the netdev name, as ifconfig -a shows
+ * in your system. usually it contains prefix "can" and the numer of the can
+ * line. e.g. "can0"
+ *
+ * @return 1 if device is up
+ * @return 0 if device is not up
+ */
+int device_is_up(const char *name)
+{
+	return !get_link(name, GET_DEVICE_UP, NULL);
+}
+
+/**
+ * @ingroup extern
  * can_do_start - start the can interface
  * @param name name of the can device. This is the netdev name, as ifconfig -a shows
  * in your system. usually it contains prefix "can" and the numer of the can
@@ -961,6 +1030,25 @@ int can_get_state(const char *name, int *state)
 
 /**
  * @ingroup extern
+ * can_get_typekind - get the type (kind) of the netlink, i.e. can or vcan
+ *
+ * @param name name of the can device. This is the netdev name, as ifconfig -a shows
+ * in your system. usually it contains prefix "can" and the numer of the can
+ * line. e.g. "can0"
+ * @param buf pointer to the first element of a string buffer, to store the kind
+ * @param buflen length of the string buffer (at most buflen-1 chars will be written)
+ *
+ * @return 0 if success
+ * @return -1 if failed
+ */
+int can_get_typekind(const char *name, char *buf, size_t buflen)
+{
+	struct str_buf sbuf = { buf, buflen };
+	return get_link(name, GET_TYPEKIND, &sbuf);
+}
+
+/**
+ * @ingroup extern
  * can_get_restart_ms - get the current interval of auto restarting.
  *
  * @param name name of the can device. This is the netdev name, as ifconfig -a shows

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: libsocketcan proposal for upstream (get typekind vcan or can, etc.)
  2016-09-23  6:19 ` aj neu
@ 2016-09-23 10:19   ` André Hartmann
  2016-09-23 12:15   ` André Hartmann
  1 sibling, 0 replies; 4+ messages in thread
From: André Hartmann @ 2016-09-23 10:19 UTC (permalink / raw)
  To: aj neu, linux-can, mkl

Am 23.09.2016 um 08:19 schrieb aj neu:
> On Fri, Sep 23, 2016 at 8:16 AM, aj neu wrote:
>> Hello,
>>
>> below, please find a patch which adds the following functions to libsocketcan
>>
>>     device_exists, device_is_up, can_get_typekind
>>
>>     int device_exists(const char *name);
>>      // determine if device is libsocketcan-compatible and exists
>>
>>     int device_is_up(const char *name);
>>      // determine if device is up (also usable for vcan)
>>
>>     int can_get_typekind(const char *name, char *buf, size_t buflen);
>>      // determine if typekind is "can" or "vcan"
>>
>>
>> The patch can be applied to
>> https://git.platon.pengutronix.de/cgit/tools/libsocketcan
>> as follows:
>>    git apply diff.patch
>>
>>
>> Can this be applied to upstream?
>>
>> Thanks.
>> ajneu
>
> Here's the patch as attachment.
>

Hello AJ,

without having a deeper look at your patch, I think it is a quite useful 
addition. Please find my comments below.

 >>     int device_exists(const char *name);

This is good, but even better would be something that enumerates 
available interfaces. Looking for available interfaces is a common task, 
I guess. Something like Kurt's library [1] does and what I do in 
QtSerialBus [2] because I was unable to use [1] because of license 
reasons :(

 >>     int device_is_up(const char *name);

OK, if device_exists returns true for devices that are not up.

 >>     int can_get_typekind(const char *name, char *buf, size_t buflen);

Can buf contains anything else beside "can" and "vcan"? If not, I 
instead propose a more concise function:

     int device_is_virtual(const char *name);

Regarding the patch itself:

Marc, what do you say? Will you accept patches to libsocketcan  The last 
commits are from 2014...

And last, one more comment to the code:

+case GET_TYPEKIND:
+  if (!linkinfo[IFLA_INFO_KIND])
+    fprintf(stderr, "no type-kind found\n");
+  else {

I don't know if there are any rules in libsocketcan, but I really prefer 
having curly braces { } around the if also, when there are curly braces 
around the else branch.

+    const size_t buflen = ((struct str_buf *)res)->capacity;
+    if (buflen) {
+      char * const buf = ((struct str_buf *)res)->buf;
+      *buf = '\0';
+      strncat(buf, RTA_DATA(linkinfo[IFLA_INFO_KIND]), buflen-1);

First I asked why not using strncpy, but I guess this is a trick to make 
sure buf is null-terminated? On the other hand, the following code is 
not longer (buflen - 1 is allowed because you checked for zero already):

       strncpy(buf, RTA_DATA(linkinfo[IFLA_INFO_KIND]), buflen);
       buf[buflen - 1] = '\0';

+    }
+    ret = 0;
+}

Best regards,
André

[1] https://github.com/kurt-vd/enumif
[2] 
https://codereview.qt-project.org/#/c/166460/13/src/plugins/canbus/socketcan/socketcanbackend.cpp



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: libsocketcan proposal for upstream (get typekind vcan or can, etc.)
  2016-09-23  6:19 ` aj neu
  2016-09-23 10:19   ` André Hartmann
@ 2016-09-23 12:15   ` André Hartmann
  1 sibling, 0 replies; 4+ messages in thread
From: André Hartmann @ 2016-09-23 12:15 UTC (permalink / raw)
  To: aj neu, linux-can

Hi again AJ,

I've now taken a second look at your patch.

As all functions in libsocketcan start with can_*, your new functions 
device_exists and device_is_up are not consistent. As all existing 
functions already have const char *name as first parameter, I think the 
word "device" is superflous. Having all functions starting with can_* 
helps including the library in existing projects.

Suggestions:

int can_is_(existing|available|present)(const char *name);
int can_is_up(const char *name);

Best regards,
André

Am 23.09.2016 um 08:19 schrieb aj neu:
> On Fri, Sep 23, 2016 at 8:16 AM, aj neu wrote:
>> Hello,
>>
>> below, please find a patch which adds the following functions to libsocketcan
>>
>>     device_exists, device_is_up, can_get_typekind
>>
>>     int device_exists(const char *name);
>>      // determine if device is libsocketcan-compatible and exists
>>
>>     int device_is_up(const char *name);
>>      // determine if device is up (also usable for vcan)
>>
>>     int can_get_typekind(const char *name, char *buf, size_t buflen);
>>      // determine if typekind is "can" or "vcan"
>>
>>
>> The patch can be applied to
>> https://git.platon.pengutronix.de/cgit/tools/libsocketcan
>> as follows:
>>    git apply diff.patch
>>
>>
>> Can this be applied to upstream?
>>
>> Thanks.
>> ajneu
>
> Here's the patch as attachment.
>


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-09-23 12:15 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-23  6:16 libsocketcan proposal for upstream (get typekind vcan or can, etc.) aj neu
2016-09-23  6:19 ` aj neu
2016-09-23 10:19   ` André Hartmann
2016-09-23 12:15   ` André Hartmann

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.