示例#1
0
/**
 * ir_rc6_decode() - Decode one RC6 pulse or space
 * @dev:	the struct rc_dev descriptor of the device
 * @ev:		the struct ir_raw_event descriptor of the pulse/space
 *
 * This function returns -EINVAL if the pulse violates the state machine
 */
static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev)
{
	struct rc6_dec *data = &dev->raw->rc6;
	u32 scancode;
	u8 toggle;
	enum rc_proto protocol;

	if (!is_timing_event(ev)) {
		if (ev.reset)
			data->state = STATE_INACTIVE;
		return 0;
	}

	if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
		goto out;

again:
	IR_dprintk(2, "RC6 decode started at state %i (%uus %s)\n",
		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));

	if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
		return 0;

	switch (data->state) {

	case STATE_INACTIVE:
		if (!ev.pulse)
			break;

		/* Note: larger margin on first pulse since each RC6_UNIT
		   is quite short and some hardware takes some time to
		   adjust to the signal */
		if (!eq_margin(ev.duration, RC6_PREFIX_PULSE, RC6_UNIT))
			break;

		data->state = STATE_PREFIX_SPACE;
		data->count = 0;
		return 0;

	case STATE_PREFIX_SPACE:
		if (ev.pulse)
			break;

		if (!eq_margin(ev.duration, RC6_PREFIX_SPACE, RC6_UNIT / 2))
			break;

		data->state = STATE_HEADER_BIT_START;
		data->header = 0;
		return 0;

	case STATE_HEADER_BIT_START:
		if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
			break;

		data->header <<= 1;
		if (ev.pulse)
			data->header |= 1;
		data->count++;
		data->state = STATE_HEADER_BIT_END;
		return 0;

	case STATE_HEADER_BIT_END:
		if (!is_transition(&ev, &dev->raw->prev_ev))
			break;

		if (data->count == RC6_HEADER_NBITS)
			data->state = STATE_TOGGLE_START;
		else
			data->state = STATE_HEADER_BIT_START;

		decrease_duration(&ev, RC6_BIT_END);
		goto again;

	case STATE_TOGGLE_START:
		if (!eq_margin(ev.duration, RC6_TOGGLE_START, RC6_UNIT / 2))
			break;

		data->toggle = ev.pulse;
		data->state = STATE_TOGGLE_END;
		return 0;

	case STATE_TOGGLE_END:
		if (!is_transition(&ev, &dev->raw->prev_ev) ||
		    !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2))
			break;

		if (!(data->header & RC6_STARTBIT_MASK)) {
			IR_dprintk(1, "RC6 invalid start bit\n");
			break;
		}

		data->state = STATE_BODY_BIT_START;
		decrease_duration(&ev, RC6_TOGGLE_END);
		data->count = 0;
		data->body = 0;

		switch (rc6_mode(data)) {
		case RC6_MODE_0:
			data->wanted_bits = RC6_0_NBITS;
			break;
		case RC6_MODE_6A:
			data->wanted_bits = RC6_6A_NBITS;
			break;
		default:
			IR_dprintk(1, "RC6 unknown mode\n");
			goto out;
		}
		goto again;

	case STATE_BODY_BIT_START:
		if (eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) {
			/* Discard LSB's that won't fit in data->body */
			if (data->count++ < CHAR_BIT * sizeof data->body) {
				data->body <<= 1;
				if (ev.pulse)
					data->body |= 1;
			}
			data->state = STATE_BODY_BIT_END;
			return 0;
		} else if (RC6_MODE_6A == rc6_mode(data) && !ev.pulse &&
				geq_margin(ev.duration, RC6_SUFFIX_SPACE, RC6_UNIT / 2)) {
			data->state = STATE_FINISHED;
			goto again;
		}
		break;

	case STATE_BODY_BIT_END:
		if (!is_transition(&ev, &dev->raw->prev_ev))
			break;

		if (data->count == data->wanted_bits)
			data->state = STATE_FINISHED;
		else
			data->state = STATE_BODY_BIT_START;

		decrease_duration(&ev, RC6_BIT_END);
		goto again;

	case STATE_FINISHED:
		if (ev.pulse)
			break;

		switch (rc6_mode(data)) {
		case RC6_MODE_0:
			scancode = data->body;
			toggle = data->toggle;
			protocol = RC_PROTO_RC6_0;
			IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n",
				   scancode, toggle);
			break;

		case RC6_MODE_6A:
			if (data->count > CHAR_BIT * sizeof data->body) {
				IR_dprintk(1, "RC6 too many (%u) data bits\n",
					data->count);
				goto out;
			}

			scancode = data->body;
			switch (data->count) {
			case 20:
				protocol = RC_PROTO_RC6_6A_20;
				toggle = 0;
				break;
			case 24:
				protocol = RC_PROTO_RC6_6A_24;
				toggle = 0;
				break;
			case 32:
				if ((scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) {
					protocol = RC_PROTO_RC6_MCE;
					toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK);
					scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
				} else {
					protocol = RC_PROTO_RC6_6A_32;
					toggle = 0;
				}
				break;
			default:
				IR_dprintk(1, "RC6(6A) unsupported length\n");
				goto out;
			}

			IR_dprintk(1, "RC6(6A) proto 0x%04x, scancode 0x%08x (toggle: %u)\n",
				   protocol, scancode, toggle);
			break;
		default:
			IR_dprintk(1, "RC6 unknown mode\n");
			goto out;
		}

		rc_keydown(dev, protocol, scancode, toggle);
		data->state = STATE_INACTIVE;
		return 0;
	}

