void WriteWorker(uv_work_t* work_req) {
  I2C_WORKER_INIT_TEMPLATE;
  iotjs_i2c_t* i2c = iotjs_i2c_instance_from_reqwrap(req_wrap);
  IOTJS_VALIDATED_STRUCT_METHOD(iotjs_i2c_t, i2c);

  uint8_t len = req_data->buf_len;
  uint8_t* data = (uint8_t*)req_data->buf_data;

  IOTJS_ASSERT(!_this->i2c_master);
  IOTJS_ASSERT(len > 0);

  int ret = i2c_write(_this->i2c_master, &_this->config, data, len);
  if (ret < 0) {
    DDLOG("I2C WriteWorker : cannot write - %d", ret);
    req_data->error = kI2cErrWrite;
  } else {
    req_data->error = kI2cErrOk;
  }

  if (req_data->buf_data != NULL) {
    iotjs_buffer_release(req_data->buf_data);
  }

  req_data->error = kI2cErrOk;
}
void WriteBlockWorker(uv_work_t* work_req) {
  I2C_WORKER_INIT_TEMPLATE;
  iotjs_i2c_t* i2c = iotjs_i2c_instance_from_reqwrap(req_wrap);
  IOTJS_VALIDATED_STRUCT_METHOD(iotjs_i2c_t, i2c);

  uint8_t cmd = req_data->cmd;
  uint8_t len = req_data->buf_len;
  char* data = req_data->buf_data;

  // The first element of data array is command.
  iotjs_buffer_reallocate(data, len + 1);
  memmove(data + 1, data, len * sizeof(char));
  data[0] = cmd;

  IOTJS_ASSERT(!_this->i2c_master);

  int ret =
      i2c_write(_this->i2c_master, &_this->config, &req_data->byte, len + 1);
  if (ret < 0) {
    DDLOG("I2C WriteBlockWorker : cannot write - %d", ret);
    req_data->error = kI2cErrWrite;
    return;
  }
  req_data->error = kI2cErrOk;
}
void WriteByteWorker(uv_work_t* work_req) {
  I2C_WORKER_INIT_TEMPLATE;
  iotjs_i2c_t* i2c = iotjs_i2c_instance_from_reqwrap(req_wrap);
  IOTJS_VALIDATED_STRUCT_METHOD(iotjs_i2c_t, i2c);

  IOTJS_ASSERT(!_this->i2c_master);

  int ret = i2c_write(_this->i2c_master, &_this->config, &req_data->byte, 1);
  if (ret < 0) {
    DDLOG("I2C WriteByteWorker : cannot write - %d", ret);
    req_data->error = kI2cErrWrite;
    return;
  }
  req_data->error = kI2cErrOk;
}
void OpenWorker(uv_work_t* work_req) {
  I2C_WORKER_INIT_TEMPLATE;
  iotjs_i2c_t* i2c = iotjs_i2c_instance_from_reqwrap(req_wrap);

  IOTJS_VALIDATED_STRUCT_METHOD(iotjs_i2c_t, i2c);
  _this->i2c_master = iotjs_i2c_config_nuttx(req_data->device);
  if (!_this->i2c_master) {
    DDLOG("I2C OpenWorker : cannot open");
    req_data->error = kI2cErrOpen;
    return;
  }

  _this->config.frequency = I2C_DEFAULT_FREQUENCY;

  req_data->error = kI2cErrOk;
}
void OpenWorker(uv_work_t* work_req) {
  I2C_WORKER_INIT_TEMPLATE;
  iotjs_i2c_t* i2c = iotjs_i2c_instance_from_reqwrap(req_wrap);

  IOTJS_I2C_METHOD_HEADER(i2c);
  platform_data->i2c_master = iotjs_i2c_config_nuttx(platform_data->device);
  if (!platform_data->i2c_master) {
    DLOG("I2C OpenWorker : cannot open");
    req_data->error = kI2cErrOpen;
    return;
  }

  platform_data->config.frequency = I2C_DEFAULT_FREQUENCY;

  req_data->error = kI2cErrOk;
}
void ReadWorker(uv_work_t* work_req) {
  I2C_WORKER_INIT_TEMPLATE;
  iotjs_i2c_t* i2c = iotjs_i2c_instance_from_reqwrap(req_wrap);
  IOTJS_VALIDATED_STRUCT_METHOD(iotjs_i2c_t, i2c);

  uint8_t len = req_data->buf_len;
  req_data->buf_data = iotjs_buffer_allocate(len);

  IOTJS_ASSERT(!_this->i2c_master);
  IOTJS_ASSERT(len > 0);

  int ret = i2c_read(_this->i2c_master, &_this->config,
                     (uint8_t*)req_data->buf_data, len);
  if (ret != 0) {
    DDLOG("I2C ReadWorker : cannot read - %d", ret);
    req_data->error = kI2cErrRead;
    return;
  }
  req_data->error = kI2cErrOk;
}