コード例 #1
0
static int cyttsp5_input_register_device(struct input_dev *input, int max_slots)
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0))
    input_mt_init_slots(input, max_slots, 0);
#else
    input_mt_init_slots(input, max_slots);
#endif
    return input_register_device(input);
}
コード例 #2
0
ファイル: touch.c プロジェクト: 5victor/droidvncserver
static int touch_init(void)
{
	int rc;

	input_dev = input_allocate_device();

	if (!input_dev) {
		pr_info("input_dev alloc fail\n");
		return -ENOMEM;
	}

	input_dev->name = "touch";

        __set_bit(EV_KEY, input_dev->evbit);
        __set_bit(EV_ABS, input_dev->evbit);
        __set_bit(BTN_TOUCH, input_dev->keybit);
        __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);

	input_mt_init_slots(input_dev, 5);
	input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, 720, 0, 0);
	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, 1280, 0, 0);
        input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 0xFF, 0, 0);

        rc = input_register_device(input_dev);
	if (rc) {
		pr_info("input_register_device fail\n");
		return -EINVAL;
	}

	return 0;
}
コード例 #3
0
ファイル: bcm5974.c プロジェクト: 020gzh/linux
/* setup which logical events to report */
static void setup_events_to_report(struct input_dev *input_dev,
				   const struct bcm5974_config *cfg)
{
	__set_bit(EV_ABS, input_dev->evbit);

	/* for synaptics only */
	input_set_abs_params(input_dev, ABS_PRESSURE, 0, 256, 5, 0);
	input_set_abs_params(input_dev, ABS_TOOL_WIDTH, 0, 16, 0, 0);

	/* finger touch area */
	set_abs(input_dev, ABS_MT_TOUCH_MAJOR, &cfg->w);
	set_abs(input_dev, ABS_MT_TOUCH_MINOR, &cfg->w);
	/* finger approach area */
	set_abs(input_dev, ABS_MT_WIDTH_MAJOR, &cfg->w);
	set_abs(input_dev, ABS_MT_WIDTH_MINOR, &cfg->w);
	/* finger orientation */
	set_abs(input_dev, ABS_MT_ORIENTATION, &cfg->o);
	/* finger position */
	set_abs(input_dev, ABS_MT_POSITION_X, &cfg->x);
	set_abs(input_dev, ABS_MT_POSITION_Y, &cfg->y);

	__set_bit(EV_KEY, input_dev->evbit);
	__set_bit(BTN_LEFT, input_dev->keybit);

	if (cfg->caps & HAS_INTEGRATED_BUTTON)
		__set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit);

	input_mt_init_slots(input_dev, MAX_FINGERS,
		INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK);
}
コード例 #4
0
ファイル: pimhyp3.c プロジェクト: procount/pinn
/**
 * pimhyp3_request_input_dev - Allocate, populate and register the input device
 * @ts: our pimhyp3_ts_data pointer
 * Must be called during probe
 */
static int pimhyp3_request_input_dev(struct pimhyp3_ts_data *ts)
{
    int error;

    ts->input_dev = devm_input_allocate_device(&ts->client->dev);
    if (!ts->input_dev) {
        dev_err(&ts->client->dev, "Failed to allocate input device.");
        return -ENOMEM;
    }

    /* Set up device parameters */
    input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,
                 0, ts->abs_x_max, 0, 0);
    input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y,
                 0, ts->abs_y_max, 0, 0);

    input_mt_init_slots(ts->input_dev, ts->max_touch_num,
                INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);

    ts->input_dev->name = "Cypress Capacitive TouchScreen";
    ts->input_dev->phys = "input/ts";
    ts->input_dev->id.bustype = BUS_I2C;
    ts->input_dev->id.vendor = 0x0416;
    ts->input_dev->id.product = ts->id;
    ts->input_dev->id.version = ts->version;

    error = input_register_device(ts->input_dev);
    if (error) {
        dev_err(&ts->client->dev,
        "Failed to register input device: %d", error);
    return error;
    }

    return 0;
}
コード例 #5
0
ファイル: silead.c プロジェクト: lumag/linux
static int silead_ts_request_input_dev(struct silead_ts_data *data)
{
	struct device *dev = &data->client->dev;
	int error;

	data->input = devm_input_allocate_device(dev);
	if (!data->input) {
		dev_err(dev,
			"Failed to allocate input device\n");
		return -ENOMEM;
	}

	input_set_abs_params(data->input, ABS_MT_POSITION_X, 0, 4095, 0, 0);
	input_set_abs_params(data->input, ABS_MT_POSITION_Y, 0, 4095, 0, 0);
	touchscreen_parse_properties(data->input, true, &data->prop);

	input_mt_init_slots(data->input, data->max_fingers,
			    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED |
			    INPUT_MT_TRACK);

	if (device_property_read_bool(dev, "silead,home-button"))
		input_set_capability(data->input, EV_KEY, KEY_LEFTMETA);

	data->input->name = SILEAD_TS_NAME;
	data->input->phys = "input/ts";
	data->input->id.bustype = BUS_I2C;

	error = input_register_device(data->input);
	if (error) {
		dev_err(dev, "Failed to register input device: %d\n", error);
		return error;
	}

	return 0;
}
コード例 #6
0
ファイル: hid-egalax.c プロジェクト: ANFS/ANFS-kernel
static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi,
		struct hid_field *field, struct hid_usage *usage,
		unsigned long **bit, int *max)
{
	struct input_dev *input = hi->input;

	switch (usage->hid & HID_USAGE_PAGE) {

	case HID_UP_GENDESK:
		switch (usage->hid) {
		case HID_GD_X:
			field->logical_maximum = 32760;
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_POSITION_X);
			set_abs(input, ABS_MT_POSITION_X, field, SN_MOVE);
			/* touchscreen emulation */
			set_abs(input, ABS_X, field, SN_MOVE);
			return 1;
		case HID_GD_Y:
			field->logical_maximum = 32760;
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_POSITION_Y);
			set_abs(input, ABS_MT_POSITION_Y, field, SN_MOVE);
			/* touchscreen emulation */
			set_abs(input, ABS_Y, field, SN_MOVE);
			return 1;
		}
		return 0;

	case HID_UP_DIGITIZER:
		switch (usage->hid) {
		case HID_DG_TIPSWITCH:
			/* touchscreen emulation */
			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
			input_set_capability(input, EV_KEY, BTN_TOUCH);
			return 1;
		case HID_DG_INRANGE:
		case HID_DG_CONFIDENCE:
		case HID_DG_CONTACTCOUNT:
		case HID_DG_CONTACTMAX:
			return -1;
		case HID_DG_CONTACTID:
			input_mt_init_slots(input, MAX_SLOTS);
			return 1;
		case HID_DG_TIPPRESSURE:
			field->logical_minimum = 0;
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_PRESSURE);
			set_abs(input, ABS_MT_PRESSURE, field, SN_PRESSURE);
			/* touchscreen emulation */
			set_abs(input, ABS_PRESSURE, field, SN_PRESSURE);
			return 1;
		}
		return 0;
	}

	/* ignore others (from other reports we won't get anyway) */
	return -1;
}
コード例 #7
0
static int cyttsp4_input_register_device(struct input_dev *input, int max_slots)
{
	input_set_abs_params(input, ABS_MT_TOOL_TYPE,
			0, MT_TOOL_MAX, 0, 0);

	input_mt_init_slots(input, max_slots);
	return input_register_device(input);
}
コード例 #8
0
ファイル: wacom_sys.c プロジェクト: 3null/fastsocket
void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac)
{
	if (wacom_wac->features->device_type == BTN_TOOL_FINGER) {
		input_dev->absbit[BIT_WORD(ABS_MISC)] &= ~BIT_MASK(ABS_MISC);

		input_mt_init_slots(input_dev, 2);
		input_set_abs_params(input_dev, ABS_MT_POSITION_X,
				     0, wacom_wac->features->x_max, 0, 0);
		input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
				     0, wacom_wac->features->y_max, 0, 0);
	}
}
コード例 #9
0
ファイル: usf.c プロジェクト: lolhi/ef52-kernel
static int prepare_tsc_input_device(uint16_t ind,
				struct usf_type *usf_info,
				struct us_input_info_type *input_info,
				const char *name)
{
	struct input_dev *in_dev = allocate_dev(ind, name);

	if (in_dev == NULL)
		return -ENOMEM;

	usf_info->input_ifs[ind] = in_dev;

#ifdef SKY_ULTRASOUNDPEN_FEATURE
	set_bit(CAMERA_KEY, in_dev->keybit);
	set_bit(CAPTURE_KEY, in_dev->keybit);
#endif

	in_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);

	in_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
	input_set_abs_params(in_dev, ABS_X,
			     input_info->tsc_x_dim[MIN_IND],
			     input_info->tsc_x_dim[MAX_IND],
			     0, 0);
	input_set_abs_params(in_dev, ABS_Y,
			     input_info->tsc_y_dim[MIN_IND],
			     input_info->tsc_y_dim[MAX_IND],
			     0, 0);
	input_set_abs_params(in_dev, ABS_DISTANCE,
			     input_info->tsc_z_dim[MIN_IND],
			     input_info->tsc_z_dim[MAX_IND],
			     0, 0);

	input_set_abs_params(in_dev, ABS_PRESSURE,
			     input_info->tsc_pressure[MIN_IND],
			     input_info->tsc_pressure[MAX_IND],
			     0, 0);

	input_set_abs_params(in_dev, ABS_TILT_X,
			     input_info->tsc_x_tilt[MIN_IND],
			     input_info->tsc_x_tilt[MAX_IND],
			     0, 0);
	input_set_abs_params(in_dev, ABS_TILT_Y,
			     input_info->tsc_y_tilt[MIN_IND],
			     input_info->tsc_y_tilt[MAX_IND],
			     0, 0);

	input_mt_init_slots(in_dev, NUM_TRK_ID);	

	return 0;
}
コード例 #10
0
static int __init vinput_multi_tc_init(void)
{
	int err;

	vinput_multi_tc_dev = input_allocate_device();
	if (!vinput_multi_tc_dev)
		return -ENOMEM;

	vinput_multi_tc_dev->name = "qwerty";

	vinput_multi_tc_dev->id.product = 0;
	vinput_multi_tc_dev->id.version = 0x0100;

	set_bit(EV_SYN, vinput_multi_tc_dev->evbit);
	set_bit(EV_KEY, vinput_multi_tc_dev->evbit);
	set_bit(EV_ABS, vinput_multi_tc_dev->evbit);

	set_bit(BTN_TOUCH, vinput_multi_tc_dev->keybit);

	input_mt_init_slots(vinput_multi_tc_dev, MAX_FINGER_NUM);

	input_set_abs_params(vinput_multi_tc_dev, ABS_X, 0, 1280, 0, 0);
	input_set_abs_params(vinput_multi_tc_dev, ABS_Y, 0, 720, 0, 0);
	input_set_abs_params(vinput_multi_tc_dev, ABS_PRESSURE, 0, 255, 0, 0);
	input_set_abs_params(vinput_multi_tc_dev, ABS_TOOL_WIDTH, 0, 15, 0, 0);
	input_set_abs_params(vinput_multi_tc_dev,
			     ABS_MT_POSITION_X, 0, 1280, 0, 0);
	input_set_abs_params(vinput_multi_tc_dev,
			     ABS_MT_POSITION_Y, 0, 720, 0, 0);
	input_set_abs_params(vinput_multi_tc_dev,
			     ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
	input_set_abs_params(vinput_multi_tc_dev,
			     ABS_MT_WIDTH_MAJOR, 0, 15, 0, 0);

	err = input_register_device(vinput_multi_tc_dev);
	if (err) {
		input_free_device(vinput_multi_tc_dev);
		return err;
	}

	return 0;
}
コード例 #11
0
ファイル: silead.c プロジェクト: tinocyngn/sofia-kernel
static int silead_ts_request_input_dev(struct silead_ts_data *data)
{
	struct device *dev = &data->client->dev;
	int ret;

	data->input_dev = devm_input_allocate_device(dev);
	if (!data->input_dev) {
		dev_err(dev,
			"Failed to allocate input device\n");
		return -ENOMEM;
	}

	data->input_dev->evbit[0] = BIT_MASK(EV_SYN) |
				    BIT_MASK(EV_KEY) |
				    BIT_MASK(EV_ABS);

	input_set_abs_params(data->input_dev, ABS_MT_POSITION_X, 0,
			     data->x_max, 0, 0);
	input_set_abs_params(data->input_dev, ABS_MT_POSITION_Y, 0,
			     data->y_max, 0, 0);
	input_set_abs_params(data->input_dev, ABS_MT_TOUCH_MAJOR, 0,
			     255, 0, 0);
	input_set_abs_params(data->input_dev, ABS_MT_WIDTH_MAJOR, 0,
			     200, 0, 0);

	input_mt_init_slots(data->input_dev, data->max_fingers,
			    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);

	data->input_dev->name = SILEAD_TS_NAME;
	data->input_dev->phys = "input/ts";
	data->input_dev->id.bustype = BUS_I2C;

	ret = input_register_device(data->input_dev);
	if (ret) {
		dev_err(dev, "Failed to register input device: %d\n", ret);
		return ret;
	}

	return 0;
}
コード例 #12
0
ファイル: goodix.c プロジェクト: 19Dan01/linux
/**
 * goodix_request_input_dev - Allocate, populate and register the input device
 *
 * @ts: our goodix_ts_data pointer
 *
 * Must be called during probe
 */
static int goodix_request_input_dev(struct goodix_ts_data *ts)
{
	int error;

	ts->input_dev = devm_input_allocate_device(&ts->client->dev);
	if (!ts->input_dev) {
		dev_err(&ts->client->dev, "Failed to allocate input device.");
		return -ENOMEM;
	}

	ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) |
				  BIT_MASK(EV_KEY) |
				  BIT_MASK(EV_ABS);

	input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0,
				ts->abs_x_max, 0, 0);
	input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0,
				ts->abs_y_max, 0, 0);
	input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
	input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);

	input_mt_init_slots(ts->input_dev, ts->max_touch_num,
			    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);

	ts->input_dev->name = "Goodix Capacitive TouchScreen";
	ts->input_dev->phys = "input/ts";
	ts->input_dev->id.bustype = BUS_I2C;
	ts->input_dev->id.vendor = 0x0416;
	ts->input_dev->id.product = 0x1001;
	ts->input_dev->id.version = 10427;

	error = input_register_device(ts->input_dev);
	if (error) {
		dev_err(&ts->client->dev,
			"Failed to register input device: %d", error);
		return error;
	}

	return 0;
}
コード例 #13
0
static int __devinit ist30xx_probe(struct i2c_client *		client,
				   const struct i2c_device_id * id)
{
	int ret;
	struct ist30xx_data *data;
	struct input_dev *input_dev;

#if 0
	/* [email protected] */
	struct touch_platform_data *ts_pdata;
//	struct ist30xx_ts_device *dev;

	ts_pdata = client->dev.platform_data;
//	dev = &ist30xx_ts_dev;
	/* [email protected] */
#endif

	tsp_info("\n%s(), the i2c addr=0x%x \n", __func__, client->addr);

/*	dev->power = ts_pdata->power;
	dev->num_irq = ts_pdata->irq;
	dev->sda_gpio = ts_pdata->sda;
	dev->scl_gpio  = ts_pdata->scl;*/

	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
		tsp_debug("failed to i2c functionality check");
		ret = -ENODEV;
		goto err_check_functionality_failed;
	}
	
	data = kzalloc(sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	data->client = client;

	if(client->dev.of_node) {
		data->pdata = devm_kzalloc(&client->dev, sizeof(struct ist30xx_tsi_platform_data), GFP_KERNEL);
		if(!data->pdata) {
			tsp_debug("failed to allocate platform_data");
			return -ENOMEM;
		}

		ret = ist30xx_parse_dt(&client->dev, data->pdata);
		if(ret) {
			tsp_debug("device tree parsing failed");
			return ret;
		}
	} else {
		data->pdata = client->dev.platform_data;
	}

	ret = ist30xx_regulator_configure(data, true);
	if (ret < 0) {
			tsp_debug("Failed to configure regulators");
	}

	ret = ist30xx_ldo_power_on(data, true);
	if (ret < 0) {
			tsp_debug("Failed to power on");
	}

	input_dev = input_allocate_device();
	if (!input_dev) {
		ret = -ENOMEM;
		tsp_err("%s(), input_allocate_device failed (%d)\n", __func__, ret);
		goto err_alloc_dev;
	}

#if 0
	DMSG("[ TSP ] irq : %d, scl : %d, sda : %d\n", client->irq, ts_pdata->scl, ts_pdata->sda);
#endif
	data->num_fingers = IST30XX_MAX_MT_FINGERS;
	data->num_keys = IST30XX_MAX_MT_FINGERS;
	data->irq_enabled = 1;
	data->client = client;
	data->input_dev = input_dev;
#if 0
	/* [email protected] */
	data->power = ts_pdata->power;
	/* [email protected] */
#endif
	i2c_set_clientdata(client, data);

#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 0, 0))
	input_mt_init_slots(input_dev, IST30XX_MAX_MT_FINGERS);
#endif

	input_dev->name = "ist30xx_ts_input";
	input_dev->id.bustype = BUS_I2C;
	input_dev->dev.parent = &client->dev;

	set_bit(EV_ABS, input_dev->evbit);
#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 0, 0))
	set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
#endif

	input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, IST30XX_MAX_X, 0, 0);
	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, IST30XX_MAX_Y, 0, 0);
