Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] rc: ir-rc6-decoder: Add encode capability

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ä <a.seppala@gmail.com>
Cc: James Hogan <james@albanarts.com>
Cc: David Härdeman <david@hardeman.nu>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>

authored by

Antti Seppälä and committed by
Mauro Carvalho Chehab
cf257e28 a0466f15

+122
+122
drivers/media/rc/ir-rc6-decoder.c
··· 291 291 return -EINVAL; 292 292 } 293 293 294 + static struct ir_raw_timings_manchester ir_rc6_timings[4] = { 295 + { 296 + .leader = RC6_PREFIX_PULSE, 297 + .pulse_space_start = 0, 298 + .clock = RC6_UNIT, 299 + .invert = 1, 300 + .trailer_space = RC6_PREFIX_SPACE, 301 + }, 302 + { 303 + .clock = RC6_UNIT, 304 + .invert = 1, 305 + }, 306 + { 307 + .clock = RC6_UNIT * 2, 308 + .invert = 1, 309 + }, 310 + { 311 + .clock = RC6_UNIT, 312 + .invert = 1, 313 + .trailer_space = RC6_SUFFIX_SPACE, 314 + }, 315 + }; 316 + 317 + static int ir_rc6_validate_filter(const struct rc_scancode_filter *scancode, 318 + unsigned int important_bits) 319 + { 320 + /* all important bits of scancode should be set in mask */ 321 + if (~scancode->mask & important_bits) 322 + return -EINVAL; 323 + /* extra bits in mask should be zero in data */ 324 + if (scancode->mask & scancode->data & ~important_bits) 325 + return -EINVAL; 326 + return 0; 327 + } 328 + 329 + /** 330 + * ir_rc6_encode() - Encode a scancode as a stream of raw events 331 + * 332 + * @protocols: allowed protocols 333 + * @scancode: scancode filter describing scancode (helps distinguish between 334 + * protocol subtypes when scancode is ambiguous) 335 + * @events: array of raw ir events to write into 336 + * @max: maximum size of @events 337 + * 338 + * Returns: The number of events written. 339 + * -ENOBUFS if there isn't enough space in the array to fit the 340 + * encoding. In this case all @max events will have been written. 341 + * -EINVAL if the scancode is ambiguous or invalid. 342 + */ 343 + static int ir_rc6_encode(u64 protocols, 344 + const struct rc_scancode_filter *scancode, 345 + struct ir_raw_event *events, unsigned int max) 346 + { 347 + int ret; 348 + struct ir_raw_event *e = events; 349 + 350 + if (protocols & RC_BIT_RC6_0 && 351 + !ir_rc6_validate_filter(scancode, 0xffff)) { 352 + 353 + /* Modulate the preamble */ 354 + ret = ir_raw_gen_manchester(&e, max, &ir_rc6_timings[0], 0, 0); 355 + if (ret < 0) 356 + return ret; 357 + 358 + /* Modulate the header (Start Bit & Mode-0) */ 359 + ret = ir_raw_gen_manchester(&e, max - (e - events), 360 + &ir_rc6_timings[1], 361 + RC6_HEADER_NBITS, (1 << 3)); 362 + if (ret < 0) 363 + return ret; 364 + 365 + /* Modulate Trailer Bit */ 366 + ret = ir_raw_gen_manchester(&e, max - (e - events), 367 + &ir_rc6_timings[2], 1, 0); 368 + if (ret < 0) 369 + return ret; 370 + 371 + /* Modulate rest of the data */ 372 + ret = ir_raw_gen_manchester(&e, max - (e - events), 373 + &ir_rc6_timings[3], RC6_0_NBITS, 374 + scancode->data); 375 + if (ret < 0) 376 + return ret; 377 + 378 + } else if (protocols & (RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 | 379 + RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE) && 380 + !ir_rc6_validate_filter(scancode, 0x8fffffff)) { 381 + 382 + /* Modulate the preamble */ 383 + ret = ir_raw_gen_manchester(&e, max, &ir_rc6_timings[0], 0, 0); 384 + if (ret < 0) 385 + return ret; 386 + 387 + /* Modulate the header (Start Bit & Header-version 6 */ 388 + ret = ir_raw_gen_manchester(&e, max - (e - events), 389 + &ir_rc6_timings[1], 390 + RC6_HEADER_NBITS, (1 << 3 | 6)); 391 + if (ret < 0) 392 + return ret; 393 + 394 + /* Modulate Trailer Bit */ 395 + ret = ir_raw_gen_manchester(&e, max - (e - events), 396 + &ir_rc6_timings[2], 1, 0); 397 + if (ret < 0) 398 + return ret; 399 + 400 + /* Modulate rest of the data */ 401 + ret = ir_raw_gen_manchester(&e, max - (e - events), 402 + &ir_rc6_timings[3], 403 + fls(scancode->mask), 404 + scancode->data); 405 + if (ret < 0) 406 + return ret; 407 + 408 + } else { 409 + return -EINVAL; 410 + } 411 + 412 + return e - events; 413 + } 414 + 294 415 static struct ir_raw_handler rc6_handler = { 295 416 .protocols = RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 | 296 417 RC_BIT_RC6_6A_24 | RC_BIT_RC6_6A_32 | 297 418 RC_BIT_RC6_MCE, 298 419 .decode = ir_rc6_decode, 420 + .encode = ir_rc6_encode, 299 421 }; 300 422 301 423 static int __init ir_rc6_decode_init(void)