lspci.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2018 K. Lange
  5. *
  6. * lspci - Print information about connected PCI devices.
  7. *
  8. */
  9. #include <stdio.h>
  10. #include <unistd.h>
  11. #include <errno.h>
  12. #include <string.h>
  13. struct device_class {
  14. char * code;
  15. char * name;
  16. } device_classes[] = {
  17. {"0101", "IDE interface"},
  18. {"0102", "Floppy disk controller"},
  19. {"0105", "ATA controller"},
  20. {"0106", "SATA controller"},
  21. {"0200", "Ethernet controller"},
  22. {"0280", "Network controller"},
  23. {"0300", "VGA compatible controller"},
  24. {"0380", "Display controller"},
  25. {"0401", "Multimedia audio controller"},
  26. {"0403", "Audio device"},
  27. {"0480", "Multimedia controller"},
  28. {"0600", "Host bridge"},
  29. {"0601", "ISA bridge"},
  30. {"0604", "PCI bridge"},
  31. {"0680", "Bridge"},
  32. {"0880", "System peripheral"},
  33. {NULL, NULL},
  34. };
  35. static void show_usage(char * argv[]) {
  36. fprintf(stderr,
  37. "lspci - show information about PCI devices\n"
  38. "\n"
  39. "usage: %s [-n]\n"
  40. "\n"
  41. " -n \033[3mshow numeric device codes\033[0m\n"
  42. " -? \033[3mshow this help text\033[0m\n"
  43. "\n", argv[0]);
  44. }
  45. int main(int argc, char * argv[]) {
  46. int numeric = 0;
  47. int opt;
  48. while ((opt = getopt(argc, argv, "n?")) != -1) {
  49. switch (opt) {
  50. case '?':
  51. show_usage(argv);
  52. return 0;
  53. case 'n':
  54. numeric = 1;
  55. break;
  56. }
  57. }
  58. FILE * f = fopen("/proc/pci","r");
  59. if (!f) {
  60. fprintf(stderr, "%s: %s: %s\n", argv[0], "/proc/pci", strerror(errno));
  61. return 1;
  62. }
  63. while (!feof(f)) {
  64. char line[1024];
  65. fgets(line, 1024, f);
  66. if (line[0] == ' ') {
  67. /* Skip; don't care about this information */
  68. continue;
  69. }
  70. /* Read bus, etc. verbatim */
  71. char * device_bus = line;
  72. /* Read device class */
  73. char * device_class = strstr(line," (");
  74. if (!device_class) {
  75. fprintf(stderr, "%s: parse error\n", argv[0]);
  76. return 1;
  77. }
  78. *device_class = '\0';
  79. device_class++; /* space */
  80. device_class++; /* ( */
  81. char * device_vendor = strstr(device_class, ", ");
  82. if (!device_vendor) {
  83. fprintf(stderr, "%s: parse error\n", argv[0]);
  84. return 1;
  85. }
  86. *device_vendor = '\0';
  87. device_vendor++; /* comma */
  88. device_vendor++; /* space */
  89. char * device_code = strstr(device_vendor, ":");
  90. if (!device_code) {
  91. fprintf(stderr, "%s: parse error\n", argv[0]);
  92. return 1;
  93. }
  94. *device_code = '\0';
  95. device_code++; /* colon */
  96. char * device_name = strstr(device_code, ") ");
  97. if (!device_name) {
  98. fprintf(stderr, "%s: parse error\n", argv[0]);
  99. return 1;
  100. }
  101. *device_name = '\0';
  102. device_name++; /* ) */
  103. device_name++; /* space */
  104. char * linefeed = strstr(device_name, "\n");
  105. if (linefeed) *linefeed = '\0';
  106. if (numeric) {
  107. fprintf(stdout, "%s %s: %s:%s\n", device_bus, device_class, device_vendor, device_code);
  108. } else {
  109. for (struct device_class * c = device_classes; c->code; ++c) {
  110. if (!strcmp(device_class, c->code)) {
  111. device_class = c->name;
  112. break;
  113. }
  114. }
  115. /* TODO: We should also look up vendor + device names ourselves and possibly remove them from the kernel */
  116. fprintf(stdout, "%s %s: %s\n", device_bus, device_class, device_name);
  117. }
  118. }
  119. return 0;
  120. }