
PSMOUSE_DEFINE_ATTR(mb_scroll);
PSMOUSE_DEFINE_ATTR(scroll_delay);

/* MAKE_ATTR_WRITE( ) for Middle Button Scroll mode */
static ssize_t psmouse_attr_set_mb_scroll(struct psmouse *psmouse, const char *buf, size_t count)
{
        struct trackpoint_data *tp = psmouse->private;

	tp->mb_scroll = (buf[0] == '1') ? 1 : 0;

        return count;
}

MAKE_ATTR_READ(mb_scroll);

/* MAKE_ATTR_WRITE( ) for delay before scroll */
static ssize_t psmouse_attr_set_scroll_delay(struct psmouse *psmouse, const char *buf, size_t count)
{
	char *rest;
	unsigned long value;

        struct trackpoint_data *tp = psmouse->private;

        value = simple_strtoul(buf, &rest, 10);
	if(*rest)
		return -EINVAL;

	tp->scroll_delay = value;

        return count;
}

MAKE_ATTR_READ(scroll_delay);


void trackpoint_sim_scroll(struct psmouse *psmouse)
{
	int diff;
	struct trackpoint_data *tp = psmouse->private;
	unsigned char *packet = psmouse->packet;

	if(!tp->mb_scroll)
		return;

	if( ((packet[0] >> 2) & 1) == 0 ) {

		if(tp->mb_was_down &&
		   time_after(tp->last_mb_press + msecs_to_jiffies(tp->scroll_delay), jiffies)) {

			input_report_key(&psmouse->dev, BTN_MIDDLE, 1);

			input_sync(&psmouse->dev);
		}

		tp->scrolling = 0;
		tp->mb_was_down = 0;
	} else if(tp->scrolling) {

		/* Vertical scrolling */
		diff = (int) ((packet[0] << 3) & 0x100) - (int) packet[2];
                if( diff < -2 ) {
			input_report_rel(&psmouse->dev, REL_WHEEL, 1);
		} else if(diff > 2) {
			input_report_rel(&psmouse->dev, REL_WHEEL, -1);
		}

		/* Horizontal scrolling */
		diff = (int) packet[1] - (int) ((packet[0] << 4) & 0x100);
		if( diff < -2) {
				input_report_rel(&psmouse->dev, REL_HWHEEL, 1);
		} else if( diff > 2) {
				input_report_rel(&psmouse->dev, REL_HWHEEL, -1);
		}

		packet[1] &= 0x00;
		packet[2] &= 0x00;
	} else {
                /* Middle button is down, but we aren't scrolling */
                if( time_after_eq(jiffies, tp->last_mb_press + msecs_to_jiffies(tp->scroll_delay)) )
                        tp->scrolling = 1;

                tp->last_mb_press = jiffies;
                tp->mb_was_down = 1;
	}

	/* Suppress the key event from entering the queue */
	packet[0] &= 0xFB;
}


	tp->mb_scroll = TP_DEF_MB_SCROLL;

	tp->scroll_delay = TP_DEF_SCROLL_DELAY;

	tp->scrolling = tp->mb_was_down = 0;
	tp->xacc = tp->yacc = 0;
}



	device_remove_file(&serio->dev, &psmouse_attr_mb_scroll);
	device_remove_file(&serio->dev, &psmouse_attr_scroll_delay);


	/* Used to simulate wheel scrolling */
	set_bit(REL_HWHEEL, psmouse->dev.relbit);
	set_bit(REL_WHEEL, psmouse->dev.relbit);

	psmouse->model = PSMOUSE_TRACKPOINT;



	device_create_file(&serio->dev, &psmouse_attr_mb_scroll);
	device_create_file(&serio->dev, &psmouse_attr_scroll_delay);
