Skip to content

Commit 1d72e7b

Browse files
LawstorantJiri Kosina
authored andcommitted
HID: pidff: Add support for AXES_ENABLE field
AXES_ENABLE can be used in place of DIRECTION_ENABLE to indicate, which FFB-enabled axes will be affected by a given effect. EFFECT_DIRECTION enables all and uses the first direction only while AXES_ENABLE is a bitmask and bit indexes are the same as the defined GD usages in the EFFECT_DIRECTION array. Each axis can have it's own direction in this case. Search for AXES_ENABLE, set AXES_ENABLE for all axes if DIRECTION_ENABLE is not used. Search for specific axes in the direction array. Save their indexes. This let us know what axes are actually available on the device and which bit in the AXES_ENABLE field corresponds to which axis. Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.com>
1 parent b974b37 commit 1d72e7b

1 file changed

Lines changed: 87 additions & 4 deletions

File tree

drivers/hid/usbhid/hid-pidff.c

Lines changed: 87 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ static const u8 pidff_reports[] = {
5151

5252
/* PID special fields */
5353
#define PID_EFFECT_TYPE 0x25
54+
#define PID_AXES_ENABLE 0x55
5455
#define PID_DIRECTION 0x57
5556
#define PID_EFFECT_OPERATION_ARRAY 0x78
5657
#define PID_BLOCK_LOAD_STATUS 0x8b
@@ -150,6 +151,31 @@ static const u8 pidff_effect_operation_status[] = { 0x79, 0x7b };
150151
/* Polar direction 90 degrees (East) */
151152
#define PIDFF_FIXED_WHEEL_DIRECTION 0x4000
152153

154+
/* AXES_ENABLE and DIRECTION axes */
155+
enum pid_axes {
156+
PID_AXIS_X,
157+
PID_AXIS_Y,
158+
PID_AXIS_Z,
159+
PID_AXIS_RX,
160+
PID_AXIS_RY,
161+
PID_AXIS_RZ,
162+
PID_AXIS_SLIDER,
163+
PID_AXIS_DIAL,
164+
PID_AXIS_WHEEL,
165+
PID_AXES_COUNT,
166+
};
167+
static const u8 pidff_direction_axis[] = {
168+
HID_USAGE & HID_GD_X,
169+
HID_USAGE & HID_GD_Y,
170+
HID_USAGE & HID_GD_Z,
171+
HID_USAGE & HID_GD_RX,
172+
HID_USAGE & HID_GD_RY,
173+
HID_USAGE & HID_GD_RZ,
174+
HID_USAGE & HID_GD_SLIDER,
175+
HID_USAGE & HID_GD_DIAL,
176+
HID_USAGE & HID_GD_WHEEL,
177+
};
178+
153179
struct pidff_usage {
154180
struct hid_field *field;
155181
s32 *value;
@@ -184,6 +210,7 @@ struct pidff_device {
184210
/* Special fields in set_effect */
185211
struct hid_field *set_effect_type;
186212
struct hid_field *effect_direction;
213+
struct hid_field *axes_enable;
187214

188215
/* Special field in device_control */
189216
struct hid_field *device_control;
@@ -198,11 +225,13 @@ struct pidff_device {
198225
int type_id[ARRAY_SIZE(pidff_effect_types)];
199226
int status_id[ARRAY_SIZE(pidff_block_load_status)];
200227
int operation_id[ARRAY_SIZE(pidff_effect_operation_status)];
228+
int direction_axis_id[ARRAY_SIZE(pidff_direction_axis)];
201229

202230
int pid_id[PID_EFFECTS_MAX];
203231

204232
u32 quirks;
205233
u8 effect_count;
234+
u8 axis_count;
206235
};
207236

208237
static int pidff_is_effect_conditional(struct ff_effect *effect)
@@ -306,14 +335,37 @@ static void pidff_set_effect_direction(struct pidff_device *pidff,
306335
struct ff_effect *effect)
307336
{
308337
u16 direction = effect->direction;
338+
int direction_enable = 1;
309339

310340
/* Use fixed direction if needed */
311341
if (pidff->quirks & HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION &&
312342
pidff_is_effect_conditional(effect))
313343
direction = PIDFF_FIXED_WHEEL_DIRECTION;
314344

345+
pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = direction_enable;
315346
pidff->effect_direction->value[0] =
316347
pidff_rescale(direction, U16_MAX, pidff->effect_direction);
348+
349+
if (direction_enable)
350+
return;
351+
352+
/*
353+
* For use with improved FFB API
354+
* We want to read the selected axes and their direction from the effect
355+
* struct and only enable those. For now, enable all axes.
356+
*
357+
*/
358+
for (int i = 0; i < PID_AXES_COUNT; i++) {
359+
/* HID index starts with 1 */
360+
int index = pidff->direction_axis_id[i] - 1;
361+
362+
if (index < 0)
363+
continue;
364+
365+
pidff->axes_enable->value[index] = 1;
366+
pidff->effect_direction->value[index] = pidff_rescale(
367+
direction, U16_MAX, pidff->effect_direction);
368+
}
317369
}
318370

319371
/*
@@ -411,7 +463,6 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
411463
effect->trigger.interval);
412464
pidff->set_effect[PID_GAIN].value[0] =
413465
pidff->set_effect[PID_GAIN].field->logical_maximum;
414-
pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
415466

416467
pidff_set_effect_direction(pidff, effect);
417468

@@ -1122,12 +1173,13 @@ static struct hid_field *pidff_find_special_field(struct hid_report *report,
11221173
* Fill a pidff->*_id struct table
11231174
*/
11241175
static int pidff_find_special_keys(int *keys, struct hid_field *fld,
1125-
const u8 *usagetable, int count)
1176+
const u8 *usagetable, int count,
1177+
unsigned int usage_page)
11261178
{
11271179
int found = 0;
11281180

11291181
for (int i = 0; i < count; i++) {
1130-
keys[i] = pidff_find_usage(fld, HID_UP_PID | usagetable[i]) + 1;
1182+
keys[i] = pidff_find_usage(fld, usage_page | usagetable[i]) + 1;
11311183
if (keys[i])
11321184
found++;
11331185
}
@@ -1136,7 +1188,11 @@ static int pidff_find_special_keys(int *keys, struct hid_field *fld,
11361188

11371189
#define PIDFF_FIND_SPECIAL_KEYS(keys, field, name) \
11381190
pidff_find_special_keys(pidff->keys, pidff->field, pidff_ ## name, \
1139-
ARRAY_SIZE(pidff_ ## name))
1191+
ARRAY_SIZE(pidff_ ## name), HID_UP_PID)
1192+
1193+
#define PIDFF_FIND_GENERAL_DESKTOP(keys, field, name) \
1194+
pidff_find_special_keys(pidff->keys, pidff->field, pidff_ ## name, \
1195+
ARRAY_SIZE(pidff_ ## name), HID_UP_GENDESK)
11401196

11411197
/*
11421198
* Find and check the special fields
@@ -1151,6 +1207,9 @@ static int pidff_find_special_fields(struct pidff_device *pidff)
11511207
pidff->set_effect_type =
11521208
pidff_find_special_field(pidff->reports[PID_SET_EFFECT],
11531209
PID_EFFECT_TYPE, 1);
1210+
pidff->axes_enable =
1211+
pidff_find_special_field(pidff->reports[PID_SET_EFFECT],
1212+
PID_AXES_ENABLE, 0);
11541213
pidff->effect_direction =
11551214
pidff_find_special_field(pidff->reports[PID_SET_EFFECT],
11561215
PID_DIRECTION, 0);
@@ -1216,6 +1275,30 @@ static int pidff_find_special_fields(struct pidff_device *pidff)
12161275
return -1;
12171276
}
12181277

1278+
if (!pidff->axes_enable)
1279+
hid_info(pidff->hid, "axes enable field not found!\n");
1280+
else
1281+
hid_dbg(pidff->hid, "axes enable report count: %u\n",
1282+
pidff->axes_enable->report_count);
1283+
1284+
uint found = PIDFF_FIND_GENERAL_DESKTOP(direction_axis_id, axes_enable,
1285+
direction_axis);
1286+
1287+
pidff->axis_count = found;
1288+
hid_dbg(pidff->hid, "found direction axes: %u", found);
1289+
1290+
for (int i = 0; i < sizeof(pidff_direction_axis); i++) {
1291+
if (!pidff->direction_axis_id[i])
1292+
continue;
1293+
1294+
hid_dbg(pidff->hid, "axis %d, usage: 0x%04x, index: %d", i + 1,
1295+
pidff_direction_axis[i], pidff->direction_axis_id[i]);
1296+
}
1297+
1298+
if (pidff->axes_enable && found != pidff->axes_enable->report_count)
1299+
hid_warn(pidff->hid, "axes_enable: %u != direction axes: %u",
1300+
pidff->axes_enable->report_count, found);
1301+
12191302
return 0;
12201303
}
12211304

0 commit comments

Comments
 (0)