/* Check if for SMBus new version device by reading version byte. */
retval = i2c_smbus_read_byte_data(client, SMB_PROTOCOL_VERSION_ADDRESS); if (retval < 0) {
dev_err(&client->dev, "failed to get SMBus version number!\n"); return retval;
}
/* * The function to get command code for smbus operations and keeps * records to the driver mapping table
*/ staticint rmi_smb_get_command_code(struct rmi_transport_dev *xport,
u16 rmiaddr, int bytecount, bool isread, u8 *commandcode)
{ struct rmi_smb_xport *rmi_smb =
container_of(xport, struct rmi_smb_xport, xport); struct mapping_table_entry new_map; int i; int retval = 0;
mutex_lock(&rmi_smb->mappingtable_mutex);
for (i = 0; i < RMI_SMB2_MAP_SIZE; i++) { struct mapping_table_entry *entry = &rmi_smb->mapping_table[i];
if (le16_to_cpu(entry->rmiaddr) == rmiaddr) { if (isread) { if (entry->readcount == bytecount) gotoexit;
} else { if (entry->flags & RMI_SMB2_MAP_FLAGS_WE) { gotoexit;
}
}
}
}
i = rmi_smb->table_index;
rmi_smb->table_index = (i + 1) % RMI_SMB2_MAP_SIZE;
retval = smb_block_write(xport, i + 0x80, &new_map, sizeof(new_map)); if (retval < 0) { /* * if not written to device mapping table * clear the driver mapping table records
*/
memset(&new_map, 0, sizeof(new_map));
}
/* save to the driver level mapping table */
rmi_smb->mapping_table[i] = new_map;
staticvoid rmi_smb_clear_state(struct rmi_smb_xport *rmi_smb)
{ /* the mapping table has been flushed, discard the current one */
mutex_lock(&rmi_smb->mappingtable_mutex);
memset(rmi_smb->mapping_table, 0, sizeof(rmi_smb->mapping_table));
mutex_unlock(&rmi_smb->mappingtable_mutex);
}
/* * psmouse driver resets the controller, we only need to wait * to give the firmware chance to fully reinitialize.
*/ if (rmi_smb->xport.pdata.reset_delay_ms)
msleep(rmi_smb->xport.pdata.reset_delay_ms);
/* we need to get the smbus version to activate the touchpad */
smbus_version = rmi_smb_get_version(rmi_smb); if (smbus_version < 0) return smbus_version;
rmi_dbg(RMI_DEBUG_XPORT, &client->dev, "Smbus version is %d",
smbus_version);
if (smbus_version != 2 && smbus_version != 3) {
dev_err(&client->dev, "Unrecognized SMB version %d\n",
smbus_version); return -ENODEV;
}
/* * We do not call the actual reset command, it has to be handled in * PS/2 or there will be races between PS/2 and SMBus. PS/2 should * ensure that a psmouse_reset is called before initializing the * device and after it has been removed to be in a known state.
*/ return rmi_smb_enable_smbus_mode(rmi_smb);
}
if (!pdata) {
dev_err(&client->dev, "no platform data, aborting\n"); return -ENOMEM;
}
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_READ_BLOCK_DATA |
I2C_FUNC_SMBUS_HOST_NOTIFY)) {
dev_err(&client->dev, "adapter does not support required functionality\n"); return -ENODEV;
}
if (client->irq <= 0) {
dev_err(&client->dev, "no IRQ provided, giving up\n"); return client->irq ? client->irq : -ENODEV;
}
rmi_smb = devm_kzalloc(&client->dev, sizeof(struct rmi_smb_xport),
GFP_KERNEL); if (!rmi_smb) return -ENOMEM;
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.