|
@@ -1,6 +1,6 @@
|
1
|
1
|
//
|
2
|
2
|
// Serial.m
|
3
|
|
-// SerialGamepad / CaseLights
|
|
3
|
+// CaseLights
|
4
|
4
|
//
|
5
|
5
|
// For more informations refer to this document:
|
6
|
6
|
// https://developer.apple.com/library/mac/documentation/DeviceDrivers/Conceptual/WorkingWSerial/WWSerial_SerialDevs/SerialDevices.html
|
|
@@ -21,13 +21,28 @@
|
21
|
21
|
|
22
|
22
|
#import "Serial.h"
|
23
|
23
|
|
24
|
|
-kern_return_t findSerialPorts(io_iterator_t *matches);
|
25
|
|
-kern_return_t getSerialPortPath(io_iterator_t serialPortIterator, char **deviceFilePath, CFIndex maxPathCount, CFIndex maxPathSize);
|
|
24
|
+@interface Serial ()
|
|
25
|
+
|
|
26
|
+@property (assign) int fd;
|
|
27
|
+
|
|
28
|
++ (kern_return_t)findSerialPorts:(io_iterator_t *)matches;
|
|
29
|
++ (kern_return_t)getSerialPortPath:(io_iterator_t)serialPortIterator to:(char **)deviceFilePath with:(CFIndex)maxPathCount and:(CFIndex)maxPathSize;
|
|
30
|
+
|
|
31
|
+@end
|
26
|
32
|
|
27
|
33
|
@implementation Serial
|
28
|
34
|
|
29
|
35
|
@synthesize fd, portName;
|
30
|
36
|
|
|
37
|
+- (id)init {
|
|
38
|
+ self = [super init];
|
|
39
|
+ if (self != nil) {
|
|
40
|
+ fd = -1;
|
|
41
|
+ portName = nil;
|
|
42
|
+ }
|
|
43
|
+ return self;
|
|
44
|
+}
|
|
45
|
+
|
31
|
46
|
- (NSInteger)openPort {
|
32
|
47
|
// We need a port name
|
33
|
48
|
if (portName == nil) {
|
|
@@ -36,11 +51,15 @@ kern_return_t getSerialPortPath(io_iterator_t serialPortIterator, char **deviceF
|
36
|
51
|
}
|
37
|
52
|
|
38
|
53
|
// Check if there was already a port opened
|
39
|
|
- if (fd != -1) {
|
|
54
|
+ if (fd > -1) {
|
40
|
55
|
NSLog(@"Closing previously opened serial port \"%@\"!\n", portName);
|
41
|
56
|
close(fd);
|
42
|
57
|
}
|
43
|
58
|
|
|
59
|
+#ifdef DEBUG
|
|
60
|
+ NSLog(@"Opening serial port \"%@\"...\n", portName);
|
|
61
|
+#endif
|
|
62
|
+
|
44
|
63
|
// Open port read-only, without controlling terminal, non-blocking
|
45
|
64
|
fd = open([portName UTF8String], O_RDONLY | O_NOCTTY | O_NONBLOCK);
|
46
|
65
|
if (fd == -1) {
|
|
@@ -84,21 +103,70 @@ kern_return_t getSerialPortPath(io_iterator_t serialPortIterator, char **deviceF
|
84
|
103
|
return 0;
|
85
|
104
|
}
|
86
|
105
|
|
87
|
|
-- (NSInteger)hasData {
|
|
106
|
+- (void)closePort {
|
|
107
|
+#ifdef DEBUG
|
|
108
|
+ NSLog(@"Closing serial port \"%@\"...\n", portName);
|
|
109
|
+#endif
|
|
110
|
+
|
|
111
|
+ if (fd > -1) {
|
|
112
|
+ close(fd);
|
|
113
|
+ } else {
|
|
114
|
+ NSLog(@"Trying to close already closed port!\n");
|
|
115
|
+ }
|
|
116
|
+ fd = -1;
|
|
117
|
+}
|
|
118
|
+
|
|
119
|
+- (BOOL)isOpen {
|
|
120
|
+ if (fd > -1) {
|
|
121
|
+ return YES;
|
|
122
|
+ } else {
|
|
123
|
+ return NO;
|
|
124
|
+ }
|
|
125
|
+}
|
|
126
|
+
|
|
127
|
+- (BOOL)hasData {
|
|
128
|
+ if (fd < 0) {
|
|
129
|
+ NSLog(@"Error trying to poll a closed port!\n");
|
|
130
|
+ return NO;
|
|
131
|
+ }
|
|
132
|
+
|
88
|
133
|
struct pollfd fds;
|
89
|
134
|
fds.fd = fd;
|
90
|
135
|
fds.events = (POLLIN | POLLPRI); // Data may be read
|
91
|
|
- if (poll(&fds, 1, 0) > 0) {
|
92
|
|
- return 1;
|
|
136
|
+ int val = poll(&fds, 1, 0);
|
|
137
|
+ if (val > 0) {
|
|
138
|
+ return YES;
|
|
139
|
+ } else if (val == 0) {
|
|
140
|
+ return NO;
|
93
|
141
|
} else {
|
94
|
|
- return 0;
|
|
142
|
+ NSLog(@"Error polling serial port: %s (%d)!\n", strerror(errno), errno);
|
|
143
|
+ return NO;
|
|
144
|
+ }
|
|
145
|
+}
|
|
146
|
+
|
|
147
|
+- (void)sendString:(NSString *)string {
|
|
148
|
+ if (fd < 0) {
|
|
149
|
+ NSLog(@"Error trying to send to a closed port!\n");
|
|
150
|
+ return;
|
|
151
|
+ }
|
|
152
|
+
|
|
153
|
+ const char *data = [string UTF8String];
|
|
154
|
+ size_t length = strlen(data);
|
|
155
|
+ ssize_t sent = 0;
|
|
156
|
+ while (sent < length) {
|
|
157
|
+ ssize_t ret = write(fd, data + sent, length - sent);
|
|
158
|
+ if (ret < 0) {
|
|
159
|
+ NSLog(@"Error writing to serial port: %s (%d)!\n", strerror(errno), errno);
|
|
160
|
+ } else {
|
|
161
|
+ sent += ret;
|
|
162
|
+ }
|
95
|
163
|
}
|
96
|
164
|
}
|
97
|
165
|
|
98
|
166
|
+ (NSArray *)listSerialPorts {
|
99
|
167
|
// Get Iterator with all serial ports
|
100
|
168
|
io_iterator_t serialPortIterator;
|
101
|
|
- kern_return_t kernResult = findSerialPorts(&serialPortIterator);
|
|
169
|
+ kern_return_t kernResult = [Serial findSerialPorts:&serialPortIterator];
|
102
|
170
|
|
103
|
171
|
// Create 2D array
|
104
|
172
|
char **portList;
|
|
@@ -106,7 +174,7 @@ kern_return_t getSerialPortPath(io_iterator_t serialPortIterator, char **deviceF
|
106
|
174
|
for (int i = 0; i < 100; i++) portList[i] = malloc(200 * sizeof(char));
|
107
|
175
|
|
108
|
176
|
// Copy device name into C-String array
|
109
|
|
- kernResult = getSerialPortPath(serialPortIterator, portList, 100, 200);
|
|
177
|
+ kernResult = [Serial getSerialPortPath:serialPortIterator to:portList with:100 and:200];
|
110
|
178
|
IOObjectRelease(serialPortIterator);
|
111
|
179
|
|
112
|
180
|
// Copy contents into NSString Array
|
|
@@ -125,9 +193,7 @@ kern_return_t getSerialPortPath(io_iterator_t serialPortIterator, char **deviceF
|
125
|
193
|
return [[NSArray alloc] initWithObjects:stringList count:realCount];
|
126
|
194
|
}
|
127
|
195
|
|
128
|
|
-@end
|
129
|
|
-
|
130
|
|
-kern_return_t findSerialPorts(io_iterator_t *matches) {
|
|
196
|
++ (kern_return_t)findSerialPorts:(io_iterator_t *)matches {
|
131
|
197
|
kern_return_t kernResult;
|
132
|
198
|
mach_port_t masterPort;
|
133
|
199
|
CFMutableDictionaryRef classesToMatch;
|
|
@@ -165,7 +231,7 @@ kern_return_t findSerialPorts(io_iterator_t *matches) {
|
165
|
231
|
return kernResult;
|
166
|
232
|
}
|
167
|
233
|
|
168
|
|
-kern_return_t getSerialPortPath(io_iterator_t serialPortIterator, char **deviceFilePath, CFIndex maxPathCount, CFIndex maxPathSize) {
|
|
234
|
++ (kern_return_t)getSerialPortPath:(io_iterator_t)serialPortIterator to:(char **)deviceFilePath with:(CFIndex)maxPathCount and:(CFIndex)maxPathSize {
|
169
|
235
|
io_object_t modemService;
|
170
|
236
|
kern_return_t kernResult = KERN_FAILURE;
|
171
|
237
|
CFIndex i = 0;
|
|
@@ -213,3 +279,5 @@ kern_return_t getSerialPortPath(io_iterator_t serialPortIterator, char **deviceF
|
213
|
279
|
|
214
|
280
|
return kernResult;
|
215
|
281
|
}
|
|
282
|
+
|
|
283
|
+@end
|