Browse Source

Added Thread reading data, fooHID interface code

Thomas Buck 8 years ago
parent
commit
658fe3d26e

+ 12
- 0
SerialGamepad.xcodeproj/project.pbxproj View File

@@ -9,6 +9,8 @@
9 9
 /* Begin PBXBuildFile section */
10 10
 		E9B6A1D21C1F623B00DA3C80 /* MainWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = E9B6A1D11C1F623B00DA3C80 /* MainWindow.m */; };
11 11
 		E9B6A1D61C1F683300DA3C80 /* Serial.m in Sources */ = {isa = PBXBuildFile; fileRef = E9B6A1D51C1F683300DA3C80 /* Serial.m */; };
12
+		E9B6A1D91C1F7E0200DA3C80 /* fooHID.m in Sources */ = {isa = PBXBuildFile; fileRef = E9B6A1D81C1F7E0200DA3C80 /* fooHID.m */; };
13
+		E9B6A1DC1C20C0F200DA3C80 /* Thread.m in Sources */ = {isa = PBXBuildFile; fileRef = E9B6A1DB1C20C0F200DA3C80 /* Thread.m */; };
12 14
 		E9F5FFB21C1F5E2B00AA4E3B /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E9F5FFB11C1F5E2B00AA4E3B /* AppDelegate.m */; };
13 15
 		E9F5FFB51C1F5E2B00AA4E3B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E9F5FFB41C1F5E2B00AA4E3B /* main.m */; };
14 16
 		E9F5FFB71C1F5E2B00AA4E3B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E9F5FFB61C1F5E2B00AA4E3B /* Assets.xcassets */; };
@@ -20,6 +22,10 @@
20 22
 		E9B6A1D11C1F623B00DA3C80 /* MainWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MainWindow.m; sourceTree = "<group>"; };
21 23
 		E9B6A1D41C1F683300DA3C80 /* Serial.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Serial.h; sourceTree = "<group>"; };
22 24
 		E9B6A1D51C1F683300DA3C80 /* Serial.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Serial.m; sourceTree = "<group>"; };
25
+		E9B6A1D71C1F7E0200DA3C80 /* fooHID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fooHID.h; sourceTree = "<group>"; };
26
+		E9B6A1D81C1F7E0200DA3C80 /* fooHID.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = fooHID.m; sourceTree = "<group>"; };
27
+		E9B6A1DA1C20C0F200DA3C80 /* Thread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Thread.h; sourceTree = "<group>"; };
28
+		E9B6A1DB1C20C0F200DA3C80 /* Thread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Thread.m; sourceTree = "<group>"; };
23 29
 		E9F5FFAD1C1F5E2B00AA4E3B /* SerialGamepad.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SerialGamepad.app; sourceTree = BUILT_PRODUCTS_DIR; };
24 30
 		E9F5FFB01C1F5E2B00AA4E3B /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
25 31
 		E9F5FFB11C1F5E2B00AA4E3B /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
@@ -67,6 +73,10 @@
67 73
 				E9B6A1D11C1F623B00DA3C80 /* MainWindow.m */,
68 74
 				E9B6A1D41C1F683300DA3C80 /* Serial.h */,
69 75
 				E9B6A1D51C1F683300DA3C80 /* Serial.m */,
76
+				E9B6A1D71C1F7E0200DA3C80 /* fooHID.h */,
77
+				E9B6A1D81C1F7E0200DA3C80 /* fooHID.m */,
78
+				E9B6A1DA1C20C0F200DA3C80 /* Thread.h */,
79
+				E9B6A1DB1C20C0F200DA3C80 /* Thread.m */,
70 80
 				E9F5FFBB1C1F5E2B00AA4E3B /* Info.plist */,
71 81
 				E9F5FFB31C1F5E2B00AA4E3B /* Supporting Files */,
72 82
 			);
@@ -170,8 +180,10 @@
170 180
 			files = (
171 181
 				E9F5FFB51C1F5E2B00AA4E3B /* main.m in Sources */,
172 182
 				E9F5FFB21C1F5E2B00AA4E3B /* AppDelegate.m in Sources */,
183
+				E9B6A1D91C1F7E0200DA3C80 /* fooHID.m in Sources */,
173 184
 				E9B6A1D21C1F623B00DA3C80 /* MainWindow.m in Sources */,
174 185
 				E9B6A1D61C1F683300DA3C80 /* Serial.m in Sources */,
186
+				E9B6A1DC1C20C0F200DA3C80 /* Thread.m in Sources */,
175 187
 			);
