Monday, 24 October 2016

Reversing PlayStation VR device (I)

First i need to give thanks to:
 The title of this blog article explains very well  about which is the main purpose of this blog entry.

PlayStation VR (before known by Morpheus) is the new device from Sony for Virtual Reality marketplace. As you know there are a few actors right now in this marketplace:
  • Oculus.
  • HTC.
  • Sony.
  • Google.
  • Samsung.
  • Others vendors.

 PlayStation VR need different parts:
  • VR headset.
  • Processor Unit.
  • PlayStation 4
  • PlayStation 4 Camera
  • PlayStation Move and PlayStation dualshock
  • TV with hdmi
Connection schema from Sony:
I have spoken already about PlayStation Move and PlayStation Camera  here in this blog and about its new design in my twitter account:

So now we are going to speak about usb connection between Processor Unit and PlayStation 4 because we want to use PlayStation VR in other platform different than PlayStation 4.

Processor Unit is a black box, if you want to know more about it you will need two things:
  1. Information about hardware. Sony published morpheus_bridge source for 1.50 and 2.0 and it will give you good information about how usb device is build and detailed information about all their 9 interfaces.
  2. An usb dump made with a usb protocol hardware analyzer.
1 was already published and 2 was shared by tokkyo_tw so...


What happen when you connect usb connector from Processor Unit to a Mac/PC?

Easy you can see a new usb device with these usb descriptors

You can check in morpheus_bridge source code that all information is already there.

Usb dump was done with:
  • Software: USB Protocol Suite 7.35
  • Hardware: USBTrace 2500H
USB Protocol Suite can be downloaded from here you must register your user to dowload it.

We are going to work with files from dump:
  • connect-to-ps4 (psvr off).usb
  • connect-to-ps4 (psvr on in game (rez))-then-vrmode-on.usb
  • connect-to-ps4 (psvr on in game (rez)).usb
  • switch-to-vr-mode (in rez).usb
We will choose  connect-to-ps4 (psvr off).usb file first opening it with USB Protocol Suite.

With PlayStation Camera we got dump from beagle hardware analyzer from totalphase and their tool is multiplatform and easy to use for me.

USB Protocol Suite is for windows only and it is  a little hard to use but task can be done with it.

After opening file, choose in menu View Apply Decoding Scripts and check that you have following interfaces and their usb class applied:

and in the endpoint option the same: 

A problem that i find with this tool is that sometimes it can't put the right type of endponint , class and packet size , so check it with usb descriptors first.(Some weird sometimes identify some endpoint with bulk type when they are interrupt type check with usb descriptor that info is correct)

Choose in menu View Transfer Level and Hide all except Transfers options and  in menu Report Detail, View Data and Decode Field View options.

After that we can go transfer by transfer to make our analysis.

I am not going to tech you how usb protocol works for that you have plenty of information, if you don't know about it stop here.

First transfers are about get device and config ,interaface and endpoint descriptors, basically a dump for all descriptors

For your reference these standard request transfer give you all information about device:
  • Transfer 4 device descriptor
  • Transfer 11 configuration descriptor
  • Transfer 12 all descriptor
  • Transfer 13 status
All these transfer can give you all usb descriptor for this device and you can compare with information in morpheus_bridge  source and lsusb output. It is the same.  Check Decoded Field View Tab to see values from these standard requests transfers.

