static void pixcir_ts_parse(struct pixcir_i2c_ts_data *tsdata, struct pixcir_report_data *report) { u8 rdbuf[2 + PIXCIR_MAX_SLOTS * 5]; u8 wrbuf[1] = { 0 }; u8 *bufptr; u8 touch; int ret, i; int readsize; const struct pixcir_i2c_chip_data *chip = tsdata->chip; memset(report, 0, sizeof(struct pixcir_report_data)); i = chip->has_hw_ids ? 1 : 0; readsize = 2 + tsdata->max_fingers * (4 + i); if (readsize > sizeof(rdbuf)) readsize = sizeof(rdbuf); ret = i2c_master_send(tsdata->client, wrbuf, sizeof(wrbuf)); if (ret != sizeof(wrbuf)) { dev_err(&tsdata->client->dev, "%s: i2c_master_send failed(), ret=%d\n", __func__, ret); return; } ret = i2c_master_recv(tsdata->client, rdbuf, readsize); if (ret != readsize) { dev_err(&tsdata->client->dev, "%s: i2c_master_recv failed(), ret=%d\n", __func__, ret); return; } touch = rdbuf[0] & 0x7; if (touch > tsdata->max_fingers) touch = tsdata->max_fingers; report->num_touches = touch; bufptr = &rdbuf[2]; for (i = 0; i < touch; i++) { touchscreen_set_mt_pos(&report->pos[i], &tsdata->prop, get_unaligned_le16(bufptr), get_unaligned_le16(bufptr + 2)); if (chip->has_hw_ids) { report->ids[i] = bufptr[4]; bufptr = bufptr + 5; } else { bufptr = bufptr + 4; } } }
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 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); }