static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts, struct pixcir_report_data *report) { struct input_mt_pos pos[PIXCIR_MAX_SLOTS]; int slots[PIXCIR_MAX_SLOTS]; struct pixcir_touch *touch; int n, i, slot; struct device *dev = &ts->client->dev; const struct pixcir_i2c_chip_data *chip = &ts->pdata->chip; n = report->num_touches; if (n > PIXCIR_MAX_SLOTS) n = PIXCIR_MAX_SLOTS; if (!chip->has_hw_ids) { for (i = 0; i < n; i++) { touch = &report->touches[i]; pos[i].x = touch->x; pos[i].y = touch->y; } input_mt_assign_slots(ts->input, slots, pos, n); } for (i = 0; i < n; i++) { touch = &report->touches[i]; if (chip->has_hw_ids) { slot = input_mt_get_slot_by_key(ts->input, touch->id); if (slot < 0) { dev_dbg(dev, "no free slot for id 0x%x\n", touch->id); continue; } } else { slot = slots[i]; } input_mt_slot(ts->input, slot); input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true); input_event(ts->input, EV_ABS, ABS_MT_POSITION_X, touch->x); input_event(ts->input, EV_ABS, ABS_MT_POSITION_Y, touch->y); dev_dbg(dev, "%d: slot %d, x %d, y %d\n", i, slot, touch->x, touch->y); } input_mt_sync_frame(ts->input); input_sync(ts->input); }
static void gtp_touch_up(struct goodix_ts_data *ts, s32 id) { #if GTP_ICS_SLOT_REPORT input_mt_slot(ts->input_dev, id); input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1); input_mt_sync_frame(ts->input_dev); GTP_DEBUG("Touch id[%2d] release!", id); #else input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0); input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0); input_mt_sync(ts->input_dev); #endif }
static void silead_ts_read_data(struct i2c_client *client) { struct silead_ts_data *data = i2c_get_clientdata(client); struct device *dev = &client->dev; u8 buf[SILEAD_TS_DATA_LEN]; int x, y, id, touch_nr, ret, i, offset; ret = i2c_smbus_read_i2c_block_data(client, SILEAD_REG_DATA, SILEAD_TS_DATA_LEN, buf); if (ret < 0) { dev_err(dev, "Data read error %d\n", ret); return; } touch_nr = buf[0]; if (touch_nr < 0) return; dev_dbg(dev, "Touch number: %d\n", touch_nr); for (i = 1; i <= touch_nr; i++) { offset = i * SILEAD_POINT_DATA_LEN; /* Bits 4-7 are the touch id */ id = (buf[offset + SILEAD_POINT_X_MSB_OFF] & SILEAD_TOUCH_ID_MASK) >> 4; /* Bits 0-3 are MSB of X */ buf[offset + SILEAD_POINT_X_MSB_OFF] = buf[offset + SILEAD_POINT_X_MSB_OFF] & SILEAD_POINT_HSB_MASK; /* Bits 0-3 are MSB of Y */ buf[offset + SILEAD_POINT_Y_MSB_OFF] = buf[offset + SILEAD_POINT_Y_MSB_OFF] & SILEAD_POINT_HSB_MASK; x = le16_to_cpup((__le16 *)(buf + offset + SILEAD_POINT_X_OFF)); y = le16_to_cpup((__le16 *)(buf + offset + SILEAD_POINT_Y_OFF)); dev_dbg(dev, "x=%d y=%d id=%d\n", x, y, id); if (data->chip_id == GSL1688_CHIP_ID) silead_ts_report_touch(data, (id * 256 + x), data->y_max - y, id); else silead_ts_report_touch(data, x, y, id); } input_mt_sync_frame(data->input_dev); input_sync(data->input_dev); }
static void silead_ts_read_data(struct i2c_client *client) { struct silead_ts_data *data = i2c_get_clientdata(client); struct input_dev *input = data->input; struct device *dev = &client->dev; u8 *bufp, buf[SILEAD_TS_DATA_LEN]; int touch_nr, error, i; error = i2c_smbus_read_i2c_block_data(client, SILEAD_REG_DATA, SILEAD_TS_DATA_LEN, buf); if (error < 0) { dev_err(dev, "Data read error %d\n", error); return; } touch_nr = buf[0]; if (touch_nr > data->max_fingers) { dev_warn(dev, "More touches reported then supported %d > %d\n", touch_nr, data->max_fingers); touch_nr = data->max_fingers; } bufp = buf + SILEAD_POINT_DATA_LEN; for (i = 0; i < touch_nr; i++, bufp += SILEAD_POINT_DATA_LEN) { /* Bits 4-7 are the touch id */ data->id[i] = (bufp[SILEAD_POINT_X_MSB_OFF] & SILEAD_TOUCH_ID_MASK) >> 4; touchscreen_set_mt_pos(&data->pos[i], &data->prop, get_unaligned_le16(&bufp[SILEAD_POINT_X_OFF]) & 0xfff, get_unaligned_le16(&bufp[SILEAD_POINT_Y_OFF]) & 0xfff); } input_mt_assign_slots(input, data->slots, data->pos, touch_nr, 0); for (i = 0; i < touch_nr; i++) { input_mt_slot(input, data->slots[i]); input_mt_report_slot_state(input, MT_TOOL_FINGER, true); input_report_abs(input, ABS_MT_POSITION_X, data->pos[i].x); input_report_abs(input, ABS_MT_POSITION_Y, data->pos[i].y); dev_dbg(dev, "x=%d y=%d hw_id=%d sw_id=%d\n", data->pos[i].x, data->pos[i].y, data->id[i], data->slots[i]); } input_mt_sync_frame(input); input_sync(input); }
/** * goodix_process_events - Process incoming events * * @ts: our goodix_ts_data pointer * * Called when the IRQ is triggered. Read the current device state, and push * the input events to the user space. */ static void goodix_process_events(struct goodix_ts_data *ts) { u8 point_data[1 + GOODIX_CONTACT_SIZE * ts->max_touch_num]; int touch_num; int i; touch_num = goodix_ts_read_input_report(ts, point_data); if (touch_num < 0) return; for (i = 0; i < touch_num; i++) goodix_ts_report_touch(ts, &point_data[1 + GOODIX_CONTACT_SIZE * i]); input_mt_sync_frame(ts->input_dev); input_sync(ts->input_dev); }
static void pixcir_ts_report(struct pixcir_i2c_ts_data *ts, struct pixcir_report_data *report) { int slots[PIXCIR_MAX_SLOTS]; int n, i, slot; struct device *dev = &ts->client->dev; const struct pixcir_i2c_chip_data *chip = ts->chip; n = report->num_touches; if (n > PIXCIR_MAX_SLOTS) n = PIXCIR_MAX_SLOTS; if (!ts->chip->has_hw_ids) input_mt_assign_slots(ts->input, slots, report->pos, n, 0); for (i = 0; i < n; i++) { if (chip->has_hw_ids) { slot = input_mt_get_slot_by_key(ts->input, report->ids[i]); if (slot < 0) { dev_dbg(dev, "no free slot for id 0x%x\n", report->ids[i]); continue; } } else { slot = slots[i]; } input_mt_slot(ts->input, slot); input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true); input_report_abs(ts->input, ABS_MT_POSITION_X, report->pos[i].x); input_report_abs(ts->input, ABS_MT_POSITION_Y, report->pos[i].y); dev_dbg(dev, "%d: slot %d, x %d, y %d\n", i, slot, report->pos[i].x, report->pos[i].y); } input_mt_sync_frame(ts->input); input_sync(ts->input); }
/* report trackpad data as logical trackpad state */ static int report_tp_state(struct bcm5974 *dev, int size) { const struct bcm5974_config *c = &dev->cfg; const struct tp_finger *f; struct input_dev *input = dev->input; int raw_n, i, n = 0; if (size < c->tp_header || (size - c->tp_header) % c->tp_fsize != 0) return -EIO; raw_n = (size - c->tp_header) / c->tp_fsize; for (i = 0; i < raw_n; i++) { f = get_tp_finger(dev, i); if (raw2int(f->touch_major) == 0) continue; dev->pos[n].x = raw2int(f->abs_x); dev->pos[n].y = c->y.min + c->y.max - raw2int(f->abs_y); dev->index[n++] = f; } input_mt_assign_slots(input, dev->slots, dev->pos, n, 0); for (i = 0; i < n; i++) report_finger_data(input, dev->slots[i], &dev->pos[i], dev->index[i]); input_mt_sync_frame(input); report_synaptics_data(input, c, get_tp_finger(dev, 0), raw_n); /* later types report button events via integrated button only */ if (c->caps & HAS_INTEGRATED_BUTTON) { int ibt = raw2int(dev->tp_data[c->tp_button]); input_report_key(input, BTN_LEFT, ibt); } input_sync(input); return 0; }
static void silead_ts_read_data(struct i2c_client *client) { struct silead_ts_data *data = i2c_get_clientdata(client); struct input_dev *input = data->input; struct device *dev = &client->dev; u8 *bufp, buf[SILEAD_TS_DATA_LEN]; int touch_nr, softbutton, error, i; bool softbutton_pressed = false; error = i2c_smbus_read_i2c_block_data(client, SILEAD_REG_DATA, SILEAD_TS_DATA_LEN, buf); if (error < 0) { dev_err(dev, "Data read error %d\n", error); return; } if (buf[0] > data->max_fingers) { dev_warn(dev, "More touches reported then supported %d > %d\n", buf[0], data->max_fingers); buf[0] = data->max_fingers; } touch_nr = 0; bufp = buf + SILEAD_POINT_DATA_LEN; for (i = 0; i < buf[0]; i++, bufp += SILEAD_POINT_DATA_LEN) { softbutton = (bufp[SILEAD_POINT_Y_MSB_OFF] & SILEAD_EXTRA_DATA_MASK) >> 4; if (softbutton) { /* * For now only respond to softbutton == 0x01, some * tablets *without* a capacative button send 0x04 * when crossing the edges of the screen. */ if (softbutton == 0x01) softbutton_pressed = true; continue; } /* * Bits 4-7 are the touch id, note not all models have * hardware touch ids so atm we don't use these. */ data->id[touch_nr] = (bufp[SILEAD_POINT_X_MSB_OFF] & SILEAD_EXTRA_DATA_MASK) >> 4; touchscreen_set_mt_pos(&data->pos[touch_nr], &data->prop, get_unaligned_le16(&bufp[SILEAD_POINT_X_OFF]) & 0xfff, get_unaligned_le16(&bufp[SILEAD_POINT_Y_OFF]) & 0xfff); touch_nr++; } input_mt_assign_slots(input, data->slots, data->pos, touch_nr, 0); for (i = 0; i < touch_nr; i++) { input_mt_slot(input, data->slots[i]); input_mt_report_slot_state(input, MT_TOOL_FINGER, true); input_report_abs(input, ABS_MT_POSITION_X, data->pos[i].x); input_report_abs(input, ABS_MT_POSITION_Y, data->pos[i].y); dev_dbg(dev, "x=%d y=%d hw_id=%d sw_id=%d\n", data->pos[i].x, data->pos[i].y, data->id[i], data->slots[i]); } input_mt_sync_frame(input); input_report_key(input, KEY_LEFTMETA, softbutton_pressed); input_sync(input); }
static void gsl_ts_mt_event(struct gsl_ts_data *ts, u8 *buf) { int rc; struct input_dev *input = ts->input; struct device *dev = &ts->client->dev; struct gsl_ts_packet_header *header; struct gsl_ts_packet_touch *touch; u8 i; u16 touches, tseq, x, y, id, pressure; struct input_mt_pos positions[GSL_MAX_CONTACTS]; int slots[GSL_MAX_CONTACTS]; header = (struct gsl_ts_packet_header *) buf; touches = header->num_fingers; tseq = le16_to_cpu(header->time_stamp); /* time_stamp is 0 on zero-touch events, seems to wrap around 21800 */ dev_vdbg(dev, "%s: got touch events for %u fingers @%u\n", __func__, touches, tseq); if (touches > GSL_MAX_CONTACTS) { touches = GSL_MAX_CONTACTS; } for (i = 0; i < touches; i++) { touch = (struct gsl_ts_packet_touch *) &buf[sizeof(*header) + i * sizeof(*touch)]; y = le16_to_cpu(touch->y_z); x = le16_to_cpu(touch->x_id); id = x >> 12; x &= 0xfff; pressure = y >> 12; y &= 0xfff; if (ts->xy_swapped) { swap(x, y); } if (ts->x_reversed) { x = ts->x_max - x; } if (ts->y_reversed) { y = ts->y_max - y; } dev_vdbg(dev, "%s: touch event %u: x=%u y=%u id=0x%x p=%u\n", __func__, i, x, y, id, pressure); positions[i].x = x; positions[i].y = y; if (!ts->soft_tracking) { slots[i] = id; } } if (ts->soft_tracking) { /* This platform does not support finger tracking. * Use the input core finger tracker instead. */ #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) rc = input_mt_assign_slots(input, slots, positions, touches); #else rc = input_mt_assign_slots(input, slots, positions, touches, GSL_DMAX); #endif if (rc < 0) { dev_err(dev, "%s: input_mt_assign_slots returned %d\n", __func__, rc); return; } } for (i = 0; i < touches; i++) { input_mt_slot(input, slots[i]); input_mt_report_slot_state(input, MT_TOOL_FINGER, true); input_report_abs(input, ABS_MT_POSITION_X, positions[i].x); input_report_abs(input, ABS_MT_POSITION_Y, positions[i].y); } input_mt_sync_frame(input); input_sync(input); }
/** * Handle touch framing events. * * @param info The device information structure for the relevant PV input * device. * @param event The touch event to be handled. */ static void __handle_touch_framing(struct openxt_kbd_info *info, union oxtkbd_in_event *event) { input_mt_sync_frame(info->absolute_pointer); input_sync(info->absolute_pointer);; }