Transfer 14 set usb configuration to 1
Transfer 15 get size for string at index 3: 30 bytes (14 characters)
Transfer 16 get string at index 3 : PS VR 3D Audio  (name associated to interface 0)
Transfer 17 put alternate setting to 1 in inteface 0
Transfer 18 get size for string at index 4: 24 bytes
Transfer 19 get string at index 4: PS VR Audio (name associated to interface 1)
Transfer 20 21 22  23  25 and 26 are audio claass requests to get min max res from both channels associate to control volume features on interface 1
Transfer 24 is a isoc transfer empty no audio send yet to endpoint 1 OUT
Transfer 27 28 29 set volume to channel 1, channel 2 and again channel 1
Transfer 30 set alternate 1 to interface 3
Transfer 31 set alternate 1 to interface 2
Transfer 32 get size for string at index 7 : 26 bytes (12 caracteres)
Transfer 33 get string at index 7:  PS VR Sensor  (associated to interface 4)
Transfer 34 get report descriptor  from interface 4
/*0x06, 0x01, 0xff, // Usage Page (Vendor-defined 0xFF01)
    0x09, 0x01, // Usage (Vendor-defined 0x0001)
    0xa1, 0x01, // Collection (Application)
    0x09, 0x10, // Usage (Vendor-defined 0x0010)
    0x15, 0x00,       //    Logical minimum (0)
    0x26, 0xff, 0x00, //    Logical maximum (255)
    0x75, 0x08,       //    Report Size (8)
    0x95, 0x40,       //    Report Count (64)
    0x81, 0x02,       //    Input
    0xc0 // End Collection
Transfer 35 get size for string at index 8 : 28 bytes (13 caracteres)
Transfer 36 get string at index 8:  PS VR Control    (associated to interface 5)
Transfer 37 get report descriptor from interface 5
    0x06, 0x00, 0xff, // Usage Page (Vendor-defined 0xFF00)
    0x15, 0x00, // Logical Minimum(0)
    0x26, 0xff, 0x00, // Logical Maximun(255)
    0x09, 0x08, //Usage (Vendor-defined 0x0008)
    0xa1, 0x01, // Collection (Application)
    0x09, 0x80, // Usage (Vendor-defined 0x0080)
    0x85, 0x40, // Report ID (0X40)
    0x75, 0x08, // Report Size(0x8)
    0x95, 0x04, // Report Count(0x4)
    0xb1, 0x02, // Feature
Transfer 38 put alternating setting to 3 to interface 6
Transfer 39 get size for string at index 10 : 26 bytes (12 caracteres)
Transfer 40 get string at index 10: PS VR BulkIn  (associated to interface 7)
Transfer 41 get size for string at index 11: 30 bytes (14 caracteres)
Transfer 42 get string at index 11: PS VR Control2  (associated to interface 8)
Transger 43 get report descriptor from interface 8
    0x06, 0xf0, 0xff, // Usage Page (Vendor-defined 0xFFF0)
    0x15, 0x00, // Logical Minimum(0)
    0x26, 0xff, 0x00, // Logical Maximum(255)
    0x75, 0x08, // Report Size(0x8)
    0x95, 0x3f, // Report Count(0x3F)

    0x09, 0x01, // Usage(Vendor-defined 0x0001)
    0xa1, 0x01, // Collection(Application)
    0x85, 0xd0, // Report ID(0xD0)
    0x09, 0xd0, // Usage(Vendor-defined 0x00d0)
    0xb1, 0x02, // Feature

    0x85, 0xd1, // Report ID(0xD1)
    0x09, 0xd1, // Usage(Vendor-defined 0x00d1)
    0xb1, 0x02, // Feature

    0x85, 0xd2, // Report ID(0xD2)
    0x09, 0xd2, // Usage(Vendor-defined 0x00d2)
    0xb1, 0x02, // Feature

    0x85, 0xd3, // Report ID(0xD3)
    0x09, 0xd3, // Usage(Vendor-defined 0x00d3)
    0xb1, 0x02, // Feature
    0xc0, // End Collection 

    0x09, 0x02, // Usage(Vendor-defined 0x0002)
    0xa1, 0x01, // Collection(Application)
    0x85, 0xe0, // Report ID(0xE0)
    0x09, 0xe0, // Usage(Vendor-defined 0x00e0)
    0xb1, 0x02, // Feature

    0x85, 0xe1, // Report ID(0xE1)
    0x09, 0xe1, // Usage(Vendor-defined 0x00e1)
    0xb1, 0x02, // Feature

    0x85, 0xe2, // Report ID(0xE2)
    0x09, 0xe2, // Usage(Vendor-defined 0x00e2)
    0xb1, 0x02, // Feature

    0x85, 0xe3, // Report ID(0xE3)
    0x09, 0xe3, // Usage(Vendor-defined 0x00e3)
    0xb1, 0x02, // Feature

    0x85, 0xe4, // Report ID(0xE4)
    0x09, 0xe4, // Usage(Vendor-defined 0x00e4)
    0xb1, 0x02, // Feature

    0x85, 0xe5, // Report ID(0xE5)
    0x09, 0xe5, // Usage(Vendor-defined 0x00e5)
    0xb1, 0x02, // Feature

    0x85, 0xe6, // Report ID(0xE6)
    0x09, 0xe6, // Usage(Vendor-defined 0x00e6)
    0xb1, 0x02, // Feature

    0x85, 0xe7, // Report ID(0xE7)
    0x09, 0xe7, // Usage(Vendor-defined 0x00e7)
    0xb1, 0x02, // Feature

    0x85, 0xe8, // Report ID(0xE8)
    0x09, 0xe8, // Usage(Vendor-defined 0x00e8)
    0xb1, 0x02, // Feature

    0x85, 0xe9, // Report ID(0xE9)
    0x09, 0xe9, // Usage(Vendor-defined 0x00e9)
    0xb1, 0x02, // Feature

    0x85, 0xef, // Report ID(0xEF)
    0x09, 0xef, // Usage(Vendor-defined 0x00ef)
    0x95, 0x04, // Report Count(0x4)
    0xb1, 0x02, // Feature
    0xc0, // End Collection 

    0x09, 0x40, // Usage(Vendor-defined 0x0040)
    0xa1, 0x01, // Collection(Application)
    0x85, 0xf0, // Report ID(0xF0)
    0x09, 0x47, // Usage(Vendor-defined 0x0047)
    0x15, 0x00, // Logical Minimum(0)
    0x26, 0xff, 0x00, // Logical Maximum(255)
    0x75, 0x08, // Report Size(0x8)
    0x95, 0x3f, // Report Count(0x3F)
    0xb1, 0x02, // Feature

    0x85, 0xf1, // Report ID(0xF1)
    0x09, 0x48, // Usage(Vendor-defined 0x0048)
    0x95, 0x3f, // Report Count(0x3F)
    0xb1, 0x02, // Feature

    0x85, 0xf2, // Report ID(0xF2)
    0x09, 0x49, // Usage(Vendor-defined 0x0049)
    0x95, 0x0f, // Report Count(0x0F)
    0xb1, 0x02, // Feature

    0x85, 0xf3, // Report ID(0xF3)
    0x0a, 0x01, 0x47, // Usage(Vendor-defined 0x4701)
    0x95, 0x07, // Report Count(0x07)
    0xb1, 0x02, // Feature
    0xc0 // End Collection 
Ttrasfer 44 set idle to interface 8

Translation to c/c++ code with libusb api call is direct with all information from dump. All repoorts are described in morpheus_bridge source code so it's confirm all  is fine.


Monday, 24 August 2015

Reversing sceLibCamera

Well, first thanks to all people involved in WebKit exploit. Without their tools i could't dump module and reverse it.

1) We need dump the module. Load libSceCamera.sprx its id is 31. So load it first.

2) Dump it. its index is 20 when it is loaded.

3) Idapro to the rescue. We need offset for all functions that can be called from other modules. Only a brief view and you can see that Sony is using printf("%s ...\n",__FUNCTION__,..) in his code (Thanks of this help Sony) so many function names are you waiting for you with the offset ready :P and plenty of them are the same names that we know from vita and ps3.

you can use getFunctionAddressByName sycall 591 with the names that you see in idapro so you can confirm all function names and the offsets.

The list is:

sceCameraAudioOpen Offset = 0x6d00
sceCameraClose Offset = 0x5550
sceCameraCloseByHandle Offset = 0x55b0
sceCameraGetAttribute Offset = 0x5a10
sceCameraGetAutoExposureGain Offset = 0x5ba0
sceCameraGetAutoWhiteBalance Offset = 0x5d00
sceCameraGetConfig Offset = 0x5710
sceCameraGetContrast Offset = 0x5e60
sceCameraGetDefectivePixelCancellation Offset = 0x5fc0
sceCameraGetDeviceConfig Offset = 0x6dc0
sceCameraGetDeviceInfo Offset = 0x5af0
sceCameraGetExposureGain Offset = 0x6120
sceCameraGetFrameData Offset = 0x5950
sceCameraGetGamma Offset = 0x62c0
sceCameraGetHue Offset = 0x6460
sceCameraGetLensCorrection Offset = 0x65c0
sceCameraGetSaturation Offset = 0x6720
sceCameraGetSharpness Offset = 0x6880
sceCameraGetWhiteBalance Offset = 0x69e0
sceCameraIsAttached Offset = 0x6bd0
sceCameraIsValidFrameData Offset = 0x59b0
sceCameraOpen Offset = 0x5430
sceCameraOpenByModuleId Offset = 0x54c0
sceCameraSetAttribute Offset = 0x5a80
sceCameraSetAutoExposureGain Offset = 0x5c50
sceCameraSetAutoWhiteBalance Offset = 0x5db0
sceCameraSetCalibData Offset = 0x6c70
sceCameraSetConfig Offset = 0x5610
sceCameraSetConfigInternal Offset = 0x5690
sceCameraSetContrast Offset = 0x5f10
sceCameraSetDefectivePixelCancellation Offset = 0x6070
sceCameraSetExposureGain Offset = 0x6200
sceCameraSetGamma Offset = 0x63a0
sceCameraSetHue Offset = 0x6510
sceCameraSetLensCorrection Offset = 0x6670
sceCameraSetSaturation Offset = 0x67d0
sceCameraSetSharpness Offset = 0x6930
sceCameraSetWhiteBalance Offset = 0x6ac0
sceCameraStart Offset = 0x5790
sceCameraStartByHandle Offset = 0x5810
sceCameraStop Offset = 0x5890
sceCameraStopByHandle Offset = 0x58f0

there are more but are internals and you can't use it outside the module.

4) Now fun job. Dissasemble each function that you can use from WebKit. You will see that Sony is using the same error Codes than in vita so this will help you to follow better the code. For example function sceCameraStop is at offset 0x5890 you can see its code in the next capture:

"The first is placed in rdi, the second in rsi, the third in rdx, and then rcx, r8 and r9. Only the 7th argument and onwards are passed on the stack
For calls that may call functions that use varargs or stdargs (prototype-less
calls or calls to functions containing ellipsis (. . . ) in the declaration)
%al is used as hidden argument to specify the number of vector registers used."

so here we go:

edi contains parameter passed to the function. It is comparing with itself so basically if it is less or equal to 0 go to loc_58c7.

You will see that in loc_58c7 it is using something like:

printf("%s invalid handle:%d\n",__FUNCTION,arg1);

then you will see our old friend 802E0000h aka SCE_CAMERA_ERROR_PARAM well known in psp2sdk. So if you pass an arg1 less or equal than 0 to this function  you will get that.

So now what happen if you pass a valid handle greater than 0. When you open it will give you handle 1. If you are not open previously the camera what happen? Test and error and you will see.

if handle >0 it will call loc_58e3 with 2 parameter first is our handle and second you can see in the code. Result is saved on rsx and if it is not 0 (our old friend SCE_OK) it will return code error. For example try to call close before open and it will return  0x802e0004 aka SCE_CAMERA_ERROR_NOT_OPEN

Easy don't you?

int sceCameraClose(int handle) 0 on success error codes on fail

5) Follow reversing functions. Advice some function are using structures in their parameter so it check if these structures are not NULL and depend of the function check the first 32 bits in these structures it is harcoded on the code so it you can call with a valid from WebKit and set the correct values on that first 32 bits you can call all the functions described with success.

6) What do you wait to help to open sdk?

sample output from ps4:

The best is yet to come ;) (greets to Kojima san)

Sunday, 15 February 2015

Reversing PlayStation 4 Camera

I have been working with PlayStation 4 Camera since 2013. So i want to share with you all things learned since then.

First of all, if device has not a public/free driver , you need to make reverse engineering  and you need to look for information about its chipset and make a research about it. So you need to open the device and look for information about its different chips. After making some research we can show the next high level design diagram:

PlayStation 4 Camera is using a propietary connector called AUX, however it is a USB 3 cable so our first goal was to cut off the AUX connector and connect it to  an USB3 male connector, after this we can connect directly to Mac/PC with USB3 female ports.  Next step was to get an USB sniffer capture from PlayStation 4 with a beagle device in the middle, without this we could not have learnt about how to initialize the device and their different options.

Chips description:

  • OV580. It is an asic from Omnivision a typical custom USB bridge solution to manage all other chip. No information or datasheet about it without signing a NDA with Omnivision. Other companies using it are Mantis Vision and LeapMotion. I have worked with others Omnivision USB bridge solutions included in PlayStation EyeToy(OV519) and PlayStation Eye(OV534) so basically it is the same work i made with other drivers for Omnivision.

  • OV9713.  Two cmos sensors well documented with full datasheet available in google.

  • AK5703. An analogical to digital converter connected with an microphone array (4). Datasheet is available.  The datasheet was very helpfull to get audio properly from PlayStation 4 Camera.

  • 4g51A. An eeprom chip. It contains the initial configuration for PlayStation 4 Camera.

When you connect device to a Mac/PC  with  USB3 it  is in boot mode waiting for loading firmware. Analizing sniffer capture we got the firmware and steps needed  to load it  to device. So after loading firmware you have and special UVC Camera device and you can learn about their different streaming modes.

Interface 1 alt setting 0 describe all video modes with these possible options:

  •     mode 0 fps 60(default), 30, 15, 8 video left and video right frames 1280x800

  •     mode 1 fps 120(default), 60, 30, 15, 8 video left and video right frames 640x400

  •     mode 2 fps 240(default), 120, 60, 30 video left and video right frames 320x192

OV580 is delivering in each mode:

  •     mode 0 3448x2x808 bytes frame each row with:
        header 32 bytes
        audio 64 bytes
        video left 1280x2 bytes
        video right 1280x2 bytes
        video interleave 840x2 bytes

  •     mode 1 1748x2x408 bytes frame each row with:
        header 32 bytes
        audio 64 bytes
        video left 640x2 bytes
        video right 640x2 bytes
        video interleave 420x2 bytes
  •     mode 2 898x2x200 bytes frame each row with
        header 32 bytes
        audio 64 bytes
        video left 320x2 bytes
        video right 320x2 bytes
        video interleave 210x2 bytes

Part of Header is showed in the next screenshot:

Part of Audio is showed in the next screenshot:

Audio has 4 channel i use Audicity tool loading a 10 second capture a reproducing 4 audio channels with success.  AK5703 datasheet was very helpfull. An screenshot from audicity tool:

Videl Left and Right can be converted to RGB with CV_YUV2RGB_YUY2 conversion:

cv::Mat yuv(size_y,size_x,CV_8UC2 ,in);
cv::Mat rgb(size_y,size_x,CV_8UC3, out);
 cv::cvtColor(yuv, rgb, CV_YUV2RGB_YUY2);

Video interleave it is also the same video format but it is making a mix of two sensor

A sample application made using basic PS4EYECam driver showing a 640x400 mode for two PlayStation Cameras at the same time:

Low level usb stuff is implemented and available in my repository. EyeLab  is a  poc of multi camera   application using PS4EYECam driver and it is not in the repository,  you don't need to make changes  in the driver to support multi cameras you need to do it at application level.

So after this i can say that PlayStation 4 Camera is full documented and it can be supported on other platforms. All information needed is here and in my repository.

PlayStation 4 receives frames with format explained here. I suppose that secondary processor makes all the job to parse frames(video and audio) and connect with image/audio libraries from sdk(if someone want to share it with me you can contact with me :P).  PlayStation 4 only has 1 AUX port so a multicam solution would be hard to implement like i am doing now in Osx.

Sunday, 21 September 2014

PS4EYECam released

I had released the first public version of PS4EYECam driver.

You can get full information in my PS4EYECam repository

It is the first public driver for PlayStation 4 Camera licensed under gpl.

I have free afternoons availables if someone is interested to offer me a partial job :P

Enjoy and remember the best is yet to come....

Thursday, 28 February 2013

ps3dev builder with Osx Mountain Lion

i have just released a tool to let you build under Osx Mountain Lion:
- Sony binutils and toolchain gcc 4.1.1 for SDK 3.60. Don't ask about how to get SDK 3.60
- ps3dev binutils,toolchain , psl1ght and ps3libraries

More details at:

Enjoy more to come...

Sunday, 27 January 2013

gemlight new libgem sample

New sample available using libgem. It shows how to use PlayStation Move without PlayStation Eye. It is not a graphic sample, you will need your pc/mac listening to show debug messages.

You can get it here

Working now in something for osx's users more to come...

Sunday, 2 October 2011

Eskiss and video output added to gemsample

This weekend KaKaRoToKS released Eskiss with Move support, some parts of gemsaple was added to efl ecore_psl1ght, very cool indeed. Check an enjoy downloading here

Video output is commited now to gemsample in my repo and will be on psl1ght repo soon!!

time to test efl stuff and finish kinect stuff...