*/
static void psmouse_disconnect(struct serio *serio)
{
- struct psmouse *psmouse, *parent = NULL;
-
- psmouse = serio_get_drvdata(serio);
+ struct psmouse *psmouse = serio_get_drvdata(serio);
+ struct psmouse *parent = NULL;
sysfs_remove_group(&serio->dev.kobj, &psmouse_attribute_group);
serio_close(serio);
serio_set_drvdata(serio, NULL);
- input_unregister_device(psmouse->dev);
+
+ if (psmouse->dev)
+ input_unregister_device(psmouse->dev);
+
kfree(psmouse);
if (parent)
psmouse_switch_protocol(psmouse, NULL);
- psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
- psmouse_initialize(psmouse);
+ if (!psmouse->protocol->smbus_companion) {
+ psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
+ psmouse_initialize(psmouse);
- error = input_register_device(psmouse->dev);
- if (error)
- goto err_protocol_disconnect;
+ error = input_register_device(input_dev);
+ if (error)
+ goto err_protocol_disconnect;
+ } else {
+ /* Smbus companion will be reporting events, not us. */
+ input_free_device(input_dev);
+ psmouse->dev = input_dev = NULL;
+ }
if (parent && parent->pt_activate)
parent->pt_activate(parent);
if (error)
goto err_pt_deactivate;
- psmouse_activate(psmouse);
+ /*
+ * PS/2 devices having SMBus companions should stay disabled
+ * on PS/2 side, in order to have SMBus part operable.
+ */
+ if (!psmouse->protocol->smbus_companion)
+ psmouse_activate(psmouse);
out:
/* If this is a pass-through port the parent needs to be re-activated */
err_pt_deactivate:
if (parent && parent->pt_deactivate)
parent->pt_deactivate(parent);
- input_unregister_device(psmouse->dev);
- input_dev = NULL; /* so we don't try to free it below */
+ if (input_dev) {
+ input_unregister_device(input_dev);
+ input_dev = NULL; /* so we don't try to free it below */
+ }
err_protocol_disconnect:
if (psmouse->disconnect)
psmouse->disconnect(psmouse);
* OK, the device type (and capabilities) match the old one,
* we can continue using it, complete initialization
*/
- psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
-
- psmouse_initialize(psmouse);
+ if (!psmouse->protocol->smbus_companion) {
+ psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
+ psmouse_initialize(psmouse);
+ }
if (parent && parent->pt_activate)
parent->pt_activate(parent);
- psmouse_activate(psmouse);
+ /*
+ * PS/2 devices having SMBus companions should stay disabled
+ * on PS/2 side, in order to have SMBus part operable.
+ */
+ if (!psmouse->protocol->smbus_companion)
+ psmouse_activate(psmouse);
+
rc = 0;
out:
{
struct serio *serio = to_serio_port(dev);
struct psmouse_attribute *attr = to_psmouse_attr(devattr);
- struct psmouse *psmouse;
+ struct psmouse *psmouse = serio_get_drvdata(serio);
- psmouse = serio_get_drvdata(serio);
+ if (psmouse->protocol->smbus_companion &&
+ devattr != &psmouse_attr_protocol.dattr)
+ return -ENOENT;
return attr->show(psmouse, attr->data, buf);
}
psmouse = serio_get_drvdata(serio);
+ if (psmouse->protocol->smbus_companion &&
+ devattr != &psmouse_attr_protocol.dattr) {
+ retval = -ENOENT;
+ goto out_unlock;
+ }
+
if (attr->protect) {
if (psmouse->state == PSMOUSE_IGNORE) {
retval = -ENODEV;
psmouse_deactivate(parent);
}
- psmouse_deactivate(psmouse);
+ if (!psmouse->protocol->smbus_companion)
+ psmouse_deactivate(psmouse);
}
retval = attr->set(psmouse, attr->data, buf, count);
if (attr->protect) {
- if (retval != -ENODEV)
+ if (retval != -ENODEV && !psmouse->protocol->smbus_companion)
psmouse_activate(psmouse);
if (parent)
psmouse_initialize(psmouse);
psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
- error = input_register_device(psmouse->dev);
- if (error) {
- if (psmouse->disconnect)
- psmouse->disconnect(psmouse);
+ if (psmouse->protocol->smbus_companion) {
+ input_free_device(psmouse->dev);
+ psmouse->dev = NULL;
+ } else {
+ error = input_register_device(psmouse->dev);
+ if (error) {
+ if (psmouse->disconnect)
+ psmouse->disconnect(psmouse);
- psmouse_set_state(psmouse, PSMOUSE_IGNORE);
- input_free_device(new_dev);
- psmouse->dev = old_dev;
- psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
- psmouse_switch_protocol(psmouse, old_proto);
- psmouse_initialize(psmouse);
- psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
+ psmouse_set_state(psmouse, PSMOUSE_IGNORE);
+ input_free_device(new_dev);
+ psmouse->dev = old_dev;
+ psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
+ psmouse_switch_protocol(psmouse, old_proto);
+ psmouse_initialize(psmouse);
+ psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
- return error;
+ return error;
+ }
}
- input_unregister_device(old_dev);
+ if (old_dev)
+ input_unregister_device(old_dev);
if (parent && parent->pt_activate)
parent->pt_activate(parent);