Mac OS X gamepad emulator for serial RC transmitters
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

Serial.m 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. //
  2. // Serial.m
  3. // SerialGamepad
  4. //
  5. // For more informations refer to this document:
  6. // https://developer.apple.com/library/mac/documentation/DeviceDrivers/Conceptual/WorkingWSerial/WWSerial_SerialDevs/SerialDevices.html
  7. //
  8. // Created by Thomas Buck on 14.12.15.
  9. // Copyright © 2015 xythobuz. All rights reserved.
  10. //
  11. #import <IOKit/serial/IOSerialKeys.h>
  12. #import "Serial.h"
  13. kern_return_t findSerialPorts(io_iterator_t *matches);
  14. kern_return_t getSerialPortPath(io_iterator_t serialPortIterator, char **deviceFilePath, CFIndex maxPathCount, CFIndex maxPathSize);
  15. @implementation Serial
  16. + (NSArray *)listSerialPorts {
  17. // Get Iterator with all serial ports
  18. io_iterator_t serialPortIterator;
  19. kern_return_t kernResult = findSerialPorts(&serialPortIterator);
  20. // Create 2D array
  21. char **portList;
  22. portList = malloc(100 * sizeof(char *));
  23. for (int i = 0; i < 100; i++) portList[i] = malloc(200 * sizeof(char));
  24. // Copy device name into C-String array
  25. kernResult = getSerialPortPath(serialPortIterator, portList, 100, 200);
  26. IOObjectRelease(serialPortIterator);
  27. // Copy contents into NSString Array
  28. NSString *stringList[100];
  29. NSUInteger realCount = 0;
  30. while (portList[realCount] != NULL) {
  31. stringList[realCount] = [NSString stringWithCString:portList[realCount] encoding:NSUTF8StringEncoding];
  32. realCount++;
  33. }
  34. // Destroy 2D array
  35. for (int i = 0; i < 100; i++) free(portList[i]);
  36. free(portList);
  37. // And return them as NSArray
  38. return [[NSArray alloc] initWithObjects:stringList count:realCount];
  39. }
  40. @end
  41. kern_return_t findSerialPorts(io_iterator_t *matches) {
  42. kern_return_t kernResult;
  43. mach_port_t masterPort;
  44. CFMutableDictionaryRef classesToMatch;
  45. kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort);
  46. if (KERN_SUCCESS != kernResult) {
  47. NSLog(@"IOMasterPort returned %d\n", kernResult);
  48. return kernResult;
  49. }
  50. // Serial devices are instances of class IOSerialBSDClient.
  51. classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
  52. if (classesToMatch == NULL) {
  53. NSLog(@"IOServiceMatching returned a NULL dictionary.\n");
  54. } else {
  55. CFDictionarySetValue(classesToMatch,
  56. CFSTR(kIOSerialBSDTypeKey),
  57. CFSTR(kIOSerialBSDRS232Type));
  58. // Each serial device object has a property with key
  59. // kIOSerialBSDTypeKey and a value that is one of
  60. // kIOSerialBSDAllTypes, kIOSerialBSDModemType,
  61. // or kIOSerialBSDRS232Type. You can change the
  62. // matching dictionary to find other types of serial
  63. // devices by changing the last parameter in the above call
  64. // to CFDictionarySetValue.
  65. }
  66. kernResult = IOServiceGetMatchingServices(masterPort, classesToMatch, matches);
  67. if (KERN_SUCCESS != kernResult) {
  68. NSLog(@"IOServiceGetMatchingServices returned %d\n", kernResult);
  69. return kernResult;
  70. }
  71. return kernResult;
  72. }
  73. kern_return_t getSerialPortPath(io_iterator_t serialPortIterator, char **deviceFilePath, CFIndex maxPathCount, CFIndex maxPathSize) {
  74. io_object_t modemService;
  75. kern_return_t kernResult = KERN_FAILURE;
  76. CFIndex i = 0;
  77. while ((modemService = IOIteratorNext(serialPortIterator)) && (i < (maxPathCount - 1))) {
  78. CFTypeRef deviceFilePathAsCFString;
  79. // Get the callout device's path (/dev/cu.xxxxx).
  80. // The callout device should almost always be
  81. // used. You would use the dialin device (/dev/tty.xxxxx) when
  82. // monitoring a serial port for
  83. // incoming calls, for example, a fax listener.
  84. deviceFilePathAsCFString = IORegistryEntryCreateCFProperty(modemService,
  85. CFSTR(kIODialinDeviceKey),
  86. kCFAllocatorDefault,
  87. 0);
  88. if (deviceFilePathAsCFString) {
  89. Boolean result;
  90. deviceFilePath[i][0] = '\0';
  91. // Convert the path from a CFString to a NULL-terminated C string
  92. // for use with the POSIX open() call.
  93. result = CFStringGetCString(deviceFilePathAsCFString,
  94. deviceFilePath[i],
  95. maxPathSize,
  96. kCFStringEncodingASCII);
  97. CFRelease(deviceFilePathAsCFString);
  98. if (result) {
  99. //NSLog(@"BSD path: %s\n", deviceFilePath[i]);
  100. i++;
  101. kernResult = KERN_SUCCESS;
  102. }
  103. }
  104. // Release the io_service_t now that we are done with it.
  105. (void) IOObjectRelease(modemService);
  106. }
  107. deviceFilePath[i] = NULL;
  108. return kernResult;
  109. }