From patchwork Wed May 4 20:25:11 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Euchner X-Patchwork-Id: 9018591 Return-Path: X-Original-To: patchwork-linux-input@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 8763C9F1D3 for ; Wed, 4 May 2016 20:26:09 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7FA722020F for ; Wed, 4 May 2016 20:26:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7ABA8201EC for ; Wed, 4 May 2016 20:26:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752524AbcEDU0F (ORCPT ); Wed, 4 May 2016 16:26:05 -0400 Received: from mail-wm0-f68.google.com ([74.125.82.68]:33301 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752666AbcEDU0E (ORCPT ); Wed, 4 May 2016 16:26:04 -0400 Received: by mail-wm0-f68.google.com with SMTP id r12so12877988wme.0; Wed, 04 May 2016 13:26:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=uh2gurlFCfKidILPQwgDGINwD1Y4If9oqEScPiE96vM=; b=RmvzPJcDbL7UF3lxa4qiUeb3JLHsVVn4KUDjAnzl9l21/tfacaRRhbqjSJQzEnrrEg /1NFFoMmDlcJj9uo8YJVgCTNFwy/2DjGh8w0bdX0yDQdBZ8mQdml8+qW2FDSTurtLeoC +XSBgBNwPDNEb5bENBdBbGgvwQanmbUVvUJXnrGaYBKUPM2HvkHtqcMixLGcfoocSkU/ HZtNeiIVydwvB+/R01oDwwT7nLM54MP3VthG56Ztes8SQjR6efYxxgwsQQS1MiCA2Osr HKNvxOyz/z75yFcVa7AxA1VBD8b0d/UZqgA4TJQG7p9xABj8Ypzmqnr6705/wMCmB/FV FMmg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=uh2gurlFCfKidILPQwgDGINwD1Y4If9oqEScPiE96vM=; b=IGV7QY3kHhjAxSeOi4QlQVwDdqKLV0ImcBvTa8iYTn6A/jO+LNIKGJyHSfIAaybxSY RIK2CRFOGLmn4tuAy3k41u7eHhYW3cSXY7zOCNimNkgxyPG2L7PMowslsRg4AISjtTGO jrnUX3iIopEvoh2WzZe9dZHy63uN8lPWNRWXjRdbAuPiCJxBkG8ou9FdUfHXjTWavU7a PbMozVDgX8KHictkWAcWpvJpcjUQIQCZn3ZIWXPtZdMJfr2OcUO87pN9lzztxI/pApgT eXr+hlqKxPa3NSqUlK9Q9e4TE8Fq3y/Ah46iTS4YwcDK7eKSUpZ8JZbTOgU4R00oDU7j RErA== X-Gm-Message-State: AOPr4FXMu464yM4uqHf/nXosaqzyRudHyDlHGwbjur4IkfaG9XLbgl7prl6o6SlrKacbxQ== X-Received: by 10.28.216.76 with SMTP id p73mr11512442wmg.3.1462393556484; Wed, 04 May 2016 13:25:56 -0700 (PDT) Received: from sparkle.lan (HSI-KBW-078-042-181-217.hsi3.kabel-badenwuerttemberg.de. [78.42.181.217]) by smtp.gmail.com with ESMTPSA id lf9sm6052850wjc.44.2016.05.04.13.25.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 04 May 2016 13:25:55 -0700 (PDT) From: Florian Euchner To: dmitry.torokhov@gmail.com Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, Florian Euchner Subject: [PATCH v2] Input: CM109: Fix handling of volume and mute buttons Date: Wed, 4 May 2016 22:25:11 +0200 Message-Id: <1462393511-20979-1-git-send-email-florian.euchner@gmail.com> X-Mailer: git-send-email 2.8.2 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Spam-Status: No, score=-8.9 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The CM109 driver reported key press events of volume up / down and record / playback mute buttons, but no release events. Report those events properly by handling volume and mute keys seperately. For the record and playback mute buttons, only presses are registered by the CM109, therefore simulate press-n-release. This fixes the volume control buttons of various USB headsets. Signed-off-by: Florian Euchner --- Thank you very much for your response to my first patch, Dmitry. I didn't realize input_report_key already does all of the logic to make sure keypresses are not reported twice, which made my code more complicated than it had to be. I have applied your code with some adjustments: * The for loop should only count to 4, not to 8. There are only four keys, otherwise this would cause reading outside the bounds of the keymap[] array and bits 4-7 of HID_IR0 are not used for keys according to the datasheet. * The RECORD_MUTE key should mute the microphone, not the speaker. * There only need to be 15 slots in the keymap for special keys since "no special key pressed" is not a valid combination anymore. I hope those adjustments make sense. drivers/input/misc/cm109.c | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c index 9365535..ee1bedd 100644 --- a/drivers/input/misc/cm109.c +++ b/drivers/input/misc/cm109.c @@ -76,8 +76,8 @@ enum { BUZZER_ON = 1 << 5, - /* up to 256 normal keys, up to 16 special keys */ - KEYMAP_SIZE = 256 + 16, + /* up to 256 normal keys, up to 15 special key combinations */ + KEYMAP_SIZE = 256 + 15, }; /* CM109 protocol packet */ @@ -139,7 +139,7 @@ static unsigned short special_keymap(int code) { if (code > 0xff) { switch (code - 0xff) { - case RECORD_MUTE: return KEY_MUTE; + case RECORD_MUTE: return KEY_MICMUTE; case PLAYBACK_MUTE: return KEY_MUTE; case VOLUME_DOWN: return KEY_VOLUMEDOWN; case VOLUME_UP: return KEY_VOLUMEUP; @@ -312,6 +312,32 @@ static void report_key(struct cm109_dev *dev, int key) input_sync(idev); } +/* + * Converts data of special key presses (volume, mute) into events + * for the input subsystem, sends press-n-release for mute keys. + */ +static void cm109_report_special(struct cm109_dev *dev) +{ + static const u8 autorelease = RECORD_MUTE | PLAYBACK_MUTE; + struct input_dev *idev = dev->idev; + u8 data = dev->irq_data->byte[HID_IR0]; + unsigned short keycode; + int i; + + for (i = 0; i < 4; i++) { + keycode = dev->keymap[0xff + BIT(i)]; + if (keycode == KEY_RESERVED) + continue; + + input_report_key(idev, keycode, data & BIT(i)); + if (data & autorelease & BIT(i)) { + input_sync(idev); + input_report_key(idev, keycode, 0); + } + } + input_sync(idev); +} + /****************************************************************************** * CM109 usb communication interface *****************************************************************************/ @@ -357,10 +383,7 @@ static void cm109_urb_irq_callback(struct urb *urb) } /* Special keys */ - if (dev->irq_data->byte[HID_IR0] & 0x0f) { - const int code = (dev->irq_data->byte[HID_IR0] & 0x0f); - report_key(dev, dev->keymap[0xff + code]); - } + cm109_report_special(dev); /* Scan key column */ if (dev->keybit == 0xf) {