#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 0, 0))
	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, IST30XX_MAX_W, 0, 0);
#else
	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, IST30XX_MAX_Z, 0, 0);
	input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, IST30XX_MAX_W, 0, 0);
#endif

#if IST30XX_USE_KEY
	{
		int i;
		set_bit(EV_KEY, input_dev->evbit);
		set_bit(EV_SYN, input_dev->evbit);
		for (i = 1; i < ARRAY_SIZE(ist30xx_key_code); i++)
			set_bit(ist30xx_key_code[i], input_dev->keybit);
	}
#endif

	input_set_drvdata(input_dev, data);
	ret = input_register_device(input_dev);
	if (ret) {
		input_free_device(input_dev);
		goto err_reg_dev;
	}

#if defined(CONFIG_FB)
	data->fb_notif.notifier_call = fb_notifier_callback;
	ret = fb_register_client(&data->fb_notif);
	if(ret)
		tsp_debug("Unable to register fb_notifier \n");
	else
		tsp_debug("Register fb_notifier \n");
#elif defined(CONFIG_HAS_EARLYSUSPEND)
	data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
	data->early_suspend.suspend = ist30xx_early_suspend;
	data->early_suspend.resume = ist30xx_late_resume;
	register_early_suspend(&data->early_suspend);
#endif

	ts_data = data;

	ret = ist30xx_init_system();
	if (ret) {
		dev_err(&client->dev, "chip initialization failed\n");
		goto err_init_drv;
	}

	ret = ist30xx_init_update_sysfs();
	if (ret)
		goto err_init_drv;

#if IST30XX_DEBUG
	ret = ist30xx_init_misc_sysfs();
	if (ret)
		goto err_init_drv;
#endif

# if IST30XX_FACTORY_TEST
	ret = ist30xx_init_factory_sysfs();
	if (ret)
		goto err_init_drv;
#endif

#if IST30XX_TRACKING_MODE
	ret = ist30xx_init_tracking_sysfs();
	if (ret)
		goto err_init_drv;
#endif

	ret = request_threaded_irq(client->irq, NULL, ist30xx_irq_thread,
				   IRQF_TRIGGER_FALLING | IRQF_ONESHOT, "ist30xx_ts", data);
	if (ret)
		goto err_irq;

	ist30xx_disable_irq(data);

#if IST30XX_INTERNAL_BIN
# if IST30XX_UPDATE_BY_WORKQUEUE
	INIT_DELAYED_WORK(&work_fw_update, fw_update_func);
	schedule_delayed_work(&work_fw_update, IST30XX_UPDATE_DELAY);
# else
	ret = ist30xx_auto_bin_update(data);
	if (ret < 0)
		goto err_irq;
# endif
#endif  // IST30XX_INTERNAL_BIN

	ret = ist30xx_get_info(data);
	tsp_info("Get info: %s\n", (ret == 0 ? "success" : "fail"));

	INIT_DELAYED_WORK(&work_reset_check, reset_work_func);

#if IRQ_THREAD_WORK_QUEUE
	INIT_WORK(&work_irq_thread, irq_thread_func);
#endif

#if IST30XX_DETECT_TA
	ist30xx_ta_status = 0;
#endif

#if IST30XX_EVENT_MODE
	init_timer(&idle_timer);
	idle_timer.function = timer_handler;
	idle_timer.expires = jiffies_64 + (EVENT_TIMER_INTERVAL);

	mod_timer(&idle_timer, get_jiffies_64() + EVENT_TIMER_INTERVAL);

	ktime_get_ts(&t_event);
#endif

	ist30xx_initialized = 1;

	return 0;

err_irq:
	ist30xx_disable_irq(data);
	free_irq(client->irq, data);
err_init_drv:
#if IST30XX_EVENT_MODE
	get_event_mode = false;
#endif
	tsp_err("Error, ist30xx init driver\n");
//	ist30xx_power_off();
	ist30xx_ts_off();
	input_unregister_device(input_dev);
	return 0;

err_reg_dev:
err_alloc_dev:
	tsp_err("Error, ist30xx mem free\n");
	kfree(data);
err_check_functionality_failed:
	return 0;
}
コード例 #14
0
static int ct36x_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
	struct ct36x_ts_info *ts = NULL;
	struct device *dev = &client->dev;
	int err = -1;

	if (dev == NULL) {
		printk(KERN_ERR  "%s(): dev not registered!\n", __func__);
		goto ERR_HW_INIT;
	}

	/* Check I2C Functionality */
	err = i2c_check_functionality(client->adapter, I2C_FUNC_I2C);
	if ( !err ) {
		dev_err(dev, "Check I2C Functionality Failed.\n");
		goto ERR_I2C_CHK;
	}

	ts = (struct ct36x_ts_info *)i2c_get_clientdata(client);
	if (ts == NULL) {
		printk(KERN_ERR  "%s(): Not registered at I2C!\n", __func__);
		goto ERR_HW_INIT;
	}

	ts->ready = 0;	// Device is not ready

	/* Init Hardware */
	err = ct36x_ts_hw_init(ts);
	if ( err ) {
		dev_err(dev, "Platform HW Init Failed.\n");
		goto ERR_HW_INIT;
	}

	/* HW Reset when Firmware request and update. */
	ct36x_ts_hw_reset(ts);

