Exemple #1
0
/** Iterate through an array of events and check whether all of them are properly defined,
	that is, whether the "type" and "value" fields are of valid type and size, and whether the
	"bufsize" fields are correct (that is, fully contained in the passed buffer, and big enough
	to hold "type" and "value".
	Returns the number of events on success (might also be 0), or
	a negative number that indicates in which event definition an error happend,
	for example, a return value of -2 means that the first event was ok, but the second event
	definition was invalid. This function returns at the first error.
*/
int check_event_array(unsigned int size, const void *buf) {
	unsigned int offset=0;
	int numEvents = 0;
	
	while (offset + sizeof(eventdef_t) <= size) {
		const eventdef_t *E;	
		unsigned int wsType, wsValue;
		
		/* Set our event pointer to the current location within the array */
		E = (const eventdef_t *) ((char *) buf + offset);
		
		/* Increase the offset by the size of this event, and check whether it's fully
		   contained within the given array.
		*/
		offset += sizeof(eventdef_t) + E->bufsize;
		if (offset > size) goto error;
		
		/* Check whether "type" and "value" are of known type */
		wsType = wordsize_from_type(E->type_type);
		if (wsType == 0) goto error;
		wsValue = wordsize_from_type(E->value_type);
		if (wsValue == 0) goto error;
		
		/* Check whether "type" and "value" are contained in this event's "buf" */
		if (wsType * E->type_numel + wsValue * E->value_numel > E->bufsize) goto error;

		/* all checks passed, continue at next offset */
		++numEvents;
	}
	return numEvents;
error:
	return -(1+numEvents);
}
Exemple #2
0
void init_data(void) {
  int verbose = 0;
  if (verbose>0) fprintf(stderr, "init_data: creating data buffer\n");
  if (header) {
    unsigned int wordsize = wordsize_from_type(header->def->data_type);

    if (wordsize==0) {
      fprintf(stderr, "init_data: unsupported data type (%u)\n", header->def->data_type);
      return;
    }
    /* heuristic of choosing size of buffer:
       set current_max_num_sample to MAXNUMSAMPLE if nchans <= 256
       otherwise, allocate about MAXNUMBYTE and calculate current_max_num_sample from nchans + wordsize
       */
    if (header->def->nchans <= 256) {
      current_max_num_sample = MAXNUMSAMPLE;
    } else {
      current_max_num_sample = MAXNUMBYTE / (wordsize * header->def->nchans);
    }
    data = (data_t*)malloc(sizeof(data_t));

    DIE_BAD_MALLOC(data);

    data->def = (datadef_t*)malloc(sizeof(datadef_t));

    DIE_BAD_MALLOC(data->def);

    data->def->nchans    = header->def->nchans;
    data->def->nsamples  = current_max_num_sample;
    data->def->data_type = header->def->data_type;
    data->buf = malloc(header->def->nchans*current_max_num_sample*wordsize);

    DIE_BAD_MALLOC(data->buf);
  }
}
Exemple #3
0
/* returns 0 on success, -1 on error */
int ft_swap_events_to_native(UINT32_T size, void *buf) {
	UINT32_T offset = 0;

	while (offset + sizeof(eventdef_t) <= size) {
		unsigned int wst, wsv;
		
		eventdef_t *edef = (eventdef_t *) ((char *) buf + offset);
		ft_swap32(8, edef); /* all fields are 32-bit */
		
		/* Increase offset to beginning of next event */
		offset += sizeof(eventdef_t) + edef->bufsize;
		if (offset > size) return -1;	/* this event is too big for "buf" */
		
		wst = wordsize_from_type(edef->type_type);
		wsv = wordsize_from_type(edef->value_type);
		
		/* check if type and value fit into this event's local buffer */
		if (wst*edef->type_numel + wsv*edef->value_numel > edef->bufsize) return -1;
		
		ft_swap_data(edef->type_numel, edef->type_type, (char *) buf + offset);
		ft_swap_data(edef->value_numel, edef->value_type, (char *) buf + offset + wst*edef->type_numel);
	}
	return 0;
}
Exemple #4
0
int ft_swap_events_from_native(UINT32_T size, void *buf) {
	UINT32_T offset = 0;
	
	while (offset + sizeof(eventdef_t) <= size) {
		unsigned int wst;
		
		eventdef_t *edef = (eventdef_t *) ((char *) buf + offset);
		offset += sizeof(eventdef_t) + edef->bufsize;
		
		wst = wordsize_from_type(edef->type_type);
		
		ft_swap_data(edef->type_numel, edef->type_type, (char *) buf + offset);
		ft_swap_data(edef->value_numel, edef->value_type, (char *) buf + offset + wst*edef->type_numel);
		ft_swap32(8, edef); /* all fields are 32-bit */
	}
	return 0;
}
Exemple #5
0
/***************************************************************************** 
 * this function handles the direct memory access to the buffer
 * and copies objects to and from memory
 *****************************************************************************/
