PS5 camera on Linux

At last a Playstation camera that does not require soldering custom cables – comes with USB 3.0!

Short version, I’ll add more details later:

Generally once you attach the camera to the USB you should see it in lsusb:


And you should see it being recognized in dmesg:

[140510.278954] usb 6-1: new SuperSpeed USB device number 2 using xhci_hcd
[140510.292048] usb 6-1: New USB device found, idVendor=05a9, idProduct=0580, bcdDevice= 1.00
[140510.292058] usb 6-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[140510.292062] usb 6-1: Product: USB Boot 
[140510.292064] usb 6-1: Manufacturer: OmniVision Technologies, Inc.

Check first if you are in the plugdev group as the user and can interface USB devices:

groups | grep plugdev

If not – add yourself to it

todo

You will need two repositories, one with custom firmware file for UVC

mkdir ps5 && cd ps5
git clone https://github.com/Hackinside/PS5_camera_files
git clone https://github.com/raleighlittles/PS5-Camera-Firmware-Loader

(as root) Load the udev file

cd ps5/PS5-Camera-Firmware-Loader
cp 100-playstation-camera.rules /etc/udev/rules.d/

it contains a single line:

SUBSYSTEM=="usb", ATTRS{idVendor}=="05a9", ATTRS{idProduct}=="0580", GROUP="plugdev", MODE="0660"

(as root) Reload the udev – be warned, this WILL reload everything, be careful, or just restart the machine if you feel nostalgic of Windows 95 era:

    udevadm control --reload ; udevadm trigger

Make the loader:

    cd ps5/PS5-Camera-Firmware-Loader
    cmake CMakeLists.txt
    make 
    ./ps5_camera_firmware_loader ../PS5_camera_files/firmware.bin 

I made a short script to load it and placed it in ps5 directory:

echo "./PS5-Camera-Firmware-Loader/ps5_camera_firmware_loader PS5_camera_files/firmware.bin " > ps5/start.sh
chmod +x ps5/start.sh

I always get a small error, but everything works either way:

    [ 0.495743] [0000782d] libusb: debug [libusb_free_transfer] transfer 0x2170a68
    ERROR: libusb reported error during control transfer, error# = -4
    Finished uploading firmware!

dmesg should now read:

[140844.373051] usb 6-1: USB disconnect, device number 2
[140844.958867] usb 6-1: new SuperSpeed USB device number 3 using xhci_hcd
[140844.977794] usb 6-1: New USB device found, idVendor=05a9, idProduct=058c, bcdDevice= 1.00
[140844.977803] usb 6-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[140844.977807] usb 6-1: Product: USB Camera-OV580
[140844.977810] usb 6-1: Manufacturer: Omnivision Technologies, Inc.
[140844.985814] usb 6-1: Found UVC 1.00 device USB Camera-OV580 (05a9:058c)

You can now interface the camera using simple V4L2 commands and opencv. I’ve got a laptop, so the webcam occupies first /dev/video0, and the ps5 camera loads as /dev/video2:

bash-5.1$ v4l2-ctl -d /dev/video2 --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
        Type: Video Capture

        [0]: 'YUYV' (YUYV 4:2:2)
                Size: Discrete 896x256
                        Interval: Discrete 0.008s (120.000 fps)
                Size: Discrete 1920x1080
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.125s (8.000 fps)
                Size: Discrete 960x520
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 448x256
                        Interval: Discrete 0.008s (120.000 fps)
                Size: Discrete 1280x800
                        Interval: Discrete 0.017s (60.000 fps)
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.125s (8.000 fps)
                Size: Discrete 640x376
                        Interval: Discrete 0.008s (120.000 fps)
                Size: Discrete 320x184
                        Interval: Discrete 0.004s (240.004 fps)
                Size: Discrete 5148x1088
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.125s (8.000 fps)
                Size: Discrete 3840x1080
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.125s (8.000 fps)
                Size: Discrete 1920x520
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 2560x800
                        Interval: Discrete 0.017s (60.000 fps)
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.125s (8.000 fps)
                Size: Discrete 1280x376
                        Interval: Discrete 0.008s (120.000 fps)
                Size: Discrete 640x184
                        Interval: Discrete 0.004s (240.004 fps)

You can also check what controls can you modify (abridged):

bash-5.1$ v4l2-ctl -d /dev/video2 --all
Driver Info:
        Driver name      : uvcvideo
        Card type        : USB Camera-OV580: USB Camera-OV
        Bus info         : usb-0000:07:00.4-2
...
...
...
                     brightness 0x00980900 (int)    : min=0 max=8 step=1 default=4 value=4
                       contrast 0x00980901 (int)    : min=0 max=8 step=1 default=4 value=4
                     saturation 0x00980902 (int)    : min=0 max=8 step=1 default=4 value=3
                            hue 0x00980903 (int)    : min=0 max=11 step=1 default=0 value=0
 white_balance_temperature_auto 0x0098090c (bool)   : default=1 value=1
                           gain 0x00980913 (int)    : min=0 max=8 step=1 default=4 value=4
           power_line_frequency 0x00980918 (menu)   : min=0 max=2 default=1 value=0
                                0: Disabled
                                1: 50 Hz
                                2: 60 Hz
      white_balance_temperature 0x0098091a (int)    : min=2800 max=6500 step=100 default=4600 value=4600 flags=inactive
                      sharpness 0x0098091b (int)    : min=0 max=8 step=1 default=4 value=4
                  exposure_auto 0x009a0901 (menu)   : min=0 max=3 default=2 value=2
                                0: Auto Mode
                                2: Shutter Priority Mode
              exposure_absolute 0x009a0902 (int)    : min=1 max=5000 step=1 default=1000 value=1000 flags=inactive

WARNING: testing this camera in OBS sometimes requires a restart of OBS (or two) for it to launch properly, but opencv works perfect every times

Time for python!

Install opencv and try the camera:

import cv2

cap = cv2.VideoCapture(2,cv2.CAP_V4L2)

# Check if the webcam is opened correctly
if not cap.isOpened():
    raise IOError("Cannot open webcam")

cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280);
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 376);
cap.set(cv2.CAP_PROP_FPS, 120);

print("Checking mode:", cap.get(cv2.CAP_PROP_FRAME_WIDTH),
                        cap.get(cv2.CAP_PROP_FRAME_HEIGHT),
                        cap.get(cv2.CAP_PROP_FPS) )

import subprocess
subprocess.check_call("v4l2-ctl -d /dev/video2 -c exposure_absolute=300",shell=True)
subprocess.check_call("v4l2-ctl -d /dev/video2 -c saturation=3",shell=True)

while True:
    ret, frame = cap.read()
    cv2.imshow('Input', frame)

    c = cv2.waitKey(1)
    if c == 27:
        break

cap.release()
cv2.destroyAllWindows()

As you can see – I set the exposure (because the ps5 by default can be very dark on linux, a small bug) and saturation for colors.

Of course better view is:

cap.set(cv2.CAP_PROP_FRAME_WIDTH, 2*1280);
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 800);
cap.set(cv2.CAP_PROP_FPS, 60);

(as root) For docker containers – for now I just am allowing everybody to use it, but groups modification should be a better option:

chmod +x /dev/video2