26
26
// Internal Includes
27
27
#include " USBSerialDevInfo.h"
28
28
29
- // Library/third-party includes
30
- #include < boost/filesystem.hpp>
31
- #include < boost/range/iterator_range.hpp>
32
- #include < boost/algorithm/string.hpp>
33
-
34
- // Standard includes
35
- #include < iostream>
36
- #include < vector>
37
- #include < string>
38
- #include < fstream>
39
-
40
- #include < fcntl.h> // for O_NONBLOCK
41
- #include < sys/ioctl.h> // for ioctl
42
- #include < unistd.h> // for open, close
43
-
44
- // IOKit includes
29
+
30
+ // System includes
31
+ #include < CoreFoundation/CoreFoundation.h>
45
32
#include < IOKit/IOKitLib.h>
46
- #include < IOKit/usb/IOUSBLib.h>
33
+ #include < IOKit/IOKitKeys.h>
34
+ #include < IOKit/serial/IOSerialKeys.h>
47
35
48
36
namespace osvr {
49
37
namespace usbserial {
50
38
51
39
namespace {
52
40
53
41
/* *
54
- * Given the name of a device, this function will create a
55
- *USBSerialDevice
56
- * object. If the device can be created successfully it will return
57
- * @c boost::none.
58
- *
59
- * @param device The name of the device to create (e.g., "ttyACM0")
60
- *
61
- * @return an optional USBSerialDevice
42
+ * Helper function that returns an IOKit iterator for all serial ports
43
+ * on the system.
44
+ * @param matchingServices pointer which will be set to the value of the
45
+ * iterator
46
+ * @return 0 on success, -1 on failure
62
47
*/
63
- boost::optional<USBSerialDevice>
64
- make_USBSerialDevice (const std::string &device) {
65
- // FIXME: STUB
66
- return boost::none;
48
+ int findSerialPorts (io_iterator_t *matchingServices) {
49
+ // Query IOKit for services matching kIOSerialBSDServiceValue
50
+ CFMutableDictionaryRef classesToMatch =
51
+ IOServiceMatching (kIOSerialBSDServiceValue );
52
+ if (classesToMatch == NULL ) {
53
+ return false ;
54
+ }
55
+ // Query only for serial ports
56
+ CFDictionarySetValue (classesToMatch, CFSTR (kIOSerialBSDTypeKey ),
57
+ CFSTR (kIOSerialBSDAllTypes ));
58
+ // Run the query
59
+ kern_return_t kernResult = IOServiceGetMatchingServices (
60
+ kIOMasterPortDefault , classesToMatch, matchingServices);
61
+ if (KERN_SUCCESS != kernResult) {
62
+ return false ;
63
+ }
64
+ return true ;
67
65
}
68
66
69
67
/* *
@@ -87,15 +85,62 @@ namespace usbserial {
87
85
88
86
return (vendor_matches && product_matches);
89
87
}
90
-
91
- } // end namespace
88
+ }
92
89
93
90
std::vector<USBSerialDevice>
94
91
getSerialDeviceList (boost::optional<uint16_t > vendorID,
95
92
boost::optional<uint16_t > productID) {
96
93
97
- // FIXME: STUB
98
94
std::vector<USBSerialDevice> devices;
95
+
96
+ io_iterator_t serialPortIterator;
97
+ io_object_t serialPortService;
98
+ // find all serial ports
99
+ if (findSerialPorts (&serialPortIterator) == true ) {
100
+ // iterate over serial ports, getting vid and pid
101
+ while ((serialPortService = IOIteratorNext (serialPortIterator)) !=
102
+ 0 ) {
103
+ const CFNumberRef vidObj =
104
+ static_cast <CFNumberRef >(IORegistryEntrySearchCFProperty (
105
+ serialPortService, kIOServicePlane , CFSTR (" idVendor" ),
106
+ NULL , kIORegistryIterateRecursively |
107
+ kIORegistryIterateParents ));
108
+ const CFNumberRef pidObj =
109
+ static_cast <CFNumberRef >(IORegistryEntrySearchCFProperty (
110
+ serialPortService, kIOServicePlane , CFSTR (" idProduct" ),
111
+ NULL , kIORegistryIterateRecursively |
112
+ kIORegistryIterateParents ));
113
+ const CFStringRef bsdPathObj =
114
+ static_cast <CFStringRef >(IORegistryEntryCreateCFProperty (
115
+ serialPortService, CFSTR (kIOCalloutDeviceKey ),
116
+ kCFAllocatorDefault , 0 ));
117
+
118
+ if (!vidObj || !pidObj || !bsdPathObj) {
119
+ continue ;
120
+ }
121
+ // handle device
122
+ uint16_t vid, pid;
123
+ CFNumberGetValue (vidObj, kCFNumberSInt16Type , &vid);
124
+ CFNumberGetValue (pidObj, kCFNumberSInt16Type , &pid);
125
+
126
+ // convert the string object into a C-string
127
+ CFIndex bufferSize = CFStringGetMaximumSizeForEncoding (
128
+ CFStringGetLength (bsdPathObj),
129
+ kCFStringEncodingMacRoman ) +
130
+ sizeof (' \0 ' );
131
+ std::vector<char > bsdPathBuf (bufferSize);
132
+ CFStringGetCString (bsdPathObj, bsdPathBuf.data (), bufferSize,
133
+ kCFStringEncodingMacRoman );
134
+ // create the device
135
+ USBSerialDevice usb_serial_device (vid, pid, bsdPathBuf.data (),
136
+ bsdPathBuf.data ());
137
+ // check if IDs match and add
138
+ if (matches_ids (usb_serial_device, vendorID, productID)) {
139
+ devices.push_back (usb_serial_device);
140
+ }
141
+ }
142
+ }
143
+
99
144
return devices;
100
145
}
101
146
0 commit comments