Пример #1
0
static int uinput_validate_absbits(struct input_dev *dev)
{
	unsigned int cnt;
	int retval = 0;

	for (cnt = 0; cnt < ABS_CNT; cnt++) {
		if (!test_bit(cnt, dev->absbit))
			continue;

		if (input_abs_get_max(dev, cnt) <= input_abs_get_min(dev, cnt)) {
			printk(KERN_DEBUG
				"%s: invalid abs[%02x] min:%d max:%d\n",
				UINPUT_NAME, cnt,
				input_abs_get_min(dev, cnt),
				input_abs_get_max(dev, cnt));
			retval = -EINVAL;
			break;
		}

		if (input_abs_get_flat(dev, cnt) >
		    input_abs_get_max(dev, cnt) - input_abs_get_min(dev, cnt)) {
			printk(KERN_DEBUG
				"%s: abs_flat #%02x out of range: %d "
				"(min:%d/max:%d)\n",
				UINPUT_NAME, cnt,
				input_abs_get_flat(dev, cnt),
				input_abs_get_min(dev, cnt),
				input_abs_get_max(dev, cnt));
			retval = -EINVAL;
			break;
		}
	}
	return retval;
}
Пример #2
0
static int uinput_setup_device(struct uinput_device *udev,
                               const char __user *buffer, size_t count)
{
    struct uinput_user_dev	*user_dev;
    struct input_dev	*dev;
    int			i;
    int			retval;

    if (count != sizeof(struct uinput_user_dev))
        return -EINVAL;

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

    dev = udev->dev;

    user_dev = memdup_user(buffer, sizeof(struct uinput_user_dev));
    if (IS_ERR(user_dev))
        return PTR_ERR(user_dev);

    udev->ff_effects_max = user_dev->ff_effects_max;

    /* Ensure name is filled in */
    if (!user_dev->name[0]) {
        retval = -EINVAL;
        goto exit;
    }

    kfree(dev->name);
    dev->name = kstrndup(user_dev->name, UINPUT_MAX_NAME_SIZE,
                         GFP_KERNEL);
    if (!dev->name) {
        retval = -ENOMEM;
        goto exit;
    }

    dev->id.bustype	= user_dev->id.bustype;
    dev->id.vendor	= user_dev->id.vendor;
    dev->id.product	= user_dev->id.product;
    dev->id.version	= user_dev->id.version;

    for (i = 0; i < ABS_CNT; i++) {
        input_abs_set_max(dev, i, user_dev->absmax[i]);
        input_abs_set_min(dev, i, user_dev->absmin[i]);
        input_abs_set_fuzz(dev, i, user_dev->absfuzz[i]);
        input_abs_set_flat(dev, i, user_dev->absflat[i]);
    }

    /* check if absmin/absmax/absfuzz/absflat are filled as
     * told in Documentation/input/input-programming.txt */
    if (test_bit(EV_ABS, dev->evbit)) {
        retval = uinput_validate_absbits(dev);
        if (retval < 0)
            goto exit;
        if (test_bit(ABS_MT_SLOT, dev->absbit)) {
            int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
            input_mt_init_slots(dev, nslot, 0);
        } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
            input_set_events_per_packet(dev, 60);
        }
    }

    udev->state = UIST_SETUP_COMPLETE;
    retval = count;

exit:
    kfree(user_dev);
    return retval;
}
Пример #3
0
/**
 * touchscreen_parse_properties - parse common touchscreen DT properties
 * @input: input device that should be parsed
 * @multitouch: specifies whether parsed properties should be applied to
 *	single-touch or multi-touch axes
 * @prop: pointer to a struct touchscreen_properties into which to store
 *	axis swap and invert info for use with touchscreen_report_x_y();
 *	or %NULL
 *
 * This function parses common DT properties for touchscreens and setups the
 * input device accordingly. The function keeps previously set up default
 * values if no value is specified via DT.
 */
void touchscreen_parse_properties(struct input_dev *input, bool multitouch,
				  struct touchscreen_properties *prop)
{
	struct device *dev = input->dev.parent;
	unsigned int axis;
	unsigned int maximum, fuzz;
	bool data_present;

	input_alloc_absinfo(input);
	if (!input->absinfo)
		return;

