ObjFW  Check-in [3d8deae83e]

Overview
Comment:ObjFWHID: Add support for DualSense via evdev
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 3d8deae83e1671164d603a849fd45b91a39ce3cc0b160c309749d150bac756f8
User & Date: js on 2024-06-08 22:40:25
Other Links: manifest | tags
Context
2024-06-08
22:47
OHEvdevGameController: Default to Xbox buttons check-in: 6b3b47c1f4 user: js tags: trunk
22:40
ObjFWHID: Add support for DualSense via evdev check-in: 3d8deae83e user: js tags: trunk
22:16
OHEvdevGamepad: Filter buttons/axes check-in: 48e6a99f7b user: js tags: trunk
Changes

Modified src/hid/Makefile from [8549234aa0] to [fcd35a0ed7].

16
17
18
19
20
21
22
23


24
25
26
27
28
29
30
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
31







-
+
+







       OHGameControllerElement.m	\
       OHGameControllerProfile.m	\
       OHGamepad.m			\
       ${USE_SRCS_EVDEV}		\
       ${USE_SRCS_NINTENDO_3DS}		\
       ${USE_SRCS_NINTENDO_DS}		\
       ${USE_SRCS_XINPUT}
SRCS_EVDEV = OHEvdevGameController.m	\
SRCS_EVDEV = OHEvdevDualSense.m		\
	     OHEvdevGameController.m	\
	     OHEvdevGamepad.m
SRCS_NINTENDO_3DS = OHNintendo3DSGameController.m	\
		    OHNintendo3DSGamepad.m
SRCS_NINTENDO_DS = OHNintendoDSGameController.m
SRCS_XINPUT = OHXInputGameController.m	\
	      OHXInputGamepad.m

Added src/hid/OHEvdevDualSense.h version [766fab2a8c].




























1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version 3.0 only,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 * version 3.0 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3.0 along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

#import "OHEvdevGamepad.h"

OF_ASSUME_NONNULL_BEGIN

@interface OHEvdevDualSense: OHEvdevGamepad
@end

OF_ASSUME_NONNULL_END

Added src/hid/OHEvdevDualSense.m version [7696fc6d10].









































































































1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
/*
 * Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version 3.0 only,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 * version 3.0 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3.0 along with this program. If not, see
 * <https://www.gnu.org/licenses/>.
 */

#include "config.h"

#import "OHEvdevDualSense.h"
#import "OFDictionary.h"
#import "OFNumber.h"
#import "OHEvdevGameController.h"
#import "OHGameControllerDirectionalPad.h"
#import "OHGameControllerEmulatedTriggerButton.h"

#import "OFInvalidArgumentException.h"

@implementation OHEvdevDualSense
- (OFDictionary OF_GENERIC(OFString *, OHGameControllerButton *) *)buttons
{
	OFMutableDictionary *buttons =
	    [[_rawProfile.buttons mutableCopy] autorelease];

	[buttons removeObjectForKey: @"D-Pad Up"];
	[buttons removeObjectForKey: @"D-Pad Down"];
	[buttons removeObjectForKey: @"D-Pad Left"];
	[buttons removeObjectForKey: @"D-Pad Right"];

	[buttons setObject: self.leftTriggerButton forKey: @"L2"];
	[buttons setObject: self.rightTriggerButton forKey: @"R2"];

	[buttons makeImmutable];

	return buttons;
}

- (OHGameControllerButton *)northButton
{
	return [_rawProfile.buttons objectForKey: @"Triangle"];
}

- (OHGameControllerButton *)southButton
{
	return [_rawProfile.buttons objectForKey: @"Cross"];
}

- (OHGameControllerButton *)westButton
{
	return [_rawProfile.buttons objectForKey: @"Square"];
}

- (OHGameControllerButton *)eastButton
{
	return [_rawProfile.buttons objectForKey: @"Circle"];
}

- (OHGameControllerButton *)leftShoulderButton
{
	return [_rawProfile.buttons objectForKey: @"L1"];
}

- (OHGameControllerButton *)rightShoulderButton
{
	return [_rawProfile.buttons objectForKey: @"R1"];
}

- (OHGameControllerButton *)leftThumbstickButton
{
	return [_rawProfile.buttons objectForKey: @"L3"];
}

- (OHGameControllerButton *)rightThumbstickButton
{
	return [_rawProfile.buttons objectForKey: @"R3"];
}

- (OHGameControllerButton *)menuButton
{
	return [_rawProfile.buttons objectForKey: @"Options"];
}

- (OHGameControllerButton *)optionsButton
{
	return [_rawProfile.buttons objectForKey: @"Create"];
}

- (OHGameControllerButton *)homeButton
{
	return [_rawProfile.buttons objectForKey: @"PS"];
}
@end

Modified src/hid/OHEvdevGameController.m from [f6abf87a47] to [34e73fdaa7].

27
28
29
30
31
32
33

34
35
36
37
38
39
40
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41







+








#import "OFArray.h"
#import "OFDictionary.h"
#import "OFFileManager.h"
#import "OFLocale.h"
#import "OFNumber.h"

#import "OHEvdevDualSense.h"
#import "OHEvdevGamepad.h"
#import "OHGameControllerAxis.h"
#import "OHGameControllerButton.h"
#import "OHGameControllerProfile.h"

#include <sys/ioctl.h>
#include <linux/input.h>
79
80
81
82
83
84
85
86

