112112#define  HIDPP_PARAM_27MHZ_DEVID 			0x03
113113#define  HIDPP_DEVICE_TYPE_MASK 			GENMASK(3, 0)
114114#define  HIDPP_LINK_STATUS_MASK 			BIT(6)
115+ #define  HIDPP_MANUFACTURER_MASK 			BIT(7)
115116
116117#define  HIDPP_DEVICE_TYPE_KEYBOARD 		1
117118#define  HIDPP_DEVICE_TYPE_MOUSE 			2
@@ -128,6 +129,7 @@ enum recvr_type {
128129	recvr_type_hidpp ,
129130	recvr_type_gaming_hidpp ,
130131	recvr_type_27mhz ,
132+ 	recvr_type_bluetooth ,
131133};
132134
133135struct  dj_report  {
@@ -295,6 +297,55 @@ static const char mse_27mhz_descriptor[] = {
295297	0xC0 ,			/*  END_COLLECTION                      */ 
296298};
297299
300+ /* Mouse descriptor (2) for Bluetooth receiver, low-res hwheel, 12 buttons */ 
301+ static  const  char  mse_bluetooth_descriptor [] =  {
302+ 	0x05 , 0x01 ,		/*  USAGE_PAGE (Generic Desktop)        */ 
303+ 	0x09 , 0x02 ,		/*  USAGE (Mouse)                       */ 
304+ 	0xA1 , 0x01 ,		/*  COLLECTION (Application)            */ 
305+ 	0x85 , 0x02 ,		/*    REPORT_ID = 2                     */ 
306+ 	0x09 , 0x01 ,		/*    USAGE (pointer)                   */ 
307+ 	0xA1 , 0x00 ,		/*    COLLECTION (physical)             */ 
308+ 	0x05 , 0x09 ,		/*      USAGE_PAGE (buttons)            */ 
309+ 	0x19 , 0x01 ,		/*      USAGE_MIN (1)                   */ 
310+ 	0x29 , 0x08 ,		/*      USAGE_MAX (8)                   */ 
311+ 	0x15 , 0x00 ,		/*      LOGICAL_MIN (0)                 */ 
312+ 	0x25 , 0x01 ,		/*      LOGICAL_MAX (1)                 */ 
313+ 	0x95 , 0x08 ,		/*      REPORT_COUNT (8)                */ 
314+ 	0x75 , 0x01 ,		/*      REPORT_SIZE (1)                 */ 
315+ 	0x81 , 0x02 ,		/*      INPUT (data var abs)            */ 
316+ 	0x05 , 0x01 ,		/*      USAGE_PAGE (generic desktop)    */ 
317+ 	0x16 , 0x01 , 0xF8 ,	/*      LOGICAL_MIN (-2047)             */ 
318+ 	0x26 , 0xFF , 0x07 ,	/*      LOGICAL_MAX (2047)              */ 
319+ 	0x75 , 0x0C ,		/*      REPORT_SIZE (12)                */ 
320+ 	0x95 , 0x02 ,		/*      REPORT_COUNT (2)                */ 
321+ 	0x09 , 0x30 ,		/*      USAGE (X)                       */ 
322+ 	0x09 , 0x31 ,		/*      USAGE (Y)                       */ 
323+ 	0x81 , 0x06 ,		/*      INPUT                           */ 
324+ 	0x15 , 0x81 ,		/*      LOGICAL_MIN (-127)              */ 
325+ 	0x25 , 0x7F ,		/*      LOGICAL_MAX (127)               */ 
326+ 	0x75 , 0x08 ,		/*      REPORT_SIZE (8)                 */ 
327+ 	0x95 , 0x01 ,		/*      REPORT_COUNT (1)                */ 
328+ 	0x09 , 0x38 ,		/*      USAGE (wheel)                   */ 
329+ 	0x81 , 0x06 ,		/*      INPUT                           */ 
330+ 	0x05 , 0x0C ,		/*      USAGE_PAGE(consumer)            */ 
331+ 	0x0A , 0x38 , 0x02 ,	/*      USAGE(AC Pan)                   */ 
332+ 	0x15 , 0xF9 ,		/*      LOGICAL_MIN (-7)                */ 
333+ 	0x25 , 0x07 ,		/*      LOGICAL_MAX (7)                 */ 
334+ 	0x75 , 0x04 ,		/*      REPORT_SIZE (4)                 */ 
335+ 	0x95 , 0x01 ,		/*      REPORT_COUNT (1)                */ 
336+ 	0x81 , 0x06 ,		/*      INPUT                           */ 
337+ 	0x05 , 0x09 ,		/*      USAGE_PAGE (buttons)            */ 
338+ 	0x19 , 0x09 ,		/*      USAGE_MIN (9)                   */ 
339+ 	0x29 , 0x0C ,		/*      USAGE_MAX (12)                  */ 
340+ 	0x15 , 0x00 ,		/*      LOGICAL_MIN (0)                 */ 
341+ 	0x25 , 0x01 ,		/*      LOGICAL_MAX (1)                 */ 
342+ 	0x75 , 0x01 ,		/*      REPORT_SIZE (1)                 */ 
343+ 	0x95 , 0x04 ,		/*      REPORT_COUNT (4)                */ 
344+ 	0x81 , 0x06 ,		/*      INPUT                           */ 
345+ 	0xC0 ,			/*    END_COLLECTION                    */ 
346+ 	0xC0 ,			/*  END_COLLECTION                      */ 
347+ };
348+ 
298349/* Gaming Mouse descriptor (2) */ 
299350static  const  char  mse_high_res_descriptor [] =  {
300351	0x05 , 0x01 ,		/*  USAGE_PAGE (Generic Desktop)        */ 
@@ -441,7 +492,7 @@ static const char hidpp_descriptor[] = {
441492/* Make sure all descriptors are present here */ 
442493#define  MAX_RDESC_SIZE 				\
443494	(sizeof(kbd_descriptor) +		\
444- 	 sizeof(mse_descriptor ) +	 	\
495+ 	 sizeof(mse_bluetooth_descriptor ) +	\
445496	 sizeof(consumer_descriptor) +		\
446497	 sizeof(syscontrol_descriptor) +	\
447498	 sizeof(media_descriptor) +	\
@@ -486,24 +537,32 @@ static DEFINE_MUTEX(dj_hdev_list_lock);
486537 * to create a single struct dj_receiver_dev for all interfaces belonging to 
487538 * a single USB-device / receiver. 
488539 */ 
489- static  struct  dj_receiver_dev  * dj_find_receiver_dev (struct  hid_device  * hdev )
540+ static  struct  dj_receiver_dev  * dj_find_receiver_dev (struct  hid_device  * hdev ,
541+ 						    enum  recvr_type  type )
490542{
491543	struct  dj_receiver_dev  * djrcv_dev ;
544+ 	char  sep ;
545+ 
546+ 	/* 
547+ 	 * The bluetooth receiver contains a built-in hub and has separate 
548+ 	 * USB-devices for the keyboard and mouse interfaces. 
549+ 	 */ 
550+ 	sep  =  (type  ==  recvr_type_bluetooth ) ? '.'  : '/' ;
492551
493552	/* Try to find an already-probed interface from the same device */ 
494553	list_for_each_entry (djrcv_dev , & dj_hdev_list , list ) {
495554		if  (djrcv_dev -> mouse  && 
496- 		    hid_compare_device_paths (hdev , djrcv_dev -> mouse , '/' )) {
555+ 		    hid_compare_device_paths (hdev , djrcv_dev -> mouse , sep )) {
497556			kref_get (& djrcv_dev -> kref );
498557			return  djrcv_dev ;
499558		}
500559		if  (djrcv_dev -> keyboard  && 
501- 		    hid_compare_device_paths (hdev , djrcv_dev -> keyboard , '/' )) {
560+ 		    hid_compare_device_paths (hdev , djrcv_dev -> keyboard , sep )) {
502561			kref_get (& djrcv_dev -> kref );
503562			return  djrcv_dev ;
504563		}
505564		if  (djrcv_dev -> hidpp  && 
506- 		    hid_compare_device_paths (hdev , djrcv_dev -> hidpp , '/' )) {
565+ 		    hid_compare_device_paths (hdev , djrcv_dev -> hidpp , sep )) {
507566			kref_get (& djrcv_dev -> kref );
508567			return  djrcv_dev ;
509568		}
@@ -548,7 +607,7 @@ static struct dj_receiver_dev *dj_get_receiver_dev(struct hid_device *hdev,
548607
549608	mutex_lock (& dj_hdev_list_lock );
550609
551- 	djrcv_dev  =  dj_find_receiver_dev (hdev );
610+ 	djrcv_dev  =  dj_find_receiver_dev (hdev ,  type );
552611	if  (!djrcv_dev ) {
553612		djrcv_dev  =  kzalloc (sizeof (* djrcv_dev ), GFP_KERNEL );
554613		if  (!djrcv_dev )
@@ -878,6 +937,14 @@ static void logi_hidpp_recv_queue_notif(struct hid_device *hdev,
878937	switch  (hidpp_report -> params [HIDPP_PARAM_PROTO_TYPE ]) {
879938	case  0x01 :
880939		device_type  =  "Bluetooth" ;
940+ 		/* Bluetooth connect packet contents is the same as (e)QUAD */ 
941+ 		logi_hidpp_dev_conn_notif_equad (hidpp_report , & workitem );
942+ 		if  (!(hidpp_report -> params [HIDPP_PARAM_DEVICE_INFO ] & 
943+ 						HIDPP_MANUFACTURER_MASK )) {
944+ 			hid_info (hdev , "Non Logitech device connected on slot %d\n" ,
945+ 				 hidpp_report -> device_index );
946+ 			workitem .reports_supported  &= ~HIDPP ;
947+ 		}
881948		break ;
882949	case  0x02 :
883950		device_type  =  "27 Mhz" ;
@@ -1267,6 +1334,9 @@ static int logi_dj_ll_parse(struct hid_device *hid)
12671334		else  if  (djdev -> dj_receiver_dev -> type  ==  recvr_type_27mhz )
12681335			rdcat (rdesc , & rsize , mse_27mhz_descriptor ,
12691336			      sizeof (mse_27mhz_descriptor ));
1337+ 		else  if  (djdev -> dj_receiver_dev -> type  ==  recvr_type_bluetooth )
1338+ 			rdcat (rdesc , & rsize , mse_bluetooth_descriptor ,
1339+ 			      sizeof (mse_bluetooth_descriptor ));
12701340		else 
12711341			rdcat (rdesc , & rsize , mse_descriptor ,
12721342			      sizeof (mse_descriptor ));
@@ -1581,6 +1651,7 @@ static int logi_dj_probe(struct hid_device *hdev,
15811651	case  recvr_type_hidpp :		no_dj_interfaces  =  2 ; break ;
15821652	case  recvr_type_gaming_hidpp :	no_dj_interfaces  =  3 ; break ;
15831653	case  recvr_type_27mhz :		no_dj_interfaces  =  2 ; break ;
1654+ 	case  recvr_type_bluetooth :	no_dj_interfaces  =  2 ; break ;
15841655	}
15851656	if  (hid_is_using_ll_driver (hdev , & usb_hid_driver )) {
15861657		intf  =  to_usb_interface (hdev -> dev .parent );
@@ -1772,6 +1843,14 @@ static const struct hid_device_id logi_dj_receivers[] = {
17721843	  HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
17731844		USB_DEVICE_ID_LOGITECH_27MHZ_MOUSE_RECEIVER ),
17741845	 .driver_data  =  recvr_type_27mhz },
1846+ 	{ /* Logitech MX5000 HID++ / bluetooth receiver keyboard intf. */ 
1847+ 	  HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
1848+ 		0xc70e ),
1849+ 	 .driver_data  =  recvr_type_bluetooth },
1850+ 	{ /* Logitech MX5000 HID++ / bluetooth receiver mouse intf. */ 
1851+ 	  HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
1852+ 		0xc70a ),
1853+ 	 .driver_data  =  recvr_type_bluetooth },
17751854	{}
17761855};
17771856
0 commit comments