176 188
 			runOnlyForDeploymentPostprocessing = 0;
177 189
 		};

BIN
SerialGamepad.xcodeproj/project.xcworkspace/xcuserdata/thomas.xcuserdatad/UserInterfaceState.xcuserstate View File


+ 4
- 6
SerialGamepad/Base.lproj/MainMenu.xib View File

@@ -678,7 +678,7 @@
678 678
                 <subviews>
679 679
                     <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fCd-m1-NwV">
680 680
                         <rect key="frame" x="14" y="169" width="152" height="32"/>
681
-                        <buttonCell key="cell" type="push" title="Connect" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="adp-gD-EEf">
681
+                        <buttonCell key="cell" type="push" title="Connect" bezelStyle="rounded" alignment="center" enabled="NO" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="adp-gD-EEf">
682 682
                             <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
683 683
                             <font key="font" metaFont="system"/>
684 684
                         </buttonCell>
@@ -688,7 +688,7 @@
688 688
                     </button>
689 689
                     <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="v8W-R7-l4G">
690 690
                         <rect key="frame" x="164" y="169" width="152" height="32"/>
691
-                        <buttonCell key="cell" type="push" title="Create" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="EEe-0L-Dx7">
691
+                        <buttonCell key="cell" type="push" title="Create" bezelStyle="rounded" alignment="center" enabled="NO" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="EEe-0L-Dx7">
692 692
                             <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
693 693
                             <font key="font" metaFont="system"/>
694 694
                         </buttonCell>
@@ -722,14 +722,12 @@
722 722
                     </levelIndicator>
723 723
                     <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="mvV-p0-WO6">
724 724
                         <rect key="frame" x="18" y="214" width="295" height="26"/>
725
-                        <popUpButtonCell key="cell" type="push" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" id="p4h-ja-UZg">
725
+                        <popUpButtonCell key="cell" type="push" title="Serial Port" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" enabled="NO" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="W0M-vU-Ybd" id="p4h-ja-UZg">
726 726
                             <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
727 727
                             <font key="font" metaFont="menu"/>
728 728
                             <menu key="menu" id="njN-zA-NVu">
729 729
                                 <items>
730
-                                    <menuItem title="Item 1" id="W0M-vU-Ybd"/>
731
-                                    <menuItem title="Item 2" id="SHC-AR-wFp"/>
732
-                                    <menuItem title="Item 3" id="PqD-oG-Ww4"/>
730
+                                    <menuItem title="Serial Port" state="on" id="W0M-vU-Ybd"/>
733 731
                                 </items>
734 732
                             </menu>
735 733
                         </popUpButtonCell>

+ 1
- 1
SerialGamepad/Info.plist View File

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

+ 4
- 0
SerialGamepad/MainWindow.h View File

@@ -8,6 +8,8 @@
8 8
 
9 9
 #import <Cocoa/Cocoa.h>
10 10
 
11
+#import "Thread.h"
12
+
11 13
 @interface MainWindow : NSWindow
12 14
 
13 15
 @property (weak) IBOutlet NSPopUpButton *portList;
@@ -20,6 +22,8 @@
20 22
 @property (weak) IBOutlet NSLevelIndicator *level5;
21 23
 @property (weak) IBOutlet NSLevelIndicator *level6;
22 24
 
25
+@property (strong) Thread *serialThread;
26
+
23 27
 - (void)populatePortList;
24 28
 
25 29
 @end

+ 30
- 4
SerialGamepad/MainWindow.m View File

@@ -12,19 +12,45 @@
12 12
 
13 13
 @implementation MainWindow
14 14
 
15
-@synthesize portList, connectButton, createButton, level1, level2, level3, level4, level5, level6;
15
+@synthesize portList, connectButton, createButton;
16
+@synthesize level1, level2, level3, level4, level5, level6;
17
+@synthesize serialThread;
16 18
 
