1 /*****************************************************************************\
3 * | || | ___ | |_ _ __ | | _ _ __ _ |_ ) *
4 * | __ |/ _ \| _|| '_ \| || || |/ _` | / / *
5 * |_||_|\___/ \__|| .__/|_| \_,_|\__, |/___| *
7 \*****************************************************************************/
18 #include <sys/socket.h>
19 #include <sys/types.h>
24 #include <linux/types.h>
25 #include <linux/netlink.h>
27 #include "../hotplug2.h"
28 #include "../mem_utils.h"
29 #include "../parser_utils.h"
30 #include "../filemap_utils.h"
31 #include "../hotplug2_utils.h"
33 inline char *get_uevent_string(char **environ
, unsigned long *uevent_string_len
) {
38 *uevent_string_len
= 4;
39 offset
= *uevent_string_len
- 1;
40 uevent_string
= xmalloc(*uevent_string_len
);
41 strcpy(uevent_string
, "add");
42 uevent_string
[offset
] = '@';
45 for (; *environ
!= NULL
; environ
++) {
46 *uevent_string_len
+= strlen(*environ
) + 1;
47 uevent_string
= xrealloc(uevent_string
, *uevent_string_len
);
48 strcpy(&uevent_string
[offset
], *environ
);
49 offset
= *uevent_string_len
;
52 /* 64 + 7 ('SEQNUM=') + 1 ('\0') */
55 snprintf(tmp
, 72, "SEQNUM=%llu", get_kernel_seqnum());
57 *uevent_string_len
+= strlen(tmp
) + 1;
58 uevent_string
= xrealloc(uevent_string
, *uevent_string_len
);
59 strcpy(&uevent_string
[offset
], tmp
);
60 offset
= *uevent_string_len
;
67 int dispatch_event(int netlink_socket
, char **environ
) {
69 unsigned long uevent_string_len
;
71 uevent_string
= get_uevent_string(environ
, &uevent_string_len
);
72 if (uevent_string
== NULL
) {
73 ERROR("dispatch_event", "Unable to create uevent string.");
77 if (send(netlink_socket
, uevent_string
, uevent_string_len
, 0) == -1) {
78 ERROR("dispatch_event","send failed: %s.", strerror(errno
));
88 char *join_to_fourhex(unsigned char hex0
, unsigned char hex1
) {
93 snprintf(tmp
, 4, "%x%2x", hex0
, hex1
);
95 snprintf(tmp
, 4, "%x", hex1
);
101 void generate_pci_events(int netlink_socket
) {
102 unsigned char pci_desc_info
[256];
103 char pci_dir_name
[256];
104 char pci_dev_name
[512];
109 DIR *procdir
, *pcidir
;
111 struct dirent
*cur_bus
, *cur_device
;
113 procdir
= opendir("/proc/bus/pci");
114 if (procdir
== NULL
) {
115 ERROR("pci coldplug", "Unable to open procfs PCI interface.");
119 while ((cur_bus
= readdir(procdir
)) != NULL
) {
120 if (cur_bus
->d_type
!= DT_DIR
)
123 if (cur_bus
->d_name
[0] == '.')
126 memset(pci_dir_name
, 0, 256);
127 snprintf(pci_dir_name
, 255, "/proc/bus/pci/%s", cur_bus
->d_name
);
128 pcidir
= opendir(pci_dir_name
);
130 while ((cur_device
= readdir(pcidir
)) != NULL
) {
131 if (cur_device
->d_type
!= DT_REG
)
134 if (cur_device
->d_name
[0] == '.')
137 memset(pci_dev_name
, 0, 256);
138 snprintf(pci_dev_name
, 511, "/proc/bus/pci/%s/%s", cur_bus
->d_name
, cur_device
->d_name
);
139 item
= fopen(pci_dev_name
, "rb");
142 ERROR("pci coldplug", "Missing PCI entry.");
146 fread(pci_desc_info
, 256, 1, item
);
150 environ
= xmalloc(sizeof(char*) * 8);
160 environ
[0] = strdup("ACTION=add");
161 environ
[1] = strdup("SUBSYSTEM=pci");
163 environ
[2] = xmalloc(21 + strlen(cur_bus
->d_name
) + strlen(cur_device
->d_name
));
164 strcpy(environ
[2], "PCI_SLOT_NAME=0000:");
165 strcat(environ
[2], cur_bus
->d_name
);
166 strcat(environ
[2], ":");
167 strcat(environ
[2], cur_device
->d_name
);
169 environ
[3] = xmalloc(17);
170 snprintf(environ
[3], 17, "PCI_ID=%02X%02X:%02X%02X", pci_desc_info
[1], pci_desc_info
[0], pci_desc_info
[3], pci_desc_info
[2]);
172 environ
[4] = xmalloc(24);
173 snprintf(environ
[4], 24, "PCI_SUBSYS_ID=%02X%02X:%02X%02X", pci_desc_info
[45], pci_desc_info
[44], pci_desc_info
[47], pci_desc_info
[46]);
175 environ
[5] = xmalloc(17);
176 snprintf(environ
[5], 17, "PCI_CLASS=%x%02X%02X", pci_desc_info
[11], pci_desc_info
[10], pci_desc_info
[9]);
178 environ
[6] = xmalloc(64);
179 snprintf(environ
[6], 64, "MODALIAS=pci:v0000%02X%02Xd0000%02X%02Xsv0000%02X%02Xsd0000%02X%02Xbc%02Xsc%02Xi%02X",
180 pci_desc_info
[1], pci_desc_info
[0], pci_desc_info
[3], pci_desc_info
[2],
181 pci_desc_info
[45], pci_desc_info
[44], pci_desc_info
[47], pci_desc_info
[46],
182 pci_desc_info
[11], pci_desc_info
[10], pci_desc_info
[9]);
184 dispatch_event(netlink_socket
, environ
);
186 for (i
= 0; environ
[i
] != NULL
; i
++)
197 void generate_usb_events(int netlink_socket
) {
198 unsigned char usb_desc_info
[52];
199 char usb_dir_name
[256];
200 char usb_dev_name
[512];
206 DIR *procdir
, *usbdir
;
208 struct dirent
*cur_bus
, *cur_device
;
210 procdir
= opendir("/proc/bus/usb");
211 if (procdir
== NULL
) {
212 ERROR("usb coldplug", "Unable to open procfs usb interface.");
216 while ((cur_bus
= readdir(procdir
)) != NULL
) {
217 if (cur_bus
->d_type
!= DT_DIR
)
220 if (cur_bus
->d_name
[0] == '.')
223 memset(usb_dir_name
, 0, 256);
224 snprintf(usb_dir_name
, 255, "/proc/bus/usb/%s", cur_bus
->d_name
);
225 usbdir
= opendir(usb_dir_name
);
227 while ((cur_device
= readdir(usbdir
)) != NULL
) {
228 if (cur_device
->d_type
!= DT_REG
)
231 if (cur_device
->d_name
[0] == '.')
234 memset(usb_dev_name
, 0, 256);
235 snprintf(usb_dev_name
, 511, "/proc/bus/usb/%s/%s", cur_bus
->d_name
, cur_device
->d_name
);
236 item
= fopen(usb_dev_name
, "rb");
239 ERROR("usb coldplug", "Missing usb entry.");
243 fread(usb_desc_info
, 52, 1, item
);
246 environ
= xmalloc(sizeof(char*) * 8);
249 environ
[0] = strdup("ACTION=add");
250 environ
[1] = strdup("SUBSYSTEM=usb");
252 environ
[2] = xmalloc(8 + strlen(usb_dev_name
));
253 strcpy(environ
[2], "DEVICE=");
254 strcat(environ
[2], usb_dev_name
);
256 environ
[3] = xmalloc(24);
257 memset(environ
[3], 0, 24);
258 t1
= join_to_fourhex(usb_desc_info
[9], usb_desc_info
[8]);
259 t2
= join_to_fourhex(usb_desc_info
[11], usb_desc_info
[10]);
260 t3
= join_to_fourhex(usb_desc_info
[13], usb_desc_info
[12]);
262 snprintf(environ
[3], 23, "PRODUCT=%s/%s/%s", t1
, t2
, t3
);
264 free(t1
); free(t2
); free(t3
);
266 environ
[4] = xmalloc(14);
267 memset(environ
[4], 0, 14);
268 snprintf(environ
[4], 13, "TYPE=%x/%x/%x", usb_desc_info
[4], usb_desc_info
[5], usb_desc_info
[6]);
270 environ
[5] = xmalloc(55);
271 memset(environ
[5], 0, 55);
273 if (usb_desc_info
[32] != 0x0 && usb_desc_info
[33] != 0x0 && usb_desc_info
[34] != 0x0) {
274 snprintf(environ
[5], 55, "MODALIAS=usb:v%02X%02Xp%02X%02Xd%02X%02Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X",
275 usb_desc_info
[9], usb_desc_info
[8], usb_desc_info
[11], usb_desc_info
[10], usb_desc_info
[13], usb_desc_info
[12],
276 usb_desc_info
[4], usb_desc_info
[5], usb_desc_info
[6],
277 usb_desc_info
[32], usb_desc_info
[33], usb_desc_info
[34]);
279 environ
[6] = xmalloc(24);
280 memset(environ
[6], 0, 24);
281 snprintf(environ
[6], 24, "INTERFACE=%x/%x/%x", usb_desc_info
[32], usb_desc_info
[33], usb_desc_info
[34]);
283 snprintf(environ
[5], 55, "MODALIAS=usb:v%02X%02Xp%02X%02Xd%02X%02Xdc%02Xdsc%02Xdp%02Xic*isc*ip*",
284 usb_desc_info
[9], usb_desc_info
[8], usb_desc_info
[11], usb_desc_info
[10], usb_desc_info
[13], usb_desc_info
[12],
285 usb_desc_info
[4], usb_desc_info
[5], usb_desc_info
[6]);
290 dispatch_event(netlink_socket
, environ
);
292 for (i
= 0; environ
[i
] != NULL
; i
++)
303 void generate_isapnp_events(int netlink_socket
) {
304 struct filemap_t isapnpmap
;
306 char *line
, *nline
, *nptr
;
311 if (map_file("/proc/bus/isapnp/devices", &isapnpmap
)) {
312 ERROR("isapnp coldplug", "Unable to open procfs isapnp interface.");
316 nptr
= isapnpmap
.map
;
318 while ((line
= dup_line(nptr
, &nptr
)) != NULL
) {
320 token
= dup_token(nline
, &nline
, isspace
);
325 token
= dup_token(nline
, &nline
, isspace
);
329 if (strlen(token
) < 14) {
334 environ
= xmalloc(sizeof(char*) * 4);
337 environ
[0] = strdup("ACTION=add");
338 environ
[1] = strdup("SUBSYSTEM=pnp");
340 environ
[2] = xmalloc(14);
341 strcpy(environ
[2], "MODALIAS=pnp:");
342 for (device
= &token
[7]; *device
!= '\0'; device
+= 7) {
343 environ
[2] = xrealloc(environ
[2], 14 + device
- token
);
344 memcpy(environ
[2] + (device
- token
) + 6, device
, 7);
345 environ
[2][13 + device
- token
] = '\0';
348 dispatch_event(netlink_socket
, environ
);
350 for (i
= 0; environ
[i
] != NULL
; i
++)
358 unmap_file(&isapnpmap
);
361 int main(int argc
, char *argv
[], char **environ
) {
364 netlink_socket
= init_netlink_socket(NETLINK_CONNECT
);
365 if (netlink_socket
== -1) {
366 ERROR("netlink init","Unable to open netlink socket.");
370 generate_pci_events(netlink_socket
);
371 generate_usb_events(netlink_socket
);
372 generate_isapnp_events(netlink_socket
);
374 close(netlink_socket
);