out:
	IR_dprintk(1, "RC6 decode failed at state %i (%uus %s)\n",
		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
	data->state = STATE_INACTIVE;
	return -EINVAL;
}
示例#2
0
    /**
     * ir_rc6_decode() - Decode one RC6 pulse or space
     * @input_dev:	the struct input_dev descriptor of the device
     * @ev:		the struct ir_raw_event descriptor of the pulse/space
     *
     * This function returns -EINVAL if the pulse violates the state machine
     */
    static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
{
    struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
    struct rc6_dec *data = &ir_dev->raw->rc6;
    u32 scancode;
    u8 toggle;

    if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6))
        return 0;

    if (IS_RESET(ev)) {
        data->state = STATE_INACTIVE;
        return 0;
    }

    if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
        goto out;

again:
    IR_dprintk(2, "RC6 decode started at state %i (%uus %s)\n",
               data->state, TO_US(ev.duration), TO_STR(ev.pulse));

    if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
        return 0;

    switch (data->state) {

    case STATE_INACTIVE:
        if (!ev.pulse)
            break;

        /* Note: larger margin on first pulse since each RC6_UNIT
           is quite short and some hardware takes some time to
           adjust to the signal */
        if (!eq_margin(ev.duration, RC6_PREFIX_PULSE, RC6_UNIT))
            break;

        data->state = STATE_PREFIX_SPACE;
        data->count = 0;
        return 0;

    case STATE_PREFIX_SPACE:
        if (ev.pulse)
            break;

        if (!eq_margin(ev.duration, RC6_PREFIX_SPACE, RC6_UNIT / 2))
            break;

        data->state = STATE_HEADER_BIT_START;
        return 0;

    case STATE_HEADER_BIT_START:
        if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
            break;

        data->header <<= 1;
        if (ev.pulse)
            data->header |= 1;
        data->count++;
        data->state = STATE_HEADER_BIT_END;
        return 0;

    case STATE_HEADER_BIT_END:
        if (!is_transition(&ev, &ir_dev->raw->prev_ev))
            break;

        if (data->count == RC6_HEADER_NBITS)
            data->state = STATE_TOGGLE_START;
        else
            data->state = STATE_HEADER_BIT_START;

        decrease_duration(&ev, RC6_BIT_END);
        goto again;

    case STATE_TOGGLE_START:
        if (!eq_margin(ev.duration, RC6_TOGGLE_START, RC6_UNIT / 2))
            break;

        data->toggle = ev.pulse;
        data->state = STATE_TOGGLE_END;
        return 0;

    case STATE_TOGGLE_END:
        if (!is_transition(&ev, &ir_dev->raw->prev_ev) ||
                !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2))
            break;

        if (!(data->header & RC6_STARTBIT_MASK)) {
            IR_dprintk(1, "RC6 invalid start bit\n");
            break;
        }

        data->state = STATE_BODY_BIT_START;
        decrease_duration(&ev, RC6_TOGGLE_END);
        data->count = 0;

        switch (rc6_mode(data)) {
        case RC6_MODE_0:
            data->wanted_bits = RC6_0_NBITS;
            break;
        case RC6_MODE_6A:
            /* This might look weird, but we basically
               check the value of the first body bit to
               determine the number of bits in mode 6A */
            if ((!ev.pulse && !geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) ||
                    geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
                data->wanted_bits = RC6_6A_LARGE_NBITS;
            else
                data->wanted_bits = RC6_6A_SMALL_NBITS;
            break;
        default:
            IR_dprintk(1, "RC6 unknown mode\n");
            goto out;
        }
        goto again;

    case STATE_BODY_BIT_START:
        if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
            break;

        data->body <<= 1;
        if (ev.pulse)
            data->body |= 1;
        data->count++;
        data->state = STATE_BODY_BIT_END;
        return 0;

    case STATE_BODY_BIT_END:
        if (!is_transition(&ev, &ir_dev->raw->prev_ev))
            break;

        if (data->count == data->wanted_bits)
            data->state = STATE_FINISHED;
        else
            data->state = STATE_BODY_BIT_START;

        decrease_duration(&ev, RC6_BIT_END);
        goto again;

    case STATE_FINISHED:
        if (ev.pulse)
            break;

        switch (rc6_mode(data)) {
        case RC6_MODE_0:
            scancode = data->body & 0xffff;
            toggle = data->toggle;
            IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n",
                       scancode, toggle);
            break;
        case RC6_MODE_6A:
            if (data->wanted_bits == RC6_6A_LARGE_NBITS) {
                toggle = data->body & RC6_6A_MCE_TOGGLE_MASK ? 1 : 0;
                scancode = data->body & ~RC6_6A_MCE_TOGGLE_MASK;
            } else {
                toggle = 0;
                scancode = data->body & 0xffffff;
            }

            IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n",
                       scancode, toggle);
            break;
        default:
            IR_dprintk(1, "RC6 unknown mode\n");
            goto out;
        }

        ir_keydown(input_dev, scancode, toggle);
        data->state = STATE_INACTIVE;
        return 0;
    }

