Re: [PATCH 2.6.38] xpad: fix for player indicator and rumble support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Chris,

On Sat, May 14, 2011 at 07:29:00PM -0700, Chris Moeller wrote:
> 1) It removes the bulk send interface and replaces it with a permanent instance of the send interface, which fixes sending LED commands to XBox360 Wireless Controllers, including the initial player number indicator so the light ring will stop flashing endlessly.
> 2) It implements rumble support for XBox360 Wireless Controllers.
> 

Thank you for the patch, please find some comments below.


> Signed-off-by: Chris Moeller <kode54@xxxxxxxxx>
> 
> ---
> 
> I could not separate the two features into different patches because the rumble support change depends on initialization and shutdown changes that are necessary for both features.
> 

It is OK if patches are dependent upon each other. In this case I'd
recommend adding XBox360 Wireless rumble first, keeping the rest of the
driver structure, and then reworking LED support, which requires more
changes.

> Resending this patch which KMail managed to munge because I did not know that it line wraps to fit the composer window regardless of the line wrapping setting. Let's see if a maximized window on 1920x1080 is big enough to get this out without wrapping anything, shall we?
> 
> I'm not sure if it matters, but I found the documentation necessary to implement the packet for XBox360 Wireless Controller rumble support in the source code to the drivers here:
> 
> http://www.katch.ne.jp/~morii/driver/x360wc/index.html
> 
> Neither the page nor the documentation included with the driver or source code, nor the source code itself, make any mention of a license. Does this matter much in the case of deriving knowledge of a single 12 byte data structure?
> 

As long as the code was not used I think this should be OK.

