Skip to content

Commit

Permalink
Merge pull request #1677 from neuschaefer/revision
Browse files Browse the repository at this point in the history
Fix Raspberry Pi model detection on mainline Linux
  • Loading branch information
hzeller authored Jul 11, 2024
2 parents 0e8ca69 + 52e2e9a commit 97607f7
Showing 1 changed file with 45 additions and 6 deletions.
51 changes: 45 additions & 6 deletions lib/gpio.cc
Original file line number Diff line number Diff line change
Expand Up @@ -244,25 +244,64 @@ static int ReadFileToBuffer(char *buffer, size_t size, const char *filename) {
return r;
}

static RaspberryPiModel DetermineRaspberryModel() {
static int ReadBinaryFileToBuffer(uint8_t *buffer, size_t size, const char *filename) {
const int fd = open(filename, O_RDONLY);
if (fd < 0) return -1;
ssize_t r = read(fd, buffer, size);
close(fd);
return r;
}

/*
* Try to read the revision from /proc/cpuinfo. In case of any errors, or if
* /proc/cpuinfo simply contains zero as the revision, this function returns
* zero. This is ok because zero was never used as a real revision code.
*/
static uint32_t ReadRevisionFromProcCpuinfo() {
char buffer[4096];
if (ReadFileToBuffer(buffer, sizeof(buffer), "/proc/cpuinfo") < 0) {
fprintf(stderr, "Reading cpuinfo: Could not determine Pi model\n");
return PI_MODEL_3; // safe guess fallback.
return 0;
}
static const char RevisionTag[] = "Revision";
const char *revision_key;
if ((revision_key = strstr(buffer, RevisionTag)) == NULL) {
fprintf(stderr, "non-existent Revision: Could not determine Pi model\n");
return PI_MODEL_3;
return 0;
}
unsigned int pi_revision;
if (sscanf(index(revision_key, ':') + 1, "%x", &pi_revision) != 1) {
fprintf(stderr, "Unknown Revision: Could not determine Pi model\n");
return PI_MODEL_3;
return 0;
}
return pi_revision;
}

// Read a 32-bit big-endian number from a 4-byte buffer.
static uint32_t read_be32(const uint8_t *p) {
return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
}

// Try to read the revision from the devicetree.
static uint32_t ReadRevisionFromDeviceTree() {
uint8_t buffer[4];
if (ReadBinaryFileToBuffer(buffer, sizeof(buffer), "/proc/device-tree/system/linux,revision") != 4) {
fprintf(stderr, "Failed to read revision from /proc/device-tree\n");
return 0;
}
return read_be32(buffer);
}

static RaspberryPiModel DetermineRaspberryModel() {
uint32_t pi_revision = ReadRevisionFromProcCpuinfo();
if (pi_revision == 0) {
pi_revision = ReadRevisionFromDeviceTree();
if (pi_revision == 0) {
fprintf(stderr, "Unknown Revision: Could not determine Pi model\n");
return PI_MODEL_3; // safe guess fallback.
}
}

// https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md
// https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#raspberry-pi-revision-codes
const unsigned pi_type = (pi_revision >> 4) & 0xff;
switch (pi_type) {
case 0x00: /* A */
Expand Down

0 comments on commit 97607f7

Please sign in to comment.