Browse Source

Open and close selected port. Can now relist serial ports.

Thomas Buck 8 years ago
parent
commit
2c169110c1

+ 4
- 0
CaseLights/AppDelegate.h View File

8
 
8
 
9
 #import <Cocoa/Cocoa.h>
9
 #import <Cocoa/Cocoa.h>
10
 
10
 
11
+@class Serial;
12
+
11
 @interface AppDelegate : NSObject <NSApplicationDelegate>
13
 @interface AppDelegate : NSObject <NSApplicationDelegate>
12
 
14
 
13
 @property (weak) IBOutlet NSMenu *statusMenu;
15
 @property (weak) IBOutlet NSMenu *statusMenu;
26
 
28
 
27
 @property (strong) NSDictionary *staticColors;
29
 @property (strong) NSDictionary *staticColors;
28
 
30
 
31
+@property (strong) Serial *serial;
32
+
29
 @end
33
 @end
30
 
34
 

+ 42
- 6
CaseLights/AppDelegate.m View File

26
 @synthesize buttonOff, buttonLights;
26
 @synthesize buttonOff, buttonLights;
27
 @synthesize statusItem, statusImage;
27
 @synthesize statusItem, statusImage;
28
 @synthesize staticColors;
28
 @synthesize staticColors;
29
+@synthesize serial;
29
 
30
 
30
 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
31
 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
32
+    serial = [[Serial alloc] init];
33
+    
31
     // Prepare status bar menu
34
     // Prepare status bar menu
32
     statusImage = [NSImage imageNamed:@"MenuIcon"];
35
     statusImage = [NSImage imageNamed:@"MenuIcon"];
33
     [statusImage setTemplate:YES];
36
     [statusImage setTemplate:YES];
138
             // Set Enabled if it was used the last time
141
             // Set Enabled if it was used the last time
139
             if ((savedPort != nil) && [[ports objectAtIndex:i] isEqualToString:savedPort]) {
142
             if ((savedPort != nil) && [[ports objectAtIndex:i] isEqualToString:savedPort]) {
140
                 [[menuPorts itemAtIndex:i] setState:NSOnState];
143
                 [[menuPorts itemAtIndex:i] setState:NSOnState];
144
+                
145
+                // Try to open serial port
146
+                [serial setPortName:savedPort];
147
+                if ([serial openPort]) {
148
+                    // Unselect it when an error occured opening the port
149
+                    [[menuPorts itemAtIndex:i] setState:NSOffState];
150
+                }
141
             }
151
             }
142
         }
152
         }
143
     }
153
     }
144
     
154
     
145
-    // TODO Open serial port, if it was already specified and found
146
-    
147
     // Restore previously used lights configuration
155
     // Restore previously used lights configuration
148
     if (turnOnLights) {
156
     if (turnOnLights) {
149
         // TODO Turn on lights
157
         // TODO Turn on lights
158
 }
166
 }
159
 
167
 
160
 - (void)applicationWillTerminate:(NSNotification *)aNotification {
168
 - (void)applicationWillTerminate:(NSNotification *)aNotification {
161
-    // TODO Close serial port, if it was specified and opened
162
-    
169
+    // Close serial port, if it was opened
170
+    if ([serial isOpen]) {
171
+        [serial closePort];
172
+    }
173
+}
174
+- (IBAction)relistSerialPorts:(id)sender {
175
+    // Refill port list
176
+    NSArray *ports = [Serial listSerialPorts];
177
+    [menuPorts removeAllItems];
178
+    for (int i = 0; i < [ports count]; i++) {
179
+        // Add Menu Item for this port
180
+        NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:[ports objectAtIndex:i] action:@selector(selectedSerialPort:) keyEquivalent:@""];
181
+        [menuPorts addItem:item];
182
+        
183
+        // Mark it if it is currently open
184
+        if ([serial isOpen]) {
185
+            if ([[ports objectAtIndex:i] isEqualToString:[serial portName]]) {
186
+                [[menuPorts itemAtIndex:i] setState:NSOnState];
187
+            }
188
+        }
189
+    }
163
 }
