+ dev->fd = fd;
+
+ if (event_support & (1 << EV_ABS)) {
+ ret = ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_support)),
+ &abs_support);
+ if (ret < 0)
+ perror("EVIOCGBIT");
+ for (i = 0; i < ARRAY_SIZE(dev->abs); i++) {
+ if (!(abs_support & (1 << i)))
+ continue;
+ ret = ioctl(fd, EVIOCGABS(i), &absi);
+ if (ret != 0) {
+ perror("EVIOCGABS");
+ continue;
+ }
+ dev->abs[i].min = absi.minimum;
+ dev->abs[i].max = absi.maximum;
+ dev->abs[i].zone = (absi.maximum - absi.minimum) / 3;
+ }
+ }
+
+ memcpy(dev->kc_map, evdev_md_default_map, sizeof(dev->kc_map));
+ if (binds != NULL) {
+ unsigned int kc, end = 0;
+
+ p = binds;
+ do {
+ s = p;
+ for (; *p != 0 && *p != ','; p++)
+ ;
+ if (*p == 0)
+ end = 1;
+ else
+ *p++ = 0;
+ if (strncmp(s, "j=", 2) == 0) {
+ kc = BTN_JOYSTICK;
+ s += 2;
+ }
+ else if (strncmp(s, "g=", 2) == 0) {
+ kc = BTN_GAMEPAD;
+ s += 2;
+ }
+ else {
+ ret = sscanf(s, "%u=", &kc);
+ if (ret != 1 || (s = strchr(s, '=')) == NULL) {
+ fprintf(stderr, "parse failed: '%s'\n", s);
+ break;
+ }
+ s++;
+ }
+ // bind
+ for (; *s != 0 && kc < sizeof(dev->kc_map); s++, kc++) {
+ uint32_t mask = bind_to_mask[(uint8_t)*s];
+ if (mask == 0 && *s != '0') {
+ fprintf(stderr, "%s: '%c' is not a valid MD btn\n", name, *s);
+ continue;
+ }
+ dev->kc_map[kc] = mask;
+ }
+ }
+ while (!end);
+ }
+
+ return 0;