1 /*
2 * Copyright (c) 2012 Adrien Guinet <adrien@guinet.me>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * Neither the name of Adrien Guinet nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include <iostream>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <memory.h>
35 #include <pcap/pcap.h>
36
37 #include <usbtop/buses.h>
38
39 #include <tuple>
40
41 #if defined(__FreeBSD__)
42 #define USB_DEVICE_START "usbus"
43 #else
44 #define USB_DEVICE_START "usbmon"
45 #endif
46
47 static size_t g_len_usb_dev_start = strlen(USB_DEVICE_START);
48
49 std::map<usbtop::UsbBus::id_type, usbtop::UsbBus> usbtop::UsbBuses::_buses;
50 bool usbtop::UsbBuses::_populated = false;
51
list(bus_func_t f,const char * filter)52 void usbtop::UsbBuses::list(bus_func_t f, const char* filter)
53 {
54 char errbuf[PCAP_ERRBUF_SIZE];
55 pcap_if_t* list_devs;
56 if (pcap_findalldevs(&list_devs, errbuf) < 0) {
57 std::cerr << "Unable to list available devices: " << errbuf << std::endl;
58 pcap_freealldevs(list_devs);
59 exit(1);
60 }
61
62 pcap_if_t* cur_dev = list_devs;
63 while (cur_dev) {
64 if (cur_dev->name) {
65 if ((strlen(cur_dev->name) > g_len_usb_dev_start) &&
66 (!filter || (filter && strcmp(cur_dev->name, filter) == 0)) &&
67 (memcmp(cur_dev->name, USB_DEVICE_START, g_len_usb_dev_start) == 0)) {
68 size_t bus_id = atoll(&cur_dev->name[g_len_usb_dev_start]);
69 f(bus_id, cur_dev->name, cur_dev->description);
70 }
71 }
72 cur_dev = cur_dev->next;
73 }
74
75 pcap_freealldevs(list_devs);
76 }
77
show(const char * filter)78 void usbtop::UsbBuses::show(const char* filter)
79 {
80 printf("Name\t\tDescription\n");
81 printf("---------------------------\n");
82 list([](UsbBus::id_type /*bus_id*/, const char* name, const char* desc)
83 {
84 printf("%s", name);
85 if (desc) {
86 printf("\t\t%s", desc);
87 }
88 printf("\n");
89 }, filter);
90 }
91
populate(const char * filter)92 void usbtop::UsbBuses::populate(const char* filter)
93 {
94 if (_populated) {
95 return;
96 }
97
98 list([](UsbBus::id_type bus_id, const char* name, const char* desc)
99 {
100 add_bus(bus_id, name, desc);
101 }, filter);
102 _populated = true;
103 }
104
add_bus(UsbBus::id_type bus_id,const char * name,const char * desc)105 void usbtop::UsbBuses::add_bus(UsbBus::id_type bus_id, const char* name, const char* desc)
106 {
107 _buses.emplace(std::piecewise_construct,
108 std::forward_as_tuple(bus_id),
109 std::forward_as_tuple(bus_id, name, desc));
110 }
111
get_bus(UsbBus::id_type bus_id)112 usbtop::UsbBus* usbtop::UsbBuses::get_bus(UsbBus::id_type bus_id)
113 {
114 list_buses_t::iterator it = _buses.find(bus_id);
115 if (it == _buses.end()) {
116 return NULL;
117 }
118
119 return &it->second;
120 }
121
size()122 size_t usbtop::UsbBuses::size()
123 {
124 return _buses.size();
125 }
126