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 + -
显示快捷键?