Example #1
2
int evdev_is_suitable(int fd)
{
	long evtype_bitmask[(EV_MAX/BITS_PER_LONG) + 1];

	/* Clean evtype_bitmask structure */
	memset(evtype_bitmask, 0, sizeof(evtype_bitmask));

	/* Ask device features */
	if (ioctl(fd, EVIOCGBIT(0, EV_MAX), evtype_bitmask) < 0) {
		log_msg(lg, "+ can't get evdev features: %s", ERRMSG);
		return 0;
	}

#ifdef DEBUG
	int yalv;
	for (yalv = 0; yalv < EV_MAX; yalv++) {
		if (test_bit(yalv, evtype_bitmask)) {
			/* this means that the bit is set in the event types list */
			switch (yalv) {
			case EV_SYN:
				log_msg(lg, " + Sync");
				break;
			case EV_KEY:
				log_msg(lg, " + Keys or Buttons");
				break;
			case EV_REL:
				log_msg(lg, " + Relative Axes");
				break;
			case EV_ABS:
				log_msg(lg, " + Absolute Axes");
				break;
			case EV_MSC:
				log_msg(lg, " + Something miscellaneous");
				break;
			case EV_SW:
				log_msg(lg, " + Switch");
				break;
			case EV_LED:
				log_msg(lg, " + LEDs");
				break;
			case EV_SND:
				log_msg(lg, " + Sounds");
				break;
			case EV_REP:
				log_msg(lg, " + Repeat");
				break;
			case EV_FF:
				log_msg(lg, " + Force Feedback");
				break;
			case EV_PWR:
				log_msg(lg, " + Power");
				break;
			case EV_FF_STATUS:
				log_msg(lg, " + Force Feedback Status");
				break;
			default:
				log_msg(lg, " + Unknown event type: 0x%04hx", yalv);
				break;
			}
		}
	}
#endif

	/* Check that we have EV_KEY bit set */
	if (test_bit(EV_KEY, evtype_bitmask)) return 1;

	/* device is not suitable */
	log_msg(lg, "+ evdev have no EV_KEY bit, skipped");
	return 0;
}
      compat_hat_offs = ev_abs_count;
     ev_hat_count++;
    }
    ev_abs_count++;
   }
  }
  //printf("%u\n", compat_hat_offs);
  CalcOldStyleID(ev_abs_count - ev_hat_count, 0, ev_hat_count / 2, num_buttons);
 }

#if 0
  uint8 keybits[(KEY_CNT + 7) / 8];
  unsigned ev_button_count = 0;
  
  memset(keybits, 0, sizeof(keybits));
  ioctl(evdev_fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits);
  hashie.update(keybits, sizeof(keybits));

  for(unsigned kbt = 0; kbt < KEY_CNT; kbt++)
  {
   if(keybits[kbt >> 3] & (1 << (kbt & 0x7)))
   {
    ev_button_count++;
   }
  }
  printf("moo: %u\n", ev_button_count);
 }
#endif

 rumble_supported = false;
 rumble_used = false;
void lightgun_event_abs_init(void)
{
	int i;

	for (i = 0; i < GUN_MAX; i++) {
		char name[256] = "Unknown";
		uint8_t abs_bitmask[ABS_MAX/8 + 1];
		struct input_absinfo abs_features;

		if (!lg_devices[i].device)
			continue;

		if ((lg_devices[i].fd = open(lg_devices[i].device, O_RDONLY)) < 0) {
			fprintf(stderr_file, "Lightgun%d: %s[open]: %s",
				i + 1, lg_devices[i].device, strerror(errno));
			continue;
		}

		if (ioctl(lg_devices[i].fd, EVIOCGNAME(sizeof(name)), name) < 0) {
			fprintf(stderr_file, "Lightgun%d: %s[ioctl/EVIOCGNAME]: %s\n",
				i + 1, lg_devices[i].device, strerror(errno));
			lg_devices[i].device = NULL;
			continue;
		}

		memset(abs_bitmask, 0, sizeof(abs_bitmask));
		if (ioctl(lg_devices[i].fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) < 0) {
			fprintf(stderr_file, "Lightgun%d: %s[ioctl/EVIOCGNAME]: %s\n",
				i + 1, lg_devices[i].device, strerror(errno));
			lg_devices[i].device = NULL;
			continue;
		}

		/* Make sure we have an X and Y axis. Not much good
		 * without it. */
		if (!test_bit(ABS_X, abs_bitmask) || !test_bit(ABS_Y, abs_bitmask)) {
			fprintf(stderr_file, "Lightgun%d: %s: Does not contain both X and Y axis, "
				"ignoring\n", i + 1, lg_devices[i].device);
			lg_devices[i].device = NULL;
			continue;
		}

		if (ioctl(lg_devices[i].fd, EVIOCGABS(ABS_X), &abs_features)) {
			fprintf(stderr_file, "Lightgun%d: %s[ioctl/EVIOCGABS(ABX_X)]: %s\n",
				i + 1, lg_devices[i].device, strerror(errno));
			lg_devices[i].device = NULL;
			continue;
		}

		lg_devices[i].min[LG_X_AXIS] = abs_features.minimum;
		lg_devices[i].range[LG_X_AXIS] = abs_features.maximum - abs_features.minimum;

		if (ioctl(lg_devices[i].fd, EVIOCGABS(ABS_Y), &abs_features)) {
			fprintf(stderr_file, "Lightgun%d: %s[ioctl/EVIOCGABS(ABX_Y)]: %s\n",
				i + 1, lg_devices[i].device, strerror(errno));
			lg_devices[i].device = NULL;
			continue;
		}

		lg_devices[i].min[LG_Y_AXIS] = abs_features.minimum;
		lg_devices[i].range[LG_Y_AXIS] = abs_features.maximum - abs_features.minimum;

		fprintf(stderr_file, "Lightgun%d: %s\n", i + 1, name);
		fprintf(stderr_file, "           X axis:  min[%d]  range[%d]\n",
			lg_devices[i].min[LG_X_AXIS], lg_devices[i].range[LG_X_AXIS]);
		fprintf(stderr_file, "           Y axis:  min[%d]  range[%d]\n",
			lg_devices[i].min[LG_Y_AXIS], lg_devices[i].range[LG_Y_AXIS]);
	}
}
/*
 * Fill device information.
 * Queries the input device and tries to classify it.
 */
void CLinuxInputDevice::GetInfo(int fd)
{
  unsigned int num_keys = 0;
  unsigned int num_ext_keys = 0;
  unsigned int num_buttons = 0;
  unsigned int num_rels = 0;
  unsigned int num_abs = 0;

  unsigned long evbit[NBITS(EV_CNT)];
  unsigned long keybit[NBITS(KEY_CNT)];

  /* get device name */
  bzero(m_deviceName, sizeof(m_deviceName));
  ioctl(fd, EVIOCGNAME(sizeof(m_deviceName)-1), m_deviceName);

  if (strncmp(m_deviceName, "D-Link Boxee D-Link Boxee Receiver", strlen("D-Link Boxee D-Link Boxee Receiver")) == 0)
  {
    m_bSkipNonKeyEvents = true;
  }
  else
  {
    m_bSkipNonKeyEvents = false;
  }
  CLog::Log(LOGINFO, "opened device '%s' (file name %s), m_bSkipNonKeyEvents %d\n", m_deviceName, m_fileName.c_str(), m_bSkipNonKeyEvents);

  /* get event type bits */
  ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit);

  if (test_bit( EV_KEY, evbit ))
  {
    int i;

    /* get keyboard bits */
    ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit);

    /**  count typical keyboard keys only */
    for (i = KEY_Q; i <= KEY_M; i++)
      if (test_bit( i, keybit ))
        num_keys++;

    for (i = KEY_OK; i < KEY_CNT; i++)
      if (test_bit( i, keybit ))
        num_ext_keys++;

    for (i = BTN_MOUSE; i < BTN_JOYSTICK; i++)
      if (test_bit( i, keybit ))
        num_buttons++;
  }

#ifndef HAS_INTELCE
  unsigned long relbit[NBITS(REL_CNT)];
  unsigned long absbit[NBITS(ABS_CNT)];

  if (test_bit( EV_REL, evbit ))
  {
    int i;

    /* get bits for relative axes */
    ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit);

    for (i = 0; i < REL_CNT; i++)
      if (test_bit( i, relbit ))
        num_rels++;
  }

  if (test_bit( EV_ABS, evbit ))
  {
    int i;

    /* get bits for absolute axes */
    ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit);

    for (i = 0; i < ABS_PRESSURE; i++)
      if (test_bit( i, absbit ))
        num_abs++;
  }

  /* Mouse, Touchscreen or Smartpad ? */
  if ((test_bit( EV_KEY, evbit ) && (test_bit( BTN_TOUCH, keybit )
      || test_bit( BTN_TOOL_FINGER, keybit ))) || ((num_rels >= 2
      && num_buttons) || (num_abs == 2 && (num_buttons == 1))))
    m_deviceType |= LI_DEVICE_MOUSE;
  else if (num_abs && num_buttons) /* Or a Joystick? */
    m_deviceType |= LI_DEVICE_JOYSTICK;