#if (CT36X_TS_CHIP_SEL == CT360_CHIP_VER)
	// Set I2C scon to 0x0f2f --> read version
	ts->data.buf[0] = 0xFF;
	ts->data.buf[1] = 0x0F;
	ts->data.buf[2] = 0x2A;
#elif (CT36X_TS_CHIP_SEL == CT36X_CHIP_VER)
	// Set I2C scon to 0x3fff --> read version
	ts->data.buf[0] = 0xFF;
	ts->data.buf[1] = 0x3F;
	ts->data.buf[2] = 0xFF;
#endif

	ct36x_ts_reg_write(client, client->addr, (char *) ts->data.buf, 3, CT36X_TS_I2C_SPEED);
	mdelay(10);

	ts->data.buf[0] = 0x00;
	ct36x_ts_reg_write(client, client->addr, (char *) ts->data.buf, 1, CT36X_TS_I2C_SPEED);
	mdelay(10);

	// do read version
	ct36x_ts_reg_read(client, client->addr, (char *) ts->data.buf, 1, CT36X_TS_I2C_SPEED);
	mdelay(10);

	dev_info(dev, "FW Version read: 0x%x \n", ts->data.buf[0]);
#if defined(CONFIG_CT360_CHIP_UPDATE_SUPPORT)
	{
		char fw_ver_upd = Binary_Data[CT36X_TS_FW_VER_OFFSET];
		dev_info(dev, "FW Version write: 0x%x \n", fw_ver_upd);

		if ( fw_ver_upd != ts->data.buf[0] )
		{
			dev_info(dev, "Running bootloader ... \n");
			err = ct36x_ts_bootloader(client);

			dev_info(dev, "Bootloader done, %s \n", err ? "Failed" : "OK");
		}
	}
#else
	dev_info(dev, "Bootloader support disabled, trying without...\n");
#endif

	// register early suspend
#ifdef CONFIG_HAS_EARLYSUSPEND
#if	(CT36X_TS_HAS_EARLYSUSPEND)
	ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
	ts->early_suspend.suspend = ct36x_early_suspend;
	ts->early_suspend.resume = ct36x_early_resume;
	register_early_suspend(&ts->early_suspend);
#endif
#endif

	// allocate input device
	ts->input = input_allocate_device();
	if ( !ts->input ) {
		dev_err(dev, "Unable to allocate input device for device %s.\n", DRIVER_NAME);
		err = -ENOMEM;
		goto ERR_INPUT_ALLOC;
	}

	__set_bit(EV_ABS, ts->input->evbit);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
	__set_bit(INPUT_PROP_DIRECT, ts->input->propbit);
#endif

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
	input_mt_init_slots(ts->input, CT36X_TS_POINT_NUM);
#endif
	input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, CT36X_TS_ABS_X_MAX, 0, 0);
	input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, CT36X_TS_ABS_Y_MAX, 0, 0);
	input_set_abs_params(ts->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
	input_set_abs_params(ts->input, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);

	ts->input->name =		DRIVER_NAME;
	ts->input->id.bustype =	BUS_I2C;

	// register input device
	err = input_register_device(ts->input);
	if ( err ) {
		dev_err(dev, "Unable to register input device for device %s.\n", DRIVER_NAME);
		goto ERR_INPUT_REGIS;
	}

	/* ct36x_zx */
	ts->ts_workqueue = create_singlethread_workqueue(CT36X_TS_WQ);
	if (!ts->ts_workqueue) {
		err = -ESRCH;
		printk(KERN_ERR "create_workqueue falled!\n");
		goto ERR_TS_WQ;
	}
	// work
	INIT_WORK(&ts->event_work, ct36x_ts_workfunc);

	// Init irq
	ts->irq = gpio_to_irq(CT36X_TS_IRQ_PIN);
	//err = request_irq(ts->irq, ct36x_ts_irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, DRIVER_NAME, ts);
	err = request_irq(ts->irq, ct36x_ts_irq, IRQF_TRIGGER_FALLING, DRIVER_NAME, ts);		/* ct36x_zx */
	if ( err ) {
		dev_err(dev, "Unable to request irq.\n");
		goto ERR_IRQ_REQEST;
	}

	// ESD timer
#if (CT36X_TS_ESD_TIMER_INTERVAL)
	setup_timer(&ts->timer, ct36x_ts_timer, ts);
	ts->timer.expires = jiffies + HZ * CT36X_TS_ESD_TIMER_INTERVAL;
	add_timer(&ts->timer);
	ts->timer_on = 1;
	dev_info(dev, "ESD timer, %s \n", ts->timer_on ? "On" : "Off");
#endif

	/* Add another reset and then state we are ready */
	ct36x_ts_hw_reset(ts);

	ts->ready = 1;	// Device is ready

	return 0;

ERR_TS_WQ:
ERR_IRQ_REQEST:
ERR_INPUT_REGIS:
	input_free_device(ts->input);
ERR_INPUT_ALLOC:
ERR_I2C_CHK:
#ifdef CONFIG_HAS_EARLYSUSPEND
#if	(CT36X_TS_HAS_EARLYSUSPEND)
	unregister_early_suspend(&ts->early_suspend);
#endif
#endif
ERR_HW_INIT:
	ct36x_ts_hw_exit(ts);

	return err;
}
コード例 #15
0
ファイル: gt818_ts.c プロジェクト: Astralix/rk29_kernel_308
static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
	int ret = 0;
	int retry=0;
	struct gt818_ts_data *ts;

	struct gt818_platform_data *pdata;
	dev_info(&client->dev,"Install touch driver.\n");
	printk("gt818: Install touch driver.\n");
	//Check I2C function
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) 
	{
		dev_err(&client->dev, "Must have I2C_FUNC_I2C.\n");
		ret = -ENODEV;
		goto err_check_functionality_failed;
	}

	ts = kzalloc(sizeof(*ts), GFP_KERNEL);
	if (ts == NULL) {
		ret = -ENOMEM;
		goto err_alloc_data_failed;
	}

	i2c_connect_client = client;	//used by Guitar_Update
	pdata = client->dev.platform_data;
	ts->client = client;
	i2c_set_clientdata(client, ts);

	//init int and reset ports
	ret = gpio_request(pdata->gpio_pendown, "TS_INT");	//Request IO
	if (ret){
		dev_err(&client->dev, "Failed to request GPIO:%d, ERRNO:%d\n",(int)pdata->gpio_pendown, ret);
		goto err_gpio_request_failed;
	}
	rk29_mux_api_set(pdata->pendown_iomux_name, pdata->pendown_iomux_mode);
	gpio_direction_input(pdata->gpio_pendown);
	gpio_pull_updown(pdata->gpio_pendown, 0);

	ret = gpio_request(pdata->gpio_reset, "gt818_resetPin");
	if(ret){
		dev_err(&client->dev, "failed to request resetPin GPIO%d\n", pdata->gpio_reset);
		goto err_gpio_request_failed;
	}
	rk29_mux_api_set(pdata->resetpin_iomux_name, pdata->resetpin_iomux_mode);

#if 1
	for(retry = 0; retry < 4; retry++)
	{
		gpio_pull_updown(pdata->gpio_reset, 1);
		gpio_direction_output(pdata->gpio_reset, 0);
		msleep(1);     //delay at least 1ms
		gpio_direction_input(pdata->gpio_reset);
		gpio_pull_updown(pdata->gpio_reset, 0);
		msleep(25);   //delay at least 20ms
		ret = i2c_pre_cmd(ts);
		if (ret > 0)
			break;
		msleep(50);
	}

	if(ret <= 0)
	{
		dev_err(&client->dev, "Warnning: I2C communication might be ERROR!\n");
		goto err_i2c_failed;
	}	

#endif

	for(retry = 0; retry < 3; retry++)
	{
		ret = goodix_init_panel(ts);

		dev_info(&client->dev,"the config ret is :%d\n", ret);
		msleep(20);
		if(ret < 0)	//Initiall failed
			continue;
		else
			break;
	}

	if(ret < 0) {
		ts->bad_data = 1;
		goto err_init_godix_ts;
	}

	goodix_read_version(ts);


	INIT_WORK(&ts->work, goodix_ts_work_func);		//init work_struct
	ts->input_dev = input_allocate_device();
	if (ts->input_dev == NULL) {
		ret = -ENOMEM;
		dev_dbg(&client->dev,"goodix_ts_probe: Failed to allocate input device\n");
		goto err_input_dev_alloc_failed;
	}

	//ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ;
	//ts->input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
	//ts->input_dev->absbit[0] = BIT_MASK(ABS_MT_POSITION_X) | BIT_MASK(ABS_MT_POSITION_Y) |
	//		BIT_MASK(ABS_MT_TOUCH_MAJOR) | BIT_MASK(ABS_MT_WIDTH_MAJOR);  // for android


#ifdef HAVE_TOUCH_KEY
	for(retry = 0; retry < MAX_KEY_NUM; retry++)
	{
		input_set_capability(ts->input_dev, EV_KEY, gt818_key_array[retry]);
	}
#endif

	snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&client->dev));
	snprintf(ts->name, sizeof(ts->name), "gt818-touchscreen");

	ts->input_dev->name = "gt818_ts";//ts->name;
	ts->input_dev->phys = ts->phys;
	ts->input_dev->dev.parent = &client->dev;
	ts->input_dev->id.bustype = BUS_I2C;
	ts->input_dev->id.vendor = 0xDEAD;
	ts->input_dev->id.product = 0xBEEF;
	ts->input_dev->id.version = 10427;	//screen firmware version

	__set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
	__set_bit(EV_ABS, ts->input_dev->evbit);
#ifdef GOODIX_MULTI_TOUCH
	input_mt_init_slots(ts->input_dev, MAX_FINGER_NUM);
	//input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
	input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
	input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, SCREEN_MAX_WIDTH, 0, 0);
	input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, SCREEN_MAX_HEIGHT, 0, 0);
	//input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 0, MAX_FINGER_NUM, 0, 0);
	input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
#else
	input_set_abs_params(ts->input_dev, ABS_X, 0, SCREEN_MAX_HEIGHT, 0, 0);
	input_set_abs_params(ts->input_dev, ABS_Y, 0, SCREEN_MAX_WIDTH, 0, 0);
	input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 255, 0, 0);
#endif	
	
	ret = input_register_device(ts->input_dev);
	if (ret) {
		dev_err(&client->dev,"Probe: Unable to register %s input device\n", ts->input_dev->name);
		goto err_input_register_device_failed;
	}
	ts->bad_data = 0;
