コード例 #1
0
static void secvib_enable(struct timed_output_dev *dev, int value)
{
	struct secvib_data	*secvib =
		container_of(dev, struct secvib_data, dev);

	pr_debug("secvib: vibrator force:%d\n", value);
	mutex_lock(&secvib->lock);

	/* cancel previous timer and set GPIO according to value */
	hrtimer_cancel(&secvib->timer);

	if (value) {
		secvib_vibrator_enable(secvib, 0, 1);

		if (value > 0) {
			if (value > secvib->max_timeout)
				value = secvib->max_timeout;

			hrtimer_start(&secvib->timer,
					ktime_set(value / 1000,
					(value % 1000) * 1000000),
					HRTIMER_MODE_REL);
		}

	} else
		secvib_vibrator_enable(secvib, 0, 0);
	mutex_unlock(&secvib->lock);
}
コード例 #2
0
static int secvib_forceout_set_samples(struct secvib_data *secvib,
		u_int8_t actr_index,
		u_int16_t bit_depth,
		u_int16_t bufsize,
		int8_t *buf)
{
	int8_t vib_force;
	static int8_t pre_vib_force;

	switch (bit_depth) {
	case 8:
		/* buf is expected to contain 1 byte */
		if (bufsize != 1) {
			pr_err("secvib: wrong  bufsize =  %d\n", bufsize);
			goto error_vibe;
		}
		vib_force = buf[0];
		break;

	case 16:
		/* buf is expected to contain 2 byte */
		if (bufsize != 2)
			goto error_vibe;

		/* Map 16-bit value to 8-bit */
		vib_force = ((int16_t *)buf)[0] >> 8;
		break;

	default:
		/* Unexpected bit depth */
		goto error_vibe;
	}

	if (vib_force == 0)
		/* Set 50% duty cycle or disable amp */
		secvib_vibrator_enable(secvib, actr_index, 0);
	else if (pre_vib_force != vib_force) {
		secvib->pdata->pwm_set(actr_index, vib_force);
		secvib_vibrator_enable(secvib, actr_index, 1);
	}

	pre_vib_force = vib_force;

	return 0;

error_vibe:
	return -1;

}
コード例 #3
0
static void secvib_timer_worker(struct work_struct *work)
{
	struct secvib_data *secvib =
		container_of(work, struct secvib_data, vib_work);

	secvib_vibrator_enable(secvib, 0, 0);
}
static enum hrtimer_restart secvib_timer_func(struct hrtimer *timer)
{
    struct secvib_data *secvib =
        container_of(timer, struct secvib_data, timer);

    secvib_vibrator_enable(secvib, 0, 0);
    return HRTIMER_NORESTART;
}
コード例 #5
0
/* ioctl - I/O control */
static long secvib_ioctl(struct file *file,
		unsigned int cmd, unsigned long arg)
{

	int ret;
	struct secvib_data *secvib =
		container_of(file->private_data, struct secvib_data, miscdev);

	pr_debug("secvib: %s[%d]\n", __func__, __LINE__);
	mutex_lock(&secvib->lock);

	switch (cmd) {
	case TSPDRV_STOP_KERNEL_TIMER:
		/*
		 * As we send one sample ahead of time, we need
		 *  to finish playing the last sample
		 *  before stopping the timer. So we just set a flag here.
		 */
		if (secvib->enabled == true)
			secvib->stop_requested = true;

		/* Last data processing to disable amp and stop timer */
		ret = secvib_process_vib_data(secvib);

		break;

	case TSPDRV_MAGIC_NUMBER:
		secvib->magic_no = TSPDRV_MAGIC_NUMBER;
		ret = 0;
		break;

	case TSPDRV_ENABLE_AMP:
		ret = secvib_vibrator_enable(secvib, arg, 1);
		pr_debug("secvib: vibrator enabled\n");
		break;

	case TSPDRV_DISABLE_AMP:
		/*
		 * Small fix for now to handle proper combination
		 * of TSPDRV_STOP_KERNEL_TIMER and
		 * TSPDRV_DISABLE_AMP together
		 * If a stop was requested, ignore the request as
		 * the amp will be disabled by the timer
		 * proc when it's ready
		 */
		if (!secvib->stop_requested)
			ret = secvib_vibrator_enable(secvib, arg, 0);
		else
			ret = 0;
		break;

	case TSPDRV_GET_NUM_ACTUATORS:
		ret = secvib->pdata->num_actuators;
		break;

	default:
		ret = -EINVAL;
		break;
	}

	mutex_unlock(&secvib->lock);

	return ret;
}
コード例 #6
0
static int secvib_process_vib_data(struct secvib_data *secvib)
{
	int ret, i;
	int actr_not_playing = 0;

	for (i = 0; i < secvib->pdata->num_actuators; i++) {

		struct actuator_samples_buffer *tmp = &(secvib->actr_buf[i]);

		if (tmp->playingbuf_idx == -1) {

			actr_not_playing++;

			if ((secvib->pdata->num_actuators == actr_not_playing)
				&& ((++secvib->wtchdg_cnt)
					> WATCHDOG_TIMEOUT)) {

				int8_t zero[1] = {0};

				/*
				 * Nothing to play for all actuators, turn off
				 * the timer when we reach the watchdog tick
				 * count limit
				 */
				secvib_forceout_set_samples(secvib,
						i, 8, 1, zero);
				secvib_vibrator_enable(secvib, i, 0);
				secvib_stop_haptic_timer(secvib);

				/* Reset watchdog counter */
				secvib->wtchdg_cnt = 0;
			}
		} else {
			int8_t idx = (int)tmp->playingbuf_idx;

			/* Play the current buffer */
			ret = secvib_forceout_set_samples(
					secvib,
					tmp->samples_buf[idx].actr_index,
					tmp->samples_buf[idx].bit_depth,
					tmp->samples_buf[idx].bufsize,
					tmp->samples_buf[idx].buf);
			if (unlikely(ret < 0))
				hrtimer_forward_now(&secvib->haptic_timer,
						ktime_set(0, 5000000));

			tmp->outputval_idx += tmp->samples_buf[idx].bufsize;

			if (tmp->outputval_idx
					>= tmp->samples_buf[idx].bufsize) {
				/* Reach the end of the current buffer */
				tmp->samples_buf[idx].bufsize = 0;

				/* Switch buffer */
				tmp->playingbuf_idx ^= 1;
				tmp->outputval_idx = 0;

				/* Finished playing, disable amp for actuator */
				if (secvib->stop_requested) {
					tmp->playingbuf_idx = -1;
					secvib_vibrator_enable(secvib, i, 0);
				}
			}
		}
	}

	/* If finished playing, stop timer */
	if (secvib->stop_requested) {
		secvib_stop_haptic_timer(secvib);

		/* Reset watchdog counter */
		secvib->wtchdg_cnt = 0;

		if (secvib_is_vib_sem(&secvib->vib_sem))
			up(&secvib->vib_sem);
		/* tell the caller this is the last iteration */
		return 1;
	}

	return 0;

}