#endif

  /* A Keyboard, do we have at least some letters? */
  if (num_keys > 20)
  {
    m_deviceType |= LI_DEVICE_KEYBOARD;
    m_deviceCaps |= LI_CAPS_KEYS;

    m_deviceMinKeyCode = 0;
    m_deviceMaxKeyCode = 127;
  }

  /* A Remote Control? */
  if (num_ext_keys)
  {
    m_deviceType |= LI_DEVICE_REMOTE;
    m_deviceCaps |= LI_CAPS_KEYS;
  }

  /* Buttons */
  if (num_buttons)
  {
    m_deviceCaps |= LI_CAPS_BUTTONS;
    m_deviceMaxKeyCode = num_buttons - 1;
  }

  /* Axes */
  if (num_rels || num_abs)
  {
    m_deviceCaps |= LI_CAPS_AXES;
    m_deviceMaxAxis = std::max(num_rels, num_abs) - 1;
  }

  /* Decide which primary input device to be. */
  if (m_deviceType & LI_DEVICE_KEYBOARD)
    m_devicePreferredId = LI_DEVICE_KEYBOARD;
  else if (m_deviceType & LI_DEVICE_REMOTE)
    m_devicePreferredId = LI_DEVICE_REMOTE;
  else if (m_deviceType & LI_DEVICE_JOYSTICK)
    m_devicePreferredId = LI_DEVICE_JOYSTICK;
  else if (m_deviceType & LI_DEVICE_MOUSE)
    m_devicePreferredId = LI_DEVICE_MOUSE;
  else
    m_devicePreferredId = LI_DEVICE_NONE;

  //printf("type: %d\n", m_deviceType);
  //printf("caps: %d\n", m_deviceCaps);
  //printf("pref: %d\n", m_devicePreferredId);
}
Example #5
0
int main(int argc, char ** argv)
{
	int fd;
	unsigned long *evtype_b = malloc(sizeof(int));
	int yalv;

	if ((fd = open(argv[1], O_RDONLY)) < 0) {
		perror("evdev open");
		exit(1);
	}

	memset(evtype_b, 0, sizeof(evtype_b));

	if (ioctl(fd, EVIOCGBIT(0, EV_MAX), evtype_b) < 0) {
		perror("evdev ioctl");
	}

	printf("Supported event types:\n");

	for (yalv = 0; yalv < EV_MAX; yalv++) {
		if (test_bit(yalv, evtype_b)) {
			/* the bit is set in the event types list */
			printf(" Event type 0x%02x ", yalv);

			switch (yalv) {
				case EV_SYN :
					printf(" (Synch Events)\n");
					break;
				case EV_KEY :
					printf(" (Keys or Buttons)\n");
					break;
				case EV_REL :
					printf(" (Relative Axes)\n");
					break;
				case EV_ABS :
					printf(" (Absolute Axes)\n");
					break;
				case EV_MSC :
					printf(" (Miscellaneous)\n");
					break;
				case EV_LED :
					printf(" (LEDs)\n");
					break;
				case EV_SND :
					printf(" (Sounds)\n");
					break;
				case EV_REP :
					printf(" (Repeat)\n");
					break;
				case EV_FF :
				case EV_FF_STATUS:
					printf(" (Force Feedback)\n");
					break;
				case EV_PWR:
					printf(" (Power Management)\n");
					break;
				default:
					printf(" (Unknown: 0x%04hx)\n", yalv);
			}
		}
	}
	close(fd);
}
Example #6
0
static int
evdev_handle_device(struct evdev_device *device)
{
	struct input_absinfo absinfo;
	unsigned long ev_bits[NBITS(EV_MAX)];
	unsigned long abs_bits[NBITS(ABS_MAX)];
	unsigned long rel_bits[NBITS(REL_MAX)];
	unsigned long key_bits[NBITS(KEY_MAX)];
	int has_key, has_abs;
	unsigned int i;

	has_key = 0;
	has_abs = 0;
	device->caps = 0;

	ioctl(device->fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits);
	if (TEST_BIT(ev_bits, EV_ABS)) {
		has_abs = 1;

		ioctl(device->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)),
		      abs_bits);
		if (TEST_BIT(abs_bits, ABS_X)) {
			ioctl(device->fd, EVIOCGABS(ABS_X), &absinfo);
			device->abs.min_x = absinfo.minimum;
			device->abs.max_x = absinfo.maximum;
			device->caps |= EVDEV_MOTION_ABS;
		}
		if (TEST_BIT(abs_bits, ABS_Y)) {
			ioctl(device->fd, EVIOCGABS(ABS_Y), &absinfo);
			device->abs.min_y = absinfo.minimum;
			device->abs.max_y = absinfo.maximum;
			device->caps |= EVDEV_MOTION_ABS;
		}
		if (TEST_BIT(abs_bits, ABS_MT_SLOT)) {
			ioctl(device->fd, EVIOCGABS(ABS_MT_POSITION_X),
			      &absinfo);
			device->abs.min_x = absinfo.minimum;
			device->abs.max_x = absinfo.maximum;
			ioctl(device->fd, EVIOCGABS(ABS_MT_POSITION_Y),
			      &absinfo);
			device->abs.min_y = absinfo.minimum;
			device->abs.max_y = absinfo.maximum;
			device->is_mt = 1;
			device->mt.slot = 0;
			device->caps |= EVDEV_TOUCH;
		}
	}
	if (TEST_BIT(ev_bits, EV_REL)) {
		ioctl(device->fd, EVIOCGBIT(EV_REL, sizeof(rel_bits)),
		      rel_bits);
		if (TEST_BIT(rel_bits, REL_X) || TEST_BIT(rel_bits, REL_Y))
			device->caps |= EVDEV_MOTION_REL;
	}
	if (TEST_BIT(ev_bits, EV_KEY)) {
		has_key = 1;
		ioctl(device->fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)),
		      key_bits);
		if (TEST_BIT(key_bits, BTN_TOOL_FINGER) &&
		    !TEST_BIT(key_bits, BTN_TOOL_PEN) &&
		    has_abs)
			device->dispatch = evdev_touchpad_create(device);
		for (i = KEY_ESC; i < KEY_MAX; i++) {
			if (i >= BTN_MISC && i < KEY_OK)
				continue;
			if (TEST_BIT(key_bits, i)) {
				device->caps |= EVDEV_KEYBOARD;
				break;
			}
		}
		for (i = BTN_MISC; i < KEY_OK; i++) {
			if (TEST_BIT(key_bits, i)) {
				device->caps |= EVDEV_BUTTON;
				break;
			}
		}
	}
	if (TEST_BIT(ev_bits, EV_LED)) {
		device->caps |= EVDEV_KEYBOARD;
	}

	/* This rule tries to catch accelerometer devices and opt out. We may
	 * want to adjust the protocol later adding a proper event for dealing
	 * with accelerometers and implement here accordingly */
	if (has_abs && !has_key && !device->is_mt) {
		weston_log("input device %s, %s "
			   "ignored: unsupported device type\n",
			   device->devname, device->devnode);
		return 0;
	}

	return 1;
}
Example #7
0
static void
ConfigJoystick(SDL_Joystick * joystick, int fd)
{
    int i, t;
    unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
    unsigned long absbit[NBITS(ABS_MAX)] = { 0 };
    unsigned long relbit[NBITS(REL_MAX)] = { 0 };

    /* See if this device uses the new unified event API */
    if ((ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) >= 0) &&
        (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) >= 0) &&
        (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relbit)), relbit) >= 0)) {

        /* Get the number of buttons, axes, and other thingamajigs */
        for (i = BTN_JOYSTICK; i < KEY_MAX; ++i) {
            if (test_bit(i, keybit)) {
#ifdef DEBUG_INPUT_EVENTS
                printf("Joystick has button: 0x%x\n", i);
#endif
                joystick->hwdata->key_map[i] = joystick->nbuttons;
                ++joystick->nbuttons;
            }
        }
        for (i = 0; i < BTN_JOYSTICK; ++i) {
            if (test_bit(i, keybit)) {
#ifdef DEBUG_INPUT_EVENTS
                printf("Joystick has button: 0x%x\n", i);
#endif
                joystick->hwdata->key_map[i] = joystick->nbuttons;
                ++joystick->nbuttons;
            }
        }
        for (i = 0; i < ABS_MAX; ++i) {
            /* Skip hats */
            if (i == ABS_HAT0X) {
                i = ABS_HAT3Y;
                continue;
            }
            if (test_bit(i, absbit)) {
                struct input_absinfo absinfo;

                if (ioctl(fd, EVIOCGABS(i), &absinfo) < 0) {
                    continue;
                }
#ifdef DEBUG_INPUT_EVENTS
                printf("Joystick has absolute axis: 0x%.2x\n", i);
                printf("Values = { %d, %d, %d, %d, %d }\n",
                       absinfo.value, absinfo.minimum, absinfo.maximum,
                       absinfo.fuzz, absinfo.flat);
#endif /* DEBUG_INPUT_EVENTS */
                joystick->hwdata->abs_map[i] = joystick->naxes;
                if (absinfo.minimum == absinfo.maximum) {
                    joystick->hwdata->abs_correct[i].used = 0;
                } else {
                    joystick->hwdata->abs_correct[i].used = 1;
                    joystick->hwdata->abs_correct[i].coef[0] =
                        (absinfo.maximum + absinfo.minimum) - 2 * absinfo.flat;
                    joystick->hwdata->abs_correct[i].coef[1] =
                        (absinfo.maximum + absinfo.minimum) + 2 * absinfo.flat;
                    t = ((absinfo.maximum - absinfo.minimum) - 4 * absinfo.flat);
                    if (t != 0) {
                        joystick->hwdata->abs_correct[i].coef[2] =
                            (1 << 28) / t;
                    } else {
                        joystick->hwdata->abs_correct[i].coef[2] = 0;
                    }
                }
                ++joystick->naxes;
            }
        }
        for (i = ABS_HAT0X; i <= ABS_HAT3Y; i += 2) {
            if (test_bit(i, absbit) || test_bit(i + 1, absbit)) {
                struct input_absinfo absinfo;

                if (ioctl(fd, EVIOCGABS(i), &absinfo) < 0) {
                    continue;
                }
#ifdef DEBUG_INPUT_EVENTS
                printf("Joystick has hat %d\n", (i - ABS_HAT0X) / 2);
                printf("Values = { %d, %d, %d, %d, %d }\n",
                       absinfo.value, absinfo.minimum, absinfo.maximum,
                       absinfo.fuzz, absinfo.flat);
#endif /* DEBUG_INPUT_EVENTS */
                ++joystick->nhats;
            }
        }
        if (test_bit(REL_X, relbit) || test_bit(REL_Y, relbit)) {
            ++joystick->nballs;
        }

        /* Allocate data to keep track of these thingamajigs */
        if (joystick->nhats > 0) {
            if (allocate_hatdata(joystick) < 0) {
                joystick->nhats = 0;
            }
        }
        if (joystick->nballs > 0) {
            if (allocate_balldata(joystick) < 0) {
                joystick->nballs = 0;
            }
        }
    }
}
Example #8
0
void joystick_linux::open_joystick(const char *p_path) {

    int joy_num = get_free_joy_slot();
    int fd = open(p_path, O_RDONLY | O_NONBLOCK);
    if (fd != -1 && joy_num != -1) {

        unsigned long evbit[NBITS(EV_MAX)] = { 0 };
        unsigned long keybit[NBITS(KEY_MAX)] = { 0 };
        unsigned long absbit[NBITS(ABS_MAX)] = { 0 };

        if ((ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit) < 0) ||
                (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) ||
                (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0)) {
            close(fd);
            return;
        }

        //check if the device supports basic gamepad events, prevents certain keyboards from
        //being detected as joysticks
        if (!(test_bit(EV_KEY, evbit) && test_bit(EV_ABS, evbit) &&
                (test_bit(ABS_X, absbit) || test_bit(ABS_Y, absbit) || test_bit(ABS_HAT0X, absbit) ||
                 test_bit(ABS_GAS, absbit) || test_bit(ABS_RUDDER, absbit)) &&
                (test_bit(BTN_A, keybit) || test_bit(BTN_THUMBL, keybit) ||
                 test_bit(BTN_TRIGGER, keybit) || test_bit(BTN_1, keybit)))) {
            close(fd);
            return;
        }

        char uid[128];
        char namebuf[128];
        String name = "";
        input_id inpid;
        if (ioctl(fd, EVIOCGNAME(sizeof(namebuf)), namebuf) >= 0) {
            name = namebuf;
        }

        if (ioctl(fd, EVIOCGID, &inpid) < 0) {
            close(fd);
            return;
        }

        joysticks[joy_num].reset();

        Joystick &joy = joysticks[joy_num];
        joy.fd = fd;
        joy.devpath = String(p_path);
        setup_joystick_properties(joy_num);
        sprintf(uid, "%04x%04x", __bswap_16(inpid.bustype), 0);
        if (inpid.vendor && inpid.product && inpid.version) {

            uint16_t vendor = __bswap_16(inpid.vendor);
            uint16_t product = __bswap_16(inpid.product);
            uint16_t version = __bswap_16(inpid.version);

            sprintf(uid + String(uid).length(), "%04x%04x%04x%04x%04x%04x", vendor,0,product,0,version,0);
            input->joy_connection_changed(joy_num, true, name, uid);
        }
        else {
            String uidname = uid;
            int uidlen = MIN(name.length(), 11);
            for (int i=0; i<uidlen; i++) {

                uidname = uidname + _hex_str(name[i]);
            }
            uidname += "00";
            input->joy_connection_changed(joy_num, true, name, uidname);
        }
    }
}
int pa__init(pa_module*m) {

    pa_modargs *ma = NULL;
    struct userdata *u;
    int version;
    struct input_id input_id;
    char name[256];
    uint8_t evtype_bitmask[EV_MAX/8 + 1];
    pa_volume_t volume_limit = PA_VOLUME_NORM*3/2;
    pa_volume_t volume_step = PA_VOLUME_NORM/20;

    pa_assert(m);

    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
        pa_log("Failed to parse module arguments");
        goto fail;
    }

    if (pa_modargs_get_value_u32(ma, "volume_limit", &volume_limit) < 0) {
        pa_log("Failed to parse volume limit");
        goto fail;
    }

    if (pa_modargs_get_value_u32(ma, "volume_step", &volume_step) < 0) {
        pa_log("Failed to parse volume step");
        goto fail;
    }

    m->userdata = u = pa_xnew(struct userdata, 1);
    u->module = m;
    u->io = NULL;
    u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));
    u->fd = -1;
    u->fd_type = 0;
    u->volume_limit = PA_CLAMP_VOLUME(volume_limit);
    u->volume_step = PA_CLAMP_VOLUME(volume_step);

    if ((u->fd = pa_open_cloexec(pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), O_RDONLY, 0)) < 0) {
        pa_log("Failed to open evdev device: %s", pa_cstrerror(errno));
        goto fail;
    }

    if (ioctl(u->fd, EVIOCGVERSION, &version) < 0) {
        pa_log("EVIOCGVERSION failed: %s", pa_cstrerror(errno));
        goto fail;
    }

    pa_log_info("evdev driver version %i.%i.%i", version >> 16, (version >> 8) & 0xff, version & 0xff);

    if (ioctl(u->fd, EVIOCGID, &input_id)) {
        pa_log("EVIOCGID failed: %s", pa_cstrerror(errno));
        goto fail;
    }

    pa_log_info("evdev vendor 0x%04hx product 0x%04hx version 0x%04hx bustype %u",
                input_id.vendor, input_id.product, input_id.version, input_id.bustype);

    memset(name, 0, sizeof(name));
    if (ioctl(u->fd, EVIOCGNAME(sizeof(name)), name) < 0) {
        pa_log("EVIOCGNAME failed: %s", pa_cstrerror(errno));
        goto fail;
    }

    pa_log_info("evdev device name: %s", name);

    memset(evtype_bitmask, 0, sizeof(evtype_bitmask));
    if (ioctl(u->fd, EVIOCGBIT(0, EV_MAX), evtype_bitmask) < 0) {
        pa_log("EVIOCGBIT failed: %s", pa_cstrerror(errno));
        goto fail;
    }

    if (!test_bit(EV_KEY, evtype_bitmask)) {
        pa_log("Device has no keys.");
        goto fail;
    }

    u->io = m->core->mainloop->io_new(m->core->mainloop, u->fd, PA_IO_EVENT_INPUT|PA_IO_EVENT_HANGUP, io_callback, u);

    pa_modargs_free(ma);

    return 0;

