-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathinterface.c
144 lines (125 loc) · 3.82 KB
/
interface.c
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
/*
* interface.c
*
* handle all struct usb_interface logic
*
* Copyright (C) 2009 Greg Kroah-Hartman <[email protected]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*/
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stddef.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <getopt.h>
#include <syslog.h>
#include <fcntl.h>
#include <poll.h>
#include <limits.h>
#include <dirent.h>
#include <ctype.h>
#include <sys/select.h>
#include <sys/stat.h>
#define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE
#include <libudev.h>
#include "list.h"
#include "usb.h"
#include "lsusb.h"
static struct usb_interface *new_usb_interface(void)
{
return robust_malloc(sizeof(struct usb_interface));
}
void free_usb_interface(struct usb_interface *usb_intf)
{
free(usb_intf->driver);
free(usb_intf->sysname);
free(usb_intf->bAlternateSetting);
free(usb_intf->bInterfaceClass);
free(usb_intf->bInterfaceNumber);
free(usb_intf->bInterfaceProtocol);
free(usb_intf->bInterfaceSubClass);
free(usb_intf->bNumEndpoints);
free(usb_intf);
}
static void create_usb_interface_endpoints(struct udev_device *device, struct usb_interface *usb_intf)
{
struct usb_endpoint *ep;
struct dirent *dirent;
DIR *dir;
dir = opendir(udev_device_get_syspath(device));
if (dir == NULL)
exit(1);
while ((dirent = readdir(dir)) != NULL) {
if (dirent->d_type != DT_DIR)
continue;
/* endpoints all start with "ep_" */
if ((dirent->d_name[0] != 'e') ||
(dirent->d_name[1] != 'p') ||
(dirent->d_name[2] != '_'))
continue;
ep = create_usb_endpoint(device, dirent->d_name);
list_add_tail(&ep->list, &usb_intf->endpoints);
}
closedir(dir);
}
void create_usb_interface(struct udev_device *device, struct usb_device *usb_device)
{
struct usb_interface *usb_intf;
struct udev_device *interface;
const char *driver_name;
int temp_file;
struct dirent *dirent;
char file[PATH_MAX];
DIR *dir;
dir = opendir(udev_device_get_syspath(device));
if (dir == NULL)
exit(1);
while ((dirent = readdir(dir)) != NULL) {
if (dirent->d_type != DT_DIR)
continue;
/*
* As the devnum isn't in older kernels, we need to guess to
* try to find the interfaces.
*
* If the first char is a digit, and bInterfaceClass is in the
* subdir, then odds are it's a child interface
*/
if (!isdigit(dirent->d_name[0]))
continue;
sprintf(file, "%s/%s/bInterfaceClass",
udev_device_get_syspath(device), dirent->d_name);
temp_file = open(file, O_RDONLY);
if (temp_file == -1)
continue;
close(temp_file);
sprintf(file, "%s/%s", udev_device_get_syspath(device),
dirent->d_name);
interface = udev_device_new_from_syspath(udev, file);
if (interface == NULL) {
fprintf(stderr, "can't get interface for %s?\n", file);
continue;
}
usb_intf = new_usb_interface();
INIT_LIST_HEAD(&usb_intf->endpoints);
usb_intf->bAlternateSetting = get_dev_string(interface, "bAlternateSetting");
usb_intf->bInterfaceClass = get_dev_string(interface, "bInterfaceClass");
usb_intf->bInterfaceNumber = get_dev_string(interface, "bInterfaceNumber");
usb_intf->bInterfaceProtocol = get_dev_string(interface, "bInterfaceProtocol");
usb_intf->bInterfaceSubClass = get_dev_string(interface, "bInterfaceSubClass");
usb_intf->bNumEndpoints = get_dev_string(interface, "bNumEndpoints");
usb_intf->sysname = strdup(udev_device_get_sysname(interface));
driver_name = udev_device_get_driver(interface);
if (driver_name)
usb_intf->driver = strdup(driver_name);
list_add_tail(&usb_intf->list, &usb_device->interfaces);
/* find all endpoints for this interface, and save them */
create_usb_interface_endpoints(interface, usb_intf);
udev_device_unref(interface);
}
closedir(dir);
}