static void ektf2127_report_event(struct ektf2127_ts *ts, const u8 *buf) { struct input_mt_pos touches[EKTF2127_MAX_TOUCHES]; int slots[EKTF2127_MAX_TOUCHES]; unsigned int touch_count, i; touch_count = buf[1] & 0x07; if (touch_count > EKTF2127_MAX_TOUCHES) { dev_err(&ts->client->dev, "Too many touches %d > %d\n", touch_count, EKTF2127_MAX_TOUCHES); touch_count = EKTF2127_MAX_TOUCHES; } ektf2127_parse_coordinates(buf, touch_count, touches); input_mt_assign_slots(ts->input, slots, touches, touch_count, 0); for (i = 0; i < touch_count; i++) { input_mt_slot(ts->input, slots[i]); input_mt_report_slot_state(ts->input, MT_TOOL_FINGER, true); touchscreen_report_pos(ts->input, &ts->prop, touches[i].x, touches[i].y, true); } input_mt_sync_frame(ts->input); input_sync(ts->input); }
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 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); }
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); }