コード例 #1
0
ファイル: RazorAHRS.cpp プロジェクト: AchimTuran/ssr
bool
RazorAHRS::_init_razor()
{
  char in;
  int result;
  struct timeval t0, t1, t2;
  const std::string synch_token = "#SYNCH";
  const std::string new_line = "\r\n";

  // start time
  gettimeofday(&t0, nullptr);

  // request synch token to see if Razor is really present
  const std::string contact_synch_id = "00"; 
  const std::string contact_synch_request = "#s" + contact_synch_id; 
  const std::string contact_synch_reply = synch_token + contact_synch_id + new_line;
  write(_serial_port, contact_synch_request.data(), contact_synch_request.length());
  gettimeofday(&t1, nullptr);

  // set non-blocking I/O
  if (!_set_nonblocking_io()) return false;

  /* look for tracker */
  while (true)
  {
    // try to read one byte from the port
    result = read(_serial_port, &in, 1);
    
    // one byte read
    if (result > 0)
    {
      if (_read_token(contact_synch_reply, in))
        break;
    }
    // no data available
    else if (result == 0)
      usleep(1000); // sleep 1ms
    // error?
    else
    {
      if (errno != EAGAIN && errno != EINTR)
        throw std::runtime_error("Can not read from serial port (1).");
    }

    // check timeout
    gettimeofday(&t2, nullptr);
    if (elapsed_ms(t1, t2) > 200)
    {
      // 200ms elapsed since last request and no answer -> request synch again
      // (this happens when DTR is connected and Razor resets on connect)
      write(_serial_port, contact_synch_request.data(), contact_synch_request.length());
      t1 = t2;
    }
    if (elapsed_ms(t0, t2) > _connect_timeout_ms)
      // timeout -> tracker not present
      throw std::runtime_error("Can not init: tracker does not answer.");
  }
  
  
  /* configure tracker */
  // set correct binary output mode, enable continuous streaming, disable errors and
  // request synch token. So we're good, no matter what state the tracker
  // currently is in.
  const std::string config_synch_id = "01";
  const std::string config_synch_reply = synch_token + config_synch_id + new_line;

  std::string config = "#o1#oe0#s" + config_synch_id;
  if (_mode == YAW_PITCH_ROLL) config = "#ob" + config;
  else if (_mode == ACC_MAG_GYR_RAW) config = "#osrb" + config;
  else if (_mode == ACC_MAG_GYR_CALIBRATED) config = "#oscb" + config;
  else throw std::runtime_error("Can not init: unknown 'mode' parameter.");  

  write(_serial_port, config.data(), config.length());
  
  // set blocking I/O
  // (actually semi-blocking, because VTIME is set)
  if (!_set_blocking_io()) return false;

  while (true)
  {    
    // try to read one byte from the port
    result = read(_serial_port, &in, 1);
    
    // one byte read
    if (result > 0)
    {
      if (_read_token(config_synch_reply, in))
        break;  // alrighty
    }
    // error?
    else
    {
      if (errno != EAGAIN && errno != EINTR)
        throw std::runtime_error("Can not read from serial port (2).");
    }
  }
  
  // we keep using blocking I/O
  //if (_set_blocking_io() == -1)
  //  return false;
  
  return true;
}
コード例 #2
0
static bool _read_params_bool(struct stream_data *s)
{
	static struct notify_msg_param const	notify_msg = {
		.op		= 'P',
		.is_flag	= 1,
	};

	char		param[sizeof(PARAM_PREFIX_FLAG) + PARAM_KEY_SZ];
	char		*p;
	unsigned char	end_c;

	notification_send(&s->notify, &notify_msg, sizeof notify_msg);

	p = stpcpy(param, PARAM_PREFIX_FLAG);
	if (!_read_token(s, p, PARAM_KEY_SZ, true, &end_c) || end_c != '\0') {
		fprintf(stderr, "bad flag name\n");
		return false;
	}

	if (setenv(param, "1", true) < 0) {
		perror("setenv()");
		return false;
	}

	return true;
}

static bool _read_params_keyval(struct stream_data *s)
{
	static struct notify_msg_param const	notify_msg = {
		.op		= 'P',
		.is_flag	= 0,
	};

	char		key[sizeof(PARAM_PREFIX_KEYVAL) + PARAM_KEY_SZ];
	char		val[PARAM_VAL_SZ];
	char		*p;
	unsigned char	end_c;

	notification_send(&s->notify, &notify_msg, sizeof notify_msg);

	p = stpcpy(key, PARAM_PREFIX_KEYVAL);
	if (!_read_token(s, p, PARAM_KEY_SZ, true, &end_c) || end_c != '=') {
		fprintf(stderr, "bad key name\n");
		return false;
	}

	if (!_read_token(s, val, sizeof val, false, &end_c) || end_c != '\0') {
		fprintf(stderr, "bad value name\n");
		return false;
	}

	if (setenv(key, val, true) < 0) {
		perror("setenv()");
		return false;
	}

	return true;
}

static bool	stream_data_read_params(struct stream_data *s)
{
	bool			rc = false;

	if (s->num_queued_char > 0) {
		fprintf(stderr, "internal error: data already queued internally\n");
		return false;
	}

	for (;;) {
		unsigned char	c;
		ssize_t		l = read(s->fd, &c, sizeof c);

		if (l < 0) {
			perror("read()");
			rc = false;
			break;
		}

		if (l == 0) {
			rc = true;
			break;
		}

		switch (c) {
		case '+':
			rc = _read_params_bool(s);
			break;

		case '?':
			rc = _read_params_keyval(s);
			break;

		default:
			s->queued_char = c;
			s->num_queued_char = 1;
			rc = true;
			goto out;
		}

		if (!rc)
			break;
	}

out:
	return rc;
}

static bool	stream_data_read(struct stream_data *s, void *buf, size_t cnt,
				 bool ignore_eos)
{
	size_t		tlen = 0;

	if (cnt > 0 && s->num_queued_char > 0) {
		size_t		l = MIN(s->num_queued_char, cnt);

		memcpy(buf, &s->queued_char, l);
		buf += l;
		cnt -= l;

		s->num_queued_char -= l;
	}

	while (cnt > 0) {
		ssize_t		l = read(s->fd, buf, cnt);

		if (l > 0) {
			cnt  -= l;
			buf  += l;
			tlen += l;
		} else if (l < 0) {
			perror("read()");
			break;
		} else {
			if (tlen > 0 || !ignore_eos)
				fprintf(stderr, "%s: EOS reached while reading\n",
					__func__);
			else
				cnt = 0;

			s->is_eos = true;
			break;
		}
	}

	return cnt == 0;
}