#include <string.h>
#include <hw/shared.h>
-#define CPUINFO_PATH "/proc/cpuinfo"
-#define SERIAL_TAG "Serial"
+#define DATA_BUFF_MAX 256
+
+#define SERIAL_PATH_NAME "/csa/imei/serialno.dat"
+#define CPUINFO_PATH "/proc/cpuinfo"
+#define SERIAL_TAG "Serial"
#define LINE_LEN 64
-static int get_device_serial(char **out)
+#define REVISION_TAG "Revision"
+
+struct board_info {
+ char serial[DATA_BUFF_MAX];
+ int serial_len;
+ int revision;
+};
+
+static struct board_info info;
+
+static int get_serialno_from_dat(void)
+{
+ FILE *fp;
+ char buffer[DATA_BUFF_MAX], *p, *q;
+ int serial_len;
+
+ fp = fopen(SERIAL_PATH_NAME, "r");
+ if (!fp) {
+ _E("Failed to open %s.", SERIAL_PATH_NAME);
+ return -ENOENT;
+ }
+
+ p = fgets(buffer, DATA_BUFF_MAX, fp);
+ if (!p) {
+ _E("Failed to find serial number from dat.");
+ fclose(fp);
+ return -EIO;
+ }
+ q = strchrnul(p, '\n');
+ *q = '\0';
+
+ serial_len = strlen(p);
+ strcpy(info.serial, p);
+ info.serial_len = strlen(p);
+
+ fclose(fp);
+ return 0;
+}
+
+static int get_serialno_from_cpuinfo(void)
{
FILE *fp;
char line[LINE_LEN], *p, *q;
+ int serial_len;
fp = fopen(CPUINFO_PATH, "r");
- if (!fp)
- return -1;
+ if (!fp) {
+ _E("Failed to open %s.", CPUINFO_PATH);
+ return -ENOENT;
+ }
while ((p = fgets(line, sizeof(line), fp)) != NULL) {
p = strchr(p, '\t');
continue;
*p = '\0';
-
if (strncmp(line, SERIAL_TAG, sizeof(line)) != 0)
continue;
if (!p)
continue;
p += 2;
+ q = strchrnul(p, '\n');
+ *q = '\0';
+
+ serial_len = strlen(p);
+ strncpy(info.serial, p, serial_len + 1);
+ info.serial_len = strlen(p);
+ fclose(fp);
+ return 0;
+ }
+
+ _E("Failed to find serial number from cpuinfo.");
+ fclose(fp);
+ return -EIO;
+}
+
+static int get_device_serial(char **out)
+{
+ int ret;
+ if (info.serial_len > 0 && strlen(info.serial) == info.serial_len) {
+ *out = strdup(info.serial);
+ if (!out) {
+ _E("Out of memory, strdup failed.");
+ return -ENOMEM;
+ }
+ return 0;
+ }
+
+ ret = get_serialno_from_dat();
+ if (ret < 0) {
+ ret = get_serialno_from_cpuinfo();
+ if (ret < 0) {
+ _E("Failed to find serial number.");
+ return ret;
+ }
+ }
+
+ *out = strdup(info.serial);
+ if (!out)
+ _E("Out of memory, strdup failed.");
+
+ return ret;
+}
+
+static int get_device_revision(int *out)
+{
+ FILE *fp;
+ char line[LINE_LEN], *p, *q;
+ int ret;
+
+ fp = fopen(CPUINFO_PATH, "r");
+ if (!fp) {
+ _E("Failed to open %s.", CPUINFO_PATH);
+ return -ENOENT;
+ }
+
+ while ((p = fgets(line, sizeof(line), fp)) != NULL) {
+ p = strstr(p, REVISION_TAG);
+ if (!p)
+ continue;
+
+ p = strchr(p, ':');
+ if (!p)
+ continue;
+ p += 2;
q = strchrnul(p, '\n');
*q = '\0';
- *out = strdup(p);
- if (!out)
- _E("Out of memory, strdup failed");
+
+ errno = 0;
+ ret = strtol(p, NULL, 16);
+ if (ret == 0 && errno != 0) {
+ _E("Invalid revision value.");
+ fclose(fp);
+ return -errno;
+ }
+ info.revision = ret;
+ *out = ret;
fclose(fp);
return 0;
}
+ _E("Failed to find revision from cpuinfo.");
fclose(fp);
- return -1;
+ return -EIO;
}
static int board_open(struct hw_info *info,
if (!info || !common)
return -EINVAL;
- b = calloc(1, sizeof(*b));
+ b = calloc(1, sizeof(struct hw_board));
if (!b)
return -ENOMEM;
b->common.info = info;
b->get_device_serial = get_device_serial;
+ b->get_device_revision = get_device_revision;
*common = &b->common;
return 0;