driver do gamepad USB para Linux

0

Meus pequenos esforços à imagem e semelhança do driver para o console do jogo joystick "XBOX" foi escrito um pequeno módulo, pelo menos para a verificação pré-teste se a tecla pressionada ou não. Um link para o código-fonte do driver para "XBOX": xpad.c . O joystick para o qual o driver primitivo "DragonRise Inc. PC TWIN SHOCK Gamepad"

Na verdade eu resultado um fragmento de código próprio, o pedido para não pagar na declaração e definição das primeiras estruturas no código. Peço que você observe que a compilação do módulo e a instalação estão indo bem, eu tiro essa conclusão dos dmesg logs. Se você leu o arquivo /proc/bus/input/devices , você pode ver que o dispositivo está conectado com sucesso (o nome e o número do fornecedor são os mesmos). Os arquivos " Event " são exibidos neste arquivo. Se eles são lidos, então é esperado que quando você pressionar qualquer botão no gamepad, qualquer lixo de texto será exibido (por exemplo, se você ler mouse0 e puxar o mouse, ele será o mesmo). O método probe() também é chamado com sucesso se você tentar desconectar o gamepad da entrada USB e inseri-lo de volta:

#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/stat.h>
#include <linux/module.h>
#include <linux/usb/input.h>

#define my_js_vendor_id 0x0079
#define my_js_product_id 0x0006

static const signed short xpad_common_btn[] = {
    BTN_A, BTN_B, BTN_X, BTN_Y,         /* "analog" buttons */
    BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR,  /* start/back/sticks */
    -1                      /* terminating entry */
};

/* original xbox controllers only */
static const signed short xpad_btn[] = {
    BTN_C, BTN_Z,       /* "analog" buttons */
    -1          /* terminating entry */
};

/* used when dpad is mapped to buttons */
static const signed short xpad_btn_pad[] = {
    BTN_TRIGGER_HAPPY1, BTN_TRIGGER_HAPPY2,     /* d-pad left, right */
    BTN_TRIGGER_HAPPY3, BTN_TRIGGER_HAPPY4,     /* d-pad up, down */
    -1              /* terminating entry */
};

/* used when triggers are mapped to buttons */
static const signed short xpad_btn_triggers[] = {
    BTN_TL2, BTN_TR2,       /* triggers left/right */
    -1
};


static const signed short xpad360_btn[] = {  /* buttons for x360 controller */
    BTN_TL, BTN_TR,     /* Button LB/RB */
    BTN_MODE,       /* The big X button */
    -1
};

static const signed short xpad_abs[] = {
    ABS_X, ABS_Y,       /* left stick */
    ABS_RX, ABS_RY,     /* right stick */
    -1          /* terminating entry */
};

/* used when dpad is mapped to axes */
static const signed short xpad_abs_pad[] = {
    ABS_HAT0X, ABS_HAT0Y,   /* d-pad axes */
    -1          /* terminating entry */
};

/* used when triggers are mapped to axes */
static const signed short xpad_abs_triggers[] = {
    ABS_Z, ABS_RZ,      /* triggers left/right */
    -1
};

static struct jdvc {
    struct input_dev *dev;
    struct usb_device *udev;
    struct usb_interface *intf;

    struct urb *irq_in;
    unsigned char *idata;
    dma_addr_t idata_dma;

    char phys[64]; 
} *j;

static void irq_hh(struct urb *urb)
{
    struct jdvc *j = urb->context;
        char *data = j->idata;
    struct input_dev *dev = j->dev;

    //printk(KERN_ERR "%s", data);
    input_report_key(dev, BTN_START,  data[2] & 0x10);
    input_report_key(dev, BTN_SELECT, data[2] & 0x20);

    /* stick press left/right */
    input_report_key(dev, BTN_THUMBL, data[2] & 0x40);
    input_report_key(dev, BTN_THUMBR, data[2] & 0x80);

    /* buttons A,B,X,Y,TL,TR and MODE */
    input_report_key(dev, BTN_A,    data[3] & 0x10);
    input_report_key(dev, BTN_B,    data[3] & 0x20);
    input_report_key(dev, BTN_X,    data[3] & 0x40);
    input_report_key(dev, BTN_Y,    data[3] & 0x80);
    input_report_key(dev, BTN_TL,   data[3] & 0x01);
    input_report_key(dev, BTN_TR,   data[3] & 0x02);
    input_report_key(dev, BTN_MODE, data[3] & 0x04);

    input_sync(dev);
}