fail:

    if (ma)
        pa_modargs_free(ma);

    pa__done(m);
    return -1;
}
Example #10
0
void evtest_test(const char* filename)
{
    int fd, rd, i, j, k;
    struct input_event ev[64];
    int version;
    unsigned short id[4];
    unsigned long bit[EV_MAX][NBITS(KEY_MAX)];
    char name[256] = "Unknown";
    int abs[5];

    if ((fd = open(filename, O_RDONLY)) < 0) {
        perror("evtest");
        exit(1);
    }

    if (ioctl(fd, EVIOCGVERSION, &version)) {
        perror("evtest: can't get version");
        exit(1);
    }

    printf("Input driver version is %d.%d.%d\n",
           version >> 16, (version >> 8) & 0xff, version & 0xff);

    ioctl(fd, EVIOCGID, id);
    printf("Input device ID: bus 0x%x vendor 0x%x product 0x%x version 0x%x\n",
           id[ID_BUS], id[ID_VENDOR], id[ID_PRODUCT], id[ID_VERSION]);

    ioctl(fd, EVIOCGNAME(sizeof(name)), name);
    printf("Input device name: \"%s\"\n", name);

    memset(bit, 0, sizeof(bit));
    ioctl(fd, EVIOCGBIT(0, EV_MAX), bit[0]);
    printf("Supported events:\n");

    for (i = 0; i < EV_MAX; i++)
        if (test_bit(i, bit[0])) {
            printf("  Event type %d (%s)\n", i, events[i] ? events[i] : "?");
            ioctl(fd, EVIOCGBIT(i, KEY_MAX), bit[i]);
            for (j = 0; j < KEY_MAX; j++)
                if (test_bit(j, bit[i])) {
                    printf("    Event code %d (%s)\n", j, names[i] ? (names[i][j] ? names[i][j] : "?") : "?");
                    if (i == EV_ABS) {
                        ioctl(fd, EVIOCGABS(j), abs);
                        for (k = 0; k < 5; k++)
                            if ((k < 3) || abs[k])
                                printf("      %s %6d\n", absval[k], abs[k]);
                    }
                }
        }


    printf("Testing ... (interrupt to exit)\n");

    while (1) {
        rd = read(fd, ev, sizeof(struct input_event) * 64);

        if (rd < (int) sizeof(struct input_event)) {
            printf("yyy\n");
            perror("\nevtest: error reading");
            exit (1);
        }

        for (i = 0; i < rd / sizeof(struct input_event); i++)
            printf("Event: time %ld.%06ld, type %d (%s), code %d (%s), value %d\n",
                   ev[i].time.tv_sec, ev[i].time.tv_usec, ev[i].type,
                   events[ev[i].type] ? events[ev[i].type] : "?",
                   ev[i].code,
                   names[ev[i].type] ? (names[ev[i].type][ev[i].code] ? names[ev[i].type][ev[i].code] : "?") : "?",
                   ev[i].value);

    }
}
Example #11
0
bool QDeviceDiscoveryStatic::checkDeviceType(const QString &device)
{
    int fd = QT_OPEN(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
    if (Q_UNLIKELY(fd == -1)) {
        qWarning() << "Device discovery cannot open device" << device;
        return false;
    }

    qCDebug(lcDD) << "doing static device discovery for " << device;

    if ((m_types & Device_DRM) && device.contains(QLatin1String(QT_DRM_DEVICE_PREFIX))) {
        QT_CLOSE(fd);
        return true;
    }

    long bitsAbs[LONG_FIELD_SIZE(ABS_CNT)];
    long bitsKey[LONG_FIELD_SIZE(KEY_CNT)];
    long bitsRel[LONG_FIELD_SIZE(REL_CNT)];
    memset(bitsAbs, 0, sizeof(bitsAbs));
    memset(bitsKey, 0, sizeof(bitsKey));
    memset(bitsRel, 0, sizeof(bitsRel));

    ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(bitsAbs)), bitsAbs);
    ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(bitsKey)), bitsKey);
    ioctl(fd, EVIOCGBIT(EV_REL, sizeof(bitsRel)), bitsRel);

    QT_CLOSE(fd);

    if ((m_types & Device_Keyboard)) {
        if (testBit(KEY_Q, bitsKey)) {
            qCDebug(lcDD) << "Found keyboard at" << device;
            return true;
        }
    }

    if ((m_types & Device_Mouse)) {
        if (testBit(REL_X, bitsRel) && testBit(REL_Y, bitsRel) && testBit(BTN_MOUSE, bitsKey)) {
            qCDebug(lcDD) << "Found mouse at" << device;
            return true;
        }
    }

    if ((m_types & (Device_Touchpad | Device_Touchscreen))) {
        if (testBit(ABS_X, bitsAbs) && testBit(ABS_Y, bitsAbs)) {
            if ((m_types & Device_Touchpad) && testBit(BTN_TOOL_FINGER, bitsKey)) {
                qCDebug(lcDD) << "Found touchpad at" << device;
                return true;
            } else if ((m_types & Device_Touchscreen) && testBit(BTN_TOUCH, bitsKey)) {
                qCDebug(lcDD) << "Found touchscreen at" << device;
                return true;
            } else if ((m_types & Device_Tablet) && (testBit(BTN_STYLUS, bitsKey) || testBit(BTN_TOOL_PEN, bitsKey))) {
                qCDebug(lcDD) << "Found tablet at" << device;
                return true;
            }
        } else if (testBit(ABS_MT_POSITION_X, bitsAbs) &&
                   testBit(ABS_MT_POSITION_Y, bitsAbs)) {
            qCDebug(lcDD) << "Found new-style touchscreen at" << device;
            return true;
        }
    }

    if ((m_types & Device_Joystick)) {
        if (testBit(BTN_A, bitsKey) || testBit(BTN_TRIGGER, bitsKey) || testBit(ABS_RX, bitsAbs)) {
            qCDebug(lcDD) << "Found joystick/gamepad at" << device;
            return true;
        }
    }

    return false;
}
Example #12
0
void evtest_info(const char* filename, int verbose)
{
    int fd;
    unsigned short id[4];
    char name[256] = "Unknown";

    if ((fd = open(filename, O_RDONLY)) < 0)
    {
        perror(filename);
    }
    else
    {
        int i, j, k;

        int version;
        if (ioctl(fd, EVIOCGVERSION, &version)) {
            perror("evtest: can't get version");
            exit(1);
        }


        unsigned long bit[EV_MAX][NBITS(KEY_MAX)];
        ioctl(fd, EVIOCGID, id);
        ioctl(fd, EVIOCGNAME(sizeof(name)), name);
        memset(bit, 0, sizeof(bit));
        ioctl(fd, EVIOCGBIT(0, EV_MAX), bit[0]);

        if (!verbose)
        {
            printf("%s\t\"%s\"\n", filename, name);
        }
        else
        {
            printf("Input device file: %s\n", filename);
            printf("Input device name: \"%s\"\n", name);

            printf("Input driver version is %d.%d.%d\n",
                   version >> 16, (version >> 8) & 0xff, version & 0xff);

            printf("Input device ID: bus 0x%x vendor 0x%x product 0x%x version 0x%x\n",
                   id[ID_BUS], id[ID_VENDOR], id[ID_PRODUCT], id[ID_VERSION]);

            printf("Supported events:\n");

            for (i = 0; i < EV_MAX; i++)
                if (test_bit(i, bit[0])) {
                    printf("  Event type %d (%s)\n", i, events[i] ? events[i] : "?");
                    ioctl(fd, EVIOCGBIT(i, KEY_MAX), bit[i]);
                    for (j = 0; j < KEY_MAX; j++)
                        if (test_bit(j, bit[i])) {
                            printf("    Event code %d (%s)\n", j, names[i] ? (names[i][j] ? names[i][j] : "?") : "?");
                            if (i == EV_ABS) {
                                int abs[5];
                                ioctl(fd, EVIOCGABS(j), abs);
                                for (k = 0; k < 5; k++)
                                    if ((k < 3) || abs[k])
                                        printf("      %s %6d\n", absval[k], abs[k]);
                            }
                        }
                }

            putchar('\n');
        }
    }
}
Example #13
0
int PIGU_detect_device(const char *device, PIGU_device_info_t *info)
{
   uint32_t types[EV_MAX];
   uint32_t events[(KEY_MAX-1)/32+1];
   
   int fd = open(device, O_RDONLY | O_NONBLOCK);

   if(fd<0)
      return -1;

   memset(info, 0, sizeof(PIGU_device_info_t));
   info->fd = fd;
   
   // get device name
   ioctl(fd, EVIOCGNAME(sizeof(info->name)), info->name);

   // query supported event types
   memset(types, 0, sizeof(types));
   ioctl(fd, EVIOCGBIT(0, EV_MAX), types);

   int key_count = 0;
   int mouse_button_count = 0;
   int joystick_button_count = 0;
   int gamepad_button_count = 0;
   PIGU_axis_data_t axes;
   PIGU_init_axis_data(&axes);
   PIGU_button_data_t buttons;
   PIGU_init_button_data(&buttons);

   if(PIGU_get_bit(types, EV_KEY))
   {
      // count events
      memset(events, 0, sizeof(events));
      ioctl(fd, EVIOCGBIT(EV_KEY, KEY_MAX), events);
      int j = 0;
      for(;j<BTN_MISC;++j)
	 if(PIGU_get_bit(events, j))
	    key_count++;

      j = BTN_MOUSE; // skip misc buttons
      
      for(;j<BTN_JOYSTICK;++j)
	 if(PIGU_get_bit(events, j))
	 {
	    mouse_button_count++;
	    if(j-BTN_MOUSE>=16)
	       continue;
	    buttons.map[buttons.count] = j-BTN_MOUSE;
	    buttons.count++;
	 }

      for(;j<BTN_GAMEPAD;++j)
	 if(PIGU_get_bit(events, j))
	 {
	    joystick_button_count++;
	    if(j-BTN_JOYSTICK>=16)
	       continue;
	    buttons.map[buttons.count] = j-BTN_JOYSTICK;
	    buttons.count++;
	 }

      for(;j<BTN_DIGI;++j)
	 if(PIGU_get_bit(events, j))
	 {
	    gamepad_button_count++;
	    if(j-BTN_GAMEPAD>=16)
	       continue;
	    buttons.map[buttons.count] = j-BTN_GAMEPAD;
	    buttons.count++;
	 }
   }


   if(PIGU_get_bit(types, EV_ABS))
   {
      struct input_absinfo abs;
      memset(events, 0, sizeof(events));
      ioctl(fd, EVIOCGBIT(EV_ABS, KEY_MAX), events);
      
      int j = 0;
      for(;j<32;++j)
	 if(PIGU_get_bit(events, j))
	 {
	    axes.map[axes.count] = j;
	    ioctl(fd, EVIOCGABS(j), &abs);

	    axes.position[j] = abs.value;
	    axes.min[j] = abs.minimum;
	    axes.max[j] = abs.maximum;
	    axes.count++;
	 }
   }

   // we simply assume that a device that reports gamepad events
   // is actually a gamepad... a device that reports different types
   // of events will simply detected according to the order of this
   // if chain here.
   info->type = PIGU_UNKNOWN;
   if(gamepad_button_count > 0)
   {
      info->type = PIGU_GAMEPAD;
      info->controller.buttons = buttons;
      info->controller.axes = axes;
   }
   else if(joystick_button_count > 0)
   {
      info->type = PIGU_JOYSTICK;
      info->controller.buttons = buttons;
      info->controller.axes = axes;
   }
   else  if(mouse_button_count > 0)
   {
      info->type = PIGU_MOUSE;
      info->mouse.buttons = buttons;
   }
   else if(key_count > 0)
   {
      info->keyboard.keys = key_count;
      info->type = PIGU_KEYBOARD;
   }
   else
   {
      // no idea what it is so we ignore it
      // touch screen devices probably end up here atm
      close(info->fd);
   }

   return 0;
}
static int builtin_keyboard(struct udev_device *dev, int argc, char *argv[], bool test) {
        struct udev_list_entry *entry;
        unsigned release[1024];
        unsigned release_count = 0;
        _cleanup_close_ int fd = -1;
        const char *node;
        int has_abs = -1;

        node = udev_device_get_devnode(dev);
        if (!node) {
                log_error("No device node for \"%s\"", udev_device_get_syspath(dev));
                return EXIT_FAILURE;
        }

        udev_list_entry_foreach(entry, udev_device_get_properties_list_entry(dev)) {
                const char *key;
                char *endptr;

                key = udev_list_entry_get_name(entry);
                if (startswith(key, "KEYBOARD_KEY_")) {
                        const char *keycode;
                        unsigned scancode;

                        /* KEYBOARD_KEY_<hex scan code>=<key identifier string> */
                        scancode = strtoul(key + 13, &endptr, 16);
                        if (endptr[0] != '\0') {
                                log_warning("Unable to parse scan code from \"%s\"", key);
                                continue;
                        }

                        keycode = udev_list_entry_get_value(entry);

                        /* a leading '!' needs a force-release entry */
                        if (keycode[0] == '!') {
                                keycode++;

                                release[release_count] = scancode;
                                if (release_count <  ELEMENTSOF(release)-1)
                                        release_count++;

                                if (keycode[0] == '\0')
                                        continue;
                        }

                        if (fd == -1) {
                                fd = open_device(node);
                                if (fd < 0)
                                        return EXIT_FAILURE;
                        }

                        map_keycode(fd, node, scancode, keycode);
                } else if (startswith(key, "EVDEV_ABS_")) {
                        unsigned evcode;

                        /* EVDEV_ABS_<EV_ABS code>=<min>:<max>:<res>:<fuzz>:<flat> */
                        evcode = strtoul(key + 10, &endptr, 16);
                        if (endptr[0] != '\0') {
                                log_warning("Unable to parse EV_ABS code from \"%s\"", key);
                                continue;
                        }

                        if (fd == -1) {
                                fd = open_device(node);
                                if (fd < 0)
                                        return EXIT_FAILURE;
                        }

                        if (has_abs == -1) {
                                unsigned long bits;
                                int rc;

                                rc = ioctl(fd, EVIOCGBIT(0, sizeof(bits)), &bits);
                                if (rc < 0) {
                                        log_error_errno(errno, "Unable to EVIOCGBIT device \"%s\"", node);
                                        return EXIT_FAILURE;
                                }

                                has_abs = !!(bits & (1 << EV_ABS));
                                if (!has_abs)
                                        log_warning("EVDEV_ABS override set but no EV_ABS present on device \"%s\"", node);
                        }

                        if (!has_abs)
                                continue;

                        override_abs(fd, node, evcode, udev_list_entry_get_value(entry));
                } else if (streq(key, "POINTINGSTICK_SENSITIVITY"))
                        set_trackpoint_sensitivity(dev, udev_list_entry_get_value(entry));
        }

        /* install list of force-release codes */
        if (release_count > 0)
                install_force_release(dev, release, release_count);

        return EXIT_SUCCESS;
}
Example #15
0
int open_dev_usb(struct device *dev)
{
	int i;
	struct input_absinfo absinfo;
	unsigned char evtype_mask[(EV_MAX + 7) / 8];

	if((dev->fd = open(dev->path, O_RDWR)) == -1) {
		if((dev->fd = open(dev->path, O_RDONLY)) == -1) {
			perror("failed to open device");
			return -1;
		}
		fprintf(stderr, "opened device read-only, LEDs won't work\n");
	}

	if(ioctl(dev->fd, EVIOCGNAME(sizeof dev->name), dev->name) == -1) {
		perror("EVIOCGNAME ioctl failed");
		strcpy(dev->name, "unknown");
	}
	printf("device name: %s\n", dev->name);

	/* get number of axes */
	dev->num_axes = 6;	/* default to regular 6dof controller axis count */
	if(ioctl(dev->fd, EVIOCGBIT(EV_ABS, sizeof evtype_mask), evtype_mask) == 0) {
		dev->num_axes = 0;
		for(i=0; i<ABS_CNT; i++) {
			int idx = i / 8;
			int bit = i % 8;

			if(evtype_mask[idx] & (1 << bit)) {
				dev->num_axes++;
			} else {
				break;
			}
		}
	}
	if(verbose) {
		printf("  Number of axes: %d\n", dev->num_axes);
	}

	dev->minval = malloc(dev->num_axes * sizeof *dev->minval);
	dev->maxval = malloc(dev->num_axes * sizeof *dev->maxval);
	dev->fuzz = malloc(dev->num_axes * sizeof *dev->fuzz);

	if(!dev->minval || !dev->maxval || !dev->fuzz) {
		perror("failed to allocate memory");
		return -1;
	}

	/* if the device is an absolute device, find the minimum and maximum axis values */
	for(i=0; i<dev->num_axes; i++) {
		dev->minval[i] = DEF_MINVAL;
		dev->maxval[i] = DEF_MAXVAL;
		dev->fuzz[i] = 0;

		if(ioctl(dev->fd, EVIOCGABS(i), &absinfo) == 0) {
			dev->minval[i] = absinfo.minimum;
			dev->maxval[i] = absinfo.maximum;
			dev->fuzz[i] = absinfo.fuzz;

			if(verbose) {
				printf("  Axis %d value range: %d - %d (fuzz: %d)\n", i, dev->minval[i], dev->maxval[i], dev->fuzz[i]);
			}
		}
	}

	/*if(ioctl(dev->fd, EVIOCGBIT(0, sizeof(evtype_mask)), evtype_mask) == -1) {
		perror("EVIOCGBIT ioctl failed\n");
		close(dev->fd);
		return -1;
	}*/

	if(cfg.grab_device) {
		int grab = 1;
		/* try to grab the device */
		if(ioctl(dev->fd, EVIOCGRAB, &grab) == -1) {
			perror("failed to grab the device");
		}
	}

	/* set non-blocking */
	fcntl(dev->fd, F_SETFL, fcntl(dev->fd, F_GETFL) | O_NONBLOCK);

	if(cfg.led) {
		set_led_evdev(dev, 1);
	}

	/* fill the device function pointers */
	dev->close = close_evdev;
	dev->read = read_evdev;
	dev->set_led = set_led_evdev;

	return 0;
}
Example #16
0
    I_NOSTATE(USBDEVFS_RESETEP, success),
    I_NOSTATE(USBDEVFS_GETDRIVER, enodata),
    I_NOSTATE(USBDEVFS_IOCTL, enotty),

    I_NOSTATE(EVIOCGRAB, success),

    /* evdev */
    I_SIMPLE_STRUCT_IN(EVIOCGVERSION, 0, ioctl_insertion_parent_stateless),
    I_SIMPLE_STRUCT_IN(EVIOCGID, 0, ioctl_insertion_parent_stateless),
    I_SIMPLE_STRUCT_IN(EVIOCGREP, 0, ioctl_insertion_parent_stateless),
    I_SIMPLE_STRUCT_IN(EVIOCGKEYCODE, 0, ioctl_insertion_parent_stateless),
    I_SIMPLE_STRUCT_IN(EVIOCGKEYCODE_V2, 0, ioctl_insertion_parent_stateless),
    I_SIMPLE_STRUCT_IN(EVIOCGEFFECTS, 0, ioctl_insertion_parent_stateless),
    I_NAMED_SIMPLE_STRUCT_IN(EVIOCGABS(0), "EVIOCGABS", ABS_MAX, ioctl_insertion_parent_stateless),
    /* we define these with len==32, but they apply to any len */
    I_NAMED_SIMPLE_STRUCT_IN(EVIOCGBIT(0, 32), "EVIOCGBIT", EV_MAX, ioctl_insertion_parent_stateless),
    I_NAMED_SIMPLE_STRUCT_IN(EVIOCGNAME(32), "EVIOCGNAME", 0, ioctl_insertion_parent_stateless),
    I_NAMED_SIMPLE_STRUCT_IN(EVIOCGPHYS(32), "EVIOCGPHYS", 0, ioctl_insertion_parent_stateless),
    I_NAMED_SIMPLE_STRUCT_IN(EVIOCGUNIQ(32), "EVIOCGUNIQ", 0, ioctl_insertion_parent_stateless),
    I_NAMED_SIMPLE_STRUCT_IN(EVIOCGPROP(32), "EVIOCGPROP", 0, ioctl_insertion_parent_stateless),
    I_NAMED_SIMPLE_STRUCT_IN(EVIOCGKEY(32), "EVIOCGKEY", 0, ioctl_insertion_parent_stateless),
    I_NAMED_SIMPLE_STRUCT_IN(EVIOCGLED(32), "EVIOCGLED", 0, ioctl_insertion_parent_stateless),
    I_NAMED_SIMPLE_STRUCT_IN(EVIOCGSND(32), "EVIOCGSND", 0, ioctl_insertion_parent_stateless),
    I_NAMED_SIMPLE_STRUCT_IN(EVIOCGSW(32), "EVIOCGSW", 0, ioctl_insertion_parent_stateless),

    /* this was introduced not too long ago */
#ifdef EVIOCGMTSLOTS
    I_NAMED_SIMPLE_STRUCT_IN(EVIOCGMTSLOTS(32), "EVIOCGMTSLOTS", 0, ioctl_insertion_parent_stateless),
#endif

    /* terminator */
