File Coverage

blib/lib/HiPi/RaspberryPi.pm
Criterion Covered Total %
statement 46 144 31.9
branch 17 74 22.9
condition 1 20 5.0
subroutine 8 31 25.8
pod 0 27 0.0
total 72 296 24.3


line stmt bran cond sub pod time code
1             ###############################################################################
2             # Distribution : HiPi Modules for Raspberry Pi
3             # File : lib/HiPi/RaspberryPi.pm
4             # Description : Information about host Raspberry Pi
5             # Copyright : Copyright (c) 2013-2019 Mark Dootson
6             # License : This is free software; you can redistribute it and/or modify it under
7             # the same terms as the Perl 5 programming language system itself.
8             #########################################################################################
9              
10             package HiPi::RaspberryPi;
11              
12             ###############################################################################
13 5     5   33 use strict;
  5         12  
  5         139  
14 5     5   22 use warnings;
  5         11  
  5         121  
15 5     5   27 use Carp;
  5         13  
  5         16752  
16              
17             our $VERSION ='0.81';
18              
19             my ( $btype1, $btype2, $btype3, $btype4) = ( 1, 2, 3, 4 );
20              
21             my $israspberry = 0;
22             my $israspberry2 = 0;
23             my $israspberry3 = 0;
24             my $israspberry4 = 0;
25             my $hasdevicetree = 0;
26             my $homedir = '/tmp';
27              
28             my $_min_gpio = 0;
29             my $_max_gpio = 53;
30              
31             my @_alt_func_names_2708 =
32             (
33             [ 'SDA0' , 'SA5' , 'PCLK' , 'AVEOUT_VCLK' , 'AVEIN_VCLK' , '-' ],
34             [ 'SCL0' , 'SA4' , 'DE' , 'AVEOUT_DSYNC' , 'AVEIN_DSYNC', '-' ],
35             [ 'SDA1' , 'SA3' , 'LCD_VSYNC' , 'AVEOUT_VSYNC' , 'AVEIN_VSYNC', '-' ],
36             [ 'SCL1' , 'SA2' , 'LCD_HSYNC' , 'AVEOUT_HSYNC' , 'AVEIN_HSYNC', '-' ],
37             [ 'GPCLK0' , 'SA1' , 'DPI_D0' , 'AVEOUT_VID0' , 'AVEIN_VID0' , 'ARM_TDI' ],
38             [ 'GPCLK1' , 'SA0' , 'DPI_D1' , 'AVEOUT_VID1' , 'AVEIN_VID1' , 'ARM_TDO' ],
39             [ 'GPCLK2' , 'SOE_N_SE' , 'DPI_D2' , 'AVEOUT_VID2' , 'AVEIN_VID2' , 'ARM_RTCK' ],
40             [ 'SPI0_CE1_N', 'SWE_N_SRW_N', 'DPI_D3' , 'AVEOUT_VID3' , 'AVEIN_VID3' , '-' ],
41             [ 'SPI0_CE0_N', 'SD0' , 'DPI_D4' , 'AVEOUT_VID4' , 'AVEIN_VID4' , '-' ],
42             [ 'SPI0_MISO' , 'SD1' , 'DPI_D5' , 'AVEOUT_VID5' , 'AVEIN_VID5' , '-' ],
43             [ 'SPI0_MOSI' , 'SD2' , 'DPI_D6' , 'AVEOUT_VID6' , 'AVEIN_VID6' , '-' ],
44             [ 'SPI0_SCLK' , 'SD3' , 'DPI_D7' , 'AVEOUT_VID7' , 'AVEIN_VID7' , '-' ],
45             [ 'PWM0' , 'SD4' , 'DPI_D8' , 'AVEOUT_VID8' , 'AVEIN_VID8' , 'ARM_TMS' ],
46             [ 'PWM1' , 'SD5' , 'DPI_D9' , 'AVEOUT_VID9' , 'AVEIN_VID9' , 'ARM_TCK' ],
47             [ 'TXD0' , 'SD6' , 'DPI_D10' , 'AVEOUT_VID10' , 'AVEIN_VID10', 'TXD1' ],
48             [ 'RXD0' , 'SD7' , 'DPI_D11' , 'AVEOUT_VID11' , 'AVEIN_VID11', 'RXD1' ],
49             [ 'FL0' , 'SD8' , 'DPI_D12' , 'CTS0' , 'SPI1_CE2_N' , 'CTS1' ],
50             [ 'FL1' , 'SD9' , 'DPI_D13' , 'RTS0' , 'SPI1_CE1_N' , 'RTS1' ],
51             [ 'PCM_CLK' , 'SD10' , 'DPI_D14' , 'I2CSL_SDA_MOSI', 'SPI1_CE0_N' , 'PWM0' ],
52             [ 'PCM_FS' , 'SD11' , 'DPI_D15' , 'I2CSL_SCL_SCLK', 'SPI1_MISO' , 'PWM1' ],
53             [ 'PCM_DIN' , 'SD12' , 'DPI_D16' , 'I2CSL_MISO' , 'SPI1_MOSI' , 'GPCLK0' ],
54             [ 'PCM_DOUT' , 'SD13' , 'DPI_D17' , 'I2CSL_CE_N' , 'SPI1_SCLK' , 'GPCLK1' ],
55             [ 'SD0_CLK' , 'SD14' , 'DPI_D18' , 'SD1_CLK' , 'ARM_TRST' , '-' ],
56             [ 'SD0_CMD' , 'SD15' , 'DPI_D19' , 'SD1_CMD' , 'ARM_RTCK' , '-' ],
57             [ 'SD0_DAT0' , 'SD16' , 'DPI_D20' , 'SD1_DAT0' , 'ARM_TDO' , '-' ],
58             [ 'SD0_DAT1' , 'SD17' , 'DPI_D21' , 'SD1_DAT1' , 'ARM_TCK' , '-' ],
59             [ 'SD0_DAT2' , 'TE0' , 'DPI_D22' , 'SD1_DAT2' , 'ARM_TDI' , '-' ],
60             [ 'SD0_DAT3' , 'TE1' , 'DPI_D23' , 'SD1_DAT3' , 'ARM_TMS' , '-' ],
61             [ 'SDA0' , 'SA5' , 'PCM_CLK' , 'FL0' , '-' , '-' ],
62             [ 'SCL0' , 'SA4' , 'PCM_FS' , 'FL1' , '-' , '-' ],
63             [ 'TE0' , 'SA3' , 'PCM_DIN' , 'CTS0' , '-' , 'CTS1' ],
64             [ 'FL0' , 'SA2' , 'PCM_DOUT' , 'RTS0' , '-' , 'RTS1' ],
65             [ 'GPCLK0' , 'SA1' , 'RING_OCLK' , 'TXD0' , '-' , 'TXD1' ],
66             [ 'FL1' , 'SA0' , 'TE1' , 'RXD0' , '-' , 'RXD1' ],
67             [ 'GPCLK0' , 'SOE_N_SE' , 'TE2' , 'SD1_CLK' , '-' , '-' ],
68             [ 'SPI0_CE1_N', 'SWE_N_SRW_N', '-' , 'SD1_CMD' , '-' , '-' ],
69             [ 'SPI0_CE0_N', 'SD0' , 'TXD0' , 'SD1_DAT0' , '-' , '-' ],
70             [ 'SPI0_MISO' , 'SD1' , 'RXD0' , 'SD1_DAT1' , '-' , '-' ],
71             [ 'SPI0_MOSI' , 'SD2' , 'RTS0' , 'SD1_DAT2' , '-' , '-' ],
72             [ 'SPI0_SCLK' , 'SD3' , 'CTS0' , 'SD1_DAT3' , '-' , '-' ],
73             [ 'PWM0' , 'SD4' , '-' , 'SD1_DAT4' , 'SPI2_MISO' , 'TXD1' ],
74             [ 'PWM1' , 'SD5' , 'TE0' , 'SD1_DAT5' , 'SPI2_MOSI' , 'RXD1' ],
75             [ 'GPCLK1' , 'SD6' , 'TE1' , 'SD1_DAT6' , 'SPI2_SCLK' , 'RTS1' ],
76             [ 'GPCLK2' , 'SD7' , 'TE2' , 'SD1_DAT7' , 'SPI2_CE0_N' , 'CTS1' ],
77             [ 'GPCLK1' , 'SDA0' , 'SDA1' , 'TE0' , 'SPI2_CE1_N' , '-' ],
78             [ 'PWM1' , 'SCL0' , 'SCL1' , 'TE1' , 'SPI2_CE2_N' , '-' ],
79             [ 'SDA0' , 'SDA1' , 'SPI0_CE0_N', '-' , '-' , 'SPI2_CE1_N'],
80             [ 'SCL0' , 'SCL1' , 'SPI0_MISO' , '-' , '-' , 'SPI2_CE0_N'],
81             [ 'SD0_CLK' , 'FL0' , 'SPI0_MOSI' , 'SD1_CLK' , 'ARM_TRST' , 'SPI2_SCLK' ],
82             [ 'SD0_CMD' , 'GPCLK0' , 'SPI0_SCLK' , 'SD1_CMD' , 'ARM_RTCK' , 'SPI2_MOSI' ],
83             [ 'SD0_DAT0' , 'GPCLK1' , 'PCM_CLK' , 'SD1_DAT0' , 'ARM_TDO' , '-' ],
84             [ 'SD0_DAT1' , 'GPCLK2' , 'PCM_FS' , 'SD1_DAT1' , 'ARM_TCK' , '-' ],
85             [ 'SD0_DAT2' , 'PWM0' , 'PCM_DIN' , 'SD1_DAT2' , 'ARM_TDI' , '-' ],
86             [ 'SD0_DAT3' , 'PWM1' , 'PCM_DOUT' , 'SD1_DAT3' , 'ARM_TMS' , '-' ],
87             );
88              
89             my @_alt_func_names_2711 =
90             (
91             # BANK 0
92             [ 'SDA0' , 'SA5' , 'PCLK' , 'SPI3_CE0_N' , 'TXD2' , 'SDA6' ], # 0
93             [ 'SCL0' , 'SA4' , 'DE' , 'SPI3_MISO' , 'RXD2' , 'SCL6' ], # 1
94             [ 'SDA1' , 'SA3' , 'LCD_VSYNC' , 'SPI3_MOSI' , 'CTS2' , 'SDA3' ], # 2
95             [ 'SCL1' , 'SA2' , 'LCD_HSYNC' , 'SPI3_SCLK' , 'RTS2' , 'SCL3' ], # 3
96             [ 'GPCLK0' , 'SA1' , 'DPI_D0' , 'SPI4_CE0_N' , 'TXD3' , 'SDA3' ], # 4
97             [ 'GPCLK1' , 'SA0' , 'DPI_D1' , 'SPI4_MISO' , 'RXD3' , 'SCL3' ], # 5
98             [ 'GPCLK2' , 'SOE_N_SE' , 'DPI_D2' , 'SPI4_MOSI' , 'CTS3' , 'SDA4' ], # 6
99             [ 'SPI0_CE1_N' , 'SWE_N_SRW_N' , 'DPI_D3' , 'SPI4_SCLK' , 'RTS3' , 'SCL4' ], # 7
100             [ 'SPI0_CE0_N' , 'SD0' , 'DPI_D4' , 'I2CSL_CE_N' , 'TXD4' , 'SDA4' ], # 8
101             [ 'SPI0_MISO' , 'SD1' , 'DPI_D5' , 'I2CSL_SDI_MISO' , 'RXD4' , 'SCL4' ], # 9
102             [ 'SPI0_MOSI' , 'SD2' , 'DPI_D6' , 'I2CSL_SDA_MOSI' , 'CTS4' , 'SDA5' ], # 10
103             [ 'SPI0_SCLK' , 'SD3' , 'DPI_D7' , 'I2CSL_SCL_SCLK' , 'RTS4' , 'SCL5' ], # 11
104             [ 'PWM0_0' , 'SD4' , 'DPI_D8' , 'SPI5_CE0_N' , 'TXD5' , 'SDA5' ], # 12
105             [ 'PWM0_1' , 'SD5' , 'DPI_D9' , 'SPI5_MISO' , 'RXD5' , 'SCL5' ], # 13
106             [ 'TXD0' , 'SD6' , 'DPI_D10' , 'SPI5_MOSI' , 'CTS5' , 'TXD1' ], # 14
107             [ 'RXD0' , 'SD7' , 'DPI_D11' , 'SPI5_SCLK' , 'RTS5' , 'RXD1' ], # 15
108             [ '-' , 'SD8' , 'DPI_D12' , 'CTS0' , 'SPI1_CE2_N' , 'CTS1' ], # 16
109             [ '-' , 'SD9' , 'DPI_D13' , 'RTS0' , 'SPI1_CE1_N' , 'RTS1' ], # 17
110             [ 'PCM_CLK' , 'SD10' , 'DPI_D14' , 'SPI6_CE0_N' , 'SPI1_CE0_N' , 'PWM0_0' ], # 18
111             [ 'PCM_FS' , 'SD11' , 'DPI_D15' , 'SPI6_MISO' , 'SPI1_MISO' , 'PWM0_1' ], # 19
112             [ 'PCM_DIN' , 'SD12' , 'DPI_D16' , 'SPI6_MOSI' , 'SPI1_MOSI' , 'GPCLK0' ], # 20
113             [ 'PCM_DOUT' , 'SD13' , 'DPI_D17' , 'SPI6_SCLK' , 'SPI1_SCLK' , 'GPCLK1' ], # 21
114             [ 'SD0_CLK' , 'SD14' , 'DPI_D18' , 'SD1_CLK' , 'ARM_TRST' , 'SDA6' ], # 22
115             [ 'SD0_CMD' , 'SD15' , 'DPI_D19' , 'SD1_CMD' , 'ARM_RTCK' , 'SCL6' ], # 23
116             [ 'SD0_DAT0' , 'SD16' , 'DPI_D20' , 'SD1_DAT0' , 'ARM_TDO' , 'SPI3_CE1_N' ], # 24
117             [ 'SD0_DAT1' , 'SD17' , 'DPI_D21' , 'SD1_DAT1' , 'ARM_TCK' , 'SPI4_CE1_N' ], # 25
118             [ 'SD0_DAT2' , '-' , 'DPI_D22' , 'SD1_DAT2' , 'ARM_TDI' , 'SPI5_CE1_N' ], # 26
119             [ 'SD0_DAT3' , '-' , 'DPI_D23' , 'SD1_DAT3' , 'ARM_TMS' , 'SPI6_CE1_N' ], # 27
120            
121             # BANK 1
122             [ 'SDA0' , 'SA5' , 'PCM_CLK' , '-' , 'MII_A_RX_ERR' , 'RGMII_MDIO' ], # 28
123             [ 'SCL0' , 'SA4' , 'PCM_FS' , '-' , 'MII_A_TX_ERR' , 'RGMII_MDC' ], # 29
124             [ '-' , 'SA3' , 'PCM_DIN' , 'CTS0' , 'MII_A_CRS' , 'CTS1' ], # 30
125             [ '-' , 'SA2' , 'PCM_DOUT' , 'RTS0' , 'MII_A_COL' , 'RTS1' ], # 31
126             [ 'GPCLK0' , 'SA1' , '-' , 'TXD0' , 'SD_CARD_PRES' , 'TXD1' ], # 32
127             [ '-' , 'SA0' , '-' , 'RXD0' , 'SD_CARD_WRPROT' , 'RXD1' ], # 33
128             [ 'GPCLK0' , 'SOE_N_SE' , '-' , 'SD1_CLK' , 'SD_CARD_LED' , 'RGMII_IRQ' ], # 34
129             [ 'SPI0_CE1_N' , 'SWE_N_SRW_N' , '-' , 'SD1_CMD' , 'RGMII_START_STOP', '-' ], # 35
130             [ 'SPI0_CE0_N' , 'SD0' , 'TXD0' , 'SD1_DAT0' , 'RGMII_RX_OK' , 'MII_A_RX_ERR' ], # 36
131             [ 'SPI0_MISO' , 'SD1' , 'RXD0' , 'SD1_DAT1' , 'RGMII_MDIO' , 'MII_A_TX_ERR' ], # 37
132             [ 'SPI0_MOSI' , 'SD2' , 'RTS0' , 'SD1_DAT2' , 'RGMII_MDC' , 'MII_A_CRS' ], # 38
133             [ 'SPI0_SCLK' , 'SD3' , 'CTS0' , 'SD1_DAT3' , 'RGMII_IRQ' , 'MII_A_COL' ], # 39
134             [ 'PWM1_0' , 'SD4' , '-' , 'SD1_DAT4' , 'SPI0_MISO' , 'TXD1' ], # 40
135             [ 'PWM1_1' , 'SD5' , '-' , 'SD1_DAT5' , 'SPI0_MOSI' , 'RXD1' ], # 41
136             [ 'GPCLK1' , 'SD6' , '-' , 'SD1_DAT6' , 'SPI0_SCLK' , 'RTS1' ], # 42
137             [ 'GPCLK2' , 'SD7' , '-' , 'SD1_DAT7' , 'SPI0_CE0_N' , 'CTS1' ], # 43
138             [ 'GPCLK1' , 'SDA0' , 'SDA1' , '-' , 'SPI0_CE1_N' , 'SD_CARD_VOLT' ], # 44
139             [ 'PWM0_1' , 'SCL0' , 'SCL1' , '-' , 'SPI0_CE2_N' , 'SD_CARD_PWR0' ], # 45
140            
141             # BANK 2
142             [ 'SDA0' , 'SDA1' , 'SPI0_CE0_N' , '-' , '-' , 'SPI2_CE1_N' ], # 46
143             [ 'SCL0' , 'SCL1' , 'SPI0_MISO' , '-' , '-' , 'SPI2_CE0_N' ], # 47
144             [ 'SD0_CLK' , '-' , 'SPI0_MOSI' , 'SD1_CLK' , 'ARM_TRST' , 'SPI2_SCLK' ], # 48
145             [ 'SD0_CMD' , 'GPCLK0' , 'SPI0_SCLK' , 'SD1_CMD' , 'ARM_RTCK' , 'SPI2_MOSI' ], # 49
146             [ 'SD0_DAT0' , 'GPCLK1' , 'PCM_CLK' , 'SD1_DAT0' , 'ARM_TDO' , 'SPI2_MISO' ], # 50
147             [ 'SD0_DAT1' , 'GPCLK2' , 'PCM_FS' , 'SD1_DAT1' , 'ARM_TCK' , 'SD_CARD_LED' ], # 51
148             [ 'SD0_DAT2' , 'PWM0_0' , 'PCM_DIN' , 'SD1_DAT2' , 'ARM_TDI' , '-' ], # 52
149             [ 'SD0_DAT3' , 'PWM0_1' , 'PCM_DOUT' , 'SD1_DAT3' , 'ARM_TMS' , '-' ], # 53
150             );
151              
152             my $_alt_function_names;
153             my $_alt_function_names_version;
154              
155             my %_revstash = (
156             'beta' => { release => 'Q1 2012', model_name => 'Raspberry Pi Model B Revision beta', revision => 'beta', board_type => $btype1, memory => 256, manufacturer => 'Generic' },
157             '0002' => { release => 'Q1 2012', model_name => 'Raspberry Pi Model B Revision 1.0', revision => '0002', board_type => $btype1, memory => 256, manufacturer => 'Generic' },
158             '0003' => { release => 'Q3 2012', model_name => 'Raspberry Pi Model B Revision 1.0', revision => '0003', board_type => $btype1, memory => 256, manufacturer => 'Generic' },
159             '0004' => { release => 'Q3 2012', model_name => 'Raspberry Pi Model B Revision 2.0', revision => '0004', board_type => $btype2, memory => 256, manufacturer => 'Sony' },
160             '0005' => { release => 'Q4 2012', model_name => 'Raspberry Pi Model B Revision 2.0', revision => '0005', board_type => $btype2, memory => 256, manufacturer => 'Qisda' },
161             '0006' => { release => 'Q4 2012', model_name => 'Raspberry Pi Model B Revision 2.0', revision => '0006', board_type => $btype2, memory => 256, manufacturer => 'Egoman' },
162             '0007' => { release => 'Q1 2013', model_name => 'Raspberry Pi Model A', revision => '0007', board_type => $btype2, memory => 256, manufacturer => 'Egoman' },
163             '0008' => { release => 'Q1 2013', model_name => 'Raspberry Pi Model A', revision => '0008', board_type => $btype2, memory => 256, manufacturer => 'Sony' },
164             '0009' => { release => 'Q1 2013', model_name => 'Raspberry Pi Model A', revision => '0009', board_type => $btype2, memory => 256, manufacturer => 'Qisda' },
165            
166             '000d' => { release => 'Q4 2012', model_name => 'Raspberry Pi Model B Revision 2.0', revision => '000d', board_type => $btype2, memory => 512, manufacturer => 'Egoman' },
167             '000e' => { release => 'Q4 2012', model_name => 'Raspberry Pi Model B Revision 2.0', revision => '000e', board_type => $btype2, memory => 512, manufacturer => 'Sony' },
168             '000f' => { release => 'Q4 2012', model_name => 'Raspberry Pi Model B Revision 2.0', revision => '000f', board_type => $btype2, memory => 512, manufacturer => 'Qisda' },
169            
170             '0010' => { release => 'Q3 2014', model_name => 'Raspberry Pi Model B +', revision => '0010', board_type => $btype3, memory => 512, manufacturer => 'Sony' },
171             '0011' => { release => 'Q2 2013', model_name => 'Compute Module', revision => '0011', board_type => $btype2, memory => 512, manufacturer => 'Sony' },
172             '0012' => { release => 'Q4 2014', model_name => 'Raspberry Pi Model A +', revision => '0012', board_type => $btype3, memory => 256, manufacturer => 'Sony' },
173            
174             '0014' => { release => 'Q2 2015', model_name => 'Compute Module', revision => '0014', board_type => $btype2, memory => 512, manufacturer => 'Sony' },
175             '0015' => { release => 'Q4 2015', model_name => 'Raspberry Pi Model A +', revision => '0015', board_type => $btype3, memory => 512, manufacturer => 'Sony' },
176             'unknown' => { release => 'Q1 2012', model_name => 'Virtual or Unknown Raspberry Pi', revision => 'UNKNOWN', board_type => $btype2, memory => 512, manufacturer => 'HiPi Virtual' },
177             'unknownex' => { release => 'Q1 2012', model_name => 'Virtual or Unknown Raspberry Pi', revision => 'UNKNOWN', board_type => $btype3, memory => 1024, manufacturer => 'HiPi Virtual' },
178             );
179              
180             # MAP 24 bits of Revision NEW:1, MEMSIZE:3, MANUFACTURER:4, PROCESSOR:4, MODEL:8, BOARD REVISION:4
181              
182             my %_revinfostash = (
183             memsize => {
184             '0' => 256,
185             '1' => 512,
186             '2' => 1024,
187             '3' => 2048,
188             '4' => 4096,
189             '5' => 8192,
190             },
191             manufacturer => {
192             '0' => 'Sony UK',
193             '1' => 'Egoman',
194             '2' => 'Embest',
195             '3' => 'Sony Japan',
196             '4' => 'Embest',
197             '5' => 'Stadium',
198             },
199            
200             processor => {
201             '0' => 'BCM2835',
202             '1' => 'BCM2836',
203             '2' => 'BCM2837',
204             '3' => 'BCM2711',
205             },
206            
207             type => {
208             '0' => 'Raspberry Pi Model A', # 00
209             '1' => 'Raspberry Pi Model B', # 01
210             '2' => 'Raspberry Pi Model A Plus', # 02
211             '3' => 'Raspberry Pi Model B Plus', # 03
212             '4' => 'Raspberry Pi 2 Model B', # 04
213             '5' => 'Raspberry Pi Alpha', # 05
214             '6' => 'Raspberry Pi Compute Module 1', # 06
215             '7' => 'Raspberry Pi Unknown Model 07', # 07
216             '8' => 'Raspberry Pi 3 Model B', # 08
217             '9' => 'Raspberry Pi Zero', # 09
218             '10' => 'Raspberry Pi Compute Module 3', # 0A
219             '11' => 'UNKNOWN Rasberry Pi Model 11', # 0B
220             '12' => 'Raspberry Pi Zero W', # 0C
221             '13' => 'Raspberry Pi 3 Model B Plus', # 0D
222             '14' => 'Raspberry Pi 3 Model A Plus', # 0E
223             '15' => 'UNKNOWN Rasberry Pi Model 15', # 0F
224             '16' => 'Raspberry Pi Compute Module 3 Plus', # 10
225             '17' => 'Raspberry Pi 4 Model B', # 11
226             },
227             board_type => {
228             '0' => $btype2,
229             '1' => $btype2,
230             '2' => $btype3,
231             '3' => $btype3,
232             '4' => $btype3,
233             '5' => $btype1,
234             '6' => $btype2,
235             '7' => $btype3,
236             '8' => $btype3,
237             '9' => $btype3,
238             '10' => $btype4,
239             '11' => $btype3,
240             '12' => $btype3,
241             '13' => $btype3,
242             '14' => $btype3,
243             '15' => $btype3,
244             '16' => $btype4,
245             '17' => $btype3,
246             },
247             release => {
248             '0' => 'Q1 2013',
249             '1' => 'Q3 2012',
250             '2' => 'Q4 2014',
251             '3' => 'Q3 2014',
252             '4' => 'Q1 2015',
253             '5' => 'Q1 2012',
254             '6' => 'Q2 2013',
255             '7' => 'Q2 2015',
256             '8' => 'Q1 2016',
257             '9' => 'Q4 2015',
258             '10' => 'Q1 2017',
259             '11' => 'unknown',
260             '12' => 'Q1 2017',
261             '13' => 'Q1 2018',
262             '14' => 'Q4 2018',
263             '15' => 'unknown',
264             '16' => 'Q1 2019',
265             '17' => 'Q2 2019',
266             },
267             extended_release => {
268             'a03111' => 'Q2 2019', # 4B 1.1 1GB Sony UK
269             'b03111' => 'Q2 2019', # 4B 1.1 2GB Sony UK
270             'b03112' => 'Q1 2020', # 4B 1.2 2GB Sony UK
271             'c03111' => 'Q2 2019', # 4B 1.1 4GB Sony UK
272             'c03112' => 'Q1 2020', # 4B 1.2 4GB Sony UK
273             'd03114' => 'Q2 2020', # 4B 1.4 8GB Sony UK
274             },
275             );
276              
277             my $_config = $_revstash{unknownex};
278              
279 5 50   5 0 85 sub os_is_windows { return ( $^O =~ /^mswin/i ) ? 1 : 0; }
280              
281 0 0   0 0 0 sub os_is_osx { return ( $^O =~ /^darwen/i ) ? 1 : 0; }
282              
283 5 50   5 0 70 sub os_is_linux { return ( $^O =~ /^linux/i ) ? 1 : 0; }
284              
285 0 0   0 0 0 sub os_is_other { return ( $^O !~ /^mswin|linux|darwen/i ) ? 1 : 0; }
286              
287 0 0   0 0 0 sub os_supported { return ( $^O =~ /^linux/i ) ? 1 : 0; }
288              
289 7     7 0 62 sub is_raspberry { return $israspberry; }
290              
291 0     0 0 0 sub is_raspberry_2 { return $israspberry2; }
292              
293 0     0 0 0 sub is_raspberry_3 { return $israspberry3; }
294              
295 0     0 0 0 sub is_raspberry_4 { return $israspberry4; }
296              
297 0     0 0 0 sub has_device_tree { return $hasdevicetree; }
298              
299 0     0 0 0 sub home_directory { return $homedir; }
300              
301 10     10 0 3428 sub board_type { return $_config->{board_type}; }
302              
303 0     0 0 0 sub gpio_header_type { return $_config->{board_type}; }
304              
305 0     0 0 0 sub manufacturer { return $_config->{manufacturer}; }
306              
307 0     0 0 0 sub release_date { return $_config->{release}; }
308              
309 0     0 0 0 sub processor { return $_config->{processor}; }
310              
311 0     0 0 0 sub hardware { return $_config->{hardware}; }
312              
313 0     0 0 0 sub model_name { return $_config->{modelname}; }
314              
315 0     0 0 0 sub revision { return $_config->{revision}; }
316              
317 0     0 0 0 sub memory { return $_config->{memory}; }
318              
319 0     0 0 0 sub serial_number { return $_config->{serial}; }
320              
321 0     0 0 0 sub get_alt_function_names { return $_alt_function_names; }
322              
323 0     0 0 0 sub alt_func_version { return $_alt_function_names_version; }
324              
325             sub board_description {
326 0     0 0 0 my $description = 'Unknown board type';
327 0 0       0 if($_config->{board_type} == $btype1 ) {
    0          
    0          
    0          
328 0         0 $description = 'Type 1 26 pin GPIO header';
329             } elsif($_config->{board_type} == $btype2 ) {
330 0         0 $description = 'Type 2 26 pin GPIO header';
331             } elsif($_config->{board_type} == $btype3 ) {
332 0         0 $description = 'Type 3 40 pin GPIO header';
333             } elsif($_config->{board_type} == $btype4 ) {
334 0         0 $description = 'Type 4 Compute Module';
335             }
336 0         0 return $description;
337             }
338              
339             sub _configure {
340            
341 5     5   10 my %_cpuinfostash = ();
342            
343 5         10 my $device_tree_boardname = '';
344            
345 5 50       12 if( os_is_linux() ) {
346             # clean our path for safety
347 5         48 local $ENV{PATH} = '/bin:/usr/bin:/usr/local/bin';
348 5         17033 my $output = qx(cat /proc/cpuinfo);
349            
350 5 50       286 if( $output ) {
351 5         1203 for ( split(/\n/, $output) ) {
352 2155 100       5677 if( $_ =~ /^([^\s]+)\s*:\s(.+)$/ ) {
353 1120         2672 $_cpuinfostash{$1} = $2;
354             }
355             }
356             }
357            
358 5 50       326 $hasdevicetree = ( -e '/proc/device-tree/soc/ranges' ) ? 1 : 0;
359 5 50       140 if( $hasdevicetree ) {
360 0         0 my $bname = qx(cat /proc/device-tree/model);
361 0         0 chomp $bname;
362            
363 0 0       0 $device_tree_boardname = $bname if( $bname );
364             }
365             }
366            
367 5 50       40 my $hardware = ($_cpuinfostash{Hardware}) ? $_cpuinfostash{Hardware} : 'BCM2709';
368 5 50       35 my $serial = ($_cpuinfostash{Serial}) ? $_cpuinfostash{Serial} : 'UNKNOWN';
369 5 50       19 my $board_type = ( $hardware eq 'BCM2708' ) ? 2 : 3;
370 5 50       31 my $defaultkey = ( $board_type == 3 ) ? 'unknownex' : 'unknown';
371 5 50       33 my $rev = ($_cpuinfostash{Revision}) ? lc( $_cpuinfostash{Revision} ) : $defaultkey;
372 5         25 $rev =~ s/^\s+//;
373 5         20 $rev =~ s/\s+$//;
374            
375 5   33     232 $israspberry = $_cpuinfostash{Hardware} && $_cpuinfostash{Hardware} =~ /^BCM2708|BCM2709|BCM2710|BCM2835$/;
376            
377 5 50       87 if ( $rev =~ /(beta|unknown|unknownex)$/) {
378 5 50       31 my $infokey = exists($_revstash{$rev}) ? $rev : $defaultkey;
379 5         28 $_config = { %{ $_revstash{$infokey} } };
  5         107  
380 5         33 $_config->{processor} = 'BCM2835';
381 5         21 $_config->{revision} = 'UNKNOWN';
382             } else {
383             # is this a scheme 0 or 1 number
384 0         0 my $revnum = oct( '0x' . $rev );
385            
386 0         0 my $schemenewt = 0b100000000000000000000000 & $revnum;
387 0         0 $schemenewt = $schemenewt >> 23;
388            
389 0 0       0 if ( $schemenewt ) {
390 0         0 my $schemerev = 0b1111 & $revnum;
391 0         0 my $schemetype = 0b111111110000 & $revnum;
392 0         0 $schemetype = $schemetype >> 4;
393 0         0 my $schemeproc = 0b1111000000000000 & $revnum;
394 0         0 $schemeproc = $schemeproc >> 12;
395 0         0 my $schememanu = 0b11110000000000000000 & $revnum;
396 0         0 $schememanu = $schememanu >> 16;
397 0         0 my $schemesize = 0b11100000000000000000000 & $revnum;
398 0         0 $schemesize = $schemesize >> 20;
399            
400             # base type
401 0         0 my $binfo = $_revstash{$defaultkey};
402            
403 0   0     0 $binfo->{release} = $_revinfostash{extended_release}->{$rev} || $_revinfostash{release}->{$schemetype} || 'Q1 2015';
404 0   0     0 $binfo->{model_name} = $_revinfostash{type}->{$schemetype} || qq(Unknown Raspberry Pi Type : $schemetype);
405 0 0       0 $binfo->{model_name} = $device_tree_boardname if $device_tree_boardname;
406 0   0     0 $binfo->{memory} = $_revinfostash{memsize}->{$schemesize} || 256;
407 0   0     0 $binfo->{manufacturer} = $_revinfostash{manufacturer}->{$schememanu} || 'Sony';
408 0   0     0 $binfo->{board_type} = $_revinfostash{board_type}->{$schemetype} || $board_type;
409 0   0     0 $binfo->{processor} = $_revinfostash{processor}->{$schemeproc} || 'BCM2835';
410 0         0 $binfo->{revision} = $rev;
411 0         0 $binfo->{revisionnumber} = $schemerev;
412            
413 0 0       0 $israspberry2 = ( $schemetype == 4 ) ? 1 : 0;
414 0 0 0     0 $israspberry3 = ( $schemetype == 8 || $schemetype == 10 || $schemetype == 13 || $schemetype == 14 || $schemetype == 16 ) ? 1 : 0;
415 0 0       0 $israspberry4 = ( $schemetype == 17 ) ? 1 : 0;
416            
417 0         0 $_config = { %$binfo };
418             } else {
419 0 0       0 my $infokey = exists($_revstash{$rev}) ? $rev : $defaultkey;
420 0         0 $_config = { %{ $_revstash{$infokey} } };
  0         0  
421 0         0 $_config->{processor} = 'BCM2835';
422 0         0 $_config->{revisionnumber} = 0;
423             }
424            
425             }
426            
427             # Home Dir
428 5 50       72 if( os_is_windows ) {
429 0         0 require Win32;
430 0         0 $homedir = Win32::GetFolderPath( 0x001C, 1);
431 0         0 $homedir = Win32::GetShortPathName( $homedir );
432 0         0 $homedir =~ s/\\/\//g;
433             } else {
434 5         4014 $homedir = (getpwuid($<))[7];
435             }
436            
437 5         40 $_config->{hardware} = $hardware;
438 5         13 $_config->{serial} = $serial;
439            
440 5 50       25 if($_config->{processor} eq 'BCM2711' ) {
441 0         0 $_alt_function_names = \@_alt_func_names_2711;
442 0         0 $_alt_function_names_version = 2;
443             } else {
444 5         13 $_alt_function_names = \@_alt_func_names_2708;
445 5         10 $_alt_function_names_version = 1;
446             }
447            
448 5         69 return;
449             }
450              
451              
452              
453             sub new {
454 0     0 0   my $class = shift;
455 0           my $self = bless {}, $class;
456 0           return $self;
457             }
458              
459             sub validpins {
460 0     0 0   my $type = board_type();
461 0 0         if ( $type == 1 ) {
    0          
462 0           return ( 0, 1, 4, 7, 8, 9, 10, 11, 14, 15, 17, 18, 21, 22, 23, 24, 25 );
463             } elsif ( $type == 2 ) {
464 0           return ( 2, 3, 4, 7, 8, 9, 10, 11, 14, 15, 17, 18, 22, 23, 24, 25, 27, 28, 29, 30, 31 );
465             } else {
466             # return current latest known pinset
467 0           return ( 0, 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 );
468             }
469             }
470              
471             sub dump_board_info {
472 0     0 0   my $dump = qq(--------------------------------------------------\n);
473 0           $dump .= qq(Raspberry Pi Board Info\n);
474 0           $dump .= qq(--------------------------------------------------\n);
475 0           $dump .= qq(Model Name : $_config->{model_name}\n);
476 0           $dump .= qq(Released : $_config->{release}\n);
477 0           $dump .= qq(Manufacturer : $_config->{manufacturer}\n);
478 0           $dump .= qq(Memory : $_config->{memory}\n);
479 0           $dump .= qq(Processor : $_config->{processor}\n);
480 0           $dump .= qq(Hardware : $_config->{hardware}\n);
481 0           my $description = board_description();
482 0           $dump .= qq(Description : $description\n);
483 0           $dump .= qq(Revision : $_config->{revision}\n);
484 0           $dump .= qq(Serial Number : $_config->{serial}\n);
485 0           $dump .= qq(GPIO Header Type : $_config->{board_type}\n);
486 0           $dump .= qq(Revision Number : $_config->{revisionnumber}\n);
487 0 0         my $devtree = ( has_device_tree() ) ? 'Yes' : 'No';
488            
489 0           $dump .= qq(Device Tree : $devtree\n);
490 0 0         $dump .= q(Is Raspberry : ) . (($israspberry) ? 'Yes' : 'No' ) . qq(\n);
491 0 0         $dump .= q(Is Raspberry 2 : ) . (($israspberry2) ? 'Yes' : 'No' ) . qq(\n);
492 0 0         $dump .= q(Is Raspberry 3 : ) . (($israspberry3) ? 'Yes' : 'No' ) . qq(\n);
493 0 0         $dump .= q(Is Raspberry 4 : ) . (($israspberry4) ? 'Yes' : 'No' ) . qq(\n);
494            
495 0           $dump .= q(Alt Function Map : Version ) . alt_func_version() . qq(\n);
496            
497 0           return $dump;
498             }
499              
500             _configure();
501              
502             1;
503              
504             __END__