Onde encontro o ioctl EVIOCGRAB documentado?

5

Eu quero usar a função ioctl EVIOCGRAB em um programa baseado em C, e pesquisando por aí eu encontrei vários bits de código-fonte exemplo que usam a função, mas estou lutando para encontrar documentação explícita que descreve corretamente como usá-lo corretamente.

Vejo que de ioctl (2) , a função ioctl está definida como

int ioctl(int d, unsigned long request, …);

E isso:

   The third argument is an untyped pointer to memory.  It's traditionally char
   *argp (from the days before void * was valid C), and will be so named
   for this discussion.

E eu esperava encontrar EVIOCGRAB listado em ioctl_list (2) , mas não foi.

Então eu não sei qual deve ser o terceiro argumento para a função EVIOCGRAB . Depois de ver vários bits de código de exemplo, tudo o que posso fazer é assumir que um valor diferente de zero captura o dispositivo e que um valor zero o libera.

O que recebi de exemplos de código aleatório, como

int grab = 1;
ioctl(fd, EVIOCGRAB, &grab);
..
ioctl(fd, EVIOCGRAB, NULL); 

ou

ioctl(fd, EVIOCGRAB, (void*)1);
..
ioctl(fd, EVIOCGRAB, (void*)0); 

ou

ioctl(fd, EVIOCGRAB, 1);
..
ioctl(fd, EVIOCGRAB, 0); 

(que parece cheirar um pouco de programação de cultos de carga.)

Então, onde posso encontrar uma explicação definitiva do parâmetro de controle EVIOCGRAB ?

    
por Peter M 28.04.2014 / 22:21

1 resposta

3

Uma explicação definitiva que você pode pelo menos encontrar nos fontes do kernel, mais especificamente drivers/input/evdev.c :

 static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                            void __user *p, int compat_mode)
 {
 […]
     switch (cmd) {
     […]
     case EVIOCGRAB:
         if (p)
             return evdev_grab(evdev, client);
         else
             return evdev_ungrab(evdev, client);
     […]
     }
 […]
 }

Pelo que entendi, tudo o que é avaliado como "false" ( 0 ) levará a evdev_ungrab ( (void*)0 , 0 ,…), tudo que é "verdadeiro" (não 0 ) causará um evdev_grab ( (void*)1 , 1 , 0xDEADBEEF …).

Uma coisa que vale a pena mencionar é que seu primeiro exemplo,

int grab = 1;
ioctl(fd, EVIOCGRAB, &grab);
..
ioctl(fd, EVIOCGRAB, NULL); 

funciona apenas de forma não intencional. Não é o valor dentro de grab , mas o fato de que &grab é diferente de zero (você poderia ter adivinhado isso, já que a caixa não é grab = 0; ioctl(…, &grab); mas ioctl(…, NULL); Engraçado.:)

    
por 29.04.2014 / 00:30