P / Invocar llamada al sistema ioctl

Estoy desarrollando una aplicación que necesita interactuar con la abstracción de Video4Linux. La aplicación se desarrolla en C #, usando el framework mono.

El problema al que me enfrento es que no puedo P / Invocar elioctl llamada al sistema. O, más precisamente, puedo P / Invocarlo, pero se bloquea gravemente.

La declaración externa es la siguiente:

<code>[DllImport("libc", EntryPoint = "ioctl", SetLastError = true)]
private extern static int KernelIoCtrl(int fd, int request, IntPtr data);
</code>

Hasta ahora tan bueno.

La rutina real que utiliza elKernelIoCtrl es el siguiente:

<code>protected virtual int Control(IoSpecification request, object data)
{
    GCHandle dataHandle;
    IntPtr dataPointer = IntPtr.Zero;

    try {
        // Pin I/O control data
        if (data != null) {
            dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
            dataPointer = dataHandle.AddrOfPinnedObject();
        }
        // Perform I/O control
        int result =  KernelIoCtrl(mFileDescriptor, request.RequestCode, dataPointer);
        int errno = Marshal.GetLastWin32Error();

        // Throw exception on errors
        if (errno != (int)ErrNumber.NoError)
            throw new System.ComponentModel.Win32Exception(errno);

        return (result);
    } finally {
        if (dataPointer != IntPtr.Zero)
            dataHandle.Free();
    }
}
</code>

Todo el código anterior parece bueno. La claseIoSpecification se utiliza para calcular el código de solicitud de E / S siguiendo la especificación del encabezado (básicamente, sigue la_IOC macro declarada en/usr/include/linux/asm/ioctl.h.

losdata El parámetro es una estructura, declarada de la siguiente manera:

<code>[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct Capability
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
    public string Driver;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
    public string Device;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
    public string BusInfo;

    public UInt32 Version;

    public CapabilityFlags Capabilities;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
    public UInt32[] Reserved;
}
</code>

que debe imitar la siguiente estructura (declarada en/usr/include/linux/videodev2.h):

<code>struct v4l2_capability {
    __u8    driver[16];     /* i.e. "bttv" */
    __u8    card[32];       /* i.e. "Hauppauge WinTV" */
    __u8    bus_info[32];   /* "PCI:" + pci_name(pci_dev) */
    __u32   version;        /* should use KERNEL_VERSION() */
    __u32   capabilities;   /* Device capabilities */
    __u32   reserved[4];
};
</code>

Antes de tener la falla, hubo un problema en el cálculo del código de solicitud de IOCTL y laKernelIoCtrl estaba trabajando como se esperaba (devolviendo unerrno igual aEINVAL). Cuando corregí el error (y de hecho con el código de solicitud IOCTRL correcto), la llamada comenzó a causar un bloqueo.

En conclusión, parece que hay un problema en el ordenamiento de la estructura, pero no puedo ver qué está mal.

Me temo que el problema es la lista de argumentos variables, porque laioctl La rutina se declara como sigue (tomada del hombre):

<code>int ioctl(int d, int request, ...);
</code>

Pero vi mucho código declarando la rutina anterior comoint ioctl(int d, int request, void*);, y puedo asegurarme de que la solicitud IOCTRL específica tome solo un argumento.

Respuestas a la pregunta(1)

Su respuesta a la pregunta