//	16finger_list.length = 0;

	client->irq = gpio_to_irq(pdata->gpio_pendown);		//If not defined in client
	if (client->irq)
	{

	#if INT_TRIGGER==0
		#define GT801_PLUS_IRQ_TYPE IRQ_TYPE_EDGE_RISING
	#elif INT_TRIGGER==1
		#define GT801_PLUS_IRQ_TYPE IRQ_TYPE_EDGE_FALLING
	#elif INT_TRIGGER==2
		#define GT801_PLUS_IRQ_TYPE IRQ_TYPE_LEVEL_LOW
	#elif INT_TRIGGER==3
		#define GT801_PLUS_IRQ_TYPE IRQ_TYPE_LEVEL_HIGH
	#endif

		ret = request_irq(client->irq, goodix_ts_irq_handler, GT801_PLUS_IRQ_TYPE,
			client->name, ts);
		if (ret != 0) {
			dev_err(&client->dev,"Cannot allocate ts INT!ERRNO:%d\n", ret);
			gpio_direction_input(pdata->gpio_pendown);
			gpio_free(pdata->gpio_pendown);
			goto err_gpio_request_failed;
		}
		else 
		{	
			disable_irq(client->irq);
			ts->use_irq = 1;
			dev_dbg(&client->dev,"Reques EIRQ %d succesd on GPIO:%d\n", client->irq, pdata->gpio_pendown);
		}	
	}

err_gpio_request_failed:
	ts->power = goodix_ts_power;
#ifdef CONFIG_HAS_EARLYSUSPEND
	ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
	ts->early_suspend.suspend = goodix_ts_early_suspend;
	ts->early_suspend.resume = goodix_ts_late_resume;
	register_early_suspend(&ts->early_suspend);
#endif
	dev_info(&client->dev,"Start %s in %s mode\n",
		ts->input_dev->name, ts->use_irq ? "interrupt" : "polling");

	if (ts->use_irq)
	{
		enable_irq(client->irq);
	}
	else
	{
		hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
		ts->timer.function = goodix_ts_timer_func;
		hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
	}

	i2c_end_cmd(ts);
	return 0;

err_init_godix_ts:
	i2c_end_cmd(ts);
	if(ts->use_irq)
	{
		ts->use_irq = 0;
		free_irq(client->irq,ts);
		gpio_direction_input(pdata->gpio_pendown);
		gpio_free(pdata->gpio_pendown);
	}
	else 
		hrtimer_cancel(&ts->timer);

err_input_register_device_failed:
	input_free_device(ts->input_dev);

err_input_dev_alloc_failed:
	i2c_set_clientdata(client, NULL);
err_i2c_failed:	
	kfree(ts);
err_alloc_data_failed:
err_check_functionality_failed:
	return ret;
}
コード例 #16
0
static int cyttsp4_input_register_device(struct input_dev *input, int max_tchs)
{
	/* max num slots equals max touches + 1 for hover */
	input_mt_init_slots(input, max_tchs + 1);
	return input_register_device(input);
}
コード例 #17
0
static int ct36x_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
	int ret = 0, i;
	struct ct36x_data *ts = NULL;
	struct ct36x_platform_data *pdata = client->dev.platform_data;

	if(!pdata){
		dev_err(&client->dev, "no platform data\n");
		return -EINVAL;
	};

	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
		dev_err(&client->dev, "I2C-Adapter doesn't support I2C_FUNC_I2C\n");
		return -ENODEV;
	}

	ts = kzalloc(sizeof(struct ct36x_data), GFP_KERNEL);
	if(!ts){
		dev_err(&client->dev, "No memory for ct36x");
		return -ENOMEM;
	}
	ts->model = pdata->model;
	ts->x_max = pdata->x_max;
	ts->y_max = pdata->y_max;
	ts->rst_io = pdata->rst_io;
	ts->irq_io = pdata->irq_io;

	for(i = 0; i < 4; i++)
		ts->orientation[i] = pdata->orientation[i];

	ts->client = client;
	ts->dev = &client->dev;

	i2c_set_clientdata(client, ts);

	ret = ct36x_set_ops(ts, pdata->model);
	if(ret < 0){
		dev_err(ts->dev, "Failed to set ct36x ops\n");
		goto err_ct36x_set_ops;
	}

	if(ts->ops->init){
		ret = ts->ops->init(ts);
		if(ret < 0){
			dev_err(ts->dev, "Failed to init ct36x chip\n");
			goto err_input_allocate_device;
		}
	}
	ret = ct36x_chip_get_ver(ts);
	if(ret < 0){
		dev_warn(ts->dev, "CT363 TOUCHSCREEN is no exist\n");
		goto err_input_allocate_device;
	}
	printk("CT363 ver=[%x]\n", ret);
	

	ts->input = input_allocate_device();
	if(!ts->input){
		ret = -ENODEV;
		dev_err(ts->dev, "Failed to allocate input device\n");
		goto err_input_allocate_device;
	}

	ts->input->name = CT36X_NAME;
	ts->input->dev.parent = &client->dev;
	set_bit(EV_ABS, ts->input->evbit);
	set_bit(INPUT_PROP_DIRECT, ts->input->propbit);
	input_mt_init_slots(ts->input, ts->point_num);
	input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0);
	input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0);
	input_set_abs_params(ts->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
	input_set_abs_params(ts->input, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);

	ret = input_register_device(ts->input);
	if(ret < 0){
		dev_err(ts->dev, "Failed to register input device\n");
		goto err_input_register_devcie;
	}

#ifdef CONFIG_HAS_EARLYSUSPEND
	ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
	ts->early_suspend.suspend = ct36x_ts_early_suspend;
	ts->early_suspend.resume = ct36x_ts_late_resume;
	register_early_suspend(&ts->early_suspend);
#endif
	ts->irq = gpio_to_irq(ts->irq_io.gpio);
	ret = request_threaded_irq(ts->irq, NULL, ct36x_irq_handler, IRQF_TRIGGER_FALLING|IRQF_ONESHOT, CT36X_NAME, ts);
	if(ret < 0){
		dev_err(ts->dev, "Failed to request threaded irq\n");
		goto err_request_threaded_irq;
	}
		
	dev_info(ts->dev, "CT363 Successfully initialized\n");
	return 0;
err_request_threaded_irq:
	unregister_early_suspend(&ts->early_suspend);
	input_unregister_device(ts->input);
err_input_register_devcie:
	input_free_device(ts->input);
err_input_allocate_device:
	if(ts->ops->deinit)
		ts->ops->deinit(ts);
err_ct36x_init_chip:
err_ct36x_set_ops:
	i2c_set_clientdata(client, NULL);
	kfree(ts);
	return ret;
}
コード例 #18
0
ファイル: pixcir_i2c_ts.c プロジェクト: 383530895/linux
static int pixcir_i2c_ts_probe(struct i2c_client *client,
					 const struct i2c_device_id *id)
{
	const struct pixcir_ts_platform_data *pdata =
			dev_get_platdata(&client->dev);
	struct device *dev = &client->dev;
	struct device_node *np = dev->of_node;
	struct pixcir_i2c_ts_data *tsdata;
	struct input_dev *input;
	int error;

	if (np && !pdata) {
		pdata = pixcir_parse_dt(dev);
		if (IS_ERR(pdata))
			return PTR_ERR(pdata);
	}

	if (!pdata) {
		dev_err(&client->dev, "platform data not defined\n");
		return -EINVAL;
	}

	if (!gpio_is_valid(pdata->gpio_attb)) {
		dev_err(dev, "Invalid gpio_attb in pdata\n");
		return -EINVAL;
	}

	if (!pdata->chip.max_fingers) {
		dev_err(dev, "Invalid max_fingers in pdata\n");
		return -EINVAL;
	}

	tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL);
	if (!tsdata)
		return -ENOMEM;

	input = devm_input_allocate_device(dev);
	if (!input) {
		dev_err(dev, "Failed to allocate input device\n");
		return -ENOMEM;
	}

	tsdata->client = client;
	tsdata->input = input;
	tsdata->pdata = pdata;

	input->name = client->name;
	input->id.bustype = BUS_I2C;
	input->open = pixcir_input_open;
	input->close = pixcir_input_close;
	input->dev.parent = &client->dev;

	__set_bit(EV_KEY, input->evbit);
	__set_bit(EV_ABS, input->evbit);
	__set_bit(BTN_TOUCH, input->keybit);
	input_set_abs_params(input, ABS_X, 0, pdata->x_max, 0, 0);
	input_set_abs_params(input, ABS_Y, 0, pdata->y_max, 0, 0);
	input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0);
	input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0);

	tsdata->max_fingers = tsdata->pdata->chip.max_fingers;
	if (tsdata->max_fingers > PIXCIR_MAX_SLOTS) {
		tsdata->max_fingers = PIXCIR_MAX_SLOTS;
		dev_info(dev, "Limiting maximum fingers to %d\n",
			 tsdata->max_fingers);
	}

	error = input_mt_init_slots(input, tsdata->max_fingers,
				    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
	if (error) {
		dev_err(dev, "Error initializing Multi-Touch slots\n");
		return error;
	}

	input_set_drvdata(input, tsdata);

	error = devm_gpio_request_one(dev, pdata->gpio_attb,
				      GPIOF_DIR_IN, "pixcir_i2c_attb");
	if (error) {
		dev_err(dev, "Failed to request ATTB gpio\n");
		return error;
	}

	error = devm_request_threaded_irq(dev, client->irq, NULL, pixcir_ts_isr,
					  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
					  client->name, tsdata);
	if (error) {
		dev_err(dev, "failed to request irq %d\n", client->irq);
		return error;
	}

	/* Always be in IDLE mode to save power, device supports auto wake */
	error = pixcir_set_power_mode(tsdata, PIXCIR_POWER_IDLE);
	if (error) {
		dev_err(dev, "Failed to set IDLE mode\n");
		return error;
	}

	/* Stop device till opened */
	error = pixcir_stop(tsdata);
	if (error)
		return error;

	error = input_register_device(input);
	if (error)
		return error;

	i2c_set_clientdata(client, tsdata);
	device_init_wakeup(&client->dev, 1);

	return 0;
}
コード例 #19
0
static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
		struct hid_field *field, struct hid_usage *usage,
		unsigned long **bit, int *max)
{
	struct mt_device *td = hid_get_drvdata(hdev);
	struct mt_class *cls = td->mtclass;
	__s32 quirks = cls->quirks;

	/* Only map fields from TouchScreen or TouchPad collections.
         * We need to ignore fields that belong to other collections
         * such as Mouse that might have the same GenericDesktop usages. */
	if (field->application == HID_DG_TOUCHSCREEN)
		set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
	else if (field->application == HID_DG_TOUCHPAD)
		set_bit(INPUT_PROP_POINTER, hi->input->propbit);
	else
		return 0;

	switch (usage->hid & HID_USAGE_PAGE) {

	case HID_UP_GENDESK:
		switch (usage->hid) {
		case HID_GD_X:
			if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP)
				field->logical_maximum = 32760;
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_POSITION_X);
			set_abs(hi->input, ABS_MT_POSITION_X, field,
				cls->sn_move);
			/* touchscreen emulation */
			set_abs(hi->input, ABS_X, field, cls->sn_move);
			if (td->last_mt_collection == usage->collection_index) {
				td->last_slot_field = usage->hid;
				td->last_field_index = field->index;
			}
			return 1;
		case HID_GD_Y:
			if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP)
				field->logical_maximum = 32760;
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_POSITION_Y);
			set_abs(hi->input, ABS_MT_POSITION_Y, field,
				cls->sn_move);
			/* touchscreen emulation */
			set_abs(hi->input, ABS_Y, field, cls->sn_move);
			if (td->last_mt_collection == usage->collection_index) {
				td->last_slot_field = usage->hid;
				td->last_field_index = field->index;
			}
			return 1;
		}
		return 0;

	case HID_UP_DIGITIZER:
		switch (usage->hid) {
		case HID_DG_INRANGE:
			if (td->last_mt_collection == usage->collection_index) {
				td->last_slot_field = usage->hid;
				td->last_field_index = field->index;
			}
			return 1;
		case HID_DG_CONFIDENCE:
			if (td->last_mt_collection == usage->collection_index) {
				td->last_slot_field = usage->hid;
				td->last_field_index = field->index;
			}
			return 1;
		case HID_DG_TIPSWITCH:
			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
			input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
			if (td->last_mt_collection == usage->collection_index) {
				td->last_slot_field = usage->hid;
				td->last_field_index = field->index;
			}
			return 1;
		case HID_DG_CONTACTID:
			if (!td->maxcontacts)
				td->maxcontacts = MT_DEFAULT_MAXCONTACT;
			input_mt_init_slots(hi->input, td->maxcontacts);
			td->last_slot_field = usage->hid;
			td->last_field_index = field->index;
			td->last_mt_collection = usage->collection_index;
			return 1;
		case HID_DG_WIDTH:
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_TOUCH_MAJOR);
			set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
				cls->sn_width);
			if (td->last_mt_collection == usage->collection_index) {
				td->last_slot_field = usage->hid;
				td->last_field_index = field->index;
			}
			return 1;
		case HID_DG_HEIGHT:
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_TOUCH_MINOR);
			set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
				cls->sn_height);
			input_set_abs_params(hi->input,
					ABS_MT_ORIENTATION, 0, 1, 0, 0);
			if (td->last_mt_collection == usage->collection_index) {
				td->last_slot_field = usage->hid;
				td->last_field_index = field->index;
			}
			return 1;
		case HID_DG_TIPPRESSURE:
			if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP)
				field->logical_minimum = 0;
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_PRESSURE);
			set_abs(hi->input, ABS_MT_PRESSURE, field,
				cls->sn_pressure);
			/* touchscreen emulation */
			set_abs(hi->input, ABS_PRESSURE, field,
				cls->sn_pressure);
			if (td->last_mt_collection == usage->collection_index) {
				td->last_slot_field = usage->hid;
				td->last_field_index = field->index;
			}
			return 1;
		case HID_DG_CONTACTCOUNT:
			if (td->last_mt_collection == usage->collection_index)
				td->last_field_index = field->index;
			return 1;
		case HID_DG_CONTACTMAX:
			/* we don't set td->last_slot_field as contactcount and
			 * contact max are global to the report */
			if (td->last_mt_collection == usage->collection_index)
				td->last_field_index = field->index;
			return -1;
		}
		/* let hid-input decide for the others */
		return 0;

	case 0xff000000:
		/* we do not want to map these: no input-oriented meaning */
		return -1;
	}

	return 0;
}
コード例 #20
0
ファイル: uinput.c プロジェクト: ricardoanguiano/linux-xlnx
static int uinput_setup_device(struct uinput_device *udev,
                               const char __user *buffer, size_t count)
{
    struct uinput_user_dev	*user_dev;
    struct input_dev	*dev;
    int			i;
    int			retval;

    if (count != sizeof(struct uinput_user_dev))
        return -EINVAL;

    if (!udev->dev) {
        retval = uinput_allocate_device(udev);
        if (retval)
            return retval;
    }

    dev = udev->dev;

    user_dev = memdup_user(buffer, sizeof(struct uinput_user_dev));
    if (IS_ERR(user_dev))
        return PTR_ERR(user_dev);

    udev->ff_effects_max = user_dev->ff_effects_max;

    /* Ensure name is filled in */
    if (!user_dev->name[0]) {
        retval = -EINVAL;
        goto exit;
    }

    kfree(dev->name);
    dev->name = kstrndup(user_dev->name, UINPUT_MAX_NAME_SIZE,
                         GFP_KERNEL);
    if (!dev->name) {
        retval = -ENOMEM;
        goto exit;
    }

    dev->id.bustype	= user_dev->id.bustype;
    dev->id.vendor	= user_dev->id.vendor;
    dev->id.product	= user_dev->id.product;
    dev->id.version	= user_dev->id.version;

    for (i = 0; i < ABS_CNT; i++) {
        input_abs_set_max(dev, i, user_dev->absmax[i]);
        input_abs_set_min(dev, i, user_dev->absmin[i]);
        input_abs_set_fuzz(dev, i, user_dev->absfuzz[i]);
        input_abs_set_flat(dev, i, user_dev->absflat[i]);
    }

    /* check if absmin/absmax/absfuzz/absflat are filled as
     * told in Documentation/input/input-programming.txt */
    if (test_bit(EV_ABS, dev->evbit)) {
        retval = uinput_validate_absbits(dev);
        if (retval < 0)
            goto exit;
        if (test_bit(ABS_MT_SLOT, dev->absbit)) {
            int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
            input_mt_init_slots(dev, nslot, 0);
        } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
            input_set_events_per_packet(dev, 60);
        }
    }

    udev->state = UIST_SETUP_COMPLETE;
    retval = count;

