aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorJan Kratochvil <honza@jikos.cz>2007-05-09 00:27:51 -0400
committerDmitry Torokhov <dtor@insightbb.com>2007-07-10 00:35:15 -0400
commite01a06e8df239de0ffd4ee37d296c7bc3f57e817 (patch)
tree1c5c5ae44ca4c534ba7d2efedfd55f9e36348747 /drivers/input
parentc7d9f7eb30dccf601cbdc67d5bd452f54ce90ce4 (diff)
Input: xpad - add Xbox360 gamepad rumble support
Implementation is using force feedback support for memoryless devices. Signed-off-by: Jan Kratochvil <honza@jikos.cz> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/joystick/Kconfig7
-rw-r--r--drivers/input/joystick/xpad.c125
2 files changed, 128 insertions, 4 deletions
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
index b0023452ec90..12db72d83ea0 100644
--- a/drivers/input/joystick/Kconfig
+++ b/drivers/input/joystick/Kconfig
@@ -268,4 +268,11 @@ config JOYSTICK_XPAD
268 To compile this driver as a module, choose M here: the 268 To compile this driver as a module, choose M here: the
269 module will be called xpad. 269 module will be called xpad.
270 270
271config JOYSTICK_XPAD_FF
272 bool "X-Box gamepad rumble support"
273 depends on JOYSTICK_XPAD && INPUT
274 select INPUT_FF_MEMLESS
275 ---help---
276 Say Y here if you want to take advantage of xbox 360 rumble features.
277
271endif 278endif
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
index f21f84a2dfff..0c04a26b8122 100644
--- a/drivers/input/joystick/xpad.c
+++ b/drivers/input/joystick/xpad.c
@@ -191,6 +191,12 @@ struct usb_xpad {
191 unsigned char *idata; /* input data */ 191 unsigned char *idata; /* input data */
192 dma_addr_t idata_dma; 192 dma_addr_t idata_dma;
193 193
194#ifdef CONFIG_JOYSTICK_XPAD_FF
195 struct urb *irq_out; /* urb for interrupt out report */
196 unsigned char *odata; /* output data */
197 dma_addr_t odata_dma;
198#endif
199
194 char phys[65]; /* physical device path */ 200 char phys[65]; /* physical device path */
195 201
196 int dpad_mapping; /* map d-pad to buttons or to axes */ 202 int dpad_mapping; /* map d-pad to buttons or to axes */
@@ -343,7 +349,113 @@ exit:
343 __FUNCTION__, retval); 349 __FUNCTION__, retval);
344} 350}
345 351
346static int xpad_open (struct input_dev *dev) 352#ifdef CONFIG_JOYSTICK_XPAD_FF
353static void xpad_irq_out(struct urb *urb)
354{
355 int retval;
356
357 switch (urb->status) {
358 case 0:
359 /* success */
360 break;
361 case -ECONNRESET:
362 case -ENOENT:
363 case -ESHUTDOWN:
364 /* this urb is terminated, clean up */
365 dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
366 return;
367 default:
368 dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
369 goto exit;
370 }
371
372exit:
373 retval = usb_submit_urb(urb, GFP_ATOMIC);
374 if (retval)
375 err("%s - usb_submit_urb failed with result %d",
376 __FUNCTION__, retval);
377}
378
379int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect)
380{
381 struct usb_xpad *xpad = input_get_drvdata(dev);
382
383 if (effect->type == FF_RUMBLE) {
384 __u16 strong = effect->u.rumble.strong_magnitude;
385 __u16 weak = effect->u.rumble.weak_magnitude;
386 xpad->odata[0] = 0x00;
387 xpad->odata[1] = 0x08;
388 xpad->odata[2] = 0x00;
389 xpad->odata[3] = strong / 256;
390 xpad->odata[4] = weak / 256;
391 xpad->odata[5] = 0x00;
392 xpad->odata[6] = 0x00;
393 xpad->odata[7] = 0x00;
394 usb_submit_urb(xpad->irq_out, GFP_KERNEL);
395 }
396
397 return 0;
398}
399
400static int xpad_init_ff(struct usb_interface *intf, struct usb_xpad *xpad)
401{
402 struct usb_endpoint_descriptor *ep_irq_out;
403 int error = -ENOMEM;
404
405 if (xpad->xtype != XTYPE_XBOX360)
406 return 0;
407
408 xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN,
409 GFP_ATOMIC, &xpad->odata_dma );
410 if (!xpad->idata)
411 goto fail1;
412
413 xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL);
414 if (!xpad->irq_out)
415 goto fail2;
416
417 ep_irq_out = &intf->cur_altsetting->endpoint[1].desc;
418 usb_fill_int_urb(xpad->irq_out, xpad->udev,
419 usb_sndintpipe(xpad->udev, ep_irq_out->bEndpointAddress),
420 xpad->odata, XPAD_PKT_LEN,
421 xpad_irq_out, xpad, ep_irq_out->bInterval);
422 xpad->irq_out->transfer_dma = xpad->odata_dma;
423 xpad->irq_out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
424
425 input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
426
427 error = input_ff_create_memless(xpad->dev, NULL, xpad_play_effect);
428 if (error)
429 goto fail2;
430
431 return 0;
432
433 fail2: usb_buffer_free(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma);
434 fail1: return error;
435}
436
437static void xpad_stop_ff(struct usb_xpad *xpad)
438{
439 if (xpad->xtype == XTYPE_XBOX360)
440 usb_kill_urb(xpad->irq_out);
441}
442
443static void xpad_deinit_ff(struct usb_xpad *xpad)
444{
445 if (xpad->xtype == XTYPE_XBOX360) {
446 usb_free_urb(xpad->irq_out);
447 usb_buffer_free(xpad->udev, XPAD_PKT_LEN,
448 xpad->odata, xpad->odata_dma);
449 }
450}
451
452#else
453static int xpad_init_ff(struct usb_interface *intf, struct usb_xpad *xpad) { return 0; }
454static void xpad_stop_ff(struct usb_xpad *xpad) { }
455static void xpad_deinit_ff(struct usb_xpad *xpad) { }
456#endif
457
458static int xpad_open(struct input_dev *dev)
347{ 459{
348 struct usb_xpad *xpad = input_get_drvdata(dev); 460 struct usb_xpad *xpad = input_get_drvdata(dev);
349 461
@@ -354,11 +466,12 @@ static int xpad_open (struct input_dev *dev)
354 return 0; 466 return 0;
355} 467}
356 468
357static void xpad_close (struct input_dev *dev) 469static void xpad_close(struct input_dev *dev)
358{ 470{
359 struct usb_xpad *xpad = input_get_drvdata(dev); 471 struct usb_xpad *xpad = input_get_drvdata(dev);
360 472
361 usb_kill_urb(xpad->irq_in); 473 usb_kill_urb(xpad->irq_in);
474 xpad_stop_ff(xpad);
362} 475}
363 476
364static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) 477static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs)
@@ -450,6 +563,10 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
450 for (i = 0; xpad_abs_pad[i] >= 0; i++) 563 for (i = 0; xpad_abs_pad[i] >= 0; i++)
451 xpad_set_up_abs(input_dev, xpad_abs_pad[i]); 564 xpad_set_up_abs(input_dev, xpad_abs_pad[i]);
452 565
566 error = xpad_init_ff(intf, xpad);
567 if (error)
568 goto fail2;
569
453 ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; 570 ep_irq_in = &intf->cur_altsetting->endpoint[0].desc;
454 usb_fill_int_urb(xpad->irq_in, udev, 571 usb_fill_int_urb(xpad->irq_in, udev,
455 usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), 572 usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress),
@@ -479,10 +596,10 @@ static void xpad_disconnect(struct usb_interface *intf)
479 596
480 usb_set_intfdata(intf, NULL); 597 usb_set_intfdata(intf, NULL);
481 if (xpad) { 598 if (xpad) {
482 usb_kill_urb(xpad->irq_in);
483 input_unregister_device(xpad->dev); 599 input_unregister_device(xpad->dev);
600 xpad_deinit_ff(xpad);
484 usb_free_urb(xpad->irq_in); 601 usb_free_urb(xpad->irq_in);
485 usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN, 602 usb_buffer_free(xpad->udev, XPAD_PKT_LEN,
486 xpad->idata, xpad->idata_dma); 603 xpad->idata, xpad->idata_dma);
487 kfree(xpad); 604 kfree(xpad);
488 } 605 }