Add capability to set PECI device file name

This adds capability to set the name of the PECI device file.
If the PECI device name is null, use "/dev/peci-default".
If that does not exist fall back to "/dev/peci-0"

PECI_DEV environment variable can be used to override default
PECI device name, for example: export PECI_DEV=/dev/peci-wire

Added -d <dev name> command line option to peci_cmds, that
can be used to specify PECI device name, for example:
peci_cmds -d /dev/peci-0 gettemp

Added peci_SetDevName(char* dev_name) to libpeci API.

Tested manually:
1) using peci_cmds -d <dev_name> gettemp
2) calling peci_SetDevName(<dev_name>) from client application

Change-Id: I236857ec3ac42b8ff227aa32899ca8f1f3577d2b
Signed-off-by: Anna Platash <anna.platash@intel.com>
Signed-off-by: Iwona Winiarska <iwona.winiarska@intel.com>
diff --git a/peci.c b/peci.c
index 2627a03..53596f6 100644
--- a/peci.c
+++ b/peci.c
@@ -16,6 +16,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <peci.h>
+#include <stdlib.h>
 #include <string.h>
 #include <sys/ioctl.h>
 #include <syslog.h>
@@ -29,6 +30,47 @@
 
 EPECIStatus peci_GetDIB_seq(uint8_t target, uint64_t* dib, int peci_fd);
 
+char* peci_device_list[2];
+#define DEV_NAME_SIZE 64
+/*-------------------------------------------------------------------------
+ * This funcion sets the name of the PECI device file to use.
+ * If the PECI device name is null try "/dev/peci-default",
+ * if "/dev/peci-default" does not exist, fall back to "/dev/peci-0"
+ *------------------------------------------------------------------------*/
+void peci_SetDevName(char* peci_dev)
+{
+    static char peci_name_new[DEV_NAME_SIZE] = {};
+
+    if (peci_dev)
+    {
+        strncpy(peci_name_new, peci_dev, sizeof(peci_name_new));
+        peci_name_new[DEV_NAME_SIZE - 1] = '\0';
+        peci_device_list[0] = peci_name_new;
+        peci_device_list[1] = NULL;
+        syslog(LOG_INFO, "PECI set dev name to %s\n", peci_device_list[0]);
+    }
+    else
+    {
+        peci_device_list[0] = "/dev/peci-default";
+        peci_device_list[1] = "/dev/peci-0";
+        syslog(LOG_INFO, "PECI set dev names to %s, %s\n", peci_device_list[0],
+               peci_device_list[1]);
+    }
+}
+
+/*-------------------------------------------------------------------------
+ * This function initializes PECI device name when a shared library
+ * is loaded, typically during program startup.
+ *------------------------------------------------------------------------*/
+static void init() __attribute__((constructor));
+static void init()
+{
+    // By default PECI_DEV is not defined in the environment,
+    // so this will call peci_SetDevName(NULL) and initialize
+    // PECI device name to defaults.
+    peci_SetDevName(getenv("PECI_DEV"));
+}
+
 /*-------------------------------------------------------------------------
  * This function unlocks the peci interface
  *------------------------------------------------------------------------*/
@@ -40,7 +82,6 @@
     }
 }
 
-#define PECI_DEVICE "/dev/peci-0"
 /*-------------------------------------------------------------------------
  * This function attempts to lock the peci interface with the specified
  * timeout and returns a file descriptor if successful.
@@ -51,6 +92,7 @@
     sRequest.tv_sec = 0;
     sRequest.tv_nsec = PECI_TIMEOUT_RESOLUTION_MS * 1000 * 1000;
     int timeout_count = 0;
+    char* peci_device = peci_device_list[0];
 
     if (NULL == peci_fd)
     {
@@ -58,7 +100,12 @@
     }
 
     // Open the PECI driver with the specified timeout
-    *peci_fd = open(PECI_DEVICE, O_RDWR | O_CLOEXEC);
+    *peci_fd = open(peci_device, O_RDWR | O_CLOEXEC);
+    if (*peci_fd == -1 && errno == ENOENT && peci_device_list[1])
+    {
+        peci_device = peci_device_list[1];
+        *peci_fd = open(peci_device, O_RDWR | O_CLOEXEC);
+    }
     switch (timeout_ms)
     {
         case PECI_NO_WAIT:
@@ -67,14 +114,14 @@
             while (-1 == *peci_fd)
             {
                 nanosleep(&sRequest, NULL);
-                *peci_fd = open(PECI_DEVICE, O_RDWR | O_CLOEXEC);
+                *peci_fd = open(peci_device, O_RDWR | O_CLOEXEC);
             }
         default:
             while (-1 == *peci_fd && timeout_count < timeout_ms)
             {
                 nanosleep(&sRequest, NULL);
                 timeout_count += PECI_TIMEOUT_RESOLUTION_MS;
-                *peci_fd = open(PECI_DEVICE, O_RDWR | O_CLOEXEC);
+                *peci_fd = open(peci_device, O_RDWR | O_CLOEXEC);
             }
     }
     if (-1 == *peci_fd)
diff --git a/peci.h b/peci.h
index cb145e3..d4c3f65 100644
--- a/peci.h
+++ b/peci.h
@@ -254,6 +254,7 @@
 EPECIStatus peci_Ping_seq(uint8_t target, int peci_fd);
 EPECIStatus peci_GetCPUID(const uint8_t clientAddr, CPUModel* cpuModel,
                           uint8_t* stepping, uint8_t* cc);
+void peci_SetDevName(char* peci_dev);
 
 #ifdef __cplusplus
 }
diff --git a/peci_cmds.c b/peci_cmds.c
index a2f709b..24c3d8d 100644
--- a/peci_cmds.c
+++ b/peci_cmds.c
@@ -50,6 +50,8 @@
     printf("\t%-12s%s\n", "-s <size>",
            "Size of data to read or write in bytes. Accepted values are 1, 2, "
            "4, 8, and 16. Default is 4");
+    printf("\t%-12s%s\n", "-d",
+           "Set PECI device name, for example \"-d /dev/peci-0\"");
     printf("Commands:\n");
     printf("\t%-28s%s\n", "Ping", "Ping the target");
     printf("\t%-28s%s\n", "GetTemp", "Get the temperature");
@@ -129,7 +131,7 @@
     //
     // Parse arguments.
     //
-    while (-1 != (c = getopt(argc, argv, "hvl:a:s:")))
+    while (-1 != (c = getopt(argc, argv, "hvl:a:s:d:")))
     {
         switch (c)
         {
@@ -178,6 +180,10 @@
                 }
                 break;
 
+            case 'd':
+                peci_SetDevName(optarg);
+                break;
+
             default:
                 printf("ERROR: Unrecognized option \"-%c\"\n", optopt);
                 goto ErrorExit;