out:
    IR_dprintk(1, "RC6 decode failed at state %i (%uus %s)\n",
               data->state, TO_US(ev.duration), TO_STR(ev.pulse));
    data->state = STATE_INACTIVE;
    return -EINVAL;
}
示例#3
0
/**
 * ir_rc5_decode() - Decode one RC-5 pulse or space
 * @dev:	the struct rc_dev descriptor of the device
 * @ev:		the struct ir_raw_event descriptor of the pulse/space
 *
 * This function returns -EINVAL if the pulse violates the state machine
 */
static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)
{
	struct rc5_dec *data = &dev->raw->rc5;
	u8 toggle;
	u32 scancode;

        if (!(dev->raw->enabled_protocols & RC_TYPE_RC5))
                return 0;

	if (!is_timing_event(ev)) {
		if (ev.reset)
			data->state = STATE_INACTIVE;
		return 0;
	}

	if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
		goto out;

again:
	IR_dprintk(2, "RC5(x) decode started at state %i (%uus %s)\n",
		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));

	if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
		return 0;

	switch (data->state) {

	case STATE_INACTIVE:
		if (!ev.pulse)
			break;

		data->state = STATE_BIT_START;
		data->count = 1;
		/* We just need enough bits to get to STATE_CHECK_RC5X */
		data->wanted_bits = RC5X_NBITS;
		decrease_duration(&ev, RC5_BIT_START);
		goto again;

	case STATE_BIT_START:
		if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
			break;

		data->bits <<= 1;
		if (!ev.pulse)
			data->bits |= 1;
		data->count++;
		data->state = STATE_BIT_END;
		return 0;

	case STATE_BIT_END:
		if (!is_transition(&ev, &dev->raw->prev_ev))
			break;

		if (data->count == data->wanted_bits)
			data->state = STATE_FINISHED;
		else if (data->count == CHECK_RC5X_NBITS)
			data->state = STATE_CHECK_RC5X;
		else
			data->state = STATE_BIT_START;

		decrease_duration(&ev, RC5_BIT_END);
		goto again;

	case STATE_CHECK_RC5X:
		if (!ev.pulse && geq_margin(ev.duration, RC5X_SPACE, RC5_UNIT / 2)) {
			/* RC5X */
			data->wanted_bits = RC5X_NBITS;
			decrease_duration(&ev, RC5X_SPACE);
		} else {
			/* RC5 */
			data->wanted_bits = RC5_NBITS;
		}
		data->state = STATE_BIT_START;
		goto again;

	case STATE_FINISHED:
		if (ev.pulse)
			break;

		if (data->wanted_bits == RC5X_NBITS) {
			/* RC5X */
			u8 xdata, command, system;
			xdata    = (data->bits & 0x0003F) >> 0;
			command  = (data->bits & 0x00FC0) >> 6;
			system   = (data->bits & 0x1F000) >> 12;
			toggle   = (data->bits & 0x20000) ? 1 : 0;
			command += (data->bits & 0x01000) ? 0 : 0x40;
			scancode = system << 16 | command << 8 | xdata;

			IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n",
				   scancode, toggle);

		} else {
示例#4
0
/**
 * ir_sony_decode() - Decode one Sony pulse or space
 * @input_dev:	the struct input_dev descriptor of the device
 * @ev:         the struct ir_raw_event descriptor of the pulse/space
 *
 * This function returns -EINVAL if the pulse violates the state machine
 */
static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
{
	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
	struct sony_dec *data = &ir_dev->raw->sony;
	u32 scancode;
	u8 device, subdevice, function;

	if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY))
		return 0;

	if (IS_RESET(ev)) {
		data->state = STATE_INACTIVE;
		return 0;
	}

	if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2))
		goto out;

	IR_dprintk(2, "Sony decode started at state %d (%uus %s)\n",
		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));

	switch (data->state) {

	case STATE_INACTIVE:
		if (!ev.pulse)
			break;

		if (!eq_margin(ev.duration, SONY_HEADER_PULSE, SONY_UNIT / 2))
			break;

		data->count = 0;
		data->state = STATE_HEADER_SPACE;
		return 0;

	case STATE_HEADER_SPACE:
		if (ev.pulse)
			break;

		if (!eq_margin(ev.duration, SONY_HEADER_SPACE, SONY_UNIT / 2))
			break;

		data->state = STATE_BIT_PULSE;
		return 0;

	case STATE_BIT_PULSE:
		if (!ev.pulse)
			break;

		data->bits <<= 1;
		if (eq_margin(ev.duration, SONY_BIT_1_PULSE, SONY_UNIT / 2))
			data->bits |= 1;
		else if (!eq_margin(ev.duration, SONY_BIT_0_PULSE, SONY_UNIT / 2))
			break;

		data->count++;
		data->state = STATE_BIT_SPACE;
		return 0;

	case STATE_BIT_SPACE:
		if (ev.pulse)
			break;

		if (!geq_margin(ev.duration, SONY_BIT_SPACE, SONY_UNIT / 2))
			break;

		decrease_duration(&ev, SONY_BIT_SPACE);

		if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2)) {
			data->state = STATE_BIT_PULSE;
			return 0;
		}

		data->state = STATE_FINISHED;
		/* Fall through */

	case STATE_FINISHED:
		if (ev.pulse)
			break;

		if (!geq_margin(ev.duration, SONY_TRAILER_SPACE, SONY_UNIT / 2))
			break;

		switch (data->count) {
		case 12:
			device    = bitrev8((data->bits <<  3) & 0xF8);
			subdevice = 0;
			function  = bitrev8((data->bits >>  4) & 0xFE);
			break;
		case 15:
			device    = bitrev8((data->bits >>  0) & 0xFF);
			subdevice = 0;
			function  = bitrev8((data->bits >>  7) & 0xFD);
			break;
		case 20:
			device    = bitrev8((data->bits >>  5) & 0xF8);
			subdevice = bitrev8((data->bits >>  0) & 0xFF);
			function  = bitrev8((data->bits >> 12) & 0xFE);
			break;
		default:
			IR_dprintk(1, "Sony invalid bitcount %u\n", data->count);
			goto out;
		}

		scancode = device << 16 | subdevice << 8 | function;
		IR_dprintk(1, "Sony(%u) scancode 0x%05x\n", data->count, scancode);
		ir_keydown(input_dev, scancode, 0);
		data->state = STATE_INACTIVE;
		return 0;
	}

