Galaxy Nexus, camera and PVRSRVExportFDToIONHandle

Denis 'GNUtoo' Carikli GNUtoo at no-log.org
Mon Dec 3 18:05:07 UTC 2012


Hi,

I've a galaxy Nexus which has a camera that seems to be tied to the OMX
system which itself uses tiler and ion.
I'm trying to make the camera work under Replicant(A 100% free android
distribution (http://replicant.us/) ).
So the free software userspace camera libs do some read/write
operations on the device node of the OMX driver.
At some point write fails(during camera preview) and the following
messages appear in dmesg:

<6>[  111.117462] PVR_K:(Error): GetHandleStructure: Handle index out
of range (1835561824 >= 0)
[454, /home/gnutoo/embedded/android/replicant-4.0/kernel/samsung/tuna/drivers/gpu/pvr/handle.c]
<6>[  111.117584] PVR_K:(Error): PVRSRVLookupHandle: Error looking up
handle (149)
[1407, /home/gnutoo/embedded/android/replicant-4.0/kernel/samsung/tuna/drivers/gpu/pvr/handle.c]
<6>[  111.117706] PVR_K:(Error): PVRSRVExportFDToIONHandle: Failed to
look up MEM_INFO handle
[78, /home/gnutoo/embedded/android/replicant-4.0/kernel/samsung/tuna/drivers/gpu/pvr/ion.c]

which is because:
 * the OMX kernel driver (drivers/rpmsg/rpmsg_omx.c at
 https://gitorious.org/replicant/kernel_samsung_tuna/blobs/replicant-4.0/drivers/rpmsg/rpmsg_omx.c
 ) uses PVRSRVExportFDToIONHandle.
 * I don't have installed and can't use the proprietary powervr
   libraries.

So I've to replace PVRSRVExportFDToIONHandle...

So I tried 2 approaches:
Approach 1) 
-----------
in userspace I've done a very simple program that
opens /dev/pvrsrvkm and loops after it(in order to prevent
the .close())
it didn't result in the full initialization but the range changed from
(1835561824 >= 0) to (1835561824 >= 256)
There is a program in android named pvrsrvinit and tracing it gives
somehthing like that:
open("/dev/pvrsrvkm", O_RDWR)           = 3
fcntl64(3, F_SETFD, FD_CLOEXEC)         = 0
ioctl(3, 0xc01c670c, 0xbeff698c)        = 0
getpid()                                = 5094
ioctl(3, 0xc01c6745, 0xbeff69cc)        = 0
I must find to what theses ioctl correspond and find their arguments.
I've also found an exploit that might help in understanding how things
works: http://jon.oberheide.org/files/levitator.c

The problem is that I don't understand the pvr driver pass-trough since
it's too much messy.

I also wonder if it can be called source code because the GPLv2 says: 
"The source code for a work means the preferred form of the work for
making modifications to it.", and it seems that they stripped the
comments.

Approach 2)
-----------
The approach 2 was to modify the OMX driver in order to make it not use
PVRSRVExportFDToIONHandle. More precisely to replace that line:
 handle = PVRSRVExportFDToIONHandle(fd, &pvr_ion_client);
I failed at that too, however it seem easier than understanding the
ioctls of the pass-trough powervr driver by reading it.


So far I've done that:
+struct ion_handle *global_handle;
+struct ion_client *global_pvr_ion_client;
 static int rpmsg_omx_open(struct inode *inode, struct file *filp)
{
[...]
+       ion_phys_addr_t phys;
+       size_t size;
+       struct tiler_view_t view;
+       void * memory;
+       int ret;
+                struct omap_ion_tiler_alloc_data sAllocData = {
+                        /* TILER will align width to 128-bytes */
+                        /* however, SGX must have full page width */
+                        .w = 900, //ALIGN(psLINFBInfo->var.xres,
PAGE_SIZE / ( 4  /*psLINFBInfo->var.bits_per
+                        .h = 1600, /* psLINFBInfo->var.yres, */
+                        .fmt =
TILER_PIXEL_FMT_32BIT, //psLINFBInfo->var.bits_per_pixel == 16 ?
TILER_PIXEL_F
+                        .flags = 0,
+                };
[...]
+        global_pvr_ion_client = ion_client_create(omap_ion_device,
+                  1 << ION_HEAP_TYPE_CARVEOUT |1 <<
OMAP_ION_HEAP_TYPE_TILER, "pvr");
+        ret = omap_ion_tiler_alloc(global_pvr_ion_client, &sAllocData);
+       global_handle = sAllocData.handle;
+        if (ret < 0 )
+               printk("[DBG] %s normal alloc failed \n",__func__);
+       else
+               printk("[DBG] %s normal alloc succedded
  \n",__func__); //it succeed
+       ion_phys(global_pvr_ion_client, sAllocData.handle, &phys,
&size);
+       tilview_create(&view, phys, 900, 1600);

And then instead of calling PVRSRVExportFDToIONHandle I would do that:
[...]
+fd = buffer;
+file = fget(fd);
+if (file){
+  handle = global_handle;
+  if (handle &&
+  !ion_phys(global_pvr_ion_client,handle, &paddr, &unused)) {
}
[...]

However that fails too:
AT some point file is false(like when the pvr libs are in use) and pa
becomes 0 in  pa = (phys_addr_t) tiler_virt2phys(buffer); which makes
the whole thing fail.

So I wonder how to make it work: maybe someone knows enough how the
powervr driver works or how ion is supposed to work and what I am doing
wrong...

Denis.


More information about the Replicant mailing list