-
Notifications
You must be signed in to change notification settings - Fork 0
/
rpi.c
155 lines (141 loc) · 3.65 KB
/
rpi.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include "rpi.h"
/* Returns the revision of the board.
*
* Returns:
* >=0: Verion of the board.
* <0: Error code.
*
* Errors:
* -2: Could not open '/proc/cpuinfo'.
* -3: Reading file failed.
* -4: Unknown hardware. */
int getPiBoardRev ()
{
const char* dataFileName = "/proc/cpuinfo";
const char* keyHardware = "Hardware";
const char* keyRevision = "Revision";
const char* supportedHardware[] = {"BCM2708", "BCM2709"};
const char* oldRevisions[] = {"0002", "0003"};
/* If we already have the revision, no need to check again. */
static int boardRev = -1 ;
if (boardRev > -1)
return boardRev ;
FILE* file = NULL;
char fileSeg[1024], *fileSegEnd = fileSeg + sizeof(fileSeg);
size_t readCount = 0;
char* hardwareStr = NULL;
char* dataEnd = NULL;
if ((file = fopen (dataFileName, "r")) == NULL)
{
boardRev = -2;
goto f_return;
}
/* Search the file for 'keyHardware'. */
while(!feof(file) && (readCount = fread(fileSeg, 1, sizeof(fileSeg), file)))
{
char* it = fileSeg;
for(;it < fileSegEnd; ++it)
{
if(*it == *keyHardware)
{
memmove(fileSeg, it, fileSegEnd - it);
readCount = fileSegEnd - it;
memset(fileSeg + readCount, 0, sizeof(fileSeg) - readCount);
if(!feof(file))
readCount += fread(fileSeg + (fileSegEnd - it), 1, sizeof(fileSeg) - readCount, file);
if(readCount > sizeof(keyHardware))
{
if(strncmp(fileSeg, keyHardware, sizeof(keyHardware) - 1) == 0)
{
it = fileSeg;
/* Find the colon. */
while(it < fileSegEnd && *it != ':' && *it != '\n')
++it;
while(it < fileSegEnd && !isalnum(*it) && *it != '\n')
++it;
if(it < fileSegEnd && *it != '\n')
{
hardwareStr = it;
break;
}
}
}
}
}
if(it < fileSegEnd)
break;
}
if(readCount == 0)
{
boardRev = -3;
goto f_return;
}
/* Check the hardware versions and make sure we support them. */
if(strncmp(hardwareStr, supportedHardware[1], sizeof( supportedHardware[1]) - 1) == 0)
{
/* This is RaspberryPi 2, we know that it uses revision 2. */
boardRev = 2;
goto f_return;
}
if(strncmp(hardwareStr, supportedHardware[0], sizeof(supportedHardware[0]) - 1) != 0)
{
boardRev = -4;
goto f_return;
}
/* Search for the revision keywords. */
rewind(file);
while(!feof(file) && (readCount = fread(fileSeg, 1, sizeof(fileSeg), file)))
{
char* it = fileSeg;
for(;it < fileSegEnd; ++it)
{
if(*it == *keyRevision)
{
memmove(fileSeg, it, fileSegEnd - it);
readCount = fileSegEnd - it;
memset(fileSeg + readCount, 0, sizeof(fileSeg) - readCount);
if(!feof(file))
readCount += fread(fileSeg + (fileSegEnd - it), 1, sizeof(fileSeg) - readCount, file);
if(readCount > sizeof(keyRevision))
{
if(strncmp(fileSeg, keyRevision, sizeof(keyRevision) - 1) == 0)
{
it = fileSeg;
/* Find the colon. */
while(it < fileSegEnd && *it != ':' && *it != '\n')
++it;
while(it < fileSegEnd && !isalnum(*it) && *it != '\n')
++it;
if(it < fileSegEnd && *it != '\n')
{
hardwareStr = it;
break;
}
}
}
}
}
if(it < fileSegEnd)
break;
}
if(readCount == 0)
{
boardRev = -3;
goto f_return;
}
/* Read to the end of the data. */
dataEnd = hardwareStr;
while(dataEnd > fileSegEnd && isxdigit(*dataEnd))
++dataEnd;
hardwareStr = dataEnd - 4;
if(strncmp(hardwareStr, oldRevisions[0], sizeof(oldRevisions[0]) - 1) == 0 ||
strncmp(hardwareStr, oldRevisions[1], sizeof(oldRevisions[1]) - 1) == 0)
boardRev = 1;
else
boardRev = 2;
f_return:
/* Cleanup. */
if(file)
fclose(file);
return(boardRev);
}