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 |