blob: aeb12ae2b688e59fbab77c8bdd742872540fe4cc [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_DEVICES_I2C_LIB_DEVICE_PROTOCOL_I2C_CHANNEL_INCLUDE_LIB_DEVICE_PROTOCOL_I2C_CHANNEL_H_
#define SRC_DEVICES_I2C_LIB_DEVICE_PROTOCOL_I2C_CHANNEL_INCLUDE_LIB_DEVICE_PROTOCOL_I2C_CHANNEL_H_
#include <lib/device-protocol/i2c.h>
#include <lib/sync/completion.h>
#include <zircon/types.h>
#include <ddktl/protocol/composite.h>
#include <ddktl/protocol/i2c.h>
namespace ddk {
class I2cChannel : public I2cProtocolClient {
public:
struct StatusRetries {
zx_status_t status;
uint8_t retries;
};
I2cChannel() {}
I2cChannel(const i2c_protocol_t* proto) : I2cProtocolClient(proto) {}
I2cChannel(zx_device_t* parent) : I2cProtocolClient(parent) {}
I2cChannel(ddk::CompositeProtocolClient& composite, const char* fragment_name)
: I2cProtocolClient(composite, fragment_name) {}
~I2cChannel() = default;
// Performs typical i2c Read: writes device register address (1 byte) followed
// by len reads into buf.
zx_status_t ReadSync(uint8_t addr, uint8_t* buf, size_t len) {
return WriteReadSync(&addr, 1, buf, len);
}
// Writes len bytes from buffer with no trailing read
zx_status_t WriteSync(const uint8_t* buf, size_t len) {
return WriteReadSync(buf, len, nullptr, 0);
}
zx_status_t WriteReadSync(const uint8_t* tx_buf, size_t tx_len, uint8_t* rx_buf, size_t rx_len) {
i2c_protocol_t proto;
GetProto(&proto);
return i2c_write_read_sync(&proto, tx_buf, tx_len, rx_buf, rx_len);
}
// ReadSync with retries, returns status and retry attempts.
StatusRetries ReadSyncRetries(uint8_t addr, uint8_t* buf, size_t len, uint8_t retries,
zx::duration delay) {
return WriteReadSyncRetries(&addr, 1, buf, len, retries, delay);
}
// WriteSync with retries, returns status and retry attempts.
StatusRetries WriteSyncRetries(const uint8_t* buf, size_t len, uint8_t retries,
zx::duration delay) {
return WriteReadSyncRetries(buf, len, nullptr, 0, retries, delay);
}
// WriteReadSync with retries, returns status and retry attempts.
StatusRetries WriteReadSyncRetries(const uint8_t* tx_buf, size_t tx_len, uint8_t* rx_buf,
size_t rx_len, uint8_t retries, zx::duration delay) {
i2c_protocol_t proto;
GetProto(&proto);
uint8_t attempt = 0;
auto status = i2c_write_read_sync(&proto, tx_buf, tx_len, rx_buf, rx_len);
while (status != ZX_OK && attempt < retries) {
zx::nanosleep(zx::deadline_after(delay));
attempt++;
status = i2c_write_read_sync(&proto, tx_buf, tx_len, rx_buf, rx_len);
}
return {status, attempt};
}
};
} // namespace ddk
#endif // SRC_DEVICES_I2C_LIB_DEVICE_PROTOCOL_I2C_CHANNEL_INCLUDE_LIB_DEVICE_PROTOCOL_I2C_CHANNEL_H_