exit:
    kfree(user_dev);
    return retval;
}
コード例 #21
0
ファイル: sis_i2c.c プロジェクト: AlexShiLucky/linux
static int sis_ts_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	struct sis_ts_data *ts;
	struct input_dev *input;
	int error;

	ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
	if (!ts)
		return -ENOMEM;

	ts->client = client;

	ts->attn_gpio = devm_gpiod_get_optional(&client->dev,
						"attn", GPIOD_IN);
	if (IS_ERR(ts->attn_gpio)) {
		error = PTR_ERR(ts->attn_gpio);
		if (error != -EPROBE_DEFER)
			dev_err(&client->dev,
				"Failed to get attention GPIO: %d\n", error);
		return error;
	}

	ts->reset_gpio = devm_gpiod_get_optional(&client->dev,
						 "reset", GPIOD_OUT_LOW);
	if (IS_ERR(ts->reset_gpio)) {
		error = PTR_ERR(ts->reset_gpio);
		if (error != -EPROBE_DEFER)
			dev_err(&client->dev,
				"Failed to get reset GPIO: %d\n", error);
		return error;
	}

	sis_ts_reset(ts);

	ts->input = input = devm_input_allocate_device(&client->dev);
	if (!input) {
		dev_err(&client->dev, "Failed to allocate input device\n");
		return -ENOMEM;
	}

	input->name = "SiS Touchscreen";
	input->id.bustype = BUS_I2C;

	input_set_abs_params(input, ABS_MT_POSITION_X, 0, SIS_MAX_X, 0, 0);
	input_set_abs_params(input, ABS_MT_POSITION_Y, 0, SIS_MAX_Y, 0, 0);
	input_set_abs_params(input, ABS_MT_PRESSURE, 0, SIS_MAX_PRESSURE, 0, 0);
	input_set_abs_params(input, ABS_MT_TOUCH_MAJOR,
			     0, SIS_AREA_LENGTH_LONGER, 0, 0);
	input_set_abs_params(input, ABS_MT_TOUCH_MINOR,
			     0, SIS_AREA_LENGTH_SHORT, 0, 0);

	error = input_mt_init_slots(input, SIS_MAX_FINGERS, INPUT_MT_DIRECT);
	if (error) {
		dev_err(&client->dev,
			"Failed to initialize MT slots: %d\n", error);
		return error;
	}

	error = devm_request_threaded_irq(&client->dev, client->irq,
					  NULL, sis_ts_irq_handler,
					  IRQF_ONESHOT,
					  client->name, ts);
	if (error) {
		dev_err(&client->dev, "Failed to request IRQ: %d\n", error);
		return error;
	}

	error = input_register_device(ts->input);
	if (error) {
		dev_err(&client->dev,
			"Failed to register input device: %d\n", error);
		return error;
	}

	return 0;
}
コード例 #22
0
static int cyttsp5_input_register_device(struct input_dev *input,
		int max_slots)
{
	input_mt_init_slots(input, max_slots, 0);
	return input_register_device(input);
}
コード例 #23
0
static int uinput_setup_device(struct uinput_device *udev, const char __user *buffer, size_t count)
{
	struct uinput_user_dev	*user_dev;
	struct input_dev	*dev;
	char			*name;
	int			size;
	int			retval;

	if (count != sizeof(struct uinput_user_dev))
		return -EINVAL;

	if (!udev->dev) {
		retval = uinput_allocate_device(udev);
		if (retval)
			return retval;
	}

	dev = udev->dev;

	user_dev = kmalloc(sizeof(struct uinput_user_dev), GFP_KERNEL);
	if (!user_dev)
		return -ENOMEM;

	if (copy_from_user(user_dev, buffer, sizeof(struct uinput_user_dev))) {
		retval = -EFAULT;
		goto exit;
	}

	udev->ff_effects_max = user_dev->ff_effects_max;

	size = strnlen(user_dev->name, UINPUT_MAX_NAME_SIZE) + 1;
	if (!size) {
		retval = -EINVAL;
		goto exit;
	}

	kfree(dev->name);
	dev->name = name = kmalloc(size, GFP_KERNEL);
	if (!name) {
		retval = -ENOMEM;
		goto exit;
	}
	strlcpy(name, user_dev->name, size);

	dev->id.bustype	= user_dev->id.bustype;
	dev->id.vendor	= user_dev->id.vendor;
	dev->id.product	= user_dev->id.product;
	dev->id.version	= user_dev->id.version;

	size = sizeof(int) * ABS_CNT;
	memcpy(dev->absmax, user_dev->absmax, size);
	memcpy(dev->absmin, user_dev->absmin, size);
	memcpy(dev->absfuzz, user_dev->absfuzz, size);
	memcpy(dev->absflat, user_dev->absflat, size);

	/* check if absmin/absmax/absfuzz/absflat are filled as
	 * told in Documentation/input/input-programming.txt */
	if (test_bit(EV_ABS, dev->evbit)) {
		retval = uinput_validate_absbits(dev);
		if (retval < 0)
			goto exit;
		if (test_bit(ABS_MT_SLOT, dev->absbit)) {
                    int nslot = 2; //input_abs_get_max(dev, ABS_MT_SLOT) + 1;
			input_mt_init_slots(dev, nslot);
		} else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
			input_set_events_per_packet(dev, 60);
		}
	}

	udev->state = UIST_SETUP_COMPLETE;
	retval = count;

 exit:
	kfree(user_dev);
	return retval;
}
コード例 #24
0
int ct36x_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
	int err = -1;
	int binchksum;
	int updcnt;
	struct ct36x_ts_info *ts;
	struct device *dev;

	if ( CT36X_TS_CORE_DEBUG )
	printk(">>>>> %s() called <<<<< \n", __FUNCTION__);

	dev = &client->dev;
