WiringPi: Improve logic of getting board information

Now WiringPi doesn't require editted /proc/cpuinfo if a proper model
name is defined in target board's device tree.

Signed-off-by: Deokgyu Yang <secugyu@gmail.com>
Change-Id: I94b6b9595577546d785f018258746032bf9a9494
diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c
index 9f658e8..bbb80ed 100755
--- a/wiringPi/wiringPi.c
+++ b/wiringPi/wiringPi.c
@@ -44,10 +44,13 @@
 /*----------------------------------------------------------------------------*/
 const char *piModelNames [16] =
 {
+	// These names must be full name of the board.
+	// And, the model name on the target board has to be a part of an item of the array.
+	// e.g, ODROID-C or ODROID-XU3/4 may not be used for recognizing a board.
 	"Unknown",
 	"ODROID-C1/C1+",
 	"ODROID-C2",
-	"ODROID-XU3/4",
+	"ODROID-XU3/XU4",
 	"ODROID-N1",
 	"ODROID-N2",
 	"ODROID-C4",
@@ -315,148 +318,148 @@
 }
 
 /*----------------------------------------------------------------------------*/
-int piGpioLayout (void)
-{
-	FILE *cpuFd, *dtFd;
-	char line [120] ;
-	char *c ;
-	static int  gpioLayout = -1 ;
+int getModelFromCpuinfo(char *line, FILE *cpuFd) {
+	char *model;
 
-	if (gpioLayout != -1)
-		return	gpioLayout;
+	if ((cpuFd = fopen("/proc/cpuinfo", "r")) != NULL) {
+		while (fgets(line, 120, cpuFd) != NULL) {
+			if (strncmp(line, "Hardware", 8) == 0)
+				break;
+		}
 
-	gpioLayout = 1;
+		if (!(strncmp(line, "Hardware", 8) != 0)) {
+			if (wiringPiDebug)
+				printf("piGpioLayout: %s: Hardware: %s\n", __func__, line);
 
-	if ((cpuFd = fopen ("/proc/cpuinfo", "r")) != NULL) {
-		while (fgets (line, 120, cpuFd) != NULL)
-			if (strncmp (line, "Hardware", 8) == 0)
-				break ;
+			model = strcasestr(line, "odroid");
+			if (!model)
+				return -1;
 
-		if (strncmp (line, "Hardware", 8) != 0)
-			wiringPiFailure (WPI_FATAL, "No \"Hardware\" line") ;
+			strcpy(line, model);
+			return 0;
+		}
+	}
+
+	return -1;
+}
+
+/*----------------------------------------------------------------------------*/
+int getModelFromDt(char *line, FILE *dtFd) {
+	char *model;
+
+	if ((dtFd = fopen("/sys/firmware/devicetree/base/model", "r")) != NULL) {
+		if (fgets(line, 120, dtFd) == NULL)
+			return -1;
 
 		if (wiringPiDebug)
-			printf ("piGpioLayout: Hardware: %s\n", line) ;
+			printf("piGpioLayout: %s: Hardware: %s\n", __func__, line);
 
-		if (!(strcasestr (line, "odroid"))) {
-			if ((dtFd = fopen("/sys/firmware/devicetree/base/model", "r")) != NULL) {
-				if (fgets(line, 30, dtFd) == NULL)
-					wiringPiFailure (WPI_FATAL, "Unable to read /sys/firmware/devicetree/base/model");
+		model = strcasestr(line, "odroid");
+		if (!model)
+			return -1;
 
-				if (wiringPiDebug)
-					printf ("piGpioLayout: devicetree/base/model: %s\n", line) ;
-
-				if (!(strcasestr (line, "odroid")))
-					wiringPiFailure (WPI_FATAL, "** This board is not ODROID. **") ;
-			} else {
-				wiringPiFailure (WPI_FATAL, "Unable to open /sys/firmware/devicetree/base/model") ;
-			}
-		}
-	} else {
-		wiringPiFailure (WPI_FATAL, "Unable to open /proc/cpuinfo") ;
+		strcpy(line, model);
+		return 0;
 	}
 
-	rewind (cpuFd) ;
-	while (fgets (line, 120, cpuFd) != NULL)
-		if (strncmp (line, "Revision", 8) == 0)
-			break ;
-	fclose (cpuFd) ;
+	return -1;
+}
 
-	if (strncmp (line, "Revision", 8) != 0)
-		wiringPiFailure (WPI_FATAL, "No \"Revision\" line") ;
+/*----------------------------------------------------------------------------*/
+int piGpioLayout (void) {
+	FILE *cpuFd = NULL, *dtFd = NULL;
+	char line[120];
+	char *model, *modelCodename, *buf, *seps = "\t\n\v\f\r ";
+	int sizeOfAssignedModelNames = 0;
+	int i;
 
-	for (c = &line [strlen (line) - 1] ; (*c == '\n') || (*c == '\r') ; --c)
-		*c = 0 ;
+	if (getModelFromCpuinfo(line, cpuFd) != 0 && getModelFromDt(line, dtFd) != 0)
+		wiringPiFailure(WPI_FATAL, "** This board is not an Odroid **");
 
-	if (wiringPiDebug)
-		printf ("piGpioLayout: Revision string: %s\n", line) ;
+	for (i = 1; i < (int)(sizeof(piModelNames) / sizeof(char*)); i++) {
+		if (piModelNames[i] == NULL) {
+			sizeOfAssignedModelNames = i - 1;
+			break;
+		}
+	}
 
-	// Scan to the first character of the revision number
-	for (c = line ; *c ; ++c)
-		if (*c == ':')
-			break ;
+	i = strlen(line) - 1;
+	while (i >= 0 && strchr(seps, line[i]) != NULL) {
+		line[i] = '\0';
+		i--;
+	}
 
-	if (*c != ':')
-		wiringPiFailure (WPI_FATAL, "Bogus \"Revision\" line (no colon)") ;
+	buf = strchr(line, '-');
+	modelCodename = buf != NULL ? buf : strchr(line, ' ');
+	if (modelCodename == NULL)
+		wiringPiFailure(WPI_FATAL, "** Model string on this board is not well formatted **");
+	modelCodename++;
 
-	// Chomp spaces
-	++c ;
-	while (isspace (*c))
-		++c ;
+	libwiring.model = 0;
+	for (i = 1; i <= sizeOfAssignedModelNames; i++) {
+		model = strstr(piModelNames[i], "-");
 
-	if (!isxdigit (*c))
-		wiringPiFailure (WPI_FATAL, "Bogus \"Revision\" line (no hex digit at start of revision)") ;
+		if (strcasestr(model, modelCodename) != NULL) {
+			libwiring.model = i;
+			break;
+		}
+	}
 
-	// Make sure its long enough
-	if (strlen (c) < 4)
-		wiringPiFailure (WPI_FATAL, "Bogus revision line (too small)") ;
+	switch (libwiring.model) {
+		case MODEL_ODROID_C1:
+			libwiring.maker = MAKER_AMLOGIC;
+			libwiring.mem = 2;
+			libwiring.rev = 1;
+			break;
+		case MODEL_ODROID_C2:
+			libwiring.maker = MAKER_AMLOGIC;
+			libwiring.mem = 3;
+			{
+				int fd = 0;
+				char buf[2];
 
-	// Isolate  last 4 characters: (in-case of overvolting or new encoding scheme)
-	c = c + strlen (c) - 4 ;
-
-	if (wiringPiDebug)
-		printf ("piGpioLayout: last4Chars are: \"%s\"\n", c) ;
-
-	if ((strcmp (c, "0002") == 0) || (strcmp (c, "0003") == 0) ||
-	    (strcmp (c, "000a") == 0) || (strcmp (c, "0100") == 0) ||
-	    (strcmp (c, "0400") == 0) )
-		gpioLayout = 1;
-	else
-		gpioLayout = 2;
-
-	if (strcmp (c, "000a") == 0) {
-		libwiring.model	= MODEL_ODROID_C1;
-		libwiring.maker	= MAKER_AMLOGIC;
-		libwiring.mem	= 2;
-		libwiring.rev	= 1;
-	} else if (strcmp (c, "0100") == 0) {
-		libwiring.model	= MODEL_ODROID_XU3;
-		libwiring.maker	= MAKER_SAMSUNG;
-		libwiring.mem	= 3;
-		libwiring.rev	= 1;
-	} else if (strncmp (c, "02", 2) == 0) {
-		libwiring.model	= MODEL_ODROID_C2;
-		libwiring.maker	= MAKER_AMLOGIC;
-		libwiring.mem	= 3;
-		{
-			int fd = 0;
-			char buf[2];
-
-			if ((fd = open ("/sys/class/odroid/boardrev", O_RDONLY)) < 0) {
-				printf ("ERROR : file not found.(boardrev)\n");
-				libwiring.rev = 1;
-			} else {
-				if (read(fd, buf, sizeof(buf)) < 0) {
-					fprintf(stderr, "Unable to read from the file descriptor: %s \n", strerror(errno));
+				if ((fd = open("/sys/class/odroid/boardrev", O_RDONLY)) < 0) {
+					printf ("ERROR : file not found.(boardrev)\n");
+					libwiring.rev = 1;
+				} else {
+					if (read(fd, buf, sizeof(buf)) < 0) {
+						fprintf(stderr, "Unable to read from the file descriptor: %s \n", strerror(errno));
+					}
+					close(fd);
+					libwiring.rev = atoi(buf) + 1;
 				}
-				close(fd);
-				libwiring.rev = atoi(buf) + 1;
 			}
-		}
-	} else if (strncmp (c, "03", 2) == 0) {
-		libwiring.model	= MODEL_ODROID_N1;
-		libwiring.maker	= MAKER_ROCKCHIP;
-		libwiring.mem	= 4;
-		libwiring.rev	= 1;
-	} else if (strncmp (c, "04", 2) == 0) {
-		libwiring.model	= MODEL_ODROID_N2;
-		libwiring.maker	= MAKER_AMLOGIC;
-		libwiring.mem	= 4;
-		libwiring.rev	= 1;
-	} else if (strncmp (c, "05", 2) == 0) {
-		libwiring.model	= MODEL_ODROID_C4;
-		libwiring.maker	= MAKER_AMLOGIC;
-		libwiring.mem	= 4;
-		libwiring.rev	= 1;
-	} else {
-		libwiring.model	= MODEL_UNKNOWN;
-		libwiring.maker	= MAKER_UNKNOWN;
-		libwiring.mem	= 0;
-		libwiring.rev	= 0;
+			break;
+		case MODEL_ODROID_XU3:
+			libwiring.maker = MAKER_SAMSUNG;
+			libwiring.mem = 3;
+			libwiring.rev = 1;
+			break;
+		case MODEL_ODROID_N1:
+			libwiring.maker = MAKER_ROCKCHIP;
+			libwiring.mem = 4;
+			libwiring.rev = 1;
+			break;
+		case MODEL_ODROID_N2:
+			libwiring.maker = MAKER_AMLOGIC;
+			libwiring.mem = 4;
+			libwiring.rev = 1;
+			break;
+		case MODEL_ODROID_C4:
+			libwiring.maker = MAKER_AMLOGIC;
+			libwiring.mem = 4;
+			libwiring.rev = 1;
+			break;
+		case MODEL_UNKNOWN:
+		default:
+			libwiring.model = MAKER_UNKNOWN;
+			libwiring.maker = MAKER_UNKNOWN;
+			libwiring.mem = 0;
+			libwiring.rev = 0;
 	}
 
 	if (wiringPiDebug)
-		printf ("BoardRev: Returning revision: %d\n", libwiring.rev) ;
+		printf("BoardRev: Returning revision: %d\n", libwiring.rev);
 
 	return libwiring.rev;
 }