Example #17
0
int main (int argc, char **argv)
{
	int fd, rd, i, j, k;
	struct input_event ev[64];
	int version;
	unsigned short id[4];
	unsigned long bit[EV_MAX][NBITS(KEY_MAX)];
	char name[256] = "Unknown";
	int abs[5];

	if (argc < 2) {
		printf("Usage: evtest /dev/input/eventX\n");
		printf("Where X = input device number\n");
		return 1;
	}

	if ((fd = open(argv[argc - 1], O_RDONLY)) < 0) {
		perror("evtest");
		return 1;
	}

	if (ioctl(fd, EVIOCGVERSION, &version)) {
		perror("evtest: can't get version");
		return 1;
	}

	printf("Input driver version is %d.%d.%d\n",
		version >> 16, (version >> 8) & 0xff, version & 0xff);

	ioctl(fd, EVIOCGID, id);
	printf("Input device ID: bus 0x%x vendor 0x%x product 0x%x version 0x%x\n",
		id[ID_BUS], id[ID_VENDOR], id[ID_PRODUCT], id[ID_VERSION]);

	ioctl(fd, EVIOCGNAME(sizeof(name)), name);
	printf("Input device name: \"%s\"\n", name);

	memset(bit, 0, sizeof(bit));
	ioctl(fd, EVIOCGBIT(0, EV_MAX), bit[0]);
	printf("Supported events:\n");

	for (i = 0; i < EV_MAX; i++)
		if (test_bit(i, bit[0])) {
			printf("  Event type %d (%s)\n", i, events[i] ? events[i] : "?");
			if (!i) continue;
			ioctl(fd, EVIOCGBIT(i, KEY_MAX), bit[i]);
			for (j = 0; j < KEY_MAX; j++) 
				if (test_bit(j, bit[i])) {
					printf("    Event code %d (%s)\n", j, names[i] ? (names[i][j] ? names[i][j] : "?") : "?");
					if (i == EV_ABS) {
						ioctl(fd, EVIOCGABS(j), abs);
						for (k = 0; k < 5; k++)
							if ((k < 3) || abs[k])
								printf("      %s %6d\n", absval[k], abs[k]);
					}
				}
		}
		

	printf("Testing ... (interrupt to exit)\n");

	while (1) {
		rd = read(fd, ev, sizeof(struct input_event) * 64);

		if (rd < (int) sizeof(struct input_event)) {
			printf("yyy\n");
			perror("\nevtest: error reading");
			return 1;
		}

		for (i = 0; i < rd / sizeof(struct input_event); i++)

			if (ev[i].type == EV_SYN) {
				printf("Event: time %ld.%06ld, -------------- %s ------------\n",
					ev[i].time.tv_sec, ev[i].time.tv_usec, ev[i].code ? "Config Sync" : "Report Sync" );
			} else if (ev[i].type == EV_MSC && (ev[i].code == MSC_RAW || ev[i].code == MSC_SCAN)) {
				printf("Event: time %ld.%06ld, type %d (%s), code %d (%s), value %02x\n",
					ev[i].time.tv_sec, ev[i].time.tv_usec, ev[i].type,
					events[ev[i].type] ? events[ev[i].type] : "?",
					ev[i].code,
					names[ev[i].type] ? (names[ev[i].type][ev[i].code] ? names[ev[i].type][ev[i].code] : "?") : "?",
					ev[i].value);
			} else {
				printf("Event: time %ld.%06ld, type %d (%s), code %d (%s), value %d\n",
					ev[i].time.tv_sec, ev[i].time.tv_usec, ev[i].type,
					events[ev[i].type] ? events[ev[i].type] : "?",
					ev[i].code,
					names[ev[i].type] ? (names[ev[i].type][ev[i].code] ? names[ev[i].type][ev[i].code] : "?") : "?",
					ev[i].value);
			}	

	}
}
Example #18
0
void Gamepad_detectDevices() {
	struct input_id id;
	DIR * dev_input;
	struct dirent * entity;
	unsigned int charsConsumed;
	int num;
	int fd;
	int evCapBits[(EV_CNT - 1) / sizeof(int) * 8 + 1];
	int evKeyBits[(KEY_CNT - 1) / sizeof(int) * 8 + 1];
	int evAbsBits[(ABS_CNT - 1) / sizeof(int) * 8 + 1];
	char fileName[PATH_MAX];
	bool duplicate;
	unsigned int gamepadIndex;
	struct stat statBuf;
	struct Gamepad_device * deviceRecord;
	struct Gamepad_devicePrivate * deviceRecordPrivate;
	char name[128];
	char * description;
	int bit;
	time_t currentTime;
	static time_t lastInputStatTime;
	
	if (!inited) {
		return;
	}
	
	pthread_mutex_lock(&devicesMutex);
	
	dev_input = opendir("/dev/input");
	currentTime = time(NULL);
	if (dev_input != NULL) {
		while ((entity = readdir(dev_input)) != NULL) {
			charsConsumed = 0;
			if (sscanf(entity->d_name, "event%d%n", &num, &charsConsumed) && charsConsumed == strlen(entity->d_name)) {
				snprintf(fileName, PATH_MAX, "/dev/input/%s", entity->d_name);
				if (stat(fileName, &statBuf) || statBuf.st_mtime < lastInputStatTime) {
					continue;
				}
				
				duplicate = false;
				for (gamepadIndex = 0; gamepadIndex < numDevices; gamepadIndex++) {
					if (!strcmp(((struct Gamepad_devicePrivate *) devices[gamepadIndex]->privateData)->path, fileName)) {
						duplicate = true;
						break;
					}
				}
				if (duplicate) {
					continue;
				}
				
				fd = open(fileName, O_RDONLY, 0);
				memset(evCapBits, 0, sizeof(evCapBits));
				memset(evKeyBits, 0, sizeof(evKeyBits));
				memset(evAbsBits, 0, sizeof(evAbsBits));
				if (ioctl(fd, EVIOCGBIT(0, sizeof(evCapBits)), evCapBits) < 0 ||
				    ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(evKeyBits)), evKeyBits) < 0 ||
				    ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(evAbsBits)), evAbsBits) < 0) {
					close(fd);
					continue;
				}
				if (!test_bit(EV_KEY, evCapBits) || !test_bit(EV_ABS, evCapBits) ||
				    !test_bit(ABS_X, evAbsBits) || !test_bit(ABS_Y, evAbsBits) ||
				    (!test_bit(BTN_TRIGGER, evKeyBits) && !test_bit(BTN_A, evKeyBits) && !test_bit(BTN_1, evKeyBits))) {
					close(fd);
					continue;
				}
				
				deviceRecord = (Gamepad_device *)malloc(sizeof(struct Gamepad_device));
				deviceRecord->deviceID = nextDeviceID++;
				devices = (Gamepad_device **)realloc(devices, sizeof(struct Gamepad_device *) * (numDevices + 1));
				devices[numDevices++] = deviceRecord;
				
				deviceRecordPrivate = (Gamepad_devicePrivate *)malloc(sizeof(struct Gamepad_devicePrivate));
				deviceRecordPrivate->fd = fd;
				deviceRecordPrivate->path = (char *)malloc(strlen(fileName) + 1);
				strcpy(deviceRecordPrivate->path, fileName);
				memset(deviceRecordPrivate->buttonMap, 0xFF, sizeof(deviceRecordPrivate->buttonMap));
				memset(deviceRecordPrivate->axisMap, 0xFF, sizeof(deviceRecordPrivate->axisMap));
				deviceRecord->privateData = deviceRecordPrivate;
				
				if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) > 0) {
					description = (char *)malloc(strlen(name) + 1);
					strcpy(description, name);
				} else {
					description = (char *)malloc(strlen(fileName) + 1);
					strcpy(description, fileName);
				}
				deviceRecord->description = description;
				
				if (!ioctl(fd, EVIOCGID, &id)) {
					deviceRecord->vendorID = id.vendor;
					deviceRecord->productID = id.product;
				} else {
					deviceRecord->vendorID = deviceRecord->productID = 0;
				}
				
				memset(evKeyBits, 0, sizeof(evKeyBits));
				memset(evAbsBits, 0, sizeof(evAbsBits));
				ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(evKeyBits)), evKeyBits);
				ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(evAbsBits)), evAbsBits);
				
				deviceRecord->numAxes = 0;
				for (bit = 0; bit < ABS_CNT; bit++) {
					if (test_bit(bit, evAbsBits)) {
						if (ioctl(fd, EVIOCGABS(bit), &deviceRecordPrivate->axisInfo[bit]) < 0 ||
							  deviceRecordPrivate->axisInfo[bit].minimum == deviceRecordPrivate->axisInfo[bit].maximum) {
							continue;
						}
						deviceRecordPrivate->axisMap[bit] = deviceRecord->numAxes;
						deviceRecord->numAxes++;
					}
				}
				deviceRecord->numButtons = 0;
				for (bit = BTN_MISC; bit < KEY_CNT; bit++) {
					if (test_bit(bit, evKeyBits)) {
						deviceRecordPrivate->buttonMap[bit - BTN_MISC] = deviceRecord->numButtons;
						deviceRecord->numButtons++;
					}
				}
				
				deviceRecord->axisStates = (float *)calloc(sizeof(float), deviceRecord->numAxes);
				deviceRecord->buttonStates = (bool *)calloc(sizeof(bool), deviceRecord->numButtons);
				
				if (Gamepad_deviceAttachCallback != NULL) {
					Gamepad_deviceAttachCallback(deviceRecord, Gamepad_deviceAttachContext);
				}
				
				pthread_create(&deviceRecordPrivate->thread, NULL, deviceThread, deviceRecord);
			}
		}
		closedir(dev_input);
	}
	
	lastInputStatTime = currentTime;
	pthread_mutex_unlock(&devicesMutex);
}
Example #19
0
static int
evdev_try_add(int fd)
{
  unsigned short id[4];
  unsigned long bit[EV_MAX][NBITS(KEY_MAX)];
  char devname[256];

  int ret;

  devname[0] = '\0';
  ioctl(fd, EVIOCGNAME(sizeof(devname)), devname);

  logdebug("\nInvestigating evdev [%s]\n", devname);

  ioctl(fd, EVIOCGID, id);

  if ((!evdev_is_internal(id))
#ifndef __powerpc__
      && !(appleir_cfg.enabled && evdev_is_appleir(id))
#endif
      && !(has_kbd_backlight() && evdev_is_lidswitch(id))
      && !(evdev_is_mouseemu(id))
      && !(evdev_is_extkbd(id)))
    {
      logdebug("Discarding evdev: bus 0x%04x, vid 0x%04x, pid 0x%04x\n", id[ID_BUS], id[ID_VENDOR], id[ID_PRODUCT]);

      close(fd);

      return -1;
    }

  memset(bit, 0, sizeof(bit));

  ioctl(fd, EVIOCGBIT(0, EV_MAX), bit[0]);

  if (!test_bit(EV_KEY, bit[0]))
    {
      logdebug("evdev: no EV_KEY event type (not a keyboard)\n");

      if (!test_bit(EV_SW, bit[0]))
	{
	  logdebug("Discarding evdev: no EV_SW event type (not a switch)\n");

	  close(fd);

	  return -1;
	}
    }
  /* Wireless keyboards advertise EV_ABS events, single them out */
  else if (test_bit(EV_ABS, bit[0]) && !(evdev_is_extkbd_alu_wl(id)))
    {
      logdebug("Discarding evdev with EV_ABS event type (mouse/trackpad)\n");

      close(fd);

      return -1;
    }

  /* There are 2 keyboards, but one of them only has the eject key;
     the real keyboard has all the keys and the LEDs. Checking for
     the LEDs is a quick way of identifying the keyboard we want.
  */
  if (test_bit(EV_LED, bit[0]) && evdev_is_internal(id))
    {
      logdebug(" -> Internal keyboard\n");

      internal_kbd_fd = fd;
    }

  ret = evloop_add(fd, EPOLLIN, evdev_process_events);
  if (ret < 0)
    {
      logmsg(LOG_ERR, "Could not add device to event loop");

      if (fd == internal_kbd_fd)
	internal_kbd_fd = -1;

      close(fd);

      return -1;
    }

  return 0;
}
Example #20
0
static int
prepareUinputInstance (UinputObject *uinput, int keyboard) {
  {
    int type = EV_KEY;
    BITMASK(mask, KEY_MAX+1, char);
    int size = ioctl(keyboard, EVIOCGBIT(type, sizeof(mask)), mask);

    if (size == -1) {
      logSystemError("ioctl[EVIOCGBIT]");
      return 0;
    }

    {
      int count = size * 8;

      {
        int key = KEY_ENTER;

        if (key >= count) return 0;
        if (!BITMASK_TEST(mask, key)) return 0;
      }

      if (!enableUinputEventType(uinput, type)) return 0;

      for (int key=0; key<count; key+=1) {
        if (BITMASK_TEST(mask, key)) {
          if (!enableUinputKey(uinput, key)) {
            return 0;
          }
        }
      }
    }
  }

  if (!enableUinputEventType(uinput, EV_REP)) return 0;
  if (!createUinputDevice(uinput)) return 0;

  {
    int properties[2];

    if (ioctl(keyboard, EVIOCGREP, properties) != -1) {
      if (!writeRepeatDelay(uinput, properties[0])) return 0;
      if (!writeRepeatPeriod(uinput, properties[1])) return 0;
    }
  }

  {
    BITMASK(mask, KEY_MAX+1, char);
    int size = ioctl(keyboard, EVIOCGKEY(sizeof(mask)), mask);

    if (size != -1) {
      int count = size * 8;
      for (int key=0; key<count; key+=1) {
        if (BITMASK_TEST(mask, key)) {
          logMessage(LOG_WARNING, "key already pressed: %d", key);
        }
      }
    }
  }

  return 1;
}
/*
 * Open the device, fill out information about it,
 * allocate and fill private data, start input thread.
 */
bool CLinuxInputDevice::Open()
{
  int fd, ret;
  unsigned long ledbit[NBITS(LED_CNT)];

  /* open device */
  fd = open(m_fileName.c_str(), O_RDWR | O_NONBLOCK);
  if (fd < 0)
  {
    CLog::Log(LOGERROR, "CLinuxInputDevice: could not open device: %s\n", m_fileName.c_str());
    return false;
  }

  /* grab device */
  ret = ioctl(fd, EVIOCGRAB, 1);
  if (ret && errno != EINVAL)
  {
    CLog::Log(LOGERROR, "CLinuxInputDevice: could not grab device: %s\n", m_fileName.c_str());
    close(fd);
    return false;
  }

  // Set the socket to non-blocking
  int opts = 0;
  if ((opts = fcntl(fd, F_GETFL)) < 0)
  {
    CLog::Log(LOGERROR, "CLinuxInputDevice %s: fcntl(F_GETFL) failed: %s", __FUNCTION__ , strerror(errno));
    close(fd);
    return false;
  }

  opts = (opts | O_NONBLOCK);
  if (fcntl(fd, F_SETFL, opts) < 0)
  {
    CLog::Log(LOGERROR, "CLinuxInputDevice %s: fcntl(F_SETFL) failed: %s", __FUNCTION__, strerror(errno));
    close(fd);
    return false;
  }

  /* fill device info structure */
  GetInfo(fd);

  if (m_deviceType & LI_DEVICE_KEYBOARD)
    SetupKeyboardAutoRepeat(fd);

  m_fd = fd;
  m_vt_fd = -1;

  if (m_deviceMinKeyCode >= 0 && m_deviceMaxKeyCode >= m_deviceMinKeyCode)
  {
    if (m_vt_fd < 0)
      m_vt_fd = open("/dev/tty0", O_RDWR | O_NOCTTY);

    if (m_vt_fd < 0)
      CLog::Log(LOGWARNING, "no keymap support (requires /dev/tty0 - CONFIG_VT)");
  }

  /* check if the device has LEDs */
  ret = ioctl(fd, EVIOCGBIT(EV_LED, sizeof(ledbit)), ledbit);
  if (ret < 0)
	  CLog::Log(LOGWARNING, "DirectFB/linux_input: could not get LED bits" );
  else
    m_hasLeds = test_bit( LED_SCROLLL, ledbit ) || test_bit( LED_NUML, ledbit )
        || test_bit( LED_CAPSL, ledbit );

  if (m_hasLeds)
  {
    /* get LED state */
    ret = ioctl(fd, EVIOCGLED(sizeof(m_ledState)), m_ledState);
    if (ret < 0)
    {
      CLog::Log(LOGERROR, "DirectFB/linux_input: could not get LED state");
      goto driver_open_device_error;
    }

    /* turn off LEDs */
    SetLed(LED_SCROLLL, 0);
    SetLed(LED_NUML, 0);
    SetLed(LED_CAPSL, 0);
  }

  return true;

driver_open_device_error:

  ioctl(fd, EVIOCGRAB, 0);
  if (m_vt_fd >= 0)
  {
    close(m_vt_fd);
    m_vt_fd = -1;
  }
  close(fd);
  m_fd = -1;

  return false;
}
Example #22
0
int EventHub::open_device(const char *deviceName)
{
    int version;
    int fd;
    struct pollfd *new_mFDs;
    device_t **new_devices;
    char **new_device_names;
    char name[80];
    char location[80];
    char idstr[80];
    struct input_id id;

    LOGV("Opening device: %s", deviceName);

    AutoMutex _l(mLock);

    fd = open(deviceName, O_RDWR);
    if(fd < 0) {
        LOGE("could not open %s, %s\n", deviceName, strerror(errno));
        return -1;
    }

    if(ioctl(fd, EVIOCGVERSION, &version)) {
        LOGE("could not get driver version for %s, %s\n", deviceName, strerror(errno));
        return -1;
    }
    if(ioctl(fd, EVIOCGID, &id)) {
        LOGE("could not get driver id for %s, %s\n", deviceName, strerror(errno));
        return -1;
    }
    name[sizeof(name) - 1] = '\0';
    location[sizeof(location) - 1] = '\0';
    idstr[sizeof(idstr) - 1] = '\0';
    if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
        //fprintf(stderr, "could not get device name for %s, %s\n", deviceName, strerror(errno));
        name[0] = '\0';
    }

    // check to see if the device is on our excluded list
    List<String8>::iterator iter = mExcludedDevices.begin();
    List<String8>::iterator end = mExcludedDevices.end();
    for ( ; iter != end; iter++) {
        const char* test = *iter;
        if (strcmp(name, test) == 0) {
            LOGI("ignoring event id %s driver %s\n", deviceName, test);
            close(fd);
            fd = -1;
            return -1;
        }
    }

    if(ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), &location) < 1) {
        //fprintf(stderr, "could not get location for %s, %s\n", deviceName, strerror(errno));
        location[0] = '\0';
    }
    if(ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), &idstr) < 1) {
        //fprintf(stderr, "could not get idstring for %s, %s\n", deviceName, strerror(errno));
        idstr[0] = '\0';
    }

    int devid = 0;
    while (devid < mNumDevicesById) {
        if (mDevicesById[devid].device == NULL) {
            break;
        }
        devid++;
    }
    if (devid >= mNumDevicesById) {
        device_ent* new_devids = (device_ent*)realloc(mDevicesById,
                sizeof(mDevicesById[0]) * (devid + 1));
        if (new_devids == NULL) {
            LOGE("out of memory");
            return -1;
        }
        mDevicesById = new_devids;
        mNumDevicesById = devid+1;
        mDevicesById[devid].device = NULL;
        mDevicesById[devid].seq = 0;
    }

    mDevicesById[devid].seq = (mDevicesById[devid].seq+(1<<SEQ_SHIFT))&SEQ_MASK;
    if (mDevicesById[devid].seq == 0) {
        mDevicesById[devid].seq = 1<<SEQ_SHIFT;
    }

    new_mFDs = (pollfd*)realloc(mFDs, sizeof(mFDs[0]) * (mFDCount + 1));
    new_devices = (device_t**)realloc(mDevices, sizeof(mDevices[0]) * (mFDCount + 1));
    if (new_mFDs == NULL || new_devices == NULL) {
        LOGE("out of memory");
        return -1;
    }
    mFDs = new_mFDs;
    mDevices = new_devices;

