2 * Common HID report descriptor helpers
4 * Copyright 2021 RĂ©mi Bernon for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #define WIN32_NO_STATUS
35 #include "ddk/hidsdi.h"
37 #include "wine/debug.h"
40 #include "unix_private.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(hid
);
44 static BOOL
hid_report_descriptor_append(struct hid_report_descriptor
*desc
, const BYTE
*buffer
, SIZE_T size
)
46 BYTE
*tmp
= desc
->data
;
48 if (desc
->size
+ size
> desc
->max_size
)
50 desc
->max_size
= max(desc
->max_size
* 3 / 2, desc
->size
+ size
);
51 desc
->data
= realloc(tmp
, desc
->max_size
);
60 memcpy(desc
->data
+ desc
->size
, buffer
, size
);
65 #include "psh_hid_macros.h"
67 static BOOL
hid_report_descriptor_append_usage(struct hid_report_descriptor
*desc
, USAGE usage
)
69 const BYTE
template[] =
74 return hid_report_descriptor_append(desc
, template, sizeof(template));
77 static BOOL
hid_device_begin_collection(struct hid_report_descriptor
*desc
, const USAGE_AND_PAGE
*usage
, BYTE type
)
79 const BYTE
template[] =
81 USAGE_PAGE(2, usage
->UsagePage
),
82 USAGE(2, usage
->Usage
),
86 return hid_report_descriptor_append(desc
, template, sizeof(template));
89 static BOOL
hid_device_end_collection(struct hid_report_descriptor
*desc
)
91 static const BYTE
template[] =
96 return hid_report_descriptor_append(desc
, template, sizeof(template));
99 BOOL
hid_device_begin_report_descriptor(struct unix_device
*iface
, const USAGE_AND_PAGE
*device_usage
)
101 struct hid_report_descriptor
*desc
= &iface
->hid_report_descriptor
;
102 memset(desc
, 0, sizeof(*desc
));
103 return hid_device_begin_collection(desc
, device_usage
, Application
);
106 BOOL
hid_device_end_report_descriptor(struct unix_device
*iface
)
108 struct hid_report_descriptor
*desc
= &iface
->hid_report_descriptor
;
109 return hid_device_end_collection(desc
);
112 BOOL
hid_device_begin_input_report(struct unix_device
*iface
, const USAGE_AND_PAGE
*physical_usage
)
114 struct hid_report_descriptor
*desc
= &iface
->hid_report_descriptor
;
115 struct hid_device_state
*state
= &iface
->hid_device_state
;
116 const BYTE report_id
= ++desc
->next_report_id
[HidP_Input
];
117 const BYTE
template[] =
119 REPORT_ID(1, report_id
),
122 if (state
->report_len
)
124 ERR("input report already created\n");
128 state
->id
= report_id
;
129 state
->bit_size
+= 8;
131 if (!hid_device_begin_collection(desc
, physical_usage
, Physical
))
134 return hid_report_descriptor_append(desc
, template, sizeof(template));
137 BOOL
hid_device_end_input_report(struct unix_device
*iface
)
139 struct hid_report_descriptor
*desc
= &iface
->hid_report_descriptor
;
140 struct hid_device_state
*state
= &iface
->hid_device_state
;
142 state
->report_len
= (state
->bit_size
+ 7) / 8;
143 if (!(state
->report_buf
= calloc(1, state
->report_len
))) return FALSE
;
144 if (!(state
->last_report_buf
= calloc(1, state
->report_len
))) return FALSE
;
146 state
->report_buf
[0] = state
->id
;
147 state
->last_report_buf
[0] = state
->id
;
148 return hid_device_end_collection(desc
);
151 static BOOL
hid_device_add_button_count(struct unix_device
*iface
, BYTE count
)
153 USHORT offset
= iface
->hid_device_state
.bit_size
/ 8;
155 if ((iface
->hid_device_state
.bit_size
% 8) && !iface
->hid_device_state
.button_count
)
156 ERR("buttons should start byte aligned, missing padding!\n");
157 else if (iface
->hid_device_state
.bit_size
+ count
> 0x80000)
158 ERR("report size overflow, too many elements!\n");
161 if (!iface
->hid_device_state
.button_count
) iface
->hid_device_state
.button_start
= offset
;
162 iface
->hid_device_state
.button_count
+= count
;
163 iface
->hid_device_state
.bit_size
+= count
;
170 BOOL
hid_device_add_buttons(struct unix_device
*iface
, USAGE usage_page
, USAGE usage_min
, USAGE usage_max
)
172 struct hid_report_descriptor
*desc
= &iface
->hid_report_descriptor
;
173 const USHORT count
= usage_max
- usage_min
+ 1;
174 const BYTE
template[] =
176 USAGE_PAGE(2, usage_page
),
177 USAGE_MINIMUM(2, usage_min
),
178 USAGE_MAXIMUM(2, usage_max
),
179 LOGICAL_MINIMUM(1, 0),
180 LOGICAL_MAXIMUM(1, 1),
181 REPORT_COUNT(2, count
),
183 INPUT(1, Data
|Var
|Abs
),
185 const BYTE template_pad
[] =
187 REPORT_COUNT(1, 8 - (count
% 8)),
189 INPUT(1, Cnst
|Var
|Abs
),
192 if (!hid_device_add_button_count(iface
, usage_max
- usage_min
+ 1))
195 if (!hid_report_descriptor_append(desc
, template, sizeof(template)))
198 if ((count
% 8) && !hid_report_descriptor_append(desc
, template_pad
, sizeof(template_pad
)))
204 static BOOL
hid_device_add_hatswitch_count(struct unix_device
*iface
, BYTE count
)
206 USHORT offset
= iface
->hid_device_state
.bit_size
/ 8;
208 if (iface
->hid_device_state
.button_count
)
209 ERR("hatswitches should be added before buttons!\n");
210 else if ((iface
->hid_device_state
.bit_size
% 8))
211 ERR("hatswitches should be byte aligned, missing padding!\n");
212 else if (iface
->hid_device_state
.bit_size
+ 4 * (count
+ 1) > 0x80000)
213 ERR("report size overflow, too many elements!\n");
216 if (!iface
->hid_device_state
.hatswitch_count
) iface
->hid_device_state
.hatswitch_start
= offset
;
217 iface
->hid_device_state
.hatswitch_count
+= count
;
218 iface
->hid_device_state
.bit_size
+= 4 * count
;
219 if (count
% 2) iface
->hid_device_state
.bit_size
+= 4;
226 BOOL
hid_device_add_hatswitch(struct unix_device
*iface
, INT count
)
228 struct hid_report_descriptor
*desc
= &iface
->hid_report_descriptor
;
229 const BYTE
template[] =
231 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC
),
232 USAGE(1, HID_USAGE_GENERIC_HATSWITCH
),
233 LOGICAL_MINIMUM(1, 1),
234 LOGICAL_MAXIMUM(1, 8),
236 REPORT_COUNT(4, count
),
237 UNIT(1, 0x0), /* None */
238 INPUT(1, Data
|Var
|Abs
|Null
),
240 const BYTE template_pad
[] =
244 INPUT(1, Cnst
|Ary
|Abs
),
247 if (!hid_device_add_hatswitch_count(iface
, count
))
250 if (!hid_report_descriptor_append(desc
, template, sizeof(template)))
253 if ((count
% 2) && !hid_report_descriptor_append(desc
, template_pad
, sizeof(template_pad
)))
259 static BOOL
hid_device_add_axis_count(struct unix_device
*iface
, BOOL rel
, BYTE count
,
260 USAGE usage_page
, const USAGE
*usages
)
262 struct hid_device_state
*state
= &iface
->hid_device_state
;
263 USHORT i
, offset
= state
->bit_size
/ 8;
265 if (!rel
&& state
->rel_axis_count
)
266 ERR("absolute axes should be added before relative axes!\n");
267 else if (state
->button_count
|| state
->hatswitch_count
)
268 ERR("axes should be added before buttons or hatswitches!\n");
269 else if ((state
->bit_size
% 8))
270 ERR("axes should be byte aligned, missing padding!\n");
271 else if (state
->bit_size
+ 32 * count
> 0x80000)
272 ERR("report size overflow, too many elements!\n");
275 if (!state
->rel_axis_count
) state
->rel_axis_start
= offset
;
276 state
->rel_axis_count
+= count
;
277 state
->bit_size
+= 32 * count
;
282 if (state
->abs_axis_count
+ count
> ARRAY_SIZE(state
->abs_axis_usages
))
284 ERR("absolute axis usage overflow, too many elements!\n");
287 for (i
= 0; i
< count
; ++i
)
289 state
->abs_axis_usages
[state
->abs_axis_count
+ i
].UsagePage
= usage_page
;
290 state
->abs_axis_usages
[state
->abs_axis_count
+ i
].Usage
= usages
[i
];
293 if (!state
->abs_axis_count
) state
->abs_axis_start
= offset
;
294 state
->abs_axis_count
+= count
;
295 state
->bit_size
+= 32 * count
;
302 BOOL
hid_device_add_axes(struct unix_device
*iface
, BYTE count
, USAGE usage_page
,
303 const USAGE
*usages
, BOOL rel
, LONG min
, LONG max
)
305 struct hid_report_descriptor
*desc
= &iface
->hid_report_descriptor
;
306 const BYTE template_begin
[] =
308 USAGE_PAGE(1, usage_page
),
309 COLLECTION(1, Physical
),
311 const BYTE template_end
[] =
315 const BYTE
template[] =
317 LOGICAL_MINIMUM(4, min
),
318 LOGICAL_MAXIMUM(4, max
),
320 REPORT_COUNT(1, count
),
321 INPUT(1, Data
|Var
|(rel
? Rel
: Abs
)),
325 if (!hid_device_add_axis_count(iface
, rel
, count
, usage_page
, usages
))
328 if (!hid_report_descriptor_append(desc
, template_begin
, sizeof(template_begin
)))
331 for (i
= 0; i
< count
; i
++)
333 if (!hid_report_descriptor_append_usage(desc
, usages
[i
]))
337 if (!hid_report_descriptor_append(desc
, template, sizeof(template)))
340 if (!hid_report_descriptor_append(desc
, template_end
, sizeof(template_end
)))
346 #include "pshpack1.h"
347 struct hid_haptics_intensity
349 UINT16 rumble_intensity
;
350 UINT16 buzz_intensity
;
351 UINT16 left_intensity
;
352 UINT16 right_intensity
;
356 BOOL
hid_device_add_haptics(struct unix_device
*iface
)
358 struct hid_report_descriptor
*desc
= &iface
->hid_report_descriptor
;
359 const BYTE haptics_features_report
= ++desc
->next_report_id
[HidP_Feature
];
360 const BYTE haptics_intensity_report
= ++desc
->next_report_id
[HidP_Output
];
361 const BYTE haptics_template
[] =
363 USAGE_PAGE(2, HID_USAGE_PAGE_HAPTICS
),
364 USAGE(1, HID_USAGE_HAPTICS_SIMPLE_CONTROLLER
),
365 COLLECTION(1, Logical
),
366 REPORT_ID(1, haptics_features_report
),
368 USAGE(1, HID_USAGE_HAPTICS_WAVEFORM_LIST
),
369 COLLECTION(1, NamedArray
),
370 /* ordinal 1 and 2 are reserved for implicit waveforms */
371 USAGE(4, (HID_USAGE_PAGE_ORDINAL
<<16)|3),
374 FEATURE(1, Data
|Var
|Abs
|Null
),
377 USAGE(1, HID_USAGE_HAPTICS_DURATION_LIST
),
378 COLLECTION(1, NamedArray
),
379 /* ordinal 1 and 2 are reserved for implicit waveforms */
380 USAGE(4, (HID_USAGE_PAGE_ORDINAL
<<16)|3),
383 FEATURE(1, Data
|Var
|Abs
|Null
),
386 USAGE(1, HID_USAGE_HAPTICS_WAVEFORM_CUTOFF_TIME
),
387 UNIT(2, 0x1001), /* seconds */
388 UNIT_EXPONENT(1, -3), /* 10^-3 */
389 LOGICAL_MINIMUM(4, 0x00000000),
390 LOGICAL_MAXIMUM(4, 0x7fffffff),
393 FEATURE(1, Data
|Var
|Abs
),
394 /* reset global items */
395 UNIT(1, 0), /* None */
398 REPORT_ID(1, haptics_intensity_report
),
399 USAGE(1, HID_USAGE_HAPTICS_INTENSITY
),
400 LOGICAL_MINIMUM(4, 0x00000000),
401 LOGICAL_MAXIMUM(4, 0x0000ffff),
404 OUTPUT(1, Data
|Var
|Abs
),
407 const BYTE trigger_template_begin
[] =
409 USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC
),
410 COLLECTION(1, Physical
),
412 const BYTE trigger_template_end
[] =
417 iface
->hid_haptics
.features_report
= haptics_features_report
;
418 iface
->hid_haptics
.intensity_report
= haptics_intensity_report
;
419 iface
->hid_haptics
.features
.rumble
.waveform
= HID_USAGE_HAPTICS_WAVEFORM_RUMBLE
;
420 iface
->hid_haptics
.features
.rumble
.duration
= 0;
421 iface
->hid_haptics
.features
.rumble
.cutoff_time_ms
= 1000;
422 iface
->hid_haptics
.features
.buzz
.waveform
= HID_USAGE_HAPTICS_WAVEFORM_BUZZ
;
423 iface
->hid_haptics
.features
.buzz
.duration
= 0;
424 iface
->hid_haptics
.features
.buzz
.cutoff_time_ms
= 1000;
425 iface
->hid_haptics
.features
.left
.waveform
= HID_USAGE_HAPTICS_WAVEFORM_RUMBLE
;
426 iface
->hid_haptics
.features
.left
.duration
= 0;
427 iface
->hid_haptics
.features
.left
.cutoff_time_ms
= 1000;
428 iface
->hid_haptics
.features
.right
.waveform
= HID_USAGE_HAPTICS_WAVEFORM_RUMBLE
;
429 iface
->hid_haptics
.features
.right
.duration
= 0;
430 iface
->hid_haptics
.features
.right
.cutoff_time_ms
= 1000;
432 if (!hid_report_descriptor_append(desc
, haptics_template
, sizeof(haptics_template
)))
434 if (!hid_report_descriptor_append(desc
, haptics_template
, sizeof(haptics_template
)))
437 if (!hid_report_descriptor_append_usage(desc
, HID_USAGE_GENERIC_Z
))
439 if (!hid_report_descriptor_append(desc
, trigger_template_begin
, sizeof(trigger_template_begin
)))
441 if (!hid_report_descriptor_append(desc
, haptics_template
, sizeof(haptics_template
)))
443 if (!hid_report_descriptor_append(desc
, trigger_template_end
, sizeof(trigger_template_end
)))
446 if (!hid_report_descriptor_append_usage(desc
, HID_USAGE_GENERIC_RZ
))
448 if (!hid_report_descriptor_append(desc
, trigger_template_begin
, sizeof(trigger_template_begin
)))
450 if (!hid_report_descriptor_append(desc
, haptics_template
, sizeof(haptics_template
)))
452 if (!hid_report_descriptor_append(desc
, trigger_template_end
, sizeof(trigger_template_end
)))
458 #include "pshpack1.h"
459 struct pid_device_control
464 static const USAGE pid_device_control_usages
[] =
466 0, /* HID nary collection indexes start at 1 */
467 PID_USAGE_DC_ENABLE_ACTUATORS
,
468 PID_USAGE_DC_DISABLE_ACTUATORS
,
469 PID_USAGE_DC_STOP_ALL_EFFECTS
,
470 PID_USAGE_DC_DEVICE_RESET
,
471 PID_USAGE_DC_DEVICE_PAUSE
,
472 PID_USAGE_DC_DEVICE_CONTINUE
,
475 struct pid_device_gain
480 struct pid_effect_control
487 static const USAGE pid_effect_control_usages
[] =
489 0, /* HID nary collection indexes start at 1 */
490 PID_USAGE_OP_EFFECT_START
,
491 PID_USAGE_OP_EFFECT_START_SOLO
,
492 PID_USAGE_OP_EFFECT_STOP
,
495 struct pid_effect_update
500 UINT16 trigger_repeat_interval
;
501 UINT16 sample_period
;
509 struct pid_set_periodic
518 struct pid_set_envelope
527 struct pid_set_condition
530 BYTE condition_index
;
531 INT16 center_point_offset
;
532 INT16 positive_coefficient
;
533 INT16 negative_coefficient
;
534 UINT16 positive_saturation
;
535 UINT16 negative_saturation
;
539 struct pid_set_constant_force
545 struct pid_set_ramp_force
552 struct pid_effect_state
559 static BOOL
hid_descriptor_add_set_periodic(struct unix_device
*iface
)
561 struct hid_report_descriptor
*desc
= &iface
->hid_report_descriptor
;
562 const BYTE report_id
= ++desc
->next_report_id
[HidP_Output
];
563 const BYTE
template[] =
565 /* Periodic Report Definition */
566 USAGE(1, PID_USAGE_SET_PERIODIC_REPORT
),
567 COLLECTION(1, Logical
),
568 REPORT_ID(1, report_id
),
570 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX
),
571 LOGICAL_MINIMUM(1, 0),
572 LOGICAL_MAXIMUM(1, 0x7f),
575 OUTPUT(1, Data
|Var
|Abs
),
577 USAGE(1, PID_USAGE_MAGNITUDE
),
578 LOGICAL_MINIMUM(1, 0),
579 LOGICAL_MAXIMUM(2, 0x7fff),
580 PHYSICAL_MINIMUM(1, 0),
581 PHYSICAL_MAXIMUM(2, 10000),
584 OUTPUT(1, Data
|Var
|Abs
),
585 PHYSICAL_MINIMUM(1, 0),
586 PHYSICAL_MAXIMUM(1, 0),
588 USAGE(1, PID_USAGE_OFFSET
),
589 LOGICAL_MINIMUM(2, 0x8000),
590 LOGICAL_MAXIMUM(2, 0x7fff),
591 PHYSICAL_MINIMUM(2, -10000),
592 PHYSICAL_MAXIMUM(2, +10000),
595 OUTPUT(1, Data
|Var
|Abs
),
596 PHYSICAL_MINIMUM(1, 0),
597 PHYSICAL_MAXIMUM(1, 0),
599 USAGE(1, PID_USAGE_PHASE
),
600 UNIT(1, 0x14), /* Eng Rot:Angular Pos */
601 UNIT_EXPONENT(1, -2),
602 LOGICAL_MINIMUM(1, 0),
603 LOGICAL_MAXIMUM(4, 36000),
606 OUTPUT(1, Data
|Var
|Abs
),
608 USAGE(1, PID_USAGE_PERIOD
),
609 UNIT(2, 0x1003), /* Eng Lin:Time */
610 UNIT_EXPONENT(1, -3), /* 10^-3 */
611 LOGICAL_MINIMUM(1, 0),
612 LOGICAL_MAXIMUM(2, 0x7fff),
615 OUTPUT(1, Data
|Var
|Abs
),
618 UNIT(1, 0), /* None */
622 iface
->hid_physical
.set_periodic_report
= report_id
;
623 return hid_report_descriptor_append(desc
, template, sizeof(template));
626 static BOOL
hid_descriptor_add_set_envelope(struct unix_device
*iface
)
628 struct hid_report_descriptor
*desc
= &iface
->hid_report_descriptor
;
629 const BYTE report_id
= ++desc
->next_report_id
[HidP_Output
];
630 const BYTE
template[] =
632 /* Envelope Report Definition */
633 USAGE(1, PID_USAGE_SET_ENVELOPE_REPORT
),
634 COLLECTION(1, Logical
),
635 REPORT_ID(1, report_id
),
637 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX
),
638 LOGICAL_MINIMUM(1, 0),
639 LOGICAL_MAXIMUM(1, 0x7f),
642 OUTPUT(1, Data
|Var
|Abs
),
644 USAGE(1, PID_USAGE_ATTACK_LEVEL
),
645 USAGE(1, PID_USAGE_FADE_LEVEL
),
646 LOGICAL_MINIMUM(1, 0),
647 LOGICAL_MAXIMUM(2, 0x7fff),
648 PHYSICAL_MINIMUM(1, 0),
649 PHYSICAL_MAXIMUM(2, 10000),
652 OUTPUT(1, Data
|Var
|Abs
),
653 PHYSICAL_MINIMUM(1, 0),
654 PHYSICAL_MAXIMUM(1, 0),
656 USAGE(1, PID_USAGE_ATTACK_TIME
),
657 USAGE(1, PID_USAGE_FADE_TIME
),
658 UNIT(2, 0x1003), /* Eng Lin:Time */
659 UNIT_EXPONENT(1, -3),
660 LOGICAL_MINIMUM(1, 0),
661 LOGICAL_MAXIMUM(2, 0x7fff),
664 OUTPUT(1, Data
|Var
|Abs
),
665 PHYSICAL_MAXIMUM(1, 0),
671 iface
->hid_physical
.set_envelope_report
= report_id
;
672 return hid_report_descriptor_append(desc
, template, sizeof(template));
675 static BOOL
hid_descriptor_add_set_condition(struct unix_device
*iface
)
677 struct hid_report_descriptor
*desc
= &iface
->hid_report_descriptor
;
678 const BYTE report_id
= ++desc
->next_report_id
[HidP_Output
];
679 const BYTE
template[] =
681 /* Condition Report Definition */
682 USAGE(1, PID_USAGE_SET_CONDITION_REPORT
),
683 COLLECTION(1, Logical
),
684 REPORT_ID(1, report_id
),
686 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX
),
687 LOGICAL_MINIMUM(1, 0),
688 LOGICAL_MAXIMUM(1, 0x7f),
691 OUTPUT(1, Data
|Var
|Abs
),
693 USAGE(1, PID_USAGE_PARAMETER_BLOCK_OFFSET
),
694 LOGICAL_MINIMUM(1, 0x00),
695 LOGICAL_MAXIMUM(1, 0x01),
698 OUTPUT(1, Data
|Var
|Abs
),
700 USAGE(1, PID_USAGE_CP_OFFSET
),
701 USAGE(1, PID_USAGE_POSITIVE_COEFFICIENT
),
702 USAGE(1, PID_USAGE_NEGATIVE_COEFFICIENT
),
703 LOGICAL_MINIMUM(2, 0x8000),
704 LOGICAL_MAXIMUM(2, 0x7fff),
705 PHYSICAL_MINIMUM(2, -10000),
706 PHYSICAL_MAXIMUM(2, +10000),
709 OUTPUT(1, Data
|Var
|Abs
),
710 PHYSICAL_MINIMUM(1, 0),
711 PHYSICAL_MAXIMUM(1, 0),
713 USAGE(1, PID_USAGE_POSITIVE_SATURATION
),
714 USAGE(1, PID_USAGE_NEGATIVE_SATURATION
),
715 USAGE(1, PID_USAGE_DEAD_BAND
),
716 LOGICAL_MINIMUM(1, 0),
717 LOGICAL_MAXIMUM(4, 0xffff),
718 PHYSICAL_MINIMUM(1, 0),
719 PHYSICAL_MAXIMUM(2, +10000),
722 OUTPUT(1, Data
|Var
|Abs
),
723 PHYSICAL_MINIMUM(1, 0),
724 PHYSICAL_MAXIMUM(1, 0),
728 iface
->hid_physical
.set_condition_report
= report_id
;
729 return hid_report_descriptor_append(desc
, template, sizeof(template));
732 static BOOL
hid_descriptor_add_set_constant_force(struct unix_device
*iface
)
734 struct hid_report_descriptor
*desc
= &iface
->hid_report_descriptor
;
735 const BYTE report_id
= ++desc
->next_report_id
[HidP_Output
];
736 const BYTE
template[] =
738 /* Constant Force Report Definition */
739 USAGE(1, PID_USAGE_SET_CONSTANT_FORCE_REPORT
),
740 COLLECTION(1, Logical
),
741 REPORT_ID(1, report_id
),
743 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX
),
744 LOGICAL_MINIMUM(1, 0),
745 LOGICAL_MAXIMUM(1, 0x7f),
748 OUTPUT(1, Data
|Var
|Abs
),
750 USAGE(1, PID_USAGE_MAGNITUDE
),
751 LOGICAL_MINIMUM(2, 0x8000),
752 LOGICAL_MAXIMUM(2, 0x7fff),
753 PHYSICAL_MINIMUM(2, -10000),
754 PHYSICAL_MAXIMUM(2, +10000),
757 OUTPUT(1, Data
|Var
|Abs
),
758 PHYSICAL_MINIMUM(1, 0),
759 PHYSICAL_MAXIMUM(1, 0),
763 iface
->hid_physical
.set_constant_force_report
= report_id
;
764 return hid_report_descriptor_append(desc
, template, sizeof(template));
767 static BOOL
hid_descriptor_add_set_ramp_force(struct unix_device
*iface
)
769 struct hid_report_descriptor
*desc
= &iface
->hid_report_descriptor
;
770 const BYTE report_id
= ++desc
->next_report_id
[HidP_Output
];
771 const BYTE
template[] =
773 /* Ramp Force Report Definition */
774 USAGE(1, PID_USAGE_SET_RAMP_FORCE_REPORT
),
775 COLLECTION(1, Logical
),
776 REPORT_ID(1, report_id
),
778 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX
),
779 LOGICAL_MINIMUM(1, 0),
780 LOGICAL_MAXIMUM(1, 0x7f),
783 OUTPUT(1, Data
|Var
|Abs
),
785 USAGE(1, PID_USAGE_RAMP_START
),
786 USAGE(1, PID_USAGE_RAMP_END
),
787 LOGICAL_MINIMUM(2, 0x8000),
788 LOGICAL_MAXIMUM(2, 0x7fff),
789 PHYSICAL_MINIMUM(2, -10000),
790 PHYSICAL_MAXIMUM(2, +10000),
793 OUTPUT(1, Data
|Var
|Abs
),
794 PHYSICAL_MINIMUM(1, 0),
795 PHYSICAL_MAXIMUM(1, 0),
799 iface
->hid_physical
.set_ramp_force_report
= report_id
;
800 return hid_report_descriptor_append(desc
, template, sizeof(template));
803 BOOL
hid_device_add_physical(struct unix_device
*iface
, USAGE
*usages
, USHORT count
)
805 struct hid_report_descriptor
*desc
= &iface
->hid_report_descriptor
;
806 const BYTE device_control_report
= ++desc
->next_report_id
[HidP_Output
];
807 struct hid_device_state
*state
= &iface
->hid_device_state
;
808 const BYTE device_control_header
[] =
810 USAGE_PAGE(1, HID_USAGE_PAGE_PID
),
811 USAGE(1, PID_USAGE_DEVICE_CONTROL_REPORT
),
812 COLLECTION(1, Logical
),
813 REPORT_ID(1, device_control_report
),
815 USAGE(1, PID_USAGE_DEVICE_CONTROL
),
816 COLLECTION(1, Logical
),
818 const BYTE device_control_footer
[] =
820 LOGICAL_MINIMUM(1, 1),
821 LOGICAL_MAXIMUM(1, 6),
824 OUTPUT(1, Data
|Ary
|Abs
),
829 const BYTE device_gain_report
= ++desc
->next_report_id
[HidP_Output
];
830 const BYTE device_gain
[] =
832 USAGE_PAGE(1, HID_USAGE_PAGE_PID
),
833 USAGE(1, PID_USAGE_DEVICE_GAIN_REPORT
),
834 COLLECTION(1, Logical
),
835 REPORT_ID(1, device_gain_report
),
837 USAGE(1, PID_USAGE_DEVICE_GAIN
),
838 LOGICAL_MINIMUM(1, 0),
839 LOGICAL_MAXIMUM(1, 100),
840 PHYSICAL_MINIMUM(1, 0),
841 PHYSICAL_MAXIMUM(2, 10000),
844 OUTPUT(1, Data
|Var
|Abs
),
845 PHYSICAL_MINIMUM(1, 0),
846 PHYSICAL_MAXIMUM(1, 0),
850 const BYTE effect_control_report
= ++desc
->next_report_id
[HidP_Output
];
851 const BYTE effect_control_header
[] =
853 /* Control effect state */
854 USAGE(1, PID_USAGE_EFFECT_OPERATION_REPORT
),
855 COLLECTION(1, Logical
),
856 REPORT_ID(1, effect_control_report
),
858 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX
),
859 LOGICAL_MINIMUM(1, 0),
860 LOGICAL_MAXIMUM(1, 0x7f),
863 OUTPUT(1, Data
|Var
|Abs
),
865 USAGE(1, PID_USAGE_EFFECT_OPERATION
),
866 COLLECTION(1, Logical
),
868 const BYTE effect_control_footer
[] =
870 LOGICAL_MINIMUM(1, 1),
871 LOGICAL_MAXIMUM(1, 3),
874 OUTPUT(1, Data
|Ary
|Abs
),
877 USAGE(1, PID_USAGE_LOOP_COUNT
),
878 LOGICAL_MINIMUM(1, 0),
879 LOGICAL_MAXIMUM(2, 0x00ff),
882 OUTPUT(1, Data
|Var
|Abs
),
886 const BYTE effect_update_report
= ++desc
->next_report_id
[HidP_Output
];
887 const BYTE effect_update_header
[] =
889 /* Set effect properties */
890 USAGE(1, PID_USAGE_SET_EFFECT_REPORT
),
891 COLLECTION(1, Logical
),
892 REPORT_ID(1, effect_update_report
),
894 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX
),
895 LOGICAL_MINIMUM(1, 0),
896 LOGICAL_MAXIMUM(1, 0x7f),
899 OUTPUT(1, Data
|Var
|Abs
),
901 USAGE(1, PID_USAGE_EFFECT_TYPE
),
902 COLLECTION(1, Logical
),
904 const BYTE effect_update_footer
[] =
906 LOGICAL_MINIMUM(1, 1),
907 LOGICAL_MAXIMUM(1, count
),
909 OUTPUT(1, Data
|Ary
|Abs
),
912 USAGE(1, PID_USAGE_DURATION
),
913 USAGE(1, PID_USAGE_TRIGGER_REPEAT_INTERVAL
),
914 USAGE(1, PID_USAGE_SAMPLE_PERIOD
),
915 USAGE(1, PID_USAGE_START_DELAY
),
916 UNIT(2, 0x1003), /* Eng Lin:Time */
917 UNIT_EXPONENT(1, -3), /* 10^-3 */
918 LOGICAL_MINIMUM(1, 0),
919 LOGICAL_MAXIMUM(2, 0x7fff),
922 OUTPUT(1, Data
|Var
|Abs
),
924 UNIT(1, 0), /* None */
926 USAGE(1, PID_USAGE_GAIN
),
927 LOGICAL_MINIMUM(1, 0),
928 LOGICAL_MAXIMUM(1, 100),
931 OUTPUT(1, Data
|Var
|Abs
|Null
),
933 USAGE(1, PID_USAGE_TRIGGER_BUTTON
),
934 LOGICAL_MINIMUM(1, 0),
935 LOGICAL_MAXIMUM(2, state
->button_count
),
938 OUTPUT(1, Data
|Var
|Abs
|Null
),
940 USAGE(1, PID_USAGE_AXES_ENABLE
),
941 COLLECTION(1, Logical
),
942 USAGE(4, (state
->abs_axis_usages
[0].UsagePage
<<16)|state
->abs_axis_usages
[0].Usage
),
943 USAGE(4, (state
->abs_axis_usages
[1].UsagePage
<<16)|state
->abs_axis_usages
[1].Usage
),
944 LOGICAL_MINIMUM(1, 0),
945 LOGICAL_MAXIMUM(1, 1),
948 OUTPUT(1, Data
|Var
|Abs
),
950 USAGE(1, PID_USAGE_DIRECTION_ENABLE
),
952 OUTPUT(1, Data
|Var
|Abs
),
954 OUTPUT(1, Cnst
|Var
|Abs
), /* 5-bit pad */
956 USAGE(1, PID_USAGE_DIRECTION
),
957 COLLECTION(1, Logical
),
958 USAGE(4, (HID_USAGE_PAGE_ORDINAL
<<16)|1),
959 USAGE(4, (HID_USAGE_PAGE_ORDINAL
<<16)|2),
960 UNIT(1, 0x14), /* Eng Rot:Angular Pos */
961 UNIT_EXPONENT(1, -2),
962 LOGICAL_MINIMUM(1, 0),
963 LOGICAL_MAXIMUM(4, 36000),
966 OUTPUT(1, Data
|Var
|Abs
),
969 UNIT(1, 0), /* None */
973 const BYTE effect_state_report
= ++desc
->next_report_id
[HidP_Input
];
974 const BYTE effect_state_template
[] =
976 /* Report effect state */
977 USAGE(1, PID_USAGE_STATE_REPORT
),
978 COLLECTION(1, Logical
),
979 REPORT_ID(1, effect_state_report
),
981 USAGE(1, PID_USAGE_DEVICE_PAUSED
),
982 USAGE(1, PID_USAGE_ACTUATORS_ENABLED
),
983 USAGE(1, PID_USAGE_EFFECT_PLAYING
),
984 LOGICAL_MINIMUM(1, 0),
985 LOGICAL_MAXIMUM(1, 1),
988 INPUT(1, Data
|Var
|Abs
),
990 USAGE(1, PID_USAGE_EFFECT_BLOCK_INDEX
),
991 LOGICAL_MINIMUM(1, 0),
992 LOGICAL_MAXIMUM(1, 0x7f),
995 INPUT(1, Data
|Var
|Abs
),
998 struct hid_effect_state
*effect_state
= &iface
->hid_physical
.effect_state
;
999 BOOL periodic
= FALSE
;
1000 BOOL envelope
= FALSE
;
1001 BOOL condition
= FALSE
;
1002 BOOL constant_force
= FALSE
;
1003 BOOL ramp_force
= FALSE
;
1006 if (!hid_report_descriptor_append(desc
, device_control_header
, sizeof(device_control_header
)))
1008 for (i
= 1; i
< ARRAY_SIZE(pid_device_control_usages
); ++i
)
1010 if (!hid_report_descriptor_append_usage(desc
, pid_device_control_usages
[i
]))
1013 if (!hid_report_descriptor_append(desc
, device_control_footer
, sizeof(device_control_footer
)))
1016 if (!hid_report_descriptor_append(desc
, device_gain
, sizeof(device_gain
)))
1019 if (!hid_report_descriptor_append(desc
, effect_control_header
, sizeof(effect_control_header
)))
1021 for (i
= 1; i
< ARRAY_SIZE(pid_effect_control_usages
); ++i
)
1023 if (!hid_report_descriptor_append_usage(desc
, pid_effect_control_usages
[i
]))
1026 if (!hid_report_descriptor_append(desc
, effect_control_footer
, sizeof(effect_control_footer
)))
1029 if (!hid_report_descriptor_append(desc
, effect_update_header
, sizeof(effect_update_header
)))
1031 for (i
= 0; i
< count
; ++i
)
1033 if (!hid_report_descriptor_append_usage(desc
, usages
[i
]))
1036 if (!hid_report_descriptor_append(desc
, effect_update_footer
, sizeof(effect_update_footer
)))
1039 for (i
= 0; i
< count
; ++i
)
1041 if (usages
[i
] == PID_USAGE_ET_SINE
||
1042 usages
[i
] == PID_USAGE_ET_SQUARE
||
1043 usages
[i
] == PID_USAGE_ET_TRIANGLE
||
1044 usages
[i
] == PID_USAGE_ET_SAWTOOTH_UP
||
1045 usages
[i
] == PID_USAGE_ET_SAWTOOTH_DOWN
)
1046 periodic
= envelope
= TRUE
;
1047 if (usages
[i
] == PID_USAGE_ET_SPRING
||
1048 usages
[i
] == PID_USAGE_ET_DAMPER
||
1049 usages
[i
] == PID_USAGE_ET_INERTIA
||
1050 usages
[i
] == PID_USAGE_ET_FRICTION
)
1052 if (usages
[i
] == PID_USAGE_ET_CONSTANT_FORCE
)
1053 envelope
= constant_force
= TRUE
;
1054 if (usages
[i
] == PID_USAGE_ET_RAMP
)
1055 envelope
= ramp_force
= TRUE
;
1058 if (periodic
&& !hid_descriptor_add_set_periodic(iface
))
1060 if (envelope
&& !hid_descriptor_add_set_envelope(iface
))
1062 if (condition
&& !hid_descriptor_add_set_condition(iface
))
1064 if (constant_force
&& !hid_descriptor_add_set_constant_force(iface
))
1066 if (ramp_force
&& !hid_descriptor_add_set_ramp_force(iface
))
1069 if (!hid_report_descriptor_append(desc
, effect_state_template
, sizeof(effect_state_template
)))
1072 /* HID nary collection indexes start at 1 */
1073 memcpy(iface
->hid_physical
.effect_types
+ 1, usages
, count
* sizeof(*usages
));
1075 iface
->hid_physical
.device_control_report
= device_control_report
;
1076 iface
->hid_physical
.device_gain_report
= device_gain_report
;
1077 iface
->hid_physical
.effect_control_report
= effect_control_report
;
1078 iface
->hid_physical
.effect_update_report
= effect_update_report
;
1080 effect_state
->id
= effect_state_report
;
1081 effect_state
->report_len
= sizeof(struct pid_effect_state
) + 1;
1082 if (!(effect_state
->report_buf
= calloc(1, effect_state
->report_len
))) return FALSE
;
1083 effect_state
->report_buf
[0] = effect_state
->id
;
1088 #include "pop_hid_macros.h"
1090 static void hid_device_destroy(struct unix_device
*iface
)
1092 iface
->hid_vtbl
->destroy(iface
);
1093 free(iface
->hid_report_descriptor
.data
);
1094 free(iface
->hid_device_state
.report_buf
);
1095 free(iface
->hid_device_state
.last_report_buf
);
1098 static NTSTATUS
hid_device_start(struct unix_device
*iface
)
1100 return iface
->hid_vtbl
->start(iface
);
1103 static void hid_device_stop(struct unix_device
*iface
)
1105 iface
->hid_vtbl
->stop(iface
);
1108 static NTSTATUS
hid_device_get_report_descriptor(struct unix_device
*iface
, BYTE
*buffer
, UINT length
, UINT
*out_length
)
1110 *out_length
= iface
->hid_report_descriptor
.size
;
1111 if (length
< iface
->hid_report_descriptor
.size
) return STATUS_BUFFER_TOO_SMALL
;
1113 memcpy(buffer
, iface
->hid_report_descriptor
.data
, iface
->hid_report_descriptor
.size
);
1114 return STATUS_SUCCESS
;
1117 static void hid_device_set_output_report(struct unix_device
*iface
, HID_XFER_PACKET
*packet
, IO_STATUS_BLOCK
*io
)
1119 struct hid_physical
*physical
= &iface
->hid_physical
;
1120 struct hid_haptics
*haptics
= &iface
->hid_haptics
;
1122 if (packet
->reportId
== haptics
->intensity_report
)
1124 struct hid_haptics_intensity
*report
= (struct hid_haptics_intensity
*)(packet
->reportBuffer
+ 1);
1127 io
->Information
= sizeof(*report
) + 1;
1128 assert(packet
->reportBufferLen
== io
->Information
);
1130 if (!report
->rumble_intensity
&& !report
->buzz_intensity
&& !report
->left_intensity
&& !report
->right_intensity
)
1131 io
->Status
= iface
->hid_vtbl
->haptics_stop(iface
);
1134 duration_ms
= min(haptics
->features
.rumble
.cutoff_time_ms
, haptics
->features
.buzz
.cutoff_time_ms
);
1135 duration_ms
= min(duration_ms
, haptics
->features
.left
.cutoff_time_ms
);
1136 duration_ms
= min(duration_ms
, haptics
->features
.right
.cutoff_time_ms
);
1137 io
->Status
= iface
->hid_vtbl
->haptics_start(iface
, duration_ms
, report
->rumble_intensity
, report
->buzz_intensity
,
1138 report
->left_intensity
, report
->right_intensity
);
1141 else if (packet
->reportId
== physical
->device_control_report
)
1143 struct pid_device_control
*report
= (struct pid_device_control
*)(packet
->reportBuffer
+ 1);
1146 io
->Information
= sizeof(*report
) + 1;
1147 if (packet
->reportBufferLen
< io
->Information
)
1148 io
->Status
= STATUS_BUFFER_TOO_SMALL
;
1149 else if (report
->control_index
>= ARRAY_SIZE(pid_device_control_usages
))
1150 io
->Status
= STATUS_INVALID_PARAMETER
;
1151 else if (!(control
= pid_device_control_usages
[report
->control_index
]))
1152 io
->Status
= STATUS_INVALID_PARAMETER
;
1155 io
->Status
= iface
->hid_vtbl
->physical_device_control(iface
, control
);
1156 if (control
== PID_USAGE_DC_DEVICE_RESET
&& io
->Status
== STATUS_SUCCESS
)
1157 memset(physical
->effect_params
, 0, sizeof(physical
->effect_params
));
1160 else if (packet
->reportId
== physical
->device_gain_report
)
1162 struct pid_device_gain
*report
= (struct pid_device_gain
*)(packet
->reportBuffer
+ 1);
1164 io
->Information
= sizeof(*report
) + 1;
1165 if (packet
->reportBufferLen
< io
->Information
)
1166 io
->Status
= STATUS_BUFFER_TOO_SMALL
;
1168 io
->Status
= iface
->hid_vtbl
->physical_device_set_gain(iface
, report
->value
);
1170 else if (packet
->reportId
== physical
->effect_control_report
)
1172 struct pid_effect_control
*report
= (struct pid_effect_control
*)(packet
->reportBuffer
+ 1);
1175 io
->Information
= sizeof(*report
) + 1;
1176 if (packet
->reportBufferLen
< io
->Information
)
1177 io
->Status
= STATUS_BUFFER_TOO_SMALL
;
1178 else if (report
->control_index
>= ARRAY_SIZE(pid_effect_control_usages
))
1179 io
->Status
= STATUS_INVALID_PARAMETER
;
1180 else if (!(control
= pid_effect_control_usages
[report
->control_index
]))
1181 io
->Status
= STATUS_INVALID_PARAMETER
;
1183 io
->Status
= iface
->hid_vtbl
->physical_effect_control(iface
, report
->index
, control
, report
->iterations
);
1185 else if (packet
->reportId
== physical
->effect_update_report
)
1187 struct pid_effect_update
*report
= (struct pid_effect_update
*)(packet
->reportBuffer
+ 1);
1188 struct effect_params
*params
= iface
->hid_physical
.effect_params
+ report
->index
;
1191 io
->Information
= sizeof(*report
) + 1;
1192 if (packet
->reportBufferLen
< io
->Information
)
1193 io
->Status
= STATUS_BUFFER_TOO_SMALL
;
1194 else if (report
->type_index
>= ARRAY_SIZE(iface
->hid_physical
.effect_types
))
1195 io
->Status
= STATUS_INVALID_PARAMETER
;
1196 else if (!(effect_type
= iface
->hid_physical
.effect_types
[report
->type_index
]))
1197 io
->Status
= STATUS_INVALID_PARAMETER
;
1200 params
->effect_type
= effect_type
;
1201 params
->duration
= report
->duration
;
1202 params
->trigger_repeat_interval
= report
->trigger_repeat_interval
;
1203 params
->sample_period
= report
->sample_period
;
1204 params
->start_delay
= report
->start_delay
;
1205 params
->gain_percent
= report
->gain_percent
;
1206 params
->trigger_button
= report
->trigger_button
== 0xff ? 0 : report
->trigger_button
;
1207 params
->axis_enabled
[0] = (report
->enable_bits
& 1) != 0;
1208 params
->axis_enabled
[1] = (report
->enable_bits
& 2) != 0;
1209 params
->direction_enabled
= (report
->enable_bits
& 4) != 0;
1210 params
->direction
[0] = report
->direction
[0];
1211 params
->direction
[1] = report
->direction
[1];
1213 io
->Status
= iface
->hid_vtbl
->physical_effect_update(iface
, report
->index
, params
);
1216 else if (packet
->reportId
== physical
->set_periodic_report
)
1218 struct pid_set_periodic
*report
= (struct pid_set_periodic
*)(packet
->reportBuffer
+ 1);
1219 struct effect_params
*params
= iface
->hid_physical
.effect_params
+ report
->index
;
1221 io
->Information
= sizeof(*report
) + 1;
1222 if (packet
->reportBufferLen
< io
->Information
)
1223 io
->Status
= STATUS_BUFFER_TOO_SMALL
;
1226 params
->periodic
.magnitude
= report
->magnitude
;
1227 params
->periodic
.offset
= report
->offset
;
1228 params
->periodic
.phase
= report
->phase
;
1229 params
->periodic
.period
= report
->period
;
1231 io
->Status
= iface
->hid_vtbl
->physical_effect_update(iface
, report
->index
, params
);
1234 else if (packet
->reportId
== physical
->set_envelope_report
)
1236 struct pid_set_envelope
*report
= (struct pid_set_envelope
*)(packet
->reportBuffer
+ 1);
1237 struct effect_params
*params
= iface
->hid_physical
.effect_params
+ report
->index
;
1239 io
->Information
= sizeof(*report
) + 1;
1240 if (packet
->reportBufferLen
< io
->Information
)
1241 io
->Status
= STATUS_BUFFER_TOO_SMALL
;
1244 params
->envelope
.attack_level
= report
->attack_level
;
1245 params
->envelope
.fade_level
= report
->fade_level
;
1246 params
->envelope
.attack_time
= report
->attack_time
;
1247 params
->envelope
.fade_time
= report
->fade_time
;
1249 io
->Status
= iface
->hid_vtbl
->physical_effect_update(iface
, report
->index
, params
);
1252 else if (packet
->reportId
== physical
->set_condition_report
)
1254 struct pid_set_condition
*report
= (struct pid_set_condition
*)(packet
->reportBuffer
+ 1);
1255 struct effect_params
*params
= iface
->hid_physical
.effect_params
+ report
->index
;
1256 struct effect_condition
*condition
;
1259 io
->Information
= sizeof(*report
) + 1;
1260 if (packet
->reportBufferLen
< io
->Information
)
1261 io
->Status
= STATUS_BUFFER_TOO_SMALL
;
1262 else if ((index
= report
->condition_index
) >= ARRAY_SIZE(params
->condition
))
1263 io
->Status
= STATUS_INVALID_PARAMETER
;
1266 if (params
->condition_count
<= index
) params
->condition_count
= index
+ 1;
1267 condition
= params
->condition
+ index
;
1268 condition
->center_point_offset
= report
->center_point_offset
;
1269 condition
->positive_coefficient
= report
->positive_coefficient
;
1270 condition
->negative_coefficient
= report
->negative_coefficient
;
1271 condition
->positive_saturation
= report
->positive_saturation
;
1272 condition
->negative_saturation
= report
->negative_saturation
;
1273 condition
->dead_band
= report
->dead_band
;
1275 io
->Status
= iface
->hid_vtbl
->physical_effect_update(iface
, report
->index
, params
);
1278 else if (packet
->reportId
== physical
->set_constant_force_report
)
1280 struct pid_set_constant_force
*report
= (struct pid_set_constant_force
*)(packet
->reportBuffer
+ 1);
1281 struct effect_params
*params
= iface
->hid_physical
.effect_params
+ report
->index
;
1283 io
->Information
= sizeof(*report
) + 1;
1284 if (packet
->reportBufferLen
< io
->Information
)
1285 io
->Status
= STATUS_BUFFER_TOO_SMALL
;
1288 params
->constant_force
.magnitude
= report
->magnitude
;
1290 io
->Status
= iface
->hid_vtbl
->physical_effect_update(iface
, report
->index
, params
);
1293 else if (packet
->reportId
== physical
->set_ramp_force_report
)
1295 struct pid_set_ramp_force
*report
= (struct pid_set_ramp_force
*)(packet
->reportBuffer
+ 1);
1296 struct effect_params
*params
= iface
->hid_physical
.effect_params
+ report
->index
;
1298 io
->Information
= sizeof(*report
) + 1;
1299 if (packet
->reportBufferLen
< io
->Information
)
1300 io
->Status
= STATUS_BUFFER_TOO_SMALL
;
1303 params
->ramp_force
.ramp_start
= report
->ramp_start
;
1304 params
->ramp_force
.ramp_end
= report
->ramp_end
;
1306 io
->Status
= iface
->hid_vtbl
->physical_effect_update(iface
, report
->index
, params
);
1311 io
->Information
= 0;
1312 io
->Status
= STATUS_NOT_IMPLEMENTED
;
1316 static void hid_device_get_feature_report(struct unix_device
*iface
, HID_XFER_PACKET
*packet
, IO_STATUS_BLOCK
*io
)
1318 struct hid_haptics
*haptics
= &iface
->hid_haptics
;
1320 if (packet
->reportId
== haptics
->features_report
)
1322 struct hid_haptics_features
*features
= (struct hid_haptics_features
*)(packet
->reportBuffer
+ 1);
1324 io
->Information
= sizeof(*features
) + 1;
1325 assert(packet
->reportBufferLen
== io
->Information
);
1327 *features
= haptics
->features
;
1328 io
->Status
= STATUS_SUCCESS
;
1332 io
->Information
= 0;
1333 io
->Status
= STATUS_NOT_IMPLEMENTED
;
1337 static void hid_device_set_feature_report(struct unix_device
*iface
, HID_XFER_PACKET
*packet
, IO_STATUS_BLOCK
*io
)
1339 struct hid_haptics
*haptics
= &iface
->hid_haptics
;
1341 if (packet
->reportId
== haptics
->features_report
)
1343 struct hid_haptics_features
*features
= (struct hid_haptics_features
*)(packet
->reportBuffer
+ 1);
1345 io
->Information
= sizeof(*features
) + 1;
1346 assert(packet
->reportBufferLen
== io
->Information
);
1348 haptics
->features
.rumble
.cutoff_time_ms
= features
->rumble
.cutoff_time_ms
;
1349 haptics
->features
.buzz
.cutoff_time_ms
= features
->buzz
.cutoff_time_ms
;
1350 haptics
->features
.left
.cutoff_time_ms
= features
->left
.cutoff_time_ms
;
1351 haptics
->features
.right
.cutoff_time_ms
= features
->right
.cutoff_time_ms
;
1352 io
->Status
= STATUS_SUCCESS
;
1356 io
->Information
= 0;
1357 io
->Status
= STATUS_NOT_IMPLEMENTED
;
1361 static const struct raw_device_vtbl raw_device_vtbl
=
1366 hid_device_get_report_descriptor
,
1367 hid_device_set_output_report
,
1368 hid_device_get_feature_report
,
1369 hid_device_set_feature_report
,
1372 void *hid_device_create(const struct hid_device_vtbl
*vtbl
, SIZE_T size
)
1374 struct unix_device
*impl
;
1376 if (!(impl
= raw_device_create(&raw_device_vtbl
, size
))) return NULL
;
1377 impl
->hid_vtbl
= vtbl
;
1382 #ifdef WORDS_BIGENDIAN
1383 # define LE_ULONG(x) RtlUlongByteSwap((ULONG)(x))
1385 # define LE_ULONG(x) ((ULONG)(x))
1388 BOOL
hid_device_set_abs_axis(struct unix_device
*iface
, ULONG index
, LONG value
)
1390 struct hid_device_state
*state
= &iface
->hid_device_state
;
1391 ULONG offset
= state
->abs_axis_start
+ index
* 4;
1392 if (index
>= state
->abs_axis_count
) return FALSE
;
1393 *(ULONG
*)(state
->report_buf
+ offset
) = LE_ULONG(value
);
1397 BOOL
hid_device_set_rel_axis(struct unix_device
*iface
, ULONG index
, LONG value
)
1399 struct hid_device_state
*state
= &iface
->hid_device_state
;
1400 ULONG offset
= state
->rel_axis_start
+ index
* 4;
1401 if (index
>= state
->rel_axis_count
) return FALSE
;
1402 *(ULONG
*)(state
->report_buf
+ offset
) = LE_ULONG(value
);
1406 BOOL
hid_device_set_button(struct unix_device
*iface
, ULONG index
, BOOL is_set
)
1408 struct hid_device_state
*state
= &iface
->hid_device_state
;
1409 ULONG offset
= state
->button_start
+ (index
/ 8);
1410 BYTE mask
= (1 << (index
% 8));
1411 if (index
>= state
->button_count
) return FALSE
;
1412 if (is_set
) state
->report_buf
[offset
] |= mask
;
1413 else state
->report_buf
[offset
] &= ~mask
;
1417 /* hatswitch x / y vs value:
1425 static void hatswitch_decompose(BYTE value
, ULONG index
, LONG
*x
, LONG
*y
)
1427 value
= (index
% 2) ? (value
>> 4) : (value
& 0x0f);
1429 if (value
== 8 || value
== 1 || value
== 2) *y
= -1;
1430 if (value
== 6 || value
== 5 || value
== 4) *y
= +1;
1431 if (value
== 8 || value
== 7 || value
== 6) *x
= -1;
1432 if (value
== 2 || value
== 3 || value
== 4) *x
= +1;
1435 static void hatswitch_compose(LONG x
, LONG y
, BYTE
*value
, ULONG index
)
1438 if (x
== 0 && y
== 0) new_value
= 0;
1439 else if (x
== 0 && y
< 0) new_value
= 1;
1440 else if (x
> 0 && y
< 0) new_value
= 2;
1441 else if (x
> 0 && y
== 0) new_value
= 3;
1442 else if (x
> 0 && y
> 0) new_value
= 4;
1443 else if (x
== 0 && y
> 0) new_value
= 5;
1444 else if (x
< 0 && y
> 0) new_value
= 6;
1445 else if (x
< 0 && y
== 0) new_value
= 7;
1446 else if (x
< 0 && y
< 0) new_value
= 8;
1451 *value
|= new_value
<< 4;
1456 *value
|= new_value
;
1460 BOOL
hid_device_set_hatswitch_x(struct unix_device
*iface
, ULONG index
, LONG new_x
)
1462 struct hid_device_state
*state
= &iface
->hid_device_state
;
1463 ULONG offset
= state
->hatswitch_start
+ index
/ 2;
1465 if (index
> state
->hatswitch_count
) return FALSE
;
1466 hatswitch_decompose(state
->report_buf
[offset
], index
, &x
, &y
);
1467 hatswitch_compose(new_x
, y
, &state
->report_buf
[offset
], index
);
1471 BOOL
hid_device_set_hatswitch_y(struct unix_device
*iface
, ULONG index
, LONG new_y
)
1473 struct hid_device_state
*state
= &iface
->hid_device_state
;
1474 ULONG offset
= state
->hatswitch_start
+ index
/ 2;
1476 if (index
> state
->hatswitch_count
) return FALSE
;
1477 hatswitch_decompose(state
->report_buf
[offset
], index
, &x
, &y
);
1478 hatswitch_compose(x
, new_y
, &state
->report_buf
[offset
], index
);
1482 BOOL
hid_device_move_hatswitch(struct unix_device
*iface
, ULONG index
, LONG x
, LONG y
)
1484 struct hid_device_state
*state
= &iface
->hid_device_state
;
1485 ULONG offset
= state
->hatswitch_start
+ index
/ 2;
1487 if (index
> state
->hatswitch_count
) return FALSE
;
1488 hatswitch_decompose(state
->report_buf
[offset
], index
, &old_x
, &old_y
);
1489 hatswitch_compose(old_x
+ x
, old_y
+ y
, &state
->report_buf
[offset
], index
);
1493 BOOL
hid_device_sync_report(struct unix_device
*iface
)
1497 if (!(dropped
= iface
->hid_device_state
.dropped
))
1498 memcpy(iface
->hid_device_state
.last_report_buf
, iface
->hid_device_state
.report_buf
,
1499 iface
->hid_device_state
.report_len
);
1501 memcpy(iface
->hid_device_state
.report_buf
, iface
->hid_device_state
.last_report_buf
,
1502 iface
->hid_device_state
.report_len
);
1503 iface
->hid_device_state
.dropped
= FALSE
;
1508 void hid_device_drop_report(struct unix_device
*iface
)
1510 iface
->hid_device_state
.dropped
= TRUE
;
1513 void hid_device_set_effect_state(struct unix_device
*iface
, BYTE index
, BYTE flags
)
1515 struct hid_effect_state
*state
= &iface
->hid_physical
.effect_state
;
1516 struct pid_effect_state
*report
= (struct pid_effect_state
*)(state
->report_buf
+ 1);
1517 report
->index
= index
;
1518 report
->flags
= flags
;