190
 }
164
 
191
 
165
 - (IBAction)turnLEDsOff:(NSMenuItem *)sender {
192
 - (IBAction)turnLEDsOff:(NSMenuItem *)sender {
328
     // Select only the current port
355
     // Select only the current port
329
     [source setState:NSOnState];
356
     [source setState:NSOnState];
330
     
357
     
331
-    // TODO Close previously opened port, if any
358
+    // Close previously opened port, if any
359
+    if ([serial isOpen]) {
360
+        [serial closePort];
361
+    }
332
     
362
     
333
-    // TODO Try to open selected port
363
+    // Try to open selected port
364
+    [serial setPortName:[source title]];
365
+    if ([serial openPort] != 0) {
366
+        [source setState:NSOffState];
367
+    } else {
368
+        // TODO Restore the current configuration
369
+    }
334
 }
370
 }
335
 
371
 
336
 - (IBAction)showAbout:(id)sender {
372
 - (IBAction)showAbout:(id)sender {

+ 6
- 0
CaseLights/Base.lproj/MainMenu.xib View File

710
                         </items>
710
                         </items>
711
                     </menu>
711
                     </menu>
712
                 </menuItem>
712
                 </menuItem>
713
+                <menuItem title="Relist Serial Ports" id="jVd-gl-Z6F">
714
+                    <modifierMask key="keyEquivalentModifierMask"/>
715
+                    <connections>
716
+                        <action selector="relistSerialPorts:" target="Voe-Tx-rLC" id="iFU-PL-xR8"/>
717
+                    </connections>
718
+                </menuItem>
713
                 <menuItem title="About CaseLights" id="GeK-ey-XEn">
719
                 <menuItem title="About CaseLights" id="GeK-ey-XEn">
714
                     <modifierMask key="keyEquivalentModifierMask"/>
720
                     <modifierMask key="keyEquivalentModifierMask"/>
715
                     <connections>
721
                     <connections>

+ 1
- 1
CaseLights/Info.plist View File

21
 	<key>CFBundleSignature</key>
21
 	<key>CFBundleSignature</key>
22
 	<string>????</string>
22
 	<string>????</string>
23
 	<key>CFBundleVersion</key>
23
 	<key>CFBundleVersion</key>
24
-	<string>61</string>
24
+	<string>66</string>
25
 	<key>LSApplicationCategoryType</key>
25
 	<key>LSApplicationCategoryType</key>
26
 	<string>public.app-category.utilities</string>
26
 	<string>public.app-category.utilities</string>
27
 	<key>LSMinimumSystemVersion</key>
27
 	<key>LSMinimumSystemVersion</key>

+ 5
- 3
CaseLights/Serial.h View File

1
 //
1
 //
2
 //  Serial.h
2
 //  Serial.h
3
-//  SerialGamepad
3
+//  CaseLights
4
 //
4
 //
5
 //  Created by Thomas Buck on 14.12.15.
5
 //  Created by Thomas Buck on 14.12.15.
6
 //  Copyright © 2015 xythobuz. All rights reserved.
6
 //  Copyright © 2015 xythobuz. All rights reserved.
10
 
10
 
11
 @interface Serial : NSObject
11
 @interface Serial : NSObject
12
 
12
 
13
-@property int fd;
14
 @property (strong) NSString *portName;
13
 @property (strong) NSString *portName;
15
 
14
 
16
 - (NSInteger)openPort;
15
 - (NSInteger)openPort;
17
-- (NSInteger)hasData;
16
+- (void)closePort;
17
+- (BOOL)isOpen;
18
+- (BOOL)hasData;
19
+- (void)sendString:(NSString *)string;
18
 
20
 
19
 + (NSArray *)listSerialPorts;
21
 + (NSArray *)listSerialPorts;
20
 
22
 

+ 82
- 14
CaseLights/Serial.m View File

1
 //
1
 //
2
 //  Serial.m
2
 //  Serial.m
3
-//  SerialGamepad / CaseLights
3
+//  CaseLights
4
 //
4
 //
5
 //  For more informations refer to this document:
5
 //  For more informations refer to this document:
6
 //  https://developer.apple.com/library/mac/documentation/DeviceDrivers/Conceptual/WorkingWSerial/WWSerial_SerialDevs/SerialDevices.html
6
 //  https://developer.apple.com/library/mac/documentation/DeviceDrivers/Conceptual/WorkingWSerial/WWSerial_SerialDevs/SerialDevices.html
21
 
21
 
22
 #import "Serial.h"
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
 @implementation Serial
33
 @implementation Serial
28
 
34
 
29
 @synthesize fd, portName;
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
 - (NSInteger)openPort {
46
 - (NSInteger)openPort {
32
     // We need a port name
47
     // We need a port name
33
     if (portName == nil) {
48
     if (portName == nil) {
36
     }
51
     }
37
     
52
     
38
     // Check if there was already a port opened
53
     // Check if there was already a port opened
39
-    if (fd != -1) {
54
+    if (fd > -1) {
40
         NSLog(@"Closing previously opened serial port \"%@\"!\n", portName);
55
         NSLog(@"Closing previously opened serial port \"%@\"!\n", portName);
41
         close(fd);
56
         close(fd);
42
     }
57
     }
43
     
58
     
59
+#ifdef DEBUG
60
+    NSLog(@"Opening serial port \"%@\"...\n", portName);
61
+#endif
62
+    
44
     // Open port read-only, without controlling terminal, non-blocking
63
     // Open port read-only, without controlling terminal, non-blocking
45
     fd = open([portName UTF8String], O_RDONLY | O_NOCTTY | O_NONBLOCK);
64
     fd = open([portName UTF8String], O_RDONLY | O_NOCTTY | O_NONBLOCK);
46
     if (fd == -1) {
65
     if (fd == -1) {
84
     return 0;
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
     struct pollfd fds;
133
     struct pollfd fds;
89
     fds.fd = fd;
134
     fds.fd = fd;
90
     fds.events = (POLLIN | POLLPRI); // Data may be read
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
     } else {
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
 + (NSArray *)listSerialPorts {
166
 + (NSArray *)listSerialPorts {
99
     // Get Iterator with all serial ports
167
     // Get Iterator with all serial ports
100
     io_iterator_t serialPortIterator;
168
     io_iterator_t serialPortIterator;
101
-    kern_return_t kernResult = findSerialPorts(&serialPortIterator);
169
+    kern_return_t kernResult = [Serial findSerialPorts:&serialPortIterator];
102
     
170
     
103
     // Create 2D array
171
     // Create 2D array
104
     char **portList;
172
     char **portList;
106
     for (int i = 0; i < 100; i++) portList[i] = malloc(200 * sizeof(char));
174
     for (int i = 0; i < 100; i++) portList[i] = malloc(200 * sizeof(char));
107
     
175
     
108
     // Copy device name into C-String array
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
     IOObjectRelease(serialPortIterator);
178
     IOObjectRelease(serialPortIterator);
111
     
179
     
112
     // Copy contents into NSString Array
180
     // Copy contents into NSString Array
125
     return [[NSArray alloc] initWithObjects:stringList count:realCount];
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
     kern_return_t kernResult;
197
     kern_return_t kernResult;
132
     mach_port_t masterPort;
198
     mach_port_t masterPort;
133
     CFMutableDictionaryRef classesToMatch;
199
     CFMutableDictionaryRef classesToMatch;
165
     return kernResult;
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
     io_object_t modemService;
235
     io_object_t modemService;
170
     kern_return_t kernResult = KERN_FAILURE;
236
     kern_return_t kernResult = KERN_FAILURE;
171
     CFIndex i = 0;
237
     CFIndex i = 0;
213
     
279
     
214
     return kernResult;
280
     return kernResult;
215
 }
281
 }
282
+
283
+@end

Loading…
Cancel
Save