OpenCPN Partial API docs
macutils.c
1 /***************************************************************************
2  * Copyright (C) 2007..2010 by David S. Register, Richard M Smith *
3  * *
4  * This program is free software; you can redistribute it and/or modify *
5  * it under the terms of the GNU General Public License as published by *
6  * the Free Software Foundation; either version 2 of the License, or *
7  * (at your option) any later version. *
8  * *
9  * This program is distributed in the hope that it will be useful, *
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12  * GNU General Public License for more details. *
13  * *
14  * You should have received a copy of the GNU General Public License *
15  * along with this program; if not, write to the *
16  * Free Software Foundation, Inc., *
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18  ***************************************************************************
19  *
20  */
21 
22 #include "wx/wxprec.h"
23 #ifdef __WXOSX__
24 
25 #include <stdio.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <sys/ioctl.h>
30 #include <errno.h>
31 #include <paths.h>
32 #include <termios.h>
33 #include <sysexits.h>
34 #include <sys/param.h>
35 #include <sys/select.h>
36 #include <sys/time.h>
37 #include <sys/sysctl.h>
38 #include <time.h>
39 #include <stdlib.h>
40 #include <AvailabilityMacros.h>
41 
42 #include <CoreFoundation/CoreFoundation.h>
43 
44 #include <IOKit/IOKitLib.h>
45 #include <IOKit/serial/IOSerialKeys.h>
46 #if defined(MAC_OS_X_VERSION_10_3) && \
47  (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3)
48 #include <IOKit/serial/ioss.h>
49 #endif
50 #include <IOKit/IOBSD.h>
51 
52 // We need CoreGraphics to read the monitor physical size.
53 // In 10.7 CoreGraphics is part of ApplicationServices.
54 #include <ApplicationServices/ApplicationServices.h>
55 // When we stop building against 10.7 we will probably want to link agains
56 // CoreGraphics directly:
57 //#include <CoreGraphics/CoreGraphics.h>
58 
59 #include "config.h"
60 
61 // Returns an iterator across all known serial ports. Caller is responsible for
62 // releasing the iterator when iteration is complete.
63 static kern_return_t FindSerialPorts(io_iterator_t* matchingServices) {
64  kern_return_t kernResult;
65  CFMutableDictionaryRef classesToMatch;
66 
82  // Serial devices are instances of class IOSerialBSDClient
83  classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
84  if (classesToMatch == NULL) {
85  printf("IOServiceMatching returned a NULL dictionary.\n");
86  } else {
109  CFDictionarySetValue(classesToMatch, CFSTR(kIOSerialBSDTypeKey),
110  CFSTR(kIOSerialBSDAllTypes));
111 
112  // Each serial device object has a property with key
113  // kIOSerialBSDTypeKey and a value that is one of kIOSerialBSDAllTypes,
114  // kIOSerialBSDModemType, or kIOSerialBSDRS232Type. You can experiment with
115  // the matching by changing the last parameter in the above call to
116  // CFDictionarySetValue.
117 
118  // As shipped, this sample is only interested in serial ports,
119  // so add this property to the CFDictionary we're matching on.
120  // This will find devices that advertise themselves as serial ports,
121  // such as built-in and USB serial ports. However, this match won't find
122  // serial serial ports.
123  }
124 
142  kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault,
143  classesToMatch, matchingServices);
144  if (KERN_SUCCESS != kernResult) {
145  printf("IOServiceGetMatchingServices returned %d\n", kernResult);
146  goto exit;
147  }
148 
149 exit:
150  return kernResult;
151 }
152 
153 // Given an iterator across a set of serial ports, return the BSD path to the
154 // first one. If no serial ports are found the path name is set to an empty
155 // string.
156 static int GetSerialPortPath(io_iterator_t serialPortIterator, char** pNames,
157  int iMaxNames, CFIndex maxPathSize) {
158  io_object_t modemService;
159  // kern_return_t kernResult = KERN_FAILURE;
160  Boolean modemFound = false;
161  char bsdPath[maxPathSize];
162  int iCurrentNameIndex = 0;
163  // Initialize the returned path
164  *bsdPath = '\0';
165 
166  // Iterate across all serial ports found.
167 
168  while ((modemService = IOIteratorNext(serialPortIterator)) && !modemFound) {
169  CFTypeRef bsdPathAsCFString;
170 
171  // Get the callout device's path (/dev/cu.xxxxx). The callout device should
172  // almost always be used: the dialin device (/dev/tty.xxxxx) would be used
173  // when monitoring a serial port for incoming calls, e.g. a fax listener.
174 
175  bsdPathAsCFString = IORegistryEntryCreateCFProperty(
176  modemService, CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
177  if (bsdPathAsCFString) {
178  Boolean result;
179 
180  // Convert the path from a CFString to a C (NUL-terminated) string for use
181  // with the POSIX open() call.
182 
183  result = CFStringGetCString(bsdPathAsCFString, bsdPath, maxPathSize,
184  kCFStringEncodingUTF8);
185  CFRelease(bsdPathAsCFString);
186 
187  if (result) {
188  pNames[iCurrentNameIndex] = calloc(1, strlen(bsdPath) + 1);
189  strncpy(pNames[iCurrentNameIndex], bsdPath, strlen(bsdPath) + 1);
190  iCurrentNameIndex++;
191  }
192  }
193  // Release the io_service_t now that we are done with it.
194  (void)IOObjectRelease(modemService);
195  }
196  return iCurrentNameIndex;
197 }
198 
199 int FindSerialPortNames(char** pNames, int iMaxNames) {
200  int iActiveNameCount = 0;
201  kern_return_t kernResult; // on PowerPC this is an int (4 bytes)
202 
203  io_iterator_t serialPortIterator;
204 
205  kernResult = FindSerialPorts(&serialPortIterator);
206 
207  iActiveNameCount =
208  GetSerialPortPath(serialPortIterator, pNames, iMaxNames, MAXPATHLEN);
209 
210  IOObjectRelease(serialPortIterator); // Release the iterator.
211  return iActiveNameCount;
212 }
213 
214 bool ValidateSerialPortName(char* pPortName, int iMaxNamestoSearch) {
215  char* paPortNames[iMaxNamestoSearch];
216  int iPortNameCount;
217  int iPortIndex;
218  bool bPortFound = false;
219  char* pPortSubName = index(pPortName, ':');
220  // name is always valid if opetion is set to 'none'
221  if (0 == strcasecmp(pPortName, "NONE")) return true;
222  // if this name done not have a leading descriptor with a 'serial:', 'GPS:',
223  // etc, use the whole name
224  if (NULL == pPortSubName)
225  pPortSubName = pPortName;
226  else
227  pPortSubName++;
228 
229  memset(paPortNames, 0x00, sizeof(paPortNames));
230  iPortNameCount = FindSerialPortNames(&paPortNames[0], iMaxNamestoSearch);
231  for (iPortIndex = 0; iPortIndex < iPortNameCount; iPortIndex++) {
232  // stripoff leading 'serial:', etc based on iColonIndex
233  int iStrCompresult = strcmp(paPortNames[iPortIndex], pPortSubName);
234  if (false == bPortFound) bPortFound = (bool)(0 == iStrCompresult);
235  free(paPortNames[iPortIndex]);
236  }
237  return bPortFound;
238 }
239 
243 int GetMacMonitorSize() {
244  CGSize displayPhysicalSize = CGDisplayScreenSize(CGMainDisplayID()); // mm
245  return displayPhysicalSize.width;
246 }
247 
252 int ProcessIsTranslated() {
253  int ret = 0;
254  size_t size = sizeof(ret);
255  if (sysctlbyname("sysctl.proc_translated", &ret, &size, NULL, 0) == -1)
256  {
257  if (errno == ENOENT)
258  return 0;
259  return -1;
260  }
261  return ret;
262 }
263 
264 int IsAppleSilicon() {
265  int ret = 0;
266  size_t size = sizeof(ret);
267 
268  if (sysctlbyname("hw.optional.arm64", &ret, &size, NULL, 0) == -1) {
269  return -1;
270  }
271  return ret;
272 }
273 
274 #endif //__WXOSX__