	axis = multitouch ? ABS_MT_POSITION_X : ABS_X;
	data_present = touchscreen_get_prop_u32(dev, "touchscreen-size-x",
						input_abs_get_max(input,
								  axis) + 1,
						&maximum) |
		       touchscreen_get_prop_u32(dev, "touchscreen-fuzz-x",
						input_abs_get_fuzz(input, axis),
						&fuzz);
	if (data_present)
		touchscreen_set_params(input, axis, maximum - 1, fuzz);

	axis = multitouch ? ABS_MT_POSITION_Y : ABS_Y;
	data_present = touchscreen_get_prop_u32(dev, "touchscreen-size-y",
						input_abs_get_max(input,
								  axis) + 1,
						&maximum) |
		       touchscreen_get_prop_u32(dev, "touchscreen-fuzz-y",
						input_abs_get_fuzz(input, axis),
						&fuzz);
	if (data_present)
		touchscreen_set_params(input, axis, maximum - 1, fuzz);

	axis = multitouch ? ABS_MT_PRESSURE : ABS_PRESSURE;
	data_present = touchscreen_get_prop_u32(dev,
						"touchscreen-max-pressure",
						input_abs_get_max(input, axis),
						&maximum) |
		       touchscreen_get_prop_u32(dev,
						"touchscreen-fuzz-pressure",
						input_abs_get_fuzz(input, axis),
						&fuzz);
	if (data_present)
		touchscreen_set_params(input, axis, maximum, fuzz);

	if (!prop)
		return;

	axis = multitouch ? ABS_MT_POSITION_X : ABS_X;

	prop->max_x = input_abs_get_max(input, axis);
	prop->max_y = input_abs_get_max(input, axis + 1);
	prop->invert_x =
		device_property_read_bool(dev, "touchscreen-inverted-x");
	prop->invert_y =
		device_property_read_bool(dev, "touchscreen-inverted-y");
	prop->swap_x_y =
		device_property_read_bool(dev, "touchscreen-swapped-x-y");

	if (prop->swap_x_y)
		swap(input->absinfo[axis], input->absinfo[axis + 1]);
}
Пример #4
0
static void hil_dev_handle_ptr_events(struct hil_dev *ptr)
{
	struct input_dev *dev = ptr->dev;
	int idx = ptr->idx4 / 4;
	hil_packet p = ptr->data[idx - 1];
	int i, cnt, laxis;
	bool absdev, ax16;

	if ((p & HIL_CMDCT_POL) != idx - 1) {
		printk(KERN_WARNING PREFIX
			"Malformed poll packet %x (idx = %i)\n", p, idx);
		return;
	}

	i = (p & HIL_POL_AXIS_ALT) ? 3 : 0;
	laxis = (p & HIL_POL_NUM_AXES_MASK) + i;

	ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */
	absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS;

	for (cnt = 1; i < laxis; i++) {
		unsigned int lo, hi, val;

		lo = ptr->data[cnt++] & HIL_PKT_DATA_MASK;
		hi = ax16 ? (ptr->data[cnt++] & HIL_PKT_DATA_MASK) : 0;

		if (absdev) {
			val = lo + (hi << 8);
#ifdef TABLET_AUTOADJUST
			if (val < input_abs_get_min(dev, ABS_X + i))
				input_abs_set_min(dev, ABS_X + i, val);
			if (val > input_abs_get_max(dev, ABS_X + i))
				input_abs_set_max(dev, ABS_X + i, val);
#endif
			if (i % 3)
				val = input_abs_get_max(dev, ABS_X + i) - val;
			input_report_abs(dev, ABS_X + i, val);
		} else {
			val = (int) (((int8_t) lo) | ((int8_t) hi << 8));
			if (i % 3)
				val *= -1;
			input_report_rel(dev, REL_X + i, val);
		}
	}

	while (cnt < idx - 1) {
		unsigned int btn = ptr->data[cnt++];
		int up = btn & 1;

		btn &= 0xfe;
		if (btn == 0x8e)
			continue; /* TODO: proximity == touch? */
		if (btn > 0x8c || btn < 0x80)
			continue;
		btn = (btn - 0x80) >> 1;
		btn = ptr->btnmap[btn];
		input_report_key(dev, btn, !up);
	}

	input_sync(dev);
}
Пример #5
0
static void hil_dev_pointer_setup(struct hil_dev *ptr)
{
	struct input_dev *input_dev = ptr->dev;
	uint8_t did = ptr->idd[0];
	uint8_t *idd = ptr->idd + 1;
	unsigned int naxsets = HIL_IDD_NUM_AXSETS(*idd);
	unsigned int i, btntype;
	const char *txt;

	ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd);

	switch (did & HIL_IDD_DID_TYPE_MASK) {
	case HIL_IDD_DID_TYPE_REL:
		input_dev->evbit[0] = BIT_MASK(EV_REL);

		for (i = 0; i < ptr->naxes; i++)
			__set_bit(REL_X + i, input_dev->relbit);

		for (i = 3; naxsets > 1 && i < ptr->naxes + 3; i++)
			__set_bit(REL_X + i, input_dev->relbit);

		txt = "relative";
		break;

	case HIL_IDD_DID_TYPE_ABS:
		input_dev->evbit[0] = BIT_MASK(EV_ABS);

		for (i = 0; i < ptr->naxes; i++)
			input_set_abs_params(input_dev, ABS_X + i,
					0, HIL_IDD_AXIS_MAX(idd, i), 0, 0);

		for (i = 3; naxsets > 1 && i < ptr->naxes + 3; i++)
			input_set_abs_params(input_dev, ABS_X + i,
					0, HIL_IDD_AXIS_MAX(idd, i - 3), 0, 0);

#ifdef TABLET_AUTOADJUST
		for (i = 0; i < ABS_MAX; i++) {
			int diff = input_abs_get_max(input_dev, ABS_X + i) / 10;
			input_abs_set_min(input_dev, ABS_X + i,
				input_abs_get_min(input_dev, ABS_X + i) + diff);
			input_abs_set_max(input_dev, ABS_X + i,
				input_abs_get_max(input_dev, ABS_X + i) - diff);
		}
#endif

		txt = "absolute";
		break;

	default:
		BUG();
	}

	ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd);
	if (ptr->nbtn)
		input_dev->evbit[0] |= BIT_MASK(EV_KEY);

	btntype = BTN_MISC;
	if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET)