#if 0
    LOGI("add device %d: %s\n", mFDCount, deviceName);
    LOGI("  bus:      %04x\n"
         "  vendor    %04x\n"
         "  product   %04x\n"
         "  version   %04x\n",
        id.bustype, id.vendor, id.product, id.version);
    LOGI("  name:     \"%s\"\n", name);
    LOGI("  location: \"%s\"\n"
         "  id:       \"%s\"\n", location, idstr);
    LOGI("  version:  %d.%d.%d\n",
        version >> 16, (version >> 8) & 0xff, version & 0xff);
#endif

    device_t* device = new device_t(devid|mDevicesById[devid].seq, deviceName, name);
    if (device == NULL) {
        LOGE("out of memory");
        return -1;
    }

    mFDs[mFDCount].fd = fd;
    mFDs[mFDCount].events = POLLIN;

    // figure out the kinds of events the device reports
    
    // See if this is a keyboard, and classify it.  Note that we only
    // consider up through the function keys; we don't want to include
    // ones after that (play cd etc) so we don't mistakenly consider a
    // controller to be a keyboard.
    uint8_t key_bitmask[(KEY_MAX+7)/8];
    memset(key_bitmask, 0, sizeof(key_bitmask));
    LOGV("Getting keys...");
    if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {
        //LOGI("MAP\n");
        //for (int i=0; i<((KEY_MAX+7)/8); i++) {
        //    LOGI("%d: 0x%02x\n", i, key_bitmask[i]);
        //}
        for (int i=0; i<((BTN_MISC+7)/8); i++) {
            if (key_bitmask[i] != 0) {
                device->classes |= CLASS_KEYBOARD;
                break;
            }
        }
        for (int i=0; i<((BTN_GAMEPAD+7)/8); i++) {
            if (key_bitmask[i] != 0) {
                device->classes |= CLASS_KEYBOARD;
                break;
            }
        }
        if ((device->classes & CLASS_KEYBOARD) != 0) {
            device->keyBitmask = new uint8_t[sizeof(key_bitmask)];
            if (device->keyBitmask != NULL) {
                memcpy(device->keyBitmask, key_bitmask, sizeof(key_bitmask));
            } else {
                delete device;
                LOGE("out of memory allocating key bitmask");
                return -1;
            }
        }
    }
    
    // See if this is a trackball.
    if (test_bit(BTN_MOUSE, key_bitmask)) {
        uint8_t rel_bitmask[(REL_MAX+7)/8];
        memset(rel_bitmask, 0, sizeof(rel_bitmask));
        LOGV("Getting relative controllers...");
        if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0)
        {
            if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y, rel_bitmask)) {
                if (test_bit(BTN_LEFT, key_bitmask) && test_bit(BTN_RIGHT, key_bitmask))
                    device->classes |= CLASS_MOUSE;
                else
                    device->classes |= CLASS_TRACKBALL;
            }
        }
    }
    
    uint8_t abs_bitmask[(ABS_MAX+7)/8];
    memset(abs_bitmask, 0, sizeof(abs_bitmask));
    LOGV("Getting absolute controllers...");
    ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask);
    
    // Is this a new modern multi-touch driver?
    if (test_bit(ABS_MT_TOUCH_MAJOR, abs_bitmask)
            && test_bit(ABS_MT_POSITION_X, abs_bitmask)
            && test_bit(ABS_MT_POSITION_Y, abs_bitmask)) {
        device->classes |= CLASS_TOUCHSCREEN | CLASS_TOUCHSCREEN_MT;
        
    // Is this an old style single-touch driver?
    } else if (test_bit(BTN_TOUCH, key_bitmask)
            && test_bit(ABS_X, abs_bitmask) && test_bit(ABS_Y, abs_bitmask)) {
        device->classes |= CLASS_TOUCHSCREEN;
    }

#ifdef EV_SW
    // figure out the switches this device reports
    uint8_t sw_bitmask[(SW_MAX+7)/8];
    memset(sw_bitmask, 0, sizeof(sw_bitmask));
    if (ioctl(fd, EVIOCGBIT(EV_SW, sizeof(sw_bitmask)), sw_bitmask) >= 0) {
        for (int i=0; i<EV_SW; i++) {
            //LOGI("Device 0x%x sw %d: has=%d", device->id, i, test_bit(i, sw_bitmask));
            if (test_bit(i, sw_bitmask)) {
                if (mSwitches[i] == 0) {
                    mSwitches[i] = device->id;
                }
            }
        }
    }
#endif

    if ((device->classes&CLASS_KEYBOARD) != 0) {
        char tmpfn[sizeof(name)];
        char keylayoutFilename[300];

        // a more descriptive name
        device->name = name;

        // replace all the spaces with underscores
        strcpy(tmpfn, name);
        for (char *p = strchr(tmpfn, ' '); p && *p; p = strchr(tmpfn, ' '))
            *p = '_';

        // find the .kl file we need for this device
        const char* root = getenv("ANDROID_ROOT");
        snprintf(keylayoutFilename, sizeof(keylayoutFilename),
                 "%s/usr/keylayout/%s.kl", root, tmpfn);
        bool defaultKeymap = false;
        if (access(keylayoutFilename, R_OK)) {
            snprintf(keylayoutFilename, sizeof(keylayoutFilename),
                     "%s/usr/keylayout/%s", root, "qwerty.kl");
            defaultKeymap = true;
        }
        device->layoutMap->load(keylayoutFilename);

        // tell the world about the devname (the descriptive name)
        if (!mHaveFirstKeyboard && !defaultKeymap && strstr(name, "-keypad")) {
            // the built-in keyboard has a well-known device ID of 0,
            // this device better not go away.
            mHaveFirstKeyboard = true;
            mFirstKeyboardId = device->id;
            property_set("hw.keyboards.0.devname", name);
        } else {
            // ensure mFirstKeyboardId is set to -something-.
            if (mFirstKeyboardId == 0) {
                mFirstKeyboardId = device->id;
            }
        }
        char propName[100];
        sprintf(propName, "hw.keyboards.%u.devname", device->id);
        property_set(propName, name);

        // 'Q' key support = cheap test of whether this is an alpha-capable kbd
        if (hasKeycode(device, kKeyCodeQ)) {
            device->classes |= CLASS_ALPHAKEY;
        }
        
        // See if this has a DPAD.
        if (hasKeycode(device, kKeyCodeDpadUp) &&
                hasKeycode(device, kKeyCodeDpadDown) &&
                hasKeycode(device, kKeyCodeDpadLeft) &&
                hasKeycode(device, kKeyCodeDpadRight) &&
                hasKeycode(device, kKeyCodeDpadCenter)) {
            device->classes |= CLASS_DPAD;
        }
        
        LOGI("New keyboard: device->id=0x%x devname='%s' propName='%s' keylayout='%s'\n",
                device->id, name, propName, keylayoutFilename);
    }

    // See if this device has a gamepad.
    for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES)/sizeof(GAMEPAD_KEYCODES[0]); i++) {
        if (hasKeycode(device, GAMEPAD_KEYCODES[i])) {
            device->classes |= CLASS_GAMEPAD;
            break;
        }
    }

    LOGI("New device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
         deviceName, name, device->id, mNumDevicesById, mFDCount, fd, device->classes);
         
    LOGV("Adding device %s %p at %d, id = %d, classes = 0x%x\n",
         deviceName, device, mFDCount, devid, device->classes);

    mDevicesById[devid].device = device;
    device->next = mOpeningDevices;
    mOpeningDevices = device;
    mDevices[mFDCount] = device;

    mFDCount++;
    return 0;
}
Example #23
0
static int print_possible_events(int fd, int print_flags)
{
    uint8_t *bits = NULL;
    ssize_t bits_size = 0;
    const char* label;
    int i, j, k;
    int res, res2;
    struct label* bit_labels;
    const char *bit_label;

    printf("  events:\n");
    for(i = EV_KEY; i <= EV_MAX; i++) { // skip EV_SYN since we cannot query its available codes
        int count = 0;
        while(1) {
            res = ioctl(fd, EVIOCGBIT(i, bits_size), bits);
            if(res < bits_size)
                break;
            bits_size = res + 16;
            bits = realloc(bits, bits_size * 2);
            if(bits == NULL) {
                fprintf(stderr, "failed to allocate buffer of size %d\n", (int)bits_size);
                return 1;
            }
        }
        res2 = 0;
        switch(i) {
            case EV_KEY:
                res2 = ioctl(fd, EVIOCGKEY(res), bits + bits_size);
                label = "KEY";
                bit_labels = key_labels;
                break;
            case EV_REL:
                label = "REL";
                bit_labels = rel_labels;
                break;
            case EV_ABS:
                label = "ABS";
                bit_labels = abs_labels;
                break;
            case EV_MSC:
                label = "MSC";
                bit_labels = msc_labels;
                break;
            case EV_LED:
                res2 = ioctl(fd, EVIOCGLED(res), bits + bits_size);
                label = "LED";
                bit_labels = led_labels;
                break;
            case EV_SND:
                res2 = ioctl(fd, EVIOCGSND(res), bits + bits_size);
                label = "SND";
                bit_labels = snd_labels;
                break;
            case EV_SW:
                res2 = ioctl(fd, EVIOCGSW(bits_size), bits + bits_size);
                label = "SW ";
                bit_labels = sw_labels;
                break;
            case EV_REP:
                label = "REP";
                bit_labels = rep_labels;
                break;
            case EV_FF:
                label = "FF ";
                bit_labels = ff_labels;
                break;
            case EV_PWR:
                label = "PWR";
                bit_labels = NULL;
                break;
            case EV_FF_STATUS:
                label = "FFS";
                bit_labels = ff_status_labels;
                break;
            default:
                res2 = 0;
                label = "???";
                bit_labels = NULL;
        }
        for(j = 0; j < res; j++) {
            for(k = 0; k < 8; k++)
                if(bits[j] & 1 << k) {
                    char down;
                    if(j < res2 && (bits[j + bits_size] & 1 << k))
                        down = '*';
                    else
                        down = ' ';
                    if(count == 0)
                        printf("    %s (%04x):", label, i);
                    else if((count & (print_flags & PRINT_LABELS ? 0x3 : 0x7)) == 0 || i == EV_ABS)
                        printf("\n               ");
                    if(bit_labels && (print_flags & PRINT_LABELS)) {
                        bit_label = get_label(bit_labels, j * 8 + k);
                        if(bit_label)
                            printf(" %.20s%c%*s", bit_label, down, 20 - strlen(bit_label), "");
                        else
                            printf(" %04x%c                ", j * 8 + k, down);
                    } else {
                        printf(" %04x%c", j * 8 + k, down);
                    }
                    if(i == EV_ABS) {
                        struct input_absinfo abs;
                        if(ioctl(fd, EVIOCGABS(j * 8 + k), &abs) == 0) {
                            printf(" : value %d, min %d, max %d, fuzz %d, flat %d, resolution %d",
                                abs.value, abs.minimum, abs.maximum, abs.fuzz, abs.flat,
                                abs.resolution);
                        }
                    }
                    count++;
                }
        }
        if(count)
            printf("\n");
    }
    free(bits);
    return 0;
}
		/*
		 * It so happens that the pointer that gives us the trouble
		 * is the last field in the structure. Since we don't support
		 * custom waveforms in uinput anyway we can just copy the whole
		 * thing (to the compat size) and ignore the pointer.
		 */
		memcpy(&ff_up_compat.effect, &ff_up->effect,
			sizeof(struct ff_effect_compat));
		memcpy(&ff_up_compat.old, &ff_up->old,
			sizeof(struct ff_effect_compat));

		if (copy_to_user(buffer, &ff_up_compat,
				 sizeof(struct uinput_ff_upload_compat)))
			return -EFAULT;
	} else {
		if (copy_to_user(buffer, ff_up,
				 sizeof(struct uinput_ff_upload)))
			return -EFAULT;
	}

	return 0;
}

static int uinput_ff_upload_from_user(const char __user *buffer,
				      struct uinput_ff_upload *ff_up)
{
	if (INPUT_COMPAT_TEST) {
		struct uinput_ff_upload_compat ff_up_compat;

		if (copy_from_user(&ff_up_compat, buffer,
				   sizeof(struct uinput_ff_upload_compat)))
			return -EFAULT;

		ff_up->request_id = ff_up_compat.request_id;
		ff_up->retval = ff_up_compat.retval;
		memcpy(&ff_up->effect, &ff_up_compat.effect,
			sizeof(struct ff_effect_compat));
		memcpy(&ff_up->old, &ff_up_compat.old,
			sizeof(struct ff_effect_compat));

	} else {
		if (copy_from_user(ff_up, buffer,
				   sizeof(struct uinput_ff_upload)))
			return -EFAULT;
	}

	return 0;
}

#else

static int uinput_ff_upload_to_user(char __user *buffer,
				    const struct uinput_ff_upload *ff_up)
{
	if (copy_to_user(buffer, ff_up, sizeof(struct uinput_ff_upload)))
		return -EFAULT;

	return 0;
}

static int uinput_ff_upload_from_user(const char __user *buffer,
				      struct uinput_ff_upload *ff_up)
{
	if (copy_from_user(ff_up, buffer, sizeof(struct uinput_ff_upload)))
		return -EFAULT;

