static void quanta_remove(struct hid_device *hdev) { hid_hw_stop(hdev); kfree(hid_get_drvdata(hdev)); hid_set_drvdata(hdev, NULL); }
/* * this function is called upon all reports * so that we can filter contact point information, * decide whether we are in multi or single touch mode * and call input_mt_sync after each point if necessary */ static int ntrig_event (struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value) { struct input_dev *input = field->hidinput->input; struct ntrig_data *nd = hid_get_drvdata(hid); if (hid->claimed & HID_CLAIMED_INPUT) { switch (usage->hid) { case HID_GD_X: nd->x = value; nd->reading_a_point = 1; break; case HID_GD_Y: nd->y = value; break; case HID_DG_CONTACTID: nd->id = value; /* we receive this only when in multitouch mode */ nd->found_contact_id = 1; break; case HID_DG_WIDTH: nd->w = value; break; case HID_DG_HEIGHT: nd->h = value; /* * when in single touch mode, this is the last * report received in a finger event. We want * to emit a normal (X, Y) position */ if (! nd->found_contact_id) { input_event(input, EV_ABS, ABS_X, nd->x); input_event(input, EV_ABS, ABS_Y, nd->y); } break; case HID_DG_TIPPRESSURE: /* * when in single touch mode, this is the last * report received in a pen event. We want * to emit a normal (X, Y) position */ if (! nd->found_contact_id) { input_event(input, EV_ABS, ABS_X, nd->x); input_event(input, EV_ABS, ABS_Y, nd->y); input_event(input, EV_ABS, ABS_PRESSURE, value); } break; case 0xff000002: /* * we receive this when the device is in multitouch * mode. The first of the three values tagged with * this usage tells if the contact point is real * or a placeholder */ if (!nd->reading_a_point || value != 1) break; /* emit a normal (X, Y) for the first point only */ if (nd->id == 0) { input_event(input, EV_ABS, ABS_X, nd->x); input_event(input, EV_ABS, ABS_Y, nd->y); } input_event(input, EV_ABS, ABS_MT_POSITION_X, nd->x); input_event(input, EV_ABS, ABS_MT_POSITION_Y, nd->y); if (nd->w > nd->h) { input_event(input, EV_ABS, ABS_MT_ORIENTATION, 1); input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, nd->w); input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, nd->h); } else { input_event(input, EV_ABS, ABS_MT_ORIENTATION, 0); input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, nd->h); input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, nd->w); } input_mt_sync(field->hidinput->input); nd->reading_a_point = 0; nd->found_contact_id = 0; break; default: /* fallback to the generic hidinput handling */ return 0; } } /* we have handled the hidinput part, now remains hiddev */ if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event) hid->hiddev_hid_event(hid, field, usage, value); return 1; }
static void apple_remove(struct hid_device *hdev) { hid_hw_stop(hdev); kfree(hid_get_drvdata(hdev)); }
static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, struct hid_usage *usage, __s32 value) { struct apple_sc *asc = hid_get_drvdata(hid); const struct apple_key_translation *trans, *table; if (usage->code == KEY_FN) { asc->fn_on = !!value; input_event(input, usage->type, usage->code, value); return 1; } if (fnmode) { int do_translate; if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING4_ANSI && hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) table = macbookair_fn_keys; else if (hid->product >= USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI && hid->product <= USB_DEVICE_ID_APPLE_WELLSPRING6_JIS) table = macbookair_fn_keys; else if (hid->product < 0x21d || hid->product >= 0x300) table = powerbook_fn_keys; else table = apple_fn_keys; trans = apple_find_translation (table, usage->code); if (trans) { if (test_bit(usage->code, asc->pressed_fn)) do_translate = 1; else if (trans->flags & APPLE_FLAG_FKEY) do_translate = (fnmode == 2 && asc->fn_on) || (fnmode == 1 && !asc->fn_on); else do_translate = asc->fn_on; if (do_translate) { if (value) set_bit(usage->code, asc->pressed_fn); else clear_bit(usage->code, asc->pressed_fn); input_event(input, usage->type, trans->to, value); return 1; } } if (asc->quirks & APPLE_NUMLOCK_EMULATION && (test_bit(usage->code, asc->pressed_numlock) || test_bit(LED_NUML, input->led))) { trans = apple_find_translation(powerbook_numlock_keys, usage->code); if (trans) { if (value) set_bit(usage->code, asc->pressed_numlock); else clear_bit(usage->code, asc->pressed_numlock); input_event(input, usage->type, trans->to, value); } return 1; } } if (iso_layout) { if (asc->quirks & APPLE_ISO_KEYBOARD) { trans = apple_find_translation(apple_iso_keyboard, usage->code); if (trans) { input_event(input, usage->type, trans->to, value); return 1; } } } return 0; }
static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { struct mt_device *td = hid_get_drvdata(hdev); struct mt_class *cls = td->mtclass; __s32 quirks = cls->quirks; /* Only map fields from TouchScreen or TouchPad collections. * We need to ignore fields that belong to other collections * such as Mouse that might have the same GenericDesktop usages. */ if (field->application == HID_DG_TOUCHSCREEN) set_bit(INPUT_PROP_DIRECT, hi->input->propbit); else if (field->application == HID_DG_TOUCHPAD) set_bit(INPUT_PROP_POINTER, hi->input->propbit); else return 0; switch (usage->hid & HID_USAGE_PAGE) { case HID_UP_GENDESK: switch (usage->hid) { case HID_GD_X: if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) field->logical_maximum = 32760; hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_POSITION_X); set_abs(hi->input, ABS_MT_POSITION_X, field, cls->sn_move); /* touchscreen emulation */ set_abs(hi->input, ABS_X, field, cls->sn_move); if (td->last_mt_collection == usage->collection_index) { td->last_slot_field = usage->hid; td->last_field_index = field->index; } return 1; case HID_GD_Y: if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) field->logical_maximum = 32760; hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_POSITION_Y); set_abs(hi->input, ABS_MT_POSITION_Y, field, cls->sn_move); /* touchscreen emulation */ set_abs(hi->input, ABS_Y, field, cls->sn_move); if (td->last_mt_collection == usage->collection_index) { td->last_slot_field = usage->hid; td->last_field_index = field->index; } return 1; } return 0; case HID_UP_DIGITIZER: switch (usage->hid) { case HID_DG_INRANGE: if (td->last_mt_collection == usage->collection_index) { td->last_slot_field = usage->hid; td->last_field_index = field->index; } return 1; case HID_DG_CONFIDENCE: if (td->last_mt_collection == usage->collection_index) { td->last_slot_field = usage->hid; td->last_field_index = field->index; } return 1; case HID_DG_TIPSWITCH: hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); input_set_capability(hi->input, EV_KEY, BTN_TOUCH); if (td->last_mt_collection == usage->collection_index) { td->last_slot_field = usage->hid; td->last_field_index = field->index; } return 1; case HID_DG_CONTACTID: if (!td->maxcontacts) td->maxcontacts = MT_DEFAULT_MAXCONTACT; input_mt_init_slots(hi->input, td->maxcontacts); td->last_slot_field = usage->hid; td->last_field_index = field->index; td->last_mt_collection = usage->collection_index; return 1; case HID_DG_WIDTH: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MAJOR); set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, cls->sn_width); if (td->last_mt_collection == usage->collection_index) { td->last_slot_field = usage->hid; td->last_field_index = field->index; } return 1; case HID_DG_HEIGHT: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MINOR); set_abs(hi->input, ABS_MT_TOUCH_MINOR, field, cls->sn_height); input_set_abs_params(hi->input, ABS_MT_ORIENTATION, 0, 1, 0, 0); if (td->last_mt_collection == usage->collection_index) { td->last_slot_field = usage->hid; td->last_field_index = field->index; } return 1; case HID_DG_TIPPRESSURE: if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) field->logical_minimum = 0; hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_PRESSURE); set_abs(hi->input, ABS_MT_PRESSURE, field, cls->sn_pressure); /* touchscreen emulation */ set_abs(hi->input, ABS_PRESSURE, field, cls->sn_pressure); if (td->last_mt_collection == usage->collection_index) { td->last_slot_field = usage->hid; td->last_field_index = field->index; } return 1; case HID_DG_CONTACTCOUNT: if (td->last_mt_collection == usage->collection_index) td->last_field_index = field->index; return 1; case HID_DG_CONTACTMAX: /* we don't set td->last_slot_field as contactcount and * contact max are global to the report */ if (td->last_mt_collection == usage->collection_index) td->last_field_index = field->index; return -1; } /* let hid-input decide for the others */ return 0; case 0xff000000: /* we do not want to map these: no input-oriented meaning */ return -1; } return 0; }
static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { struct mt_device *td = hid_get_drvdata(hdev); struct mt_class *cls = &td->mtclass; int code; struct hid_usage *prev_usage = NULL; if (field->application == HID_DG_TOUCHSCREEN) td->mt_flags |= INPUT_MT_DIRECT; /* * Model touchscreens providing buttons as touchpads. */ if (field->application == HID_DG_TOUCHPAD || (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) td->mt_flags |= INPUT_MT_POINTER; /* Only map fields from TouchScreen or TouchPad collections. * We need to ignore fields that belong to other collections * such as Mouse that might have the same GenericDesktop usages. */ if (field->application == HID_DG_TOUCHSCREEN) set_bit(INPUT_PROP_DIRECT, hi->input->propbit); else if (field->application == HID_DG_TOUCHPAD) set_bit(INPUT_PROP_POINTER, hi->input->propbit); else return 0; if (usage->usage_index) prev_usage = &field->usage[usage->usage_index - 1]; switch (usage->hid & HID_USAGE_PAGE) { case HID_UP_GENDESK: switch (usage->hid) { case HID_GD_X: if (prev_usage && (prev_usage->hid == usage->hid)) { hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOOL_X); set_abs(hi->input, ABS_MT_TOOL_X, field, cls->sn_move); } else { hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_POSITION_X); set_abs(hi->input, ABS_MT_POSITION_X, field, cls->sn_move); } mt_store_field(usage, td, hi); return 1; case HID_GD_Y: if (prev_usage && (prev_usage->hid == usage->hid)) { hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOOL_Y); set_abs(hi->input, ABS_MT_TOOL_Y, field, cls->sn_move); } else { hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_POSITION_Y); set_abs(hi->input, ABS_MT_POSITION_Y, field, cls->sn_move); } mt_store_field(usage, td, hi); return 1; } return 0; case HID_UP_DIGITIZER: switch (usage->hid) { case HID_DG_INRANGE: if (cls->quirks & MT_QUIRK_HOVERING) { hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_DISTANCE); input_set_abs_params(hi->input, ABS_MT_DISTANCE, 0, 1, 0, 0); } mt_store_field(usage, td, hi); return 1; case HID_DG_CONFIDENCE: mt_store_field(usage, td, hi); return 1; case HID_DG_TIPSWITCH: hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); input_set_capability(hi->input, EV_KEY, BTN_TOUCH); mt_store_field(usage, td, hi); return 1; case HID_DG_CONTACTID: mt_store_field(usage, td, hi); td->touches_by_report++; td->mt_report_id = field->report->id; return 1; case HID_DG_WIDTH: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MAJOR); if (!(cls->quirks & MT_QUIRK_NO_AREA)) set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, cls->sn_width); mt_store_field(usage, td, hi); return 1; case HID_DG_HEIGHT: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MINOR); if (!(cls->quirks & MT_QUIRK_NO_AREA)) { set_abs(hi->input, ABS_MT_TOUCH_MINOR, field, cls->sn_height); input_set_abs_params(hi->input, ABS_MT_ORIENTATION, 0, 1, 0, 0); } mt_store_field(usage, td, hi); return 1; case HID_DG_TIPPRESSURE: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_PRESSURE); set_abs(hi->input, ABS_MT_PRESSURE, field, cls->sn_pressure); mt_store_field(usage, td, hi); return 1; case HID_DG_CONTACTCOUNT: /* Ignore if indexes are out of bounds. */ if (field->index >= field->report->maxfield || usage->usage_index >= field->report_count) return 1; td->cc_index = field->index; td->cc_value_index = usage->usage_index; return 1; case HID_DG_CONTACTMAX: /* we don't set td->last_slot_field as contactcount and * contact max are global to the report */ return -1; case HID_DG_TOUCH: /* Legacy devices use TIPSWITCH and not TOUCH. * Let's just ignore this field. */ return -1; } /* let hid-input decide for the others */ return 0; case HID_UP_BUTTON: code = BTN_MOUSE + ((usage->hid - 1) & HID_USAGE); hid_map_usage(hi, usage, bit, max, EV_KEY, code); input_set_capability(hi->input, EV_KEY, code); return 1; case 0xff000000: /* we do not want to map these: no input-oriented meaning */ return -1; } return 0; }
static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { struct mt_device *td = hid_get_drvdata(hdev); struct mt_class *cls = &td->mtclass; int code; /* Only map fields from TouchScreen or TouchPad collections. * We need to ignore fields that belong to other collections * such as Mouse that might have the same GenericDesktop usages. */ if (field->application == HID_DG_TOUCHSCREEN) set_bit(INPUT_PROP_DIRECT, hi->input->propbit); else if (field->application != HID_DG_TOUCHPAD) return 0; /* In case of an indirect device (touchpad), we need to add * specific BTN_TOOL_* to be handled by the synaptics xorg * driver. * We also consider that touchscreens providing buttons are touchpads. */ if (field->application == HID_DG_TOUCHPAD || (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON || cls->is_indirect) { set_bit(INPUT_PROP_POINTER, hi->input->propbit); set_bit(BTN_TOOL_FINGER, hi->input->keybit); set_bit(BTN_TOOL_DOUBLETAP, hi->input->keybit); set_bit(BTN_TOOL_TRIPLETAP, hi->input->keybit); set_bit(BTN_TOOL_QUADTAP, hi->input->keybit); } /* eGalax devices provide a Digitizer.Stylus input which overrides * the correct Digitizers.Finger X/Y ranges. * Let's just ignore this input. */ if (field->physical == HID_DG_STYLUS) return -1; /* Only map fields from TouchScreen or TouchPad collections. * We need to ignore fields that belong to other collections * such as Mouse that might have the same GenericDesktop usages. */ if (field->application == HID_DG_TOUCHSCREEN) set_bit(INPUT_PROP_DIRECT, hi->input->propbit); else if (field->application == HID_DG_TOUCHPAD) set_bit(INPUT_PROP_POINTER, hi->input->propbit); else return 0; switch (usage->hid & HID_USAGE_PAGE) { case HID_UP_GENDESK: switch (usage->hid) { case HID_GD_X: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_POSITION_X); set_abs(hi->input, ABS_MT_POSITION_X, field, cls->sn_move); /* touchscreen emulation */ set_abs(hi->input, ABS_X, field, cls->sn_move); mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_GD_Y: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_POSITION_Y); set_abs(hi->input, ABS_MT_POSITION_Y, field, cls->sn_move); /* touchscreen emulation */ set_abs(hi->input, ABS_Y, field, cls->sn_move); mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; } return 0; case HID_UP_DIGITIZER: switch (usage->hid) { case HID_DG_INRANGE: mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_CONFIDENCE: mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_TIPSWITCH: hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); input_set_capability(hi->input, EV_KEY, BTN_TOUCH); mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_CONTACTID: if (!td->maxcontacts) td->maxcontacts = MT_DEFAULT_MAXCONTACT; input_mt_init_slots(hi->input, td->maxcontacts); mt_store_field(usage, td, hi); td->last_field_index = field->index; td->touches_by_report++; return 1; case HID_DG_WIDTH: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MAJOR); set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, cls->sn_width); mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_HEIGHT: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MINOR); set_abs(hi->input, ABS_MT_TOUCH_MINOR, field, cls->sn_height); input_set_abs_params(hi->input, ABS_MT_ORIENTATION, 0, 1, 0, 0); mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_TIPPRESSURE: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_PRESSURE); set_abs(hi->input, ABS_MT_PRESSURE, field, cls->sn_pressure); /* touchscreen emulation */ set_abs(hi->input, ABS_PRESSURE, field, cls->sn_pressure); mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_CONTACTCOUNT: td->last_field_index = field->index; return 1; case HID_DG_CONTACTMAX: /* we don't set td->last_slot_field as contactcount and * contact max are global to the report */ td->last_field_index = field->index; return -1; } case HID_DG_TOUCH: /* Legacy devices use TIPSWITCH and not TOUCH. * Let's just ignore this field. */ return -1; /* let hid-input decide for the others */ return 0; case HID_UP_BUTTON: code = BTN_MOUSE + ((usage->hid - 1) & HID_USAGE); hid_map_usage(hi, usage, bit, max, EV_KEY, code); input_set_capability(hi->input, EV_KEY, code); return 1; case 0xff000000: /* we do not want to map these: no input-oriented meaning */ return -1; } return 0; }