Author Topic: Performing a PS Vita UART Mod  (Read 9736 times)

Offline dots_tb

  • Refugee
  • **
  • Posts: 93
    • View Profile
Performing a PS Vita UART Mod
« on: January 18, 2020, 02:52:55 AM »
FAPS Team is currently working on something that required better logs as the current "real-time" logging methods used, while well written, did not perform well enough for this. Thus, I looked into getting UART, a simple serial communication, out on the Vita. This is not a new hack and has been known forever thanks to the work of Yiffy and the vita scene lord Xerpi.

This article is just a compilation of their work and the steps I took to replicate it. If a brainlet like myself can do it, so can you!(Don't blame me if you are an omega brainlet and break something though)

If you are in EE, you can just stay for some laughs.

Also Disclaimer: I am not an EE and I do not claim to be and again am not responsible for what happens to your device. This is just what worked for me.

Making a plan:

I only have one Vita, so I only had one chance, so I did as much research as my patience would allow. From the information on the internet (henkaku wiki -https://wiki.henkaku.xyz/vita/UART_Console):

  • UART0 is obtainable on the PS TV and on OLED 1000 Vita models. On the PSV1000, there are two points to obtain UART0: On the multi-connector or in the metal can near the multi-connector. All points have easily solder-able test pads. However, the one directly on the multi-connector, you need to deal with that switch thing and they have a bit smaller pads.
  • On the multi-connector itself.
  • Furthermore, the 3G model has UART5 on it's PCIE connector but who cares you can get that with Yifan's PSVD.
  • The logic level is 1.8v!
  • It seemed that you can use both UART0 and UART5 them respectively. The number is the port.

After consulting with Celesteblue. I found that his Frankenvita, created by CentrinoUK, uses the one under the metal can (Kermit UART0). He said that the multi-connector one was not proven to be working (the one with the extra connections and the nonsense with the jumper).

So with this information, I decided to mod my PSV1000 to get Kermit UART0 using the test pads under the metal can because I could use the same applications as Celeste, there is a labeled points for 1.8v, and it is known to work thus removing uncertainty.

However, there comes the hurdle of actually having a device for communication. I don't like spending money and waiting, so I decided to use devices already have. I had just recently found an Arduino pro micro clone (I lost it right before I did my port of psp2048), so I used that.

Modding the Vita:

This is not a teardown, go to iFixit or something. However some tips if you are too lazy like me:

Do not remove the front facing camera from the mainboard (it is the one with the thick connector that goes into a ZIF socket) until you remove the mainboard. Do not remove the mainboard until you free the front facing camera from underneath the controller board. Watch out when removing the controller board as I broke one of the connectors, nothing a bit of tape can't fix... This probably wouldn't be a problem for careful people. Which I am not.

Click the images for larger versions:


Opening the metal can was probably the hardest part of dissembling the device, it's not soldered, just an annoyance to lift.

I used a solenoid's wires (thin wire with enamel) and soldered them to each of the necessary points. To remove the insulation off the wire, use a hot solder blob on the tip of the soldering iron or burn it with a lighter. For UART, you only need: TX, RX, GND, 1.8v. There are holes in the metal can that are big enough for these wires to escape. Please keep in mind that the Vita is a premium product, and these wires will turn them into a Nintendo DS.

I pushed the power related wires and the communication wires through different holes. This makes it so you can identify them with one color of tape. Speaking of tape, I covered the soldered points with tape to insulate from the metal can (especially that capacitor with the power wires). No, tx is not touching that capacitor... I think. Be sure before covering that you test the connections, obviously. These points were quite easy to solder to even with my shaky hands and terrible tools. I used a Michael's woodcraft soldering iron with a pitted conical tip with no magnification.



A hole was burned through using the same soldering iron, the vita plastic had a weird gritty feeling while melting it. It is pretty easy to form a desired exit for the header (just get any header and trim it down or use any connector you have lying around). I don't remember if I started burning from the inside or outside, sorry. Regardless, watch out for the battery.



There is also plenty of space internally which a header could easily fit. Zexceil was able to fit a USB port in his 3g model. I am wondering if you could another SD card slot maybe for an SD2Vita... If only I had not wasted so much space with this UART. Also, before putting hot glue don't be a tough guy like myself. I didn't test it before hot gluing and the first time it did not work so I had to rip it out.



I was going to put a disconnect header, but whatever. You can see I broke the battery connector (from repeatably testing the UART as you will see later)... You can also see I used blue tape to distinguish wire pairings, you could just get away with one color tape though. I used the following pinout:
1 1.8v
2 Tx -blue
3 Rx -black -blue
4 GND - black



Not a bad job for a brainlet, probably should have pushed the header in more though. I will write here (before I forget) that pin 1 is closer to the multi-connector, hopefully this site doesn't go down... You should mark yours with a pen or make some sort of key pin. This was a relatively simple mod to perform. All in all, I managed to only break the battery connector, one controller connector, and left only one screw out! This is good for me. The bulk of the issues came in testing it without a known working UART communicator...

The Pain of Getting UART

The rest of the process is dedicated to documenting getting 1.8v logic levels to work with the Arduino pro micro's 5v logic levels.
Many devices use either 3.3v (Linux computers like odroid or Raspberry pi), ESP2866 or 5v (many Arduinos), thus you must have a logic level shifter or circuitry to compensate. Or you could just buy a UART communication device that supports 1.8v (again many cheap ones only support 3.3v and 5v).

I found some guy ran into the same issue and fixed it with the diagram in this post: https://forum.arduino.cc/index.php?topic=160716.msg1210677#msg1210677. Luckily I had a bags of assorted transistors and resistors from when I biked to Radio Shack as a kid one summer. I just say that because it sounds extremely boomer.

It was a great pain getting this to work because I did not know if it was my Vita, Arduino and its code, or the circuitry was at fault.

I confirmed the Vita connection worked and that UART on the Vita was initialized properly because I had originally had a broken Arduino nano with the ATMEL chip ripped off to use as a serial device (this route did not work btw) which exposed blinking RX lights when the Vita was sending data through a test application. The Vita also reacted when I removed the RX line connection from Vita. I switched to using a pro micro (again).

I am relatively new to the microcontroller memes, but I managed to code something to redirect Serial1 to Serial. After a while, I started to get weird symbols on the serial monitor. I messed with the baud rate (115200 recommended by Celeste), and restarted the pro micro a couple times. Then finally remembered you send characters not strings.

However, there was no sending (PC-> Vita) yet. I used a voltage divider, it didn't work. I tried inverting it, it didn't work. Then I realized I forgot to code the redirection of input... Then the characters came in wrong with "q" coming back as "G" on the Vita.

Code: [Select]
q 01110001
G 01000111

I'm sure you can now see the inverter is not necessary... So voltage divider only, it is.

Thus, here is the circuit I used (it's mostly that guys diagram redrawn to be more absolute with a voltage divider). Please keep in mind you will have to recalculate the voltage divider, easily googe-able or you can pay thousands of dollars and go to University.

Diagram for 1.8v to 5v logic levels:



UPDATE: I got the broken Arduino nano to work, thus do not need the script. This was accomplished by using a wire bypassing the resistors on the bottom of the board creating a direct line for the tx and rx line to the CH340G. The original diagram had a 1k resistor going to the Vita, however it is 10k in the build. I have updated the diagram to reflect that.

It finally all put together:



Vita Side kplugin code:

Code: [Select]
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <vitasdkkern.h>

#include <taihen.h>

#define printf ksceDebugPrintf

static tai_hook_ref_t SceLowio_kscePervasiveUartResetEnable_ref;
static SceUID SceLowio_kscePervasiveUartResetEnable_hook_uid = -1;
static tai_hook_ref_t SceLowio_ScePervasiveForDriver_81A155F1_ref;
static SceUID SceLowio_ScePervasiveForDriver_81A155F1_hook_uid = -1;
static int kscePervasiveUartResetEnable_hook_func(int uart_bus)
{
/*
* We want to keep the UART enabled...
*/
return 0;
}

/*
 * Returns ScePervasiveMisc vaddr, ScePower uses it to disable the UART
 * by writing 0x80000000 to the word 0x20 bytes past the return value.
 */
static void *ScePervasiveForDriver_81A155F1_hook_func(void)
{
static unsigned int tmp[0x24 / 4];
//LOG("ScePervasiveForDriver_81A155F1()\n");
return tmp;
}


int module_start(SceSize argc, const void *args) {
SceLowio_kscePervasiveUartResetEnable_hook_uid = taiHookFunctionExportForKernel(KERNEL_PID,
&SceLowio_kscePervasiveUartResetEnable_ref, "SceLowio", 0xE692C727,
0x788B6C61, kscePervasiveUartResetEnable_hook_func);

SceLowio_ScePervasiveForDriver_81A155F1_hook_uid = taiHookFunctionExportForKernel(KERNEL_PID,
&SceLowio_ScePervasiveForDriver_81A155F1_ref, "SceLowio", 0xE692C727,
0x81A155F1, ScePervasiveForDriver_81A155F1_hook_func);

printf("kscePervasiveUartClockEnable %x\n:", kscePervasiveUartClockEnable(0)); // Turn on clock
printf("kscePervasiveUartResetDisable %x\n", kscePervasiveUartResetDisable(0)); // Out of reset
printf("ksceUartInit %x\n", ksceUartInit(0));
printf("kscePervasiveUartSetBaudrate %x\n", kscePervasiveUartSetBaudrate(0, 115200));

ksceKernelDelayThread(100000);
ksceUartWrite(0, 'h');
ksceKernelDelayThread(100000);
ksceUartWrite(0, 'e');
ksceKernelDelayThread(100000);
ksceUartWrite(0, 'l');
ksceKernelDelayThread(100000);
ksceUartWrite(0, 'l');
ksceKernelDelayThread(100000);
ksceUartWrite(0, 'o');
int done = 0;
while(!done) {
if(ksceUartReadAvailable(0)){
int c = ksceUartRead(0);
printf("get char %c\n",c);
if(c == 'q')
break;
}
}
}
int module_stop(SceSize argc, const void *args)
{
return SCE_KERNEL_STOP_SUCCESS;
}

Arduino Sketch:

Code: [Select]
void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial1.begin(115200);

}

void loop() {
  // put your main code here, to run repeatedly:
  if(Serial1.available()) {
  int c = Serial1.read();
  Serial.write(c);
  }
  if(Serial.available()) {
  int c = Serial.read();
  Serial1.write(c);
  }
}

Anyways, it was not a good idea to introduce so many places for errors without many knowns especially with no background in this. Hopefully this will help you also reduce your errors and learned something though. However, you could literally skip the second half if you just wait 2 days for Amazon prime and pay the 12 dollars. I apologize for the dirty objects in the pictures.

UPDATE:
Celeste has given his recommendations:
UART Serial adapter:https://www.amazon.fr/AptoFun-Convertisseur-convertisseur-broches-Arduino/dp/B01IROOL5U/
(This may not be available in your area)
Software for communication:https://realterm.sourceforge.io/

Here is everything in action (UART on the right, stdout from the vita on the left):



We will release a plugin to make stdout go to UART at a later date.

I hope you will attempt this mod, it was a nice learning experience.

Special thanks:
Xerpi
Team Molecule
Celesteblue
Princess of Sleeping
CentrinoUK
Sysie
runaway_pancak
« Last Edit: January 18, 2020, 10:31:42 PM by dots_tb »

Offline chrisdevchroma

  • End User
  • *
  • Posts: 8
    • View Profile
Re: Performing a PS Vita UART Mod
« Reply #1 on: January 19, 2020, 02:00:11 PM »
Nice~

Offline dots_tb

  • Refugee
  • **
  • Posts: 93
    • View Profile
Re: Performing a PS Vita UART Mod
« Reply #2 on: January 20, 2020, 02:48:07 AM »
Based. I'd leave the Arduino part out and just mount a serial connector though.  Other than that, really really based. So based it makes me want to do it too.
It already says that you should skip the Arduino stuff. It's mostly just for documentation just in case someone else has the same issue/idea.

Offline dots_tb

  • Refugee
  • **
  • Posts: 93
    • View Profile
Re: Performing a PS Vita UART Mod
« Reply #3 on: March 02, 2020, 06:06:01 AM »
Code: [Select]
void putchar_sub(int args, char *c) {
ksceUartWrite(0, c);
}

int init_uart_test() {
printf("kscePervasiveUartClockEnable %x\n:", kscePervasiveUartClockEnable(0)); // Turn on clock
printf("kscePervasiveUartResetDisable %x\n", kscePervasiveUartResetDisable(0)); // Out of reset
printf("ksceUartInit %x\n", ksceUartInit(0));
printf("kscePervasiveUartSetBaudrate %x\n", kscePervasiveUartSetBaudrate(0, 115200));

ksceKernelDelayThread(100000);
ksceUartWrite(0, 'h');
ksceKernelDelayThread(100000);
ksceUartWrite(0, 'e');
ksceKernelDelayThread(100000);
ksceUartWrite(0, 'l');
ksceKernelDelayThread(100000);
ksceUartWrite(0, 'l');
ksceKernelDelayThread(100000);
ksceUartWrite(0, 'o');

ksceDebugRegisterPutcharHandler(&putchar_sub, 0);
}

This is the code I used to test stdout on uart. However, you could probably can properly enable it by looking at sysmem's start up which has mechanisms to enable it. I didn't really need it so I never looked into it.

You could also probably put ksceUartWrite directly into ksceDebugRegisterPutcharHandler.

Teakhanirons asked for this so I decided to post it.