Send data to a PS3 DualShock3 controller from a Mac (IOHIDDeviceSetReport)
Asked Answered
A

2

10

I've been playing around with the HID part of IOKit lately on my Mac with a PS3 controller. I've managed to look though the sample code and connect to my controller, receive a stream of data and parse it (Everything, including the accelerometer and gyro).

However, today I decided I wanted to start setting the LEDs on the back of the device and triggering the rumble motors, but I just can't get it to work!

Looking though the sample code Apple provides for IOHID there isn't much I can see on setting things on the HID device, only receiving data. From looking on the web (for petty much half a day) I've got what I think is a working send method which uses IOHIDDeviceSetReport(). However, I can't work out what data I should be sending.

I've found several sites that list data examples:

(I know not all these examples are for between Mac an a PS3 controller)

A lot of people seem to be talking about this and even doing it (I refuse to believe no one has got this working) but I can't seem to find anything about actually how to do it that works!

I feel like I am missing a simple step here, so if anyone has any ideas, help or a solution please let me know.

Thanks.

Example Code of how I'm trying to send a report (is is returning success):

CFIndex len = 64;
uint8_t report[64] = {0x0};

IOReturn  tIOReturn = IOHIDDeviceSetReport(deviceRef,
                                           kIOHIDReportTypeOutput,
                                           reportID,
                                           report,
                                           len);

This is just sending a lot of nothing (literally) but it's just an example of what I'm using just incase it's not correct.

Extra: I've also just noticed that Apples defenition of IOHIDDeviceSetReport differes from there example given.

https://developer.apple.com/library/mac/documentation/DeviceDrivers/Conceptual/HID/new_api_10_5/tn2187.html#//apple_ref/doc/uid/TP40000970-CH214-SW81

There it says report should be "address of report buffer". But...

https://developer.apple.com/library/mac/documentation/IOKit/Reference/IOHIDDevice_iokit_header_reference/Reference/reference.html#//apple_ref/doc/uid/TP40012408-CHIOHIDDevicehFunctions-DontLinkElementID_23

There it say *report (being a pointer) is "The report bytes to be sent to the device.".

Armpit answered 15/10, 2013 at 23:24 Comment(4)
Did you ever get this working to the point where you could change the LEDs and rumble motor states? I have IOKit code working to read out values, but following the below suggestion of setting an output report does not change any LEDs.Widgeon
@TristanSeifert Sadly no. The answer by Karsten was useful but I'd found those linked previously and not been able to get them working. Let me know if you have any luck in the future with rumble or LEDs.Armpit
I've narrowed it down to IOKit giving me an error about writing to a stalled pipe, but there's no documentation on that error and I'm not familiar enough with IOKit to resolve it, so it can be assumed that the data never gets through to the device. I'll look into it more in the future and keep you posted! (if I remember, that is…)Widgeon
I asked Feral why the PS3 Controller does not vibrate even if the game has this option and they told me that the driver that is included by Apple in OS X does not support this. In another discussion about this someone said that Apple has removed ForceFeedback from their drivers (can't remember in which OS this started). --> So since the HID Driver does not support this function it can only fail even if everything is done right. I assume that also means that we can't set the LED.Deepsea
B
3

there's an example at: http://www.circuitsathome.com/mcu/ps3-and-wiimote-game-controllers-on-the-arduino-host-shield-part-2

with the code describing the LED and Rumble control at: https://github.com/ribbotson/USB-Host/blob/master/ps3/PS3USB/ps3_usb.cpp#L187

It seems that the bytes that you sent as report need to have a certain format:

 prog_char output_01_report[] PROGMEM = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                     0x00, 0x02, 0xff, 0x27, 0x10, 0x00, 0x32, 0xff, 
                                     0x27, 0x10, 0x00, 0x32, 0xff, 0x27, 0x10, 0x00, 
                                     0x32, 0xff, 0x27, 0x10, 0x00, 0x32, 0x00, 0x00, 
                                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  };

In the LEDRumble function, these bytes are copied into buf and then buf[9] is overridden to set the LED state and the bytes from buf[1] through buf[4] are used to configure the Rumble. The the bytes are all sent to the controller.

There are some constants defined here: https://github.com/ribbotson/USB-Host/blob/master/ps3/PS3USB/ps3_usb.h#L100

#define psLED1 0x01
#define psLED2 0x02
#define psLED3 0x04
#define psLED4 0x08
#define psRumbleHigh 0x10
#define psRumbleLow 0x20

These constants are passed to the LEDRumble function as parameters.

Bacardi answered 28/12, 2013 at 10:54 Comment(0)
S
2

Their example seems fine, as far as I've read it. Under these circumstances, either an uint8_t[64] variable or an uint8_t* variable will be both interpreted as a pointer to uint8_t when passed to IOHIDDeviceSetReport.

I'm on a restricted network right now, so I won't be able to help any further. But I'll try to read a little bit more about this later at home, as I also have a related project in mind. If I find out anything that can help us on this, I'll get back here to talk about it.

Skittle answered 25/10, 2013 at 14:10 Comment(1)
Thanks, let me know if you come up with anything. :)Armpit

© 2022 - 2024 — McMap. All rights reserved.