--- drivers/lirc_atiusb/lirc_atiusb.c 2009/03/11 00:21:46 1.85 +++ drivers/lirc_atiusb/lirc_atiusb.c 2010/03/17 14:16:15 1.86 @@ -17,7 +17,7 @@ * Vassilis Virvilis 2006 * reworked the patch for lirc submission * - * $Id: lirc_atiusb.c,v 1.85 2009/03/11 00:21:46 jarodwilson Exp $ + * $Id: lirc_atiusb.c,v 1.86 2010/03/17 14:16:15 jarodwilson Exp $ */ /* @@ -67,7 +69,7 @@ #include "drivers/kcompat.h" #include "drivers/lirc_dev/lirc_dev.h" -#define DRIVER_VERSION "$Revision: 1.85 $" +#define DRIVER_VERSION "$Revision: 1.86 $" #define DRIVER_AUTHOR "Paul Miller " #define DRIVER_DESC "USB remote driver for LIRC" #define DRIVER_NAME "lirc_atiusb" @@ -1374,7 +1376,7 @@ DRIVER_VERSION "\n"); printk(DRIVER_NAME ": " DRIVER_AUTHOR "\n"); dprintk(DRIVER_NAME ": debug mode enabled: " - "$Id: lirc_atiusb.c,v 1.85 2009/03/11 00:21:46 jarodwilson Exp $\n"); + "$Id: lirc_atiusb.c,v 1.86 2010/03/17 14:16:15 jarodwilson Exp $\n"); repeat_jiffies = repeat*HZ/100; --- drivers/lirc_atiusb/lirc_atiusb.c 2010/03/17 14:16:15 1.86 +++ drivers/lirc_atiusb/lirc_atiusb.c 2010/07/24 14:35:58 1.87 @@ -17,7 +17,7 @@ * Vassilis Virvilis 2006 * reworked the patch for lirc submission * - * $Id: lirc_atiusb.c,v 1.86 2010/03/17 14:16:15 jarodwilson Exp $ + * $Id: lirc_atiusb.c,v 1.87 2010/07/24 14:35:58 jarodwilson Exp $ */ /* @@ -69,7 +69,7 @@ #include "drivers/kcompat.h" #include "drivers/lirc_dev/lirc_dev.h" -#define DRIVER_VERSION "$Revision: 1.86 $" +#define DRIVER_VERSION "$Revision: 1.87 $" #define DRIVER_AUTHOR "Paul Miller " #define DRIVER_DESC "USB remote driver for LIRC" #define DRIVER_NAME "lirc_atiusb" @@ -824,7 +824,11 @@ ir->devnum); case 3: #ifdef KERNEL_2_5 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34) + usb_free_coherent(iep->ir->usbdev, iep->len, iep->buf, iep->dma); +#else usb_buffer_free(iep->ir->usbdev, iep->len, iep->buf, iep->dma); +#endif #else kfree(iep->buf); #endif @@ -869,7 +873,11 @@ iep->len = len; #ifdef KERNEL_2_5 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34) + iep->buf = usb_alloc_coherent(dev, len, GFP_ATOMIC, &iep->dma); +#else iep->buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &iep->dma); +#endif #else iep->buf = kmalloc(len, GFP_KERNEL); #endif @@ -931,8 +939,13 @@ } case 3: #ifdef KERNEL_2_5 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34) + usb_free_coherent(oep->ir->usbdev, USB_OUTLEN, + oep->buf, oep->dma); +#else usb_buffer_free(oep->ir->usbdev, USB_OUTLEN, oep->buf, oep->dma); +#endif #else kfree(oep->buf); #endif @@ -965,8 +978,13 @@ init_waitqueue_head(&oep->wait); #ifdef KERNEL_2_5 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34) + oep->buf = usb_alloc_coherent(dev, USB_OUTLEN, + GFP_ATOMIC, &oep->dma); +#else oep->buf = usb_buffer_alloc(dev, USB_OUTLEN, GFP_ATOMIC, &oep->dma); +#endif #else oep->buf = kmalloc(USB_OUTLEN, GFP_KERNEL); #endif @@ -1376,7 +1394,7 @@ DRIVER_VERSION "\n"); printk(DRIVER_NAME ": " DRIVER_AUTHOR "\n"); dprintk(DRIVER_NAME ": debug mode enabled: " - "$Id: lirc_atiusb.c,v 1.86 2010/03/17 14:16:15 jarodwilson Exp $\n"); + "$Id: lirc_atiusb.c,v 1.87 2010/07/24 14:35:58 jarodwilson Exp $\n"); repeat_jiffies = repeat*HZ/100; --- drivers/lirc_atiusb/lirc_atiusb.c 2010/07/24 14:35:58 1.87 +++ drivers/lirc_atiusb/lirc_atiusb.c 2010/07/25 16:43:33 1.88 @@ -17,7 +17,7 @@ * Vassilis Virvilis 2006 * reworked the patch for lirc submission * - * $Id: lirc_atiusb.c,v 1.87 2010/07/24 14:35:58 jarodwilson Exp $ + * $Id: lirc_atiusb.c,v 1.88 2010/07/25 16:43:33 jarodwilson Exp $ */ /* @@ -69,7 +69,7 @@ #include "drivers/kcompat.h" #include "drivers/lirc_dev/lirc_dev.h" -#define DRIVER_VERSION "$Revision: 1.87 $" +#define DRIVER_VERSION "$Revision: 1.88 $" #define DRIVER_AUTHOR "Paul Miller " #define DRIVER_DESC "USB remote driver for LIRC" #define DRIVER_NAME "lirc_atiusb" @@ -824,12 +824,8 @@ ir->devnum); case 3: #ifdef KERNEL_2_5 -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34) usb_free_coherent(iep->ir->usbdev, iep->len, iep->buf, iep->dma); #else - usb_buffer_free(iep->ir->usbdev, iep->len, iep->buf, iep->dma); -#endif -#else kfree(iep->buf); #endif iep->buf = 0; @@ -873,12 +869,8 @@ iep->len = len; #ifdef KERNEL_2_5 -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34) iep->buf = usb_alloc_coherent(dev, len, GFP_ATOMIC, &iep->dma); #else - iep->buf = usb_buffer_alloc(dev, len, GFP_ATOMIC, &iep->dma); -#endif -#else iep->buf = kmalloc(len, GFP_KERNEL); #endif if (!iep->buf) { @@ -939,14 +931,9 @@ } case 3: #ifdef KERNEL_2_5 -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34) usb_free_coherent(oep->ir->usbdev, USB_OUTLEN, oep->buf, oep->dma); #else - usb_buffer_free(oep->ir->usbdev, USB_OUTLEN, - oep->buf, oep->dma); -#endif -#else kfree(oep->buf); #endif oep->buf = 0; @@ -978,14 +965,9 @@ init_waitqueue_head(&oep->wait); #ifdef KERNEL_2_5 -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 34) oep->buf = usb_alloc_coherent(dev, USB_OUTLEN, GFP_ATOMIC, &oep->dma); #else - oep->buf = usb_buffer_alloc(dev, USB_OUTLEN, - GFP_ATOMIC, &oep->dma); -#endif -#else oep->buf = kmalloc(USB_OUTLEN, GFP_KERNEL); #endif if (!oep->buf) @@ -1394,7 +1376,7 @@ DRIVER_VERSION "\n"); printk(DRIVER_NAME ": " DRIVER_AUTHOR "\n"); dprintk(DRIVER_NAME ": debug mode enabled: " - "$Id: lirc_atiusb.c,v 1.87 2010/07/24 14:35:58 jarodwilson Exp $\n"); + "$Id: lirc_atiusb.c,v 1.88 2010/07/25 16:43:33 jarodwilson Exp $\n"); repeat_jiffies = repeat*HZ/100; --- drivers/kcompat.h 2009/08/02 11:15:28 5.45 +++ drivers/kcompat.h 2010/07/27 05:43:21 5.50 @@ -1,4 +1,4 @@ -/* $Id: kcompat.h,v 5.45 2009/08/02 11:15:28 lirc Exp $ */ +/* $Id: kcompat.h,v 5.50 2010/07/27 05:43:21 jarodwilson Exp $ */ #ifndef _KCOMPAT_H #define _KCOMPAT_H @@ -9,6 +9,11 @@ #define __func__ __FUNCTION__ #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34) +#define usb_alloc_coherent usb_buffer_alloc +#define usb_free_coherent usb_buffer_free +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16) #define LIRC_THIS_MODULE(x) x, #else /* >= 2.6.16 */ @@ -364,6 +369,11 @@ #endif /* kernel < 2.6.11 */ #endif /* kernel >= 2.6.0 */ +/*************************** pm_wakeup.h ******************************/ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) +static inline void device_set_wakeup_capable(struct device *dev, int val) {} +#endif /* kernel < 2.6.27 */ + /*************************** interrupt.h ******************************/ /* added in 2.6.18, old defines removed in 2.6.24 */ #ifndef IRQF_DISABLED @@ -378,6 +388,9 @@ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) #define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) +#define __SPIN_LOCK_UNLOCKED(x) SPIN_LOCK_UNLOCKED; +#endif /***************************** slab.h *********************************/ /* added in 2.6.14 */ @@ -405,4 +418,14 @@ #define BIT_WORD(nr) ((nr) / BITS_PER_LONG) #endif +/****************************** kernel.h **********************************/ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) +#define DIV_ROUND_CLOSEST(x, divisor)( \ +{ \ + typeof(divisor) __divisor = divisor; \ + (((x) + ((__divisor) / 2)) / (__divisor)); \ +} \ +) +#endif + #endif /* _KCOMPAT_H */ --- drivers/lirc_igorplugusb/lirc_igorplugusb.c 2009/11/09 18:59:21 1.35 +++ drivers/lirc_igorplugusb/lirc_igorplugusb.c 2010/07/25 16:43:33 1.38 @@ -450,7 +452,7 @@ } #if defined(KERNEL_2_5) - ir->buf_in = usb_buffer_alloc(dev, + ir->buf_in = usb_alloc_coherent(dev, DEVICE_BUFLEN+DEVICE_HEADERLEN, GFP_ATOMIC, &ir->dma_in); #else @@ -486,7 +488,7 @@ switch (mem_failure) { case 9: #if defined(KERNEL_2_5) - usb_buffer_free(dev, DEVICE_BUFLEN+DEVICE_HEADERLEN, + usb_free_coherent(dev, DEVICE_BUFLEN+DEVICE_HEADERLEN, ir->buf_in, ir->dma_in); #else kfree(ir->buf_in); @@ -566,7 +568,7 @@ #if defined(KERNEL_2_5) - usb_buffer_free(dev, ir->len_in, ir->buf_in, ir->dma_in); + usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in); #else kfree(ir->buf_in); #endif --- drivers/lirc_mceusb/lirc_mceusb.c 2010/03/17 14:16:16 1.54 +++ drivers/lirc_mceusb/lirc_mceusb.c 2010/07/25 16:43:33 1.70 @@ -80,6 +80,7 @@ #define DRIVER_NAME "lirc_mceusb" #define USB_BUFLEN 32 /* USB reception buffer length */ +#define USB_CTRL_MSG_SZ 2 /* Size of usb ctrl msg on gen1 hw */ #define LIRCBUF_SIZE 256 /* LIRC work buffer length */ /* MCE constants */ @@ -95,7 +96,7 @@ #define MCE_PULSE_BIT 0x80 /* Pulse bit, MSB set == PULSE else SPACE */ #define MCE_PULSE_MASK 0x7F /* Pulse mask */ #define MCE_MAX_PULSE_LENGTH 0x7F /* Longest transmittable pulse symbol */ -#define MCE_PACKET_LENGTH_MASK 0x7F /* Pulse mask */ +#define MCE_PACKET_LENGTH_MASK 0x7F /* Packet length mask */ /* module parameters */ @@ -116,8 +117,8 @@ #define RECV_FLAG_IN_PROGRESS 3 #define RECV_FLAG_COMPLETE 4 -#define MCEUSB_INBOUND 1 -#define MCEUSB_OUTBOUND 2 +#define MCEUSB_RX 1 +#define MCEUSB_TX 2 #define VENDOR_PHILIPS 0x0471 #define VENDOR_SMK 0x0609 @@ -211,6 +212,8 @@ { USB_DEVICE(VENDOR_FORMOSA, 0xe03a) }, /* Formosa Industrial Computing AIM IR605/A */ { USB_DEVICE(VENDOR_FORMOSA, 0xe03c) }, + /* Formosa Industrial Computing AIM IR605/A */ + { USB_DEVICE(VENDOR_FORMOSA, 0xe03e) }, /* Fintek eHome Infrared Transceiver */ { USB_DEVICE(VENDOR_FINTEK, 0x0602) }, /* Fintek eHome Infrared Transceiver (in the AOpen MP45) */ @@ -233,8 +236,9 @@ { } }; -static struct usb_device_id pinnacle_list[] = { +static struct usb_device_id gen3_list[] = { { USB_DEVICE(VENDOR_PINNACLE, 0x0225) }, + { USB_DEVICE(VENDOR_TOPSEED, 0x0008) }, {} }; @@ -282,10 +286,9 @@ unsigned char is_pulse; struct { u32 connected:1; - u32 pinnacle:1; u32 transmitter_mask_inverted:1; u32 microsoft_gen1:1; - u32 reserved:28; + u32 reserved:29; } flags; unsigned char transmitter_mask; @@ -295,16 +298,44 @@ int send_flags; wait_queue_head_t wait_out; - struct mutex lock; + struct mutex dev_lock; }; -/* init strings */ -static char init1[] = {0x00, 0xff, 0xaa, 0xff, 0x0b}; -static char init2[] = {0xff, 0x18}; - -static char pin_init1[] = { 0x9f, 0x07}; -static char pin_init2[] = { 0x9f, 0x13}; -static char pin_init3[] = { 0x9f, 0x0d}; +/* + * MCE Device Command Strings + * Device command responses vary from device to device... + * - DEVICE_RESET resets the hardware to its default state + * - GET_REVISION fetches the hardware/software revision, common + * replies are ff 0b 45 ff 1b 08 and ff 0b 50 ff 1b 42 + * - GET_CARRIER_FREQ gets the carrier mode and frequency of the + * device, with replies in the form of 9f 06 MM FF, where MM is 0-3, + * meaning clk of 10000000, 2500000, 625000 or 156250, and FF is + * ((clk / frequency) - 1) + * - GET_RX_TIMEOUT fetches the receiver timeout in units of 50us, + * response in the form of 9f 0c msb lsb + * - GET_TX_BITMASK fetches the transmitter bitmask, replies in + * the form of 9f 08 bm, where bm is the bitmask + * - GET_RX_SENSOR fetches the RX sensor setting -- long-range + * general use one or short-range learning one, in the form of + * 9f 14 ss, where ss is either 01 for long-range or 02 for short + * - SET_CARRIER_FREQ sets a new carrier mode and frequency + * - SET_TX_BITMASK sets the transmitter bitmask + * - SET_RX_TIMEOUT sets the receiver timeout + * - SET_RX_SENSOR sets which receiver sensor to use + */ +static char DEVICE_RESET[] = {0x00, 0xff, 0xaa}; +static char GET_REVISION[] = {0xff, 0x0b}; +static char GET_UNKNOWN[] = {0xff, 0x18}; +static char GET_UNKNOWN2[] = {0x9f, 0x05}; +static char GET_CARRIER_FREQ[] = {0x9f, 0x07}; +static char GET_RX_TIMEOUT[] = {0x9f, 0x0d}; +static char GET_TX_BITMASK[] = {0x9f, 0x13}; +static char GET_RX_SENSOR[] = {0x9f, 0x15}; +/* sub in desired values in lower byte or bytes for full command */ +//static char SET_CARRIER_FREQ[] = {0x9f, 0x06, 0x00, 0x00}; +//static char SET_TX_BITMASK[] = {0x9f, 0x08, 0x00}; +//static char SET_RX_TIMEOUT[] = {0x9f, 0x0c, 0x00, 0x00}; +//static char SET_RX_SENSOR[] = {0x9f, 0x14, 0x00}; #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) static unsigned long usecs_to_jiffies(const unsigned int u) @@ -320,22 +351,126 @@ #endif } #endif -static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, int len) +static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, + int len, bool out) { char codes[USB_BUFLEN * 3 + 1]; + char inout[9]; int i; + u8 cmd, subcmd, data1, data2; + int idx = 0; - if (len <= 0) - return; + if (ir->flags.microsoft_gen1 && !out) + idx = 2; - if (ir->flags.microsoft_gen1 && len <= 2) + if (len <= idx) return; for (i = 0; i < len && i < USB_BUFLEN; i++) snprintf(codes + i * 3, 4, "%02x ", buf[i] & 0xFF); - printk(KERN_INFO "" DRIVER_NAME "[%d]: data received %s (length=%d)\n", - ir->devnum, codes, len); + printk(KERN_INFO "" DRIVER_NAME "[%d]: %sx data: %s (length=%d)\n", + ir->devnum, (out ? "t" : "r"), codes, len); + + if (out) + strcpy(inout, "Request\0"); + else + strcpy(inout, "Got\0"); + + cmd = buf[idx] & 0xff; + subcmd = buf[idx + 1] & 0xff; + data1 = buf[idx + 2] & 0xff; + data2 = buf[idx + 3] & 0xff; + + switch (cmd) { + case 0x00: + if (subcmd == 0xff && data1 == 0xaa) + printk(KERN_INFO "Device reset requested\n"); + else + printk(KERN_INFO "Unknown command 0x%02x 0x%02x\n", + cmd, subcmd); + break; + case 0xff: + switch (subcmd) { + case 0x0b: + if (len == 2) + printk(KERN_INFO "Get hw/sw rev?\n"); + else + printk(KERN_INFO "hw/sw rev 0x%02x 0x%02x " + "0x%02x 0x%02x\n", data1, data2, + buf[4], buf[5]); + break; + case 0xaa: + printk(KERN_INFO "Device reset requested\n"); + break; + case 0xfe: + printk(KERN_INFO "Previous command not supported\n"); + break; + case 0x18: + case 0x1b: + default: + printk(KERN_INFO "Unknown command 0x%02x 0x%02x\n", + cmd, subcmd); + break; + } + break; + case 0x9f: + switch (subcmd) { + case 0x03: + printk(KERN_INFO "Ping\n"); + break; + case 0x04: + printk(KERN_INFO "Resp to 9f 05 of 0x%02x 0x%02x\n", + data1, data2); + break; + case 0x06: + printk(KERN_INFO "%s carrier mode and freq of 0x%02x 0x%02x\n", + inout, data1, data2); + break; + case 0x07: + printk(KERN_INFO "Get carrier mode and freq\n"); + break; + case 0x08: + printk(KERN_INFO "%s transmit blaster mask of 0x%02x\n", + inout, data1); + break; + case 0x0c: + /* value is in units of 50us, so x*50/100 or x/2 ms */ + printk(KERN_INFO "%s receive timeout of %d ms\n", + inout, ((data1 << 8) | data2) / 2); + break; + case 0x0d: + printk(KERN_INFO "Get receive timeout\n"); + break; + case 0x13: + printk(KERN_INFO "Get transmit blaster mask\n"); + break; + case 0x14: + printk(KERN_INFO "%s %s-range receive sensor in use\n", + inout, data1 == 0x02 ? "short" : "long"); + break; + case 0x15: + if (len == 2) + printk(KERN_INFO "Get receive sensor\n"); + else + printk(KERN_INFO "Received pulse count is %d\n", + ((data1 << 8) | data2)); + break; + case 0xfe: + printk(KERN_INFO "Error! Hardware is likely wedged...\n"); + break; + case 0x05: + case 0x09: + case 0x0f: + default: + printk(KERN_INFO "Unknown command 0x%02x 0x%02x\n", + cmd, subcmd); + break; + } + break; + default: + break; + } } static void usb_async_callback(struct urb *urb, struct pt_regs *regs) @@ -355,54 +490,48 @@ ir->devnum, urb->status, len); if (debug) - mceusb_dev_printdata(ir, urb->transfer_buffer, len); + mceusb_dev_printdata(ir, urb->transfer_buffer, len, true); } } /* request incoming or send outgoing usb packet - used to initialize remote */ -static void request_packet_async(struct mceusb_dev *ir, - struct usb_endpoint_descriptor *ep, - unsigned char *data, int size, int urb_type) +static void mce_request_packet(struct mceusb_dev *ir, + struct usb_endpoint_descriptor *ep, + unsigned char *data, int size, int urb_type) { int res; struct urb *async_urb; unsigned char *async_buf; - if (urb_type) { + if (urb_type == MCEUSB_TX) { async_urb = usb_alloc_urb(0, GFP_KERNEL); - if (unlikely(!async_urb)) + if (unlikely(!async_urb)) { + printk(KERN_ERR "Error, couldn't allocate urb!\n"); return; + } - async_buf = kmalloc(size, GFP_KERNEL); + async_buf = kzalloc(size, GFP_KERNEL); if (!async_buf) { + printk(KERN_ERR "Error, couldn't allocate buf!\n"); usb_free_urb(async_urb); return; } - if (urb_type == MCEUSB_OUTBOUND) { - /* outbound data */ - usb_fill_int_urb(async_urb, ir->usbdev, - usb_sndintpipe(ir->usbdev, - ep->bEndpointAddress), - async_buf, size, - (usb_complete_t) usb_async_callback, - ir, ep->bInterval); - memcpy(async_buf, data, size); - } else { - /* inbound data */ - usb_fill_int_urb(async_urb, ir->usbdev, - usb_rcvintpipe(ir->usbdev, - ep->bEndpointAddress), - async_buf, size, - (usb_complete_t) usb_async_callback, - ir, ep->bInterval); - } - async_urb->transfer_flags = URB_ASYNC_UNLINK; - } else { + /* outbound data */ + usb_fill_int_urb(async_urb, ir->usbdev, + usb_sndintpipe(ir->usbdev, ep->bEndpointAddress), + async_buf, size, (usb_complete_t) usb_async_callback, + ir, ep->bInterval); + memcpy(async_buf, data, size); + + } else if (urb_type == MCEUSB_RX) { /* standard request */ async_urb = ir->urb_in; ir->send_flags = RECV_FLAG_IN_PROGRESS; + } else { + printk(KERN_ERR "Error! Unknown urb type %d\n", urb_type); + return; } dprintk(DRIVER_NAME "[%d]: receive request called (size=%#x)\n", @@ -421,6 +550,16 @@ ir->devnum, res); } +static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size) +{ + mce_request_packet(ir, ir->usb_ep_out, data, size, MCEUSB_TX); +} + +static void mce_sync_in(struct mceusb_dev *ir, unsigned char *data, int size) +{ + mce_request_packet(ir, ir->usb_ep_in, data, size, MCEUSB_RX); +} + static int unregister_from_lirc(struct mceusb_dev *ir) { struct lirc_driver *d = ir->d; @@ -496,9 +635,9 @@ dprintk(DRIVER_NAME "[%d]: mceusb IR device closed\n", ir->devnum); if (ir->flags.connected) { - mutex_lock(&ir->lock); + mutex_lock(&ir->dev_lock); ir->flags.connected = 0; - mutex_unlock(&ir->lock); + mutex_unlock(&ir->dev_lock); } MOD_DEC_USE_COUNT; } @@ -616,7 +755,7 @@ buf_len = urb->actual_length; if (debug) - mceusb_dev_printdata(ir, urb->transfer_buffer, buf_len); + mceusb_dev_printdata(ir, urb->transfer_buffer, buf_len, false); if (ir->send_flags == RECV_FLAG_IN_PROGRESS) { ir->send_flags = SEND_FLAG_COMPLETE; @@ -715,8 +854,7 @@ cmdbuf[cmdcount++] = 0x80; /* Transmit the command to the mce device */ - request_packet_async(ir, ir->usb_ep_out, cmdbuf, - cmdcount, MCEUSB_OUTBOUND); + mce_async_out(ir, cmdbuf, cmdcount); /* * The lircd gap calculation expects the write function to @@ -762,9 +900,7 @@ ir->carrier_freq = carrier; dprintk(DRIVER_NAME "[%d]: SET_CARRIER disabling " "carrier modulation\n", ir->devnum); - request_packet_async(ir, ir->usb_ep_out, - cmdbuf, sizeof(cmdbuf), - MCEUSB_OUTBOUND); + mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); return carrier; } @@ -779,9 +915,7 @@ ir->devnum, carrier); /* Transmit new carrier to mce device */ - request_packet_async(ir, ir->usb_ep_out, - cmdbuf, sizeof(cmdbuf), - MCEUSB_OUTBOUND); + mce_async_out(ir, cmdbuf, sizeof(cmdbuf)); return carrier; } } @@ -799,7 +933,6 @@ { int result; unsigned int ivalue; - unsigned long lvalue; struct mceusb_dev *ir = NULL; /* Retrieve lirc_driver data for the device */ @@ -828,26 +961,6 @@ dprintk(DRIVER_NAME ": SET_TRANSMITTERS mask=%d\n", ivalue); break; - case LIRC_GET_SEND_MODE: - - result = put_user(LIRC_SEND2MODE(LIRC_CAN_SEND_PULSE & - LIRC_CAN_SEND_MASK), - (unsigned long *) arg); - - if (result) - return result; - break; - - case LIRC_SET_SEND_MODE: - - result = get_user(lvalue, (unsigned long *) arg); - - if (result) - return result; - if (lvalue != (LIRC_MODE_PULSE&LIRC_CAN_SEND_MASK)) - return -EINVAL; - break; - case LIRC_SET_SEND_CARRIER: result = get_user(ivalue, (unsigned int *) arg); @@ -870,45 +983,25 @@ .ioctl = mceusb_lirc_ioctl, }; -static int mceusb_gen1_init(struct mceusb_dev *ir) +static void mceusb_gen1_init(struct mceusb_dev *ir) { - int i, ret; - char junk[64], data[8]; - int partial = 0; - - /* - * Clear off the first few messages. These look like calibration - * or test data, I can't really tell. This also flushes in case - * we have random ir data queued up. - */ - for (i = 0; i < 40; i++) - usb_bulk_msg(ir->usbdev, - usb_rcvbulkpipe(ir->usbdev, - ir->usb_ep_in->bEndpointAddress), - junk, 64, &partial, HZ * 10); - - ir->is_pulse = 1; - - memset(data, 0, 8); - - /* Get Status */ - ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), - USB_REQ_GET_STATUS, USB_DIR_IN, - 0, 0, data, 2, HZ * 3); - - /* ret = usb_get_status( ir->usbdev, 0, 0, data ); */ - dprintk("%s - ret = %d status = 0x%x 0x%x\n", __func__, - ret, data[0], data[1]); + int ret; + int maxp = ir->len_in; + char *data; + + data = kzalloc(USB_CTRL_MSG_SZ, GFP_KERNEL); + if (!data) { + printk(KERN_ERR "%s: memory allocation failed!\n", __func__); + return; + } /* * This is a strange one. They issue a set address to the device * on the receive control pipe and expect a certain value pair back */ - memset(data, 0, 8); - ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0, - data, 2, HZ * 3); + data, USB_CTRL_MSG_SZ, HZ * 3); dprintk("%s - ret = %d, devnum = %d\n", __func__, ret, ir->usbdev->devnum); dprintk("%s - data[0] = %d, data[1] = %d\n", @@ -933,12 +1026,62 @@ 0x0000, 0x0100, NULL, 0, HZ * 3); dprintk("%s - retC = %d\n", __func__, ret); - return ret; + /* device reset */ + mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET)); + mce_sync_in(ir, NULL, maxp); + + /* get hw/sw revision? */ + mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION)); + mce_sync_in(ir, NULL, maxp); + + kfree(data); + + return; }; -static int mceusb_dev_probe(struct usb_interface *intf, - const struct usb_device_id *id) +static void mceusb_gen2_init(struct mceusb_dev *ir) +{ + int maxp = ir->len_in; + + /* device reset */ + mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET)); + mce_sync_in(ir, NULL, maxp); + + /* get hw/sw revision? */ + mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION)); + mce_sync_in(ir, NULL, maxp); + + /* unknown what the next two actually return... */ + mce_async_out(ir, GET_UNKNOWN, sizeof(GET_UNKNOWN)); + mce_sync_in(ir, NULL, maxp); + mce_async_out(ir, GET_UNKNOWN2, sizeof(GET_UNKNOWN2)); + mce_sync_in(ir, NULL, maxp); +} + +static void mceusb_get_parameters(struct mceusb_dev *ir) +{ + int maxp = ir->len_in; + + /* get the carrier and frequency */ + mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ)); + mce_sync_in(ir, NULL, maxp); + + /* get the transmitter bitmask */ + mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK)); + mce_sync_in(ir, NULL, maxp); + + /* get receiver timeout value */ + mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT)); + mce_sync_in(ir, NULL, maxp); + + /* get receiver sensor setting */ + mce_async_out(ir, GET_RX_SENSOR, sizeof(GET_RX_SENSOR)); + mce_sync_in(ir, NULL, maxp); +} + +static int __devinit mceusb_dev_probe(struct usb_interface *intf, + const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(intf); struct usb_host_interface *idesc; @@ -954,19 +1097,15 @@ int i; char buf[63], name[128] = ""; int mem_failure = 0; - int is_pinnacle; - int is_microsoft_gen1; + bool is_gen3; + bool is_microsoft_gen1; dprintk(DRIVER_NAME ": %s called\n", __func__); - usb_reset_device(dev); - config = dev->actconfig; - idesc = intf->cur_altsetting; - is_pinnacle = usb_match_id(intf, pinnacle_list) ? 1 : 0; - + is_gen3 = usb_match_id(intf, gen3_list) ? 1 : 0; is_microsoft_gen1 = usb_match_id(intf, microsoft_gen1_list) ? 1 : 0; /* step through the endpoints to find first bulk in and out endpoint */ @@ -985,14 +1124,7 @@ "found\n"); ep_in = ep; ep_in->bmAttributes = USB_ENDPOINT_XFER_INT; - if (is_pinnacle) - /* - * setting seems to 1 seem to cause issues with - * Pinnacle timing out on transfer. - */ - ep_in->bInterval = ep->bInterval; - else - ep_in->bInterval = 1; + ep_in->bInterval = 1; } if ((ep_out == NULL) @@ -1007,14 +1139,7 @@ "found\n"); ep_out = ep; ep_out->bmAttributes = USB_ENDPOINT_XFER_INT; - if (is_pinnacle) - /* - * setting seems to 1 seem to cause issues with - * Pinnacle timing out on transfer. - */ - ep_out->bInterval = ep->bInterval; - else - ep_out->bInterval = 1; + ep_out->bInterval = 1; } } if (ep_in == NULL || ep_out == NULL) { @@ -1029,39 +1154,27 @@ mem_failure = 0; ir = kzalloc(sizeof(struct mceusb_dev), GFP_KERNEL); - if (!ir) { - mem_failure = 1; - goto mem_failure_switch; - } + if (!ir) + goto mem_alloc_fail; driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); - if (!driver) { - mem_failure = 2; - goto mem_failure_switch; - } + if (!driver) + goto mem_alloc_fail; - rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); - if (!rbuf) { - mem_failure = 3; - goto mem_failure_switch; - } - - if (lirc_buffer_init(rbuf, sizeof(lirc_t), LIRCBUF_SIZE)) { - mem_failure = 4; - goto mem_failure_switch; - } - - ir->buf_in = usb_buffer_alloc(dev, maxp, GFP_ATOMIC, &ir->dma_in); - if (!ir->buf_in) { - mem_failure = 5; - goto mem_failure_switch; - } + rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL); + if (!rbuf) + goto mem_alloc_fail; + + if (lirc_buffer_init(rbuf, sizeof(lirc_t), LIRCBUF_SIZE)) + goto mem_alloc_fail; + + ir->buf_in = usb_alloc_coherent(dev, maxp, GFP_ATOMIC, &ir->dma_in); + if (!ir->buf_in) + goto buf_in_alloc_fail; ir->urb_in = usb_alloc_urb(0, GFP_KERNEL); - if (!ir->urb_in) { - mem_failure = 7; - goto mem_failure_switch; - } + if (!ir->urb_in) + goto urb_in_alloc_fail; strcpy(driver->name, DRIVER_NAME " "); driver->minor = -1; @@ -1078,33 +1191,12 @@ driver->dev = &intf->dev; driver->owner = THIS_MODULE; - mutex_init(&ir->lock); + mutex_init(&ir->dev_lock); init_waitqueue_head(&ir->wait_out); minor = lirc_register_driver(driver); if (minor < 0) - mem_failure = 9; - -mem_failure_switch: - - switch (mem_failure) { - case 9: - usb_free_urb(ir->urb_in); - case 7: - usb_buffer_free(dev, maxp, ir->buf_in, ir->dma_in); - case 5: - lirc_buffer_free(rbuf); - case 4: - kfree(rbuf); - case 3: - kfree(driver); - case 2: - kfree(ir); - case 1: - printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n", - devnum, mem_failure); - return -ENOMEM; - } + goto lirc_register_fail; driver->minor = minor; ir->d = driver; @@ -1113,7 +1205,6 @@ ir->len_in = maxp; ir->overflow_len = 0; ir->flags.connected = 0; - ir->flags.pinnacle = is_pinnacle; ir->flags.microsoft_gen1 = is_microsoft_gen1; ir->flags.transmitter_mask_inverted = usb_match_id(intf, transmitter_mask_list) ? 0 : 1; @@ -1121,8 +1212,6 @@ ir->lircdata = PULSE_MASK; ir->is_pulse = 0; - /* ir->flags.transmitter_mask_inverted must be set */ - set_transmitter_mask(ir, MCE_DEFAULT_TX_MASK); /* Saving usb interface data for use by the transmitter routine */ ir->usb_ep_in = ep_in; ir->usb_ep_out = ep_out; @@ -1139,73 +1228,49 @@ printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", devnum, name, dev->bus->busnum, devnum); - /* inbound data */ + /* flush buffers on the device */ + mce_sync_in(ir, NULL, maxp); + mce_sync_in(ir, NULL, maxp); + + /* wire up inbound data handler */ usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in, maxp, (usb_complete_t) mceusb_dev_recv, ir, ep_in->bInterval); ir->urb_in->transfer_dma = ir->dma_in; ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* initialize device */ - if (ir->flags.pinnacle) { - int usbret; - - /* - * I have no idea why but this reset seems to be crucial to - * getting the device to do outbound IO correctly - without - * this the device seems to hang, ignoring all input - although - * IR signals are correctly sent from the device, no input is - * interpreted by the device and the host never does the - * completion routine - */ - - usbret = usb_reset_configuration(dev); - printk(DRIVER_NAME "[%d]: usb reset config ret %x\n", - devnum, usbret); - - /* - * its possible we really should wait for a return - * for each of these... - */ - request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND); - request_packet_async(ir, ep_out, pin_init1, sizeof(pin_init1), - MCEUSB_OUTBOUND); - request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND); - request_packet_async(ir, ep_out, pin_init2, sizeof(pin_init2), - MCEUSB_OUTBOUND); - request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND); - request_packet_async(ir, ep_out, pin_init3, sizeof(pin_init3), - MCEUSB_OUTBOUND); - } else if (ir->flags.microsoft_gen1) { - /* original ms mce device requires some additional setup */ + if (ir->flags.microsoft_gen1) mceusb_gen1_init(ir); - } else { + else if (!is_gen3) + mceusb_gen2_init(ir); - request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND); - request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND); - request_packet_async(ir, ep_out, init1, - sizeof(init1), MCEUSB_OUTBOUND); - request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND); - request_packet_async(ir, ep_out, init2, - sizeof(init2), MCEUSB_OUTBOUND); - } + mceusb_get_parameters(ir); - /* - * if we don't issue the correct number of receives (MCEUSB_INBOUND) - * for each outbound, then the first few ir pulses will be interpreted - * by the usb_async_callback routine - we should ensure we have the - * right amount OR less - as the meusb_dev_recv routine will handle - * the control packets OK - they start with 0x9f - but the async - * callback doesn't handle ir pulse packets - */ - request_packet_async(ir, ep_in, NULL, maxp, 0); + /* ir->flags.transmitter_mask_inverted must be set */ + set_transmitter_mask(ir, MCE_DEFAULT_TX_MASK); usb_set_intfdata(intf, ir); return 0; + + /* Error-handling path */ +lirc_register_fail: + usb_free_urb(ir->urb_in); +urb_in_alloc_fail: + usb_free_coherent(dev, maxp, ir->buf_in, ir->dma_in); +buf_in_alloc_fail: + lirc_buffer_free(rbuf); +mem_alloc_fail: + kfree(rbuf); + kfree(driver); + kfree(ir); + printk(KERN_ERR "out of memory (code=%d)\n", mem_failure); + + return -ENOMEM; } -static void mceusb_dev_disconnect(struct usb_interface *intf) +static void __devexit mceusb_dev_disconnect(struct usb_interface *intf) { struct usb_device *dev = interface_to_usbdev(intf); struct mceusb_dev *ir = usb_get_intfdata(intf); @@ -1218,11 +1283,11 @@ ir->usbdev = NULL; wake_up_all(&ir->wait_out); - mutex_lock(&ir->lock); + mutex_lock(&ir->dev_lock); usb_kill_urb(ir->urb_in); usb_free_urb(ir->urb_in); - usb_buffer_free(dev, ir->len_in, ir->buf_in, ir->dma_in); - mutex_unlock(&ir->lock); + usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in); + mutex_unlock(&ir->dev_lock); unregister_from_lirc(ir); } --- drivers/lirc_streamzap/lirc_streamzap.c 2010/03/17 14:16:16 1.48 +++ drivers/lirc_streanzap/lirc_streamzap.c 2010/07/25 16:43:33 1.54 @@ -1,4 +1,4 @@ -/* $Id: lirc_streamzap.c,v 1.48 2009/03/15 09:34:00 lirc Exp $ */ +/* $Id: lirc_streamzap.c,v 1.54 2010/07/25 16:43:33 jarodwilson Exp $ */ /* * Streamzap Remote Control driver * @@ -54,7 +56,7 @@ #include "drivers/kcompat.h" #include "drivers/lirc_dev/lirc_dev.h" -#define DRIVER_VERSION "$Revision: 1.48 $" +#define DRIVER_VERSION "$Revision: 1.54 $" #define DRIVER_NAME "lirc_streamzap" #define DRIVER_DESC "Streamzap Remote Control driver" @@ -83,10 +85,11 @@ #define STREAMZAP_PULSE_MASK 0xf0 #define STREAMZAP_SPACE_MASK 0x0f +#define STREAMZAP_TIMEOUT 0xff #define STREAMZAP_RESOLUTION 256 /* number of samples buffered */ -#define STREAMZAP_BUFFER_SIZE 128 +#define STREAMZAP_BUFFER_SIZE 256 enum StreamzapDecoderState { PulseSpace, @@ -154,6 +157,7 @@ struct timer_list flush_timer; int flush; int in_use; + int timeout_enabled; }; @@ -317,12 +321,14 @@ deltv = sz->signal_start.tv_sec-sz->signal_last.tv_sec; if (deltv > 15) { - tmp = PULSE_MASK; /* really long time */ + /* really long time */ + tmp = LIRC_SPACE(LIRC_VALUE_MASK); } else { tmp = (lirc_t) (deltv*1000000+ sz->signal_start.tv_usec - sz->signal_last.tv_usec); tmp -= sz->sum; + tmp = LIRC_SPACE(tmp); } dprintk("ls %u", sz->driver.minor, tmp); push(sz, (char *)&tmp); @@ -334,7 +340,7 @@ pulse = ((lirc_t) value)*STREAMZAP_RESOLUTION; pulse += STREAMZAP_RESOLUTION/2; sz->sum += pulse; - pulse |= PULSE_BIT; + pulse = LIRC_PULSE(pulse); dprintk("p %u", sz->driver.minor, pulse&PULSE_MASK); push(sz, (char *)&pulse); @@ -354,6 +360,7 @@ space = ((lirc_t) value)*STREAMZAP_RESOLUTION; space += STREAMZAP_RESOLUTION/2; sz->sum += space; + space = LIRC_SPACE(space); dprintk("s %u", sz->driver.minor, space); push(sz, (char *)&space); } @@ -426,9 +433,16 @@ sz->decoder_state = IgnorePulse; break; case FullSpace: - if (sz->buf_in[i] == 0xff) { + if (sz->buf_in[i] == STREAMZAP_TIMEOUT) { sz->idle = 1; stop_timer(sz); + if (sz->timeout_enabled) { + lirc_t timeout = + LIRC_TIMEOUT + (STREAMZAP_TIMEOUT * + STREAMZAP_RESOLUTION); + push(sz, (char *)&timeout); + } flush_delay_buffer(sz); } else push_full_space(sz, sz->buf_in[i]); @@ -546,8 +560,8 @@ sz->buf_in_len = sz->endpoint->wMaxPacketSize; #ifdef KERNEL_2_5 - sz->buf_in = usb_buffer_alloc(sz->udev, sz->buf_in_len, - GFP_ATOMIC, &sz->dma_in); + sz->buf_in = usb_alloc_coherent(sz->udev, sz->buf_in_len, + GFP_ATOMIC, &sz->dma_in); #else sz->buf_in = kmalloc(sz->buf_in_len, GFP_KERNEL); #endif @@ -579,8 +593,12 @@ sz->driver.minor = -1; sz->driver.sample_rate = 0; sz->driver.code_length = sizeof(lirc_t) * 8; - sz->driver.features = LIRC_CAN_REC_MODE2 | LIRC_CAN_GET_REC_RESOLUTION; + sz->driver.features = LIRC_CAN_REC_MODE2 | + LIRC_CAN_GET_REC_RESOLUTION | + LIRC_CAN_SET_REC_TIMEOUT; sz->driver.data = sz; + sz->driver.min_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION; + sz->driver.max_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION; sz->driver.rbuf = &sz->lirc_buf; sz->driver.set_use_inc = &streamzap_use_inc; sz->driver.set_use_dec = &streamzap_use_dec; @@ -657,7 +675,7 @@ if (sz) { usb_free_urb(sz->urb_in); #ifdef KERNEL_2_5 - usb_buffer_free(udev, sz->buf_in_len, sz->buf_in, sz->dma_in); + usb_free_coherent(udev, sz->buf_in_len, sz->buf_in, sz->dma_in); #else if (sz->buf_in) { kfree(sz->buf_in); @@ -691,6 +709,8 @@ sz->flush = 1; add_timer(&sz->flush_timer); + sz->timeout_enabled = 0; + sz->urb_in->dev = sz->udev; #ifdef KERNEL_2_5 if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) { @@ -733,18 +753,35 @@ static int streamzap_ioctl(struct inode *node, struct file *filep, unsigned int cmd, unsigned long arg) { - int result; + int result = 0; + lirc_t val; + unsigned int flag = 0; + struct usb_streamzap *sz = lirc_get_pdata(filep); switch (cmd) { case LIRC_GET_REC_RESOLUTION: result = put_user(STREAMZAP_RESOLUTION, (unsigned int *) arg); - if (result) - return result; + break; + case LIRC_SET_REC_TIMEOUT: + result = get_user(val, (lirc_t *)arg); + if (result == 0) { + if (val != STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION) + result = -EINVAL; + } + break; + case LIRC_SET_REC_TIMEOUT_REPORTS: + result = get_user(flag, (unsigned int *)arg); + if (result == 0) { + if (flag != 0) + sz->timeout_enabled = 1; + else + sz->timeout_enabled = 0; + } break; default: return -ENOIOCTLCMD; } - return 0; + return result; } /** @@ -788,7 +825,7 @@ usb_free_urb(sz->urb_in); #ifdef KERNEL_2_5 - usb_buffer_free(sz->udev, sz->buf_in_len, sz->buf_in, sz->dma_in); + usb_free_coherent(sz->udev, sz->buf_in_len, sz->buf_in, sz->dma_in); #else kfree(sz->buf_in); #endif --- drivers/lirc.h 2009/08/29 07:52:41 5.19 +++ drivers/lirc.h 2010/05/13 15:45:48 5.27 @@ -1,4 +1,4 @@ -/* $Id: lirc.h,v 5.19 2009/08/29 07:52:41 lirc Exp $ */ +/* $Id: lirc.h,v 5.27 2010/05/13 15:45:48 lirc Exp $ */ #ifndef _LINUX_LIRC_H #define _LINUX_LIRC_H @@ -12,8 +12,31 @@ #include #endif -#define PULSE_BIT 0x01000000 -#define PULSE_MASK 0x00FFFFFF +/* */ +#define PULSE_BIT 0x01000000 +#define PULSE_MASK 0x00FFFFFF +/* */ + +#define LIRC_MODE2_SPACE 0x00000000 +#define LIRC_MODE2_PULSE 0x01000000 +#define LIRC_MODE2_FREQUENCY 0x02000000 +#define LIRC_MODE2_TIMEOUT 0x03000000 + +#define LIRC_VALUE_MASK 0x00FFFFFF +#define LIRC_MODE2_MASK 0xFF000000 + +#define LIRC_SPACE(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_SPACE) +#define LIRC_PULSE(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_PULSE) +#define LIRC_FREQUENCY(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_FREQUENCY) +#define LIRC_TIMEOUT(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_TIMEOUT) + +#define LIRC_VALUE(val) ((val)&LIRC_VALUE_MASK) +#define LIRC_MODE2(val) ((val)&LIRC_MODE2_MASK) + +#define LIRC_IS_SPACE(val) (LIRC_MODE2(val) == LIRC_MODE2_SPACE) +#define LIRC_IS_PULSE(val) (LIRC_MODE2(val) == LIRC_MODE2_PULSE) +#define LIRC_IS_FREQUENCY(val) (LIRC_MODE2(val) == LIRC_MODE2_FREQUENCY) +#define LIRC_IS_TIMEOUT(val) (LIRC_MODE2(val) == LIRC_MODE2_TIMEOUT) typedef int lirc_t; @@ -27,17 +50,17 @@ #define LIRC_MODE_RAW 0x00000001 #define LIRC_MODE_PULSE 0x00000002 #define LIRC_MODE_MODE2 0x00000004 -#define LIRC_MODE_CODE 0x00000008 +/* obsolete: #define LIRC_MODE_CODE 0x00000008 */ #define LIRC_MODE_LIRCCODE 0x00000010 -#define LIRC_MODE_STRING 0x00000020 +/* obsolete: #define LIRC_MODE_STRING 0x00000020 */ #define LIRC_CAN_SEND_RAW LIRC_MODE2SEND(LIRC_MODE_RAW) #define LIRC_CAN_SEND_PULSE LIRC_MODE2SEND(LIRC_MODE_PULSE) #define LIRC_CAN_SEND_MODE2 LIRC_MODE2SEND(LIRC_MODE_MODE2) -#define LIRC_CAN_SEND_CODE LIRC_MODE2SEND(LIRC_MODE_CODE) +/* obsolete: #define LIRC_CAN_SEND_CODE LIRC_MODE2SEND(LIRC_MODE_CODE) */ #define LIRC_CAN_SEND_LIRCCODE LIRC_MODE2SEND(LIRC_MODE_LIRCCODE) -#define LIRC_CAN_SEND_STRING LIRC_MODE2SEND(LIRC_MODE_STRING) +/* obsolete: #define LIRC_CAN_SEND_STRING LIRC_MODE2SEND(LIRC_MODE_STRING) */ #define LIRC_CAN_SEND_MASK 0x0000003f @@ -48,9 +71,9 @@ #define LIRC_CAN_REC_RAW LIRC_MODE2REC(LIRC_MODE_RAW) #define LIRC_CAN_REC_PULSE LIRC_MODE2REC(LIRC_MODE_PULSE) #define LIRC_CAN_REC_MODE2 LIRC_MODE2REC(LIRC_MODE_MODE2) -#define LIRC_CAN_REC_CODE LIRC_MODE2REC(LIRC_MODE_CODE) +/* obsolete: #define LIRC_CAN_REC_CODE LIRC_MODE2REC(LIRC_MODE_CODE) */ #define LIRC_CAN_REC_LIRCCODE LIRC_MODE2REC(LIRC_MODE_LIRCCODE) -#define LIRC_CAN_REC_STRING LIRC_MODE2REC(LIRC_MODE_STRING) +/* obsolete: #define LIRC_CAN_REC_STRING LIRC_MODE2REC(LIRC_MODE_STRING) */ #define LIRC_CAN_REC_MASK LIRC_MODE2REC(LIRC_CAN_SEND_MASK) @@ -60,6 +83,10 @@ #define LIRC_CAN_SET_REC_DUTY_CYCLE_RANGE 0x40000000 #define LIRC_CAN_SET_REC_CARRIER_RANGE 0x80000000 #define LIRC_CAN_GET_REC_RESOLUTION 0x20000000 +#define LIRC_CAN_SET_REC_TIMEOUT 0x10000000 +#define LIRC_CAN_SET_REC_FILTER 0x08000000 + +#define LIRC_CAN_MEASURE_CARRIER 0x02000000 #define LIRC_CAN_SEND(x) ((x)&LIRC_CAN_SEND_MASK) #define LIRC_CAN_REC(x) ((x)&LIRC_CAN_REC_MASK) @@ -78,10 +105,23 @@ #define LIRC_GET_REC_DUTY_CYCLE _IOR('i', 0x00000006, unsigned int) #define LIRC_GET_REC_RESOLUTION _IOR('i', 0x00000007, unsigned int) +#define LIRC_GET_MIN_TIMEOUT _IOR('i', 0x00000008, lirc_t) +#define LIRC_GET_MAX_TIMEOUT _IOR('i', 0x00000009, lirc_t) + +#define LIRC_GET_MIN_FILTER_PULSE _IOR('i', 0x0000000a, lirc_t) +#define LIRC_GET_MAX_FILTER_PULSE _IOR('i', 0x0000000b, lirc_t) +#define LIRC_GET_MIN_FILTER_SPACE _IOR('i', 0x0000000c, lirc_t) +#define LIRC_GET_MAX_FILTER_SPACE _IOR('i', 0x0000000d, lirc_t) + /* code length in bits, currently only for LIRC_MODE_LIRCCODE */ #define LIRC_GET_LENGTH _IOR('i', 0x0000000f, unsigned long) +/* all values set should be reset by the driver when the device is + reopened */ + +/* obsolete: drivers only support one mode */ #define LIRC_SET_SEND_MODE _IOW('i', 0x00000011, unsigned long) +/* obsolete: drivers only support one mode */ #define LIRC_SET_REC_MODE _IOW('i', 0x00000012, unsigned long) /* Note: these can reset the according pulse_width */ #define LIRC_SET_SEND_CARRIER _IOW('i', 0x00000013, unsigned int) @@ -90,6 +130,26 @@ #define LIRC_SET_REC_DUTY_CYCLE _IOW('i', 0x00000016, unsigned int) #define LIRC_SET_TRANSMITTER_MASK _IOW('i', 0x00000017, unsigned int) +/* a value of 0 disables all hardware timeouts and data should be + reported as soon as possible */ +#define LIRC_SET_REC_TIMEOUT _IOW('i', 0x00000018, lirc_t) +/* 1 enables, 0 disables timeout reports in MODE2 */ +#define LIRC_SET_REC_TIMEOUT_REPORTS _IOW('i', 0x00000019, unsigned int) + +/* pulses shorter than this are filtered out by hardware (software + emulation in lirc_dev/lircd?) */ +#define LIRC_SET_REC_FILTER_PULSE _IOW('i', 0x0000001a, lirc_t) +/* spaces shorter than this are filtered out by hardware (software + emulation in lirc_dev/lircd?) */ +#define LIRC_SET_REC_FILTER_SPACE _IOW('i', 0x0000001b, lirc_t) +/* if filter cannot be set independently for pulse/space, this should + be used */ +#define LIRC_SET_REC_FILTER _IOW('i', 0x0000001c, lirc_t) + +/* if enabled from the next key press on the driver will send + LIRC_MODE2_FREQUENCY packets */ +#define LIRC_SET_MEASURE_CARRIER_MODE _IOW('i', 0x0000001d, unsigned int) + /* * to set a range use * LIRC_SET_REC_DUTY_CYCLE_RANGE/LIRC_SET_REC_CARRIER_RANGE with the @@ -102,4 +162,7 @@ #define LIRC_NOTIFY_DECODE _IO('i', 0x00000020) +#define LIRC_SETUP_START _IO('i', 0x00000021) +#define LIRC_SETUP_END _IO('i', 0x00000022) + #endif --- drivers/lirc_dev/lirc_dev.c 2009/08/31 16:57:55 1.96 +++ drivers/lirc_dev/lirc_dev.c 2010/05/13 15:45:48 1.105 @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * $Id: lirc_dev.c,v 1.96 2009/08/31 16:57:55 lirc Exp $ + * $Id: lirc_dev.c,v 1.105 2010/05/13 15:45:48 lirc Exp $ * */ @@ -367,8 +369,7 @@ ir->chunk_size = ir->buf->chunk_size; if (d->features == 0) - d->features = (d->code_length > 8) ? - LIRC_CAN_REC_LIRCCODE : LIRC_CAN_REC_CODE; + d->features = LIRC_CAN_REC_LIRCCODE; ir->d = *d; ir->d.minor = minor; @@ -541,7 +542,7 @@ static int irctl_open(struct inode *inode, struct file *file) { struct irctl *ir; - int retval; + int retval = 0; if (iminor(inode) >= MAX_IRCTL_DEVICES || !irctls[iminor(inode)]) { dprintk("lirc_dev [%d]: open result = -ENODEV\n", @@ -591,6 +592,8 @@ if (ir->task) wake_up_process(ir->task); #endif + } else { + retval = -ENODEV; } error: if (ir) @@ -692,6 +695,23 @@ case LIRC_GET_FEATURES: result = put_user(ir->d.features, (unsigned long *)arg); break; + case LIRC_GET_LENGTH: + result = put_user(ir->d.code_length, (unsigned long *) arg); + break; + case LIRC_GET_MIN_TIMEOUT: + if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) || + ir->d.min_timeout == 0) + return -ENOSYS; + + result = put_user(ir->d.min_timeout, (lirc_t *) arg); + break; + case LIRC_GET_MAX_TIMEOUT: + if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) || + ir->d.max_timeout == 0) + return -ENOSYS; + + result = put_user(ir->d.max_timeout, (lirc_t *) arg); + break; case LIRC_GET_REC_MODE: if (!(ir->d.features & LIRC_CAN_REC_MASK)) return -ENOSYS; @@ -700,6 +720,16 @@ (ir->d.features & LIRC_CAN_REC_MASK), (unsigned long *)arg); break; + case LIRC_GET_SEND_MODE: + if (!(ir->d.features & LIRC_CAN_SEND_MASK)) + return -ENOSYS; + + result = put_user(LIRC_SEND2MODE + (ir->d.features & LIRC_CAN_SEND_MASK), + (unsigned long *)arg); + break; + + /*obsolete */ case LIRC_SET_REC_MODE: if (!(ir->d.features & LIRC_CAN_REC_MASK)) return -ENOSYS; @@ -707,18 +737,30 @@ result = get_user(mode, (unsigned long *)arg); if (!result && !(LIRC_MODE2REC(mode) & ir->d.features)) result = -EINVAL; - /* - * FIXME: We should actually set the mode somehow but - * for now, lirc_serial doesn't support mode changing either - */ break; - case LIRC_GET_LENGTH: - result = put_user(ir->d.code_length, (unsigned long *) arg); + case LIRC_SET_SEND_MODE: + if (!(ir->d.features & LIRC_CAN_SEND_MASK)) + return -ENOSYS; + + result = get_user(mode, (unsigned long *)arg); + if (!result && !(LIRC_MODE2SEND(mode) & ir->d.features)) + result = -EINVAL; break; default: result = -EINVAL; } + switch (cmd) { + case LIRC_SET_REC_MODE: + case LIRC_SET_SEND_MODE: + printk(KERN_NOTICE LOGHEAD "userspace uses outdated ioctl " + "please update your lirc installation\n", + ir->d.name, ir->d.minor); + break; + default: + break; + } + dprintk(LOGHEAD "ioctl result = %d\n", ir->d.name, ir->d.minor, result); @@ -791,16 +833,31 @@ case LIRC_GET_SEND_DUTY_CYCLE: case LIRC_GET_REC_DUTY_CYCLE: case LIRC_GET_REC_RESOLUTION: + case LIRC_GET_MIN_TIMEOUT: + case LIRC_GET_MAX_TIMEOUT: + case LIRC_GET_MIN_FILTER_PULSE: + case LIRC_GET_MAX_FILTER_PULSE: + case LIRC_GET_MIN_FILTER_SPACE: + case LIRC_GET_MAX_FILTER_SPACE: case LIRC_SET_SEND_CARRIER: case LIRC_SET_REC_CARRIER: case LIRC_SET_SEND_DUTY_CYCLE: case LIRC_SET_REC_DUTY_CYCLE: case LIRC_SET_TRANSMITTER_MASK: + case LIRC_SET_REC_TIMEOUT: + case LIRC_SET_REC_TIMEOUT_REPORTS: + case LIRC_SET_REC_FILTER_PULSE: + case LIRC_SET_REC_FILTER_SPACE: + case LIRC_SET_REC_FILTER: + case LIRC_SET_MEASURE_CARRIER_MODE: case LIRC_SET_REC_DUTY_CYCLE_RANGE: case LIRC_SET_REC_CARRIER_RANGE: + case LIRC_NOTIFY_DECODE: + case LIRC_SETUP_START: + case LIRC_SETUP_END: /* - * These commands expect (unsigned int *)arg - * so no problems here. Just handle the locking. + * These commands expect (unsigned int *) or (lirc_t *) + * arg so no problems here. Just handle the locking. */ lock_kernel(); cmd = cmd32; --- drivers/lirc_dev/lirc_dev.h 2009/12/28 15:21:17 1.38 +++ drivers/lirc_dev/lirc_dev.h 2010/04/25 08:33:52 1.41 @@ -4,7 +4,7 @@ * (L) by Artur Lipowski * This code is licensed under GNU GPL * - * $Id: lirc_dev.h,v 1.38 2009/12/28 15:21:17 jarodwilson Exp $ + * $Id: lirc_dev.h,v 1.41 2010/04/25 08:33:52 lirc Exp $ * */ @@ -28,6 +28,8 @@ #include #endif +#include "drivers/lirc.h" + struct lirc_buffer { wait_queue_head_t wait_poll; spinlock_t fifo_lock; @@ -68,13 +70,13 @@ #endif static inline void lirc_buffer_clear(struct lirc_buffer *buf) { - unsigned long flags; - #ifdef LIRC_HAVE_KFIFO #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) if (buf->fifo) kfifo_reset(buf->fifo); #else + unsigned long flags; + if (buf->fifo_initialized) { spin_lock_irqsave(&buf->fifo_lock, flags); kfifo_reset(&buf->fifo); @@ -82,6 +84,8 @@ } #endif #else + unsigned long flags; + lirc_buffer_lock(buf, &flags); _lirc_buffer_clear(buf); lirc_buffer_unlock(buf, &flags); @@ -331,6 +335,8 @@ int sample_rate; unsigned long features; void *data; + lirc_t min_timeout; + lirc_t max_timeout; int (*add_to_buf) (void *data, struct lirc_buffer *buf); #ifndef LIRC_REMOVE_DURING_EXPORT wait_queue_head_t* (*get_queue) (void *data); @@ -338,7 +344,7 @@ struct lirc_buffer *rbuf; int (*set_use_inc) (void *data); void (*set_use_dec) (void *data); - struct file_operations *fops; + const struct file_operations *fops; struct device *dev; struct module *owner; };