Skip to content

Commit 54021f9

Browse files
author
Jiri Kosina
committed
Merge branch 'for-6.7/logitech' into for-linus
- big cleanup of logitech-hidpp probe code (Hans de Goede)
2 parents 7601fef + 3e6b0bb commit 54021f9

File tree

1 file changed

+63
-111
lines changed

1 file changed

+63
-111
lines changed

drivers/hid/hid-logitech-hidpp.c

Lines changed: 63 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,11 @@ MODULE_PARM_DESC(disable_tap_to_click,
6969
#define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS BIT(22)
7070
#define HIDPP_QUIRK_DELAYED_INIT BIT(23)
7171
#define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS BIT(24)
72-
#define HIDPP_QUIRK_UNIFYING BIT(25)
73-
#define HIDPP_QUIRK_HIDPP_WHEELS BIT(26)
74-
#define HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS BIT(27)
75-
#define HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS BIT(28)
76-
#define HIDPP_QUIRK_HI_RES_SCROLL_1P0 BIT(29)
77-
#define HIDPP_QUIRK_WIRELESS_STATUS BIT(30)
72+
#define HIDPP_QUIRK_HIDPP_WHEELS BIT(25)
73+
#define HIDPP_QUIRK_HIDPP_EXTRA_MOUSE_BTNS BIT(26)
74+
#define HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS BIT(27)
75+
#define HIDPP_QUIRK_HI_RES_SCROLL_1P0 BIT(28)
76+
#define HIDPP_QUIRK_WIRELESS_STATUS BIT(29)
7877

7978
/* These are just aliases for now */
8079
#define HIDPP_QUIRK_KBD_SCROLL_WHEEL HIDPP_QUIRK_HIDPP_WHEELS
@@ -194,7 +193,6 @@ struct hidpp_device {
194193

195194
struct work_struct work;
196195
struct kfifo delayed_work_fifo;
197-
atomic_t connected;
198196
struct input_dev *delayed_input;
199197

200198
unsigned long quirks;
@@ -235,8 +233,6 @@ struct hidpp_device {
235233
#define HIDPP20_ERROR_UNSUPPORTED 0x09
236234
#define HIDPP20_ERROR 0xff
237235

238-
static void hidpp_connect_event(struct hidpp_device *hidpp_dev);
239-
240236
static int __hidpp_send_report(struct hid_device *hdev,
241237
struct hidpp_report *hidpp_report)
242238
{
@@ -450,13 +446,6 @@ static int hidpp_send_rap_command_sync(struct hidpp_device *hidpp_dev,
450446
return ret;
451447
}
452448

453-
static void delayed_work_cb(struct work_struct *work)
454-
{
455-
struct hidpp_device *hidpp = container_of(work, struct hidpp_device,
456-
work);
457-
hidpp_connect_event(hidpp);
458-
}
459-
460449
static inline bool hidpp_match_answer(struct hidpp_report *question,
461450
struct hidpp_report *answer)
462451
{
@@ -1835,15 +1824,14 @@ static int hidpp_battery_get_property(struct power_supply *psy,
18351824
/* -------------------------------------------------------------------------- */
18361825
#define HIDPP_PAGE_WIRELESS_DEVICE_STATUS 0x1d4b
18371826

1838-
static int hidpp_set_wireless_feature_index(struct hidpp_device *hidpp)
1827+
static int hidpp_get_wireless_feature_index(struct hidpp_device *hidpp, u8 *feature_index)
18391828
{
18401829
u8 feature_type;
18411830
int ret;
18421831

18431832
ret = hidpp_root_get_feature(hidpp,
18441833
HIDPP_PAGE_WIRELESS_DEVICE_STATUS,
1845-
&hidpp->wireless_feature_index,
1846-
&feature_type);
1834+
feature_index, &feature_type);
18471835

18481836
return ret;
18491837
}
@@ -3142,7 +3130,7 @@ static int wtp_allocate(struct hid_device *hdev, const struct hid_device_id *id)
31423130
return 0;
31433131
};
31443132

3145-
static int wtp_connect(struct hid_device *hdev, bool connected)
3133+
static int wtp_connect(struct hid_device *hdev)
31463134
{
31473135
struct hidpp_device *hidpp = hid_get_drvdata(hdev);
31483136
struct wtp_data *wd = hidpp->private_data;
@@ -3204,7 +3192,7 @@ static const u8 m560_config_parameter[] = {0x00, 0xaf, 0x03};
32043192
#define M560_SUB_ID 0x0a
32053193
#define M560_BUTTON_MODE_REGISTER 0x35
32063194

3207-
static int m560_send_config_command(struct hid_device *hdev, bool connected)
3195+
static int m560_send_config_command(struct hid_device *hdev)
32083196
{
32093197
struct hidpp_report response;
32103198
struct hidpp_device *hidpp_dev;
@@ -3399,7 +3387,7 @@ static int k400_allocate(struct hid_device *hdev)
33993387
return 0;
34003388
};
34013389

3402-
static int k400_connect(struct hid_device *hdev, bool connected)
3390+
static int k400_connect(struct hid_device *hdev)
34033391
{
34043392
struct hidpp_device *hidpp = hid_get_drvdata(hdev);
34053393

@@ -3894,8 +3882,6 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data,
38943882
}
38953883

38963884
if (unlikely(hidpp_report_is_connect_event(hidpp, report))) {
3897-
atomic_set(&hidpp->connected,
3898-
!(report->rap.params[0] & (1 << 6)));
38993885
if (schedule_work(&hidpp->work) == 0)
39003886
dbg_hid("%s: connect event already queued\n", __func__);
39013887
return 1;
@@ -4131,24 +4117,22 @@ static int hidpp_initialize_battery(struct hidpp_device *hidpp)
41314117
return ret;
41324118
}
41334119

4134-
static void hidpp_overwrite_name(struct hid_device *hdev)
4120+
/* Get name + serial for USB and Bluetooth HID++ devices */
4121+
static void hidpp_non_unifying_init(struct hidpp_device *hidpp)
41354122
{
4136-
struct hidpp_device *hidpp = hid_get_drvdata(hdev);
4123+
struct hid_device *hdev = hidpp->hid_dev;
41374124
char *name;
41384125

4139-
if (hidpp->protocol_major < 2)
4140-
return;
4126+
/* Bluetooth devices already have their serialnr set */
4127+
if (hid_is_usb(hdev))
4128+
hidpp_serial_init(hidpp);
41414129

41424130
name = hidpp_get_device_name(hidpp);
4143-
4144-
if (!name) {
4145-
hid_err(hdev, "unable to retrieve the name of the device");
4146-
} else {
4131+
if (name) {
41474132
dbg_hid("HID++: Got name: %s\n", name);
41484133
snprintf(hdev->name, sizeof(hdev->name), "%s", name);
4134+
kfree(name);
41494135
}
4150-
4151-
kfree(name);
41524136
}
41534137

41544138
static int hidpp_input_open(struct input_dev *dev)
@@ -4189,15 +4173,18 @@ static struct input_dev *hidpp_allocate_input(struct hid_device *hdev)
41894173
return input_dev;
41904174
}
41914175

4192-
static void hidpp_connect_event(struct hidpp_device *hidpp)
4176+
static void hidpp_connect_event(struct work_struct *work)
41934177
{
4178+
struct hidpp_device *hidpp = container_of(work, struct hidpp_device, work);
41944179
struct hid_device *hdev = hidpp->hid_dev;
4195-
int ret = 0;
4196-
bool connected = atomic_read(&hidpp->connected);
41974180
struct input_dev *input;
41984181
char *name, *devm_name;
4182+
int ret;
41994183

4200-
if (!connected) {
4184+
/* Get device version to check if it is connected */
4185+
ret = hidpp_root_get_protocol_version(hidpp);
4186+
if (ret) {
4187+
hid_info(hidpp->hid_dev, "Disconnected\n");
42014188
if (hidpp->battery.ps) {
42024189
hidpp->battery.online = false;
42034190
hidpp->battery.status = POWER_SUPPLY_STATUS_UNKNOWN;
@@ -4208,15 +4195,15 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
42084195
}
42094196

42104197
if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) {
4211-
ret = wtp_connect(hdev, connected);
4198+
ret = wtp_connect(hdev);
42124199
if (ret)
42134200
return;
42144201
} else if (hidpp->quirks & HIDPP_QUIRK_CLASS_M560) {
4215-
ret = m560_send_config_command(hdev, connected);
4202+
ret = m560_send_config_command(hdev);
42164203
if (ret)
42174204
return;
42184205
} else if (hidpp->quirks & HIDPP_QUIRK_CLASS_K400) {
4219-
ret = k400_connect(hdev, connected);
4206+
ret = k400_connect(hdev);
42204207
if (ret)
42214208
return;
42224209
}
@@ -4239,14 +4226,11 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)
42394226
return;
42404227
}
42414228

4242-
/* the device is already connected, we can ask for its name and
4243-
* protocol */
4244-
if (!hidpp->protocol_major) {
4245-
ret = hidpp_root_get_protocol_version(hidpp);
4246-
if (ret) {
4247-
hid_err(hdev, "Can not get the protocol version.\n");
4248-
return;
4249-
}
4229+
if (hidpp->protocol_major >= 2) {
4230+
u8 feature_index;
4231+
4232+
if (!hidpp_get_wireless_feature_index(hidpp, &feature_index))
4233+
hidpp->wireless_feature_index = feature_index;
42504234
}
42514235

42524236
if (hidpp->name == hdev->name && hidpp->protocol_major >= 2) {
@@ -4391,10 +4375,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
43914375
{
43924376
struct hidpp_device *hidpp;
43934377
int ret;
4394-
bool connected;
43954378
unsigned int connect_mask = HID_CONNECT_DEFAULT;
4396-
struct hidpp_ff_private_data data;
4397-
bool will_restart = false;
43984379

43994380
/* report_fixup needs drvdata to be set before we call hid_parse */
44004381
hidpp = devm_kzalloc(&hdev->dev, sizeof(*hidpp), GFP_KERNEL);
@@ -4423,9 +4404,6 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
44234404
return hid_hw_start(hdev, HID_CONNECT_DEFAULT);
44244405
}
44254406

4426-
if (id->group == HID_GROUP_LOGITECH_DJ_DEVICE)
4427-
hidpp->quirks |= HIDPP_QUIRK_UNIFYING;
4428-
44294407
if (id->group == HID_GROUP_LOGITECH_27MHZ_DEVICE &&
44304408
hidpp_application_equals(hdev, HID_GD_MOUSE))
44314409
hidpp->quirks |= HIDPP_QUIRK_HIDPP_WHEELS |
@@ -4445,11 +4423,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
44454423
return ret;
44464424
}
44474425

4448-
if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT ||
4449-
hidpp->quirks & HIDPP_QUIRK_UNIFYING)
4450-
will_restart = true;
4451-
4452-
INIT_WORK(&hidpp->work, delayed_work_cb);
4426+
INIT_WORK(&hidpp->work, hidpp_connect_event);
44534427
mutex_init(&hidpp->send_mutex);
44544428
init_waitqueue_head(&hidpp->wait);
44554429

@@ -4460,10 +4434,12 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
44604434
hdev->name);
44614435

44624436
/*
4463-
* Plain USB connections need to actually call start and open
4464-
* on the transport driver to allow incoming data.
4437+
* First call hid_hw_start(hdev, 0) to allow IO without connecting any
4438+
* hid subdrivers (hid-input, hidraw). This allows retrieving the dev's
4439+
* name and serial number and store these in hdev->name and hdev->uniq,
4440+
* before the hid-input and hidraw drivers expose these to userspace.
44654441
*/
4466-
ret = hid_hw_start(hdev, will_restart ? 0 : connect_mask);
4442+
ret = hid_hw_start(hdev, 0);
44674443
if (ret) {
44684444
hid_err(hdev, "hw start failed\n");
44694445
goto hid_hw_start_fail;
@@ -4479,70 +4455,46 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
44794455
/* Allow incoming packets */
44804456
hid_device_io_start(hdev);
44814457

4482-
if (hidpp->quirks & HIDPP_QUIRK_UNIFYING)
4458+
/* Get name + serial, store in hdev->name + hdev->uniq */
4459+
if (id->group == HID_GROUP_LOGITECH_DJ_DEVICE)
44834460
hidpp_unifying_init(hidpp);
4484-
else if (hid_is_usb(hidpp->hid_dev))
4485-
hidpp_serial_init(hidpp);
4486-
4487-
connected = hidpp_root_get_protocol_version(hidpp) == 0;
4488-
atomic_set(&hidpp->connected, connected);
4489-
if (!(hidpp->quirks & HIDPP_QUIRK_UNIFYING)) {
4490-
if (!connected) {
4491-
ret = -ENODEV;
4492-
hid_err(hdev, "Device not connected");
4493-
goto hid_hw_init_fail;
4494-
}
4495-
4496-
hidpp_overwrite_name(hdev);
4497-
}
4461+
else
4462+
hidpp_non_unifying_init(hidpp);
44984463

4499-
if (connected && hidpp->protocol_major >= 2) {
4500-
ret = hidpp_set_wireless_feature_index(hidpp);
4501-
if (ret == -ENOENT)
4502-
hidpp->wireless_feature_index = 0;
4503-
else if (ret)
4504-
goto hid_hw_init_fail;
4505-
ret = 0;
4506-
}
4464+
if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT)
4465+
connect_mask &= ~HID_CONNECT_HIDINPUT;
45074466

4508-
if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP)) {
4509-
ret = wtp_get_config(hidpp);
4510-
if (ret)
4511-
goto hid_hw_init_fail;
4512-
} else if (connected && (hidpp->quirks & HIDPP_QUIRK_CLASS_G920)) {
4513-
ret = g920_get_config(hidpp, &data);
4514-
if (ret)
4515-
goto hid_hw_init_fail;
4467+
/* Now export the actual inputs and hidraw nodes to the world */
4468+
hid_device_io_stop(hdev);
4469+
ret = hid_connect(hdev, connect_mask);
4470+
if (ret) {
4471+
hid_err(hdev, "%s:hid_connect returned error %d\n", __func__, ret);
4472+
goto hid_hw_init_fail;
45164473
}
45174474

4475+
/* Check for connected devices now that incoming packets will not be disabled again */
4476+
hid_device_io_start(hdev);
45184477
schedule_work(&hidpp->work);
45194478
flush_work(&hidpp->work);
45204479

4521-
if (will_restart) {
4522-
/* Reset the HID node state */
4523-
hid_device_io_stop(hdev);
4524-
hid_hw_close(hdev);
4525-
hid_hw_stop(hdev);
4526-
4527-
if (hidpp->quirks & HIDPP_QUIRK_DELAYED_INIT)
4528-
connect_mask &= ~HID_CONNECT_HIDINPUT;
4480+
if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
4481+
struct hidpp_ff_private_data data;
45294482

4530-
/* Now export the actual inputs and hidraw nodes to the world */
4531-
ret = hid_hw_start(hdev, connect_mask);
4532-
if (ret) {
4533-
hid_err(hdev, "%s:hid_hw_start returned error\n", __func__);
4534-
goto hid_hw_start_fail;
4535-
}
4536-
}
4483+
ret = g920_get_config(hidpp, &data);
4484+
if (!ret)
4485+
ret = hidpp_ff_init(hidpp, &data);
45374486

4538-
if (hidpp->quirks & HIDPP_QUIRK_CLASS_G920) {
4539-
ret = hidpp_ff_init(hidpp, &data);
45404487
if (ret)
45414488
hid_warn(hidpp->hid_dev,
45424489
"Unable to initialize force feedback support, errno %d\n",
45434490
ret);
45444491
}
45454492

4493+
/*
4494+
* This relies on logi_dj_ll_close() being a no-op so that DJ connection
4495+
* events will still be received.
4496+
*/
4497+
hid_hw_close(hdev);
45464498
return ret;
45474499

45484500
hid_hw_init_fail:

0 commit comments

Comments
 (0)