out:
	IR_dprintk(1, "Sony decode failed at state %d (%uus %s)\n",
		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
	data->state = STATE_INACTIVE;
	return -EINVAL;
}
示例#5
0
/**
 * ir_rc5_decode() - Decode one RC-5 pulse or space
 * @dev:	the struct rc_dev descriptor of the device
 * @ev:		the struct ir_raw_event descriptor of the pulse/space
 *
 * This function returns -EINVAL if the pulse violates the state machine
 */
static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)
{
	struct rc5_dec *data = &dev->raw->rc5;
	u8 toggle;
	u32 scancode;
	enum rc_type protocol;

	if (!is_timing_event(ev)) {
		if (ev.reset)
			data->state = STATE_INACTIVE;
		return 0;
	}

	if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
		goto out;

again:
	IR_dprintk(2, "RC5(x/sz) decode started at state %i (%uus %s)\n",
		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));

	if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
		return 0;

	switch (data->state) {

	case STATE_INACTIVE:
		if (!ev.pulse)
			break;

		data->state = STATE_BIT_START;
		data->count = 1;
		decrease_duration(&ev, RC5_BIT_START);
		goto again;

	case STATE_BIT_START:
		if (!ev.pulse && geq_margin(ev.duration, RC5_TRAILER, RC5_UNIT / 2)) {
			data->state = STATE_FINISHED;
			goto again;
		}

		if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
			break;

		data->bits <<= 1;
		if (!ev.pulse)
			data->bits |= 1;
		data->count++;
		data->state = STATE_BIT_END;
		return 0;

	case STATE_BIT_END:
		if (!is_transition(&ev, &dev->raw->prev_ev))
			break;

		if (data->count == CHECK_RC5X_NBITS)
			data->state = STATE_CHECK_RC5X;
		else
			data->state = STATE_BIT_START;

		decrease_duration(&ev, RC5_BIT_END);
		goto again;

	case STATE_CHECK_RC5X:
		if (!ev.pulse && geq_margin(ev.duration, RC5X_SPACE, RC5_UNIT / 2)) {
			data->is_rc5x = true;
			decrease_duration(&ev, RC5X_SPACE);
		} else
			data->is_rc5x = false;
		data->state = STATE_BIT_START;
		goto again;

	case STATE_FINISHED:
		if (ev.pulse)
			break;

		if (data->is_rc5x && data->count == RC5X_NBITS) {
			/* RC5X */
			u8 xdata, command, system;
			if (!(dev->enabled_protocols & RC_BIT_RC5X)) {
				data->state = STATE_INACTIVE;
				return 0;
			}
			xdata    = (data->bits & 0x0003F) >> 0;
			command  = (data->bits & 0x00FC0) >> 6;
			system   = (data->bits & 0x1F000) >> 12;
			toggle   = (data->bits & 0x20000) ? 1 : 0;
			command += (data->bits & 0x01000) ? 0 : 0x40;
			scancode = system << 16 | command << 8 | xdata;
			protocol = RC_TYPE_RC5X;

		} else if (!data->is_rc5x && data->count == RC5_NBITS) {
示例#6
0
static int ir_rc6_decode(struct rc6_ir *data, struct ir_signal signal,
		struct ir_protocol *ip)
{
	int i;
	i = ip->priv;
	if (i >= MAX_RC6_INFR_NR)
		goto out;

	if (!geq_margin(signal.duration, RC6_UNIT, RC6_UNIT / 2))
		goto out;
		
again:
	hiir_debug("RC6 decode started at state %i (%uus %s) "
		"count %d header 0x%x bits 0x%llx, count:%d\n",
		data->state, signal.duration, TO_STR(signal.pulse),
		data->count, data->header, data->bits, data->count);

	if (!geq_margin(signal.duration, RC6_UNIT, RC6_UNIT / 2))
		return 0;

	switch (data->state) {
	case STATE_INACTIVE:
		if (!signal.pulse)
			break;

		if (!eq_margin(signal.duration, RC6_PREFIX_PULSE, RC6_UNIT))
			break;

		data->state = STATE_PREFIX_SPACE;
		data->bits = 0;
		data->count = 0;
		data->header = 0;
		memset(&data->this_key, 0, sizeof(struct key_attr));
		return 0;

	case STATE_PREFIX_SPACE:
		if (signal.pulse)
			break;

		if (!eq_margin(signal.duration, RC6_PREFIX_SPACE,
			RC6_UNIT / 2))
			break;

		data->state = STATE_HEADER_BIT_START;
		return 0;

	case STATE_HEADER_BIT_START:
		if (!eq_margin(signal.duration, RC6_BIT_START,
			RC6_UNIT / 2))
			break;

		data->header <<= 1;
		if (signal.pulse)
			data->header |= 1;

		data->count++;
		data->state = STATE_HEADER_BIT_END;
		return 0;

	case STATE_HEADER_BIT_END:
		if (!is_transition(&signal, &data->prev_signal))
			break;

		if (data->count == RC6_HEADER_NBITS)
			data->state = STATE_TOGGLE_START;
		else
			data->state = STATE_HEADER_BIT_START;

		decrease_duration(&signal, RC6_BIT_END);
		goto again;

	case STATE_TOGGLE_START:
		if (!eq_margin(signal.duration, RC6_TOGGLE_START, RC6_UNIT / 2))
			break;

		data->state = STATE_TOGGLE_END;
		return 0;

	case STATE_TOGGLE_END:
		if (!is_transition(&signal, &data->prev_signal) 
			|| !geq_margin(signal.duration, RC6_TOGGLE_END,
				RC6_UNIT / 2))
			break;

		data->state = STATE_BIT_START;
		decrease_duration(&signal, RC6_TOGGLE_END);
		data->count = 0;

		goto again;

	case STATE_BIT_START:
		if (!eq_margin(signal.duration, RC6_BIT_START, RC6_UNIT / 2))
			break;
		
		data->bits <<= 1;
		if (signal.pulse)
			data->bits |= 1;
		data->count++;
		data->state = STATE_BIT_END;
		return 0;

	case STATE_BIT_END:
		if (!is_transition(&signal, &data->prev_signal))
			break;

		if (data->count == ip->attr.wanna_bits) {
			data->scancode = data->bits;
			data->this_key.lower = (data->scancode & (~RC6_TOGGLE_MASK));
			data->this_key.upper = 0;
			data->state = STATE_FINISHED;
			return 0;
		} else
			data->state = STATE_BIT_START;

		decrease_duration(&signal, RC6_BIT_END);
		goto again;

	case STATE_FINISHED:
		if (signal.pulse)
			break;

		data->state = STATE_INACTIVE;
		return 0;
	}

out:
	hiir_info("RC6 decode failed at state %i (%uus %s), bits received:%d\n",
		   data->state, signal.duration, TO_STR(signal.pulse), data->count);
	data->state = STATE_INACTIVE;
	return -EINVAL;
}
示例#7
0
/**
 * ir_rc5_sz_decode() - Decode one RC-5 Streamzap pulse or space
 * @input_dev:	the struct input_dev descriptor of the device
 * @ev:		the struct ir_raw_event descriptor of the pulse/space
 *
 * This function returns -EINVAL if the pulse violates the state machine
 */
static int ir_rc5_sz_decode(struct input_dev *input_dev, struct ir_raw_event ev)
{
	struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
	struct rc5_sz_dec *data = &ir_dev->raw->rc5_sz;
	u8 toggle, command, system;
	u32 scancode;

        if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5_SZ))
                return 0;

	if (!is_timing_event(ev)) {
		if (ev.reset)
			data->state = STATE_INACTIVE;
		return 0;
	}

	if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
		goto out;

again:
	IR_dprintk(2, "RC5-sz decode started at state %i (%uus %s)\n",
		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));

	if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
		return 0;

	switch (data->state) {

	case STATE_INACTIVE:
		if (!ev.pulse)
			break;

		data->state = STATE_BIT_START;
		data->count = 1;
		data->wanted_bits = RC5_SZ_NBITS;
		decrease_duration(&ev, RC5_BIT_START);
		goto again;

	case STATE_BIT_START:
		if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
			break;

		data->bits <<= 1;
		if (!ev.pulse)
			data->bits |= 1;
		data->count++;
		data->state = STATE_BIT_END;
		return 0;

	case STATE_BIT_END:
		if (!is_transition(&ev, &ir_dev->raw->prev_ev))
			break;

		if (data->count == data->wanted_bits)
			data->state = STATE_FINISHED;
		else
			data->state = STATE_BIT_START;

		decrease_duration(&ev, RC5_BIT_END);
		goto again;

	case STATE_FINISHED:
		if (ev.pulse)
			break;

		/* RC5-sz */
		command  = (data->bits & 0x0003F) >> 0;
		system   = (data->bits & 0x02FC0) >> 6;
		toggle   = (data->bits & 0x01000) ? 1 : 0;
		scancode = system << 6 | command;

		IR_dprintk(1, "RC5-sz scancode 0x%04x (toggle: %u)\n",
			   scancode, toggle);

		ir_keydown(input_dev, scancode, toggle);
		data->state = STATE_INACTIVE;
		return 0;
	}

