libVitaMTP & OpenCMA: Vita content management on Linux (and more)

More than a year ago, I’ve analyzed how the Vita communicates with the computer. I mentioned at the end that I started a project that will be an open source implementation of the protocol that the Vita uses. This protocol is just MTP (media transfer protocol) with some additional commands that I had to figure out. MTP is used by most Windows supported media players and cameras, so I was able to use a lot of existing code from libmtp and gphoto2. After lots of on and off work, I am happy to announce the first (beta) version of libVitaMTP and OpenCMA.

What is libVitaMTP and OpenCMA?

In anticipation of allowing developers to include Vita support in their media management applications, and for allowing developers to create custom applications that use the Vita (for example, it would be possible to write an application that uses the Vita as a general purpose storage device), I’ve placed all the backend code into libVitaMTP. This includes connecting of the Vita through libusb-1.0, processing various XML data sent from the device with libxml2, and supports an interface that allows the developer to send the various custom MTP commands to the device.

OpenCMA is the first user-level software that uses libVitaMTP. It serves two purposes. First, it’s a stripped down, open source implementation of CMA, that allows the user to send and receive games, backups, and media to and from the Vita. It is stripped down because Sony’s official CMA supports reading the metadata from media files, and I chose not to include this feature because it would complicate things.

More information can be found on the Github page.

Testing

If you are a developer and wish to include libVitaMTP in your projects, please give feedback on any bugs or difficulties/bad documentation/inconsistant documentation.

If you are a user and wish to test OpenCMA, I’ve provided some Debian packages (created and tested on Ubuntu 12.04) for you to try. After installing, just invoke “opencma -h” in the terminal to see how to use it.

A sample run of OpenCMA could be

$ opencma -u /path/to/dir/containing/updatelist -p /path/to/photos -v /path/to/videos -m /path/to/music -a /path/to/apps -l 4

the -l 4 means to show more logging information. This is very important for filing bug reports. If you encounter a crash or bug, please make sure to include the output of the OpenCMA session with -l 4. Note that more logging means slower transfers.

Please be careful not to pass in large directories because OpenCMA tries to create an index of all files (recursively) for each path.

Please submit all bug reports and feature requests to the Github issues page. It would make things easier if you include the -l 4 output.

Downloads

As always, the most up to date packages will be uploaded to the project page.

Playstation Vita’s USB MTP Connection Analyzed

This is the first of (hopefully) many posts on the PS Vita. Before I attempt anything drastic with the device, such as getting unsigned code to run, I hope I can try something easy (well, easier) to get used to the device. Ultimately, I want to make a content manager for the PS Vita for Linux. Unlike the PSP, the Vita does not export the memory card as a USB storage device, but instead relies on their custom application to copy content to and from the device. This post will give just a peek into how the communication between the Vita and the PC works.

There are two ways of approaching this. One is to sniff the USB packets to figure out what data gets sent to and from the device, and second is to disassemble the content manager application to find out how it communicates with the device. I tried both methods.

Reverse engineering the Content Manager

The biggest problem here is that the PC version of Sony’s content manager has its symbols removed. This makes everything a hundred times harder as you would have a harder time guessing what each function does. Luckily, the OSX version of the content manager does have the symbols intact. The problem here is that IDA does not work perfectly with Objective-C (it works, but you get a C++ish interpretation of Objective-C). I have a good idea of how the application is laid out, but there isn’t much point giving all the details (not useful). I will give some important points:

  • The Vita uses the Media Transfer Protocol, however I am not sure if it adheres completely to standards or if it uses a custom implementation
  • USB endpoint 0×2 is for input, while 0×81 is for data output, and 0×83 is for MTP event output
  • There is support for passing PSN account information to and from the Vita (password would be in plain text!), but it is unimplemented
  • CMA uses a SQLite database to index media information and licenses
Also, I’ve compiled a list of MTP operation codes for the Vita that are referenced in CMA (and therefore implemented in the Vita). Note that some of the codes are not in the standards while others are. For events, the second number is for reference with regards to the jump-table inside CMA only.