17 19
 - (IBAction)connectButtonPressed:(id)sender {
20
+    if (serialThread == nil) {
21
+        serialThread = [[Thread alloc] init];
22
+        [serialThread setName:@"Serial Communication"];
23
+        [serialThread setPortName:[portList titleOfSelectedItem]];
24
+        
25
+        if ([serialThread openPort] != 0) {
26
+            serialThread = nil;
27
+        } else {
28
+            [serialThread start];
29
+            [connectButton setTitle:@"Disconnect"];
30
+        }
31
+    } else {
32
+        [serialThread setRunning:NO];
33
+        // TODO disable button, thread should call back when closed
34
+        // so we can set serialThread to nil then
35
+        serialThread = nil;
36
+        [connectButton setTitle:@"Connect"];
37
+    }
18 38
 }
19 39
 
20 40
 - (IBAction)createButtonPressed:(id)sender {
41
+    
21 42
 }
22 43
 
23 44
 - (void)populatePortList {
24 45
     NSArray *ports = [Serial listSerialPorts];
25
-    
26
-    [portList removeAllItems];
27
-    [portList addItemsWithTitles:ports];
46
+    if ([ports count] > 0) {
47
+        [portList removeAllItems];
48
+        [portList addItemsWithTitles:ports];
49
+        [portList setEnabled:YES];
50
+        [connectButton setEnabled:YES];
51
+    } else {
52
+        NSLog(@"Couldn't find any serial ports!\n");
53
+    }
28 54
 }
29 55
 
30 56
 @end

+ 0
- 4
SerialGamepad/Serial.h View File

@@ -13,7 +13,3 @@
13 13
 + (NSArray *)listSerialPorts;
14 14
 
15 15
 @end
16
-
17
-// Internal
18
-kern_return_t findSerialPorts(io_iterator_t *matches);
19
-kern_return_t getSerialPortPath(io_iterator_t serialPortIterator, char **deviceFilePath, CFIndex maxPathCount, CFIndex maxPathSize);

+ 4
- 1
SerialGamepad/Serial.m View File

@@ -13,6 +13,9 @@
13 13
 
14 14
 #import "Serial.h"
15 15
 
16
+kern_return_t findSerialPorts(io_iterator_t *matches);
17
+kern_return_t getSerialPortPath(io_iterator_t serialPortIterator, char **deviceFilePath, CFIndex maxPathCount, CFIndex maxPathSize);
18
+
16 19
 @implementation Serial
17 20
 
