xpad.c
来自「linux 内核源代码」· C语言 代码 · 共 760 行 · 第 1/2 页
C
760 行
/* success */ break; case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); return; default: dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); goto exit; }exit: retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) err("%s - usb_submit_urb failed with result %d", __FUNCTION__, retval);}static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad){ struct usb_endpoint_descriptor *ep_irq_out; int error = -ENOMEM; if (xpad->xtype != XTYPE_XBOX360) return 0; xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN, GFP_ATOMIC, &xpad->odata_dma ); if (!xpad->odata) goto fail1; mutex_init(&xpad->odata_mutex); xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL); if (!xpad->irq_out) goto fail2; ep_irq_out = &intf->cur_altsetting->endpoint[1].desc; usb_fill_int_urb(xpad->irq_out, xpad->udev, usb_sndintpipe(xpad->udev, ep_irq_out->bEndpointAddress), xpad->odata, XPAD_PKT_LEN, xpad_irq_out, xpad, ep_irq_out->bInterval); xpad->irq_out->transfer_dma = xpad->odata_dma; xpad->irq_out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; return 0; fail2: usb_buffer_free(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma); fail1: return error;}static void xpad_stop_output(struct usb_xpad *xpad){ if (xpad->xtype == XTYPE_XBOX360) usb_kill_urb(xpad->irq_out);}static void xpad_deinit_output(struct usb_xpad *xpad){ if (xpad->xtype == XTYPE_XBOX360) { usb_free_urb(xpad->irq_out); usb_buffer_free(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma); }}#elsestatic int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) { return 0; }static void xpad_deinit_output(struct usb_xpad *xpad) {}static void xpad_stop_output(struct usb_xpad *xpad) {}#endif#ifdef CONFIG_JOYSTICK_XPAD_FFstatic int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect){ struct usb_xpad *xpad = input_get_drvdata(dev); if (effect->type == FF_RUMBLE) { __u16 strong = effect->u.rumble.strong_magnitude; __u16 weak = effect->u.rumble.weak_magnitude; xpad->odata[0] = 0x00; xpad->odata[1] = 0x08; xpad->odata[2] = 0x00; xpad->odata[3] = strong / 256; xpad->odata[4] = weak / 256; xpad->odata[5] = 0x00; xpad->odata[6] = 0x00; xpad->odata[7] = 0x00; usb_submit_urb(xpad->irq_out, GFP_KERNEL); } return 0;}static int xpad_init_ff(struct usb_xpad *xpad){ input_set_capability(xpad->dev, EV_FF, FF_RUMBLE); return input_ff_create_memless(xpad->dev, NULL, xpad_play_effect);}#elsestatic int xpad_init_ff(struct usb_xpad *xpad) { return 0; }#endif#if defined(CONFIG_JOYSTICK_XPAD_LEDS)#include <linux/leds.h>struct xpad_led { char name[16]; struct led_classdev led_cdev; struct usb_xpad *xpad;};static void xpad_send_led_command(struct usb_xpad *xpad, int command){ if (command >= 0 && command < 14) { mutex_lock(&xpad->odata_mutex); xpad->odata[0] = 0x01; xpad->odata[1] = 0x03; xpad->odata[2] = command; usb_submit_urb(xpad->irq_out, GFP_KERNEL); mutex_unlock(&xpad->odata_mutex); }}static void xpad_led_set(struct led_classdev *led_cdev, enum led_brightness value){ struct xpad_led *xpad_led = container_of(led_cdev, struct xpad_led, led_cdev); xpad_send_led_command(xpad_led->xpad, value);}static int xpad_led_probe(struct usb_xpad *xpad){ static atomic_t led_seq = ATOMIC_INIT(0); long led_no; struct xpad_led *led; struct led_classdev *led_cdev; int error; if (xpad->xtype != XTYPE_XBOX360) return 0; xpad->led = led = kzalloc(sizeof(struct xpad_led), GFP_KERNEL); if (!led) return -ENOMEM; led_no = (long)atomic_inc_return(&led_seq) - 1; snprintf(led->name, sizeof(led->name), "xpad%ld", led_no); led->xpad = xpad; led_cdev = &led->led_cdev; led_cdev->name = led->name; led_cdev->brightness_set = xpad_led_set; error = led_classdev_register(&xpad->udev->dev, led_cdev); if (error) { kfree(led); xpad->led = NULL; return error; } /* * Light up the segment corresponding to controller number */ xpad_send_led_command(xpad, (led_no % 4) + 2); return 0;}static void xpad_led_disconnect(struct usb_xpad *xpad){ struct xpad_led *xpad_led = xpad->led; if (xpad_led) { led_classdev_unregister(&xpad_led->led_cdev); kfree(xpad_led->name); }}#elsestatic int xpad_led_probe(struct usb_xpad *xpad) { return 0; }static void xpad_led_disconnect(struct usb_xpad *xpad) { }#endifstatic int xpad_open(struct input_dev *dev){ struct usb_xpad *xpad = input_get_drvdata(dev); xpad->irq_in->dev = xpad->udev; if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) return -EIO; return 0;}static void xpad_close(struct input_dev *dev){ struct usb_xpad *xpad = input_get_drvdata(dev); usb_kill_urb(xpad->irq_in); xpad_stop_output(xpad);}static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs){ set_bit(abs, input_dev->absbit); switch (abs) { case ABS_X: case ABS_Y: case ABS_RX: case ABS_RY: /* the two sticks */ input_set_abs_params(input_dev, abs, -32768, 32767, 16, 128); break; case ABS_Z: case ABS_RZ: /* the triggers */ input_set_abs_params(input_dev, abs, 0, 255, 0, 0); break; case ABS_HAT0X: case ABS_HAT0Y: /* the d-pad (only if MAP_DPAD_TO_AXES) */ input_set_abs_params(input_dev, abs, -1, 1, 0, 0); break; }}static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id){ struct usb_device *udev = interface_to_usbdev(intf); struct usb_xpad *xpad; struct input_dev *input_dev; struct usb_endpoint_descriptor *ep_irq_in; int i; int error = -ENOMEM; for (i = 0; xpad_device[i].idVendor; i++) { if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) && (le16_to_cpu(udev->descriptor.idProduct) == xpad_device[i].idProduct)) break; } xpad = kzalloc(sizeof(struct usb_xpad), GFP_KERNEL); input_dev = input_allocate_device(); if (!xpad || !input_dev) goto fail1; xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN, GFP_ATOMIC, &xpad->idata_dma); if (!xpad->idata) goto fail1; xpad->irq_in = usb_alloc_urb(0, GFP_KERNEL); if (!xpad->irq_in) goto fail2; xpad->udev = udev; xpad->dpad_mapping = xpad_device[i].dpad_mapping; xpad->xtype = xpad_device[i].xtype; if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN) xpad->dpad_mapping = dpad_to_buttons; xpad->dev = input_dev; usb_make_path(udev, xpad->phys, sizeof(xpad->phys)); strlcat(xpad->phys, "/input0", sizeof(xpad->phys)); input_dev->name = xpad_device[i].name; input_dev->phys = xpad->phys; usb_to_input_id(udev, &input_dev->id); input_dev->dev.parent = &intf->dev; input_set_drvdata(input_dev, xpad); input_dev->open = xpad_open; input_dev->close = xpad_close; input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); /* set up buttons */ for (i = 0; xpad_btn[i] >= 0; i++) set_bit(xpad_btn[i], input_dev->keybit); if (xpad->xtype == XTYPE_XBOX360) for (i = 0; xpad360_btn[i] >= 0; i++) set_bit(xpad360_btn[i], input_dev->keybit); if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) for (i = 0; xpad_btn_pad[i] >= 0; i++) set_bit(xpad_btn_pad[i], input_dev->keybit); /* set up axes */ for (i = 0; xpad_abs[i] >= 0; i++) xpad_set_up_abs(input_dev, xpad_abs[i]); if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) for (i = 0; xpad_abs_pad[i] >= 0; i++) xpad_set_up_abs(input_dev, xpad_abs_pad[i]); error = xpad_init_output(intf, xpad); if (error) goto fail2; error = xpad_init_ff(xpad); if (error) goto fail3; error = xpad_led_probe(xpad); if (error) goto fail3; ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; usb_fill_int_urb(xpad->irq_in, udev, usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), xpad->idata, XPAD_PKT_LEN, xpad_irq_in, xpad, ep_irq_in->bInterval); xpad->irq_in->transfer_dma = xpad->idata_dma; xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; error = input_register_device(xpad->dev); if (error) goto fail4; usb_set_intfdata(intf, xpad); return 0; fail4: usb_free_urb(xpad->irq_in); fail3: xpad_deinit_output(xpad); fail2: usb_buffer_free(udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); fail1: input_free_device(input_dev); kfree(xpad); return error;}static void xpad_disconnect(struct usb_interface *intf){ struct usb_xpad *xpad = usb_get_intfdata (intf); usb_set_intfdata(intf, NULL); if (xpad) { xpad_led_disconnect(xpad); input_unregister_device(xpad->dev); xpad_deinit_output(xpad); usb_free_urb(xpad->irq_in); usb_buffer_free(xpad->udev, XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); kfree(xpad); }}static struct usb_driver xpad_driver = { .name = "xpad", .probe = xpad_probe, .disconnect = xpad_disconnect, .id_table = xpad_table,};static int __init usb_xpad_init(void){ int result = usb_register(&xpad_driver); if (result == 0) info(DRIVER_DESC ":" DRIVER_VERSION); return result;}static void __exit usb_xpad_exit(void){ usb_deregister(&xpad_driver);}module_init(usb_xpad_init);module_exit(usb_xpad_exit);MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?