From patchwork Thu Sep 16 05:23:39 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jarod Wilson X-Patchwork-Id: 184462 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o8G5NtBK032693 for ; Thu, 16 Sep 2010 05:23:55 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752160Ab0IPFXy (ORCPT ); Thu, 16 Sep 2010 01:23:54 -0400 Received: from mx1.redhat.com ([209.132.183.28]:53662 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751976Ab0IPFXx (ORCPT ); Thu, 16 Sep 2010 01:23:53 -0400 Received: from int-mx03.intmail.prod.int.phx2.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o8G5NeZA008699 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 16 Sep 2010 01:23:40 -0400 Received: from ihatethathostname.lab.bos.redhat.com (ihatethathostname.lab.bos.redhat.com [10.16.43.238]) by int-mx03.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o8G5NdMf015893 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Thu, 16 Sep 2010 01:23:40 -0400 Received: from ihatethathostname.lab.bos.redhat.com (ihatethathostname.lab.bos.redhat.com [127.0.0.1]) by ihatethathostname.lab.bos.redhat.com (8.14.4/8.14.3) with ESMTP id o8G5NduA023746; Thu, 16 Sep 2010 01:23:39 -0400 Received: (from jarod@localhost) by ihatethathostname.lab.bos.redhat.com (8.14.4/8.14.4/Submit) id o8G5Ndgj023745; Thu, 16 Sep 2010 01:23:39 -0400 X-Authentication-Warning: ihatethathostname.lab.bos.redhat.com: jarod set sender to jarod@redhat.com using -f Date: Thu, 16 Sep 2010 01:23:39 -0400 From: Jarod Wilson To: linux-media@vger.kernel.org Cc: David =?iso-8859-1?Q?H=E4rdeman?= , Dmitry Torokhov , Anders Eriksson , Anssi Hannula Subject: [PATCH 3/4] IR/imon: protect ictx's kc and last_keycode w/spinlock Message-ID: <20100916052339.GD23299@redhat.com> References: <20100916051932.GA23299@redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20100916051932.GA23299@redhat.com> User-Agent: Mutt/1.5.20 (2009-12-10) X-Scanned-By: MIMEDefang 2.67 on 10.5.11.16 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Thu, 16 Sep 2010 05:23:55 +0000 (UTC) diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c index d36fe72..4b73b8e 100644 --- a/drivers/media/IR/imon.c +++ b/drivers/media/IR/imon.c @@ -1,7 +1,7 @@ /* * imon.c: input and display driver for SoundGraph iMON IR/VFD/LCD * - * Copyright(C) 2009 Jarod Wilson + * Copyright(C) 2010 Jarod Wilson * Portions based on the original lirc_imon driver, * Copyright(C) 2004 Venky Raju(dev@venky.ws) * @@ -125,6 +125,7 @@ struct imon_context { struct input_dev *idev; /* input device for panel & IR mouse */ struct input_dev *touch; /* input device for touchscreen */ + spinlock_t kc_lock; /* make sure we get keycodes right */ u32 kc; /* current input keycode */ u32 last_keycode; /* last reported input keycode */ u32 rc_scancode; /* the computed remote scancode */ @@ -1210,6 +1211,9 @@ static bool imon_mouse_event(struct imon_context *ictx, u8 right_shift = 1; bool mouse_input = true; int dir = 0; + unsigned long flags; + + spin_lock_irqsave(&ictx->kc_lock, flags); /* newer iMON device PAD or mouse button */ if (ictx->product != 0xffdc && (buf[0] & 0x01) && len == 5) { @@ -1241,6 +1245,8 @@ static bool imon_mouse_event(struct imon_context *ictx, } else mouse_input = false; + spin_unlock_irqrestore(&ictx->kc_lock, flags); + if (mouse_input) { dev_dbg(ictx->dev, "sending mouse data via input subsystem\n"); @@ -1255,7 +1261,9 @@ static bool imon_mouse_event(struct imon_context *ictx, buf[1] >> right_shift & 0x1); } input_sync(ictx->idev); + spin_lock_irqsave(&ictx->kc_lock, flags); ictx->last_keycode = ictx->kc; + spin_unlock_irqrestore(&ictx->kc_lock, flags); } return mouse_input; @@ -1278,6 +1286,7 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf) char rel_x = 0x00, rel_y = 0x00; u16 timeout, threshold; u32 scancode = KEY_RESERVED; + unsigned long flags; /* * The imon directional pad functions more like a touchpad. Bytes 3 & 4 @@ -1301,7 +1310,11 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf) dir = stabilize((int)rel_x, (int)rel_y, timeout, threshold); if (!dir) { + spin_lock_irqsave(&ictx->kc_lock, + flags); ictx->kc = KEY_UNKNOWN; + spin_unlock_irqrestore(&ictx->kc_lock, + flags); return; } buf[2] = dir & 0xFF; @@ -1363,7 +1376,9 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf) dir = stabilize((int)rel_x, (int)rel_y, timeout, threshold); if (!dir) { + spin_lock_irqsave(&ictx->kc_lock, flags); ictx->kc = KEY_UNKNOWN; + spin_unlock_irqrestore(&ictx->kc_lock, flags); return; } buf[2] = dir & 0xFF; @@ -1392,8 +1407,11 @@ static void imon_pad_to_keys(struct imon_context *ictx, unsigned char *buf) } } - if (scancode) + if (scancode) { + spin_lock_irqsave(&ictx->kc_lock, flags); ictx->kc = imon_remote_key_lookup(ictx, scancode); + spin_unlock_irqrestore(&ictx->kc_lock, flags); + } } /** @@ -1405,6 +1423,9 @@ static int imon_parse_press_type(struct imon_context *ictx, unsigned char *buf, u8 ktype) { int press_type = 0; + unsigned long flags; + + spin_lock_irqsave(&ictx->kc_lock, flags); /* key release of 0x02XXXXXX key */ if (ictx->kc == KEY_RESERVED && buf[0] == 0x02 && buf[3] == 0x00) @@ -1437,6 +1458,8 @@ static int imon_parse_press_type(struct imon_context *ictx, else press_type = 1; + spin_unlock_irqrestore(&ictx->kc_lock, flags); + return press_type; } @@ -1449,6 +1472,7 @@ static void imon_incoming_packet(struct imon_context *ictx, int len = urb->actual_length; unsigned char *buf = urb->transfer_buffer; struct device *dev = ictx->dev; + unsigned long flags; u32 kc; bool norelease = false; int i; @@ -1486,6 +1510,7 @@ static void imon_incoming_packet(struct imon_context *ictx, } } + spin_lock_irqsave(&ictx->kc_lock, flags); /* keyboard/mouse mode toggle button */ if (kc == KEY_KEYBOARD && !ictx->release_code) { ictx->last_keycode = kc; @@ -1493,6 +1518,7 @@ static void imon_incoming_packet(struct imon_context *ictx, ictx->pad_mouse = ~(ictx->pad_mouse) & 0x1; dev_dbg(dev, "toggling to %s mode\n", ictx->pad_mouse ? "mouse" : "keyboard"); + spin_unlock_irqrestore(&ictx->kc_lock, flags); return; } else { ictx->pad_mouse = 0; @@ -1501,6 +1527,7 @@ static void imon_incoming_packet(struct imon_context *ictx, } ictx->kc = kc; + spin_unlock_irqrestore(&ictx->kc_lock, flags); /* send touchscreen events through input subsystem if touchpad data */ if (ictx->display_type == IMON_DISPLAY_TYPE_VGA && len == 8 && @@ -1534,8 +1561,10 @@ static void imon_incoming_packet(struct imon_context *ictx, if (press_type < 0) goto not_input_data; + spin_lock_irqsave(&ictx->kc_lock, flags); if (ictx->kc == KEY_UNKNOWN) goto unknown_key; + spin_unlock_irqrestore(&ictx->kc_lock, flags); if (ktype != IMON_KEY_PANEL) { if (press_type == 0) @@ -1543,33 +1572,43 @@ static void imon_incoming_packet(struct imon_context *ictx, else { ir_keydown(ictx->rdev, ictx->rc_scancode, ictx->rc_toggle); + spin_lock_irqsave(&ictx->kc_lock, flags); ictx->last_keycode = ictx->kc; + spin_unlock_irqrestore(&ictx->kc_lock, flags); } return; } /* Only panel type events left to process now */ + spin_lock_irqsave(&ictx->kc_lock, flags); + /* KEY_MUTE repeats from knob need to be suppressed */ if (ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode) { do_gettimeofday(&t); msec = tv2int(&t, &prev_time); prev_time = t; - if (msec < idev->rep[REP_DELAY]) + if (msec < idev->rep[REP_DELAY]) { + spin_unlock_irqrestore(&ictx->kc_lock, flags); return; + } } + kc = ictx->kc; + + spin_unlock_irqrestore(&ictx->kc_lock, flags); - input_report_key(idev, ictx->kc, press_type); + input_report_key(idev, kc, press_type); input_sync(idev); /* panel keys don't generate a release */ - input_report_key(idev, ictx->kc, 0); + input_report_key(idev, kc, 0); input_sync(idev); - ictx->last_keycode = ictx->kc; + ictx->last_keycode = kc; return; unknown_key: + spin_unlock_irqrestore(&ictx->kc_lock, flags); dev_info(dev, "%s: unknown keypress, code 0x%llx\n", __func__, (long long)scancode); return; @@ -1927,6 +1966,7 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf) } mutex_init(&ictx->lock); + spin_lock_init(&ictx->kc_lock); mutex_lock(&ictx->lock);