#ifdef TABLET_SIMULATES_MOUSE
		btntype = BTN_TOUCH;
#else
		btntype = BTN_DIGI;
#endif
	if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN)
		btntype = BTN_TOUCH;

	if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE)
		btntype = BTN_MOUSE;

	for (i = 0; i < ptr->nbtn; i++) {
		__set_bit(btntype | i, input_dev->keybit);
		ptr->btnmap[i] = btntype | i;
	}

	if (btntype == BTN_MOUSE) {
		/* Swap buttons 2 and 3 */
		ptr->btnmap[1] = BTN_MIDDLE;
		ptr->btnmap[2] = BTN_RIGHT;
	}

	input_dev->name = strlen(ptr->rnm) ? ptr->rnm : "HIL pointer device";

	printk(KERN_INFO PREFIX
		"HIL pointer device found (did: 0x%02x, axis: %s)\n",
		did, txt);
	printk(KERN_INFO PREFIX
		"HIL pointer has %i buttons and %i sets of %i axes\n",
		ptr->nbtn, naxsets, ptr->naxes);
}
Пример #6
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;
}
Пример #7
0
static int uinput_setup_device(struct uinput_device *udev,
			       const char __user *buffer, size_t count)
{
	struct uinput_user_dev	*user_dev;
	struct input_dev	*dev;
	int			i;
	int			retval;
	size_t			size;

	size = min_t(size_t, count, sizeof(struct uinput_user_dev));

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

	dev = udev->dev;

	user_dev = kzalloc(sizeof(struct uinput_user_dev), GFP_KERNEL);
	if (!user_dev)
		return -ENOMEM;
	if (copy_from_user(user_dev, buffer, size)) {
		retval = -EFAULT;
		goto exit;
	}

	udev->ff_effects_max = user_dev->ff_effects_max;

	/* Ensure name is filled in */
	if (!user_dev->name[0]) {
		retval = -EINVAL;
		goto exit;
	}

	kfree(dev->name);
	dev->name = kstrndup(user_dev->name, UINPUT_MAX_NAME_SIZE,
			     GFP_KERNEL);
	if (!dev->name) {
		retval = -ENOMEM;
		goto exit;
	}

	dev->id.bustype	= user_dev->id.bustype;
	dev->id.vendor	= user_dev->id.vendor;
	dev->id.product	= user_dev->id.product;
	dev->id.version	= user_dev->id.version;

	for (i = 0; i < ABS_CNT; i++) {
		input_abs_set_max(dev, i, user_dev->absmax[i]);
		input_abs_set_min(dev, i, user_dev->absmin[i]);
		input_abs_set_fuzz(dev, i, user_dev->absfuzz[i]);
		input_abs_set_flat(dev, i, user_dev->absflat[i]);
		input_abs_set_res(dev, i, user_dev->absres[i]);
	}

	/* check if absmin/absmax/absfuzz/absflat are filled as
	 * told in Documentation/input/input-programming.txt */
	if (test_bit(EV_ABS, dev->evbit)) {
		retval = uinput_validate_absbits(dev);
		if (retval < 0)
			goto exit;
		if (test_bit(ABS_MT_SLOT, dev->absbit)) {
			int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
#ifdef INPUT_MT_POINTER
			input_mt_init_slots(dev, nslot, 0);
#else /* INPUT_MT_POINTER */
			input_mt_init_slots(dev, nslot);
#endif /* INPUT_MT_POINTER */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
		} else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
			input_set_events_per_packet(dev, 60);
#endif /* LINUX_VERSION_CODE >= 2.6.36 */
		}
	}

	udev->state = UIST_SETUP_COMPLETE;
	retval = count;

 exit:
	kfree(user_dev);
	return retval;
}
Пример #8
0
static int pixcir_i2c_ts_probe(struct i2c_client *client,
			       const struct i2c_device_id *id)
{
	const struct pixcir_ts_platform_data *pdata =
			dev_get_platdata(&client->dev);
	struct device *dev = &client->dev;
	struct pixcir_i2c_ts_data *tsdata;
	struct input_dev *input;
	int error;

	tsdata = devm_kzalloc(dev, sizeof(*tsdata), GFP_KERNEL);
	if (!tsdata)
		return -ENOMEM;

	if (pdata) {
		tsdata->chip = &pdata->chip;
	} else if (dev->of_node) {
		error = pixcir_parse_dt(dev, tsdata);
		if (error)
			return error;
	} else {
		dev_err(&client->dev, "platform data not defined\n");
		return -EINVAL;
	}

	if (!tsdata->chip->max_fingers) {
		dev_err(dev, "Invalid max_fingers in chip data\n");
		return -EINVAL;
	}

	input = devm_input_allocate_device(dev);
	if (!input) {
		dev_err(dev, "Failed to allocate input device\n");
		return -ENOMEM;
	}

	tsdata->client = client;
	tsdata->input = input;

	input->name = client->name;
	input->id.bustype = BUS_I2C;
	input->open = pixcir_input_open;
	input->close = pixcir_input_close;
	input->dev.parent = &client->dev;

	if (pdata) {
		input_set_abs_params(input, ABS_MT_POSITION_X, 0, pdata->x_max, 0, 0);
		input_set_abs_params(input, ABS_MT_POSITION_Y, 0, pdata->y_max, 0, 0);
	} else {
		input_set_capability(input, EV_ABS, ABS_MT_POSITION_X);
		input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y);
		touchscreen_parse_properties(input, true, &tsdata->prop);
		if (!input_abs_get_max(input, ABS_MT_POSITION_X) ||
		    !input_abs_get_max(input, ABS_MT_POSITION_Y)) {
			dev_err(dev, "Touchscreen size is not specified\n");
			return -EINVAL;
		}
	}

	tsdata->max_fingers = tsdata->chip->max_fingers;
	if (tsdata->max_fingers > PIXCIR_MAX_SLOTS) {
		tsdata->max_fingers = PIXCIR_MAX_SLOTS;
		dev_info(dev, "Limiting maximum fingers to %d\n",
			 tsdata->max_fingers);
	}

	error = input_mt_init_slots(input, tsdata->max_fingers,
				    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
	if (error) {
		dev_err(dev, "Error initializing Multi-Touch slots\n");
		return error;
	}

	input_set_drvdata(input, tsdata);

	tsdata->gpio_attb = devm_gpiod_get(dev, "attb", GPIOD_IN);
	if (IS_ERR(tsdata->gpio_attb)) {
		error = PTR_ERR(tsdata->gpio_attb);
		dev_err(dev, "Failed to request ATTB gpio: %d\n", error);
		return error;
	}

	tsdata->gpio_reset = devm_gpiod_get_optional(dev, "reset",
						     GPIOD_OUT_LOW);
	if (IS_ERR(tsdata->gpio_reset)) {
		error = PTR_ERR(tsdata->gpio_reset);
		dev_err(dev, "Failed to request RESET gpio: %d\n", error);
		return error;
	}

	tsdata->gpio_wake = devm_gpiod_get_optional(dev, "wake",
						    GPIOD_OUT_HIGH);
	if (IS_ERR(tsdata->gpio_wake)) {
		error = PTR_ERR(tsdata->gpio_wake);
		if (error != -EPROBE_DEFER)
			dev_err(dev, "Failed to get wake gpio: %d\n", error);
		return error;
	}

	tsdata->gpio_enable = devm_gpiod_get_optional(dev, "enable",
						      GPIOD_OUT_HIGH);
	if (IS_ERR(tsdata->gpio_enable)) {
		error = PTR_ERR(tsdata->gpio_enable);
		if (error != -EPROBE_DEFER)
			dev_err(dev, "Failed to get enable gpio: %d\n", error);
		return error;
	}

	if (tsdata->gpio_enable)
		msleep(100);

	error = devm_request_threaded_irq(dev, client->irq, NULL, pixcir_ts_isr,
					  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
					  client->name, tsdata);
	if (error) {
		dev_err(dev, "failed to request irq %d\n", client->irq);
		return error;
	}

	pixcir_reset(tsdata);

	/* Always be in IDLE mode to save power, device supports auto wake */
	error = pixcir_set_power_mode(tsdata, PIXCIR_POWER_IDLE);
	if (error) {
		dev_err(dev, "Failed to set IDLE mode\n");
		return error;
	}

	/* Stop device till opened */
	error = pixcir_stop(tsdata);
	if (error)
		return error;

	error = input_register_device(input);
	if (error)
		return error;

	i2c_set_clientdata(client, tsdata);

	return 0;
}
Пример #9
0
void genode_evdev_event(struct input_handle *handle, unsigned int type,
                        unsigned int code, int value)
{
#if DEBUG_EVDEV
	static unsigned long count = 0;
#endif

	static int last_ax = -1; /* store the last absolute x value */
	  
	/* filter sound events */
	if (test_bit(EV_SND, handle->dev->evbit)) return;

	/* filter input_repeat_key() */
	if ((type == EV_KEY) && (value == 2)) return;

	/* filter EV_SYN */
	if (type == EV_SYN) return;

	/* generate arguments and call back */
	enum input_event_type arg_type;
	unsigned arg_keycode = KEY_UNKNOWN;
	int arg_ax = 0, arg_ay = 0, arg_rx = 0, arg_ry = 0;

	switch (type) {

	case EV_KEY:
		arg_keycode = code;

		/* map BTN_TOUCH events to BTN_LEFT */
		if (code == BTN_TOUCH)
			arg_keycode = BTN_LEFT;

		switch (value) {

		case 0:
			arg_type = EVENT_TYPE_RELEASE;
			break;

		case 1:
			arg_type = EVENT_TYPE_PRESS;
			break;

		default:
			printk("Unknown key event value %d - not handled\n", value);
			return;
		}
		break;

	case EV_ABS:
		switch (code) {

		case ABS_X:
		case ABS_MT_POSITION_X:

			/*
			 * Don't create an input event yet. Store the value and wait for the
			 * subsequent Y event.
			 */
			last_ax = value;
			return;

		case ABS_Y:
		case ABS_MT_POSITION_Y:

			/*
			 * Create a unified input event with absolute positions on x and y
			 * axis.
			 */
			arg_type = EVENT_TYPE_MOTION;
			arg_ax = last_ax;
			arg_ay = value;

			/* transform if requested */
			if (screen_x && screen_y) {
				int const min_x_dev  = input_abs_get_min(handle->dev, ABS_X);
				int const min_y_dev  = input_abs_get_min(handle->dev, ABS_Y);
				int const max_x_dev  = input_abs_get_max(handle->dev, ABS_X);
				int const max_y_dev  = input_abs_get_max(handle->dev, ABS_Y);
				int const max_y_norm = max_y_dev - min_y_dev;
				int const max_x_norm = max_x_dev - min_x_dev;

				if ((max_x_norm == 0)     || (max_y_norm == 0)   ||
				    (last_ax < min_x_dev) || (value < min_y_dev) ||
				    (last_ax > max_x_dev) || (value > max_y_dev))
				{
					printk("Ignore input source with coordinates out of range\n");
					return;
				}

				arg_ax = screen_x * (last_ax - min_x_dev) / (max_x_norm);
				arg_ay = screen_y * (value   - min_y_dev) / (max_y_norm);
			}

			last_ax = -1;
			if (arg_ax == -1) {
				printk("Ignore absolute Y event without a preceeding X event\n");
				return;
			}
			break;

		case ABS_WHEEL:

			/*
			 * XXX I do not know, how to handle this correctly. At least, this
			 * scheme works on Qemu.
			 */
			arg_type = EVENT_TYPE_WHEEL;
			arg_ry = value;
			break;

		default:
			printk("Unknown absolute event code %d - not handled\n", code);
			return;
		}
		break;

	case EV_REL:
		switch (code) {

		case REL_X:
			arg_type = EVENT_TYPE_MOTION;
			arg_rx = value;
			break;

		case REL_Y:
			arg_type = EVENT_TYPE_MOTION;
			arg_ry = value;
			break;

		case REL_HWHEEL:
			arg_type = EVENT_TYPE_WHEEL;
			arg_rx = value;
			break;

		case REL_WHEEL:
			arg_type = EVENT_TYPE_WHEEL;
			arg_ry = value;
			break;

		default:
			printk("Unknown relative event code %d - not handled\n", code);
			return;
		}
		break;

	default:
		printk("Unknown event type %d - not handled\n", type);
		return;
	}

	if (handler)
		handler(arg_type, arg_keycode, arg_ax, arg_ay, arg_rx, arg_ry);

#if DEBUG_EVDEV
	printk("event[%ld]. dev: %s, type: %d, code: %d, value: %d a=%d,%d "
	       "r=%d,%d\n", count++, handle->dev->name, type, code, value, arg_ax,
	       arg_ay, arg_rx, arg_ry);
#endif
}
Пример #10
0
static int uinput_setup_device(struct uinput_device *udev, const char __user *buffer, size_t count)
{
	struct uinput_user_dev	*user_dev;
	struct input_dev	*dev;
	char			*name;
	int			size;
	int			retval;

	if (count != sizeof(struct uinput_user_dev))
		return -EINVAL;

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

	dev = udev->dev;

	user_dev = kmalloc(sizeof(struct uinput_user_dev), GFP_KERNEL);
	if (!user_dev)
		return -ENOMEM;

	if (copy_from_user(user_dev, buffer, sizeof(struct uinput_user_dev))) {
		retval = -EFAULT;
		goto exit;
	}

	udev->ff_effects_max = user_dev->ff_effects_max;

	size = strnlen(user_dev->name, UINPUT_MAX_NAME_SIZE) + 1;
	if (!size) {
		retval = -EINVAL;
		goto exit;
	}

	kfree(dev->name);
	dev->name = name = kmalloc(size, GFP_KERNEL);
	if (!name) {
		retval = -ENOMEM;
		goto exit;
	}
	strlcpy(name, user_dev->name, size);

	dev->id.bustype	= user_dev->id.bustype;
	dev->id.vendor	= user_dev->id.vendor;
	dev->id.product	= user_dev->id.product;
	dev->id.version	= user_dev->id.version;

	size = sizeof(int) * (ABS_MAX + 1);
	memcpy(dev->absmax, user_dev->absmax, size);
	memcpy(dev->absmin, user_dev->absmin, size);
	memcpy(dev->absfuzz, user_dev->absfuzz, size);
	memcpy(dev->absflat, user_dev->absflat, size);

	/* check if absmin/absmax/absfuzz/absflat are filled as
	 * told in Documentation/input/input-programming.txt */
	if (test_bit(EV_ABS, dev->evbit)) {
		retval = uinput_validate_absbits(dev);
		if (retval < 0)
			goto exit;
		if (test_bit(ABS_MT_SLOT, dev->absbit)) {
			int nslot = input_abs_get_max(dev, ABS_MT_SLOT) + 1;
			input_mt_init_slots(dev, nslot, 0);
		}
	}

	udev->state = UIST_SETUP_COMPLETE;
	retval = count;

 exit:
	kfree(user_dev);
	return retval;
}