| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // NOTE: this file is translated from gpio_setup.py | 5 // NOTE: this file is translated from gpio_setup.py |
| 6 // | 6 // |
| 7 // A script to create symlinks to platform specific GPIO pins. | 7 // A script to create symlinks to platform specific GPIO pins. |
| 8 // | 8 // |
| 9 // This script creates a set of symlinks pointing at the sys fs files returning | 9 // This script creates a set of symlinks pointing at the sys fs files returning |
| 10 // the appropriate GPIO pin values. Each symlink is named to represent the | 10 // the appropriate GPIO pin values. Each symlink is named to represent the |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 // Can be changed using --pci_address command line option. | 62 // Can be changed using --pci_address command line option. |
| 63 #define DEFAULT_GPIO_DEVICE_PCI_ADDRESS "0000:00:1f.0" | 63 #define DEFAULT_GPIO_DEVICE_PCI_ADDRESS "0000:00:1f.0" |
| 64 | 64 |
| 65 // Can be changed using --acpi_root command line option. | 65 // Can be changed using --acpi_root command line option. |
| 66 #define DEFAULT_ACPI_ROOT "/sys/bus/platform/devices/chromeos_acpi" | 66 #define DEFAULT_ACPI_ROOT "/sys/bus/platform/devices/chromeos_acpi" |
| 67 | 67 |
| 68 // can be changed using --symlink_root command line option. | 68 // can be changed using --symlink_root command line option. |
| 69 #define DEFAULT_SYMLINK_ROOT "/home/gpio" | 69 #define DEFAULT_SYMLINK_ROOT "/home/gpio" |
| 70 | 70 |
| 71 #define GPIO_SIGNAL_TYPE_EXTENSION "0" | 71 #define GPIO_SIGNAL_TYPE_EXTENSION "0" |
| 72 #define GPIO_ATTRIBUTES_EXTENSION "1" |
| 72 #define GPIO_PIN_NUMBER_EXTENSION "2" | 73 #define GPIO_PIN_NUMBER_EXTENSION "2" |
| 73 | 74 |
| 74 // Debug header signal type codes are offset by 0x100, the tuple below | 75 // Debug header signal type codes are offset by 0x100, the tuple below |
| 75 // represents the range of valid codes for the debug header. The range | 76 // represents the range of valid codes for the debug header. The range |
| 76 // starts at 0x100 and is 0x100 wide. | 77 // starts at 0x100 and is 0x100 wide. |
| 77 const int GPIO_DEBUG_HEADER_RANGE[2] = { 0x100, 0x100 }; | 78 const int GPIO_DEBUG_HEADER_RANGE[2] = { 0x100, 0x100 }; |
| 78 | 79 |
| 79 // This dictionary maps GPIO signal types codes into their actual names. | 80 // This dictionary maps GPIO signal types codes into their actual names. |
| 80 const char *GPIO_SIGNAL_TYPES[] = { | 81 const char *GPIO_SIGNAL_TYPES[] = { |
| 81 NULL, // note: 0 is NOT a valid index, so we must | 82 NULL, // note: 0 is NOT a valid index, so we must |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 | 304 |
| 304 private: | 305 private: |
| 305 string pci_address_; | 306 string pci_address_; |
| 306 int base_; | 307 int base_; |
| 307 int capacity_; | 308 int capacity_; |
| 308 string description_; | 309 string description_; |
| 309 | 310 |
| 310 GpioChip() { } | 311 GpioChip() { } |
| 311 }; | 312 }; |
| 312 | 313 |
| 313 typedef std::pair<string, int> AcpiMappingEntry; | 314 typedef struct { |
| 315 string name; |
| 316 int index; |
| 317 int pin_number; |
| 318 } AcpiMappingEntry; |
| 319 |
| 314 typedef std::vector<AcpiMappingEntry> AcpiMapping; | 320 typedef std::vector<AcpiMappingEntry> AcpiMapping; |
| 315 | 321 |
| 316 // Scan ACPI information about GPIO and generate a mapping. | 322 // Scan ACPI information about GPIO and generate a mapping. |
| 317 // | 323 // |
| 318 // Returns: a list of tuples, each tuple consisting of a string representing | 324 // Returns: a list of tuples, each tuple consisting of a string representing |
| 319 // the GPIO pin name and a number, representing the GPIO pin within | 325 // the GPIO pin name and a number, representing the GPIO pin within |
| 320 // the GPIO device space. | 326 // the GPIO device space. |
| 321 AcpiMapping ParseAcpiMappings(const string &acpi_root) { | 327 AcpiMapping ParseAcpiMappings(const string &acpi_root) { |
| 322 GlobResult r = glob_glob(format_string("%s/GPIO.[0-9]*", acpi_root.c_str())); | 328 GlobResult r = glob_glob(format_string("%s/GPIO.[0-9]*", acpi_root.c_str())); |
| 323 AcpiMapping acpi_gpio_mapping; | 329 AcpiMapping acpi_gpio_mapping; |
| 324 GlobResult::iterator i; | 330 GlobResult::iterator i; |
| 331 |
| 325 for (i = r.begin(); i != r.end(); i++) { | 332 for (i = r.begin(); i != r.end(); i++) { |
| 333 AcpiMappingEntry entry; |
| 326 const char *d = i->c_str(); | 334 const char *d = i->c_str(); |
| 335 const char *dot_index_string = strrchr(d, '.'); |
| 327 int signal_type = atoi(open_read_strip( | 336 int signal_type = atoi(open_read_strip( |
| 328 format_string("%s/GPIO.%s", d, GPIO_SIGNAL_TYPE_EXTENSION)).c_str()); | 337 format_string("%s/GPIO.%s", d, GPIO_SIGNAL_TYPE_EXTENSION)).c_str()); |
| 329 int pin_number = atoi(open_read_strip( | 338 |
| 339 assert(dot_index_string); |
| 340 entry.index = atoi(dot_index_string + 1); |
| 341 entry.pin_number = atoi(open_read_strip( |
| 330 format_string("%s/GPIO.%s", d, GPIO_PIN_NUMBER_EXTENSION)).c_str()); | 342 format_string("%s/GPIO.%s", d, GPIO_PIN_NUMBER_EXTENSION)).c_str()); |
| 331 | 343 |
| 332 if (signal_type >= GPIO_SIGNAL_TYPE_MIN && | 344 if (signal_type >= GPIO_SIGNAL_TYPE_MIN && |
| 333 signal_type <= static_cast<int>(GPIO_SIGNAL_TYPE_MAX) && | 345 signal_type <= static_cast<int>(GPIO_SIGNAL_TYPE_MAX) && |
| 334 GPIO_SIGNAL_TYPES[signal_type] != NULL) { | 346 GPIO_SIGNAL_TYPES[signal_type] != NULL) { |
| 335 acpi_gpio_mapping.push_back(AcpiMappingEntry( | 347 entry.name = GPIO_SIGNAL_TYPES[signal_type]; |
| 336 GPIO_SIGNAL_TYPES[signal_type], pin_number)); | 348 acpi_gpio_mapping.push_back(entry); |
| 337 continue; | 349 continue; |
| 338 } | 350 } |
| 339 | 351 |
| 340 // This is not a specific signal, could be a debug header pin. | 352 // This is not a specific signal, could be a debug header pin. |
| 341 int debug_header = signal_type - GPIO_DEBUG_HEADER_RANGE[0]; | 353 int debug_header = signal_type - GPIO_DEBUG_HEADER_RANGE[0]; |
| 342 if (debug_header >= 0 && debug_header < GPIO_DEBUG_HEADER_RANGE[1]) { | 354 if (debug_header >= 0 && debug_header < GPIO_DEBUG_HEADER_RANGE[1]) { |
| 343 acpi_gpio_mapping.push_back(AcpiMappingEntry( | 355 entry.name = format_string("debug_header_%d", debug_header); |
| 344 format_string("debug_header_%d", debug_header), pin_number)); | 356 acpi_gpio_mapping.push_back(AcpiMappingEntry(entry)); |
| 345 continue; | 357 continue; |
| 346 } | 358 } |
| 347 | 359 |
| 348 // Unrecognized mapping, could happen if BIOS version is ahead of this | 360 // Unrecognized mapping, could happen if BIOS version is ahead of this |
| 349 // script. | 361 // script. |
| 350 printf("unknown signal type encoding %d in %s\n", signal_type, d); | 362 printf("unknown signal type encoding %d in %s\n", signal_type, d); |
| 351 } | 363 } |
| 352 | 364 |
| 353 if (acpi_gpio_mapping.empty()) | 365 if (acpi_gpio_mapping.empty()) |
| 354 GpioSetupError("no gpio mapping found. Is ACPI driver installed?"); | 366 GpioSetupError("no gpio mapping found. Is ACPI driver installed?"); |
| 355 | 367 |
| 356 return acpi_gpio_mapping; | 368 return acpi_gpio_mapping; |
| 357 } | 369 } |
| 358 | 370 |
| 371 void CreateSymLink(const string &source_file, const string &symlink) { |
| 372 if (!os_path_exists(symlink)) { |
| 373 os_symlink(source_file.c_str(), symlink.c_str()); |
| 374 return; |
| 375 } |
| 376 |
| 377 if (!os_path_islink(symlink)) |
| 378 GpioSetupError("%s exists but is not a symlink", |
| 379 os_path_abspath(symlink).c_str()); |
| 380 if (os_readlink(symlink) != source_file) |
| 381 GpioSetupError("%s points to a wrong file", |
| 382 os_path_abspath(symlink).c_str()); |
| 383 } |
| 384 |
| 359 void CreateGpioSymlinks(const AcpiMapping& mappings, | 385 void CreateGpioSymlinks(const AcpiMapping& mappings, |
| 360 GpioChip &gpio, | 386 GpioChip &gpio, |
| 387 const char *acpi_root, |
| 361 const char *symlink_root) { | 388 const char *symlink_root) { |
| 362 if (!os_path_exists(symlink_root)) | 389 if (!os_path_exists(symlink_root)) |
| 363 GpioSetupError("%s does not exist", symlink_root); | 390 GpioSetupError("%s does not exist", symlink_root); |
| 364 | 391 |
| 365 if (!os_path_isdir(symlink_root)) | 392 if (!os_path_isdir(symlink_root)) |
| 366 GpioSetupError("%s is not a directory", symlink_root); | 393 GpioSetupError("%s is not a directory", symlink_root); |
| 367 | 394 |
| 368 if (access(symlink_root, W_OK) != 0) | 395 if (access(symlink_root, W_OK) != 0) |
| 369 GpioSetupError("%s is not writable", symlink_root); | 396 GpioSetupError("%s is not writable", symlink_root); |
| 370 | 397 |
| 371 if (chdir(symlink_root) != 0) | 398 if (chdir(symlink_root) != 0) |
| 372 GpioSetupError("failed to change directory to %s", symlink_root); | 399 GpioSetupError("failed to change directory to %s", symlink_root); |
| 373 | 400 |
| 374 AcpiMapping::const_iterator i; | 401 AcpiMapping::const_iterator i; |
| 375 for (i = mappings.begin(); i != mappings.end(); ++i) { | 402 for (i = mappings.begin(); i != mappings.end(); ++i) { |
| 376 string symlink = i->first; | 403 string symlink, source_file; |
| 377 int pin = i->second; | 404 gpio.EnablePin(i->pin_number); |
| 378 gpio.EnablePin(pin); | |
| 379 | 405 |
| 380 string source_file = format_string("%s/gpio%d/value", | 406 symlink = i->name; |
| 381 GPIO_ROOT, pin+gpio.base()); | 407 source_file = format_string("%s/gpio%d/value", GPIO_ROOT, |
| 382 if (!os_path_exists(symlink)) { | 408 i->pin_number + gpio.base()); |
| 383 os_symlink(source_file.c_str(), symlink.c_str()); | 409 CreateSymLink(source_file, symlink); |
| 384 continue; | |
| 385 } | |
| 386 | 410 |
| 387 if (!os_path_islink(symlink)) | 411 symlink = i->name + ".attr"; |
| 388 GpioSetupError("%s exists but is not a symlink", | 412 source_file = format_string("%s/GPIO.%d/GPIO.%s", |
| 389 os_path_abspath(symlink).c_str()); | 413 acpi_root, |
| 390 | 414 i->index, |
| 391 if (os_readlink(symlink) != source_file) | 415 GPIO_ATTRIBUTES_EXTENSION); |
| 392 GpioSetupError("%s points to a wrong file", | 416 CreateSymLink(source_file, symlink); |
| 393 os_path_abspath(symlink).c_str()); | |
| 394 } | 417 } |
| 395 } | 418 } |
| 396 | 419 |
| 397 static const char *__name__ = ""; | 420 static const char *__name__ = ""; |
| 398 static void usage_help_exit(int ret) { | 421 static void usage_help_exit(int ret) { |
| 399 printf( | 422 printf( |
| 400 "Usage: %s [options]\n" | 423 "Usage: %s [options]\n" |
| 401 "\n" | 424 "\n" |
| 402 "Options:\n" | 425 "Options:\n" |
| 403 " -h, --help \t show this help message and exit\n" | 426 " -h, --help \t show this help message and exit\n" |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 452 } | 475 } |
| 453 | 476 |
| 454 // currently no other non-dashed arguments allowed. | 477 // currently no other non-dashed arguments allowed. |
| 455 if (optind != argc) | 478 if (optind != argc) |
| 456 usage_help_exit(1); | 479 usage_help_exit(1); |
| 457 | 480 |
| 458 GpioChip gpioc(cmd_line_options.pci_address); | 481 GpioChip gpioc(cmd_line_options.pci_address); |
| 459 gpioc.Attach(); | 482 gpioc.Attach(); |
| 460 CreateGpioSymlinks( | 483 CreateGpioSymlinks( |
| 461 ParseAcpiMappings(cmd_line_options.acpi_root), | 484 ParseAcpiMappings(cmd_line_options.acpi_root), |
| 462 gpioc, cmd_line_options.symlink_root.c_str()); | 485 gpioc, |
| 486 cmd_line_options.acpi_root.c_str(), |
| 487 cmd_line_options.symlink_root.c_str()); |
| 463 return 0; | 488 return 0; |
| 464 } | 489 } |
| OLD | NEW |