	return 0;
}

#endif

#define uinput_set_bit(_arg, _bit, _max)		\
({							\
	int __ret = 0;					\
	if (udev->state == UIST_CREATED)		\
		__ret =  -EINVAL;			\
	else if ((_arg) > (_max))			\
		__ret = -EINVAL;			\
	else set_bit((_arg), udev->dev->_bit);		\
	__ret;						\
})

#ifdef CONFIG_FEATURE_PANTECH_MDS_MTC //|| defined(FEATURE_PANTECH_STABILITY)
#ifdef CONFIG_COMPAT 
#define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8)
#define BITS_TO_LONGS_COMPAT(x) ((((x) - 1) / BITS_PER_LONG_COMPAT) + 1)
#ifdef __BIG_ENDIAN
static int bits_to_user(unsigned long *bits, unsigned int maxbit,
       unsigned int maxlen, void __user *p, int compat)
{
   int len, i;
   if (compat) {
     len = BITS_TO_LONGS_COMPAT(maxbit) * sizeof(compat_long_t);
     if (len > maxlen)
       len = maxlen;
     for (i = 0; i < len / sizeof(compat_long_t); i++)
       if (copy_to_user((compat_long_t __user *) p + i,
            (compat_long_t *) bits +
             i + 1 - ((i % 2) << 1),
            sizeof(compat_long_t)))
         return -EFAULT;
   } else {
     len = BITS_TO_LONGS(maxbit) * sizeof(long);
     if (len > maxlen)
       len = maxlen;
     if (copy_to_user(p, bits, len))
       return -EFAULT;
   }
   return len;
}
#else
 static int bits_to_user(unsigned long *bits, unsigned int maxbit,
      unsigned int maxlen, void __user *p, int compat)
{
  int len = compat ?
      BITS_TO_LONGS_COMPAT(maxbit) * sizeof(compat_long_t) :
      BITS_TO_LONGS(maxbit) * sizeof(long);
  if (len > maxlen)
    len = maxlen;
  return copy_to_user(p, bits, len) ? -EFAULT : len;
}
#endif /* __BIG_ENDIAN */
#else
static int bits_to_user(unsigned long *bits, unsigned int maxbit,
      unsigned int maxlen, void __user *p, int compat)
{
  int len = BITS_TO_LONGS(maxbit) * sizeof(long);
  if (len > maxlen)
    len = maxlen;
  return copy_to_user(p, bits, len) ? -EFAULT : len;
}
#endif /* CONFIG_COMPAT */
static int str_to_user(const char *str, unsigned int maxlen, void __user *p)
{
  int len;
  if (!str)
    return -ENOENT;
  len = strlen(str) + 1;
  if (len > maxlen)
    len = maxlen;
  return copy_to_user(p, str, len) ? -EFAULT : len;
}
#define OLD_KEY_MAX 0x1ff
static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user *p, int compat_mode) 
{
  unsigned long *bits;
  int len;
  switch (_IOC_NR(cmd) & EV_MAX) {
   case      0: bits = dev->evbit;  len = EV_MAX;  break;
   case EV_KEY: bits = dev->keybit; len = KEY_MAX; break;
   case EV_REL: bits = dev->relbit; len = REL_MAX; break;
   case EV_ABS: bits = dev->absbit; len = ABS_MAX; break;
   case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break;
   case EV_LED: bits = dev->ledbit; len = LED_MAX; break;
   case EV_SND: bits = dev->sndbit; len = SND_MAX; break;
   case EV_FF:  bits = dev->ffbit;  len = FF_MAX;  break;
   case EV_SW:  bits = dev->swbit;  len = SW_MAX;  break;
   default: return -EINVAL;
  }
  if ((_IOC_NR(cmd) & EV_MAX) == EV_KEY && _IOC_SIZE(cmd) == OLD_KEY_MAX) {
     len = OLD_KEY_MAX;
  }
   return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode);
}
#undef OLD_KEY_MAX
#endif/*CONFIG_FEATURE_PANTECH_MDS_MTC || FEATURE_PANTECH_STABILITY*/
static long uinput_ioctl_handler(struct file *file, unsigned int cmd,
				 unsigned long arg, void __user *p)
{
	int			retval;
	struct uinput_device	*udev = file->private_data;
	struct uinput_ff_upload ff_up;
	struct uinput_ff_erase  ff_erase;
	struct uinput_request   *req;
	char			*phys;

	retval = mutex_lock_interruptible(&udev->mutex);
	if (retval)
		return retval;

	if (!udev->dev) {
		retval = uinput_allocate_device(udev);
		if (retval)
			goto out;
	}

	switch (cmd) {
		case UI_DEV_CREATE:
			retval = uinput_create_device(udev);
			break;

		case UI_DEV_DESTROY:
			uinput_destroy_device(udev);
			break;
#ifdef CONFIG_FEATURE_PANTECH_MDS_MTC //|| defined(FEATURE_PANTECH_STABILITY)
   case EVIOCGVERSION: 
		 if (udev->state != UIST_CREATED) 
			retval = -ENODEV;	
		 else put_user(EV_VERSION, (int __user *)p);
		  break;
	 case EVIOCGID:
		 if (udev->state != UIST_CREATED) 
			retval = -ENODEV;	
	   else if (copy_to_user(p, &udev->dev->id, sizeof(struct input_id)))
			retval = -EFAULT;
			break; 
#endif/*CONFIG_FEATURE_PANTECH_MDS_MTC || FEATURE_PANTECH_STABILITY*/	 

		case UI_SET_EVBIT:
			retval = uinput_set_bit(arg, evbit, EV_MAX);
			break;

		case UI_SET_KEYBIT:
			retval = uinput_set_bit(arg, keybit, KEY_MAX);
			break;

		case UI_SET_RELBIT:
			retval = uinput_set_bit(arg, relbit, REL_MAX);
			break;

		case UI_SET_ABSBIT:
			retval = uinput_set_bit(arg, absbit, ABS_MAX);
			break;

		case UI_SET_MSCBIT:
			retval = uinput_set_bit(arg, mscbit, MSC_MAX);
			break;

		case UI_SET_LEDBIT:
			retval = uinput_set_bit(arg, ledbit, LED_MAX);
			break;

		case UI_SET_SNDBIT:
			retval = uinput_set_bit(arg, sndbit, SND_MAX);
			break;

		case UI_SET_FFBIT:
			retval = uinput_set_bit(arg, ffbit, FF_MAX);
			break;

		case UI_SET_SWBIT:
			retval = uinput_set_bit(arg, swbit, SW_MAX);
			break;

		case UI_SET_PROPBIT:
			retval = uinput_set_bit(arg, propbit, INPUT_PROP_MAX);
			break;

		case UI_SET_PHYS:
			if (udev->state == UIST_CREATED) {
				retval = -EINVAL;
				goto out;
			}

			phys = strndup_user(p, 1024);
			if (IS_ERR(phys)) {
				retval = PTR_ERR(phys);
				goto out;
			}

			kfree(udev->dev->phys);
			udev->dev->phys = phys;
			break;

		case UI_BEGIN_FF_UPLOAD:
			retval = uinput_ff_upload_from_user(p, &ff_up);
			if (retval)
				break;

			req = uinput_request_find(udev, ff_up.request_id);
			if (!req || req->code != UI_FF_UPLOAD || !req->u.upload.effect) {
				retval = -EINVAL;
				break;
			}

			ff_up.retval = 0;
			ff_up.effect = *req->u.upload.effect;
			if (req->u.upload.old)
				ff_up.old = *req->u.upload.old;
			else
				memset(&ff_up.old, 0, sizeof(struct ff_effect));

			retval = uinput_ff_upload_to_user(p, &ff_up);
			break;

		case UI_BEGIN_FF_ERASE:
			if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
				retval = -EFAULT;
				break;
			}

			req = uinput_request_find(udev, ff_erase.request_id);
			if (!req || req->code != UI_FF_ERASE) {
				retval = -EINVAL;
				break;
			}

			ff_erase.retval = 0;
			ff_erase.effect_id = req->u.effect_id;
			if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) {
				retval = -EFAULT;
				break;
			}

			break;

		case UI_END_FF_UPLOAD:
			retval = uinput_ff_upload_from_user(p, &ff_up);
			if (retval)
				break;

			req = uinput_request_find(udev, ff_up.request_id);
			if (!req || req->code != UI_FF_UPLOAD ||
			    !req->u.upload.effect) {
				retval = -EINVAL;
				break;
			}

			req->retval = ff_up.retval;
			uinput_request_done(udev, req);
			break;

		case UI_END_FF_ERASE:
			if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
				retval = -EFAULT;
				break;
			}

			req = uinput_request_find(udev, ff_erase.request_id);
			if (!req || req->code != UI_FF_ERASE) {
				retval = -EINVAL;
				break;
			}

			req->retval = ff_erase.retval;
			uinput_request_done(udev, req);
			break;

		default:
#ifdef CONFIG_FEATURE_PANTECH_MDS_MTC // || defined(FEATURE_PANTECH_STABILITY)
		{
			 if (udev->state != UIST_CREATED){ 
				retval = -ENODEV;	
				break;
			 }
			 if (_IOC_DIR(cmd) == _IOC_READ) { 
				if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0)))
				  handle_eviocgbit(udev->dev, cmd, p, 0);
				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0)))
				  bits_to_user(udev->dev->key, KEY_MAX, _IOC_SIZE(cmd),
				              p, 0);
				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0)))
				  bits_to_user(udev->dev->led, LED_MAX, _IOC_SIZE(cmd),
				              p, 0);
				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0)))
				  bits_to_user(udev->dev->snd, SND_MAX, _IOC_SIZE(cmd),
				              p, 0);
				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSW(0)))
				  bits_to_user(udev->dev->sw, SW_MAX, _IOC_SIZE(cmd),
				              p, 0);
				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0)))
				  str_to_user(udev->dev->name, _IOC_SIZE(cmd), p);
				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0)))
				  str_to_user(udev->dev->phys, _IOC_SIZE(cmd), p);
				if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0)))
				  str_to_user(udev->dev->uniq, _IOC_SIZE(cmd), p);
				if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) {
			      int t;
			      struct input_absinfo abs;
			      t = _IOC_NR(cmd) & ABS_MAX;
						abs.value = input_abs_get_val(udev->dev,t);
						abs.minimum = input_abs_get_min(udev->dev,t);
				    abs.maximum = input_abs_get_max(udev->dev,t);
				    abs.fuzz = input_abs_get_fuzz(udev->dev,t);
				    abs.flat = input_abs_get_flat(udev->dev,t);
				/*
			      abs.value = udev->dev->abs[t];
				    abs.minimum = udev->dev->absmin[t];
				    abs.maximum = udev->dev->absmax[t];
				    abs.fuzz = udev->dev->absfuzz[t];
				    abs.flat = udev->dev->absflat[t];

				*/
						if (copy_to_user(p, &abs, sizeof(struct input_absinfo)))
						 retval= -EFAULT;
				  }
			}
		}
#else
			retval = -EINVAL;