int dmarequest(const message_t *request, message_t **response_ptr) {
  unsigned int offset;
  /*
     int blockrequest = 0;
     */
  int verbose = 0;

  /* these are used for blocking the read requests */
  struct timeval tp;
  struct timespec ts;

  /* use a local variable for datasel (in GET_DAT) */
  datasel_t datasel;

  /* these are for typecasting */
  headerdef_t    *headerdef;
  datadef_t      *datadef;
  eventdef_t     *eventdef;
  eventsel_t     *eventsel;

  /* this will hold the response */
  message_t *response;
  response      = (message_t*)malloc(sizeof(message_t));

  /* check for "out of memory" problems */
  if (response == NULL) {
    *response_ptr = NULL;
    return -1;
  }
  response->def = (messagedef_t*)malloc(sizeof(messagedef_t));

  /* check for "out of memory" problems */
  if (response->def == NULL) {
    *response_ptr = NULL;
    free(response);
    return -1;
  }
  response->buf = NULL;
  /* the response should be passed to the calling function, where it should be freed */
  *response_ptr = response;

  if (verbose>1) print_request(request->def);

  switch (request->def->command) {

    case PUT_HDR:
      if (verbose>1) fprintf(stderr, "dmarequest: PUT_HDR\n");
      pthread_mutex_lock(&mutexheader);
      pthread_mutex_lock(&mutexdata);
      pthread_mutex_lock(&mutexevent);

      headerdef = (headerdef_t*)request->buf;
      if (verbose>1) print_headerdef(headerdef);

      /* delete the old header, data and events */
      free_header();
      free_data();
      free_event();

      /* store the header and re-initialize */
      header      = (header_t*)malloc(sizeof(header_t));
      DIE_BAD_MALLOC(header);
      header->def = (headerdef_t*)malloc(sizeof(headerdef_t));
      DIE_BAD_MALLOC(header->def);
      header->buf = malloc(headerdef->bufsize);
      DIE_BAD_MALLOC(header->buf);
      memcpy(header->def, request->buf, sizeof(headerdef_t));
      memcpy(header->buf, (char*)request->buf+sizeof(headerdef_t), headerdef->bufsize);
      header->def->nsamples = 0;
      header->def->nevents  = 0;

      init_data();
      init_event();

      response->def->version = VERSION;
      response->def->bufsize = 0;
      /* check whether memory could indeed be allocated */
      if (data!= NULL && data->buf != NULL && data->def != NULL) {
        response->def->command = PUT_OK;
      } else {
        /* let's at least tell the client that something's wrong */
        response->def->command = PUT_ERR;	
      }

      pthread_mutex_unlock(&mutexevent);
      pthread_mutex_unlock(&mutexdata);
      pthread_mutex_unlock(&mutexheader);
      break;

    case PUT_DAT:
      if (verbose>1) fprintf(stderr, "dmarequest: PUT_DAT\n");
      pthread_mutex_lock(&mutexheader);
      pthread_mutex_lock(&mutexdata);

      datadef = (datadef_t*)request->buf;
      if (verbose>1) print_datadef(datadef);
      if (verbose>2) print_buf(request->buf, request->def->bufsize);

      response->def->version = VERSION;
      response->def->bufsize = 0;
      if (request->def->bufsize < sizeof(datadef_t))
        response->def->command = PUT_ERR;
      else if (header==NULL || data==NULL)
        response->def->command = PUT_ERR;
      else if (header->def->nchans != datadef->nchans)
        response->def->command = PUT_ERR;
      else if (header->def->data_type != datadef->data_type)
        response->def->command = PUT_ERR;
      else if (datadef->nsamples > current_max_num_sample)
        response->def->command = PUT_ERR;
      else {
        unsigned int i;
        unsigned int wordsize = wordsize_from_type(header->def->data_type);
        unsigned int datasize = wordsize * datadef->nsamples * datadef->nchans;

        response->def->command = PUT_OK;

        if (wordsize == 0) {
          fprintf(stderr, "dmarequest: unsupported data type (%d)\n", datadef->data_type);
          response->def->command = PUT_ERR;
        } else if (datasize > datadef->bufsize || (datadef->bufsize + sizeof(datadef_t)) > request->def->bufsize) {
          fprintf(stderr, "dmarequest: invalid size definitions in PUT_DAT request\n");
          response->def->command = PUT_ERR;
        } else {

          /* record the time at which the data was received */
          if (clock_gettime(CLOCK_REALTIME, &putdat_clock) != 0) {
            perror("clock_gettime");
            return -1;
          }

          /* number of bytes per sample (all channels) is given by wordsize x number of channels */
          unsigned int chansize = wordsize * data->def->nchans;
          /* request_data points to actual data samples within the request, use char* for convenience */
          const char *request_data = (const char *) request->buf + sizeof(datadef_t);
          char *buffer_data = (char *)data->buf;

          for (i=0; i<datadef->nsamples; i++) {
            memcpy(buffer_data+(thissample*chansize), request_data+(i*chansize), chansize);
            header->def->nsamples++;
            thissample++;
            thissample = WRAP(thissample, current_max_num_sample);
          }
          /* Signal possibly waiting threads that we have received data */
          pthread_cond_broadcast(&getData_cond);
        }
      }

      pthread_mutex_unlock(&mutexdata);
      pthread_mutex_unlock(&mutexheader);
      break;

    case PUT_EVT:
      if (verbose>1) fprintf(stderr, "dmarequest: PUT_EVT\n");
      pthread_mutex_lock(&mutexheader);
      pthread_mutex_lock(&mutexevent);

      /* record the time at which the event was received */
      if (clock_gettime(CLOCK_REALTIME, &putevt_clock) != 0) {
        perror("clock_gettime");
        return -1;
      }

      /* Give an error message if there is no header, or if the given event array is defined badly */
      if (header==NULL || event==NULL || check_event_array(request->def->bufsize, request->buf) < 0) {
        response->def->version = VERSION;
        response->def->command = PUT_ERR;
        response->def->bufsize = 0;
      }
      else {	/* go over all events and store them one by one */
        response->def->version = VERSION;
        response->def->command = PUT_OK;
        response->def->bufsize = 0;

        offset = 0; /* this represents the offset of the event in the buffer */
        while (offset<request->def->bufsize) {
          FREE(event[thisevent].def);
          FREE(event[thisevent].buf);

          eventdef = (eventdef_t*)((char*)request->buf+offset);
          if (verbose>1) print_eventdef(eventdef);

          event[thisevent].def = (eventdef_t*)malloc(sizeof(eventdef_t));
          DIE_BAD_MALLOC(event[thisevent].def);
          memcpy(event[thisevent].def, (char*)request->buf+offset, sizeof(eventdef_t));

          if (event[thisevent].def->sample == EVENT_AUTO_SAMPLE) {
            /* automatically convert event->def->sample to current sample number */
            /* make some fine adjustment of the assigned sample number */
            double adjust = (putevt_clock.tv_sec - putdat_clock.tv_sec) + (double)(putevt_clock.tv_nsec - putdat_clock.tv_nsec) / 1000000000L;
            event[thisevent].def->sample = header->def->nsamples + (int)(header->def->fsample*adjust);
          }

          offset += sizeof(eventdef_t);
          event[thisevent].buf = malloc(eventdef->bufsize);
          DIE_BAD_MALLOC(event[thisevent].buf);
          memcpy(event[thisevent].buf, (char*)request->buf+offset, eventdef->bufsize);
          offset += eventdef->bufsize;
          if (verbose>1) print_eventdef(event[thisevent].def);
          thisevent++;
          thisevent = WRAP(thisevent, MAXNUMEVENT);
          header->def->nevents++;
        }
      }

      pthread_mutex_unlock(&mutexevent);
      pthread_mutex_unlock(&mutexheader);
      break;

    case GET_HDR:
      if (verbose>1) fprintf(stderr, "dmarequest: GET_HDR\n");
      if (header==NULL) {
        response->def->version = VERSION;
        response->def->command = GET_ERR;
        response->def->bufsize = 0;
        break;
      }

      pthread_mutex_lock(&mutexheader);

      response->def->version = VERSION;
      response->def->command = GET_OK;
      response->def->bufsize = 0;
      response->def->bufsize = append(&response->buf, response->def->bufsize, header->def, sizeof(headerdef_t));
      response->def->bufsize = append(&response->buf, response->def->bufsize, header->buf, header->def->bufsize);

      pthread_mutex_unlock(&mutexheader);
      break;

    case GET_DAT:
      if (verbose>1) fprintf(stderr, "dmarequest: GET_DAT\n");
      if (header==NULL || data==NULL) {
        response->def->version = VERSION;
        response->def->command = GET_ERR;
        response->def->bufsize = 0;
        break;
      }

      pthread_mutex_lock(&mutexheader);
      pthread_mutex_lock(&mutexdata);

      if (request->def->bufsize) {
        /* the selection has been specified */
        memcpy(&datasel, request->buf, sizeof(datasel_t));
        /* If endsample is -1 read the buffer to the end */
        if(datasel.endsample == -1)
        {
          datasel.endsample = header->def->nsamples - 1;
        }
      }
      else {
        /* determine a valid selection */
        if (header->def->nsamples>current_max_num_sample) {
          /* the ringbuffer is completely full */
          datasel.begsample = header->def->nsamples - current_max_num_sample;
          datasel.endsample = header->def->nsamples - 1;
        }
        else {
          /* the ringbuffer is not yet completely full */
          datasel.begsample = 0;
          datasel.endsample = header->def->nsamples - 1;
        }
      }

      /*

      // if the read should block...
      if(blockrequest == 1)
      {
      // check whether data is available
      while((datasel.begsample >= (datasel.endsample+1)) || (datasel.endsample > header->def->nsamples - 1))
      {
      // if not unlock all mutexes
      pthread_mutex_unlock(&mutexdata);
      pthread_mutex_unlock(&mutexheader);

      // wait for the condition to be signaled
      pthread_mutex_lock(&getData_mutex);
      gettimeofday(&tp, NULL);
      ts.tv_sec = tp.tv_sec;
      ts.tv_nsec = tp.tv_usec * 1000;
      ts.tv_sec += 1;
      pthread_cond_timedwait(&getData_cond, &getData_mutex, &ts);
      pthread_mutex_unlock(&getData_mutex);

      // Lock the mutexes again
      pthread_mutex_lock(&mutexheader);
      pthread_mutex_lock(&mutexdata);
      if(datasel.begsample == (datasel.endsample+1))
      datasel.endsample = header->def->nsamples - 1;
      }
      }
      */

      if (verbose>1) print_headerdef(header->def);
      if (verbose>1) print_datasel(&datasel);

      if (datasel.begsample < 0 || datasel.endsample < 0) {
        fprintf(stderr, "dmarequest: err1\n");
        response->def->version = VERSION;
        response->def->command = GET_ERR;
        response->def->bufsize = 0;
      }
      else if (datasel.begsample >= header->def->nsamples || datasel.endsample >= header->def->nsamples) {
        fprintf(stderr, "dmarequest: err2\n");
        response->def->version = VERSION;
        response->def->command = GET_ERR;
        response->def->bufsize = 0;
      }
      else if ((header->def->nsamples - datasel.begsample) > current_max_num_sample) {
        fprintf(stderr, "dmarequest: err3\n");
        response->def->version = VERSION;
        response->def->command = GET_ERR;
        response->def->bufsize = 0;
      }
      else {
        unsigned int wordsize = wordsize_from_type(data->def->data_type);
        if (wordsize==0) {
          fprintf(stderr, "dmarequest: unsupported data type (%d)\n", data->def->data_type);
          response->def->version = VERSION;
          response->def->command = GET_ERR;
          response->def->bufsize = 0;
        }  else {
          unsigned int n;
          response->def->version = VERSION;
          response->def->command = GET_OK;
          response->def->bufsize = 0;

          /* determine the number of samples to return */
          n = datasel.endsample - datasel.begsample + 1;

          response->buf = malloc(sizeof(datadef_t) + n*data->def->nchans*wordsize);
          if (response->buf == NULL) {
            /* not enough space for copying data into response */
            fprintf(stderr, "dmarequest: out of memory\n");
            response->def->command = GET_ERR;
          } 
          else {
            /* number of bytes per sample (all channels) */
            unsigned int chansize = data->def->nchans * wordsize;

            /* convenience pointer to start of actual data in response */
            char *resp_data = ((char *) response->buf) + sizeof(datadef_t);

            /* this is the location of begsample within the ringbuffer */
            unsigned int start_index = 	WRAP(datasel.begsample, current_max_num_sample);

            /* have datadef point into the freshly allocated response buffer and directly
               fill in the information */
            datadef = (datadef_t *) response->buf;
            datadef->nchans    = data->def->nchans;
            datadef->data_type = data->def->data_type;
            datadef->nsamples  = n;
            datadef->bufsize   = n*chansize;

            response->def->bufsize = sizeof(datadef_t) + datadef->bufsize;

            if (start_index + n <= current_max_num_sample) {
              /* we can copy everything in one go */
              memcpy(resp_data, (char*)(data->buf) + start_index*chansize, n*chansize);
            } else {
              /* need to wrap around at current_max_num_sample */
              unsigned int na = current_max_num_sample - start_index;
              unsigned int nb = n - na;

              memcpy(resp_data, (char*)(data->buf) + start_index*chansize, na*chansize);
              memcpy(resp_data + na*chansize, (char*)(data->buf), nb*chansize);

              /* printf("Wrapped around!\n"); */
            }
          }
        }
      }

      pthread_mutex_unlock(&mutexdata);
      pthread_mutex_unlock(&mutexheader);
      break;

    case GET_EVT:
      if (verbose>1) fprintf(stderr, "dmarequest: GET_EVT\n");
      if (header==NULL || event==NULL || header->def->nevents==0) {
        response->def->version = VERSION;
        response->def->command = GET_ERR;
        response->def->bufsize = 0;
        break;
      }

      pthread_mutex_lock(&mutexheader);
      pthread_mutex_lock(&mutexevent);

      eventsel = (eventsel_t*)malloc(sizeof(eventsel_t));
      DIE_BAD_MALLOC(eventsel);

      /* determine the selection */
      if (request->def->bufsize) {
        /* the selection has been specified */
        memcpy(eventsel, request->buf, sizeof(eventsel_t));
      }
      else {
        /* determine a valid selection */
        if (header->def->nevents>MAXNUMEVENT) {
          /* the ringbuffer is completely full */
          eventsel->begevent = header->def->nevents - MAXNUMEVENT;
          eventsel->endevent = header->def->nevents - 1;
        }
        else {
          /* the ringbuffer is not yet completely full */
          eventsel->begevent = 0;
          eventsel->endevent = header->def->nevents - 1;
        }
      }

      if (verbose>1) print_headerdef(header->def);
      if (verbose>1) print_eventsel(eventsel);

      if (eventsel==NULL) {
        response->def->version = VERSION;
        response->def->command = GET_ERR;
        response->def->bufsize = 0;
      }
      else if (eventsel->begevent < 0 || eventsel->endevent < 0) {
        fprintf(stderr, "dmarequest: err1\n");
        response->def->version = VERSION;
        response->def->command = GET_ERR;
        response->def->bufsize = 0;
      }
      else if (eventsel->begevent >= header->def->nevents || eventsel->endevent >= header->def->nevents) {
        fprintf(stderr, "dmarequest: err2\n");
        response->def->version = VERSION;
        response->def->command = GET_ERR;
        response->def->bufsize = 0;
      }
      else if ((header->def->nevents-eventsel->begevent) > MAXNUMEVENT) {
        fprintf(stderr, "dmarequest: err3\n");
        response->def->version = VERSION;
        response->def->command = GET_ERR;
        response->def->bufsize = 0;
      }
      else {
        unsigned int j,n;

        response->def->version = VERSION;
        response->def->command = GET_OK;
        response->def->bufsize = 0;

        /* determine the number of events to return */
        n = eventsel->endevent - eventsel->begevent + 1;

        for (j=0; j<n; j++) {
          if (verbose>1) print_eventdef(event[WRAP(eventsel->begevent+j, MAXNUMEVENT)].def);
          response->def->bufsize = append(&response->buf, response->def->bufsize, event[WRAP(eventsel->begevent+j, MAXNUMEVENT)].def, sizeof(eventdef_t));
          response->def->bufsize = append(&response->buf, response->def->bufsize, event[WRAP(eventsel->begevent+j, MAXNUMEVENT)].buf, event[WRAP(eventsel->begevent+j, MAXNUMEVENT)].def->bufsize);
        }
      }

      FREE(eventsel);
      pthread_mutex_unlock(&mutexevent);
      pthread_mutex_unlock(&mutexheader);
      break;

    case FLUSH_HDR:
      pthread_mutex_lock(&mutexheader);
      pthread_mutex_lock(&mutexdata);
      pthread_mutex_lock(&mutexevent);
      if (header) {
        free_header();
        free_data();
        free_event();
        response->def->version = VERSION;
        response->def->command = FLUSH_OK;
        response->def->bufsize = 0;
      }
      else {
        response->def->version = VERSION;
        response->def->command = FLUSH_ERR;
        response->def->bufsize = 0;
      }
      pthread_mutex_unlock(&mutexevent);
      pthread_mutex_unlock(&mutexdata);
      pthread_mutex_unlock(&mutexheader);
      break;

    case FLUSH_DAT:
      pthread_mutex_lock(&mutexheader);
      pthread_mutex_lock(&mutexdata);
      if (header && data) {
        header->def->nsamples = thissample = 0;
        response->def->version = VERSION;
        response->def->command = FLUSH_OK;
        response->def->bufsize = 0;
      }
      else {
        response->def->version = VERSION;
        response->def->command = FLUSH_ERR;
        response->def->bufsize = 0;
      }
      pthread_mutex_unlock(&mutexdata);
      pthread_mutex_unlock(&mutexheader);
      break;

    case FLUSH_EVT:
      pthread_mutex_lock(&mutexheader);
      pthread_mutex_lock(&mutexevent);
      if (header && event) {
        unsigned int i;

        header->def->nevents = thisevent = 0;
        for (i=0; i<MAXNUMEVENT; i++) {
          FREE(event[i].def);
          FREE(event[i].buf);
        }
        response->def->version = VERSION;
        response->def->command = FLUSH_OK;
        response->def->bufsize = 0;
      }
      else {
        response->def->version = VERSION;
        response->def->command = FLUSH_ERR;
        response->def->bufsize = 0;
      }
      pthread_mutex_unlock(&mutexevent);
      pthread_mutex_unlock(&mutexheader);
      break;

    case WAIT_DAT:
      /* SK: This request means that the client wants to wait until
         MORE than waitdef_t.threshold.nsamples samples OR 
         MORE THAN waitdef_t.threshold.nevents events 
         are in the buffer, BUT 
         only for the time given in waitdef_t.milliseconds. 
         The response is just the number of samples and events 
         in the buffer as described by samples_events_t.
         */
      response->def->version = VERSION;
      if (header==NULL || request->def->bufsize!=sizeof(waitdef_t)) {
        response->def->command = WAIT_ERR;
        response->def->bufsize = 0;
      } else {
        int waiterr;
        waitdef_t *wd = (waitdef_t *) request->buf;
        samples_events_t *nret = malloc(sizeof(samples_events_t));
        UINT32_T nsmp, nevt;

        if (nret == NULL) {
          /* highly unlikely, but we cannot allocate a sample_event_t - return an error */
          response->def->command = WAIT_ERR;
          response->def->bufsize = 0;
          break;
        }
        /* Let response->buf point to the new sample_event_t structure */
        response->def->command = WAIT_OK;
        response->def->bufsize = sizeof(samples_events_t);
        response->buf = nret;

        /* get current number of samples */
        pthread_mutex_lock(&mutexheader);
        nsmp = header->def->nsamples;
        nevt = header->def->nevents;
        pthread_mutex_unlock(&mutexheader);

        if (wd->milliseconds == 0 || nsmp > wd->threshold.nsamples || nevt > wd->threshold.nevents) {
          /* the client doesn't want to wait, or
             we're already above the threshold: 
             return immediately */
          nret->nsamples = nsmp;
          nret->nevents = nevt;
          break;
        }
        gettimeofday(&tp, NULL);
        ts.tv_sec = tp.tv_sec + (wd->milliseconds/1000);
        ts.tv_nsec = 1000 * (tp.tv_usec + (wd->milliseconds % 1000)*1000);
        while (ts.tv_nsec >= 1000000000) {
          ts.tv_sec++;
          ts.tv_nsec-=1000000000;
        }

        /* FIXME: The getData condition variable is only triggered by incoming data, not events */
        do {
          pthread_mutex_lock(&getData_mutex);
          waiterr = pthread_cond_timedwait(&getData_cond, &getData_mutex, &ts);
          pthread_mutex_unlock(&getData_mutex);

          /* get current number of samples */
          pthread_mutex_lock(&mutexheader);
          nsmp = header->def->nsamples;
          nevt = header->def->nevents;
          pthread_mutex_unlock(&mutexheader);
        } while (nsmp <= wd->threshold.nsamples && nevt <= wd->threshold.nevents && waiterr==0);
        nret->nsamples = nsmp;
        nret->nevents = nevt;				
      }
      break;
    default:
      fprintf(stderr, "dmarequest: unknown command\n");
  }

  if (verbose>0) fprintf(stderr, "dmarequest: thissample = %u, thisevent = %u\n", thissample, thisevent);

  /* everything went fine */
  return 0;
}
Exemple #6
0
/** Retrieves samples and markers and returns them in as a new 'item', or NULL on errors.
*/
rda_buffer_item_t *rda_aux_get_samples_and_markers(int ft_buffer, const samples_events_t *last, const samples_events_t *cur, int numBlock, int use16bit) {
	rda_buffer_item_t *item = NULL;
	int numEvt = 0,numChans = 0,numSmp = 0;
	message_t req, *respSmp = NULL, *respEvt = NULL;
	messagedef_t msg_def;
	datadef_t *ddef;
	size_t bytesSamples = 0, bytesMarkers = 0;
	
	/* First, try to grab the samples */
	if (cur->nsamples > last->nsamples) {
		datasel_t dat_sel;
		
		msg_def.version = VERSION;
		msg_def.command = GET_DAT;
		msg_def.bufsize = sizeof(dat_sel);
		dat_sel.begsample = last->nsamples;
		dat_sel.endsample = cur->nsamples-1;
		req.def = &msg_def;
		req.buf = &dat_sel;
	
		if (clientrequest(ft_buffer, &req, &respSmp)<0) {
			goto cleanup;
		}
		
		numSmp = cur->nsamples - last->nsamples;
		
		if (respSmp == NULL || respSmp->def == NULL || respSmp->buf == NULL || respSmp->def->command != GET_OK) {
			goto cleanup;
		} else {
			ddef = (datadef_t *) respSmp->buf;
			
			if (ddef->nsamples != numSmp) goto cleanup;
			
			numChans = ddef->nchans;
			bytesSamples  = (use16bit ? sizeof(INT16_T) : sizeof(float)) * numSmp * numChans;
		}
	} 
	
	/* Now, try to grab the markers */
	if (cur->nevents > last->nevents) {
		eventsel_t evt_sel;
		int offset = 0;
		
		msg_def.version = VERSION;
		msg_def.command = GET_EVT;
		msg_def.bufsize = sizeof(evt_sel);
		evt_sel.begevent = last->nevents;
		evt_sel.endevent = cur->nevents-1;
		req.def = &msg_def;
		req.buf = &evt_sel;
	
		if (clientrequest(ft_buffer, &req, &respEvt) < 0) {
			goto cleanup;
		}
		if (respEvt == NULL || respEvt->def == NULL || respEvt->buf == NULL || respEvt->def->command != GET_OK) {
			goto cleanup;
		}
		
		/* count the number of events, increase bytesTotal as required */
		while (offset + sizeof(eventdef_t) <= respEvt->def->bufsize) {
			eventdef_t *evdef = (eventdef_t *) ((char *)respEvt->buf + offset);
			offset += sizeof(eventdef_t) + evdef->bufsize;
			
			if (evdef->bufsize < evdef->type_numel*wordsize_from_type(evdef->type_type) + evdef->value_numel*wordsize_from_type(evdef->value_type)) {
				fprintf(stderr,"Invalid event received: Buffer to small for given value/type description\n");
				continue;	/* Skip to next event */
			}
			
			bytesMarkers += sizeof(rda_marker_t);
			if (evdef->type_type == DATATYPE_CHAR) {
				if (evdef->value_type == DATATYPE_CHAR) {
					/* Transform into TYPE:VALUE\0 */
					bytesMarkers += evdef->type_numel + evdef->value_numel + 2;
				} else {
					/* Transform into TYPE:-\0 */
					bytesMarkers += evdef->type_numel + 3;
				}
			} else {
				if (evdef->value_type == DATATYPE_CHAR) {
					/* Transform into FT:VALUE\0 */
					bytesMarkers += evdef->value_numel + 4;
				} else {
					/* Transform into FT:-\0 */
					bytesMarkers += 5; 
				}
			}
			numEvt++;
		}
	}
	
	/* Now, allocate an item with enough space for both samples and markers */
	item = rda_aux_alloc_item(sizeof(rda_msg_data_t) + bytesSamples + bytesMarkers);
	if (item == NULL) {
		fprintf(stderr, "Out of memory\n");
		goto cleanup;
	}
	
	item->blockNumber = numBlock;
	
	/* Okay, we've got the samples in respSmp, events in respEvt, and a big enough 'item'.
		First fill in the header.
	*/
	{
		rda_msg_data_t *R = (rda_msg_data_t *) item->data;

		memcpy(R->hdr.guid, _rda_guid, sizeof(_rda_guid));
		R->hdr.nType = use16bit ? RDA_INT_MSG : RDA_FLOAT_MSG;
		R->hdr.nSize = item->size;
		R->nBlock = numBlock; 
		R->nPoints = numSmp;
		R->nMarkers = numEvt;
		if (_i_am_big_endian_) {
			/* take care of hdr.nSize, hdr.nType, nBlocks, nPoints, nMarkers */
			ft_swap32(5, &(R->hdr.nSize)); 
		}
	}
	
	/* Now, fill in the samples, possibly using conversion */
	if (numSmp > 0) {
		char *dataDest = ((char *) item->data + sizeof(rda_msg_data_t));
		char *dataSrc  = ((char *) respSmp->buf + sizeof(datadef_t));
		int numTotal = numSmp * numChans;
		
		if (use16bit) {
			if (_i_am_big_endian_) {
				/* copy + swap the 16 bit samples */
				int i;
				for (i=0;i<numTotal;i++) {
					dataDest[0] = dataSrc[1];
					dataDest[1] = dataSrc[0];
					dataDest+=2;
					dataSrc+=2;
				}
			} else {
				/* just copy the samples */
				memcpy(dataDest, dataSrc, bytesSamples);
			}
		} else {
			rda_aux_convert_to_float(numTotal, dataDest, ddef->data_type, dataSrc);
			if (_i_am_big_endian_) ft_swap32(numTotal, dataDest);
		}
	}
	
	/* Finally, fill in the events */
	if (numEvt>0) {
		char *ptr = (char *) item->data + sizeof(rda_msg_data_t) + bytesSamples;
		int offset = 0;
		
		/* count the number of events, increase bytesTotal as required */
		while (offset + sizeof(eventdef_t) <= respEvt->def->bufsize) {
			eventdef_t *evdef = (eventdef_t *) ((char *)respEvt->buf + offset);
			char *evbuf = (char *)respEvt->buf + offset + sizeof(eventdef_t);
			rda_marker_t *marker = (rda_marker_t *) ptr;
			int i, markerPos;
			
			offset += sizeof(eventdef_t) + evdef->bufsize;			
			
			if (evdef->bufsize < evdef->type_numel*wordsize_from_type(evdef->type_type) + evdef->value_numel*wordsize_from_type(evdef->value_type)) {
				continue; /* skip to next event */
			}
			
			markerPos = evdef->sample - (last->nsamples +1); /* relative to first sample in this block */
			marker->nPosition = (markerPos > 0) ? markerPos : 0;  /* needs to be unsigned! */
			marker->nChannel  = -1; /* All channels, FieldTrip doesn't have this*/
			marker->nPoints   = evdef->duration;
			
			ptr += sizeof(rda_marker_t);
			
			if (evdef->type_type == DATATYPE_CHAR) {
				/* copy type */
				for (i=0;i<evdef->type_numel;i++) {
					*ptr++ = *evbuf++;
				}
			} else {
				*ptr++ = 'F';
				*ptr++ = 'T';
				/* Skip bytes in event->buffer */
				evbuf += evdef->type_numel;
			}
			*ptr++ = ':';				
			if (evdef->value_type == DATATYPE_CHAR) {
				/* copy value */
				for (i=0;i<evdef->value_numel;i++) {
					*ptr++ = *evbuf++;
				}
			} else {
				*ptr++ = '-';
			}
			/* add trailing 0, see how big the complete marker got */
			*ptr++ = 0;
			marker->nSize = (ptr - (char *) marker);
			
			if (_i_am_big_endian_) {
				/* convert the 4 int32's in the marker definition */
				ft_swap32(4, (void *) marker);
			}
		}		
	} 
	/* Done */
cleanup:
	if (respSmp) {
		FREE(respSmp->buf);
		FREE(respSmp->def);
		free(respSmp);
	}
	if (respEvt) {
		FREE(respEvt->buf);
		FREE(respEvt->def);
		free(respEvt);
	}
	return item;
}
int main(int argc, char **argv) {
	SerialPort SP;
	int ftBuffer = -1;
	eventdef_t *evdef;
	UINT32_T sizetype, sizevalue, bufsize;
	char *valBuf;
	messagedef_t reqdef;
	message_t request, *response;
	char *confname;
	
	if (argc < 2) {
		confname = "serial_event.conf";
	} else {
		confname = argv[1];
	}
	
	if (parseConfig(&conf, confname) != 0) {
		printf("Errors during parsing the configuration file\n");
		exit(1);
	}
	
	sizetype = wordsize_from_type(conf.type_type) * conf.type_numel;
	sizevalue = wordsize_from_type(conf.value_type) * conf.value_numel;
	
	bufsize = sizeof(eventdef_t) + sizetype + sizevalue;
	evdef = (eventdef_t *) malloc(bufsize);
	
	if (evdef == NULL) {
		printf("Out of memory\n");
		exit(1);
	}
	
	/* prepare fixed fields */
	reqdef.version = VERSION;
	reqdef.bufsize = bufsize;
	reqdef.command = PUT_EVT;
	request.def = &reqdef;
	request.buf = evdef;
	
	evdef->offset = conf.offset;
	evdef->duration = conf.duration;
	evdef->type_type = conf.type_type;
	evdef->type_numel = conf.type_numel;
	evdef->value_type = conf.value_type;
	evdef->value_numel = conf.value_numel;
	evdef->bufsize = sizetype + sizevalue;
	
	valBuf = (char *) evdef + sizeof(eventdef_t);
	memcpy(valBuf, conf.type_buf, sizetype);
	valBuf += sizetype;
	memcpy(valBuf, conf.value_buf, sizevalue);
	
	if (!serialOpenByName(&SP, conf.comport)) {
		printf("Could not open serial port.\n");
		exit(1);
	}
	
	/* timeout = 1 decisecond (least common denominator) = 100 ms */
	if (!serialSetParameters(&SP, conf.baudrate, conf.databits, conf.parity, conf.stopbits, 1)) {
		printf("Could not modify serial port parameters\n");
		exit(1);
	}
	
	ftBuffer = open_connection(conf.hostname, conf.port);
	if (ftBuffer < 0) {
		printf("Connection to FieldTrip buffer failed.\n");
		exit(1);
	}
	
	sample = conf.sample_start;
	
	udp_socket = create_udp_receiver(conf.udp_port);
	
	if (udp_socket != -1) {
		if (pthread_create(&udpThread, NULL, _udp_thread, NULL)) {
			printf("Warning: UDP socket thread could not be spawned.\n");
			closesocket(udp_socket);
			udp_socket = -1;
		}
	}
	
	/* register CTRL-C handler */
	signal(SIGINT, abortHandler);
	
	printf("Starting to listen - press CTRL-C to quit\n");
	while (keepRunning) {
		char input;
		int n;
				
		n = serialRead(&SP, 1, &input);
		if (n<0) {
			printf("Error while reading from serial port - exiting\n");
			break;
		}
		if (n==0) continue; /* timeout - just wait longer */
		
		/* we got one */
		if (conf.character != -1 && conf.character != input) {
			printf("Ignoring input %c\n", input);
			continue;
		}
		
		if (conf.set_value) *valBuf = input;
		pthread_mutex_lock(&sampleMutex);
		evdef->sample = sample;
		pthread_mutex_unlock(&sampleMutex);
		
		if (evdef->sample < 0) {
			printf("Ignoring negative sample (%i) event...\n", evdef->sample);
		} else {
			n = tcprequest(ftBuffer, &request, &response);
		
			if (n<0 || response == NULL) {
				printf("Error in FieldTrip connection\n");
			} else {
				if (response->def == NULL || response->def->command != PUT_OK) {
					printf("FieldTrip server returned an error\n");
				} else {
					printf("Sent off event (sample = %i, input = %c)\n", evdef->sample, input);
				}
				FREE(response->def);
				FREE(response->buf);
				free(response);
			}
		}
		
		pthread_mutex_lock(&sampleMutex);
		sample += conf.sample_increase;
		pthread_mutex_unlock(&sampleMutex);
	}
	
	if (udp_socket!=-1) {
		pthread_join(udpThread, NULL);
		closesocket(udp_socket);
	}

	close_connection(ftBuffer);
	serialClose(&SP);
	free(evdef);
	
	return 0;
}
Exemple #8
0
int buffer_getevt(int server, mxArray *plhs[], const mxArray *prhs[])
{
  int verbose = 0;
  int i, nevents;
  int offset;
  double *val;
  int result;
  
  mxArray *bufptr;
  
  
  message_t *request  = NULL;
  message_t *response = NULL;
  eventsel_t eventsel;
  
  /* this is for the Matlab specific output */
  const char *field_names[] = {
    "type",
    "value",
    "sample",
    "offset",
    "duration"
  };
  
  /* allocate the elements that will be used in the communication */
  request      = malloc(sizeof(message_t));
  request->def = malloc(sizeof(messagedef_t));
  request->buf = NULL;
  request->def->version = VERSION;
  request->def->command = GET_EVT;
  request->def->bufsize = 0;
  
  if ((prhs[0]!=NULL) && (mxGetNumberOfElements(prhs[0])==2) && (mxIsDouble(prhs[0])) && (!mxIsComplex(prhs[0]))) {
    /* fprintf(stderr, "args OK\n"); */
    val = (double *)mxGetData(prhs[0]);
    eventsel.begevent = (UINT32_T)(val[0]);
    eventsel.endevent = (UINT32_T)(val[1]);
    if (verbose) print_eventsel(&eventsel);
    request->def->bufsize = append(&request->buf, request->def->bufsize, &eventsel, sizeof(eventsel_t));
  }
  
  if (verbose) print_request(request->def);
  result = clientrequest(server, request, &response);
  if (verbose) print_response(response->def);
  
  if (result == 0) {
    if (response->def->command==GET_OK) {
	  eventdef_t *event_def;
      /* first count the number of events */
      nevents = 0;
      offset = 0;
      while (offset<response->def->bufsize) {
        event_def = (eventdef_t *)((char *)response->buf + offset);
        /* event_buf = (char *)response->buf + offset + sizeof(eventdef_t); */
        if (verbose) print_eventdef(event_def);
        offset += sizeof(eventdef_t) + event_def->bufsize;
        nevents++;
      }
      
      /* create a structure array that can hold all events */
      plhs[0] = mxCreateStructMatrix(1, nevents, NUMBER_OF_FIELDS, field_names);
      
      offset = 0;
      for (i=0; i<nevents; i++) {
	  	char *buf_type,*buf_value;
		
        event_def = (eventdef_t *) ((char *)response->buf + offset);
		buf_type = (char *) response->buf + offset + sizeof(eventdef_t);
		buf_value = buf_type + event_def->type_numel * wordsize_from_type(event_def->type_type);
                
		mxSetFieldByNumber(plhs[0], i, 0, matrix_from_ft_type_data(event_def->type_type, 1, event_def->type_numel, buf_type));
		mxSetFieldByNumber(plhs[0], i, 1, matrix_from_ft_type_data(event_def->value_type, 1, event_def->value_numel, buf_value));
        mxSetFieldByNumber(plhs[0], i, 2, mxCreateDoubleScalar((double)event_def->sample+1)); /* 1-based in Matlab, 0-based in protocol */
        mxSetFieldByNumber(plhs[0], i, 3, mxCreateDoubleScalar((double)event_def->offset));
        mxSetFieldByNumber(plhs[0], i, 4, mxCreateDoubleScalar((double)event_def->duration));
        offset += sizeof(eventdef_t) + event_def->bufsize;
      }
    }
    else {
      result = response->def->command;
    }
  }
  
  if (request) {
    FREE(request->def);
    FREE(request->buf);
    FREE(request);
  }
  if (response) {
    FREE(response->def);
    FREE(response->buf);
    FREE(response);
  }
  
  return result;
}