@@ -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+
153179struct 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
208237static 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 */
11241175static 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