I'm using an Arduino nano 33 IOT and attempting to communicate with a custom plugin i have compiled and running on the PSP.
I'm attempting to replicate what has been achieved in this article (it is in Russian but Google translate works well)
Specifically the RPi script to communicate with the PSP (bottom of the page). I have ran the PSP plugin and RPi script and they work so i'm confident this issue is on my Arduino side rather than the PSP's.
I will attach the RPi script at the bottom of the post to save you trawling through the post.
Iv'e ran the USB_desc
example sketch from the USBHost library downloaded as part of the Boards Manager
package for the Arduino nano 33 iot and it returns a shed load of data about the PSP (the fact i refer to it as shed load should probably hint my lack of USB protocol knowledge)
After finding the device address based on product and vendor id's i figured i would try and send data in the same fashion the RPi script does (it uses libusb
) however i get a error code back.
uint32_t res = usb.outTransfer(*addr, 0, sizeof(PS), (unsigned char *)&PS);
My response is 219
however i have no idea what that means. I assume that's a standard error code for something but im struggling to find out what that something is.
I know the USB protocol is complex with multiple messages to instigate data transfer but i assumed that was handled within the USBHost lib.
Below i have added my entire Arduino script and the script from the linked post for the RPi im trying to port to the Arduino.
I know this is an odd one, but hopefully a fun challenge and any help anyone can offer will be greatly appretiated.
For reference/context i created a PSP Consolizer now attempting to do the same but via usb and custom PSP code to mean i can do the same without opening a PSP (and run on all model PSP's)
My Script
#include "Arduino.h"
#include <usbhub.h>
#include "pgmstrings.h"
#define SONY_VENDOR_ID 0x054C
#define PSP_B_PRODUCT_ID 0x01C9
USBHost usb;
struct
{
unsigned int Pattern;
unsigned int Btn;
unsigned int X;
unsigned int Y;
} PS = {0x1234ABFE, 0, 127, 127};
#define UP 0x00000010
#define DOWN 0x00000040
#define LEFT 0x00000080
#define RIGHT 0x00000020
#define B_X 0x00004000
#define B_O 0x00002000
#define B_KVADRAT 0x00008000
#define B_TREUGOLNIK 0x00001000
#define B_L 0x00000100
#define B_R 0x00000200
#define B_SELECT 0x00000001
#define B_START 0x00000008
#define B_NOTE 0x00800000
uint32_t *addr = NULL;
void setup()
{
pinMode(5, INPUT_PULLUP);
SERIAL_PORT_HARDWARE.begin( 9600 );
while (!SERIAL_PORT_HARDWARE); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
SERIAL_PORT_HARDWARE.println("Start USB Desc");
if (usb.Init() == -1)
SERIAL_PORT_HARDWARE.println("OSC did not start.");
delay( 20 );
}
void findPSPAddress(UsbDeviceDefinition *pdev)
{
USB_DEVICE_DESCRIPTOR buf;
byte rcode = usb.getDevDescr( pdev->address.devAddress, 0, 0x12, ( uint8_t *)&buf );
if (rcode) {
SERIAL_PORT_HARDWARE.print("\n\nERROR: getting usb dev descr");
SERIAL_PORT_HARDWARE.println(rcode);
return;
}
if (buf.idVendor == SONY_VENDOR_ID && buf.idProduct == PSP_B_PRODUCT_ID) {
SERIAL_PORT_HARDWARE.println("\n\nITS A PSP!\n\n");
addr = &pdev->address.devAddress;
}
}
void loop()
{
usb.Task();
if( usb.getUsbTaskState() == USB_STATE_RUNNING )
{
if (!addr) {
usb.ForEachUsbDevice(&findPSPAddress);
} else {
bool pressed = digitalRead(5);
int t = 0;
if (pressed == LOW) {
SERIAL_PORT_HARDWARE.println("\n\nButton PRessed");
PS.Btn |= RIGHT;
t = 1;
}
if (t == 1) {
SERIAL_PORT_HARDWARE.println("\n\nTransfering");
uint32_t res = usb.outTransfer(*addr, 2, sizeof(PS), (unsigned char *)&PS);
SERIAL_PORT_HARDWARE.print("\n\RES: ");
SERIAL_PORT_HARDWARE.println(res);
}
}
delay(5);
}
}
RPi Script attempting to port
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <libusb-1.0/libusb.h>
#define SONY_VENDOR_ID 0x054C
#define PSP_B_PRODUCT_ID 0x01C9
#define UP 0x00000010
#define DOWN 0x00000040
#define LEFT 0x00000080
#define RIGHT 0x00000020
#define B_X 0x00004000
#define B_O 0x00002000
#define B_KVADRAT 0x00008000
#define B_TREUGOLNIK 0x00001000
#define B_L 0x00000100
#define B_R 0x00000200
#define B_SELECT 0x00000001
#define B_START 0x00000008
#define B_NOTE 0x00800000
struct
{
unsigned int Pattern;
unsigned int Btn;
unsigned int X;
unsigned int Y;
} PS = {0x1234ABFE, 0, 127, 127};
struct js_event
{
unsigned int time;
short value;
unsigned char type;
unsigned char number;
};
int is_usbdevblock(libusb_device *dev)
{
struct libusb_device_descriptor desc;
int r = libusb_get_device_descriptor(dev, &desc);
if((desc.idVendor == SONY_VENDOR_ID) && (desc.idProduct == PSP_B_PRODUCT_ID))
{
return 1;
}
return 0;
}
int main(int argc, char** argv)
{
unsigned int real_x = 0, real_y = 0;
int x, y;
int fd = 0;
while(1)
{
libusb_device **list;
libusb_device *found = NULL;
libusb_context *ctx = NULL;
int attached = 0;
libusb_init(&ctx);
libusb_set_debug(ctx, 3);
ssize_t cnt = libusb_get_device_list(ctx, &list);
ssize_t i = 0;
int err = 0;
if(cnt < 0)
{
return -1;
}
for(i = 0; i < cnt; i++)
{
libusb_device *device = list[i];
if(is_usbdevblock(device))
{
found = device;
break;
}
}
if(found)
{
libusb_device_handle *handle;
err = libusb_open(found, &handle);
if (err)
{
return -1;
}
if (libusb_kernel_driver_active(handle, 0))
{
libusb_detach_kernel_driver(handle, 0);
attached = 1;
}
err = libusb_claim_interface(handle, 0);
if (err)
{
return -1;
}
if(fd == 0)
{
fd = open("/dev/input/js0", O_RDONLY);
}
if(fd < 0)
{
goto clean;
}
int nEndpoint = 0x01;
int nTimeout = 500; //in milliseconds
int BytesWritten = 0;
int ret;
struct js_event e;
int t;
while(1)
{
read(fd, &e, sizeof(struct js_event));
e.type &= ~0x80;
t = 0; //transfer = 0;
if(e.type == 1)
{
if(e.value == 1)
{
if(e.number == 0) {PS.Btn |= B_X; t = 1;}
if(e.number == 1) {PS.Btn |= B_O; t = 1;}
if(e.number == 2) {PS.Btn |= B_KVADRAT; t = 1;}
if(e.number == 3) {PS.Btn |= B_TREUGOLNIK; t = 1;}
if(e.number == 4) {PS.Btn |= B_L; t = 1;}
if(e.number == 5) {PS.Btn |= B_R; t = 1;}
if(e.number == 6) {PS.Btn |= B_SELECT; t = 1;}
if(e.number == 7) {PS.Btn |= B_START; t = 1;}
if(e.number == 8) {PS.Btn |= B_NOTE; t = 1;}//XBOX_HOME
//if(e.number == 9) PS.Btn |= ;//L_STICK_PRESS
//if(e.number == 10)PS.Btn |= ;//R_STICK_PRESS
}
if(e.value == 0)
{
if(e.number == 0) {PS.Btn &= ~B_X; t = 1;}
if(e.number == 1) {PS.Btn &= ~B_O; t = 1;}
if(e.number == 2) {PS.Btn &= ~B_KVADRAT; t = 1;}
if(e.number == 3) {PS.Btn &= ~B_TREUGOLNIK; t = 1;}
if(e.number == 4) {PS.Btn &= ~B_L; t = 1;}
if(e.number == 5) {PS.Btn &= ~B_R; t = 1;}
if(e.number == 6) {PS.Btn &= ~B_SELECT; t = 1;}
if(e.number == 7) {PS.Btn &= ~B_START; t = 1;}
if(e.number == 8) {PS.Btn &= ~B_NOTE; t = 1;}
}
}
if(e.type == 2)
{
if(e.number == 6)
{
if(e.value == -32767) {PS.Btn |= LEFT; t = 1;}
if(e.value == 32767) {PS.Btn |= RIGHT; t = 1;}
if(e.value == 0) {PS.Btn &= ~(LEFT | RIGHT); t = 1;}
}
if(e.number == 7)
{
if(e.value == -32767) {PS.Btn |= UP; t = 1;}
if(e.value == 32767) {PS.Btn |= DOWN; t = 1;}
if(e.value == 0) {PS.Btn &= ~(UP | DOWN); t = 1;}
}
if(e.number == 0)
{
if(real_x != ((e.value + 32767) / 256)) {real_x = ((e.value + 32767) / 256); t = 1;}
}
if(e.number == 1)
{
if(real_y != ((e.value + 32767) / 256)) {real_y = ((e.value + 32767) / 256); t = 1;}
}
}
if(t == 1)
{
#define KOEF 1.4
//[-128..0..127]
x = real_x - 128;
y = real_y - 128;
x = x * (1. + ((abs(x) * (KOEF-1.))/(127./KOEF))); if(x > 127) x = 127; if(x < -128) x = -128;
y = y * (1. + ((abs(y) * (KOEF-1.))/(127./KOEF))); if(y > 127) y = 127; if(y < -128) y = -128;
PS.X = 128 + x;
PS.Y = 128 + y;
ret = libusb_bulk_transfer(handle, nEndpoint, (unsigned char *)&PS, sizeof(PS), &BytesWritten, nTimeout);
if(ret < 0)
{
break;
}
}
}
clean:
if(fd)
{
close(fd);
fd = 0;
}
if(attached == 1)
{
libusb_attach_kernel_driver(handle, 0);
}
libusb_close(handle);
}
libusb_free_device_list(list, 1);
libusb_exit(ctx);
sleep(1);
}
return 0;
}
On the face of it the RPi script is not doing anything extensively complex. Communicating with the controller i already have working in my existing Consolizer project. I'm just struggling to find the equivalent libusb
methods in USBHost.