Skip to content

Commit 3379782

Browse files
bentissJiri Kosina
authored andcommitted
HID: logitech: allow the DJ device to request the unifying name
The names of the DJ devices are stored in the receiver. These names can be retrieved through a HID++ command. However, the protocol says that you have to ask the receiver for that, not the device iteself. Introduce a special case in the DJ handling where a device can request its unifying name, and when such a name is given, forward it also to the corresponding device. On the HID++ side, the receiver talks only HID++ 1.0, so we need to implement this part of the protocol in the module. Signed-off-by: Benjamin Tissoires <[email protected]> Tested-by: Andrew de los Reyes <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent 925f0f3 commit 3379782

File tree

2 files changed

+97
-7
lines changed

2 files changed

+97
-7
lines changed

drivers/hid/hid-logitech-dj.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,9 @@ static void logi_dj_ll_close(struct hid_device *hid)
667667
dbg_hid("%s:%s\n", __func__, hid->phys);
668668
}
669669

670+
static u8 unifying_name_query[] = {0x10, 0xff, 0x83, 0xb5, 0x40, 0x00, 0x00};
671+
static u8 unifying_name_answer[] = {0x11, 0xff, 0x83, 0xb5};
672+
670673
static int logi_dj_ll_raw_request(struct hid_device *hid,
671674
unsigned char reportnum, __u8 *buf,
672675
size_t count, unsigned char report_type,
@@ -682,7 +685,13 @@ static int logi_dj_ll_raw_request(struct hid_device *hid,
682685
if (count < 2)
683686
return -EINVAL;
684687

685-
buf[1] = djdev->device_index;
688+
/* special case where we should not overwrite
689+
* the device_index */
690+
if (count == 7 && !memcmp(buf, unifying_name_query,
691+
sizeof(unifying_name_query)))
692+
buf[4] |= djdev->device_index - 1;
693+
else
694+
buf[1] = djdev->device_index;
686695
return hid_hw_raw_request(djrcv_dev->hdev, reportnum, buf,
687696
count, report_type, reqtype);
688697
}
@@ -873,8 +882,17 @@ static int logi_dj_hidpp_event(struct hid_device *hdev,
873882
unsigned long flags;
874883
u8 device_index = dj_report->device_index;
875884

876-
if (device_index == HIDPP_RECEIVER_INDEX)
877-
return false;
885+
if (device_index == HIDPP_RECEIVER_INDEX) {
886+
/* special case were the device wants to know its unifying
887+
* name */
888+
if (size == HIDPP_REPORT_LONG_LENGTH &&
889+
!memcmp(data, unifying_name_answer,
890+
sizeof(unifying_name_answer)) &&
891+
((data[4] & 0xF0) == 0x40))
892+
device_index = (data[4] & 0x0F) + 1;
893+
else
894+
return false;
895+
}
878896

879897
/*
880898
* Data is from the HID++ collection, in this case, we forward the

drivers/hid/hid-logitech-hidpp.c

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,31 @@ static int hidpp_send_fap_command_sync(struct hidpp_device *hidpp,
205205
return ret;
206206
}
207207

208+
static int hidpp_send_rap_command_sync(struct hidpp_device *hidpp_dev,
209+
u8 report_id, u8 sub_id, u8 reg_address, u8 *params, int param_count,
210+
struct hidpp_report *response)
211+
{
212+
struct hidpp_report *message = kzalloc(sizeof(struct hidpp_report),
213+
GFP_KERNEL);
214+
int ret;
215+
216+
if ((report_id != REPORT_ID_HIDPP_SHORT) &&
217+
(report_id != REPORT_ID_HIDPP_LONG))
218+
return -EINVAL;
219+
220+
if (param_count > sizeof(message->rap.params))
221+
return -EINVAL;
222+
223+
message->report_id = report_id;
224+
message->rap.sub_id = sub_id;
225+
message->rap.reg_address = reg_address;
226+
memcpy(&message->rap.params, params, param_count);
227+
228+
ret = hidpp_send_message_sync(hidpp_dev, message, response);
229+
kfree(message);
230+
return ret;
231+
}
232+
208233
static inline bool hidpp_match_answer(struct hidpp_report *question,
209234
struct hidpp_report *answer)
210235
{
@@ -220,6 +245,45 @@ static inline bool hidpp_match_error(struct hidpp_report *question,
220245
(answer->fap.params[0] == question->fap.funcindex_clientid);
221246
}
222247

248+
/* -------------------------------------------------------------------------- */
249+
/* HIDP++ 1.0 commands */
250+
/* -------------------------------------------------------------------------- */
251+
252+
#define HIDPP_SET_REGISTER 0x80
253+
#define HIDPP_GET_REGISTER 0x81
254+
#define HIDPP_SET_LONG_REGISTER 0x82
255+
#define HIDPP_GET_LONG_REGISTER 0x83
256+
257+
#define HIDPP_REG_PAIRING_INFORMATION 0xB5
258+
#define DEVICE_NAME 0x40
259+
260+
static char *hidpp_get_unifying_name(struct hidpp_device *hidpp_dev)
261+
{
262+
struct hidpp_report response;
263+
int ret;
264+
/* hid-logitech-dj is in charge of setting the right device index */
265+
u8 params[1] = { DEVICE_NAME };
266+
char *name;
267+
int len;
268+
269+
ret = hidpp_send_rap_command_sync(hidpp_dev,
270+
REPORT_ID_HIDPP_SHORT,
271+
HIDPP_GET_LONG_REGISTER,
272+
HIDPP_REG_PAIRING_INFORMATION,
273+
params, 1, &response);
274+
if (ret)
275+
return NULL;
276+
277+
len = response.rap.params[1];
278+
279+
name = kzalloc(len + 1, GFP_KERNEL);
280+
if (!name)
281+
return NULL;
282+
283+
memcpy(name, &response.rap.params[2], len);
284+
return name;
285+
}
286+
223287
/* -------------------------------------------------------------------------- */
224288
/* 0x0000: Root */
225289
/* -------------------------------------------------------------------------- */
@@ -726,13 +790,21 @@ static int hidpp_raw_event(struct hid_device *hdev, struct hid_report *report,
726790
return 0;
727791
}
728792

729-
static void hidpp_overwrite_name(struct hid_device *hdev)
793+
static void hidpp_overwrite_name(struct hid_device *hdev, bool use_unifying)
730794
{
731795
struct hidpp_device *hidpp = hid_get_drvdata(hdev);
732796
char *name;
733797
u8 name_length;
734798

735-
name = hidpp_get_device_name(hidpp, &name_length);
799+
if (use_unifying)
800+
/*
801+
* the device is connected through an Unifying receiver, and
802+
* might not be already connected.
803+
* Ask the receiver for its name.
804+
*/
805+
name = hidpp_get_unifying_name(hidpp);
806+
else
807+
name = hidpp_get_device_name(hidpp, &name_length);
736808

737809
if (!name)
738810
hid_err(hdev, "unable to retrieve the name of the device");
@@ -783,12 +855,12 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
783855
goto hid_parse_fail;
784856
}
785857

786-
/* the device is connected, we can ask for its name */
787858
hid_info(hdev, "HID++ %u.%u device connected.\n",
788859
hidpp->protocol_major, hidpp->protocol_minor);
789-
hidpp_overwrite_name(hdev);
790860
}
791861

862+
hidpp_overwrite_name(hdev, id->group == HID_GROUP_LOGITECH_DJ_DEVICE);
863+
792864
if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) {
793865
ret = wtp_get_config(hidpp);
794866
if (ret)

0 commit comments

Comments
 (0)