#ifdef CONFIG_OF
	if (ts_com->owner != NULL) return -ENODEV;
	memset(ts_com, 0 ,sizeof(struct touch_pdata));
	ts_com = (struct touch_pdata*)client->dev.platform_data;
	printk("ts_com->owner = %s\n", ts_com->owner);
	ct36x_platform_get_cfg(&ct36x_ts);
	ct36x_ts.client = client;
	i2c_set_clientdata(client, &ct36x_ts);
	ts_com->hardware_reset = ct36x_hw_reset;
	ts_com->read_version = ct36x_read_version;
	ts_com->upgrade_touch = ct36x_upgrade_touch;
#else
	struct ct36x_platform_data *pdata;
	pdata = dev->platform_data;

	if ( pdata ) {
		ct36x_ts.i2c_address = client->addr;
		ct36x_ts.irq = pdata->irq;
		ct36x_ts.rst = pdata->rst;
		ct36x_ts.ss = pdata->ss;
		ct36x_platform_get_cfg(&ct36x_ts);

		ct36x_ts.client = client;
		i2c_set_clientdata(client, &ct36x_ts);
	} else {
		printk("No platform data for device %s.\n", DRIVER_NAME);
	}
	
	plat_data = dev->platform_data;
#endif
	ts = (struct ct36x_ts_info *)i2c_get_clientdata(client);

	/* Create Proc Entry File */
	//ts->proc_entry = create_proc_entry(DRIVER_NAME, 0666/*S_IFREG | S_IRUGO | S_IWUSR*/, NULL);
	ts->proc_entry = proc_create(DRIVER_NAME, 0666/*S_IFREG | S_IRUGO | S_IWUSR*/, NULL, &ct36x_ts_fops);
	if ( ts->proc_entry == NULL ) {
		dev_err(dev, "Failed creating proc dir entry file.\n");
	}
	//else {
		//ts->proc_entry->proc_fops = &ct36x_ts_fops;
	//}

	/* register early suspend */
#ifdef CONFIG_HAS_EARLYSUSPEND
	ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
	ts->early_suspend.suspend = ct36x_early_suspend;
	ts->early_suspend.resume = ct36x_early_resume;
	register_early_suspend(&ts->early_suspend);
#endif

	/* Check I2C Functionality */
	err = i2c_check_functionality(client->adapter, I2C_FUNC_I2C);
	if ( !err ) {
		dev_err(dev, "Check I2C Functionality Failed.\n");
		goto ERR_I2C_CHK;
	}

	/* Request platform resources (gpio/interrupt pins) */
	err = ct36x_platform_get_resource(ts);
	if ( err ) {
		dev_err(dev, "Unable to request platform resource for device %s.\n", DRIVER_NAME);
		goto ERR_PLAT_RSC;
	}

	/* Hardware reset */
	#ifdef CONFIG_OF
	ct36x_platform_hw_reset(ts);
	#else
	ct36x_platform_hw_reset(pdata);
	#endif

	updcnt = 5;
	while (updcnt--) {
		if (ct36x_test_read(client, client->addr, (char *)&binchksum, 1) == 1) 
			break;
	}
	if (updcnt <= 0) {
		printk("ct36x touch not exit!\n");
		goto ERR_PLAT_RSC;
	}
	binchksum = 0;

#ifdef LATE_UPGRADE
	ts_com->upgrade_task = kthread_run(ct36x_late_upgrade, NULL, "ct36x_late_upgrade");
	if (!ts_com->upgrade_task)
		printk("%s creat upgrade process failed\n", __func__);
	else
		printk("%s creat upgrade process sucessful\n", __func__);
#else
	// Get binary Checksum
	binchksum = ct36x_chip_get_binchksum(ts->data.buf);
	if ( CT36X_TS_CORE_DEBUG )
	printk("Bin checksum: 0x%x\n", binchksum);

	// Get firmware Checksum
	fwchksum = ct36x_chip_get_fwchksum(client, ts->data.buf);
	if ( CT36X_TS_CORE_DEBUG )
	printk("Fw checksum: 0x%x\n", fwchksum);
	//while(1){}
	updcnt = 2;
	while ( binchksum != fwchksum && updcnt--) {
		/* Update Firmware */
		ct36x_chip_go_bootloader(client, ts->data.buf);

		/* Hardware reset */
		#ifdef CONFIG_OF
		ct36x_platform_hw_reset(&ct36x_ts);
		#else
		ct36x_platform_hw_reset(plat_data);
		#endif

		// Get firmware Checksum
		fwchksum = ct36x_chip_get_fwchksum(client, ts->data.buf);

		if ( CT36X_TS_CORE_DEBUG )
		printk("Fw checksum: 0x%x\n", fwchksum);
	}
#if defined(CONFIG_TOUCHSCREEN_CT36X_CHIP_CT365)
	ct36x_check_trim(ct36x_ts.client);
#endif
	printk("Fw update %s. 0x%x, 0x%x\n", binchksum != fwchksum ? "Failed" : "Success", binchksum, fwchksum);

	/* Hardware reset */
	#ifdef CONFIG_OF
	ct36x_platform_hw_reset(&ct36x_ts);
	#else
	ct36x_platform_hw_reset(plat_data);
	#endif
