int main()

in testing/drivers/fftest/fftest.c [61:449]


int main(int argc, FAR char **argv)
{
  unsigned char fffeatures[1 + FF_MAX / 8 / sizeof(unsigned char)];
  FAR const char *device_file_name = "/dev/input_ff0";
  struct ff_effect effects[N_EFFECTS];
  struct ff_event_s play;
  struct ff_event_s stop;
  struct ff_event_s gain;
  int neffects; /* Number of effects the device can play at the same time */
  int fd;
  int i;

  printf("Force feedback test program.\n");
  for (i = 1; i < argc; i++)
    {
      if (strncmp(argv[i], "--help", 8) == 0)
        {
          printf("Usage: %s /dev/input_ffX\n", argv[0]);
          printf("Tests the force feedback driver\n");
          return -EINVAL;
        }
      else
        {
          device_file_name = argv[i];
        }
    }

  fd = open(device_file_name, O_WRONLY);
  if (fd < 0)
    {
      perror("Open device file");
      return -errno;
    }

  printf("Device %s opened\n", device_file_name);

  /* Query device */

  printf("features:\n");

  /* Force feedback effects */

  memset(fffeatures, 0, sizeof(fffeatures));
  if (ioctl(fd, EVIOCGBIT, fffeatures) < 0)
    {
      perror("Ioctl force feedback features query");
      goto out;
    }

  printf("  * Force feedback effects types: ");
  if (test_bit(FF_CONSTANT, fffeatures))
    {
      printf("Constant, ");
    }

  if (test_bit(FF_PERIODIC, fffeatures))
    {
      printf("Periodic, ");
    }

  if (test_bit(FF_RAMP, fffeatures))
    {
      printf("Ramp, ");
    }

  if (test_bit(FF_SPRING, fffeatures))
    {
      printf("Spring, ");
    }

  if (test_bit(FF_FRICTION, fffeatures))
    {
      printf("Friction, ");
    }

  if (test_bit(FF_DAMPER, fffeatures))
    {
      printf("Damper, ");
    }

  if (test_bit(FF_RUMBLE, fffeatures))
    {
      printf("Rumble, ");
    }

  if (test_bit(FF_INERTIA, fffeatures))
    {
      printf("Inertia, ");
    }

  if (test_bit(FF_GAIN, fffeatures))
    {
      printf("Gain, ");
    }

  if (test_bit(FF_AUTOCENTER, fffeatures))
    {
      printf("Autocenter, ");
    }

  printf("\n    Force feedback periodic effects: ");
  if (test_bit(FF_SQUARE, fffeatures))
    {
      printf("Square, ");
    }

  if (test_bit(FF_TRIANGLE, fffeatures))
    {
      printf("Triangle, ");
    }

  if (test_bit(FF_SINE, fffeatures))
    {
      printf("Sine, ");
    }

  if (test_bit(FF_SAW_UP, fffeatures))
    {
      printf("Saw up, ");
    }

  if (test_bit(FF_SAW_DOWN, fffeatures))
    {
      printf("Saw down, ");
    }

  if (test_bit(FF_CUSTOM, fffeatures))
    {
      printf("Custom, ");
    }

  printf("\n    [");
  for (i = 0; i < sizeof(fffeatures) / sizeof(unsigned char); i++)
    {
      printf("%02X ", fffeatures[i]);
    }

  printf("]\n");
  printf("  * Number of simultaneous effects: ");
  if (ioctl(fd, EVIOCGEFFECTS, &neffects) < 0)
    {
      perror("Ioctl number of effects");
      goto out;
    }

  printf("%d\n\n", neffects);

  /* Set master gain to 75% if supported */

  if (test_bit(FF_GAIN, fffeatures))
    {
      memset(&gain, 0, sizeof(gain));
      gain.code = FF_GAIN;
      gain.value = 0xc000; /* [0, 0xFFFF] */

      printf("Setting master gain to 75%% ... ");
      fflush(stdout);

      if (write(fd, &gain, sizeof(gain)) != sizeof(gain))
        {
          perror("Error: write fd failed");
          goto out;
        }
      else
        {
          printf("OK\n");
        }
    }

  /* Download a periodic sinusoidal effect */

  memset(&effects[0], 0, sizeof(effects[0]));
  effects[0].type = FF_PERIODIC;
  effects[0].id = -1;
  effects[0].u.periodic.waveform = FF_SINE;
  effects[0].u.periodic.period = 100; /* 0.1 second */
  effects[0].u.periodic.magnitude = 0x7fff;
  effects[0].u.periodic.offset = 0;
  effects[0].u.periodic.phase = 0;
  effects[0].direction = 0x4000; /* Along X axis */
  effects[0].u.periodic.envelope.attack_length = 1000;
  effects[0].u.periodic.envelope.attack_level = 0x7fff;
  effects[0].u.periodic.envelope.fade_length = 1000;
  effects[0].u.periodic.envelope.fade_level = 0x7fff;
  effects[0].trigger.button = 0;
  effects[0].trigger.interval = 0;
  effects[0].replay.length = 20000; /* 20 seconds */
  effects[0].replay.delay = 1000;

  printf("Uploading effect #0 (Periodic sinusoidal) ... ");
  fflush(stdout);

  if (ioctl(fd, EVIOCSFF, &effects[0]) < 0)
    {
      perror("Error: ioctl failed");
      goto out;
    }
  else
    {
      printf("OK (id %d)\n", effects[0].id);
    }

  /* Download a constant effect */

  effects[1].type = FF_CONSTANT;
  effects[1].id = -1;
  effects[1].u.constant.level = 0x2000; /* Strength : 25 % */
  effects[1].direction = 0x6000;
  effects[1].u.constant.envelope.attack_length = 1000;
  effects[1].u.constant.envelope.attack_level = 0x1000;
  effects[1].u.constant.envelope.fade_length = 1000;
  effects[1].u.constant.envelope.fade_level = 0x1000;
  effects[1].trigger.button = 0;
  effects[1].trigger.interval = 0;
  effects[1].replay.length = 20000; /* 20 seconds */
  effects[1].replay.delay = 0;

  printf("Uploading effect #1 (Constant) ... ");
  fflush(stdout);

  if (ioctl(fd, EVIOCSFF, &effects[1]) < 0)
    {
      perror("Error: ioctl failed");
      goto out;
    }
  else
    {
      printf("OK (id %d)\n", effects[1].id);
    }

  /* Download a condition spring effect */

  effects[2].type = FF_SPRING;
  effects[2].id = -1;
  effects[2].u.condition[0].right_saturation = 0x7fff;
  effects[2].u.condition[0].left_saturation = 0x7fff;
  effects[2].u.condition[0].right_coeff = 0x2000;
  effects[2].u.condition[0].left_coeff = 0x2000;
  effects[2].u.condition[0].deadband = 0x0;
  effects[2].u.condition[0].center = 0x0;
  effects[2].u.condition[1] = effects[2].u.condition[0];
  effects[2].trigger.button = 0;
  effects[2].trigger.interval = 0;
  effects[2].replay.length = 20000; /* 20 seconds */
  effects[2].replay.delay = 0;

  printf("Uploading effect #2 (Spring) ... ");
  fflush(stdout);

  if (ioctl(fd, EVIOCSFF, &effects[2]) < 0)
    {
      perror("Error: ioctl failed");
      goto out;
    }
  else
    {
      printf("OK (id %d)\n", effects[2].id);
    }

  /* Download a condition damper effect */

  effects[3].type = FF_DAMPER;
  effects[3].id = -1;
  effects[3].u.condition[0].right_saturation = 0x7fff;
  effects[3].u.condition[0].left_saturation = 0x7fff;
  effects[3].u.condition[0].right_coeff = 0x2000;
  effects[3].u.condition[0].left_coeff = 0x2000;
  effects[3].u.condition[0].deadband = 0x0;
  effects[3].u.condition[0].center = 0x0;
  effects[3].u.condition[1] = effects[3].u.condition[0];
  effects[3].trigger.button = 0;
  effects[3].trigger.interval = 0;
  effects[3].replay.length = 20000; /* 20 seconds */
  effects[3].replay.delay = 0;

  printf("Uploading effect #3 (Damper) ... ");
  fflush(stdout);

  if (ioctl(fd, EVIOCSFF, &effects[3]) < 0)
    {
      perror("Error: ioctl failed");
      goto out;
    }
  else
    {
      printf("OK (id %d)\n", effects[3].id);
    }

  /* A strong rumbling effect */

  effects[4].type = FF_RUMBLE;
  effects[4].id = -1;
  effects[4].u.rumble.strong_magnitude = 0x8000;
  effects[4].u.rumble.weak_magnitude = 0;
  effects[4].replay.length = 5000;
  effects[4].replay.delay = 1000;

  printf("Uploading effect #4 (Strong rumble, with heavy motor) ... ");
  fflush(stdout);

  if (ioctl(fd, EVIOCSFF, &effects[4]) < 0)
    {
      perror("Error: ioctl failed");
      goto out;
    }
  else
    {
      printf("OK (id %d)\n", effects[4].id);
    }

  /* A weak rumbling effect */

  effects[5].type = FF_RUMBLE;
  effects[5].id = -1;
  effects[5].u.rumble.strong_magnitude = 0;
  effects[5].u.rumble.weak_magnitude = 0xc000;
  effects[5].replay.length = 5000;
  effects[5].replay.delay = 0;

  printf("Uploading effect #5 (Weak rumble, with light motor) ... ");
  fflush(stdout);

  if (ioctl(fd, EVIOCSFF, &effects[5]) < 0)
    {
      perror("Error: ioctl failed");
      goto out;
    }
  else
    {
      printf("OK (id %d)\n", effects[5].id);
    }

  /* Ask user what effects to play */

  do
    {
      printf("Enter effect number, -1 to exit\n");
      i = -1;
      if (scanf("%d", &i) == EOF)
        {
          printf("Read error\n");
        }
      else if (i >= 0 && i < N_EFFECTS)
        {
          memset(&play, 0, sizeof(play));
          play.code = effects[i].id;
          play.value = 1;
          if (write(fd, &play, sizeof(play)) < 0)
            {
              perror("Play effect failed");
              goto out;
            }

          printf("Now Playing: %s\n", g_effect_names[i]);
        }
      else if (i == -2)
        {
          /* Crash test */

          i = *((FAR int *)0);
          printf("Crash test: %d\n", i);
        }
      else if (i != -1)
        {
          printf("No such effect\n");
        }
    }
  while (i >= 0);

  /* Stop the effects */

  printf("Stopping effects\n");
  for (i = 0; i < N_EFFECTS; i++)
    {
      memset(&stop, 0, sizeof(stop));
      stop.code = effects[i].id;
      stop.value = 0;

      if (write(fd, &stop, sizeof(stop)) < 0)
        {
          perror("Error write fd failed");
          goto out;
        }
    }

out:
  close(fd);
  return errno > 0 ? -errno : 0;
}