Beispiel #1
0
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);
}
Beispiel #2
0
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);
}
Beispiel #3
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, 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);
}
Beispiel #4
0
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);
}
Beispiel #5
0
/* 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;
}
Beispiel #6
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);
}