diff options
author | David Hardeman <david@hardeman.nu> | 2006-12-02 18:16:05 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2006-12-10 06:05:17 -0500 |
commit | 64741b70cf2030ffe017e5ed731620b4a4570f77 (patch) | |
tree | e40dea50beae6824ba8e1d2bf0740f39b59b536b /drivers/media/dvb/ttpci | |
parent | 2520fffd8b7a312e77009414d3201c9751d6448c (diff) |
V4L/DVB (4880): budget-ci IR: decode rc5 device byte
Decode the RC5 device byte as well as the command byte. Introduce a
parameter to set the device events to listen for. Default to try
to auto-detect the proper device code, otherwise, listen to any
device as the old code did.
Based on Darren Salt's dvb-ir patchset.
Signed-off-by: Darren Salt <linux@youmustbejoking.demon.co.uk>
Signed-off-by: David Hardeman <david@hardeman.nu>
Signed-off-by: Andrew de Quincey <adq_dvb@lidskialf.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/dvb/ttpci')
-rw-r--r-- | drivers/media/dvb/ttpci/budget-ci.c | 76 |
1 files changed, 59 insertions, 17 deletions
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index d1b5402cd6fe..76d3b6694bce 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c | |||
@@ -78,6 +78,9 @@ | |||
78 | */ | 78 | */ |
79 | #define IR_REPEAT_TIMEOUT 350 | 79 | #define IR_REPEAT_TIMEOUT 350 |
80 | 80 | ||
81 | /* RC5 device wildcard */ | ||
82 | #define IR_DEVICE_ANY 255 | ||
83 | |||
81 | /* Some remotes sends multiple sequences per keypress (e.g. Zenith sends two), | 84 | /* Some remotes sends multiple sequences per keypress (e.g. Zenith sends two), |
82 | * this setting allows the superflous sequences to be ignored | 85 | * this setting allows the superflous sequences to be ignored |
83 | */ | 86 | */ |
@@ -85,12 +88,17 @@ static int debounce = 0; | |||
85 | module_param(debounce, int, 0644); | 88 | module_param(debounce, int, 0644); |
86 | MODULE_PARM_DESC(debounce, "ignore repeated IR sequences (default: 0 = ignore no sequences)"); | 89 | MODULE_PARM_DESC(debounce, "ignore repeated IR sequences (default: 0 = ignore no sequences)"); |
87 | 90 | ||
91 | static int rc5_device = -1; | ||
92 | module_param(rc5_device, int, 0644); | ||
93 | MODULE_PARM_DESC(rc5_device, "only IR commands to given RC5 device (device = 0 - 31, any device = 255, default: autodetect)"); | ||
94 | |||
88 | struct budget_ci_ir { | 95 | struct budget_ci_ir { |
89 | struct input_dev *dev; | 96 | struct input_dev *dev; |
90 | struct tasklet_struct msp430_irq_tasklet; | 97 | struct tasklet_struct msp430_irq_tasklet; |
91 | char name[72]; /* 40 + 32 for (struct saa7146_dev).name */ | 98 | char name[72]; /* 40 + 32 for (struct saa7146_dev).name */ |
92 | char phys[32]; | 99 | char phys[32]; |
93 | struct ir_input_state state; | 100 | struct ir_input_state state; |
101 | int rc5_device; | ||
94 | }; | 102 | }; |
95 | 103 | ||
96 | struct budget_ci { | 104 | struct budget_ci { |
@@ -114,32 +122,56 @@ static void msp430_ir_interrupt(unsigned long data) | |||
114 | struct budget_ci *budget_ci = (struct budget_ci *) data; | 122 | struct budget_ci *budget_ci = (struct budget_ci *) data; |
115 | struct input_dev *dev = budget_ci->ir.dev; | 123 | struct input_dev *dev = budget_ci->ir.dev; |
116 | static int bounces = 0; | 124 | static int bounces = 0; |
117 | u32 ir_key; | 125 | int device; |
126 | int toggle; | ||
127 | static int prev_toggle = -1; | ||
128 | static u32 ir_key; | ||
118 | u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; | 129 | u32 command = ttpci_budget_debiread(&budget_ci->budget, DEBINOSWAP, DEBIADDR_IR, 2, 1, 0) >> 8; |
119 | 130 | ||
131 | /* | ||
132 | * The msp430 chip can generate two different bytes, command and device | ||
133 | * | ||
134 | * type1: X1CCCCCC, C = command bits (0 - 63) | ||
135 | * type2: X0TDDDDD, D = device bits (0 - 31), T = RC5 toggle bit | ||
136 | * | ||
137 | * More than one command byte may be generated before the device byte | ||
138 | * Only when we have both, a correct keypress is generated | ||
139 | */ | ||
140 | |||
141 | /* Is this a RC5 command byte? */ | ||
120 | if (command & 0x40) { | 142 | if (command & 0x40) { |
121 | ir_key = command & 0x3f; | 143 | ir_key = command & 0x3f; |
144 | return; | ||
145 | } | ||
122 | 146 | ||
123 | if (ir_key != dev->repeat_key && del_timer(&dev->timer)) | 147 | /* It's a RC5 device byte */ |
124 | /* We were still waiting for a keyup event but this is a new key */ | 148 | device = command & 0x1f; |
125 | ir_input_nokey(dev, &budget_ci->ir.state); | 149 | toggle = command & 0x20; |
126 | 150 | ||
127 | if (ir_key == dev->repeat_key && bounces > 0 && timer_pending(&dev->timer)) { | 151 | if (budget_ci->ir.rc5_device != IR_DEVICE_ANY && budget_ci->ir.rc5_device != device) |
128 | /* Ignore repeated key sequences if requested */ | 152 | return; |
129 | bounces--; | ||
130 | return; | ||
131 | } | ||
132 | 153 | ||
133 | if (!timer_pending(&dev->timer)) | 154 | /* Are we still waiting for a keyup event while this is a new key? */ |
134 | /* New keypress */ | 155 | if ((ir_key != dev->repeat_key || toggle != prev_toggle) && del_timer(&dev->timer)) |
135 | bounces = debounce; | 156 | ir_input_nokey(dev, &budget_ci->ir.state); |
136 | 157 | ||
137 | /* Prepare a keyup event sometime in the future */ | 158 | prev_toggle = toggle; |
138 | mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT)); | ||
139 | 159 | ||
140 | /* Generate a new or repeated keypress */ | 160 | /* Ignore repeated key sequences if requested */ |
141 | ir_input_keydown(dev, &budget_ci->ir.state, ir_key, command); | 161 | if (ir_key == dev->repeat_key && bounces > 0 && timer_pending(&dev->timer)) { |
162 | bounces--; | ||
163 | return; | ||
142 | } | 164 | } |
165 | |||
166 | /* New keypress? */ | ||
167 | if (!timer_pending(&dev->timer)) | ||
168 | bounces = debounce; | ||
169 | |||
170 | /* Prepare a keyup event sometime in the future */ | ||
171 | mod_timer(&dev->timer, jiffies + msecs_to_jiffies(IR_REPEAT_TIMEOUT)); | ||
172 | |||
173 | /* Generate a new or repeated keypress */ | ||
174 | ir_input_keydown(dev, &budget_ci->ir.state, ir_key, ((device << 8) | command)); | ||
143 | } | 175 | } |
144 | 176 | ||
145 | static void msp430_ir_debounce(unsigned long data) | 177 | static void msp430_ir_debounce(unsigned long data) |
@@ -228,7 +260,7 @@ static int msp430_ir_init(struct budget_ci *budget_ci) | |||
228 | input_dev->dev = &saa->pci->dev; | 260 | input_dev->dev = &saa->pci->dev; |
229 | # endif | 261 | # endif |
230 | 262 | ||
231 | /* Select keymap */ | 263 | /* Select keymap and address */ |
232 | switch (budget_ci->budget.dev->pci->subsystem_device) { | 264 | switch (budget_ci->budget.dev->pci->subsystem_device) { |
233 | case 0x100c: | 265 | case 0x100c: |
234 | case 0x100f: | 266 | case 0x100f: |
@@ -239,11 +271,21 @@ static int msp430_ir_init(struct budget_ci *budget_ci) | |||
239 | /* The hauppauge keymap is a superset of these remotes */ | 271 | /* The hauppauge keymap is a superset of these remotes */ |
240 | ir_input_init(input_dev, &budget_ci->ir.state, | 272 | ir_input_init(input_dev, &budget_ci->ir.state, |
241 | IR_TYPE_RC5, ir_codes_hauppauge_new); | 273 | IR_TYPE_RC5, ir_codes_hauppauge_new); |
274 | |||
275 | if (rc5_device < 0) | ||
276 | budget_ci->ir.rc5_device = 0x1f; | ||
277 | else | ||
278 | budget_ci->ir.rc5_device = rc5_device; | ||
242 | break; | 279 | break; |
243 | default: | 280 | default: |
244 | /* unknown remote */ | 281 | /* unknown remote */ |
245 | ir_input_init(input_dev, &budget_ci->ir.state, | 282 | ir_input_init(input_dev, &budget_ci->ir.state, |
246 | IR_TYPE_RC5, ir_codes_budget_ci_old); | 283 | IR_TYPE_RC5, ir_codes_budget_ci_old); |
284 | |||
285 | if (rc5_device < 0) | ||
286 | budget_ci->ir.rc5_device = IR_DEVICE_ANY; | ||
287 | else | ||
288 | budget_ci->ir.rc5_device = rc5_device; | ||
247 | break; | 289 | break; |
248 | } | 290 | } |
249 | 291 | ||