out:
	IR_dprintk(1, "RC5-sz decode failed at state %i (%uus %s)\n",
		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
	data->state = STATE_INACTIVE;
	return -EINVAL;
}
static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev)
{
	struct rc6_dec *data = &dev->raw->rc6;
	u32 scancode;
	u8 toggle;

	if (!(dev->raw->enabled_protocols & RC_TYPE_RC6))
		return 0;

	if (!is_timing_event(ev)) {
		if (ev.reset)
			data->state = STATE_INACTIVE;
		return 0;
	}

	if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
		goto out;

again:
	IR_dprintk(2, "RC6 decode started at state %i (%uus %s)\n",
		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));

	if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
		return 0;

	switch (data->state) {

	case STATE_INACTIVE:
		if (!ev.pulse)
			break;

		if (!eq_margin(ev.duration, RC6_PREFIX_PULSE, RC6_UNIT))
			break;

		data->state = STATE_PREFIX_SPACE;
		data->count = 0;
		return 0;

	case STATE_PREFIX_SPACE:
		if (ev.pulse)
			break;

		if (!eq_margin(ev.duration, RC6_PREFIX_SPACE, RC6_UNIT / 2))
			break;

		data->state = STATE_HEADER_BIT_START;
		data->header = 0;
		return 0;

	case STATE_HEADER_BIT_START:
		if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
			break;

		data->header <<= 1;
		if (ev.pulse)
			data->header |= 1;
		data->count++;
		data->state = STATE_HEADER_BIT_END;
		return 0;

	case STATE_HEADER_BIT_END:
		if (!is_transition(&ev, &dev->raw->prev_ev))
			break;

		if (data->count == RC6_HEADER_NBITS)
			data->state = STATE_TOGGLE_START;
		else
			data->state = STATE_HEADER_BIT_START;

		decrease_duration(&ev, RC6_BIT_END);
		goto again;

	case STATE_TOGGLE_START:
		if (!eq_margin(ev.duration, RC6_TOGGLE_START, RC6_UNIT / 2))
			break;

		data->toggle = ev.pulse;
		data->state = STATE_TOGGLE_END;
		return 0;

	case STATE_TOGGLE_END:
		if (!is_transition(&ev, &dev->raw->prev_ev) ||
		    !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2))
			break;

		if (!(data->header & RC6_STARTBIT_MASK)) {
			IR_dprintk(1, "RC6 invalid start bit\n");
			break;
		}

		data->state = STATE_BODY_BIT_START;
		decrease_duration(&ev, RC6_TOGGLE_END);
		data->count = 0;
		data->body = 0;

		switch (rc6_mode(data)) {
		case RC6_MODE_0:
			data->wanted_bits = RC6_0_NBITS;
			break;
		case RC6_MODE_6A:
			data->wanted_bits = RC6_6A_NBITS;
			break;
		default:
			IR_dprintk(1, "RC6 unknown mode\n");
			goto out;
		}
		goto again;

	case STATE_BODY_BIT_START:
		if (eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) {
			
			if (data->count++ < CHAR_BIT * sizeof data->body) {
				data->body <<= 1;
				if (ev.pulse)
					data->body |= 1;
			}
			data->state = STATE_BODY_BIT_END;
			return 0;
		} else if (RC6_MODE_6A == rc6_mode(data) && !ev.pulse &&
				geq_margin(ev.duration, RC6_SUFFIX_SPACE, RC6_UNIT / 2)) {
			data->state = STATE_FINISHED;
			goto again;
		}
		break;

	case STATE_BODY_BIT_END:
		if (!is_transition(&ev, &dev->raw->prev_ev))
			break;

		if (data->count == data->wanted_bits)
			data->state = STATE_FINISHED;
		else
			data->state = STATE_BODY_BIT_START;

		decrease_duration(&ev, RC6_BIT_END);
		goto again;

	case STATE_FINISHED:
		if (ev.pulse)
			break;

		switch (rc6_mode(data)) {
		case RC6_MODE_0:
			scancode = data->body;
			toggle = data->toggle;
			IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n",
				   scancode, toggle);
			break;
		case RC6_MODE_6A:
			if (data->count > CHAR_BIT * sizeof data->body) {
				IR_dprintk(1, "RC6 too many (%u) data bits\n",
					data->count);
				goto out;
			}

			scancode = data->body;
			if (data->count == RC6_6A_32_NBITS &&
					(scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) {
				
				toggle = (scancode & RC6_6A_MCE_TOGGLE_MASK) ? 1 : 0;
				scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
			} else {
				toggle = 0;
			}
			IR_dprintk(1, "RC6(6A) scancode 0x%08x (toggle: %u)\n",
				   scancode, toggle);
			break;
		default:
			IR_dprintk(1, "RC6 unknown mode\n");
			goto out;
		}

		rc_keydown(dev, scancode, toggle);
		data->state = STATE_INACTIVE;
		return 0;
	}

out:
	IR_dprintk(1, "RC6 decode failed at state %i (%uus %s)\n",
		   data->state, TO_US(ev.duration), TO_STR(ev.pulse));
	data->state = STATE_INACTIVE;
	return -EINVAL;
}