/* * Responses the controller sends as a result of * command requests
*/ #define RESPONSE_DEACTIVATE 0x00 #define RESPONSE_INITIALIZE 0x01 #define RESPONSE_RESOLUTION 0x02 #define RESPONSE_SETCONFIG 0x03 #define RESPONSE_SCANFREQ 0x08 #define RESPONSE_STATUS 0X1e
/* * Notifications are sent by the touch controller without * being requested by the driver and include for example * touch indications
*/ #define NOTIFICATION_TOUCH 0x04 #define NOTIFICATION_BOOTCOMPLETE 0x07 #define NOTIFICATION_OVERRUN 0x25 #define NOTIFICATION_PROXIMITY 0x26 #define NOTIFICATION_INVALID_COMMAND 0xfe
struct zforce_point { int coord_x; int coord_y; int state; int id; int area_major; int area_minor; int orientation; int pressure; int prblty;
};
/* * @client the i2c_client * @input the input device * @suspending in the process of going to suspend (don't emit wakeup * events for commands executed to suspend the device) * @suspended device suspended * @command_done completion to wait for the command result * @command_waiting the id of the command that is currently waiting * for a result * @command_result returned result of the command
*/ struct zforce_ts { struct i2c_client *client; struct input_dev *input; struct touchscreen_properties prop; char phys[32];
/* * When still suspended, return. * Due to the level-interrupt we will get re-triggered later.
*/ if (ts->suspended) {
msleep(20); return IRQ_HANDLED;
}
dev_dbg(&client->dev, "handling interrupt\n");
/* Don't emit wakeup events from commands run by zforce_suspend */
suspending = READ_ONCE(ts->suspending); if (!suspending && device_may_wakeup(&client->dev))
pm_stay_awake(&client->dev);
/* * Run at least once and exit the loop if * - the optional interrupt GPIO isn't specified * (there is only one packet read per ISR invocation, then) * or * - the GPIO isn't active any more * (packet read until the level GPIO indicates that there is * no IRQ any more)
*/ do {
error = zforce_read_packet(ts, payload_buffer); if (error) {
dev_err(&client->dev, "could not read packet, ret: %d\n", error); break;
}
payload = &payload_buffer[PAYLOAD_BODY];
switch (payload[RESPONSE_ID]) { case NOTIFICATION_TOUCH: /* * Always report touch-events received while * suspending, when being a wakeup source
*/ if (suspending && device_may_wakeup(&client->dev))
pm_wakeup_event(&client->dev, 500);
zforce_touch_event(ts, &payload[RESPONSE_DATA]); break;
case NOTIFICATION_BOOTCOMPLETE:
ts->boot_complete = payload[RESPONSE_DATA];
zforce_complete(ts, payload[RESPONSE_ID], 0); break;
case RESPONSE_INITIALIZE: case RESPONSE_DEACTIVATE: case RESPONSE_SETCONFIG: case RESPONSE_RESOLUTION: case RESPONSE_SCANFREQ:
zforce_complete(ts, payload[RESPONSE_ID],
payload[RESPONSE_DATA]); break;
/* * When configured as a wakeup source device should always wake * the system, therefore start device if necessary.
*/ if (device_may_wakeup(&client->dev)) {
dev_dbg(&client->dev, "suspend while being a wakeup source\n");
/* Need to start device, if not open, to be a wakeup source. */ if (!input_device_enabled(input)) {
error = zforce_start(ts); if (error) return error;
}
enable_irq_wake(client->irq);
} elseif (input_device_enabled(input)) {
dev_dbg(&client->dev, "suspend without being a wakeup source\n");
if (device_may_wakeup(&client->dev)) {
dev_dbg(&client->dev, "resume from being a wakeup source\n");
disable_irq_wake(client->irq);
/* need to stop device if it was not open on suspend */ if (!input_device_enabled(input)) {
error = zforce_stop(ts); if (error) return error;
}
} elseif (input_device_enabled(input)) {
dev_dbg(&client->dev, "resume without being a wakeup source\n");
enable_irq(client->irq);
error = zforce_start(ts); if (error) return error;
}
error = input_mt_init_slots(input_dev, ZFORCE_REPORT_POINTS,
INPUT_MT_DIRECT); if (error) return error;
input_set_drvdata(ts->input, ts);
init_completion(&ts->command_done);
/* * The zforce pulls the interrupt low when it has data ready. * After it is triggered the isr thread runs until all the available * packets have been read and the interrupt is high again. * Therefore we can trigger the interrupt anytime it is low and do * not need to limit it to the interrupt edge.
*/
error = devm_request_threaded_irq(&client->dev, client->irq,
zforce_irq, zforce_irq_thread,
IRQF_ONESHOT, input_dev->name, ts); if (error) return dev_err_probe(&client->dev, error, "irq %d request failed\n", client->irq);
i2c_set_clientdata(client, ts);
/* let the controller boot */
gpiod_set_value_cansleep(ts->gpio_rst, 0);
/* need to start device to get version information */
error = zforce_command_wait(ts, COMMAND_INITIALIZE); if (error) return dev_err_probe(&client->dev, error, "unable to initialize\n");
/* this gets the firmware version among other information */
error = zforce_command_wait(ts, COMMAND_STATUS); if (error) {
dev_err_probe(&client->dev, error, "couldn't get status\n");
zforce_stop(ts); return error;
}
/* stop device and put it into sleep until it is opened */
error = zforce_stop(ts); if (error) return error;
device_set_wakeup_capable(&client->dev, true);
error = input_register_device(input_dev); if (error) return dev_err_probe(&client->dev, error, "could not register input device\n");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.