@@ -168,17 +168,131 @@ namespace Util
168168 return " Mac" ;
169169
170170#elif __linux__
171- std::string line, model_name, revision ;
171+ std::string line, model_name;
172172
173- // Try device-tree first (works for Raspberry Pi and other ARM boards)
173+ // Raspberry Pi: prefer device-tree compatible (recommended by Raspberry Pi docs)
174+ // Ref: https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#raspberry-pi-revision-codes
174175 {
175- std::ifstream inFile (" /proc/device-tree/model" );
176- if (inFile.is_open () && std::getline (inFile, line))
176+ auto normalize_rpi_model = [](const std::string &model) -> std::string
177177 {
178- // Remove null terminator if present
179- if (!line.empty () && line[line.length () - 1 ] == ' \0 ' )
180- line.resize (line.length () - 1 );
178+ // Keep it intentionally simple: map device-tree models into stable product families.
179+ if (model == " 5-model-b" )
180+ return " Raspberry Pi 5" ;
181+ if (model == " 4-model-b" )
182+ return " Raspberry Pi 4" ;
183+ if (model == " 500" )
184+ return " Raspberry Pi 500" ;
185+ if (model == " 400" )
186+ return " Raspberry Pi 400" ;
187+ if (model == " 3-model-b" || model == " 3-model-b-plus" || model == " 3-model-a-plus" )
188+ return " Raspberry Pi 3" ;
189+ if (model == " 2-model-b" )
190+ return " Raspberry Pi 2" ;
191+ // Compute Modules
192+ if (model == " compute-module" )
193+ return " Raspberry Pi Compute Module 1" ;
194+ if (model == " 3-compute-module" )
195+ return " Raspberry Pi Compute Module 3" ;
196+ if (model == " 3-plus-compute-module" )
197+ return " Raspberry Pi Compute Module 3+" ;
198+ if (model == " 4-compute-module" || model == " 4s-compute-module" )
199+ return " Raspberry Pi Compute Module 4" ;
200+ if (model == " 5-compute-module" )
201+ return " Raspberry Pi Compute Module 5" ;
202+ // Future-proofing: some distros/DTs may append qualifiers.
203+ if (model.find (" 5-compute-module" ) == 0 )
204+ {
205+ if (model.find (" lite" ) != std::string::npos)
206+ return " Raspberry Pi Compute Module 5 Lite" ;
207+ return " Raspberry Pi Compute Module 5" ;
208+ }
209+ if (model == " model-zero" || model == " model-zero-w" || model == " model-zero-2-w" )
210+ return " Raspberry Pi Zero" ;
211+ if (model == " model-a" || model == " model-a-plus" || model == " model-b" || model == " model-b-plus" ||
212+ model == " model-b-rev2" )
213+ return " Raspberry Pi 1" ;
214+ return " " ;
215+ };
216+
217+ auto parse_dt_compatible = [&](const std::string &path) -> std::string
218+ {
219+ std::ifstream inFile (path, std::ios::in | std::ios::binary);
220+ if (!inFile.is_open ())
221+ return " " ;
222+
223+ std::string token;
224+ while (std::getline (inFile, token, ' \0 ' ))
225+ {
226+ // token looks like: "raspberrypi,5-model-b" or "brcm,bcm2712"
227+ static const std::string prefix = " raspberrypi," ;
228+ if (token.compare (0 , prefix.size (), prefix) == 0 )
229+ {
230+ std::string model = token.substr (prefix.size ());
231+ std::string mapped = normalize_rpi_model (model);
232+ if (!mapped.empty ())
233+ return mapped;
234+ }
235+ }
236+ return " " ;
237+ };
238+
239+ std::string rpi = parse_dt_compatible (" /proc/device-tree/compatible" );
240+ if (rpi.empty ())
241+ rpi = parse_dt_compatible (" /sys/firmware/devicetree/base/compatible" );
242+ if (!rpi.empty ())
243+ return rpi;
244+ }
245+
246+ // Try device-tree model as a fallback (works for Raspberry Pi and other ARM boards)
247+ {
248+ auto read_model = [&](const std::string &path) -> std::string
249+ {
250+ std::ifstream inFile (path, std::ios::in | std::ios::binary);
251+ if (!inFile.is_open () || !std::getline (inFile, line, ' \0 ' ))
252+ return " " ;
253+ if (!line.empty () && line.back () == ' \0 ' )
254+ line.pop_back ();
181255 return line;
256+ };
257+
258+ std::string model = read_model (" /proc/device-tree/model" );
259+ if (model.empty ())
260+ model = read_model (" /sys/firmware/devicetree/base/model" );
261+ if (!model.empty ())
262+ {
263+ // Normalize common Raspberry Pi strings to the simple families requested.
264+ if (model.find (" Raspberry Pi 5" ) != std::string::npos)
265+ return " Raspberry Pi 5" ;
266+ if (model.find (" Raspberry Pi 500" ) != std::string::npos)
267+ return " Raspberry Pi 500" ;
268+ if (model.find (" Raspberry Pi 400" ) != std::string::npos)
269+ return " Raspberry Pi 400" ;
270+ if (model.find (" Raspberry Pi 4" ) != std::string::npos)
271+ return " Raspberry Pi 4" ;
272+ if (model.find (" Raspberry Pi 3" ) != std::string::npos)
273+ return " Raspberry Pi 3" ;
274+ if (model.find (" Raspberry Pi 2" ) != std::string::npos)
275+ return " Raspberry Pi 2" ;
276+ if (model.find (" Compute Module 5" ) != std::string::npos)
277+ {
278+ if (model.find (" Lite" ) != std::string::npos || model.find (" lite" ) != std::string::npos)
279+ return " Raspberry Pi Compute Module 5 Lite" ;
280+ return " Raspberry Pi Compute Module 5" ;
281+ }
282+ if (model.find (" Compute Module 4" ) != std::string::npos)
283+ return " Raspberry Pi Compute Module 4" ;
284+ if (model.find (" Compute Module 3+" ) != std::string::npos)
285+ return " Raspberry Pi Compute Module 3+" ;
286+ if (model.find (" Compute Module 3" ) != std::string::npos)
287+ return " Raspberry Pi Compute Module 3" ;
288+ if (model.find (" Compute Module" ) != std::string::npos)
289+ return " Raspberry Pi Compute Module 1" ;
290+ if (model.find (" Raspberry Pi Zero" ) != std::string::npos)
291+ return " Raspberry Pi Zero" ;
292+ if (model.find (" Raspberry Pi Model" ) != std::string::npos)
293+ return " Raspberry Pi 1" ;
294+
295+ return model;
182296 }
183297 }
184298
@@ -208,7 +322,7 @@ namespace Util
208322 }
209323 }
210324
211- // Parse cpuinfo for Raspberry Pi revision codes and CPU model
325+ // Parse cpuinfo for CPU model name (best-effort fallback)
212326 {
213327 std::ifstream inFile (" /proc/cpuinfo" );
214328 if (inFile.is_open ())
@@ -219,79 +333,12 @@ namespace Util
219333 {
220334 std::size_t pos = line.find (" : " );
221335 if (pos != std::string::npos)
222- {
223336 model_name = line.substr (pos + 2 );
224- }
225- }
226- else if (line.substr (0 , 8 ) == " Revision" )
227- {
228- std::size_t pos = line.find (" : " );
229- if (pos != std::string::npos)
230- {
231- revision = line.substr (pos + 2 );
232- }
233337 }
234338 }
235339 }
236340 }
237341
238- // Raspberry Pi revision lookup table
239- if (!revision.empty ())
240- {
241- static const std::unordered_map<std::string, std::string> rpi_revisions = {
242- {" 900021" , " Raspberry Pi A+ 1.1" },
243- {" 900032" , " Raspberry Pi B+ 1.2" },
244- {" 900092" , " Raspberry Pi Zero 1.2" },
245- {" 900093" , " Raspberry Pi Zero 1.3" },
246- {" 9000c1" , " Raspberry Pi Zero W 1.1" },
247- {" 9020e0" , " Raspberry Pi 3A+ 1.0" },
248- {" 920092" , " Raspberry Pi Zero 1.2" },
249- {" 920093" , " Raspberry Pi Zero 1.3" },
250- {" 900061" , " Raspberry Pi CM1 1.1" },
251- {" a01040" , " Raspberry Pi 2B 1.0" },
252- {" a01041" , " Raspberry Pi 2B 1.1" },
253- {" a02082" , " Raspberry Pi 3B 1.2" },
254- {" a020a0" , " Raspberry Pi CM3 1.0" },
255- {" a020d3" , " Raspberry Pi 3B+ 1.3" },
256- {" a02042" , " Raspberry Pi 2B (with BCM2837) 1.2" },
257- {" a21041" , " Raspberry Pi 2B 1.1" },
258- {" a22042" , " Raspberry Pi 2B (with BCM2837) 1.2" },
259- {" a22082" , " Raspberry Pi 3B 1.2" },
260- {" a220a0" , " Raspberry Pi CM3 1.0" },
261- {" a32082" , " Raspberry Pi 3B 1.2" },
262- {" a52082" , " Raspberry Pi 3B 1.2" },
263- {" a22083" , " Raspberry Pi 3B 1.3" },
264- {" a02100" , " Raspberry Pi CM3+ 1.0" },
265- {" a03111" , " Raspberry Pi 4B 1.1" },
266- {" b03111" , " Raspberry Pi 4B 1.1" },
267- {" b03112" , " Raspberry Pi 4B 1.2" },
268- {" b03114" , " Raspberry Pi 4B 1.4" },
269- {" b03115" , " Raspberry Pi 4B 1.5" },
270- {" c03111" , " Raspberry Pi 4B 1.1" },
271- {" c03112" , " Raspberry Pi 4B 1.2" },
272- {" c03114" , " Raspberry Pi 4B 1.4" },
273- {" c03115" , " Raspberry Pi 4B 1.5" },
274- {" d03114" , " Raspberry Pi 4B 1.4" },
275- {" d03115" , " Raspberry Pi 4B 1.5" },
276- {" c03130" , " Raspberry Pi 400 1.0" },
277- {" a03140" , " Raspberry Pi CM4 1.0" },
278- {" b03140" , " Raspberry Pi CM4 1.0" },
279- {" c03140" , " Raspberry Pi CM4 1.0" },
280- {" d03140" , " Raspberry Pi CM4 1.0" },
281- {" 902120" , " Raspberry Pi Zero 2 W 1.0" },
282- {" c04170" , " Raspberry Pi 5 8GB" },
283- {" d04170" , " Raspberry Pi 5 4GB" },
284- {" c04171" , " Raspberry Pi 5 8GB" },
285- {" d04171" , " Raspberry Pi 5 4GB" },
286- {" 902121" , " Raspberry Pi Zero 2 W 1.0" }};
287-
288- std::unordered_map<std::string, std::string>::const_iterator it = rpi_revisions.find (revision);
289- if (it != rpi_revisions.end ())
290- {
291- return it->second ;
292- }
293- }
294-
295342 // Return CPU model name if available
296343 if (!model_name.empty ())
297344 return model_name;
0 commit comments