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!