18 21
 + (NSArray *)listSerialPorts {
@@ -118,7 +121,7 @@ kern_return_t getSerialPortPath(io_iterator_t serialPortIterator, char **deviceF
118 121
             CFRelease(deviceFilePathAsCFString);
119 122
             
120 123
             if (result) {
121
-                NSLog(@"BSD path: %s\n", deviceFilePath[i]);
124
+                //NSLog(@"BSD path: %s\n", deviceFilePath[i]);
122 125
                 i++;
123 126
                 kernResult = KERN_SUCCESS;
124 127
             }

+ 19
- 0
SerialGamepad/Thread.h View File

@@ -0,0 +1,19 @@
1
+//
2
+//  Thread.h
3
+//  SerialGamepad
4
+//
5
+//  Created by Thomas Buck on 15.12.15.
6
+//  Copyright © 2015 xythobuz. All rights reserved.
7
+//
8
+
9
+#import <Foundation/Foundation.h>
10
+
11
+@interface Thread : NSThread
12
+
13
+@property BOOL running;
14
+@property int fd;
15
+@property (strong) NSString *portName;
16
+
17
+- (NSInteger)openPort;
18
+
19
+@end

+ 123
- 0
SerialGamepad/Thread.m View File

@@ -0,0 +1,123 @@
1
+//
2
+//  Thread.m
3
+//  SerialGamepad
4
+//
5
+//  Created by Thomas Buck on 15.12.15.
6
+//  Copyright © 2015 xythobuz. All rights reserved.
7
+//
8
+
9
+#import <termios.h>
10
+#import <fcntl.h>
11
+#import <unistd.h>
12
+
13
+#import "Thread.h"
14
+#import "fooHID.h"
15
+
16
+@implementation Thread
17
+
18
+@synthesize running, fd, portName;
19
+
20
+- (NSInteger)openPort {
21
+    if (portName == nil) {
22
+        return 1;
23
+    }
24
+    
25
+    fd = open([portName UTF8String], O_RDONLY | O_NOCTTY | O_NONBLOCK);
26
+    if (fd == -1) {
27
+        NSLog(@"Error opening serial port \"%@\"!\n", portName);
28
+        return 1;
29
+    }
30
+    
31
+    fcntl(fd, F_SETFL, 0);
32
+    
33
+    struct termios options;
34
+    tcgetattr(fd, &options);
35
+    
36
+    options.c_lflag = 0;
37
+    options.c_oflag = 0;
38
+    options.c_iflag = 0;
39
+    options.c_cflag = 0;
40
+    
41
+    options.c_cflag |= CS8;
42
+    options.c_cflag |= CREAD;
43
+    options.c_cflag |= CLOCAL;
44
+    
45
+    cfsetispeed(&options, B115200);
46
+    cfsetospeed(&options, B115200);
47
+    
48
+    options.c_cc[VMIN] = 0;
49
+    options.c_cc[VTIME] = 1;
50
+    
51
+    tcsetattr(fd, TCSANOW, &options);
52
+    tcflush(fd, TCIOFLUSH);
53
+    
54
+    return 0;
55
+}
56
+
57
+#define PACKETSIZE 18
58
+#define HEADERBYTES 2
59
+#define CHECKSUMBYTES 2
60
+#define PAYLOADBYTES (PACKETSIZE - HEADERBYTES - CHECKSUMBYTES)
61
+#define HEADERBYTE_A 85
62
+#define HEADERBYTE_B 252
63
+
64
+enum ThreadState {
65
+    READ_FIRST_BYTE,
66
+    READ_SECOND_BYTE,
67
+    READ_PAYLOAD,
68
+    READ_CHECKSUM
69
+};
70
+
71
+- (void)main {
72
+    enum ThreadState state = READ_FIRST_BYTE;
73
+    unsigned char c = 0;
74
+    unsigned char buffer[PACKETSIZE];
75
+    unsigned char checksum[CHECKSUMBYTES];
76
+    int received = 0;
77
+    
78
+    NSLog(@"Connection running...\n");
79
+    
80
+    running = YES;
81
+    while (running) {
82
+        if (state == READ_FIRST_BYTE) {
83
+            if (read(fd, &c, 1) == 1) {
84
+                if (c == HEADERBYTE_A) {
85
+                    state = READ_SECOND_BYTE;
86
+                }
87
+            }
88
+        } else if (state == READ_SECOND_BYTE) {
89
+            if (read(fd, &c, 1) == 1) {
90
+                if (c == HEADERBYTE_B) {
91
+                    state = READ_PAYLOAD;
92
+                    received = 0;
93
+                } else {
94
+                    state = READ_FIRST_BYTE;
95
+                }
96
+            }
97
+        } else if (state == READ_PAYLOAD) {
98
+            ssize_t ret = read(fd, buffer + received, PAYLOADBYTES - received);
99
+            if (ret >= 0) received += ret;
100
+            if (received >= PAYLOADBYTES) {
101
+                state = READ_CHECKSUM;
102
+                received = 0;
103
+            }
104
+        } else if (state == READ_CHECKSUM) {
105
+            ssize_t ret = read(fd, checksum + received, CHECKSUMBYTES - received);
106
+            if (ret >= 0) received += ret;
107
+            if (received >= CHECKSUMBYTES) {
108
+                state = READ_FIRST_BYTE;
109
+                
110
+                // TODO got something
111
+            }
112
+        } else {
113
+            NSLog(@"Invalid state?!\n");
114
+            state = READ_FIRST_BYTE;
115
+        }
116
+    }
117
+    
118
+    close(fd);
119
+    NSLog(@"Connection closed...\n");
120
+    fd = -1;
121
+}
122
+
123
+@end

+ 17
- 0
SerialGamepad/fooHID.h View File

@@ -0,0 +1,17 @@
1
+//
2
+//  fooHID.h
3
+//  SerialGamepad
4
+//
5
+//  Created by Thomas Buck on 14.12.15.
6
+//  Copyright © 2015 xythobuz. All rights reserved.
7
+//
8
+
9
+#import <Foundation/Foundation.h>
10
+
11
+@interface fooHID : NSObject
12
+
13
++ (NSInteger)init;
14
++ (void)close;
15
++ (void)send:(NSArray *)data;
16
+
17
+@end

+ 182
- 0
SerialGamepad/fooHID.m View File

@@ -0,0 +1,182 @@
1
+//
2
+//  fooHID.m
3
+//  SerialGamepad
4
+//
5
+//  Created by Thomas Buck on 14.12.15.
6
+//  Copyright © 2015 xythobuz. All rights reserved.
7
+//
8
+
9
+#import <IOKit/IOKitLib.h>
10
+
11
+#import "fooHID.h"
12
+
13
+#define CHANNELS 6
14
+#define CHANNELMAXIMUM 1022
15
+#define CHANNELOFFSET (CHANNELMAXIMUM / 2)
16
+
17
+#define FOOHID_NAME "it_unbit_foohid"
18
+#define FOOHID_CREATE 0
19
+#define FOOHID_DESTROY 1
20
+#define FOOHID_SEND 2
21
+#define FOOHID_LIST 3
22
+#define VIRTUAL_DEVICE_NAME "Virtual Serial Transmitter"
23
+
24
+int foohidInit();
25
+void foohidClose();
26
+void foohidSend(uint16_t *data);
27
+
28
+@implementation fooHID
29
+
30
++ (NSInteger)init {
31
+    return foohidInit();
32
+}
33
+
34
++ (void)close {
35
+    return foohidClose();
36
+}
37
+
38
++ (void)send:(NSArray *)data {
39
+    if ([data count] < CHANNELS) {
40
+        NSLog(@"Not enough data values to send (%lu)!\n", (unsigned long)[data count]);
41
+    } else {
42
+        uint16_t buffer[CHANNELS];
43
+        for (int i = 0; i < CHANNELS; i++) {
44
+            buffer[i] = [((NSNumber *)[data objectAtIndex:i]) integerValue];
45
+        }
46
+        foohidSend(buffer);
47
+    }
48
+}
49
+
50
+@end
51
+
52
+struct gamepad_report_t {
53
+    int16_t leftX;
54
+    int16_t leftY;
55
+    int16_t rightX;
56
+    int16_t rightY;
57
+    int16_t aux1;
58
+    int16_t aux2;
59
+};
60
+
61
+static io_connect_t connector;
62
+static uint64_t input[4];
63
+static struct gamepad_report_t gamepad;
64
+
65
+/*
66
+ * This is my USB HID Descriptor for this emulated Gamepad.
67
+ * For more informations refer to:
68
+ * http://eleccelerator.com/tutorial-about-usb-hid-report-descriptors/
69
+ * http://www.usb.org/developers/hidpage#HID%20Descriptor%20Tool
70
+ */
71
+static char report_descriptor[36] = {
72
+    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
73
+    0x09, 0x05,                    // USAGE (Game Pad)
74
+    0xa1, 0x01,                    // COLLECTION (Application)
75
+    0xa1, 0x00,                    //   COLLECTION (Physical)
76
+    0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
77
+    0x09, 0x30,                    //     USAGE (X)
78
+    0x09, 0x31,                    //     USAGE (Y)
79
+    0x09, 0x32,                    //     USAGE (Z)
80
+    0x09, 0x33,                    //     USAGE (Rx)
81
+    0x09, 0x34,                    //     USAGE (Ry)
82
+    0x09, 0x35,                    //     USAGE (Rz)
83
+    0x16, 0x01, 0xfe,              //     LOGICAL_MINIMUM (-511)
84
+    0x26, 0xff, 0x01,              //     LOGICAL_MAXIMUM (511)
85
+    0x75, 0x10,                    //     REPORT_SIZE (16)
86
+    0x95, 0x06,                    //     REPORT_COUNT (6)
87
+    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
88
+    0xc0,                          //     END_COLLECTION
89
+    0xc0                           // END_COLLECTION
90
+};
91
+
92
+int foohidInit() {
93
+    NSLog(@"Searching for foohid Kernel extension...\n");
94
+    
95
+    // get a reference to the IOService
96
+    io_iterator_t iterator;
97
+    kern_return_t ret = IOServiceGetMatchingServices(kIOMasterPortDefault,
98
+                                                     IOServiceMatching(FOOHID_NAME), &iterator);
99
+    if (ret != KERN_SUCCESS) {
100
+        NSLog(@"Unable to access foohid IOService\n");
101
+        return 1;
102
+    }
103
+    
104
+    int found = 0;
105
+    io_service_t service;
106
+    while ((service = IOIteratorNext(iterator)) != IO_OBJECT_NULL) {
107
+        ret = IOServiceOpen(service, mach_task_self(), 0, &connector);
108
+        if (ret == KERN_SUCCESS) {
109
+            found = 1;
110
+            break;
111
+        }
112
+    }
113
+    IOObjectRelease(iterator);
114
+    if (!found) {
115
+        NSLog(@"Unable to open foohid IOService\n");
116
+        return 1;
117
+    }
118
+    
119
+    NSLog(@"Creating virtual HID device...\n");
120
+    
121
+    input[0] = (uint64_t)strdup(VIRTUAL_DEVICE_NAME);
122
+    input[1] = strlen((char*)input[0]);
123
+    
124
+    input[2] = (uint64_t)report_descriptor;
125
+    input[3] = sizeof(report_descriptor);
126
+    
127
+    uint32_t output_count = 1;
128
+    uint64_t output = 0;
129
+    ret = IOConnectCallScalarMethod(connector, FOOHID_CREATE, input, 4, &output, &output_count);
130
+    if (ret != KERN_SUCCESS) {
131
+        NSLog(@"Unable to create virtual HID device\n");
132
+        return 1;
133
+    }
134
+    
135
+    return 0;
136
+}
137
+
138
+void foohidClose() {
139
+    NSLog(@"Destroying virtual HID device\n");
140
+    
141
+    uint32_t output_count = 1;
142
+    uint64_t output = 0;
143
+    kern_return_t ret = IOConnectCallScalarMethod(connector, FOOHID_DESTROY, input, 2, &output, &output_count);
144
+    if (ret != KERN_SUCCESS) {
145
+        NSLog(@"Unable to destroy virtual HID device\n");
146
+    }
147
+}
148
+
149
+void foohidSend(uint16_t *data) {
150
+    for (int i = 0; i < CHANNELS; i++) {
151
+        if (data[i] > CHANNELMAXIMUM) {
152
+            data[i] = CHANNELMAXIMUM;
153
+        }
154
+    }
155
+    
156
+    gamepad.leftX = data[3] - CHANNELOFFSET;
157
+    gamepad.leftY = data[2] - CHANNELOFFSET;
158
+    gamepad.rightX = data[0] - CHANNELOFFSET;
159
+    gamepad.rightY = data[1] - CHANNELOFFSET;
160
+    gamepad.aux1 = data[4] - CHANNELOFFSET;
161
+    gamepad.aux2 = data[5] - CHANNELOFFSET;
162
+    
163
+    /*
164
+     NSLog(@"Sending data packet:\n");
165
+     NSLog(@"Left X: %d\n", gamepad.leftX);
166
+     NSLog(@"Left Y: %d\n", gamepad.leftY);
167
+     NSLog(@"Right X: %d\n", gamepad.rightX);
168
+     NSLog(@"Right Y: %d\n", gamepad.rightY);
169
+     NSLog(@"Aux 1: %d\n", gamepad.aux1);
170
+     NSLog(@"Aux 2: %d\n", gamepad.aux2);
171
+     */
172
+    
173
+    input[2] = (uint64_t)&gamepad;
174
+    input[3] = sizeof(struct gamepad_report_t);
175
+    
176
+    uint32_t output_count = 1;
177
+    uint64_t output = 0;
178
+    kern_return_t ret = IOConnectCallScalarMethod(connector, FOOHID_SEND, input, 4, &output, &output_count);
179
+    if (ret != KERN_SUCCESS) {
180
+        NSLog(@"Unable to send packet to virtual HID device\n");
181
+    }
182
+}

Loading…
Cancel
Save