Events:
0xC104 0: RequestSendNumOfObject
0xC105 1: RequestSendObjectMetadata
0xC107 3: RequestSendObject
0xC108 4: RequestCancelTask
0xC10B 7: RequestSendHttpObjectFromURL
0xC10F 11: RequestSendObjectStatus
0xC110 12: RequestSendObjectThumb
0xC111 13: RequestDeleteObject
0xC112 14: RequestGetSettingInfo
0xC113 15: RequestSendHttpObjectPropFromURL
0xC115 17: RequestSendPartOfObject
0xC117 19: RequestOperateObject
0xC118 20: RequestGetPartOfObject
0xC119 21: RequestSendStorageSize
0xC120 28: RequestCheckExistance
0xC122 30: RequestGetTreatObject
0xC123 31: RequestSendCopyConfirmationInfo
0xC124 32: RequestSendObjectMetadataItems
0xC125 33: RequestSendNPAccountInfo
0xC801 1789: Unimplemented (seen when getting object from Vita)

Commands:
0x1001: GetDeviceInfo
0x1002: OpenSession
0x1007: GetObjectHandles
0x1008: GetObjectInfo
0x1009: GetObject
0x100C: SendObjectInfo
0x100D: SendObject
0x101B: GetPartialObject
0x9511: GetVitaInfo
0x9513: SendNumOfObject
0x9514: GetBrowseInfo
0x9515: SendObjectMetadata
0x9516: SendObjectThumb
0x9518: ReportResult
0x951C: SendInitiatorInfo
0x951F: GetUrl
0x9520: SendHttpObjectFromURL
0x9523: SendNPAccountInfo
0x9524: GetSettingInfo
0x9528: SendObjectStatus
0x9529: SendHttpObjectPropFromUR
0x952A: SendHostStatus
0x952B: SendPartOfObject (?)
0x952C: SendPartOfObject (?)
0x952E: OperateObject
0x952F: GetPartOfObject
0x9533: SendStorageSize
0x9534: GetTreatObject
0x9535: SendCopyConfirmationInfo (?)
0x9536: SendObjectMetadataItems
0x9537: SendCopyConfirmationInfo (?)
0x9538: KeepAlive
0x9802: ?
0x9803: GetObjectPropValue
0x9805: GetObjectPropList

Response:
0x2001: OK
0x2002: GeneralError
0x2006: ParameterNotSupported
0x2007: IncompleteTransfer
0x200C: StoreFull
0x200D: ObjectWriteProtected
0x2013: StoreNotAvailable
0x201D: InvalidParameter
0xA002: ?
0xA003: ?
0xA004: ?
0xA00A: ?
0xA00D: ?
0xA008: ?
0xA010: ?
0xA012: ?
0xA017: ?
0xA018: ?
0xA01B: ?
0xA01C: ?
0xA01F: ?
0xA020: ?
0xA027: ?

Data Types:
0xDC01: StorageID
0xDC02: ObjectFormat
0xDC03: ProtectionStatus
0xDC04: ObjectSize
0xDC05: AssociationType
0xDC07: ObjectFileName
0xDC08: DateCreated
0xDC09: DateModified
0xDC0A: Keywords
0xDC0B: ParentObject
0xDC0C: AllowedFolderContents
0xDC0D: Hidden
0xDC0E: SystemObject
0xDC41: PersistentUniqueObjectIdentifier
0xDC42: SyncID
0xDC43: PropertyBag
0xDC44: Name
0xDC45: CreatedBy
0xDC46: Artist

Object Formats:
0x3000: Undefined
0x3001: Association
0x3008: WAV
0x3009: MP3
0x3801: EXIF/JPEG
0x3804: BMP
0x3806: UndefinedReserved
0x380A: PICT
0x380B: PNG
0xB007: PSPGame
0xB00A: PSPSave
0xB014: VitaGame
0xB400: ?
0xB411: MNV
0xB984: MNV2
0xB982: MP4/MGV/M4V/MNV3

USB packets

I’ve also captured the USB packets for initializing the device (from device plug-in to Vita displaying the content menu) and gave my best interpretation of it. First line is PC to Vita packet or Vita to PC packet

, followed by packets captured by VMWare running Windows 7, followed by the same action on OSX (dumped from memory using GDB on CMA, not from capturing USB packets), followed by my interpretation of what the packet does (question mark means not sure). EDIT: Some of my comments in the log I know are wrong now.

Next time

I’m hoping to decode these packets and implement them using libusb. I hope Sony is using the MTP standard so I can also make use of libmtp. I also need to be more familiar with how the USB protocol works so I can understand the packet layout better.

EDIT: I’ve begun work on a new project to create an open source content manager for the Vita. As of this post, it can init the device and tell it to show the main menu.