Пример #1
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);
}
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
}
Пример #3
0
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);
}
Пример #4
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);
}
Пример #5
0
/**
 * 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);
}
Пример #6
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);
}
Пример #7
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;
}
Пример #8
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);
}
Пример #9
0
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);
}
Пример #10
0
/**
 * 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);;
}