File Coverage

blib/lib/HiPi/RaspberryPi.pm
Criterion Covered Total %
statement 44 139 31.6
branch 17 74 22.9
condition 1 20 5.0
subroutine 8 30 26.6
pod 0 26 0.0
total 70 289 24.2


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   31 use strict;
  5         9  
  5         123  
14 5     5   20 use warnings;
  5         10  
  5         111  
15 5     5   26 use Carp;
  5         16  
  5         12844  
16              
17             our $VERSION ='0.80';
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              
154             my %_revstash = (
155             'beta' => { release => 'Q1 2012', model_name => 'Raspberry Pi Model B Revision beta', revision => 'beta', board_type => $btype1, memory => 256, manufacturer => 'Generic' },
156             '0002' => { release => 'Q1 2012', model_name => 'Raspberry Pi Model B Revision 1.0', revision => '0002', board_type => $btype1, memory => 256, manufacturer => 'Generic' },
157             '0003' => { release => 'Q3 2012', model_name => 'Raspberry Pi Model B Revision 1.0', revision => '0003', board_type => $btype1, memory => 256, manufacturer => 'Generic' },
158             '0004' => { release => 'Q3 2012', model_name => 'Raspberry Pi Model B Revision 2.0', revision => '0004', board_type => $btype2, memory => 256, manufacturer => 'Sony' },
159             '0005' => { release => 'Q4 2012', model_name => 'Raspberry Pi Model B Revision 2.0', revision => '0005', board_type => $btype2, memory => 256, manufacturer => 'Qisda' },
160             '0006' => { release => 'Q4 2012', model_name => 'Raspberry Pi Model B Revision 2.0', revision => '0006', board_type => $btype2, memory => 256, manufacturer => 'Egoman' },
161             '0007' => { release => 'Q1 2013', model_name => 'Raspberry Pi Model A', revision => '0007', board_type => $btype2, memory => 256, manufacturer => 'Egoman' },
162             '0008' => { release => 'Q1 2013', model_name => 'Raspberry Pi Model A', revision => '0008', board_type => $btype2, memory => 256, manufacturer => 'Sony' },
163             '0009' => { release => 'Q1 2013', model_name => 'Raspberry Pi Model A', revision => '0009', board_type => $btype2, memory => 256, manufacturer => 'Qisda' },
164            
165             '000d' => { release => 'Q4 2012', model_name => 'Raspberry Pi Model B Revision 2.0', revision => '000d', board_type => $btype2, memory => 512, manufacturer => 'Egoman' },
166             '000e' => { release => 'Q4 2012', model_name => 'Raspberry Pi Model B Revision 2.0', revision => '000e', board_type => $btype2, memory => 512, manufacturer => 'Sony' },
167             '000f' => { release => 'Q4 2012', model_name => 'Raspberry Pi Model B Revision 2.0', revision => '000f', board_type => $btype2, memory => 512, manufacturer => 'Qisda' },
168            
169             '0010' => { release => 'Q3 2014', model_name => 'Raspberry Pi Model B +', revision => '0010', board_type => $btype3, memory => 512, manufacturer => 'Sony' },
170             '0011' => { release => 'Q2 2013', model_name => 'Compute Module', revision => '0011', board_type => $btype2, memory => 512, manufacturer => 'Sony' },
171             '0012' => { release => 'Q4 2014', model_name => 'Raspberry Pi Model A +', revision => '0012', board_type => $btype3, memory => 256, manufacturer => 'Sony' },
172            
173             '0014' => { release => 'Q2 2015', model_name => 'Compute Module', revision => '0014', board_type => $btype2, memory => 512, manufacturer => 'Sony' },
174             '0015' => { release => 'Q4 2015', model_name => 'Raspberry Pi Model A +', revision => '0015', board_type => $btype3, memory => 512, manufacturer => 'Sony' },
175             'unknown' => { release => 'Q1 2012', model_name => 'Virtual or Unknown Raspberry Pi', revision => 'UNKNOWN', board_type => $btype2, memory => 512, manufacturer => 'HiPi Virtual' },
176             'unknownex' => { release => 'Q1 2012', model_name => 'Virtual or Unknown Raspberry Pi', revision => 'UNKNOWN', board_type => $btype3, memory => 1024, manufacturer => 'HiPi Virtual' },
177             );
178              
179             # MAP 24 bits of Revision NEW:1, MEMSIZE:3, MANUFACTURER:4, PROCESSOR:4, MODEL:8, BOARD REVISION:4
180              
181             my %_revinfostash = (
182             memsize => {
183             '0' => 256,
184             '1' => 512,
185             '2' => 1024,
186             '3' => 2048,
187             '4' => 4096,
188             },
189             manufacturer => {
190             '0' => 'Sony UK',
191             '1' => 'Egoman',
192             '2' => 'Embest',
193             '3' => 'Sony Japan',
194             '4' => 'Embest',
195             '5' => 'Stadium',
196             },
197            
198             processor => {
199             '0' => 'BCM2835',
200             '1' => 'BCM2836',
201             '2' => 'BCM2837',
202             '3' => 'BCM2711',
203             },
204            
205             type => {
206             '0' => 'Raspberry Pi Model A', # 00
207             '1' => 'Raspberry Pi Model B', # 01
208             '2' => 'Raspberry Pi Model A Plus', # 02
209             '3' => 'Raspberry Pi Model B Plus', # 03
210             '4' => 'Raspberry Pi 2 Model B', # 04
211             '5' => 'Raspberry Pi Alpha', # 05
212             '6' => 'Raspberry Pi Compute Module 1', # 06
213             '7' => 'Raspberry Pi Unknown Model 07', # 07
214             '8' => 'Raspberry Pi 3 Model B', # 08
215             '9' => 'Raspberry Pi Zero', # 09
216             '10' => 'Raspberry Pi Compute Module 3', # 0A
217             '11' => 'UNKNOWN Rasberry Pi Model 11', # 0B
218             '12' => 'Raspberry Pi Zero W', # 0C
219             '13' => 'Raspberry Pi 3 Model B Plus', # 0D
220             '14' => 'Raspberry Pi 3 Model A Plus', # 0E
221             '15' => 'UNKNOWN Rasberry Pi Model 15', # 0F
222             '16' => 'Raspberry Pi Compute Module 3 Plus', # 10
223             '17' => 'Raspberry Pi 4 Model B', # 11
224             },
225             board_type => {
226             '0' => $btype2,
227             '1' => $btype2,
228             '2' => $btype3,
229             '3' => $btype3,
230             '4' => $btype3,
231             '5' => $btype1,
232             '6' => $btype2,
233             '7' => $btype3,
234             '8' => $btype3,
235             '9' => $btype3,
236             '10' => $btype4,
237             '11' => $btype3,
238             '12' => $btype3,
239             '13' => $btype3,
240             '14' => $btype3,
241             '15' => $btype3,
242             '16' => $btype4,
243             '17' => $btype3,
244             },
245             release => {
246             '0' => 'Q1 2013',
247             '1' => 'Q3 2012',
248             '2' => 'Q4 2014',
249             '3' => 'Q3 2014',
250             '4' => 'Q1 2015',
251             '5' => 'Q1 2012',
252             '6' => 'Q2 2013',
253             '7' => 'Q2 2015',
254             '8' => 'Q1 2016',
255             '9' => 'Q4 2015',
256             '10' => 'Q1 2017',
257             '11' => 'unknown',
258             '12' => 'Q1 2017',
259             '13' => 'Q1 2018',
260             '14' => 'Q4 2018',
261             '15' => 'unknown',
262             '16' => 'Q1 2019',
263             '17' => 'Q2 2019',
264            
265             },
266             );
267              
268             my $_config = $_revstash{unknownex};
269              
270 5 50   5 0 94 sub os_is_windows { return ( $^O =~ /^mswin/i ) ? 1 : 0; }
271              
272 0 0   0 0 0 sub os_is_osx { return ( $^O =~ /^darwen/i ) ? 1 : 0; }
273              
274 5 50   5 0 70 sub os_is_linux { return ( $^O =~ /^linux/i ) ? 1 : 0; }
275              
276 0 0   0 0 0 sub os_is_other { return ( $^O !~ /^mswin|linux|darwen/i ) ? 1 : 0; }
277              
278 0 0   0 0 0 sub os_supported { return ( $^O =~ /^linux/i ) ? 1 : 0; }
279              
280 7     7 0 59 sub is_raspberry { return $israspberry; }
281              
282 0     0 0 0 sub is_raspberry_2 { return $israspberry2; }
283              
284 0     0 0 0 sub is_raspberry_3 { return $israspberry3; }
285              
286 0     0 0 0 sub is_raspberry_4 { return $israspberry4; }
287              
288 0     0 0 0 sub has_device_tree { return $hasdevicetree; }
289              
290 0     0 0 0 sub home_directory { return $homedir; }
291              
292 10     10 0 3300 sub board_type { return $_config->{board_type}; }
293              
294 0     0 0 0 sub gpio_header_type { return $_config->{board_type}; }
295              
296 0     0 0 0 sub manufacturer { return $_config->{manufacturer}; }
297              
298 0     0 0 0 sub release_date { return $_config->{release}; }
299              
300 0     0 0 0 sub processor { return $_config->{processor}; }
301              
302 0     0 0 0 sub hardware { return $_config->{hardware}; }
303              
304 0     0 0 0 sub model_name { return $_config->{modelname}; }
305              
306 0     0 0 0 sub revision { return $_config->{revision}; }
307              
308 0     0 0 0 sub memory { return $_config->{memory}; }
309              
310 0     0 0 0 sub serial_number { return $_config->{serial}; }
311              
312 0     0 0 0 sub get_alt_function_names { return $_alt_function_names; }
313              
314             sub board_description {
315 0     0 0 0 my $description = 'Unknown board type';
316 0 0       0 if($_config->{board_type} == $btype1 ) {
    0          
    0          
    0          
317 0         0 $description = 'Type 1 26 pin GPIO header';
318             } elsif($_config->{board_type} == $btype2 ) {
319 0         0 $description = 'Type 2 26 pin GPIO header';
320             } elsif($_config->{board_type} == $btype3 ) {
321 0         0 $description = 'Type 3 40 pin GPIO header';
322             } elsif($_config->{board_type} == $btype4 ) {
323 0         0 $description = 'Type 4 Compute Module';
324             }
325 0         0 return $description;
326             }
327              
328             sub _configure {
329            
330 5     5   10 my %_cpuinfostash = ();
331            
332 5         9 my $device_tree_boardname = '';
333            
334 5 50       14 if( os_is_linux() ) {
335             # clean our path for safety
336 5         42 local $ENV{PATH} = '/bin:/usr/bin:/usr/local/bin';
337 5         15203 my $output = qx(cat /proc/cpuinfo);
338            
339 5 50       254 if( $output ) {
340 5         2139 for ( split(/\n/, $output) ) {
341 2155 100       4961 if( $_ =~ /^([^\s]+)\s*:\s(.+)$/ ) {
342 1120         2352 $_cpuinfostash{$1} = $2;
343             }
344             }
345             }
346            
347 5 50       393 $hasdevicetree = ( -e '/proc/device-tree/soc/ranges' ) ? 1 : 0;
348 5 50       168 if( $hasdevicetree ) {
349 0         0 my $bname = qx(cat /proc/device-tree/model);
350 0         0 chomp $bname;
351            
352 0 0       0 $device_tree_boardname = $bname if( $bname );
353             }
354             }
355            
356 5 50       84 my $hardware = ($_cpuinfostash{Hardware}) ? $_cpuinfostash{Hardware} : 'BCM2709';
357 5 50       63 my $serial = ($_cpuinfostash{Serial}) ? $_cpuinfostash{Serial} : 'UNKNOWN';
358 5 50       61 my $board_type = ( $hardware eq 'BCM2708' ) ? 2 : 3;
359 5 50       53 my $defaultkey = ( $board_type == 3 ) ? 'unknownex' : 'unknown';
360 5 50       44 my $rev = ($_cpuinfostash{Revision}) ? lc( $_cpuinfostash{Revision} ) : $defaultkey;
361 5         38 $rev =~ s/^\s+//;
362 5         193 $rev =~ s/\s+$//;
363            
364 5   33     87 $israspberry = $_cpuinfostash{Hardware} && $_cpuinfostash{Hardware} =~ /^BCM2708|BCM2709|BCM2710|BCM2835$/;
365            
366 5 50       126 if ( $rev =~ /(beta|unknown|unknownex)$/) {
367 5 50       48 my $infokey = exists($_revstash{$rev}) ? $rev : $defaultkey;
368 5         24 $_config = { %{ $_revstash{$infokey} } };
  5         190  
369 5         45 $_config->{processor} = 'BCM2835';
370 5         30 $_config->{revision} = 'UNKNOWN';
371             } else {
372             # is this a scheme 0 or 1 number
373 0         0 my $revnum = oct( '0x' . $rev );
374            
375 0         0 my $schemenewt = 0b100000000000000000000000 & $revnum;
376 0         0 $schemenewt = $schemenewt >> 23;
377            
378 0 0       0 if ( $schemenewt ) {
379 0         0 my $schemerev = 0b1111 & $revnum;
380 0         0 my $schemetype = 0b111111110000 & $revnum;
381 0         0 $schemetype = $schemetype >> 4;
382 0         0 my $schemeproc = 0b1111000000000000 & $revnum;
383 0         0 $schemeproc = $schemeproc >> 12;
384 0         0 my $schememanu = 0b11110000000000000000 & $revnum;
385 0         0 $schememanu = $schememanu >> 16;
386 0         0 my $schemesize = 0b11100000000000000000000 & $revnum;
387 0         0 $schemesize = $schemesize >> 20;
388            
389             # base type
390 0         0 my $binfo = $_revstash{$defaultkey};
391            
392 0   0     0 $binfo->{release} = $_revinfostash{release}->{$schemetype} || 'Q1 2015';
393 0   0     0 $binfo->{model_name} = $_revinfostash{type}->{$schemetype} || qq(Unknown Raspberry Pi Type : $schemetype);
394 0 0       0 $binfo->{model_name} = $device_tree_boardname if $device_tree_boardname;
395 0   0     0 $binfo->{memory} = $_revinfostash{memsize}->{$schemesize} || 256;
396 0   0     0 $binfo->{manufacturer} = $_revinfostash{manufacturer}->{$schememanu} || 'Sony';
397 0   0     0 $binfo->{board_type} = $_revinfostash{board_type}->{$schemetype} || $board_type;
398 0   0     0 $binfo->{processor} = $_revinfostash{processor}->{$schemeproc} || 'BCM2835';
399 0         0 $binfo->{revision} = $rev;
400 0         0 $binfo->{revisionnumber} = $schemerev;
401            
402 0 0       0 $israspberry2 = ( $schemetype == 4 ) ? 1 : 0;
403 0 0 0     0 $israspberry3 = ( $schemetype == 8 || $schemetype == 10 || $schemetype == 13 || $schemetype == 14 || $schemetype == 16 ) ? 1 : 0;
404 0 0       0 $israspberry4 = ( $schemetype == 17 ) ? 1 : 0;
405            
406 0         0 $_config = { %$binfo };
407             } else {
408 0 0       0 my $infokey = exists($_revstash{$rev}) ? $rev : $defaultkey;
409 0         0 $_config = { %{ $_revstash{$infokey} } };
  0         0  
410 0         0 $_config->{processor} = 'BCM2835';
411 0         0 $_config->{revisionnumber} = 0;
412             }
413            
414             }
415            
416             # Home Dir
417 5 50       66 if( os_is_windows ) {
418 0         0 require Win32;
419 0         0 $homedir = Win32::GetFolderPath( 0x001C, 1);
420 0         0 $homedir = Win32::GetShortPathName( $homedir );
421 0         0 $homedir =~ s/\\/\//g;
422             } else {
423 5         4041 $homedir = (getpwuid($<))[7];
424             }
425            
426 5         75 $_config->{hardware} = $hardware;
427 5         39 $_config->{serial} = $serial;
428            
429 5 50       56 $_alt_function_names = ( $_config->{processor} eq 'BCM2711' ) ? \@_alt_func_names_2711 : \@_alt_func_names_2708;
430            
431 5         84 return;
432             }
433              
434             sub new {
435 0     0 0   my $class = shift;
436 0           my $self = bless {}, $class;
437 0           return $self;
438             }
439              
440             sub validpins {
441 0     0 0   my $type = board_type();
442 0 0         if ( $type == 1 ) {
    0          
443 0           return ( 0, 1, 4, 7, 8, 9, 10, 11, 14, 15, 17, 18, 21, 22, 23, 24, 25 );
444             } elsif ( $type == 2 ) {
445 0           return ( 2, 3, 4, 7, 8, 9, 10, 11, 14, 15, 17, 18, 22, 23, 24, 25, 27, 28, 29, 30, 31 );
446             } else {
447             # return current latest known pinset
448 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 );
449             }
450             }
451              
452             sub dump_board_info {
453 0     0 0   my $dump = qq(--------------------------------------------------\n);
454 0           $dump .= qq(Raspberry Pi Board Info\n);
455 0           $dump .= qq(--------------------------------------------------\n);
456 0           $dump .= qq(Model Name : $_config->{model_name}\n);
457 0           $dump .= qq(Released : $_config->{release}\n);
458 0           $dump .= qq(Manufacturer : $_config->{manufacturer}\n);
459 0           $dump .= qq(Memory : $_config->{memory}\n);
460 0           $dump .= qq(Processor : $_config->{processor}\n);
461 0           $dump .= qq(Hardware : $_config->{hardware}\n);
462 0           my $description = board_description();
463 0           $dump .= qq(Description : $description\n);
464 0           $dump .= qq(Revision : $_config->{revision}\n);
465 0           $dump .= qq(Serial Number : $_config->{serial}\n);
466 0           $dump .= qq(GPIO Header Type : $_config->{board_type}\n);
467 0           $dump .= qq(Revision Number : $_config->{revisionnumber}\n);
468 0 0         my $devtree = ( has_device_tree() ) ? 'Yes' : 'No';
469            
470 0           $dump .= qq(Device Tree : $devtree\n);
471 0 0         $dump .= q(Is Raspberry : ) . (($israspberry) ? 'Yes' : 'No' ) . qq(\n);
472 0 0         $dump .= q(Is Raspberry 2 : ) . (($israspberry2) ? 'Yes' : 'No' ) . qq(\n);
473 0 0         $dump .= q(Is Raspberry 3 : ) . (($israspberry3) ? 'Yes' : 'No' ) . qq(\n);
474 0 0         $dump .= q(Is Raspberry 4 : ) . (($israspberry4) ? 'Yes' : 'No' ) . qq(\n);
475            
476 0           $dump .= q(Alt Function Map : Version ) . alt_func_version() . qq(\n);
477            
478 0           return $dump;
479             }
480              
481             _configure();
482              
483             1;
484              
485             __END__