Skip to content

Commit

Permalink
[media] rc: ir-rc6-decoder: Add encode capability
Browse files Browse the repository at this point in the history
Add the capability to encode RC-6 and RC-6A scancodes as raw events.
The protocol is chosen based on the specified protocol mask, and
whether all the required bits are set in the scancode mask, and none of
the unused bits are set in the scancode data.

The Manchester modulation helper is used several times with various
timings so that RC-6 header preamble, the header, header trailing bit
and the data itself can be modulated correctly.

Signed-off-by: Antti Seppälä <[email protected]>
Cc: James Hogan <[email protected]>
Cc: David Härdeman <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
  • Loading branch information
pesintta authored and mchehab committed May 14, 2015
1 parent a0466f1 commit cf257e2
Showing 1 changed file with 122 additions and 0 deletions.
122 changes: 122 additions & 0 deletions drivers/media/rc/ir-rc6-decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,11 +291,133 @@ static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev)
return -EINVAL;
}

static struct ir_raw_timings_manchester ir_rc6_timings[4] = {
{
.leader = RC6_PREFIX_PULSE,
.pulse_space_start = 0,
.clock = RC6_UNIT,
.invert = 1,
.trailer_space = RC6_PREFIX_SPACE,
},
{
.clock = RC6_UNIT,
.invert = 1,
},
{
.clock = RC6_UNIT * 2,
.invert = 1,
},
{
.clock = RC6_UNIT,
.invert = 1,
.trailer_space = RC6_SUFFIX_SPACE,
},
};

static int ir_rc6_validate_filter(const struct rc_scancode_filter *scancode,
unsigned int important_bits)
{
/* all important bits of scancode should be set in mask */
if (~scancode->mask & important_bits)
return -EINVAL;
/* extra bits in mask should be zero in data */
if (scancode->mask & scancode->data & ~important_bits)
return -EINVAL;
return 0;
}

/**
* ir_rc6_encode() - Encode a scancode as a stream of raw events
*
* @protocols: allowed protocols
* @scancode: scancode filter describing scancode (helps distinguish between
* protocol subtypes when scancode is ambiguous)
* @events: array of raw ir events to write into
* @max: maximum size of @events
*
* Returns: The number of events written.
* -ENOBUFS if there isn't enough space in the array to fit the
* encoding. In this case all @max events will have been written.
* -EINVAL if the scancode is ambiguous or invalid.
*/
static int ir_rc6_encode(u64 protocols,
const struct rc_scancode_filter *scancode,
struct ir_raw_event *events, unsigned int max)
{
int ret;
struct ir_raw_event *e = events;

if (protocols & RC_BIT_RC6_0 &&
!ir_rc6_validate_filter(scancode, 0xffff)) {

/* Modulate the preamble */
ret = ir_raw_gen_manchester(&e, max, &ir_rc6_timings[0], 0, 0);
if (ret < 0)
return ret;

/* Modulate the header (Start Bit & Mode-0) */
ret = ir_raw_gen_manchester(&e, max - (e - events),
&ir_rc6_timings[1],
RC6_HEADER_NBITS, (1 << 3));
if (ret < 0)
return ret;

/* Modulate Trailer Bit */
ret = ir_raw_gen_manchester(&e, max - (e - events),
&ir_rc6_timings[2], 1, 0);
if (ret < 0)
return ret;

/* Modulate rest of the data */
ret = ir_raw_gen_manchester(&e, max - (e - events),
&ir_rc6_timings[3], RC6_0_NBITS,
scancode->data);
if (ret < 0)
return ret;

} else if (protocols & (RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 |
RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE) &&
!ir_rc6_validate_filter(scancode, 0x8fffffff)) {

/* Modulate the preamble */
ret = ir_raw_gen_manchester(&e, max, &ir_rc6_timings[0], 0, 0);
if (ret < 0)
return ret;

/* Modulate the header (Start Bit & Header-version 6 */
ret = ir_raw_gen_manchester(&e, max - (e - events),
&ir_rc6_timings[1],
RC6_HEADER_NBITS, (1 << 3 | 6));
if (ret < 0)
return ret;

/* Modulate Trailer Bit */
ret = ir_raw_gen_manchester(&e, max - (e - events),
&ir_rc6_timings[2], 1, 0);
if (ret < 0)
return ret;

/* Modulate rest of the data */
ret = ir_raw_gen_manchester(&e, max - (e - events),
&ir_rc6_timings[3],
fls(scancode->mask),
scancode->data);
if (ret < 0)
return ret;

} else {
return -EINVAL;
}

return e - events;
}

static struct ir_raw_handler rc6_handler = {
.protocols = RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 |
RC_BIT_RC6_6A_24 | RC_BIT_RC6_6A_32 |
RC_BIT_RC6_MCE,
.decode = ir_rc6_decode,
.encode = ir_rc6_encode,
};

static int __init ir_rc6_decode_init(void)
Expand Down

0 comments on commit cf257e2

Please sign in to comment.