1
2
3
4
5 package oshi.hardware.platform.windows;
6
7 import java.util.ArrayList;
8 import java.util.Collections;
9 import java.util.List;
10 import java.util.Map;
11 import java.util.Map.Entry;
12 import java.util.Set;
13 import java.util.stream.Collectors;
14
15 import com.sun.jna.platform.win32.Guid.GUID;
16
17 import oshi.annotation.concurrent.Immutable;
18 import oshi.driver.windows.DeviceTree;
19 import oshi.hardware.UsbDevice;
20 import oshi.hardware.common.AbstractUsbDevice;
21 import oshi.util.ParseUtil;
22 import oshi.util.tuples.Quintet;
23 import oshi.util.tuples.Triplet;
24
25
26
27
28 @Immutable
29 public class WindowsUsbDevice extends AbstractUsbDevice {
30
31 private static final GUID GUID_DEVINTERFACE_USB_HOST_CONTROLLER = new GUID(
32 "{3ABF6F2D-71C4-462A-8A92-1E6861E6AF27}");
33
34 public WindowsUsbDevice(String name, String vendor, String vendorId, String productId, String serialNumber,
35 String uniqueDeviceId, List<UsbDevice> connectedDevices) {
36 super(name, vendor, vendorId, productId, serialNumber, uniqueDeviceId, connectedDevices);
37 }
38
39
40
41
42
43
44
45
46
47
48
49
50
51 public static List<UsbDevice> getUsbDevices(boolean tree) {
52 List<UsbDevice> devices = queryUsbDevices();
53 if (tree) {
54 return devices;
55 }
56 List<UsbDevice> deviceList = new ArrayList<>();
57
58
59 for (UsbDevice device : devices) {
60
61 addDevicesToList(deviceList, device.getConnectedDevices());
62 }
63 return deviceList;
64 }
65
66 private static void addDevicesToList(List<UsbDevice> deviceList, List<UsbDevice> list) {
67 for (UsbDevice device : list) {
68 deviceList.add(new WindowsUsbDevice(device.getName(), device.getVendor(), device.getVendorId(),
69 device.getProductId(), device.getSerialNumber(), device.getUniqueDeviceId(),
70 Collections.emptyList()));
71 addDevicesToList(deviceList, device.getConnectedDevices());
72 }
73 }
74
75 private static List<UsbDevice> queryUsbDevices() {
76 Quintet<Set<Integer>, Map<Integer, Integer>, Map<Integer, String>, Map<Integer, String>, Map<Integer, String>> controllerDevices = DeviceTree
77 .queryDeviceTree(GUID_DEVINTERFACE_USB_HOST_CONTROLLER);
78 Map<Integer, Integer> parentMap = controllerDevices.getB();
79 Map<Integer, String> nameMap = controllerDevices.getC();
80 Map<Integer, String> deviceIdMap = controllerDevices.getD();
81 Map<Integer, String> mfgMap = controllerDevices.getE();
82
83 List<UsbDevice> usbDevices = new ArrayList<>();
84
85 for (Integer controllerDevice : controllerDevices.getA()) {
86 WindowsUsbDevice deviceAndChildren = queryDeviceAndChildren(controllerDevice, parentMap, nameMap,
87 deviceIdMap, mfgMap, "0000", "0000", "");
88 if (deviceAndChildren != null) {
89 usbDevices.add(deviceAndChildren);
90 }
91 }
92 return usbDevices;
93 }
94
95 private static WindowsUsbDevice queryDeviceAndChildren(Integer device, Map<Integer, Integer> parentMap,
96 Map<Integer, String> nameMap, Map<Integer, String> deviceIdMap, Map<Integer, String> mfgMap, String vid,
97 String pid, String parentSerial) {
98
99
100 String vendorId = vid;
101 String productId = pid;
102 String serial = parentSerial;
103 Triplet<String, String, String> idsAndSerial = ParseUtil
104 .parseDeviceIdToVendorProductSerial(deviceIdMap.get(device));
105 if (idsAndSerial != null) {
106 vendorId = idsAndSerial.getA();
107 productId = idsAndSerial.getB();
108 serial = idsAndSerial.getC();
109 if (serial.isEmpty() && vendorId.equals(vid) && productId.equals(pid)) {
110 serial = parentSerial;
111 }
112 }
113
114 Set<Integer> childDeviceSet = parentMap.entrySet().stream().filter(e -> e.getValue().equals(device))
115 .map(Entry::getKey).collect(Collectors.toSet());
116
117 List<UsbDevice> childDevices = new ArrayList<>();
118 for (Integer child : childDeviceSet) {
119 WindowsUsbDevice deviceAndChildren = queryDeviceAndChildren(child, parentMap, nameMap, deviceIdMap, mfgMap,
120 vendorId, productId, serial);
121 if (deviceAndChildren != null) {
122 childDevices.add(deviceAndChildren);
123 }
124 }
125 Collections.sort(childDevices);
126
127 if (nameMap.containsKey(device)) {
128 String name = nameMap.get(device);
129 if (name.isEmpty()) {
130 name = vendorId + ":" + productId;
131 }
132 String deviceId = deviceIdMap.get(device);
133 String mfg = mfgMap.get(device);
134 return new WindowsUsbDevice(name, mfg, vendorId, productId, serial, deviceId, childDevices);
135 }
136 return null;
137 }
138 }