static int jopen(struct input_dev *dev) {
    printk(KERN_INFO "%s", j->idata);
    return 0;
}
//static int jclose(struct input_dev *dev);
//usb-0000:00:1d.0-1.6/input101


static int js_probe(struct usb_interface *intf, const struct usb_device_id *id)
{

    struct usb_device *udev; //!
    struct input_dev *input_dev;
    struct usb_endpoint_descriptor *ep_irq_in;
    int ep_irq_in_idx;
    int i;//, error;

    printk(KERN_ERR "js_probe is active");

    j = kzalloc(sizeof(struct jdvc), GFP_KERNEL);
    input_dev = input_allocate_device();
    udev = interface_to_usbdev(intf);

    j->irq_in = usb_alloc_urb(0, GFP_KERNEL); /* irq handler? */

    j->udev = udev;
    j->intf = intf;
    j->dev = input_dev;

    j->idata = usb_alloc_coherent(udev,32,GFP_KERNEL,&j->idata_dma); //DMA buffer

    usb_make_path(udev, j->phys, sizeof(j->phys));
    strlcat(j->phys, "/input101", sizeof(j->phys));


    input_dev->name = "JSD";
    input_dev->phys = j->phys;
    usb_to_input_id(udev, &input_dev->id); //!
    input_dev->dev.parent = &intf->dev;

    input_set_drvdata(input_dev, j);
    input_dev->open = jopen;
    //input_dev->close = jclose;

    input_dev->evbit[0] = BIT_MASK(EV_KEY);

    for (i = 0; xpad_common_btn[i] >= 0; i++)
        __set_bit(xpad_common_btn[i], input_dev->keybit);

    for (i = 0; xpad_btn_pad[i] >= 0; i++)
            __set_bit(xpad_btn_pad[i], input_dev->keybit);

    for (i = 0; xpad_btn_triggers[i] >= 0; i++)
            __set_bit(xpad_btn_triggers[i], input_dev->keybit);

    //for (i = 0; i < BITS_TO_LONGS(KEY_CNT); i++)
    //printk(KERN_INFO "%ld ", input_dev->keybit[i]);

    ep_irq_in_idx = 0;
    ep_irq_in = &intf->cur_altsetting->endpoint[ep_irq_in_idx].desc;


    usb_fill_int_urb(j->irq_in, udev,
             usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), //!
             j->idata, 32, irq_hh,
             j, ep_irq_in->bInterval); //irq handler 

    j->irq_in->transfer_dma = j->idata_dma;
    j->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /**/

    input_register_device(j->dev);

    usb_set_intfdata(intf, j); //!


    return 0;
}

static void js_disconnect(struct usb_interface *intf)
{
    struct jdvc *j = usb_get_intfdata(intf);

    input_unregister_device(j->dev);
    usb_free_urb(j->irq_in);
    kfree(j);

    usb_set_intfdata(intf, NULL);
}

static struct usb_device_id js_table[] =
{
    { USB_DEVICE(my_js_vendor_id, my_js_product_id) },
    {} /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, js_table);

static struct usb_driver js_driver =
{
    .name = "js_driver",
    .id_table = js_table,
    .probe = js_probe,
    .disconnect = js_disconnect,
};

static int __init js_init(void)
{
    printk(KERN_INFO "js drive is installing...\n");
    return usb_register(&js_driver); 
}

static void __exit js_exit(void)
{
    usb_deregister(&js_driver);
}

module_init(js_init);
module_exit(js_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yarik");
MODULE_DESCRIPTION("USB Pen Registration Driver");

Como mencionado anteriormente, /proc/bus/input/devices aponta para os arquivos event3 and js0 . Nem um nem o outro não dão nenhuma reação. Eu acredito que o problema da operação incorreta do método input_report_key (dev, BTN_START, data [2] & 0x10); // data is j-> idata . De alguma forma, ao chamar o manipulador de interrupção, alguns dados especiais em j-> idata devem ser colocados e, de acordo com a descrição desse método, o evento deve corresponder a esse valor. Mas talvez eu não entenda o que é esse valor e como ele se compara com a tecla pressionada. E pode ser que o evento não aconteça, porque as máscaras de bits (o terceiro parâmetro input_report_key) são usadas no joystick de outro. Eu também não tenho certeza se o manipulador URB está registrado corretamente! Ficarei muito feliz com a sua ajuda!

    
por Ayrat Arifullin 23.08.2018 / 17:21

0 respostas