-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
yaml --- r: 192894 b: refs/heads/master c: a3572c3 h: refs/heads/master v: v3
- Loading branch information
Mauro Carvalho Chehab
committed
May 18, 2010
1 parent
6f3847b
commit 4f7753e
Showing
7 changed files
with
366 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
--- | ||
refs/heads/master: 0210894956cf57d525d56341cc3e0f3d5d2db659 | ||
refs/heads/master: a3572c34da8dacc78a629211a91cf34e9b408701 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
ir-common-objs := ir-functions.o ir-keymaps.o | ||
ir-core-objs := ir-keytable.o ir-sysfs.o | ||
ir-core-objs := ir-keytable.o ir-sysfs.o ir-raw-event.o ir-nec-decoder.o | ||
|
||
obj-$(CONFIG_IR_CORE) += ir-core.o | ||
obj-$(CONFIG_VIDEO_IR) += ir-common.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
/* ir-raw-event.c - handle IR Pulse/Space event | ||
* | ||
* Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation version 2 of the License. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
*/ | ||
|
||
#include <media/ir-core.h> | ||
|
||
/* Start time: 4.5 ms */ | ||
#define MIN_START_TIME 3900000 | ||
#define MAX_START_TIME 5100000 | ||
|
||
/* Pulse time: 560 us */ | ||
#define MIN_PULSE_TIME 460000 | ||
#define MAX_PULSE_TIME 660000 | ||
|
||
/* Bit 1 space time: 2.25ms-560 us */ | ||
#define MIN_BIT1_TIME 1490000 | ||
#define MAX_BIT1_TIME 1890000 | ||
|
||
/* Bit 0 space time: 1.12ms-560 us */ | ||
#define MIN_BIT0_TIME 360000 | ||
#define MAX_BIT0_TIME 760000 | ||
|
||
|
||
/** Decode NEC pulsecode. This code can take up to 76.5 ms to run. | ||
Unfortunately, using IRQ to decode pulse didn't work, since it uses | ||
a pulse train of 38KHz. This means one pulse on each 52 us | ||
*/ | ||
|
||
int ir_nec_decode(struct input_dev *input_dev, | ||
struct ir_raw_event *evs, | ||
int len) | ||
{ | ||
int i, count = -1; | ||
int ircode = 0, not_code = 0; | ||
#if 0 | ||
/* Needed only after porting the event code to the decoder */ | ||
struct ir_input_dev *ir = input_get_drvdata(input_dev); | ||
#endif | ||
|
||
/* Be sure that the first event is an start one and is a pulse */ | ||
for (i = 0; i < len; i++) { | ||
if (evs[i].type & (IR_START_EVENT | IR_PULSE)) | ||
break; | ||
} | ||
i++; /* First event doesn't contain data */ | ||
|
||
if (i >= len) | ||
return 0; | ||
|
||
/* First space should have 4.5 ms otherwise is not NEC protocol */ | ||
if ((evs[i].delta.tv_nsec < MIN_START_TIME) | | ||
(evs[i].delta.tv_nsec > MAX_START_TIME) | | ||
(evs[i].type != IR_SPACE)) | ||
goto err; | ||
|
||
/* | ||
* FIXME: need to implement the repeat sequence | ||
*/ | ||
|
||
count = 0; | ||
for (i++; i < len; i++) { | ||
int bit; | ||
|
||
if ((evs[i].delta.tv_nsec < MIN_PULSE_TIME) | | ||
(evs[i].delta.tv_nsec > MAX_PULSE_TIME) | | ||
(evs[i].type != IR_PULSE)) | ||
goto err; | ||
|
||
if (++i >= len) | ||
goto err; | ||
if (evs[i].type != IR_SPACE) | ||
goto err; | ||
|
||
if ((evs[i].delta.tv_nsec > MIN_BIT1_TIME) && | ||
(evs[i].delta.tv_nsec < MAX_BIT1_TIME)) | ||
bit = 1; | ||
else if ((evs[i].delta.tv_nsec > MIN_BIT0_TIME) && | ||
(evs[i].delta.tv_nsec < MAX_BIT0_TIME)) | ||
bit = 0; | ||
else | ||
goto err; | ||
|
||
if (bit) { | ||
int shift = count; | ||
/* Address first, then command */ | ||
if (shift < 8) { | ||
shift += 8; | ||
ircode |= 1 << shift; | ||
} else if (shift < 16) { | ||
not_code |= 1 << shift; | ||
} else if (shift < 24) { | ||
shift -= 16; | ||
ircode |= 1 << shift; | ||
} else { | ||
shift -= 24; | ||
not_code |= 1 << shift; | ||
} | ||
} | ||
if (++count == 32) | ||
break; | ||
} | ||
|
||
/* | ||
* Fixme: may need to accept Extended NEC protocol? | ||
*/ | ||
if ((ircode & ~not_code) != ircode) { | ||
IR_dprintk(1, "NEC checksum error: code 0x%04x, not-code 0x%04x\n", | ||
ircode, not_code); | ||
return -EINVAL; | ||
} | ||
|
||
IR_dprintk(1, "NEC scancode 0x%04x\n", ircode); | ||
|
||
return ircode; | ||
err: | ||
IR_dprintk(1, "NEC decoded failed at bit %d while decoding %luus time\n", | ||
count, (evs[i].delta.tv_nsec + 500) / 1000); | ||
|
||
return -EINVAL; | ||
} | ||
EXPORT_SYMBOL_GPL(ir_nec_decode); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
/* ir-raw-event.c - handle IR Pulse/Space event | ||
* | ||
* Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License as published by | ||
* the Free Software Foundation version 2 of the License. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
*/ | ||
|
||
#include <media/ir-core.h> | ||
|
||
/* Define the max number of bit transitions per IR keycode */ | ||
#define MAX_IR_EVENT_SIZE 256 | ||
|
||
int ir_raw_event_register(struct input_dev *input_dev) | ||
{ | ||
struct ir_input_dev *ir = input_get_drvdata(input_dev); | ||
int rc, size; | ||
|
||
ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); | ||
|
||
size = sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE * 2; | ||
size = roundup_pow_of_two(size); | ||
|
||
rc = kfifo_alloc(&ir->raw->kfifo, size, GFP_KERNEL); | ||
|
||
return rc; | ||
} | ||
EXPORT_SYMBOL_GPL(ir_raw_event_register); | ||
|
||
void ir_raw_event_unregister(struct input_dev *input_dev) | ||
{ | ||
struct ir_input_dev *ir = input_get_drvdata(input_dev); | ||
|
||
if (!ir->raw) | ||
return; | ||
|
||
kfifo_free(&ir->raw->kfifo); | ||
kfree(ir->raw); | ||
ir->raw = NULL; | ||
} | ||
EXPORT_SYMBOL_GPL(ir_raw_event_unregister); | ||
|
||
int ir_raw_event_store(struct input_dev *input_dev, enum raw_event_type type) | ||
{ | ||
struct ir_input_dev *ir = input_get_drvdata(input_dev); | ||
struct timespec ts; | ||
struct ir_raw_event event; | ||
int rc; | ||
|
||
if (!ir->raw) | ||
return -EINVAL; | ||
|
||
event.type = type; | ||
event.delta.tv_sec = 0; | ||
event.delta.tv_nsec = 0; | ||
|
||
ktime_get_ts(&ts); | ||
|
||
if (timespec_equal(&ir->raw->last_event, &event.delta)) | ||
event.type |= IR_START_EVENT; | ||
else | ||
event.delta = timespec_sub(ts, ir->raw->last_event); | ||
|
||
memcpy(&ir->raw->last_event, &ts, sizeof(ts)); | ||
|
||
if (event.delta.tv_sec) { | ||
event.type |= IR_START_EVENT; | ||
event.delta.tv_sec = 0; | ||
event.delta.tv_nsec = 0; | ||
} | ||
|
||
kfifo_in(&ir->raw->kfifo, &event, sizeof(event)); | ||
|
||
return rc; | ||
} | ||
EXPORT_SYMBOL_GPL(ir_raw_event_store); | ||
|
||
int ir_raw_event_handle(struct input_dev *input_dev) | ||
{ | ||
struct ir_input_dev *ir = input_get_drvdata(input_dev); | ||
int rc; | ||
struct ir_raw_event *evs; | ||
int len, i; | ||
|
||
/* | ||
* Store the events into a temporary buffer. This allows calling more than | ||
* one decoder to deal with the received data | ||
*/ | ||
len = kfifo_len(&ir->raw->kfifo) / sizeof(*evs); | ||
if (!len) | ||
return 0; | ||
evs = kmalloc(len * sizeof(*evs), GFP_ATOMIC); | ||
|
||
for (i = 0; i < len; i++) { | ||
rc = kfifo_out(&ir->raw->kfifo, &evs[i], sizeof(*evs)); | ||
if (rc != sizeof(*evs)) { | ||
IR_dprintk(1, "overflow error: received %d instead of %zd\n", | ||
rc, sizeof(*evs)); | ||
return -EINVAL; | ||
} | ||
IR_dprintk(2, "event type %d, time before event: %07luus\n", | ||
evs[i].type, (evs[i].delta.tv_nsec + 500) / 1000); | ||
} | ||
|
||
rc = ir_nec_decode(input_dev, evs, len); | ||
|
||
kfree(evs); | ||
|
||
return rc; | ||
} | ||
EXPORT_SYMBOL_GPL(ir_raw_event_handle); |
Oops, something went wrong.