Due native USB bidirectional I/O performance [Now with specific example]

I believe the problems you've been seeing are caused by incorrect baud rate settings on the programming port.

Using "stty" to set the baud rate is not reliable. Here is a copy of your code using the proper termios functions to set the baud rate after the port is open. This version always receives the 2400 32-byte packets in 6 or 7 seconds.

#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <termios.h>

#define PKTS           2400
#define PKT_SIZE       32
#define SER_PORT_IN    "/dev/ttyACM0"  // On my system this is programming                                                                   
#define SER_PORT_OUT   "/dev/ttyACM1"  // On my system this is native USB                                                                    
#define SER_PORT_SPEED 115200

#define TEST_READ     1
#define TEST_WRITE    0

int main() {

  time_t deltaT = 0;
  int i = 0, bytes = 0, totalBytes = 0, fdIn = 0, fdOut = 0;
  char buf[PKT_SIZE];
  struct termios t;

#if !(TEST_READ || TEST_WRITE)
  printf("Nothing to test, change TEST_READ to 1 or TEST_WRITE to 1\n");
  return(0);
#endif

#if TEST_READ
  // this stty command does not seem to set the baud rate in some cases
  snprintf(buf, sizeof(buf)-1, "stty -F %s sane raw -echo %d", SER_PORT_IN, SER_PORT_SPEED);
  errno = 0;
  fdIn = open(SER_PORT_IN, O_RDWR | O_NOCTTY);
  if (fdIn < 0)  {
    printf("ERROR: Unable to open port %s, err(%d): %s\n",
           SER_PORT_IN, errno, strerror(errno));
    return(-1);
  }
  // using the termios functions after the port is open is very reliable
  tcgetattr(fdIn, &t);
  cfsetispeed(&t, B115200);
  tcsetattr(fdIn, TCSANOW, &t);
  printf("Succfully opened %s for reading\n", SER_PORT_IN);
#endif

#if TEST_WRITE
  snprintf(buf, sizeof(buf)-1, "stty -F %s sane raw -echo", SER_PORT_OUT);
  system(buf);

  // Time for device to reset and native USB dev node to show up again                                                                       
  sleep(4);

  errno = 0;
  fdOut = open(SER_PORT_OUT, O_RDWR | O_NOCTTY);
  if (fdOut < 0)  {
    printf("ERROR: Unable to open port %s, err(%d): %s\n",
           SER_PORT_OUT, errno, strerror(errno));
    return(-1);
  }
  printf("Succfully opened %s for writing\n", SER_PORT_OUT);
#endif

  deltaT = time(NULL);
  for (i = 0; i < PKTS; i++) {
#if TEST_WRITE
    // Ensure full packet is delivered                                                                                                       
    bytes = 0; totalBytes = 0;
    while (totalBytes < sizeof(buf)) {
      errno = 0;
      bytes = write(fdOut, buf+totalBytes, sizeof(buf) - totalBytes);
      if (bytes < 0) {
        printf("ERROR: Unable to write to  port %s, err(%d): %s\n",
               SER_PORT_OUT, errno, strerror(errno));
        return(-1);
      }
      totalBytes += bytes;
    }
#endif

#if TEST_READ
    bytes = 0; totalBytes = 0;
    while (totalBytes < sizeof(buf)) {
      errno = 0;
      bytes = read(fdIn, buf+totalBytes, sizeof(buf) - totalBytes);
      if (bytes < 0) {
        printf("ERROR: Unable to read from port %s, err(%d): %s\n",
               SER_PORT_IN, errno, strerror(errno));
        return(-2);
      }
      //printf("read %d\n", bytes);
      totalBytes += bytes;
    }
#endif
  }
  printf("Total time to run test with %d packets of size %d was %d seconds\n",
         PKTS, (int)sizeof(buf), (int)(time(NULL) - deltaT));
  return 0;
}