Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ OBJS := $(OBJS) \
src/hid/hid.o \
src/unix/apple/image.o \
src/unix/apple/macosx/hid.o \
src/unix/apple/macosx/hid_gc.o \
src/unix/apple/macosx/gfx/metal-ctx.o

else
Expand Down
4 changes: 4 additions & 0 deletions bang.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
make
cd test
clear
make 0-minimal
10 changes: 9 additions & 1 deletion src/hid/hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

#include "hid.h"
#include "utils.h"

#include "stdio.h"
#include <math.h>
#include <string.h>

Expand Down Expand Up @@ -88,6 +88,10 @@ void mty_hid_driver_init(struct hid_dev *device)
case MTY_CTYPE_XBOX:
xbox_init(device);
break;
case MTY_CTYPE_XBOXW:
printf("Got to initing MTY_CTYPE_XBOXW\n");
xboxw_init(device);
break;
}
}

Expand Down Expand Up @@ -134,6 +138,10 @@ void mty_hid_driver_rumble(struct hid *hid, uint32_t id, uint16_t low, uint16_t
case MTY_CTYPE_XBOX:
xbox_rumble(device, low, high);
break;
case MTY_CTYPE_XBOXW:
printf("IT IS AN XBOXW!\n");
xboxw_rumble(device, low, high);
break;
case MTY_CTYPE_DEFAULT:
mty_hid_default_rumble(hid, id, low, high);
break;
Expand Down
54 changes: 54 additions & 0 deletions src/hid/xboxw.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,59 @@

#pragma once

struct xboxw_state {
bool rumble;
uint16_t low;
uint16_t high;
};

// Rumble

static void xboxw_rumble(struct hid_dev *device, uint16_t low, uint16_t high)
{
struct xboxw_state *ctx = mty_hid_device_get_state(device);

printf("Got here 1\n");
// Xbox 360 wired controller rumble packet format
uint8_t rumble_packet[8] = {0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
rumble_packet[3] = low >> 8; // Low frequency motor intensity
rumble_packet[4] = high >> 8; // High frequency motor intensity
printf("Got here 2 - low: %u, high: %u\n", low >> 8, high >> 8);

mty_hid_device_write(device, rumble_packet, sizeof(rumble_packet));
printf("Got here 3\n");

// Store values for potential retransmission
ctx->low = low;
ctx->high = high;
ctx->rumble = true;
}

static void xboxw_do_rumble(struct hid_dev *device)
{
struct xboxw_state *ctx = mty_hid_device_get_state(device);

if (ctx->rumble) {
uint8_t rumble_packet[8] = {0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
rumble_packet[3] = ctx->low >> 8;
rumble_packet[4] = ctx->high >> 8;
printf("Got here 2\n");

mty_hid_device_write(device, rumble_packet, sizeof(rumble_packet));
printf("Got here 4\n");
ctx->rumble = false;
}
}

static void xboxw_init(struct hid_dev *device)
{
printf("Got to xboxw_init\n");
struct xboxw_state *ctx = mty_hid_device_get_state(device);
ctx->rumble = false;
ctx->low = 0;
ctx->high = 0;
}

static bool xboxw_state(struct hid_dev *device, const void *data, size_t size, MTY_ControllerEvent *c)
{
const uint8_t *d = data;
Expand Down Expand Up @@ -65,6 +118,7 @@ static bool xboxw_state(struct hid_dev *device, const void *data, size_t size, M

c->buttons[MTY_CBUTTON_LEFT_TRIGGER] = c->axes[MTY_CAXIS_TRIGGER_L].value > 0;
c->buttons[MTY_CBUTTON_RIGHT_TRIGGER] = c->axes[MTY_CAXIS_TRIGGER_R].value > 0;
xboxw_do_rumble(device);

return true;
}
40 changes: 37 additions & 3 deletions src/unix/apple/macosx/hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
// You can obtain one at https://spdx.org/licenses/MIT.html.

#include "hid/hid.h"
#include <stdio.h>

#include <IOKit/hid/IOHIDManager.h>
#include <IOKit/hid/IOHIDKeys.h>
#include "hid_gc.h"

#define HID_DEV_GET_USAGE(dev) \
hid_device_get_prop_int(dev, CFSTR(kIOHIDPrimaryUsageKey))
Expand Down Expand Up @@ -63,6 +65,11 @@ static void hid_device_destroy(void *hdevice)

struct hid_dev *ctx = hdevice;

// Clean up GCController rumble context if it exists
if (ctx->device) {
mty_hid_gc_cleanup(ctx->device);
}

MTY_Free(ctx->state);
MTY_Free(ctx);
}
Expand Down Expand Up @@ -223,17 +230,44 @@ void mty_hid_destroy(struct hid **hid)
void mty_hid_device_write(struct hid_dev *ctx, const void *buf, size_t size)
{
const uint8_t *buf8 = buf;


// Check if this is an Xbox controller rumble packet
if (ctx->vid == 0x045E && size >= 8 && buf8[0] == 0x00 && buf8[1] == 0x08) {
// This is an Xbox rumble packet, use GCController instead
uint8_t low_intensity = buf8[3];
uint8_t high_intensity = buf8[4];
// Convert 8-bit (0-255) to 16-bit (0-65535) range
uint16_t low = ((uint16_t)low_intensity << 8) | low_intensity;
uint16_t high = ((uint16_t)high_intensity << 8) | high_intensity;

printf("Xbox rumble: low=%u, high=%u\n", low, high);

if (mty_hid_gc_rumble(ctx->device, low, high)) {
return; // Successfully sent rumble via GCController
}
// Fall through to try IOHIDDeviceSetReport if GCController fails
}

printf("buf8[0]: %d\n", buf8[0]);
printf("size: %zu\n", size);
printf("ctx->device: %p\n", ctx->device);

if (buf8[0] == 0) {
buf += 1;
size -= 1;
}

printf("buf after adjustment: %p\n", buf);
printf("size after adjustment: %zu\n", size);

IOReturn e = IOHIDDeviceSetReport(ctx->device, kIOHIDReportTypeOutput, buf8[0], buf, size);
if (e != kIOReturnSuccess)
printf("Return from IOHIDDeviceSetReport (e): 0x%X\n", e);

if (e != kIOReturnSuccess) {
printf("'IOHIDDeviceSetReport' failed with error 0x%X\n", e);
MTY_Log("'IOHIDDeviceSetReport' failed with error 0x%X", e);
}
}

bool mty_hid_device_feature(struct hid_dev *ctx, void *buf, size_t size, size_t *size_out)
{
const uint8_t *buf8 = buf;
Expand Down
29 changes: 29 additions & 0 deletions src/unix/apple/macosx/hid_gc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT License was not distributed with this file,
// You can obtain one at https://spdx.org/licenses/MIT.html.

#pragma once

#include <stdbool.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

// Send rumble to an Xbox controller using GCController framework
// device: IOHIDDeviceRef pointer
// low: Low frequency rumble intensity (0-65535)
// high: High frequency rumble intensity (0-65535)
// Returns true if rumble was sent successfully
bool mty_hid_gc_rumble(void *device, uint16_t low, uint16_t high);

// Clean up rumble context for a device
void mty_hid_gc_cleanup(void *device);

// Check if GCController rumble is available for a device
bool mty_hid_gc_rumble_available(void *device);

#ifdef __cplusplus
}
#endif
Loading