Advertisement
Guest User

Untitled

a guest
May 4th, 2015
215
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.84 KB | None | 0 0
  1. // Standard c and unix libraries
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <stdint.h>
  5. #include <unistd.h>
  6. #include <string.h>
  7. #include <time.h>
  8. #include <fcntl.h>
  9.  
  10. // Threading
  11. #include <pthread.h>
  12. //Input management
  13. #include <linux/input.h>
  14. #include <linux/uinput.h>
  15. // Joystick reading
  16. #include <linux/joystick.h>
  17.  
  18. // ALL OF MY FUNCTIONS EXIT ON ERROR
  19. // Gets a single input event and returns it.
  20. struct js_event getAnInput(FILE *file);
  21.  
  22. // Creates/opens the uinput device (returns filedescriptor)
  23. int createUinput();
  24. // Configures the event types based on an array argv
  25. void configEvtype(int argc, int* argv,int fd);
  26. // Configure the keys usable based on an array argv
  27. void configKeys(int argc, int* argv, int fd);
  28. // Configures the relitive axis usable based on array argv
  29. void configRel(int argc, int* argv, int fd);
  30. // Configure the virtual device and submits it to the filedescriptor
  31. void configureDevice(int fd, char* name, int vendor, int product, int version);
  32. // Send a single event
  33. void sendEvent(int fd, int type, int code, int value);
  34. // Macro to send and then sync an event
  35. #define SendAndSync(fd,type,code,value) sendEvent(fd,type,code,value);sendEvent(fd,EV_SYN,0,0);
  36. // A pthread function which performs mouse axis movements constantly
  37. void *axisThreadLoop(void *ptr);
  38.  
  39. // A record of which axis are pressed, and how much (the last one is for speed of motion on axis)
  40. int axisLog[7] = {0,0,0,0,0,0,1};
  41.  
  42. int main(int argc, char* argv[]) {
  43. // Want root for the uinput device
  44. if (getuid()!=0) {
  45. printf("You must be root to use the uinput device, self escalating with sudo\n");
  46. printf("Hopefully you didnt change the program name\n");
  47. system("sudo ./ouycraft");
  48. exit(0);
  49. }
  50. printf("The program is running as root\n");
  51. // Open the joystick device
  52. FILE *file;
  53. // Either opens to the given joystick, or if none is given, js0
  54. file=fopen(argc==2?argv[1]:"/dev/input/js0","rb");
  55. if (!file) {
  56. printf("File not opened/found\n");
  57. exit(1);
  58. }
  59.  
  60. // Creates the uinput device (returns filedescriptor)
  61. int fd = createUinput();
  62.  
  63. // Configures the evtype to sync, relitive axis, and syncing
  64. int bits[3] = {EV_KEY,EV_REL,EV_SYN};
  65. configEvtype(3, bits,fd);
  66.  
  67. // Configure the keys usable W,S,A,D,ESC,SPACE,E,leftclick,rightclick,middleclick,leftshift
  68. int keys[11] = {KEY_W,KEY_S,KEY_D,KEY_ESC,KEY_SPACE,KEY_A,KEY_E,BTN_LEFT,BTN_RIGHT,BTN_MIDDLE,KEY_LEFTSHIFT};
  69. configKeys(11, keys,fd);
  70.  
  71. // Configure the x and y mouse axis, and the wheel motion
  72. int rel[3] = {REL_X,REL_Y,REL_WHEEL};
  73. configRel(3,rel,fd);
  74.  
  75. // Configure the virtual device for uinput
  76. configureDevice(fd, "ouyInputDevice", 0x1234, 0x5678, 1);
  77. // Tell uinput to now create our device
  78. int ret = ioctl(fd,UI_DEV_CREATE);
  79. if (ret < 0) {
  80. printf("Error creating dev\n");
  81. exit(1);
  82. }
  83. printf("Congratulations, everything is configure, please wait a second");
  84. sleep(1);
  85. printf("Ready to run joystick actions!\n");
  86.  
  87. // Thread to control the axis, needs the filedescriptor too
  88. pthread_t axisThread;
  89. int retval = pthread_create( &axisThread, NULL, axisThreadLoop, (void*)&fd);
  90. if (retval) {printf("Thread not created, exiting\n");exit(1);}
  91.  
  92. // A main loop for the program
  93. while (1) {
  94. // jevent is not java event, but joystick event, its read in every while loop
  95. struct js_event jevent = getAnInput(file);
  96. // If jevent.type = 2 then its a axis movement with extra possible values
  97. if (jevent.type == 2) {
  98. // axis
  99. switch(jevent.number) {
  100. // Move left or right (left joystick x)
  101. case 0:
  102. if (axisLog[0] == 1 && jevent.value>=10) break;
  103. if (axisLog[0] == 0 && jevent.value<=10 && jevent.value>=-10) break;
  104. if (axisLog[0] == -1 && jevent.value<=-10) break;
  105. if (axisLog[0] == 1 && jevent.value<10) {SendAndSync(fd,EV_KEY,KEY_D,0); axisLog[0]=0;}
  106. if (axisLog[0] == -1 && jevent.value>-10) {SendAndSync(fd,EV_KEY,KEY_A,0);axisLog[0]=0;}
  107. if (axisLog[0] == 0 && jevent.value<=-10) {SendAndSync(fd,EV_KEY,KEY_A,1);axisLog[0]=-1;}
  108. if (axisLog[0] == 0 && jevent.value>=10) {SendAndSync(fd,EV_KEY,KEY_D,1);axisLog[0]=1;}
  109. break;
  110. // Move forward or backwards (left joystick y)
  111. case 1:
  112. if (axisLog[1] == 1 && jevent.value>=10) break;
  113. if (axisLog[1] == 0 && jevent.value<=10 && jevent.value>=-10) break;
  114. if (axisLog[1] == -1 && jevent.value<=-10) break;
  115. if (axisLog[1] == 1 && jevent.value<10) {SendAndSync(fd,EV_KEY,KEY_S,0); axisLog[1]=0;}
  116. if (axisLog[1] == -1 && jevent.value>-10) {SendAndSync(fd,EV_KEY,KEY_W,0);axisLog[1]=0;}
  117. if (axisLog[1] == 0 && jevent.value<=-10) {SendAndSync(fd,EV_KEY,KEY_W,1);axisLog[1]=-1;}
  118. if (axisLog[1] == 0 && jevent.value>=10) {SendAndSync(fd,EV_KEY,KEY_S,1);axisLog[1]=1;}
  119. break;
  120. // Select an item to the left (left trigger)
  121. case 2:
  122. if (axisLog[2] == jevent.value>=-32760 || axisLog[2]) break;
  123. axisLog[2] = jevent.value>=-32760;
  124. SendAndSync(fd,EV_REL,REL_WHEEL,-1);
  125. break;
  126. // just copy the mousemove for x, (right joystick x)
  127. case 3:
  128. axisLog[3] = jevent.value;
  129. break;
  130. // Just copy the mousemove for y, (right joystick y)
  131. case 4:
  132. axisLog[4] = jevent.value;
  133. break;
  134. // Select an item to the right (right trigger)
  135. case 5:
  136. if (axisLog[5] == jevent.value>=-32760 || axisLog[5]) break;
  137. axisLog[5] = jevent.value>=-32760;
  138. SendAndSync(fd,EV_REL,REL_WHEEL,1);
  139. break;
  140. }
  141. // If jevent.type = 1 its a simple button press
  142. } else if (jevent.type == 1) {
  143. // button
  144. switch (jevent.number) {
  145. // PS x Equivlent(jump)
  146. case 0: SendAndSync(fd,EV_KEY,KEY_SPACE,jevent.value);break;
  147. // PS circle equivlent (open inventory and slow mouse)
  148. case 3: SendAndSync(fd,EV_KEY,KEY_E,jevent.value);if (jevent.value) {axisLog[6]= !axisLog[6];}break;
  149. // Left bumper (place block)
  150. case 4: SendAndSync(fd,EV_KEY,BTN_RIGHT,jevent.value);break;//if(jevent.value){SendAndSync(fd,EV_REL,REL_WHEEL,1);}break;
  151. // Right bumper (remove block)
  152. case 5: SendAndSync(fd,EV_KEY,BTN_LEFT,jevent.value);break;//if (jevent.value){SendAndSync(fd,EV_REL,REL_WHEEL,-1);}break;
  153. // Left stick click (shiftwalk)
  154. case 6: SendAndSync(fd,EV_KEY,KEY_LEFTSHIFT,jevent.value);break;
  155. // Right stick click (copy block)
  156. case 7: SendAndSync(fd,EV_KEY,BTN_MIDDLE,jevent.value);break;
  157. // Dpad down (slow mouse)
  158. case 9: if (jevent.value) {axisLog[6]= !axisLog[6];}break;
  159. //case 12: SendAndSync(fd,EV_KEY,BTN_RIGHT,jevent.value);break;
  160. //case 13: SendAndSync(fd,EV_KEY,BTN_LEFT,jevent.value);break;
  161. // Home button (open menu)
  162. case 14: SendAndSync(fd,EV_KEY,KEY_ESC,jevent.value);break;
  163. }
  164. // Ignore all other messages, (joystick initialization actions)
  165. } else continue;
  166. }
  167. }
  168.  
  169. // Get a single input event, and return it
  170. struct js_event getAnInput(FILE *file) {
  171. struct js_event jevent;
  172. int returnvalue = fread(&jevent,sizeof(jevent),1, file);
  173. if (returnvalue<0) {printf("file failed read\n");exit(1);}
  174. return jevent;
  175. }
  176.  
  177. // Deal with the axis on a time based loop, prevents blocking from fread on the js0 file
  178. void *axisThreadLoop(void *ptr) {
  179. // Restore the filedescriptor
  180. int fd = * (int*) ptr;
  181.  
  182. // get the current time for usage later
  183. clock_t start = clock();
  184. clock_t cur;
  185.  
  186. // Loop for the events,(never exits)
  187. while (1) {
  188. // get the current time of the loop start
  189. cur = clock();
  190. // clock() calls can rap arround after about 75 minutes, should only hickup this way
  191. if (cur-start < 0) start=clock();
  192. // Wait a consistent time
  193. if (cur-start <= 10000) continue;
  194. // Reset the start time
  195. start = clock();
  196. // The axisLog[6] is to change the mouse speed, helpful for menus
  197. // The x axis is sent first but not synced
  198. sendEvent(fd,EV_REL,REL_X,(int)axisLog[3]/(axisLog[6]?1900:4000));
  199. // The y axis is sent, and we can sync it now, so now x and y are synced
  200. SendAndSync(fd,EV_REL,REL_Y,(int)axisLog[4]/(axisLog[6]?1900:4000));
  201. }
  202. }
  203.  
  204. // Send our event into the uevent descriptor
  205. void sendEvent(int fd, int type, int code, int value) {
  206. // The event to be sent
  207. struct input_event ev;
  208. // 0 out all the values(i was told to)
  209. memset(&ev,0,sizeof(ev));
  210. // Copy in the type, code, and value
  211. ev.type = type;
  212. ev.code = code;
  213. ev.value = value;
  214.  
  215. //POTENTIAL BUG? i dont know what the write shoudl return, il leave asis
  216. if (write(fd,&ev,sizeof(ev))<=0) {
  217. printf("Error write\n");
  218. exit(1);
  219. }
  220. }
  221.  
  222. // Configure the ev types based on the loop
  223. void configEvtype(int argc, int* argv,int fd) {
  224. int ret;
  225. for (int i = 0; i < argc; i++) {
  226. // Ioctl configures the ui_set_evbit for me
  227. ret = ioctl(fd,UI_SET_EVBIT,argv[i]);
  228. if (ret < 0) {
  229. printf("Error setevntype %i\n",i);
  230. exit(1);
  231. }
  232. }
  233. }
  234.  
  235. // same as configevtype but with keys
  236. void configKeys(int argc, int* argv, int fd) {
  237. int ret;
  238. for (int i = 0; i < argc; i++) {
  239. ret = ioctl(fd,UI_SET_KEYBIT,argv[i]);
  240. if (ret < 0) {
  241. printf("Error setkey %i\n",i);
  242. exit(1);
  243. }
  244. }
  245. }
  246.  
  247. // same as configevtype but with relitive events
  248. void configRel(int argc, int* argv, int fd) {
  249. int ret;
  250. for (int i = 0; i < argc; i++) {
  251. ret = ioctl(fd,UI_SET_RELBIT,argv[i]);
  252. if (ret < 0) {
  253. printf("Error setrel %i\n",i);
  254. exit(1);
  255. }
  256. }
  257. }
  258.  
  259. // Create a fake device for our uevent
  260. void configureDevice(int fd, char* name, int vendor, int product, int version) {
  261. struct uinput_user_dev uidev;
  262. memset(&uidev,0,sizeof(uidev));
  263. snprintf(uidev.name,UINPUT_MAX_NAME_SIZE,name);
  264. uidev.id.bustype=BUS_USB;
  265. uidev.id.vendor=vendor;
  266. uidev.id.product=product;
  267. uidev.id.version=version;
  268.  
  269. int ret = write(fd,&uidev,sizeof(uidev));
  270. if (ret < 0) {
  271. printf("Error on writing thing\n");
  272. exit(1);
  273. }
  274. }
  275.  
  276. // Create an input device based on /dev/uinput or /dev/input/uinput
  277. int createUinput() {
  278. int fd;
  279. // On my system its /dev/uinput, on some it may be /dev/input/uinput. lets try both
  280. fd = open("/dev/uinput",O_WRONLY | O_NONBLOCK);
  281. if (fd < 0) {
  282. printf("Failed to open file, Trying other input device\n");
  283. fd = open("/dev/input/uinput",O_WRONLY | O_NONBLOCK);
  284. if (fd < 0) {
  285. printf("No luck on input files, exiting\n");
  286. exit(1);
  287. }
  288. }
  289. return fd;
  290. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement