3 votes

L'appel à ioctl() sur un périphérique usb utilisant usbfs ne fonctionne pas

J'essaie de créer mon propre pilote pour mon Gamepad en ce moment, j'ai découvert que la raison originale pour laquelle je voulais le créer n'existe pas mais je veux quand même le faire pour l'expérience. Alors ne me dites pas qu'il existe une meilleure façon de faire que d'écrire mon propre pilote.

La partie dans l'espace-noyau avec le ioctl La fonction qui doit être appelée est :

static int xpad_ioctl (struct usb_interface *intf, unsigned int code,void *buf) {
    //struct usb_xpad *xpad = usb_get_intfdata(intf);
    printk(KERN_INFO"(Ongy)IOCTL called\n");

    //if (_IOC_TYPE(code) != XPAD_IOMAGIC) return -ENOTTY;
    //if (_IOC_NR(code) > XPAD_IOMAX) return -ENOTTY;
    switch(code){
        case XPAD_IORMAP:
            printk(KERN_INFO"(Ongy)IORMAP called\n");
            break;
        default:
           return -EINVAL;
    }
    return 0;
}

static struct usb_driver xpad_driver =
{
    .name = "Cyborg-V5-driver",
    .probe = xpad_probe,
    .disconnect = xpad_disconnect,
    .unlocked_ioctl = xpad_ioctl,
    .id_table = xpad_table,
};

La partie dans l'espace utilisateur pour l'appeler est (c'est une partie d'une application Qt) :

int openfile() {
    char *device = "/dev/bus/usb/005/009";
    printf("Opening device %s\n", device);
    return open(device, /*O_RDONLY*/O_WRONLY | O_NONBLOCK );
}

[...] La fonction closefile(int file_desc) est manquante ici, cette fonction et la fonction openfile existent parce que je ne savais pas qu'on pouvait appeler "::open()" quand Qt surcharge les appels de fonctions.

void MainContainer::callioctl() {
    int file_desc, ret_val;
    errno = 0;
    file_desc = openfile();
    if (file_desc==-1){
        printf("Ioctl notcalled because of: error %s\n", strerror(errno));
    }
    else
    {
        errno = 0;
        //struct usbdevfs_getdriver* driver = (usbdevfs_getdriver*)malloc(sizeof(struct usbdevfs_getdriver));
        struct mappingpair* pair = (mappingpair*)malloc(sizeof(struct mappingpair));
        ret_val = ioctl(file_desc, XPAD_IORMAP, pair);
        //printf("Drivername %s\n", driver->driver);
        closefile(file_desc);
        if (ret_val==-1) printf("Ioctl failed with error %s\n", strerror(errno));
        else printf("Ioctl call successfull\n");
    }
}

ok, la chaine du fichier que j'ouvre, je l'obtiens avec un appel à lsusb et je la change à la main dans le code, c'est seulement pour le débogage et jusqu'à ce que je fasse fonctionner les appels ioctl.

Quand j'appelle le callioctl(), il imprime :

Ioctl failed with error Unpassender IOCTL (I/O-Control) für das Gerät

La partie allemande signifie "mauvais ioctl (I/O-Control) pour le périphérique" et rien n'apparaît dans dmesg C'est pourquoi je pense que ma fonction ioctl dans le pilote n'est pas appelée.

0voto

Christophe Augier Points 485

Si vous regardez http://www.hep.by/gnu/kernel/usb/usbfs.html il est dit que pour envoyer un ioctl à la usb_driver appareil que vous devez faire :

struct usbdevfs_ioctl {
    int     ifno;
    int     ioctl_code;
    void    *data;
};

/* user mode call looks like this.
 * 'request' becomes the driver->ioctl() 'code' parameter.
 * the size of 'param' is encoded in 'request', and that data
 * is copied to or from the driver->ioctl() 'buf' parameter.
 */
static int
usbdev_ioctl (int fd, int ifno, unsigned request, void *param)
{
        struct usbdevfs_ioctl   wrapper;

        wrapper.ifno = ifno;
        wrapper.ioctl_code = request;
        wrapper.data = param;

        return ioctl (fd, USBDEVFS_IOCTL, &wrapper);
}

La documentation liste le périphérique usb sous /proc/bus donc il est vrai que cela a pu changer.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X