#endif/*CONFIG_FEATURE_PANTECH_MDS_MTC || FEATURE_PANTECH_STABILITY*/
	}

 out:
	mutex_unlock(&udev->mutex);
	return retval;
}
/* Initialization. This should run automatically. */
void __attribute__ ((constructor)) joyrumble_init(void)
{
	
	#ifdef DEBUG
		printf("INIT\n");
	#endif
	
	/* event_fd is the handle of the event file */
	int event_fd;
	
	int count=0, j=0;
	
	/* this will hold the path of files while we do some checks */
	char tmp[128];
	
	for (count = 0; count < MAXJOY; count++)
	{
		
		sprintf(tmp,"/dev/input/js%d",count);
		/* Check if joystick device exists */
		if (file_exists(tmp)==1){
			lastjoy=count;	
			for (j = 0; j <= 99; j++)
			{
			/* Try to discover the corresponding event number */
			sprintf(tmp,"/sys/class/input/js%d/device/event%d",count,j);
			if (dir_exists(tmp)==1){
				/* Store the full path of the event file in the eventfile[] array */
				sprintf(tmp,"/dev/input/event%d",j);
				eventfile[count]=(char *)calloc(sizeof(tmp),sizeof(char));
				sprintf(eventfile[count], "%s", tmp);
				#ifdef DEBUG
					printf("%s", eventfile[count]);
					printf("\n");
				#endif
				}
			}
		
		} // else printf("Joystick does not exist!");
		
	}
	
	#ifdef DEBUG
		printf("lastjoy=%d\n",lastjoy);
	#endif

	for (count = 0; count <= lastjoy ; count++)
	{
	
	hasrumble[count]=0;
		
	/* Prepare the effects */
	effects[count].type = FF_RUMBLE;
	effects[count].u.rumble.strong_magnitude = 65535;
	effects[count].u.rumble.weak_magnitude = 65535;
	effects[count].replay.length = 1000;
	effects[count].replay.delay = 0;
	effects[count].id = -1;

	/* Prepare the stop event */
	stop[count].type = EV_FF;
	stop[count].code = effects[count].id;
	stop[count].value = 0;
		
	/* Prepare the play event */
	play[count].type = EV_FF;
	play[count].code = effects[count].id;
	play[count].value = 1;

		
	/* Open event file to verify if the device and the drivers support rumble */
	event_fd = open(eventfile[count], O_RDWR);
	
		
	if (event_fd < 0)
		
		/* Can't acess the event file */
		hasrumble[count]=0;
	
	else{

		if (ioctl(event_fd, EVIOCGBIT(EV_FF, sizeof(unsigned long) * 4), features) == -1)
			/* This device can't rumble, or the drivers don't support it */
			hasrumble[count]=0;
		
		else{
		
			if (test_bit(FF_RUMBLE, features))
				/* Success! This device can rumble! */
				hasrumble[count]=1;
		}
		
	/* Close the event file */
	if (event_fd>0) 	
		close(event_fd);
	
	}

	#ifdef DEBUG
		printf("%s", eventfile[count]);
	
		if (hasrumble[count]){
			printf(" can rumble.\n");
		}
		else{
			printf(" can't rumble.\n");
		}
	#endif
	
	}
	
	/* Initialization is complete */
	initialized=1;
}
Example #26
0
static adv_error joystickb_setup(struct joystick_item_context* item, int f)
{
	unsigned char key_bitmask[KEY_MAX/8 + 1];
	unsigned char abs_bitmask[ABS_MAX/8 + 1];
	unsigned char rel_bitmask[REL_MAX/8 + 1];
	unsigned i;
	unsigned short device_info[4];

	struct button_entry {
		int code;
		const char* name;
	} button_map[] = {
		#ifdef BTN_TRIGGER
		{ BTN_TRIGGER, "trigger" }, /* joystick */
		#endif
		#ifdef BTN_THUMB
		{ BTN_THUMB, "thumb" }, /* joystick */
		#endif
		#ifdef BTN_THUMB2
		{ BTN_THUMB2, "thumb2" }, /* joystick */
		#endif
		#ifdef BTN_TOP
		{ BTN_TOP, "top" }, /* joystick */
		#endif
		#ifdef BTN_TOP2
		{ BTN_TOP2, "top2" }, /* joystick */
		#endif
		#ifdef BTN_PINKIE
		{ BTN_PINKIE, "pinkie" }, /* joystick */
		#endif
		#ifdef BTN_BASE
		{ BTN_BASE, "base" }, /* joystick */
		#endif
		#ifdef BTN_BASE2
		{ BTN_BASE2, "base2" }, /* joystick */
		#endif
		#ifdef BTN_BASE3
		{ BTN_BASE3, "base3" }, /* joystick */
		#endif
		#ifdef BTN_BASE4
		{ BTN_BASE4, "base4" }, /* joystick */
		#endif
		#ifdef BTN_BASE5
		{ BTN_BASE5, "base5" }, /* joystick */
		#endif
		#ifdef BTN_BASE6
		{ BTN_BASE6, "base6" }, /* joystick */
		#endif
		#ifdef BTN_DEAD
		{ BTN_DEAD, "dead" }, /* joystick */
		#endif
		#ifdef BTN_A
		{ BTN_A, "a" }, /* gamepad */
		#endif
		#ifdef BTN_B
		{ BTN_B, "b" }, /* gamepad */
		#endif
		#ifdef BTN_C
		{ BTN_C, "c" }, /* gamepad */
		#endif
		#ifdef BTN_X
		{ BTN_X, "x" }, /* gamepad */
		#endif
		#ifdef BTN_Y
		{ BTN_Y, "y" }, /* gamepad */
		#endif
		#ifdef BTN_Z
		{ BTN_Z, "z" }, /* gamepad */
		#endif
		#ifdef BTN_TL
		{ BTN_TL, "tl" }, /* gamepad (top left) */
		#endif
		#ifdef BTN_TR
		{ BTN_TR, "tr" }, /* gamepad (top right) */
		#endif
		#ifdef BTN_TL2
		{ BTN_TL2, "tl2" }, /* gamepad (top left 2) */
		#endif
		#ifdef BTN_TR2
		{ BTN_TR2, "tr2" }, /* gamepad (top right 2) */
		#endif
		#ifdef BTN_SELECT
		{ BTN_SELECT, "select" }, /* gamepad */
		#endif
		#ifdef BTN_START
		{ BTN_START, "start" }, /* gamepad */
		#endif
		#ifdef BTN_MODE
		{ BTN_MODE, "mode" }, /* gamepad */
		#endif
		#ifdef BTN_THUMBL
		{ BTN_THUMBL, "thumbl" }, /* gamepad (thumb left) */
		#endif
		#ifdef BTN_THUMBR
		{ BTN_THUMBR, "thumbr" }, /* gamepad (thumb right) */
		#endif
		#ifdef BTN_GEAR_DOWN
		{ BTN_GEAR_DOWN, "gear_down" }, /* wheel */
		#endif
		#ifdef BTN_GEAR_UP
		{ BTN_GEAR_UP, "gear_up" }, /* wheel */
		#endif
		#ifdef BTN_0
		{ BTN_0, "0" }, /* misc */
		#endif
		#ifdef BTN_1
		{ BTN_1, "1" }, /* misc */
		#endif
		#ifdef BTN_2
		{ BTN_2, "2" }, /* misc */
		#endif
		#ifdef BTN_3
		{ BTN_3, "3" }, /* misc */
		#endif
		#ifdef BTN_4
		{ BTN_4, "4" }, /* misc */
		#endif
		#ifdef BTN_5
		{ BTN_5, "5" }, /* misc */
		#endif
		#ifdef BTN_6
		{ BTN_6, "6" }, /* misc */
		#endif
		#ifdef BTN_7
		{ BTN_7, "7" }, /* misc */
		#endif
		#ifdef BTN_8
		{ BTN_8, "8" }, /* misc */
		#endif
		#ifdef BTN_9
		{ BTN_9, "9" }, /* misc */
		#endif
		#ifdef BTN_LEFT
		{ BTN_LEFT, "left" }, /* ball */
		#endif
		#ifdef BTN_RIGHT
		{ BTN_RIGHT, "right" }, /* ball */
		#endif
		#ifdef BTN_MIDDLE
		{ BTN_MIDDLE, "middle" }, /* ball/lightgun first button */
		#endif
		#ifdef BTN_SIDE
		{ BTN_SIDE, "side" }, /* ball/lightgun second button */
		#endif
		#ifdef BTN_EXTRA
		{ BTN_EXTRA, "extra" }, /* ball */
		#endif
		#ifdef BTN_FORWARD
		{ BTN_FORWARD, "forward" }, /* ball */
		#endif
		#ifdef BTN_BACK
		{ BTN_BACK, "back" } /* ball */
		#endif
	};

	/* WARNING: It must be syncronized with the list in event.c */
	struct stick_entry {
		struct axe_entry {
			int code;
			const char* name;
		} axe_map[7];
		const char* name;
	} stick_map[] = {
		{ { { ABS_X, "x" }, { ABS_Y, "y" }, { ABS_Z, "z" }, { ABS_RX, "rx" }, { ABS_RY, "ry" }, { ABS_RZ, "rz" }, { ABS_UNASSIGNED, 0 } }, "stick" },
		#ifdef ABS_GAS
		{ { { ABS_GAS, "mono" }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 } }, "gas" }, /* IT:acceleratore */
		#endif
		#ifdef ABS_BRAKE
		{ { { ABS_BRAKE, "mono" }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 } }, "brake" }, /* IT:freno */
		#endif
		#ifdef ABS_WHEEL
		{ { { ABS_WHEEL, "mono" }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 } }, "wheel" }, /* IT:volante */
		#endif
		#ifdef ABS_HAT0X
		{ { { ABS_HAT0X, "x" }, { ABS_HAT0Y, "y" }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 } }, "hat" }, /* IT:mini joystick digitale */
		#endif
		#ifdef ABS_HAT1X
		{ { { ABS_HAT1X, "x" }, { ABS_HAT1Y, "y" }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 } }, "hat2" },
		#endif
		#ifdef ABS_HAT2X
		{ { { ABS_HAT2X, "x" }, { ABS_HAT2Y, "y" }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 } }, "hat3" },
		#endif
		#ifdef ABS_HAT3X
		{ { { ABS_HAT3X, "x" }, { ABS_HAT3Y, "y" }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 } }, "hat4" },
		#endif
		#ifdef ABS_THROTTLE
		{ { { ABS_THROTTLE, "mono" }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 } }, "throttle" },
		#endif
		#ifdef ABS_RUDDER
		{ { { ABS_RUDDER, "mono" }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 } }, "rudder" }, /* IT:timone */
		#endif
		/* { { { ABS_PRESSURE, "mono" }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 } }, "pressure" }, */ /* tablet */
		/* { { { ABS_DISTANCE, "mono" }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 } }, "distance" }, */ /* tablet */
		/* { { { ABS_TILT_X, "x" }, { ABS_TILT_Y, "y" }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 } }, "tilt" }, */ /* tablet */
		/* { { { ABS_VOLUME, "mono" }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 } }, "volume" }, */ /* not an action control */
		#ifdef ABS_MISC
		{ { { ABS_MISC, "mono" }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 }, { ABS_UNASSIGNED, 0 } }, "misc" }
		#endif
	};

	struct rel_entry {
		int code;
		const char* name;
	} rel_map[] = {
		#ifdef REL_X
		{ REL_X, "x" },
		#endif
		#ifdef REL_Y
		{ REL_Y, "y" },
		#endif
		#ifdef REL_Z
		{ REL_Z, "z" },
		#endif
		#ifdef REL_WHEEL
		{ REL_WHEEL, "wheel" }, /* (IT: rotella del mouse verticale) */
		#endif
		#ifdef REL_HWHEEL
		{ REL_HWHEEL, "hwheel" }, /* (IT: rotella del mouse orizzontale) */
		#endif
		#ifdef REL_DIAL
		{ REL_DIAL, "dial" }, /* (IT: manopola che gira) */
		#endif
		#ifdef REL_MISC
		{ REL_MISC, "misc" }
		#endif
	};

	item->f = f;

#ifdef USE_ACTLABS_HACK
	item->actlabs_hack_enable = 0;