#endif
	/* allocate input device */
	ts->input = input_allocate_device();
	if ( !ts->input ) {
		dev_err(dev, "Unable to allocate input device for device %s.\n", DRIVER_NAME);
		err = -ENOMEM;
		goto ERR_INPUT_ALLOC;
	}

	/* config input device */
	__set_bit(EV_SYN, ts->input->evbit);
	__set_bit(EV_KEY, ts->input->evbit);
	__set_bit(EV_ABS, ts->input->evbit);

	__set_bit(INPUT_PROP_DIRECT, ts->input->propbit);
	input_mt_init_slots(ts->input, CT36X_TS_POINT_NUM, 0);

	//input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, CT36X_TS_ABS_X_MAX, 0, 0);
	//input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, CT36X_TS_ABS_Y_MAX, 0, 0);
	#ifdef CONFIG_OF
	if (ts_com->pol & 4)
		swap(ts_com->xres, ts_com->yres);
	input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, ts_com->xres, 0, 0);
	input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, ts_com->yres, 0, 0);
	#else
	input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, plat_data->x_max, 0, 0);
	input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, plat_data->y_max, 0, 0);
	#endif
	input_set_abs_params(ts->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
	input_set_abs_params(ts->input, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
	ts->input->name = DRIVER_NAME;
	ts->input->id.bustype =	BUS_I2C;

	/* register input device */
	err = input_register_device(ts->input);
	if ( err ) {
		dev_err(dev, "Unable to register input device for device %s.\n", DRIVER_NAME);
		goto ERR_INPUT_REGIS;
	}

	/* Create work queue */
	INIT_WORK(&ts->event_work, ct36x_ts_workfunc);
	ts->workqueue = create_singlethread_workqueue(dev_name(&client->dev));

	/* Init irq */
	//gpio_set_status(GPIO_FT_IRQ, gpio_status_in);
  //gpio_irq_set(170, GPIO_IRQ(FT_IRQ-INT_GPIO_0, GPIO_IRQ_FALLING));
	//err = request_irq(ts->irq, ct36x_ts_irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, DRIVER_NAME, ts);
	#ifndef CONFIG_OF
	if (pdata->init_gpio) {
  	pdata->init_gpio();
	}
	#endif
	err = request_irq(ts->irq, ct36x_ts_irq, IRQF_DISABLED,  DRIVER_NAME, ts);
	#ifdef LATE_UPGRADE
	disable_irq(ts->irq);
	#endif
	if ( err ) {
		dev_err(dev, "Unable to request irq for device %s.\n", DRIVER_NAME);
		goto ERR_IRQ_REQ;
	}

	/* Set device is ready */
	ts->state = CT36X_STATE_NORMAL;

	/* power denoisy*/
	//ct36x_chip_set_adapter_on(client, ts->data.buf);
	//ct36x_chip_set_adapter_off(client, ts->data.buf);
	//ct36x_ts_adapter(0);
	create_init(client->dev, ts_com);
	printk("%s: over\n",__func__);
	return 0;

	ERR_IRQ_REQ:
	destroy_workqueue(ts->workqueue);
	ERR_INPUT_REGIS:
	input_free_device(ts->input);
	ERR_INPUT_ALLOC:
	ERR_PLAT_RSC:
	ct36x_platform_put_resource(ts);
	ERR_I2C_CHK:
#ifdef CONFIG_HAS_EARLYSUSPEND
	unregister_early_suspend(&ts->early_suspend);
#endif
	remove_proc_entry(DRIVER_NAME, NULL);
	ts_com->owner = NULL;
	return err;
}
コード例 #25
0
static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
		struct hid_field *field, struct hid_usage *usage,
		unsigned long **bit, int *max)
{
	struct mt_device *td = hid_get_drvdata(hdev);
	struct mt_class *cls = &td->mtclass;
	int code;

	/* Only map fields from TouchScreen or TouchPad collections.
	* We need to ignore fields that belong to other collections
	* such as Mouse that might have the same GenericDesktop usages. */
	if (field->application == HID_DG_TOUCHSCREEN)
		set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
	else if (field->application != HID_DG_TOUCHPAD)
		return 0;

	/* In case of an indirect device (touchpad), we need to add
	 * specific BTN_TOOL_* to be handled by the synaptics xorg
	 * driver.
	 * We also consider that touchscreens providing buttons are touchpads.
	 */
	if (field->application == HID_DG_TOUCHPAD ||
	    (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON ||
	    cls->is_indirect) {
		set_bit(INPUT_PROP_POINTER, hi->input->propbit);
		set_bit(BTN_TOOL_FINGER, hi->input->keybit);
		set_bit(BTN_TOOL_DOUBLETAP, hi->input->keybit);
		set_bit(BTN_TOOL_TRIPLETAP, hi->input->keybit);
		set_bit(BTN_TOOL_QUADTAP, hi->input->keybit);
	}

	/* eGalax devices provide a Digitizer.Stylus input which overrides
	 * the correct Digitizers.Finger X/Y ranges.
	 * Let's just ignore this input. */
	if (field->physical == HID_DG_STYLUS)
		return -1;

	/* Only map fields from TouchScreen or TouchPad collections.
         * We need to ignore fields that belong to other collections
         * such as Mouse that might have the same GenericDesktop usages. */
	if (field->application == HID_DG_TOUCHSCREEN)
		set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
	else if (field->application == HID_DG_TOUCHPAD)
		set_bit(INPUT_PROP_POINTER, hi->input->propbit);
	else
		return 0;

	switch (usage->hid & HID_USAGE_PAGE) {

	case HID_UP_GENDESK:
		switch (usage->hid) {
		case HID_GD_X:
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_POSITION_X);
			set_abs(hi->input, ABS_MT_POSITION_X, field,
				cls->sn_move);
			/* touchscreen emulation */
			set_abs(hi->input, ABS_X, field, cls->sn_move);
			mt_store_field(usage, td, hi);
			td->last_field_index = field->index;
			return 1;
		case HID_GD_Y:
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_POSITION_Y);
			set_abs(hi->input, ABS_MT_POSITION_Y, field,
				cls->sn_move);
			/* touchscreen emulation */
			set_abs(hi->input, ABS_Y, field, cls->sn_move);
			mt_store_field(usage, td, hi);
			td->last_field_index = field->index;
			return 1;
		}
		return 0;

	case HID_UP_DIGITIZER:
		switch (usage->hid) {
		case HID_DG_INRANGE:
			mt_store_field(usage, td, hi);
			td->last_field_index = field->index;
			return 1;
		case HID_DG_CONFIDENCE:
			mt_store_field(usage, td, hi);
			td->last_field_index = field->index;
			return 1;
		case HID_DG_TIPSWITCH:
			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
			input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
			mt_store_field(usage, td, hi);
			td->last_field_index = field->index;
			return 1;
		case HID_DG_CONTACTID:
			if (!td->maxcontacts)
				td->maxcontacts = MT_DEFAULT_MAXCONTACT;
			input_mt_init_slots(hi->input, td->maxcontacts);
			mt_store_field(usage, td, hi);
			td->last_field_index = field->index;
			td->touches_by_report++;
			return 1;
		case HID_DG_WIDTH:
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_TOUCH_MAJOR);
			set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
				cls->sn_width);
			mt_store_field(usage, td, hi);
			td->last_field_index = field->index;
			return 1;
		case HID_DG_HEIGHT:
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_TOUCH_MINOR);
			set_abs(hi->input, ABS_MT_TOUCH_MINOR, field,
				cls->sn_height);
			input_set_abs_params(hi->input,
					ABS_MT_ORIENTATION, 0, 1, 0, 0);
			mt_store_field(usage, td, hi);
			td->last_field_index = field->index;
			return 1;
		case HID_DG_TIPPRESSURE:
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_PRESSURE);
			set_abs(hi->input, ABS_MT_PRESSURE, field,
				cls->sn_pressure);
			/* touchscreen emulation */
			set_abs(hi->input, ABS_PRESSURE, field,
				cls->sn_pressure);
			mt_store_field(usage, td, hi);
			td->last_field_index = field->index;
			return 1;
		case HID_DG_CONTACTCOUNT:
			td->last_field_index = field->index;
			return 1;
		case HID_DG_CONTACTMAX:
			/* we don't set td->last_slot_field as contactcount and
			 * contact max are global to the report */
			td->last_field_index = field->index;
			return -1;
		}
		case HID_DG_TOUCH:
			/* Legacy devices use TIPSWITCH and not TOUCH.
			 * Let's just ignore this field. */
			return -1;
		/* let hid-input decide for the others */
		return 0;

	case HID_UP_BUTTON:
		code = BTN_MOUSE + ((usage->hid - 1) & HID_USAGE);
		hid_map_usage(hi, usage, bit, max, EV_KEY, code);
		input_set_capability(hi->input, EV_KEY, code);
		return 1;

	case 0xff000000:
		/* we do not want to map these: no input-oriented meaning */
		return -1;
	}

	return 0;
}
コード例 #26
0
static int pm_connect(struct serio *serio, struct serio_driver *drv)
{
	struct pm *pm;
	struct input_dev *input_dev;
	int max_x, max_y;
	int err;

	pm = kzalloc(sizeof(struct pm), GFP_KERNEL);
	input_dev = input_allocate_device();
	if (!pm || !input_dev) {
		err = -ENOMEM;
		goto fail1;
	}

	pm->serio = serio;
	pm->dev = input_dev;
	snprintf(pm->phys, sizeof(pm->phys), "%s/input0", serio->phys);
	pm->maxcontacts = 1;

	input_dev->name = "PenMount Serial TouchScreen";
	input_dev->phys = pm->phys;
	input_dev->id.bustype = BUS_RS232;
	input_dev->id.vendor = SERIO_PENMOUNT;
	input_dev->id.product = 0;
	input_dev->id.version = 0x0100;
	input_dev->dev.parent = &serio->dev;

	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);

	switch (serio->id.id) {
	default:
	case 0:
		pm->packetsize = 5;
		pm->parse_packet = pm_parse_9000;
		input_dev->id.product = 0x9000;
		max_x = max_y = 0x3ff;
		break;

	case 1:
		pm->packetsize = 6;
		pm->parse_packet = pm_parse_6000;
		input_dev->id.product = 0x6000;
		max_x = max_y = 0x3ff;
		break;

	case 2:
		pm->packetsize = 6;
		pm->parse_packet = pm_parse_3000;
		input_dev->id.product = 0x3000;
		max_x = max_y = 0x7ff;
		pm->maxcontacts = PM_3000_MTSLOT;
		break;

	case 3:
		pm->packetsize = 6;
		pm->parse_packet = pm_parse_6250;
		input_dev->id.product = 0x6250;
		max_x = max_y = 0x3ff;
		pm->maxcontacts = PM_6250_MTSLOT;
		break;
	}

	input_set_abs_params(pm->dev, ABS_X, 0, max_x, 0, 0);
	input_set_abs_params(pm->dev, ABS_Y, 0, max_y, 0, 0);

	if (pm->maxcontacts > 1) {
		input_mt_init_slots(pm->dev, pm->maxcontacts);
		input_set_abs_params(pm->dev,
				     ABS_MT_POSITION_X, 0, max_x, 0, 0);
		input_set_abs_params(pm->dev,
				     ABS_MT_POSITION_Y, 0, max_y, 0, 0);
	}

	serio_set_drvdata(serio, pm);

	err = serio_open(serio, drv);
	if (err)
		goto fail2;

	err = input_register_device(pm->dev);
	if (err)
		goto fail3;

	return 0;

 fail3:	serio_close(serio);
 fail2:	serio_set_drvdata(serio, NULL);
 fail1:	input_free_device(input_dev);
	kfree(pm);
	return err;
}
コード例 #27
0
ファイル: hid-multitouch.c プロジェクト: ANFS/ANFS-kernel
static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
		struct hid_field *field, struct hid_usage *usage,
		unsigned long **bit, int *max)
{
	struct mt_device *td = hid_get_drvdata(hdev);
	struct mt_class *cls = td->mtclass;
	switch (usage->hid & HID_USAGE_PAGE) {

	case HID_UP_GENDESK:
		switch (usage->hid) {
		case HID_GD_X:
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_POSITION_X);
			set_abs(hi->input, ABS_MT_POSITION_X, field,
				cls->sn_move);
			/* touchscreen emulation */
			set_abs(hi->input, ABS_X, field, cls->sn_move);
			td->last_slot_field = usage->hid;
			return 1;
		case HID_GD_Y:
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_POSITION_Y);
			set_abs(hi->input, ABS_MT_POSITION_Y, field,
				cls->sn_move);
			/* touchscreen emulation */
			set_abs(hi->input, ABS_Y, field, cls->sn_move);
			td->last_slot_field = usage->hid;
			return 1;
		}
		return 0;

	case HID_UP_DIGITIZER:
		switch (usage->hid) {
		case HID_DG_INRANGE:
			td->last_slot_field = usage->hid;
			return 1;
		case HID_DG_CONFIDENCE:
			td->last_slot_field = usage->hid;
			return 1;
		case HID_DG_TIPSWITCH:
			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
			input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
			td->last_slot_field = usage->hid;
			return 1;
		case HID_DG_CONTACTID:
			input_mt_init_slots(hi->input,
					td->mtclass->maxcontacts);
			td->last_slot_field = usage->hid;
			return 1;
		case HID_DG_WIDTH:
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_TOUCH_MAJOR);
			td->last_slot_field = usage->hid;
			return 1;
		case HID_DG_HEIGHT:
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_TOUCH_MINOR);
			field->logical_maximum = 1;
			field->logical_minimum = 0;
			set_abs(hi->input, ABS_MT_ORIENTATION, field, 0);
			td->last_slot_field = usage->hid;
			return 1;
		case HID_DG_TIPPRESSURE:
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_PRESSURE);
			set_abs(hi->input, ABS_MT_PRESSURE, field,
				cls->sn_pressure);
			/* touchscreen emulation */
			set_abs(hi->input, ABS_PRESSURE, field,
				cls->sn_pressure);
			td->last_slot_field = usage->hid;
			return 1;
		case HID_DG_CONTACTCOUNT:
			td->last_field_index = field->report->maxfield - 1;
			return 1;
		case HID_DG_CONTACTMAX:
			/* we don't set td->last_slot_field as contactcount and
			 * contact max are global to the report */
			return -1;
		}
		/* let hid-input decide for the others */
		return 0;

	case 0xff000000:
		/* we do not want to map these: no input-oriented meaning */
		return -1;
	}

	return 0;
}
コード例 #28
0
static int cyttsp4_input_register_device(struct input_dev *input, int max_tchs)
{
	/* max num slots equals max touches + 1 for hover */
	input_mt_init_slots(input, max_tchs + 1);//modified by linghai interim because of the input-mt.c change
	return input_register_device(input);
}
コード例 #29
0
/*******************************************************	
功能:
	触摸屏探测函数
	在注册驱动时调用(要求存在对应的client);
	用于IO,中断等资源申请;设备注册;触摸屏初始化等工作
参数:
	client:待驱动的设备结构体
	id:设备ID
return:
	执行结果码,0表示正常执行
********************************************************/
static int goodix_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
	struct goodix_ts_data *ts;
	int ret = 0;
	int retry=0;
	int ret1 = -1;
	//int count=0;

	struct goodix_i2c_rmi_platform_data *pdata = client->dev.platform_data;
	if (!pdata) {		// gModify.Add
		dev_err(&client->dev, "platform data is required!\n");
		return -EINVAL;
	}
	int INT_PORT  = pdata ->gpio_irq;
	int SHUTDOWN_PORT  = pdata->gpio_shutdown;
	if (!SHUTDOWN_PORT  || !INT_PORT) {
	    ret = -1;
	    printk(KERN_ALERT  "goodix platform data error\n");
	    goto err_check_functionality_failed ;
	}
	dev_dbg(&client->dev,"Install touchscreen driver for guitar.\n");
	//Check I2C function
	
	ret=i2c_write_bytes(client,pdata->config_info,pdata->config_info_len);
	if (ret < 0){
		printk("I2C transfer error in panel init");
		goto error_i2c_transfer;
	}
	msleep(1);
	
	ret = gpio_request(SHUTDOWN_PORT, "TS_SHUTDOWN");	//Request IO
	if (ret < 0)
	{
		printk(KERN_ALERT "Failed to request GPIO:%d, ERRNO:%d\n",(int)SHUTDOWN_PORT,ret);
		goto err_check_functionality_failed;
	}
	gpio_direction_output(SHUTDOWN_PORT, 0);	//Touchscreen is waiting to wakeup
	ret = gpio_get_value(SHUTDOWN_PORT);
	if (ret)
	{
		printk(KERN_ALERT  "Cannot set touchscreen to work.\n");
		goto err_check_functionality_failed;
	}								//waite guitar start
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) 
	{
		dev_err(&client->dev, "System need I2C function.\n");
		ret = -ENODEV;
		goto err_check_functionality_failed;
	}

	i2c_connect_client = client;	//used by Guitar Updating.
	/* gModify.unCmmt
	msleep(16);
	for(retry=0; retry < 5; retry++)
	{
		ret =i2c_write_bytes(client, NULL, 0);	//Test i2c.
		if (ret > 0)
			break;
	}
	if(ret < 0)
	{
		dev_err(&client->dev, "Warnning: I2C connection might be something wrong!\n");
		//ret = -ENOSYS;
		//goto err_i2c_failed;
	} */

