1. 16 2月, 2018 1 次提交
  2. 23 1月, 2018 12 次提交
  3. 07 12月, 2017 3 次提交
    • D
      HID: add quirk for another PIXART OEM mouse used by HP · 01cffe9d
      Dave Young 提交于
      This mouse keep disconnecting in runleve 3 like below, add it needs the
      quirk to mute the anoying messages.
      
      [  111.230555] usb 2-2: USB disconnect, device number 6
      [  112.718156] usb 2-2: new low-speed USB device number 7 using xhci_hcd
      [  112.941594] usb 2-2: New USB device found, idVendor=03f0, idProduct=094a
      [  112.984866] usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
      [  113.027731] usb 2-2: Product: HP USB Optical Mouse
      [  113.069977] usb 2-2: Manufacturer: PixArt
      [  113.113500] input: PixArt HP USB Optical Mouse as /devices/pci0000:00/0000:00:14.0/usb2/2-2/2-2:1.0/0003:03F0:094A.0002/input/input14
      [  113.156787] hid-generic 0003:03F0:094A.0002: input: USB HID v1.11 Mouse [PixArt HP USB Optical Mouse] on usb-0000:00:14.0-2/input0
      [  173.262642] usb 2-2: USB disconnect, device number 7
      [  174.750244] usb 2-2: new low-speed USB device number 8 using xhci_hcd
      [  174.935740] usb 2-2: New USB device found, idVendor=03f0, idProduct=094a
      [  174.990435] usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
      [  175.014984] usb 2-2: Product: HP USB Optical Mouse
      [  175.037886] usb 2-2: Manufacturer: PixArt
      [  175.061794] input: PixArt HP USB Optical Mouse as /devices/pci0000:00/0000:00:14.0/usb2/2-2/2-2:1.0/0003:03F0:094A.0003/input/input15
      [  175.084946] hid-generic 0003:03F0:094A.0003: input: USB HID v1.11 Mouse [PixArt HP USB Optical Mouse] on usb-0000:00:14.0-2/input0
      Signed-off-by: NDave Young <dyoung@redhat.com>
      Cc: stable@vger.kernel.org
      Reviewed-by: NBenjamin Tissoires <benjamin.tissoires@redhat.com>
      Signed-off-by: NJiri Kosina <jkosina@suse.cz>
      01cffe9d
    • H
      HID: core: lower log level for unknown main item tags to warnings · 7cb4774e
      Hans de Goede 提交于
      Given all the effort distros have done with splash-screens to give
      users a nice clean boot experience, we really want dmesg --level=err
      to not print anything unless there is a real problem with either the
      hardware or the kernel. Buggy HID descriptors unfortunately happen
      all too often, so lower the log level to warning keep the console
      clear of error messages such as:
      
      [  441.079664] apple 0005:05AC:0239.0003: unknown main item tag 0x0
      Signed-off-by: NHans de Goede <hdegoede@redhat.com>
      Acked-by: NBenjamin Tissoires <benjamin.tissoires@redhat.com>
      Signed-off-by: NJiri Kosina <jkosina@suse.cz>
      7cb4774e
    • C
      HID: quirks: make array hid_quirks static · 332347d4
      Colin Ian King 提交于
      Array hid_quirks is local to the source and does not need to be in
      global scope, so make it static.
      
      Cleans up sparse warning:
      drivers/hid/hid-quirks.c:29:28: warning: symbol 'hid_quirks' was not
      declared. Should it be static?
      Signed-off-by: NColin Ian King <colin.king@canonical.com>
      Reviewed-by: NBenjamin Tissoires <benjamin.tissoires@redhat.com>
      Signed-off-by: NJiri Kosina <jkosina@suse.cz>
      332347d4
  4. 01 12月, 2017 3 次提交
  5. 29 11月, 2017 1 次提交
  6. 24 11月, 2017 1 次提交
    • J
      HID: elo: clear BTN_LEFT mapping · 9abd04af
      Jiri Kosina 提交于
      ELO devices have one Button usage in GenDesk field, which makes hid-input map
      it to BTN_LEFT; that confuses userspace, which then considers the device to be
      a mouse/touchpad instead of touchscreen.
      
      Fix that by unmapping BTN_LEFT and keeping only BTN_TOUCH in place.
      Signed-off-by: NJiri Kosina <jkosina@suse.cz>
      9abd04af
  7. 22 11月, 2017 6 次提交
    • H
      HID: multitouch: Combine all left-button events in a frame · 127e71bd
      Hans de Goede 提交于
      According to the Win8 Precision Touchpad spec, inside the HID_UP_BUTTON
      usage-page usage 1 is for a clickpad getting clicked, 2 for an external
      left button and 3 for an external right button. Since Linux uses
      BTN_LEFT for a clickpad being clicked we end up mapping both usage 1
      and 2 to BTN_LEFT and if a single report contains both then we ended
      up always reporting the value of both in a single SYN, e.g. :
      BTN_LEFT 1, BTN_LEFT 0, SYN. This happens for example with Hantick
      HTT5288 i2c mt touchpads.
      
      This commit fixes this by not immediately reporting left button when we
      parse the report, but instead storing or-ing together the values and
      reporting the result from mt_sync_frame() when we've a complete frame.
      Signed-off-by: NHans de Goede <hdegoede@redhat.com>
      Reviewed-by: NBenjamin Tissoires <benjamin.tissoires@redhat.com>
      Signed-off-by: NJiri Kosina <jkosina@suse.cz>
      127e71bd
    • H
      HID: multitouch: Only look at non touch fields in first packet of a frame · 55746d28
      Hans de Goede 提交于
      Devices in "single finger hybrid mode" will send one report per finger,
      on some devices only the first report of such a multi-packet frame will
      contain a value for BTN_LEFT, in subsequent reports (if multiple fingers
      are down) the value is always 0, causing hid-mt to report BTN_LEFT going
      1 - 0 - 1 - 0 when pressing a clickpad and putting down a second finger.
      This happens for example on USB 0603:0002 mt touchpads.
      
      This commit fixes this by only reporting non touch fields for the first
      packet of a (possibly) multi-packet frame.
      Signed-off-by: NHans de Goede <hdegoede@redhat.com>
      Reviewed-by: NBenjamin Tissoires <benjamin.tissoires@redhat.com>
      Signed-off-by: NJiri Kosina <jkosina@suse.cz>
      55746d28
    • H
      HID: multitouch: Properly deal with Win8 PTP reports with 0 touches · af8dc4d0
      Hans de Goede 提交于
      The Windows Precision Touchpad spec "Figure 4 Button Only Down and Up"
      and "Table 9 Report Sequence for Button Only Down and Up" indicate
      that the first packet of a (possibly hybrid mode multi-packet) frame
      may contain a contact-count of 0 if only a button is pressed and no
      fingers are detected.
      
      This means that a value of 0 for contact-count is a valid value and
      should be used as expected contact count when it is the first packet
      (num_received == 0), as extra check to make sure that this is the first
      packet of a buttons only frame, we also check that the timestamp is
      different.
      Signed-off-by: NHans de Goede <hdegoede@redhat.com>
      Reviewed-by: NBenjamin Tissoires <benjamin.tissoires@redhat.com>
      Signed-off-by: NJiri Kosina <jkosina@suse.cz>
      af8dc4d0
    • H
      HID: multitouch: Fix alphabetic sorting of mt_devices table. · fb55b402
      Hans de Goede 提交于
      Fix alphabetic sorting of mt_devices hid_device_id table.
      Signed-off-by: NHans de Goede <hdegoede@redhat.com>
      Reviewed-by: NBenjamin Tissoires <benjamin.tissoires@redhat.com>
      Signed-off-by: NJiri Kosina <jkosina@suse.cz>
      fb55b402
    • K
      treewide: setup_timer() -> timer_setup() · e99e88a9
      Kees Cook 提交于
      This converts all remaining cases of the old setup_timer() API into using
      timer_setup(), where the callback argument is the structure already
      holding the struct timer_list. These should have no behavioral changes,
      since they just change which pointer is passed into the callback with
      the same available pointers after conversion. It handles the following
      examples, in addition to some other variations.
      
      Casting from unsigned long:
      
          void my_callback(unsigned long data)
          {
              struct something *ptr = (struct something *)data;
          ...
          }
          ...
          setup_timer(&ptr->my_timer, my_callback, ptr);
      
      and forced object casts:
      
          void my_callback(struct something *ptr)
          {
          ...
          }
          ...
          setup_timer(&ptr->my_timer, my_callback, (unsigned long)ptr);
      
      become:
      
          void my_callback(struct timer_list *t)
          {
              struct something *ptr = from_timer(ptr, t, my_timer);
          ...
          }
          ...
          timer_setup(&ptr->my_timer, my_callback, 0);
      
      Direct function assignments:
      
          void my_callback(unsigned long data)
          {
              struct something *ptr = (struct something *)data;
          ...
          }
          ...
          ptr->my_timer.function = my_callback;
      
      have a temporary cast added, along with converting the args:
      
          void my_callback(struct timer_list *t)
          {
              struct something *ptr = from_timer(ptr, t, my_timer);
          ...
          }
          ...
          ptr->my_timer.function = (TIMER_FUNC_TYPE)my_callback;
      
      And finally, callbacks without a data assignment:
      
          void my_callback(unsigned long data)
          {
          ...
          }
          ...
          setup_timer(&ptr->my_timer, my_callback, 0);
      
      have their argument renamed to verify they're unused during conversion:
      
          void my_callback(struct timer_list *unused)
          {
          ...
          }
          ...
          timer_setup(&ptr->my_timer, my_callback, 0);
      
      The conversion is done with the following Coccinelle script:
      
      spatch --very-quiet --all-includes --include-headers \
      	-I ./arch/x86/include -I ./arch/x86/include/generated \
      	-I ./include -I ./arch/x86/include/uapi \
      	-I ./arch/x86/include/generated/uapi -I ./include/uapi \
      	-I ./include/generated/uapi --include ./include/linux/kconfig.h \
      	--dir . \
      	--cocci-file ~/src/data/timer_setup.cocci
      
      @fix_address_of@
      expression e;
      @@
      
       setup_timer(
      -&(e)
      +&e
       , ...)
      
      // Update any raw setup_timer() usages that have a NULL callback, but
      // would otherwise match change_timer_function_usage, since the latter
      // will update all function assignments done in the face of a NULL
      // function initialization in setup_timer().
      @change_timer_function_usage_NULL@
      expression _E;
      identifier _timer;
      type _cast_data;
      @@
      
      (
      -setup_timer(&_E->_timer, NULL, _E);
      +timer_setup(&_E->_timer, NULL, 0);
      |
      -setup_timer(&_E->_timer, NULL, (_cast_data)_E);
      +timer_setup(&_E->_timer, NULL, 0);
      |
      -setup_timer(&_E._timer, NULL, &_E);
      +timer_setup(&_E._timer, NULL, 0);
      |
      -setup_timer(&_E._timer, NULL, (_cast_data)&_E);
      +timer_setup(&_E._timer, NULL, 0);
      )
      
      @change_timer_function_usage@
      expression _E;
      identifier _timer;
      struct timer_list _stl;
      identifier _callback;
      type _cast_func, _cast_data;
      @@
      
      (
      -setup_timer(&_E->_timer, _callback, _E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, &_callback, _E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, _callback, (_cast_data)_E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, &_callback, (_cast_data)_E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, (_cast_func)_callback, _E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, (_cast_func)&_callback, _E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, (_cast_func)_callback, (_cast_data)_E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, (_cast_func)&_callback, (_cast_data)_E);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E._timer, _callback, (_cast_data)_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, _callback, (_cast_data)&_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, &_callback, (_cast_data)_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, &_callback, (_cast_data)&_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, (_cast_func)_callback, (_cast_data)_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, (_cast_func)_callback, (_cast_data)&_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, (_cast_func)&_callback, (_cast_data)_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, (_cast_func)&_callback, (_cast_data)&_E);
      +timer_setup(&_E._timer, _callback, 0);
      |
       _E->_timer@_stl.function = _callback;
      |
       _E->_timer@_stl.function = &_callback;
      |
       _E->_timer@_stl.function = (_cast_func)_callback;
      |
       _E->_timer@_stl.function = (_cast_func)&_callback;
      |
       _E._timer@_stl.function = _callback;
      |
       _E._timer@_stl.function = &_callback;
      |
       _E._timer@_stl.function = (_cast_func)_callback;
      |
       _E._timer@_stl.function = (_cast_func)&_callback;
      )
      
      // callback(unsigned long arg)
      @change_callback_handle_cast
       depends on change_timer_function_usage@
      identifier change_timer_function_usage._callback;
      identifier change_timer_function_usage._timer;
      type _origtype;
      identifier _origarg;
      type _handletype;
      identifier _handle;
      @@
      
       void _callback(
      -_origtype _origarg
      +struct timer_list *t
       )
       {
      (
      	... when != _origarg
      	_handletype *_handle =
      -(_handletype *)_origarg;
      +from_timer(_handle, t, _timer);
      	... when != _origarg
      |
      	... when != _origarg
      	_handletype *_handle =
      -(void *)_origarg;
      +from_timer(_handle, t, _timer);
      	... when != _origarg
      |
      	... when != _origarg
      	_handletype *_handle;
      	... when != _handle
      	_handle =
      -(_handletype *)_origarg;
      +from_timer(_handle, t, _timer);
      	... when != _origarg
      |
      	... when != _origarg
      	_handletype *_handle;
      	... when != _handle
      	_handle =
      -(void *)_origarg;
      +from_timer(_handle, t, _timer);
      	... when != _origarg
      )
       }
      
      // callback(unsigned long arg) without existing variable
      @change_callback_handle_cast_no_arg
       depends on change_timer_function_usage &&
                           !change_callback_handle_cast@
      identifier change_timer_function_usage._callback;
      identifier change_timer_function_usage._timer;
      type _origtype;
      identifier _origarg;
      type _handletype;
      @@
      
       void _callback(
      -_origtype _origarg
      +struct timer_list *t
       )
       {
      +	_handletype *_origarg = from_timer(_origarg, t, _timer);
      +
      	... when != _origarg
      -	(_handletype *)_origarg
      +	_origarg
      	... when != _origarg
       }
      
      // Avoid already converted callbacks.
      @match_callback_converted
       depends on change_timer_function_usage &&
                  !change_callback_handle_cast &&
      	    !change_callback_handle_cast_no_arg@
      identifier change_timer_function_usage._callback;
      identifier t;
      @@
      
       void _callback(struct timer_list *t)
       { ... }
      
      // callback(struct something *handle)
      @change_callback_handle_arg
       depends on change_timer_function_usage &&
      	    !match_callback_converted &&
                  !change_callback_handle_cast &&
                  !change_callback_handle_cast_no_arg@
      identifier change_timer_function_usage._callback;
      identifier change_timer_function_usage._timer;
      type _handletype;
      identifier _handle;
      @@
      
       void _callback(
      -_handletype *_handle
      +struct timer_list *t
       )
       {
      +	_handletype *_handle = from_timer(_handle, t, _timer);
      	...
       }
      
      // If change_callback_handle_arg ran on an empty function, remove
      // the added handler.
      @unchange_callback_handle_arg
       depends on change_timer_function_usage &&
      	    change_callback_handle_arg@
      identifier change_timer_function_usage._callback;
      identifier change_timer_function_usage._timer;
      type _handletype;
      identifier _handle;
      identifier t;
      @@
      
       void _callback(struct timer_list *t)
       {
      -	_handletype *_handle = from_timer(_handle, t, _timer);
       }
      
      // We only want to refactor the setup_timer() data argument if we've found
      // the matching callback. This undoes changes in change_timer_function_usage.
      @unchange_timer_function_usage
       depends on change_timer_function_usage &&
                  !change_callback_handle_cast &&
                  !change_callback_handle_cast_no_arg &&
      	    !change_callback_handle_arg@
      expression change_timer_function_usage._E;
      identifier change_timer_function_usage._timer;
      identifier change_timer_function_usage._callback;
      type change_timer_function_usage._cast_data;
      @@
      
      (
      -timer_setup(&_E->_timer, _callback, 0);
      +setup_timer(&_E->_timer, _callback, (_cast_data)_E);
      |
      -timer_setup(&_E._timer, _callback, 0);
      +setup_timer(&_E._timer, _callback, (_cast_data)&_E);
      )
      
      // If we fixed a callback from a .function assignment, fix the
      // assignment cast now.
      @change_timer_function_assignment
       depends on change_timer_function_usage &&
                  (change_callback_handle_cast ||
                   change_callback_handle_cast_no_arg ||
                   change_callback_handle_arg)@
      expression change_timer_function_usage._E;
      identifier change_timer_function_usage._timer;
      identifier change_timer_function_usage._callback;
      type _cast_func;
      typedef TIMER_FUNC_TYPE;
      @@
      
      (
       _E->_timer.function =
      -_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E->_timer.function =
      -&_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E->_timer.function =
      -(_cast_func)_callback;
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E->_timer.function =
      -(_cast_func)&_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E._timer.function =
      -_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E._timer.function =
      -&_callback;
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E._timer.function =
      -(_cast_func)_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      |
       _E._timer.function =
      -(_cast_func)&_callback
      +(TIMER_FUNC_TYPE)_callback
       ;
      )
      
      // Sometimes timer functions are called directly. Replace matched args.
      @change_timer_function_calls
       depends on change_timer_function_usage &&
                  (change_callback_handle_cast ||
                   change_callback_handle_cast_no_arg ||
                   change_callback_handle_arg)@
      expression _E;
      identifier change_timer_function_usage._timer;
      identifier change_timer_function_usage._callback;
      type _cast_data;
      @@
      
       _callback(
      (
      -(_cast_data)_E
      +&_E->_timer
      |
      -(_cast_data)&_E
      +&_E._timer
      |
      -_E
      +&_E->_timer
      )
       )
      
      // If a timer has been configured without a data argument, it can be
      // converted without regard to the callback argument, since it is unused.
      @match_timer_function_unused_data@
      expression _E;
      identifier _timer;
      identifier _callback;
      @@
      
      (
      -setup_timer(&_E->_timer, _callback, 0);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, _callback, 0L);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E->_timer, _callback, 0UL);
      +timer_setup(&_E->_timer, _callback, 0);
      |
      -setup_timer(&_E._timer, _callback, 0);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, _callback, 0L);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_E._timer, _callback, 0UL);
      +timer_setup(&_E._timer, _callback, 0);
      |
      -setup_timer(&_timer, _callback, 0);
      +timer_setup(&_timer, _callback, 0);
      |
      -setup_timer(&_timer, _callback, 0L);
      +timer_setup(&_timer, _callback, 0);
      |
      -setup_timer(&_timer, _callback, 0UL);
      +timer_setup(&_timer, _callback, 0);
      |
      -setup_timer(_timer, _callback, 0);
      +timer_setup(_timer, _callback, 0);
      |
      -setup_timer(_timer, _callback, 0L);
      +timer_setup(_timer, _callback, 0);
      |
      -setup_timer(_timer, _callback, 0UL);
      +timer_setup(_timer, _callback, 0);
      )
      
      @change_callback_unused_data
       depends on match_timer_function_unused_data@
      identifier match_timer_function_unused_data._callback;
      type _origtype;
      identifier _origarg;
      @@
      
       void _callback(
      -_origtype _origarg
      +struct timer_list *unused
       )
       {
      	... when != _origarg
       }
      Signed-off-by: NKees Cook <keescook@chromium.org>
      e99e88a9
    • E
      HID: cp2112: Fix I2C_BLOCK_DATA transactions · 542134c0
      Eudean Sun 提交于
      The existing driver erroneously treats I2C_BLOCK_DATA and BLOCK_DATA
      commands the same.
      
      For I2C_BLOCK_DATA reads, the length of the read is provided in
      data->block[0], but the length itself should not be sent to the slave. In
      contrast, for BLOCK_DATA reads no length is specified since the length
      will be the first byte returned from the slave. When copying data back
      to the data buffer, for an I2C_BLOCK_DATA read we have to take care not to
      overwrite data->block[0] to avoid overwriting the length. A BLOCK_DATA
      read doesn't have this concern since the first byte returned by the device
      is the length and belongs in data->block[0].
      
      For I2C_BLOCK_DATA writes, the length is also provided in data->block[0],
      but the length itself is not sent to the slave (in contrast to BLOCK_DATA
      writes where the length prefixes the data sent to the slave).
      
      This was tested on physical hardware using i2cdump with the i and s flags
      to test the behavior of I2C_BLOCK_DATA reads and BLOCK_DATA reads,
      respectively. Writes were not tested but the I2C_BLOCK_DATA write change
      is pretty simple to verify by inspection.
      Signed-off-by: NEudean Sun <eudean@arista.com>
      Signed-off-by: NJiri Kosina <jkosina@suse.cz>
      542134c0
  8. 21 11月, 2017 9 次提交
  9. 10 11月, 2017 3 次提交
  10. 09 11月, 2017 1 次提交