Ejemplo n.º 1
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);
}
Ejemplo n.º 2
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) {
		
		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);
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
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
}