Merge branch 'ib/4.17-xen-kbdfront-runtime-config' into next
Bring in xen-kbdfront changes.
此提交包含在:
@@ -63,6 +63,9 @@ static void xenkbd_disconnect_backend(struct xenkbd_info *);
|
||||
static void xenkbd_handle_motion_event(struct xenkbd_info *info,
|
||||
struct xenkbd_motion *motion)
|
||||
{
|
||||
if (unlikely(!info->ptr))
|
||||
return;
|
||||
|
||||
input_report_rel(info->ptr, REL_X, motion->rel_x);
|
||||
input_report_rel(info->ptr, REL_Y, motion->rel_y);
|
||||
if (motion->rel_z)
|
||||
@@ -73,6 +76,9 @@ static void xenkbd_handle_motion_event(struct xenkbd_info *info,
|
||||
static void xenkbd_handle_position_event(struct xenkbd_info *info,
|
||||
struct xenkbd_position *pos)
|
||||
{
|
||||
if (unlikely(!info->ptr))
|
||||
return;
|
||||
|
||||
input_report_abs(info->ptr, ABS_X, pos->abs_x);
|
||||
input_report_abs(info->ptr, ABS_Y, pos->abs_y);
|
||||
if (pos->rel_z)
|
||||
@@ -97,6 +103,9 @@ static void xenkbd_handle_key_event(struct xenkbd_info *info,
|
||||
return;
|
||||
}
|
||||
|
||||
if (unlikely(!dev))
|
||||
return;
|
||||
|
||||
input_event(dev, EV_KEY, key->keycode, value);
|
||||
input_sync(dev);
|
||||
}
|
||||
@@ -192,7 +201,7 @@ static int xenkbd_probe(struct xenbus_device *dev,
|
||||
const struct xenbus_device_id *id)
|
||||
{
|
||||
int ret, i;
|
||||
unsigned int abs, touch;
|
||||
bool with_mtouch, with_kbd, with_ptr;
|
||||
struct xenkbd_info *info;
|
||||
struct input_dev *kbd, *ptr, *mtouch;
|
||||
|
||||
@@ -211,106 +220,127 @@ static int xenkbd_probe(struct xenbus_device *dev,
|
||||
if (!info->page)
|
||||
goto error_nomem;
|
||||
|
||||
/* Set input abs params to match backend screen res */
|
||||
abs = xenbus_read_unsigned(dev->otherend,
|
||||
XENKBD_FIELD_FEAT_ABS_POINTER, 0);
|
||||
ptr_size[KPARAM_X] = xenbus_read_unsigned(dev->otherend,
|
||||
XENKBD_FIELD_WIDTH,
|
||||
ptr_size[KPARAM_X]);
|
||||
ptr_size[KPARAM_Y] = xenbus_read_unsigned(dev->otherend,
|
||||
XENKBD_FIELD_HEIGHT,
|
||||
ptr_size[KPARAM_Y]);
|
||||
if (abs) {
|
||||
ret = xenbus_write(XBT_NIL, dev->nodename,
|
||||
XENKBD_FIELD_REQ_ABS_POINTER, "1");
|
||||
if (ret) {
|
||||
pr_warn("xenkbd: can't request abs-pointer\n");
|
||||
abs = 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* The below are reverse logic, e.g. if the feature is set, then
|
||||
* do not expose the corresponding virtual device.
|
||||
*/
|
||||
with_kbd = !xenbus_read_unsigned(dev->otherend,
|
||||
XENKBD_FIELD_FEAT_DSBL_KEYBRD, 0);
|
||||
|
||||
touch = xenbus_read_unsigned(dev->nodename,
|
||||
XENKBD_FIELD_FEAT_MTOUCH, 0);
|
||||
if (touch) {
|
||||
with_ptr = !xenbus_read_unsigned(dev->otherend,
|
||||
XENKBD_FIELD_FEAT_DSBL_POINTER, 0);
|
||||
|
||||
/* Direct logic: if set, then create multi-touch device. */
|
||||
with_mtouch = xenbus_read_unsigned(dev->otherend,
|
||||
XENKBD_FIELD_FEAT_MTOUCH, 0);
|
||||
if (with_mtouch) {
|
||||
ret = xenbus_write(XBT_NIL, dev->nodename,
|
||||
XENKBD_FIELD_REQ_MTOUCH, "1");
|
||||
if (ret) {
|
||||
pr_warn("xenkbd: can't request multi-touch");
|
||||
touch = 0;
|
||||
with_mtouch = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* keyboard */
|
||||
kbd = input_allocate_device();
|
||||
if (!kbd)
|
||||
goto error_nomem;
|
||||
kbd->name = "Xen Virtual Keyboard";
|
||||
kbd->phys = info->phys;
|
||||
kbd->id.bustype = BUS_PCI;
|
||||
kbd->id.vendor = 0x5853;
|
||||
kbd->id.product = 0xffff;
|
||||
if (with_kbd) {
|
||||
kbd = input_allocate_device();
|
||||
if (!kbd)
|
||||
goto error_nomem;
|
||||
kbd->name = "Xen Virtual Keyboard";
|
||||
kbd->phys = info->phys;
|
||||
kbd->id.bustype = BUS_PCI;
|
||||
kbd->id.vendor = 0x5853;
|
||||
kbd->id.product = 0xffff;
|
||||
|
||||
__set_bit(EV_KEY, kbd->evbit);
|
||||
for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
|
||||
__set_bit(i, kbd->keybit);
|
||||
for (i = KEY_OK; i < KEY_MAX; i++)
|
||||
__set_bit(i, kbd->keybit);
|
||||
__set_bit(EV_KEY, kbd->evbit);
|
||||
for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
|
||||
__set_bit(i, kbd->keybit);
|
||||
for (i = KEY_OK; i < KEY_MAX; i++)
|
||||
__set_bit(i, kbd->keybit);
|
||||
|
||||
ret = input_register_device(kbd);
|
||||
if (ret) {
|
||||
input_free_device(kbd);
|
||||
xenbus_dev_fatal(dev, ret, "input_register_device(kbd)");
|
||||
goto error;
|
||||
ret = input_register_device(kbd);
|
||||
if (ret) {
|
||||
input_free_device(kbd);
|
||||
xenbus_dev_fatal(dev, ret,
|
||||
"input_register_device(kbd)");
|
||||
goto error;
|
||||
}
|
||||
info->kbd = kbd;
|
||||
}
|
||||
info->kbd = kbd;
|
||||
|
||||
/* pointing device */
|
||||
ptr = input_allocate_device();
|
||||
if (!ptr)
|
||||
goto error_nomem;
|
||||
ptr->name = "Xen Virtual Pointer";
|
||||
ptr->phys = info->phys;
|
||||
ptr->id.bustype = BUS_PCI;
|
||||
ptr->id.vendor = 0x5853;
|
||||
ptr->id.product = 0xfffe;
|
||||
if (with_ptr) {
|
||||
unsigned int abs;
|
||||
|
||||
if (abs) {
|
||||
__set_bit(EV_ABS, ptr->evbit);
|
||||
input_set_abs_params(ptr, ABS_X, 0, ptr_size[KPARAM_X], 0, 0);
|
||||
input_set_abs_params(ptr, ABS_Y, 0, ptr_size[KPARAM_Y], 0, 0);
|
||||
} else {
|
||||
input_set_capability(ptr, EV_REL, REL_X);
|
||||
input_set_capability(ptr, EV_REL, REL_Y);
|
||||
/* Set input abs params to match backend screen res */
|
||||
abs = xenbus_read_unsigned(dev->otherend,
|
||||
XENKBD_FIELD_FEAT_ABS_POINTER, 0);
|
||||
ptr_size[KPARAM_X] = xenbus_read_unsigned(dev->otherend,
|
||||
XENKBD_FIELD_WIDTH,
|
||||
ptr_size[KPARAM_X]);
|
||||
ptr_size[KPARAM_Y] = xenbus_read_unsigned(dev->otherend,
|
||||
XENKBD_FIELD_HEIGHT,
|
||||
ptr_size[KPARAM_Y]);
|
||||
if (abs) {
|
||||
ret = xenbus_write(XBT_NIL, dev->nodename,
|
||||
XENKBD_FIELD_REQ_ABS_POINTER, "1");
|
||||
if (ret) {
|
||||
pr_warn("xenkbd: can't request abs-pointer\n");
|
||||
abs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ptr = input_allocate_device();
|
||||
if (!ptr)
|
||||
goto error_nomem;
|
||||
ptr->name = "Xen Virtual Pointer";
|
||||
ptr->phys = info->phys;
|
||||
ptr->id.bustype = BUS_PCI;
|
||||
ptr->id.vendor = 0x5853;
|
||||
ptr->id.product = 0xfffe;
|
||||
|
||||
if (abs) {
|
||||
__set_bit(EV_ABS, ptr->evbit);
|
||||
input_set_abs_params(ptr, ABS_X, 0,
|
||||
ptr_size[KPARAM_X], 0, 0);
|
||||
input_set_abs_params(ptr, ABS_Y, 0,
|
||||
ptr_size[KPARAM_Y], 0, 0);
|
||||
} else {
|
||||
input_set_capability(ptr, EV_REL, REL_X);
|
||||
input_set_capability(ptr, EV_REL, REL_Y);
|
||||
}
|
||||
input_set_capability(ptr, EV_REL, REL_WHEEL);
|
||||
|
||||
__set_bit(EV_KEY, ptr->evbit);
|
||||
for (i = BTN_LEFT; i <= BTN_TASK; i++)
|
||||
__set_bit(i, ptr->keybit);
|
||||
|
||||
ret = input_register_device(ptr);
|
||||
if (ret) {
|
||||
input_free_device(ptr);
|
||||
xenbus_dev_fatal(dev, ret,
|
||||
"input_register_device(ptr)");
|
||||
goto error;
|
||||
}
|
||||
info->ptr = ptr;
|
||||
}
|
||||
input_set_capability(ptr, EV_REL, REL_WHEEL);
|
||||
|
||||
__set_bit(EV_KEY, ptr->evbit);
|
||||
for (i = BTN_LEFT; i <= BTN_TASK; i++)
|
||||
__set_bit(i, ptr->keybit);
|
||||
|
||||
ret = input_register_device(ptr);
|
||||
if (ret) {
|
||||
input_free_device(ptr);
|
||||
xenbus_dev_fatal(dev, ret, "input_register_device(ptr)");
|
||||
goto error;
|
||||
}
|
||||
info->ptr = ptr;
|
||||
|
||||
/* multi-touch device */
|
||||
if (touch) {
|
||||
if (with_mtouch) {
|
||||
int num_cont, width, height;
|
||||
|
||||
mtouch = input_allocate_device();
|
||||
if (!mtouch)
|
||||
goto error_nomem;
|
||||
|
||||
num_cont = xenbus_read_unsigned(info->xbdev->nodename,
|
||||
num_cont = xenbus_read_unsigned(info->xbdev->otherend,
|
||||
XENKBD_FIELD_MT_NUM_CONTACTS,
|
||||
1);
|
||||
width = xenbus_read_unsigned(info->xbdev->nodename,
|
||||
width = xenbus_read_unsigned(info->xbdev->otherend,
|
||||
XENKBD_FIELD_MT_WIDTH,
|
||||
XENFB_WIDTH);
|
||||
height = xenbus_read_unsigned(info->xbdev->nodename,
|
||||
height = xenbus_read_unsigned(info->xbdev->otherend,
|
||||
XENKBD_FIELD_MT_HEIGHT,
|
||||
XENFB_HEIGHT);
|
||||
|
||||
@@ -346,6 +376,11 @@ static int xenkbd_probe(struct xenbus_device *dev,
|
||||
info->mtouch = mtouch;
|
||||
}
|
||||
|
||||
if (!(with_kbd || with_ptr || with_mtouch)) {
|
||||
ret = -ENXIO;
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = xenkbd_connect_backend(dev, info);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
@@ -130,7 +130,7 @@ static int elan_smbus_get_baseline_data(struct i2c_client *client,
|
||||
bool max_baseline, u8 *value)
|
||||
{
|
||||
int error;
|
||||
u8 val[3];
|
||||
u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
|
||||
|
||||
error = i2c_smbus_read_block_data(client,
|
||||
max_baseline ?
|
||||
@@ -149,7 +149,7 @@ static int elan_smbus_get_version(struct i2c_client *client,
|
||||
bool iap, u8 *version)
|
||||
{
|
||||
int error;
|
||||
u8 val[3];
|
||||
u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
|
||||
|
||||
error = i2c_smbus_read_block_data(client,
|
||||
iap ? ETP_SMBUS_IAP_VERSION_CMD :
|
||||
@@ -170,7 +170,7 @@ static int elan_smbus_get_sm_version(struct i2c_client *client,
|
||||
u8 *clickpad)
|
||||
{
|
||||
int error;
|
||||
u8 val[3];
|
||||
u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
|
||||
|
||||
error = i2c_smbus_read_block_data(client,
|
||||
ETP_SMBUS_SM_VERSION_CMD, val);
|
||||
@@ -188,7 +188,7 @@ static int elan_smbus_get_sm_version(struct i2c_client *client,
|
||||
static int elan_smbus_get_product_id(struct i2c_client *client, u16 *id)
|
||||
{
|
||||
int error;
|
||||
u8 val[3];
|
||||
u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
|
||||
|
||||
error = i2c_smbus_read_block_data(client,
|
||||
ETP_SMBUS_UNIQUEID_CMD, val);
|
||||
@@ -205,7 +205,7 @@ static int elan_smbus_get_checksum(struct i2c_client *client,
|
||||
bool iap, u16 *csum)
|
||||
{
|
||||
int error;
|
||||
u8 val[3];
|
||||
u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
|
||||
|
||||
error = i2c_smbus_read_block_data(client,
|
||||
iap ? ETP_SMBUS_FW_CHECKSUM_CMD :
|
||||
@@ -226,7 +226,7 @@ static int elan_smbus_get_max(struct i2c_client *client,
|
||||
{
|
||||
int ret;
|
||||
int error;
|
||||
u8 val[3];
|
||||
u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
|
||||
|
||||
ret = i2c_smbus_read_block_data(client, ETP_SMBUS_RANGE_CMD, val);
|
||||
if (ret != 3) {
|
||||
@@ -246,7 +246,7 @@ static int elan_smbus_get_resolution(struct i2c_client *client,
|
||||
{
|
||||
int ret;
|
||||
int error;
|
||||
u8 val[3];
|
||||
u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
|
||||
|
||||
ret = i2c_smbus_read_block_data(client, ETP_SMBUS_RESOLUTION_CMD, val);
|
||||
if (ret != 3) {
|
||||
@@ -267,7 +267,7 @@ static int elan_smbus_get_num_traces(struct i2c_client *client,
|
||||
{
|
||||
int ret;
|
||||
int error;
|
||||
u8 val[3];
|
||||
u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
|
||||
|
||||
ret = i2c_smbus_read_block_data(client, ETP_SMBUS_XY_TRACENUM_CMD, val);
|
||||
if (ret != 3) {
|
||||
@@ -294,7 +294,7 @@ static int elan_smbus_iap_get_mode(struct i2c_client *client,
|
||||
{
|
||||
int error;
|
||||
u16 constant;
|
||||
u8 val[3];
|
||||
u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
|
||||
|
||||
error = i2c_smbus_read_block_data(client, ETP_SMBUS_IAP_CTRL_CMD, val);
|
||||
if (error < 0) {
|
||||
@@ -345,7 +345,7 @@ static int elan_smbus_prepare_fw_update(struct i2c_client *client)
|
||||
int len;
|
||||
int error;
|
||||
enum tp_mode mode;
|
||||
u8 val[3];
|
||||
u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
|
||||
u8 cmd[4] = {0x0F, 0x78, 0x00, 0x06};
|
||||
u16 password;
|
||||
|
||||
@@ -419,7 +419,7 @@ static int elan_smbus_write_fw_block(struct i2c_client *client,
|
||||
struct device *dev = &client->dev;
|
||||
int error;
|
||||
u16 result;
|
||||
u8 val[3];
|
||||
u8 val[I2C_SMBUS_BLOCK_MAX] = {0};
|
||||
|
||||
/*
|
||||
* Due to the limitation of smbus protocol limiting
|
||||
|
@@ -172,6 +172,12 @@ static const char * const smbus_pnp_ids[] = {
|
||||
"LEN0048", /* X1 Carbon 3 */
|
||||
"LEN0046", /* X250 */
|
||||
"LEN004a", /* W541 */
|
||||
"LEN0071", /* T480 */
|
||||
"LEN0072", /* X1 Carbon Gen 5 (2017) - Elan/ALPS trackpoint */
|
||||
"LEN0073", /* X1 Carbon G5 (Elantech) */
|
||||
"LEN0092", /* X1 Carbon 6 */
|
||||
"LEN0096", /* X280 */
|
||||
"LEN0097", /* X280 -> ALPS trackpoint */
|
||||
"LEN200f", /* T450s */
|
||||
NULL
|
||||
};
|
||||
|
新增問題並參考
封鎖使用者