> --- linux/drivers/input/joystick/xpad.c.orig	2011-03-14 18:20:32.000000000 -0700
> +++ linux/drivers/input/joystick/xpad.c	2011-05-14 18:41:08.000000000 -0700
> @@ -250,20 +250,17 @@ struct usb_xpad {
>  	struct usb_device *udev;	/* usb device */
>  
>  	int pad_present;
> +	
> +	int interface_number;
>  
>  	struct urb *irq_in;		/* urb for interrupt in report */
>  	unsigned char *idata;		/* input data */
>  	dma_addr_t idata_dma;
>  
> -	struct urb *bulk_out;
> -	unsigned char *bdata;
> -
> -#if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
>  	struct urb *irq_out;		/* urb for interrupt out report */
>  	unsigned char *odata;		/* output data */
>  	dma_addr_t odata_dma;
>  	struct mutex odata_mutex;
> -#endif
>  
>  #if defined(CONFIG_JOYSTICK_XPAD_LEDS)
>  	struct xpad_led *led;
> @@ -432,13 +429,15 @@ static void xpad360_process_packet(struc
>   *
>   */
>  
> +static void xpad_send_led_command(struct usb_xpad *xpad, int command, int mutex);
> +
>  static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data)
>  {
>  	/* Presence change */
>  	if (data[0] & 0x08) {
>  		if (data[1] & 0x80) {
>  			xpad->pad_present = 1;
> -			usb_submit_urb(xpad->bulk_out, GFP_ATOMIC);
> +			xpad_send_led_command(xpad, 0x42 + ((xpad->interface_number / 2) & 3), 0);

I'd prefer the "command" calculation be hidden in
xpad_send_led_command(), i.e. it should accept led number and figure out
the proper command byte based on device type.

>  		} else
>  			xpad->pad_present = 0;
>  	}
> @@ -492,24 +491,6 @@ exit:
>  		     __func__, retval);
>  }
>  
> -static void xpad_bulk_out(struct urb *urb)
> -{
> -	switch (urb->status) {
> -	case 0:
> -		/* success */
> -		break;
> -	case -ECONNRESET:
> -	case -ENOENT:
> -	case -ESHUTDOWN:
> -		/* this urb is terminated, clean up */
> -		dbg("%s - urb shutting down with status: %d", __func__, urb->status);
> -		break;
> -	default:
> -		dbg("%s - nonzero urb status received: %d", __func__, urb->status);
> -	}
> -}
> -
> -#if defined(CONFIG_JOYSTICK_XPAD_FF) || defined(CONFIG_JOYSTICK_XPAD_LEDS)
>  static void xpad_irq_out(struct urb *urb)
>  {
>  	int retval, status;
> @@ -545,9 +526,6 @@ static int xpad_init_output(struct usb_i
>  	struct usb_endpoint_descriptor *ep_irq_out;
>  	int error;
>  
> -	if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX)
> -		return 0;
> -
>  	xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN,
>  					 GFP_KERNEL, &xpad->odata_dma);
>  	if (!xpad->odata) {
> @@ -579,23 +557,15 @@ static int xpad_init_output(struct usb_i
>  
>  static void xpad_stop_output(struct usb_xpad *xpad)
>  {
> -	if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX)
> -		usb_kill_urb(xpad->irq_out);
> +	usb_kill_urb(xpad->irq_out);
>  }
>  
>  static void xpad_deinit_output(struct usb_xpad *xpad)
>  {
> -	if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX) {
> -		usb_free_urb(xpad->irq_out);
> -		usb_free_coherent(xpad->udev, XPAD_PKT_LEN,
> -				xpad->odata, xpad->odata_dma);
> -	}
> +	usb_free_urb(xpad->irq_out);
> +	usb_free_coherent(xpad->udev, XPAD_PKT_LEN,
> +			xpad->odata, xpad->odata_dma);
>  }
> -#else
> -static 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_FF
>  static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect)
> @@ -632,6 +602,23 @@ static int xpad_play_effect(struct input
>  
>  			return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
>  
> +		case XTYPE_XBOX360W:
> +			xpad->odata[0] = 0x00;
> +			xpad->odata[1] = 0x01;
> +			xpad->odata[2] = 0x0F;
> +			xpad->odata[3] = 0xC0;
> +			xpad->odata[4] = 0x00;
> +			xpad->odata[5] = strong / 256;
> +			xpad->odata[6] = weak / 256;
> +			xpad->odata[7] = 0x00;
> +			xpad->odata[8] = 0x00;
> +			xpad->odata[9] = 0x00;
> +			xpad->odata[10] = 0x00;
> +			xpad->odata[11] = 0x00;
> +			xpad->irq_out->transfer_buffer_length = 12;
> +
> +			return usb_submit_urb(xpad->irq_out, GFP_ATOMIC);
> +
>  		default:
>  			dbg("%s - rumble command sent to unsupported xpad type: %d",
>  				__func__, xpad->xtype);
> @@ -644,7 +631,7 @@ static int xpad_play_effect(struct input
>  
>  static int xpad_init_ff(struct usb_xpad *xpad)
>  {
> -	if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX)
> +	if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX && xpad->xtype != XTYPE_XBOX360W)

This should probably be:

	if (xpad->xtype == XTYPE_UNKNOWN)

>  		return 0;
>  
>  	input_set_capability(xpad->dev, EV_FF, FF_RUMBLE);
> @@ -665,16 +652,33 @@ struct xpad_led {
>  	struct usb_xpad *xpad;
>  };
>  
> -static void xpad_send_led_command(struct usb_xpad *xpad, int command)
> +static void xpad_send_led_command(struct usb_xpad *xpad, int command, int mutex)
>  {
>  	if (command >= 0 && command < 14) {
> -		mutex_lock(&xpad->odata_mutex);
> +		if (mutex) mutex_lock(&xpad->odata_mutex);

No, this conditional locking will not do. What happens if
xpad_send_led_command() gets called from both xpad360w_process_packet()
and xpad_led_set()? There is also bigger problem - we are using the same
URB/buffers as FF playback so we need to make sure we do not stomp on
each other toes.

Thanks.

-- 
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux