summaryrefslogtreecommitdiff
path: root/com32/lua/src/pci.c
blob: c367ba9ac702886fb42035d547011072eed63f7b (plain)
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define lpcilib_c       /* Define the library */

#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include <sys/pci.h>

/* removing any \n found in a string */
static void remove_eol(char *string)
{
    int j = strlen(string);
    int i = 0;
    for (i = 0; i < j; i++)
        if (string[i] == '\n')
            string[i] = 0;
}

static int pci_getinfo(lua_State *L)
{
  struct pci_domain *pci_domain;
  struct pci_device *pci_device;
  int pci_dev = 1;

  pci_domain = pci_scan();

  lua_newtable(L);	/* list of busses */

  for_each_pci_func(pci_device, pci_domain) {
    lua_pushnumber(L, pci_dev++);

    lua_newtable(L); /* device infos */

    lua_pushstring(L, "bus");
    lua_pushnumber(L, __pci_bus);
    lua_settable(L,-3);

    lua_pushstring(L, "slot");
    lua_pushnumber(L, __pci_slot);
    lua_settable(L,-3);

    lua_pushstring(L, "func");
    lua_pushnumber(L, __pci_func);
    lua_settable(L,-3);

    lua_pushstring(L, "vendor");
    lua_pushnumber(L, pci_device->vendor);
    lua_settable(L,-3);

    lua_pushstring(L, "product");
    lua_pushnumber(L, pci_device->product);
    lua_settable(L,-3);

    lua_pushstring(L, "sub_vendor");
    lua_pushnumber(L, pci_device->sub_vendor);
    lua_settable(L,-3);

    lua_pushstring(L, "sub_product");
    lua_pushnumber(L, pci_device->sub_product);
    lua_settable(L,-3);

    lua_settable(L,-3); /* end device infos */
  }

  return 1;
}

/* Try to match any pci device to the appropriate kernel module */
/* it uses the modules.pcimap from the boot device*/
static int pci_getidlist(lua_State *L)
{
  const char *pciidfile;
  char line[1024];
  char vendor[255];
  char vendor_id[5];
  char product[255];
  char productvendor[9];
  char productvendorsub[17];
  FILE *f;

  if (lua_gettop(L) == 1) {
    pciidfile = luaL_checkstring(L, 1);
  } else {
    pciidfile = "pci.ids";
  }

  lua_newtable(L);	/* list of vendors */

  /* Opening the pci.ids from the boot device*/
  f=fopen(pciidfile,"r");
  if (!f)
        return -1;

  /* for each line we found in the pci.ids*/
  while ( fgets(line, sizeof line, f) ) {
    /* Skipping uncessary lines */
    if ((line[0] == '#') || (line[0] == ' ') || (line[0] == 'C') ||
	(line[0] == 10))
        continue;

    /* If the line doesn't start with a tab, it means that's a vendor id */
    if (line[0] != '\t') {

	/* the 4th first chars are the vendor_id */
        strlcpy(vendor_id,line,4);

	/* the vendor name is the next field*/
        vendor_id[4]=0;
        strlcpy(vendor,skipspace(strstr(line," ")),255);
        remove_eol(vendor);

	/* ffff is an invalid vendor id */
	if (strstr(vendor_id,"ffff")) break;

	lua_pushstring(L, vendor_id);
	lua_pushstring(L, vendor);
	lua_settable(L,-3);

    /* if we have a tab + a char, it means this is a product id */
    } else if ((line[0] == '\t') && (line[1] != '\t')) {

	/* the product name the second field */
        strlcpy(product,skipspace(strstr(line," ")),255);
        remove_eol(product);

	/* the 4th first chars are the vendor_id */
	strlcpy(productvendor,vendor_id,4);
	/* the product id is first field */
	strlcpy(productvendor+4,&line[1],4);
        productvendor[8]=0;

	lua_pushstring(L, productvendor);
	lua_pushstring(L, product);
	lua_settable(L,-3);

    /* if we have two tabs, it means this is a sub product */
    } else if ((line[0] == '\t') && (line[1] == '\t')) {

      /* the product name is last field */
      strlcpy(product,skipspace(strstr(line," ")),255);
      strlcpy(product,skipspace(strstr(product," ")),255);
      remove_eol(product);

      strlcpy(productvendorsub, productvendor,8);
      strlcpy(productvendorsub+8, &line[2],4);
      strlcpy(productvendorsub+12, &line[7],4);
      productvendorsub[16]=0;

      lua_pushstring(L, productvendorsub);
      lua_pushstring(L, product);
      lua_settable(L,-3);

    }
  }
  fclose(f);
  return(1);
}

static const luaL_reg pcilib[] = {
  {"getinfo", pci_getinfo},
  {"getidlist", pci_getidlist},
  {NULL, NULL}
};

/* This defines a function that opens up your library. */

LUALIB_API int luaopen_pci (lua_State *L) {
  luaL_openlib(L, LUA_PCILIBNAME, pcilib, 0);
  return 1;
}