Hung-Te Lin | c6b8b2a | 2011-01-20 17:08:12 +0800 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | # Copyright (c) 2011 The Chromium OS Authors. All rights reserved. |
| 3 | # Use of this source code is governed by a BSD-style license that can be |
| 4 | # found in the LICENSE file. |
| 5 | |
| 6 | '''Chrome OS device GPIO library |
| 7 | |
| 8 | This module provides a convenient way to detect, setup, and access to GPIO |
| 9 | values on a Chrome OS compatible device. |
| 10 | |
| 11 | See help(Gpio) for more information. |
Hung-Te Lin | c6b8b2a | 2011-01-20 17:08:12 +0800 | [diff] [blame] | 12 | ''' |
| 13 | |
| 14 | import os |
| 15 | import shutil |
| 16 | import sys |
| 17 | import tempfile |
| 18 | |
Hung-Te Lin | b87193c | 2011-01-20 18:01:28 +0800 | [diff] [blame] | 19 | |
Hung-Te Lin | c6b8b2a | 2011-01-20 17:08:12 +0800 | [diff] [blame] | 20 | class Gpio(object): |
| 21 | ''' |
| 22 | Utility to access GPIO values. |
| 23 | |
| 24 | Usage: |
| 25 | gpio = Gpio() |
| 26 | try: |
| 27 | gpio.setup() |
Hung-Te Lin | ff52cb6 | 2011-02-18 18:37:53 +0800 | [diff] [blame] | 28 | print gpio.read(gpio.DEVELOPER_SWITCH_CURRENT) |
Hung-Te Lin | c6b8b2a | 2011-01-20 17:08:12 +0800 | [diff] [blame] | 29 | except: |
| 30 | print "gpio failed" |
| 31 | ''' |
| 32 | |
Hung-Te Lin | ff52cb6 | 2011-02-18 18:37:53 +0800 | [diff] [blame] | 33 | # GPIO property names (by "crossystem"): |
| 34 | DEVELOPER_SWITCH_CURRENT = 'devsw_cur' |
| 35 | RECOVERY_BUTTON_CURRENT = 'recoverysw_cur' |
| 36 | WRITE_PROTECT_CURRENT = 'wpsw_cur' |
| 37 | |
| 38 | DEVELOPER_SWITCH_BOOT = 'devsw_boot' |
| 39 | RECOVERY_BUTTON_BOOT = 'recoverysw_boot' |
| 40 | WRITE_PROTECT_BOOT = 'wpsw_boot' |
| 41 | |
Hung-Te Lin | c6b8b2a | 2011-01-20 17:08:12 +0800 | [diff] [blame] | 42 | def __init__(self, exception_type=IOError): |
Hung-Te Lin | c6b8b2a | 2011-01-20 17:08:12 +0800 | [diff] [blame] | 43 | self._exception_type = exception_type |
| 44 | |
Hung-Te Lin | ff52cb6 | 2011-02-18 18:37:53 +0800 | [diff] [blame] | 45 | # list of property conversions, usually str2int. |
| 46 | self._override_map = { |
| 47 | self.DEVELOPER_SWITCH_CURRENT: int, |
| 48 | self.DEVELOPER_SWITCH_BOOT: int, |
| 49 | self.RECOVERY_BUTTON_CURRENT: int, |
| 50 | self.RECOVERY_BUTTON_BOOT: int, |
| 51 | self.WRITE_PROTECT_CURRENT: int, |
| 52 | self.WRITE_PROTECT_BOOT: int, |
| 53 | } |
| 54 | |
| 55 | # list of legacy (chromeos_acpi) property names. |
| 56 | self._legacy_map = { |
| 57 | 'developer_switch': self.DEVELOPER_SWITCH_CURRENT, |
| 58 | 'recovery_button': self.RECOVERY_BUTTON_CURRENT, |
| 59 | 'write_protect': self.WRITE_PROTECT_CURRENT, |
| 60 | } |
| 61 | |
| 62 | def setup(self): |
Hung-Te Lin | c6b8b2a | 2011-01-20 17:08:12 +0800 | [diff] [blame] | 63 | '''Configures system for processing GPIO. |
| 64 | |
Hung-Te Lin | c6b8b2a | 2011-01-20 17:08:12 +0800 | [diff] [blame] | 65 | Returns: |
| 66 | Raises an exception if gpio_setup execution failed. |
| 67 | ''' |
Hung-Te Lin | ff52cb6 | 2011-02-18 18:37:53 +0800 | [diff] [blame] | 68 | # This is the place to do any configuration / system detection. |
| 69 | # Currently "crossystem" handles everything so we don't need to do |
| 70 | # anything now. |
| 71 | pass |
Hung-Te Lin | b87193c | 2011-01-20 18:01:28 +0800 | [diff] [blame] | 72 | |
Hung-Te Lin | c6b8b2a | 2011-01-20 17:08:12 +0800 | [diff] [blame] | 73 | def read(self, name): |
Hung-Te Lin | ff52cb6 | 2011-02-18 18:37:53 +0800 | [diff] [blame] | 74 | '''Reads a GPIO property value. |
| 75 | Check "crossystem" command for the list of available property names. |
Hung-Te Lin | c6b8b2a | 2011-01-20 17:08:12 +0800 | [diff] [blame] | 76 | |
| 77 | Parameters: |
Hung-Te Lin | ff52cb6 | 2011-02-18 18:37:53 +0800 | [diff] [blame] | 78 | name: the name of property to read. |
Hung-Te Lin | c6b8b2a | 2011-01-20 17:08:12 +0800 | [diff] [blame] | 79 | |
Hung-Te Lin | ff52cb6 | 2011-02-18 18:37:53 +0800 | [diff] [blame] | 80 | Returns: current value, or raise exceptions. |
Hung-Te Lin | c6b8b2a | 2011-01-20 17:08:12 +0800 | [diff] [blame] | 81 | ''' |
Hung-Te Lin | ff52cb6 | 2011-02-18 18:37:53 +0800 | [diff] [blame] | 82 | debug_title = "Gpio.read('%s'): " % name |
Hung-Te Lin | b87193c | 2011-01-20 18:01:28 +0800 | [diff] [blame] | 83 | |
Hung-Te Lin | ff52cb6 | 2011-02-18 18:37:53 +0800 | [diff] [blame] | 84 | # convert legacy names |
| 85 | if name in self._legacy_map: |
| 86 | name = self._legacy_map[name] |
Hung-Te Lin | b87193c | 2011-01-20 18:01:28 +0800 | [diff] [blame] | 87 | |
Hung-Te Lin | ff52cb6 | 2011-02-18 18:37:53 +0800 | [diff] [blame] | 88 | temp_fd, temp_file = tempfile.mkstemp() |
| 89 | os.close(temp_fd) |
| 90 | command = "crossystem %s 2>%s" % (name, temp_file) |
| 91 | pipe = os.popen(command, 'r') |
| 92 | value = pipe.read() |
| 93 | exit_status = pipe.close() |
| 94 | if exit_status: |
| 95 | with open(temp_file, 'r') as temp_handle: |
| 96 | debug_info = temp_handle.read() |
| 97 | value = value.strip() |
| 98 | debug_info = debug_info.strip() |
| 99 | if value: |
| 100 | debug_info = value + '\n' + debug_info |
| 101 | if debug_info: |
| 102 | debug_info = '\nInformation: ' + debug_info |
| 103 | raise self._exception_type( |
| 104 | debug_title + "Command failed (%d): %s%s" % |
| 105 | (exit_status, command, debug_info)) |
| 106 | # convert values |
| 107 | if name in self._override_map: |
| 108 | try: |
| 109 | value = self._override_map[name](value) |
| 110 | except: |
| 111 | raise self._exception_type(debug_title + |
| 112 | 'Conversion failed: %s' % value) |
Hung-Te Lin | b87193c | 2011-01-20 18:01:28 +0800 | [diff] [blame] | 113 | return value |
Hung-Te Lin | c6b8b2a | 2011-01-20 17:08:12 +0800 | [diff] [blame] | 114 | |
| 115 | |
| 116 | def main(): |
| 117 | gpio = Gpio() |
| 118 | try: |
| 119 | gpio.setup() |
Hung-Te Lin | ff52cb6 | 2011-02-18 18:37:53 +0800 | [diff] [blame] | 120 | print ("developer switch current status: %s" % |
| 121 | gpio.read(gpio.DEVELOPER_SWITCH_CURRENT)) |
| 122 | except Exception, e: |
| 123 | print "GPIO failed. %s" % e |
Hung-Te Lin | c6b8b2a | 2011-01-20 17:08:12 +0800 | [diff] [blame] | 124 | sys.exit(1) |
| 125 | |
| 126 | if __name__ == '__main__': |
| 127 | main() |