/* * There are a few cases where the device is sending wrong event * sequences, all related to the second button (the pen doesn't * have an eraser switch on the tail end): * * whenever the second button gets pressed or released, an * out-of-proximity event is generated and then the firmware * compensate for the missing state (and the firmware uses * eraser for that button): * * - if the pen is in range, an extra out-of-range is sent * when the second button is pressed/released: * // Pen is in range * E: InRange * * // Second button is pressed * E: * E: Eraser InRange * * // Second button is released * E: * E: InRange * * This case is ignored by this filter, it's "valid" * and userspace knows how to deal with it, there are just * a few out-of-prox events generated, but the user doesn´t * see them. * * - if the pen is in contact, 2 extra events are added when * the second button is pressed/released: an out of range * and an in range: * * // Pen is in contact * E: TipSwitch InRange * * // Second button is pressed * E: <- false release, needs to be filtered out * E: Eraser InRange <- false release, needs to be filtered out * E: TipSwitch Eraser InRange * * // Second button is released * E: <- false release, needs to be filtered out * E: InRange <- false release, needs to be filtered out * E: TipSwitch InRange *
*/
SEC(HID_BPF_DEVICE_EVENT) int BPF_PROG(xppen_24_fix_eraser, struct hid_bpf_ctx *hctx)
{
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */);
__u8 current_state, changed_state; bool prev_tip;
if (!data) return 0; /* EPERM check */
current_state = data[1];
/* if the state is identical to previously, early return */ if (current_state == prev_state) return 0;
prev_tip = !!(prev_state & TIP_SWITCH);
/* * Illegal transition: pen is in range with the tip pressed, and * it goes into out of proximity. * * Ideally we should hold the event, start a timer and deliver it * only if the timer ends, but we are not capable of that now. * * And it doesn't matter because when we are in such cases, this * means we are detecting a false release.
*/ if ((current_state & IN_RANGE) == 0) { if (prev_tip) return HID_IGNORE_EVENT; return 0;
}
/* * XOR to only set the bits that have changed between * previous and current state
*/
changed_state = prev_state ^ current_state;
/* Store the new state for future processing */
prev_state = current_state;
/* * We get both a tipswitch and eraser change in the same HID report: * this is not an authorized transition and is unlikely to happen * in real life. * This is likely to be added by the firmware to emulate the * eraser mode so we can skip the event.
*/ if ((changed_state & (TIP_SWITCH | ERASER)) == (TIP_SWITCH | ERASER)) /* we get both a tipswitch and eraser change at the same time */ return HID_IGNORE_EVENT;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.