#endif

	if (ioctl(f, EVIOCGID, &device_info)) {
		log_std(("event: error in ioctl(EVIOCGID)\n"));
		item->vendor_id = 0;
		item->device_id = 0;
		item->version_id = 0;
		item->bus_id = 0;
	} else {
		item->vendor_id = device_info[ID_VENDOR];
		item->device_id = device_info[ID_PRODUCT];
		item->version_id = device_info[ID_VERSION];
		item->bus_id = device_info[ID_BUS];
	}

	memset(key_bitmask, 0, sizeof(key_bitmask));
	if (event_test_bit(EV_KEY, item->evtype_bitmask)) {
		if (ioctl(f, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) < 0) {
			log_std(("event: error in ioctl(EVIOCGBIT(EV_KEY,%d))\n", (int)KEY_MAX));
			return -1;
		}
	}

	item->button_mac = 0;
	for(i=0;i<sizeof(button_map)/sizeof(button_map[0]);++i) {
		if (event_test_bit(button_map[i].code, key_bitmask)) {
			if (item->button_mac < EVENT_JOYSTICK_BUTTON_MAX) {
				item->button_map[item->button_mac].code = button_map[i].code;
				item->button_map[item->button_mac].state = 0;
				sncpy(item->button_map[item->button_mac].name, sizeof(item->button_map[item->button_mac].name), button_map[i].name);
				++item->button_mac;
			}
		}
	}

	memset(abs_bitmask, 0, sizeof(abs_bitmask));
	if (event_test_bit(EV_ABS, item->evtype_bitmask)) {
		if (ioctl(f, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) < 0) {
			log_std(("event: error in ioctl(EVIOCGBIT(EV_ABS,%d))\n", (int)ABS_MAX));
			return -1;
		}
	}

	item->stick_mac = 0;
	for(i=0;i<sizeof(stick_map)/sizeof(stick_map[0]);++i) {
		if (item->stick_mac < EVENT_JOYSTICK_STICK_MAX) {
			unsigned j;
			struct joystick_stick_context* stick = item->stick_map + item->stick_mac;

			stick->axe_mac = 0;
			sncpy(stick->name, sizeof(stick->name), stick_map[i].name);

			for(j=0;stick_map[i].axe_map[j].code != ABS_UNASSIGNED;++j) {
				int code = stick_map[i].axe_map[j].code;
				if (event_test_bit(code, abs_bitmask)) {
					if (stick->axe_mac < EVENT_JOYSTICK_AXE_MAX) {
						struct joystick_axe_context* axe = stick->axe_map + stick->axe_mac;
						int features[5];

						axe->code = code;

						sncpy(axe->name, sizeof(axe->name), stick_map[i].axe_map[j].name);

						memset(features, 0, sizeof(features));
						if (ioctl(f, EVIOCGABS(code), features) < 0) {
							axe->min = 0;
							axe->max = 0;
							axe->fuzz = 0;
							axe->flat = 0;
							axe->digit_low = -32;
							axe->digit_high = 32;
							axe->value = 0;
							axe->value_adj = 0;
						} else {
							int middle = (features[1] + features[2]) / 2;
							int size = features[2] - features[1];
							int flat = features[4];
							axe->min = features[1];
							axe->max = features[2];
							axe->fuzz = features[3];
							axe->flat = features[4];
							axe->digit_low = middle - flat - (size - flat) / 8;
							axe->digit_high = middle + flat + (size - flat) / 8;
							axe->value = middle;
							axe->value_adj = 0;
						}

						++stick->axe_mac;
					}
				}
			}

			/* save the stick only if it hash some axes */
			if (stick->axe_mac)
				++item->stick_mac;
		}
	}

	memset(rel_bitmask, 0, sizeof(rel_bitmask));
	if (event_test_bit(EV_REL, item->evtype_bitmask)) {
		if (ioctl(f, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) < 0) {
			log_std(("event: error in ioctl(EVIOCGBIT(EV_REL,%d))\n", (int)REL_MAX));
			return -1;
		}
	}

	item->rel_mac = 0;
	for(i=0;i<sizeof(rel_map)/sizeof(rel_map[0]);++i) {
		if (event_test_bit(rel_map[i].code, rel_bitmask)) {
			if (item->rel_mac < EVENT_JOYSTICK_REL_MAX) {
				item->rel_map[item->rel_mac].code = rel_map[i].code;
				item->rel_map[item->rel_mac].value = 0;
				sncpy(item->rel_map[item->rel_mac].name, sizeof(item->rel_map[item->rel_mac].name), rel_map[i].name);
				++item->rel_mac;
			}
		}
	}

	return 0;
}
Joystick_Linux::Joystick_Linux(const char *jsdev_path, const char *evdev_path) : jsdev_fd(-1), evdev_fd(-1)
{
 unsigned char tmp;

 //printf("%s %s\n", jsdev_path, evdev_path);

 jsdev_fd = open(jsdev_path, O_RDONLY);
 if(jsdev_fd == -1)
 {
  ErrnoHolder ene(errno);

  throw MDFN_Error(ene.Errno(), _("Error opening joystick device \"%s\": %s"), jsdev_path, ene.StrError());
 }

 fcntl(jsdev_fd, F_SETFL, fcntl(jsdev_fd, F_GETFL) | O_NONBLOCK);

 if(evdev_path != NULL)
 {
  evdev_fd = open(evdev_path, O_RDWR);
  if(evdev_fd == -1)
  {
   ErrnoHolder ene(errno);

   if(ene.Errno() == EACCES)
   {
    evdev_fd = open(evdev_path, O_RDONLY);
    if(evdev_fd == -1)
    {
     ErrnoHolder ene2(errno);

     fprintf(stderr, _("WARNING: Failed to open event device \"%s\": %s --- !!!!! BASE JOYSTICK FUNCTIONALITY WILL BE AVAILABLE, BUT FORCE-FEEDBACK(E.G. RUMBLE) WILL BE UNAVAILABLE, AND THE CALCULATED JOYSTICK ID WILL BE DIFFERENT. !!!!!\n"), evdev_path, ene2.StrError());
    }
    else
    {
     fprintf(stderr, _("WARNING: Could only open event device \"%s\" for reading, and not reading+writing: %s --- !!!!! FORCE-FEEDBACK(E.G. RUMBLE) WILL BE UNAVAILABLE. !!!!!\n"), evdev_path, ene.StrError());
    }
   }
   else
    fprintf(stderr, _("WARNING: Failed to open event device \"%s\": %s --- !!!!! BASE JOYSTICK FUNCTIONALITY WILL BE AVAILABLE, BUT FORCE-FEEDBACK(E.G. RUMBLE) WILL BE UNAVAILABLE, AND THE CALCULATED JOYSTICK ID WILL BE DIFFERENT. !!!!!\n"), evdev_path, ene.StrError());
  }
 }
 else
  fprintf(stderr, _("WARNING: Failed to find a valid corresponding event device to joystick device \"%s\" --- !!!!! BASE JOYSTICK FUNCTIONALITY WILL BE AVAILABLE, BUT FORCE-FEEDBACK(E.G. RUMBLE) WILL BE UNAVAILABLE, AND THE CALCULATED JOYSTICK ID WILL BE DIFFERENT. !!!!!\n"), jsdev_path);

 if(evdev_fd != -1)
  fcntl(evdev_fd, F_SETFL, fcntl(evdev_fd, F_GETFL) | O_NONBLOCK);



 num_rel_axes = 0;

 if(ioctl(jsdev_fd, JSIOCGAXES, &tmp) == -1)
 {
  ErrnoHolder ene(errno);

  throw MDFN_Error(ene.Errno(), _("Failed to get number of axes: %s"), ene.StrError());
 }
 else
  num_axes = tmp;

 if(ioctl(jsdev_fd, JSIOCGBUTTONS, &tmp) == -1)
 {
  ErrnoHolder ene(errno);

  throw MDFN_Error(ene.Errno(), _("Failed to get number of buttons: %s"), ene.StrError());
 }
 else
  num_buttons = tmp;

 axis_state.resize(num_axes);
 button_state.resize(num_buttons);

 memset(name, 0, sizeof(name));
 ioctl(jsdev_fd, JSIOCGNAME(sizeof(name) - 1), name);
 if(name[0] == 0)
  snprintf(name, sizeof(name), _("%u-button, %u-axis controller"), num_buttons, num_axes);

 compat_hat_offs = ~0U;
 CalcOldStyleID(num_axes, 0, 0, num_buttons);
 if(evdev_fd != -1)
 {
#if 0
  uint8 keybits[(KEY_CNT + 7) / 8];
  unsigned ev_button_count = 0;
  
  memset(keybits, 0, sizeof(keybits));
  ioctl(evdev_fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits);

  for(unsigned kbt = 0; kbt < KEY_CNT; kbt++)
  {
   if(keybits[kbt >> 3] & (1 << (kbt & 0x7)))
   {
    ev_button_count++;
   }
  }
  printf("moo: %u\n", ev_button_count);
#endif
  uint8 absaxbits[(ABS_CNT + 7) / 8];
  unsigned ev_abs_count = 0;
  unsigned ev_hat_count = 0;

  memset(absaxbits, 0, sizeof(absaxbits));
  ioctl(evdev_fd, EVIOCGBIT(EV_ABS, sizeof(absaxbits)), absaxbits);
  for(unsigned aat = 0; aat < ABS_CNT; aat++)
  {
   if(TestEVBit(absaxbits, aat))
   {
    if(aat >= ABS_HAT0X && aat <= ABS_HAT3Y)
    {
     if(compat_hat_offs == ~0U)
      compat_hat_offs = ev_abs_count;
     ev_hat_count++;
    }
    ev_abs_count++;
   }
  }
  //printf("%u\n", compat_hat_offs);
  CalcOldStyleID(ev_abs_count - ev_hat_count, 0, ev_hat_count / 2, num_buttons);
 }
Example #28
0
EvdevDevice::EvdevDevice(const std::string& filename) :
  fd(),
  version(),
  relatives(),
  absolutes(),
  keys(),
  name(),
  device(filename)
{
  fd = open(device.c_str(), O_RDONLY | O_NONBLOCK);

  if (fd == -1)
  {
    throw std::runtime_error(filename + ": " + std::string(strerror(errno)));
  }

  if (ioctl(fd, EVIOCGVERSION, &version)) 
  {
    throw std::runtime_error("Error: EvdevDevice: Couldn't get version for " + filename);
  }

  if (1)
  { // FIXME: Some versions of linux don't have these structs, use arrays there
    struct input_id id;
    ioctl(fd, EVIOCGID, &id);
    printf("Input device ID: bus 0x%x vendor 0x%x product 0x%x version 0x%x\n",
           id.bustype, id.vendor, id.product, id.vendor);
  }

  {  // Get the human readable name
    char c_name[256] = "unknown";
    ioctl(fd, EVIOCGNAME(sizeof(c_name)), c_name);
    name = c_name;
    log_info("Name: " << name);
  }

  { // Read in how many buttons the device has
    unsigned long bit[EV_MAX][NBITS(KEY_MAX)];
    memset(bit, 0, sizeof(bit));
    ioctl(fd, EVIOCGBIT(0, EV_MAX), bit[0]);

    for (int i = 0; i < EV_MAX; i++)
    {
      if (test_bit(i, bit[0])) 
      {
        //printf("  Event type %d (%s)\n", i, events[i] ? events[i] : "?");
                                
        if (!i) continue;

        ioctl(fd, EVIOCGBIT(i, KEY_MAX), bit[i]);
        for (int j = 0; j < KEY_MAX; j++) 
        {
          if (test_bit(j, bit[i])) 
          {
            if (i == EV_KEY) 
            { 
              keys.push_back(Key(j));
            } 
            else if (i == EV_ABS)
            { 
              // FIXME: Some Linuxes don't have these struct
              struct input_absinfo absinfo;
              ioctl(fd, EVIOCGABS(j), &absinfo);
              // FIXME: we are ignoring absinfo.fuzz and
              // absinfo.flat = deadzone
              // absinfo.fuzz = values in which range can be considered the same (jitter)
              absolutes.push_back(Absolute(j, absinfo.minimum, absinfo.maximum, absinfo.value));
            }
            else if (i == EV_REL) 
            {
              relatives.push_back(Relative(j));
            }
          }
        }
      }
    }
  }
}
Example #29
0
status_t EventHub::openDeviceLocked(const char *devicePath) {
    char buffer[80];

    ALOGV("Opening device: %s", devicePath);

    int fd = open(devicePath, O_RDWR);
    if(fd < 0) {
        ALOGE("could not open %s, %s\n", devicePath, strerror(errno));
        return -1;
    }

    InputDeviceIdentifier identifier;

    // Get device name.
    if(ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
        //fprintf(stderr, "could not get device name for %s, %s\n", devicePath, strerror(errno));
    } else {
        buffer[sizeof(buffer) - 1] = '\0';
        identifier.name.setTo(buffer);
    }

    // Check to see if the device is on our excluded list
    for (size_t i = 0; i < mExcludedDevices.size(); i++) {
        const String8& item = mExcludedDevices.itemAt(i);
        if (identifier.name == item) {
            ALOGI("ignoring event id %s driver %s\n", devicePath, item.string());
            close(fd);
            return -1;
        }
    }

    // Get device driver version.
    int driverVersion;
    if(ioctl(fd, EVIOCGVERSION, &driverVersion)) {
        ALOGE("could not get driver version for %s, %s\n", devicePath, strerror(errno));
        close(fd);
        return -1;
    }

    // Get device identifier.
    struct input_id inputId;
    if(ioctl(fd, EVIOCGID, &inputId)) {
        ALOGE("could not get device input id for %s, %s\n", devicePath, strerror(errno));
        close(fd);
        return -1;
    }
    identifier.bus = inputId.bustype;
    identifier.product = inputId.product;
    identifier.vendor = inputId.vendor;
    identifier.version = inputId.version;

    // Get device physical location.
    if(ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
        //fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));
    } else {
        buffer[sizeof(buffer) - 1] = '\0';
        identifier.location.setTo(buffer);
    }

    // Get device unique id.
    if(ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
        //fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));
    } else {
        buffer[sizeof(buffer) - 1] = '\0';
        identifier.uniqueId.setTo(buffer);
    }

    // Make file descriptor non-blocking for use with poll().
    if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
        ALOGE("Error %d making device file descriptor non-blocking.", errno);
        close(fd);
        return -1;
    }

    // Allocate device.  (The device object takes ownership of the fd at this point.)
    int32_t deviceId = mNextDeviceId++;
    Device* device = new Device(fd, deviceId, String8(devicePath), identifier);

#if 0
    ALOGI("add device %d: %s\n", deviceId, devicePath);
    ALOGI("  bus:       %04x\n"
         "  vendor     %04x\n"
         "  product    %04x\n"
         "  version    %04x\n",
        identifier.bus, identifier.vendor, identifier.product, identifier.version);
    ALOGI("  name:      \"%s\"\n", identifier.name.string());
    ALOGI("  location:  \"%s\"\n", identifier.location.string());
    ALOGI("  unique id: \"%s\"\n", identifier.uniqueId.string());
    ALOGI("  driver:    v%d.%d.%d\n",
        driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff);
#endif

    // Load the configuration file for the device.
    loadConfigurationLocked(device);

    // Figure out the kinds of events the device reports.
    ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask);
    ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(device->absBitmask)), device->absBitmask);
    ioctl(fd, EVIOCGBIT(EV_REL, sizeof(device->relBitmask)), device->relBitmask);
    ioctl(fd, EVIOCGBIT(EV_SW, sizeof(device->swBitmask)), device->swBitmask);
    ioctl(fd, EVIOCGBIT(EV_LED, sizeof(device->ledBitmask)), device->ledBitmask);
    ioctl(fd, EVIOCGPROP(sizeof(device->propBitmask)), device->propBitmask);

    // See if this is a keyboard.  Ignore everything in the button range except for
    // joystick and gamepad buttons which are handled like keyboards for the most part.
    bool haveKeyboardKeys = containsNonZeroByte(device->keyBitmask, 0, sizeof_bit_array(BTN_MISC))
            || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(KEY_OK),
                    sizeof_bit_array(KEY_MAX + 1));
    bool haveGamepadButtons = containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_MISC),
                    sizeof_bit_array(BTN_MOUSE))
            || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_JOYSTICK),
                    sizeof_bit_array(BTN_DIGI));
    if (haveKeyboardKeys || haveGamepadButtons) {
        device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
    }

    // See if this is a cursor device such as a trackball or mouse.
    if (test_bit(BTN_MOUSE, device->keyBitmask)
            && test_bit(REL_X, device->relBitmask)
            && test_bit(REL_Y, device->relBitmask)) {
        device->classes |= INPUT_DEVICE_CLASS_CURSOR;
    }

    // See if this is a touch pad.
    // Is this a new modern multi-touch driver?
    if (test_bit(ABS_MT_POSITION_X, device->absBitmask)
            && test_bit(ABS_MT_POSITION_Y, device->absBitmask)) {
        // Some joysticks such as the PS3 controller report axes that conflict
        // with the ABS_MT range.  Try to confirm that the device really is
        // a touch screen.
        // Mozilla Bug 741038 - support GB touchscreen drivers
        //if (test_bit(BTN_TOUCH, device->keyBitmask) || !haveGamepadButtons) {
            device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
        //}
    // Is this an old style single-touch driver?
    } else if (test_bit(BTN_TOUCH, device->keyBitmask)
            && test_bit(ABS_X, device->absBitmask)
            && test_bit(ABS_Y, device->absBitmask)) {
        device->classes |= INPUT_DEVICE_CLASS_TOUCH;
    }

    // See if this device is a joystick.
    // Assumes that joysticks always have gamepad buttons in order to distinguish them
    // from other devices such as accelerometers that also have absolute axes.
    if (haveGamepadButtons) {
        uint32_t assumedClasses = device->classes | INPUT_DEVICE_CLASS_JOYSTICK;
        for (int i = 0; i <= ABS_MAX; i++) {
            if (test_bit(i, device->absBitmask)
                    && (getAbsAxisUsage(i, assumedClasses) & INPUT_DEVICE_CLASS_JOYSTICK)) {
                device->classes = assumedClasses;
                break;
            }
        }
    }

    // Check whether this device has switches.
    for (int i = 0; i <= SW_MAX; i++) {
        if (test_bit(i, device->swBitmask)) {
            device->classes |= INPUT_DEVICE_CLASS_SWITCH;
            break;
        }
    }

    // Configure virtual keys.
    if ((device->classes & INPUT_DEVICE_CLASS_TOUCH)) {
        // Load the virtual keys for the touch screen, if any.
        // We do this now so that we can make sure to load the keymap if necessary.
        status_t status = loadVirtualKeyMapLocked(device);
        if (!status) {
            device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
        }
    }

    // Load the key map.
    // We need to do this for joysticks too because the key layout may specify axes.
    status_t keyMapStatus = NAME_NOT_FOUND;
    if (device->classes & (INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_JOYSTICK)) {
        // Load the keymap for the device.
        keyMapStatus = loadKeyMapLocked(device);
    }

    // Configure the keyboard, gamepad or virtual keyboard.
    if (device->classes & INPUT_DEVICE_CLASS_KEYBOARD) {
        // Register the keyboard as a built-in keyboard if it is eligible.
        if (!keyMapStatus
                && mBuiltInKeyboardId == -1
                && isEligibleBuiltInKeyboard(device->identifier,
                        device->configuration, &device->keyMap)) {
            mBuiltInKeyboardId = device->id;
        }

        // 'Q' key support = cheap test of whether this is an alpha-capable kbd
        if (hasKeycodeLocked(device, AKEYCODE_Q)) {
            device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY;
        }

        // See if this device has a DPAD.
        if (hasKeycodeLocked(device, AKEYCODE_DPAD_UP) &&
                hasKeycodeLocked(device, AKEYCODE_DPAD_DOWN) &&
                hasKeycodeLocked(device, AKEYCODE_DPAD_LEFT) &&
                hasKeycodeLocked(device, AKEYCODE_DPAD_RIGHT) &&
                hasKeycodeLocked(device, AKEYCODE_DPAD_CENTER)) {
            device->classes |= INPUT_DEVICE_CLASS_DPAD;
        }

        // See if this device has a gamepad.
        for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES)/sizeof(GAMEPAD_KEYCODES[0]); i++) {
            if (hasKeycodeLocked(device, GAMEPAD_KEYCODES[i])) {
                device->classes |= INPUT_DEVICE_CLASS_GAMEPAD;
                break;
            }
        }
    }

    // If the device isn't recognized as something we handle, don't monitor it.
    if (device->classes == 0) {
        ALOGV("Dropping device: id=%d, path='%s', name='%s'",
                deviceId, devicePath, device->identifier.name.string());
        delete device;
        return -1;
    }

    // Determine whether the device is external or internal.
    if (isExternalDeviceLocked(device)) {
        device->classes |= INPUT_DEVICE_CLASS_EXTERNAL;
    }

    // Register with epoll.
    struct epoll_event eventItem;
    memset(&eventItem, 0, sizeof(eventItem));
    eventItem.events = EPOLLIN;
    eventItem.data.u32 = deviceId;
    if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {
        ALOGE("Could not add device fd to epoll instance.  errno=%d", errno);
        delete device;
        return -1;
    }

    ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
            "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s",
         deviceId, fd, devicePath, device->identifier.name.string(),
         device->classes,
         device->configurationFile.string(),
         device->keyMap.keyLayoutFile.string(),
         device->keyMap.keyCharacterMapFile.string(),
         toString(mBuiltInKeyboardId == deviceId));

    mDevices.add(deviceId, device);

    device->next = mOpeningDevices;
    mOpeningDevices = device;
    return 0;
}
Example #30
0
// Get the event types and event codes that the input device supports
static PyObject *
ioctl_capabilities(PyObject *self, PyObject *args)
{
    int fd, ev_type, ev_code;
    char ev_bits[EV_MAX/8 + 1], code_bits[KEY_MAX/8 + 1];
    struct input_absinfo absinfo;

    int ret = PyArg_ParseTuple(args, "i", &fd);
    if (!ret) return NULL;

    // @todo: figure out why fd gets zeroed on an ioctl after the
    // refactoring and get rid of this workaround
    const int _fd = fd;

    // Capabilities is a mapping of supported event types to lists of handled
    // events e.g: {1: [272, 273, 274, 275], 2: [0, 1, 6, 8]}
    PyObject* capabilities = PyDict_New();
    PyObject* eventcodes = NULL;
    PyObject* evlong = NULL;
    PyObject* capability = NULL;
    PyObject* py_absinfo = NULL;
    PyObject* absitem = NULL;

    memset(&ev_bits, 0, sizeof(ev_bits));

    if (ioctl(_fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) < 0)
        goto on_err;

    // Build a dictionary of the device's capabilities
    for (ev_type=0 ; ev_type<EV_MAX ; ev_type++) {
        if (test_bit(ev_bits, ev_type)) {

            capability = PyLong_FromLong(ev_type);
            eventcodes = PyList_New(0);

            memset(&code_bits, 0, sizeof(code_bits));
            ioctl(_fd, EVIOCGBIT(ev_type, sizeof(code_bits)), code_bits);

            for (ev_code = 0; ev_code < KEY_MAX; ev_code++) {
                if (test_bit(code_bits, ev_code)) {
                    // Get abs{min,max,fuzz,flat} values for ABS_* event codes
                    if (ev_type == EV_ABS) {
                        memset(&absinfo, 0, sizeof(absinfo));
                        ioctl(_fd, EVIOCGABS(ev_code), &absinfo);

                        py_absinfo = Py_BuildValue("(iiiiii)",
                                                   absinfo.value,
                                                   absinfo.minimum,
                                                   absinfo.maximum,
                                                   absinfo.fuzz,
                                                   absinfo.flat,
                                                   absinfo.resolution);

                        evlong = PyLong_FromLong(ev_code);
                        absitem = Py_BuildValue("(OO)", evlong, py_absinfo);

                        // absitem -> tuple(ABS_X, (0, 255, 0, 0))
                        PyList_Append(eventcodes, absitem);

                        Py_DECREF(absitem);
                        Py_DECREF(py_absinfo);
                    }
                    else {
                        evlong = PyLong_FromLong(ev_code);
                        PyList_Append(eventcodes, evlong);
                    }

                    Py_DECREF(evlong);
                }
            }
            // capabilities[EV_KEY] = [KEY_A, KEY_B, KEY_C, ...]
            // capabilities[EV_ABS] = [(ABS_X, (0, 255, 0, 0)), ...]
            PyDict_SetItem(capabilities, capability, eventcodes);

            Py_DECREF(capability);
            Py_DECREF(eventcodes);
        }
    }

    return capabilities;

    on_err:
        PyErr_SetFromErrno(PyExc_IOError);
        return NULL;
}