87































88
89
90
91
92
93
94
80
81
82
83
84
85
86

87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126







-
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







static const uint16_t axisIDs[] = {
	ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ, ABS_THROTTLE, ABS_RUDDER,
	ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X,
	ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y, ABS_HAT3X, ABS_HAT3Y
};

static OFString *
buttonToName(uint16_t button)
buttonToName(uint16_t button, uint16_t vendorID, uint16_t productID)
{
	if (vendorID == OHVendorIDSony && productID == OHProductIDDualSense) {
		switch (button) {
		case BTN_NORTH:
			return @"Triangle";
		case BTN_SOUTH:
			return @"Cross";
		case BTN_WEST:
			return @"Square";
		case BTN_EAST:
			return @"Circle";
		case BTN_TL:
			return @"L1";
		case BTN_TR:
			return @"R1";
		case BTN_TL2:
			return @"L2";
		case BTN_TR2:
			return @"R2";
		case BTN_THUMBL:
			return @"L3";
		case BTN_THUMBR:
			return @"R3";
		case BTN_START:
			return @"Options";
		case BTN_SELECT:
			return @"Create";
		case BTN_MODE:
			return @"PS";
		}
	}

	switch (button) {
	case BTN_A:
		return @"A";
	case BTN_B:
		return @"B";
	case BTN_C:
		return @"C";
367
368
369
370
371
372
373
374


375
376
377
378
379
380
381
399
400
401
402
403
404
405

406
407
408
409
410
411
412
413
414







-
+
+







		buttons = [OFMutableDictionary dictionary];
		for (size_t i = 0; i < sizeof(buttonIDs) / sizeof(*buttonIDs);
		    i++) {
			if (OFBitSetIsSet(_keyBits, buttonIDs[i])) {
				OFString *buttonName;
				OHGameControllerButton *button;

				buttonName = buttonToName(buttonIDs[i]);
				buttonName = buttonToName(buttonIDs[i],
				    _vendorID, _productID);
				if (buttonName == nil)
					continue;

				button = [[[OHGameControllerButton alloc]
				    initWithName: buttonName] autorelease];

				[buttons setObject: button forKey: buttonName];
472
473
474
475
476
477
478
479

480
481
482
483
484
485
486
505
506
507
508
509
510
511

512
513
514
515
516
517
518
519







-
+







	    i++) {
		OFString *name;
		OHGameControllerButton *button;

		if (!OFBitSetIsSet(_keyBits, buttonIDs[i]))
			continue;

		name = buttonToName(buttonIDs[i]);
		name = buttonToName(buttonIDs[i], _vendorID, _productID);
		if (name == nil)
			continue;

		button = [_rawProfile.buttons objectForKey: name];
		if (button == nil)
			continue;

560
561
562
563
564
565
566
567

568
569
570
571
572
573
574
593
594
595
596
597
598
599

600
601
602
603
604
605
606
607







-
+







		case EV_SYN:
			if (event.value == SYN_DROPPED) {
				_discardUntilReport = true;
				continue;
			}
			break;
		case EV_KEY:
			name = buttonToName(event.code);
			name = buttonToName(event.code, _vendorID, _productID);
			if (name == nil)
				continue;

			button = [_rawProfile.buttons objectForKey: name];
			if (button == nil)
				continue;

595
596
597
598
599
600
601





602
603


604
605
606
607
608
609
610
628
629
630
631
632
633
634
635
636
637
638
639


640
641
642
643
644
645
646
647
648







+
+
+
+
+
-
-
+
+







		}
	}
}

- (OHGamepad *)gamepad
{
	@try {
		if (_vendorID == OHVendorIDSony &&
		    _productID == OHProductIDDualSense)
			return [[[OHEvdevDualSense alloc]
			    initWithController: self] autorelease];
		else
		return [[[OHEvdevGamepad alloc]
		    initWithController: self] autorelease];
			return [[[OHEvdevGamepad alloc]
			    initWithController: self] autorelease];
	} @catch (OFInvalidArgumentException *e) {
		return nil;
	}
}

- (OFComparisonResult)compare: (OHEvdevGameController *)otherController
{

Modified src/hid/OHGameController.h from [5443a68735] to [c319f82148].

91
92
93
94
95
96
97









98
99
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108







+
+
+
+
+
+
+
+
+


 * The state returned by @ref OHGameController's methods does not change until
 * this method is called.
 *
 * @throw OFReadFailedException The controller's state could not be read
 */
- (void)retrieveState;
@end

#ifdef __cplusplus
extern "C" {
#endif
extern const uint16_t OHVendorIDSony;
extern const uint16_t OHProductIDDualSense;
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

Modified src/hid/OHGameController.m from [5de26d2df5] to [cbf85ef3d3].

34
35
36
37
38
39
40



41
42
43
44
45
46
47
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50







+
+
+







#ifdef OF_NINTENDO_DS
# import "OHNintendoDSGameController.h"
#endif
#ifdef OF_NINTENDO_3DS
# import "OHNintendo3DSGameController.h"
#endif

const uint16_t OHVendorIDSony = 0x054C;
const uint16_t OHProductIDDualSense = 0x0CE6;

@implementation OHGameController
@dynamic name, rawProfile;

+ (OFArray OF_GENERIC(OHGameController *) *)controllers
{
#if defined(OF_LINUX) && defined(OF_HAVE_FILES)
	return [OHEvdevGameController controllers];