You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

108 lines
2.7 KiB

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <stdbool.h>
  5. #include <fcntl.h>
  6. #include <unistd.h>
  7. #include <sys/ioctl.h>
  8. #include <linux/input.h>
  9. static char *argv0 = "./vibrate";
  10. static char *vibrator_file = "/dev/input/by-path/platform-vibrator-event";
  11. void print_usage()
  12. {
  13. printf("usage: %s LENGTH [DELAY] [COUNT]\n", argv0);
  14. printf(" LENGTH = [0..] ... duration of vibration (in ms)\n");
  15. printf(" DELAY = [0..] ... delay before vibration is repeated (in ms)\n");
  16. printf(" COUNT = [1..] ... how many times the vibration pattern is to be repeated\n");
  17. }
  18. void print_usage_and_fail()
  19. {
  20. print_usage();
  21. exit(EXIT_FAILURE);
  22. }
  23. void assert(bool success, char* error_message)
  24. {
  25. if (success) {
  26. return;
  27. }
  28. fprintf(stderr, "%s\n", error_message);
  29. exit(EXIT_FAILURE);
  30. }
  31. void write_event(int fd, int e_id, int value)
  32. {
  33. struct input_event event;
  34. memset(&event, 0, sizeof(event));
  35. event.type = EV_FF;
  36. event.code = e_id;
  37. event.value = value;
  38. int res = write(fd, &event, sizeof event);
  39. assert(res >= 0, "write event failed");
  40. }
  41. void vibrate(int length, int delay, int repeat)
  42. {
  43. int res;
  44. res = setuid(0);
  45. assert(res == 0, "Cannot set root permissions via setuid(0).");
  46. int fd = open(vibrator_file, O_RDWR | O_CLOEXEC);
  47. if (fd < 0) {
  48. fprintf(stderr, "Cannot open file '%s' for writing.\n", vibrator_file);
  49. exit(EXIT_FAILURE);
  50. }
  51. int effects;
  52. res = ioctl(fd, EVIOCGEFFECTS, &effects);
  53. assert(res >= 0, "ioctl(EVIOCGEFFECTS) failed");
  54. assert(effects > 0, "not enough simultaneous effects supported");
  55. /* upload rumble effect */
  56. struct ff_effect e;
  57. memset(&e, 0, sizeof(e));
  58. e.type = FF_RUMBLE,
  59. e.id = -1;
  60. e.replay.length = length;
  61. e.replay.delay = delay;
  62. e.u.rumble.strong_magnitude = 0xc000;
  63. e.u.rumble.weak_magnitude = 0;
  64. res = ioctl(fd, EVIOCSFF, &e);
  65. assert(res >= 0, "ioctl(EVIOCSFF) failed");
  66. /* play vibration pattern */
  67. write_event(fd, e.id, repeat);
  68. usleep((length + delay) * repeat * 1000);
  69. write_event(fd, e.id, 0);
  70. /* clear rumble effect */
  71. res = ioctl(fd, EVIOCRMFF, e.id);
  72. assert(res >= 0, "ioctl(EVIOCRMFF) failed");
  73. close(fd);
  74. }
  75. int main(int argc, char *argv[])
  76. {
  77. if (argc < 1) {
  78. print_usage_and_fail();
  79. }
  80. argv0 = argv[0];
  81. if (argc < 2) {
  82. print_usage_and_fail();
  83. }
  84. int length = atoi(argv[1]);
  85. int delay = argc < 3 ? 0 : atoi(argv[2]);
  86. int repeat = argc < 4 ? 1 : atoi(argv[3]);
  87. if (length < 0 || delay < 0 || repeat <= 0) {
  88. print_usage_and_fail();
  89. }
  90. //printf("vibrate %d ms, wait %d ms, repeat %d\n", length, delay, repeat);
  91. vibrate(length, delay, repeat);
  92. exit(EXIT_SUCCESS);
  93. }