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 >
2010-06-28 20:54:25 +04:00
*/
/*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation ; either version 2 of the License , or ( at your option )
* any later version .
*/
# 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 .
*
* Report descriptor format :
* Positions 13 , 15 , 21 and 31 store the button bit count , button usage minimum ,
* button usage maximum and padding bit count respectively .
*/
# define MOUSE_BUTTONS_MAX 8
static void mouse_button_fixup ( struct hid_device * hdev ,
__u8 * rdesc , unsigned int rsize ,
int nbuttons )
{
if ( rsize < 32 | | rdesc [ 12 ] ! = 0x95 | |
rdesc [ 14 ] ! = 0x75 | | rdesc [ 15 ] ! = 0x01 | |
rdesc [ 20 ] ! = 0x29 | | rdesc [ 30 ] ! = 0x75 )
return ;
hid_info ( hdev , " Fixing up Elecom mouse button count \n " ) ;
nbuttons = clamp ( nbuttons , 0 , MOUSE_BUTTONS_MAX ) ;
rdesc [ 13 ] = nbuttons ;
rdesc [ 21 ] = nbuttons ;
rdesc [ 31 ] = MOUSE_BUTTONS_MAX - nbuttons ;
}
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 ;
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 :
2017-12-19 23:44:36 +03:00
mouse_button_fixup ( hdev , rdesc , * rsize , 6 ) ;
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 :
case USB_DEVICE_ID_ELECOM_M_HT1DRBK :
2017-12-19 23:44:36 +03:00
mouse_button_fixup ( hdev , rdesc , * rsize , 8 ) ;
2017-04-26 19:37:04 +03:00
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 ) } ,
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 ) } ,
{ HID_USB_DEVICE ( USB_VENDOR_ID_ELECOM , USB_DEVICE_ID_ELECOM_M_HT1DRBK ) } ,
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 " ) ;