Added lirc.
[irreco.git] / lirc-0.8.4a / drivers / lirc_cmdir / lirc_cmdir.c
blobe44b2886cf676d128104c9cbc26123a241be8c2e
1 /* $Id: lirc_cmdir.c,v 1.9 2008/01/13 11:13:49 lirc Exp $ */
3 /*
4 * lirc_cmdir.c - Driver for InnovationOne's COMMANDIR USB Transceiver
6 * This driver requires the COMMANDIR hardware driver, available at
7 * http://www.commandir.com/.
9 * Copyright (C) 2005 InnovationOne - Evelyn Yeung
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #ifdef HAVE_CONFIG_H
28 # include <config.h>
29 #endif
31 #include <linux/version.h>
32 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18)
33 #error "**********************************************************"
34 #error " Sorry, this driver needs kernel version 2.2.18 or higher "
35 #error "**********************************************************"
36 #endif
38 #include <linux/autoconf.h>
39 #include <linux/module.h>
40 #include <linux/errno.h>
41 #include <linux/signal.h>
42 #include <linux/sched.h>
43 #include <linux/kernel.h>
44 #include <linux/time.h>
45 #include <linux/string.h>
46 #include <linux/delay.h>
47 #include <linux/poll.h>
48 #include "drivers/lirc.h"
49 #include "drivers/lirc_dev/lirc_dev.h"
50 #include "drivers/kcompat.h"
51 #include "lirc_cmdir.h"
53 static int debug;
54 #define dprintk(fmt, args...) \
55 do { \
56 if (debug) \
57 printk(KERN_DEBUG fmt, ## args); \
58 } while (0)
60 struct lirc_cmdir {
61 int features;
64 struct lirc_cmdir hardware = {
66 /* LIRC_CAN_SET_SEND_DUTY_CYCLE| */
67 LIRC_CAN_SET_SEND_CARRIER|
68 LIRC_CAN_SEND_PULSE|
69 LIRC_CAN_SET_TRANSMITTER_MASK|
70 LIRC_CAN_REC_MODE2)
74 #define LIRC_DRIVER_NAME "lirc_cmdir"
75 #define RBUF_LEN 256
76 #define WBUF_LEN 256
77 #define MAX_PACKET 64
79 static struct lirc_buffer rbuf;
80 static lirc_t wbuf[WBUF_LEN];
81 static unsigned char cmdir_char[4*WBUF_LEN];
82 static unsigned char write_control[MCU_CTRL_SIZE];
83 static unsigned int last_mc_time;
84 static int usb_status = ON;
85 static unsigned char signal_num;
86 char timerval;
88 unsigned int freq = 38000;
89 /* unsigned int duty_cycle = 50; */
92 #ifndef MAX_UDELAY_MS
93 #define MAX_UDELAY_US 5000
94 #else
95 #define MAX_UDELAY_US (MAX_UDELAY_MS*1000)
96 #endif
98 static inline void safe_udelay(unsigned long usecs)
100 while (usecs > MAX_UDELAY_US) {
101 udelay(MAX_UDELAY_US);
102 usecs -= MAX_UDELAY_US;
104 udelay(usecs);
107 static unsigned int get_time_value(unsigned int firstint,
108 unsigned int secondint, unsigned char overflow)
109 { /* get difference between two timestamps from MCU */
110 unsigned int t_answer = 0;
112 if (secondint > firstint) {
113 t_answer = secondint - firstint + overflow*65536;
114 } else {
115 if (overflow > 0)
116 t_answer = (65536 - firstint) + secondint +
117 (overflow - 1) * 65536;
118 else
119 t_answer = (65536 - firstint) + secondint;
122 /* clamp to long signal */
123 if (t_answer > 16000000)
124 t_answer = PULSE_MASK;
126 return t_answer;
130 static int set_use_inc(void *data)
132 /* Init read buffer. */
133 if (lirc_buffer_init(&rbuf, sizeof(lirc_t), RBUF_LEN) < 0)
134 return -ENOMEM;
136 MOD_INC_USE_COUNT;
137 return 0;
140 static void set_use_dec(void *data)
142 lirc_buffer_free(&rbuf);
143 MOD_DEC_USE_COUNT;
147 static void usb_error_handle(int retval)
149 switch (retval) {
150 case -ENODEV:
151 /* device has been unplugged */
152 if (usb_status == ON) {
153 usb_status = OFF;
154 printk(LIRC_DRIVER_NAME ": device is unplugged\n");
156 break;
157 default:
158 printk(LIRC_DRIVER_NAME ": usb error = %d\n", retval);
159 break;
163 static int write_to_usb(unsigned char *buffer, int count, int time_elapsed)
165 int write_return;
167 write_return = cmdir_write(buffer, count, NULL, time_elapsed);
168 if (write_return != count) {
169 usb_error_handle(write_return);
170 } else {
171 if (usb_status == OFF) {
172 printk(LIRC_DRIVER_NAME ": device is now plugged in\n");
173 usb_status = ON;
176 return write_return;
179 static void set_freq(void)
181 /* float tempfreq = 0.0; */
182 int write_return;
185 * Can't use floating point in 2.6 kernel!
186 * May be some loss of precision
188 timerval = (1000000 / freq) / 2;
189 write_control[0] = FREQ_HEADER;
190 write_control[1] = timerval;
191 write_control[2] = 0;
192 write_return = write_to_usb(write_control, MCU_CTRL_SIZE, 0);
193 if (write_return == MCU_CTRL_SIZE)
194 printk(LIRC_DRIVER_NAME ": freq set to %dHz\n", freq);
195 else
196 printk(LIRC_DRIVER_NAME ": freq unchanged\n");
200 static int cmdir_convert_RX(unsigned char *orig_rxbuffer)
202 unsigned char tmp_char_buffer[80];
203 unsigned int tmp_int_buffer[20];
204 unsigned int final_data_buffer[20];
205 unsigned int num_data_values = 0;
206 unsigned char num_data_bytes = 0;
207 unsigned int orig_index = 0;
208 int i;
210 for (i = 0; i < 80; i++)
211 tmp_char_buffer[i] = 0;
212 for (i = 0; i < 20; i++)
213 tmp_int_buffer[i] = 0;
216 * get number of data bytes that follow the control bytes
217 * (NOT including them)
219 num_data_bytes = orig_rxbuffer[1];
221 /* check if num_bytes is multiple of 3; if not, error */
222 if (num_data_bytes % 3 > 0)
223 return -1;
224 if (num_data_bytes > 60)
225 return -3;
226 if (num_data_bytes < 3)
227 return -2;
230 * get number of ints to be returned; num_data_bytes does
231 * NOT include control bytes
233 num_data_values = num_data_bytes/3;
235 for (i = 0; i < num_data_values; i++) {
236 tmp_char_buffer[i*4] = orig_rxbuffer[(i+1)*3];
237 tmp_char_buffer[i*4+1] = orig_rxbuffer[(i+1)*3+1];
238 tmp_char_buffer[i*4+2] = 0;
239 tmp_char_buffer[i*4+3] = 0;
242 /* convert to int array */
243 memcpy((unsigned char *)tmp_int_buffer, tmp_char_buffer,
244 (num_data_values*4));
246 if (orig_rxbuffer[5] < 255) {
247 /* space */
248 final_data_buffer[0] = get_time_value(last_mc_time,
249 tmp_int_buffer[0],
250 orig_rxbuffer[5]);
251 } else { /* is pulse */
252 final_data_buffer[0] = get_time_value(last_mc_time,
253 tmp_int_buffer[0],
255 final_data_buffer[0] |= PULSE_BIT;
257 for (i = 1; i < num_data_values; i++) {
259 * index of orig_rxbuffer that corresponds to
260 * overflow/pulse/space
262 orig_index = (i + 1)*3 + 2;
263 if (orig_rxbuffer[orig_index] < 255) {
264 final_data_buffer[i] =
265 get_time_value(tmp_int_buffer[i - 1],
266 tmp_int_buffer[i],
267 orig_rxbuffer[orig_index]);
268 } else {
269 final_data_buffer[i] =
270 get_time_value(tmp_int_buffer[i - 1],
271 tmp_int_buffer[i],
273 final_data_buffer[i] |= PULSE_BIT;
276 last_mc_time = tmp_int_buffer[num_data_values - 1];
278 if (lirc_buffer_full(&rbuf)) {
279 printk(KERN_ERR LIRC_DRIVER_NAME ": lirc_buffer is full\n");
280 return -EOVERFLOW;
282 lirc_buffer_write_n(&rbuf, (char *)final_data_buffer, num_data_values);
284 return 0;
288 static int usb_read_once(void)
290 int read_retval = 0;
291 int conv_retval = 0;
292 unsigned char read_buffer[MAX_PACKET];
293 int i = 0;
294 int tooFull = 5; /* read up to 5 packets */
296 for (i = 0; i < MAX_PACKET; i++)
297 read_buffer[i] = 0;
299 while (tooFull--) {
300 read_retval = cmdir_read(read_buffer, MAX_PACKET);
301 /* Loop until we unload the data build-up */
302 if (read_buffer[1] < 60)
303 tooFull = 0;
304 if (!(read_retval == MAX_PACKET)) {
305 if (read_retval == -ENODEV) {
306 if (usb_status == ON) {
307 printk(KERN_ALERT LIRC_DRIVER_NAME
308 ": device is unplugged\n");
309 usb_status = OFF;
311 } else {
312 /* supress errors */
313 printk(KERN_ALERT LIRC_DRIVER_NAME
314 ": usb error on read = %d\n",
315 read_retval);
316 return -ENODATA;
318 dprintk("Error 3\n");
319 return -ENODATA;
320 } else {
321 if (usb_status == OFF) {
322 usb_status = ON;
323 printk(LIRC_DRIVER_NAME
324 ": device is now plugged in\n");
328 if (read_buffer[0] & 0x08) {
329 conv_retval = cmdir_convert_RX(read_buffer);
330 if (conv_retval == 0) {
331 if (!tooFull)
332 return 0;
333 else
334 dprintk("Looping for more data...\n");
335 } else {
336 dprintk("Error 2: %d\n", (int)conv_retval);
337 return -ENODATA;
339 } else {
340 /* There really is no data in their buffer */
341 dprintk("Empty RX Buffer!\n");
342 return -ENODATA;
345 return -1;
348 int add_to_buf(void *data, struct lirc_buffer *buf)
350 return usb_read_once();
354 static ssize_t lirc_write(struct file *file, const char *buf,
355 size_t n, loff_t *ppos)
357 int i, count;
358 unsigned int mod_signal_length = 0;
359 unsigned int time_elapse = 0;
360 unsigned int total_time_elapsed = 0;
361 unsigned int num_bytes_already_sent = 0;
362 unsigned int hibyte = 0;
363 unsigned int lobyte = 0;
364 int cmdir_cnt = 0;
365 unsigned int wait_this = 0;
366 struct timeval start_time;
367 struct timeval end_time;
368 unsigned int real_time_elapsed = 0;
370 /* save the time we started the write: */
371 do_gettimeofday(&start_time);
373 if (n % sizeof(lirc_t))
374 return -EINVAL;
376 count = n/sizeof(lirc_t);
377 if (count > WBUF_LEN || count % 2 == 0)
378 return -EINVAL;
379 if (copy_from_user(wbuf, buf, n))
380 return -EFAULT;
383 * the first time we have to flag that this is the start of a new
384 * signal otherwise COMMANDIR may receive 2 back-to-back pulses &
385 * invert the signal
387 cmdir_char[0] = TX_HEADER_NEW;
388 signal_num++;
389 cmdir_char[1] = signal_num;
390 cmdir_cnt = 2;
391 for (i = 0; i < count; i++) {
392 /* conversion to number of modulation frequency pulse edges */
393 mod_signal_length = wbuf[i] >> 3;
395 * account for minor rounding errors -
396 * calculate length from this:
398 time_elapse += mod_signal_length * timerval;
400 hibyte = mod_signal_length / 256;
401 lobyte = mod_signal_length % 256;
402 cmdir_char[cmdir_cnt+1] = lobyte;
403 cmdir_char[cmdir_cnt] = hibyte;
404 cmdir_cnt += 2;
406 /* write data to usb if full packet is collected */
407 if (cmdir_cnt % MAX_PACKET == 0) {
408 write_to_usb(cmdir_char, MAX_PACKET, time_elapse);
410 total_time_elapsed += time_elapse;
412 num_bytes_already_sent += MAX_PACKET;
413 time_elapse = 0;
415 if ((i + 1) < count) {
416 /* still more to send: */
417 cmdir_char[0] = TX_HEADER; /* Next Packet */
418 cmdir_char[1] = signal_num;
419 cmdir_cnt = 2; /* reset the count */
424 /* send last chunk of data */
425 if (cmdir_cnt > 0) {
426 total_time_elapsed += time_elapse;
427 write_to_usb(cmdir_char, cmdir_cnt, time_elapse);
429 /* XXX ERS remove all this? */
431 * we need to _manually delay ourselves_ to remain backwards
432 * compatible with LIRC and prevent our queue buffer from overflowing.
433 * Queuing in this driver is about instant, and send_start for example
434 * will fill it up quickly and prevent send_stop from taking immediate
435 * effect.
437 dprintk("Total elapsed time is: %d. \n", total_time_elapsed);
438 do_gettimeofday(&end_time);
440 * udelay for the difference between endtime and
441 * start + total_time_elapsed
443 if (start_time.tv_usec < end_time.tv_usec)
444 real_time_elapsed = (end_time.tv_usec - start_time.tv_usec);
445 else
446 real_time_elapsed = ((end_time.tv_usec + 1000000) -
447 start_time.tv_usec);
448 dprintk("Real time elapsed was %u.\n", real_time_elapsed);
449 if (real_time_elapsed < (total_time_elapsed - 1000))
450 wait_this = total_time_elapsed - real_time_elapsed - 1000;
452 #if 0 /* enable this for backwards compatibility */
453 safe_udelay(wait_this);
454 #endif
456 return(n);
460 static int lirc_ioctl(struct inode *node, struct file *filep, unsigned int cmd,
461 unsigned long arg)
463 int result;
464 unsigned long value;
465 unsigned int ivalue;
466 unsigned int multiplier = 1;
467 unsigned int mask = 0;
468 int i;
470 switch (cmd) {
471 case LIRC_SET_TRANSMITTER_MASK:
472 if (!(hardware.features&LIRC_CAN_SET_TRANSMITTER_MASK))
473 return -ENOIOCTLCMD;
474 result = get_user(ivalue, (unsigned int *) arg);
475 if (result)
476 return result;
477 for (i = 0; i < MAX_CHANNELS; i++) {
478 multiplier = multiplier * 0x10;
479 mask |= multiplier;
481 if (ivalue >= mask)
482 return MAX_CHANNELS;
483 set_tx_channels(ivalue);
484 return 0;
485 break;
487 case LIRC_GET_SEND_MODE:
488 if (!(hardware.features & LIRC_CAN_SEND_MASK))
489 return -ENOIOCTLCMD;
491 result = put_user(LIRC_SEND2MODE
492 (hardware.features & LIRC_CAN_SEND_MASK),
493 (unsigned long *) arg);
494 if (result)
495 return result;
496 break;
498 case LIRC_SET_SEND_MODE:
499 if (!(hardware.features&LIRC_CAN_SEND_MASK))
500 return -ENOIOCTLCMD;
502 result = get_user(value, (unsigned long *)arg);
503 if (result)
504 return result;
505 break;
507 case LIRC_GET_LENGTH:
508 return -ENOSYS;
509 break;
511 case LIRC_SET_SEND_DUTY_CYCLE:
512 dprintk(KERN_WARNING LIRC_DRIVER_NAME
513 ": SET_SEND_DUTY_CYCLE\n");
515 if (!(hardware.features&LIRC_CAN_SET_SEND_DUTY_CYCLE))
516 return -ENOIOCTLCMD;
518 result = get_user(ivalue, (unsigned int *)arg);
519 if (result)
520 return result;
521 if (ivalue <= 0 || ivalue > 100)
522 return -EINVAL;
524 /* TODO: */
525 dprintk(LIRC_DRIVER_NAME
526 ": set_send_duty_cycle not yet supported\n");
528 return 0;
529 break;
531 case LIRC_SET_SEND_CARRIER:
532 dprintk(KERN_WARNING LIRC_DRIVER_NAME ": SET_SEND_CARRIER\n");
534 if (!(hardware.features & LIRC_CAN_SET_SEND_CARRIER))
535 return -ENOIOCTLCMD;
537 result = get_user(ivalue, (unsigned int *)arg);
538 if (result)
539 return result;
540 if (ivalue > 500000 || ivalue < 24000)
541 return -EINVAL;
542 if (ivalue != freq) {
543 freq = ivalue;
544 set_freq();
546 return 0;
547 break;
549 default:
550 return -ENOIOCTLCMD;
552 return 0;
555 static struct file_operations lirc_fops = {
556 .write = lirc_write,
559 static struct lirc_plugin plugin = {
560 .name = LIRC_DRIVER_NAME,
561 .minor = -1,
562 .code_length = 1,
563 .sample_rate = 20,
564 .data = NULL,
565 .add_to_buf = add_to_buf,
566 .get_queue = NULL,
567 .rbuf = &rbuf,
568 .set_use_inc = set_use_inc,
569 .set_use_dec = set_use_dec,
570 .ioctl = lirc_ioctl,
571 .fops = &lirc_fops,
572 .dev = NULL,
573 .owner = THIS_MODULE,
576 #ifdef MODULE
578 MODULE_AUTHOR("Evelyn Yeung, Matt Bodkin");
579 MODULE_DESCRIPTION("InnovationOne driver for "
580 "CommandIR USB infrared transceiver");
581 #ifdef MODULE_LICENSE
582 MODULE_LICENSE("GPL");
583 #endif
585 module_param(debug, bool, 0644);
586 MODULE_PARM_DESC(debug, "Enable debugging messages");
588 #ifndef KERNEL_2_5
589 EXPORT_NO_SYMBOLS;
590 #endif
592 int init_module(void)
594 plugin.features = hardware.features;
595 plugin.minor = lirc_register_plugin(&plugin);
596 if (plugin.minor < 0) {
597 printk(KERN_ERR LIRC_DRIVER_NAME
598 ": register_chrdev failed!\n");
599 return -EIO;
601 set_freq();
602 return 0;
605 void cleanup_module(void)
607 lirc_unregister_plugin(plugin.minor);
608 printk(KERN_INFO LIRC_DRIVER_NAME ": module removed\n");
611 #endif