Chamada do sistema P / Invoke ioctl

Estou desenvolvendo um aplicativo que precisa interagir com a abstração do Video4Linux. O aplicativo é desenvolvido em C #, usando o framework mono.

O problema que estou enfrentando é que eu não posso P / Invocar oioctl chamada do sistema. Ou, mais precisamente, eu posso P / Invoke, mas ele falha muito.

A declaração externa é a seguinte:

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

Por enquanto, tudo bem.

A rotina real que usa oKernelIoCtrl é o seguinte:

<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 o código acima parece bom. A classeIoSpecification é usado para calcular o código de solicitação de E / S após a especificação do cabeçalho (basicamente segue a_IOC macro declarado em/usr/include/linux/asm/ioctl.h.

odata parâmetro é uma estrutura, declarada da seguinte forma:

<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 deve imitar a seguinte estrutura (declarada em/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 ocorrer a falha, havia um problema no cálculo do código de solicitação IOCTL eKernelIoCtrl estava funcionando como esperado (retornandoerrno igual aEINVAL). Quando eu corrigi o bug (e, na verdade, tenho o código de solicitação IOCTRL correto), a chamada foi iniciada para causar uma falha.

Em conclusão, parece que há um problema na organização da estrutura, mas não consigo ver o que está dando errado.

Temo que o problema seja a lista de argumentos variáveis, porque oioctl a rotina é declarada como segue (tirada do homem):

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

Mas eu vi muito código declarando a rotina acima comoint ioctl(int d, int request, void*);e posso garantir que a solicitação IOCTRL específica leve apenas um argumento.

questionAnswers(1)

yourAnswerToTheQuestion