/* Filled in by udev-hid-bpf */ char UDEV_PROP_HUION_FIRMWARE_ID[64];
/* The prefix of the firmware ID we expect for this device. The full firmware * string has a date suffix, e.g. HUION_T21j_221221
*/ char EXPECTED_FIRMWARE_ID[] = "HUION_T216_";
staticconst __u8 fixed_rdesc_pad[] = {
UsagePage_GenericDesktop
Usage_GD_Keypad
CollectionApplication( // -- Byte 0 in report
ReportId(PAD_REPORT_ID)
LogicalMaximum_i8(0)
LogicalMaximum_i8(1)
UsagePage_Digitizers
Usage_Dig_TabletFunctionKeys
CollectionPhysical( // Byte 1 in report - just exists so we get to be a tablet pad
Usage_Dig_BarrelSwitch // BTN_STYLUS
ReportCount(1)
ReportSize(1)
Input(Var|Abs)
ReportCount(7) // padding
Input(Const) // Bytes 2/3 in report - just exists so we get to be a tablet pad
UsagePage_GenericDesktop
Usage_GD_X
Usage_GD_Y
ReportCount(2)
ReportSize(8)
Input(Var|Abs) // Byte 4 in report is the dial
Usage_GD_Wheel
LogicalMinimum_i8(-1)
LogicalMaximum_i8(1)
ReportCount(1)
ReportSize(8)
Input(Var|Rel) // Byte 5 is the button state
UsagePage_Button
UsageMinimum_i8(0x01)
UsageMaximum_i8(0x08)
LogicalMinimum_i8(0x0)
LogicalMaximum_i8(0x1)
ReportCount(7)
ReportSize(1)
Input(Var|Abs)
ReportCount(1) // padding
Input(Const)
) // Make sure we match our original report length
FixedSizeVendorReport(PAD_REPORT_LENGTH)
)
};
staticconst __u8 fixed_rdesc_vendor[] = {
UsagePage_Digitizers
Usage_Dig_Pen
CollectionApplication( // Byte 0 // We leave the pen on the vendor report ID
ReportId(VENDOR_REPORT_ID)
Usage_Dig_Pen
CollectionPhysical( // Byte 1 are the buttons
LogicalMinimum_i8(0)
LogicalMaximum_i8(1)
ReportSize(1)
Usage_Dig_TipSwitch
Usage_Dig_BarrelSwitch
Usage_Dig_SecondaryBarrelSwitch
ReportCount(3)
Input(Var|Abs)
ReportCount(4) // Padding
Input(Const)
Usage_Dig_InRange
ReportCount(1)
Input(Var|Abs)
ReportSize(16)
ReportCount(1)
PushPop(
UsagePage_GenericDesktop
Unit(cm)
UnitExponent(-1) // Note: reported logical range differs // from the pen report ID for x and y
LogicalMinimum_i16(0)
LogicalMaximum_i16(53340)
PhysicalMinimum_i16(0)
PhysicalMaximum_i16(266) // Bytes 2/3 in report
Usage_GD_X
Input(Var|Abs)
LogicalMinimum_i16(0)
LogicalMaximum_i16(33340)
PhysicalMinimum_i16(0)
PhysicalMaximum_i16(166) // Bytes 4/5 in report
Usage_GD_Y
Input(Var|Abs)
) // Bytes 6/7 in report
LogicalMinimum_i16(0)
LogicalMaximum_i16(8191)
Usage_Dig_TipPressure
Input(Var|Abs) // Bytes 8/9 in report
ReportCount(1) // Padding
Input(Const)
LogicalMinimum_i8(-60)
LogicalMaximum_i8(60) // Byte 10 in report
Usage_Dig_XTilt // Byte 11 in report
Usage_Dig_YTilt
ReportSize(8)
ReportCount(2)
Input(Var|Abs)
)
)
UsagePage_GenericDesktop
Usage_GD_Keypad
CollectionApplication( // Byte 0
ReportId(PAD_REPORT_ID)
LogicalMinimum_i8(0)
LogicalMaximum_i8(1)
UsagePage_Digitizers
Usage_Dig_TabletFunctionKeys
CollectionPhysical( // Byte 1 are the buttons
Usage_Dig_BarrelSwitch // BTN_STYLUS, needed so we get to be a tablet pad
ReportCount(1)
ReportSize(1)
Input(Var|Abs)
ReportCount(7) // Padding
Input(Const) // Bytes 2/3 - x/y just exist so we get to be a tablet pad
UsagePage_GenericDesktop
Usage_GD_X
Usage_GD_Y
ReportCount(2)
ReportSize(8)
Input(Var|Abs) // Byte 4 is the button state
UsagePage_Button
UsageMinimum_i8(0x1)
UsageMaximum_i8(0x8)
LogicalMinimum_i8(0x0)
LogicalMaximum_i8(0x1)
ReportCount(8)
ReportSize(1)
Input(Var|Abs) // Byte 5 is the top dial
UsagePage_GenericDesktop
Usage_GD_Wheel
LogicalMinimum_i8(-1)
LogicalMaximum_i8(1)
ReportCount(1)
ReportSize(8)
Input(Var|Rel) // Byte 6 is the bottom dial
UsagePage_Consumer
Usage_Con_ACPan
Input(Var|Rel)
) // Make sure we match our original report length
FixedSizeVendorReport(VENDOR_REPORT_LENGTH)
)
};
/* If we have a firmware ID and it matches our expected prefix, we * disable the default pad/pen nodes. They won't send events * but cause duplicate devices.
*/
have_fw_id = __builtin_memcmp(UDEV_PROP_HUION_FIRMWARE_ID,
EXPECTED_FIRMWARE_ID, sizeof(EXPECTED_FIRMWARE_ID) - 1) == 0; if (rdesc_size == PAD_REPORT_DESCRIPTOR_LENGTH) { if (have_fw_id) {
__builtin_memcpy(data, disabled_rdesc_pad, sizeof(disabled_rdesc_pad)); returnsizeof(disabled_rdesc_pad);
}
__builtin_memcpy(data, fixed_rdesc_pad, sizeof(fixed_rdesc_pad)); returnsizeof(fixed_rdesc_pad);
} if (rdesc_size == PEN_REPORT_DESCRIPTOR_LENGTH) { if (have_fw_id) {
__builtin_memcpy(data, disabled_rdesc_pen, sizeof(disabled_rdesc_pen)); returnsizeof(disabled_rdesc_pen);
}
__builtin_memcpy(data, fixed_rdesc_pen, sizeof(fixed_rdesc_pen)); returnsizeof(fixed_rdesc_pen);
} /* Always fix the vendor mode so the tablet will work even if nothing sets * the udev property (e.g. huion-switcher run manually)
*/ if (rdesc_size == VENDOR_REPORT_DESCRIPTOR_LENGTH) {
__builtin_memcpy(data, fixed_rdesc_vendor, sizeof(fixed_rdesc_vendor)); returnsizeof(fixed_rdesc_vendor);
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.