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 {
128129recvr_type_hidpp ,
129130recvr_type_gaming_hidpp ,
130131recvr_type_27mhz ,
132+ recvr_type_bluetooth ,
131133};
132134
133135struct dj_report {
@@ -295,6 +297,55 @@ static const char mse_27mhz_descriptor[] = {
2952970xC0 ,/* 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 []= {
3003510x05 ,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{
491543struct 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 */
494553list_for_each_entry (djrcv_dev ,& dj_hdev_list ,list ) {
495554if (djrcv_dev -> mouse &&
496- hid_compare_device_paths (hdev ,djrcv_dev -> mouse ,'/' )) {
555+ hid_compare_device_paths (hdev ,djrcv_dev -> mouse ,sep )) {
497556kref_get (& djrcv_dev -> kref );
498557return djrcv_dev ;
499558}
500559if (djrcv_dev -> keyboard &&
501- hid_compare_device_paths (hdev ,djrcv_dev -> keyboard ,'/' )) {
560+ hid_compare_device_paths (hdev ,djrcv_dev -> keyboard ,sep )) {
502561kref_get (& djrcv_dev -> kref );
503562return djrcv_dev ;
504563}
505564if (djrcv_dev -> hidpp &&
506- hid_compare_device_paths (hdev ,djrcv_dev -> hidpp ,'/' )) {
565+ hid_compare_device_paths (hdev ,djrcv_dev -> hidpp ,sep )) {
507566kref_get (& djrcv_dev -> kref );
508567return djrcv_dev ;
509568}
@@ -548,7 +607,7 @@ static struct dj_receiver_dev *dj_get_receiver_dev(struct hid_device *hdev,
548607
549608mutex_lock (& dj_hdev_list_lock );
550609
551- djrcv_dev = dj_find_receiver_dev (hdev );
610+ djrcv_dev = dj_find_receiver_dev (hdev , type );
552611if (!djrcv_dev ) {
553612djrcv_dev = kzalloc (sizeof (* djrcv_dev ),GFP_KERNEL );
554613if (!djrcv_dev )
@@ -878,6 +937,14 @@ static void logi_hidpp_recv_queue_notif(struct hid_device *hdev,
878937switch (hidpp_report -> params [HIDPP_PARAM_PROTO_TYPE ]) {
879938case 0x01 :
880939device_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+ }
881948break ;
882949case 0x02 :
883950device_type = "27 Mhz" ;
@@ -1267,6 +1334,9 @@ static int logi_dj_ll_parse(struct hid_device *hid)
12671334else if (djdev -> dj_receiver_dev -> type == recvr_type_27mhz )
12681335rdcat (rdesc ,& rsize ,mse_27mhz_descriptor ,
12691336sizeof (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 ));
12701340else
12711341rdcat (rdesc ,& rsize ,mse_descriptor ,
12721342sizeof (mse_descriptor ));
@@ -1581,6 +1651,7 @@ static int logi_dj_probe(struct hid_device *hdev,
15811651case recvr_type_hidpp :no_dj_interfaces = 2 ;break ;
15821652case recvr_type_gaming_hidpp :no_dj_interfaces = 3 ;break ;
15831653case recvr_type_27mhz :no_dj_interfaces = 2 ;break ;
1654+ case recvr_type_bluetooth :no_dj_interfaces = 2 ;break ;
15841655}
15851656if (hid_is_using_ll_driver (hdev ,& usb_hid_driver )) {
15861657intf = to_usb_interface (hdev -> dev .parent );
@@ -1772,6 +1843,14 @@ static const struct hid_device_id logi_dj_receivers[] = {
17721843HID_USB_DEVICE (USB_VENDOR_ID_LOGITECH ,
17731844USB_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