//	gpio_set_value(SHUTDOWN_PORT, 1);		//suspend
	ts = kzalloc(sizeof(*ts), GFP_KERNEL);
	if (ts == NULL) {
		ret = -ENOMEM;
		goto err_alloc_data_failed;
	}
	
	INIT_WORK(&ts->work, goodix_ts_work_func);
	ts->client = client;
	i2c_set_clientdata(client, ts);
	
	ts->input_dev = input_allocate_device();
	if (ts->input_dev == NULL) {
		ret = -ENOMEM;
		dev_dbg(&client->dev," In File:%s Function:%s Failed to allocate input device\n", __FILE__, __func__);
		goto err_input_dev_alloc_failed;
	}

#if 0
	ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS) ;
	ts->input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
	ts->input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y); // for android

	//#ifdef GOODIX_MULTI_TOUCH	//used by android 1.x for multi-touch, not realized
	//ts->input_dev->absbit[0]=BIT(ABS_HAT0X) |BIT(ABS_HAT0Y);
	//ts->input_dev->keybit[BIT_WORD(BTN_2)] = BIT_MASK(BTN_2);
	//#endif

	input_set_abs_params(ts->input_dev, ABS_X, 0, pdata->xmax, 0, 0);
	input_set_abs_params(ts->input_dev, ABS_Y, 0, pdata->ymax, 0, 0);
	input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 255, 0, 0);
#endif

#ifdef GOODIX_MULTI_TOUCH
	ts->input_dev->name = "Goodix TouchScreen of Guitar";
	ts->input_dev->phys = "I2C";
	ts->input_dev->id.bustype = BUS_I2C;
	ts->input_dev->id.vendor = 0x0EEF;
	ts->input_dev->id.product = 0x0020;
	
	//hkw add
//	input_set_capability(ts->input_dev, EV_KEY, EV_KEY);
	input_set_capability(ts->input_dev, EV_KEY, KEY_BACK);
	input_set_capability(ts->input_dev, EV_KEY, KEY_HOMEPAGE);
	input_set_capability(ts->input_dev, EV_KEY, KEY_MENU);
	
	__set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
	__set_bit(EV_ABS, ts->input_dev->evbit);
	
	input_mt_init_slots(ts->input_dev, MAX_FINGER_NUM);
	input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0, pdata->xmax, 0, 0);
	input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0, pdata->ymax, 0, 0);
	input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
	input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
#endif	



	finger_list.length = 0;
	ret = input_register_device(ts->input_dev);
	if (ret) {
		dev_err(&client->dev,"Probe: Unable to register %s input device\n", ts->input_dev->name);
		goto err_input_register_device_failed;
	}

	gpio_set_value(SHUTDOWN_PORT, 0);
	msleep(10);
	
	/*
	ret1=goodix_init_panel(ts);
	if(ret1 < 0)
		goto err_init_godix_ts;
	*/	
//	goodix_read_version(ts);
	msleep(500);

	ts->init_finished = 0;
	ts->use_irq = 0;
	ts->retry=0;
	ts->bad_data = 0;
	if (client->irq)
	{
		ret = gpio_request(INT_PORT, "TS_INT");	//Request IO
		if (ret < 0)
		{
			dev_err(&client->dev, "Failed to request GPIO:%d, ERRNO:%d\n",(int)INT_PORT,ret);
			goto err_gpio_request_failed;
		}
		/* set input mode */
		gpio_direction_input(INT_PORT);
		//gpio_enable_edge_int(gpio_to_idx(INT_PORT),	// gModify.unCmmt
		//         pdata->irq_edge, client->irq - INT_GPIO_0);
		ret  = request_irq(gpio_to_irq(client->irq), goodix_ts_irq_handler,
				IRQF_TRIGGER_FALLING, client->name, ts);
		if (ret != 0) {
			dev_err(&client->dev,"Can't allocate touchscreen's interrupt!ERRNO:%d\n", ret);
			gpio_free( INT_PORT);
			goto err_gpio_request_failed;
		}
		else
		{
//			disable_irq(client->irq);
			ts->use_irq = 1;
			dev_info(&client->dev,"Requestt EIRQ %d succesd on GPIO:%d\n",client->irq,INT_PORT);
		}
	}

err_gpio_request_failed:
	if (!ts->use_irq) 
	{
		hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
		ts->timer.function = goodix_ts_timer_func;
		hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
	}
	
#ifdef CONFIG_HAS_EARLYSUSPEND
	ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
	ts->early_suspend.suspend = goodix_ts_early_suspend;
	ts->early_suspend.resume = goodix_ts_late_resume;
	register_early_suspend(&ts->early_suspend);
#endif
	dev_info(&client->dev,"Start  %s in %s mode\n", 
		ts->input_dev->name, ts->use_irq ? "Interrupt" : "Polling\n");
	return 0;

err_init_godix_ts:
	if(ts->use_irq)
		free_irq(client->irq,ts);
	gpio_request(INT_PORT,"TS_INT");
	gpio_free(INT_PORT);

err_input_register_device_failed:
	input_free_device(ts->input_dev);

err_input_dev_alloc_failed:
	i2c_set_clientdata(client, NULL);
	kfree(ts);
err_i2c_failed:
	gpio_direction_input(SHUTDOWN_PORT);
	gpio_free(SHUTDOWN_PORT);
error_i2c_transfer:
err_alloc_data_failed:
err_check_functionality_failed:
	return ret;
}
コード例 #30
0
static int gsl_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
	struct gsl_ts_data *ts;
	const struct firmware *fw = NULL;
	unsigned long irqflags;
	int error;
	bool acpipower;

	dev_warn(&client->dev, "%s: got a device named %s at address 0x%x, IRQ %d, flags 0x%x\n", __func__, client->name, client->addr, client->irq, client->flags);

	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
		dev_err(&client->dev, "%s: i2c check functionality error\n", __func__);
		error = -ENXIO;
		goto release;
	}

	if (client->irq <= 0) {
		dev_err(&client->dev, "%s: missing IRQ configuration\n", __func__);
		error = -ENODEV;
		goto release;
	}
	
	ts = devm_kzalloc(&client->dev, sizeof(struct gsl_ts_data), GFP_KERNEL);
	if (!ts) {
		error = -ENOMEM;
		goto release;
	}
	
	ts->client = client;
	i2c_set_clientdata(client, ts);
	
	if (gsl_fw_name != NULL) {
		strncpy(ts->fw_name, gsl_fw_name, sizeof(ts->fw_name));
	} else {
		strncpy(ts->fw_name, GSL_FW_NAME_DEFAULT, sizeof(ts->fw_name));
	}
	error = request_firmware(&fw, ts->fw_name, &ts->client->dev);
	if (error < 0) {
		dev_err(&client->dev, "%s: failed to load firmware: %d\n", __func__, error);
		goto release;
	}

	error = gsl_ts_init(ts, fw);
	if (error < 0) {
		dev_err(&client->dev, "%s: failed to initialize: %d\n", __func__, error);
		goto release;
	}

	ts->input = devm_input_allocate_device(&client->dev);
	if (!ts->input) {
		dev_err(&client->dev, "%s: failed to allocate input device\n", __func__);
		error = -ENOMEM;
		goto release;
	}

	ts->input->name = "Silead GSLx680 Touchscreen";
	ts->input->id.bustype = BUS_I2C;
	ts->input->phys = "input/ts";

	input_set_capability(ts->input, EV_ABS, ABS_X);
	input_set_capability(ts->input, EV_ABS, ABS_Y);

	input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, ts->x_max, ts->jitter, ts->deadzone);
	input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, ts->y_max, ts->jitter, ts->deadzone);

	input_mt_init_slots(ts->input, ts->multi_touches, INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED | INPUT_MT_TRACK);

	input_set_drvdata(ts->input, ts);

	error = input_register_device(ts->input);
	if (error) {
		dev_err(&client->dev, "%s: unable to register input device: %d\n", __func__, error);
		goto release;
	}

	/* Try to use ACPI power methods first */
	acpipower = false;
#ifdef CONFIG_ACPI
	if (ACPI_COMPANION(&client->dev)) {
		/* Wake the device up with a power on reset */
		if (acpi_bus_set_power(ACPI_HANDLE(&client->dev), ACPI_STATE_D3)) {
			dev_warn(&client->dev, "%s: failed to wake up device through ACPI: %d, using GPIO controls instead\n", __func__, error);
		} else {
			acpipower = true;
		}
	}
#endif
	/* Not available, use GPIO settings from DSDT/DT instead */
	if (!acpipower) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
		ts->gpio = devm_gpiod_get_index(&client->dev, GSL_PWR_GPIO, 0);
#else
		ts->gpio = devm_gpiod_get_index(&client->dev, GSL_PWR_GPIO, 0, GPIOD_OUT_LOW);
#endif
		if (IS_ERR(ts->gpio)) {
			dev_err(&client->dev, "%s: error obtaining power pin GPIO resource\n", __func__);
			error = PTR_ERR(ts->gpio);
			goto release;
		}
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)
		error = gpiod_direction_output(ts->gpio, 0);
		if (error < 0) {
			dev_err(&client->dev, "%s: error setting GPIO pin direction\n", __func__);
			goto release;
		}
#endif
	} else {
		ts->gpio = NULL;
	}

	/* Enable power */
	gsl_ts_power(client, false);

	/* Execute the controller startup sequence */
	error = gsl_ts_reset_chip(client);
	if (error < 0) {
		dev_err(&client->dev, "%s: chip reset failed\n", __func__);
		goto release;
	}
	error = gsl_ts_write_fw(ts, fw);
	if (error < 0) {
		dev_err(&client->dev, "%s: firmware transfer failed\n", __func__);
		goto release;
	}
	error = gsl_ts_startup_chip(client);
	if (error < 0) {
		dev_err(&client->dev, "%s: chip startup failed\n", __func__);
		goto release;
	}

	/*
	 * Systems using device tree should set up interrupt via DTS,
	 * the rest will use the default falling edge interrupts.
	 */
	irqflags = client->dev.of_node ? 0 : IRQF_TRIGGER_FALLING;

	/* Set up interrupt handler - do we still need to account for shared interrupts? */
	error = devm_request_threaded_irq(
		&client->dev,
		client->irq,
		NULL,
		gsl_ts_irq,
		irqflags | IRQF_ONESHOT,
		client->name,
		ts
	);
	if (error) {
		dev_err(&client->dev, "%s: failed to register interrupt\n", __func__);
		goto release;
	}

	/*
	 * Systems using device tree should set up wakeup via DTS,
	 * the rest will configure device as wakeup source by default.
	 */
	if (!client->dev.of_node) {
		device_init_wakeup(&client->dev, true);
	}

	ts->state = GSL_TS_GREEN;

release:
	if (fw) {
		release_firmware(fw);
	}

	if (error < 0) {
		return error;
	}
	return 0;
}