1
0
Fork 0

Setting up sample rate by writing position rate report.

pull/10/head
Thomas Ingebretsen 2019-05-30 00:58:58 +02:00 committed by Steinar Bakkemo
parent 676f0a2e29
commit 130bf89b14
1 changed files with 152 additions and 59 deletions

View File

@ -25,6 +25,38 @@
#include <linux/reset.h>
#include <linux/delay.h>
// Bitmasks (for data[3])
#define WACOM_TIP_SWITCH_bm (1 << 0)
#define WACOM_BARREL_SWITCH_bm (1 << 1)
#define WACOM_ERASER_bm (1 << 2)
#define WACOM_INVERT_bm (1 << 3)
// Registers
#define WACOM_COMMAND_LSB 0x04
#define WACOM_COMMAND_MSB 0x00
#define WACOM_DATA_LSB 0x05
#define WACOM_DATA_MSB 0x00
// Report types
#define REPORT_INPUT 0x10
#define REPORT_OUTPUT 0x20
#define REPORT_FEATURE 0x30
// Requests / operations
#define OPCODE_RESET 0x01
#define OPCODE_GET_REPORT 0x02
#define OPCODE_SET_REPORT 0x03
#define OPCODE_SET_POWER 0x08
// Power settings
#define POWER_ON 0x00
#define POWER_SLEEP 0x01
// Report ids
#define WACOM_POSITION_RATE_REPORT 0x19
#define WACOM_MAX_DATA_SIZE 20
struct wacom_features {
@ -46,6 +78,20 @@ struct wacom_i2c {
int tool;
};
u8 wakeup_cmd[] = {
WACOM_COMMAND_LSB,
WACOM_COMMAND_MSB,
POWER_ON,
OPCODE_SET_POWER,
};
u8 sleep_cmd[] = {
WACOM_COMMAND_LSB,
WACOM_COMMAND_MSB,
POWER_SLEEP,
OPCODE_SET_POWER,
};
//#define GPIO_TEST_LED 174
static int wacom_query_device(struct i2c_client *client,
@ -55,51 +101,19 @@ static int wacom_query_device(struct i2c_client *client,
u8 data[WACOM_MAX_DATA_SIZE];
struct reset_control *rstc;
u8 set_sample_rate_cmd[] = {
0x04, // COMMAND_REGISTER LSB
0x00, // COMMAND_REGISTER MSB
0x3F, // Feature (0b0011) + ReportID: (0b1111) (sentinel value)
0x03, // Op-code: SET_REPORT
0x19, // Actual ReportID: (0b11001) (25 / 0x19)
};
u8 set_sample_rate_data[] = {
0x05, // DATA_REGISTER LSB
0x00, // DATA_REGISTER MSB
0x04, // LENGTH LSB
0x00, // LENGTH MSB
0x19, // ReportID (0x19 = Position Report Rate)
0x06, // Selected rate (1=240pps, 3=360pps (def), 5=480pps, 6=540pps)
};
u8 get_query_data_cmd[] = {
0x04, // COMMAND_REGISTER LSB
0x00, // COMMAND_REGISTER MSB
0x33, // Feature (0b0011) + ReportID: (0b0011) (3)
0x02, // Op-code: GET_REPORT
};
// TODO: No need for repeated start condition?
u8 read_data[] = {
0x05, // DATA_REGISTER LSB
0x00, // DATA_REGISTER MSB
};
struct i2c_msg msgs[] = {
#if 0
// Request writing of feature, ReportID 24 / Position Report Rate
{
.addr = client->addr,
.flags = 0,
.len = sizeof(set_sample_rate_cmd),
.buf = set_sample_rate_cmd,
},
// Set sample rate data
{
.addr = client->addr,
.flags = 0,
.len = sizeof(set_sample_rate_data),
.buf = set_sample_rate_data,
},
#endif
// Request reading of feature ReportID: 3 (Pen Query Data)
{
.addr = client->addr,
@ -123,6 +137,7 @@ static int wacom_query_device(struct i2c_client *client,
},
};
printk("[---- SBA ----] Asserting/deasserting WACOM reset ..\n");
rstc = devm_reset_control_get_optional_exclusive(&client->dev, NULL);
if (IS_ERR(rstc)) {
@ -143,6 +158,8 @@ static int wacom_query_device(struct i2c_client *client,
return -EIO;
}
printk("[---- SBA ----] query report (%d) length: %d\n", data[2], data[0] + 256*data[1]);
features->x_max = get_unaligned_le16(&data[3]);
features->y_max = get_unaligned_le16(&data[5]);
features->pressure_max = get_unaligned_le16(&data[11]);
@ -164,45 +181,115 @@ static int wacom_query_device(struct i2c_client *client,
return 0;
}
static int wacom_setup_device(struct i2c_client *client)
{
int ret;
u8 data[WACOM_MAX_DATA_SIZE];
u8 get_sample_rate_cmd[] = {
WACOM_COMMAND_LSB,
WACOM_COMMAND_MSB,
REPORT_FEATURE | 0xF,
OPCODE_GET_REPORT,
WACOM_POSITION_RATE_REPORT,
WACOM_DATA_LSB,
WACOM_DATA_MSB,
};
u8 set_sample_rate_cmd[] = {
WACOM_COMMAND_LSB,
WACOM_COMMAND_MSB,
REPORT_FEATURE | 0xF,
OPCODE_SET_REPORT,
WACOM_POSITION_RATE_REPORT,
WACOM_DATA_LSB,
WACOM_DATA_MSB,
0x04, // LENGTH LSB
0x00, // LENGTH MSB
WACOM_POSITION_RATE_REPORT,
0x05, // Selected rate (1=240pps, 3=360pps (def), 5=480pps, 6=540pps)
};
struct i2c_msg msgs[] = {
// Request writing of feature, ReportID 25 / Position Report Rate
{
.addr = client->addr,
.flags = 0,
.len = sizeof(set_sample_rate_cmd),
.buf = set_sample_rate_cmd,
},
};
struct i2c_msg msgs_readback[] = {
// Request reading of feature, ReportID 25 / Position Report Rate
{
.addr = client->addr,
.flags = 0,
.len = sizeof(get_sample_rate_cmd),
.buf = get_sample_rate_cmd,
},
// Read 4 bytes
{
.addr = client->addr,
.flags = I2C_M_RD,
.len = 4,
.buf = data,
},
};
printk("[---- SBA ----] Writing sample rate..\n");
ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
if (ret < 0) {
printk("[---- SBA ----] i2c_transfer returned with errorcode %d\n", ret);
return ret;
}
if (ret != ARRAY_SIZE(msgs)) {
printk("[---- SBA ----] i2c_transfer returned with unexpected return value %d\n", ret);
return -EIO;
}
printk("[---- SBA ----] Reading sample rate..\n");
ret = i2c_transfer(client->adapter, msgs_readback, ARRAY_SIZE(msgs_readback));
if (ret < 0) {
printk("[---- SBA ----] i2c_transfer returned with errorcode %d\n", ret);
return ret;
}
if (ret != ARRAY_SIZE(msgs_readback)) {
printk("[---- SBA ----] i2c_transfer returned with unexpected return value %d\n", ret);
return -EIO;
}
printk("[---- SBA ----] Rate report: %x %x %x %x ..\n", data[0], data[1], data[2], data[3]);
return 0;
}
static irqreturn_t wacom_i2c_irq(int irq, void *dev_id)
{
#if 0
static unsigned count = 0;
static int turnoff = 0;
if (count++ > 500) {
count = 0;
if (turnoff) {
gpio_set_value(GPIO_TEST_LED, 1);
turnoff = 0;
} else {
gpio_set_value(GPIO_TEST_LED, 0);
turnoff = 1;
}
//printk("lol\n");
}
#endif
struct wacom_i2c *wac_i2c = dev_id;
struct input_dev *input = wac_i2c->input;
u8 *data = wac_i2c->data;
unsigned int x, y, z, pressure;
unsigned char tip, f1, f2, eraser, distance;
unsigned int x, y, pressure;
unsigned char tip, f1, f2, eraser, distance, transducer = 0;
short tilt_x, tilt_y;
int error;
// TODO: Should continue to read packets until DIGITIZER_INT is pulled high
//gpio_set_value(GPIO_TEST_LED, 1);
#if 1
error = i2c_master_recv(wac_i2c->client,
wac_i2c->data, 17);
#else
// Skip bus locking
const struct i2c_client *client = wac_i2c->client;
struct i2c_adapter *adap = client->adapter;
struct i2c_msg msg;
msg.addr = client->addr;
msg.flags = client->flags & I2C_M_TEN;
msg.flags |= I2C_M_RD;
msg.len = 15;
msg.len = 17;
msg.buf = wac_i2c->data;
error = __i2c_transfer(adap, &msg, 1);
#endif
@ -212,11 +299,9 @@ static irqreturn_t wacom_i2c_irq(int irq, void *dev_id)
if (error < 0)
goto out;
//TODO: Check ReportID (CP Pen = 2, Chinonome Refill = 26)
// data[0] == Length LSB
// data[1] == Length MSB
// data[2] == ReportID (2)
// data[2] == ReportID (2 | 26)
tip = data[3] & 0x01;
eraser = data[3] & 0x04;
f1 = data[3] & 0x02;
@ -224,16 +309,20 @@ static irqreturn_t wacom_i2c_irq(int irq, void *dev_id)
x = le16_to_cpup((__le16 *)&data[4]);
y = le16_to_cpup((__le16 *)&data[6]);
pressure = le16_to_cpup((__le16 *)&data[8]);
distance = data[10];
// Shinonome Refill has a transducer index field:
if (data[2] == 26) {
transducer = (data[3] >> 6);
}
// Tilt (signed)
tilt_x = le16_to_cpup((__le16 *)&data[11]);
tilt_y = le16_to_cpup((__le16 *)&data[13]);
// Hover height
//z = le16_to_cpup((__le16 *)&data[15]);
distance = le16_to_cpup((__le16 *)&data[15]);
// Toggle GPIO 174:
// Toggle LED GPIO:
#if 0
if (x > 10484) {
gpio_set_value(GPIO_TEST_LED, 1);
@ -254,7 +343,6 @@ static irqreturn_t wacom_i2c_irq(int irq, void *dev_id)
input_report_key(input, BTN_STYLUS2, f2);
input_report_abs(input, ABS_X, x);
input_report_abs(input, ABS_Y, y);
//input_report_abs(input, ABS_Z, z);
input_report_abs(input, ABS_PRESSURE, pressure);
input_report_abs(input, ABS_DISTANCE, distance);
input_report_abs(input, ABS_TILT_X, tilt_x);
@ -341,6 +429,11 @@ static int wacom_i2c_probe(struct i2c_client *client,
if (error)
return error;
printk("[---- SBA ----] Setting up device ..\n");
error = wacom_setup_device(client);
if (error)
return error;
printk("[---- SBA ----] Allocating memory to hold device info..\n");
wac_i2c = kzalloc(sizeof(*wac_i2c), GFP_KERNEL);