2019-05-27 09:55:01 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2010-06-28 20:54:25 +04:00
/*
2017-12-19 23:44:36 +03:00
* HID driver for ELECOM devices :
* - BM084 Bluetooth Mouse
2018-03-01 20:22:24 +03:00
* - EX - G Trackballs ( M - XT3DRBK , M - XT3URBK , M - XT4DRBK )
2018-03-01 20:22:23 +03:00
* - DEFT Trackballs ( M - DT1DRBK , M - DT1URBK , M - DT2DRBK , M - DT2URBK )
* - HUGE Trackballs ( M - HT1DRBK , M - HT1URBK )
2017-12-19 23:44:36 +03:00
*
2010-06-28 20:54:25 +04:00
* Copyright ( c ) 2010 Richard Nauber < Richard . Nauber @ gmail . com >
2017-04-26 19:37:04 +03:00
* Copyright ( c ) 2016 Yuxuan Shui < yshuiv7 @ gmail . com >
* Copyright ( c ) 2017 Diego Elio Pettenò < flameeyes @ flameeyes . eu >
2017-10-05 20:41:20 +03:00
* Copyright ( c ) 2017 Alex Manoussakis < amanou @ gnu . org >
2017-12-19 23:44:36 +03:00
* Copyright ( c ) 2017 Tomasz Kramkowski < tk @ the - tk . com >
2020-11-21 23:54:37 +03:00
* Copyright ( c ) 2020 YOSHIOKA Takuma < lo48576 @ hard - wi . red >
2023-01-19 21:30:02 +03:00
* Copyright ( c ) 2022 Takahiro Fujii < fujii @ xaxxi . net >
2010-06-28 20:54:25 +04:00
*/
/*
*/
# include <linux/device.h>
# include <linux/hid.h>
# include <linux/module.h>
# include "hid-ids.h"
2017-12-19 23:44:36 +03:00
/*
* Certain ELECOM mice misreport their button count meaning that they only work
* correctly with the ELECOM mouse assistant software which is unavailable for
* Linux . A four extra INPUT reports and a FEATURE report are described by the
* report descriptor but it does not appear that these enable software to
* control what the extra buttons map to . The only simple and straightforward
* solution seems to involve fixing up the report descriptor .
*/
# define MOUSE_BUTTONS_MAX 8
static void mouse_button_fixup ( struct hid_device * hdev ,
__u8 * rdesc , unsigned int rsize ,
2020-11-21 23:54:37 +03:00
unsigned int button_bit_count ,
unsigned int padding_bit ,
unsigned int button_report_size ,
unsigned int button_usage_maximum ,
2017-12-19 23:44:36 +03:00
int nbuttons )
{
2020-11-21 23:54:37 +03:00
if ( rsize < 32 | | rdesc [ button_bit_count ] ! = 0x95 | |
rdesc [ button_report_size ] ! = 0x75 | |
rdesc [ button_report_size + 1 ] ! = 0x01 | |
rdesc [ button_usage_maximum ] ! = 0x29 | | rdesc [ padding_bit ] ! = 0x75 )
2017-12-19 23:44:36 +03:00
return ;
hid_info ( hdev , " Fixing up Elecom mouse button count \n " ) ;
nbuttons = clamp ( nbuttons , 0 , MOUSE_BUTTONS_MAX ) ;
2020-11-21 23:54:37 +03:00
rdesc [ button_bit_count + 1 ] = nbuttons ;
rdesc [ button_usage_maximum + 1 ] = nbuttons ;
rdesc [ padding_bit + 1 ] = MOUSE_BUTTONS_MAX - nbuttons ;
2017-12-19 23:44:36 +03:00
}
2010-08-06 23:03:06 +04:00
static __u8 * elecom_report_fixup ( struct hid_device * hdev , __u8 * rdesc ,
unsigned int * rsize )
2010-06-28 20:54:25 +04:00
{
2017-04-26 19:37:04 +03:00
switch ( hdev - > product ) {
case USB_DEVICE_ID_ELECOM_BM084 :
/* The BM084 Bluetooth mouse includes a non-existing horizontal
* wheel in the HID descriptor . */
if ( * rsize > = 48 & & rdesc [ 46 ] = = 0x05 & & rdesc [ 47 ] = = 0x0c ) {
hid_info ( hdev , " Fixing up Elecom BM084 report descriptor \n " ) ;
rdesc [ 47 ] = 0x00 ;
}
break ;
2020-11-21 23:54:38 +03:00
case USB_DEVICE_ID_ELECOM_M_XGL20DLBK :
/*
* Report descriptor format :
* 20 : button bit count
* 28 : padding bit count
* 22 : button report size
* 14 : button usage maximum
*/
mouse_button_fixup ( hdev , rdesc , * rsize , 20 , 28 , 22 , 14 , 8 ) ;
break ;
2018-03-01 20:22:23 +03:00
case USB_DEVICE_ID_ELECOM_M_XT3URBK :
case USB_DEVICE_ID_ELECOM_M_XT3DRBK :
2018-03-01 20:22:24 +03:00
case USB_DEVICE_ID_ELECOM_M_XT4DRBK :
2020-11-21 23:54:37 +03:00
/*
* Report descriptor format :
* 12 : button bit count
* 30 : padding bit count
* 14 : button report size
* 20 : button usage maximum
*/
mouse_button_fixup ( hdev , rdesc , * rsize , 12 , 30 , 14 , 20 , 6 ) ;
2017-12-19 23:44:36 +03:00
break ;
2018-03-01 20:22:23 +03:00
case USB_DEVICE_ID_ELECOM_M_DT1URBK :
case USB_DEVICE_ID_ELECOM_M_DT1DRBK :
case USB_DEVICE_ID_ELECOM_M_HT1URBK :
2023-01-19 21:30:02 +03:00
case USB_DEVICE_ID_ELECOM_M_HT1DRBK_010D :
2020-11-21 23:54:37 +03:00
/*
* Report descriptor format :
* 12 : button bit count
* 30 : padding bit count
* 14 : button report size
* 20 : button usage maximum
*/
mouse_button_fixup ( hdev , rdesc , * rsize , 12 , 30 , 14 , 20 , 8 ) ;
2017-04-26 19:37:04 +03:00
break ;
2023-01-19 21:30:02 +03:00
case USB_DEVICE_ID_ELECOM_M_HT1DRBK_011C :
/*
* Report descriptor format :
* 22 : button bit count
* 30 : padding bit count
* 24 : button report size
* 16 : button usage maximum
*/
mouse_button_fixup ( hdev , rdesc , * rsize , 22 , 30 , 24 , 16 , 8 ) ;
break ;
2010-06-28 20:54:25 +04:00
}
2015-10-11 17:18:22 +03:00
return rdesc ;
2010-06-28 20:54:25 +04:00
}
static const struct hid_device_id elecom_devices [ ] = {
2017-04-26 19:37:04 +03:00
{ HID_BLUETOOTH_DEVICE ( USB_VENDOR_ID_ELECOM , USB_DEVICE_ID_ELECOM_BM084 ) } ,
2020-11-21 23:54:38 +03:00
{ HID_USB_DEVICE ( USB_VENDOR_ID_ELECOM , USB_DEVICE_ID_ELECOM_M_XGL20DLBK ) } ,
2018-03-01 20:22:23 +03:00
{ HID_USB_DEVICE ( USB_VENDOR_ID_ELECOM , USB_DEVICE_ID_ELECOM_M_XT3URBK ) } ,
{ HID_USB_DEVICE ( USB_VENDOR_ID_ELECOM , USB_DEVICE_ID_ELECOM_M_XT3DRBK ) } ,
2018-03-01 20:22:24 +03:00
{ HID_USB_DEVICE ( USB_VENDOR_ID_ELECOM , USB_DEVICE_ID_ELECOM_M_XT4DRBK ) } ,
2018-03-01 20:22:23 +03:00
{ HID_USB_DEVICE ( USB_VENDOR_ID_ELECOM , USB_DEVICE_ID_ELECOM_M_DT1URBK ) } ,
{ HID_USB_DEVICE ( USB_VENDOR_ID_ELECOM , USB_DEVICE_ID_ELECOM_M_DT1DRBK ) } ,
{ HID_USB_DEVICE ( USB_VENDOR_ID_ELECOM , USB_DEVICE_ID_ELECOM_M_HT1URBK ) } ,
2023-01-19 21:30:02 +03:00
{ HID_USB_DEVICE ( USB_VENDOR_ID_ELECOM , USB_DEVICE_ID_ELECOM_M_HT1DRBK_010D ) } ,
{ HID_USB_DEVICE ( USB_VENDOR_ID_ELECOM , USB_DEVICE_ID_ELECOM_M_HT1DRBK_011C ) } ,
2010-06-28 20:54:25 +04:00
{ }
} ;
MODULE_DEVICE_TABLE ( hid , elecom_devices ) ;
static struct hid_driver elecom_driver = {
. name = " elecom " ,
. id_table = elecom_devices ,
. report_fixup = elecom_report_fixup
} ;
2012-12-18 02:28:26 +04:00
module_hid_driver ( elecom_driver ) ;
2010-06-28 20:54:25 +04:00
MODULE_LICENSE ( " GPL " ) ;