Skip to content

Commit

Permalink
Update device wake
Browse files Browse the repository at this point in the history
Move wake to io operations, as the means of pulling SDA to low
depends on the capabilities of the I2C driver.

Improve wake on i2c_linux. SDA is now pulled low continuously,
by transmitting to address 0x00.

Update s96at_wake() to return S96AT_STATUS_READY on wake.

Signed-off-by: Michalis Pappas <[email protected]>
  • Loading branch information
michpappas authored and jbech-linaro committed May 17, 2018
1 parent 9732134 commit 21747e3
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 25 deletions.
4 changes: 0 additions & 4 deletions s96at/include/cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,6 @@ enum {
#define PKT_FUNC_IDLE 0x2
#define PKT_FUNC_COMMAND 0x3

#define CMD_WAKEUP 0x0

/* OP-codes for each command, see section 8.5.4 in spec */
#define OPCODE_DERIVEKEY 0x1c
#define OPCODE_DEVREV 0x30
Expand Down Expand Up @@ -155,8 +153,6 @@ uint8_t cmd_update_extra(struct io_interface *ioif, uint8_t mode, uint8_t value)
uint8_t cmd_gen_dig(struct io_interface *ioif, const uint8_t *in, size_t in_size,
uint8_t zone, uint16_t slotnbr);

bool cmd_wake(struct io_interface *ioif);

uint8_t cmd_write(struct io_interface *ioif, uint8_t zone, uint8_t addr,
bool encrypted, const uint8_t *data, size_t size);
#endif
2 changes: 2 additions & 0 deletions s96at/include/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ struct io_interface {
size_t (*write)(void *ctx, const void *buf, size_t size);
size_t (*read)(void *ctx, void *buf, size_t size);
uint32_t (*close)(void *ctx);
uint32_t (*wake)(void *ctx);
};

uint32_t register_io_interface(uint8_t io_interface_type,
Expand All @@ -37,6 +38,7 @@ int at204_write(struct io_interface *ioif, void *buf, size_t size);
int at204_write2(struct io_interface *ioif, struct cmd_packet *p);
int at204_read(struct io_interface *ioif, void *buf, size_t size);
int at204_close(struct io_interface *ioif);
int at204_wake(struct io_interface *ioif);
int at204_msg(struct io_interface *ioif, struct cmd_packet *p, void *resp_buf,
size_t size);
#endif
3 changes: 2 additions & 1 deletion s96at/include/s96at.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#define S96AT_STATUS_OK 0x00
#define S96AT_STATUS_CHECKMAC_FAIL 0x01
#define S96AT_STATUS_EXEC_ERROR 0x0f
#define S96AT_STATUS_READY 0x11
#define S96AT_STATUS_PADDING_ERROR 0x98
#define S96AT_STATUS_BAD_PARAMETERS 0x99

Expand Down Expand Up @@ -396,7 +397,7 @@ uint8_t s96at_read(struct s96at_desc *desc, enum s96at_zone zone, uint8_t id, ui
* current command execution or IO state. It is therefore required that all operations
* are completed within S96AT_WATCHDOG_TIME.
*
* Returns S96AT_STATUS_OK on success, otherwise S96AT_STATUS_EXEC_ERROR.
* Returns S96AT_STATUS_READY on device wake, otherwise S96AT_STATUS_EXEC_ERROR.
*/
uint8_t s96at_wake(struct s96at_desc *desc);

Expand Down
15 changes: 0 additions & 15 deletions s96at/src/cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,21 +102,6 @@ void get_command(struct cmd_packet *p, uint8_t opcode)
}
}

bool cmd_wake(struct io_interface *ioif)
{
int ret = STATUS_EXEC_ERROR;
ssize_t n = 0;
uint8_t cmd = CMD_WAKEUP;
uint8_t buf;

n = at204_write(ioif, &cmd, sizeof(cmd));
if (n <= 0)
return false;

ret = at204_read(ioif, &buf, sizeof(buf));
return ret == STATUS_OK || ret == STATUS_AFTER_WAKE;
}

uint8_t cmd_read(struct io_interface *ioif, uint8_t zone, uint8_t addr,
uint8_t offset, size_t size, void *data, size_t data_size)
{
Expand Down
29 changes: 28 additions & 1 deletion s96at/src/i2c_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,39 @@ static uint32_t i2c_linux_close(void *ctx)
return close(ictx->fd) == 0 ? STATUS_OK : STATUS_EXEC_ERROR;
}

/* As Linux ioctls do not provide a way to control the I2C lines directly,
* we send a request to address 0x00, which pulls SDA low for 7 cycles.
* This method is not failsafe as the wakeup low duration is 60 usec
* and the device can operate on frequencies up to 1MHz. This will therefore
* only work on systems clocked up to 133KHz.
*/
static uint32_t i2c_linux_wake(void *ctx)
{
int fd;
uint8_t data = 0;

fd = open(I2C_DEVICE, O_RDWR);
if (fd < 0) {
loge("Couldn't open the device\n");
return STATUS_EXEC_ERROR;
}
if (ioctl(fd, I2C_SLAVE, 0) < 0) {
loge("Couldn't talk to the slave\n");
return STATUS_EXEC_ERROR;
}
write(fd, &data, sizeof(data));
close(fd);

return STATUS_OK;
}

static struct i2c_linux_ctx i2c_ctx;

struct io_interface i2c_linux = {
.ctx = &i2c_ctx,
.open = i2c_linux_open,
.write = i2c_linux_write,
.read = i2c_linux_read,
.close = i2c_linux_close
.close = i2c_linux_close,
.wake = i2c_linux_wake
};
5 changes: 5 additions & 0 deletions s96at/src/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ int at204_close(struct io_interface *ioif)
return ioif->close(ioif->ctx);
}

int at204_wake(struct io_interface *ioif)
{
return ioif->wake(ioif->ctx);
}

int at204_write2(struct io_interface *ioif, struct cmd_packet *p)
{
uint8_t *serialized_pkt = NULL;
Expand Down
14 changes: 11 additions & 3 deletions s96at/src/s96at.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,18 @@ uint8_t s96at_cleanup(struct s96at_desc *desc)

uint8_t s96at_wake(struct s96at_desc *desc)
{
if (cmd_wake(desc->ioif) == true)
return S96AT_STATUS_OK;
else
uint8_t ret;
uint8_t buf;

if (at204_wake(desc->ioif) != STATUS_OK)
return S96AT_STATUS_EXEC_ERROR;

ret = at204_read(desc->ioif, &buf, sizeof(buf));

if (ret == S96AT_STATUS_OK && buf == S96AT_STATUS_READY)
ret = S96AT_STATUS_READY;

return ret;
}

uint8_t s96at_derive_key(struct s96at_desc *desc, uint8_t slot, uint8_t *mac,
Expand Down
2 changes: 1 addition & 1 deletion s96at/tests/tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,7 @@ int main(int argc, char *argv[])
}

logd("\n - Wake -\n");
while (!s96at_wake(&desc)) {};
while (s96at_wake(&desc) != S96AT_STATUS_READY) {};
logd("ATSHA204A is awake\n");

for (int i = 0 ; tests[i].func != NULL; i++) {
Expand Down

0 comments on commit 21747e3

Please sign in to comment.