diff options
Diffstat (limited to 'drivers/staging/lirc')
-rw-r--r-- | drivers/staging/lirc/Kconfig | 78 | ||||
-rw-r--r-- | drivers/staging/lirc/Makefile | 14 | ||||
-rw-r--r-- | drivers/staging/lirc/TODO | 8 | ||||
-rw-r--r-- | drivers/staging/lirc/TODO.lirc_zilog | 36 | ||||
-rw-r--r-- | drivers/staging/lirc/lirc_bt829.c | 383 | ||||
-rw-r--r-- | drivers/staging/lirc/lirc_ene0100.h | 169 | ||||
-rw-r--r-- | drivers/staging/lirc/lirc_igorplugusb.c | 577 | ||||
-rw-r--r-- | drivers/staging/lirc/lirc_imon.c | 1050 | ||||
-rw-r--r-- | drivers/staging/lirc/lirc_parallel.c | 755 | ||||
-rw-r--r-- | drivers/staging/lirc/lirc_parallel.h | 26 | ||||
-rw-r--r-- | drivers/staging/lirc/lirc_sasem.c | 939 | ||||
-rw-r--r-- | drivers/staging/lirc/lirc_serial.c | 1315 | ||||
-rw-r--r-- | drivers/staging/lirc/lirc_sir.c | 1279 | ||||
-rw-r--r-- | drivers/staging/lirc/lirc_ttusbir.c | 395 | ||||
-rw-r--r-- | drivers/staging/lirc/lirc_zilog.c | 1676 |
15 files changed, 8700 insertions, 0 deletions
diff --git a/drivers/staging/lirc/Kconfig b/drivers/staging/lirc/Kconfig new file mode 100644 index 00000000000..526ec0fc2f0 --- /dev/null +++ b/drivers/staging/lirc/Kconfig | |||
@@ -0,0 +1,78 @@ | |||
1 | # | ||
2 | # LIRC driver(s) configuration | ||
3 | # | ||
4 | menuconfig LIRC_STAGING | ||
5 | bool "Linux Infrared Remote Control IR receiver/transmitter drivers" | ||
6 | depends on LIRC | ||
7 | help | ||
8 | Say Y here, and all supported Linux Infrared Remote Control IR and | ||
9 | RF receiver and transmitter drivers will be displayed. When paired | ||
10 | with a remote control and the lirc daemon, the receiver drivers | ||
11 | allow control of your Linux system via remote control. | ||
12 | |||
13 | if LIRC_STAGING | ||
14 | |||
15 | config LIRC_BT829 | ||
16 | tristate "BT829 based hardware" | ||
17 | depends on LIRC && PCI | ||
18 | help | ||
19 | Driver for the IR interface on BT829-based hardware | ||
20 | |||
21 | config LIRC_IGORPLUGUSB | ||
22 | tristate "Igor Cesko's USB IR Receiver" | ||
23 | depends on LIRC && USB | ||
24 | help | ||
25 | Driver for Igor Cesko's USB IR Receiver | ||
26 | |||
27 | config LIRC_IMON | ||
28 | tristate "Legacy SoundGraph iMON Receiver and Display" | ||
29 | depends on LIRC && USB | ||
30 | help | ||
31 | Driver for the original SoundGraph iMON IR Receiver and Display | ||
32 | |||
33 | Current generation iMON devices use the input layer imon driver. | ||
34 | |||
35 | config LIRC_PARALLEL | ||
36 | tristate "Homebrew Parallel Port Receiver" | ||
37 | depends on LIRC && PARPORT | ||
38 | help | ||
39 | Driver for Homebrew Parallel Port Receivers | ||
40 | |||
41 | config LIRC_SASEM | ||
42 | tristate "Sasem USB IR Remote" | ||
43 | depends on LIRC && USB | ||
44 | help | ||
45 | Driver for the Sasem OnAir Remocon-V or Dign HV5 HTPC IR/VFD Module | ||
46 | |||
47 | config LIRC_SERIAL | ||
48 | tristate "Homebrew Serial Port Receiver" | ||
49 | depends on LIRC | ||
50 | help | ||
51 | Driver for Homebrew Serial Port Receivers | ||
52 | |||
53 | config LIRC_SERIAL_TRANSMITTER | ||
54 | bool "Serial Port Transmitter" | ||
55 | default y | ||
56 | depends on LIRC_SERIAL | ||
57 | help | ||
58 | Serial Port Transmitter support | ||
59 | |||
60 | config LIRC_SIR | ||
61 | tristate "Built-in SIR IrDA port" | ||
62 | depends on LIRC | ||
63 | help | ||
64 | Driver for the SIR IrDA port | ||
65 | |||
66 | config LIRC_TTUSBIR | ||
67 | tristate "Technotrend USB IR Receiver" | ||
68 | depends on LIRC && USB | ||
69 | help | ||
70 | Driver for the Technotrend USB IR Receiver | ||
71 | |||
72 | config LIRC_ZILOG | ||
73 | tristate "Zilog/Hauppauge IR Transmitter" | ||
74 | depends on LIRC && I2C | ||
75 | help | ||
76 | Driver for the Zilog/Hauppauge IR Transmitter, found on | ||
77 | PVR-150/500, HVR-1200/1250/1700/1800, HD-PVR and other cards | ||
78 | endif | ||
diff --git a/drivers/staging/lirc/Makefile b/drivers/staging/lirc/Makefile new file mode 100644 index 00000000000..d76b0fa2af5 --- /dev/null +++ b/drivers/staging/lirc/Makefile | |||
@@ -0,0 +1,14 @@ | |||
1 | # Makefile for the lirc drivers. | ||
2 | # | ||
3 | |||
4 | # Each configuration option enables a list of files. | ||
5 | |||
6 | obj-$(CONFIG_LIRC_BT829) += lirc_bt829.o | ||
7 | obj-$(CONFIG_LIRC_IGORPLUGUSB) += lirc_igorplugusb.o | ||
8 | obj-$(CONFIG_LIRC_IMON) += lirc_imon.o | ||
9 | obj-$(CONFIG_LIRC_PARALLEL) += lirc_parallel.o | ||
10 | obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o | ||
11 | obj-$(CONFIG_LIRC_SERIAL) += lirc_serial.o | ||
12 | obj-$(CONFIG_LIRC_SIR) += lirc_sir.o | ||
13 | obj-$(CONFIG_LIRC_TTUSBIR) += lirc_ttusbir.o | ||
14 | obj-$(CONFIG_LIRC_ZILOG) += lirc_zilog.o | ||
diff --git a/drivers/staging/lirc/TODO b/drivers/staging/lirc/TODO new file mode 100644 index 00000000000..b6cb593f55c --- /dev/null +++ b/drivers/staging/lirc/TODO | |||
@@ -0,0 +1,8 @@ | |||
1 | - All drivers should either be ported to ir-core, or dropped entirely | ||
2 | (see drivers/media/IR/mceusb.c vs. lirc_mceusb.c in lirc cvs for an | ||
3 | example of a previously completed port). | ||
4 | |||
5 | Please send patches to: | ||
6 | Jarod Wilson <jarod@wilsonet.com> | ||
7 | Greg Kroah-Hartman <greg@kroah.com> | ||
8 | |||
diff --git a/drivers/staging/lirc/TODO.lirc_zilog b/drivers/staging/lirc/TODO.lirc_zilog new file mode 100644 index 00000000000..a97800a8e12 --- /dev/null +++ b/drivers/staging/lirc/TODO.lirc_zilog | |||
@@ -0,0 +1,36 @@ | |||
1 | 1. Both ir-kbd-i2c and lirc_zilog provide support for RX events for | ||
2 | the chips supported by lirc_zilog. Before moving lirc_zilog out of staging: | ||
3 | |||
4 | a. ir-kbd-i2c needs a module parameter added to allow the user to tell | ||
5 | ir-kbd-i2c to ignore Z8 IR units. | ||
6 | |||
7 | b. lirc_zilog should provide Rx key presses to the rc core like ir-kbd-i2c | ||
8 | does. | ||
9 | |||
10 | |||
11 | 2. lirc_zilog module ref-counting need examination. It has not been | ||
12 | verified that cdev and lirc_dev will take the proper module references on | ||
13 | lirc_zilog to prevent removal of lirc_zilog when the /dev/lircN device node | ||
14 | is open. | ||
15 | |||
16 | (The good news is ref-counting of lirc_zilog internal structures appears to be | ||
17 | complete. Testing has shown the cx18 module can be unloaded out from under | ||
18 | irw + lircd + lirc_dev, with the /dev/lirc0 device node open, with no adverse | ||
19 | effects. The cx18 module could then be reloaded and irw properly began | ||
20 | receiving button presses again and ir_send worked without error.) | ||
21 | |||
22 | |||
23 | 3. Bridge drivers, if able, should provide a chip reset() callback | ||
24 | to lirc_zilog via struct IR_i2c_init_data. cx18 and ivtv already have routines | ||
25 | to perform Z8 chip resets via GPIO manipulations. This would allow lirc_zilog | ||
26 | to bring the chip back to normal when it hangs, in the same places the | ||
27 | original lirc_pvr150 driver code does. This is not strictly needed, so it | ||
28 | is not required to move lirc_zilog out of staging. | ||
29 | |||
30 | Note: Both lirc_zilog and ir-kbd-i2c support the Zilog Z8 for IR, as programmed | ||
31 | and installed on Hauppauge products. When working on either module, developers | ||
32 | must consider at least the following bridge drivers which mention an IR Rx unit | ||
33 | at address 0x71 (indicative of a Z8): | ||
34 | |||
35 | ivtv cx18 hdpvr pvrusb2 bt8xx cx88 saa7134 | ||
36 | |||
diff --git a/drivers/staging/lirc/lirc_bt829.c b/drivers/staging/lirc/lirc_bt829.c new file mode 100644 index 00000000000..c5a0d27a02d --- /dev/null +++ b/drivers/staging/lirc/lirc_bt829.c | |||
@@ -0,0 +1,383 @@ | |||
1 | /* | ||
2 | * Remote control driver for the TV-card based on bt829 | ||
3 | * | ||
4 | * by Leonid Froenchenko <lfroen@galileo.co.il> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/threads.h> | ||
24 | #include <linux/sched.h> | ||
25 | #include <linux/ioport.h> | ||
26 | #include <linux/pci.h> | ||
27 | #include <linux/delay.h> | ||
28 | |||
29 | #include <media/lirc_dev.h> | ||
30 | |||
31 | static int poll_main(void); | ||
32 | static int atir_init_start(void); | ||
33 | |||
34 | static void write_index(unsigned char index, unsigned int value); | ||
35 | static unsigned int read_index(unsigned char index); | ||
36 | |||
37 | static void do_i2c_start(void); | ||
38 | static void do_i2c_stop(void); | ||
39 | |||
40 | static void seems_wr_byte(unsigned char al); | ||
41 | static unsigned char seems_rd_byte(void); | ||
42 | |||
43 | static unsigned int read_index(unsigned char al); | ||
44 | static void write_index(unsigned char ah, unsigned int edx); | ||
45 | |||
46 | static void cycle_delay(int cycle); | ||
47 | |||
48 | static void do_set_bits(unsigned char bl); | ||
49 | static unsigned char do_get_bits(void); | ||
50 | |||
51 | #define DATA_PCI_OFF 0x7FFC00 | ||
52 | #define WAIT_CYCLE 20 | ||
53 | |||
54 | #define DRIVER_NAME "lirc_bt829" | ||
55 | |||
56 | static int debug; | ||
57 | #define dprintk(fmt, args...) \ | ||
58 | do { \ | ||
59 | if (debug) \ | ||
60 | printk(KERN_DEBUG DRIVER_NAME ": "fmt, ## args); \ | ||
61 | } while (0) | ||
62 | |||
63 | static int atir_minor; | ||
64 | static unsigned long pci_addr_phys; | ||
65 | static unsigned char *pci_addr_lin; | ||
66 | |||
67 | static struct lirc_driver atir_driver; | ||
68 | |||
69 | static struct pci_dev *do_pci_probe(void) | ||
70 | { | ||
71 | struct pci_dev *my_dev; | ||
72 | my_dev = pci_get_device(PCI_VENDOR_ID_ATI, | ||
73 | PCI_DEVICE_ID_ATI_264VT, NULL); | ||
74 | if (my_dev) { | ||
75 | printk(KERN_ERR DRIVER_NAME ": Using device: %s\n", | ||
76 | pci_name(my_dev)); | ||
77 | pci_addr_phys = 0; | ||
78 | if (my_dev->resource[0].flags & IORESOURCE_MEM) { | ||
79 | pci_addr_phys = my_dev->resource[0].start; | ||
80 | printk(KERN_INFO DRIVER_NAME ": memory at 0x%08X\n", | ||
81 | (unsigned int)pci_addr_phys); | ||
82 | } | ||
83 | if (pci_addr_phys == 0) { | ||
84 | printk(KERN_ERR DRIVER_NAME ": no memory resource ?\n"); | ||
85 | return NULL; | ||
86 | } | ||
87 | } else { | ||
88 | printk(KERN_ERR DRIVER_NAME ": pci_probe failed\n"); | ||
89 | return NULL; | ||
90 | } | ||
91 | return my_dev; | ||
92 | } | ||
93 | |||
94 | static int atir_add_to_buf(void *data, struct lirc_buffer *buf) | ||
95 | { | ||
96 | unsigned char key; | ||
97 | int status; | ||
98 | status = poll_main(); | ||
99 | key = (status >> 8) & 0xFF; | ||
100 | if (status & 0xFF) { | ||
101 | dprintk("reading key %02X\n", key); | ||
102 | lirc_buffer_write(buf, &key); | ||
103 | return 0; | ||
104 | } | ||
105 | return -ENODATA; | ||
106 | } | ||
107 | |||
108 | static int atir_set_use_inc(void *data) | ||
109 | { | ||
110 | dprintk("driver is opened\n"); | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static void atir_set_use_dec(void *data) | ||
115 | { | ||
116 | dprintk("driver is closed\n"); | ||
117 | } | ||
118 | |||
119 | int init_module(void) | ||
120 | { | ||
121 | struct pci_dev *pdev; | ||
122 | |||
123 | pdev = do_pci_probe(); | ||
124 | if (pdev == NULL) | ||
125 | return -ENODEV; | ||
126 | |||
127 | if (!atir_init_start()) | ||
128 | return -ENODEV; | ||
129 | |||
130 | strcpy(atir_driver.name, "ATIR"); | ||
131 | atir_driver.minor = -1; | ||
132 | atir_driver.code_length = 8; | ||
133 | atir_driver.sample_rate = 10; | ||
134 | atir_driver.data = 0; | ||
135 | atir_driver.add_to_buf = atir_add_to_buf; | ||
136 | atir_driver.set_use_inc = atir_set_use_inc; | ||
137 | atir_driver.set_use_dec = atir_set_use_dec; | ||
138 | atir_driver.dev = &pdev->dev; | ||
139 | atir_driver.owner = THIS_MODULE; | ||
140 | |||
141 | atir_minor = lirc_register_driver(&atir_driver); | ||
142 | if (atir_minor < 0) { | ||
143 | printk(KERN_ERR DRIVER_NAME ": failed to register driver!\n"); | ||
144 | return atir_minor; | ||
145 | } | ||
146 | dprintk("driver is registered on minor %d\n", atir_minor); | ||
147 | |||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | |||
152 | void cleanup_module(void) | ||
153 | { | ||
154 | lirc_unregister_driver(atir_minor); | ||
155 | } | ||
156 | |||
157 | |||
158 | static int atir_init_start(void) | ||
159 | { | ||
160 | pci_addr_lin = ioremap(pci_addr_phys + DATA_PCI_OFF, 0x400); | ||
161 | if (pci_addr_lin == 0) { | ||
162 | printk(KERN_INFO DRIVER_NAME ": pci mem must be mapped\n"); | ||
163 | return 0; | ||
164 | } | ||
165 | return 1; | ||
166 | } | ||
167 | |||
168 | static void cycle_delay(int cycle) | ||
169 | { | ||
170 | udelay(WAIT_CYCLE*cycle); | ||
171 | } | ||
172 | |||
173 | |||
174 | static int poll_main() | ||
175 | { | ||
176 | unsigned char status_high, status_low; | ||
177 | |||
178 | do_i2c_start(); | ||
179 | |||
180 | seems_wr_byte(0xAA); | ||
181 | seems_wr_byte(0x01); | ||
182 | |||
183 | do_i2c_start(); | ||
184 | |||
185 | seems_wr_byte(0xAB); | ||
186 | |||
187 | status_low = seems_rd_byte(); | ||
188 | status_high = seems_rd_byte(); | ||
189 | |||
190 | do_i2c_stop(); | ||
191 | |||
192 | return (status_high << 8) | status_low; | ||
193 | } | ||
194 | |||
195 | static void do_i2c_start(void) | ||
196 | { | ||
197 | do_set_bits(3); | ||
198 | cycle_delay(4); | ||
199 | |||
200 | do_set_bits(1); | ||
201 | cycle_delay(7); | ||
202 | |||
203 | do_set_bits(0); | ||
204 | cycle_delay(2); | ||
205 | } | ||
206 | |||
207 | static void do_i2c_stop(void) | ||
208 | { | ||
209 | unsigned char bits; | ||
210 | bits = do_get_bits() & 0xFD; | ||
211 | do_set_bits(bits); | ||
212 | cycle_delay(1); | ||
213 | |||
214 | bits |= 1; | ||
215 | do_set_bits(bits); | ||
216 | cycle_delay(2); | ||
217 | |||
218 | bits |= 2; | ||
219 | do_set_bits(bits); | ||
220 | bits = 3; | ||
221 | do_set_bits(bits); | ||
222 | cycle_delay(2); | ||
223 | } | ||
224 | |||
225 | static void seems_wr_byte(unsigned char value) | ||
226 | { | ||
227 | int i; | ||
228 | unsigned char reg; | ||
229 | |||
230 | reg = do_get_bits(); | ||
231 | for (i = 0; i < 8; i++) { | ||
232 | if (value & 0x80) | ||
233 | reg |= 0x02; | ||
234 | else | ||
235 | reg &= 0xFD; | ||
236 | |||
237 | do_set_bits(reg); | ||
238 | cycle_delay(1); | ||
239 | |||
240 | reg |= 1; | ||
241 | do_set_bits(reg); | ||
242 | cycle_delay(1); | ||
243 | |||
244 | reg &= 0xFE; | ||
245 | do_set_bits(reg); | ||
246 | cycle_delay(1); | ||
247 | value <<= 1; | ||
248 | } | ||
249 | cycle_delay(2); | ||
250 | |||
251 | reg |= 2; | ||
252 | do_set_bits(reg); | ||
253 | |||
254 | reg |= 1; | ||
255 | do_set_bits(reg); | ||
256 | |||
257 | cycle_delay(1); | ||
258 | do_get_bits(); | ||
259 | |||
260 | reg &= 0xFE; | ||
261 | do_set_bits(reg); | ||
262 | cycle_delay(3); | ||
263 | } | ||
264 | |||
265 | static unsigned char seems_rd_byte(void) | ||
266 | { | ||
267 | int i; | ||
268 | int rd_byte; | ||
269 | unsigned char bits_2, bits_1; | ||
270 | |||
271 | bits_1 = do_get_bits() | 2; | ||
272 | do_set_bits(bits_1); | ||
273 | |||
274 | rd_byte = 0; | ||
275 | for (i = 0; i < 8; i++) { | ||
276 | bits_1 &= 0xFE; | ||
277 | do_set_bits(bits_1); | ||
278 | cycle_delay(2); | ||
279 | |||
280 | bits_1 |= 1; | ||
281 | do_set_bits(bits_1); | ||
282 | cycle_delay(1); | ||
283 | |||
284 | bits_2 = do_get_bits(); | ||
285 | if (bits_2 & 2) | ||
286 | rd_byte |= 1; | ||
287 | |||
288 | rd_byte <<= 1; | ||
289 | } | ||
290 | |||
291 | bits_1 = 0; | ||
292 | if (bits_2 == 0) | ||
293 | bits_1 |= 2; | ||
294 | |||
295 | do_set_bits(bits_1); | ||
296 | cycle_delay(2); | ||
297 | |||
298 | bits_1 |= 1; | ||
299 | do_set_bits(bits_1); | ||
300 | cycle_delay(3); | ||
301 | |||
302 | bits_1 &= 0xFE; | ||
303 | do_set_bits(bits_1); | ||
304 | cycle_delay(2); | ||
305 | |||
306 | rd_byte >>= 1; | ||
307 | rd_byte &= 0xFF; | ||
308 | return rd_byte; | ||
309 | } | ||
310 | |||
311 | static void do_set_bits(unsigned char new_bits) | ||
312 | { | ||
313 | int reg_val; | ||
314 | reg_val = read_index(0x34); | ||
315 | if (new_bits & 2) { | ||
316 | reg_val &= 0xFFFFFFDF; | ||
317 | reg_val |= 1; | ||
318 | } else { | ||
319 | reg_val &= 0xFFFFFFFE; | ||
320 | reg_val |= 0x20; | ||
321 | } | ||
322 | reg_val |= 0x10; | ||
323 | write_index(0x34, reg_val); | ||
324 | |||
325 | reg_val = read_index(0x31); | ||
326 | if (new_bits & 1) | ||
327 | reg_val |= 0x1000000; | ||
328 | else | ||
329 | reg_val &= 0xFEFFFFFF; | ||
330 | |||
331 | reg_val |= 0x8000000; | ||
332 | write_index(0x31, reg_val); | ||
333 | } | ||
334 | |||
335 | static unsigned char do_get_bits(void) | ||
336 | { | ||
337 | unsigned char bits; | ||
338 | int reg_val; | ||
339 | |||
340 | reg_val = read_index(0x34); | ||
341 | reg_val |= 0x10; | ||
342 | reg_val &= 0xFFFFFFDF; | ||
343 | write_index(0x34, reg_val); | ||
344 | |||
345 | reg_val = read_index(0x34); | ||
346 | bits = 0; | ||
347 | if (reg_val & 8) | ||
348 | bits |= 2; | ||
349 | else | ||
350 | bits &= 0xFD; | ||
351 | |||
352 | reg_val = read_index(0x31); | ||
353 | if (reg_val & 0x1000000) | ||
354 | bits |= 1; | ||
355 | else | ||
356 | bits &= 0xFE; | ||
357 | |||
358 | return bits; | ||
359 | } | ||
360 | |||
361 | static unsigned int read_index(unsigned char index) | ||
362 | { | ||
363 | unsigned char *addr; | ||
364 | unsigned int value; | ||
365 | /* addr = pci_addr_lin + DATA_PCI_OFF + ((index & 0xFF) << 2); */ | ||
366 | addr = pci_addr_lin + ((index & 0xFF) << 2); | ||
367 | value = readl(addr); | ||
368 | return value; | ||
369 | } | ||
370 | |||
371 | static void write_index(unsigned char index, unsigned int reg_val) | ||
372 | { | ||
373 | unsigned char *addr; | ||
374 | addr = pci_addr_lin + ((index & 0xFF) << 2); | ||
375 | writel(reg_val, addr); | ||
376 | } | ||
377 | |||
378 | MODULE_AUTHOR("Froenchenko Leonid"); | ||
379 | MODULE_DESCRIPTION("IR remote driver for bt829 based TV cards"); | ||
380 | MODULE_LICENSE("GPL"); | ||
381 | |||
382 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
383 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | ||
diff --git a/drivers/staging/lirc/lirc_ene0100.h b/drivers/staging/lirc/lirc_ene0100.h new file mode 100644 index 00000000000..06bebd6acc4 --- /dev/null +++ b/drivers/staging/lirc/lirc_ene0100.h | |||
@@ -0,0 +1,169 @@ | |||
1 | /* | ||
2 | * driver for ENE KB3926 B/C/D CIR (also known as ENE0100) | ||
3 | * | ||
4 | * Copyright (C) 2009 Maxim Levitsky <maximlevitsky@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation; either version 2 of the | ||
9 | * License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | ||
19 | * USA | ||
20 | */ | ||
21 | |||
22 | #include <media/lirc.h> | ||
23 | #include <media/lirc_dev.h> | ||
24 | |||
25 | /* hardware address */ | ||
26 | #define ENE_STATUS 0 /* hardware status - unused */ | ||
27 | #define ENE_ADDR_HI 1 /* hi byte of register address */ | ||
28 | #define ENE_ADDR_LO 2 /* low byte of register address */ | ||
29 | #define ENE_IO 3 /* read/write window */ | ||
30 | #define ENE_MAX_IO 4 | ||
31 | |||
32 | /* 8 bytes of samples, divided in 2 halfs*/ | ||
33 | #define ENE_SAMPLE_BUFFER 0xF8F0 /* regular sample buffer */ | ||
34 | #define ENE_SAMPLE_SPC_MASK (1 << 7) /* sample is space */ | ||
35 | #define ENE_SAMPLE_VALUE_MASK 0x7F | ||
36 | #define ENE_SAMPLE_OVERFLOW 0x7F | ||
37 | #define ENE_SAMPLES_SIZE 4 | ||
38 | |||
39 | /* fan input sample buffer */ | ||
40 | #define ENE_SAMPLE_BUFFER_FAN 0xF8FB /* this buffer holds high byte of */ | ||
41 | /* each sample of normal buffer */ | ||
42 | |||
43 | #define ENE_FAN_SMPL_PULS_MSK 0x8000 /* this bit of combined sample */ | ||
44 | /* if set, says that sample is pulse */ | ||
45 | #define ENE_FAN_VALUE_MASK 0x0FFF /* mask for valid bits of the value */ | ||
46 | |||
47 | /* first firmware register */ | ||
48 | #define ENE_FW1 0xF8F8 | ||
49 | #define ENE_FW1_ENABLE (1 << 0) /* enable fw processing */ | ||
50 | #define ENE_FW1_TXIRQ (1 << 1) /* TX interrupt pending */ | ||
51 | #define ENE_FW1_WAKE (1 << 6) /* enable wake from S3 */ | ||
52 | #define ENE_FW1_IRQ (1 << 7) /* enable interrupt */ | ||
53 | |||
54 | /* second firmware register */ | ||
55 | #define ENE_FW2 0xF8F9 | ||
56 | #define ENE_FW2_BUF_HIGH (1 << 0) /* which half of the buffer to read */ | ||
57 | #define ENE_FW2_IRQ_CLR (1 << 2) /* clear this on IRQ */ | ||
58 | #define ENE_FW2_GP40_AS_LEARN (1 << 4) /* normal input is used as */ | ||
59 | /* learning input */ | ||
60 | #define ENE_FW2_FAN_AS_NRML_IN (1 << 6) /* fan is used as normal input */ | ||
61 | #define ENE_FW2_LEARNING (1 << 7) /* hardware supports learning and TX */ | ||
62 | |||
63 | /* fan as input settings - only if learning capable */ | ||
64 | #define ENE_FAN_AS_IN1 0xFE30 /* fan init reg 1 */ | ||
65 | #define ENE_FAN_AS_IN1_EN 0xCD | ||
66 | #define ENE_FAN_AS_IN2 0xFE31 /* fan init reg 2 */ | ||
67 | #define ENE_FAN_AS_IN2_EN 0x03 | ||
68 | #define ENE_SAMPLE_PERIOD_FAN 61 /* fan input has fixed sample period */ | ||
69 | |||
70 | /* IRQ registers block (for revision B) */ | ||
71 | #define ENEB_IRQ 0xFD09 /* IRQ number */ | ||
72 | #define ENEB_IRQ_UNK1 0xFD17 /* unknown setting = 1 */ | ||
73 | #define ENEB_IRQ_STATUS 0xFD80 /* irq status */ | ||
74 | #define ENEB_IRQ_STATUS_IR (1 << 5) /* IR irq */ | ||
75 | |||
76 | /* IRQ registers block (for revision C,D) */ | ||
77 | #define ENEC_IRQ 0xFE9B /* new irq settings register */ | ||
78 | #define ENEC_IRQ_MASK 0x0F /* irq number mask */ | ||
79 | #define ENEC_IRQ_UNK_EN (1 << 4) /* always enabled */ | ||
80 | #define ENEC_IRQ_STATUS (1 << 5) /* irq status and ACK */ | ||
81 | |||
82 | /* CIR block settings */ | ||
83 | #define ENE_CIR_CONF1 0xFEC0 | ||
84 | #define ENE_CIR_CONF1_ADC_ON 0x7 /* receiver on gpio40 enabled */ | ||
85 | #define ENE_CIR_CONF1_LEARN1 (1 << 3) /* enabled on learning mode */ | ||
86 | #define ENE_CIR_CONF1_TX_ON 0x30 /* enabled on transmit */ | ||
87 | #define ENE_CIR_CONF1_TX_CARR (1 << 7) /* send TX carrier or not */ | ||
88 | |||
89 | #define ENE_CIR_CONF2 0xFEC1 /* unknown setting = 0 */ | ||
90 | #define ENE_CIR_CONF2_LEARN2 (1 << 4) /* set on enable learning */ | ||
91 | #define ENE_CIR_CONF2_GPIO40DIS (1 << 5) /* disable normal input via gpio40 */ | ||
92 | |||
93 | #define ENE_CIR_SAMPLE_PERIOD 0xFEC8 /* sample period in us */ | ||
94 | #define ENE_CIR_SAMPLE_OVERFLOW (1 << 7) /* interrupt on overflows if set */ | ||
95 | |||
96 | |||
97 | /* transmitter - not implemented yet */ | ||
98 | /* KB3926C and higher */ | ||
99 | /* transmission is very similar to receiving, a byte is written to */ | ||
100 | /* ENE_TX_INPUT, in same manner as it is read from sample buffer */ | ||
101 | /* sample period is fixed*/ | ||
102 | |||
103 | |||
104 | /* transmitter ports */ | ||
105 | #define ENE_TX_PORT1 0xFC01 /* this enables one or both */ | ||
106 | #define ENE_TX_PORT1_EN (1 << 5) /* TX ports */ | ||
107 | #define ENE_TX_PORT2 0xFC08 | ||
108 | #define ENE_TX_PORT2_EN (1 << 1) | ||
109 | |||
110 | #define ENE_TX_INPUT 0xFEC9 /* next byte to transmit */ | ||
111 | #define ENE_TX_SPC_MASK (1 << 7) /* Transmitted sample is space */ | ||
112 | #define ENE_TX_UNK1 0xFECB /* set to 0x63 */ | ||
113 | #define ENE_TX_SMPL_PERIOD 50 /* transmit sample period */ | ||
114 | |||
115 | |||
116 | #define ENE_TX_CARRIER 0xFECE /* TX carrier * 2 (khz) */ | ||
117 | #define ENE_TX_CARRIER_UNKBIT 0x80 /* This bit set on transmit */ | ||
118 | #define ENE_TX_CARRIER_LOW 0xFECF /* TX carrier / 2 */ | ||
119 | |||
120 | /* Hardware versions */ | ||
121 | #define ENE_HW_VERSION 0xFF00 /* hardware revision */ | ||
122 | #define ENE_HW_UNK 0xFF1D | ||
123 | #define ENE_HW_UNK_CLR (1 << 2) | ||
124 | #define ENE_HW_VER_MAJOR 0xFF1E /* chip version */ | ||
125 | #define ENE_HW_VER_MINOR 0xFF1F | ||
126 | #define ENE_HW_VER_OLD 0xFD00 | ||
127 | |||
128 | #define same_sign(a, b) ((((a) > 0) && (b) > 0) || ((a) < 0 && (b) < 0)) | ||
129 | |||
130 | #define ENE_DRIVER_NAME "enecir" | ||
131 | #define ENE_MAXGAP 250000 /* this is amount of time we wait | ||
132 | before turning the sampler, chosen | ||
133 | arbitry */ | ||
134 | |||
135 | #define space(len) (-(len)) /* add a space */ | ||
136 | |||
137 | /* software defines */ | ||
138 | #define ENE_IRQ_RX 1 | ||
139 | #define ENE_IRQ_TX 2 | ||
140 | |||
141 | #define ENE_HW_B 1 /* 3926B */ | ||
142 | #define ENE_HW_C 2 /* 3926C */ | ||
143 | #define ENE_HW_D 3 /* 3926D */ | ||
144 | |||
145 | #define ene_printk(level, text, ...) \ | ||
146 | printk(level ENE_DRIVER_NAME ": " text, ## __VA_ARGS__) | ||
147 | |||
148 | struct ene_device { | ||
149 | struct pnp_dev *pnp_dev; | ||
150 | struct lirc_driver *lirc_driver; | ||
151 | |||
152 | /* hw settings */ | ||
153 | unsigned long hw_io; | ||
154 | int irq; | ||
155 | |||
156 | int hw_revision; /* hardware revision */ | ||
157 | int hw_learning_and_tx_capable; /* learning capable */ | ||
158 | int hw_gpio40_learning; /* gpio40 is learning */ | ||
159 | int hw_fan_as_normal_input; /* fan input is used as regular input */ | ||
160 | |||
161 | /* device data */ | ||
162 | int idle; | ||
163 | int fan_input_inuse; | ||
164 | |||
165 | int sample; | ||
166 | int in_use; | ||
167 | |||
168 | struct timeval gap_start; | ||
169 | }; | ||
diff --git a/drivers/staging/lirc/lirc_igorplugusb.c b/drivers/staging/lirc/lirc_igorplugusb.c new file mode 100644 index 00000000000..0dc2c2b22c2 --- /dev/null +++ b/drivers/staging/lirc/lirc_igorplugusb.c | |||
@@ -0,0 +1,577 @@ | |||
1 | /* | ||
2 | * lirc_igorplugusb - USB remote support for LIRC | ||
3 | * | ||
4 | * Supports the standard homebrew IgorPlugUSB receiver with Igor's firmware. | ||
5 | * See http://www.cesko.host.sk/IgorPlugUSB/IgorPlug-USB%20(AVR)_eng.htm | ||
6 | * | ||
7 | * The device can only record bursts of up to 36 pulses/spaces. | ||
8 | * Works fine with RC5. Longer commands lead to device buffer overrun. | ||
9 | * (Maybe a better firmware or a microcontroller with more ram can help?) | ||
10 | * | ||
11 | * Version 0.1 [beta status] | ||
12 | * | ||
13 | * Copyright (C) 2004 Jan M. Hochstein | ||
14 | * <hochstein@algo.informatik.tu-darmstadt.de> | ||
15 | * | ||
16 | * This driver was derived from: | ||
17 | * Paul Miller <pmiller9@users.sourceforge.net> | ||
18 | * "lirc_atiusb" module | ||
19 | * Vladimir Dergachev <volodya@minspring.com>'s 2002 | ||
20 | * "USB ATI Remote support" (input device) | ||
21 | * Adrian Dewhurst <sailor-lk@sailorfrag.net>'s 2002 | ||
22 | * "USB StreamZap remote driver" (LIRC) | ||
23 | * Artur Lipowski <alipowski@kki.net.pl>'s 2002 | ||
24 | * "lirc_dev" and "lirc_gpio" LIRC modules | ||
25 | */ | ||
26 | |||
27 | /* | ||
28 | * This program is free software; you can redistribute it and/or modify | ||
29 | * it under the terms of the GNU General Public License as published by | ||
30 | * the Free Software Foundation; either version 2 of the License, or | ||
31 | * (at your option) any later version. | ||
32 | * | ||
33 | * This program is distributed in the hope that it will be useful, | ||
34 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
35 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
36 | * GNU General Public License for more details. | ||
37 | * | ||
38 | * You should have received a copy of the GNU General Public License | ||
39 | * along with this program; if not, write to the Free Software | ||
40 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
41 | */ | ||
42 | |||
43 | #include <linux/module.h> | ||
44 | #include <linux/kernel.h> | ||
45 | #include <linux/kmod.h> | ||
46 | #include <linux/sched.h> | ||
47 | #include <linux/errno.h> | ||
48 | #include <linux/fs.h> | ||
49 | #include <linux/usb.h> | ||
50 | #include <linux/time.h> | ||
51 | |||
52 | #include <media/lirc.h> | ||
53 | #include <media/lirc_dev.h> | ||
54 | |||
55 | |||
56 | /* module identification */ | ||
57 | #define DRIVER_VERSION "0.2" | ||
58 | #define DRIVER_AUTHOR \ | ||
59 | "Jan M. Hochstein <hochstein@algo.informatik.tu-darmstadt.de>" | ||
60 | #define DRIVER_DESC "Igorplug USB remote driver for LIRC" | ||
61 | #define DRIVER_NAME "lirc_igorplugusb" | ||
62 | |||
63 | /* debugging support */ | ||
64 | #ifdef CONFIG_USB_DEBUG | ||
65 | static int debug = 1; | ||
66 | #else | ||
67 | static int debug; | ||
68 | #endif | ||
69 | |||
70 | #define dprintk(fmt, args...) \ | ||
71 | do { \ | ||
72 | if (debug) \ | ||
73 | printk(KERN_DEBUG fmt, ## args); \ | ||
74 | } while (0) | ||
75 | |||
76 | /* One mode2 pulse/space has 4 bytes. */ | ||
77 | #define CODE_LENGTH sizeof(int) | ||
78 | |||
79 | /* Igor's firmware cannot record bursts longer than 36. */ | ||
80 | #define DEVICE_BUFLEN 36 | ||
81 | |||
82 | /* | ||
83 | * Header at the beginning of the device's buffer: | ||
84 | * unsigned char data_length | ||
85 | * unsigned char data_start (!=0 means ring-buffer overrun) | ||
86 | * unsigned char counter (incremented by each burst) | ||
87 | */ | ||
88 | #define DEVICE_HEADERLEN 3 | ||
89 | |||
90 | /* This is for the gap */ | ||
91 | #define ADDITIONAL_LIRC_BYTES 2 | ||
92 | |||
93 | /* times to poll per second */ | ||
94 | #define SAMPLE_RATE 100 | ||
95 | static int sample_rate = SAMPLE_RATE; | ||
96 | |||
97 | |||
98 | /**** Igor's USB Request Codes */ | ||
99 | |||
100 | #define SET_INFRABUFFER_EMPTY 1 | ||
101 | /** | ||
102 | * Params: none | ||
103 | * Answer: empty | ||
104 | */ | ||
105 | |||
106 | #define GET_INFRACODE 2 | ||
107 | /** | ||
108 | * Params: | ||
109 | * wValue: offset to begin reading infra buffer | ||
110 | * | ||
111 | * Answer: infra data | ||
112 | */ | ||
113 | |||
114 | #define SET_DATAPORT_DIRECTION 3 | ||
115 | /** | ||
116 | * Params: | ||
117 | * wValue: (byte) 1 bit for each data port pin (0=in, 1=out) | ||
118 | * | ||
119 | * Answer: empty | ||
120 | */ | ||
121 | |||
122 | #define GET_DATAPORT_DIRECTION 4 | ||
123 | /** | ||
124 | * Params: none | ||
125 | * | ||
126 | * Answer: (byte) 1 bit for each data port pin (0=in, 1=out) | ||
127 | */ | ||
128 | |||
129 | #define SET_OUT_DATAPORT 5 | ||
130 | /** | ||
131 | * Params: | ||
132 | * wValue: byte to write to output data port | ||
133 | * | ||
134 | * Answer: empty | ||
135 | */ | ||
136 | |||
137 | #define GET_OUT_DATAPORT 6 | ||
138 | /** | ||
139 | * Params: none | ||
140 | * | ||
141 | * Answer: least significant 3 bits read from output data port | ||
142 | */ | ||
143 | |||
144 | #define GET_IN_DATAPORT 7 | ||
145 | /** | ||
146 | * Params: none | ||
147 | * | ||
148 | * Answer: least significant 3 bits read from input data port | ||
149 | */ | ||
150 | |||
151 | #define READ_EEPROM 8 | ||
152 | /** | ||
153 | * Params: | ||
154 | * wValue: offset to begin reading EEPROM | ||
155 | * | ||
156 | * Answer: EEPROM bytes | ||
157 | */ | ||
158 | |||
159 | #define WRITE_EEPROM 9 | ||
160 | /** | ||
161 | * Params: | ||
162 | * wValue: offset to EEPROM byte | ||
163 | * wIndex: byte to write | ||
164 | * | ||
165 | * Answer: empty | ||
166 | */ | ||
167 | |||
168 | #define SEND_RS232 10 | ||
169 | /** | ||
170 | * Params: | ||
171 | * wValue: byte to send | ||
172 | * | ||
173 | * Answer: empty | ||
174 | */ | ||
175 | |||
176 | #define RECV_RS232 11 | ||
177 | /** | ||
178 | * Params: none | ||
179 | * | ||
180 | * Answer: byte received | ||
181 | */ | ||
182 | |||
183 | #define SET_RS232_BAUD 12 | ||
184 | /** | ||
185 | * Params: | ||
186 | * wValue: byte to write to UART bit rate register (UBRR) | ||
187 | * | ||
188 | * Answer: empty | ||
189 | */ | ||
190 | |||
191 | #define GET_RS232_BAUD 13 | ||
192 | /** | ||
193 | * Params: none | ||
194 | * | ||
195 | * Answer: byte read from UART bit rate register (UBRR) | ||
196 | */ | ||
197 | |||
198 | |||
199 | /* data structure for each usb remote */ | ||
200 | struct igorplug { | ||
201 | |||
202 | /* usb */ | ||
203 | struct usb_device *usbdev; | ||
204 | int devnum; | ||
205 | |||
206 | unsigned char *buf_in; | ||
207 | unsigned int len_in; | ||
208 | int in_space; | ||
209 | struct timeval last_time; | ||
210 | |||
211 | dma_addr_t dma_in; | ||
212 | |||
213 | /* lirc */ | ||
214 | struct lirc_driver *d; | ||
215 | |||
216 | /* handle sending (init strings) */ | ||
217 | int send_flags; | ||
218 | }; | ||
219 | |||
220 | static int unregister_from_lirc(struct igorplug *ir) | ||
221 | { | ||
222 | struct lirc_driver *d; | ||
223 | int devnum; | ||
224 | |||
225 | if (!ir) { | ||
226 | printk(KERN_ERR "%s: called with NULL device struct!\n", | ||
227 | __func__); | ||
228 | return -EINVAL; | ||
229 | } | ||
230 | |||
231 | devnum = ir->devnum; | ||
232 | d = ir->d; | ||
233 | |||
234 | if (!d) { | ||
235 | printk(KERN_ERR "%s: called with NULL lirc driver struct!\n", | ||
236 | __func__); | ||
237 | return -EINVAL; | ||
238 | } | ||
239 | |||
240 | dprintk(DRIVER_NAME "[%d]: calling lirc_unregister_driver\n", devnum); | ||
241 | lirc_unregister_driver(d->minor); | ||
242 | |||
243 | kfree(d); | ||
244 | ir->d = NULL; | ||
245 | kfree(ir); | ||
246 | |||
247 | return devnum; | ||
248 | } | ||
249 | |||
250 | static int set_use_inc(void *data) | ||
251 | { | ||
252 | struct igorplug *ir = data; | ||
253 | |||
254 | if (!ir) { | ||
255 | printk(DRIVER_NAME "[?]: set_use_inc called with no context\n"); | ||
256 | return -EIO; | ||
257 | } | ||
258 | |||
259 | dprintk(DRIVER_NAME "[%d]: set use inc\n", ir->devnum); | ||
260 | |||
261 | if (!ir->usbdev) | ||
262 | return -ENODEV; | ||
263 | |||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | static void set_use_dec(void *data) | ||
268 | { | ||
269 | struct igorplug *ir = data; | ||
270 | |||
271 | if (!ir) { | ||
272 | printk(DRIVER_NAME "[?]: set_use_dec called with no context\n"); | ||
273 | return; | ||
274 | } | ||
275 | |||
276 | dprintk(DRIVER_NAME "[%d]: set use dec\n", ir->devnum); | ||
277 | } | ||
278 | |||
279 | static void send_fragment(struct igorplug *ir, struct lirc_buffer *buf, | ||
280 | int i, int max) | ||
281 | { | ||
282 | int code; | ||
283 | |||
284 | /* MODE2: pulse/space (PULSE_BIT) in 1us units */ | ||
285 | while (i < max) { | ||
286 | /* 1 Igor-tick = 85.333333 us */ | ||
287 | code = (unsigned int)ir->buf_in[i] * 85 + | ||
288 | (unsigned int)ir->buf_in[i] / 3; | ||
289 | ir->last_time.tv_usec += code; | ||
290 | if (ir->in_space) | ||
291 | code |= PULSE_BIT; | ||
292 | lirc_buffer_write(buf, (unsigned char *)&code); | ||
293 | /* 1 chunk = CODE_LENGTH bytes */ | ||
294 | ir->in_space ^= 1; | ||
295 | ++i; | ||
296 | } | ||
297 | } | ||
298 | |||
299 | /** | ||
300 | * Called in user context. | ||
301 | * return 0 if data was added to the buffer and | ||
302 | * -ENODATA if none was available. This should add some number of bits | ||
303 | * evenly divisible by code_length to the buffer | ||
304 | */ | ||
305 | static int igorplugusb_remote_poll(void *data, struct lirc_buffer *buf) | ||
306 | { | ||
307 | int ret; | ||
308 | struct igorplug *ir = (struct igorplug *)data; | ||
309 | |||
310 | if (!ir || !ir->usbdev) /* Has the device been removed? */ | ||
311 | return -ENODEV; | ||
312 | |||
313 | memset(ir->buf_in, 0, ir->len_in); | ||
314 | |||
315 | ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), | ||
316 | GET_INFRACODE, USB_TYPE_VENDOR | USB_DIR_IN, | ||
317 | 0/* offset */, /*unused*/0, | ||
318 | ir->buf_in, ir->len_in, | ||
319 | /*timeout*/HZ * USB_CTRL_GET_TIMEOUT); | ||
320 | if (ret > 0) { | ||
321 | int code, timediff; | ||
322 | struct timeval now; | ||
323 | |||
324 | /* ACK packet has 1 byte --> ignore */ | ||
325 | if (ret < DEVICE_HEADERLEN) | ||
326 | return -ENODATA; | ||
327 | |||
328 | dprintk(DRIVER_NAME ": Got %d bytes. Header: %02x %02x %02x\n", | ||
329 | ret, ir->buf_in[0], ir->buf_in[1], ir->buf_in[2]); | ||
330 | |||
331 | do_gettimeofday(&now); | ||
332 | timediff = now.tv_sec - ir->last_time.tv_sec; | ||
333 | if (timediff + 1 > PULSE_MASK / 1000000) | ||
334 | timediff = PULSE_MASK; | ||
335 | else { | ||
336 | timediff *= 1000000; | ||
337 | timediff += now.tv_usec - ir->last_time.tv_usec; | ||
338 | } | ||
339 | ir->last_time.tv_sec = now.tv_sec; | ||
340 | ir->last_time.tv_usec = now.tv_usec; | ||
341 | |||
342 | /* create leading gap */ | ||
343 | code = timediff; | ||
344 | lirc_buffer_write(buf, (unsigned char *)&code); | ||
345 | ir->in_space = 1; /* next comes a pulse */ | ||
346 | |||
347 | if (ir->buf_in[2] == 0) | ||
348 | send_fragment(ir, buf, DEVICE_HEADERLEN, ret); | ||
349 | else { | ||
350 | printk(KERN_WARNING DRIVER_NAME | ||
351 | "[%d]: Device buffer overrun.\n", ir->devnum); | ||
352 | /* HHHNNNNNNNNNNNOOOOOOOO H = header | ||
353 | <---[2]---> N = newer | ||
354 | <---------ret--------> O = older */ | ||
355 | ir->buf_in[2] %= ret - DEVICE_HEADERLEN; /* sanitize */ | ||
356 | /* keep even-ness to not desync pulse/pause */ | ||
357 | send_fragment(ir, buf, DEVICE_HEADERLEN + | ||
358 | ir->buf_in[2] - (ir->buf_in[2] & 1), ret); | ||
359 | send_fragment(ir, buf, DEVICE_HEADERLEN, | ||
360 | DEVICE_HEADERLEN + ir->buf_in[2]); | ||
361 | } | ||
362 | |||
363 | ret = usb_control_msg( | ||
364 | ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), | ||
365 | SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN, | ||
366 | /*unused*/0, /*unused*/0, | ||
367 | /*dummy*/ir->buf_in, /*dummy*/ir->len_in, | ||
368 | /*timeout*/HZ * USB_CTRL_GET_TIMEOUT); | ||
369 | if (ret < 0) | ||
370 | printk(DRIVER_NAME "[%d]: SET_INFRABUFFER_EMPTY: " | ||
371 | "error %d\n", ir->devnum, ret); | ||
372 | return 0; | ||
373 | } else if (ret < 0) | ||
374 | printk(DRIVER_NAME "[%d]: GET_INFRACODE: error %d\n", | ||
375 | ir->devnum, ret); | ||
376 | |||
377 | return -ENODATA; | ||
378 | } | ||
379 | |||
380 | |||
381 | |||
382 | static int igorplugusb_remote_probe(struct usb_interface *intf, | ||
383 | const struct usb_device_id *id) | ||
384 | { | ||
385 | struct usb_device *dev = NULL; | ||
386 | struct usb_host_interface *idesc = NULL; | ||
387 | struct usb_endpoint_descriptor *ep; | ||
388 | struct igorplug *ir = NULL; | ||
389 | struct lirc_driver *driver = NULL; | ||
390 | int devnum, pipe, maxp; | ||
391 | int minor = 0; | ||
392 | char buf[63], name[128] = ""; | ||
393 | int mem_failure = 0; | ||
394 | int ret; | ||
395 | |||
396 | dprintk(DRIVER_NAME ": usb probe called.\n"); | ||
397 | |||
398 | dev = interface_to_usbdev(intf); | ||
399 | |||
400 | idesc = intf->cur_altsetting; | ||
401 | |||
402 | if (idesc->desc.bNumEndpoints != 1) | ||
403 | return -ENODEV; | ||
404 | |||
405 | ep = &idesc->endpoint->desc; | ||
406 | if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) | ||
407 | != USB_DIR_IN) | ||
408 | || (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) | ||
409 | != USB_ENDPOINT_XFER_CONTROL) | ||
410 | return -ENODEV; | ||
411 | |||
412 | pipe = usb_rcvctrlpipe(dev, ep->bEndpointAddress); | ||
413 | devnum = dev->devnum; | ||
414 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); | ||
415 | |||
416 | dprintk(DRIVER_NAME "[%d]: bytes_in_key=%zu maxp=%d\n", | ||
417 | devnum, CODE_LENGTH, maxp); | ||
418 | |||
419 | mem_failure = 0; | ||
420 | ir = kzalloc(sizeof(struct igorplug), GFP_KERNEL); | ||
421 | if (!ir) { | ||
422 | mem_failure = 1; | ||
423 | goto mem_failure_switch; | ||
424 | } | ||
425 | driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); | ||
426 | if (!driver) { | ||
427 | mem_failure = 2; | ||
428 | goto mem_failure_switch; | ||
429 | } | ||
430 | |||
431 | ir->buf_in = usb_alloc_coherent(dev, DEVICE_BUFLEN + DEVICE_HEADERLEN, | ||
432 | GFP_ATOMIC, &ir->dma_in); | ||
433 | if (!ir->buf_in) { | ||
434 | mem_failure = 3; | ||
435 | goto mem_failure_switch; | ||
436 | } | ||
437 | |||
438 | strcpy(driver->name, DRIVER_NAME " "); | ||
439 | driver->minor = -1; | ||
440 | driver->code_length = CODE_LENGTH * 8; /* in bits */ | ||
441 | driver->features = LIRC_CAN_REC_MODE2; | ||
442 | driver->data = ir; | ||
443 | driver->chunk_size = CODE_LENGTH; | ||
444 | driver->buffer_size = DEVICE_BUFLEN + ADDITIONAL_LIRC_BYTES; | ||
445 | driver->set_use_inc = &set_use_inc; | ||
446 | driver->set_use_dec = &set_use_dec; | ||
447 | driver->sample_rate = sample_rate; /* per second */ | ||
448 | driver->add_to_buf = &igorplugusb_remote_poll; | ||
449 | driver->dev = &intf->dev; | ||
450 | driver->owner = THIS_MODULE; | ||
451 | |||
452 | minor = lirc_register_driver(driver); | ||
453 | if (minor < 0) | ||
454 | mem_failure = 9; | ||
455 | |||
456 | mem_failure_switch: | ||
457 | |||
458 | switch (mem_failure) { | ||
459 | case 9: | ||
460 | usb_free_coherent(dev, DEVICE_BUFLEN + DEVICE_HEADERLEN, | ||
461 | ir->buf_in, ir->dma_in); | ||
462 | case 3: | ||
463 | kfree(driver); | ||
464 | case 2: | ||
465 | kfree(ir); | ||
466 | case 1: | ||
467 | printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n", | ||
468 | devnum, mem_failure); | ||
469 | return -ENOMEM; | ||
470 | } | ||
471 | |||
472 | driver->minor = minor; | ||
473 | ir->d = driver; | ||
474 | ir->devnum = devnum; | ||
475 | ir->usbdev = dev; | ||
476 | ir->len_in = DEVICE_BUFLEN + DEVICE_HEADERLEN; | ||
477 | ir->in_space = 1; /* First mode2 event is a space. */ | ||
478 | do_gettimeofday(&ir->last_time); | ||
479 | |||
480 | if (dev->descriptor.iManufacturer | ||
481 | && usb_string(dev, dev->descriptor.iManufacturer, | ||
482 | buf, sizeof(buf)) > 0) | ||
483 | strlcpy(name, buf, sizeof(name)); | ||
484 | if (dev->descriptor.iProduct | ||
485 | && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0) | ||
486 | snprintf(name + strlen(name), sizeof(name) - strlen(name), | ||
487 | " %s", buf); | ||
488 | printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", devnum, name, | ||
489 | dev->bus->busnum, devnum); | ||
490 | |||
491 | /* clear device buffer */ | ||
492 | ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), | ||
493 | SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN, | ||
494 | /*unused*/0, /*unused*/0, | ||
495 | /*dummy*/ir->buf_in, /*dummy*/ir->len_in, | ||
496 | /*timeout*/HZ * USB_CTRL_GET_TIMEOUT); | ||
497 | if (ret < 0) | ||
498 | printk(DRIVER_NAME "[%d]: SET_INFRABUFFER_EMPTY: error %d\n", | ||
499 | devnum, ret); | ||
500 | |||
501 | usb_set_intfdata(intf, ir); | ||
502 | return 0; | ||
503 | } | ||
504 | |||
505 | |||
506 | static void igorplugusb_remote_disconnect(struct usb_interface *intf) | ||
507 | { | ||
508 | struct usb_device *usbdev = interface_to_usbdev(intf); | ||
509 | struct igorplug *ir = usb_get_intfdata(intf); | ||
510 | struct device *dev = &intf->dev; | ||
511 | int devnum; | ||
512 | |||
513 | usb_set_intfdata(intf, NULL); | ||
514 | |||
515 | if (!ir || !ir->d) | ||
516 | return; | ||
517 | |||
518 | ir->usbdev = NULL; | ||
519 | |||
520 | usb_free_coherent(usbdev, ir->len_in, ir->buf_in, ir->dma_in); | ||
521 | |||
522 | devnum = unregister_from_lirc(ir); | ||
523 | |||
524 | dev_info(dev, DRIVER_NAME "[%d]: %s done\n", devnum, __func__); | ||
525 | } | ||
526 | |||
527 | static struct usb_device_id igorplugusb_remote_id_table[] = { | ||
528 | /* Igor Plug USB (Atmel's Manufact. ID) */ | ||
529 | { USB_DEVICE(0x03eb, 0x0002) }, | ||
530 | /* Fit PC2 Infrared Adapter */ | ||
531 | { USB_DEVICE(0x03eb, 0x21fe) }, | ||
532 | |||
533 | /* Terminating entry */ | ||
534 | { } | ||
535 | }; | ||
536 | |||
537 | static struct usb_driver igorplugusb_remote_driver = { | ||
538 | .name = DRIVER_NAME, | ||
539 | .probe = igorplugusb_remote_probe, | ||
540 | .disconnect = igorplugusb_remote_disconnect, | ||
541 | .id_table = igorplugusb_remote_id_table | ||
542 | }; | ||
543 | |||
544 | static int __init igorplugusb_remote_init(void) | ||
545 | { | ||
546 | int ret = 0; | ||
547 | |||
548 | dprintk(DRIVER_NAME ": loaded, debug mode enabled\n"); | ||
549 | |||
550 | ret = usb_register(&igorplugusb_remote_driver); | ||
551 | if (ret) | ||
552 | printk(KERN_ERR DRIVER_NAME ": usb register failed!\n"); | ||
553 | |||
554 | return ret; | ||
555 | } | ||
556 | |||
557 | static void __exit igorplugusb_remote_exit(void) | ||
558 | { | ||
559 | usb_deregister(&igorplugusb_remote_driver); | ||
560 | } | ||
561 | |||
562 | module_init(igorplugusb_remote_init); | ||
563 | module_exit(igorplugusb_remote_exit); | ||
564 | |||
565 | #include <linux/vermagic.h> | ||
566 | MODULE_INFO(vermagic, VERMAGIC_STRING); | ||
567 | |||
568 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
569 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
570 | MODULE_LICENSE("GPL"); | ||
571 | MODULE_DEVICE_TABLE(usb, igorplugusb_remote_id_table); | ||
572 | |||
573 | module_param(sample_rate, int, S_IRUGO | S_IWUSR); | ||
574 | MODULE_PARM_DESC(sample_rate, "Sampling rate in Hz (default: 100)"); | ||
575 | |||
576 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
577 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | ||
diff --git a/drivers/staging/lirc/lirc_imon.c b/drivers/staging/lirc/lirc_imon.c new file mode 100644 index 00000000000..4a9e563f40f --- /dev/null +++ b/drivers/staging/lirc/lirc_imon.c | |||
@@ -0,0 +1,1050 @@ | |||
1 | /* | ||
2 | * lirc_imon.c: LIRC/VFD/LCD driver for SoundGraph iMON IR/VFD/LCD | ||
3 | * including the iMON PAD model | ||
4 | * | ||
5 | * Copyright(C) 2004 Venky Raju(dev@venky.ws) | ||
6 | * Copyright(C) 2009 Jarod Wilson <jarod@wilsonet.com> | ||
7 | * | ||
8 | * lirc_imon is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/errno.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/uaccess.h> | ||
29 | #include <linux/usb.h> | ||
30 | |||
31 | #include <media/lirc.h> | ||
32 | #include <media/lirc_dev.h> | ||
33 | |||
34 | |||
35 | #define MOD_AUTHOR "Venky Raju <dev@venky.ws>" | ||
36 | #define MOD_DESC "Driver for SoundGraph iMON MultiMedia IR/Display" | ||
37 | #define MOD_NAME "lirc_imon" | ||
38 | #define MOD_VERSION "0.8" | ||
39 | |||
40 | #define DISPLAY_MINOR_BASE 144 | ||
41 | #define DEVICE_NAME "lcd%d" | ||
42 | |||
43 | #define BUF_CHUNK_SIZE 4 | ||
44 | #define BUF_SIZE 128 | ||
45 | |||
46 | #define BIT_DURATION 250 /* each bit received is 250us */ | ||
47 | |||
48 | /*** P R O T O T Y P E S ***/ | ||
49 | |||
50 | /* USB Callback prototypes */ | ||
51 | static int imon_probe(struct usb_interface *interface, | ||
52 | const struct usb_device_id *id); | ||
53 | static void imon_disconnect(struct usb_interface *interface); | ||
54 | static void usb_rx_callback(struct urb *urb); | ||
55 | static void usb_tx_callback(struct urb *urb); | ||
56 | |||
57 | /* suspend/resume support */ | ||
58 | static int imon_resume(struct usb_interface *intf); | ||
59 | static int imon_suspend(struct usb_interface *intf, pm_message_t message); | ||
60 | |||
61 | /* Display file_operations function prototypes */ | ||
62 | static int display_open(struct inode *inode, struct file *file); | ||
63 | static int display_close(struct inode *inode, struct file *file); | ||
64 | |||
65 | /* VFD write operation */ | ||
66 | static ssize_t vfd_write(struct file *file, const char *buf, | ||
67 | size_t n_bytes, loff_t *pos); | ||
68 | |||
69 | /* LIRC driver function prototypes */ | ||
70 | static int ir_open(void *data); | ||
71 | static void ir_close(void *data); | ||
72 | |||
73 | /* Driver init/exit prototypes */ | ||
74 | static int __init imon_init(void); | ||
75 | static void __exit imon_exit(void); | ||
76 | |||
77 | /*** G L O B A L S ***/ | ||
78 | #define IMON_DATA_BUF_SZ 35 | ||
79 | |||
80 | struct imon_context { | ||
81 | struct usb_device *usbdev; | ||
82 | /* Newer devices have two interfaces */ | ||
83 | int display; /* not all controllers do */ | ||
84 | int display_isopen; /* display port has been opened */ | ||
85 | int ir_isopen; /* IR port open */ | ||
86 | int dev_present; /* USB device presence */ | ||
87 | struct mutex ctx_lock; /* to lock this object */ | ||
88 | wait_queue_head_t remove_ok; /* For unexpected USB disconnects */ | ||
89 | |||
90 | int vfd_proto_6p; /* some VFD require a 6th packet */ | ||
91 | |||
92 | struct lirc_driver *driver; | ||
93 | struct usb_endpoint_descriptor *rx_endpoint; | ||
94 | struct usb_endpoint_descriptor *tx_endpoint; | ||
95 | struct urb *rx_urb; | ||
96 | struct urb *tx_urb; | ||
97 | unsigned char usb_rx_buf[8]; | ||
98 | unsigned char usb_tx_buf[8]; | ||
99 | |||
100 | struct rx_data { | ||
101 | int count; /* length of 0 or 1 sequence */ | ||
102 | int prev_bit; /* logic level of sequence */ | ||
103 | int initial_space; /* initial space flag */ | ||
104 | } rx; | ||
105 | |||
106 | struct tx_t { | ||
107 | unsigned char data_buf[IMON_DATA_BUF_SZ]; /* user data buffer */ | ||
108 | struct completion finished; /* wait for write to finish */ | ||
109 | atomic_t busy; /* write in progress */ | ||
110 | int status; /* status of tx completion */ | ||
111 | } tx; | ||
112 | }; | ||
113 | |||
114 | static const struct file_operations display_fops = { | ||
115 | .owner = THIS_MODULE, | ||
116 | .open = &display_open, | ||
117 | .write = &vfd_write, | ||
118 | .release = &display_close, | ||
119 | .llseek = noop_llseek, | ||
120 | }; | ||
121 | |||
122 | /* | ||
123 | * USB Device ID for iMON USB Control Boards | ||
124 | * | ||
125 | * The Windows drivers contain 6 different inf files, more or less one for | ||
126 | * each new device until the 0x0034-0x0046 devices, which all use the same | ||
127 | * driver. Some of the devices in the 34-46 range haven't been definitively | ||
128 | * identified yet. Early devices have either a TriGem Computer, Inc. or a | ||
129 | * Samsung vendor ID (0x0aa8 and 0x04e8 respectively), while all later | ||
130 | * devices use the SoundGraph vendor ID (0x15c2). | ||
131 | */ | ||
132 | static struct usb_device_id imon_usb_id_table[] = { | ||
133 | /* TriGem iMON (IR only) -- TG_iMON.inf */ | ||
134 | { USB_DEVICE(0x0aa8, 0x8001) }, | ||
135 | |||
136 | /* SoundGraph iMON (IR only) -- sg_imon.inf */ | ||
137 | { USB_DEVICE(0x04e8, 0xff30) }, | ||
138 | |||
139 | /* SoundGraph iMON VFD (IR & VFD) -- iMON_VFD.inf */ | ||
140 | { USB_DEVICE(0x0aa8, 0xffda) }, | ||
141 | |||
142 | /* SoundGraph iMON SS (IR & VFD) -- iMON_SS.inf */ | ||
143 | { USB_DEVICE(0x15c2, 0xffda) }, | ||
144 | |||
145 | {} | ||
146 | }; | ||
147 | |||
148 | /* Some iMON VFD models requires a 6th packet for VFD writes */ | ||
149 | static struct usb_device_id vfd_proto_6p_list[] = { | ||
150 | { USB_DEVICE(0x15c2, 0xffda) }, | ||
151 | {} | ||
152 | }; | ||
153 | |||
154 | /* Some iMON devices have no lcd/vfd, don't set one up */ | ||
155 | static struct usb_device_id ir_only_list[] = { | ||
156 | { USB_DEVICE(0x0aa8, 0x8001) }, | ||
157 | { USB_DEVICE(0x04e8, 0xff30) }, | ||
158 | {} | ||
159 | }; | ||
160 | |||
161 | /* USB Device data */ | ||
162 | static struct usb_driver imon_driver = { | ||
163 | .name = MOD_NAME, | ||
164 | .probe = imon_probe, | ||
165 | .disconnect = imon_disconnect, | ||
166 | .suspend = imon_suspend, | ||
167 | .resume = imon_resume, | ||
168 | .id_table = imon_usb_id_table, | ||
169 | }; | ||
170 | |||
171 | static struct usb_class_driver imon_class = { | ||
172 | .name = DEVICE_NAME, | ||
173 | .fops = &display_fops, | ||
174 | .minor_base = DISPLAY_MINOR_BASE, | ||
175 | }; | ||
176 | |||
177 | /* to prevent races between open() and disconnect(), probing, etc */ | ||
178 | static DEFINE_MUTEX(driver_lock); | ||
179 | |||
180 | static int debug; | ||
181 | |||
182 | /*** M O D U L E C O D E ***/ | ||
183 | |||
184 | MODULE_AUTHOR(MOD_AUTHOR); | ||
185 | MODULE_DESCRIPTION(MOD_DESC); | ||
186 | MODULE_VERSION(MOD_VERSION); | ||
187 | MODULE_LICENSE("GPL"); | ||
188 | MODULE_DEVICE_TABLE(usb, imon_usb_id_table); | ||
189 | module_param(debug, int, S_IRUGO | S_IWUSR); | ||
190 | MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes(default: no)"); | ||
191 | |||
192 | static void free_imon_context(struct imon_context *context) | ||
193 | { | ||
194 | struct device *dev = context->driver->dev; | ||
195 | usb_free_urb(context->tx_urb); | ||
196 | usb_free_urb(context->rx_urb); | ||
197 | lirc_buffer_free(context->driver->rbuf); | ||
198 | kfree(context->driver->rbuf); | ||
199 | kfree(context->driver); | ||
200 | kfree(context); | ||
201 | |||
202 | dev_dbg(dev, "%s: iMON context freed\n", __func__); | ||
203 | } | ||
204 | |||
205 | static void deregister_from_lirc(struct imon_context *context) | ||
206 | { | ||
207 | int retval; | ||
208 | int minor = context->driver->minor; | ||
209 | |||
210 | retval = lirc_unregister_driver(minor); | ||
211 | if (retval) | ||
212 | err("%s: unable to deregister from lirc(%d)", | ||
213 | __func__, retval); | ||
214 | else | ||
215 | printk(KERN_INFO MOD_NAME ": Deregistered iMON driver " | ||
216 | "(minor:%d)\n", minor); | ||
217 | |||
218 | } | ||
219 | |||
220 | /** | ||
221 | * Called when the Display device (e.g. /dev/lcd0) | ||
222 | * is opened by the application. | ||
223 | */ | ||
224 | static int display_open(struct inode *inode, struct file *file) | ||
225 | { | ||
226 | struct usb_interface *interface; | ||
227 | struct imon_context *context = NULL; | ||
228 | int subminor; | ||
229 | int retval = 0; | ||
230 | |||
231 | /* prevent races with disconnect */ | ||
232 | mutex_lock(&driver_lock); | ||
233 | |||
234 | subminor = iminor(inode); | ||
235 | interface = usb_find_interface(&imon_driver, subminor); | ||
236 | if (!interface) { | ||
237 | err("%s: could not find interface for minor %d", | ||
238 | __func__, subminor); | ||
239 | retval = -ENODEV; | ||
240 | goto exit; | ||
241 | } | ||
242 | context = usb_get_intfdata(interface); | ||
243 | |||
244 | if (!context) { | ||
245 | err("%s: no context found for minor %d", | ||
246 | __func__, subminor); | ||
247 | retval = -ENODEV; | ||
248 | goto exit; | ||
249 | } | ||
250 | |||
251 | mutex_lock(&context->ctx_lock); | ||
252 | |||
253 | if (!context->display) { | ||
254 | err("%s: display not supported by device", __func__); | ||
255 | retval = -ENODEV; | ||
256 | } else if (context->display_isopen) { | ||
257 | err("%s: display port is already open", __func__); | ||
258 | retval = -EBUSY; | ||
259 | } else { | ||
260 | context->display_isopen = 1; | ||
261 | file->private_data = context; | ||
262 | dev_info(context->driver->dev, "display port opened\n"); | ||
263 | } | ||
264 | |||
265 | mutex_unlock(&context->ctx_lock); | ||
266 | |||
267 | exit: | ||
268 | mutex_unlock(&driver_lock); | ||
269 | return retval; | ||
270 | } | ||
271 | |||
272 | /** | ||
273 | * Called when the display device (e.g. /dev/lcd0) | ||
274 | * is closed by the application. | ||
275 | */ | ||
276 | static int display_close(struct inode *inode, struct file *file) | ||
277 | { | ||
278 | struct imon_context *context = NULL; | ||
279 | int retval = 0; | ||
280 | |||
281 | context = file->private_data; | ||
282 | |||
283 | if (!context) { | ||
284 | err("%s: no context for device", __func__); | ||
285 | return -ENODEV; | ||
286 | } | ||
287 | |||
288 | mutex_lock(&context->ctx_lock); | ||
289 | |||
290 | if (!context->display) { | ||
291 | err("%s: display not supported by device", __func__); | ||
292 | retval = -ENODEV; | ||
293 | } else if (!context->display_isopen) { | ||
294 | err("%s: display is not open", __func__); | ||
295 | retval = -EIO; | ||
296 | } else { | ||
297 | context->display_isopen = 0; | ||
298 | dev_info(context->driver->dev, "display port closed\n"); | ||
299 | if (!context->dev_present && !context->ir_isopen) { | ||
300 | /* | ||
301 | * Device disconnected before close and IR port is not | ||
302 | * open. If IR port is open, context will be deleted by | ||
303 | * ir_close. | ||
304 | */ | ||
305 | mutex_unlock(&context->ctx_lock); | ||
306 | free_imon_context(context); | ||
307 | return retval; | ||
308 | } | ||
309 | } | ||
310 | |||
311 | mutex_unlock(&context->ctx_lock); | ||
312 | return retval; | ||
313 | } | ||
314 | |||
315 | /** | ||
316 | * Sends a packet to the device -- this function must be called | ||
317 | * with context->ctx_lock held. | ||
318 | */ | ||
319 | static int send_packet(struct imon_context *context) | ||
320 | { | ||
321 | unsigned int pipe; | ||
322 | int interval = 0; | ||
323 | int retval = 0; | ||
324 | |||
325 | /* Check if we need to use control or interrupt urb */ | ||
326 | pipe = usb_sndintpipe(context->usbdev, | ||
327 | context->tx_endpoint->bEndpointAddress); | ||
328 | interval = context->tx_endpoint->bInterval; | ||
329 | |||
330 | usb_fill_int_urb(context->tx_urb, context->usbdev, pipe, | ||
331 | context->usb_tx_buf, | ||
332 | sizeof(context->usb_tx_buf), | ||
333 | usb_tx_callback, context, interval); | ||
334 | |||
335 | context->tx_urb->actual_length = 0; | ||
336 | |||
337 | init_completion(&context->tx.finished); | ||
338 | atomic_set(&(context->tx.busy), 1); | ||
339 | |||
340 | retval = usb_submit_urb(context->tx_urb, GFP_KERNEL); | ||
341 | if (retval) { | ||
342 | atomic_set(&(context->tx.busy), 0); | ||
343 | err("%s: error submitting urb(%d)", __func__, retval); | ||
344 | } else { | ||
345 | /* Wait for transmission to complete (or abort) */ | ||
346 | mutex_unlock(&context->ctx_lock); | ||
347 | retval = wait_for_completion_interruptible( | ||
348 | &context->tx.finished); | ||
349 | if (retval) | ||
350 | err("%s: task interrupted", __func__); | ||
351 | mutex_lock(&context->ctx_lock); | ||
352 | |||
353 | retval = context->tx.status; | ||
354 | if (retval) | ||
355 | err("%s: packet tx failed (%d)", __func__, retval); | ||
356 | } | ||
357 | |||
358 | return retval; | ||
359 | } | ||
360 | |||
361 | /** | ||
362 | * Writes data to the VFD. The iMON VFD is 2x16 characters | ||
363 | * and requires data in 5 consecutive USB interrupt packets, | ||
364 | * each packet but the last carrying 7 bytes. | ||
365 | * | ||
366 | * I don't know if the VFD board supports features such as | ||
367 | * scrolling, clearing rows, blanking, etc. so at | ||
368 | * the caller must provide a full screen of data. If fewer | ||
369 | * than 32 bytes are provided spaces will be appended to | ||
370 | * generate a full screen. | ||
371 | */ | ||
372 | static ssize_t vfd_write(struct file *file, const char *buf, | ||
373 | size_t n_bytes, loff_t *pos) | ||
374 | { | ||
375 | int i; | ||
376 | int offset; | ||
377 | int seq; | ||
378 | int retval = 0; | ||
379 | struct imon_context *context; | ||
380 | const unsigned char vfd_packet6[] = { | ||
381 | 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF }; | ||
382 | int *data_buf = NULL; | ||
383 | |||
384 | context = file->private_data; | ||
385 | if (!context) { | ||
386 | err("%s: no context for device", __func__); | ||
387 | return -ENODEV; | ||
388 | } | ||
389 | |||
390 | mutex_lock(&context->ctx_lock); | ||
391 | |||
392 | if (!context->dev_present) { | ||
393 | err("%s: no iMON device present", __func__); | ||
394 | retval = -ENODEV; | ||
395 | goto exit; | ||
396 | } | ||
397 | |||
398 | if (n_bytes <= 0 || n_bytes > IMON_DATA_BUF_SZ - 3) { | ||
399 | err("%s: invalid payload size", __func__); | ||
400 | retval = -EINVAL; | ||
401 | goto exit; | ||
402 | } | ||
403 | |||
404 | data_buf = memdup_user(buf, n_bytes); | ||
405 | if (IS_ERR(data_buf)) { | ||
406 | retval = PTR_ERR(data_buf); | ||
407 | goto exit; | ||
408 | } | ||
409 | |||
410 | memcpy(context->tx.data_buf, data_buf, n_bytes); | ||
411 | |||
412 | /* Pad with spaces */ | ||
413 | for (i = n_bytes; i < IMON_DATA_BUF_SZ - 3; ++i) | ||
414 | context->tx.data_buf[i] = ' '; | ||
415 | |||
416 | for (i = IMON_DATA_BUF_SZ - 3; i < IMON_DATA_BUF_SZ; ++i) | ||
417 | context->tx.data_buf[i] = 0xFF; | ||
418 | |||
419 | offset = 0; | ||
420 | seq = 0; | ||
421 | |||
422 | do { | ||
423 | memcpy(context->usb_tx_buf, context->tx.data_buf + offset, 7); | ||
424 | context->usb_tx_buf[7] = (unsigned char) seq; | ||
425 | |||
426 | retval = send_packet(context); | ||
427 | if (retval) { | ||
428 | err("%s: send packet failed for packet #%d", | ||
429 | __func__, seq/2); | ||
430 | goto exit; | ||
431 | } else { | ||
432 | seq += 2; | ||
433 | offset += 7; | ||
434 | } | ||
435 | |||
436 | } while (offset < IMON_DATA_BUF_SZ); | ||
437 | |||
438 | if (context->vfd_proto_6p) { | ||
439 | /* Send packet #6 */ | ||
440 | memcpy(context->usb_tx_buf, &vfd_packet6, sizeof(vfd_packet6)); | ||
441 | context->usb_tx_buf[7] = (unsigned char) seq; | ||
442 | retval = send_packet(context); | ||
443 | if (retval) | ||
444 | err("%s: send packet failed for packet #%d", | ||
445 | __func__, seq/2); | ||
446 | } | ||
447 | |||
448 | exit: | ||
449 | mutex_unlock(&context->ctx_lock); | ||
450 | kfree(data_buf); | ||
451 | |||
452 | return (!retval) ? n_bytes : retval; | ||
453 | } | ||
454 | |||
455 | /** | ||
456 | * Callback function for USB core API: transmit data | ||
457 | */ | ||
458 | static void usb_tx_callback(struct urb *urb) | ||
459 | { | ||
460 | struct imon_context *context; | ||
461 | |||
462 | if (!urb) | ||
463 | return; | ||
464 | context = (struct imon_context *)urb->context; | ||
465 | if (!context) | ||
466 | return; | ||
467 | |||
468 | context->tx.status = urb->status; | ||
469 | |||
470 | /* notify waiters that write has finished */ | ||
471 | atomic_set(&context->tx.busy, 0); | ||
472 | complete(&context->tx.finished); | ||
473 | |||
474 | return; | ||
475 | } | ||
476 | |||
477 | /** | ||
478 | * Called by lirc_dev when the application opens /dev/lirc | ||
479 | */ | ||
480 | static int ir_open(void *data) | ||
481 | { | ||
482 | int retval = 0; | ||
483 | struct imon_context *context; | ||
484 | |||
485 | /* prevent races with disconnect */ | ||
486 | mutex_lock(&driver_lock); | ||
487 | |||
488 | context = (struct imon_context *)data; | ||
489 | |||
490 | /* initial IR protocol decode variables */ | ||
491 | context->rx.count = 0; | ||
492 | context->rx.initial_space = 1; | ||
493 | context->rx.prev_bit = 0; | ||
494 | |||
495 | context->ir_isopen = 1; | ||
496 | dev_info(context->driver->dev, "IR port opened\n"); | ||
497 | |||
498 | mutex_unlock(&driver_lock); | ||
499 | return retval; | ||
500 | } | ||
501 | |||
502 | /** | ||
503 | * Called by lirc_dev when the application closes /dev/lirc | ||
504 | */ | ||
505 | static void ir_close(void *data) | ||
506 | { | ||
507 | struct imon_context *context; | ||
508 | |||
509 | context = (struct imon_context *)data; | ||
510 | if (!context) { | ||
511 | err("%s: no context for device", __func__); | ||
512 | return; | ||
513 | } | ||
514 | |||
515 | mutex_lock(&context->ctx_lock); | ||
516 | |||
517 | context->ir_isopen = 0; | ||
518 | dev_info(context->driver->dev, "IR port closed\n"); | ||
519 | |||
520 | if (!context->dev_present) { | ||
521 | /* | ||
522 | * Device disconnected while IR port was still open. Driver | ||
523 | * was not deregistered at disconnect time, so do it now. | ||
524 | */ | ||
525 | deregister_from_lirc(context); | ||
526 | |||
527 | if (!context->display_isopen) { | ||
528 | mutex_unlock(&context->ctx_lock); | ||
529 | free_imon_context(context); | ||
530 | return; | ||
531 | } | ||
532 | /* | ||
533 | * If display port is open, context will be deleted by | ||
534 | * display_close | ||
535 | */ | ||
536 | } | ||
537 | |||
538 | mutex_unlock(&context->ctx_lock); | ||
539 | return; | ||
540 | } | ||
541 | |||
542 | /** | ||
543 | * Convert bit count to time duration (in us) and submit | ||
544 | * the value to lirc_dev. | ||
545 | */ | ||
546 | static void submit_data(struct imon_context *context) | ||
547 | { | ||
548 | unsigned char buf[4]; | ||
549 | int value = context->rx.count; | ||
550 | int i; | ||
551 | |||
552 | dev_dbg(context->driver->dev, "submitting data to LIRC\n"); | ||
553 | |||
554 | value *= BIT_DURATION; | ||
555 | value &= PULSE_MASK; | ||
556 | if (context->rx.prev_bit) | ||
557 | value |= PULSE_BIT; | ||
558 | |||
559 | for (i = 0; i < 4; ++i) | ||
560 | buf[i] = value>>(i*8); | ||
561 | |||
562 | lirc_buffer_write(context->driver->rbuf, buf); | ||
563 | wake_up(&context->driver->rbuf->wait_poll); | ||
564 | return; | ||
565 | } | ||
566 | |||
567 | static inline int tv2int(const struct timeval *a, const struct timeval *b) | ||
568 | { | ||
569 | int usecs = 0; | ||
570 | int sec = 0; | ||
571 | |||
572 | if (b->tv_usec > a->tv_usec) { | ||
573 | usecs = 1000000; | ||
574 | sec--; | ||
575 | } | ||
576 | |||
577 | usecs += a->tv_usec - b->tv_usec; | ||
578 | |||
579 | sec += a->tv_sec - b->tv_sec; | ||
580 | sec *= 1000; | ||
581 | usecs /= 1000; | ||
582 | sec += usecs; | ||
583 | |||
584 | if (sec < 0) | ||
585 | sec = 1000; | ||
586 | |||
587 | return sec; | ||
588 | } | ||
589 | |||
590 | /** | ||
591 | * Process the incoming packet | ||
592 | */ | ||
593 | static void imon_incoming_packet(struct imon_context *context, | ||
594 | struct urb *urb, int intf) | ||
595 | { | ||
596 | int len = urb->actual_length; | ||
597 | unsigned char *buf = urb->transfer_buffer; | ||
598 | struct device *dev = context->driver->dev; | ||
599 | int octet, bit; | ||
600 | unsigned char mask; | ||
601 | int i; | ||
602 | |||
603 | /* | ||
604 | * just bail out if no listening IR client | ||
605 | */ | ||
606 | if (!context->ir_isopen) | ||
607 | return; | ||
608 | |||
609 | if (len != 8) { | ||
610 | dev_warn(dev, "imon %s: invalid incoming packet " | ||
611 | "size (len = %d, intf%d)\n", __func__, len, intf); | ||
612 | return; | ||
613 | } | ||
614 | |||
615 | if (debug) { | ||
616 | printk(KERN_INFO "raw packet: "); | ||
617 | for (i = 0; i < len; ++i) | ||
618 | printk("%02x ", buf[i]); | ||
619 | printk("\n"); | ||
620 | } | ||
621 | |||
622 | /* | ||
623 | * Translate received data to pulse and space lengths. | ||
624 | * Received data is active low, i.e. pulses are 0 and | ||
625 | * spaces are 1. | ||
626 | * | ||
627 | * My original algorithm was essentially similar to | ||
628 | * Changwoo Ryu's with the exception that he switched | ||
629 | * the incoming bits to active high and also fed an | ||
630 | * initial space to LIRC at the start of a new sequence | ||
631 | * if the previous bit was a pulse. | ||
632 | * | ||
633 | * I've decided to adopt his algorithm. | ||
634 | */ | ||
635 | |||
636 | if (buf[7] == 1 && context->rx.initial_space) { | ||
637 | /* LIRC requires a leading space */ | ||
638 | context->rx.prev_bit = 0; | ||
639 | context->rx.count = 4; | ||
640 | submit_data(context); | ||
641 | context->rx.count = 0; | ||
642 | } | ||
643 | |||
644 | for (octet = 0; octet < 5; ++octet) { | ||
645 | mask = 0x80; | ||
646 | for (bit = 0; bit < 8; ++bit) { | ||
647 | int curr_bit = !(buf[octet] & mask); | ||
648 | if (curr_bit != context->rx.prev_bit) { | ||
649 | if (context->rx.count) { | ||
650 | submit_data(context); | ||
651 | context->rx.count = 0; | ||
652 | } | ||
653 | context->rx.prev_bit = curr_bit; | ||
654 | } | ||
655 | ++context->rx.count; | ||
656 | mask >>= 1; | ||
657 | } | ||
658 | } | ||
659 | |||
660 | if (buf[7] == 10) { | ||
661 | if (context->rx.count) { | ||
662 | submit_data(context); | ||
663 | context->rx.count = 0; | ||
664 | } | ||
665 | context->rx.initial_space = context->rx.prev_bit; | ||
666 | } | ||
667 | } | ||
668 | |||
669 | /** | ||
670 | * Callback function for USB core API: receive data | ||
671 | */ | ||
672 | static void usb_rx_callback(struct urb *urb) | ||
673 | { | ||
674 | struct imon_context *context; | ||
675 | int intfnum = 0; | ||
676 | |||
677 | if (!urb) | ||
678 | return; | ||
679 | |||
680 | context = (struct imon_context *)urb->context; | ||
681 | if (!context) | ||
682 | return; | ||
683 | |||
684 | switch (urb->status) { | ||
685 | case -ENOENT: /* usbcore unlink successful! */ | ||
686 | return; | ||
687 | |||
688 | case 0: | ||
689 | imon_incoming_packet(context, urb, intfnum); | ||
690 | break; | ||
691 | |||
692 | default: | ||
693 | dev_warn(context->driver->dev, "imon %s: status(%d): ignored\n", | ||
694 | __func__, urb->status); | ||
695 | break; | ||
696 | } | ||
697 | |||
698 | usb_submit_urb(context->rx_urb, GFP_ATOMIC); | ||
699 | |||
700 | return; | ||
701 | } | ||
702 | |||
703 | /** | ||
704 | * Callback function for USB core API: Probe | ||
705 | */ | ||
706 | static int imon_probe(struct usb_interface *interface, | ||
707 | const struct usb_device_id *id) | ||
708 | { | ||
709 | struct usb_device *usbdev = NULL; | ||
710 | struct usb_host_interface *iface_desc = NULL; | ||
711 | struct usb_endpoint_descriptor *rx_endpoint = NULL; | ||
712 | struct usb_endpoint_descriptor *tx_endpoint = NULL; | ||
713 | struct urb *rx_urb = NULL; | ||
714 | struct urb *tx_urb = NULL; | ||
715 | struct lirc_driver *driver = NULL; | ||
716 | struct lirc_buffer *rbuf = NULL; | ||
717 | struct device *dev = &interface->dev; | ||
718 | int ifnum; | ||
719 | int lirc_minor = 0; | ||
720 | int num_endpts; | ||
721 | int retval = 0; | ||
722 | int display_ep_found = 0; | ||
723 | int ir_ep_found = 0; | ||
724 | int alloc_status = 0; | ||
725 | int vfd_proto_6p = 0; | ||
726 | struct imon_context *context = NULL; | ||
727 | int i; | ||
728 | u16 vendor, product; | ||
729 | |||
730 | context = kzalloc(sizeof(struct imon_context), GFP_KERNEL); | ||
731 | if (!context) { | ||
732 | err("%s: kzalloc failed for context", __func__); | ||
733 | alloc_status = 1; | ||
734 | goto alloc_status_switch; | ||
735 | } | ||
736 | |||
737 | /* | ||
738 | * Try to auto-detect the type of display if the user hasn't set | ||
739 | * it by hand via the display_type modparam. Default is VFD. | ||
740 | */ | ||
741 | if (usb_match_id(interface, ir_only_list)) | ||
742 | context->display = 0; | ||
743 | else | ||
744 | context->display = 1; | ||
745 | |||
746 | usbdev = usb_get_dev(interface_to_usbdev(interface)); | ||
747 | iface_desc = interface->cur_altsetting; | ||
748 | num_endpts = iface_desc->desc.bNumEndpoints; | ||
749 | ifnum = iface_desc->desc.bInterfaceNumber; | ||
750 | vendor = le16_to_cpu(usbdev->descriptor.idVendor); | ||
751 | product = le16_to_cpu(usbdev->descriptor.idProduct); | ||
752 | |||
753 | dev_dbg(dev, "%s: found iMON device (%04x:%04x, intf%d)\n", | ||
754 | __func__, vendor, product, ifnum); | ||
755 | |||
756 | /* prevent races probing devices w/multiple interfaces */ | ||
757 | mutex_lock(&driver_lock); | ||
758 | |||
759 | /* | ||
760 | * Scan the endpoint list and set: | ||
761 | * first input endpoint = IR endpoint | ||
762 | * first output endpoint = display endpoint | ||
763 | */ | ||
764 | for (i = 0; i < num_endpts && !(ir_ep_found && display_ep_found); ++i) { | ||
765 | struct usb_endpoint_descriptor *ep; | ||
766 | int ep_dir; | ||
767 | int ep_type; | ||
768 | ep = &iface_desc->endpoint[i].desc; | ||
769 | ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK; | ||
770 | ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; | ||
771 | |||
772 | if (!ir_ep_found && | ||
773 | ep_dir == USB_DIR_IN && | ||
774 | ep_type == USB_ENDPOINT_XFER_INT) { | ||
775 | |||
776 | rx_endpoint = ep; | ||
777 | ir_ep_found = 1; | ||
778 | dev_dbg(dev, "%s: found IR endpoint\n", __func__); | ||
779 | |||
780 | } else if (!display_ep_found && ep_dir == USB_DIR_OUT && | ||
781 | ep_type == USB_ENDPOINT_XFER_INT) { | ||
782 | tx_endpoint = ep; | ||
783 | display_ep_found = 1; | ||
784 | dev_dbg(dev, "%s: found display endpoint\n", __func__); | ||
785 | } | ||
786 | } | ||
787 | |||
788 | /* | ||
789 | * Some iMON receivers have no display. Unfortunately, it seems | ||
790 | * that SoundGraph recycles device IDs between devices both with | ||
791 | * and without... :\ | ||
792 | */ | ||
793 | if (context->display == 0) { | ||
794 | display_ep_found = 0; | ||
795 | dev_dbg(dev, "%s: device has no display\n", __func__); | ||
796 | } | ||
797 | |||
798 | /* Input endpoint is mandatory */ | ||
799 | if (!ir_ep_found) { | ||
800 | err("%s: no valid input (IR) endpoint found.", __func__); | ||
801 | retval = -ENODEV; | ||
802 | alloc_status = 2; | ||
803 | goto alloc_status_switch; | ||
804 | } | ||
805 | |||
806 | /* Determine if display requires 6 packets */ | ||
807 | if (display_ep_found) { | ||
808 | if (usb_match_id(interface, vfd_proto_6p_list)) | ||
809 | vfd_proto_6p = 1; | ||
810 | |||
811 | dev_dbg(dev, "%s: vfd_proto_6p: %d\n", | ||
812 | __func__, vfd_proto_6p); | ||
813 | } | ||
814 | |||
815 | driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); | ||
816 | if (!driver) { | ||
817 | err("%s: kzalloc failed for lirc_driver", __func__); | ||
818 | alloc_status = 2; | ||
819 | goto alloc_status_switch; | ||
820 | } | ||
821 | rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); | ||
822 | if (!rbuf) { | ||
823 | err("%s: kmalloc failed for lirc_buffer", __func__); | ||
824 | alloc_status = 3; | ||
825 | goto alloc_status_switch; | ||
826 | } | ||
827 | if (lirc_buffer_init(rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) { | ||
828 | err("%s: lirc_buffer_init failed", __func__); | ||
829 | alloc_status = 4; | ||
830 | goto alloc_status_switch; | ||
831 | } | ||
832 | rx_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
833 | if (!rx_urb) { | ||
834 | err("%s: usb_alloc_urb failed for IR urb", __func__); | ||
835 | alloc_status = 5; | ||
836 | goto alloc_status_switch; | ||
837 | } | ||
838 | tx_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
839 | if (!tx_urb) { | ||
840 | err("%s: usb_alloc_urb failed for display urb", | ||
841 | __func__); | ||
842 | alloc_status = 6; | ||
843 | goto alloc_status_switch; | ||
844 | } | ||
845 | |||
846 | mutex_init(&context->ctx_lock); | ||
847 | context->vfd_proto_6p = vfd_proto_6p; | ||
848 | |||
849 | strcpy(driver->name, MOD_NAME); | ||
850 | driver->minor = -1; | ||
851 | driver->code_length = BUF_CHUNK_SIZE * 8; | ||
852 | driver->sample_rate = 0; | ||
853 | driver->features = LIRC_CAN_REC_MODE2; | ||
854 | driver->data = context; | ||
855 | driver->rbuf = rbuf; | ||
856 | driver->set_use_inc = ir_open; | ||
857 | driver->set_use_dec = ir_close; | ||
858 | driver->dev = &interface->dev; | ||
859 | driver->owner = THIS_MODULE; | ||
860 | |||
861 | mutex_lock(&context->ctx_lock); | ||
862 | |||
863 | context->driver = driver; | ||
864 | /* start out in keyboard mode */ | ||
865 | |||
866 | lirc_minor = lirc_register_driver(driver); | ||
867 | if (lirc_minor < 0) { | ||
868 | err("%s: lirc_register_driver failed", __func__); | ||
869 | alloc_status = 7; | ||
870 | goto unlock; | ||
871 | } else | ||
872 | dev_info(dev, "Registered iMON driver " | ||
873 | "(lirc minor: %d)\n", lirc_minor); | ||
874 | |||
875 | /* Needed while unregistering! */ | ||
876 | driver->minor = lirc_minor; | ||
877 | |||
878 | context->usbdev = usbdev; | ||
879 | context->dev_present = 1; | ||
880 | context->rx_endpoint = rx_endpoint; | ||
881 | context->rx_urb = rx_urb; | ||
882 | |||
883 | /* | ||
884 | * tx is used to send characters to lcd/vfd, associate RF | ||
885 | * remotes, set IR protocol, and maybe more... | ||
886 | */ | ||
887 | context->tx_endpoint = tx_endpoint; | ||
888 | context->tx_urb = tx_urb; | ||
889 | |||
890 | if (display_ep_found) | ||
891 | context->display = 1; | ||
892 | |||
893 | usb_fill_int_urb(context->rx_urb, context->usbdev, | ||
894 | usb_rcvintpipe(context->usbdev, | ||
895 | context->rx_endpoint->bEndpointAddress), | ||
896 | context->usb_rx_buf, sizeof(context->usb_rx_buf), | ||
897 | usb_rx_callback, context, | ||
898 | context->rx_endpoint->bInterval); | ||
899 | |||
900 | retval = usb_submit_urb(context->rx_urb, GFP_KERNEL); | ||
901 | |||
902 | if (retval) { | ||
903 | err("%s: usb_submit_urb failed for intf0 (%d)", | ||
904 | __func__, retval); | ||
905 | mutex_unlock(&context->ctx_lock); | ||
906 | goto exit; | ||
907 | } | ||
908 | |||
909 | usb_set_intfdata(interface, context); | ||
910 | |||
911 | if (context->display && ifnum == 0) { | ||
912 | dev_dbg(dev, "%s: Registering iMON display with sysfs\n", | ||
913 | __func__); | ||
914 | |||
915 | if (usb_register_dev(interface, &imon_class)) { | ||
916 | /* Not a fatal error, so ignore */ | ||
917 | dev_info(dev, "%s: could not get a minor number for " | ||
918 | "display\n", __func__); | ||
919 | } | ||
920 | } | ||
921 | |||
922 | dev_info(dev, "iMON device (%04x:%04x, intf%d) on " | ||
923 | "usb<%d:%d> initialized\n", vendor, product, ifnum, | ||
924 | usbdev->bus->busnum, usbdev->devnum); | ||
925 | |||
926 | unlock: | ||
927 | mutex_unlock(&context->ctx_lock); | ||
928 | alloc_status_switch: | ||
929 | |||
930 | switch (alloc_status) { | ||
931 | case 7: | ||
932 | usb_free_urb(tx_urb); | ||
933 | case 6: | ||
934 | usb_free_urb(rx_urb); | ||
935 | case 5: | ||
936 | if (rbuf) | ||
937 | lirc_buffer_free(rbuf); | ||
938 | case 4: | ||
939 | kfree(rbuf); | ||
940 | case 3: | ||
941 | kfree(driver); | ||
942 | case 2: | ||
943 | kfree(context); | ||
944 | context = NULL; | ||
945 | case 1: | ||
946 | if (retval != -ENODEV) | ||
947 | retval = -ENOMEM; | ||
948 | break; | ||
949 | case 0: | ||
950 | retval = 0; | ||
951 | } | ||
952 | |||
953 | exit: | ||
954 | mutex_unlock(&driver_lock); | ||
955 | |||
956 | return retval; | ||
957 | } | ||
958 | |||
959 | /** | ||
960 | * Callback function for USB core API: disconnect | ||
961 | */ | ||
962 | static void imon_disconnect(struct usb_interface *interface) | ||
963 | { | ||
964 | struct imon_context *context; | ||
965 | int ifnum; | ||
966 | |||
967 | /* prevent races with ir_open()/display_open() */ | ||
968 | mutex_lock(&driver_lock); | ||
969 | |||
970 | context = usb_get_intfdata(interface); | ||
971 | ifnum = interface->cur_altsetting->desc.bInterfaceNumber; | ||
972 | |||
973 | mutex_lock(&context->ctx_lock); | ||
974 | |||
975 | usb_set_intfdata(interface, NULL); | ||
976 | |||
977 | /* Abort ongoing write */ | ||
978 | if (atomic_read(&context->tx.busy)) { | ||
979 | usb_kill_urb(context->tx_urb); | ||
980 | complete_all(&context->tx.finished); | ||
981 | } | ||
982 | |||
983 | context->dev_present = 0; | ||
984 | usb_kill_urb(context->rx_urb); | ||
985 | if (context->display) | ||
986 | usb_deregister_dev(interface, &imon_class); | ||
987 | |||
988 | if (!context->ir_isopen && !context->dev_present) { | ||
989 | deregister_from_lirc(context); | ||
990 | mutex_unlock(&context->ctx_lock); | ||
991 | if (!context->display_isopen) | ||
992 | free_imon_context(context); | ||
993 | } else | ||
994 | mutex_unlock(&context->ctx_lock); | ||
995 | |||
996 | mutex_unlock(&driver_lock); | ||
997 | |||
998 | printk(KERN_INFO "%s: iMON device (intf%d) disconnected\n", | ||
999 | __func__, ifnum); | ||
1000 | } | ||
1001 | |||
1002 | static int imon_suspend(struct usb_interface *intf, pm_message_t message) | ||
1003 | { | ||
1004 | struct imon_context *context = usb_get_intfdata(intf); | ||
1005 | |||
1006 | usb_kill_urb(context->rx_urb); | ||
1007 | |||
1008 | return 0; | ||
1009 | } | ||
1010 | |||
1011 | static int imon_resume(struct usb_interface *intf) | ||
1012 | { | ||
1013 | int rc = 0; | ||
1014 | struct imon_context *context = usb_get_intfdata(intf); | ||
1015 | |||
1016 | usb_fill_int_urb(context->rx_urb, context->usbdev, | ||
1017 | usb_rcvintpipe(context->usbdev, | ||
1018 | context->rx_endpoint->bEndpointAddress), | ||
1019 | context->usb_rx_buf, sizeof(context->usb_rx_buf), | ||
1020 | usb_rx_callback, context, | ||
1021 | context->rx_endpoint->bInterval); | ||
1022 | |||
1023 | rc = usb_submit_urb(context->rx_urb, GFP_ATOMIC); | ||
1024 | |||
1025 | return rc; | ||
1026 | } | ||
1027 | |||
1028 | static int __init imon_init(void) | ||
1029 | { | ||
1030 | int rc; | ||
1031 | |||
1032 | printk(KERN_INFO MOD_NAME ": " MOD_DESC ", v" MOD_VERSION "\n"); | ||
1033 | |||
1034 | rc = usb_register(&imon_driver); | ||
1035 | if (rc) { | ||
1036 | err("%s: usb register failed(%d)", __func__, rc); | ||
1037 | return -ENODEV; | ||
1038 | } | ||
1039 | |||
1040 | return 0; | ||
1041 | } | ||
1042 | |||
1043 | static void __exit imon_exit(void) | ||
1044 | { | ||
1045 | usb_deregister(&imon_driver); | ||
1046 | printk(KERN_INFO MOD_NAME ": module removed. Goodbye!\n"); | ||
1047 | } | ||
1048 | |||
1049 | module_init(imon_init); | ||
1050 | module_exit(imon_exit); | ||
diff --git a/drivers/staging/lirc/lirc_parallel.c b/drivers/staging/lirc/lirc_parallel.c new file mode 100644 index 00000000000..792aac0a8e7 --- /dev/null +++ b/drivers/staging/lirc/lirc_parallel.c | |||
@@ -0,0 +1,755 @@ | |||
1 | /* | ||
2 | * lirc_parallel.c | ||
3 | * | ||
4 | * lirc_parallel - device driver for infra-red signal receiving and | ||
5 | * transmitting unit built by the author | ||
6 | * | ||
7 | * Copyright (C) 1998 Christoph Bartelmus <lirc@bartelmus.de> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | /*** Includes ***/ | ||
26 | |||
27 | #include <linux/module.h> | ||
28 | #include <linux/sched.h> | ||
29 | #include <linux/errno.h> | ||
30 | #include <linux/signal.h> | ||
31 | #include <linux/fs.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/ioport.h> | ||
34 | #include <linux/time.h> | ||
35 | #include <linux/mm.h> | ||
36 | #include <linux/delay.h> | ||
37 | |||
38 | #include <linux/io.h> | ||
39 | #include <linux/irq.h> | ||
40 | #include <linux/uaccess.h> | ||
41 | #include <asm/div64.h> | ||
42 | |||
43 | #include <linux/poll.h> | ||
44 | #include <linux/parport.h> | ||
45 | #include <linux/platform_device.h> | ||
46 | |||
47 | #include <media/lirc.h> | ||
48 | #include <media/lirc_dev.h> | ||
49 | |||
50 | #include "lirc_parallel.h" | ||
51 | |||
52 | #define LIRC_DRIVER_NAME "lirc_parallel" | ||
53 | |||
54 | #ifndef LIRC_IRQ | ||
55 | #define LIRC_IRQ 7 | ||
56 | #endif | ||
57 | #ifndef LIRC_PORT | ||
58 | #define LIRC_PORT 0x378 | ||
59 | #endif | ||
60 | #ifndef LIRC_TIMER | ||
61 | #define LIRC_TIMER 65536 | ||
62 | #endif | ||
63 | |||
64 | /*** Global Variables ***/ | ||
65 | |||
66 | static int debug; | ||
67 | static int check_pselecd; | ||
68 | |||
69 | unsigned int irq = LIRC_IRQ; | ||
70 | unsigned int io = LIRC_PORT; | ||
71 | #ifdef LIRC_TIMER | ||
72 | unsigned int timer; | ||
73 | unsigned int default_timer = LIRC_TIMER; | ||
74 | #endif | ||
75 | |||
76 | #define RBUF_SIZE (256) /* this must be a power of 2 larger than 1 */ | ||
77 | |||
78 | static int rbuf[RBUF_SIZE]; | ||
79 | |||
80 | DECLARE_WAIT_QUEUE_HEAD(lirc_wait); | ||
81 | |||
82 | unsigned int rptr; | ||
83 | unsigned int wptr; | ||
84 | unsigned int lost_irqs; | ||
85 | int is_open; | ||
86 | |||
87 | struct parport *pport; | ||
88 | struct pardevice *ppdevice; | ||
89 | int is_claimed; | ||
90 | |||
91 | unsigned int tx_mask = 1; | ||
92 | |||
93 | /*** Internal Functions ***/ | ||
94 | |||
95 | static unsigned int in(int offset) | ||
96 | { | ||
97 | switch (offset) { | ||
98 | case LIRC_LP_BASE: | ||
99 | return parport_read_data(pport); | ||
100 | case LIRC_LP_STATUS: | ||
101 | return parport_read_status(pport); | ||
102 | case LIRC_LP_CONTROL: | ||
103 | return parport_read_control(pport); | ||
104 | } | ||
105 | return 0; /* make compiler happy */ | ||
106 | } | ||
107 | |||
108 | static void out(int offset, int value) | ||
109 | { | ||
110 | switch (offset) { | ||
111 | case LIRC_LP_BASE: | ||
112 | parport_write_data(pport, value); | ||
113 | break; | ||
114 | case LIRC_LP_CONTROL: | ||
115 | parport_write_control(pport, value); | ||
116 | break; | ||
117 | case LIRC_LP_STATUS: | ||
118 | printk(KERN_INFO "%s: attempt to write to status register\n", | ||
119 | LIRC_DRIVER_NAME); | ||
120 | break; | ||
121 | } | ||
122 | } | ||
123 | |||
124 | static unsigned int lirc_get_timer(void) | ||
125 | { | ||
126 | return in(LIRC_PORT_TIMER) & LIRC_PORT_TIMER_BIT; | ||
127 | } | ||
128 | |||
129 | static unsigned int lirc_get_signal(void) | ||
130 | { | ||
131 | return in(LIRC_PORT_SIGNAL) & LIRC_PORT_SIGNAL_BIT; | ||
132 | } | ||
133 | |||
134 | static void lirc_on(void) | ||
135 | { | ||
136 | out(LIRC_PORT_DATA, tx_mask); | ||
137 | } | ||
138 | |||
139 | static void lirc_off(void) | ||
140 | { | ||
141 | out(LIRC_PORT_DATA, 0); | ||
142 | } | ||
143 | |||
144 | static unsigned int init_lirc_timer(void) | ||
145 | { | ||
146 | struct timeval tv, now; | ||
147 | unsigned int level, newlevel, timeelapsed, newtimer; | ||
148 | int count = 0; | ||
149 | |||
150 | do_gettimeofday(&tv); | ||
151 | tv.tv_sec++; /* wait max. 1 sec. */ | ||
152 | level = lirc_get_timer(); | ||
153 | do { | ||
154 | newlevel = lirc_get_timer(); | ||
155 | if (level == 0 && newlevel != 0) | ||
156 | count++; | ||
157 | level = newlevel; | ||
158 | do_gettimeofday(&now); | ||
159 | } while (count < 1000 && (now.tv_sec < tv.tv_sec | ||
160 | || (now.tv_sec == tv.tv_sec | ||
161 | && now.tv_usec < tv.tv_usec))); | ||
162 | |||
163 | timeelapsed = ((now.tv_sec + 1 - tv.tv_sec)*1000000 | ||
164 | + (now.tv_usec - tv.tv_usec)); | ||
165 | if (count >= 1000 && timeelapsed > 0) { | ||
166 | if (default_timer == 0) { | ||
167 | /* autodetect timer */ | ||
168 | newtimer = (1000000*count)/timeelapsed; | ||
169 | printk(KERN_INFO "%s: %u Hz timer detected\n", | ||
170 | LIRC_DRIVER_NAME, newtimer); | ||
171 | return newtimer; | ||
172 | } else { | ||
173 | newtimer = (1000000*count)/timeelapsed; | ||
174 | if (abs(newtimer - default_timer) > default_timer/10) { | ||
175 | /* bad timer */ | ||
176 | printk(KERN_NOTICE "%s: bad timer: %u Hz\n", | ||
177 | LIRC_DRIVER_NAME, newtimer); | ||
178 | printk(KERN_NOTICE "%s: using default timer: " | ||
179 | "%u Hz\n", | ||
180 | LIRC_DRIVER_NAME, default_timer); | ||
181 | return default_timer; | ||
182 | } else { | ||
183 | printk(KERN_INFO "%s: %u Hz timer detected\n", | ||
184 | LIRC_DRIVER_NAME, newtimer); | ||
185 | return newtimer; /* use detected value */ | ||
186 | } | ||
187 | } | ||
188 | } else { | ||
189 | printk(KERN_NOTICE "%s: no timer detected\n", LIRC_DRIVER_NAME); | ||
190 | return 0; | ||
191 | } | ||
192 | } | ||
193 | |||
194 | static int lirc_claim(void) | ||
195 | { | ||
196 | if (parport_claim(ppdevice) != 0) { | ||
197 | printk(KERN_WARNING "%s: could not claim port\n", | ||
198 | LIRC_DRIVER_NAME); | ||
199 | printk(KERN_WARNING "%s: waiting for port becoming available" | ||
200 | "\n", LIRC_DRIVER_NAME); | ||
201 | if (parport_claim_or_block(ppdevice) < 0) { | ||
202 | printk(KERN_NOTICE "%s: could not claim port, giving" | ||
203 | " up\n", LIRC_DRIVER_NAME); | ||
204 | return 0; | ||
205 | } | ||
206 | } | ||
207 | out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP); | ||
208 | is_claimed = 1; | ||
209 | return 1; | ||
210 | } | ||
211 | |||
212 | /*** interrupt handler ***/ | ||
213 | |||
214 | static void rbuf_write(int signal) | ||
215 | { | ||
216 | unsigned int nwptr; | ||
217 | |||
218 | nwptr = (wptr + 1) & (RBUF_SIZE - 1); | ||
219 | if (nwptr == rptr) { | ||
220 | /* no new signals will be accepted */ | ||
221 | lost_irqs++; | ||
222 | printk(KERN_NOTICE "%s: buffer overrun\n", LIRC_DRIVER_NAME); | ||
223 | return; | ||
224 | } | ||
225 | rbuf[wptr] = signal; | ||
226 | wptr = nwptr; | ||
227 | } | ||
228 | |||
229 | static void irq_handler(void *blah) | ||
230 | { | ||
231 | struct timeval tv; | ||
232 | static struct timeval lasttv; | ||
233 | static int init; | ||
234 | long signal; | ||
235 | int data; | ||
236 | unsigned int level, newlevel; | ||
237 | unsigned int timeout; | ||
238 | |||
239 | if (!is_open) | ||
240 | return; | ||
241 | |||
242 | if (!is_claimed) | ||
243 | return; | ||
244 | |||
245 | #if 0 | ||
246 | /* disable interrupt */ | ||
247 | disable_irq(irq); | ||
248 | out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ) & (~LP_PINTEN)); | ||
249 | #endif | ||
250 | if (check_pselecd && (in(1) & LP_PSELECD)) | ||
251 | return; | ||
252 | |||
253 | #ifdef LIRC_TIMER | ||
254 | if (init) { | ||
255 | do_gettimeofday(&tv); | ||
256 | |||
257 | signal = tv.tv_sec - lasttv.tv_sec; | ||
258 | if (signal > 15) | ||
259 | /* really long time */ | ||
260 | data = PULSE_MASK; | ||
261 | else | ||
262 | data = (int) (signal*1000000 + | ||
263 | tv.tv_usec - lasttv.tv_usec + | ||
264 | LIRC_SFH506_DELAY); | ||
265 | |||
266 | rbuf_write(data); /* space */ | ||
267 | } else { | ||
268 | if (timer == 0) { | ||
269 | /* | ||
270 | * wake up; we'll lose this signal, but it will be | ||
271 | * garbage if the device is turned on anyway | ||
272 | */ | ||
273 | timer = init_lirc_timer(); | ||
274 | /* enable_irq(irq); */ | ||
275 | return; | ||
276 | } | ||
277 | init = 1; | ||
278 | } | ||
279 | |||
280 | timeout = timer/10; /* timeout after 1/10 sec. */ | ||
281 | signal = 1; | ||
282 | level = lirc_get_timer(); | ||
283 | do { | ||
284 | newlevel = lirc_get_timer(); | ||
285 | if (level == 0 && newlevel != 0) | ||
286 | signal++; | ||
287 | level = newlevel; | ||
288 | |||
289 | /* giving up */ | ||
290 | if (signal > timeout | ||
291 | || (check_pselecd && (in(1) & LP_PSELECD))) { | ||
292 | signal = 0; | ||
293 | printk(KERN_NOTICE "%s: timeout\n", LIRC_DRIVER_NAME); | ||
294 | break; | ||
295 | } | ||
296 | } while (lirc_get_signal()); | ||
297 | |||
298 | if (signal != 0) { | ||
299 | /* adjust value to usecs */ | ||
300 | __u64 helper; | ||
301 | |||
302 | helper = ((__u64) signal)*1000000; | ||
303 | do_div(helper, timer); | ||
304 | signal = (long) helper; | ||
305 | |||
306 | if (signal > LIRC_SFH506_DELAY) | ||
307 | data = signal - LIRC_SFH506_DELAY; | ||
308 | else | ||
309 | data = 1; | ||
310 | rbuf_write(PULSE_BIT|data); /* pulse */ | ||
311 | } | ||
312 | do_gettimeofday(&lasttv); | ||
313 | #else | ||
314 | /* add your code here */ | ||
315 | #endif | ||
316 | |||
317 | wake_up_interruptible(&lirc_wait); | ||
318 | |||
319 | /* enable interrupt */ | ||
320 | /* | ||
321 | enable_irq(irq); | ||
322 | out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ)|LP_PINTEN); | ||
323 | */ | ||
324 | } | ||
325 | |||
326 | /*** file operations ***/ | ||
327 | |||
328 | static loff_t lirc_lseek(struct file *filep, loff_t offset, int orig) | ||
329 | { | ||
330 | return -ESPIPE; | ||
331 | } | ||
332 | |||
333 | static ssize_t lirc_read(struct file *filep, char *buf, size_t n, loff_t *ppos) | ||
334 | { | ||
335 | int result = 0; | ||
336 | int count = 0; | ||
337 | DECLARE_WAITQUEUE(wait, current); | ||
338 | |||
339 | if (n % sizeof(int)) | ||
340 | return -EINVAL; | ||
341 | |||
342 | add_wait_queue(&lirc_wait, &wait); | ||
343 | set_current_state(TASK_INTERRUPTIBLE); | ||
344 | while (count < n) { | ||
345 | if (rptr != wptr) { | ||
346 | if (copy_to_user(buf+count, (char *) &rbuf[rptr], | ||
347 | sizeof(int))) { | ||
348 | result = -EFAULT; | ||
349 | break; | ||
350 | } | ||
351 | rptr = (rptr + 1) & (RBUF_SIZE - 1); | ||
352 | count += sizeof(int); | ||
353 | } else { | ||
354 | if (filep->f_flags & O_NONBLOCK) { | ||
355 | result = -EAGAIN; | ||
356 | break; | ||
357 | } | ||
358 | if (signal_pending(current)) { | ||
359 | result = -ERESTARTSYS; | ||
360 | break; | ||
361 | } | ||
362 | schedule(); | ||
363 | set_current_state(TASK_INTERRUPTIBLE); | ||
364 | } | ||
365 | } | ||
366 | remove_wait_queue(&lirc_wait, &wait); | ||
367 | set_current_state(TASK_RUNNING); | ||
368 | return count ? count : result; | ||
369 | } | ||
370 | |||
371 | static ssize_t lirc_write(struct file *filep, const char *buf, size_t n, | ||
372 | loff_t *ppos) | ||
373 | { | ||
374 | int count; | ||
375 | unsigned int i; | ||
376 | unsigned int level, newlevel; | ||
377 | unsigned long flags; | ||
378 | int counttimer; | ||
379 | int *wbuf; | ||
380 | ssize_t ret; | ||
381 | |||
382 | if (!is_claimed) | ||
383 | return -EBUSY; | ||
384 | |||
385 | count = n / sizeof(int); | ||
386 | |||
387 | if (n % sizeof(int) || count % 2 == 0) | ||
388 | return -EINVAL; | ||
389 | |||
390 | wbuf = memdup_user(buf, n); | ||
391 | if (IS_ERR(wbuf)) | ||
392 | return PTR_ERR(wbuf); | ||
393 | |||
394 | #ifdef LIRC_TIMER | ||
395 | if (timer == 0) { | ||
396 | /* try again if device is ready */ | ||
397 | timer = init_lirc_timer(); | ||
398 | if (timer == 0) { | ||
399 | ret = -EIO; | ||
400 | goto out; | ||
401 | } | ||
402 | } | ||
403 | |||
404 | /* adjust values from usecs */ | ||
405 | for (i = 0; i < count; i++) { | ||
406 | __u64 helper; | ||
407 | |||
408 | helper = ((__u64) wbuf[i])*timer; | ||
409 | do_div(helper, 1000000); | ||
410 | wbuf[i] = (int) helper; | ||
411 | } | ||
412 | |||
413 | local_irq_save(flags); | ||
414 | i = 0; | ||
415 | while (i < count) { | ||
416 | level = lirc_get_timer(); | ||
417 | counttimer = 0; | ||
418 | lirc_on(); | ||
419 | do { | ||
420 | newlevel = lirc_get_timer(); | ||
421 | if (level == 0 && newlevel != 0) | ||
422 | counttimer++; | ||
423 | level = newlevel; | ||
424 | if (check_pselecd && (in(1) & LP_PSELECD)) { | ||
425 | lirc_off(); | ||
426 | local_irq_restore(flags); | ||
427 | ret = -EIO; | ||
428 | goto out; | ||
429 | } | ||
430 | } while (counttimer < wbuf[i]); | ||
431 | i++; | ||
432 | |||
433 | lirc_off(); | ||
434 | if (i == count) | ||
435 | break; | ||
436 | counttimer = 0; | ||
437 | do { | ||
438 | newlevel = lirc_get_timer(); | ||
439 | if (level == 0 && newlevel != 0) | ||
440 | counttimer++; | ||
441 | level = newlevel; | ||
442 | if (check_pselecd && (in(1) & LP_PSELECD)) { | ||
443 | local_irq_restore(flags); | ||
444 | ret = -EIO; | ||
445 | goto out; | ||
446 | } | ||
447 | } while (counttimer < wbuf[i]); | ||
448 | i++; | ||
449 | } | ||
450 | local_irq_restore(flags); | ||
451 | #else | ||
452 | /* place code that handles write without external timer here */ | ||
453 | #endif | ||
454 | ret = n; | ||
455 | out: | ||
456 | kfree(wbuf); | ||
457 | |||
458 | return ret; | ||
459 | } | ||
460 | |||
461 | static unsigned int lirc_poll(struct file *file, poll_table *wait) | ||
462 | { | ||
463 | poll_wait(file, &lirc_wait, wait); | ||
464 | if (rptr != wptr) | ||
465 | return POLLIN | POLLRDNORM; | ||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) | ||
470 | { | ||
471 | int result; | ||
472 | __u32 features = LIRC_CAN_SET_TRANSMITTER_MASK | | ||
473 | LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2; | ||
474 | __u32 mode; | ||
475 | __u32 value; | ||
476 | |||
477 | switch (cmd) { | ||
478 | case LIRC_GET_FEATURES: | ||
479 | result = put_user(features, (__u32 *) arg); | ||
480 | if (result) | ||
481 | return result; | ||
482 | break; | ||
483 | case LIRC_GET_SEND_MODE: | ||
484 | result = put_user(LIRC_MODE_PULSE, (__u32 *) arg); | ||
485 | if (result) | ||
486 | return result; | ||
487 | break; | ||
488 | case LIRC_GET_REC_MODE: | ||
489 | result = put_user(LIRC_MODE_MODE2, (__u32 *) arg); | ||
490 | if (result) | ||
491 | return result; | ||
492 | break; | ||
493 | case LIRC_SET_SEND_MODE: | ||
494 | result = get_user(mode, (__u32 *) arg); | ||
495 | if (result) | ||
496 | return result; | ||
497 | if (mode != LIRC_MODE_PULSE) | ||
498 | return -EINVAL; | ||
499 | break; | ||
500 | case LIRC_SET_REC_MODE: | ||
501 | result = get_user(mode, (__u32 *) arg); | ||
502 | if (result) | ||
503 | return result; | ||
504 | if (mode != LIRC_MODE_MODE2) | ||
505 | return -ENOSYS; | ||
506 | break; | ||
507 | case LIRC_SET_TRANSMITTER_MASK: | ||
508 | result = get_user(value, (__u32 *) arg); | ||
509 | if (result) | ||
510 | return result; | ||
511 | if ((value & LIRC_PARALLEL_TRANSMITTER_MASK) != value) | ||
512 | return LIRC_PARALLEL_MAX_TRANSMITTERS; | ||
513 | tx_mask = value; | ||
514 | break; | ||
515 | default: | ||
516 | return -ENOIOCTLCMD; | ||
517 | } | ||
518 | return 0; | ||
519 | } | ||
520 | |||
521 | static int lirc_open(struct inode *node, struct file *filep) | ||
522 | { | ||
523 | if (is_open || !lirc_claim()) | ||
524 | return -EBUSY; | ||
525 | |||
526 | parport_enable_irq(pport); | ||
527 | |||
528 | /* init read ptr */ | ||
529 | rptr = 0; | ||
530 | wptr = 0; | ||
531 | lost_irqs = 0; | ||
532 | |||
533 | is_open = 1; | ||
534 | return 0; | ||
535 | } | ||
536 | |||
537 | static int lirc_close(struct inode *node, struct file *filep) | ||
538 | { | ||
539 | if (is_claimed) { | ||
540 | is_claimed = 0; | ||
541 | parport_release(ppdevice); | ||
542 | } | ||
543 | is_open = 0; | ||
544 | return 0; | ||
545 | } | ||
546 | |||
547 | static const struct file_operations lirc_fops = { | ||
548 | .owner = THIS_MODULE, | ||
549 | .llseek = lirc_lseek, | ||
550 | .read = lirc_read, | ||
551 | .write = lirc_write, | ||
552 | .poll = lirc_poll, | ||
553 | .unlocked_ioctl = lirc_ioctl, | ||
554 | #ifdef CONFIG_COMPAT | ||
555 | .compat_ioctl = lirc_ioctl, | ||
556 | #endif | ||
557 | .open = lirc_open, | ||
558 | .release = lirc_close | ||
559 | }; | ||
560 | |||
561 | static int set_use_inc(void *data) | ||
562 | { | ||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | static void set_use_dec(void *data) | ||
567 | { | ||
568 | } | ||
569 | |||
570 | static struct lirc_driver driver = { | ||
571 | .name = LIRC_DRIVER_NAME, | ||
572 | .minor = -1, | ||
573 | .code_length = 1, | ||
574 | .sample_rate = 0, | ||
575 | .data = NULL, | ||
576 | .add_to_buf = NULL, | ||
577 | .set_use_inc = set_use_inc, | ||
578 | .set_use_dec = set_use_dec, | ||
579 | .fops = &lirc_fops, | ||
580 | .dev = NULL, | ||
581 | .owner = THIS_MODULE, | ||
582 | }; | ||
583 | |||
584 | static struct platform_device *lirc_parallel_dev; | ||
585 | |||
586 | static int __devinit lirc_parallel_probe(struct platform_device *dev) | ||
587 | { | ||
588 | return 0; | ||
589 | } | ||
590 | |||
591 | static int __devexit lirc_parallel_remove(struct platform_device *dev) | ||
592 | { | ||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | static int lirc_parallel_suspend(struct platform_device *dev, | ||
597 | pm_message_t state) | ||
598 | { | ||
599 | return 0; | ||
600 | } | ||
601 | |||
602 | static int lirc_parallel_resume(struct platform_device *dev) | ||
603 | { | ||
604 | return 0; | ||
605 | } | ||
606 | |||
607 | static struct platform_driver lirc_parallel_driver = { | ||
608 | .probe = lirc_parallel_probe, | ||
609 | .remove = __devexit_p(lirc_parallel_remove), | ||
610 | .suspend = lirc_parallel_suspend, | ||
611 | .resume = lirc_parallel_resume, | ||
612 | .driver = { | ||
613 | .name = LIRC_DRIVER_NAME, | ||
614 | .owner = THIS_MODULE, | ||
615 | }, | ||
616 | }; | ||
617 | |||
618 | static int pf(void *handle) | ||
619 | { | ||
620 | parport_disable_irq(pport); | ||
621 | is_claimed = 0; | ||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | static void kf(void *handle) | ||
626 | { | ||
627 | if (!is_open) | ||
628 | return; | ||
629 | if (!lirc_claim()) | ||
630 | return; | ||
631 | parport_enable_irq(pport); | ||
632 | lirc_off(); | ||
633 | /* this is a bit annoying when you actually print...*/ | ||
634 | /* | ||
635 | printk(KERN_INFO "%s: reclaimed port\n", LIRC_DRIVER_NAME); | ||
636 | */ | ||
637 | } | ||
638 | |||
639 | /*** module initialization and cleanup ***/ | ||
640 | |||
641 | static int __init lirc_parallel_init(void) | ||
642 | { | ||
643 | int result; | ||
644 | |||
645 | result = platform_driver_register(&lirc_parallel_driver); | ||
646 | if (result) { | ||
647 | printk(KERN_NOTICE "platform_driver_register" | ||
648 | " returned %d\n", result); | ||
649 | return result; | ||
650 | } | ||
651 | |||
652 | lirc_parallel_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0); | ||
653 | if (!lirc_parallel_dev) { | ||
654 | result = -ENOMEM; | ||
655 | goto exit_driver_unregister; | ||
656 | } | ||
657 | |||
658 | result = platform_device_add(lirc_parallel_dev); | ||
659 | if (result) | ||
660 | goto exit_device_put; | ||
661 | |||
662 | pport = parport_find_base(io); | ||
663 | if (pport == NULL) { | ||
664 | printk(KERN_NOTICE "%s: no port at %x found\n", | ||
665 | LIRC_DRIVER_NAME, io); | ||
666 | result = -ENXIO; | ||
667 | goto exit_device_put; | ||
668 | } | ||
669 | ppdevice = parport_register_device(pport, LIRC_DRIVER_NAME, | ||
670 | pf, kf, irq_handler, 0, NULL); | ||
671 | parport_put_port(pport); | ||
672 | if (ppdevice == NULL) { | ||
673 | printk(KERN_NOTICE "%s: parport_register_device() failed\n", | ||
674 | LIRC_DRIVER_NAME); | ||
675 | result = -ENXIO; | ||
676 | goto exit_device_put; | ||
677 | } | ||
678 | if (parport_claim(ppdevice) != 0) | ||
679 | goto skip_init; | ||
680 | is_claimed = 1; | ||
681 | out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP); | ||
682 | |||
683 | #ifdef LIRC_TIMER | ||
684 | if (debug) | ||
685 | out(LIRC_PORT_DATA, tx_mask); | ||
686 | |||
687 | timer = init_lirc_timer(); | ||
688 | |||
689 | #if 0 /* continue even if device is offline */ | ||
690 | if (timer == 0) { | ||
691 | is_claimed = 0; | ||
692 | parport_release(pport); | ||
693 | parport_unregister_device(ppdevice); | ||
694 | result = -EIO; | ||
695 | goto exit_device_put; | ||
696 | } | ||
697 | |||
698 | #endif | ||
699 | if (debug) | ||
700 | out(LIRC_PORT_DATA, 0); | ||
701 | #endif | ||
702 | |||
703 | is_claimed = 0; | ||
704 | parport_release(ppdevice); | ||
705 | skip_init: | ||
706 | driver.dev = &lirc_parallel_dev->dev; | ||
707 | driver.minor = lirc_register_driver(&driver); | ||
708 | if (driver.minor < 0) { | ||
709 | printk(KERN_NOTICE "%s: register_chrdev() failed\n", | ||
710 | LIRC_DRIVER_NAME); | ||
711 | parport_unregister_device(ppdevice); | ||
712 | result = -EIO; | ||
713 | goto exit_device_put; | ||
714 | } | ||
715 | printk(KERN_INFO "%s: installed using port 0x%04x irq %d\n", | ||
716 | LIRC_DRIVER_NAME, io, irq); | ||
717 | return 0; | ||
718 | |||
719 | exit_device_put: | ||
720 | platform_device_put(lirc_parallel_dev); | ||
721 | exit_driver_unregister: | ||
722 | platform_driver_unregister(&lirc_parallel_driver); | ||
723 | return result; | ||
724 | } | ||
725 | |||
726 | static void __exit lirc_parallel_exit(void) | ||
727 | { | ||
728 | parport_unregister_device(ppdevice); | ||
729 | lirc_unregister_driver(driver.minor); | ||
730 | |||
731 | platform_device_unregister(lirc_parallel_dev); | ||
732 | platform_driver_unregister(&lirc_parallel_driver); | ||
733 | } | ||
734 | |||
735 | module_init(lirc_parallel_init); | ||
736 | module_exit(lirc_parallel_exit); | ||
737 | |||
738 | MODULE_DESCRIPTION("Infrared receiver driver for parallel ports."); | ||
739 | MODULE_AUTHOR("Christoph Bartelmus"); | ||
740 | MODULE_LICENSE("GPL"); | ||
741 | |||
742 | module_param(io, int, S_IRUGO); | ||
743 | MODULE_PARM_DESC(io, "I/O address base (0x3bc, 0x378 or 0x278)"); | ||
744 | |||
745 | module_param(irq, int, S_IRUGO); | ||
746 | MODULE_PARM_DESC(irq, "Interrupt (7 or 5)"); | ||
747 | |||
748 | module_param(tx_mask, int, S_IRUGO); | ||
749 | MODULE_PARM_DESC(tx_maxk, "Transmitter mask (default: 0x01)"); | ||
750 | |||
751 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
752 | MODULE_PARM_DESC(debug, "Enable debugging messages"); | ||
753 | |||
754 | module_param(check_pselecd, bool, S_IRUGO | S_IWUSR); | ||
755 | MODULE_PARM_DESC(debug, "Check for printer (default: 0)"); | ||
diff --git a/drivers/staging/lirc/lirc_parallel.h b/drivers/staging/lirc/lirc_parallel.h new file mode 100644 index 00000000000..4bed6afe063 --- /dev/null +++ b/drivers/staging/lirc/lirc_parallel.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* lirc_parallel.h */ | ||
2 | |||
3 | #ifndef _LIRC_PARALLEL_H | ||
4 | #define _LIRC_PARALLEL_H | ||
5 | |||
6 | #include <linux/lp.h> | ||
7 | |||
8 | #define LIRC_PORT_LEN 3 | ||
9 | |||
10 | #define LIRC_LP_BASE 0 | ||
11 | #define LIRC_LP_STATUS 1 | ||
12 | #define LIRC_LP_CONTROL 2 | ||
13 | |||
14 | #define LIRC_PORT_DATA LIRC_LP_BASE /* base */ | ||
15 | #define LIRC_PORT_TIMER LIRC_LP_STATUS /* status port */ | ||
16 | #define LIRC_PORT_TIMER_BIT LP_PBUSY /* busy signal */ | ||
17 | #define LIRC_PORT_SIGNAL LIRC_LP_STATUS /* status port */ | ||
18 | #define LIRC_PORT_SIGNAL_BIT LP_PACK /* ack signal */ | ||
19 | #define LIRC_PORT_IRQ LIRC_LP_CONTROL /* control port */ | ||
20 | |||
21 | #define LIRC_SFH506_DELAY 0 /* delay t_phl in usecs */ | ||
22 | |||
23 | #define LIRC_PARALLEL_MAX_TRANSMITTERS 8 | ||
24 | #define LIRC_PARALLEL_TRANSMITTER_MASK ((1<<LIRC_PARALLEL_MAX_TRANSMITTERS) - 1) | ||
25 | |||
26 | #endif | ||
diff --git a/drivers/staging/lirc/lirc_sasem.c b/drivers/staging/lirc/lirc_sasem.c new file mode 100644 index 00000000000..7080cdeab5a --- /dev/null +++ b/drivers/staging/lirc/lirc_sasem.c | |||
@@ -0,0 +1,939 @@ | |||
1 | /* | ||
2 | * lirc_sasem.c - USB remote support for LIRC | ||
3 | * Version 0.5 | ||
4 | * | ||
5 | * Copyright (C) 2004-2005 Oliver Stabel <oliver.stabel@gmx.de> | ||
6 | * Tim Davies <tim@opensystems.net.au> | ||
7 | * | ||
8 | * This driver was derived from: | ||
9 | * Venky Raju <dev@venky.ws> | ||
10 | * "lirc_imon - "LIRC/VFD driver for Ahanix/Soundgraph IMON IR/VFD" | ||
11 | * Paul Miller <pmiller9@users.sourceforge.net>'s 2003-2004 | ||
12 | * "lirc_atiusb - USB remote support for LIRC" | ||
13 | * Culver Consulting Services <henry@culcon.com>'s 2003 | ||
14 | * "Sasem OnAir VFD/IR USB driver" | ||
15 | * | ||
16 | * | ||
17 | * NOTE - The LCDproc iMon driver should work with this module. More info at | ||
18 | * http://www.frogstorm.info/sasem | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | * This program is free software; you can redistribute it and/or modify | ||
23 | * it under the terms of the GNU General Public License as published by | ||
24 | * the Free Software Foundation; either version 2 of the License, or | ||
25 | * (at your option) any later version. | ||
26 | * | ||
27 | * This program is distributed in the hope that it will be useful, | ||
28 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
29 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
30 | * GNU General Public License for more details. | ||
31 | * | ||
32 | * You should have received a copy of the GNU General Public License | ||
33 | * along with this program; if not, write to the Free Software | ||
34 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
35 | */ | ||
36 | |||
37 | #include <linux/errno.h> | ||
38 | #include <linux/init.h> | ||
39 | #include <linux/kernel.h> | ||
40 | #include <linux/module.h> | ||
41 | #include <linux/slab.h> | ||
42 | #include <linux/uaccess.h> | ||
43 | #include <linux/usb.h> | ||
44 | |||
45 | #include <media/lirc.h> | ||
46 | #include <media/lirc_dev.h> | ||
47 | |||
48 | |||
49 | #define MOD_AUTHOR "Oliver Stabel <oliver.stabel@gmx.de>, " \ | ||
50 | "Tim Davies <tim@opensystems.net.au>" | ||
51 | #define MOD_DESC "USB Driver for Sasem Remote Controller V1.1" | ||
52 | #define MOD_NAME "lirc_sasem" | ||
53 | #define MOD_VERSION "0.5" | ||
54 | |||
55 | #define VFD_MINOR_BASE 144 /* Same as LCD */ | ||
56 | #define DEVICE_NAME "lcd%d" | ||
57 | |||
58 | #define BUF_CHUNK_SIZE 8 | ||
59 | #define BUF_SIZE 128 | ||
60 | |||
61 | #define IOCTL_LCD_CONTRAST 1 | ||
62 | |||
63 | /*** P R O T O T Y P E S ***/ | ||
64 | |||
65 | /* USB Callback prototypes */ | ||
66 | static int sasem_probe(struct usb_interface *interface, | ||
67 | const struct usb_device_id *id); | ||
68 | static void sasem_disconnect(struct usb_interface *interface); | ||
69 | static void usb_rx_callback(struct urb *urb); | ||
70 | static void usb_tx_callback(struct urb *urb); | ||
71 | |||
72 | /* VFD file_operations function prototypes */ | ||
73 | static int vfd_open(struct inode *inode, struct file *file); | ||
74 | static long vfd_ioctl(struct file *file, unsigned cmd, unsigned long arg); | ||
75 | static int vfd_close(struct inode *inode, struct file *file); | ||
76 | static ssize_t vfd_write(struct file *file, const char *buf, | ||
77 | size_t n_bytes, loff_t *pos); | ||
78 | |||
79 | /* LIRC driver function prototypes */ | ||
80 | static int ir_open(void *data); | ||
81 | static void ir_close(void *data); | ||
82 | |||
83 | /* Driver init/exit prototypes */ | ||
84 | static int __init sasem_init(void); | ||
85 | static void __exit sasem_exit(void); | ||
86 | |||
87 | /*** G L O B A L S ***/ | ||
88 | #define SASEM_DATA_BUF_SZ 32 | ||
89 | |||
90 | struct sasem_context { | ||
91 | |||
92 | struct usb_device *dev; | ||
93 | int vfd_isopen; /* VFD port has been opened */ | ||
94 | unsigned int vfd_contrast; /* VFD contrast */ | ||
95 | int ir_isopen; /* IR port has been opened */ | ||
96 | int dev_present; /* USB device presence */ | ||
97 | struct mutex ctx_lock; /* to lock this object */ | ||
98 | wait_queue_head_t remove_ok; /* For unexpected USB disconnects */ | ||
99 | |||
100 | struct lirc_driver *driver; | ||
101 | struct usb_endpoint_descriptor *rx_endpoint; | ||
102 | struct usb_endpoint_descriptor *tx_endpoint; | ||
103 | struct urb *rx_urb; | ||
104 | struct urb *tx_urb; | ||
105 | unsigned char usb_rx_buf[8]; | ||
106 | unsigned char usb_tx_buf[8]; | ||
107 | |||
108 | struct tx_t { | ||
109 | unsigned char data_buf[SASEM_DATA_BUF_SZ]; /* user data buffer */ | ||
110 | struct completion finished; /* wait for write to finish */ | ||
111 | atomic_t busy; /* write in progress */ | ||
112 | int status; /* status of tx completion */ | ||
113 | } tx; | ||
114 | |||
115 | /* for dealing with repeat codes (wish there was a toggle bit!) */ | ||
116 | struct timeval presstime; | ||
117 | char lastcode[8]; | ||
118 | int codesaved; | ||
119 | }; | ||
120 | |||
121 | /* VFD file operations */ | ||
122 | static const struct file_operations vfd_fops = { | ||
123 | .owner = THIS_MODULE, | ||
124 | .open = &vfd_open, | ||
125 | .write = &vfd_write, | ||
126 | .unlocked_ioctl = &vfd_ioctl, | ||
127 | .release = &vfd_close, | ||
128 | .llseek = noop_llseek, | ||
129 | }; | ||
130 | |||
131 | /* USB Device ID for Sasem USB Control Board */ | ||
132 | static struct usb_device_id sasem_usb_id_table[] = { | ||
133 | /* Sasem USB Control Board */ | ||
134 | { USB_DEVICE(0x11ba, 0x0101) }, | ||
135 | /* Terminating entry */ | ||
136 | {} | ||
137 | }; | ||
138 | |||
139 | /* USB Device data */ | ||
140 | static struct usb_driver sasem_driver = { | ||
141 | .name = MOD_NAME, | ||
142 | .probe = sasem_probe, | ||
143 | .disconnect = sasem_disconnect, | ||
144 | .id_table = sasem_usb_id_table, | ||
145 | }; | ||
146 | |||
147 | static struct usb_class_driver sasem_class = { | ||
148 | .name = DEVICE_NAME, | ||
149 | .fops = &vfd_fops, | ||
150 | .minor_base = VFD_MINOR_BASE, | ||
151 | }; | ||
152 | |||
153 | /* to prevent races between open() and disconnect() */ | ||
154 | static DEFINE_MUTEX(disconnect_lock); | ||
155 | |||
156 | static int debug; | ||
157 | |||
158 | |||
159 | /*** M O D U L E C O D E ***/ | ||
160 | |||
161 | MODULE_AUTHOR(MOD_AUTHOR); | ||
162 | MODULE_DESCRIPTION(MOD_DESC); | ||
163 | MODULE_LICENSE("GPL"); | ||
164 | module_param(debug, int, S_IRUGO | S_IWUSR); | ||
165 | MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes (default: no)"); | ||
166 | |||
167 | static void delete_context(struct sasem_context *context) | ||
168 | { | ||
169 | usb_free_urb(context->tx_urb); /* VFD */ | ||
170 | usb_free_urb(context->rx_urb); /* IR */ | ||
171 | lirc_buffer_free(context->driver->rbuf); | ||
172 | kfree(context->driver->rbuf); | ||
173 | kfree(context->driver); | ||
174 | kfree(context); | ||
175 | |||
176 | if (debug) | ||
177 | printk(KERN_INFO "%s: context deleted\n", __func__); | ||
178 | } | ||
179 | |||
180 | static void deregister_from_lirc(struct sasem_context *context) | ||
181 | { | ||
182 | int retval; | ||
183 | int minor = context->driver->minor; | ||
184 | |||
185 | retval = lirc_unregister_driver(minor); | ||
186 | if (retval) | ||
187 | err("%s: unable to deregister from lirc (%d)", | ||
188 | __func__, retval); | ||
189 | else | ||
190 | printk(KERN_INFO "Deregistered Sasem driver (minor:%d)\n", | ||
191 | minor); | ||
192 | |||
193 | } | ||
194 | |||
195 | /** | ||
196 | * Called when the VFD device (e.g. /dev/usb/lcd) | ||
197 | * is opened by the application. | ||
198 | */ | ||
199 | static int vfd_open(struct inode *inode, struct file *file) | ||
200 | { | ||
201 | struct usb_interface *interface; | ||
202 | struct sasem_context *context = NULL; | ||
203 | int subminor; | ||
204 | int retval = 0; | ||
205 | |||
206 | /* prevent races with disconnect */ | ||
207 | mutex_lock(&disconnect_lock); | ||
208 | |||
209 | subminor = iminor(inode); | ||
210 | interface = usb_find_interface(&sasem_driver, subminor); | ||
211 | if (!interface) { | ||
212 | err("%s: could not find interface for minor %d", | ||
213 | __func__, subminor); | ||
214 | retval = -ENODEV; | ||
215 | goto exit; | ||
216 | } | ||
217 | context = usb_get_intfdata(interface); | ||
218 | |||
219 | if (!context) { | ||
220 | err("%s: no context found for minor %d", | ||
221 | __func__, subminor); | ||
222 | retval = -ENODEV; | ||
223 | goto exit; | ||
224 | } | ||
225 | |||
226 | mutex_lock(&context->ctx_lock); | ||
227 | |||
228 | if (context->vfd_isopen) { | ||
229 | err("%s: VFD port is already open", __func__); | ||
230 | retval = -EBUSY; | ||
231 | } else { | ||
232 | context->vfd_isopen = 1; | ||
233 | file->private_data = context; | ||
234 | printk(KERN_INFO "VFD port opened\n"); | ||
235 | } | ||
236 | |||
237 | mutex_unlock(&context->ctx_lock); | ||
238 | |||
239 | exit: | ||
240 | mutex_unlock(&disconnect_lock); | ||
241 | return retval; | ||
242 | } | ||
243 | |||
244 | /** | ||
245 | * Called when the VFD device (e.g. /dev/usb/lcd) | ||
246 | * is closed by the application. | ||
247 | */ | ||
248 | static long vfd_ioctl(struct file *file, unsigned cmd, unsigned long arg) | ||
249 | { | ||
250 | struct sasem_context *context = NULL; | ||
251 | |||
252 | context = (struct sasem_context *) file->private_data; | ||
253 | |||
254 | if (!context) { | ||
255 | err("%s: no context for device", __func__); | ||
256 | return -ENODEV; | ||
257 | } | ||
258 | |||
259 | mutex_lock(&context->ctx_lock); | ||
260 | |||
261 | switch (cmd) { | ||
262 | case IOCTL_LCD_CONTRAST: | ||
263 | if (arg > 1000) | ||
264 | arg = 1000; | ||
265 | context->vfd_contrast = (unsigned int)arg; | ||
266 | break; | ||
267 | default: | ||
268 | printk(KERN_INFO "Unknown IOCTL command\n"); | ||
269 | mutex_unlock(&context->ctx_lock); | ||
270 | return -ENOIOCTLCMD; /* not supported */ | ||
271 | } | ||
272 | |||
273 | mutex_unlock(&context->ctx_lock); | ||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | /** | ||
278 | * Called when the VFD device (e.g. /dev/usb/lcd) | ||
279 | * is closed by the application. | ||
280 | */ | ||
281 | static int vfd_close(struct inode *inode, struct file *file) | ||
282 | { | ||
283 | struct sasem_context *context = NULL; | ||
284 | int retval = 0; | ||
285 | |||
286 | context = (struct sasem_context *) file->private_data; | ||
287 | |||
288 | if (!context) { | ||
289 | err("%s: no context for device", __func__); | ||
290 | return -ENODEV; | ||
291 | } | ||
292 | |||
293 | mutex_lock(&context->ctx_lock); | ||
294 | |||
295 | if (!context->vfd_isopen) { | ||
296 | err("%s: VFD is not open", __func__); | ||
297 | retval = -EIO; | ||
298 | } else { | ||
299 | context->vfd_isopen = 0; | ||
300 | printk(KERN_INFO "VFD port closed\n"); | ||
301 | if (!context->dev_present && !context->ir_isopen) { | ||
302 | |||
303 | /* Device disconnected before close and IR port is | ||
304 | * not open. If IR port is open, context will be | ||
305 | * deleted by ir_close. */ | ||
306 | mutex_unlock(&context->ctx_lock); | ||
307 | delete_context(context); | ||
308 | return retval; | ||
309 | } | ||
310 | } | ||
311 | |||
312 | mutex_unlock(&context->ctx_lock); | ||
313 | return retval; | ||
314 | } | ||
315 | |||
316 | /** | ||
317 | * Sends a packet to the VFD. | ||
318 | */ | ||
319 | static int send_packet(struct sasem_context *context) | ||
320 | { | ||
321 | unsigned int pipe; | ||
322 | int interval = 0; | ||
323 | int retval = 0; | ||
324 | |||
325 | pipe = usb_sndintpipe(context->dev, | ||
326 | context->tx_endpoint->bEndpointAddress); | ||
327 | interval = context->tx_endpoint->bInterval; | ||
328 | |||
329 | usb_fill_int_urb(context->tx_urb, context->dev, pipe, | ||
330 | context->usb_tx_buf, sizeof(context->usb_tx_buf), | ||
331 | usb_tx_callback, context, interval); | ||
332 | |||
333 | context->tx_urb->actual_length = 0; | ||
334 | |||
335 | init_completion(&context->tx.finished); | ||
336 | atomic_set(&(context->tx.busy), 1); | ||
337 | |||
338 | retval = usb_submit_urb(context->tx_urb, GFP_KERNEL); | ||
339 | if (retval) { | ||
340 | atomic_set(&(context->tx.busy), 0); | ||
341 | err("%s: error submitting urb (%d)", __func__, retval); | ||
342 | } else { | ||
343 | /* Wait for transmission to complete (or abort) */ | ||
344 | mutex_unlock(&context->ctx_lock); | ||
345 | wait_for_completion(&context->tx.finished); | ||
346 | mutex_lock(&context->ctx_lock); | ||
347 | |||
348 | retval = context->tx.status; | ||
349 | if (retval) | ||
350 | err("%s: packet tx failed (%d)", __func__, retval); | ||
351 | } | ||
352 | |||
353 | return retval; | ||
354 | } | ||
355 | |||
356 | /** | ||
357 | * Writes data to the VFD. The Sasem VFD is 2x16 characters | ||
358 | * and requires data in 9 consecutive USB interrupt packets, | ||
359 | * each packet carrying 8 bytes. | ||
360 | */ | ||
361 | static ssize_t vfd_write(struct file *file, const char *buf, | ||
362 | size_t n_bytes, loff_t *pos) | ||
363 | { | ||
364 | int i; | ||
365 | int retval = 0; | ||
366 | struct sasem_context *context; | ||
367 | int *data_buf = NULL; | ||
368 | |||
369 | context = (struct sasem_context *) file->private_data; | ||
370 | if (!context) { | ||
371 | err("%s: no context for device", __func__); | ||
372 | return -ENODEV; | ||
373 | } | ||
374 | |||
375 | mutex_lock(&context->ctx_lock); | ||
376 | |||
377 | if (!context->dev_present) { | ||
378 | err("%s: no Sasem device present", __func__); | ||
379 | retval = -ENODEV; | ||
380 | goto exit; | ||
381 | } | ||
382 | |||
383 | if (n_bytes <= 0 || n_bytes > SASEM_DATA_BUF_SZ) { | ||
384 | err("%s: invalid payload size", __func__); | ||
385 | retval = -EINVAL; | ||
386 | goto exit; | ||
387 | } | ||
388 | |||
389 | data_buf = memdup_user(buf, n_bytes); | ||
390 | if (IS_ERR(data_buf)) { | ||
391 | retval = PTR_ERR(data_buf); | ||
392 | goto exit; | ||
393 | } | ||
394 | |||
395 | memcpy(context->tx.data_buf, data_buf, n_bytes); | ||
396 | |||
397 | /* Pad with spaces */ | ||
398 | for (i = n_bytes; i < SASEM_DATA_BUF_SZ; ++i) | ||
399 | context->tx.data_buf[i] = ' '; | ||
400 | |||
401 | /* Nine 8 byte packets to be sent */ | ||
402 | /* NOTE: "\x07\x01\0\0\0\0\0\0" or "\x0c\0\0\0\0\0\0\0" | ||
403 | * will clear the VFD */ | ||
404 | for (i = 0; i < 9; i++) { | ||
405 | switch (i) { | ||
406 | case 0: | ||
407 | memcpy(context->usb_tx_buf, "\x07\0\0\0\0\0\0\0", 8); | ||
408 | context->usb_tx_buf[1] = (context->vfd_contrast) ? | ||
409 | (0x2B - (context->vfd_contrast - 1) / 250) | ||
410 | : 0x2B; | ||
411 | break; | ||
412 | case 1: | ||
413 | memcpy(context->usb_tx_buf, "\x09\x01\0\0\0\0\0\0", 8); | ||
414 | break; | ||
415 | case 2: | ||
416 | memcpy(context->usb_tx_buf, "\x0b\x01\0\0\0\0\0\0", 8); | ||
417 | break; | ||
418 | case 3: | ||
419 | memcpy(context->usb_tx_buf, context->tx.data_buf, 8); | ||
420 | break; | ||
421 | case 4: | ||
422 | memcpy(context->usb_tx_buf, | ||
423 | context->tx.data_buf + 8, 8); | ||
424 | break; | ||
425 | case 5: | ||
426 | memcpy(context->usb_tx_buf, "\x09\x01\0\0\0\0\0\0", 8); | ||
427 | break; | ||
428 | case 6: | ||
429 | memcpy(context->usb_tx_buf, "\x0b\x02\0\0\0\0\0\0", 8); | ||
430 | break; | ||
431 | case 7: | ||
432 | memcpy(context->usb_tx_buf, | ||
433 | context->tx.data_buf + 16, 8); | ||
434 | break; | ||
435 | case 8: | ||
436 | memcpy(context->usb_tx_buf, | ||
437 | context->tx.data_buf + 24, 8); | ||
438 | break; | ||
439 | } | ||
440 | retval = send_packet(context); | ||
441 | if (retval) { | ||
442 | |||
443 | err("%s: send packet failed for packet #%d", | ||
444 | __func__, i); | ||
445 | goto exit; | ||
446 | } | ||
447 | } | ||
448 | exit: | ||
449 | |||
450 | mutex_unlock(&context->ctx_lock); | ||
451 | kfree(data_buf); | ||
452 | |||
453 | return (!retval) ? n_bytes : retval; | ||
454 | } | ||
455 | |||
456 | /** | ||
457 | * Callback function for USB core API: transmit data | ||
458 | */ | ||
459 | static void usb_tx_callback(struct urb *urb) | ||
460 | { | ||
461 | struct sasem_context *context; | ||
462 | |||
463 | if (!urb) | ||
464 | return; | ||
465 | context = (struct sasem_context *) urb->context; | ||
466 | if (!context) | ||
467 | return; | ||
468 | |||
469 | context->tx.status = urb->status; | ||
470 | |||
471 | /* notify waiters that write has finished */ | ||
472 | atomic_set(&context->tx.busy, 0); | ||
473 | complete(&context->tx.finished); | ||
474 | |||
475 | return; | ||
476 | } | ||
477 | |||
478 | /** | ||
479 | * Called by lirc_dev when the application opens /dev/lirc | ||
480 | */ | ||
481 | static int ir_open(void *data) | ||
482 | { | ||
483 | int retval = 0; | ||
484 | struct sasem_context *context; | ||
485 | |||
486 | /* prevent races with disconnect */ | ||
487 | mutex_lock(&disconnect_lock); | ||
488 | |||
489 | context = (struct sasem_context *) data; | ||
490 | |||
491 | mutex_lock(&context->ctx_lock); | ||
492 | |||
493 | if (context->ir_isopen) { | ||
494 | err("%s: IR port is already open", __func__); | ||
495 | retval = -EBUSY; | ||
496 | goto exit; | ||
497 | } | ||
498 | |||
499 | usb_fill_int_urb(context->rx_urb, context->dev, | ||
500 | usb_rcvintpipe(context->dev, | ||
501 | context->rx_endpoint->bEndpointAddress), | ||
502 | context->usb_rx_buf, sizeof(context->usb_rx_buf), | ||
503 | usb_rx_callback, context, context->rx_endpoint->bInterval); | ||
504 | |||
505 | retval = usb_submit_urb(context->rx_urb, GFP_KERNEL); | ||
506 | |||
507 | if (retval) | ||
508 | err("%s: usb_submit_urb failed for ir_open (%d)", | ||
509 | __func__, retval); | ||
510 | else { | ||
511 | context->ir_isopen = 1; | ||
512 | printk(KERN_INFO "IR port opened\n"); | ||
513 | } | ||
514 | |||
515 | exit: | ||
516 | mutex_unlock(&context->ctx_lock); | ||
517 | |||
518 | mutex_unlock(&disconnect_lock); | ||
519 | return retval; | ||
520 | } | ||
521 | |||
522 | /** | ||
523 | * Called by lirc_dev when the application closes /dev/lirc | ||
524 | */ | ||
525 | static void ir_close(void *data) | ||
526 | { | ||
527 | struct sasem_context *context; | ||
528 | |||
529 | context = (struct sasem_context *)data; | ||
530 | if (!context) { | ||
531 | err("%s: no context for device", __func__); | ||
532 | return; | ||
533 | } | ||
534 | |||
535 | mutex_lock(&context->ctx_lock); | ||
536 | |||
537 | usb_kill_urb(context->rx_urb); | ||
538 | context->ir_isopen = 0; | ||
539 | printk(KERN_INFO "IR port closed\n"); | ||
540 | |||
541 | if (!context->dev_present) { | ||
542 | |||
543 | /* | ||
544 | * Device disconnected while IR port was | ||
545 | * still open. Driver was not deregistered | ||
546 | * at disconnect time, so do it now. | ||
547 | */ | ||
548 | deregister_from_lirc(context); | ||
549 | |||
550 | if (!context->vfd_isopen) { | ||
551 | |||
552 | mutex_unlock(&context->ctx_lock); | ||
553 | delete_context(context); | ||
554 | return; | ||
555 | } | ||
556 | /* If VFD port is open, context will be deleted by vfd_close */ | ||
557 | } | ||
558 | |||
559 | mutex_unlock(&context->ctx_lock); | ||
560 | return; | ||
561 | } | ||
562 | |||
563 | /** | ||
564 | * Process the incoming packet | ||
565 | */ | ||
566 | static void incoming_packet(struct sasem_context *context, | ||
567 | struct urb *urb) | ||
568 | { | ||
569 | int len = urb->actual_length; | ||
570 | unsigned char *buf = urb->transfer_buffer; | ||
571 | long ms; | ||
572 | struct timeval tv; | ||
573 | int i; | ||
574 | |||
575 | if (len != 8) { | ||
576 | printk(KERN_WARNING "%s: invalid incoming packet size (%d)\n", | ||
577 | __func__, len); | ||
578 | return; | ||
579 | } | ||
580 | |||
581 | if (debug) { | ||
582 | printk(KERN_INFO "Incoming data: "); | ||
583 | for (i = 0; i < 8; ++i) | ||
584 | printk(KERN_CONT "%02x ", buf[i]); | ||
585 | printk(KERN_CONT "\n"); | ||
586 | } | ||
587 | |||
588 | /* | ||
589 | * Lirc could deal with the repeat code, but we really need to block it | ||
590 | * if it arrives too late. Otherwise we could repeat the wrong code. | ||
591 | */ | ||
592 | |||
593 | /* get the time since the last button press */ | ||
594 | do_gettimeofday(&tv); | ||
595 | ms = (tv.tv_sec - context->presstime.tv_sec) * 1000 + | ||
596 | (tv.tv_usec - context->presstime.tv_usec) / 1000; | ||
597 | |||
598 | if (memcmp(buf, "\x08\0\0\0\0\0\0\0", 8) == 0) { | ||
599 | /* | ||
600 | * the repeat code is being sent, so we copy | ||
601 | * the old code to LIRC | ||
602 | */ | ||
603 | |||
604 | /* | ||
605 | * NOTE: Only if the last code was less than 250ms ago | ||
606 | * - no one should be able to push another (undetected) button | ||
607 | * in that time and then get a false repeat of the previous | ||
608 | * press but it is long enough for a genuine repeat | ||
609 | */ | ||
610 | if ((ms < 250) && (context->codesaved != 0)) { | ||
611 | memcpy(buf, &context->lastcode, 8); | ||
612 | context->presstime.tv_sec = tv.tv_sec; | ||
613 | context->presstime.tv_usec = tv.tv_usec; | ||
614 | } | ||
615 | } else { | ||
616 | /* save the current valid code for repeats */ | ||
617 | memcpy(&context->lastcode, buf, 8); | ||
618 | /* | ||
619 | * set flag to signal a valid code was save; | ||
620 | * just for safety reasons | ||
621 | */ | ||
622 | context->codesaved = 1; | ||
623 | context->presstime.tv_sec = tv.tv_sec; | ||
624 | context->presstime.tv_usec = tv.tv_usec; | ||
625 | } | ||
626 | |||
627 | lirc_buffer_write(context->driver->rbuf, buf); | ||
628 | wake_up(&context->driver->rbuf->wait_poll); | ||
629 | } | ||
630 | |||
631 | /** | ||
632 | * Callback function for USB core API: receive data | ||
633 | */ | ||
634 | static void usb_rx_callback(struct urb *urb) | ||
635 | { | ||
636 | struct sasem_context *context; | ||
637 | |||
638 | if (!urb) | ||
639 | return; | ||
640 | context = (struct sasem_context *) urb->context; | ||
641 | if (!context) | ||
642 | return; | ||
643 | |||
644 | switch (urb->status) { | ||
645 | |||
646 | case -ENOENT: /* usbcore unlink successful! */ | ||
647 | return; | ||
648 | |||
649 | case 0: | ||
650 | if (context->ir_isopen) | ||
651 | incoming_packet(context, urb); | ||
652 | break; | ||
653 | |||
654 | default: | ||
655 | printk(KERN_WARNING "%s: status (%d): ignored", | ||
656 | __func__, urb->status); | ||
657 | break; | ||
658 | } | ||
659 | |||
660 | usb_submit_urb(context->rx_urb, GFP_ATOMIC); | ||
661 | return; | ||
662 | } | ||
663 | |||
664 | |||
665 | |||
666 | /** | ||
667 | * Callback function for USB core API: Probe | ||
668 | */ | ||
669 | static int sasem_probe(struct usb_interface *interface, | ||
670 | const struct usb_device_id *id) | ||
671 | { | ||
672 | struct usb_device *dev = NULL; | ||
673 | struct usb_host_interface *iface_desc = NULL; | ||
674 | struct usb_endpoint_descriptor *rx_endpoint = NULL; | ||
675 | struct usb_endpoint_descriptor *tx_endpoint = NULL; | ||
676 | struct urb *rx_urb = NULL; | ||
677 | struct urb *tx_urb = NULL; | ||
678 | struct lirc_driver *driver = NULL; | ||
679 | struct lirc_buffer *rbuf = NULL; | ||
680 | int lirc_minor = 0; | ||
681 | int num_endpoints; | ||
682 | int retval = 0; | ||
683 | int vfd_ep_found; | ||
684 | int ir_ep_found; | ||
685 | int alloc_status; | ||
686 | struct sasem_context *context = NULL; | ||
687 | int i; | ||
688 | |||
689 | printk(KERN_INFO "%s: found Sasem device\n", __func__); | ||
690 | |||
691 | |||
692 | dev = usb_get_dev(interface_to_usbdev(interface)); | ||
693 | iface_desc = interface->cur_altsetting; | ||
694 | num_endpoints = iface_desc->desc.bNumEndpoints; | ||
695 | |||
696 | /* | ||
697 | * Scan the endpoint list and set: | ||
698 | * first input endpoint = IR endpoint | ||
699 | * first output endpoint = VFD endpoint | ||
700 | */ | ||
701 | |||
702 | ir_ep_found = 0; | ||
703 | vfd_ep_found = 0; | ||
704 | |||
705 | for (i = 0; i < num_endpoints && !(ir_ep_found && vfd_ep_found); ++i) { | ||
706 | |||
707 | struct usb_endpoint_descriptor *ep; | ||
708 | int ep_dir; | ||
709 | int ep_type; | ||
710 | ep = &iface_desc->endpoint [i].desc; | ||
711 | ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK; | ||
712 | ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; | ||
713 | |||
714 | if (!ir_ep_found && | ||
715 | ep_dir == USB_DIR_IN && | ||
716 | ep_type == USB_ENDPOINT_XFER_INT) { | ||
717 | |||
718 | rx_endpoint = ep; | ||
719 | ir_ep_found = 1; | ||
720 | if (debug) | ||
721 | printk(KERN_INFO "%s: found IR endpoint\n", | ||
722 | __func__); | ||
723 | |||
724 | } else if (!vfd_ep_found && | ||
725 | ep_dir == USB_DIR_OUT && | ||
726 | ep_type == USB_ENDPOINT_XFER_INT) { | ||
727 | |||
728 | tx_endpoint = ep; | ||
729 | vfd_ep_found = 1; | ||
730 | if (debug) | ||
731 | printk(KERN_INFO "%s: found VFD endpoint\n", | ||
732 | __func__); | ||
733 | } | ||
734 | } | ||
735 | |||
736 | /* Input endpoint is mandatory */ | ||
737 | if (!ir_ep_found) { | ||
738 | |||
739 | err("%s: no valid input (IR) endpoint found.", __func__); | ||
740 | retval = -ENODEV; | ||
741 | goto exit; | ||
742 | } | ||
743 | |||
744 | if (!vfd_ep_found) | ||
745 | printk(KERN_INFO "%s: no valid output (VFD) endpoint found.\n", | ||
746 | __func__); | ||
747 | |||
748 | |||
749 | /* Allocate memory */ | ||
750 | alloc_status = 0; | ||
751 | |||
752 | context = kzalloc(sizeof(struct sasem_context), GFP_KERNEL); | ||
753 | if (!context) { | ||
754 | err("%s: kzalloc failed for context", __func__); | ||
755 | alloc_status = 1; | ||
756 | goto alloc_status_switch; | ||
757 | } | ||
758 | driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); | ||
759 | if (!driver) { | ||
760 | err("%s: kzalloc failed for lirc_driver", __func__); | ||
761 | alloc_status = 2; | ||
762 | goto alloc_status_switch; | ||
763 | } | ||
764 | rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); | ||
765 | if (!rbuf) { | ||
766 | err("%s: kmalloc failed for lirc_buffer", __func__); | ||
767 | alloc_status = 3; | ||
768 | goto alloc_status_switch; | ||
769 | } | ||
770 | if (lirc_buffer_init(rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) { | ||
771 | err("%s: lirc_buffer_init failed", __func__); | ||
772 | alloc_status = 4; | ||
773 | goto alloc_status_switch; | ||
774 | } | ||
775 | rx_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
776 | if (!rx_urb) { | ||
777 | err("%s: usb_alloc_urb failed for IR urb", __func__); | ||
778 | alloc_status = 5; | ||
779 | goto alloc_status_switch; | ||
780 | } | ||
781 | if (vfd_ep_found) { | ||
782 | tx_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
783 | if (!tx_urb) { | ||
784 | err("%s: usb_alloc_urb failed for VFD urb", | ||
785 | __func__); | ||
786 | alloc_status = 6; | ||
787 | goto alloc_status_switch; | ||
788 | } | ||
789 | } | ||
790 | |||
791 | mutex_init(&context->ctx_lock); | ||
792 | |||
793 | strcpy(driver->name, MOD_NAME); | ||
794 | driver->minor = -1; | ||
795 | driver->code_length = 64; | ||
796 | driver->sample_rate = 0; | ||
797 | driver->features = LIRC_CAN_REC_LIRCCODE; | ||
798 | driver->data = context; | ||
799 | driver->rbuf = rbuf; | ||
800 | driver->set_use_inc = ir_open; | ||
801 | driver->set_use_dec = ir_close; | ||
802 | driver->dev = &interface->dev; | ||
803 | driver->owner = THIS_MODULE; | ||
804 | |||
805 | mutex_lock(&context->ctx_lock); | ||
806 | |||
807 | lirc_minor = lirc_register_driver(driver); | ||
808 | if (lirc_minor < 0) { | ||
809 | err("%s: lirc_register_driver failed", __func__); | ||
810 | alloc_status = 7; | ||
811 | retval = lirc_minor; | ||
812 | goto unlock; | ||
813 | } else | ||
814 | printk(KERN_INFO "%s: Registered Sasem driver (minor:%d)\n", | ||
815 | __func__, lirc_minor); | ||
816 | |||
817 | alloc_status_switch: | ||
818 | |||
819 | switch (alloc_status) { | ||
820 | |||
821 | case 7: | ||
822 | if (vfd_ep_found) | ||
823 | usb_free_urb(tx_urb); | ||
824 | case 6: | ||
825 | usb_free_urb(rx_urb); | ||
826 | case 5: | ||
827 | lirc_buffer_free(rbuf); | ||
828 | case 4: | ||
829 | kfree(rbuf); | ||
830 | case 3: | ||
831 | kfree(driver); | ||
832 | case 2: | ||
833 | kfree(context); | ||
834 | context = NULL; | ||
835 | case 1: | ||
836 | retval = -ENOMEM; | ||
837 | goto unlock; | ||
838 | } | ||
839 | |||
840 | /* Needed while unregistering! */ | ||
841 | driver->minor = lirc_minor; | ||
842 | |||
843 | context->dev = dev; | ||
844 | context->dev_present = 1; | ||
845 | context->rx_endpoint = rx_endpoint; | ||
846 | context->rx_urb = rx_urb; | ||
847 | if (vfd_ep_found) { | ||
848 | context->tx_endpoint = tx_endpoint; | ||
849 | context->tx_urb = tx_urb; | ||
850 | context->vfd_contrast = 1000; /* range 0 - 1000 */ | ||
851 | } | ||
852 | context->driver = driver; | ||
853 | |||
854 | usb_set_intfdata(interface, context); | ||
855 | |||
856 | if (vfd_ep_found) { | ||
857 | |||
858 | if (debug) | ||
859 | printk(KERN_INFO "Registering VFD with sysfs\n"); | ||
860 | if (usb_register_dev(interface, &sasem_class)) | ||
861 | /* Not a fatal error, so ignore */ | ||
862 | printk(KERN_INFO "%s: could not get a minor number " | ||
863 | "for VFD\n", __func__); | ||
864 | } | ||
865 | |||
866 | printk(KERN_INFO "%s: Sasem device on usb<%d:%d> initialized\n", | ||
867 | __func__, dev->bus->busnum, dev->devnum); | ||
868 | unlock: | ||
869 | mutex_unlock(&context->ctx_lock); | ||
870 | exit: | ||
871 | return retval; | ||
872 | } | ||
873 | |||
874 | /** | ||
875 | * Callback function for USB core API: disonnect | ||
876 | */ | ||
877 | static void sasem_disconnect(struct usb_interface *interface) | ||
878 | { | ||
879 | struct sasem_context *context; | ||
880 | |||
881 | /* prevent races with ir_open()/vfd_open() */ | ||
882 | mutex_lock(&disconnect_lock); | ||
883 | |||
884 | context = usb_get_intfdata(interface); | ||
885 | mutex_lock(&context->ctx_lock); | ||
886 | |||
887 | printk(KERN_INFO "%s: Sasem device disconnected\n", __func__); | ||
888 | |||
889 | usb_set_intfdata(interface, NULL); | ||
890 | context->dev_present = 0; | ||
891 | |||
892 | /* Stop reception */ | ||
893 | usb_kill_urb(context->rx_urb); | ||
894 | |||
895 | /* Abort ongoing write */ | ||
896 | if (atomic_read(&context->tx.busy)) { | ||
897 | |||
898 | usb_kill_urb(context->tx_urb); | ||
899 | wait_for_completion(&context->tx.finished); | ||
900 | } | ||
901 | |||
902 | /* De-register from lirc_dev if IR port is not open */ | ||
903 | if (!context->ir_isopen) | ||
904 | deregister_from_lirc(context); | ||
905 | |||
906 | usb_deregister_dev(interface, &sasem_class); | ||
907 | |||
908 | mutex_unlock(&context->ctx_lock); | ||
909 | |||
910 | if (!context->ir_isopen && !context->vfd_isopen) | ||
911 | delete_context(context); | ||
912 | |||
913 | mutex_unlock(&disconnect_lock); | ||
914 | } | ||
915 | |||
916 | static int __init sasem_init(void) | ||
917 | { | ||
918 | int rc; | ||
919 | |||
920 | printk(KERN_INFO MOD_DESC ", v" MOD_VERSION "\n"); | ||
921 | printk(KERN_INFO MOD_AUTHOR "\n"); | ||
922 | |||
923 | rc = usb_register(&sasem_driver); | ||
924 | if (rc < 0) { | ||
925 | err("%s: usb register failed (%d)", __func__, rc); | ||
926 | return -ENODEV; | ||
927 | } | ||
928 | return 0; | ||
929 | } | ||
930 | |||
931 | static void __exit sasem_exit(void) | ||
932 | { | ||
933 | usb_deregister(&sasem_driver); | ||
934 | printk(KERN_INFO "module removed. Goodbye!\n"); | ||
935 | } | ||
936 | |||
937 | |||
938 | module_init(sasem_init); | ||
939 | module_exit(sasem_exit); | ||
diff --git a/drivers/staging/lirc/lirc_serial.c b/drivers/staging/lirc/lirc_serial.c new file mode 100644 index 00000000000..805df913bb6 --- /dev/null +++ b/drivers/staging/lirc/lirc_serial.c | |||
@@ -0,0 +1,1315 @@ | |||
1 | /* | ||
2 | * lirc_serial.c | ||
3 | * | ||
4 | * lirc_serial - Device driver that records pulse- and pause-lengths | ||
5 | * (space-lengths) between DDCD event on a serial port. | ||
6 | * | ||
7 | * Copyright (C) 1996,97 Ralph Metzler <rjkm@thp.uni-koeln.de> | ||
8 | * Copyright (C) 1998 Trent Piepho <xyzzy@u.washington.edu> | ||
9 | * Copyright (C) 1998 Ben Pfaff <blp@gnu.org> | ||
10 | * Copyright (C) 1999 Christoph Bartelmus <lirc@bartelmus.de> | ||
11 | * Copyright (C) 2007 Andrei Tanas <andrei@tanas.ca> (suspend/resume support) | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | /* | ||
29 | * Steve's changes to improve transmission fidelity: | ||
30 | * - for systems with the rdtsc instruction and the clock counter, a | ||
31 | * send_pule that times the pulses directly using the counter. | ||
32 | * This means that the LIRC_SERIAL_TRANSMITTER_LATENCY fudge is | ||
33 | * not needed. Measurement shows very stable waveform, even where | ||
34 | * PCI activity slows the access to the UART, which trips up other | ||
35 | * versions. | ||
36 | * - For other system, non-integer-microsecond pulse/space lengths, | ||
37 | * done using fixed point binary. So, much more accurate carrier | ||
38 | * frequency. | ||
39 | * - fine tuned transmitter latency, taking advantage of fractional | ||
40 | * microseconds in previous change | ||
41 | * - Fixed bug in the way transmitter latency was accounted for by | ||
42 | * tuning the pulse lengths down - the send_pulse routine ignored | ||
43 | * this overhead as it timed the overall pulse length - so the | ||
44 | * pulse frequency was right but overall pulse length was too | ||
45 | * long. Fixed by accounting for latency on each pulse/space | ||
46 | * iteration. | ||
47 | * | ||
48 | * Steve Davies <steve@daviesfam.org> July 2001 | ||
49 | */ | ||
50 | |||
51 | #include <linux/module.h> | ||
52 | #include <linux/errno.h> | ||
53 | #include <linux/signal.h> | ||
54 | #include <linux/sched.h> | ||
55 | #include <linux/fs.h> | ||
56 | #include <linux/interrupt.h> | ||
57 | #include <linux/ioport.h> | ||
58 | #include <linux/kernel.h> | ||
59 | #include <linux/serial_reg.h> | ||
60 | #include <linux/time.h> | ||
61 | #include <linux/string.h> | ||
62 | #include <linux/types.h> | ||
63 | #include <linux/wait.h> | ||
64 | #include <linux/mm.h> | ||
65 | #include <linux/delay.h> | ||
66 | #include <linux/poll.h> | ||
67 | #include <linux/platform_device.h> | ||
68 | |||
69 | #include <asm/system.h> | ||
70 | #include <linux/io.h> | ||
71 | #include <linux/irq.h> | ||
72 | #include <linux/fcntl.h> | ||
73 | #include <linux/spinlock.h> | ||
74 | |||
75 | #ifdef CONFIG_LIRC_SERIAL_NSLU2 | ||
76 | #include <asm/hardware.h> | ||
77 | #endif | ||
78 | /* From Intel IXP42X Developer's Manual (#252480-005): */ | ||
79 | /* ftp://download.intel.com/design/network/manuals/25248005.pdf */ | ||
80 | #define UART_IE_IXP42X_UUE 0x40 /* IXP42X UART Unit enable */ | ||
81 | #define UART_IE_IXP42X_RTOIE 0x10 /* IXP42X Receiver Data Timeout int.enable */ | ||
82 | |||
83 | #include <media/lirc.h> | ||
84 | #include <media/lirc_dev.h> | ||
85 | |||
86 | #define LIRC_DRIVER_NAME "lirc_serial" | ||
87 | |||
88 | struct lirc_serial { | ||
89 | int signal_pin; | ||
90 | int signal_pin_change; | ||
91 | u8 on; | ||
92 | u8 off; | ||
93 | long (*send_pulse)(unsigned long length); | ||
94 | void (*send_space)(long length); | ||
95 | int features; | ||
96 | spinlock_t lock; | ||
97 | }; | ||
98 | |||
99 | #define LIRC_HOMEBREW 0 | ||
100 | #define LIRC_IRDEO 1 | ||
101 | #define LIRC_IRDEO_REMOTE 2 | ||
102 | #define LIRC_ANIMAX 3 | ||
103 | #define LIRC_IGOR 4 | ||
104 | #define LIRC_NSLU2 5 | ||
105 | |||
106 | /*** module parameters ***/ | ||
107 | static int type; | ||
108 | static int io; | ||
109 | static int irq; | ||
110 | static int iommap; | ||
111 | static int ioshift; | ||
112 | static int softcarrier = 1; | ||
113 | static int share_irq; | ||
114 | static int debug; | ||
115 | static int sense = -1; /* -1 = auto, 0 = active high, 1 = active low */ | ||
116 | static int txsense; /* 0 = active high, 1 = active low */ | ||
117 | |||
118 | #define dprintk(fmt, args...) \ | ||
119 | do { \ | ||
120 | if (debug) \ | ||
121 | printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ | ||
122 | fmt, ## args); \ | ||
123 | } while (0) | ||
124 | |||
125 | /* forward declarations */ | ||
126 | static long send_pulse_irdeo(unsigned long length); | ||
127 | static long send_pulse_homebrew(unsigned long length); | ||
128 | static void send_space_irdeo(long length); | ||
129 | static void send_space_homebrew(long length); | ||
130 | |||
131 | static struct lirc_serial hardware[] = { | ||
132 | [LIRC_HOMEBREW] = { | ||
133 | .signal_pin = UART_MSR_DCD, | ||
134 | .signal_pin_change = UART_MSR_DDCD, | ||
135 | .on = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR), | ||
136 | .off = (UART_MCR_RTS | UART_MCR_OUT2), | ||
137 | .send_pulse = send_pulse_homebrew, | ||
138 | .send_space = send_space_homebrew, | ||
139 | #ifdef CONFIG_LIRC_SERIAL_TRANSMITTER | ||
140 | .features = (LIRC_CAN_SET_SEND_DUTY_CYCLE | | ||
141 | LIRC_CAN_SET_SEND_CARRIER | | ||
142 | LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2) | ||
143 | #else | ||
144 | .features = LIRC_CAN_REC_MODE2 | ||
145 | #endif | ||
146 | }, | ||
147 | |||
148 | [LIRC_IRDEO] = { | ||
149 | .signal_pin = UART_MSR_DSR, | ||
150 | .signal_pin_change = UART_MSR_DDSR, | ||
151 | .on = UART_MCR_OUT2, | ||
152 | .off = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2), | ||
153 | .send_pulse = send_pulse_irdeo, | ||
154 | .send_space = send_space_irdeo, | ||
155 | .features = (LIRC_CAN_SET_SEND_DUTY_CYCLE | | ||
156 | LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2) | ||
157 | }, | ||
158 | |||
159 | [LIRC_IRDEO_REMOTE] = { | ||
160 | .signal_pin = UART_MSR_DSR, | ||
161 | .signal_pin_change = UART_MSR_DDSR, | ||
162 | .on = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2), | ||
163 | .off = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2), | ||
164 | .send_pulse = send_pulse_irdeo, | ||
165 | .send_space = send_space_irdeo, | ||
166 | .features = (LIRC_CAN_SET_SEND_DUTY_CYCLE | | ||
167 | LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2) | ||
168 | }, | ||
169 | |||
170 | [LIRC_ANIMAX] = { | ||
171 | .signal_pin = UART_MSR_DCD, | ||
172 | .signal_pin_change = UART_MSR_DDCD, | ||
173 | .on = 0, | ||
174 | .off = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2), | ||
175 | .send_pulse = NULL, | ||
176 | .send_space = NULL, | ||
177 | .features = LIRC_CAN_REC_MODE2 | ||
178 | }, | ||
179 | |||
180 | [LIRC_IGOR] = { | ||
181 | .signal_pin = UART_MSR_DSR, | ||
182 | .signal_pin_change = UART_MSR_DDSR, | ||
183 | .on = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR), | ||
184 | .off = (UART_MCR_RTS | UART_MCR_OUT2), | ||
185 | .send_pulse = send_pulse_homebrew, | ||
186 | .send_space = send_space_homebrew, | ||
187 | #ifdef CONFIG_LIRC_SERIAL_TRANSMITTER | ||
188 | .features = (LIRC_CAN_SET_SEND_DUTY_CYCLE | | ||
189 | LIRC_CAN_SET_SEND_CARRIER | | ||
190 | LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2) | ||
191 | #else | ||
192 | .features = LIRC_CAN_REC_MODE2 | ||
193 | #endif | ||
194 | }, | ||
195 | |||
196 | #ifdef CONFIG_LIRC_SERIAL_NSLU2 | ||
197 | /* | ||
198 | * Modified Linksys Network Storage Link USB 2.0 (NSLU2): | ||
199 | * We receive on CTS of the 2nd serial port (R142,LHS), we | ||
200 | * transmit with a IR diode between GPIO[1] (green status LED), | ||
201 | * and ground (Matthias Goebl <matthias.goebl@goebl.net>). | ||
202 | * See also http://www.nslu2-linux.org for this device | ||
203 | */ | ||
204 | [LIRC_NSLU2] = { | ||
205 | .signal_pin = UART_MSR_CTS, | ||
206 | .signal_pin_change = UART_MSR_DCTS, | ||
207 | .on = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR), | ||
208 | .off = (UART_MCR_RTS | UART_MCR_OUT2), | ||
209 | .send_pulse = send_pulse_homebrew, | ||
210 | .send_space = send_space_homebrew, | ||
211 | #ifdef CONFIG_LIRC_SERIAL_TRANSMITTER | ||
212 | .features = (LIRC_CAN_SET_SEND_DUTY_CYCLE | | ||
213 | LIRC_CAN_SET_SEND_CARRIER | | ||
214 | LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2) | ||
215 | #else | ||
216 | .features = LIRC_CAN_REC_MODE2 | ||
217 | #endif | ||
218 | }, | ||
219 | #endif | ||
220 | |||
221 | }; | ||
222 | |||
223 | #define RS_ISR_PASS_LIMIT 256 | ||
224 | |||
225 | /* | ||
226 | * A long pulse code from a remote might take up to 300 bytes. The | ||
227 | * daemon should read the bytes as soon as they are generated, so take | ||
228 | * the number of keys you think you can push before the daemon runs | ||
229 | * and multiply by 300. The driver will warn you if you overrun this | ||
230 | * buffer. If you have a slow computer or non-busmastering IDE disks, | ||
231 | * maybe you will need to increase this. | ||
232 | */ | ||
233 | |||
234 | /* This MUST be a power of two! It has to be larger than 1 as well. */ | ||
235 | |||
236 | #define RBUF_LEN 256 | ||
237 | |||
238 | static struct timeval lasttv = {0, 0}; | ||
239 | |||
240 | static struct lirc_buffer rbuf; | ||
241 | |||
242 | static unsigned int freq = 38000; | ||
243 | static unsigned int duty_cycle = 50; | ||
244 | |||
245 | /* Initialized in init_timing_params() */ | ||
246 | static unsigned long period; | ||
247 | static unsigned long pulse_width; | ||
248 | static unsigned long space_width; | ||
249 | |||
250 | #if defined(__i386__) | ||
251 | /* | ||
252 | * From: | ||
253 | * Linux I/O port programming mini-HOWTO | ||
254 | * Author: Riku Saikkonen <Riku.Saikkonen@hut.fi> | ||
255 | * v, 28 December 1997 | ||
256 | * | ||
257 | * [...] | ||
258 | * Actually, a port I/O instruction on most ports in the 0-0x3ff range | ||
259 | * takes almost exactly 1 microsecond, so if you're, for example, using | ||
260 | * the parallel port directly, just do additional inb()s from that port | ||
261 | * to delay. | ||
262 | * [...] | ||
263 | */ | ||
264 | /* transmitter latency 1.5625us 0x1.90 - this figure arrived at from | ||
265 | * comment above plus trimming to match actual measured frequency. | ||
266 | * This will be sensitive to cpu speed, though hopefully most of the 1.5us | ||
267 | * is spent in the uart access. Still - for reference test machine was a | ||
268 | * 1.13GHz Athlon system - Steve | ||
269 | */ | ||
270 | |||
271 | /* | ||
272 | * changed from 400 to 450 as this works better on slower machines; | ||
273 | * faster machines will use the rdtsc code anyway | ||
274 | */ | ||
275 | #define LIRC_SERIAL_TRANSMITTER_LATENCY 450 | ||
276 | |||
277 | #else | ||
278 | |||
279 | /* does anybody have information on other platforms ? */ | ||
280 | /* 256 = 1<<8 */ | ||
281 | #define LIRC_SERIAL_TRANSMITTER_LATENCY 256 | ||
282 | |||
283 | #endif /* __i386__ */ | ||
284 | /* | ||
285 | * FIXME: should we be using hrtimers instead of this | ||
286 | * LIRC_SERIAL_TRANSMITTER_LATENCY nonsense? | ||
287 | */ | ||
288 | |||
289 | /* fetch serial input packet (1 byte) from register offset */ | ||
290 | static u8 sinp(int offset) | ||
291 | { | ||
292 | if (iommap != 0) | ||
293 | /* the register is memory-mapped */ | ||
294 | offset <<= ioshift; | ||
295 | |||
296 | return inb(io + offset); | ||
297 | } | ||
298 | |||
299 | /* write serial output packet (1 byte) of value to register offset */ | ||
300 | static void soutp(int offset, u8 value) | ||
301 | { | ||
302 | if (iommap != 0) | ||
303 | /* the register is memory-mapped */ | ||
304 | offset <<= ioshift; | ||
305 | |||
306 | outb(value, io + offset); | ||
307 | } | ||
308 | |||
309 | static void on(void) | ||
310 | { | ||
311 | #ifdef CONFIG_LIRC_SERIAL_NSLU2 | ||
312 | /* | ||
313 | * On NSLU2, we put the transmit diode between the output of the green | ||
314 | * status LED and ground | ||
315 | */ | ||
316 | if (type == LIRC_NSLU2) { | ||
317 | gpio_line_set(NSLU2_LED_GRN, IXP4XX_GPIO_LOW); | ||
318 | return; | ||
319 | } | ||
320 | #endif | ||
321 | if (txsense) | ||
322 | soutp(UART_MCR, hardware[type].off); | ||
323 | else | ||
324 | soutp(UART_MCR, hardware[type].on); | ||
325 | } | ||
326 | |||
327 | static void off(void) | ||
328 | { | ||
329 | #ifdef CONFIG_LIRC_SERIAL_NSLU2 | ||
330 | if (type == LIRC_NSLU2) { | ||
331 | gpio_line_set(NSLU2_LED_GRN, IXP4XX_GPIO_HIGH); | ||
332 | return; | ||
333 | } | ||
334 | #endif | ||
335 | if (txsense) | ||
336 | soutp(UART_MCR, hardware[type].on); | ||
337 | else | ||
338 | soutp(UART_MCR, hardware[type].off); | ||
339 | } | ||
340 | |||
341 | #ifndef MAX_UDELAY_MS | ||
342 | #define MAX_UDELAY_US 5000 | ||
343 | #else | ||
344 | #define MAX_UDELAY_US (MAX_UDELAY_MS*1000) | ||
345 | #endif | ||
346 | |||
347 | static void safe_udelay(unsigned long usecs) | ||
348 | { | ||
349 | while (usecs > MAX_UDELAY_US) { | ||
350 | udelay(MAX_UDELAY_US); | ||
351 | usecs -= MAX_UDELAY_US; | ||
352 | } | ||
353 | udelay(usecs); | ||
354 | } | ||
355 | |||
356 | #ifdef USE_RDTSC | ||
357 | /* | ||
358 | * This is an overflow/precision juggle, complicated in that we can't | ||
359 | * do long long divide in the kernel | ||
360 | */ | ||
361 | |||
362 | /* | ||
363 | * When we use the rdtsc instruction to measure clocks, we keep the | ||
364 | * pulse and space widths as clock cycles. As this is CPU speed | ||
365 | * dependent, the widths must be calculated in init_port and ioctl | ||
366 | * time | ||
367 | */ | ||
368 | |||
369 | /* So send_pulse can quickly convert microseconds to clocks */ | ||
370 | static unsigned long conv_us_to_clocks; | ||
371 | |||
372 | static int init_timing_params(unsigned int new_duty_cycle, | ||
373 | unsigned int new_freq) | ||
374 | { | ||
375 | __u64 loops_per_sec, work; | ||
376 | |||
377 | duty_cycle = new_duty_cycle; | ||
378 | freq = new_freq; | ||
379 | |||
380 | loops_per_sec = __this_cpu_read(cpu.info.loops_per_jiffy); | ||
381 | loops_per_sec *= HZ; | ||
382 | |||
383 | /* How many clocks in a microsecond?, avoiding long long divide */ | ||
384 | work = loops_per_sec; | ||
385 | work *= 4295; /* 4295 = 2^32 / 1e6 */ | ||
386 | conv_us_to_clocks = (work >> 32); | ||
387 | |||
388 | /* | ||
389 | * Carrier period in clocks, approach good up to 32GHz clock, | ||
390 | * gets carrier frequency within 8Hz | ||
391 | */ | ||
392 | period = loops_per_sec >> 3; | ||
393 | period /= (freq >> 3); | ||
394 | |||
395 | /* Derive pulse and space from the period */ | ||
396 | pulse_width = period * duty_cycle / 100; | ||
397 | space_width = period - pulse_width; | ||
398 | dprintk("in init_timing_params, freq=%d, duty_cycle=%d, " | ||
399 | "clk/jiffy=%ld, pulse=%ld, space=%ld, " | ||
400 | "conv_us_to_clocks=%ld\n", | ||
401 | freq, duty_cycle, __this_cpu_read(cpu_info.loops_per_jiffy), | ||
402 | pulse_width, space_width, conv_us_to_clocks); | ||
403 | return 0; | ||
404 | } | ||
405 | #else /* ! USE_RDTSC */ | ||
406 | static int init_timing_params(unsigned int new_duty_cycle, | ||
407 | unsigned int new_freq) | ||
408 | { | ||
409 | /* | ||
410 | * period, pulse/space width are kept with 8 binary places - | ||
411 | * IE multiplied by 256. | ||
412 | */ | ||
413 | if (256 * 1000000L / new_freq * new_duty_cycle / 100 <= | ||
414 | LIRC_SERIAL_TRANSMITTER_LATENCY) | ||
415 | return -EINVAL; | ||
416 | if (256 * 1000000L / new_freq * (100 - new_duty_cycle) / 100 <= | ||
417 | LIRC_SERIAL_TRANSMITTER_LATENCY) | ||
418 | return -EINVAL; | ||
419 | duty_cycle = new_duty_cycle; | ||
420 | freq = new_freq; | ||
421 | period = 256 * 1000000L / freq; | ||
422 | pulse_width = period * duty_cycle / 100; | ||
423 | space_width = period - pulse_width; | ||
424 | dprintk("in init_timing_params, freq=%d pulse=%ld, " | ||
425 | "space=%ld\n", freq, pulse_width, space_width); | ||
426 | return 0; | ||
427 | } | ||
428 | #endif /* USE_RDTSC */ | ||
429 | |||
430 | |||
431 | /* return value: space length delta */ | ||
432 | |||
433 | static long send_pulse_irdeo(unsigned long length) | ||
434 | { | ||
435 | long rawbits, ret; | ||
436 | int i; | ||
437 | unsigned char output; | ||
438 | unsigned char chunk, shifted; | ||
439 | |||
440 | /* how many bits have to be sent ? */ | ||
441 | rawbits = length * 1152 / 10000; | ||
442 | if (duty_cycle > 50) | ||
443 | chunk = 3; | ||
444 | else | ||
445 | chunk = 1; | ||
446 | for (i = 0, output = 0x7f; rawbits > 0; rawbits -= 3) { | ||
447 | shifted = chunk << (i * 3); | ||
448 | shifted >>= 1; | ||
449 | output &= (~shifted); | ||
450 | i++; | ||
451 | if (i == 3) { | ||
452 | soutp(UART_TX, output); | ||
453 | while (!(sinp(UART_LSR) & UART_LSR_THRE)) | ||
454 | ; | ||
455 | output = 0x7f; | ||
456 | i = 0; | ||
457 | } | ||
458 | } | ||
459 | if (i != 0) { | ||
460 | soutp(UART_TX, output); | ||
461 | while (!(sinp(UART_LSR) & UART_LSR_TEMT)) | ||
462 | ; | ||
463 | } | ||
464 | |||
465 | if (i == 0) | ||
466 | ret = (-rawbits) * 10000 / 1152; | ||
467 | else | ||
468 | ret = (3 - i) * 3 * 10000 / 1152 + (-rawbits) * 10000 / 1152; | ||
469 | |||
470 | return ret; | ||
471 | } | ||
472 | |||
473 | #ifdef USE_RDTSC | ||
474 | /* Version that uses Pentium rdtsc instruction to measure clocks */ | ||
475 | |||
476 | /* | ||
477 | * This version does sub-microsecond timing using rdtsc instruction, | ||
478 | * and does away with the fudged LIRC_SERIAL_TRANSMITTER_LATENCY | ||
479 | * Implicitly i586 architecture... - Steve | ||
480 | */ | ||
481 | |||
482 | static long send_pulse_homebrew_softcarrier(unsigned long length) | ||
483 | { | ||
484 | int flag; | ||
485 | unsigned long target, start, now; | ||
486 | |||
487 | /* Get going quick as we can */ | ||
488 | rdtscl(start); | ||
489 | on(); | ||
490 | /* Convert length from microseconds to clocks */ | ||
491 | length *= conv_us_to_clocks; | ||
492 | /* And loop till time is up - flipping at right intervals */ | ||
493 | now = start; | ||
494 | target = pulse_width; | ||
495 | flag = 1; | ||
496 | /* | ||
497 | * FIXME: This looks like a hard busy wait, without even an occasional, | ||
498 | * polite, cpu_relax() call. There's got to be a better way? | ||
499 | * | ||
500 | * The i2c code has the result of a lot of bit-banging work, I wonder if | ||
501 | * there's something there which could be helpful here. | ||
502 | */ | ||
503 | while ((now - start) < length) { | ||
504 | /* Delay till flip time */ | ||
505 | do { | ||
506 | rdtscl(now); | ||
507 | } while ((now - start) < target); | ||
508 | |||
509 | /* flip */ | ||
510 | if (flag) { | ||
511 | rdtscl(now); | ||
512 | off(); | ||
513 | target += space_width; | ||
514 | } else { | ||
515 | rdtscl(now); on(); | ||
516 | target += pulse_width; | ||
517 | } | ||
518 | flag = !flag; | ||
519 | } | ||
520 | rdtscl(now); | ||
521 | return ((now - start) - length) / conv_us_to_clocks; | ||
522 | } | ||
523 | #else /* ! USE_RDTSC */ | ||
524 | /* Version using udelay() */ | ||
525 | |||
526 | /* | ||
527 | * here we use fixed point arithmetic, with 8 | ||
528 | * fractional bits. that gets us within 0.1% or so of the right average | ||
529 | * frequency, albeit with some jitter in pulse length - Steve | ||
530 | */ | ||
531 | |||
532 | /* To match 8 fractional bits used for pulse/space length */ | ||
533 | |||
534 | static long send_pulse_homebrew_softcarrier(unsigned long length) | ||
535 | { | ||
536 | int flag; | ||
537 | unsigned long actual, target, d; | ||
538 | length <<= 8; | ||
539 | |||
540 | actual = 0; target = 0; flag = 0; | ||
541 | while (actual < length) { | ||
542 | if (flag) { | ||
543 | off(); | ||
544 | target += space_width; | ||
545 | } else { | ||
546 | on(); | ||
547 | target += pulse_width; | ||
548 | } | ||
549 | d = (target - actual - | ||
550 | LIRC_SERIAL_TRANSMITTER_LATENCY + 128) >> 8; | ||
551 | /* | ||
552 | * Note - we've checked in ioctl that the pulse/space | ||
553 | * widths are big enough so that d is > 0 | ||
554 | */ | ||
555 | udelay(d); | ||
556 | actual += (d << 8) + LIRC_SERIAL_TRANSMITTER_LATENCY; | ||
557 | flag = !flag; | ||
558 | } | ||
559 | return (actual-length) >> 8; | ||
560 | } | ||
561 | #endif /* USE_RDTSC */ | ||
562 | |||
563 | static long send_pulse_homebrew(unsigned long length) | ||
564 | { | ||
565 | if (length <= 0) | ||
566 | return 0; | ||
567 | |||
568 | if (softcarrier) | ||
569 | return send_pulse_homebrew_softcarrier(length); | ||
570 | else { | ||
571 | on(); | ||
572 | safe_udelay(length); | ||
573 | return 0; | ||
574 | } | ||
575 | } | ||
576 | |||
577 | static void send_space_irdeo(long length) | ||
578 | { | ||
579 | if (length <= 0) | ||
580 | return; | ||
581 | |||
582 | safe_udelay(length); | ||
583 | } | ||
584 | |||
585 | static void send_space_homebrew(long length) | ||
586 | { | ||
587 | off(); | ||
588 | if (length <= 0) | ||
589 | return; | ||
590 | safe_udelay(length); | ||
591 | } | ||
592 | |||
593 | static void rbwrite(int l) | ||
594 | { | ||
595 | if (lirc_buffer_full(&rbuf)) { | ||
596 | /* no new signals will be accepted */ | ||
597 | dprintk("Buffer overrun\n"); | ||
598 | return; | ||
599 | } | ||
600 | lirc_buffer_write(&rbuf, (void *)&l); | ||
601 | } | ||
602 | |||
603 | static void frbwrite(int l) | ||
604 | { | ||
605 | /* simple noise filter */ | ||
606 | static int pulse, space; | ||
607 | static unsigned int ptr; | ||
608 | |||
609 | if (ptr > 0 && (l & PULSE_BIT)) { | ||
610 | pulse += l & PULSE_MASK; | ||
611 | if (pulse > 250) { | ||
612 | rbwrite(space); | ||
613 | rbwrite(pulse | PULSE_BIT); | ||
614 | ptr = 0; | ||
615 | pulse = 0; | ||
616 | } | ||
617 | return; | ||
618 | } | ||
619 | if (!(l & PULSE_BIT)) { | ||
620 | if (ptr == 0) { | ||
621 | if (l > 20000) { | ||
622 | space = l; | ||
623 | ptr++; | ||
624 | return; | ||
625 | } | ||
626 | } else { | ||
627 | if (l > 20000) { | ||
628 | space += pulse; | ||
629 | if (space > PULSE_MASK) | ||
630 | space = PULSE_MASK; | ||
631 | space += l; | ||
632 | if (space > PULSE_MASK) | ||
633 | space = PULSE_MASK; | ||
634 | pulse = 0; | ||
635 | return; | ||
636 | } | ||
637 | rbwrite(space); | ||
638 | rbwrite(pulse | PULSE_BIT); | ||
639 | ptr = 0; | ||
640 | pulse = 0; | ||
641 | } | ||
642 | } | ||
643 | rbwrite(l); | ||
644 | } | ||
645 | |||
646 | static irqreturn_t irq_handler(int i, void *blah) | ||
647 | { | ||
648 | struct timeval tv; | ||
649 | int counter, dcd; | ||
650 | u8 status; | ||
651 | long deltv; | ||
652 | int data; | ||
653 | static int last_dcd = -1; | ||
654 | |||
655 | if ((sinp(UART_IIR) & UART_IIR_NO_INT)) { | ||
656 | /* not our interrupt */ | ||
657 | return IRQ_NONE; | ||
658 | } | ||
659 | |||
660 | counter = 0; | ||
661 | do { | ||
662 | counter++; | ||
663 | status = sinp(UART_MSR); | ||
664 | if (counter > RS_ISR_PASS_LIMIT) { | ||
665 | printk(KERN_WARNING LIRC_DRIVER_NAME ": AIEEEE: " | ||
666 | "We're caught!\n"); | ||
667 | break; | ||
668 | } | ||
669 | if ((status & hardware[type].signal_pin_change) | ||
670 | && sense != -1) { | ||
671 | /* get current time */ | ||
672 | do_gettimeofday(&tv); | ||
673 | |||
674 | /* New mode, written by Trent Piepho | ||
675 | <xyzzy@u.washington.edu>. */ | ||
676 | |||
677 | /* | ||
678 | * The old format was not very portable. | ||
679 | * We now use an int to pass pulses | ||
680 | * and spaces to user space. | ||
681 | * | ||
682 | * If PULSE_BIT is set a pulse has been | ||
683 | * received, otherwise a space has been | ||
684 | * received. The driver needs to know if your | ||
685 | * receiver is active high or active low, or | ||
686 | * the space/pulse sense could be | ||
687 | * inverted. The bits denoted by PULSE_MASK are | ||
688 | * the length in microseconds. Lengths greater | ||
689 | * than or equal to 16 seconds are clamped to | ||
690 | * PULSE_MASK. All other bits are unused. | ||
691 | * This is a much simpler interface for user | ||
692 | * programs, as well as eliminating "out of | ||
693 | * phase" errors with space/pulse | ||
694 | * autodetection. | ||
695 | */ | ||
696 | |||
697 | /* calc time since last interrupt in microseconds */ | ||
698 | dcd = (status & hardware[type].signal_pin) ? 1 : 0; | ||
699 | |||
700 | if (dcd == last_dcd) { | ||
701 | printk(KERN_WARNING LIRC_DRIVER_NAME | ||
702 | ": ignoring spike: %d %d %lx %lx %lx %lx\n", | ||
703 | dcd, sense, | ||
704 | tv.tv_sec, lasttv.tv_sec, | ||
705 | tv.tv_usec, lasttv.tv_usec); | ||
706 | continue; | ||
707 | } | ||
708 | |||
709 | deltv = tv.tv_sec-lasttv.tv_sec; | ||
710 | if (tv.tv_sec < lasttv.tv_sec || | ||
711 | (tv.tv_sec == lasttv.tv_sec && | ||
712 | tv.tv_usec < lasttv.tv_usec)) { | ||
713 | printk(KERN_WARNING LIRC_DRIVER_NAME | ||
714 | ": AIEEEE: your clock just jumped " | ||
715 | "backwards\n"); | ||
716 | printk(KERN_WARNING LIRC_DRIVER_NAME | ||
717 | ": %d %d %lx %lx %lx %lx\n", | ||
718 | dcd, sense, | ||
719 | tv.tv_sec, lasttv.tv_sec, | ||
720 | tv.tv_usec, lasttv.tv_usec); | ||
721 | data = PULSE_MASK; | ||
722 | } else if (deltv > 15) { | ||
723 | data = PULSE_MASK; /* really long time */ | ||
724 | if (!(dcd^sense)) { | ||
725 | /* sanity check */ | ||
726 | printk(KERN_WARNING LIRC_DRIVER_NAME | ||
727 | ": AIEEEE: " | ||
728 | "%d %d %lx %lx %lx %lx\n", | ||
729 | dcd, sense, | ||
730 | tv.tv_sec, lasttv.tv_sec, | ||
731 | tv.tv_usec, lasttv.tv_usec); | ||
732 | /* | ||
733 | * detecting pulse while this | ||
734 | * MUST be a space! | ||
735 | */ | ||
736 | sense = sense ? 0 : 1; | ||
737 | } | ||
738 | } else | ||
739 | data = (int) (deltv*1000000 + | ||
740 | tv.tv_usec - | ||
741 | lasttv.tv_usec); | ||
742 | frbwrite(dcd^sense ? data : (data|PULSE_BIT)); | ||
743 | lasttv = tv; | ||
744 | last_dcd = dcd; | ||
745 | wake_up_interruptible(&rbuf.wait_poll); | ||
746 | } | ||
747 | } while (!(sinp(UART_IIR) & UART_IIR_NO_INT)); /* still pending ? */ | ||
748 | return IRQ_HANDLED; | ||
749 | } | ||
750 | |||
751 | |||
752 | static int hardware_init_port(void) | ||
753 | { | ||
754 | u8 scratch, scratch2, scratch3; | ||
755 | |||
756 | /* | ||
757 | * This is a simple port existence test, borrowed from the autoconfig | ||
758 | * function in drivers/serial/8250.c | ||
759 | */ | ||
760 | scratch = sinp(UART_IER); | ||
761 | soutp(UART_IER, 0); | ||
762 | #ifdef __i386__ | ||
763 | outb(0xff, 0x080); | ||
764 | #endif | ||
765 | scratch2 = sinp(UART_IER) & 0x0f; | ||
766 | soutp(UART_IER, 0x0f); | ||
767 | #ifdef __i386__ | ||
768 | outb(0x00, 0x080); | ||
769 | #endif | ||
770 | scratch3 = sinp(UART_IER) & 0x0f; | ||
771 | soutp(UART_IER, scratch); | ||
772 | if (scratch2 != 0 || scratch3 != 0x0f) { | ||
773 | /* we fail, there's nothing here */ | ||
774 | printk(KERN_ERR LIRC_DRIVER_NAME ": port existence test " | ||
775 | "failed, cannot continue\n"); | ||
776 | return -EINVAL; | ||
777 | } | ||
778 | |||
779 | |||
780 | |||
781 | /* Set DLAB 0. */ | ||
782 | soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); | ||
783 | |||
784 | /* First of all, disable all interrupts */ | ||
785 | soutp(UART_IER, sinp(UART_IER) & | ||
786 | (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); | ||
787 | |||
788 | /* Clear registers. */ | ||
789 | sinp(UART_LSR); | ||
790 | sinp(UART_RX); | ||
791 | sinp(UART_IIR); | ||
792 | sinp(UART_MSR); | ||
793 | |||
794 | #ifdef CONFIG_LIRC_SERIAL_NSLU2 | ||
795 | if (type == LIRC_NSLU2) { | ||
796 | /* Setup NSLU2 UART */ | ||
797 | |||
798 | /* Enable UART */ | ||
799 | soutp(UART_IER, sinp(UART_IER) | UART_IE_IXP42X_UUE); | ||
800 | /* Disable Receiver data Time out interrupt */ | ||
801 | soutp(UART_IER, sinp(UART_IER) & ~UART_IE_IXP42X_RTOIE); | ||
802 | /* set out2 = interrupt unmask; off() doesn't set MCR | ||
803 | on NSLU2 */ | ||
804 | soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2); | ||
805 | } | ||
806 | #endif | ||
807 | |||
808 | /* Set line for power source */ | ||
809 | off(); | ||
810 | |||
811 | /* Clear registers again to be sure. */ | ||
812 | sinp(UART_LSR); | ||
813 | sinp(UART_RX); | ||
814 | sinp(UART_IIR); | ||
815 | sinp(UART_MSR); | ||
816 | |||
817 | switch (type) { | ||
818 | case LIRC_IRDEO: | ||
819 | case LIRC_IRDEO_REMOTE: | ||
820 | /* setup port to 7N1 @ 115200 Baud */ | ||
821 | /* 7N1+start = 9 bits at 115200 ~ 3 bits at 38kHz */ | ||
822 | |||
823 | /* Set DLAB 1. */ | ||
824 | soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB); | ||
825 | /* Set divisor to 1 => 115200 Baud */ | ||
826 | soutp(UART_DLM, 0); | ||
827 | soutp(UART_DLL, 1); | ||
828 | /* Set DLAB 0 + 7N1 */ | ||
829 | soutp(UART_LCR, UART_LCR_WLEN7); | ||
830 | /* THR interrupt already disabled at this point */ | ||
831 | break; | ||
832 | default: | ||
833 | break; | ||
834 | } | ||
835 | |||
836 | return 0; | ||
837 | } | ||
838 | |||
839 | static int init_port(void) | ||
840 | { | ||
841 | int i, nlow, nhigh, result; | ||
842 | |||
843 | result = request_irq(irq, irq_handler, | ||
844 | IRQF_DISABLED | (share_irq ? IRQF_SHARED : 0), | ||
845 | LIRC_DRIVER_NAME, (void *)&hardware); | ||
846 | |||
847 | switch (result) { | ||
848 | case -EBUSY: | ||
849 | printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n", irq); | ||
850 | return -EBUSY; | ||
851 | case -EINVAL: | ||
852 | printk(KERN_ERR LIRC_DRIVER_NAME | ||
853 | ": Bad irq number or handler\n"); | ||
854 | return -EINVAL; | ||
855 | default: | ||
856 | break; | ||
857 | }; | ||
858 | |||
859 | /* Reserve io region. */ | ||
860 | /* | ||
861 | * Future MMAP-Developers: Attention! | ||
862 | * For memory mapped I/O you *might* need to use ioremap() first, | ||
863 | * for the NSLU2 it's done in boot code. | ||
864 | */ | ||
865 | if (((iommap != 0) | ||
866 | && (request_mem_region(iommap, 8 << ioshift, | ||
867 | LIRC_DRIVER_NAME) == NULL)) | ||
868 | || ((iommap == 0) | ||
869 | && (request_region(io, 8, LIRC_DRIVER_NAME) == NULL))) { | ||
870 | printk(KERN_ERR LIRC_DRIVER_NAME | ||
871 | ": port %04x already in use\n", io); | ||
872 | printk(KERN_WARNING LIRC_DRIVER_NAME | ||
873 | ": use 'setserial /dev/ttySX uart none'\n"); | ||
874 | printk(KERN_WARNING LIRC_DRIVER_NAME | ||
875 | ": or compile the serial port driver as module and\n"); | ||
876 | printk(KERN_WARNING LIRC_DRIVER_NAME | ||
877 | ": make sure this module is loaded first\n"); | ||
878 | return -EBUSY; | ||
879 | } | ||
880 | |||
881 | if (hardware_init_port() < 0) | ||
882 | return -EINVAL; | ||
883 | |||
884 | /* Initialize pulse/space widths */ | ||
885 | init_timing_params(duty_cycle, freq); | ||
886 | |||
887 | /* If pin is high, then this must be an active low receiver. */ | ||
888 | if (sense == -1) { | ||
889 | /* wait 1/2 sec for the power supply */ | ||
890 | msleep(500); | ||
891 | |||
892 | /* | ||
893 | * probe 9 times every 0.04s, collect "votes" for | ||
894 | * active high/low | ||
895 | */ | ||
896 | nlow = 0; | ||
897 | nhigh = 0; | ||
898 | for (i = 0; i < 9; i++) { | ||
899 | if (sinp(UART_MSR) & hardware[type].signal_pin) | ||
900 | nlow++; | ||
901 | else | ||
902 | nhigh++; | ||
903 | msleep(40); | ||
904 | } | ||
905 | sense = (nlow >= nhigh ? 1 : 0); | ||
906 | printk(KERN_INFO LIRC_DRIVER_NAME ": auto-detected active " | ||
907 | "%s receiver\n", sense ? "low" : "high"); | ||
908 | } else | ||
909 | printk(KERN_INFO LIRC_DRIVER_NAME ": Manually using active " | ||
910 | "%s receiver\n", sense ? "low" : "high"); | ||
911 | |||
912 | dprintk("Interrupt %d, port %04x obtained\n", irq, io); | ||
913 | return 0; | ||
914 | } | ||
915 | |||
916 | static int set_use_inc(void *data) | ||
917 | { | ||
918 | unsigned long flags; | ||
919 | |||
920 | /* initialize timestamp */ | ||
921 | do_gettimeofday(&lasttv); | ||
922 | |||
923 | spin_lock_irqsave(&hardware[type].lock, flags); | ||
924 | |||
925 | /* Set DLAB 0. */ | ||
926 | soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); | ||
927 | |||
928 | soutp(UART_IER, sinp(UART_IER)|UART_IER_MSI); | ||
929 | |||
930 | spin_unlock_irqrestore(&hardware[type].lock, flags); | ||
931 | |||
932 | return 0; | ||
933 | } | ||
934 | |||
935 | static void set_use_dec(void *data) | ||
936 | { unsigned long flags; | ||
937 | |||
938 | spin_lock_irqsave(&hardware[type].lock, flags); | ||
939 | |||
940 | /* Set DLAB 0. */ | ||
941 | soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); | ||
942 | |||
943 | /* First of all, disable all interrupts */ | ||
944 | soutp(UART_IER, sinp(UART_IER) & | ||
945 | (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); | ||
946 | spin_unlock_irqrestore(&hardware[type].lock, flags); | ||
947 | } | ||
948 | |||
949 | static ssize_t lirc_write(struct file *file, const char *buf, | ||
950 | size_t n, loff_t *ppos) | ||
951 | { | ||
952 | int i, count; | ||
953 | unsigned long flags; | ||
954 | long delta = 0; | ||
955 | int *wbuf; | ||
956 | |||
957 | if (!(hardware[type].features & LIRC_CAN_SEND_PULSE)) | ||
958 | return -EBADF; | ||
959 | |||
960 | count = n / sizeof(int); | ||
961 | if (n % sizeof(int) || count % 2 == 0) | ||
962 | return -EINVAL; | ||
963 | wbuf = memdup_user(buf, n); | ||
964 | if (IS_ERR(wbuf)) | ||
965 | return PTR_ERR(wbuf); | ||
966 | spin_lock_irqsave(&hardware[type].lock, flags); | ||
967 | if (type == LIRC_IRDEO) { | ||
968 | /* DTR, RTS down */ | ||
969 | on(); | ||
970 | } | ||
971 | for (i = 0; i < count; i++) { | ||
972 | if (i%2) | ||
973 | hardware[type].send_space(wbuf[i] - delta); | ||
974 | else | ||
975 | delta = hardware[type].send_pulse(wbuf[i]); | ||
976 | } | ||
977 | off(); | ||
978 | spin_unlock_irqrestore(&hardware[type].lock, flags); | ||
979 | kfree(wbuf); | ||
980 | return n; | ||
981 | } | ||
982 | |||
983 | static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) | ||
984 | { | ||
985 | int result; | ||
986 | __u32 value; | ||
987 | |||
988 | switch (cmd) { | ||
989 | case LIRC_GET_SEND_MODE: | ||
990 | if (!(hardware[type].features&LIRC_CAN_SEND_MASK)) | ||
991 | return -ENOIOCTLCMD; | ||
992 | |||
993 | result = put_user(LIRC_SEND2MODE | ||
994 | (hardware[type].features&LIRC_CAN_SEND_MASK), | ||
995 | (__u32 *) arg); | ||
996 | if (result) | ||
997 | return result; | ||
998 | break; | ||
999 | |||
1000 | case LIRC_SET_SEND_MODE: | ||
1001 | if (!(hardware[type].features&LIRC_CAN_SEND_MASK)) | ||
1002 | return -ENOIOCTLCMD; | ||
1003 | |||
1004 | result = get_user(value, (__u32 *) arg); | ||
1005 | if (result) | ||
1006 | return result; | ||
1007 | /* only LIRC_MODE_PULSE supported */ | ||
1008 | if (value != LIRC_MODE_PULSE) | ||
1009 | return -ENOSYS; | ||
1010 | break; | ||
1011 | |||
1012 | case LIRC_GET_LENGTH: | ||
1013 | return -ENOSYS; | ||
1014 | break; | ||
1015 | |||
1016 | case LIRC_SET_SEND_DUTY_CYCLE: | ||
1017 | dprintk("SET_SEND_DUTY_CYCLE\n"); | ||
1018 | if (!(hardware[type].features&LIRC_CAN_SET_SEND_DUTY_CYCLE)) | ||
1019 | return -ENOIOCTLCMD; | ||
1020 | |||
1021 | result = get_user(value, (__u32 *) arg); | ||
1022 | if (result) | ||
1023 | return result; | ||
1024 | if (value <= 0 || value > 100) | ||
1025 | return -EINVAL; | ||
1026 | return init_timing_params(value, freq); | ||
1027 | break; | ||
1028 | |||
1029 | case LIRC_SET_SEND_CARRIER: | ||
1030 | dprintk("SET_SEND_CARRIER\n"); | ||
1031 | if (!(hardware[type].features&LIRC_CAN_SET_SEND_CARRIER)) | ||
1032 | return -ENOIOCTLCMD; | ||
1033 | |||
1034 | result = get_user(value, (__u32 *) arg); | ||
1035 | if (result) | ||
1036 | return result; | ||
1037 | if (value > 500000 || value < 20000) | ||
1038 | return -EINVAL; | ||
1039 | return init_timing_params(duty_cycle, value); | ||
1040 | break; | ||
1041 | |||
1042 | default: | ||
1043 | return lirc_dev_fop_ioctl(filep, cmd, arg); | ||
1044 | } | ||
1045 | return 0; | ||
1046 | } | ||
1047 | |||
1048 | static const struct file_operations lirc_fops = { | ||
1049 | .owner = THIS_MODULE, | ||
1050 | .write = lirc_write, | ||
1051 | .unlocked_ioctl = lirc_ioctl, | ||
1052 | #ifdef CONFIG_COMPAT | ||
1053 | .compat_ioctl = lirc_ioctl, | ||
1054 | #endif | ||
1055 | .read = lirc_dev_fop_read, | ||
1056 | .poll = lirc_dev_fop_poll, | ||
1057 | .open = lirc_dev_fop_open, | ||
1058 | .release = lirc_dev_fop_close, | ||
1059 | .llseek = no_llseek, | ||
1060 | }; | ||
1061 | |||
1062 | static struct lirc_driver driver = { | ||
1063 | .name = LIRC_DRIVER_NAME, | ||
1064 | .minor = -1, | ||
1065 | .code_length = 1, | ||
1066 | .sample_rate = 0, | ||
1067 | .data = NULL, | ||
1068 | .add_to_buf = NULL, | ||
1069 | .rbuf = &rbuf, | ||
1070 | .set_use_inc = set_use_inc, | ||
1071 | .set_use_dec = set_use_dec, | ||
1072 | .fops = &lirc_fops, | ||
1073 | .dev = NULL, | ||
1074 | .owner = THIS_MODULE, | ||
1075 | }; | ||
1076 | |||
1077 | static struct platform_device *lirc_serial_dev; | ||
1078 | |||
1079 | static int __devinit lirc_serial_probe(struct platform_device *dev) | ||
1080 | { | ||
1081 | return 0; | ||
1082 | } | ||
1083 | |||
1084 | static int __devexit lirc_serial_remove(struct platform_device *dev) | ||
1085 | { | ||
1086 | return 0; | ||
1087 | } | ||
1088 | |||
1089 | static int lirc_serial_suspend(struct platform_device *dev, | ||
1090 | pm_message_t state) | ||
1091 | { | ||
1092 | /* Set DLAB 0. */ | ||
1093 | soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); | ||
1094 | |||
1095 | /* Disable all interrupts */ | ||
1096 | soutp(UART_IER, sinp(UART_IER) & | ||
1097 | (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); | ||
1098 | |||
1099 | /* Clear registers. */ | ||
1100 | sinp(UART_LSR); | ||
1101 | sinp(UART_RX); | ||
1102 | sinp(UART_IIR); | ||
1103 | sinp(UART_MSR); | ||
1104 | |||
1105 | return 0; | ||
1106 | } | ||
1107 | |||
1108 | /* twisty maze... need a forward-declaration here... */ | ||
1109 | static void lirc_serial_exit(void); | ||
1110 | |||
1111 | static int lirc_serial_resume(struct platform_device *dev) | ||
1112 | { | ||
1113 | unsigned long flags; | ||
1114 | |||
1115 | if (hardware_init_port() < 0) { | ||
1116 | lirc_serial_exit(); | ||
1117 | return -EINVAL; | ||
1118 | } | ||
1119 | |||
1120 | spin_lock_irqsave(&hardware[type].lock, flags); | ||
1121 | /* Enable Interrupt */ | ||
1122 | do_gettimeofday(&lasttv); | ||
1123 | soutp(UART_IER, sinp(UART_IER)|UART_IER_MSI); | ||
1124 | off(); | ||
1125 | |||
1126 | lirc_buffer_clear(&rbuf); | ||
1127 | |||
1128 | spin_unlock_irqrestore(&hardware[type].lock, flags); | ||
1129 | |||
1130 | return 0; | ||
1131 | } | ||
1132 | |||
1133 | static struct platform_driver lirc_serial_driver = { | ||
1134 | .probe = lirc_serial_probe, | ||
1135 | .remove = __devexit_p(lirc_serial_remove), | ||
1136 | .suspend = lirc_serial_suspend, | ||
1137 | .resume = lirc_serial_resume, | ||
1138 | .driver = { | ||
1139 | .name = "lirc_serial", | ||
1140 | .owner = THIS_MODULE, | ||
1141 | }, | ||
1142 | }; | ||
1143 | |||
1144 | static int __init lirc_serial_init(void) | ||
1145 | { | ||
1146 | int result; | ||
1147 | |||
1148 | /* Init read buffer. */ | ||
1149 | result = lirc_buffer_init(&rbuf, sizeof(int), RBUF_LEN); | ||
1150 | if (result < 0) | ||
1151 | return -ENOMEM; | ||
1152 | |||
1153 | result = platform_driver_register(&lirc_serial_driver); | ||
1154 | if (result) { | ||
1155 | printk("lirc register returned %d\n", result); | ||
1156 | goto exit_buffer_free; | ||
1157 | } | ||
1158 | |||
1159 | lirc_serial_dev = platform_device_alloc("lirc_serial", 0); | ||
1160 | if (!lirc_serial_dev) { | ||
1161 | result = -ENOMEM; | ||
1162 | goto exit_driver_unregister; | ||
1163 | } | ||
1164 | |||
1165 | result = platform_device_add(lirc_serial_dev); | ||
1166 | if (result) | ||
1167 | goto exit_device_put; | ||
1168 | |||
1169 | return 0; | ||
1170 | |||
1171 | exit_device_put: | ||
1172 | platform_device_put(lirc_serial_dev); | ||
1173 | exit_driver_unregister: | ||
1174 | platform_driver_unregister(&lirc_serial_driver); | ||
1175 | exit_buffer_free: | ||
1176 | lirc_buffer_free(&rbuf); | ||
1177 | return result; | ||
1178 | } | ||
1179 | |||
1180 | static void lirc_serial_exit(void) | ||
1181 | { | ||
1182 | platform_device_unregister(lirc_serial_dev); | ||
1183 | platform_driver_unregister(&lirc_serial_driver); | ||
1184 | lirc_buffer_free(&rbuf); | ||
1185 | } | ||
1186 | |||
1187 | static int __init lirc_serial_init_module(void) | ||
1188 | { | ||
1189 | int result; | ||
1190 | |||
1191 | result = lirc_serial_init(); | ||
1192 | if (result) | ||
1193 | return result; | ||
1194 | |||
1195 | switch (type) { | ||
1196 | case LIRC_HOMEBREW: | ||
1197 | case LIRC_IRDEO: | ||
1198 | case LIRC_IRDEO_REMOTE: | ||
1199 | case LIRC_ANIMAX: | ||
1200 | case LIRC_IGOR: | ||
1201 | /* if nothing specified, use ttyS0/com1 and irq 4 */ | ||
1202 | io = io ? io : 0x3f8; | ||
1203 | irq = irq ? irq : 4; | ||
1204 | break; | ||
1205 | #ifdef CONFIG_LIRC_SERIAL_NSLU2 | ||
1206 | case LIRC_NSLU2: | ||
1207 | io = io ? io : IRQ_IXP4XX_UART2; | ||
1208 | irq = irq ? irq : (IXP4XX_UART2_BASE_VIRT + REG_OFFSET); | ||
1209 | iommap = iommap ? iommap : IXP4XX_UART2_BASE_PHYS; | ||
1210 | ioshift = ioshift ? ioshift : 2; | ||
1211 | break; | ||
1212 | #endif | ||
1213 | default: | ||
1214 | result = -EINVAL; | ||
1215 | goto exit_serial_exit; | ||
1216 | } | ||
1217 | if (!softcarrier) { | ||
1218 | switch (type) { | ||
1219 | case LIRC_HOMEBREW: | ||
1220 | case LIRC_IGOR: | ||
1221 | #ifdef CONFIG_LIRC_SERIAL_NSLU2 | ||
1222 | case LIRC_NSLU2: | ||
1223 | #endif | ||
1224 | hardware[type].features &= | ||
1225 | ~(LIRC_CAN_SET_SEND_DUTY_CYCLE| | ||
1226 | LIRC_CAN_SET_SEND_CARRIER); | ||
1227 | break; | ||
1228 | } | ||
1229 | } | ||
1230 | |||
1231 | result = init_port(); | ||
1232 | if (result < 0) | ||
1233 | goto exit_serial_exit; | ||
1234 | driver.features = hardware[type].features; | ||
1235 | driver.dev = &lirc_serial_dev->dev; | ||
1236 | driver.minor = lirc_register_driver(&driver); | ||
1237 | if (driver.minor < 0) { | ||
1238 | printk(KERN_ERR LIRC_DRIVER_NAME | ||
1239 | ": register_chrdev failed!\n"); | ||
1240 | result = -EIO; | ||
1241 | goto exit_release; | ||
1242 | } | ||
1243 | return 0; | ||
1244 | exit_release: | ||
1245 | release_region(io, 8); | ||
1246 | exit_serial_exit: | ||
1247 | lirc_serial_exit(); | ||
1248 | return result; | ||
1249 | } | ||
1250 | |||
1251 | static void __exit lirc_serial_exit_module(void) | ||
1252 | { | ||
1253 | lirc_serial_exit(); | ||
1254 | |||
1255 | free_irq(irq, (void *)&hardware); | ||
1256 | |||
1257 | if (iommap != 0) | ||
1258 | release_mem_region(iommap, 8 << ioshift); | ||
1259 | else | ||
1260 | release_region(io, 8); | ||
1261 | lirc_unregister_driver(driver.minor); | ||
1262 | dprintk("cleaned up module\n"); | ||
1263 | } | ||
1264 | |||
1265 | |||
1266 | module_init(lirc_serial_init_module); | ||
1267 | module_exit(lirc_serial_exit_module); | ||
1268 | |||
1269 | MODULE_DESCRIPTION("Infra-red receiver driver for serial ports."); | ||
1270 | MODULE_AUTHOR("Ralph Metzler, Trent Piepho, Ben Pfaff, " | ||
1271 | "Christoph Bartelmus, Andrei Tanas"); | ||
1272 | MODULE_LICENSE("GPL"); | ||
1273 | |||
1274 | module_param(type, int, S_IRUGO); | ||
1275 | MODULE_PARM_DESC(type, "Hardware type (0 = home-brew, 1 = IRdeo," | ||
1276 | " 2 = IRdeo Remote, 3 = AnimaX, 4 = IgorPlug," | ||
1277 | " 5 = NSLU2 RX:CTS2/TX:GreenLED)"); | ||
1278 | |||
1279 | module_param(io, int, S_IRUGO); | ||
1280 | MODULE_PARM_DESC(io, "I/O address base (0x3f8 or 0x2f8)"); | ||
1281 | |||
1282 | /* some architectures (e.g. intel xscale) have memory mapped registers */ | ||
1283 | module_param(iommap, bool, S_IRUGO); | ||
1284 | MODULE_PARM_DESC(iommap, "physical base for memory mapped I/O" | ||
1285 | " (0 = no memory mapped io)"); | ||
1286 | |||
1287 | /* | ||
1288 | * some architectures (e.g. intel xscale) align the 8bit serial registers | ||
1289 | * on 32bit word boundaries. | ||
1290 | * See linux-kernel/serial/8250.c serial_in()/out() | ||
1291 | */ | ||
1292 | module_param(ioshift, int, S_IRUGO); | ||
1293 | MODULE_PARM_DESC(ioshift, "shift I/O register offset (0 = no shift)"); | ||
1294 | |||
1295 | module_param(irq, int, S_IRUGO); | ||
1296 | MODULE_PARM_DESC(irq, "Interrupt (4 or 3)"); | ||
1297 | |||
1298 | module_param(share_irq, bool, S_IRUGO); | ||
1299 | MODULE_PARM_DESC(share_irq, "Share interrupts (0 = off, 1 = on)"); | ||
1300 | |||
1301 | module_param(sense, bool, S_IRUGO); | ||
1302 | MODULE_PARM_DESC(sense, "Override autodetection of IR receiver circuit" | ||
1303 | " (0 = active high, 1 = active low )"); | ||
1304 | |||
1305 | #ifdef CONFIG_LIRC_SERIAL_TRANSMITTER | ||
1306 | module_param(txsense, bool, S_IRUGO); | ||
1307 | MODULE_PARM_DESC(txsense, "Sense of transmitter circuit" | ||
1308 | " (0 = active high, 1 = active low )"); | ||
1309 | #endif | ||
1310 | |||
1311 | module_param(softcarrier, bool, S_IRUGO); | ||
1312 | MODULE_PARM_DESC(softcarrier, "Software carrier (0 = off, 1 = on, default on)"); | ||
1313 | |||
1314 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
1315 | MODULE_PARM_DESC(debug, "Enable debugging messages"); | ||
diff --git a/drivers/staging/lirc/lirc_sir.c b/drivers/staging/lirc/lirc_sir.c new file mode 100644 index 00000000000..0d3864594b1 --- /dev/null +++ b/drivers/staging/lirc/lirc_sir.c | |||
@@ -0,0 +1,1279 @@ | |||
1 | /* | ||
2 | * LIRC SIR driver, (C) 2000 Milan Pikula <www@fornax.sk> | ||
3 | * | ||
4 | * lirc_sir - Device driver for use with SIR (serial infra red) | ||
5 | * mode of IrDA on many notebooks. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | * | ||
22 | * 2000/09/16 Frank Przybylski <mail@frankprzybylski.de> : | ||
23 | * added timeout and relaxed pulse detection, removed gap bug | ||
24 | * | ||
25 | * 2000/12/15 Christoph Bartelmus <lirc@bartelmus.de> : | ||
26 | * added support for Tekram Irmate 210 (sending does not work yet, | ||
27 | * kind of disappointing that nobody was able to implement that | ||
28 | * before), | ||
29 | * major clean-up | ||
30 | * | ||
31 | * 2001/02/27 Christoph Bartelmus <lirc@bartelmus.de> : | ||
32 | * added support for StrongARM SA1100 embedded microprocessor | ||
33 | * parts cut'n'pasted from sa1100_ir.c (C) 2000 Russell King | ||
34 | */ | ||
35 | |||
36 | #include <linux/module.h> | ||
37 | #include <linux/sched.h> | ||
38 | #include <linux/errno.h> | ||
39 | #include <linux/signal.h> | ||
40 | #include <linux/fs.h> | ||
41 | #include <linux/interrupt.h> | ||
42 | #include <linux/ioport.h> | ||
43 | #include <linux/kernel.h> | ||
44 | #include <linux/serial_reg.h> | ||
45 | #include <linux/time.h> | ||
46 | #include <linux/string.h> | ||
47 | #include <linux/types.h> | ||
48 | #include <linux/wait.h> | ||
49 | #include <linux/mm.h> | ||
50 | #include <linux/delay.h> | ||
51 | #include <linux/poll.h> | ||
52 | #include <asm/system.h> | ||
53 | #include <linux/io.h> | ||
54 | #include <asm/irq.h> | ||
55 | #include <linux/fcntl.h> | ||
56 | #ifdef LIRC_ON_SA1100 | ||
57 | #include <asm/hardware.h> | ||
58 | #ifdef CONFIG_SA1100_COLLIE | ||
59 | #include <asm/arch/tc35143.h> | ||
60 | #include <asm/ucb1200.h> | ||
61 | #endif | ||
62 | #endif | ||
63 | |||
64 | #include <linux/timer.h> | ||
65 | |||
66 | #include <media/lirc.h> | ||
67 | #include <media/lirc_dev.h> | ||
68 | |||
69 | /* SECTION: Definitions */ | ||
70 | |||
71 | /*** Tekram dongle ***/ | ||
72 | #ifdef LIRC_SIR_TEKRAM | ||
73 | /* stolen from kernel source */ | ||
74 | /* definitions for Tekram dongle */ | ||
75 | #define TEKRAM_115200 0x00 | ||
76 | #define TEKRAM_57600 0x01 | ||
77 | #define TEKRAM_38400 0x02 | ||
78 | #define TEKRAM_19200 0x03 | ||
79 | #define TEKRAM_9600 0x04 | ||
80 | #define TEKRAM_2400 0x08 | ||
81 | |||
82 | #define TEKRAM_PW 0x10 /* Pulse select bit */ | ||
83 | |||
84 | /* 10bit * 1s/115200bit in milliseconds = 87ms*/ | ||
85 | #define TIME_CONST (10000000ul/115200ul) | ||
86 | |||
87 | #endif | ||
88 | |||
89 | #ifdef LIRC_SIR_ACTISYS_ACT200L | ||
90 | static void init_act200(void); | ||
91 | #elif defined(LIRC_SIR_ACTISYS_ACT220L) | ||
92 | static void init_act220(void); | ||
93 | #endif | ||
94 | |||
95 | /*** SA1100 ***/ | ||
96 | #ifdef LIRC_ON_SA1100 | ||
97 | struct sa1100_ser2_registers { | ||
98 | /* HSSP control register */ | ||
99 | unsigned char hscr0; | ||
100 | /* UART registers */ | ||
101 | unsigned char utcr0; | ||
102 | unsigned char utcr1; | ||
103 | unsigned char utcr2; | ||
104 | unsigned char utcr3; | ||
105 | unsigned char utcr4; | ||
106 | unsigned char utdr; | ||
107 | unsigned char utsr0; | ||
108 | unsigned char utsr1; | ||
109 | } sr; | ||
110 | |||
111 | static int irq = IRQ_Ser2ICP; | ||
112 | |||
113 | #define LIRC_ON_SA1100_TRANSMITTER_LATENCY 0 | ||
114 | |||
115 | /* pulse/space ratio of 50/50 */ | ||
116 | static unsigned long pulse_width = (13-LIRC_ON_SA1100_TRANSMITTER_LATENCY); | ||
117 | /* 1000000/freq-pulse_width */ | ||
118 | static unsigned long space_width = (13-LIRC_ON_SA1100_TRANSMITTER_LATENCY); | ||
119 | static unsigned int freq = 38000; /* modulation frequency */ | ||
120 | static unsigned int duty_cycle = 50; /* duty cycle of 50% */ | ||
121 | |||
122 | #endif | ||
123 | |||
124 | #define RBUF_LEN 1024 | ||
125 | #define WBUF_LEN 1024 | ||
126 | |||
127 | #define LIRC_DRIVER_NAME "lirc_sir" | ||
128 | |||
129 | #define PULSE '[' | ||
130 | |||
131 | #ifndef LIRC_SIR_TEKRAM | ||
132 | /* 9bit * 1s/115200bit in milli seconds = 78.125ms*/ | ||
133 | #define TIME_CONST (9000000ul/115200ul) | ||
134 | #endif | ||
135 | |||
136 | |||
137 | /* timeout for sequences in jiffies (=5/100s), must be longer than TIME_CONST */ | ||
138 | #define SIR_TIMEOUT (HZ*5/100) | ||
139 | |||
140 | #ifndef LIRC_ON_SA1100 | ||
141 | #ifndef LIRC_IRQ | ||
142 | #define LIRC_IRQ 4 | ||
143 | #endif | ||
144 | #ifndef LIRC_PORT | ||
145 | /* for external dongles, default to com1 */ | ||
146 | #if defined(LIRC_SIR_ACTISYS_ACT200L) || \ | ||
147 | defined(LIRC_SIR_ACTISYS_ACT220L) || \ | ||
148 | defined(LIRC_SIR_TEKRAM) | ||
149 | #define LIRC_PORT 0x3f8 | ||
150 | #else | ||
151 | /* onboard sir ports are typically com3 */ | ||
152 | #define LIRC_PORT 0x3e8 | ||
153 | #endif | ||
154 | #endif | ||
155 | |||
156 | static int io = LIRC_PORT; | ||
157 | static int irq = LIRC_IRQ; | ||
158 | static int threshold = 3; | ||
159 | #endif | ||
160 | |||
161 | static DEFINE_SPINLOCK(timer_lock); | ||
162 | static struct timer_list timerlist; | ||
163 | /* time of last signal change detected */ | ||
164 | static struct timeval last_tv = {0, 0}; | ||
165 | /* time of last UART data ready interrupt */ | ||
166 | static struct timeval last_intr_tv = {0, 0}; | ||
167 | static int last_value; | ||
168 | |||
169 | static DECLARE_WAIT_QUEUE_HEAD(lirc_read_queue); | ||
170 | |||
171 | static DEFINE_SPINLOCK(hardware_lock); | ||
172 | |||
173 | static int rx_buf[RBUF_LEN]; | ||
174 | static unsigned int rx_tail, rx_head; | ||
175 | |||
176 | static int debug; | ||
177 | #define dprintk(fmt, args...) \ | ||
178 | do { \ | ||
179 | if (debug) \ | ||
180 | printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ | ||
181 | fmt, ## args); \ | ||
182 | } while (0) | ||
183 | |||
184 | /* SECTION: Prototypes */ | ||
185 | |||
186 | /* Communication with user-space */ | ||
187 | static unsigned int lirc_poll(struct file *file, poll_table *wait); | ||
188 | static ssize_t lirc_read(struct file *file, char *buf, size_t count, | ||
189 | loff_t *ppos); | ||
190 | static ssize_t lirc_write(struct file *file, const char *buf, size_t n, | ||
191 | loff_t *pos); | ||
192 | static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); | ||
193 | static void add_read_queue(int flag, unsigned long val); | ||
194 | static int init_chrdev(void); | ||
195 | static void drop_chrdev(void); | ||
196 | /* Hardware */ | ||
197 | static irqreturn_t sir_interrupt(int irq, void *dev_id); | ||
198 | static void send_space(unsigned long len); | ||
199 | static void send_pulse(unsigned long len); | ||
200 | static int init_hardware(void); | ||
201 | static void drop_hardware(void); | ||
202 | /* Initialisation */ | ||
203 | static int init_port(void); | ||
204 | static void drop_port(void); | ||
205 | |||
206 | #ifdef LIRC_ON_SA1100 | ||
207 | static void on(void) | ||
208 | { | ||
209 | PPSR |= PPC_TXD2; | ||
210 | } | ||
211 | |||
212 | static void off(void) | ||
213 | { | ||
214 | PPSR &= ~PPC_TXD2; | ||
215 | } | ||
216 | #else | ||
217 | static inline unsigned int sinp(int offset) | ||
218 | { | ||
219 | return inb(io + offset); | ||
220 | } | ||
221 | |||
222 | static inline void soutp(int offset, int value) | ||
223 | { | ||
224 | outb(value, io + offset); | ||
225 | } | ||
226 | #endif | ||
227 | |||
228 | #ifndef MAX_UDELAY_MS | ||
229 | #define MAX_UDELAY_US 5000 | ||
230 | #else | ||
231 | #define MAX_UDELAY_US (MAX_UDELAY_MS*1000) | ||
232 | #endif | ||
233 | |||
234 | static void safe_udelay(unsigned long usecs) | ||
235 | { | ||
236 | while (usecs > MAX_UDELAY_US) { | ||
237 | udelay(MAX_UDELAY_US); | ||
238 | usecs -= MAX_UDELAY_US; | ||
239 | } | ||
240 | udelay(usecs); | ||
241 | } | ||
242 | |||
243 | /* SECTION: Communication with user-space */ | ||
244 | |||
245 | static unsigned int lirc_poll(struct file *file, poll_table *wait) | ||
246 | { | ||
247 | poll_wait(file, &lirc_read_queue, wait); | ||
248 | if (rx_head != rx_tail) | ||
249 | return POLLIN | POLLRDNORM; | ||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | static ssize_t lirc_read(struct file *file, char *buf, size_t count, | ||
254 | loff_t *ppos) | ||
255 | { | ||
256 | int n = 0; | ||
257 | int retval = 0; | ||
258 | DECLARE_WAITQUEUE(wait, current); | ||
259 | |||
260 | if (count % sizeof(int)) | ||
261 | return -EINVAL; | ||
262 | |||
263 | add_wait_queue(&lirc_read_queue, &wait); | ||
264 | set_current_state(TASK_INTERRUPTIBLE); | ||
265 | while (n < count) { | ||
266 | if (rx_head != rx_tail) { | ||
267 | if (copy_to_user((void *) buf + n, | ||
268 | (void *) (rx_buf + rx_head), | ||
269 | sizeof(int))) { | ||
270 | retval = -EFAULT; | ||
271 | break; | ||
272 | } | ||
273 | rx_head = (rx_head + 1) & (RBUF_LEN - 1); | ||
274 | n += sizeof(int); | ||
275 | } else { | ||
276 | if (file->f_flags & O_NONBLOCK) { | ||
277 | retval = -EAGAIN; | ||
278 | break; | ||
279 | } | ||
280 | if (signal_pending(current)) { | ||
281 | retval = -ERESTARTSYS; | ||
282 | break; | ||
283 | } | ||
284 | schedule(); | ||
285 | set_current_state(TASK_INTERRUPTIBLE); | ||
286 | } | ||
287 | } | ||
288 | remove_wait_queue(&lirc_read_queue, &wait); | ||
289 | set_current_state(TASK_RUNNING); | ||
290 | return n ? n : retval; | ||
291 | } | ||
292 | static ssize_t lirc_write(struct file *file, const char *buf, size_t n, | ||
293 | loff_t *pos) | ||
294 | { | ||
295 | unsigned long flags; | ||
296 | int i, count; | ||
297 | int *tx_buf; | ||
298 | |||
299 | count = n / sizeof(int); | ||
300 | if (n % sizeof(int) || count % 2 == 0) | ||
301 | return -EINVAL; | ||
302 | tx_buf = memdup_user(buf, n); | ||
303 | if (IS_ERR(tx_buf)) | ||
304 | return PTR_ERR(tx_buf); | ||
305 | i = 0; | ||
306 | #ifdef LIRC_ON_SA1100 | ||
307 | /* disable receiver */ | ||
308 | Ser2UTCR3 = 0; | ||
309 | #endif | ||
310 | local_irq_save(flags); | ||
311 | while (1) { | ||
312 | if (i >= count) | ||
313 | break; | ||
314 | if (tx_buf[i]) | ||
315 | send_pulse(tx_buf[i]); | ||
316 | i++; | ||
317 | if (i >= count) | ||
318 | break; | ||
319 | if (tx_buf[i]) | ||
320 | send_space(tx_buf[i]); | ||
321 | i++; | ||
322 | } | ||
323 | local_irq_restore(flags); | ||
324 | #ifdef LIRC_ON_SA1100 | ||
325 | off(); | ||
326 | udelay(1000); /* wait 1ms for IR diode to recover */ | ||
327 | Ser2UTCR3 = 0; | ||
328 | /* clear status register to prevent unwanted interrupts */ | ||
329 | Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB); | ||
330 | /* enable receiver */ | ||
331 | Ser2UTCR3 = UTCR3_RXE|UTCR3_RIE; | ||
332 | #endif | ||
333 | kfree(tx_buf); | ||
334 | return count; | ||
335 | } | ||
336 | |||
337 | static long lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) | ||
338 | { | ||
339 | int retval = 0; | ||
340 | __u32 value = 0; | ||
341 | #ifdef LIRC_ON_SA1100 | ||
342 | |||
343 | if (cmd == LIRC_GET_FEATURES) | ||
344 | value = LIRC_CAN_SEND_PULSE | | ||
345 | LIRC_CAN_SET_SEND_DUTY_CYCLE | | ||
346 | LIRC_CAN_SET_SEND_CARRIER | | ||
347 | LIRC_CAN_REC_MODE2; | ||
348 | else if (cmd == LIRC_GET_SEND_MODE) | ||
349 | value = LIRC_MODE_PULSE; | ||
350 | else if (cmd == LIRC_GET_REC_MODE) | ||
351 | value = LIRC_MODE_MODE2; | ||
352 | #else | ||
353 | if (cmd == LIRC_GET_FEATURES) | ||
354 | value = LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2; | ||
355 | else if (cmd == LIRC_GET_SEND_MODE) | ||
356 | value = LIRC_MODE_PULSE; | ||
357 | else if (cmd == LIRC_GET_REC_MODE) | ||
358 | value = LIRC_MODE_MODE2; | ||
359 | #endif | ||
360 | |||
361 | switch (cmd) { | ||
362 | case LIRC_GET_FEATURES: | ||
363 | case LIRC_GET_SEND_MODE: | ||
364 | case LIRC_GET_REC_MODE: | ||
365 | retval = put_user(value, (__u32 *) arg); | ||
366 | break; | ||
367 | |||
368 | case LIRC_SET_SEND_MODE: | ||
369 | case LIRC_SET_REC_MODE: | ||
370 | retval = get_user(value, (__u32 *) arg); | ||
371 | break; | ||
372 | #ifdef LIRC_ON_SA1100 | ||
373 | case LIRC_SET_SEND_DUTY_CYCLE: | ||
374 | retval = get_user(value, (__u32 *) arg); | ||
375 | if (retval) | ||
376 | return retval; | ||
377 | if (value <= 0 || value > 100) | ||
378 | return -EINVAL; | ||
379 | /* (value/100)*(1000000/freq) */ | ||
380 | duty_cycle = value; | ||
381 | pulse_width = (unsigned long) duty_cycle*10000/freq; | ||
382 | space_width = (unsigned long) 1000000L/freq-pulse_width; | ||
383 | if (pulse_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY) | ||
384 | pulse_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY; | ||
385 | if (space_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY) | ||
386 | space_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY; | ||
387 | break; | ||
388 | case LIRC_SET_SEND_CARRIER: | ||
389 | retval = get_user(value, (__u32 *) arg); | ||
390 | if (retval) | ||
391 | return retval; | ||
392 | if (value > 500000 || value < 20000) | ||
393 | return -EINVAL; | ||
394 | freq = value; | ||
395 | pulse_width = (unsigned long) duty_cycle*10000/freq; | ||
396 | space_width = (unsigned long) 1000000L/freq-pulse_width; | ||
397 | if (pulse_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY) | ||
398 | pulse_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY; | ||
399 | if (space_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY) | ||
400 | space_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY; | ||
401 | break; | ||
402 | #endif | ||
403 | default: | ||
404 | retval = -ENOIOCTLCMD; | ||
405 | |||
406 | } | ||
407 | |||
408 | if (retval) | ||
409 | return retval; | ||
410 | if (cmd == LIRC_SET_REC_MODE) { | ||
411 | if (value != LIRC_MODE_MODE2) | ||
412 | retval = -ENOSYS; | ||
413 | } else if (cmd == LIRC_SET_SEND_MODE) { | ||
414 | if (value != LIRC_MODE_PULSE) | ||
415 | retval = -ENOSYS; | ||
416 | } | ||
417 | |||
418 | return retval; | ||
419 | } | ||
420 | |||
421 | static void add_read_queue(int flag, unsigned long val) | ||
422 | { | ||
423 | unsigned int new_rx_tail; | ||
424 | int newval; | ||
425 | |||
426 | dprintk("add flag %d with val %lu\n", flag, val); | ||
427 | |||
428 | newval = val & PULSE_MASK; | ||
429 | |||
430 | /* | ||
431 | * statistically, pulses are ~TIME_CONST/2 too long. we could | ||
432 | * maybe make this more exact, but this is good enough | ||
433 | */ | ||
434 | if (flag) { | ||
435 | /* pulse */ | ||
436 | if (newval > TIME_CONST/2) | ||
437 | newval -= TIME_CONST/2; | ||
438 | else /* should not ever happen */ | ||
439 | newval = 1; | ||
440 | newval |= PULSE_BIT; | ||
441 | } else { | ||
442 | newval += TIME_CONST/2; | ||
443 | } | ||
444 | new_rx_tail = (rx_tail + 1) & (RBUF_LEN - 1); | ||
445 | if (new_rx_tail == rx_head) { | ||
446 | dprintk("Buffer overrun.\n"); | ||
447 | return; | ||
448 | } | ||
449 | rx_buf[rx_tail] = newval; | ||
450 | rx_tail = new_rx_tail; | ||
451 | wake_up_interruptible(&lirc_read_queue); | ||
452 | } | ||
453 | |||
454 | static const struct file_operations lirc_fops = { | ||
455 | .owner = THIS_MODULE, | ||
456 | .read = lirc_read, | ||
457 | .write = lirc_write, | ||
458 | .poll = lirc_poll, | ||
459 | .unlocked_ioctl = lirc_ioctl, | ||
460 | #ifdef CONFIG_COMPAT | ||
461 | .compat_ioctl = lirc_ioctl, | ||
462 | #endif | ||
463 | .open = lirc_dev_fop_open, | ||
464 | .release = lirc_dev_fop_close, | ||
465 | .llseek = no_llseek, | ||
466 | }; | ||
467 | |||
468 | static int set_use_inc(void *data) | ||
469 | { | ||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | static void set_use_dec(void *data) | ||
474 | { | ||
475 | } | ||
476 | |||
477 | static struct lirc_driver driver = { | ||
478 | .name = LIRC_DRIVER_NAME, | ||
479 | .minor = -1, | ||
480 | .code_length = 1, | ||
481 | .sample_rate = 0, | ||
482 | .data = NULL, | ||
483 | .add_to_buf = NULL, | ||
484 | .set_use_inc = set_use_inc, | ||
485 | .set_use_dec = set_use_dec, | ||
486 | .fops = &lirc_fops, | ||
487 | .dev = NULL, | ||
488 | .owner = THIS_MODULE, | ||
489 | }; | ||
490 | |||
491 | |||
492 | static int init_chrdev(void) | ||
493 | { | ||
494 | driver.minor = lirc_register_driver(&driver); | ||
495 | if (driver.minor < 0) { | ||
496 | printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n"); | ||
497 | return -EIO; | ||
498 | } | ||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | static void drop_chrdev(void) | ||
503 | { | ||
504 | lirc_unregister_driver(driver.minor); | ||
505 | } | ||
506 | |||
507 | /* SECTION: Hardware */ | ||
508 | static long delta(struct timeval *tv1, struct timeval *tv2) | ||
509 | { | ||
510 | unsigned long deltv; | ||
511 | |||
512 | deltv = tv2->tv_sec - tv1->tv_sec; | ||
513 | if (deltv > 15) | ||
514 | deltv = 0xFFFFFF; | ||
515 | else | ||
516 | deltv = deltv*1000000 + | ||
517 | tv2->tv_usec - | ||
518 | tv1->tv_usec; | ||
519 | return deltv; | ||
520 | } | ||
521 | |||
522 | static void sir_timeout(unsigned long data) | ||
523 | { | ||
524 | /* | ||
525 | * if last received signal was a pulse, but receiving stopped | ||
526 | * within the 9 bit frame, we need to finish this pulse and | ||
527 | * simulate a signal change to from pulse to space. Otherwise | ||
528 | * upper layers will receive two sequences next time. | ||
529 | */ | ||
530 | |||
531 | unsigned long flags; | ||
532 | unsigned long pulse_end; | ||
533 | |||
534 | /* avoid interference with interrupt */ | ||
535 | spin_lock_irqsave(&timer_lock, flags); | ||
536 | if (last_value) { | ||
537 | #ifndef LIRC_ON_SA1100 | ||
538 | /* clear unread bits in UART and restart */ | ||
539 | outb(UART_FCR_CLEAR_RCVR, io + UART_FCR); | ||
540 | #endif | ||
541 | /* determine 'virtual' pulse end: */ | ||
542 | pulse_end = delta(&last_tv, &last_intr_tv); | ||
543 | dprintk("timeout add %d for %lu usec\n", last_value, pulse_end); | ||
544 | add_read_queue(last_value, pulse_end); | ||
545 | last_value = 0; | ||
546 | last_tv = last_intr_tv; | ||
547 | } | ||
548 | spin_unlock_irqrestore(&timer_lock, flags); | ||
549 | } | ||
550 | |||
551 | static irqreturn_t sir_interrupt(int irq, void *dev_id) | ||
552 | { | ||
553 | unsigned char data; | ||
554 | struct timeval curr_tv; | ||
555 | static unsigned long deltv; | ||
556 | #ifdef LIRC_ON_SA1100 | ||
557 | int status; | ||
558 | static int n; | ||
559 | |||
560 | status = Ser2UTSR0; | ||
561 | /* | ||
562 | * Deal with any receive errors first. The bytes in error may be | ||
563 | * the only bytes in the receive FIFO, so we do this first. | ||
564 | */ | ||
565 | while (status & UTSR0_EIF) { | ||
566 | int bstat; | ||
567 | |||
568 | if (debug) { | ||
569 | dprintk("EIF\n"); | ||
570 | bstat = Ser2UTSR1; | ||
571 | |||
572 | if (bstat & UTSR1_FRE) | ||
573 | dprintk("frame error\n"); | ||
574 | if (bstat & UTSR1_ROR) | ||
575 | dprintk("receive fifo overrun\n"); | ||
576 | if (bstat & UTSR1_PRE) | ||
577 | dprintk("parity error\n"); | ||
578 | } | ||
579 | |||
580 | bstat = Ser2UTDR; | ||
581 | n++; | ||
582 | status = Ser2UTSR0; | ||
583 | } | ||
584 | |||
585 | if (status & (UTSR0_RFS | UTSR0_RID)) { | ||
586 | do_gettimeofday(&curr_tv); | ||
587 | deltv = delta(&last_tv, &curr_tv); | ||
588 | do { | ||
589 | data = Ser2UTDR; | ||
590 | dprintk("%d data: %u\n", n, (unsigned int) data); | ||
591 | n++; | ||
592 | } while (status & UTSR0_RID && /* do not empty fifo in order to | ||
593 | * get UTSR0_RID in any case */ | ||
594 | Ser2UTSR1 & UTSR1_RNE); /* data ready */ | ||
595 | |||
596 | if (status&UTSR0_RID) { | ||
597 | add_read_queue(0 , deltv - n * TIME_CONST); /*space*/ | ||
598 | add_read_queue(1, n * TIME_CONST); /*pulse*/ | ||
599 | n = 0; | ||
600 | last_tv = curr_tv; | ||
601 | } | ||
602 | } | ||
603 | |||
604 | if (status & UTSR0_TFS) | ||
605 | printk(KERN_ERR "transmit fifo not full, shouldn't happen\n"); | ||
606 | |||
607 | /* We must clear certain bits. */ | ||
608 | status &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB); | ||
609 | if (status) | ||
610 | Ser2UTSR0 = status; | ||
611 | #else | ||
612 | unsigned long deltintrtv; | ||
613 | unsigned long flags; | ||
614 | int iir, lsr; | ||
615 | |||
616 | while ((iir = inb(io + UART_IIR) & UART_IIR_ID)) { | ||
617 | switch (iir&UART_IIR_ID) { /* FIXME toto treba preriedit */ | ||
618 | case UART_IIR_MSI: | ||
619 | (void) inb(io + UART_MSR); | ||
620 | break; | ||
621 | case UART_IIR_RLSI: | ||
622 | (void) inb(io + UART_LSR); | ||
623 | break; | ||
624 | case UART_IIR_THRI: | ||
625 | #if 0 | ||
626 | if (lsr & UART_LSR_THRE) /* FIFO is empty */ | ||
627 | outb(data, io + UART_TX) | ||
628 | #endif | ||
629 | break; | ||
630 | case UART_IIR_RDI: | ||
631 | /* avoid interference with timer */ | ||
632 | spin_lock_irqsave(&timer_lock, flags); | ||
633 | do { | ||
634 | del_timer(&timerlist); | ||
635 | data = inb(io + UART_RX); | ||
636 | do_gettimeofday(&curr_tv); | ||
637 | deltv = delta(&last_tv, &curr_tv); | ||
638 | deltintrtv = delta(&last_intr_tv, &curr_tv); | ||
639 | dprintk("t %lu, d %d\n", deltintrtv, (int)data); | ||
640 | /* | ||
641 | * if nothing came in last X cycles, | ||
642 | * it was gap | ||
643 | */ | ||
644 | if (deltintrtv > TIME_CONST * threshold) { | ||
645 | if (last_value) { | ||
646 | dprintk("GAP\n"); | ||
647 | /* simulate signal change */ | ||
648 | add_read_queue(last_value, | ||
649 | deltv - | ||
650 | deltintrtv); | ||
651 | last_value = 0; | ||
652 | last_tv.tv_sec = | ||
653 | last_intr_tv.tv_sec; | ||
654 | last_tv.tv_usec = | ||
655 | last_intr_tv.tv_usec; | ||
656 | deltv = deltintrtv; | ||
657 | } | ||
658 | } | ||
659 | data = 1; | ||
660 | if (data ^ last_value) { | ||
661 | /* | ||
662 | * deltintrtv > 2*TIME_CONST, remember? | ||
663 | * the other case is timeout | ||
664 | */ | ||
665 | add_read_queue(last_value, | ||
666 | deltv-TIME_CONST); | ||
667 | last_value = data; | ||
668 | last_tv = curr_tv; | ||
669 | if (last_tv.tv_usec >= TIME_CONST) { | ||
670 | last_tv.tv_usec -= TIME_CONST; | ||
671 | } else { | ||
672 | last_tv.tv_sec--; | ||
673 | last_tv.tv_usec += 1000000 - | ||
674 | TIME_CONST; | ||
675 | } | ||
676 | } | ||
677 | last_intr_tv = curr_tv; | ||
678 | if (data) { | ||
679 | /* | ||
680 | * start timer for end of | ||
681 | * sequence detection | ||
682 | */ | ||
683 | timerlist.expires = jiffies + | ||
684 | SIR_TIMEOUT; | ||
685 | add_timer(&timerlist); | ||
686 | } | ||
687 | |||
688 | lsr = inb(io + UART_LSR); | ||
689 | } while (lsr & UART_LSR_DR); /* data ready */ | ||
690 | spin_unlock_irqrestore(&timer_lock, flags); | ||
691 | break; | ||
692 | default: | ||
693 | break; | ||
694 | } | ||
695 | } | ||
696 | #endif | ||
697 | return IRQ_RETVAL(IRQ_HANDLED); | ||
698 | } | ||
699 | |||
700 | #ifdef LIRC_ON_SA1100 | ||
701 | static void send_pulse(unsigned long length) | ||
702 | { | ||
703 | unsigned long k, delay; | ||
704 | int flag; | ||
705 | |||
706 | if (length == 0) | ||
707 | return; | ||
708 | /* | ||
709 | * this won't give us the carrier frequency we really want | ||
710 | * due to integer arithmetic, but we can accept this inaccuracy | ||
711 | */ | ||
712 | |||
713 | for (k = flag = 0; k < length; k += delay, flag = !flag) { | ||
714 | if (flag) { | ||
715 | off(); | ||
716 | delay = space_width; | ||
717 | } else { | ||
718 | on(); | ||
719 | delay = pulse_width; | ||
720 | } | ||
721 | safe_udelay(delay); | ||
722 | } | ||
723 | off(); | ||
724 | } | ||
725 | |||
726 | static void send_space(unsigned long length) | ||
727 | { | ||
728 | if (length == 0) | ||
729 | return; | ||
730 | off(); | ||
731 | safe_udelay(length); | ||
732 | } | ||
733 | #else | ||
734 | static void send_space(unsigned long len) | ||
735 | { | ||
736 | safe_udelay(len); | ||
737 | } | ||
738 | |||
739 | static void send_pulse(unsigned long len) | ||
740 | { | ||
741 | long bytes_out = len / TIME_CONST; | ||
742 | |||
743 | if (bytes_out == 0) | ||
744 | bytes_out++; | ||
745 | |||
746 | while (bytes_out--) { | ||
747 | outb(PULSE, io + UART_TX); | ||
748 | /* FIXME treba seriozne cakanie z char/serial.c */ | ||
749 | while (!(inb(io + UART_LSR) & UART_LSR_THRE)) | ||
750 | ; | ||
751 | } | ||
752 | } | ||
753 | #endif | ||
754 | |||
755 | #ifdef CONFIG_SA1100_COLLIE | ||
756 | static int sa1100_irda_set_power_collie(int state) | ||
757 | { | ||
758 | if (state) { | ||
759 | /* | ||
760 | * 0 - off | ||
761 | * 1 - short range, lowest power | ||
762 | * 2 - medium range, medium power | ||
763 | * 3 - maximum range, high power | ||
764 | */ | ||
765 | ucb1200_set_io_direction(TC35143_GPIO_IR_ON, | ||
766 | TC35143_IODIR_OUTPUT); | ||
767 | ucb1200_set_io(TC35143_GPIO_IR_ON, TC35143_IODAT_LOW); | ||
768 | udelay(100); | ||
769 | } else { | ||
770 | /* OFF */ | ||
771 | ucb1200_set_io_direction(TC35143_GPIO_IR_ON, | ||
772 | TC35143_IODIR_OUTPUT); | ||
773 | ucb1200_set_io(TC35143_GPIO_IR_ON, TC35143_IODAT_HIGH); | ||
774 | } | ||
775 | return 0; | ||
776 | } | ||
777 | #endif | ||
778 | |||
779 | static int init_hardware(void) | ||
780 | { | ||
781 | unsigned long flags; | ||
782 | |||
783 | spin_lock_irqsave(&hardware_lock, flags); | ||
784 | /* reset UART */ | ||
785 | #ifdef LIRC_ON_SA1100 | ||
786 | #ifdef CONFIG_SA1100_BITSY | ||
787 | if (machine_is_bitsy()) { | ||
788 | printk(KERN_INFO "Power on IR module\n"); | ||
789 | set_bitsy_egpio(EGPIO_BITSY_IR_ON); | ||
790 | } | ||
791 | #endif | ||
792 | #ifdef CONFIG_SA1100_COLLIE | ||
793 | sa1100_irda_set_power_collie(3); /* power on */ | ||
794 | #endif | ||
795 | sr.hscr0 = Ser2HSCR0; | ||
796 | |||
797 | sr.utcr0 = Ser2UTCR0; | ||
798 | sr.utcr1 = Ser2UTCR1; | ||
799 | sr.utcr2 = Ser2UTCR2; | ||
800 | sr.utcr3 = Ser2UTCR3; | ||
801 | sr.utcr4 = Ser2UTCR4; | ||
802 | |||
803 | sr.utdr = Ser2UTDR; | ||
804 | sr.utsr0 = Ser2UTSR0; | ||
805 | sr.utsr1 = Ser2UTSR1; | ||
806 | |||
807 | /* configure GPIO */ | ||
808 | /* output */ | ||
809 | PPDR |= PPC_TXD2; | ||
810 | PSDR |= PPC_TXD2; | ||
811 | /* set output to 0 */ | ||
812 | off(); | ||
813 | |||
814 | /* Enable HP-SIR modulation, and ensure that the port is disabled. */ | ||
815 | Ser2UTCR3 = 0; | ||
816 | Ser2HSCR0 = sr.hscr0 & (~HSCR0_HSSP); | ||
817 | |||
818 | /* clear status register to prevent unwanted interrupts */ | ||
819 | Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB); | ||
820 | |||
821 | /* 7N1 */ | ||
822 | Ser2UTCR0 = UTCR0_1StpBit|UTCR0_7BitData; | ||
823 | /* 115200 */ | ||
824 | Ser2UTCR1 = 0; | ||
825 | Ser2UTCR2 = 1; | ||
826 | /* use HPSIR, 1.6 usec pulses */ | ||
827 | Ser2UTCR4 = UTCR4_HPSIR|UTCR4_Z1_6us; | ||
828 | |||
829 | /* enable receiver, receive fifo interrupt */ | ||
830 | Ser2UTCR3 = UTCR3_RXE|UTCR3_RIE; | ||
831 | |||
832 | /* clear status register to prevent unwanted interrupts */ | ||
833 | Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB); | ||
834 | |||
835 | #elif defined(LIRC_SIR_TEKRAM) | ||
836 | /* disable FIFO */ | ||
837 | soutp(UART_FCR, | ||
838 | UART_FCR_CLEAR_RCVR| | ||
839 | UART_FCR_CLEAR_XMIT| | ||
840 | UART_FCR_TRIGGER_1); | ||
841 | |||
842 | /* Set DLAB 0. */ | ||
843 | soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); | ||
844 | |||
845 | /* First of all, disable all interrupts */ | ||
846 | soutp(UART_IER, sinp(UART_IER) & | ||
847 | (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); | ||
848 | |||
849 | /* Set DLAB 1. */ | ||
850 | soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB); | ||
851 | |||
852 | /* Set divisor to 12 => 9600 Baud */ | ||
853 | soutp(UART_DLM, 0); | ||
854 | soutp(UART_DLL, 12); | ||
855 | |||
856 | /* Set DLAB 0. */ | ||
857 | soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); | ||
858 | |||
859 | /* power supply */ | ||
860 | soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); | ||
861 | safe_udelay(50*1000); | ||
862 | |||
863 | /* -DTR low -> reset PIC */ | ||
864 | soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2); | ||
865 | udelay(1*1000); | ||
866 | |||
867 | soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); | ||
868 | udelay(100); | ||
869 | |||
870 | |||
871 | /* -RTS low -> send control byte */ | ||
872 | soutp(UART_MCR, UART_MCR_DTR|UART_MCR_OUT2); | ||
873 | udelay(7); | ||
874 | soutp(UART_TX, TEKRAM_115200|TEKRAM_PW); | ||
875 | |||
876 | /* one byte takes ~1042 usec to transmit at 9600,8N1 */ | ||
877 | udelay(1500); | ||
878 | |||
879 | /* back to normal operation */ | ||
880 | soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); | ||
881 | udelay(50); | ||
882 | |||
883 | udelay(1500); | ||
884 | |||
885 | /* read previous control byte */ | ||
886 | printk(KERN_INFO LIRC_DRIVER_NAME | ||
887 | ": 0x%02x\n", sinp(UART_RX)); | ||
888 | |||
889 | /* Set DLAB 1. */ | ||
890 | soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB); | ||
891 | |||
892 | /* Set divisor to 1 => 115200 Baud */ | ||
893 | soutp(UART_DLM, 0); | ||
894 | soutp(UART_DLL, 1); | ||
895 | |||
896 | /* Set DLAB 0, 8 Bit */ | ||
897 | soutp(UART_LCR, UART_LCR_WLEN8); | ||
898 | /* enable interrupts */ | ||
899 | soutp(UART_IER, sinp(UART_IER)|UART_IER_RDI); | ||
900 | #else | ||
901 | outb(0, io + UART_MCR); | ||
902 | outb(0, io + UART_IER); | ||
903 | /* init UART */ | ||
904 | /* set DLAB, speed = 115200 */ | ||
905 | outb(UART_LCR_DLAB | UART_LCR_WLEN7, io + UART_LCR); | ||
906 | outb(1, io + UART_DLL); outb(0, io + UART_DLM); | ||
907 | /* 7N1+start = 9 bits at 115200 ~ 3 bits at 44000 */ | ||
908 | outb(UART_LCR_WLEN7, io + UART_LCR); | ||
909 | /* FIFO operation */ | ||
910 | outb(UART_FCR_ENABLE_FIFO, io + UART_FCR); | ||
911 | /* interrupts */ | ||
912 | /* outb(UART_IER_RLSI|UART_IER_RDI|UART_IER_THRI, io + UART_IER); */ | ||
913 | outb(UART_IER_RDI, io + UART_IER); | ||
914 | /* turn on UART */ | ||
915 | outb(UART_MCR_DTR|UART_MCR_RTS|UART_MCR_OUT2, io + UART_MCR); | ||
916 | #ifdef LIRC_SIR_ACTISYS_ACT200L | ||
917 | init_act200(); | ||
918 | #elif defined(LIRC_SIR_ACTISYS_ACT220L) | ||
919 | init_act220(); | ||
920 | #endif | ||
921 | #endif | ||
922 | spin_unlock_irqrestore(&hardware_lock, flags); | ||
923 | return 0; | ||
924 | } | ||
925 | |||
926 | static void drop_hardware(void) | ||
927 | { | ||
928 | unsigned long flags; | ||
929 | |||
930 | spin_lock_irqsave(&hardware_lock, flags); | ||
931 | |||
932 | #ifdef LIRC_ON_SA1100 | ||
933 | Ser2UTCR3 = 0; | ||
934 | |||
935 | Ser2UTCR0 = sr.utcr0; | ||
936 | Ser2UTCR1 = sr.utcr1; | ||
937 | Ser2UTCR2 = sr.utcr2; | ||
938 | Ser2UTCR4 = sr.utcr4; | ||
939 | Ser2UTCR3 = sr.utcr3; | ||
940 | |||
941 | Ser2HSCR0 = sr.hscr0; | ||
942 | #ifdef CONFIG_SA1100_BITSY | ||
943 | if (machine_is_bitsy()) | ||
944 | clr_bitsy_egpio(EGPIO_BITSY_IR_ON); | ||
945 | #endif | ||
946 | #ifdef CONFIG_SA1100_COLLIE | ||
947 | sa1100_irda_set_power_collie(0); /* power off */ | ||
948 | #endif | ||
949 | #else | ||
950 | /* turn off interrupts */ | ||
951 | outb(0, io + UART_IER); | ||
952 | #endif | ||
953 | spin_unlock_irqrestore(&hardware_lock, flags); | ||
954 | } | ||
955 | |||
956 | /* SECTION: Initialisation */ | ||
957 | |||
958 | static int init_port(void) | ||
959 | { | ||
960 | int retval; | ||
961 | |||
962 | /* get I/O port access and IRQ line */ | ||
963 | #ifndef LIRC_ON_SA1100 | ||
964 | if (request_region(io, 8, LIRC_DRIVER_NAME) == NULL) { | ||
965 | printk(KERN_ERR LIRC_DRIVER_NAME | ||
966 | ": i/o port 0x%.4x already in use.\n", io); | ||
967 | return -EBUSY; | ||
968 | } | ||
969 | #endif | ||
970 | retval = request_irq(irq, sir_interrupt, IRQF_DISABLED, | ||
971 | LIRC_DRIVER_NAME, NULL); | ||
972 | if (retval < 0) { | ||
973 | # ifndef LIRC_ON_SA1100 | ||
974 | release_region(io, 8); | ||
975 | # endif | ||
976 | printk(KERN_ERR LIRC_DRIVER_NAME | ||
977 | ": IRQ %d already in use.\n", | ||
978 | irq); | ||
979 | return retval; | ||
980 | } | ||
981 | #ifndef LIRC_ON_SA1100 | ||
982 | printk(KERN_INFO LIRC_DRIVER_NAME | ||
983 | ": I/O port 0x%.4x, IRQ %d.\n", | ||
984 | io, irq); | ||
985 | #endif | ||
986 | |||
987 | init_timer(&timerlist); | ||
988 | timerlist.function = sir_timeout; | ||
989 | timerlist.data = 0xabadcafe; | ||
990 | |||
991 | return 0; | ||
992 | } | ||
993 | |||
994 | static void drop_port(void) | ||
995 | { | ||
996 | free_irq(irq, NULL); | ||
997 | del_timer_sync(&timerlist); | ||
998 | #ifndef LIRC_ON_SA1100 | ||
999 | release_region(io, 8); | ||
1000 | #endif | ||
1001 | } | ||
1002 | |||
1003 | #ifdef LIRC_SIR_ACTISYS_ACT200L | ||
1004 | /* Crystal/Cirrus CS8130 IR transceiver, used in Actisys Act200L dongle */ | ||
1005 | /* some code borrowed from Linux IRDA driver */ | ||
1006 | |||
1007 | /* Register 0: Control register #1 */ | ||
1008 | #define ACT200L_REG0 0x00 | ||
1009 | #define ACT200L_TXEN 0x01 /* Enable transmitter */ | ||
1010 | #define ACT200L_RXEN 0x02 /* Enable receiver */ | ||
1011 | #define ACT200L_ECHO 0x08 /* Echo control chars */ | ||
1012 | |||
1013 | /* Register 1: Control register #2 */ | ||
1014 | #define ACT200L_REG1 0x10 | ||
1015 | #define ACT200L_LODB 0x01 /* Load new baud rate count value */ | ||
1016 | #define ACT200L_WIDE 0x04 /* Expand the maximum allowable pulse */ | ||
1017 | |||
1018 | /* Register 3: Transmit mode register #2 */ | ||
1019 | #define ACT200L_REG3 0x30 | ||
1020 | #define ACT200L_B0 0x01 /* DataBits, 0=6, 1=7, 2=8, 3=9(8P) */ | ||
1021 | #define ACT200L_B1 0x02 /* DataBits, 0=6, 1=7, 2=8, 3=9(8P) */ | ||
1022 | #define ACT200L_CHSY 0x04 /* StartBit Synced 0=bittime, 1=startbit */ | ||
1023 | |||
1024 | /* Register 4: Output Power register */ | ||
1025 | #define ACT200L_REG4 0x40 | ||
1026 | #define ACT200L_OP0 0x01 /* Enable LED1C output */ | ||
1027 | #define ACT200L_OP1 0x02 /* Enable LED2C output */ | ||
1028 | #define ACT200L_BLKR 0x04 | ||
1029 | |||
1030 | /* Register 5: Receive Mode register */ | ||
1031 | #define ACT200L_REG5 0x50 | ||
1032 | #define ACT200L_RWIDL 0x01 /* fixed 1.6us pulse mode */ | ||
1033 | /*.. other various IRDA bit modes, and TV remote modes..*/ | ||
1034 | |||
1035 | /* Register 6: Receive Sensitivity register #1 */ | ||
1036 | #define ACT200L_REG6 0x60 | ||
1037 | #define ACT200L_RS0 0x01 /* receive threshold bit 0 */ | ||
1038 | #define ACT200L_RS1 0x02 /* receive threshold bit 1 */ | ||
1039 | |||
1040 | /* Register 7: Receive Sensitivity register #2 */ | ||
1041 | #define ACT200L_REG7 0x70 | ||
1042 | #define ACT200L_ENPOS 0x04 /* Ignore the falling edge */ | ||
1043 | |||
1044 | /* Register 8,9: Baud Rate Divider register #1,#2 */ | ||
1045 | #define ACT200L_REG8 0x80 | ||
1046 | #define ACT200L_REG9 0x90 | ||
1047 | |||
1048 | #define ACT200L_2400 0x5f | ||
1049 | #define ACT200L_9600 0x17 | ||
1050 | #define ACT200L_19200 0x0b | ||
1051 | #define ACT200L_38400 0x05 | ||
1052 | #define ACT200L_57600 0x03 | ||
1053 | #define ACT200L_115200 0x01 | ||
1054 | |||
1055 | /* Register 13: Control register #3 */ | ||
1056 | #define ACT200L_REG13 0xd0 | ||
1057 | #define ACT200L_SHDW 0x01 /* Enable access to shadow registers */ | ||
1058 | |||
1059 | /* Register 15: Status register */ | ||
1060 | #define ACT200L_REG15 0xf0 | ||
1061 | |||
1062 | /* Register 21: Control register #4 */ | ||
1063 | #define ACT200L_REG21 0x50 | ||
1064 | #define ACT200L_EXCK 0x02 /* Disable clock output driver */ | ||
1065 | #define ACT200L_OSCL 0x04 /* oscillator in low power, medium accuracy mode */ | ||
1066 | |||
1067 | static void init_act200(void) | ||
1068 | { | ||
1069 | int i; | ||
1070 | __u8 control[] = { | ||
1071 | ACT200L_REG15, | ||
1072 | ACT200L_REG13 | ACT200L_SHDW, | ||
1073 | ACT200L_REG21 | ACT200L_EXCK | ACT200L_OSCL, | ||
1074 | ACT200L_REG13, | ||
1075 | ACT200L_REG7 | ACT200L_ENPOS, | ||
1076 | ACT200L_REG6 | ACT200L_RS0 | ACT200L_RS1, | ||
1077 | ACT200L_REG5 | ACT200L_RWIDL, | ||
1078 | ACT200L_REG4 | ACT200L_OP0 | ACT200L_OP1 | ACT200L_BLKR, | ||
1079 | ACT200L_REG3 | ACT200L_B0, | ||
1080 | ACT200L_REG0 | ACT200L_TXEN | ACT200L_RXEN, | ||
1081 | ACT200L_REG8 | (ACT200L_115200 & 0x0f), | ||
1082 | ACT200L_REG9 | ((ACT200L_115200 >> 4) & 0x0f), | ||
1083 | ACT200L_REG1 | ACT200L_LODB | ACT200L_WIDE | ||
1084 | }; | ||
1085 | |||
1086 | /* Set DLAB 1. */ | ||
1087 | soutp(UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN8); | ||
1088 | |||
1089 | /* Set divisor to 12 => 9600 Baud */ | ||
1090 | soutp(UART_DLM, 0); | ||
1091 | soutp(UART_DLL, 12); | ||
1092 | |||
1093 | /* Set DLAB 0. */ | ||
1094 | soutp(UART_LCR, UART_LCR_WLEN8); | ||
1095 | /* Set divisor to 12 => 9600 Baud */ | ||
1096 | |||
1097 | /* power supply */ | ||
1098 | soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); | ||
1099 | for (i = 0; i < 50; i++) | ||
1100 | safe_udelay(1000); | ||
1101 | |||
1102 | /* Reset the dongle : set RTS low for 25 ms */ | ||
1103 | soutp(UART_MCR, UART_MCR_DTR|UART_MCR_OUT2); | ||
1104 | for (i = 0; i < 25; i++) | ||
1105 | udelay(1000); | ||
1106 | |||
1107 | soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); | ||
1108 | udelay(100); | ||
1109 | |||
1110 | /* Clear DTR and set RTS to enter command mode */ | ||
1111 | soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2); | ||
1112 | udelay(7); | ||
1113 | |||
1114 | /* send out the control register settings for 115K 7N1 SIR operation */ | ||
1115 | for (i = 0; i < sizeof(control); i++) { | ||
1116 | soutp(UART_TX, control[i]); | ||
1117 | /* one byte takes ~1042 usec to transmit at 9600,8N1 */ | ||
1118 | udelay(1500); | ||
1119 | } | ||
1120 | |||
1121 | /* back to normal operation */ | ||
1122 | soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); | ||
1123 | udelay(50); | ||
1124 | |||
1125 | udelay(1500); | ||
1126 | soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB); | ||
1127 | |||
1128 | /* Set DLAB 1. */ | ||
1129 | soutp(UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN7); | ||
1130 | |||
1131 | /* Set divisor to 1 => 115200 Baud */ | ||
1132 | soutp(UART_DLM, 0); | ||
1133 | soutp(UART_DLL, 1); | ||
1134 | |||
1135 | /* Set DLAB 0. */ | ||
1136 | soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); | ||
1137 | |||
1138 | /* Set DLAB 0, 7 Bit */ | ||
1139 | soutp(UART_LCR, UART_LCR_WLEN7); | ||
1140 | |||
1141 | /* enable interrupts */ | ||
1142 | soutp(UART_IER, sinp(UART_IER)|UART_IER_RDI); | ||
1143 | } | ||
1144 | #endif | ||
1145 | |||
1146 | #ifdef LIRC_SIR_ACTISYS_ACT220L | ||
1147 | /* | ||
1148 | * Derived from linux IrDA driver (net/irda/actisys.c) | ||
1149 | * Drop me a mail for any kind of comment: maxx@spaceboyz.net | ||
1150 | */ | ||
1151 | |||
1152 | void init_act220(void) | ||
1153 | { | ||
1154 | int i; | ||
1155 | |||
1156 | /* DLAB 1 */ | ||
1157 | soutp(UART_LCR, UART_LCR_DLAB|UART_LCR_WLEN7); | ||
1158 | |||
1159 | /* 9600 baud */ | ||
1160 | soutp(UART_DLM, 0); | ||
1161 | soutp(UART_DLL, 12); | ||
1162 | |||
1163 | /* DLAB 0 */ | ||
1164 | soutp(UART_LCR, UART_LCR_WLEN7); | ||
1165 | |||
1166 | /* reset the dongle, set DTR low for 10us */ | ||
1167 | soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2); | ||
1168 | udelay(10); | ||
1169 | |||
1170 | /* back to normal (still 9600) */ | ||
1171 | soutp(UART_MCR, UART_MCR_DTR|UART_MCR_RTS|UART_MCR_OUT2); | ||
1172 | |||
1173 | /* | ||
1174 | * send RTS pulses until we reach 115200 | ||
1175 | * i hope this is really the same for act220l/act220l+ | ||
1176 | */ | ||
1177 | for (i = 0; i < 3; i++) { | ||
1178 | udelay(10); | ||
1179 | /* set RTS low for 10 us */ | ||
1180 | soutp(UART_MCR, UART_MCR_DTR|UART_MCR_OUT2); | ||
1181 | udelay(10); | ||
1182 | /* set RTS high for 10 us */ | ||
1183 | soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); | ||
1184 | } | ||
1185 | |||
1186 | /* back to normal operation */ | ||
1187 | udelay(1500); /* better safe than sorry ;) */ | ||
1188 | |||
1189 | /* Set DLAB 1. */ | ||
1190 | soutp(UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN7); | ||
1191 | |||
1192 | /* Set divisor to 1 => 115200 Baud */ | ||
1193 | soutp(UART_DLM, 0); | ||
1194 | soutp(UART_DLL, 1); | ||
1195 | |||
1196 | /* Set DLAB 0, 7 Bit */ | ||
1197 | /* The dongle doesn't seem to have any problems with operation at 7N1 */ | ||
1198 | soutp(UART_LCR, UART_LCR_WLEN7); | ||
1199 | |||
1200 | /* enable interrupts */ | ||
1201 | soutp(UART_IER, UART_IER_RDI); | ||
1202 | } | ||
1203 | #endif | ||
1204 | |||
1205 | static int init_lirc_sir(void) | ||
1206 | { | ||
1207 | int retval; | ||
1208 | |||
1209 | init_waitqueue_head(&lirc_read_queue); | ||
1210 | retval = init_port(); | ||
1211 | if (retval < 0) | ||
1212 | return retval; | ||
1213 | init_hardware(); | ||
1214 | printk(KERN_INFO LIRC_DRIVER_NAME | ||
1215 | ": Installed.\n"); | ||
1216 | return 0; | ||
1217 | } | ||
1218 | |||
1219 | |||
1220 | static int __init lirc_sir_init(void) | ||
1221 | { | ||
1222 | int retval; | ||
1223 | |||
1224 | retval = init_chrdev(); | ||
1225 | if (retval < 0) | ||
1226 | return retval; | ||
1227 | retval = init_lirc_sir(); | ||
1228 | if (retval) { | ||
1229 | drop_chrdev(); | ||
1230 | return retval; | ||
1231 | } | ||
1232 | return 0; | ||
1233 | } | ||
1234 | |||
1235 | static void __exit lirc_sir_exit(void) | ||
1236 | { | ||
1237 | drop_hardware(); | ||
1238 | drop_chrdev(); | ||
1239 | drop_port(); | ||
1240 | printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n"); | ||
1241 | } | ||
1242 | |||
1243 | module_init(lirc_sir_init); | ||
1244 | module_exit(lirc_sir_exit); | ||
1245 | |||
1246 | #ifdef LIRC_SIR_TEKRAM | ||
1247 | MODULE_DESCRIPTION("Infrared receiver driver for Tekram Irmate 210"); | ||
1248 | MODULE_AUTHOR("Christoph Bartelmus"); | ||
1249 | #elif defined(LIRC_ON_SA1100) | ||
1250 | MODULE_DESCRIPTION("LIRC driver for StrongARM SA1100 embedded microprocessor"); | ||
1251 | MODULE_AUTHOR("Christoph Bartelmus"); | ||
1252 | #elif defined(LIRC_SIR_ACTISYS_ACT200L) | ||
1253 | MODULE_DESCRIPTION("LIRC driver for Actisys Act200L"); | ||
1254 | MODULE_AUTHOR("Karl Bongers"); | ||
1255 | #elif defined(LIRC_SIR_ACTISYS_ACT220L) | ||
1256 | MODULE_DESCRIPTION("LIRC driver for Actisys Act220L(+)"); | ||
1257 | MODULE_AUTHOR("Jan Roemisch"); | ||
1258 | #else | ||
1259 | MODULE_DESCRIPTION("Infrared receiver driver for SIR type serial ports"); | ||
1260 | MODULE_AUTHOR("Milan Pikula"); | ||
1261 | #endif | ||
1262 | MODULE_LICENSE("GPL"); | ||
1263 | |||
1264 | #ifdef LIRC_ON_SA1100 | ||
1265 | module_param(irq, int, S_IRUGO); | ||
1266 | MODULE_PARM_DESC(irq, "Interrupt (16)"); | ||
1267 | #else | ||
1268 | module_param(io, int, S_IRUGO); | ||
1269 | MODULE_PARM_DESC(io, "I/O address base (0x3f8 or 0x2f8)"); | ||
1270 | |||
1271 | module_param(irq, int, S_IRUGO); | ||
1272 | MODULE_PARM_DESC(irq, "Interrupt (4 or 3)"); | ||
1273 | |||
1274 | module_param(threshold, int, S_IRUGO); | ||
1275 | MODULE_PARM_DESC(threshold, "space detection threshold (3)"); | ||
1276 | #endif | ||
1277 | |||
1278 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
1279 | MODULE_PARM_DESC(debug, "Enable debugging messages"); | ||
diff --git a/drivers/staging/lirc/lirc_ttusbir.c b/drivers/staging/lirc/lirc_ttusbir.c new file mode 100644 index 00000000000..e4b329b8caf --- /dev/null +++ b/drivers/staging/lirc/lirc_ttusbir.c | |||
@@ -0,0 +1,395 @@ | |||
1 | /* | ||
2 | * lirc_ttusbir.c | ||
3 | * | ||
4 | * lirc_ttusbir - LIRC device driver for the TechnoTrend USB IR Receiver | ||
5 | * | ||
6 | * Copyright (C) 2007 Stefan Macher <st_maker-lirc@yahoo.de> | ||
7 | * | ||
8 | * This LIRC driver provides access to the TechnoTrend USB IR Receiver. | ||
9 | * The receiver delivers the IR signal as raw sampled true/false data in | ||
10 | * isochronous USB packets each of size 128 byte. | ||
11 | * Currently the driver reduces the sampling rate by factor of 8 as this | ||
12 | * is still more than enough to decode RC-5 - others should be analyzed. | ||
13 | * But the driver does not rely on RC-5 it should be able to decode every | ||
14 | * IR signal that is not too fast. | ||
15 | */ | ||
16 | |||
17 | /* | ||
18 | * This program is free software; you can redistribute it and/or modify | ||
19 | * it under the terms of the GNU General Public License as published by | ||
20 | * the Free Software Foundation; either version 2 of the License, or | ||
21 | * (at your option) any later version. | ||
22 | * | ||
23 | * This program is distributed in the hope that it will be useful, | ||
24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
26 | * GNU General Public License for more details. | ||
27 | * | ||
28 | * You should have received a copy of the GNU General Public License | ||
29 | * along with this program; if not, write to the Free Software | ||
30 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
31 | */ | ||
32 | |||
33 | #include <linux/kernel.h> | ||
34 | #include <linux/init.h> | ||
35 | #include <linux/module.h> | ||
36 | #include <linux/errno.h> | ||
37 | #include <linux/slab.h> | ||
38 | #include <linux/usb.h> | ||
39 | |||
40 | #include <media/lirc.h> | ||
41 | #include <media/lirc_dev.h> | ||
42 | |||
43 | MODULE_DESCRIPTION("TechnoTrend USB IR device driver for LIRC"); | ||
44 | MODULE_AUTHOR("Stefan Macher (st_maker-lirc@yahoo.de)"); | ||
45 | MODULE_LICENSE("GPL"); | ||
46 | |||
47 | /* #define DEBUG */ | ||
48 | #ifdef DEBUG | ||
49 | #define DPRINTK printk | ||
50 | #else | ||
51 | #define DPRINTK(_x_, a...) | ||
52 | #endif | ||
53 | |||
54 | /* function declarations */ | ||
55 | static int probe(struct usb_interface *intf, const struct usb_device_id *id); | ||
56 | static void disconnect(struct usb_interface *intf); | ||
57 | static void urb_complete(struct urb *urb); | ||
58 | static int set_use_inc(void *data); | ||
59 | static void set_use_dec(void *data); | ||
60 | |||
61 | static int num_urbs = 2; | ||
62 | module_param(num_urbs, int, S_IRUGO); | ||
63 | MODULE_PARM_DESC(num_urbs, | ||
64 | "Number of URBs in queue. Try to increase to 4 in case " | ||
65 | "of problems (default: 2; minimum: 2)"); | ||
66 | |||
67 | /* table of devices that work with this driver */ | ||
68 | static struct usb_device_id device_id_table[] = { | ||
69 | /* TechnoTrend USB IR Receiver */ | ||
70 | { USB_DEVICE(0x0B48, 0x2003) }, | ||
71 | /* Terminating entry */ | ||
72 | { } | ||
73 | }; | ||
74 | MODULE_DEVICE_TABLE(usb, device_id_table); | ||
75 | |||
76 | /* USB driver definition */ | ||
77 | static struct usb_driver usb_driver = { | ||
78 | .name = "TTUSBIR", | ||
79 | .id_table = &(device_id_table[0]), | ||
80 | .probe = probe, | ||
81 | .disconnect = disconnect, | ||
82 | }; | ||
83 | |||
84 | /* USB device definition */ | ||
85 | struct ttusbir_device { | ||
86 | struct usb_driver *usb_driver; | ||
87 | struct usb_device *udev; | ||
88 | struct usb_interface *interf; | ||
89 | struct usb_class_driver class_driver; | ||
90 | unsigned int ifnum; /* Interface number to use */ | ||
91 | unsigned int alt_setting; /* alternate setting to use */ | ||
92 | unsigned int endpoint; /* Endpoint to use */ | ||
93 | struct urb **urb; /* num_urb URB pointers*/ | ||
94 | char **buffer; /* 128 byte buffer for each URB */ | ||
95 | struct lirc_buffer rbuf; /* Buffer towards LIRC */ | ||
96 | struct lirc_driver driver; | ||
97 | int minor; | ||
98 | int last_pulse; /* remembers if last received byte was pulse or space */ | ||
99 | int last_num; /* remembers how many last bytes appeared */ | ||
100 | int opened; | ||
101 | }; | ||
102 | |||
103 | /*** LIRC specific functions ***/ | ||
104 | static int set_use_inc(void *data) | ||
105 | { | ||
106 | int i, retval; | ||
107 | struct ttusbir_device *ttusbir = data; | ||
108 | |||
109 | DPRINTK("Sending first URBs\n"); | ||
110 | /* @TODO Do I need to check if I am already opened */ | ||
111 | ttusbir->opened = 1; | ||
112 | |||
113 | for (i = 0; i < num_urbs; i++) { | ||
114 | retval = usb_submit_urb(ttusbir->urb[i], GFP_KERNEL); | ||
115 | if (retval) { | ||
116 | err("%s: usb_submit_urb failed on urb %d", | ||
117 | __func__, i); | ||
118 | return retval; | ||
119 | } | ||
120 | } | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static void set_use_dec(void *data) | ||
125 | { | ||
126 | struct ttusbir_device *ttusbir = data; | ||
127 | |||
128 | DPRINTK("Device closed\n"); | ||
129 | |||
130 | ttusbir->opened = 0; | ||
131 | } | ||
132 | |||
133 | /*** USB specific functions ***/ | ||
134 | |||
135 | /* | ||
136 | * This mapping table is used to do a very simple filtering of the | ||
137 | * input signal. | ||
138 | * For a value with at least 4 bits set it returns 0xFF otherwise | ||
139 | * 0x00. For faster IR signals this can not be used. But for RC-5 we | ||
140 | * still have about 14 samples per pulse/space, i.e. we sample with 14 | ||
141 | * times higher frequency than the signal frequency | ||
142 | */ | ||
143 | const unsigned char map_table[] = { | ||
144 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
145 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
146 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
147 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, | ||
148 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
149 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, | ||
150 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, | ||
151 | 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, | ||
152 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
153 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, | ||
154 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, | ||
155 | 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, | ||
156 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, | ||
157 | 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, | ||
158 | 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, | ||
159 | 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
160 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
161 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, | ||
162 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, | ||
163 | 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, | ||
164 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, | ||
165 | 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, | ||
166 | 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, | ||
167 | 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
168 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, | ||
169 | 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, | ||
170 | 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, | ||
171 | 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
172 | 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, | ||
173 | 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
174 | 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
175 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF | ||
176 | }; | ||
177 | |||
178 | static void urb_complete(struct urb *urb) | ||
179 | { | ||
180 | struct ttusbir_device *ttusbir; | ||
181 | unsigned char *buf; | ||
182 | int i; | ||
183 | int l; | ||
184 | |||
185 | ttusbir = urb->context; | ||
186 | |||
187 | if (!ttusbir->opened) | ||
188 | return; | ||
189 | |||
190 | buf = (unsigned char *)urb->transfer_buffer; | ||
191 | |||
192 | for (i = 0; i < 128; i++) { | ||
193 | /* Here we do the filtering and some kind of down sampling */ | ||
194 | buf[i] = ~map_table[buf[i]]; | ||
195 | if (ttusbir->last_pulse == buf[i]) { | ||
196 | if (ttusbir->last_num < PULSE_MASK/63) | ||
197 | ttusbir->last_num++; | ||
198 | /* | ||
199 | * else we are in a idle period and do not need to | ||
200 | * increment any longer | ||
201 | */ | ||
202 | } else { | ||
203 | l = ttusbir->last_num * 62; /* about 62 = us/byte */ | ||
204 | if (ttusbir->last_pulse) /* pulse or space? */ | ||
205 | l |= PULSE_BIT; | ||
206 | if (!lirc_buffer_full(&ttusbir->rbuf)) { | ||
207 | lirc_buffer_write(&ttusbir->rbuf, (void *)&l); | ||
208 | wake_up_interruptible(&ttusbir->rbuf.wait_poll); | ||
209 | } | ||
210 | ttusbir->last_num = 0; | ||
211 | ttusbir->last_pulse = buf[i]; | ||
212 | } | ||
213 | } | ||
214 | usb_submit_urb(urb, GFP_ATOMIC); /* keep data rolling :-) */ | ||
215 | } | ||
216 | |||
217 | /* | ||
218 | * Called whenever the USB subsystem thinks we could be the right driver | ||
219 | * to handle this device | ||
220 | */ | ||
221 | static int probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
222 | { | ||
223 | int alt_set, endp; | ||
224 | int found = 0; | ||
225 | int i, j; | ||
226 | int struct_size; | ||
227 | struct usb_host_interface *host_interf; | ||
228 | struct usb_interface_descriptor *interf_desc; | ||
229 | struct usb_host_endpoint *host_endpoint; | ||
230 | struct ttusbir_device *ttusbir; | ||
231 | |||
232 | DPRINTK("Module ttusbir probe\n"); | ||
233 | |||
234 | /* To reduce memory fragmentation we use only one allocation */ | ||
235 | struct_size = sizeof(struct ttusbir_device) + | ||
236 | (sizeof(struct urb *) * num_urbs) + | ||
237 | (sizeof(char *) * num_urbs) + | ||
238 | (num_urbs * 128); | ||
239 | ttusbir = kzalloc(struct_size, GFP_KERNEL); | ||
240 | if (!ttusbir) | ||
241 | return -ENOMEM; | ||
242 | |||
243 | ttusbir->urb = (struct urb **)((char *)ttusbir + | ||
244 | sizeof(struct ttusbir_device)); | ||
245 | ttusbir->buffer = (char **)((char *)ttusbir->urb + | ||
246 | (sizeof(struct urb *) * num_urbs)); | ||
247 | for (i = 0; i < num_urbs; i++) | ||
248 | ttusbir->buffer[i] = (char *)ttusbir->buffer + | ||
249 | (sizeof(char *)*num_urbs) + (i * 128); | ||
250 | |||
251 | ttusbir->usb_driver = &usb_driver; | ||
252 | ttusbir->alt_setting = -1; | ||
253 | /* @TODO check if error can be returned */ | ||
254 | ttusbir->udev = usb_get_dev(interface_to_usbdev(intf)); | ||
255 | ttusbir->interf = intf; | ||
256 | ttusbir->last_pulse = 0x00; | ||
257 | ttusbir->last_num = 0; | ||
258 | |||
259 | /* | ||
260 | * Now look for interface setting we can handle | ||
261 | * We are searching for the alt setting where end point | ||
262 | * 0x82 has max packet size 16 | ||
263 | */ | ||
264 | for (alt_set = 0; alt_set < intf->num_altsetting && !found; alt_set++) { | ||
265 | host_interf = &intf->altsetting[alt_set]; | ||
266 | interf_desc = &host_interf->desc; | ||
267 | for (endp = 0; endp < interf_desc->bNumEndpoints; endp++) { | ||
268 | host_endpoint = &host_interf->endpoint[endp]; | ||
269 | if ((host_endpoint->desc.bEndpointAddress == 0x82) && | ||
270 | (host_endpoint->desc.wMaxPacketSize == 0x10)) { | ||
271 | ttusbir->alt_setting = alt_set; | ||
272 | ttusbir->endpoint = endp; | ||
273 | found = 1; | ||
274 | break; | ||
275 | } | ||
276 | } | ||
277 | } | ||
278 | if (ttusbir->alt_setting != -1) | ||
279 | DPRINTK("alt setting: %d\n", ttusbir->alt_setting); | ||
280 | else { | ||
281 | err("Could not find alternate setting\n"); | ||
282 | kfree(ttusbir); | ||
283 | return -EINVAL; | ||
284 | } | ||
285 | |||
286 | /* OK lets setup this interface setting */ | ||
287 | usb_set_interface(ttusbir->udev, 0, ttusbir->alt_setting); | ||
288 | |||
289 | /* Store device info in interface structure */ | ||
290 | usb_set_intfdata(intf, ttusbir); | ||
291 | |||
292 | /* Register as a LIRC driver */ | ||
293 | if (lirc_buffer_init(&ttusbir->rbuf, sizeof(int), 256) < 0) { | ||
294 | err("Could not get memory for LIRC data buffer\n"); | ||
295 | usb_set_intfdata(intf, NULL); | ||
296 | kfree(ttusbir); | ||
297 | return -ENOMEM; | ||
298 | } | ||
299 | strcpy(ttusbir->driver.name, "TTUSBIR"); | ||
300 | ttusbir->driver.minor = -1; | ||
301 | ttusbir->driver.code_length = 1; | ||
302 | ttusbir->driver.sample_rate = 0; | ||
303 | ttusbir->driver.data = ttusbir; | ||
304 | ttusbir->driver.add_to_buf = NULL; | ||
305 | ttusbir->driver.rbuf = &ttusbir->rbuf; | ||
306 | ttusbir->driver.set_use_inc = set_use_inc; | ||
307 | ttusbir->driver.set_use_dec = set_use_dec; | ||
308 | ttusbir->driver.dev = &intf->dev; | ||
309 | ttusbir->driver.owner = THIS_MODULE; | ||
310 | ttusbir->driver.features = LIRC_CAN_REC_MODE2; | ||
311 | ttusbir->minor = lirc_register_driver(&ttusbir->driver); | ||
312 | if (ttusbir->minor < 0) { | ||
313 | err("Error registering as LIRC driver\n"); | ||
314 | usb_set_intfdata(intf, NULL); | ||
315 | lirc_buffer_free(&ttusbir->rbuf); | ||
316 | kfree(ttusbir); | ||
317 | return -EIO; | ||
318 | } | ||
319 | |||
320 | /* Allocate and setup the URB that we will use to talk to the device */ | ||
321 | for (i = 0; i < num_urbs; i++) { | ||
322 | ttusbir->urb[i] = usb_alloc_urb(8, GFP_KERNEL); | ||
323 | if (!ttusbir->urb[i]) { | ||
324 | err("Could not allocate memory for the URB\n"); | ||
325 | for (j = i - 1; j >= 0; j--) | ||
326 | kfree(ttusbir->urb[j]); | ||
327 | lirc_buffer_free(&ttusbir->rbuf); | ||
328 | lirc_unregister_driver(ttusbir->minor); | ||
329 | kfree(ttusbir); | ||
330 | usb_set_intfdata(intf, NULL); | ||
331 | return -ENOMEM; | ||
332 | } | ||
333 | ttusbir->urb[i]->dev = ttusbir->udev; | ||
334 | ttusbir->urb[i]->context = ttusbir; | ||
335 | ttusbir->urb[i]->pipe = usb_rcvisocpipe(ttusbir->udev, | ||
336 | ttusbir->endpoint); | ||
337 | ttusbir->urb[i]->interval = 1; | ||
338 | ttusbir->urb[i]->transfer_flags = URB_ISO_ASAP; | ||
339 | ttusbir->urb[i]->transfer_buffer = &ttusbir->buffer[i][0]; | ||
340 | ttusbir->urb[i]->complete = urb_complete; | ||
341 | ttusbir->urb[i]->number_of_packets = 8; | ||
342 | ttusbir->urb[i]->transfer_buffer_length = 128; | ||
343 | for (j = 0; j < 8; j++) { | ||
344 | ttusbir->urb[i]->iso_frame_desc[j].offset = j*16; | ||
345 | ttusbir->urb[i]->iso_frame_desc[j].length = 16; | ||
346 | } | ||
347 | } | ||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | /** | ||
352 | * Called when the driver is unloaded or the device is unplugged | ||
353 | */ | ||
354 | static void disconnect(struct usb_interface *intf) | ||
355 | { | ||
356 | int i; | ||
357 | struct ttusbir_device *ttusbir; | ||
358 | |||
359 | DPRINTK("Module ttusbir disconnect\n"); | ||
360 | |||
361 | ttusbir = (struct ttusbir_device *) usb_get_intfdata(intf); | ||
362 | usb_set_intfdata(intf, NULL); | ||
363 | lirc_unregister_driver(ttusbir->minor); | ||
364 | DPRINTK("unregistered\n"); | ||
365 | |||
366 | for (i = 0; i < num_urbs; i++) { | ||
367 | usb_kill_urb(ttusbir->urb[i]); | ||
368 | usb_free_urb(ttusbir->urb[i]); | ||
369 | } | ||
370 | DPRINTK("URBs killed\n"); | ||
371 | lirc_buffer_free(&ttusbir->rbuf); | ||
372 | kfree(ttusbir); | ||
373 | } | ||
374 | |||
375 | static int ttusbir_init_module(void) | ||
376 | { | ||
377 | int result; | ||
378 | |||
379 | DPRINTK(KERN_DEBUG "Module ttusbir init\n"); | ||
380 | |||
381 | /* register this driver with the USB subsystem */ | ||
382 | result = usb_register(&usb_driver); | ||
383 | if (result) | ||
384 | err("usb_register failed. Error number %d", result); | ||
385 | return result; | ||
386 | } | ||
387 | |||
388 | static void ttusbir_exit_module(void) | ||
389 | { | ||
390 | printk(KERN_DEBUG "Module ttusbir exit\n"); | ||
391 | usb_deregister(&usb_driver); | ||
392 | } | ||
393 | |||
394 | module_init(ttusbir_init_module); | ||
395 | module_exit(ttusbir_exit_module); | ||
diff --git a/drivers/staging/lirc/lirc_zilog.c b/drivers/staging/lirc/lirc_zilog.c new file mode 100644 index 00000000000..0302d82a12f --- /dev/null +++ b/drivers/staging/lirc/lirc_zilog.c | |||
@@ -0,0 +1,1676 @@ | |||
1 | /* | ||
2 | * i2c IR lirc driver for devices with zilog IR processors | ||
3 | * | ||
4 | * Copyright (c) 2000 Gerd Knorr <kraxel@goldbach.in-berlin.de> | ||
5 | * modified for PixelView (BT878P+W/FM) by | ||
6 | * Michal Kochanowicz <mkochano@pld.org.pl> | ||
7 | * Christoph Bartelmus <lirc@bartelmus.de> | ||
8 | * modified for KNC ONE TV Station/Anubis Typhoon TView Tuner by | ||
9 | * Ulrich Mueller <ulrich.mueller42@web.de> | ||
10 | * modified for Asus TV-Box and Creative/VisionTek BreakOut-Box by | ||
11 | * Stefan Jahn <stefan@lkcc.org> | ||
12 | * modified for inclusion into kernel sources by | ||
13 | * Jerome Brock <jbrock@users.sourceforge.net> | ||
14 | * modified for Leadtek Winfast PVR2000 by | ||
15 | * Thomas Reitmayr (treitmayr@yahoo.com) | ||
16 | * modified for Hauppauge PVR-150 IR TX device by | ||
17 | * Mark Weaver <mark@npsl.co.uk> | ||
18 | * changed name from lirc_pvr150 to lirc_zilog, works on more than pvr-150 | ||
19 | * Jarod Wilson <jarod@redhat.com> | ||
20 | * | ||
21 | * parts are cut&pasted from the lirc_i2c.c driver | ||
22 | * | ||
23 | * Numerous changes updating lirc_zilog.c in kernel 2.6.38 and later are | ||
24 | * Copyright (C) 2011 Andy Walls <awalls@md.metrocast.net> | ||
25 | * | ||
26 | * This program is free software; you can redistribute it and/or modify | ||
27 | * it under the terms of the GNU General Public License as published by | ||
28 | * the Free Software Foundation; either version 2 of the License, or | ||
29 | * (at your option) any later version. | ||
30 | * | ||
31 | * This program is distributed in the hope that it will be useful, | ||
32 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
33 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
34 | * GNU General Public License for more details. | ||
35 | * | ||
36 | * You should have received a copy of the GNU General Public License | ||
37 | * along with this program; if not, write to the Free Software | ||
38 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
39 | * | ||
40 | */ | ||
41 | |||
42 | #include <linux/module.h> | ||
43 | #include <linux/kmod.h> | ||
44 | #include <linux/kernel.h> | ||
45 | #include <linux/sched.h> | ||
46 | #include <linux/fs.h> | ||
47 | #include <linux/poll.h> | ||
48 | #include <linux/string.h> | ||
49 | #include <linux/timer.h> | ||
50 | #include <linux/delay.h> | ||
51 | #include <linux/completion.h> | ||
52 | #include <linux/errno.h> | ||
53 | #include <linux/slab.h> | ||
54 | #include <linux/i2c.h> | ||
55 | #include <linux/firmware.h> | ||
56 | #include <linux/vmalloc.h> | ||
57 | |||
58 | #include <linux/mutex.h> | ||
59 | #include <linux/kthread.h> | ||
60 | |||
61 | #include <media/lirc_dev.h> | ||
62 | #include <media/lirc.h> | ||
63 | |||
64 | struct IR; | ||
65 | |||
66 | struct IR_rx { | ||
67 | struct kref ref; | ||
68 | struct IR *ir; | ||
69 | |||
70 | /* RX device */ | ||
71 | struct mutex client_lock; | ||
72 | struct i2c_client *c; | ||
73 | |||
74 | /* RX polling thread data */ | ||
75 | struct task_struct *task; | ||
76 | |||
77 | /* RX read data */ | ||
78 | unsigned char b[3]; | ||
79 | bool hdpvr_data_fmt; | ||
80 | }; | ||
81 | |||
82 | struct IR_tx { | ||
83 | struct kref ref; | ||
84 | struct IR *ir; | ||
85 | |||
86 | /* TX device */ | ||
87 | struct mutex client_lock; | ||
88 | struct i2c_client *c; | ||
89 | |||
90 | /* TX additional actions needed */ | ||
91 | int need_boot; | ||
92 | bool post_tx_ready_poll; | ||
93 | }; | ||
94 | |||
95 | struct IR { | ||
96 | struct kref ref; | ||
97 | struct list_head list; | ||
98 | |||
99 | /* FIXME spinlock access to l.features */ | ||
100 | struct lirc_driver l; | ||
101 | struct lirc_buffer rbuf; | ||
102 | |||
103 | struct mutex ir_lock; | ||
104 | atomic_t open_count; | ||
105 | |||
106 | struct i2c_adapter *adapter; | ||
107 | |||
108 | spinlock_t rx_ref_lock; /* struct IR_rx kref get()/put() */ | ||
109 | struct IR_rx *rx; | ||
110 | |||
111 | spinlock_t tx_ref_lock; /* struct IR_tx kref get()/put() */ | ||
112 | struct IR_tx *tx; | ||
113 | }; | ||
114 | |||
115 | /* IR transceiver instance object list */ | ||
116 | /* | ||
117 | * This lock is used for the following: | ||
118 | * a. ir_devices_list access, insertions, deletions | ||
119 | * b. struct IR kref get()s and put()s | ||
120 | * c. serialization of ir_probe() for the two i2c_clients for a Z8 | ||
121 | */ | ||
122 | static DEFINE_MUTEX(ir_devices_lock); | ||
123 | static LIST_HEAD(ir_devices_list); | ||
124 | |||
125 | /* Block size for IR transmitter */ | ||
126 | #define TX_BLOCK_SIZE 99 | ||
127 | |||
128 | /* Hauppauge IR transmitter data */ | ||
129 | struct tx_data_struct { | ||
130 | /* Boot block */ | ||
131 | unsigned char *boot_data; | ||
132 | |||
133 | /* Start of binary data block */ | ||
134 | unsigned char *datap; | ||
135 | |||
136 | /* End of binary data block */ | ||
137 | unsigned char *endp; | ||
138 | |||
139 | /* Number of installed codesets */ | ||
140 | unsigned int num_code_sets; | ||
141 | |||
142 | /* Pointers to codesets */ | ||
143 | unsigned char **code_sets; | ||
144 | |||
145 | /* Global fixed data template */ | ||
146 | int fixed[TX_BLOCK_SIZE]; | ||
147 | }; | ||
148 | |||
149 | static struct tx_data_struct *tx_data; | ||
150 | static struct mutex tx_data_lock; | ||
151 | |||
152 | #define zilog_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, \ | ||
153 | ## args) | ||
154 | #define zilog_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args) | ||
155 | #define zilog_info(s, args...) printk(KERN_INFO KBUILD_MODNAME ": " s, ## args) | ||
156 | |||
157 | /* module parameters */ | ||
158 | static int debug; /* debug output */ | ||
159 | static int tx_only; /* only handle the IR Tx function */ | ||
160 | static int minor = -1; /* minor number */ | ||
161 | |||
162 | #define dprintk(fmt, args...) \ | ||
163 | do { \ | ||
164 | if (debug) \ | ||
165 | printk(KERN_DEBUG KBUILD_MODNAME ": " fmt, \ | ||
166 | ## args); \ | ||
167 | } while (0) | ||
168 | |||
169 | |||
170 | /* struct IR reference counting */ | ||
171 | static struct IR *get_ir_device(struct IR *ir, bool ir_devices_lock_held) | ||
172 | { | ||
173 | if (ir_devices_lock_held) { | ||
174 | kref_get(&ir->ref); | ||
175 | } else { | ||
176 | mutex_lock(&ir_devices_lock); | ||
177 | kref_get(&ir->ref); | ||
178 | mutex_unlock(&ir_devices_lock); | ||
179 | } | ||
180 | return ir; | ||
181 | } | ||
182 | |||
183 | static void release_ir_device(struct kref *ref) | ||
184 | { | ||
185 | struct IR *ir = container_of(ref, struct IR, ref); | ||
186 | |||
187 | /* | ||
188 | * Things should be in this state by now: | ||
189 | * ir->rx set to NULL and deallocated - happens before ir->rx->ir put() | ||
190 | * ir->rx->task kthread stopped - happens before ir->rx->ir put() | ||
191 | * ir->tx set to NULL and deallocated - happens before ir->tx->ir put() | ||
192 | * ir->open_count == 0 - happens on final close() | ||
193 | * ir_lock, tx_ref_lock, rx_ref_lock, all released | ||
194 | */ | ||
195 | if (ir->l.minor >= 0 && ir->l.minor < MAX_IRCTL_DEVICES) { | ||
196 | lirc_unregister_driver(ir->l.minor); | ||
197 | ir->l.minor = MAX_IRCTL_DEVICES; | ||
198 | } | ||
199 | if (ir->rbuf.fifo_initialized) | ||
200 | lirc_buffer_free(&ir->rbuf); | ||
201 | list_del(&ir->list); | ||
202 | kfree(ir); | ||
203 | } | ||
204 | |||
205 | static int put_ir_device(struct IR *ir, bool ir_devices_lock_held) | ||
206 | { | ||
207 | int released; | ||
208 | |||
209 | if (ir_devices_lock_held) | ||
210 | return kref_put(&ir->ref, release_ir_device); | ||
211 | |||
212 | mutex_lock(&ir_devices_lock); | ||
213 | released = kref_put(&ir->ref, release_ir_device); | ||
214 | mutex_unlock(&ir_devices_lock); | ||
215 | |||
216 | return released; | ||
217 | } | ||
218 | |||
219 | /* struct IR_rx reference counting */ | ||
220 | static struct IR_rx *get_ir_rx(struct IR *ir) | ||
221 | { | ||
222 | struct IR_rx *rx; | ||
223 | |||
224 | spin_lock(&ir->rx_ref_lock); | ||
225 | rx = ir->rx; | ||
226 | if (rx != NULL) | ||
227 | kref_get(&rx->ref); | ||
228 | spin_unlock(&ir->rx_ref_lock); | ||
229 | return rx; | ||
230 | } | ||
231 | |||
232 | static void destroy_rx_kthread(struct IR_rx *rx, bool ir_devices_lock_held) | ||
233 | { | ||
234 | /* end up polling thread */ | ||
235 | if (!IS_ERR_OR_NULL(rx->task)) { | ||
236 | kthread_stop(rx->task); | ||
237 | rx->task = NULL; | ||
238 | /* Put the ir ptr that ir_probe() gave to the rx poll thread */ | ||
239 | put_ir_device(rx->ir, ir_devices_lock_held); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | static void release_ir_rx(struct kref *ref) | ||
244 | { | ||
245 | struct IR_rx *rx = container_of(ref, struct IR_rx, ref); | ||
246 | struct IR *ir = rx->ir; | ||
247 | |||
248 | /* | ||
249 | * This release function can't do all the work, as we want | ||
250 | * to keep the rx_ref_lock a spinlock, and killing the poll thread | ||
251 | * and releasing the ir reference can cause a sleep. That work is | ||
252 | * performed by put_ir_rx() | ||
253 | */ | ||
254 | ir->l.features &= ~LIRC_CAN_REC_LIRCCODE; | ||
255 | /* Don't put_ir_device(rx->ir) here; lock can't be freed yet */ | ||
256 | ir->rx = NULL; | ||
257 | /* Don't do the kfree(rx) here; we still need to kill the poll thread */ | ||
258 | return; | ||
259 | } | ||
260 | |||
261 | static int put_ir_rx(struct IR_rx *rx, bool ir_devices_lock_held) | ||
262 | { | ||
263 | int released; | ||
264 | struct IR *ir = rx->ir; | ||
265 | |||
266 | spin_lock(&ir->rx_ref_lock); | ||
267 | released = kref_put(&rx->ref, release_ir_rx); | ||
268 | spin_unlock(&ir->rx_ref_lock); | ||
269 | /* Destroy the rx kthread while not holding the spinlock */ | ||
270 | if (released) { | ||
271 | destroy_rx_kthread(rx, ir_devices_lock_held); | ||
272 | kfree(rx); | ||
273 | /* Make sure we're not still in a poll_table somewhere */ | ||
274 | wake_up_interruptible(&ir->rbuf.wait_poll); | ||
275 | } | ||
276 | /* Do a reference put() for the rx->ir reference, if we released rx */ | ||
277 | if (released) | ||
278 | put_ir_device(ir, ir_devices_lock_held); | ||
279 | return released; | ||
280 | } | ||
281 | |||
282 | /* struct IR_tx reference counting */ | ||
283 | static struct IR_tx *get_ir_tx(struct IR *ir) | ||
284 | { | ||
285 | struct IR_tx *tx; | ||
286 | |||
287 | spin_lock(&ir->tx_ref_lock); | ||
288 | tx = ir->tx; | ||
289 | if (tx != NULL) | ||
290 | kref_get(&tx->ref); | ||
291 | spin_unlock(&ir->tx_ref_lock); | ||
292 | return tx; | ||
293 | } | ||
294 | |||
295 | static void release_ir_tx(struct kref *ref) | ||
296 | { | ||
297 | struct IR_tx *tx = container_of(ref, struct IR_tx, ref); | ||
298 | struct IR *ir = tx->ir; | ||
299 | |||
300 | ir->l.features &= ~LIRC_CAN_SEND_PULSE; | ||
301 | /* Don't put_ir_device(tx->ir) here, so our lock doesn't get freed */ | ||
302 | ir->tx = NULL; | ||
303 | kfree(tx); | ||
304 | } | ||
305 | |||
306 | static int put_ir_tx(struct IR_tx *tx, bool ir_devices_lock_held) | ||
307 | { | ||
308 | int released; | ||
309 | struct IR *ir = tx->ir; | ||
310 | |||
311 | spin_lock(&ir->tx_ref_lock); | ||
312 | released = kref_put(&tx->ref, release_ir_tx); | ||
313 | spin_unlock(&ir->tx_ref_lock); | ||
314 | /* Do a reference put() for the tx->ir reference, if we released tx */ | ||
315 | if (released) | ||
316 | put_ir_device(ir, ir_devices_lock_held); | ||
317 | return released; | ||
318 | } | ||
319 | |||
320 | static int add_to_buf(struct IR *ir) | ||
321 | { | ||
322 | __u16 code; | ||
323 | unsigned char codes[2]; | ||
324 | unsigned char keybuf[6]; | ||
325 | int got_data = 0; | ||
326 | int ret; | ||
327 | int failures = 0; | ||
328 | unsigned char sendbuf[1] = { 0 }; | ||
329 | struct lirc_buffer *rbuf = ir->l.rbuf; | ||
330 | struct IR_rx *rx; | ||
331 | struct IR_tx *tx; | ||
332 | |||
333 | if (lirc_buffer_full(rbuf)) { | ||
334 | dprintk("buffer overflow\n"); | ||
335 | return -EOVERFLOW; | ||
336 | } | ||
337 | |||
338 | rx = get_ir_rx(ir); | ||
339 | if (rx == NULL) | ||
340 | return -ENXIO; | ||
341 | |||
342 | /* Ensure our rx->c i2c_client remains valid for the duration */ | ||
343 | mutex_lock(&rx->client_lock); | ||
344 | if (rx->c == NULL) { | ||
345 | mutex_unlock(&rx->client_lock); | ||
346 | put_ir_rx(rx, false); | ||
347 | return -ENXIO; | ||
348 | } | ||
349 | |||
350 | tx = get_ir_tx(ir); | ||
351 | |||
352 | /* | ||
353 | * service the device as long as it is returning | ||
354 | * data and we have space | ||
355 | */ | ||
356 | do { | ||
357 | if (kthread_should_stop()) { | ||
358 | ret = -ENODATA; | ||
359 | break; | ||
360 | } | ||
361 | |||
362 | /* | ||
363 | * Lock i2c bus for the duration. RX/TX chips interfere so | ||
364 | * this is worth it | ||
365 | */ | ||
366 | mutex_lock(&ir->ir_lock); | ||
367 | |||
368 | if (kthread_should_stop()) { | ||
369 | mutex_unlock(&ir->ir_lock); | ||
370 | ret = -ENODATA; | ||
371 | break; | ||
372 | } | ||
373 | |||
374 | /* | ||
375 | * Send random "poll command" (?) Windows driver does this | ||
376 | * and it is a good point to detect chip failure. | ||
377 | */ | ||
378 | ret = i2c_master_send(rx->c, sendbuf, 1); | ||
379 | if (ret != 1) { | ||
380 | zilog_error("i2c_master_send failed with %d\n", ret); | ||
381 | if (failures >= 3) { | ||
382 | mutex_unlock(&ir->ir_lock); | ||
383 | zilog_error("unable to read from the IR chip " | ||
384 | "after 3 resets, giving up\n"); | ||
385 | break; | ||
386 | } | ||
387 | |||
388 | /* Looks like the chip crashed, reset it */ | ||
389 | zilog_error("polling the IR receiver chip failed, " | ||
390 | "trying reset\n"); | ||
391 | |||
392 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
393 | if (kthread_should_stop()) { | ||
394 | mutex_unlock(&ir->ir_lock); | ||
395 | ret = -ENODATA; | ||
396 | break; | ||
397 | } | ||
398 | schedule_timeout((100 * HZ + 999) / 1000); | ||
399 | if (tx != NULL) | ||
400 | tx->need_boot = 1; | ||
401 | |||
402 | ++failures; | ||
403 | mutex_unlock(&ir->ir_lock); | ||
404 | ret = 0; | ||
405 | continue; | ||
406 | } | ||
407 | |||
408 | if (kthread_should_stop()) { | ||
409 | mutex_unlock(&ir->ir_lock); | ||
410 | ret = -ENODATA; | ||
411 | break; | ||
412 | } | ||
413 | ret = i2c_master_recv(rx->c, keybuf, sizeof(keybuf)); | ||
414 | mutex_unlock(&ir->ir_lock); | ||
415 | if (ret != sizeof(keybuf)) { | ||
416 | zilog_error("i2c_master_recv failed with %d -- " | ||
417 | "keeping last read buffer\n", ret); | ||
418 | } else { | ||
419 | rx->b[0] = keybuf[3]; | ||
420 | rx->b[1] = keybuf[4]; | ||
421 | rx->b[2] = keybuf[5]; | ||
422 | dprintk("key (0x%02x/0x%02x)\n", rx->b[0], rx->b[1]); | ||
423 | } | ||
424 | |||
425 | /* key pressed ? */ | ||
426 | if (rx->hdpvr_data_fmt) { | ||
427 | if (got_data && (keybuf[0] == 0x80)) { | ||
428 | ret = 0; | ||
429 | break; | ||
430 | } else if (got_data && (keybuf[0] == 0x00)) { | ||
431 | ret = -ENODATA; | ||
432 | break; | ||
433 | } | ||
434 | } else if ((rx->b[0] & 0x80) == 0) { | ||
435 | ret = got_data ? 0 : -ENODATA; | ||
436 | break; | ||
437 | } | ||
438 | |||
439 | /* look what we have */ | ||
440 | code = (((__u16)rx->b[0] & 0x7f) << 6) | (rx->b[1] >> 2); | ||
441 | |||
442 | codes[0] = (code >> 8) & 0xff; | ||
443 | codes[1] = code & 0xff; | ||
444 | |||
445 | /* return it */ | ||
446 | lirc_buffer_write(rbuf, codes); | ||
447 | ++got_data; | ||
448 | ret = 0; | ||
449 | } while (!lirc_buffer_full(rbuf)); | ||
450 | |||
451 | mutex_unlock(&rx->client_lock); | ||
452 | if (tx != NULL) | ||
453 | put_ir_tx(tx, false); | ||
454 | put_ir_rx(rx, false); | ||
455 | return ret; | ||
456 | } | ||
457 | |||
458 | /* | ||
459 | * Main function of the polling thread -- from lirc_dev. | ||
460 | * We don't fit the LIRC model at all anymore. This is horrible, but | ||
461 | * basically we have a single RX/TX device with a nasty failure mode | ||
462 | * that needs to be accounted for across the pair. lirc lets us provide | ||
463 | * fops, but prevents us from using the internal polling, etc. if we do | ||
464 | * so. Hence the replication. Might be neater to extend the LIRC model | ||
465 | * to account for this but I'd think it's a very special case of seriously | ||
466 | * messed up hardware. | ||
467 | */ | ||
468 | static int lirc_thread(void *arg) | ||
469 | { | ||
470 | struct IR *ir = arg; | ||
471 | struct lirc_buffer *rbuf = ir->l.rbuf; | ||
472 | |||
473 | dprintk("poll thread started\n"); | ||
474 | |||
475 | while (!kthread_should_stop()) { | ||
476 | set_current_state(TASK_INTERRUPTIBLE); | ||
477 | |||
478 | /* if device not opened, we can sleep half a second */ | ||
479 | if (atomic_read(&ir->open_count) == 0) { | ||
480 | schedule_timeout(HZ/2); | ||
481 | continue; | ||
482 | } | ||
483 | |||
484 | /* | ||
485 | * This is ~113*2 + 24 + jitter (2*repeat gap + code length). | ||
486 | * We use this interval as the chip resets every time you poll | ||
487 | * it (bad!). This is therefore just sufficient to catch all | ||
488 | * of the button presses. It makes the remote much more | ||
489 | * responsive. You can see the difference by running irw and | ||
490 | * holding down a button. With 100ms, the old polling | ||
491 | * interval, you'll notice breaks in the repeat sequence | ||
492 | * corresponding to lost keypresses. | ||
493 | */ | ||
494 | schedule_timeout((260 * HZ) / 1000); | ||
495 | if (kthread_should_stop()) | ||
496 | break; | ||
497 | if (!add_to_buf(ir)) | ||
498 | wake_up_interruptible(&rbuf->wait_poll); | ||
499 | } | ||
500 | |||
501 | dprintk("poll thread ended\n"); | ||
502 | return 0; | ||
503 | } | ||
504 | |||
505 | static int set_use_inc(void *data) | ||
506 | { | ||
507 | return 0; | ||
508 | } | ||
509 | |||
510 | static void set_use_dec(void *data) | ||
511 | { | ||
512 | return; | ||
513 | } | ||
514 | |||
515 | /* safe read of a uint32 (always network byte order) */ | ||
516 | static int read_uint32(unsigned char **data, | ||
517 | unsigned char *endp, unsigned int *val) | ||
518 | { | ||
519 | if (*data + 4 > endp) | ||
520 | return 0; | ||
521 | *val = ((*data)[0] << 24) | ((*data)[1] << 16) | | ||
522 | ((*data)[2] << 8) | (*data)[3]; | ||
523 | *data += 4; | ||
524 | return 1; | ||
525 | } | ||
526 | |||
527 | /* safe read of a uint8 */ | ||
528 | static int read_uint8(unsigned char **data, | ||
529 | unsigned char *endp, unsigned char *val) | ||
530 | { | ||
531 | if (*data + 1 > endp) | ||
532 | return 0; | ||
533 | *val = *((*data)++); | ||
534 | return 1; | ||
535 | } | ||
536 | |||
537 | /* safe skipping of N bytes */ | ||
538 | static int skip(unsigned char **data, | ||
539 | unsigned char *endp, unsigned int distance) | ||
540 | { | ||
541 | if (*data + distance > endp) | ||
542 | return 0; | ||
543 | *data += distance; | ||
544 | return 1; | ||
545 | } | ||
546 | |||
547 | /* decompress key data into the given buffer */ | ||
548 | static int get_key_data(unsigned char *buf, | ||
549 | unsigned int codeset, unsigned int key) | ||
550 | { | ||
551 | unsigned char *data, *endp, *diffs, *key_block; | ||
552 | unsigned char keys, ndiffs, id; | ||
553 | unsigned int base, lim, pos, i; | ||
554 | |||
555 | /* Binary search for the codeset */ | ||
556 | for (base = 0, lim = tx_data->num_code_sets; lim; lim >>= 1) { | ||
557 | pos = base + (lim >> 1); | ||
558 | data = tx_data->code_sets[pos]; | ||
559 | |||
560 | if (!read_uint32(&data, tx_data->endp, &i)) | ||
561 | goto corrupt; | ||
562 | |||
563 | if (i == codeset) | ||
564 | break; | ||
565 | else if (codeset > i) { | ||
566 | base = pos + 1; | ||
567 | --lim; | ||
568 | } | ||
569 | } | ||
570 | /* Not found? */ | ||
571 | if (!lim) | ||
572 | return -EPROTO; | ||
573 | |||
574 | /* Set end of data block */ | ||
575 | endp = pos < tx_data->num_code_sets - 1 ? | ||
576 | tx_data->code_sets[pos + 1] : tx_data->endp; | ||
577 | |||
578 | /* Read the block header */ | ||
579 | if (!read_uint8(&data, endp, &keys) || | ||
580 | !read_uint8(&data, endp, &ndiffs) || | ||
581 | ndiffs > TX_BLOCK_SIZE || keys == 0) | ||
582 | goto corrupt; | ||
583 | |||
584 | /* Save diffs & skip */ | ||
585 | diffs = data; | ||
586 | if (!skip(&data, endp, ndiffs)) | ||
587 | goto corrupt; | ||
588 | |||
589 | /* Read the id of the first key */ | ||
590 | if (!read_uint8(&data, endp, &id)) | ||
591 | goto corrupt; | ||
592 | |||
593 | /* Unpack the first key's data */ | ||
594 | for (i = 0; i < TX_BLOCK_SIZE; ++i) { | ||
595 | if (tx_data->fixed[i] == -1) { | ||
596 | if (!read_uint8(&data, endp, &buf[i])) | ||
597 | goto corrupt; | ||
598 | } else { | ||
599 | buf[i] = (unsigned char)tx_data->fixed[i]; | ||
600 | } | ||
601 | } | ||
602 | |||
603 | /* Early out key found/not found */ | ||
604 | if (key == id) | ||
605 | return 0; | ||
606 | if (keys == 1) | ||
607 | return -EPROTO; | ||
608 | |||
609 | /* Sanity check */ | ||
610 | key_block = data; | ||
611 | if (!skip(&data, endp, (keys - 1) * (ndiffs + 1))) | ||
612 | goto corrupt; | ||
613 | |||
614 | /* Binary search for the key */ | ||
615 | for (base = 0, lim = keys - 1; lim; lim >>= 1) { | ||
616 | /* Seek to block */ | ||
617 | unsigned char *key_data; | ||
618 | pos = base + (lim >> 1); | ||
619 | key_data = key_block + (ndiffs + 1) * pos; | ||
620 | |||
621 | if (*key_data == key) { | ||
622 | /* skip key id */ | ||
623 | ++key_data; | ||
624 | |||
625 | /* found, so unpack the diffs */ | ||
626 | for (i = 0; i < ndiffs; ++i) { | ||
627 | unsigned char val; | ||
628 | if (!read_uint8(&key_data, endp, &val) || | ||
629 | diffs[i] >= TX_BLOCK_SIZE) | ||
630 | goto corrupt; | ||
631 | buf[diffs[i]] = val; | ||
632 | } | ||
633 | |||
634 | return 0; | ||
635 | } else if (key > *key_data) { | ||
636 | base = pos + 1; | ||
637 | --lim; | ||
638 | } | ||
639 | } | ||
640 | /* Key not found */ | ||
641 | return -EPROTO; | ||
642 | |||
643 | corrupt: | ||
644 | zilog_error("firmware is corrupt\n"); | ||
645 | return -EFAULT; | ||
646 | } | ||
647 | |||
648 | /* send a block of data to the IR TX device */ | ||
649 | static int send_data_block(struct IR_tx *tx, unsigned char *data_block) | ||
650 | { | ||
651 | int i, j, ret; | ||
652 | unsigned char buf[5]; | ||
653 | |||
654 | for (i = 0; i < TX_BLOCK_SIZE;) { | ||
655 | int tosend = TX_BLOCK_SIZE - i; | ||
656 | if (tosend > 4) | ||
657 | tosend = 4; | ||
658 | buf[0] = (unsigned char)(i + 1); | ||
659 | for (j = 0; j < tosend; ++j) | ||
660 | buf[1 + j] = data_block[i + j]; | ||
661 | dprintk("%02x %02x %02x %02x %02x", | ||
662 | buf[0], buf[1], buf[2], buf[3], buf[4]); | ||
663 | ret = i2c_master_send(tx->c, buf, tosend + 1); | ||
664 | if (ret != tosend + 1) { | ||
665 | zilog_error("i2c_master_send failed with %d\n", ret); | ||
666 | return ret < 0 ? ret : -EFAULT; | ||
667 | } | ||
668 | i += tosend; | ||
669 | } | ||
670 | return 0; | ||
671 | } | ||
672 | |||
673 | /* send boot data to the IR TX device */ | ||
674 | static int send_boot_data(struct IR_tx *tx) | ||
675 | { | ||
676 | int ret, i; | ||
677 | unsigned char buf[4]; | ||
678 | |||
679 | /* send the boot block */ | ||
680 | ret = send_data_block(tx, tx_data->boot_data); | ||
681 | if (ret != 0) | ||
682 | return ret; | ||
683 | |||
684 | /* Hit the go button to activate the new boot data */ | ||
685 | buf[0] = 0x00; | ||
686 | buf[1] = 0x20; | ||
687 | ret = i2c_master_send(tx->c, buf, 2); | ||
688 | if (ret != 2) { | ||
689 | zilog_error("i2c_master_send failed with %d\n", ret); | ||
690 | return ret < 0 ? ret : -EFAULT; | ||
691 | } | ||
692 | |||
693 | /* | ||
694 | * Wait for zilog to settle after hitting go post boot block upload. | ||
695 | * Without this delay, the HD-PVR and HVR-1950 both return an -EIO | ||
696 | * upon attempting to get firmware revision, and tx probe thus fails. | ||
697 | */ | ||
698 | for (i = 0; i < 10; i++) { | ||
699 | ret = i2c_master_send(tx->c, buf, 1); | ||
700 | if (ret == 1) | ||
701 | break; | ||
702 | udelay(100); | ||
703 | } | ||
704 | |||
705 | if (ret != 1) { | ||
706 | zilog_error("i2c_master_send failed with %d\n", ret); | ||
707 | return ret < 0 ? ret : -EFAULT; | ||
708 | } | ||
709 | |||
710 | /* Here comes the firmware version... (hopefully) */ | ||
711 | ret = i2c_master_recv(tx->c, buf, 4); | ||
712 | if (ret != 4) { | ||
713 | zilog_error("i2c_master_recv failed with %d\n", ret); | ||
714 | return 0; | ||
715 | } | ||
716 | if ((buf[0] != 0x80) && (buf[0] != 0xa0)) { | ||
717 | zilog_error("unexpected IR TX init response: %02x\n", buf[0]); | ||
718 | return 0; | ||
719 | } | ||
720 | zilog_notify("Zilog/Hauppauge IR blaster firmware version " | ||
721 | "%d.%d.%d loaded\n", buf[1], buf[2], buf[3]); | ||
722 | |||
723 | return 0; | ||
724 | } | ||
725 | |||
726 | /* unload "firmware", lock held */ | ||
727 | static void fw_unload_locked(void) | ||
728 | { | ||
729 | if (tx_data) { | ||
730 | if (tx_data->code_sets) | ||
731 | vfree(tx_data->code_sets); | ||
732 | |||
733 | if (tx_data->datap) | ||
734 | vfree(tx_data->datap); | ||
735 | |||
736 | vfree(tx_data); | ||
737 | tx_data = NULL; | ||
738 | dprintk("successfully unloaded IR blaster firmware\n"); | ||
739 | } | ||
740 | } | ||
741 | |||
742 | /* unload "firmware" for the IR TX device */ | ||
743 | static void fw_unload(void) | ||
744 | { | ||
745 | mutex_lock(&tx_data_lock); | ||
746 | fw_unload_locked(); | ||
747 | mutex_unlock(&tx_data_lock); | ||
748 | } | ||
749 | |||
750 | /* load "firmware" for the IR TX device */ | ||
751 | static int fw_load(struct IR_tx *tx) | ||
752 | { | ||
753 | int ret; | ||
754 | unsigned int i; | ||
755 | unsigned char *data, version, num_global_fixed; | ||
756 | const struct firmware *fw_entry; | ||
757 | |||
758 | /* Already loaded? */ | ||
759 | mutex_lock(&tx_data_lock); | ||
760 | if (tx_data) { | ||
761 | ret = 0; | ||
762 | goto out; | ||
763 | } | ||
764 | |||
765 | /* Request codeset data file */ | ||
766 | ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", tx->ir->l.dev); | ||
767 | if (ret != 0) { | ||
768 | zilog_error("firmware haup-ir-blaster.bin not available " | ||
769 | "(%d)\n", ret); | ||
770 | ret = ret < 0 ? ret : -EFAULT; | ||
771 | goto out; | ||
772 | } | ||
773 | dprintk("firmware of size %zu loaded\n", fw_entry->size); | ||
774 | |||
775 | /* Parse the file */ | ||
776 | tx_data = vmalloc(sizeof(*tx_data)); | ||
777 | if (tx_data == NULL) { | ||
778 | zilog_error("out of memory\n"); | ||
779 | release_firmware(fw_entry); | ||
780 | ret = -ENOMEM; | ||
781 | goto out; | ||
782 | } | ||
783 | tx_data->code_sets = NULL; | ||
784 | |||
785 | /* Copy the data so hotplug doesn't get confused and timeout */ | ||
786 | tx_data->datap = vmalloc(fw_entry->size); | ||
787 | if (tx_data->datap == NULL) { | ||
788 | zilog_error("out of memory\n"); | ||
789 | release_firmware(fw_entry); | ||
790 | vfree(tx_data); | ||
791 | ret = -ENOMEM; | ||
792 | goto out; | ||
793 | } | ||
794 | memcpy(tx_data->datap, fw_entry->data, fw_entry->size); | ||
795 | tx_data->endp = tx_data->datap + fw_entry->size; | ||
796 | release_firmware(fw_entry); fw_entry = NULL; | ||
797 | |||
798 | /* Check version */ | ||
799 | data = tx_data->datap; | ||
800 | if (!read_uint8(&data, tx_data->endp, &version)) | ||
801 | goto corrupt; | ||
802 | if (version != 1) { | ||
803 | zilog_error("unsupported code set file version (%u, expected" | ||
804 | "1) -- please upgrade to a newer driver", | ||
805 | version); | ||
806 | fw_unload_locked(); | ||
807 | ret = -EFAULT; | ||
808 | goto out; | ||
809 | } | ||
810 | |||
811 | /* Save boot block for later */ | ||
812 | tx_data->boot_data = data; | ||
813 | if (!skip(&data, tx_data->endp, TX_BLOCK_SIZE)) | ||
814 | goto corrupt; | ||
815 | |||
816 | if (!read_uint32(&data, tx_data->endp, | ||
817 | &tx_data->num_code_sets)) | ||
818 | goto corrupt; | ||
819 | |||
820 | dprintk("%u IR blaster codesets loaded\n", tx_data->num_code_sets); | ||
821 | |||
822 | tx_data->code_sets = vmalloc( | ||
823 | tx_data->num_code_sets * sizeof(char *)); | ||
824 | if (tx_data->code_sets == NULL) { | ||
825 | fw_unload_locked(); | ||
826 | ret = -ENOMEM; | ||
827 | goto out; | ||
828 | } | ||
829 | |||
830 | for (i = 0; i < TX_BLOCK_SIZE; ++i) | ||
831 | tx_data->fixed[i] = -1; | ||
832 | |||
833 | /* Read global fixed data template */ | ||
834 | if (!read_uint8(&data, tx_data->endp, &num_global_fixed) || | ||
835 | num_global_fixed > TX_BLOCK_SIZE) | ||
836 | goto corrupt; | ||
837 | for (i = 0; i < num_global_fixed; ++i) { | ||
838 | unsigned char pos, val; | ||
839 | if (!read_uint8(&data, tx_data->endp, &pos) || | ||
840 | !read_uint8(&data, tx_data->endp, &val) || | ||
841 | pos >= TX_BLOCK_SIZE) | ||
842 | goto corrupt; | ||
843 | tx_data->fixed[pos] = (int)val; | ||
844 | } | ||
845 | |||
846 | /* Filch out the position of each code set */ | ||
847 | for (i = 0; i < tx_data->num_code_sets; ++i) { | ||
848 | unsigned int id; | ||
849 | unsigned char keys; | ||
850 | unsigned char ndiffs; | ||
851 | |||
852 | /* Save the codeset position */ | ||
853 | tx_data->code_sets[i] = data; | ||
854 | |||
855 | /* Read header */ | ||
856 | if (!read_uint32(&data, tx_data->endp, &id) || | ||
857 | !read_uint8(&data, tx_data->endp, &keys) || | ||
858 | !read_uint8(&data, tx_data->endp, &ndiffs) || | ||
859 | ndiffs > TX_BLOCK_SIZE || keys == 0) | ||
860 | goto corrupt; | ||
861 | |||
862 | /* skip diff positions */ | ||
863 | if (!skip(&data, tx_data->endp, ndiffs)) | ||
864 | goto corrupt; | ||
865 | |||
866 | /* | ||
867 | * After the diffs we have the first key id + data - | ||
868 | * global fixed | ||
869 | */ | ||
870 | if (!skip(&data, tx_data->endp, | ||
871 | 1 + TX_BLOCK_SIZE - num_global_fixed)) | ||
872 | goto corrupt; | ||
873 | |||
874 | /* Then we have keys-1 blocks of key id+diffs */ | ||
875 | if (!skip(&data, tx_data->endp, | ||
876 | (ndiffs + 1) * (keys - 1))) | ||
877 | goto corrupt; | ||
878 | } | ||
879 | ret = 0; | ||
880 | goto out; | ||
881 | |||
882 | corrupt: | ||
883 | zilog_error("firmware is corrupt\n"); | ||
884 | fw_unload_locked(); | ||
885 | ret = -EFAULT; | ||
886 | |||
887 | out: | ||
888 | mutex_unlock(&tx_data_lock); | ||
889 | return ret; | ||
890 | } | ||
891 | |||
892 | /* copied from lirc_dev */ | ||
893 | static ssize_t read(struct file *filep, char *outbuf, size_t n, loff_t *ppos) | ||
894 | { | ||
895 | struct IR *ir = filep->private_data; | ||
896 | struct IR_rx *rx; | ||
897 | struct lirc_buffer *rbuf = ir->l.rbuf; | ||
898 | int ret = 0, written = 0, retries = 0; | ||
899 | unsigned int m; | ||
900 | DECLARE_WAITQUEUE(wait, current); | ||
901 | |||
902 | dprintk("read called\n"); | ||
903 | if (n % rbuf->chunk_size) { | ||
904 | dprintk("read result = -EINVAL\n"); | ||
905 | return -EINVAL; | ||
906 | } | ||
907 | |||
908 | rx = get_ir_rx(ir); | ||
909 | if (rx == NULL) | ||
910 | return -ENXIO; | ||
911 | |||
912 | /* | ||
913 | * we add ourselves to the task queue before buffer check | ||
914 | * to avoid losing scan code (in case when queue is awaken somewhere | ||
915 | * between while condition checking and scheduling) | ||
916 | */ | ||
917 | add_wait_queue(&rbuf->wait_poll, &wait); | ||
918 | set_current_state(TASK_INTERRUPTIBLE); | ||
919 | |||
920 | /* | ||
921 | * while we didn't provide 'length' bytes, device is opened in blocking | ||
922 | * mode and 'copy_to_user' is happy, wait for data. | ||
923 | */ | ||
924 | while (written < n && ret == 0) { | ||
925 | if (lirc_buffer_empty(rbuf)) { | ||
926 | /* | ||
927 | * According to the read(2) man page, 'written' can be | ||
928 | * returned as less than 'n', instead of blocking | ||
929 | * again, returning -EWOULDBLOCK, or returning | ||
930 | * -ERESTARTSYS | ||
931 | */ | ||
932 | if (written) | ||
933 | break; | ||
934 | if (filep->f_flags & O_NONBLOCK) { | ||
935 | ret = -EWOULDBLOCK; | ||
936 | break; | ||
937 | } | ||
938 | if (signal_pending(current)) { | ||
939 | ret = -ERESTARTSYS; | ||
940 | break; | ||
941 | } | ||
942 | schedule(); | ||
943 | set_current_state(TASK_INTERRUPTIBLE); | ||
944 | } else { | ||
945 | unsigned char buf[rbuf->chunk_size]; | ||
946 | m = lirc_buffer_read(rbuf, buf); | ||
947 | if (m == rbuf->chunk_size) { | ||
948 | ret = copy_to_user((void *)outbuf+written, buf, | ||
949 | rbuf->chunk_size); | ||
950 | written += rbuf->chunk_size; | ||
951 | } else { | ||
952 | retries++; | ||
953 | } | ||
954 | if (retries >= 5) { | ||
955 | zilog_error("Buffer read failed!\n"); | ||
956 | ret = -EIO; | ||
957 | } | ||
958 | } | ||
959 | } | ||
960 | |||
961 | remove_wait_queue(&rbuf->wait_poll, &wait); | ||
962 | put_ir_rx(rx, false); | ||
963 | set_current_state(TASK_RUNNING); | ||
964 | |||
965 | dprintk("read result = %d (%s)\n", ret, ret ? "Error" : "OK"); | ||
966 | |||
967 | return ret ? ret : written; | ||
968 | } | ||
969 | |||
970 | /* send a keypress to the IR TX device */ | ||
971 | static int send_code(struct IR_tx *tx, unsigned int code, unsigned int key) | ||
972 | { | ||
973 | unsigned char data_block[TX_BLOCK_SIZE]; | ||
974 | unsigned char buf[2]; | ||
975 | int i, ret; | ||
976 | |||
977 | /* Get data for the codeset/key */ | ||
978 | ret = get_key_data(data_block, code, key); | ||
979 | |||
980 | if (ret == -EPROTO) { | ||
981 | zilog_error("failed to get data for code %u, key %u -- check " | ||
982 | "lircd.conf entries\n", code, key); | ||
983 | return ret; | ||
984 | } else if (ret != 0) | ||
985 | return ret; | ||
986 | |||
987 | /* Send the data block */ | ||
988 | ret = send_data_block(tx, data_block); | ||
989 | if (ret != 0) | ||
990 | return ret; | ||
991 | |||
992 | /* Send data block length? */ | ||
993 | buf[0] = 0x00; | ||
994 | buf[1] = 0x40; | ||
995 | ret = i2c_master_send(tx->c, buf, 2); | ||
996 | if (ret != 2) { | ||
997 | zilog_error("i2c_master_send failed with %d\n", ret); | ||
998 | return ret < 0 ? ret : -EFAULT; | ||
999 | } | ||
1000 | |||
1001 | /* Give the z8 a moment to process data block */ | ||
1002 | for (i = 0; i < 10; i++) { | ||
1003 | ret = i2c_master_send(tx->c, buf, 1); | ||
1004 | if (ret == 1) | ||
1005 | break; | ||
1006 | udelay(100); | ||
1007 | } | ||
1008 | |||
1009 | if (ret != 1) { | ||
1010 | zilog_error("i2c_master_send failed with %d\n", ret); | ||
1011 | return ret < 0 ? ret : -EFAULT; | ||
1012 | } | ||
1013 | |||
1014 | /* Send finished download? */ | ||
1015 | ret = i2c_master_recv(tx->c, buf, 1); | ||
1016 | if (ret != 1) { | ||
1017 | zilog_error("i2c_master_recv failed with %d\n", ret); | ||
1018 | return ret < 0 ? ret : -EFAULT; | ||
1019 | } | ||
1020 | if (buf[0] != 0xA0) { | ||
1021 | zilog_error("unexpected IR TX response #1: %02x\n", | ||
1022 | buf[0]); | ||
1023 | return -EFAULT; | ||
1024 | } | ||
1025 | |||
1026 | /* Send prepare command? */ | ||
1027 | buf[0] = 0x00; | ||
1028 | buf[1] = 0x80; | ||
1029 | ret = i2c_master_send(tx->c, buf, 2); | ||
1030 | if (ret != 2) { | ||
1031 | zilog_error("i2c_master_send failed with %d\n", ret); | ||
1032 | return ret < 0 ? ret : -EFAULT; | ||
1033 | } | ||
1034 | |||
1035 | /* | ||
1036 | * The sleep bits aren't necessary on the HD PVR, and in fact, the | ||
1037 | * last i2c_master_recv always fails with a -5, so for now, we're | ||
1038 | * going to skip this whole mess and say we're done on the HD PVR | ||
1039 | */ | ||
1040 | if (!tx->post_tx_ready_poll) { | ||
1041 | dprintk("sent code %u, key %u\n", code, key); | ||
1042 | return 0; | ||
1043 | } | ||
1044 | |||
1045 | /* | ||
1046 | * This bit NAKs until the device is ready, so we retry it | ||
1047 | * sleeping a bit each time. This seems to be what the windows | ||
1048 | * driver does, approximately. | ||
1049 | * Try for up to 1s. | ||
1050 | */ | ||
1051 | for (i = 0; i < 20; ++i) { | ||
1052 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
1053 | schedule_timeout((50 * HZ + 999) / 1000); | ||
1054 | ret = i2c_master_send(tx->c, buf, 1); | ||
1055 | if (ret == 1) | ||
1056 | break; | ||
1057 | dprintk("NAK expected: i2c_master_send " | ||
1058 | "failed with %d (try %d)\n", ret, i+1); | ||
1059 | } | ||
1060 | if (ret != 1) { | ||
1061 | zilog_error("IR TX chip never got ready: last i2c_master_send " | ||
1062 | "failed with %d\n", ret); | ||
1063 | return ret < 0 ? ret : -EFAULT; | ||
1064 | } | ||
1065 | |||
1066 | /* Seems to be an 'ok' response */ | ||
1067 | i = i2c_master_recv(tx->c, buf, 1); | ||
1068 | if (i != 1) { | ||
1069 | zilog_error("i2c_master_recv failed with %d\n", ret); | ||
1070 | return -EFAULT; | ||
1071 | } | ||
1072 | if (buf[0] != 0x80) { | ||
1073 | zilog_error("unexpected IR TX response #2: %02x\n", buf[0]); | ||
1074 | return -EFAULT; | ||
1075 | } | ||
1076 | |||
1077 | /* Oh good, it worked */ | ||
1078 | dprintk("sent code %u, key %u\n", code, key); | ||
1079 | return 0; | ||
1080 | } | ||
1081 | |||
1082 | /* | ||
1083 | * Write a code to the device. We take in a 32-bit number (an int) and then | ||
1084 | * decode this to a codeset/key index. The key data is then decompressed and | ||
1085 | * sent to the device. We have a spin lock as per i2c documentation to prevent | ||
1086 | * multiple concurrent sends which would probably cause the device to explode. | ||
1087 | */ | ||
1088 | static ssize_t write(struct file *filep, const char *buf, size_t n, | ||
1089 | loff_t *ppos) | ||
1090 | { | ||
1091 | struct IR *ir = filep->private_data; | ||
1092 | struct IR_tx *tx; | ||
1093 | size_t i; | ||
1094 | int failures = 0; | ||
1095 | |||
1096 | /* Validate user parameters */ | ||
1097 | if (n % sizeof(int)) | ||
1098 | return -EINVAL; | ||
1099 | |||
1100 | /* Get a struct IR_tx reference */ | ||
1101 | tx = get_ir_tx(ir); | ||
1102 | if (tx == NULL) | ||
1103 | return -ENXIO; | ||
1104 | |||
1105 | /* Ensure our tx->c i2c_client remains valid for the duration */ | ||
1106 | mutex_lock(&tx->client_lock); | ||
1107 | if (tx->c == NULL) { | ||
1108 | mutex_unlock(&tx->client_lock); | ||
1109 | put_ir_tx(tx, false); | ||
1110 | return -ENXIO; | ||
1111 | } | ||
1112 | |||
1113 | /* Lock i2c bus for the duration */ | ||
1114 | mutex_lock(&ir->ir_lock); | ||
1115 | |||
1116 | /* Send each keypress */ | ||
1117 | for (i = 0; i < n;) { | ||
1118 | int ret = 0; | ||
1119 | int command; | ||
1120 | |||
1121 | if (copy_from_user(&command, buf + i, sizeof(command))) { | ||
1122 | mutex_unlock(&ir->ir_lock); | ||
1123 | mutex_unlock(&tx->client_lock); | ||
1124 | put_ir_tx(tx, false); | ||
1125 | return -EFAULT; | ||
1126 | } | ||
1127 | |||
1128 | /* Send boot data first if required */ | ||
1129 | if (tx->need_boot == 1) { | ||
1130 | /* Make sure we have the 'firmware' loaded, first */ | ||
1131 | ret = fw_load(tx); | ||
1132 | if (ret != 0) { | ||
1133 | mutex_unlock(&ir->ir_lock); | ||
1134 | mutex_unlock(&tx->client_lock); | ||
1135 | put_ir_tx(tx, false); | ||
1136 | if (ret != -ENOMEM) | ||
1137 | ret = -EIO; | ||
1138 | return ret; | ||
1139 | } | ||
1140 | /* Prep the chip for transmitting codes */ | ||
1141 | ret = send_boot_data(tx); | ||
1142 | if (ret == 0) | ||
1143 | tx->need_boot = 0; | ||
1144 | } | ||
1145 | |||
1146 | /* Send the code */ | ||
1147 | if (ret == 0) { | ||
1148 | ret = send_code(tx, (unsigned)command >> 16, | ||
1149 | (unsigned)command & 0xFFFF); | ||
1150 | if (ret == -EPROTO) { | ||
1151 | mutex_unlock(&ir->ir_lock); | ||
1152 | mutex_unlock(&tx->client_lock); | ||
1153 | put_ir_tx(tx, false); | ||
1154 | return ret; | ||
1155 | } | ||
1156 | } | ||
1157 | |||
1158 | /* | ||
1159 | * Hmm, a failure. If we've had a few then give up, otherwise | ||
1160 | * try a reset | ||
1161 | */ | ||
1162 | if (ret != 0) { | ||
1163 | /* Looks like the chip crashed, reset it */ | ||
1164 | zilog_error("sending to the IR transmitter chip " | ||
1165 | "failed, trying reset\n"); | ||
1166 | |||
1167 | if (failures >= 3) { | ||
1168 | zilog_error("unable to send to the IR chip " | ||
1169 | "after 3 resets, giving up\n"); | ||
1170 | mutex_unlock(&ir->ir_lock); | ||
1171 | mutex_unlock(&tx->client_lock); | ||
1172 | put_ir_tx(tx, false); | ||
1173 | return ret; | ||
1174 | } | ||
1175 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
1176 | schedule_timeout((100 * HZ + 999) / 1000); | ||
1177 | tx->need_boot = 1; | ||
1178 | ++failures; | ||
1179 | } else | ||
1180 | i += sizeof(int); | ||
1181 | } | ||
1182 | |||
1183 | /* Release i2c bus */ | ||
1184 | mutex_unlock(&ir->ir_lock); | ||
1185 | |||
1186 | mutex_unlock(&tx->client_lock); | ||
1187 | |||
1188 | /* Give back our struct IR_tx reference */ | ||
1189 | put_ir_tx(tx, false); | ||
1190 | |||
1191 | /* All looks good */ | ||
1192 | return n; | ||
1193 | } | ||
1194 | |||
1195 | /* copied from lirc_dev */ | ||
1196 | static unsigned int poll(struct file *filep, poll_table *wait) | ||
1197 | { | ||
1198 | struct IR *ir = filep->private_data; | ||
1199 | struct IR_rx *rx; | ||
1200 | struct lirc_buffer *rbuf = ir->l.rbuf; | ||
1201 | unsigned int ret; | ||
1202 | |||
1203 | dprintk("poll called\n"); | ||
1204 | |||
1205 | rx = get_ir_rx(ir); | ||
1206 | if (rx == NULL) { | ||
1207 | /* | ||
1208 | * Revisit this, if our poll function ever reports writeable | ||
1209 | * status for Tx | ||
1210 | */ | ||
1211 | dprintk("poll result = POLLERR\n"); | ||
1212 | return POLLERR; | ||
1213 | } | ||
1214 | |||
1215 | /* | ||
1216 | * Add our lirc_buffer's wait_queue to the poll_table. A wake up on | ||
1217 | * that buffer's wait queue indicates we may have a new poll status. | ||
1218 | */ | ||
1219 | poll_wait(filep, &rbuf->wait_poll, wait); | ||
1220 | |||
1221 | /* Indicate what ops could happen immediately without blocking */ | ||
1222 | ret = lirc_buffer_empty(rbuf) ? 0 : (POLLIN|POLLRDNORM); | ||
1223 | |||
1224 | dprintk("poll result = %s\n", ret ? "POLLIN|POLLRDNORM" : "none"); | ||
1225 | return ret; | ||
1226 | } | ||
1227 | |||
1228 | static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg) | ||
1229 | { | ||
1230 | struct IR *ir = filep->private_data; | ||
1231 | int result; | ||
1232 | unsigned long mode, features; | ||
1233 | |||
1234 | features = ir->l.features; | ||
1235 | |||
1236 | switch (cmd) { | ||
1237 | case LIRC_GET_LENGTH: | ||
1238 | result = put_user((unsigned long)13, | ||
1239 | (unsigned long *)arg); | ||
1240 | break; | ||
1241 | case LIRC_GET_FEATURES: | ||
1242 | result = put_user(features, (unsigned long *) arg); | ||
1243 | break; | ||
1244 | case LIRC_GET_REC_MODE: | ||
1245 | if (!(features&LIRC_CAN_REC_MASK)) | ||
1246 | return -ENOSYS; | ||
1247 | |||
1248 | result = put_user(LIRC_REC2MODE | ||
1249 | (features&LIRC_CAN_REC_MASK), | ||
1250 | (unsigned long *)arg); | ||
1251 | break; | ||
1252 | case LIRC_SET_REC_MODE: | ||
1253 | if (!(features&LIRC_CAN_REC_MASK)) | ||
1254 | return -ENOSYS; | ||
1255 | |||
1256 | result = get_user(mode, (unsigned long *)arg); | ||
1257 | if (!result && !(LIRC_MODE2REC(mode) & features)) | ||
1258 | result = -EINVAL; | ||
1259 | break; | ||
1260 | case LIRC_GET_SEND_MODE: | ||
1261 | if (!(features&LIRC_CAN_SEND_MASK)) | ||
1262 | return -ENOSYS; | ||
1263 | |||
1264 | result = put_user(LIRC_MODE_PULSE, (unsigned long *) arg); | ||
1265 | break; | ||
1266 | case LIRC_SET_SEND_MODE: | ||
1267 | if (!(features&LIRC_CAN_SEND_MASK)) | ||
1268 | return -ENOSYS; | ||
1269 | |||
1270 | result = get_user(mode, (unsigned long *) arg); | ||
1271 | if (!result && mode != LIRC_MODE_PULSE) | ||
1272 | return -EINVAL; | ||
1273 | break; | ||
1274 | default: | ||
1275 | return -EINVAL; | ||
1276 | } | ||
1277 | return result; | ||
1278 | } | ||
1279 | |||
1280 | static struct IR *get_ir_device_by_minor(unsigned int minor) | ||
1281 | { | ||
1282 | struct IR *ir; | ||
1283 | struct IR *ret = NULL; | ||
1284 | |||
1285 | mutex_lock(&ir_devices_lock); | ||
1286 | |||
1287 | if (!list_empty(&ir_devices_list)) { | ||
1288 | list_for_each_entry(ir, &ir_devices_list, list) { | ||
1289 | if (ir->l.minor == minor) { | ||
1290 | ret = get_ir_device(ir, true); | ||
1291 | break; | ||
1292 | } | ||
1293 | } | ||
1294 | } | ||
1295 | |||
1296 | mutex_unlock(&ir_devices_lock); | ||
1297 | return ret; | ||
1298 | } | ||
1299 | |||
1300 | /* | ||
1301 | * Open the IR device. Get hold of our IR structure and | ||
1302 | * stash it in private_data for the file | ||
1303 | */ | ||
1304 | static int open(struct inode *node, struct file *filep) | ||
1305 | { | ||
1306 | struct IR *ir; | ||
1307 | unsigned int minor = MINOR(node->i_rdev); | ||
1308 | |||
1309 | /* find our IR struct */ | ||
1310 | ir = get_ir_device_by_minor(minor); | ||
1311 | |||
1312 | if (ir == NULL) | ||
1313 | return -ENODEV; | ||
1314 | |||
1315 | atomic_inc(&ir->open_count); | ||
1316 | |||
1317 | /* stash our IR struct */ | ||
1318 | filep->private_data = ir; | ||
1319 | |||
1320 | nonseekable_open(node, filep); | ||
1321 | return 0; | ||
1322 | } | ||
1323 | |||
1324 | /* Close the IR device */ | ||
1325 | static int close(struct inode *node, struct file *filep) | ||
1326 | { | ||
1327 | /* find our IR struct */ | ||
1328 | struct IR *ir = filep->private_data; | ||
1329 | if (ir == NULL) { | ||
1330 | zilog_error("close: no private_data attached to the file!\n"); | ||
1331 | return -ENODEV; | ||
1332 | } | ||
1333 | |||
1334 | atomic_dec(&ir->open_count); | ||
1335 | |||
1336 | put_ir_device(ir, false); | ||
1337 | return 0; | ||
1338 | } | ||
1339 | |||
1340 | static int ir_remove(struct i2c_client *client); | ||
1341 | static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id); | ||
1342 | |||
1343 | #define ID_FLAG_TX 0x01 | ||
1344 | #define ID_FLAG_HDPVR 0x02 | ||
1345 | |||
1346 | static const struct i2c_device_id ir_transceiver_id[] = { | ||
1347 | { "ir_tx_z8f0811_haup", ID_FLAG_TX }, | ||
1348 | { "ir_rx_z8f0811_haup", 0 }, | ||
1349 | { "ir_tx_z8f0811_hdpvr", ID_FLAG_HDPVR | ID_FLAG_TX }, | ||
1350 | { "ir_rx_z8f0811_hdpvr", ID_FLAG_HDPVR }, | ||
1351 | { } | ||
1352 | }; | ||
1353 | |||
1354 | static struct i2c_driver driver = { | ||
1355 | .driver = { | ||
1356 | .owner = THIS_MODULE, | ||
1357 | .name = "Zilog/Hauppauge i2c IR", | ||
1358 | }, | ||
1359 | .probe = ir_probe, | ||
1360 | .remove = ir_remove, | ||
1361 | .id_table = ir_transceiver_id, | ||
1362 | }; | ||
1363 | |||
1364 | static const struct file_operations lirc_fops = { | ||
1365 | .owner = THIS_MODULE, | ||
1366 | .llseek = no_llseek, | ||
1367 | .read = read, | ||
1368 | .write = write, | ||
1369 | .poll = poll, | ||
1370 | .unlocked_ioctl = ioctl, | ||
1371 | #ifdef CONFIG_COMPAT | ||
1372 | .compat_ioctl = ioctl, | ||
1373 | #endif | ||
1374 | .open = open, | ||
1375 | .release = close | ||
1376 | }; | ||
1377 | |||
1378 | static struct lirc_driver lirc_template = { | ||
1379 | .name = "lirc_zilog", | ||
1380 | .minor = -1, | ||
1381 | .code_length = 13, | ||
1382 | .buffer_size = BUFLEN / 2, | ||
1383 | .sample_rate = 0, /* tell lirc_dev to not start its own kthread */ | ||
1384 | .chunk_size = 2, | ||
1385 | .set_use_inc = set_use_inc, | ||
1386 | .set_use_dec = set_use_dec, | ||
1387 | .fops = &lirc_fops, | ||
1388 | .owner = THIS_MODULE, | ||
1389 | }; | ||
1390 | |||
1391 | static int ir_remove(struct i2c_client *client) | ||
1392 | { | ||
1393 | if (strncmp("ir_tx_z8", client->name, 8) == 0) { | ||
1394 | struct IR_tx *tx = i2c_get_clientdata(client); | ||
1395 | if (tx != NULL) { | ||
1396 | mutex_lock(&tx->client_lock); | ||
1397 | tx->c = NULL; | ||
1398 | mutex_unlock(&tx->client_lock); | ||
1399 | put_ir_tx(tx, false); | ||
1400 | } | ||
1401 | } else if (strncmp("ir_rx_z8", client->name, 8) == 0) { | ||
1402 | struct IR_rx *rx = i2c_get_clientdata(client); | ||
1403 | if (rx != NULL) { | ||
1404 | mutex_lock(&rx->client_lock); | ||
1405 | rx->c = NULL; | ||
1406 | mutex_unlock(&rx->client_lock); | ||
1407 | put_ir_rx(rx, false); | ||
1408 | } | ||
1409 | } | ||
1410 | return 0; | ||
1411 | } | ||
1412 | |||
1413 | |||
1414 | /* ir_devices_lock must be held */ | ||
1415 | static struct IR *get_ir_device_by_adapter(struct i2c_adapter *adapter) | ||
1416 | { | ||
1417 | struct IR *ir; | ||
1418 | |||
1419 | if (list_empty(&ir_devices_list)) | ||
1420 | return NULL; | ||
1421 | |||
1422 | list_for_each_entry(ir, &ir_devices_list, list) | ||
1423 | if (ir->adapter == adapter) { | ||
1424 | get_ir_device(ir, true); | ||
1425 | return ir; | ||
1426 | } | ||
1427 | |||
1428 | return NULL; | ||
1429 | } | ||
1430 | |||
1431 | static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
1432 | { | ||
1433 | struct IR *ir; | ||
1434 | struct IR_tx *tx; | ||
1435 | struct IR_rx *rx; | ||
1436 | struct i2c_adapter *adap = client->adapter; | ||
1437 | int ret; | ||
1438 | bool tx_probe = false; | ||
1439 | |||
1440 | dprintk("%s: %s on i2c-%d (%s), client addr=0x%02x\n", | ||
1441 | __func__, id->name, adap->nr, adap->name, client->addr); | ||
1442 | |||
1443 | /* | ||
1444 | * The IR receiver is at i2c address 0x71. | ||
1445 | * The IR transmitter is at i2c address 0x70. | ||
1446 | */ | ||
1447 | |||
1448 | if (id->driver_data & ID_FLAG_TX) | ||
1449 | tx_probe = true; | ||
1450 | else if (tx_only) /* module option */ | ||
1451 | return -ENXIO; | ||
1452 | |||
1453 | zilog_info("probing IR %s on %s (i2c-%d)\n", | ||
1454 | tx_probe ? "Tx" : "Rx", adap->name, adap->nr); | ||
1455 | |||
1456 | mutex_lock(&ir_devices_lock); | ||
1457 | |||
1458 | /* Use a single struct IR instance for both the Rx and Tx functions */ | ||
1459 | ir = get_ir_device_by_adapter(adap); | ||
1460 | if (ir == NULL) { | ||
1461 | ir = kzalloc(sizeof(struct IR), GFP_KERNEL); | ||
1462 | if (ir == NULL) { | ||
1463 | ret = -ENOMEM; | ||
1464 | goto out_no_ir; | ||
1465 | } | ||
1466 | kref_init(&ir->ref); | ||
1467 | |||
1468 | /* store for use in ir_probe() again, and open() later on */ | ||
1469 | INIT_LIST_HEAD(&ir->list); | ||
1470 | list_add_tail(&ir->list, &ir_devices_list); | ||
1471 | |||
1472 | ir->adapter = adap; | ||
1473 | mutex_init(&ir->ir_lock); | ||
1474 | atomic_set(&ir->open_count, 0); | ||
1475 | spin_lock_init(&ir->tx_ref_lock); | ||
1476 | spin_lock_init(&ir->rx_ref_lock); | ||
1477 | |||
1478 | /* set lirc_dev stuff */ | ||
1479 | memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver)); | ||
1480 | /* | ||
1481 | * FIXME this is a pointer reference to us, but no refcount. | ||
1482 | * | ||
1483 | * This OK for now, since lirc_dev currently won't touch this | ||
1484 | * buffer as we provide our own lirc_fops. | ||
1485 | * | ||
1486 | * Currently our own lirc_fops rely on this ir->l.rbuf pointer | ||
1487 | */ | ||
1488 | ir->l.rbuf = &ir->rbuf; | ||
1489 | ir->l.dev = &adap->dev; | ||
1490 | ret = lirc_buffer_init(ir->l.rbuf, | ||
1491 | ir->l.chunk_size, ir->l.buffer_size); | ||
1492 | if (ret) | ||
1493 | goto out_put_ir; | ||
1494 | } | ||
1495 | |||
1496 | if (tx_probe) { | ||
1497 | /* Get the IR_rx instance for later, if already allocated */ | ||
1498 | rx = get_ir_rx(ir); | ||
1499 | |||
1500 | /* Set up a struct IR_tx instance */ | ||
1501 | tx = kzalloc(sizeof(struct IR_tx), GFP_KERNEL); | ||
1502 | if (tx == NULL) { | ||
1503 | ret = -ENOMEM; | ||
1504 | goto out_put_xx; | ||
1505 | } | ||
1506 | kref_init(&tx->ref); | ||
1507 | ir->tx = tx; | ||
1508 | |||
1509 | ir->l.features |= LIRC_CAN_SEND_PULSE; | ||
1510 | mutex_init(&tx->client_lock); | ||
1511 | tx->c = client; | ||
1512 | tx->need_boot = 1; | ||
1513 | tx->post_tx_ready_poll = | ||
1514 | (id->driver_data & ID_FLAG_HDPVR) ? false : true; | ||
1515 | |||
1516 | /* An ir ref goes to the struct IR_tx instance */ | ||
1517 | tx->ir = get_ir_device(ir, true); | ||
1518 | |||
1519 | /* A tx ref goes to the i2c_client */ | ||
1520 | i2c_set_clientdata(client, get_ir_tx(ir)); | ||
1521 | |||
1522 | /* | ||
1523 | * Load the 'firmware'. We do this before registering with | ||
1524 | * lirc_dev, so the first firmware load attempt does not happen | ||
1525 | * after a open() or write() call on the device. | ||
1526 | * | ||
1527 | * Failure here is not deemed catastrophic, so the receiver will | ||
1528 | * still be usable. Firmware load will be retried in write(), | ||
1529 | * if it is needed. | ||
1530 | */ | ||
1531 | fw_load(tx); | ||
1532 | |||
1533 | /* Proceed only if the Rx client is also ready or not needed */ | ||
1534 | if (rx == NULL && !tx_only) { | ||
1535 | zilog_info("probe of IR Tx on %s (i2c-%d) done. Waiting" | ||
1536 | " on IR Rx.\n", adap->name, adap->nr); | ||
1537 | goto out_ok; | ||
1538 | } | ||
1539 | } else { | ||
1540 | /* Get the IR_tx instance for later, if already allocated */ | ||
1541 | tx = get_ir_tx(ir); | ||
1542 | |||
1543 | /* Set up a struct IR_rx instance */ | ||
1544 | rx = kzalloc(sizeof(struct IR_rx), GFP_KERNEL); | ||
1545 | if (rx == NULL) { | ||
1546 | ret = -ENOMEM; | ||
1547 | goto out_put_xx; | ||
1548 | } | ||
1549 | kref_init(&rx->ref); | ||
1550 | ir->rx = rx; | ||
1551 | |||
1552 | ir->l.features |= LIRC_CAN_REC_LIRCCODE; | ||
1553 | mutex_init(&rx->client_lock); | ||
1554 | rx->c = client; | ||
1555 | rx->hdpvr_data_fmt = | ||
1556 | (id->driver_data & ID_FLAG_HDPVR) ? true : false; | ||
1557 | |||
1558 | /* An ir ref goes to the struct IR_rx instance */ | ||
1559 | rx->ir = get_ir_device(ir, true); | ||
1560 | |||
1561 | /* An rx ref goes to the i2c_client */ | ||
1562 | i2c_set_clientdata(client, get_ir_rx(ir)); | ||
1563 | |||
1564 | /* | ||
1565 | * Start the polling thread. | ||
1566 | * It will only perform an empty loop around schedule_timeout() | ||
1567 | * until we register with lirc_dev and the first user open() | ||
1568 | */ | ||
1569 | /* An ir ref goes to the new rx polling kthread */ | ||
1570 | rx->task = kthread_run(lirc_thread, get_ir_device(ir, true), | ||
1571 | "zilog-rx-i2c-%d", adap->nr); | ||
1572 | if (IS_ERR(rx->task)) { | ||
1573 | ret = PTR_ERR(rx->task); | ||
1574 | zilog_error("%s: could not start IR Rx polling thread" | ||
1575 | "\n", __func__); | ||
1576 | /* Failed kthread, so put back the ir ref */ | ||
1577 | put_ir_device(ir, true); | ||
1578 | /* Failure exit, so put back rx ref from i2c_client */ | ||
1579 | i2c_set_clientdata(client, NULL); | ||
1580 | put_ir_rx(rx, true); | ||
1581 | ir->l.features &= ~LIRC_CAN_REC_LIRCCODE; | ||
1582 | goto out_put_xx; | ||
1583 | } | ||
1584 | |||
1585 | /* Proceed only if the Tx client is also ready */ | ||
1586 | if (tx == NULL) { | ||
1587 | zilog_info("probe of IR Rx on %s (i2c-%d) done. Waiting" | ||
1588 | " on IR Tx.\n", adap->name, adap->nr); | ||
1589 | goto out_ok; | ||
1590 | } | ||
1591 | } | ||
1592 | |||
1593 | /* register with lirc */ | ||
1594 | ir->l.minor = minor; /* module option: user requested minor number */ | ||
1595 | ir->l.minor = lirc_register_driver(&ir->l); | ||
1596 | if (ir->l.minor < 0 || ir->l.minor >= MAX_IRCTL_DEVICES) { | ||
1597 | zilog_error("%s: \"minor\" must be between 0 and %d (%d)!\n", | ||
1598 | __func__, MAX_IRCTL_DEVICES-1, ir->l.minor); | ||
1599 | ret = -EBADRQC; | ||
1600 | goto out_put_xx; | ||
1601 | } | ||
1602 | zilog_info("IR unit on %s (i2c-%d) registered as lirc%d and ready\n", | ||
1603 | adap->name, adap->nr, ir->l.minor); | ||
1604 | |||
1605 | out_ok: | ||
1606 | if (rx != NULL) | ||
1607 | put_ir_rx(rx, true); | ||
1608 | if (tx != NULL) | ||
1609 | put_ir_tx(tx, true); | ||
1610 | put_ir_device(ir, true); | ||
1611 | zilog_info("probe of IR %s on %s (i2c-%d) done\n", | ||
1612 | tx_probe ? "Tx" : "Rx", adap->name, adap->nr); | ||
1613 | mutex_unlock(&ir_devices_lock); | ||
1614 | return 0; | ||
1615 | |||
1616 | out_put_xx: | ||
1617 | if (rx != NULL) | ||
1618 | put_ir_rx(rx, true); | ||
1619 | if (tx != NULL) | ||
1620 | put_ir_tx(tx, true); | ||
1621 | out_put_ir: | ||
1622 | put_ir_device(ir, true); | ||
1623 | out_no_ir: | ||
1624 | zilog_error("%s: probing IR %s on %s (i2c-%d) failed with %d\n", | ||
1625 | __func__, tx_probe ? "Tx" : "Rx", adap->name, adap->nr, | ||
1626 | ret); | ||
1627 | mutex_unlock(&ir_devices_lock); | ||
1628 | return ret; | ||
1629 | } | ||
1630 | |||
1631 | static int __init zilog_init(void) | ||
1632 | { | ||
1633 | int ret; | ||
1634 | |||
1635 | zilog_notify("Zilog/Hauppauge IR driver initializing\n"); | ||
1636 | |||
1637 | mutex_init(&tx_data_lock); | ||
1638 | |||
1639 | request_module("firmware_class"); | ||
1640 | |||
1641 | ret = i2c_add_driver(&driver); | ||
1642 | if (ret) | ||
1643 | zilog_error("initialization failed\n"); | ||
1644 | else | ||
1645 | zilog_notify("initialization complete\n"); | ||
1646 | |||
1647 | return ret; | ||
1648 | } | ||
1649 | |||
1650 | static void __exit zilog_exit(void) | ||
1651 | { | ||
1652 | i2c_del_driver(&driver); | ||
1653 | /* if loaded */ | ||
1654 | fw_unload(); | ||
1655 | zilog_notify("Zilog/Hauppauge IR driver unloaded\n"); | ||
1656 | } | ||
1657 | |||
1658 | module_init(zilog_init); | ||
1659 | module_exit(zilog_exit); | ||
1660 | |||
1661 | MODULE_DESCRIPTION("Zilog/Hauppauge infrared transmitter driver (i2c stack)"); | ||
1662 | MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, " | ||
1663 | "Ulrich Mueller, Stefan Jahn, Jerome Brock, Mark Weaver, " | ||
1664 | "Andy Walls"); | ||
1665 | MODULE_LICENSE("GPL"); | ||
1666 | /* for compat with old name, which isn't all that accurate anymore */ | ||
1667 | MODULE_ALIAS("lirc_pvr150"); | ||
1668 | |||
1669 | module_param(minor, int, 0444); | ||
1670 | MODULE_PARM_DESC(minor, "Preferred minor device number"); | ||
1671 | |||
1672 | module_param(debug, bool, 0644); | ||
1673 | MODULE_PARM_DESC(debug, "Enable debugging messages"); | ||
1674 | |||
1675 | module_param(tx_only, bool, 0644); | ||
1676 | MODULE_PARM_DESC(tx_only, "Only handle the IR transmit function"); | ||