diff options
author | Mario Limonciello <superm1@ubuntu.com> | 2010-08-18 11:08:32 -0500 |
---|---|---|
committer | Leann Ogasawara <leann.ogasawara@canonical.com> | 2010-09-02 13:48:38 -0700 |
commit | 60d134446074116c190be32f665fc6fd06c977de (patch) | |
tree | f93a7271eee19dd39e9ed92d41de1979213db393 /ubuntu | |
parent | 71d1ddca8515d3ddbb964aa7489e31b7f84b5afa (diff) |
UBUNTU: Remove ubuntu/lirc in favor of staging/lirc from 2.6.36
BugLink: http://bugs.launchpad.net/bugs/609234
ExternalDriver: LIRC
Description: Linux Infrared Remote Control
Url: www.lirc.org
Mask:
Version: 0.8.6
Remove: yes
Signed-off-by: Mario Limonciello <superm1@ubuntu.com>
Acked-by: Tim Gardner <tim.gardner@canonical.com>
Signed-off-by: Leann Ogasawara <leann.ogasawara@canonical.com>
Diffstat (limited to 'ubuntu')
49 files changed, 0 insertions, 19443 deletions
diff --git a/ubuntu/Kconfig b/ubuntu/Kconfig index b4d435002de..ad2d2c4d127 100644 --- a/ubuntu/Kconfig +++ b/ubuntu/Kconfig @@ -5,7 +5,6 @@ source "ubuntu/compcache/Kconfig" source "ubuntu/dm-raid4-5/Kconfig" source "ubuntu/fsam7400/Kconfig" source "ubuntu/iscsitarget/Kconfig" -source "ubuntu/lirc/Kconfig" source "ubuntu/ndiswrapper/Kconfig" source "ubuntu/omnibook/Kconfig" source "ubuntu/rtl8192se/Kconfig" diff --git a/ubuntu/Makefile b/ubuntu/Makefile index 770204f521c..fb365185a37 100644 --- a/ubuntu/Makefile +++ b/ubuntu/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_BLK_DEV_COMPCACHE) += compcache/ obj-$(CONFIG_DM_RAID45) += dm-raid4-5/ obj-$(CONFIG_FSAM7400) += fsam7400/ obj-$(CONFIG_SCSI_ISCSITARGET) += iscsitarget/ -obj-$(CONFIG_LIRC_DEV) += lirc/ obj-$(CONFIG_NDISWRAPPER) += ndiswrapper/ obj-$(CONFIG_OMNIBOOK) += omnibook/ obj-$(CONFIG_RTL8192SE) += rtl8192se/ diff --git a/ubuntu/lirc/Kconfig b/ubuntu/lirc/Kconfig deleted file mode 100644 index 21dcc40d1f9..00000000000 --- a/ubuntu/lirc/Kconfig +++ /dev/null @@ -1,88 +0,0 @@ -config LIRC_DEV - tristate "LIRC Device support" - default m - -config LIRC_ATIUSB - tristate "LIRC ATI RF Remote" - default m - depends on LIRC_DEV - -config LIRC_BT829 - tristate "LIRC BT829" - default m - depends on LIRC_DEV - -config LIRC_ENE0100 - tristate "LIRC ENE0100" - default m - depends on LIRC_DEV - -config LIRC_I2C - tristate "LIRC I2C interface remote" - default m - depends on LIRC_DEV - -config LIRC_IGORPLUGUSB - tristate "LIRC IGOR custom remote" - default m - depends on LIRC_DEV - -config LIRC_IMON - tristate "LIRC Imon remote or pad" - default m - depends on LIRC_DEV - -config LIRC_IT87 - tristate "LIRC IT87" - default m - depends on LIRC_DEV - -config LIRC_ITE8709 - tristate "LIRC ITE8709" - default m - depends on LIRC_DEV - -config LIRC_MCEUSB - tristate "LIRC Microsoft Media Center Remote" - default m - depends on LIRC_DEV - -config LIRC_PARALLEL - tristate "LIRC Parallel port custom remote" - default n - depends on LIRC_DEV - -config LIRC_SASEM - tristate "LIRC Sasem" - default m - depends on LIRC_DEV - -config LIRC_SERIAL - tristate "LIRC Serial port remote" - default m - depends on LIRC_DEV - -config LIRC_SIR - tristate "LIRC Laptop port IR (SIR))" - default m - depends on LIRC_DEV - -config LIRC_STREAMZAP - tristate "LIRC Streamzap remote" - default m - depends on LIRC_DEV - -config LIRC_TTUSBIR - tristate "LIRC TT USB IR device" - default m - depends on LIRC_DEV - -config LIRC_CONFIG_LIRC_WPC8769L - tristate "LIRC WPC8769L device" - default m - depends on LIRC_DEV - -config LIRC_GPIO - tristate "LIRC TV Card GPIO remote" - default n - depends on LIRC_DEV diff --git a/ubuntu/lirc/Makefile b/ubuntu/lirc/Makefile deleted file mode 100644 index 006a6c8c97f..00000000000 --- a/ubuntu/lirc/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -#include $(src)/../../.config - -EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src) - -obj-$(CONFIG_LIRC_DEV) += lirc_dev/ -obj-$(CONFIG_LIRC_ATIUSB) += lirc_atiusb/ -obj-$(CONFIG_LIRC_BT829) += lirc_bt829/ -obj-$(CONFIG_LIRC_ENE0100) += lirc_ene0100/ -obj-$(CONFIG_LIRC_I2C) += lirc_i2c/ -obj-$(CONFIG_LIRC_IGORPLUGUSB) += lirc_igorplugusb/ -obj-$(CONFIG_LIRC_IMON) += lirc_imon/ -obj-$(CONFIG_LIRC_IT87) += lirc_it87/ -obj-$(CONFIG_LIRC_ITE8709) += lirc_ite8709/ -obj-$(CONFIG_LIRC_MCEUSB) += lirc_mceusb/ -obj-$(CONFIG_LIRC_PARALLEL) += lirc_parallel/ -obj-$(CONFIG_LIRC_SASEM) += lirc_sasem/ -obj-$(CONFIG_LIRC_SERIAL) += lirc_serial/ -obj-$(CONFIG_LIRC_SIR) += lirc_sir/ -obj-$(CONFIG_LIRC_STREAMZAP) += lirc_streamzap/ -obj-$(CONFIG_LIRC_TTUSBIR) += lirc_ttusbir/ -obj-$(CONFIG_LIRC_GPIO) += lirc_gpio/ -obj-$(CONFIG_LIRC_TTUSBIR) += lirc_ttusbir/ -obj-$(CONFIG_LIRC_WPC8769L) += lirc_wpc8769l/ diff --git a/ubuntu/lirc/kcompat.h b/ubuntu/lirc/kcompat.h deleted file mode 100644 index 1ede9429dd6..00000000000 --- a/ubuntu/lirc/kcompat.h +++ /dev/null @@ -1,402 +0,0 @@ -/* $Id: kcompat.h,v 5.44 2009/03/22 08:45:47 lirc Exp $ */ - -#ifndef _KCOMPAT_H -#define _KCOMPAT_H - -#include <linux/version.h> - -#ifndef __func__ -#define __func__ __FUNCTION__ -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16) -#define LIRC_THIS_MODULE(x) x, -#else /* >= 2.6.16 */ -#define LIRC_THIS_MODULE(x) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) - -#include <linux/device.h> - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) -#define LIRC_HAVE_DEVFS -#define LIRC_HAVE_DEVFS_26 -#endif - -#define LIRC_HAVE_SYSFS - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 13) - -typedef struct class_simple lirc_class_t; - -static inline lirc_class_t *class_create(struct module *owner, char *name) -{ - return class_simple_create(owner, name); -} - -static inline void class_destroy(lirc_class_t *cls) -{ - class_simple_destroy(cls); -} - -#define lirc_device_create(cs, parent, dev, drvdata, fmt, args...) \ - class_simple_device_add(cs, dev, parent, fmt, ## args) - -static inline void lirc_device_destroy(lirc_class_t *cls, dev_t devt) -{ - class_simple_device_remove(devt); -} - -#else /* >= 2.6.13 */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) - -#define lirc_device_create(cs, parent, dev, drvdata, fmt, args...) \ - class_device_create(cs, dev, parent, fmt, ## args) - -#else /* >= 2.6.15 */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) - -#define lirc_device_create(cs, parent, dev, drvdata, fmt, args...) \ - class_device_create(cs, NULL, dev, parent, fmt, ## args) - -#else /* >= 2.6.26 */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) - -#define lirc_device_create(cs, parent, dev, drvdata, fmt, args...) \ - device_create(cs, parent, dev, fmt, ## args) - -#else /* >= 2.6.27 */ - -#define lirc_device_create device_create - -#endif /* >= 2.6.27 */ - -#endif /* >= 2.6.26 */ - -#define LIRC_DEVFS_PREFIX - -#endif /* >= 2.6.15 */ - -typedef struct class lirc_class_t; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) - -#define lirc_device_destroy class_device_destroy - -#else - -#define lirc_device_destroy device_destroy - -#endif - -#endif /* >= 2.6.13 */ - -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) -#define LIRC_HAVE_DEVFS -#define LIRC_HAVE_DEVFS_24 -#endif - -#ifndef LIRC_DEVFS_PREFIX -#define LIRC_DEVFS_PREFIX "usb/" -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0) -#include <linux/timer.h> -#include <linux/interrupt.h> -static inline void del_timer_sync(struct timer_list *timerlist) -{ - start_bh_atomic(); - del_timer(timerlist); - end_bh_atomic(); -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) -#ifdef daemonize -#undef daemonize -#endif -#define daemonize(name) do { \ - \ - lock_kernel(); \ - \ - exit_mm(current); \ - exit_files(current); \ - exit_fs(current); \ - current->session = 1; \ - current->pgrp = 1; \ - current->euid = 0; \ - current->tty = NULL; \ - sigfillset(¤t->blocked); \ - \ - strcpy(current->comm, name); \ - \ - unlock_kernel(); \ - \ -} while (0) - -/* Not sure when this was introduced, sometime during 2.5.X */ -#define MODULE_PARM_int(x) MODULE_PARM(x, "i") -#define MODULE_PARM_bool(x) MODULE_PARM(x, "i") -#define MODULE_PARM_long(x) MODULE_PARM(x, "l") -#define module_param(x, y, z) MODULE_PARM_##y(x) -#else -#include <linux/moduleparam.h> -#endif /* Linux < 2.6.0 */ - -/* DevFS header */ -#if defined(LIRC_HAVE_DEVFS) -#include <linux/devfs_fs_kernel.h> -#endif - -#ifdef LIRC_HAVE_DEVFS_24 -#ifdef register_chrdev -#undef register_chrdev -#endif -#define register_chrdev devfs_register_chrdev -#ifdef unregister_chrdev -#undef unregister_chrdev -#endif -#define unregister_chrdev devfs_unregister_chrdev -#endif /* DEVFS 2.4 */ - -#ifndef LIRC_HAVE_SYSFS -#define class_destroy(x) do { } while (0) -#define class_create(x, y) NULL -#define lirc_device_destroy(x, y) do { } while (0) -#define lirc_device_create(x, y, z, xx, yy, zz) 0 -#define IS_ERR(x) 0 -typedef struct class_simple -{ - int notused; -} lirc_class_t; -#endif /* No SYSFS */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0) -#define KERNEL_2_5 - -/* - * We still are using MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT in the set_use_inc - * function of all modules for 2.4 kernel compatibility. - * - * For 2.6 kernels reference counting is done in lirc_dev by - * try_module_get()/module_put() because the old approach is racy. - * - */ -#ifdef MOD_INC_USE_COUNT -#undef MOD_INC_USE_COUNT -#endif -#define MOD_INC_USE_COUNT - -#ifdef MOD_DEC_USE_COUNT -#undef MOD_DEC_USE_COUNT -#endif -#define MOD_DEC_USE_COUNT - -#ifdef EXPORT_NO_SYMBOLS -#undef EXPORT_NO_SYMBOLS -#endif -#define EXPORT_NO_SYMBOLS - -#else /* Kernel < 2.5.0 */ - -static inline int try_module_get(struct module *module) -{ - return 1; -} - -static inline void module_put(struct module *module) -{ -} - -#endif /* Kernel >= 2.5.0 */ - -#ifndef MODULE_LICENSE -#define MODULE_LICENSE(x) -#endif - -#ifndef MODULE_PARM_DESC -#define MODULE_PARM_DESC(x, y) -#endif - -#ifndef MODULE_ALIAS_CHARDEV_MAJOR -#define MODULE_ALIAS_CHARDEV_MAJOR(x) -#endif - -#ifndef MODULE_DEVICE_TABLE -#define MODULE_DEVICE_TABLE(x, y) -#endif - -#include <linux/interrupt.h> -#ifndef IRQ_RETVAL -typedef void irqreturn_t; -#define IRQ_NONE -#define IRQ_HANDLED -#define IRQ_RETVAL(x) -#endif - -#ifndef MOD_IN_USE -#ifdef CONFIG_MODULE_UNLOAD -#define MOD_IN_USE module_refcount(THIS_MODULE) -#else -#error "LIRC modules currently require" -#error " 'Loadable module support ---> Module unloading'" -#error "to be enabled in the kernel" -#endif -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) -#if !defined(local_irq_save) -#define local_irq_save(flags) do { save_flags(flags); cli(); } while (0) -#endif -#if !defined(local_irq_restore) -#define local_irq_restore(flags) do { restore_flags(flags); } while (0) -#endif -#endif - -#if KERNEL_VERSION(2, 4, 0) <= LINUX_VERSION_CODE -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 22) -#include <linux/pci.h> -static inline char *pci_name(struct pci_dev *pdev) -{ - return pdev->slot_name; -} -#endif /* kernel < 2.4.22 */ -#endif /* kernel >= 2.4.0 */ - -/*************************** I2C specific *****************************/ -#include <linux/i2c.h> - -#ifndef I2C_CLIENT_END -#error "********************************************************" -#error " Sorry, this driver needs the new I2C stack. " -#error " You can get it at http://www2.lm-sensors.nu/~lm78/. " -#error "********************************************************" -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) - -#undef i2c_get_clientdata -#define i2c_get_clientdata(client) ((client)->data) - - -#undef i2c_set_clientdata -#define i2c_set_clientdata(client_ptr, new_data) do { \ - (client_ptr)->data = new_data; \ -} while (0) - - -#endif - -/* removed in 2.6.14 */ -#ifndef I2C_ALGO_BIT -# define I2C_ALGO_BIT 0 -#endif - -/* removed in 2.6.16 */ -#ifndef I2C_DRIVERID_EXP3 -# define I2C_DRIVERID_EXP3 0xf003 -#endif - -/*************************** USB specific *****************************/ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) -#include <linux/usb.h> - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 8) -static inline int usb_kill_urb(struct urb *urb) -{ - return usb_unlink_urb(urb); -} -#endif - -/* removed in 2.6.14 */ -#ifndef URB_ASYNC_UNLINK -#define URB_ASYNC_UNLINK 0 -#endif -#endif - -/*************************** bttv specific ****************************/ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) /* BTTV_* -> BTTV_BOARD_* */ -#define BTTV_BOARD_UNKNOWN BTTV_UNKNOWN -#define BTTV_BOARD_PXELVWPLTVPAK BTTV_PXELVWPLTVPAK -#define BTTV_BOARD_PXELVWPLTVPRO BTTV_PXELVWPLTVPRO -#define BTTV_BOARD_PV_BT878P_9B BTTV_PV_BT878P_9B -#define BTTV_BOARD_PV_BT878P_PLUS BTTV_PV_BT878P_PLUS -#define BTTV_BOARD_AVERMEDIA BTTV_AVERMEDIA -#define BTTV_BOARD_AVPHONE98 BTTV_AVPHONE98 -#define BTTV_BOARD_AVERMEDIA98 BTTV_AVERMEDIA98 -#define BTTV_BOARD_CHRONOS_VS2 BTTV_CHRONOS_VS2 -#define BTTV_BOARD_MIRO BTTV_MIRO -#define BTTV_BOARD_DYNALINK BTTV_DYNALINK -#define BTTV_BOARD_WINVIEW_601 BTTV_WINVIEW_601 -#ifdef BTTV_KWORLD -#define BTTV_BOARD_KWORLD BTTV_KWORLD -#endif -#define BTTV_BOARD_MAGICTVIEW061 BTTV_MAGICTVIEW061 -#define BTTV_BOARD_MAGICTVIEW063 BTTV_MAGICTVIEW063 -#define BTTV_BOARD_PHOEBE_TVMAS BTTV_PHOEBE_TVMAS -#ifdef BTTV_BESTBUY_EASYTV2 -#define BTTV_BOARD_BESTBUY_EASYTV BTTV_BESTBUY_EASYTV -#define BTTV_BOARD_BESTBUY_EASYTV2 BTTV_BESTBUY_EASYTV2 -#endif -#define BTTV_BOARD_FLYVIDEO BTTV_FLYVIDEO -#define BTTV_BOARD_FLYVIDEO_98 BTTV_FLYVIDEO_98 -#define BTTV_BOARD_TYPHOON_TVIEW BTTV_TYPHOON_TVIEW -#ifdef BTTV_FLYVIDEO_98FM -#define BTTV_BOARD_FLYVIDEO_98FM BTTV_FLYVIDEO_98FM -#endif -#define BTTV_BOARD_WINFAST2000 BTTV_WINFAST2000 -#ifdef BTTV_GVBCTV5PCI -#define BTTV_BOARD_GVBCTV5PCI BTTV_GVBCTV5PCI -#endif -#endif /* end BTTV_* -> BTTV_BOARD_* */ - - -/******************************* pm.h *********************************/ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) -typedef u32 pm_message_t; -#endif /* kernel < 2.6.11 */ -#endif /* kernel >= 2.6.0 */ - -/*************************** interrupt.h ******************************/ -/* added in 2.6.18, old defines removed in 2.6.24 */ -#ifndef IRQF_DISABLED -#define IRQF_DISABLED SA_INTERRUPT -#endif -#ifndef IRQF_SHARED -#define IRQF_SHARED SA_SHIRQ -#endif - -/*************************** spinlock.h *******************************/ -/* added in 2.6.11 */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) -#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED -#endif - -/***************************** slab.h *********************************/ -/* added in 2.6.14 */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14) -static inline void *kzalloc(size_t size, gfp_t flags) -{ - void *ret = kmalloc(size, flags); - if (ret) - memset(ret, 0, size); - return ret; -} -#endif - -/****************************** fs.h **********************************/ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) -static inline unsigned iminor(struct inode *inode) -{ - return MINOR(inode->i_rdev); -} -#endif - -#endif /* _KCOMPAT_H */ diff --git a/ubuntu/lirc/lirc.h b/ubuntu/lirc/lirc.h deleted file mode 100644 index 7c4d09e0c44..00000000000 --- a/ubuntu/lirc/lirc.h +++ /dev/null @@ -1,105 +0,0 @@ -/* $Id: lirc.h,v 5.19 2009/08/29 07:52:41 lirc Exp $ */ - -#ifndef _LINUX_LIRC_H -#define _LINUX_LIRC_H - -#if defined(__linux__) -#include <linux/ioctl.h> -#elif defined(_NetBSD_) -#include <sys/ioctl.h> -#elif defined(_CYGWIN_) -#define __USE_LINUX_IOCTL_DEFS -#include <sys/ioctl.h> -#endif - -#define PULSE_BIT 0x01000000 -#define PULSE_MASK 0x00FFFFFF - -typedef int lirc_t; - -/*** lirc compatible hardware features ***/ - -#define LIRC_MODE2SEND(x) (x) -#define LIRC_SEND2MODE(x) (x) -#define LIRC_MODE2REC(x) ((x) << 16) -#define LIRC_REC2MODE(x) ((x) >> 16) - -#define LIRC_MODE_RAW 0x00000001 -#define LIRC_MODE_PULSE 0x00000002 -#define LIRC_MODE_MODE2 0x00000004 -#define LIRC_MODE_CODE 0x00000008 -#define LIRC_MODE_LIRCCODE 0x00000010 -#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) -#define LIRC_CAN_SEND_LIRCCODE LIRC_MODE2SEND(LIRC_MODE_LIRCCODE) -#define LIRC_CAN_SEND_STRING LIRC_MODE2SEND(LIRC_MODE_STRING) - -#define LIRC_CAN_SEND_MASK 0x0000003f - -#define LIRC_CAN_SET_SEND_CARRIER 0x00000100 -#define LIRC_CAN_SET_SEND_DUTY_CYCLE 0x00000200 -#define LIRC_CAN_SET_TRANSMITTER_MASK 0x00000400 - -#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) -#define LIRC_CAN_REC_LIRCCODE LIRC_MODE2REC(LIRC_MODE_LIRCCODE) -#define LIRC_CAN_REC_STRING LIRC_MODE2REC(LIRC_MODE_STRING) - -#define LIRC_CAN_REC_MASK LIRC_MODE2REC(LIRC_CAN_SEND_MASK) - -#define LIRC_CAN_SET_REC_CARRIER (LIRC_CAN_SET_SEND_CARRIER << 16) -#define LIRC_CAN_SET_REC_DUTY_CYCLE (LIRC_CAN_SET_SEND_DUTY_CYCLE << 16) - -#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_SEND(x) ((x)&LIRC_CAN_SEND_MASK) -#define LIRC_CAN_REC(x) ((x)&LIRC_CAN_REC_MASK) - -#define LIRC_CAN_NOTIFY_DECODE 0x01000000 - -/*** IOCTL commands for lirc driver ***/ - -#define LIRC_GET_FEATURES _IOR('i', 0x00000000, unsigned long) - -#define LIRC_GET_SEND_MODE _IOR('i', 0x00000001, unsigned long) -#define LIRC_GET_REC_MODE _IOR('i', 0x00000002, unsigned long) -#define LIRC_GET_SEND_CARRIER _IOR('i', 0x00000003, unsigned int) -#define LIRC_GET_REC_CARRIER _IOR('i', 0x00000004, unsigned int) -#define LIRC_GET_SEND_DUTY_CYCLE _IOR('i', 0x00000005, unsigned int) -#define LIRC_GET_REC_DUTY_CYCLE _IOR('i', 0x00000006, unsigned int) -#define LIRC_GET_REC_RESOLUTION _IOR('i', 0x00000007, unsigned int) - -/* code length in bits, currently only for LIRC_MODE_LIRCCODE */ -#define LIRC_GET_LENGTH _IOR('i', 0x0000000f, unsigned long) - -#define LIRC_SET_SEND_MODE _IOW('i', 0x00000011, unsigned long) -#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) -#define LIRC_SET_REC_CARRIER _IOW('i', 0x00000014, unsigned int) -#define LIRC_SET_SEND_DUTY_CYCLE _IOW('i', 0x00000015, unsigned int) -#define LIRC_SET_REC_DUTY_CYCLE _IOW('i', 0x00000016, unsigned int) -#define LIRC_SET_TRANSMITTER_MASK _IOW('i', 0x00000017, unsigned int) - -/* - * to set a range use - * LIRC_SET_REC_DUTY_CYCLE_RANGE/LIRC_SET_REC_CARRIER_RANGE with the - * lower bound first and later - * LIRC_SET_REC_DUTY_CYCLE/LIRC_SET_REC_CARRIER with the upper bound - */ - -#define LIRC_SET_REC_DUTY_CYCLE_RANGE _IOW('i', 0x0000001e, unsigned int) -#define LIRC_SET_REC_CARRIER_RANGE _IOW('i', 0x0000001f, unsigned int) - -#define LIRC_NOTIFY_DECODE _IO('i', 0x00000020) - -#endif diff --git a/ubuntu/lirc/lirc_atiusb/Makefile b/ubuntu/lirc/lirc_atiusb/Makefile deleted file mode 100644 index a1b837ebb53..00000000000 --- a/ubuntu/lirc/lirc_atiusb/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. - -obj-$(CONFIG_LIRC_ATIUSB) += lirc_atiusb.o diff --git a/ubuntu/lirc/lirc_atiusb/lirc_atiusb.c b/ubuntu/lirc/lirc_atiusb/lirc_atiusb.c deleted file mode 100644 index a529f69d1a1..00000000000 --- a/ubuntu/lirc/lirc_atiusb/lirc_atiusb.c +++ /dev/null @@ -1,1450 +0,0 @@ -/* - * lirc_atiusb - USB remote support for LIRC - * (currently only supports X10 USB remotes) - * (supports ATI Remote Wonder and ATI Remote Wonder II, too) - * - * Copyright (C) 2003-2004 Paul Miller <pmiller9@users.sourceforge.net> - * - * This driver was derived from: - * Vladimir Dergachev <volodya@minspring.com>'s 2002 - * "USB ATI Remote support" (input device) - * Adrian Dewhurst <sailor-lk@sailorfrag.net>'s 2002 - * "USB StreamZap remote driver" (LIRC) - * Artur Lipowski <alipowski@kki.net.pl>'s 2002 - * "lirc_dev" and "lirc_gpio" LIRC modules - * Michael Wojciechowski - * initial xbox support - * Vassilis Virvilis <vasvir@iit.demokritos.gr> 2006 - * reworked the patch for lirc submission - * - * $Id: lirc_atiusb.c,v 1.85 2009/03/11 00:21:46 jarodwilson Exp $ - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/version.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) -#error "*******************************************************" -#error "Sorry, this driver needs kernel version 2.4.0 or higher" -#error "*******************************************************" -#endif - -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/kmod.h> -#include <linux/smp_lock.h> -#include <linux/completion.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) -#include <asm/uaccess.h> -#else -#include <linux/uaccess.h> -#endif -#include <linux/usb.h> -#include <linux/poll.h> -#include <linux/wait.h> -#include <linux/list.h> - -#include "../lirc.h" -#include "../kcompat.h" -#include "../lirc_dev/lirc_dev.h" - -#define DRIVER_VERSION "$Revision: 1.85 $" -#define DRIVER_AUTHOR "Paul Miller <pmiller9@users.sourceforge.net>" -#define DRIVER_DESC "USB remote driver for LIRC" -#define DRIVER_NAME "lirc_atiusb" - -#define CODE_LENGTH (code_length[ir->remote_type]) -#define CODE_MIN_LENGTH (code_min_length[ir->remote_type]) -#define DECODE_LENGTH (decode_length[ir->remote_type]) - -#define RW2_MODENAV_KEYCODE 0x3F -#define RW2_NULL_MODE 0xFF -/* Fake (virtual) keycode indicating compass mouse usage */ -#define RW2_MOUSE_KEYCODE 0xFF -#define RW2_PRESSRELEASE_KEYCODE 0xFE - -#define RW2_PRESS_CODE 1 -#define RW2_HOLD_CODE 2 -#define RW2_RELEASE_CODE 0 - -/* module parameters */ -#ifdef CONFIG_USB_DEBUG -static int debug = 1; -#else -static int debug; -#endif -#define dprintk(fmt, args...) \ - do { \ - if (debug) \ - printk(KERN_DEBUG fmt, ## args); \ - } while (0) - -/* ATI, ATI2, XBOX */ -static const int code_length[] = {5, 3, 6}; -static const int code_min_length[] = {3, 3, 6}; -static const int decode_length[] = {5, 3, 1}; -/* - * USB_BUFF_LEN must be the maximum value of the code_length array. - * It is used for static arrays. - */ -#define USB_BUFF_LEN 6 - -static int mask = 0xFFFF; /* channel acceptance bit mask */ -static int unique; /* enable channel-specific codes */ -static int repeat = 10; /* repeat time in 1/100 sec */ -static int emit_updown; /* send separate press/release codes (rw2) */ -static int emit_modekeys; /* send keycodes for aux1-4, pc, mouse (rw2) */ -static unsigned long repeat_jiffies; /* repeat timeout */ -static int mdeadzone; /* mouse sensitivity >= 0 */ -static int mgradient = 375; /* 1000*gradient from cardinal direction */ - -/* get hi and low bytes of a 16-bits int */ -#define HI(a) ((unsigned char)((a) >> 8)) -#define LO(a) ((unsigned char)((a) & 0xff)) - -/* general constants */ -#define SEND_FLAG_IN_PROGRESS 1 -#define SEND_FLAG_COMPLETE 2 -#define FREE_ALL 0xFF - -/* endpoints */ -#define EP_KEYS 0 -#define EP_MOUSE 1 -#define EP_MOUSE_ADDR 0x81 -#define EP_KEYS_ADDR 0x82 - -#define VENDOR_ATI1 0x0bc7 -#define VENDOR_ATI2 0x0471 -#define VENDOR_MS1 0x040b -#define VENDOR_MS2 0x045e -#define VENDOR_MS3 0xFFFF - -static struct usb_device_id usb_remote_table[] = { - /* X10 USB Firecracker Interface */ - { USB_DEVICE(VENDOR_ATI1, 0x0002) }, - - /* X10 VGA Video Sender */ - { USB_DEVICE(VENDOR_ATI1, 0x0003) }, - - /* ATI Wireless Remote Receiver */ - { USB_DEVICE(VENDOR_ATI1, 0x0004) }, - - /* NVIDIA Wireless Remote Receiver */ - { USB_DEVICE(VENDOR_ATI1, 0x0005) }, - - /* ATI Wireless Remote Receiver */ - { USB_DEVICE(VENDOR_ATI1, 0x0006) }, - - /* X10 USB Wireless Transceivers */ - { USB_DEVICE(VENDOR_ATI1, 0x0007) }, - { USB_DEVICE(VENDOR_ATI1, 0x0008) }, - { USB_DEVICE(VENDOR_ATI1, 0x0009) }, - { USB_DEVICE(VENDOR_ATI1, 0x000A) }, - { USB_DEVICE(VENDOR_ATI1, 0x000B) }, - { USB_DEVICE(VENDOR_ATI1, 0x000C) }, - { USB_DEVICE(VENDOR_ATI1, 0x000D) }, - { USB_DEVICE(VENDOR_ATI1, 0x000E) }, - { USB_DEVICE(VENDOR_ATI1, 0x000F) }, - - /* ATI Remote Wonder 2: Input Device */ - { USB_DEVICE(VENDOR_ATI2, 0x0602) }, - - /* ATI Remote Wonder 2: Controller (???) */ - { USB_DEVICE(VENDOR_ATI2, 0x0603) }, - - /* Gamester Xbox DVD Movie Playback Kit IR */ - { USB_DEVICE(VENDOR_MS1, 0x6521) }, - - /* Microsoft Xbox DVD Movie Playback Kit IR */ - { USB_DEVICE(VENDOR_MS2, 0x0284) }, - - /* - * Some Chinese manufacturer -- conflicts with the joystick from the - * same manufacturer - */ - { USB_DEVICE(VENDOR_MS3, 0xFFFF) }, - - /* Terminating entry */ - { } -}; - - -/* init strings */ -#define USB_OUTLEN 7 - -static char init1[] = {0x01, 0x00, 0x20, 0x14}; -static char init2[] = {0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20}; - -struct in_endpt { - /* inner link in list of endpoints for the remote specified by ir */ - struct list_head iep_list_link; - struct atirf_dev *ir; - struct urb *urb; - struct usb_endpoint_descriptor *ep; - int type; - - /* buffers and dma */ - unsigned char *buf; - unsigned int len; -#ifdef KERNEL_2_5 - dma_addr_t dma; -#endif - - /* handle repeats */ - unsigned char old[USB_BUFF_LEN]; - unsigned long old_jiffies; -}; - -struct out_endpt { - struct atirf_dev *ir; - struct urb *urb; - struct usb_endpoint_descriptor *ep; - - /* buffers and dma */ - unsigned char *buf; -#ifdef KERNEL_2_5 - dma_addr_t dma; -#endif - - /* handle sending (init strings) */ - int send_flags; - wait_queue_head_t wait; -}; - - -/* data structure for each usb remote */ -struct atirf_dev { - /* inner link in list of all remotes managed by this module */ - struct list_head remote_list_link; - /* Number of usb interfaces associated with this device */ - int dev_refcount; - - /* usb */ - struct usb_device *usbdev; - /* Head link to list of all inbound endpoints in this remote */ - struct list_head iep_listhead; - struct out_endpt *out_init; - int devnum; - - /* remote type based on usb_device_id tables */ - enum { - ATI1_COMPATIBLE, - ATI2_COMPATIBLE, - XBOX_COMPATIBLE - } remote_type; - - /* rw2 current mode (mirrors the state of the remote) */ - int mode; - - /* lirc */ - struct lirc_driver *d; - int connected; - - /* locking */ - struct mutex lock; -}; - -/* list of all registered devices via the remote_list_link in atirf_dev */ -static struct list_head remote_list; - -/* - * Convenience macros to retrieve a pointer to the surrounding struct from - * the given list_head reference within, pointed at by link. - */ -#define get_iep_from_link(link) \ - list_entry((link), struct in_endpt, iep_list_link); -#define get_irctl_from_link(link) \ - list_entry((link), struct atirf_dev, remote_list_link); - -/* send packet - used to initialize remote */ -static void send_packet(struct out_endpt *oep, u16 cmd, unsigned char *data) -{ - struct atirf_dev *ir = oep->ir; - DECLARE_WAITQUEUE(wait, current); - int timeout = HZ; /* 1 second */ - unsigned char buf[USB_OUTLEN]; - - dprintk(DRIVER_NAME "[%d]: send called (%#x)\n", ir->devnum, cmd); - - mutex_lock(&ir->lock); - oep->urb->transfer_buffer_length = LO(cmd) + 1; - oep->urb->dev = oep->ir->usbdev; - oep->send_flags = SEND_FLAG_IN_PROGRESS; - - memcpy(buf+1, data, LO(cmd)); - buf[0] = HI(cmd); - memcpy(oep->buf, buf, LO(cmd)+1); - - set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&oep->wait, &wait); - -#ifdef KERNEL_2_5 - if (usb_submit_urb(oep->urb, GFP_ATOMIC)) { -#else - if (usb_submit_urb(oep->urb)) { -#endif - set_current_state(TASK_RUNNING); - remove_wait_queue(&oep->wait, &wait); - mutex_unlock(&ir->lock); - return; - } - mutex_unlock(&ir->lock); - - while (timeout && (oep->urb->status == -EINPROGRESS) - && !(oep->send_flags & SEND_FLAG_COMPLETE)) { - timeout = schedule_timeout(timeout); - rmb(); - } - - dprintk(DRIVER_NAME "[%d]: send complete (%#x)\n", ir->devnum, cmd); - - set_current_state(TASK_RUNNING); - remove_wait_queue(&oep->wait, &wait); -#ifdef KERNEL_2_5 - oep->urb->transfer_flags |= URB_ASYNC_UNLINK; -#endif - usb_unlink_urb(oep->urb); -} - -static int unregister_from_lirc(struct atirf_dev *ir) -{ - struct lirc_driver *d = ir->d; - int devnum; - - devnum = ir->devnum; - dprintk(DRIVER_NAME "[%d]: unregister from lirc called\n", devnum); - - lirc_unregister_driver(d->minor); - - printk(DRIVER_NAME "[%d]: usb remote disconnected\n", devnum); - return 0; -} - - -static int set_use_inc(void *data) -{ - struct atirf_dev *ir = data; - struct list_head *pos, *n; - struct in_endpt *iep; - int rtn; - - if (!ir) { - printk(DRIVER_NAME "[?]: set_use_inc called with no context\n"); - return -EIO; - } - dprintk(DRIVER_NAME "[%d]: set use inc\n", ir->devnum); - - MOD_INC_USE_COUNT; - - mutex_lock(&ir->lock); - if (!ir->connected) { - if (!ir->usbdev) { - mutex_unlock(&ir->lock); - dprintk(DRIVER_NAME "[%d]: !ir->usbdev\n", ir->devnum); - return -ENOENT; - } - - /* Iterate through the inbound endpoints */ - list_for_each_safe(pos, n, &ir->iep_listhead) { - /* extract the current in_endpt */ - iep = get_iep_from_link(pos); - iep->urb->dev = ir->usbdev; - dprintk(DRIVER_NAME "[%d]: linking iep 0x%02x (%p)\n", - ir->devnum, iep->ep->bEndpointAddress, iep); -#ifdef KERNEL_2_5 - rtn = usb_submit_urb(iep->urb, GFP_ATOMIC); -#else - rtn = usb_submit_urb(iep->urb); -#endif - if (rtn) { - printk(DRIVER_NAME "[%d]: open result = %d " - "error submitting urb\n", - ir->devnum, rtn); - mutex_unlock(&ir->lock); - MOD_DEC_USE_COUNT; - return -EIO; - } - } - ir->connected = 1; - } - mutex_unlock(&ir->lock); - - return 0; -} - -static void set_use_dec(void *data) -{ - struct atirf_dev *ir = data; - struct list_head *pos, *n; - struct in_endpt *iep; - - if (!ir) { - printk(DRIVER_NAME "[?]: set_use_dec called with no context\n"); - return; - } - dprintk(DRIVER_NAME "[%d]: set use dec\n", ir->devnum); - - mutex_lock(&ir->lock); - if (ir->connected) { - /* Free inbound usb urbs */ - list_for_each_safe(pos, n, &ir->iep_listhead) { - iep = get_iep_from_link(pos); - dprintk(DRIVER_NAME "[%d]: unlinking iep 0x%02x (%p)\n", - ir->devnum, iep->ep->bEndpointAddress, iep); - usb_kill_urb(iep->urb); - } - ir->connected = 0; - } - mutex_unlock(&ir->lock); - MOD_DEC_USE_COUNT; -} - -static void print_data(struct in_endpt *iep, char *buf, int len) -{ - const int clen = code_length[iep->ir->remote_type]; - char codes[clen * 3 + 1]; - int i; - - if (len <= 0) - return; - - for (i = 0; i < len && i < clen; i++) - snprintf(codes+i*3, 4, "%02x ", buf[i] & 0xFF); - printk(DRIVER_NAME "[%d]: data received %s (ep=0x%x length=%d)\n", - iep->ir->devnum, codes, iep->ep->bEndpointAddress, len); -} - -static int code_check_ati1(struct in_endpt *iep, int len) -{ - struct atirf_dev *ir = iep->ir; - int i, chan; - - /* ATI RW1: some remotes emit both 4 and 5 byte length codes. */ - /* ATI RW2: emit 3 byte codes */ - if (len < CODE_MIN_LENGTH || len > CODE_LENGTH) - return -1; - - /* *** channel not tested with 4/5-byte Dutch remotes *** */ - chan = ((iep->buf[len-1]>>4) & 0x0F); - - /* strip channel code */ - if (!unique) { - iep->buf[len-1] &= 0x0F; - iep->buf[len-3] -= (chan<<4); - } - - if (!((1U<<chan) & mask)) { - dprintk(DRIVER_NAME "[%d]: ignore channel %d\n", - ir->devnum, chan+1); - return -1; - } - dprintk(DRIVER_NAME "[%d]: accept channel %d\n", ir->devnum, chan+1); - - if (ir->remote_type == ATI1_COMPATIBLE) { - for (i = len; i < CODE_LENGTH; i++) - iep->buf[i] = 0; - /* check for repeats */ - if (memcmp(iep->old, iep->buf, len) == 0) { - if (iep->old_jiffies + repeat_jiffies > jiffies) - return -1; - } else - memcpy(iep->old, iep->buf, CODE_LENGTH); - iep->old_jiffies = jiffies; - } - - return 0; -} - -/* - * Since the ATI Remote Wonder II has quite a different structure from the - * prior version, this function was separated out to clarify the sanitization - * process. - * - * Here is a summary of the main differences: - * - * a. The rw2 has no sense of a transmission channel. But, it does have an - * auxiliary mode state, which is set by the mode buttons Aux1 through - * Aux4 and "PC". These map respectively to 0-4 in the first byte of the - * recv buffer. Any subsequent button press sends this mode number as its - * "channel code." Annoyingly enough, the mode setting buttons all send - * the same key code (0x3f), and can only be distinguished via their mode - * byte. - * - * Because of this, old-style "unique"-parameter-enabled channel squashing - * kills the functionality of the aux1-aux4 and PC buttons. However, to - * not do so would cause each remote key to send a different code depending - * on the active aux. Further complicating matters, using the mouse norb - * also sends an identical code as would pushing the active aux button. To - * handle this we need a separate parameter, like rw2modes, with the - * following values and meanings: - * - * 0: Don't squash any channel info - * 1: Only squash channel data for non-mode setting keys - * 2: Ignore aux keypresses, but don't squash channel - * 3: Ignore aux keypresses and squash channel data - * - * Option 1 may seem useless since the mouse sends the same code, but one - * need only ignore in userspace any press of a mode-setting code that only - * reaffirms the current mode. The 3rd party lirccd should be able to - * handle this easily enough, but lircd doesn't keep the state necessary - * for this. TODO We could work around this in the driver by emitting a - * single 02 (press) code for a mode key only if that mode is not currently - * active. - * - * Option 2 would be useful for those wanting super configurability, - * offering the ability to program 5 times the number actions based on the - * current mode. - * - * b. The rw2 has its own built in repeat handling; the keys endpoint - * encodes this in the second byte as 1 for press, 2 for hold, and 0 for - * release. This is generally much more responsive than lirc's built-in - * timeout handling. - * - * The problem is that the remote can send the release-receive pair - * (0,1) while one is still holding down the same button if the - * transmission is momentarily interrupted. (It seems that the receiver - * manages this count instead of the remote.) By default, this information - * is squashed to 2. - * - * In order to expose the built-in repeat code, set the emit_updown - * parameter as described below. - * - * c. The mouse norb is much more sensitive than on the rw1. It emulates - * a joystick-like controller with the second byte representing the x-axis - * and the third, the y-axis. Treated as signed integers, these axes range - * approximately as follows: - * - * x: (left) -46 ... 46 (right) (0xd2..0x2e) - * y: (up) -46 ... 46 (down) (0xd2..0x2e) - * - * NB these values do not correspond to the pressure with which the mouse - * norb is pushed in a given direction, but rather seems to indicate the - * duration for which a given direction is held. - * - * These are normalized to 8 cardinal directions for easy configuration via - * lircd.conf. The normalization can be fined tuned with the mdeadzone and - * mgradient parameters as described below. - * - * d. The interrupt rate of the mouse vs. the normal keys is different. - * - * mouse: ~27Hz (37ms between interrupts) - * keys: ~10Hz (100ms between interrupts) - * - * This means that the normal gap mechanism for lircd won't work as - * expected; is emit_updown>0 if you can get away with it. - */ -static int code_check_ati2(struct in_endpt *iep, int len) -{ - struct atirf_dev *ir = iep->ir; - int mode, i; - char *buf = iep->buf; - - if (len != CODE_LENGTH) { - dprintk(DRIVER_NAME - "[%d]: Huh? Abnormal length (%d) buffer received.\n", - ir->devnum, len); - return -1; - } - for (i = len; i < CODE_LENGTH; i++) - iep->buf[i] = 0; - - mode = buf[0]; - - /* Squash the mode indicator if unique wasn't set non-zero */ - if (!unique) - buf[0] = 0; - - if (iep->ep->bEndpointAddress == EP_KEYS_ADDR) { - /* ignore mouse nav indicator key and mode-set (aux) keys */ - if (buf[2] == RW2_MODENAV_KEYCODE) { - if (emit_modekeys >= 2) /* emit raw */ - buf[0] = mode; - else if (emit_modekeys == 1) { - /* translate */ - buf[0] = mode; - if (ir->mode != mode) { - buf[1] = 0x03; - ir->mode = mode; - return 0; - } - } else { - dprintk(DRIVER_NAME - "[%d]: ignore dummy code 0x%x " - "(ep=0x%x)\n", ir->devnum, - buf[2], iep->ep->bEndpointAddress); - return -1; - } - } - - if (buf[1] != 2) { - /* handle press/release codes */ - if (emit_updown == 0) /* ignore */ - return -1; - else if (emit_updown == 1) /* normalize keycode */ - buf[2] = RW2_PRESSRELEASE_KEYCODE; - /* else emit raw */ - } - - } else { - int x = (signed char)buf[1]; - int y = (signed char)buf[2]; - int code = 0x00; - int dir_ew, dir_ns; - - buf[2] = RW2_MOUSE_KEYCODE; - - /* sensitivity threshold (use L2norm^2) */ - if (mdeadzone > (x*x+y*y)) { - buf[1] = 0x00; - return 0; - } - -/* Nybble encoding: xy, 2 is -1 (S or W); 1 (N or E) */ -#define MOUSE_N 0x01 -#define MOUSE_NE 0x11 -#define MOUSE_E 0x10 -#define MOUSE_SE 0x12 -#define MOUSE_S 0x02 -#define MOUSE_SW 0x22 -#define MOUSE_W 0x20 -#define MOUSE_NW 0x21 - - /* cardinal leanings: positive x -> E, positive y -> S */ - dir_ew = (x > 0) ? MOUSE_E : MOUSE_W; - dir_ns = (y > 0) ? MOUSE_S : MOUSE_N; - - /* convert coordinates(angle) into compass direction */ - if (x == 0) - code = dir_ns; - else if (y == 0) - code = dir_ew; - else { - if (abs(1000*y/x) > mgradient) - code = dir_ns; - if (abs(1000*x/y) > mgradient) - code |= dir_ew; - } - - buf[1] = code; - dprintk(DRIVER_NAME "[%d]: mouse compass=0x%x %s%s (%d,%d)\n", - ir->devnum, code, - (code & MOUSE_S ? "S" : (code & MOUSE_N ? "N" : "")), - (code & MOUSE_E ? "E" : (code & MOUSE_W ? "W" : "")), - x, y); - } - - return 0; -} - -static int code_check_xbox(struct in_endpt *iep, int len) -{ - struct atirf_dev *ir = iep->ir; - const int clen = CODE_LENGTH; - - if (len != clen) { - dprintk(DRIVER_NAME ": We got %d instead of %d bytes from xbox " - "ir.. ?\n", len, clen); - return -1; - } - - /* check for repeats */ - if (memcmp(iep->old, iep->buf, len) == 0) { - if (iep->old_jiffies + repeat_jiffies > jiffies) - return -1; - } else { - /* - * the third byte of xbox ir packet seems to contain key info - * the last two bytes are.. some kind of clock? - */ - iep->buf[0] = iep->buf[2]; - memset(iep->buf + 1, 0, len - 1); - memcpy(iep->old, iep->buf, len); - } - iep->old_jiffies = jiffies; - - return 0; -} - -#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -static void usb_remote_recv(struct urb *urb, struct pt_regs *regs) -#else -static void usb_remote_recv(struct urb *urb) -#endif -{ - struct in_endpt *iep; - int len, result = -1; - - if (!urb) - return; - iep = urb->context; - if (!iep) { -#ifdef KERNEL_2_5 - urb->transfer_flags |= URB_ASYNC_UNLINK; -#endif - usb_unlink_urb(urb); - return; - } - if (!iep->ir->usbdev) - return; - - len = urb->actual_length; - if (debug) - print_data(iep, urb->transfer_buffer, len); - - switch (urb->status) { - - case 0: - switch (iep->ir->remote_type) { - case XBOX_COMPATIBLE: - result = code_check_xbox(iep, len); - break; - case ATI2_COMPATIBLE: - result = code_check_ati2(iep, len); - break; - case ATI1_COMPATIBLE: - default: - result = code_check_ati1(iep, len); - } - if (result < 0) - break; - lirc_buffer_write(iep->ir->d->rbuf, iep->buf); - wake_up(&iep->ir->d->rbuf->wait_poll); - break; - - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: -#ifdef KERNEL_2_5 - urb->transfer_flags |= URB_ASYNC_UNLINK; -#endif - usb_unlink_urb(urb); - return; - - case -EPIPE: - default: - break; - } - -#ifdef KERNEL_2_5 - usb_submit_urb(urb, GFP_ATOMIC); -#endif -} - -#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -static void usb_remote_send(struct urb *urb, struct pt_regs *regs) -#else -static void usb_remote_send(struct urb *urb) -#endif -{ - struct out_endpt *oep; - - if (!urb) - return; - oep = urb->context; - if (!oep) { -#ifdef KERNEL_2_5 - urb->transfer_flags |= URB_ASYNC_UNLINK; -#endif - usb_unlink_urb(urb); - return; - } - if (!oep->ir->usbdev) - return; - - dprintk(DRIVER_NAME "[%d]: usb out called\n", oep->ir->devnum); - - if (urb->status) - return; - - oep->send_flags |= SEND_FLAG_COMPLETE; - wmb(); - if (waitqueue_active(&oep->wait)) - wake_up(&oep->wait); -} - - -/* - * Initialization and removal - */ - -/* - * Free iep according to mem_failure which specifies a checkpoint into the - * initialization sequence for rollback recovery. - */ -static void free_in_endpt(struct in_endpt *iep, int mem_failure) -{ - struct atirf_dev *ir; - dprintk(DRIVER_NAME ": free_in_endpt(%p, %d)\n", iep, mem_failure); - if (!iep) - return; - - ir = iep->ir; - if (!ir) { - dprintk(DRIVER_NAME ": free_in_endpt: WARNING! null ir\n"); - return; - } - mutex_lock(&ir->lock); - switch (mem_failure) { - case FREE_ALL: - case 5: - list_del(&iep->iep_list_link); - dprintk(DRIVER_NAME "[%d]: free_in_endpt removing ep=0x%0x " - "from list\n", ir->devnum, iep->ep->bEndpointAddress); - case 4: - if (iep->urb) { -#ifdef KERNEL_2_5 - iep->urb->transfer_flags |= URB_ASYNC_UNLINK; -#endif - usb_unlink_urb(iep->urb); - usb_free_urb(iep->urb); - iep->urb = 0; - } else - dprintk(DRIVER_NAME "[%d]: free_in_endpt null urb!\n", - ir->devnum); - case 3: -#ifdef KERNEL_2_5 - usb_free_coherent(iep->ir->usbdev, iep->len, iep->buf, iep->dma); -#else - kfree(iep->buf); -#endif - iep->buf = 0; - case 2: - kfree(iep); - } - mutex_unlock(&ir->lock); -} - -/* - * Construct a new inbound endpoint for this remote, and add it to the list of - * in_epts in ir. - */ -static struct in_endpt *new_in_endpt(struct atirf_dev *ir, - struct usb_endpoint_descriptor *ep) -{ - struct usb_device *dev = ir->usbdev; - struct in_endpt *iep; - int pipe, maxp, len, addr; - int mem_failure; - - addr = ep->bEndpointAddress; - pipe = usb_rcvintpipe(dev, addr); - maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - -/* len = (maxp > USB_BUFLEN) ? USB_BUFLEN : maxp; - * len -= (len % CODE_LENGTH); */ - len = CODE_LENGTH; - - dprintk(DRIVER_NAME "[%d]: acceptable inbound endpoint (0x%x) found " - "(maxp=%d len=%d)\n", ir->devnum, addr, maxp, len); - - mem_failure = 0; - iep = kzalloc(sizeof(*iep), GFP_KERNEL); - if (!iep) { - mem_failure = 1; - goto new_in_endpt_failure_check; - } - iep->ir = ir; - iep->ep = ep; - iep->len = len; - -#ifdef KERNEL_2_5 - iep->buf = usb_alloc_coherent(dev, len, GFP_ATOMIC, &iep->dma); -#else - iep->buf = kmalloc(len, GFP_KERNEL); -#endif - if (!iep->buf) { - mem_failure = 2; - goto new_in_endpt_failure_check; - } - -#ifdef KERNEL_2_5 - iep->urb = usb_alloc_urb(0, GFP_KERNEL); -#else - iep->urb = usb_alloc_urb(0); -#endif - if (!iep->urb) - mem_failure = 3; - -new_in_endpt_failure_check: - - if (mem_failure) { - free_in_endpt(iep, mem_failure); - printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n", - ir->devnum, addr, mem_failure); - return NULL; - } - list_add_tail(&iep->iep_list_link, &ir->iep_listhead); - dprintk(DRIVER_NAME "[%d]: adding ep=0x%0x to list\n", - ir->devnum, iep->ep->bEndpointAddress); - return iep; -} - -static void free_out_endpt(struct out_endpt *oep, int mem_failure) -{ - struct atirf_dev *ir; - dprintk(DRIVER_NAME ": free_out_endpt(%p, %d)\n", oep, mem_failure); - if (!oep) - return; - - wake_up_all(&oep->wait); - - ir = oep->ir; - if (!ir) { - dprintk(DRIVER_NAME ": free_out_endpt: WARNING! null ir\n"); - return; - } - mutex_lock(&ir->lock); - switch (mem_failure) { - case FREE_ALL: - case 4: - if (oep->urb) { -#ifdef KERNEL_2_5 - oep->urb->transfer_flags |= URB_ASYNC_UNLINK; -#endif - usb_unlink_urb(oep->urb); - usb_free_urb(oep->urb); - oep->urb = 0; - } else { - dprintk(DRIVER_NAME "[%d]: free_out_endpt: null urb!\n", - ir->devnum); - } - case 3: -#ifdef KERNEL_2_5 - usb_free_coherent(oep->ir->usbdev, USB_OUTLEN, - oep->buf, oep->dma); -#else - kfree(oep->buf); -#endif - oep->buf = 0; - case 2: - kfree(oep); - } - mutex_unlock(&ir->lock); -} - -static struct out_endpt *new_out_endpt(struct atirf_dev *ir, - struct usb_endpoint_descriptor *ep) -{ -#ifdef KERNEL_2_5 - struct usb_device *dev = ir->usbdev; -#endif - struct out_endpt *oep; - int mem_failure; - - dprintk(DRIVER_NAME "[%d]: acceptable outbound endpoint (0x%x) found\n", - ir->devnum, ep->bEndpointAddress); - - mem_failure = 0; - oep = kzalloc(sizeof(*oep), GFP_KERNEL); - if (!oep) - mem_failure = 1; - else { - oep->ir = ir; - oep->ep = ep; - init_waitqueue_head(&oep->wait); - -#ifdef KERNEL_2_5 - oep->buf = usb_alloc_coherent(dev, USB_OUTLEN, - GFP_ATOMIC, &oep->dma); -#else - oep->buf = kmalloc(USB_OUTLEN, GFP_KERNEL); -#endif - if (!oep->buf) - mem_failure = 2; - else { -#ifdef KERNEL_2_5 - oep->urb = usb_alloc_urb(0, GFP_KERNEL); -#else - oep->urb = usb_alloc_urb(0); -#endif - if (!oep->urb) - mem_failure = 3; - } - } - if (mem_failure) { - free_out_endpt(oep, mem_failure); - printk(DRIVER_NAME "[%d]: ep=0x%x out of memory (code=%d)\n", - ir->devnum, ep->bEndpointAddress, mem_failure); - return NULL; - } - return oep; -} - -static void free_irctl(struct atirf_dev *ir, int mem_failure) -{ - struct list_head *pos, *n; - struct in_endpt *in; - dprintk(DRIVER_NAME ": free_irctl(%p, %d)\n", ir, mem_failure); - - if (!ir) - return; - - list_for_each_safe(pos, n, &ir->iep_listhead) { - in = get_iep_from_link(pos); - free_in_endpt(in, FREE_ALL); - } - if (ir->out_init) { - free_out_endpt(ir->out_init, FREE_ALL); - ir->out_init = NULL; - } - - mutex_lock(&ir->lock); - switch (mem_failure) { - case FREE_ALL: - case 6: - if (!--ir->dev_refcount) { - list_del(&ir->remote_list_link); - dprintk(DRIVER_NAME "[%d]: free_irctl: removing " - "remote from list\n", ir->devnum); - } else { - dprintk(DRIVER_NAME "[%d]: free_irctl: refcount at %d," - "aborting free_irctl\n", - ir->devnum, ir->dev_refcount); - mutex_unlock(&ir->lock); - return; - } - case 5: - case 4: - case 3: - if (ir->d) { - switch (mem_failure) { - case 5: - lirc_buffer_free(ir->d->rbuf); - case 4: - kfree(ir->d->rbuf); - case 3: - kfree(ir->d); - } - } else - printk(DRIVER_NAME "[%d]: ir->d is a null pointer!\n", - ir->devnum); - case 2: - mutex_unlock(&ir->lock); - kfree(ir); - return; - } - mutex_unlock(&ir->lock); -} - -static struct atirf_dev *new_irctl(struct usb_interface *intf) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct atirf_dev *ir; - struct lirc_driver *driver; - int type, devnum, dclen; - int mem_failure; - - devnum = dev->devnum; - - switch (cpu_to_le16(dev->descriptor.idVendor)) { - case VENDOR_ATI1: - type = ATI1_COMPATIBLE; - break; - case VENDOR_ATI2: - type = ATI2_COMPATIBLE; - break; - case VENDOR_MS1: - case VENDOR_MS2: - case VENDOR_MS3: - type = XBOX_COMPATIBLE; - break; - default: - dprintk(DRIVER_NAME "[%d]: unknown type\n", devnum); - return NULL; - } - dprintk(DRIVER_NAME "[%d]: remote type = %d\n", devnum, type); - - mem_failure = 0; - ir = kzalloc(sizeof(*ir), GFP_KERNEL); - if (!ir) { - mem_failure = 1; - goto new_irctl_failure_check; - } - - /* - * at this stage we cannot use the macro [DE]CODE_LENGTH: ir - * is not yet setup - */ - dclen = decode_length[type]; - /* - * add this infrared remote struct to remote_list, keeping track - * of the number of drivers registered. - */ - dprintk(DRIVER_NAME "[%d]: adding remote to list\n", devnum); - list_add_tail(&ir->remote_list_link, &remote_list); - ir->dev_refcount = 1; - - driver = kzalloc(sizeof(*driver), GFP_KERNEL); - if (!driver) { - mem_failure = 2; - goto new_irctl_failure_check; - } - - ir->d = driver; - driver->rbuf = kmalloc(sizeof(*(driver->rbuf)), GFP_KERNEL); - if (!driver->rbuf) { - mem_failure = 3; - goto new_irctl_failure_check; - } - - if (lirc_buffer_init(driver->rbuf, dclen, 1)) { - mem_failure = 4; - goto new_irctl_failure_check; - } - - strcpy(driver->name, DRIVER_NAME " "); - driver->minor = -1; - driver->code_length = dclen * 8; - driver->features = LIRC_CAN_REC_LIRCCODE; - driver->data = ir; - driver->set_use_inc = &set_use_inc; - driver->set_use_dec = &set_use_dec; -#ifdef LIRC_HAVE_SYSFS - driver->dev = &intf->dev; -#endif - driver->owner = THIS_MODULE; - ir->usbdev = dev; - ir->remote_type = type; - ir->devnum = devnum; - ir->mode = RW2_NULL_MODE; - - mutex_init(&ir->lock); - INIT_LIST_HEAD(&ir->iep_listhead); - -new_irctl_failure_check: - - if (mem_failure) { - free_irctl(ir, mem_failure); - printk(DRIVER_NAME "[%d]: out of memory (code=%d)\n", - devnum, mem_failure); - return NULL; - } - return ir; -} - - -/* - * Scan the global list of remotes to see if the device listed is one of them. - * If it is, the corresponding atirf_dev is returned, with its dev_refcount - * incremented. Otherwise, returns null. - */ -static struct atirf_dev *get_prior_reg_ir(struct usb_device *dev) -{ - struct list_head *pos; - struct atirf_dev *ir = NULL; - - dprintk(DRIVER_NAME "[%d]: scanning remote_list...\n", dev->devnum); - list_for_each(pos, &remote_list) { - ir = get_irctl_from_link(pos); - if (ir->usbdev != dev) { - dprintk(DRIVER_NAME "[%d]: device %d isn't it...", - dev->devnum, ir->devnum); - ir = NULL; - } else { - dprintk(DRIVER_NAME "[%d]: prior instance found.\n", - dev->devnum); - ir->dev_refcount++; - break; - } - } - return ir; -} - -/* - * If the USB interface has an out endpoint for control (eg, the first Remote - * Wonder) send the appropriate initialization packets. - */ -static void send_outbound_init(struct atirf_dev *ir) -{ - if (ir->out_init) { - struct out_endpt *oep = ir->out_init; - dprintk(DRIVER_NAME "[%d]: usb_remote_probe: initializing " - "outbound ep\n", ir->devnum); - usb_fill_int_urb(oep->urb, ir->usbdev, - usb_sndintpipe(ir->usbdev, oep->ep->bEndpointAddress), - oep->buf, USB_OUTLEN, usb_remote_send, - oep, oep->ep->bInterval); -#ifdef KERNEL_2_5 - oep->urb->transfer_dma = oep->dma; - oep->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; -#endif - - send_packet(oep, 0x8004, init1); - send_packet(oep, 0x8007, init2); - } -} - -/* Log driver and usb info */ -static void log_usb_dev_info(struct usb_device *dev) -{ - char buf[63], name[128] = ""; - - if (dev->descriptor.iManufacturer - && usb_string(dev, dev->descriptor.iManufacturer, - buf, sizeof(buf)) > 0) - strlcpy(name, buf, sizeof(name)); - if (dev->descriptor.iProduct - && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0) - snprintf(name + strlen(name), sizeof(name) - strlen(name), - " %s", buf); - printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", dev->devnum, name, - dev->bus->busnum, dev->devnum); -} - - -#ifdef KERNEL_2_5 -static int usb_remote_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct usb_host_interface *idesc; -#else -static void *usb_remote_probe(struct usb_device *dev, unsigned int ifnum, - const struct usb_device_id *id) -{ - struct usb_interface *intf = &dev->actconfig->interface[ifnum]; - struct usb_interface_descriptor *idesc; -#endif - struct usb_endpoint_descriptor *ep; - struct in_endpt *iep; - struct atirf_dev *ir; - int i, type; - - dprintk(DRIVER_NAME "[%d]: usb_remote_probe: dev:%p, intf:%p, id:%p)\n", - dev->devnum, dev, intf, id); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 5) - idesc = &intf->altsetting[intf->act_altsetting]; -#else - idesc = intf->cur_altsetting; -#endif - - /* Check if a usb remote has already been registered for this device */ - ir = get_prior_reg_ir(dev); - - if (!ir) { - ir = new_irctl(intf); - if (!ir) -#ifdef KERNEL_2_5 - return -ENOMEM; -#else - return NULL; -#endif - } - type = ir->remote_type; - - /* - * step through the endpoints to find first in and first out endpoint - * of type interrupt transfer - */ -#ifdef KERNEL_2_5 - for (i = 0; i < idesc->desc.bNumEndpoints; ++i) { - ep = &idesc->endpoint[i].desc; -#else - for (i = 0; i < idesc->bNumEndpoints; ++i) { - ep = &idesc->endpoint[i]; -#endif - dprintk(DRIVER_NAME "[%d]: processing endpoint %d\n", - dev->devnum, i); - if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == - USB_DIR_IN) && - ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_INT)) { - - iep = new_in_endpt(ir, ep); - if (iep) - { - usb_fill_int_urb(iep->urb, dev, - usb_rcvintpipe(dev, - iep->ep->bEndpointAddress), - iep->buf, iep->len, usb_remote_recv, - iep, iep->ep->bInterval); -#ifdef KERNEL_2_5 - iep->urb->transfer_dma = iep->dma; - iep->urb->transfer_flags |= - URB_NO_TRANSFER_DMA_MAP; -#endif - } - } - - if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == - USB_DIR_OUT) && - ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_INT) && - (ir->out_init == NULL)) - ir->out_init = new_out_endpt(ir, ep); - } - if (list_empty(&ir->iep_listhead)) { - printk(DRIVER_NAME "[%d]: inbound endpoint not found\n", - ir->devnum); - free_irctl(ir, FREE_ALL); -#ifdef KERNEL_2_5 - return -ENODEV; -#else - return NULL; -#endif - } - if (ir->dev_refcount == 1) { - ir->d->minor = lirc_register_driver(ir->d); - if (ir->d->minor < 0) { - free_irctl(ir, FREE_ALL); -#ifdef KERNEL_2_5 - return -ENODEV; -#else - return NULL; -#endif - } - - /* Note new driver registration in kernel logs */ - log_usb_dev_info(dev); - - /* outbound data (initialization) */ - send_outbound_init(ir); - } - -#ifdef KERNEL_2_5 - usb_set_intfdata(intf, ir); - return 0; -#else - return ir; -#endif -} - -#ifdef KERNEL_2_5 -static void usb_remote_disconnect(struct usb_interface *intf) -{ - /* struct usb_device *dev = interface_to_usbdev(intf); */ - struct atirf_dev *ir = usb_get_intfdata(intf); - usb_set_intfdata(intf, NULL); -#else -static void usb_remote_disconnect(struct usb_device *dev, void *ptr) -{ - struct atirf_dev *ir = ptr; -#endif - - dprintk(DRIVER_NAME ": disconnecting remote %d:\n", - (ir ? ir->devnum : -1)); - if (!ir || !ir->d) - return; - - if (ir->usbdev) { - /* Only unregister once */ - ir->usbdev = NULL; - unregister_from_lirc(ir); - } - - /* This also removes the current remote from remote_list */ - free_irctl(ir, FREE_ALL); -} - -static struct usb_driver usb_remote_driver = { - LIRC_THIS_MODULE(.owner = THIS_MODULE) - .name = DRIVER_NAME, - .probe = usb_remote_probe, - .disconnect = usb_remote_disconnect, - .id_table = usb_remote_table -}; - -static int __init usb_remote_init(void) -{ - int i; - - INIT_LIST_HEAD(&remote_list); - - printk(KERN_INFO "\n" DRIVER_NAME ": " DRIVER_DESC " " - 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"); - - repeat_jiffies = repeat*HZ/100; - - i = usb_register(&usb_remote_driver); - if (i) { - printk(DRIVER_NAME ": usb register failed, result = %d\n", i); - return -ENODEV; - } - - return 0; -} - -static void __exit usb_remote_exit(void) -{ - usb_deregister(&usb_remote_driver); -} - -module_init(usb_remote_init); -module_exit(usb_remote_exit); - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(usb, usb_remote_table); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not (default: 0)"); - -module_param(mask, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(mask, "Set channel acceptance bit mask (default: 0xFFFF)"); - -module_param(unique, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(unique, "Enable channel-specific codes (default: 0)"); - -module_param(repeat, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(repeat, "Repeat timeout (1/100 sec) (default: 10)"); - -module_param(mdeadzone, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(mdeadzone, "rw2 mouse sensitivity threshold (default: 0)"); - -/* - * Enabling this will cause the built-in Remote Wonder II repeat coding to - * not be squashed. The second byte of the keys output will then be: - * - * 1 initial press (button down) - * 2 holding (button remains pressed) - * 0 release (button up) - * - * By default, the driver emits 2 for both 1 and 2, and emits nothing for 0. - * This is good for people having trouble getting their rw2 to send a good - * consistent signal to the receiver. - * - * However, if you have no troubles with the driver outputting up-down pairs - * at random points while you're still holding a button, then you can enable - * this parameter to get finer grain repeat control out of your remote: - * - * 1 Emit a single (per-channel) virtual code for all up/down events - * 2 Emit the actual rw2 output - * - * 1 is easier to write lircd configs for; 2 allows full control. - */ -module_param(emit_updown, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(emit_updown, "emit press/release codes (rw2): 0:don't " - "(default), 1:emit 2 codes only, 2:code for each button"); - -module_param(emit_modekeys, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(emit_modekeys, "emit keycodes for aux1-aux4, pc, and mouse " - "(rw2): 0:don't (default), 1:emit translated codes: one for " - "mode switch, one for same mode, 2:raw codes"); - -module_param(mgradient, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(mgradient, "rw2 mouse: 1000*gradient from E to NE (default: " - "500 => .5 => ~27 degrees)"); - -EXPORT_NO_SYMBOLS; diff --git a/ubuntu/lirc/lirc_bt829/Makefile b/ubuntu/lirc/lirc_bt829/Makefile deleted file mode 100644 index 81a821c1c46..00000000000 --- a/ubuntu/lirc/lirc_bt829/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. - -obj-$(CONFIG_LIRC_ATIUSB) += lirc_bt829.o diff --git a/ubuntu/lirc/lirc_bt829/lirc_bt829.c b/ubuntu/lirc/lirc_bt829/lirc_bt829.c deleted file mode 100644 index fad355c603f..00000000000 --- a/ubuntu/lirc/lirc_bt829/lirc_bt829.c +++ /dev/null @@ -1,398 +0,0 @@ -/* - * Remote control driver for the TV-card based on bt829 - * - * by Leonid Froenchenko <lfroen@galileo.co.il> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include <linux/version.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) -#error "This driver needs kernel version 2.4.0 or higher" -#endif -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/threads.h> -#include <linux/sched.h> -#include <linux/ioport.h> -#include <linux/pci.h> -#include <linux/delay.h> - -#include "../kcompat.h" -#include "../lirc_dev/lirc_dev.h" - -static int poll_main(void); -static int atir_init_start(void); - -static void write_index(unsigned char index, unsigned int value); -static unsigned int read_index(unsigned char index); - -static void do_i2c_start(void); -static void do_i2c_stop(void); - -static void seems_wr_byte(unsigned char al); -static unsigned char seems_rd_byte(void); - -static unsigned int read_index(unsigned char al); -static void write_index(unsigned char ah, unsigned int edx); - -static void cycle_delay(int cycle); - -static void do_set_bits(unsigned char bl); -static unsigned char do_get_bits(void); - -#define DATA_PCI_OFF 0x7FFC00 -#define WAIT_CYCLE 20 - -#define DRIVER_NAME "lirc_bt829" - -static int debug; -#define dprintk(fmt, args...) \ - do { \ - if (debug) \ - printk(KERN_DEBUG DRIVER_NAME ": " fmt, ## args); \ - } while (0) - -static int atir_minor; -static unsigned long pci_addr_phys; -static unsigned char *pci_addr_lin; - -static struct lirc_driver atir_driver; - -static struct pci_dev *do_pci_probe(void) -{ - struct pci_dev *my_dev; -#ifndef KERNEL_2_5 - /* unnecessary with recent kernels */ - if (!pci_present()) - printk(KERN_ERR DRIVER_NAME ": no pci in this kernel\n"); -#endif - my_dev = pci_get_device(PCI_VENDOR_ID_ATI, - PCI_DEVICE_ID_ATI_264VT, NULL); - if (my_dev) { - printk(KERN_ERR DRIVER_NAME ": Using device: %s\n", - pci_name(my_dev)); - pci_addr_phys = 0; - if (my_dev->resource[0].flags & IORESOURCE_MEM) { - pci_addr_phys = my_dev->resource[0].start; - printk(KERN_INFO DRIVER_NAME ": memory at 0x%08X\n", - (unsigned int)pci_addr_phys); - } - if (pci_addr_phys == 0) { - printk(KERN_ERR DRIVER_NAME ": no memory resource ?\n"); - return NULL; - } - } else { - printk(KERN_ERR DRIVER_NAME ": pci_probe failed\n"); - return NULL; - } - return my_dev; -} - -static int atir_add_to_buf(void *data, struct lirc_buffer *buf) -{ - unsigned char key; - int status; - status = poll_main(); - key = (status >> 8) & 0xFF; - if (status & 0xFF) { - dprintk("reading key %02X\n", key); - lirc_buffer_write(buf, &key); - return 0; - } - return -ENODATA; -} - -static int atir_set_use_inc(void *data) -{ - MOD_INC_USE_COUNT; - dprintk("driver is opened\n"); - return 0; -} - -static void atir_set_use_dec(void *data) -{ - MOD_DEC_USE_COUNT; - dprintk("driver is closed\n"); -} - -int init_module(void) -{ - struct pci_dev *pdev; - - pdev = do_pci_probe(); - if (pdev == NULL) - return 1; - - if (!atir_init_start()) - return 1; - - strcpy(atir_driver.name, "ATIR"); - atir_driver.minor = -1; - atir_driver.code_length = 8; - atir_driver.sample_rate = 10; - atir_driver.data = 0; - atir_driver.add_to_buf = atir_add_to_buf; - atir_driver.set_use_inc = atir_set_use_inc; - atir_driver.set_use_dec = atir_set_use_dec; -#ifdef LIRC_HAVE_SYSFS - atir_driver.dev = &pdev->dev; -#endif - atir_driver.owner = THIS_MODULE; - - atir_minor = lirc_register_driver(&atir_driver); - if (atir_minor < 0) { - printk(KERN_ERR DRIVER_NAME ": failed to register driver!\n"); - return atir_minor; - } - dprintk("driver is registered on minor %d\n", atir_minor); - - return 0; -} - - -void cleanup_module(void) -{ - lirc_unregister_driver(atir_minor); -} - - -static int atir_init_start(void) -{ - pci_addr_lin = ioremap(pci_addr_phys + DATA_PCI_OFF, 0x400); - if (pci_addr_lin == 0) { - printk(KERN_INFO DRIVER_NAME ": pci mem must be mapped\n"); - return 0; - } - return 1; -} - -static void cycle_delay(int cycle) -{ - udelay(WAIT_CYCLE*cycle); -} - - -static int poll_main() -{ - unsigned char status_high, status_low; - - do_i2c_start(); - - seems_wr_byte(0xAA); - seems_wr_byte(0x01); - - do_i2c_start(); - - seems_wr_byte(0xAB); - - status_low = seems_rd_byte(); - status_high = seems_rd_byte(); - - do_i2c_stop(); - - return (status_high << 8) | status_low; -} - -static void do_i2c_start(void) -{ - do_set_bits(3); - cycle_delay(4); - - do_set_bits(1); - cycle_delay(7); - - do_set_bits(0); - cycle_delay(2); -} - -static void do_i2c_stop(void) -{ - unsigned char bits; - bits = do_get_bits() & 0xFD; - do_set_bits(bits); - cycle_delay(1); - - bits |= 1; - do_set_bits(bits); - cycle_delay(2); - - bits |= 2; - do_set_bits(bits); - bits = 3; - do_set_bits(bits); - cycle_delay(2); -} - -static void seems_wr_byte(unsigned char value) -{ - int i; - unsigned char reg; - - reg = do_get_bits(); - for (i = 0; i < 8; i++) { - if (value & 0x80) - reg |= 0x02; - else - reg &= 0xFD; - - do_set_bits(reg); - cycle_delay(1); - - reg |= 1; - do_set_bits(reg); - cycle_delay(1); - - reg &= 0xFE; - do_set_bits(reg); - cycle_delay(1); - value <<= 1; - } - cycle_delay(2); - - reg |= 2; - do_set_bits(reg); - - reg |= 1; - do_set_bits(reg); - - cycle_delay(1); - do_get_bits(); - - reg &= 0xFE; - do_set_bits(reg); - cycle_delay(3); -} - -static unsigned char seems_rd_byte(void) -{ - int i; - int rd_byte; - unsigned char bits_2, bits_1; - - bits_1 = do_get_bits() | 2; - do_set_bits(bits_1); - - rd_byte = 0; - for (i = 0; i < 8; i++) { - bits_1 &= 0xFE; - do_set_bits(bits_1); - cycle_delay(2); - - bits_1 |= 1; - do_set_bits(bits_1); - cycle_delay(1); - - bits_2 = do_get_bits(); - if (bits_2 & 2) - rd_byte |= 1; - - rd_byte <<= 1; - } - - bits_1 = 0; - if (bits_2 == 0) - bits_1 |= 2; - - do_set_bits(bits_1); - cycle_delay(2); - - bits_1 |= 1; - do_set_bits(bits_1); - cycle_delay(3); - - bits_1 &= 0xFE; - do_set_bits(bits_1); - cycle_delay(2); - - rd_byte >>= 1; - rd_byte &= 0xFF; - return rd_byte; -} - -static void do_set_bits(unsigned char new_bits) -{ - int reg_val; - reg_val = read_index(0x34); - if (new_bits & 2) { - reg_val &= 0xFFFFFFDF; - reg_val |= 1; - } else { - reg_val &= 0xFFFFFFFE; - reg_val |= 0x20; - } - reg_val |= 0x10; - write_index(0x34, reg_val); - - reg_val = read_index(0x31); - if (new_bits & 1) - reg_val |= 0x1000000; - else - reg_val &= 0xFEFFFFFF; - - reg_val |= 0x8000000; - write_index(0x31, reg_val); -} - -static unsigned char do_get_bits(void) -{ - unsigned char bits; - int reg_val; - - reg_val = read_index(0x34); - reg_val |= 0x10; - reg_val &= 0xFFFFFFDF; - write_index(0x34, reg_val); - - reg_val = read_index(0x34); - bits = 0; - if (reg_val & 8) - bits |= 2; - else - bits &= 0xFD; - - reg_val = read_index(0x31); - if (reg_val & 0x1000000) - bits |= 1; - else - bits &= 0xFE; - - return bits; -} - -static unsigned int read_index(unsigned char index) -{ - unsigned char *addr; - unsigned int value; - /* addr = pci_addr_lin + DATA_PCI_OFF + ((index & 0xFF) << 2); */ - addr = pci_addr_lin + ((index & 0xFF) << 2); - value = readl(addr); - return value; -} - -static void write_index(unsigned char index, unsigned int reg_val) -{ - unsigned char *addr; - addr = pci_addr_lin + ((index & 0xFF) << 2); - writel(reg_val, addr); -} - -MODULE_AUTHOR("Froenchenko Leonid"); -MODULE_DESCRIPTION("IR remote driver for bt829 based TV cards"); -MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -EXPORT_NO_SYMBOLS; diff --git a/ubuntu/lirc/lirc_dev/Makefile b/ubuntu/lirc/lirc_dev/Makefile deleted file mode 100644 index b48b0321eb4..00000000000 --- a/ubuntu/lirc/lirc_dev/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. - -obj-$(CONFIG_LIRC_DEV) += lirc_dev.o diff --git a/ubuntu/lirc/lirc_dev/lirc_dev.c b/ubuntu/lirc/lirc_dev/lirc_dev.c deleted file mode 100644 index 1ead88a5b2a..00000000000 --- a/ubuntu/lirc/lirc_dev/lirc_dev.c +++ /dev/null @@ -1,1024 +0,0 @@ -/* - * LIRC base driver - * - * (L) by Artur Lipowski <alipowski@interia.pl> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * 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 $ - * - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#include <linux/version.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18) -#error "**********************************************************" -#error " Sorry, this driver needs kernel version 2.2.18 or higher " -#error "**********************************************************" -#endif - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/ioctl.h> -#include <linux/fs.h> -#include <linux/poll.h> -#include <linux/smp_lock.h> -#include <linux/completion.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) -#include <asm/uaccess.h> -#include <asm/errno.h> -#else -#include <linux/uaccess.h> -#include <linux/errno.h> -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) -#include <linux/wrapper.h> -#endif -#define __KERNEL_SYSCALLS__ -#include <linux/unistd.h> -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) -#include <linux/kthread.h> -#endif -#ifdef CONFIG_COMPAT -#include <linux/compat.h> -#endif - -#include "../kcompat.h" - -/* SysFS header */ -#if defined(LIRC_HAVE_SYSFS) -#include <linux/device.h> -#endif - -#include "../lirc.h" -#include "lirc_dev.h" - -static int debug; -#define dprintk(fmt, args...) \ - do { \ - if (debug) \ - printk(KERN_DEBUG fmt, ## args); \ - } while (0) - -#define IRCTL_DEV_NAME "BaseRemoteCtl" -#define NOPLUG -1 -#define LOGHEAD "lirc_dev (%s[%d]): " - -struct irctl { - struct lirc_driver d; - int attached; - int open; - - struct mutex buffer_lock; - struct lirc_buffer *buf; - unsigned int chunk_size; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) - int tpid; - struct completion *t_notify; - struct completion *t_notify2; - int shutdown; -#else - struct task_struct *task; -#endif - long jiffies_to_wait; - -#ifdef LIRC_HAVE_DEVFS_24 - devfs_handle_t devfs_handle; -#endif -}; - -static DEFINE_MUTEX(lirc_dev_lock); - -static struct irctl *irctls[MAX_IRCTL_DEVICES]; -static struct file_operations fops; - -/* Only used for sysfs but defined to void otherwise */ -static lirc_class_t *lirc_class; - -/* helper function - * initializes the irctl structure - */ -static void init_irctl(struct irctl *ir) -{ - mutex_init(&ir->buffer_lock); - ir->d.minor = NOPLUG; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) - ir->tpid = -1; -#endif -} - -static void cleanup(struct irctl *ir) -{ - dprintk(LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor); - - if (ir->buf != ir->d.rbuf) { - lirc_buffer_free(ir->buf); - kfree(ir->buf); - } - ir->buf = NULL; -} - -/* helper function - * reads key codes from driver and puts them into buffer - * returns 0 on success - */ -static int add_to_buf(struct irctl *ir) -{ - if (ir->d.add_to_buf) { - int res = -ENODATA; - int got_data = 0; - - /* - * service the device as long as it is returning - * data and we have space - */ - while ((res = ir->d.add_to_buf(ir->d.data, ir->buf)) == 0) { - got_data++; - } - - if (res == -ENODEV) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) - ir->shutdown = 1; -#else - kthread_stop(ir->task); -#endif - - return got_data ? 0 : res; - } - - return 0; -} - -/* main function of the polling thread */ -static int lirc_thread(void *irctl) -{ - struct irctl *ir = irctl; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) - /* - * This thread doesn't need any user-level access, so get rid - * of all our resources - */ - daemonize("lirc_dev"); - - if (ir->t_notify != NULL) - complete(ir->t_notify); - -#endif - dprintk(LOGHEAD "poll thread started\n", ir->d.name, ir->d.minor); - - do { - if (ir->open) { - if (ir->jiffies_to_wait) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(ir->jiffies_to_wait); -#ifndef LIRC_REMOVE_DURING_EXPORT - } else { - interruptible_sleep_on( - ir->d.get_queue(ir->d.data)); -#endif - } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) - if (ir->shutdown) -#else - if (kthread_should_stop()) -#endif - break; - if (!add_to_buf(ir)) - wake_up_interruptible(&ir->buf->wait_poll); - } else { - set_current_state(TASK_INTERRUPTIBLE); - schedule(); - } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) - } while (!ir->shutdown); - - if (ir->t_notify2 != NULL) - wait_for_completion(ir->t_notify2); - - ir->tpid = -1; - if (ir->t_notify != NULL) - complete(ir->t_notify); -#else - } while (!kthread_should_stop()); -#endif - - dprintk(LOGHEAD "poll thread ended\n", ir->d.name, ir->d.minor); - - return 0; -} - -int lirc_register_driver(struct lirc_driver *d) -{ - struct irctl *ir; - int minor; - int bytes_in_key; - unsigned int buffer_size; - int err; -#ifdef LIRC_HAVE_DEVFS_24 - char name[16]; -#endif - DECLARE_COMPLETION(tn); - - if (!d) { - printk(KERN_ERR "lirc_dev: lirc_register_driver: " - "driver pointer must be not NULL!\n"); - err = -EBADRQC; - goto out; - } - - if (MAX_IRCTL_DEVICES <= d->minor) { - printk(KERN_ERR "lirc_dev: lirc_register_driver: " - "\"minor\" must be between 0 and %d (%d)!\n", - MAX_IRCTL_DEVICES-1, d->minor); - err = -EBADRQC; - goto out; - } - - if (1 > d->code_length || (BUFLEN * 8) < d->code_length) { - printk(KERN_ERR "lirc_dev: lirc_register_driver: " - "code length in bits for minor (%d) " - "must be less than %d!\n", - d->minor, BUFLEN * 8); - err = -EBADRQC; - goto out; - } - - printk(KERN_INFO "lirc_dev: lirc_register_driver: sample_rate: %d\n", - d->sample_rate); - if (d->sample_rate) { - if (2 > d->sample_rate || HZ < d->sample_rate) { - printk(KERN_ERR "lirc_dev: lirc_register_driver: " - "sample_rate must be between 2 and %d!\n", HZ); - err = -EBADRQC; - goto out; - } - if (!d->add_to_buf) { - printk(KERN_ERR "lirc_dev: lirc_register_driver: " - "add_to_buf cannot be NULL when " - "sample_rate is set\n"); - err = -EBADRQC; - goto out; - } -#ifndef LIRC_REMOVE_DURING_EXPORT - } else if (!(d->fops && d->fops->read) && !d->get_queue && !d->rbuf) { -#else - } else if (!(d->fops && d->fops->read) && !d->rbuf) { -#endif - printk(KERN_ERR "lirc_dev: lirc_register_driver: " -#ifndef LIRC_REMOVE_DURING_EXPORT - "fops->read, get_queue and rbuf " -#else - "fops->read and rbuf " -#endif - "cannot all be NULL!\n"); - err = -EBADRQC; - goto out; -#ifndef LIRC_REMOVE_DURING_EXPORT - } else if (!d->get_queue && !d->rbuf) { -#else - } else if (!d->rbuf) { -#endif - if (!(d->fops && d->fops->read && d->fops->poll && - d->fops->ioctl)) { - printk(KERN_ERR "lirc_dev: lirc_register_driver: " - "neither read, poll nor ioctl can be NULL!\n"); - err = -EBADRQC; - goto out; - } - } - - mutex_lock(&lirc_dev_lock); - - minor = d->minor; - - if (minor < 0) { - /* find first free slot for driver */ - for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++) - if (!irctls[minor]) - break; - if (MAX_IRCTL_DEVICES == minor) { - printk(KERN_ERR "lirc_dev: lirc_register_driver: " - "no free slots for drivers!\n"); - err = -ENOMEM; - goto out_lock; - } - } else if (irctls[minor]) { - printk(KERN_ERR "lirc_dev: lirc_register_driver: " - "minor (%d) just registered!\n", minor); - err = -EBUSY; - goto out_lock; - } - - ir = kzalloc(sizeof(struct irctl), GFP_KERNEL); - if (!ir) { - err = -ENOMEM; - goto out_lock; - } - init_irctl(ir); - irctls[minor] = ir; - - if (d->sample_rate) { - ir->jiffies_to_wait = HZ / d->sample_rate; - } else { - /* it means - wait for external event in task queue */ - ir->jiffies_to_wait = 0; - } - - /* some safety check 8-) */ - d->name[sizeof(d->name)-1] = '\0'; - - bytes_in_key = d->code_length/8 + (d->code_length%8 ? 1 : 0); - buffer_size = d->buffer_size ? d->buffer_size : BUFLEN / bytes_in_key; - - if (d->rbuf) { - ir->buf = d->rbuf; - } else { - ir->buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); - if (!ir->buf) { - err = -ENOMEM; - goto out_lock; - } - err = lirc_buffer_init(ir->buf, bytes_in_key, buffer_size); - if (err) { - kfree(ir->buf); - goto out_lock; - } - } - 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; - - ir->d = *d; - ir->d.minor = minor; - -#if defined(LIRC_HAVE_DEVFS_24) - sprintf(name, DEV_LIRC "/%d", ir->d.minor); - ir->devfs_handle = devfs_register(NULL, name, DEVFS_FL_DEFAULT, - IRCTL_DEV_MAJOR, ir->d.minor, - S_IFCHR | S_IRUSR | S_IWUSR, - &fops, NULL); -#elif defined(LIRC_HAVE_DEVFS_26) - devfs_mk_cdev(MKDEV(IRCTL_DEV_MAJOR, ir->d.minor), - S_IFCHR|S_IRUSR|S_IWUSR, - DEV_LIRC "/%u", ir->d.minor); -#endif - (void) lirc_device_create(lirc_class, ir->d.dev, - MKDEV(IRCTL_DEV_MAJOR, ir->d.minor), NULL, - "lirc%u", ir->d.minor); - -#ifndef LIRC_REMOVE_DURING_EXPORT - if (d->sample_rate || d->get_queue) { -#else - if (d->sample_rate) { -#endif - /* try to fire up polling thread */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) - ir->t_notify = &tn; - ir->tpid = kernel_thread(lirc_thread, (void *)ir, 0); - if (ir->tpid < 0) { -#else - ir->task = kthread_run(lirc_thread, (void *)ir, "lirc_dev"); - if (IS_ERR(ir->task)) { -#endif - printk(KERN_ERR "lirc_dev: lirc_register_driver: " - "cannot run poll thread for minor = %d\n", - d->minor); - err = -ECHILD; - goto out_sysfs; - } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) - wait_for_completion(&tn); - ir->t_notify = NULL; -#endif - } - ir->attached = 1; - mutex_unlock(&lirc_dev_lock); - -/* - * Recent kernels should handle this autmatically by increasing/decreasing - * use count when a dependant module is loaded/unloaded. - */ -#ifndef KERNEL_2_5 - MOD_INC_USE_COUNT; -#endif - dprintk("lirc_dev: driver %s registered at minor number = %d\n", - ir->d.name, ir->d.minor); - d->minor = minor; - return minor; - -out_sysfs: - lirc_device_destroy(lirc_class, - MKDEV(IRCTL_DEV_MAJOR, ir->d.minor)); -#ifdef LIRC_HAVE_DEVFS_24 - devfs_unregister(ir->devfs_handle); -#endif -#ifdef LIRC_HAVE_DEVFS_26 - devfs_remove(DEV_LIRC "/%i", ir->d.minor); -#endif -out_lock: - mutex_unlock(&lirc_dev_lock); -out: - return err; -} -EXPORT_SYMBOL(lirc_register_driver); - -int lirc_unregister_driver(int minor) -{ - struct irctl *ir; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) - DECLARE_COMPLETION(tn); - DECLARE_COMPLETION(tn2); -#endif - - if (minor < 0 || minor >= MAX_IRCTL_DEVICES) { - printk(KERN_ERR "lirc_dev: lirc_unregister_driver: " - "\"minor\" must be between 0 and %d!\n", - MAX_IRCTL_DEVICES-1); - return -EBADRQC; - } - - ir = irctls[minor]; - - mutex_lock(&lirc_dev_lock); - - if (ir->d.minor != minor) { - printk(KERN_ERR "lirc_dev: lirc_unregister_driver: " - "minor (%d) device not registered!", minor); - mutex_unlock(&lirc_dev_lock); - return -ENOENT; - } - - /* end up polling thread */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) - if (ir->tpid >= 0) { - ir->t_notify = &tn; - ir->t_notify2 = &tn2; - ir->shutdown = 1; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) - { - struct task_struct *p; - - p = find_task_by_pid(ir->tpid); - wake_up_process(p); - } -#else - /* 2.2.x does not export wake_up_process() */ - wake_up_interruptible(ir->d.get_queue(ir->d.data)); -#endif - complete(&tn2); - wait_for_completion(&tn); - ir->t_notify = NULL; - ir->t_notify2 = NULL; - } -#else /* kernel >= 2.6.23 */ - if (ir->task) - kthread_stop(ir->task); -#endif - - dprintk("lirc_dev: driver %s unregistered from minor number = %d\n", - ir->d.name, ir->d.minor); - - ir->attached = 0; - if (ir->open) { - dprintk(LOGHEAD "releasing opened driver\n", - ir->d.name, ir->d.minor); - wake_up_interruptible(&ir->buf->wait_poll); - mutex_lock(&ir->buffer_lock); - ir->d.set_use_dec(ir->d.data); - module_put(ir->d.owner); - mutex_unlock(&ir->buffer_lock); - } else { - cleanup(ir); - irctls[minor] = NULL; - kfree(ir); - } - -#ifdef LIRC_HAVE_DEVFS_24 - devfs_unregister(ir->devfs_handle); -#endif -#ifdef LIRC_HAVE_DEVFS_26 - devfs_remove(DEV_LIRC "/%u", ir->d.minor); -#endif - lirc_device_destroy(lirc_class, - MKDEV(IRCTL_DEV_MAJOR, ir->d.minor)); - - mutex_unlock(&lirc_dev_lock); - -/* - * Recent kernels should handle this autmatically by increasing/decreasing - * use count when a dependant module is loaded/unloaded. - */ -#ifndef KERNEL_2_5 - MOD_DEC_USE_COUNT; -#endif - - return 0; -} -EXPORT_SYMBOL(lirc_unregister_driver); - -static int irctl_open(struct inode *inode, struct file *file) -{ - struct irctl *ir; - int retval; - - if (iminor(inode) >= MAX_IRCTL_DEVICES || !irctls[iminor(inode)]) { - dprintk("lirc_dev [%d]: open result = -ENODEV\n", - iminor(inode)); - return -ENODEV; - } - - ir = irctls[iminor(inode)]; - - dprintk(LOGHEAD "open called\n", ir->d.name, ir->d.minor); - - /* if the driver has an open function use it instead */ - if (ir->d.fops && ir->d.fops->open) - return ir->d.fops->open(inode, file); - - if (mutex_lock_interruptible(&lirc_dev_lock)) - return -ERESTARTSYS; - - if (ir->d.minor == NOPLUG) { - retval = -ENODEV; - goto error; - } - - if (ir->open) { - retval = -EBUSY; - goto error; - } - - if (try_module_get(ir->d.owner)) { - ++ir->open; - retval = ir->d.set_use_inc(ir->d.data); - - if (retval) { - module_put(ir->d.owner); - --ir->open; - } else { - lirc_buffer_clear(ir->buf); - } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) - if (ir->tpid >= 0) { - struct task_struct *p; - - p = find_task_by_pid(ir->tpid); - wake_up_process(p); - } -#else - if (ir->task) - wake_up_process(ir->task); -#endif - } - error: - if (ir) - dprintk(LOGHEAD "open result = %d\n", ir->d.name, ir->d.minor, - retval); - - mutex_unlock(&lirc_dev_lock); - - return retval; -} - -static int irctl_close(struct inode *inode, struct file *file) -{ - struct irctl *ir = irctls[iminor(inode)]; - - dprintk(LOGHEAD "close called\n", ir->d.name, ir->d.minor); - - /* if the driver has a close function use it instead */ - if (ir->d.fops && ir->d.fops->release) - return ir->d.fops->release(inode, file); - - if (mutex_lock_interruptible(&lirc_dev_lock)) - return -ERESTARTSYS; - - --ir->open; - if (ir->attached) { - ir->d.set_use_dec(ir->d.data); - module_put(ir->d.owner); - } else { - cleanup(ir); - irctls[ir->d.minor] = NULL; - kfree(ir); - } - - mutex_unlock(&lirc_dev_lock); - - return 0; -} - -static unsigned int irctl_poll(struct file *file, poll_table *wait) -{ - struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; - unsigned int ret; - - dprintk(LOGHEAD "poll called\n", ir->d.name, ir->d.minor); - - /* if the driver has a poll function use it instead */ - if (ir->d.fops && ir->d.fops->poll) - return ir->d.fops->poll(file, wait); - - mutex_lock(&ir->buffer_lock); - if (!ir->attached) { - mutex_unlock(&ir->buffer_lock); - return POLLERR; - } - - poll_wait(file, &ir->buf->wait_poll, wait); - - dprintk(LOGHEAD "poll result = %s\n", - ir->d.name, ir->d.minor, - lirc_buffer_empty(ir->buf) ? "0" : "POLLIN|POLLRDNORM"); - - ret = lirc_buffer_empty(ir->buf) ? 0 : (POLLIN|POLLRDNORM); - - mutex_unlock(&ir->buffer_lock); - return ret; -} - -/* - * - */ -static int irctl_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - unsigned long mode; - int result; - struct irctl *ir = irctls[iminor(inode)]; - - dprintk(LOGHEAD "ioctl called (0x%x)\n", - ir->d.name, ir->d.minor, cmd); - - /* if the driver has a ioctl function use it instead */ - if (ir->d.fops && ir->d.fops->ioctl) { - result = ir->d.fops->ioctl(inode, file, cmd, arg); - if (result != -ENOIOCTLCMD) - return result; - } - - if (ir->d.minor == NOPLUG || !ir->attached) { - dprintk(LOGHEAD "ioctl result = -ENODEV\n", - ir->d.name, ir->d.minor); - return -ENODEV; - } - - /* The driver can't handle cmd */ - result = 0; - - switch (cmd) { - case LIRC_GET_FEATURES: - result = put_user(ir->d.features, (unsigned long *)arg); - break; - case LIRC_GET_REC_MODE: - if (!(ir->d.features & LIRC_CAN_REC_MASK)) - return -ENOSYS; - - result = put_user(LIRC_REC2MODE - (ir->d.features & LIRC_CAN_REC_MASK), - (unsigned long *)arg); - break; - case LIRC_SET_REC_MODE: - if (!(ir->d.features & LIRC_CAN_REC_MASK)) - return -ENOSYS; - - 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); - break; - default: - result = -EINVAL; - } - - dprintk(LOGHEAD "ioctl result = %d\n", - ir->d.name, ir->d.minor, result); - - return result; -} - -#ifdef CONFIG_COMPAT -#define LIRC_GET_FEATURES_COMPAT32 _IOR('i', 0x00000000, __u32) - -#define LIRC_GET_SEND_MODE_COMPAT32 _IOR('i', 0x00000001, __u32) -#define LIRC_GET_REC_MODE_COMPAT32 _IOR('i', 0x00000002, __u32) - -#define LIRC_GET_LENGTH_COMPAT32 _IOR('i', 0x0000000f, __u32) - -#define LIRC_SET_SEND_MODE_COMPAT32 _IOW('i', 0x00000011, __u32) -#define LIRC_SET_REC_MODE_COMPAT32 _IOW('i', 0x00000012, __u32) - -static long irctl_compat_ioctl(struct file *file, - unsigned int cmd32, - unsigned long arg) -{ - mm_segment_t old_fs; - int ret; - unsigned long val; - unsigned int cmd; - - switch (cmd32) { - case LIRC_GET_FEATURES_COMPAT32: - case LIRC_GET_SEND_MODE_COMPAT32: - case LIRC_GET_REC_MODE_COMPAT32: - case LIRC_GET_LENGTH_COMPAT32: - case LIRC_SET_SEND_MODE_COMPAT32: - case LIRC_SET_REC_MODE_COMPAT32: - /* - * These commands expect (unsigned long *) arg - * but the 32-bit app supplied (__u32 *). - * Conversion is required. - */ - if (get_user(val, (__u32 *)compat_ptr(arg))) - return -EFAULT; - lock_kernel(); - /* - * tell irctl_ioctl that it's safe to use the pointer - * to val which is in kernel address space and not in - * user address space - */ - old_fs = get_fs(); - set_fs(KERNEL_DS); - - cmd = _IOC(_IOC_DIR(cmd32), _IOC_TYPE(cmd32), _IOC_NR(cmd32), - (_IOC_TYPECHECK(unsigned long))); - ret = irctl_ioctl(file->f_dentry->d_inode, file, - cmd, (unsigned long)(&val)); - - set_fs(old_fs); - unlock_kernel(); - switch (cmd) { - case LIRC_GET_FEATURES: - case LIRC_GET_SEND_MODE: - case LIRC_GET_REC_MODE: - case LIRC_GET_LENGTH: - if (!ret && put_user(val, (__u32 *)compat_ptr(arg))) - return -EFAULT; - break; - } - return ret; - - case LIRC_GET_SEND_CARRIER: - case LIRC_GET_REC_CARRIER: - case LIRC_GET_SEND_DUTY_CYCLE: - case LIRC_GET_REC_DUTY_CYCLE: - case LIRC_GET_REC_RESOLUTION: - 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_DUTY_CYCLE_RANGE: - case LIRC_SET_REC_CARRIER_RANGE: - /* - * These commands expect (unsigned int *)arg - * so no problems here. Just handle the locking. - */ - lock_kernel(); - cmd = cmd32; - ret = irctl_ioctl(file->f_dentry->d_inode, - file, cmd, arg); - unlock_kernel(); - return ret; - default: - /* unknown */ - printk(KERN_ERR "lirc_dev: %s(%s:%d): Unknown cmd %08x\n", - __func__, current->comm, current->pid, cmd32); - return -ENOIOCTLCMD; - } -} -#endif - -static ssize_t irctl_read(struct file *file, - char *buffer, - size_t length, - loff_t *ppos) -{ - struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; - unsigned char buf[ir->chunk_size]; - int ret = 0, written = 0; - int unlock = 1; - DECLARE_WAITQUEUE(wait, current); - - dprintk(LOGHEAD "read called\n", ir->d.name, ir->d.minor); - - /* if the driver has a specific read function use it instead */ - if (ir->d.fops && ir->d.fops->read) - return ir->d.fops->read(file, buffer, length, ppos); - - if (mutex_lock_interruptible(&ir->buffer_lock)) - return -ERESTARTSYS; - if (!ir->attached) { - mutex_unlock(&ir->buffer_lock); - return -ENODEV; - } - - if (length % ir->buf->chunk_size) { - dprintk(LOGHEAD "read result = -EINVAL\n", - ir->d.name, ir->d.minor); - mutex_unlock(&ir->buffer_lock); - return -EINVAL; - } - - /* - * we add ourselves to the task queue before buffer check - * to avoid losing scan code (in case when queue is awaken somewhere - * between while condition checking and scheduling) - */ - add_wait_queue(&ir->buf->wait_poll, &wait); - set_current_state(TASK_INTERRUPTIBLE); - - /* - * while we didn't provide 'length' bytes, device is opened in blocking - * mode and 'copy_to_user' is happy, wait for data. - */ - while (written < length && ret == 0) { - if (lirc_buffer_empty(ir->buf)) { - /* According to the read(2) man page, 'written' can be - * returned as less than 'length', instead of blocking - * again, returning -EWOULDBLOCK, or returning - * -ERESTARTSYS */ - if (written) - break; - if (file->f_flags & O_NONBLOCK) { - ret = -EWOULDBLOCK; - break; - } - if (signal_pending(current)) { - ret = -ERESTARTSYS; - break; - } - - mutex_unlock(&ir->buffer_lock); - schedule(); - set_current_state(TASK_INTERRUPTIBLE); - - if (mutex_lock_interruptible(&ir->buffer_lock)) { - unlock = 0; - ret = -ERESTARTSYS; - break; - } - - if (!ir->attached) { - ret = -ENODEV; - break; - } - } else { - lirc_buffer_read(ir->buf, buf); - ret = copy_to_user((void *)buffer+written, buf, - ir->buf->chunk_size); - written += ir->buf->chunk_size; - } - } - - remove_wait_queue(&ir->buf->wait_poll, &wait); - set_current_state(TASK_RUNNING); - if(unlock) mutex_unlock(&ir->buffer_lock); - - dprintk(LOGHEAD "read result = %s (%d)\n", - ir->d.name, ir->d.minor, ret ? "-EFAULT" : "OK", ret); - - return ret ? ret : written; -} - - -void *lirc_get_pdata(struct file *file) -{ - void *data = NULL; - - if (file && file->f_dentry && file->f_dentry->d_inode && - file->f_dentry->d_inode->i_rdev) { - struct irctl *ir; - ir = irctls[iminor(file->f_dentry->d_inode)]; - data = ir->d.data; - } - - return data; -} -EXPORT_SYMBOL(lirc_get_pdata); - - -static ssize_t irctl_write(struct file *file, const char *buffer, - size_t length, loff_t *ppos) -{ - struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)]; - - dprintk(LOGHEAD "write called\n", ir->d.name, ir->d.minor); - - /* if the driver has a specific read function use it instead */ - if (ir->d.fops && ir->d.fops->write) - return ir->d.fops->write(file, buffer, length, ppos); - - if (!ir->attached) - return -ENODEV; - - return -EINVAL; -} - - -static struct file_operations fops = { - .owner = THIS_MODULE, - .read = irctl_read, - .write = irctl_write, - .poll = irctl_poll, - .ioctl = irctl_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = irctl_compat_ioctl, -#endif - .open = irctl_open, - .release = irctl_close -}; - -/* For now don't try to use it as a static version ! */ -#ifdef MODULE - -static int __init lirc_dev_init(void) -{ - if (register_chrdev(IRCTL_DEV_MAJOR, IRCTL_DEV_NAME, &fops)) { - printk(KERN_ERR "lirc_dev: register_chrdev failed\n"); - goto out; - } - - lirc_class = class_create(THIS_MODULE, "lirc"); - if (IS_ERR(lirc_class)) { - printk(KERN_ERR "lirc_dev: class_create failed\n"); - goto out_unregister; - } - - printk(KERN_INFO "lirc_dev: IR Remote Control driver registered, " - "major %d \n", IRCTL_DEV_MAJOR); - - return 0; - -out_unregister: -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) - if (unregister_chrdev(IRCTL_DEV_MAJOR, IRCTL_DEV_NAME)) - printk(KERN_ERR "lirc_dev: unregister_chrdev failed!\n"); -#else - /* unregister_chrdev returns void now */ - unregister_chrdev(IRCTL_DEV_MAJOR, IRCTL_DEV_NAME); -#endif -out: - return -1; -} - -static void __exit lirc_dev_exit(void) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) - int ret; - - ret = unregister_chrdev(IRCTL_DEV_MAJOR, IRCTL_DEV_NAME); - class_destroy(lirc_class); - - if (ret) - printk(KERN_ERR "lirc_dev: error in " - "module_unregister_chrdev: %d\n", ret); - else - dprintk("lirc_dev: module successfully unloaded\n"); -#else - /* unregister_chrdev returns void now */ - unregister_chrdev(IRCTL_DEV_MAJOR, IRCTL_DEV_NAME); - class_destroy(lirc_class); - dprintk("lirc_dev: module unloaded\n"); -#endif -} - -module_init(lirc_dev_init); -module_exit(lirc_dev_exit); - -MODULE_DESCRIPTION("LIRC base driver module"); -MODULE_AUTHOR("Artur Lipowski"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_CHARDEV_MAJOR(IRCTL_DEV_MAJOR); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Enable debugging messages"); - -#endif /* MODULE */ diff --git a/ubuntu/lirc/lirc_dev/lirc_dev.h b/ubuntu/lirc/lirc_dev/lirc_dev.h deleted file mode 100644 index c94086ef25a..00000000000 --- a/ubuntu/lirc/lirc_dev/lirc_dev.h +++ /dev/null @@ -1,343 +0,0 @@ -/* - * LIRC base driver - * - * (L) by Artur Lipowski <alipowski@interia.pl> - * This code is licensed under GNU GPL - * - * $Id: lirc_dev.h,v 1.37 2009/03/15 09:34:00 lirc Exp $ - * - */ - -#ifndef _LINUX_LIRC_DEV_H -#define _LINUX_LIRC_DEV_H - -#ifndef LIRC_REMOVE_DURING_EXPORT -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11) -/* when was it really introduced? */ -#define LIRC_HAVE_KFIFO -#endif -#endif -#define MAX_IRCTL_DEVICES 4 -#define BUFLEN 16 - -#define mod(n, div) ((n) % (div)) - -#include <linux/slab.h> -#include <linux/fs.h> -#ifdef LIRC_HAVE_KFIFO -#include <linux/kfifo.h> -#endif - -struct lirc_buffer { - wait_queue_head_t wait_poll; - spinlock_t lock; - unsigned int chunk_size; - unsigned int size; /* in chunks */ - /* Using chunks instead of bytes pretends to simplify boundary checking - * And should allow for some performance fine tunning later */ -#ifdef LIRC_HAVE_KFIFO - struct kfifo *fifo; -#else - unsigned int fill; /* in chunks */ - int head, tail; /* in chunks */ - unsigned char *data; -#endif -}; -#ifndef LIRC_HAVE_KFIFO -static inline void lirc_buffer_lock(struct lirc_buffer *buf, - unsigned long *flags) -{ - spin_lock_irqsave(&buf->lock, *flags); -} -static inline void lirc_buffer_unlock(struct lirc_buffer *buf, - unsigned long *flags) -{ - spin_unlock_irqrestore(&buf->lock, *flags); -} -static inline void _lirc_buffer_clear(struct lirc_buffer *buf) -{ - buf->head = 0; - buf->tail = 0; - buf->fill = 0; -} -#endif -static inline void lirc_buffer_clear(struct lirc_buffer *buf) -{ -#ifdef LIRC_HAVE_KFIFO - if (buf->fifo) - kfifo_reset(buf->fifo); -#else - unsigned long flags; - lirc_buffer_lock(buf, &flags); - _lirc_buffer_clear(buf); - lirc_buffer_unlock(buf, &flags); -#endif -} -static inline int lirc_buffer_init(struct lirc_buffer *buf, - unsigned int chunk_size, - unsigned int size) -{ - int ret; - init_waitqueue_head(&buf->wait_poll); - spin_lock_init(&buf->lock); -#ifndef LIRC_HAVE_KFIFO - _lirc_buffer_clear(buf); -#endif - buf->chunk_size = chunk_size; - buf->size = size; -#ifdef LIRC_HAVE_KFIFO - ret = kfifo_alloc(buf->fifo, size*chunk_size, GFP_KERNEL); - if (ret) - return -ENOMEM; -#else - buf->data = kmalloc(size*chunk_size, GFP_KERNEL); - if (buf->data == NULL) - return -ENOMEM; - memset(buf->data, 0, size*chunk_size); -#endif - return 0; -} -static inline void lirc_buffer_free(struct lirc_buffer *buf) -{ -#ifdef LIRC_HAVE_KFIFO - if (buf->fifo) - kfifo_free(buf->fifo); -#else - kfree(buf->data); - buf->data = NULL; - buf->head = 0; - buf->tail = 0; - buf->fill = 0; - buf->chunk_size = 0; - buf->size = 0; -#endif -} -#ifndef LIRC_HAVE_KFIFO -static inline int _lirc_buffer_full(struct lirc_buffer *buf) -{ - return (buf->fill >= buf->size); -} -#endif -static inline int lirc_buffer_full(struct lirc_buffer *buf) -{ -#ifdef LIRC_HAVE_KFIFO - return kfifo_len(buf->fifo) == buf->size * buf->chunk_size; -#else - unsigned long flags; - int ret; - lirc_buffer_lock(buf, &flags); - ret = _lirc_buffer_full(buf); - lirc_buffer_unlock(buf, &flags); - return ret; -#endif -} -#ifndef LIRC_HAVE_KFIFO -static inline int _lirc_buffer_empty(struct lirc_buffer *buf) -{ - return !(buf->fill); -} -#endif -static inline int lirc_buffer_empty(struct lirc_buffer *buf) -{ -#ifdef LIRC_HAVE_KFIFO - return !kfifo_len(buf->fifo); -#else - unsigned long flags; - int ret; - lirc_buffer_lock(buf, &flags); - ret = _lirc_buffer_empty(buf); - lirc_buffer_unlock(buf, &flags); - return ret; -#endif -} -#ifndef LIRC_HAVE_KFIFO -static inline int _lirc_buffer_available(struct lirc_buffer *buf) -{ - return (buf->size - buf->fill); -} -#endif -static inline int lirc_buffer_available(struct lirc_buffer *buf) -{ -#ifdef LIRC_HAVE_KFIFO - return buf->size - (kfifo_len(buf->fifo) / buf->chunk_size); -#else - unsigned long flags; - int ret; - lirc_buffer_lock(buf, &flags); - ret = _lirc_buffer_available(buf); - lirc_buffer_unlock(buf, &flags); - return ret; -#endif -} -#ifndef LIRC_HAVE_KFIFO -static inline void _lirc_buffer_read_1(struct lirc_buffer *buf, - unsigned char *dest) -{ - memcpy(dest, &buf->data[buf->head*buf->chunk_size], buf->chunk_size); - buf->head = mod(buf->head+1, buf->size); - buf->fill -= 1; -} -#endif -static inline void lirc_buffer_read(struct lirc_buffer *buf, - unsigned char *dest) -{ -#ifdef LIRC_HAVE_KFIFO - if (kfifo_len(buf->fifo) >= buf->chunk_size) - kfifo_out(buf->fifo, dest, buf->chunk_size); -#else - unsigned long flags; - lirc_buffer_lock(buf, &flags); - _lirc_buffer_read_1(buf, dest); - lirc_buffer_unlock(buf, &flags); -#endif -} -#ifndef LIRC_HAVE_KFIFO -static inline void _lirc_buffer_write_1(struct lirc_buffer *buf, - unsigned char *orig) -{ - memcpy(&buf->data[buf->tail*buf->chunk_size], orig, buf->chunk_size); - buf->tail = mod(buf->tail+1, buf->size); - buf->fill++; -} -#endif -static inline void lirc_buffer_write(struct lirc_buffer *buf, - unsigned char *orig) -{ -#ifdef LIRC_HAVE_KFIFO - kfifo_in(buf->fifo, orig, buf->chunk_size); -#else - unsigned long flags; - lirc_buffer_lock(buf, &flags); - _lirc_buffer_write_1(buf, orig); - lirc_buffer_unlock(buf, &flags); -#endif -} -#ifndef LIRC_HAVE_KFIFO -static inline void _lirc_buffer_write_n(struct lirc_buffer *buf, - unsigned char *orig, int count) -{ - int space1; - if (buf->head > buf->tail) - space1 = buf->head - buf->tail; - else - space1 = buf->size - buf->tail; - - if (count > space1) { - memcpy(&buf->data[buf->tail * buf->chunk_size], orig, - space1 * buf->chunk_size); - memcpy(&buf->data[0], orig + (space1 * buf->chunk_size), - (count - space1) * buf->chunk_size); - } else { - memcpy(&buf->data[buf->tail * buf->chunk_size], orig, - count * buf->chunk_size); - } - buf->tail = mod(buf->tail + count, buf->size); - buf->fill += count; -} -#endif -static inline void lirc_buffer_write_n(struct lirc_buffer *buf, - unsigned char *orig, int count) -{ -#ifdef LIRC_HAVE_KFIFO - kfifo_in(buf->fifo, orig, count * buf->chunk_size); -#else - unsigned long flags; - lirc_buffer_lock(buf, &flags); - _lirc_buffer_write_n(buf, orig, count); - lirc_buffer_unlock(buf, &flags); -#endif -} - -struct lirc_driver { - char name[40]; - int minor; - unsigned long code_length; - unsigned int buffer_size; /* in chunks holding one code each */ - int sample_rate; - unsigned long features; - void *data; - int (*add_to_buf) (void *data, struct lirc_buffer *buf); -#ifndef LIRC_REMOVE_DURING_EXPORT - wait_queue_head_t* (*get_queue) (void *data); -#endif - struct lirc_buffer *rbuf; - int (*set_use_inc) (void *data); - void (*set_use_dec) (void *data); - struct file_operations *fops; - struct device *dev; - struct module *owner; -}; -/* name: - * this string will be used for logs - * - * minor: - * indicates minor device (/dev/lirc) number for registered driver - * if caller fills it with negative value, then the first free minor - * number will be used (if available) - * - * code_length: - * length of the remote control key code expressed in bits - * - * sample_rate: - * sample_rate equal to 0 means that no polling will be performed and - * add_to_buf will be triggered by external events (through task queue - * returned by get_queue) - * - * data: - * it may point to any driver data and this pointer will be passed to - * all callback functions - * - * add_to_buf: - * add_to_buf will be called after specified period of the time or - * triggered by the external event, this behavior depends on value of - * the sample_rate this function will be called in user context. This - * routine should return 0 if data was added to the buffer and - * -ENODATA if none was available. This should add some number of bits - * evenly divisible by code_length to the buffer - * - * get_queue: - * this callback should return a pointer to the task queue which will - * be used for external event waiting - * - * rbuf: - * if not NULL, it will be used as a read buffer, you will have to - * write to the buffer by other means, like irq's (see also - * lirc_serial.c). - * - * set_use_inc: - * set_use_inc will be called after device is opened - * - * set_use_dec: - * set_use_dec will be called after device is closed - * - * fops: - * file_operations for drivers which don't fit the current driver model. - * - * Some ioctl's can be directly handled by lirc_dev if the driver's - * ioctl function is NULL or if it returns -ENOIOCTLCMD (see also - * lirc_serial.c). - * - * owner: - * the module owning this struct - * - */ - - -/* following functions can be called ONLY from user context - * - * returns negative value on error or minor number - * of the registered device if success - * contents of the structure pointed by d is copied - */ -extern int lirc_register_driver(struct lirc_driver *d); - -/* returns negative value on error or 0 if success -*/ -extern int lirc_unregister_driver(int minor); - -/* Returns the private data stored in the lirc_driver - * associated with the given device file pointer. - */ -void *lirc_get_pdata(struct file *file); - -#endif diff --git a/ubuntu/lirc/lirc_ene0100/Makefile b/ubuntu/lirc/lirc_ene0100/Makefile deleted file mode 100644 index b5f2e6fd137..00000000000 --- a/ubuntu/lirc/lirc_ene0100/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. - -obj-$(CONFIG_LIRC_ENE0100) += lirc_ene0100.o diff --git a/ubuntu/lirc/lirc_ene0100/lirc_ene0100.c b/ubuntu/lirc/lirc_ene0100/lirc_ene0100.c deleted file mode 100644 index da9519fcadd..00000000000 --- a/ubuntu/lirc/lirc_ene0100/lirc_ene0100.c +++ /dev/null @@ -1,653 +0,0 @@ -/* - * driver for ENE KB3926 B/C/D CIR (also known as ENE0100) - * - * Copyright (C) 2009 Maxim Levitsky <maximlevitsky@gmail.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/pnp.h> -#include <linux/io.h> -#include <linux/interrupt.h> -#include "lirc_ene0100.h" - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16) -#error "Sorry, this driver needs kernel version 2.6.16 or higher" -#else - -static int sample_period = 75; -static int enable_idle = 1; -static int enable_learning; - -static void ene_set_idle(struct ene_device *dev, int idle); -static void ene_set_inputs(struct ene_device *dev, int enable); - -/* read a hardware register */ -static u8 ene_hw_read_reg(struct ene_device *dev, u16 reg) -{ - outb(reg >> 8, dev->hw_io + ENE_ADDR_HI); - outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO); - return inb(dev->hw_io + ENE_IO); -} - -/* write a hardware register */ -static void ene_hw_write_reg(struct ene_device *dev, u16 reg, u8 value) -{ - outb(reg >> 8, dev->hw_io + ENE_ADDR_HI); - outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO); - outb(value, dev->hw_io + ENE_IO); -} - -/* change specific bits in hardware register */ -static void ene_hw_write_reg_mask(struct ene_device *dev, - u16 reg, u8 value, u8 mask) -{ - u8 regvalue; - - outb(reg >> 8, dev->hw_io + ENE_ADDR_HI); - outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO); - - regvalue = inb(dev->hw_io + ENE_IO) & ~mask; - regvalue |= (value & mask); - outb(regvalue, dev->hw_io + ENE_IO); -} - -/* read irq status and ack it */ -static int ene_hw_irq_status(struct ene_device *dev, int *buffer_pointer) -{ - u8 irq_status; - u8 fw_flags1, fw_flags2; - - fw_flags2 = ene_hw_read_reg(dev, ENE_FW2); - - if (buffer_pointer) - *buffer_pointer = 4 * (fw_flags2 & ENE_FW2_BUF_HIGH); - - if (dev->hw_revision < ENE_HW_C) { - irq_status = ene_hw_read_reg(dev, ENEB_IRQ_STATUS); - - if (!irq_status & ENEB_IRQ_STATUS_IR) - return 0; - ene_hw_write_reg(dev, ENEB_IRQ_STATUS, - irq_status & ~ENEB_IRQ_STATUS_IR); - - /* rev B support only recieving */ - return ENE_IRQ_RX; - } - - irq_status = ene_hw_read_reg(dev, ENEC_IRQ); - - if (!irq_status && ENEC_IRQ_STATUS) - return 0; - - /* original driver does that twice - a workaround ? */ - ene_hw_write_reg(dev, ENEC_IRQ, irq_status & ~ENEC_IRQ_STATUS); - ene_hw_write_reg(dev, ENEC_IRQ, irq_status & ~ENEC_IRQ_STATUS); - - /* clear unknown flag in F8F9 */ - if (fw_flags2 & ENE_FW2_IRQ_CLR) - ene_hw_write_reg(dev, ENE_FW2, fw_flags2 & ~ENE_FW2_IRQ_CLR); - - /* check if this is a TX interrupt */ - fw_flags1 = ene_hw_read_reg(dev, ENE_FW1); - - if (fw_flags1 & ENE_FW1_TXIRQ) { - ene_hw_write_reg(dev, ENE_FW1, fw_flags1 & ~ENE_FW1_TXIRQ); - return ENE_IRQ_TX; - } else - return ENE_IRQ_RX; -} - -static int ene_hw_detect(struct ene_device *dev) -{ - u8 chip_major, chip_minor; - u8 hw_revision, old_ver; - u8 tmp; - u8 fw_capabilities; - - tmp = ene_hw_read_reg(dev, ENE_HW_UNK); - ene_hw_write_reg(dev, ENE_HW_UNK, tmp & ~ENE_HW_UNK_CLR); - - chip_major = ene_hw_read_reg(dev, ENE_HW_VER_MAJOR); - chip_minor = ene_hw_read_reg(dev, ENE_HW_VER_MINOR); - - ene_hw_write_reg(dev, ENE_HW_UNK, tmp); - hw_revision = ene_hw_read_reg(dev, ENE_HW_VERSION); - old_ver = ene_hw_read_reg(dev, ENE_HW_VER_OLD); - - if (hw_revision == 0xFF) { - - ene_printk(KERN_WARNING, "device seems to be disabled\n"); - ene_printk(KERN_WARNING, - "send a mail to lirc-list@lists.sourceforge.net\n"); - ene_printk(KERN_WARNING, "please attach output of acpidump\n"); - - return -ENODEV; - } - - if (chip_major == 0x33) { - ene_printk(KERN_WARNING, "chips 0x33xx aren't supported yet\n"); - return -ENODEV; - } - - if (chip_major == 0x39 && chip_minor == 0x26 && hw_revision == 0xC0) { - dev->hw_revision = ENE_HW_C; - ene_printk(KERN_WARNING, - "KB3926C detected, driver support is not complete!\n"); - - } else if (old_ver == 0x24 && hw_revision == 0xC0) { - dev->hw_revision = ENE_HW_B; - ene_printk(KERN_NOTICE, "KB3926B detected\n"); - } else { - dev->hw_revision = ENE_HW_D; - ene_printk(KERN_WARNING, - "unknown ENE chip detected, assuming KB3926D\n"); - ene_printk(KERN_WARNING, "driver support incomplete"); - - } - - ene_printk(KERN_DEBUG, "chip is 0x%02x%02x - 0x%02x, 0x%02x\n", - chip_major, chip_minor, old_ver, hw_revision); - - - /* detect features hardware supports */ - - if (dev->hw_revision < ENE_HW_C) - return 0; - - fw_capabilities = ene_hw_read_reg(dev, ENE_FW2); - - dev->hw_gpio40_learning = fw_capabilities & ENE_FW2_GP40_AS_LEARN; - dev->hw_learning_and_tx_capable = fw_capabilities & ENE_FW2_LEARNING; - - dev->hw_fan_as_normal_input = dev->hw_learning_and_tx_capable && - fw_capabilities & ENE_FW2_FAN_AS_NRML_IN; - - ene_printk(KERN_NOTICE, "hardware features:\n"); - ene_printk(KERN_NOTICE, - "learning and tx %s, gpio40_learn %s, fan_in %s\n", - dev->hw_learning_and_tx_capable ? "on" : "off", - dev->hw_gpio40_learning ? "on" : "off", - dev->hw_fan_as_normal_input ? "on" : "off"); - - if (!dev->hw_learning_and_tx_capable && enable_learning) - enable_learning = 0; - - if (dev->hw_learning_and_tx_capable) { - ene_printk(KERN_WARNING, - "Device supports transmitting, but the driver doesn't\n"); - ene_printk(KERN_WARNING, - "due to lack of hardware to test against.\n"); - ene_printk(KERN_WARNING, - "Send a mail to: lirc-list@lists.sourceforge.net\n"); - } - return 0; -} - -/* hardware initialization */ -static int ene_hw_init(void *data) -{ - u8 reg_value; - struct ene_device *dev = (struct ene_device *)data; - dev->in_use = 1; - - if (dev->hw_revision < ENE_HW_C) { - ene_hw_write_reg(dev, ENEB_IRQ, dev->irq << 1); - ene_hw_write_reg(dev, ENEB_IRQ_UNK1, 0x01); - } else { - reg_value = ene_hw_read_reg(dev, ENEC_IRQ) & 0xF0; - reg_value |= ENEC_IRQ_UNK_EN; - reg_value &= ~ENEC_IRQ_STATUS; - reg_value |= (dev->irq & ENEC_IRQ_MASK); - ene_hw_write_reg(dev, ENEC_IRQ, reg_value); - ene_hw_write_reg(dev, ENE_TX_UNK1, 0x63); - } - - ene_hw_write_reg(dev, ENE_CIR_CONF2, 0x00); - ene_set_inputs(dev, enable_learning); - - /* set sampling period */ - ene_hw_write_reg(dev, ENE_CIR_SAMPLE_PERIOD, sample_period); - - /* ack any pending irqs - just in case */ - ene_hw_irq_status(dev, NULL); - - /* enter idle mode */ - ene_set_idle(dev, 1); - - /* enable firmware bits */ - ene_hw_write_reg_mask(dev, ENE_FW1, - ENE_FW1_ENABLE | ENE_FW1_IRQ, - ENE_FW1_ENABLE | ENE_FW1_IRQ); - /* clear stats */ - dev->sample = 0; - return 0; -} - -/* this enables gpio40 signal, used if connected to wide band input*/ -static void ene_enable_gpio40(struct ene_device *dev, int enable) -{ - ene_hw_write_reg_mask(dev, ENE_CIR_CONF1, enable ? - 0 : ENE_CIR_CONF2_GPIO40DIS, - ENE_CIR_CONF2_GPIO40DIS); -} - -/* this enables the classic sampler */ -static void ene_enable_normal_recieve(struct ene_device *dev, int enable) -{ - ene_hw_write_reg(dev, ENE_CIR_CONF1, enable ? ENE_CIR_CONF1_ADC_ON : 0); -} - -/* this enables recieve via fan input */ -static void ene_enable_fan_recieve(struct ene_device *dev, int enable) -{ - if (!enable) - ene_hw_write_reg(dev, ENE_FAN_AS_IN1, 0); - else { - ene_hw_write_reg(dev, ENE_FAN_AS_IN1, ENE_FAN_AS_IN1_EN); - ene_hw_write_reg(dev, ENE_FAN_AS_IN2, ENE_FAN_AS_IN2_EN); - } - dev->fan_input_inuse = enable; -} - -/* determine which input to use*/ -static void ene_set_inputs(struct ene_device *dev, int learning_enable) -{ - ene_enable_normal_recieve(dev, 1); - - /* old hardware doesn't support learning mode for sure */ - if (dev->hw_revision <= ENE_HW_B) - return; - - /* reciever not learning capable, still set gpio40 correctly */ - if (!dev->hw_learning_and_tx_capable) { - ene_enable_gpio40(dev, !dev->hw_gpio40_learning); - return; - } - - /* enable learning mode */ - if (learning_enable) { - ene_enable_gpio40(dev, dev->hw_gpio40_learning); - - /* fan input is not used for learning */ - if (dev->hw_fan_as_normal_input) - ene_enable_fan_recieve(dev, 0); - - /* disable learning mode */ - } else { - if (dev->hw_fan_as_normal_input) { - ene_enable_fan_recieve(dev, 1); - ene_enable_normal_recieve(dev, 0); - } else - ene_enable_gpio40(dev, !dev->hw_gpio40_learning); - } - - /* set few additional settings for this mode */ - ene_hw_write_reg_mask(dev, ENE_CIR_CONF1, learning_enable ? - ENE_CIR_CONF1_LEARN1 : 0, ENE_CIR_CONF1_LEARN1); - - ene_hw_write_reg_mask(dev, ENE_CIR_CONF2, learning_enable ? - ENE_CIR_CONF2_LEARN2 : 0, ENE_CIR_CONF2_LEARN2); -} - -/* deinitialization */ -static void ene_hw_deinit(void *data) -{ - struct ene_device *dev = (struct ene_device *)data; - - /* disable samplers */ - ene_enable_normal_recieve(dev, 0); - - if (dev->hw_fan_as_normal_input) - ene_enable_fan_recieve(dev, 0); - - /* disable hardware IRQ and firmware flag */ - ene_hw_write_reg_mask(dev, ENE_FW1, 0, ENE_FW1_ENABLE | ENE_FW1_IRQ); - - ene_set_idle(dev, 1); - dev->in_use = 0; -} - -/* sends current sample to userspace */ -static void send_sample(struct ene_device *dev) -{ - int value = abs(dev->sample) & PULSE_MASK; - - if (dev->sample > 0) - value |= PULSE_BIT; - - if (!lirc_buffer_full(dev->lirc_driver->rbuf)) { - lirc_buffer_write(dev->lirc_driver->rbuf, (void *)&value); - wake_up(&dev->lirc_driver->rbuf->wait_poll); - } - dev->sample = 0; -} - -/* this updates current sample */ -static void update_sample(struct ene_device *dev, int sample) -{ - if (!dev->sample) - dev->sample = sample; - else if (same_sign(dev->sample, sample)) - dev->sample += sample; - else { - send_sample(dev); - dev->sample = sample; - } -} - -/* enable or disable idle mode */ -static void ene_set_idle(struct ene_device *dev, int idle) -{ - struct timeval now; - int disable = idle && enable_idle && (dev->hw_revision < ENE_HW_C); - - ene_hw_write_reg_mask(dev, ENE_CIR_SAMPLE_PERIOD, - disable ? 0 : ENE_CIR_SAMPLE_OVERFLOW, - ENE_CIR_SAMPLE_OVERFLOW); - dev->idle = idle; - - /* remember when we have entered the idle mode */ - if (idle) { - do_gettimeofday(&dev->gap_start); - return; - } - - /* send the gap between keypresses now */ - do_gettimeofday(&now); - - if (now.tv_sec - dev->gap_start.tv_sec > 16) - dev->sample = space(PULSE_MASK); - else - dev->sample = dev->sample + - space(1000000ull * (now.tv_sec - dev->gap_start.tv_sec)) - + space(now.tv_usec - dev->gap_start.tv_usec); - - if (abs(dev->sample) > PULSE_MASK) - dev->sample = space(PULSE_MASK); - send_sample(dev); -} - -/* interrupt handler */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) -static irqreturn_t ene_hw_irq(int irq, void *data) -#else -static irqreturn_t ene_hw_irq(int irq, void *data, struct pt_regs *regs) -#endif -{ - u16 hw_value; - int i, hw_sample; - int space; - int buffer_pointer; - int irq_status; - - struct ene_device *dev = (struct ene_device *)data; - irq_status = ene_hw_irq_status(dev, &buffer_pointer); - - if (!irq_status) - return IRQ_NONE; - - /* TODO: only RX for now */ - if (irq_status == ENE_IRQ_TX) - return IRQ_HANDLED; - - for (i = 0; i < ENE_SAMPLES_SIZE; i++) { - - hw_value = ene_hw_read_reg(dev, - ENE_SAMPLE_BUFFER + buffer_pointer + i); - - if (dev->fan_input_inuse) { - /* read high part of the sample */ - hw_value |= ene_hw_read_reg(dev, - ENE_SAMPLE_BUFFER_FAN + buffer_pointer + i) << 8; - - /* test for _space_ bit */ - space = !(hw_value & ENE_FAN_SMPL_PULS_MSK); - - /* clear space bit, and other unused bits */ - hw_value &= ENE_FAN_VALUE_MASK; - hw_sample = hw_value * ENE_SAMPLE_PERIOD_FAN; - - } else { - space = hw_value & ENE_SAMPLE_SPC_MASK; - hw_value &= ENE_SAMPLE_VALUE_MASK; - hw_sample = hw_value * sample_period; - } - - /* no more data */ - if (!(hw_value)) - break; - - if (space) - hw_sample *= -1; - - /* overflow sample recieved, handle it */ - - if (!dev->fan_input_inuse && hw_value == ENE_SAMPLE_OVERFLOW) { - - if (dev->idle) - continue; - - if (dev->sample > 0 || abs(dev->sample) <= ENE_MAXGAP) - update_sample(dev, hw_sample); - else - ene_set_idle(dev, 1); - - continue; - } - - /* normal first sample recieved */ - if (!dev->fan_input_inuse && dev->idle) { - ene_set_idle(dev, 0); - - /* discard first recieved value, its random - since its the time signal was off before - first pulse if idle mode is enabled, HW - does that for us */ - - if (!enable_idle) - continue; - } - update_sample(dev, hw_sample); - send_sample(dev); - } - return IRQ_HANDLED; -} - -static int ene_probe(struct pnp_dev *pnp_dev, - const struct pnp_device_id *dev_id) -{ - struct ene_device *dev; - struct lirc_driver *lirc_driver; - int error = -ENOMEM; - - dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL); - - if (!dev) - goto err1; - - dev->pnp_dev = pnp_dev; - pnp_set_drvdata(pnp_dev, dev); - - - /* prepare lirc interface */ - error = -ENOMEM; - lirc_driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); - - if (!lirc_driver) - goto err2; - - dev->lirc_driver = lirc_driver; - - strcpy(lirc_driver->name, ENE_DRIVER_NAME); - lirc_driver->minor = -1; - lirc_driver->code_length = sizeof(int) * 8; - lirc_driver->features = LIRC_CAN_REC_MODE2; - lirc_driver->data = dev; - lirc_driver->set_use_inc = ene_hw_init; - lirc_driver->set_use_dec = ene_hw_deinit; - lirc_driver->dev = &pnp_dev->dev; - lirc_driver->owner = THIS_MODULE; - - lirc_driver->rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL); - - if (!lirc_driver->rbuf) - goto err3; - - if (lirc_buffer_init(lirc_driver->rbuf, sizeof(int), sizeof(int) * 256)) - goto err4; - - error = -ENODEV; - if (lirc_register_driver(lirc_driver)) - goto err5; - - /* validate resources */ - if (!pnp_port_valid(pnp_dev, 0) || pnp_port_len(pnp_dev, 0) < ENE_MAX_IO) - goto err6; - - if (!pnp_irq_valid(pnp_dev, 0)) - goto err6; - - dev->hw_io = pnp_port_start(pnp_dev, 0); - dev->irq = pnp_irq(pnp_dev, 0); - - /* claim the resources */ - error = -EBUSY; - if (!request_region(dev->hw_io, ENE_MAX_IO, ENE_DRIVER_NAME)) - goto err6; - - if (request_irq(dev->irq, ene_hw_irq, - IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) - goto err7; - - /* detect hardware version and features */ - error = ene_hw_detect(dev); - if (error) - goto err8; - - ene_printk(KERN_NOTICE, "driver has been succesfully loaded\n"); - return 0; - -err8: - free_irq(dev->irq, dev); -err7: - release_region(dev->hw_io, ENE_MAX_IO); -err6: - lirc_unregister_driver(lirc_driver->minor); -err5: - lirc_buffer_free(lirc_driver->rbuf); -err4: - kfree(lirc_driver->rbuf); -err3: - kfree(lirc_driver); -err2: - kfree(dev); -err1: - return error; -} - -static void ene_remove(struct pnp_dev *pnp_dev) -{ - struct ene_device *dev = pnp_get_drvdata(pnp_dev); - ene_hw_deinit(dev); - free_irq(dev->irq, dev); - release_region(dev->hw_io, ENE_MAX_IO); - lirc_unregister_driver(dev->lirc_driver->minor); - lirc_buffer_free(dev->lirc_driver->rbuf); - kfree(dev->lirc_driver); - kfree(dev); -} - -#ifdef CONFIG_PM - -/* TODO: make 'wake on IR' configurable and add .shutdown */ -/* currently impossible due to lack of kernel support */ - -static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state) -{ - struct ene_device *dev = pnp_get_drvdata(pnp_dev); - ene_hw_write_reg_mask(dev, ENE_FW1, ENE_FW1_WAKE, ENE_FW1_WAKE); - return 0; -} - -static int ene_resume(struct pnp_dev *pnp_dev) -{ - struct ene_device *dev = pnp_get_drvdata(pnp_dev); - if (dev->in_use) - ene_hw_init(dev); - - ene_hw_write_reg_mask(dev, ENE_FW1, 0, ENE_FW1_WAKE); - return 0; -} - -#endif - -static const struct pnp_device_id ene_ids[] = { - {.id = "ENE0100",}, - {}, -}; - -static struct pnp_driver ene_driver = { - .name = ENE_DRIVER_NAME, - .id_table = ene_ids, - .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, - - .probe = ene_probe, - .remove = __devexit_p(ene_remove), - -#ifdef CONFIG_PM - .suspend = ene_suspend, - .resume = ene_resume, -#endif -}; - -static int __init ene_init(void) -{ - if (sample_period < 5) { - ene_printk(KERN_ERR, "sample period must be at\n"); - ene_printk(KERN_ERR, "least 5 us, (at least 30 recommended)\n"); - return -EINVAL; - } - return pnp_register_driver(&ene_driver); -} - -static void ene_exit(void) -{ - pnp_unregister_driver(&ene_driver); -} - -module_param(sample_period, int, S_IRUGO); -MODULE_PARM_DESC(sample_period, "Hardware sample period (75 us default)"); - -module_param(enable_idle, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(enable_idle, - "Enables turning off signal sampling after long inactivity time; " - "if disabled might help detecting input signal (default: enabled)"); - -module_param(enable_learning, bool, S_IRUGO); -MODULE_PARM_DESC(enable_learning, "Use wide band (learning) reciever"); - -MODULE_DEVICE_TABLE(pnp, ene_ids); -MODULE_DESCRIPTION - ("LIRC driver for KB3926B/KB3926C/KB3926D (aka ENE0100) CIR port"); -MODULE_AUTHOR("Maxim Levitsky"); -MODULE_LICENSE("GPL"); - -module_init(ene_init); -module_exit(ene_exit); -#endif diff --git a/ubuntu/lirc/lirc_ene0100/lirc_ene0100.h b/ubuntu/lirc/lirc_ene0100/lirc_ene0100.h deleted file mode 100644 index ae197531357..00000000000 --- a/ubuntu/lirc/lirc_ene0100/lirc_ene0100.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * driver for ENE KB3926 B/C/D CIR (also known as ENE0100) - * - * Copyright (C) 2009 Maxim Levitsky <maximlevitsky@gmail.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#include "../kcompat.h" -#include "../lirc.h" -#include "../lirc_dev/lirc_dev.h" - -/* hardware address */ -#define ENE_STATUS 0 /* hardware status - unused */ -#define ENE_ADDR_HI 1 /* hi byte of register address */ -#define ENE_ADDR_LO 2 /* low byte of register address */ -#define ENE_IO 3 /* read/write window */ -#define ENE_MAX_IO 4 - -/* 8 bytes of samples, divided in 2 halfs*/ -#define ENE_SAMPLE_BUFFER 0xF8F0 /* regular sample buffer */ -#define ENE_SAMPLE_SPC_MASK (1 << 7) /* sample is space */ -#define ENE_SAMPLE_VALUE_MASK 0x7F -#define ENE_SAMPLE_OVERFLOW 0x7F -#define ENE_SAMPLES_SIZE 4 - -/* fan input sample buffer */ -#define ENE_SAMPLE_BUFFER_FAN 0xF8FB /* this buffer holds high byte of */ - /* each sample of normal buffer */ - -#define ENE_FAN_SMPL_PULS_MSK 0x8000 /* this bit of combined sample */ - /* if set, says that sample is pulse */ -#define ENE_FAN_VALUE_MASK 0x0FFF /* mask for valid bits of the value */ - -/* first firmware register */ -#define ENE_FW1 0xF8F8 -#define ENE_FW1_ENABLE (1 << 0) /* enable fw processing */ -#define ENE_FW1_TXIRQ (1 << 1) /* TX interrupt pending */ -#define ENE_FW1_WAKE (1 << 6) /* enable wake from S3 */ -#define ENE_FW1_IRQ (1 << 7) /* enable interrupt */ - -/* second firmware register */ -#define ENE_FW2 0xF8F9 -#define ENE_FW2_BUF_HIGH (1 << 0) /* which half of the buffer to read */ -#define ENE_FW2_IRQ_CLR (1 << 2) /* clear this on IRQ */ -#define ENE_FW2_GP40_AS_LEARN (1 << 4) /* normal input is used as */ - /* learning input */ -#define ENE_FW2_FAN_AS_NRML_IN (1 << 6) /* fan is used as normal input */ -#define ENE_FW2_LEARNING (1 << 7) /* hardware supports learning and TX */ - -/* fan as input settings - only if learning capable */ -#define ENE_FAN_AS_IN1 0xFE30 /* fan init reg 1 */ -#define ENE_FAN_AS_IN1_EN 0xCD -#define ENE_FAN_AS_IN2 0xFE31 /* fan init reg 2 */ -#define ENE_FAN_AS_IN2_EN 0x03 -#define ENE_SAMPLE_PERIOD_FAN 61 /* fan input has fixed sample period */ - -/* IRQ registers block (for revision B) */ -#define ENEB_IRQ 0xFD09 /* IRQ number */ -#define ENEB_IRQ_UNK1 0xFD17 /* unknown setting = 1 */ -#define ENEB_IRQ_STATUS 0xFD80 /* irq status */ -#define ENEB_IRQ_STATUS_IR (1 << 5) /* IR irq */ - -/* IRQ registers block (for revision C,D) */ -#define ENEC_IRQ 0xFE9B /* new irq settings register */ -#define ENEC_IRQ_MASK 0x0F /* irq number mask */ -#define ENEC_IRQ_UNK_EN (1 << 4) /* always enabled */ -#define ENEC_IRQ_STATUS (1 << 5) /* irq status and ACK */ - -/* CIR block settings */ -#define ENE_CIR_CONF1 0xFEC0 -#define ENE_CIR_CONF1_ADC_ON 0x7 /* reciever on gpio40 enabled */ -#define ENE_CIR_CONF1_LEARN1 (1 << 3) /* enabled on learning mode */ -#define ENE_CIR_CONF1_TX_ON 0x30 /* enabled on transmit */ -#define ENE_CIR_CONF1_TX_CARR (1 << 7) /* send TX carrier or not */ - -#define ENE_CIR_CONF2 0xFEC1 /* unknown setting = 0 */ -#define ENE_CIR_CONF2_LEARN2 (1 << 4) /* set on enable learning */ -#define ENE_CIR_CONF2_GPIO40DIS (1 << 5) /* disable normal input via gpio40 */ - -#define ENE_CIR_SAMPLE_PERIOD 0xFEC8 /* sample period in us */ -#define ENE_CIR_SAMPLE_OVERFLOW (1 << 7) /* interrupt on overflows if set */ - - -/* transmitter - not implemented yet */ -/* KB3926C and higher */ -/* transmission is very similiar to recieving, a byte is written to */ -/* ENE_TX_INPUT, in same manner as it is read from sample buffer */ -/* sample period is fixed*/ - - -/* transmitter ports */ -#define ENE_TX_PORT1 0xFC01 /* this enables one or both */ -#define ENE_TX_PORT1_EN (1 << 5) /* TX ports */ -#define ENE_TX_PORT2 0xFC08 -#define ENE_TX_PORT2_EN (1 << 1) - -#define ENE_TX_INPUT 0xFEC9 /* next byte to transmit */ -#define ENE_TX_SPC_MASK (1 << 7) /* Transmitted sample is space */ -#define ENE_TX_UNK1 0xFECB /* set to 0x63 */ -#define ENE_TX_SMPL_PERIOD 50 /* transmit sample period */ - - -#define ENE_TX_CARRIER 0xFECE /* TX carrier * 2 (khz) */ -#define ENE_TX_CARRIER_UNKBIT 0x80 /* This bit set on transmit */ -#define ENE_TX_CARRIER_LOW 0xFECF /* TX carrier / 2 */ - -/* Hardware versions */ -#define ENE_HW_VERSION 0xFF00 /* hardware revision */ -#define ENE_HW_UNK 0xFF1D -#define ENE_HW_UNK_CLR (1 << 2) -#define ENE_HW_VER_MAJOR 0xFF1E /* chip version */ -#define ENE_HW_VER_MINOR 0xFF1F -#define ENE_HW_VER_OLD 0xFD00 - -#define same_sign(a, b) ((((a) > 0) && (b) > 0) || ((a) < 0 && (b) < 0)) - -#define ENE_DRIVER_NAME "enecir" -#define ENE_MAXGAP 250000 /* this is amount of time we wait - before turning the sampler, chosen - arbitry */ - -#define space(len) (-(len)) /* add a space */ - -/* software defines */ -#define ENE_IRQ_RX 1 -#define ENE_IRQ_TX 2 - -#define ENE_HW_B 1 /* 3926B */ -#define ENE_HW_C 2 /* 3926C */ -#define ENE_HW_D 3 /* 3926D */ - -#define ene_printk(level, text, ...) \ - printk(level ENE_DRIVER_NAME ": " text, ## __VA_ARGS__) - -struct ene_device { - struct pnp_dev *pnp_dev; - struct lirc_driver *lirc_driver; - - /* hw settings */ - unsigned long hw_io; - int irq; - - int hw_revision; /* hardware revision */ - int hw_learning_and_tx_capable; /* learning capable */ - int hw_gpio40_learning; /* gpio40 is learning */ - int hw_fan_as_normal_input; /* fan input is used as regular input */ - - /* device data */ - int idle; - int fan_input_inuse; - - int sample; - int in_use; - - struct timeval gap_start; -}; diff --git a/ubuntu/lirc/lirc_gpio/Makefile b/ubuntu/lirc/lirc_gpio/Makefile deleted file mode 100644 index 1f2794509f8..00000000000 --- a/ubuntu/lirc/lirc_gpio/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. - -obj-$(CONFIG_LIRC_GPIO) += lirc_gpio.o diff --git a/ubuntu/lirc/lirc_gpio/lirc_gpio.c b/ubuntu/lirc/lirc_gpio/lirc_gpio.c deleted file mode 100644 index f98a0ca415c..00000000000 --- a/ubuntu/lirc/lirc_gpio/lirc_gpio.c +++ /dev/null @@ -1,613 +0,0 @@ -/* - * Remote control driver for the TV-card - * key codes are obtained from GPIO port - * - * (L) by Artur Lipowski <alipowski@interia.pl> - * patch for the AverMedia by Santiago Garcia Mantinan <manty@i.am> - * and Christoph Bartelmus <lirc@bartelmus.de> - * patch for the BestBuy by Miguel Angel Alvarez <maacruz@navegalia.com> - * patch for the Winfast TV2000 by Juan Toledo - * <toledo@users.sourceforge.net> - * patch for the I-O Data GV-BCTV5/PCI by Jens C. Rasmussen - * <jens.rasmussen@ieee.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * 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_gpio.c,v 1.57 2009/02/14 19:35:52 lirc Exp $ - * - */ - -#include <linux/version.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 4) -#error "*******************************************************" -#error "Sorry, this driver needs kernel version 2.2.4 or higher" -#error "*******************************************************" -#endif - -#include <linux/version.h> -#include <linux/module.h> -#include <linux/kmod.h> -#include <linux/sched.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) -#include <linux/wrapper.h> -#endif -#include <linux/errno.h> - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) -#include "../drivers/char/bttv.h" -#include "../drivers/char/bttvp.h" -#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17) -#include "../drivers/media/video/bttv.h" -#include "../drivers/media/video/bttvp.h" -#else -#include "../drivers/media/video/bt8xx/bttv.h" -#include "../drivers/media/video/bt8xx/bttvp.h" -#endif - -#if BTTV_VERSION_CODE < KERNEL_VERSION(0, 7, 45) -#error "*******************************************************" -#error " Sorry, this driver needs bttv version 0.7.45 or " -#error " higher. If you are using the bttv package, copy it to " -#error " the kernel " -#error "*******************************************************" -#endif - -#include "../kcompat.h" -#include "../lirc_dev/lirc_dev.h" - -/* insmod parameters */ -static int debug; -static int card; -static int minor = -1; -static int bttv_id = BTTV_BOARD_UNKNOWN; -static unsigned long gpio_mask; -static unsigned long gpio_enable; -static unsigned long gpio_lock_mask; -static unsigned long gpio_xor_mask; -static int soft_gap; -static int sample_rate = 10; - -#define dprintk(fmt, args...) \ - do { \ - if (debug) \ - printk(KERN_DEBUG fmt, ## args); \ - } while (0) - -struct rcv_info { - int bttv_id; - int card_id; - unsigned long gpio_mask; - unsigned long gpio_enable; - unsigned long gpio_lock_mask; - unsigned long gpio_xor_mask; - int soft_gap; - int sample_rate; - unsigned char code_length; -}; - -static struct rcv_info rcv_infos[] = { - {BTTV_BOARD_UNKNOWN, - 0, 0, 0, 0, 0, 0, 1, 0}, - {BTTV_BOARD_PXELVWPLTVPAK, - 0, 0x00003e00, 0, 0x0010000, 0, 0, 15, 32}, - {BTTV_BOARD_PXELVWPLTVPRO, - 0, 0x00001f00, 0, 0x0008000, 0, 500, 12, 32}, - {BTTV_BOARD_PV_BT878P_9B, - 0, 0x00001f00, 0, 0x0008000, 0, 500, 12, 32}, - {BTTV_BOARD_PV_BT878P_PLUS, - 0, 0x00001f00, 0, 0x0008000, 0, 500, 12, 32}, -#ifdef BTTV_BOARD_PV_M4900 - {BTTV_BOARD_PV_M4900, - 0, 0x00001f00, 0, 0x0008000, 0, 500, 12, 32}, -#endif - {BTTV_BOARD_AVERMEDIA, - 0, 0x00f88000, 0, 0x0010000, 0x00010000, 0, 10, 32}, - - /* mapped to Capture98 */ - {BTTV_BOARD_AVPHONE98, - 0x00011461, 0x003b8000, 0x00004000, - 0x0800000, 0x00800000, 0, 10, 0}, - {BTTV_BOARD_AVERMEDIA98, - 0x00021461, 0x003b8000, 0x00004000, - 0x0800000, 0x00800000, 0, 10, 0}, - - /* mapped to Phone98 */ - {BTTV_BOARD_AVPHONE98, - 0x00031461, 0x00f88000, 0, 0x0010000, 0x00010000, 0, 10, 32}, - /* is this one correct? */ - {BTTV_BOARD_AVERMEDIA98, - 0x00041461, 0x00f88000, 0, 0x0010000, 0x00010000, 0, 10, 32}, - /* work-around for VDOMATE */ - {BTTV_BOARD_AVERMEDIA98, - 0x03001461, 0x00f88000, 0, 0x0010000, 0x00010000, 0, 10, 32}, - /* reported by Danijel Korzinek, AVerTV GOw/FM */ - {BTTV_BOARD_AVERMEDIA98, - 0x00000000, 0x00f88000, 0, 0x0010000, 0x00010000, 0, 10, 32}, - - {BTTV_BOARD_CHRONOS_VS2, - 0, 0x000000f8, 0, 0x0000100, 0, 0, 20, 0}, - /* CPH031 and CPH033 cards (?) */ - /* MIRO was just a work-around */ - {BTTV_BOARD_MIRO, - 0, 0x00001f00, 0, 0x0004000, 0, 0, 10, 32}, - {BTTV_BOARD_DYNALINK, - 0, 0x00001f00, 0, 0x0004000, 0, 0, 10, 32}, -#ifdef BTTV_BOARD_ASKEY_CPH03X - {BTTV_BOARD_ASKEY_CPH03X, - 0, 0x00001f00, 0, 0x0004000, 0, 0, 10, 32}, -#endif - {BTTV_BOARD_WINVIEW_601, - 0, 0x00001f00, 0, 0x0004000, 0, 0, 0, 32}, -#ifdef BTTV_BOARD_KWORLD - {BTTV_BOARD_KWORLD, - 0, 0x00007f00, 0, 0x0004000, 0, 0, 12, 32}, -#endif - /* just a guess */ - {BTTV_BOARD_MAGICTVIEW061, - 0, 0x0028e000, 0, 0x0020000, 0, 0, 20, 32}, - {BTTV_BOARD_MAGICTVIEW063, - 0, 0x0028e000, 0, 0x0020000, 0, 0, 20, 32}, - {BTTV_BOARD_PHOEBE_TVMAS, - 0, 0x0028e000, 0, 0x0020000, 0, 0, 20, 32}, -#ifdef BTTV_BOARD_BESTBUY_EASYTV2 - {BTTV_BOARD_BESTBUY_EASYTV, - 0, 0x00007F00, 0, 0x0004000, 0, 0, 10, 8}, - {BTTV_BOARD_BESTBUY_EASYTV2, - 0, 0x00007F00, 0, 0x0008000, 0, 0, 10, 8}, -#endif - /* lock_mask probably also 0x100, or maybe it is 0x0 for all others? */ - {BTTV_BOARD_FLYVIDEO, - 0, 0x000000f8, 0, 0, 0, 0, 0, 42}, - {BTTV_BOARD_FLYVIDEO_98, - 0, 0x000000f8, 0, 0x0000100, 0, 0, 0, 42}, - {BTTV_BOARD_TYPHOON_TVIEW, - 0, 0x000000f8, 0, 0x0000100, 0, 0, 0, 42}, -#ifdef BTTV_BOARD_FLYVIDEO_98FM - /* smorar@alfonzo.smuts.uct.ac.za */ - {BTTV_BOARD_FLYVIDEO_98FM, - 0, 0x000000f8, 0, 0x0000100, 0, 0, 0, 42}, -#endif - /* The Leadtek WinFast TV 2000 XP card (id 0x6606107d) uses an - * extra gpio bit compared to the original TV 2000 card (id - * 0x217d6606); as the bttv-0.7.100 driver does not - * distinguish between the two cards, we enable the extra bit - * based on the card id: */ - {BTTV_BOARD_WINFAST2000, - 0x6606107d, 0x000008f8, 0, 0x0000100, 0, 0, 0, 32}, - {BTTV_BOARD_WINFAST2000, - 0x6609107d, 0x000008f8, 0, 0x0000100, 0, 0, 0, 32}, - {BTTV_BOARD_WINFAST2000, - 0xff06107d, 0x000008f8, 0, 0x0000100, 0, 0, 0, 32}, - /* default: */ - {BTTV_BOARD_WINFAST2000, - 0, 0x000000f8, 0, 0x0000100, 0, 0, 0, 32}, -#ifdef BTTV_BOARD_GVBCTV5PCI - {BTTV_BOARD_GVBCTV5PCI, - 0, 0x00f0b000, 0, 0, 0, 0, 20, 8}, -#endif -}; - -static unsigned char code_length; -static unsigned char code_bytes = 1; - -#define MAX_BYTES 8 - -#define LOGHEAD "lirc_gpio (%d): " - -/* how many bits GPIO value can be shifted right before processing - * it is computed from the value of gpio_mask_parameter - */ -static unsigned char gpio_pre_shift; - -static int reverse(int data, int bits) -{ - int i; - int c; - - for (c = 0, i = 0; i < bits; i++) - c |= (((data & (1<<i)) ? 1:0)) << (bits-1-i); - - return c; -} - -static int build_key(unsigned long gpio_val, unsigned char codes[MAX_BYTES]) -{ - unsigned long mask = gpio_mask; - unsigned char shift = 0; - - dprintk(LOGHEAD "gpio_val is %lx\n", card, (unsigned long) gpio_val); - - gpio_val ^= gpio_xor_mask; - - if (gpio_lock_mask && (gpio_val & gpio_lock_mask)) - return -EBUSY; - - switch (bttv_id) { - case BTTV_BOARD_AVERMEDIA98: - if (bttv_write_gpio(card, gpio_enable, gpio_enable)) { - dprintk(LOGHEAD "cannot write to GPIO\n", card); - return -EIO; - } - if (bttv_read_gpio(card, &gpio_val)) { - dprintk(LOGHEAD "cannot read GPIO\n", card); - return -EIO; - } - if (bttv_write_gpio(card, gpio_enable, 0)) { - dprintk(LOGHEAD "cannot write to GPIO\n", card); - return -EIO; - } - break; - default: - break; - } - - /* extract bits from "raw" GPIO value using gpio_mask */ - codes[0] = 0; - gpio_val >>= gpio_pre_shift; - while (mask) { - if (mask & 1u) - codes[0] |= (gpio_val & 1u) << shift++; - mask >>= 1; - gpio_val >>= 1; - } - - dprintk(LOGHEAD "code is %lx\n", card, (unsigned long) codes[0]); - switch (bttv_id) { - case BTTV_BOARD_AVERMEDIA: - codes[2] = (codes[0]<<2)&0xff; - codes[3] = (~codes[2])&0xff; - codes[0] = 0x02; - codes[1] = 0xFD; - break; - case BTTV_BOARD_AVPHONE98: - codes[2] = ((codes[0]&(~0x1))<<2)&0xff; - codes[3] = (~codes[2])&0xff; - if (codes[0]&0x1) { - codes[0] = 0xc0; - codes[1] = 0x3f; - } else { - codes[0] = 0x40; - codes[1] = 0xbf; - } - break; - case BTTV_BOARD_AVERMEDIA98: - break; - case BTTV_BOARD_FLYVIDEO: - case BTTV_BOARD_FLYVIDEO_98: - case BTTV_BOARD_TYPHOON_TVIEW: -#ifdef BTTV_BOARD_FLYVIDEO_98FM - case BTTV_BOARD_FLYVIDEO_98FM: -#endif - codes[4] = codes[0]<<3; - codes[5] = ((~codes[4])&0xff); - - codes[0] = 0x00; - codes[1] = 0x1A; - codes[2] = 0x1F; - codes[3] = 0x2F; - break; - case BTTV_BOARD_MAGICTVIEW061: - case BTTV_BOARD_MAGICTVIEW063: - case BTTV_BOARD_PHOEBE_TVMAS: - codes[0] = (codes[0]&0x01) - | ((codes[0]&0x02)<<1) - | ((codes[0]&0x04)<<2) - | ((codes[0]&0x08)>>2) - | ((codes[0]&0x10)>>1); - /* FALLTHROUGH */ - case BTTV_BOARD_MIRO: - case BTTV_BOARD_DYNALINK: -#ifdef BTTV_BOARD_ASKEY_CPH03X - case BTTV_BOARD_ASKEY_CPH03X: -#endif - case BTTV_BOARD_PXELVWPLTVPAK: - case BTTV_BOARD_PXELVWPLTVPRO: - case BTTV_BOARD_PV_BT878P_9B: - case BTTV_BOARD_PV_BT878P_PLUS: -#ifdef BTTV_BOARD_PV_M4900 - case BTTV_BOARD_PV_M4900: -#endif -#ifdef BTTV_BOARD_KWORLD - case BTTV_BOARD_KWORLD: -#endif - codes[2] = reverse(codes[0], 8); - codes[3] = (~codes[2])&0xff; - codes[0] = 0x61; - codes[1] = 0xD6; - break; -#if 0 - /* derived from e-tech config file */ - /* 26 + 16 bits */ - /* won't apply it until it's confirmed with a fly98 */ - case BTTV_BOARD_FLYVIDEO_98: - case BTTV_BOARD_FLYVIDEO_98FM: - codes[4] = codes[0]<<3; - codes[5] = (~codes[4])&0xff; - - codes[0] = 0x00; - codes[1] = 0x1A; - codes[2] = 0x1F; - codes[3] = 0x2F; - break; -#endif - case BTTV_BOARD_WINFAST2000: - /* shift extra bit */ - codes[0] = (codes[0]&0x1f) | ((codes[0]&0x20) << 1); - case BTTV_BOARD_WINVIEW_601: - codes[2] = reverse(codes[0], 8); - codes[3] = (~codes[2])&0xff; - codes[0] = 0xC0; - codes[1] = 0x3F; - break; - default: - break; - } - - return 0; -} - -/* add_to_buf - copy a code to the buffer */ -static int add_to_buf(void *data, struct lirc_buffer *buf) -{ - static unsigned long next_time; - static unsigned char prev_codes[MAX_BYTES]; - unsigned long code = 0; - unsigned char cur_codes[MAX_BYTES]; - - if (bttv_read_gpio(card, &code)) { - dprintk(LOGHEAD "cannot read GPIO\n", card); - return -EIO; - } - - if (build_key(code, cur_codes)) - return -EFAULT; - - if (soft_gap) { - if (!memcmp(prev_codes, cur_codes, code_bytes) && - jiffies < next_time) - return -EAGAIN; - - next_time = jiffies + soft_gap; - } - memcpy(prev_codes, cur_codes, code_bytes); - - lirc_buffer_write(buf, cur_codes); - - return 0; -} - -static int set_use_inc(void *data) -{ - MOD_INC_USE_COUNT; - return 0; -} - -static void set_use_dec(void *data) -{ - MOD_DEC_USE_COUNT; -} - -static wait_queue_head_t *get_queue(void *data) -{ - return bttv_get_gpio_queue(card); -} - -static struct lirc_driver driver = { - .name = "lirc_gpio ", - .add_to_buf = add_to_buf, - .get_queue = get_queue, - .set_use_inc = set_use_inc, - .set_use_dec = set_use_dec, - .dev = NULL, - .owner = THIS_MODULE, -}; - -/* - * - */ -static int gpio_remote_init(void) -{ - int ret; - unsigned int mask; - - /* "normalize" gpio_mask - * this means shift it right until first bit is set - */ - while (!(gpio_mask & 1u)) { - gpio_pre_shift++; - gpio_mask >>= 1; - } - - if (code_length) - driver.code_length = code_length; - else { - /* calculate scan code length in bits if needed */ - driver.code_length = 1; - mask = gpio_mask >> 1; - while (mask) { - if (mask & 1u) - driver.code_length++; - mask >>= 1; - } - } - - code_bytes = (driver.code_length/8) + (driver.code_length % 8 ? 1 : 0); - if (MAX_BYTES < code_bytes) { - printk(LOGHEAD "scan code too long (%d bytes)\n", - minor, code_bytes); - return -EBADRQC; - } - - if (gpio_enable) { - if (bttv_gpio_enable(card, gpio_enable, gpio_enable)) { - printk(LOGHEAD "gpio_enable failure\n", minor); - return -EIO; - } - } - - - /* translate ms to jiffies */ - soft_gap = (soft_gap*HZ) / 1000; - - driver.minor = minor; - driver.sample_rate = sample_rate; - - ret = lirc_register_driver(&driver); - - if (0 > ret) { - printk(LOGHEAD "device registration failed with %d\n", - minor, ret); - return ret; - } - - minor = ret; - printk(LOGHEAD "driver registered\n", minor); - - return 0; -} - -#ifdef MODULE -/* - * - */ -int init_module(void) -{ - int type, cardid, card_type; - - if (MAX_IRCTL_DEVICES < minor) { - printk(KERN_INFO "lirc_gpio: parameter minor (%d) " - "must be less than %d!\n", - minor, MAX_IRCTL_DEVICES - 1); - return -EBADRQC; - } - - /* if gpio_mask not zero then use module parameters - * instead of autodetecting TV card - */ - if (gpio_mask) { - if (sample_rate != 0 && - (2 > sample_rate || HZ < sample_rate)) { - printk(LOGHEAD "parameter sample_rate " - "must be between 2 and %d!\n", minor, HZ); - return -EBADRQC; - } - - if (sample_rate != 0 && soft_gap && - ((2000/sample_rate) > soft_gap || 1000 < soft_gap)) { - printk(LOGHEAD "parameter soft_gap " - "must be between %d and 1000!\n", - minor, 2000/sample_rate); - return -EBADRQC; - } - } else { - if (bttv_get_cardinfo(card, &type, &cardid) == -1) { - printk(LOGHEAD "could not get card type\n", minor); - return -EBADRQC; - } - printk(LOGHEAD "card type 0x%x, id 0x%x\n", minor, - type, cardid); - - if (type == BTTV_BOARD_UNKNOWN) { - printk(LOGHEAD "cannot detect TV card nr %d!\n", - minor, card); - return -EBADRQC; - } - for (card_type = 1; - card_type < sizeof(rcv_infos)/sizeof(struct rcv_info); - card_type++) { - if (rcv_infos[card_type].bttv_id == type && - (rcv_infos[card_type].card_id == 0 || - rcv_infos[card_type].card_id == cardid)) { - bttv_id = rcv_infos[card_type].bttv_id; - gpio_mask = rcv_infos[card_type].gpio_mask; - gpio_enable = rcv_infos[card_type].gpio_enable; - gpio_lock_mask = - rcv_infos[card_type].gpio_lock_mask; - gpio_xor_mask = - rcv_infos[card_type].gpio_xor_mask; - soft_gap = rcv_infos[card_type].soft_gap; - sample_rate = rcv_infos[card_type].sample_rate; - code_length = rcv_infos[card_type].code_length; - break; - } - } - if (type == BTTV_BOARD_AVPHONE98 && cardid == 0x00011461) - bttv_id = BTTV_BOARD_AVERMEDIA98; - - if (type == BTTV_BOARD_AVERMEDIA98 && cardid == 0x00041461) - bttv_id = BTTV_BOARD_AVPHONE98; - - if (type == BTTV_BOARD_AVERMEDIA98 && cardid == 0x03001461) - bttv_id = BTTV_BOARD_AVPHONE98; - - if (type == BTTV_BOARD_AVERMEDIA98 && cardid == 0x00000000) - bttv_id = BTTV_BOARD_AVPHONE98; - - if (card_type == sizeof(rcv_infos)/sizeof(struct rcv_info)) { - printk(LOGHEAD "TV card type 0x%x not supported!\n", - minor, type); - return -EBADRQC; - } - } - - return gpio_remote_init(); -} - -/* - * - */ -void cleanup_module(void) -{ - lirc_unregister_driver(minor); - - dprintk(LOGHEAD "module successfully unloaded\n", minor); -} - -/* Dont try to use it as a static version ! */ -MODULE_DESCRIPTION("Driver module for remote control (data " - "from bt848 GPIO port)"); -MODULE_AUTHOR("Artur Lipowski"); -MODULE_LICENSE("GPL"); - -module_param(minor, int, S_IRUGO); -MODULE_PARM_DESC(minor, "Preferred minor device number"); - -module_param(card, int, S_IRUGO); -MODULE_PARM_DESC(card, "TV card number to attach to"); - -module_param(gpio_mask, long, S_IRUGO); -MODULE_PARM_DESC(gpio_mask, "gpio_mask"); - -module_param(gpio_lock_mask, long, S_IRUGO); -MODULE_PARM_DESC(gpio_lock_mask, "gpio_lock_mask"); - -module_param(gpio_xor_mask, long, S_IRUGO); -MODULE_PARM_DESC(gpio_xor_mask, "gpio_xor_mask"); - -module_param(soft_gap, int, S_IRUGO); -MODULE_PARM_DESC(soft_gap, "Time between keypresses (in ms)"); - -module_param(sample_rate, int, S_IRUGO); -MODULE_PARM_DESC(sample_rate, "Sample rate (between 2 and HZ)"); - -module_param(bttv_id, int, S_IRUGO); -MODULE_PARM_DESC(bttv_id, "BTTV card type"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Enable debugging messages"); - -EXPORT_NO_SYMBOLS; - -#endif /* MODULE */ diff --git a/ubuntu/lirc/lirc_i2c/Makefile b/ubuntu/lirc/lirc_i2c/Makefile deleted file mode 100644 index 40ee53ebc82..00000000000 --- a/ubuntu/lirc/lirc_i2c/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. - -obj-$(CONFIG_LIRC_I2C) += lirc_i2c.o diff --git a/ubuntu/lirc/lirc_i2c/lirc_i2c.c b/ubuntu/lirc/lirc_i2c/lirc_i2c.c deleted file mode 100644 index dca6b513c0c..00000000000 --- a/ubuntu/lirc/lirc_i2c/lirc_i2c.c +++ /dev/null @@ -1,778 +0,0 @@ -/* $Id: lirc_i2c.c,v 1.70 2009/08/30 16:59:53 jarodwilson Exp $ */ - -/* - * lirc_i2c.c - * - * i2c IR driver for the onboard IR port on many TV tuner cards, including: - * -Flavors of the Hauppauge PVR-150/250/350 - * -Hauppauge HVR-1300 - * -PixelView (BT878P+W/FM) - * -KNC ONE TV Station/Anubis Typhoon TView Tuner - * -Asus TV-Box and Creative/VisionTek BreakOut-Box - * -Leadtek Winfast PVR2000 - * - * Copyright (c) 2000 Gerd Knorr <kraxel@goldbach.in-berlin.de> - * modified for PixelView (BT878P+W/FM) by - * Michal Kochanowicz <mkochano@pld.org.pl> - * Christoph Bartelmus <lirc@bartelmus.de> - * modified for KNC ONE TV Station/Anubis Typhoon TView Tuner by - * Ulrich Mueller <ulrich.mueller42@web.de> - * modified for Asus TV-Box and Creative/VisionTek BreakOut-Box by - * Stefan Jahn <stefan@lkcc.org> - * modified for inclusion into kernel sources by - * Jerome Brock <jbrock@users.sourceforge.net> - * modified for Leadtek Winfast PVR2000 by - * Thomas Reitmayr (treitmayr@yahoo.com) - * modified for Hauppauge HVR-1300 by - * Jan Frey (jfrey@gmx.de) - * - * parts are cut&pasted from the old lirc_haup.c driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <linux/version.h> -#include <linux/module.h> -#include <linux/kmod.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/timer.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/slab.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> - -#include "../kcompat.h" -#include "../lirc_dev/lirc_dev.h" - -struct IR { - struct lirc_driver l; - struct i2c_client c; - int nextkey; - unsigned char b[3]; - unsigned char bits; - unsigned char flag; -}; - -#define DEVICE_NAME "lirc_i2c" - -/* module parameters */ -static int debug; /* debug output */ -static int minor = -1; /* minor number */ - -#define dprintk(fmt, args...) \ - do { \ - if (debug) \ - printk(KERN_DEBUG DEVICE_NAME ": " fmt, \ - ## args); \ - } while (0) - -static int reverse(int data, int bits) -{ - int i; - int c; - - for (c = 0, i = 0; i < bits; i++) - c |= ((data & (1<<i)) ? 1 : 0) << (bits-1-i); - - return c; -} - -static int add_to_buf_adap(void *data, struct lirc_buffer *buf) -{ - struct IR *ir = data; - unsigned char keybuf[4]; - - keybuf[0] = 0x00; - i2c_master_send(&ir->c, keybuf, 1); - /* poll IR chip */ - if (i2c_master_recv(&ir->c, keybuf, sizeof(keybuf)) != sizeof(keybuf)) { - dprintk("read error\n"); - return -EIO; - } - - dprintk("key (0x%02x%02x%02x%02x)\n", - keybuf[0], keybuf[1], keybuf[2], keybuf[3]); - - /* key pressed ? */ - if (keybuf[2] == 0xff) - return -ENODATA; - - /* remove repeat bit */ - keybuf[2] &= 0x7f; - keybuf[3] |= 0x80; - - lirc_buffer_write(buf, keybuf); - return 0; -} - -static int add_to_buf_pcf8574(void *data, struct lirc_buffer *buf) -{ - struct IR *ir = data; - int rc; - unsigned char all, mask; - unsigned char key; - - /* compute all valid bits (key code + pressed/release flag) */ - all = ir->bits | ir->flag; - - /* save IR writable mask bits */ - mask = i2c_smbus_read_byte(&ir->c) & ~all; - - /* send bit mask */ - rc = i2c_smbus_write_byte(&ir->c, (0xff & all) | mask); - - /* receive scan code */ - rc = i2c_smbus_read_byte(&ir->c); - - if (rc == -1) { - dprintk("%s read error\n", ir->c.name); - return -EIO; - } - - /* drop duplicate polls */ - if (ir->b[0] == (rc & all)) - return -ENODATA; - - ir->b[0] = rc & all; - - dprintk("%s key 0x%02X %s\n", ir->c.name, rc & ir->bits, - (rc & ir->flag) ? "released" : "pressed"); - - /* ignore released buttons */ - if (rc & ir->flag) - return -ENODATA; - - /* set valid key code */ - key = rc & ir->bits; - lirc_buffer_write(buf, &key); - return 0; -} - -/* common for Hauppauge IR receivers */ -static int add_to_buf_haup_common(void *data, struct lirc_buffer *buf, - unsigned char *keybuf, int size, int offset) -{ - struct IR *ir = data; - __u16 code; - unsigned char codes[2]; - int ret; - - /* poll IR chip */ - ret = i2c_master_recv(&ir->c, keybuf, size); - if (ret == size) { - ir->b[0] = keybuf[offset]; - ir->b[1] = keybuf[offset+1]; - ir->b[2] = keybuf[offset+2]; - if (ir->b[0] != 0x00 && ir->b[1] != 0x00) - dprintk("key (0x%02x/0x%02x)\n", ir->b[0], ir->b[1]); - } else { - dprintk("read error (ret=%d)\n", ret); - /* keep last successful read buffer */ - } - - /* key pressed ? */ - if ((ir->b[0] & 0x80) == 0) - return -ENODATA; - - /* look what we have */ - code = (((__u16)ir->b[0]&0x7f)<<6) | (ir->b[1]>>2); - - codes[0] = (code >> 8) & 0xff; - codes[1] = code & 0xff; - - /* return it */ - dprintk("sending code 0x%02x%02x to lirc\n", codes[0], codes[1]); - lirc_buffer_write(buf, codes); - return 0; -} - -/* specific for the Hauppauge PVR150 IR receiver */ -static int add_to_buf_haup_pvr150(void *data, struct lirc_buffer *buf) -{ - unsigned char keybuf[6]; - /* fetch 6 bytes, first relevant is at offset 3 */ - return add_to_buf_haup_common(data, buf, keybuf, 6, 3); -} - -/* used for all Hauppauge IR receivers but the PVR150 */ -static int add_to_buf_haup(void *data, struct lirc_buffer *buf) -{ - unsigned char keybuf[3]; - /* fetch 3 bytes, first relevant is at offset 0 */ - return add_to_buf_haup_common(data, buf, keybuf, 3, 0); -} - - -static int add_to_buf_pvr2000(void *data, struct lirc_buffer *buf) -{ - struct IR *ir = data; - unsigned char key; - s32 flags; - s32 code; - - /* poll IR chip */ - flags = i2c_smbus_read_byte_data(&ir->c, 0x10); - if (-1 == flags) { - dprintk("read error\n"); - return -ENODATA; - } - /* key pressed ? */ - if (0 == (flags & 0x80)) - return -ENODATA; - - /* read actual key code */ - code = i2c_smbus_read_byte_data(&ir->c, 0x00); - if (-1 == code) { - dprintk("read error\n"); - return -ENODATA; - } - - key = code & 0xFF; - - dprintk("IR Key/Flags: (0x%02x/0x%02x)\n", key, flags & 0xFF); - - /* return it */ - lirc_buffer_write(buf, &key); - return 0; -} - -static int add_to_buf_pixelview(void *data, struct lirc_buffer *buf) -{ - struct IR *ir = data; - unsigned char key; - - /* poll IR chip */ - if (1 != i2c_master_recv(&ir->c, &key, 1)) { - dprintk("read error\n"); - return -1; - } - dprintk("key %02x\n", key); - - /* return it */ - lirc_buffer_write(buf, &key); - return 0; -} - -static int add_to_buf_pv951(void *data, struct lirc_buffer *buf) -{ - struct IR *ir = data; - unsigned char key; - unsigned char codes[4]; - - /* poll IR chip */ - if (1 != i2c_master_recv(&ir->c, &key, 1)) { - dprintk("read error\n"); - return -ENODATA; - } - /* ignore 0xaa */ - if (key == 0xaa) - return -ENODATA; - dprintk("key %02x\n", key); - - codes[0] = 0x61; - codes[1] = 0xD6; - codes[2] = reverse(key, 8); - codes[3] = (~codes[2])&0xff; - - lirc_buffer_write(buf, codes); - return 0; -} - -static int add_to_buf_knc1(void *data, struct lirc_buffer *buf) -{ - static unsigned char last_key = 0xFF; - struct IR *ir = data; - unsigned char key; - - /* poll IR chip */ - if (1 != i2c_master_recv(&ir->c, &key, 1)) { - dprintk("read error\n"); - return -ENODATA; - } - - /* - * it seems that 0xFE indicates that a button is still held - * down, while 0xFF indicates that no button is held - * down. 0xFE sequences are sometimes interrupted by 0xFF - */ - - dprintk("key %02x\n", key); - - if (key == 0xFF) - return -ENODATA; - - if (key == 0xFE) - key = last_key; - - last_key = key; - lirc_buffer_write(buf, &key); - - return 0; -} - -static int set_use_inc(void *data) -{ - struct IR *ir = data; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) - int ret; -#endif - - dprintk("%s called\n", __func__); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) - i2c_use_client(&ir->c); -#else - /* lock bttv in memory while /dev/lirc is in use */ - ret = i2c_use_client(&ir->c); - if (ret != 0) - return ret; -#endif - - MOD_INC_USE_COUNT; - return 0; -} - -static void set_use_dec(void *data) -{ - struct IR *ir = data; - - dprintk("%s called\n", __func__); - - i2c_release_client(&ir->c); - MOD_DEC_USE_COUNT; -} - -static struct lirc_driver lirc_template = { - .name = "lirc_i2c", - .set_use_inc = set_use_inc, - .set_use_dec = set_use_dec, - .dev = NULL, - .owner = THIS_MODULE, -}; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) -static int ir_attach(struct i2c_adapter *adap, int addr, - unsigned short flags, int kind); -static int ir_probe(struct i2c_adapter *adap); -# else -static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id); -#endif -static int ir_remove(struct i2c_client *client); -static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg); - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 30) -static const struct i2c_device_id ir_receiver_id[] = { - /* Generic entry for any IR receiver */ - { "ir_video", 0 }, - /* IR device specific entries could be added here */ - { } -}; -#endif - -static struct i2c_driver driver = { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16) - .name = "i2c ir driver", - .flags = I2C_DF_NOTIFY, -#else - .driver = { - .owner = THIS_MODULE, - .name = "i2c ir driver", - }, -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) - .attach_adapter = ir_probe, - .detach_client = ir_remove, -#else - .probe = ir_probe, - .remove = ir_remove, - .id_table = ir_receiver_id, -#endif - .command = ir_command, -}; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) -static struct i2c_client client_template = { - .name = "unset", - .driver = &driver -}; -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) -static int ir_attach(struct i2c_adapter *adap, int addr, - unsigned short flags, int kind) -#else -static void pcf_probe(struct i2c_client *client, struct IR *ir) -{ - int ret1, ret2, ret3, ret4; - - ret1 = i2c_smbus_write_byte(client, 0xff); - ret2 = i2c_smbus_read_byte(client); - ret3 = i2c_smbus_write_byte(client, 0x00); - ret4 = i2c_smbus_read_byte(client); - - /* in the Asus TV-Box: bit 1-0 */ - if (((ret2 & 0x03) == 0x03) && ((ret4 & 0x03) == 0x00)) { - ir->bits = (unsigned char) ~0x07; - ir->flag = 0x04; - /* in the Creative/VisionTek BreakOut-Box: bit 7-6 */ - } else if (((ret2 & 0xc0) == 0xc0) && ((ret4 & 0xc0) == 0x00)) { - ir->bits = (unsigned char) ~0xe0; - ir->flag = 0x20; - } - - return; -} - -static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id) -#endif -{ - struct IR *ir; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) - int err, retval; - - client_template.adapter = adap; - client_template.addr = addr; -#else - struct i2c_adapter *adap = client->adapter; - unsigned short addr = client->addr; - int retval; -#endif - - ir = kmalloc(sizeof(struct IR), GFP_KERNEL); - if (!ir) - return -ENOMEM; - memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver)); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) - memcpy(&ir->c, &client_template, sizeof(struct i2c_client)); - - ir->c.adapter = adap; - ir->c.addr = addr; - i2c_set_clientdata(&ir->c, ir); -#else - memcpy(&ir->c, client, sizeof(struct i2c_client)); - - i2c_set_clientdata(client, ir); -#endif - ir->l.data = ir; - ir->l.minor = minor; - ir->l.sample_rate = 10; - ir->l.dev = &ir->c.dev; - ir->nextkey = -1; - - switch (addr) { - case 0x64: - strlcpy(ir->c.name, "Pixelview IR", I2C_NAME_SIZE); - ir->l.code_length = 8; - ir->l.add_to_buf = add_to_buf_pixelview; - break; - case 0x4b: - strlcpy(ir->c.name, "PV951 IR", I2C_NAME_SIZE); - ir->l.code_length = 32; - ir->l.add_to_buf = add_to_buf_pv951; - break; - case 0x71: -#ifdef I2C_HW_B_CX2341X - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848) || - adap->id == (I2C_ALGO_BIT | I2C_HW_B_CX2341X)) { -#else - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) { -#endif - /* - * The PVR150 IR receiver uses the same protocol as - * other Hauppauge cards, but the data flow is - * different, so we need to deal with it by its own. - */ - strlcpy(ir->c.name, "Hauppauge PVR150", I2C_NAME_SIZE); - } else /* I2C_HW_B_CX2388x */ - strlcpy(ir->c.name, "Hauppauge HVR1300", I2C_NAME_SIZE); - ir->l.code_length = 13; - ir->l.add_to_buf = add_to_buf_haup_pvr150; - break; - case 0x6b: - strlcpy(ir->c.name, "Adaptec IR", I2C_NAME_SIZE); - ir->l.code_length = 32; - ir->l.add_to_buf = add_to_buf_adap; - break; - case 0x18: - case 0x1a: -#ifdef I2C_HW_B_CX2341X - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848) || - adap->id == (I2C_ALGO_BIT | I2C_HW_B_CX2341X)) { -#else - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) { -#endif - strlcpy(ir->c.name, "Hauppauge IR", I2C_NAME_SIZE); - ir->l.code_length = 13; - ir->l.add_to_buf = add_to_buf_haup; - } else { /* I2C_HW_B_CX2388x */ - strlcpy(ir->c.name, "Leadtek IR", I2C_NAME_SIZE); - ir->l.code_length = 8; - ir->l.add_to_buf = add_to_buf_pvr2000; - } - break; - case 0x30: - strlcpy(ir->c.name, "KNC ONE IR", I2C_NAME_SIZE); - ir->l.code_length = 8; - ir->l.add_to_buf = add_to_buf_knc1; - break; - case 0x21: - case 0x23: -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) - ir->bits = flags & 0xff; - ir->flag = (flags >> 8) & 0xff; -#else - pcf_probe(client, ir); -#endif - strlcpy(ir->c.name, "TV-Box IR", I2C_NAME_SIZE); - ir->l.code_length = 8; - ir->l.add_to_buf = add_to_buf_pcf8574; - break; - default: - /* shouldn't happen */ - printk("lirc_i2c: Huh? unknown i2c address (0x%02x)?\n", addr); - kfree(ir); - return -EINVAL; - } - printk(KERN_INFO "lirc_i2c: chip 0x%x found @ 0x%02x (%s)\n", - adap->id, addr, ir->c.name); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) - /* register device */ - err = i2c_attach_client(&ir->c); - if (err) { - kfree(ir); - return err; - } -#endif - - retval = lirc_register_driver(&ir->l); - - if (retval < 0) { - printk(KERN_ERR "lirc_i2c: failed to register driver!\n"); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) - i2c_detach_client(&ir->c); -#endif - kfree(ir); - return retval; - } - - ir->l.minor = retval; - - return 0; -} - -static int ir_remove(struct i2c_client *client) -{ - struct IR *ir = i2c_get_clientdata(client); - - /* unregister device */ - lirc_unregister_driver(ir->l.minor); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) - i2c_detach_client(&ir->c); -#endif - - /* free memory */ - kfree(ir); - return 0; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) -static int ir_probe(struct i2c_adapter *adap) -{ - /* - * The external IR receiver is at i2c address 0x34 (0x35 for - * reads). Future Hauppauge cards will have an internal - * receiver at 0x30 (0x31 for reads). In theory, both can be - * fitted, and Hauppauge suggest an external overrides an - * internal. - * - * That's why we probe 0x1a (~0x34) first. CB - * - * The i2c address for the Hauppauge PVR-150 card is 0xe2, - * so we need to probe 0x71 as well. - */ - - static const int probe[] = { - 0x1a, /* Hauppauge IR external */ - 0x18, /* Hauppauge IR internal */ - 0x71, /* Hauppauge IR (PVR150) */ - 0x4b, /* PV951 IR */ - 0x64, /* Pixelview IR */ - 0x30, /* KNC ONE IR */ - 0x6b, /* Adaptec IR */ - -1}; - -#ifdef I2C_HW_B_CX2388x - static const int probe_cx88[] = { - 0x18, /* Leadtek Winfast PVR2000 */ - 0x71, /* Hauppauge HVR-IR */ - -1}; -#endif - - struct i2c_client c; - char buf; - int i, rc; - - memset(&c, 0, sizeof(c)); -#ifdef I2C_HW_B_CX2341X - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848) || - adap->id == (I2C_ALGO_BIT | I2C_HW_B_CX2341X)) { -#else - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) { -#endif - c.adapter = adap; - for (i = 0; -1 != probe[i]; i++) { - c.addr = probe[i]; - rc = i2c_master_recv(&c, &buf, 1); - dprintk("probe 0x%02x @ %s: %s\n", - probe[i], adap->name, - (1 == rc) ? "yes" : "no"); - if (1 == rc) { - rc = ir_attach(adap, probe[i], 0, 0); - if (rc < 0) - goto attach_fail; - } - } - } - -#ifdef I2C_HW_B_CX2388x - /* Leadtek Winfast PVR2000 or Hauppauge HVR-1300 */ - else if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_CX2388x)) { - c.adapter = adap; - for (i = 0; -1 != probe_cx88[i]; i++) { - c.addr = probe_cx88[i]; - rc = i2c_master_recv(&c, &buf, 1); - dprintk("probe 0x%02x @ %s: %s\n", - c.addr, adap->name, - (1 == rc) ? "yes" : "no"); - if (1 == rc) { - rc = ir_attach(adap, c.addr, 0, 0); - if (rc < 0) - goto attach_fail; - } - } - } -#endif - - /* Asus TV-Box and Creative/VisionTek BreakOut-Box (PCF8574) */ - else if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_RIVA)) { - /* - * addresses to probe; - * leave 0x24 and 0x25 because SAA7113H possibly uses it - * 0x21 and 0x22 possibly used by SAA7108E - * Asus: 0x21 is a correct address (channel 1 of PCF8574) - * Creative: 0x23 is a correct address (channel 3 of PCF8574) - * VisionTek: 0x23 is a correct address (channel 3 of PCF8574) - */ - static const int pcf_probe[] = { 0x20, 0x21, 0x22, 0x23, - 0x24, 0x25, 0x26, 0x27, -1 }; - int ret1, ret2, ret3, ret4; - unsigned char bits = 0, flag = 0; - - c.adapter = adap; - for (i = 0; -1 != pcf_probe[i]; i++) { - c.addr = pcf_probe[i]; - ret1 = i2c_smbus_write_byte(&c, 0xff); - ret2 = i2c_smbus_read_byte(&c); - ret3 = i2c_smbus_write_byte(&c, 0x00); - ret4 = i2c_smbus_read_byte(&c); - - /* ensure that the writable bitmask works correctly */ - rc = 0; - if (ret1 != -1 && ret2 != -1 && - ret3 != -1 && ret4 != -1) { - /* in the Asus TV-Box: bit 1-0 */ - if (((ret2 & 0x03) == 0x03) && - ((ret4 & 0x03) == 0x00)) { - bits = (unsigned char) ~0x07; - flag = 0x04; - rc = 1; - } - /* in the Creative/VisionTek BreakOut-Box: bit 7-6 */ - if (((ret2 & 0xc0) == 0xc0) && - ((ret4 & 0xc0) == 0x00)) { - bits = (unsigned char) ~0xe0; - flag = 0x20; - rc = 1; - } - } - dprintk("probe 0x%02x @ %s: %s\n", - c.addr, adap->name, rc ? "yes" : "no"); - if (rc) { - rc = ir_attach(adap, pcf_probe[i], - bits | (flag << 8), 0); - if (rc < 0) - goto attach_fail; - } - } - } - - return 0; - -attach_fail: - printk(KERN_ERR "lirc_i2c: %s: ir_attach failed!\n", __func__); - return rc; - -} -#endif - -static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - /* nothing */ - return 0; -} - -#ifdef MODULE - -static int __init lirc_i2c_init(void) -{ - request_module("bttv"); - request_module("rivatv"); - request_module("ivtv"); - request_module("cx8800"); - i2c_add_driver(&driver); - return 0; -} - -static void __exit lirc_i2c_exit(void) -{ - i2c_del_driver(&driver); -} - -MODULE_DESCRIPTION("Infrared receiver driver for Hauppauge and " - "Pixelview cards (i2c stack)"); -MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, " - "Ulrich Mueller, Stefan Jahn, Jerome Brock"); -MODULE_LICENSE("GPL"); - -module_param(minor, int, S_IRUGO); -MODULE_PARM_DESC(minor, "Preferred minor device number"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Enable debugging messages"); - -module_init(lirc_i2c_init); -module_exit(lirc_i2c_exit); -EXPORT_NO_SYMBOLS; - -#endif /* MODULE */ diff --git a/ubuntu/lirc/lirc_igorplugusb/Makefile b/ubuntu/lirc/lirc_igorplugusb/Makefile deleted file mode 100644 index 8e8bafca3fc..00000000000 --- a/ubuntu/lirc/lirc_igorplugusb/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. - -obj-$(CONFIG_LIRC_IGORPLUGUSB) += lirc_igorplugusb.o diff --git a/ubuntu/lirc/lirc_igorplugusb/lirc_igorplugusb.c b/ubuntu/lirc/lirc_igorplugusb/lirc_igorplugusb.c deleted file mode 100644 index c38d9254cab..00000000000 --- a/ubuntu/lirc/lirc_igorplugusb/lirc_igorplugusb.c +++ /dev/null @@ -1,636 +0,0 @@ -/* - * lirc_igorplugusb - USB remote support for LIRC - * - * Supports the standard homebrew IgorPlugUSB receiver with Igor's firmware. - * See http://www.cesko.host.sk/IgorPlugUSB/IgorPlug-USB%20(AVR)_eng.htm - * - * The device can only record bursts of up to 36 pulses/spaces. - * Works fine with RC5. Longer commands lead to device buffer overrun. - * (Maybe a better firmware or a microcontroller with more ram can help?) - * - * Version 0.1 [beta status] - * - * Copyright (C) 2004 Jan M. Hochstein - * <hochstein@algo.informatik.tu-darmstadt.de> - * - * This driver was derived from: - * Paul Miller <pmiller9@users.sourceforge.net> - * "lirc_atiusb" module - * Vladimir Dergachev <volodya@minspring.com>'s 2002 - * "USB ATI Remote support" (input device) - * Adrian Dewhurst <sailor-lk@sailorfrag.net>'s 2002 - * "USB StreamZap remote driver" (LIRC) - * Artur Lipowski <alipowski@kki.net.pl>'s 2002 - * "lirc_dev" and "lirc_gpio" LIRC modules - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/version.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) -#error "*******************************************************" -#error "Sorry, this driver needs kernel version 2.4.0 or higher" -#error "*******************************************************" -#endif - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/kmod.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/ioctl.h> -#include <linux/fs.h> -#include <linux/usb.h> -#include <linux/poll.h> -#include <linux/smp_lock.h> -#include <linux/time.h> - -#include "../kcompat.h" -#include "../lirc.h" -#include "../lirc_dev/lirc_dev.h" - -#if !defined(KERNEL_2_5) -#define USB_CTRL_GET_TIMEOUT 5 -#endif - -/* module identification */ -#define DRIVER_VERSION "0.2" -#define DRIVER_AUTHOR \ - "Jan M. Hochstein <hochstein@algo.informatik.tu-darmstadt.de>" -#define DRIVER_DESC "USB remote driver for LIRC" -#define DRIVER_NAME "lirc_igorplugusb" - -/* debugging support */ -#ifdef CONFIG_USB_DEBUG -static int debug = 1; -#else -static int debug; -#endif - -#define dprintk(fmt, args...) \ - do { \ - if (debug) \ - printk(KERN_DEBUG DRIVER_NAME fmt, ## args); \ - } while (0) - -/* One mode2 pulse/space has 4 bytes. */ -#define CODE_LENGTH sizeof(lirc_t) - -/* Igor's firmware cannot record bursts longer than 36. */ -#define DEVICE_BUFLEN 36 - -/* - * Header at the beginning of the device's buffer: - * unsigned char data_length - * unsigned char data_start (!=0 means ring-buffer overrun) - * unsigned char counter (incremented by each burst) - */ -#define DEVICE_HEADERLEN 3 - -/* This is for the gap */ -#define ADDITIONAL_LIRC_BYTES 2 - -/* times to poll per second */ -#define SAMPLE_RATE 100 -static int sample_rate = SAMPLE_RATE; - - -/**** Igor's USB Request Codes */ - -#define SET_INFRABUFFER_EMPTY 1 -/** - * Params: none - * Answer: empty - */ - -#define GET_INFRACODE 2 -/** - * Params: - * wValue: offset to begin reading infra buffer - * - * Answer: infra data - */ - -#define SET_DATAPORT_DIRECTION 3 -/** - * Params: - * wValue: (byte) 1 bit for each data port pin (0=in, 1=out) - * - * Answer: empty - */ - -#define GET_DATAPORT_DIRECTION 4 -/** - * Params: none - * - * Answer: (byte) 1 bit for each data port pin (0=in, 1=out) - */ - -#define SET_OUT_DATAPORT 5 -/** - * Params: - * wValue: byte to write to output data port - * - * Answer: empty - */ - -#define GET_OUT_DATAPORT 6 -/** - * Params: none - * - * Answer: least significant 3 bits read from output data port - */ - -#define GET_IN_DATAPORT 7 -/** - * Params: none - * - * Answer: least significant 3 bits read from input data port - */ - -#define READ_EEPROM 8 -/** - * Params: - * wValue: offset to begin reading EEPROM - * - * Answer: EEPROM bytes - */ - -#define WRITE_EEPROM 9 -/** - * Params: - * wValue: offset to EEPROM byte - * wIndex: byte to write - * - * Answer: empty - */ - -#define SEND_RS232 10 -/** - * Params: - * wValue: byte to send - * - * Answer: empty - */ - -#define RECV_RS232 11 -/** - * Params: none - * - * Answer: byte received - */ - -#define SET_RS232_BAUD 12 -/** - * Params: - * wValue: byte to write to UART bit rate register (UBRR) - * - * Answer: empty - */ - -#define GET_RS232_BAUD 13 -/** - * Params: none - * - * Answer: byte read from UART bit rate register (UBRR) - */ - - -/* data structure for each usb remote */ -struct igorplug { - - /* usb */ - struct usb_device *usbdev; - struct urb *urb_in; - int devnum; - - unsigned char *buf_in; - unsigned int len_in; - int in_space; - struct timeval last_time; - -#if defined(KERNEL_2_5) - dma_addr_t dma_in; -#endif - - /* lirc */ - struct lirc_driver *d; - - /* handle sending (init strings) */ - int send_flags; -}; - -static int set_use_inc(void *data) -{ - struct igorplug *ir = data; - - if (!ir) { - printk(KERN_ERR DRIVER_NAME - "[?]: set_use_inc called with no context\n"); - return -EIO; - } - dprintk("[%d]: set use inc\n", ir->devnum); - - MOD_INC_USE_COUNT; - - if (!ir->usbdev) - return -ENODEV; - - return 0; -} - -static void set_use_dec(void *data) -{ - struct igorplug *ir = data; - - if (!ir) { - printk(KERN_ERR DRIVER_NAME - "[?]: set_use_dec called with no context\n"); - return; - } - dprintk("[%d]: set use dec\n", ir->devnum); - - MOD_DEC_USE_COUNT; -} - -static void send_fragment(struct igorplug *ir, struct lirc_buffer *buf, - int i, int max) -{ - /* MODE2: pulse/space (PULSE_BIT) in 1us units */ - while (i < max) { - /* 1 Igor-tick = 85.333333 us */ - lirc_t code = (unsigned int)ir->buf_in[i] * 85 + - (unsigned int)ir->buf_in[i] / 3; - ir->last_time.tv_usec += code; - if (ir->in_space) - code |= PULSE_BIT; - lirc_buffer_write_n(buf, (unsigned char *)&code, 1); - /* 1 chunk = CODE_LENGTH bytes */ - ir->in_space ^= 1; - ++i; - } -} - -/** - * Called in user context. - * return 0 if data was added to the buffer and - * -ENODATA if none was available. This should add some number of bits - * evenly divisible by code_length to the buffer - */ -static int usb_remote_poll(void *data, struct lirc_buffer *buf) -{ - int ret; - struct igorplug *ir = (struct igorplug *)data; - - if (!ir->usbdev) /* Has the device been removed? */ - return -ENODEV; - - memset(ir->buf_in, 0, ir->len_in); - - ret = usb_control_msg( - ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), - GET_INFRACODE, USB_TYPE_VENDOR|USB_DIR_IN, - 0/* offset */, /*unused*/0, - ir->buf_in, ir->len_in, - /*timeout*/HZ * USB_CTRL_GET_TIMEOUT); - if (ret > 0) { - lirc_t code, timediff; - struct timeval now; - - /* ACK packet has 1 byte --> ignore */ - if (ret < DEVICE_HEADERLEN) - return -ENODATA; - - dprintk(": Got %d bytes. Header: %02x %02x %02x\n", - ret, ir->buf_in[0], ir->buf_in[1], ir->buf_in[2]); - - do_gettimeofday(&now); - timediff = now.tv_sec - ir->last_time.tv_sec; - if (timediff + 1 > PULSE_MASK / 1000000) - timediff = PULSE_MASK; - else { - timediff *= 1000000; - timediff += now.tv_usec - ir->last_time.tv_usec; - } - ir->last_time.tv_sec = now.tv_sec; - ir->last_time.tv_usec = now.tv_usec; - - /* create leading gap */ - code = timediff; - lirc_buffer_write(buf, (unsigned char *)&code); - ir->in_space = 1; /* next comes a pulse */ - - if (ir->buf_in[2] == 0) - send_fragment(ir, buf, DEVICE_HEADERLEN, ret); - else { - printk(KERN_WARNING DRIVER_NAME - "[%d]: Device buffer overrun.\n", ir->devnum); - /* HHHNNNNNNNNNNNOOOOOOOO H = header - <---[2]---> N = newer - <---------ret--------> O = older */ - ir->buf_in[2] %= ret - DEVICE_HEADERLEN; /* sanitize */ - /* keep even-ness to not desync pulse/pause */ - send_fragment(ir, buf, DEVICE_HEADERLEN + - ir->buf_in[2] - (ir->buf_in[2] & 1), - ret); - send_fragment(ir, buf, DEVICE_HEADERLEN, - DEVICE_HEADERLEN + ir->buf_in[2]); - } - - ret = usb_control_msg( - ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), - SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN, - /*unused*/0, /*unused*/0, - /*dummy*/ir->buf_in, /*dummy*/ir->len_in, - /*timeout*/HZ * USB_CTRL_GET_TIMEOUT); - if (ret < 0) - printk(KERN_WARNING DRIVER_NAME - "[%d]: SET_INFRABUFFER_EMPTY: error %d\n", - ir->devnum, ret); - return 0; - } else - printk(KERN_WARNING DRIVER_NAME - "[%d]: GET_INFRACODE: error %d\n", - ir->devnum, ret); - - return -ENODATA; -} - - - -#if defined(KERNEL_2_5) -static int usb_remote_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *dev = NULL; - struct usb_host_interface *idesc = NULL; - struct usb_host_endpoint *ep_ctl2; -#else -static void *usb_remote_probe(struct usb_device *dev, unsigned int ifnum, - const struct usb_device_id *id) -{ - struct usb_interface *intf; - struct usb_interface_descriptor *idesc; - struct usb_endpoint_descriptor *ep_ctl2; -#endif - struct igorplug *ir = NULL; - struct lirc_driver *driver = NULL; - int devnum, pipe, maxp; - int minor = 0; - char buf[63], name[128] = ""; - int mem_failure = 0; - int ret; - - dprintk(": usb probe called.\n"); - -#if defined(KERNEL_2_5) - dev = interface_to_usbdev(intf); - -# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 5) - idesc = &intf->altsetting[intf->act_altsetting]; /* in 2.6.4 */ -# else - idesc = intf->cur_altsetting; /* in 2.6.6 */ -# endif - - if (idesc->desc.bNumEndpoints != 1) - return -ENODEV; - ep_ctl2 = idesc->endpoint; - if (((ep_ctl2->desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) - != USB_DIR_IN) - || (ep_ctl2->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - != USB_ENDPOINT_XFER_CONTROL) - return -ENODEV; - pipe = usb_rcvctrlpipe(dev, ep_ctl2->desc.bEndpointAddress); -#else - intf = &dev->actconfig->interface[ifnum]; - idesc = &intf->altsetting[intf->act_altsetting]; - if (idesc->bNumEndpoints != 1) - return NULL; - ep_ctl2 = idesc->endpoint; - if (((ep_ctl2->bEndpointAddress & USB_ENDPOINT_DIR_MASK) - != USB_DIR_IN) - || (ep_ctl2->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - != USB_ENDPOINT_XFER_CONTROL) - return NULL; - pipe = usb_rcvctrlpipe(dev, ep_ctl2->bEndpointAddress); -#endif - devnum = dev->devnum; - maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - - dprintk(DRIVER_NAME "[%d]: bytes_in_key=%d maxp=%d\n", - devnum, CODE_LENGTH, maxp); - - - mem_failure = 0; - ir = kzalloc(sizeof(struct igorplug), GFP_KERNEL); - if (!ir) { - mem_failure = 1; - goto mem_failure_switch; - } - - driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); - if (!driver) { - mem_failure = 2; - goto mem_failure_switch; - } - -#if defined(KERNEL_2_5) - ir->buf_in = usb_alloc_coherent(dev, - DEVICE_BUFLEN+DEVICE_HEADERLEN, - GFP_ATOMIC, &ir->dma_in); -#else - ir->buf_in = kmalloc(DEVICE_BUFLEN+DEVICE_HEADERLEN, - GFP_KERNEL); -#endif - if (!ir->buf_in) { - mem_failure = 3; - goto mem_failure_switch; - } - - strcpy(driver->name, DRIVER_NAME " "); - driver->minor = -1; - driver->code_length = CODE_LENGTH * 8; /* in bits */ - driver->features = LIRC_CAN_REC_MODE2; - driver->data = ir; - driver->buffer_size = DEVICE_BUFLEN + ADDITIONAL_LIRC_BYTES; - driver->set_use_inc = &set_use_inc; - driver->set_use_dec = &set_use_dec; - driver->sample_rate = sample_rate; /* per second */ - driver->add_to_buf = &usb_remote_poll; -#ifdef LIRC_HAVE_SYSFS - driver->dev = &intf->dev; -#endif - driver->owner = THIS_MODULE; - - minor = lirc_register_driver(driver); - if (minor < 0) - mem_failure = 9; - -mem_failure_switch: - - switch (mem_failure) { - case 9: -#if defined(KERNEL_2_5) - usb_free_coherent(dev, DEVICE_BUFLEN+DEVICE_HEADERLEN, - ir->buf_in, ir->dma_in); -#else - kfree(ir->buf_in); -#endif - case 3: - kfree(driver); - case 2: - kfree(ir); - case 1: - printk(KERN_ERR DRIVER_NAME "[%d]: out of memory (code=%d)\n", - devnum, mem_failure); -#if defined(KERNEL_2_5) - return -ENOMEM; -#else - return NULL; -#endif - } - - driver->minor = minor; - ir->d = driver; - ir->devnum = devnum; - ir->usbdev = dev; - ir->len_in = DEVICE_BUFLEN+DEVICE_HEADERLEN; - ir->in_space = 1; /* First mode2 event is a space. */ - do_gettimeofday(&ir->last_time); - - if (dev->descriptor.iManufacturer - && usb_string(dev, dev->descriptor.iManufacturer, - buf, sizeof(buf)) > 0) - strlcpy(name, buf, sizeof(name)); - if (dev->descriptor.iProduct - && usb_string(dev, dev->descriptor.iProduct, buf, sizeof(buf)) > 0) - snprintf(name + strlen(name), sizeof(name) - strlen(name), - " %s", buf); - printk(KERN_INFO DRIVER_NAME "[%d]: %s on usb%d:%d\n", devnum, name, - dev->bus->busnum, devnum); - - /* clear device buffer */ - ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), - SET_INFRABUFFER_EMPTY, USB_TYPE_VENDOR|USB_DIR_IN, - /*unused*/0, /*unused*/0, - /*dummy*/ir->buf_in, /*dummy*/ir->len_in, - /*timeout*/HZ * USB_CTRL_GET_TIMEOUT); - if (ret < 0) - printk(KERN_WARNING DRIVER_NAME - "[%d]: SET_INFRABUFFER_EMPTY: error %d\n", - devnum, ret); - -#if defined(KERNEL_2_5) - usb_set_intfdata(intf, ir); - return 0; -#else - return ir; -#endif -} - - -#if defined(KERNEL_2_5) -static void usb_remote_disconnect(struct usb_interface *intf) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct igorplug *ir = usb_get_intfdata(intf); -#else -static void usb_remote_disconnect(struct usb_device *dev, void *ptr) -{ - struct igorplug *ir = ptr; -#endif - - if (!ir || !ir->d) - return; - - printk(KERN_INFO DRIVER_NAME - "[%d]: usb remote disconnected\n", ir->devnum); - - lirc_unregister_driver(ir->d->minor); - - lirc_buffer_free(ir->d->rbuf); - kfree(ir->d->rbuf); - kfree(ir->d); - - -#if defined(KERNEL_2_5) - usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in); -#else - kfree(ir->buf_in); -#endif - - kfree(ir); -} - -static struct usb_device_id usb_remote_id_table [] = { - /* Igor Plug USB (Atmel's Manufact. ID) */ - { USB_DEVICE(0x03eb, 0x0002) }, - /* Fit PC2 Infrared Adapter */ - { USB_DEVICE(0x03eb, 0x21fe) }, - - /* Terminating entry */ - { } -}; - -static struct usb_driver usb_remote_driver = { - LIRC_THIS_MODULE(.owner = THIS_MODULE) - .name = DRIVER_NAME, - .probe = usb_remote_probe, - .disconnect = usb_remote_disconnect, - .id_table = usb_remote_id_table -}; - -static int __init usb_remote_init(void) -{ - int i; - - printk(KERN_INFO DRIVER_NAME ": " DRIVER_DESC " v" DRIVER_VERSION "\n"); - printk(KERN_INFO DRIVER_NAME ": " DRIVER_AUTHOR "\n"); - dprintk(": debug mode enabled\n"); - - i = usb_register(&usb_remote_driver); - if (i < 0) { - printk(KERN_ERR DRIVER_NAME - ": usb register failed, result = %d\n", i); - return -ENODEV; - } - - return 0; -} - -static void __exit usb_remote_exit(void) -{ - usb_deregister(&usb_remote_driver); -} - -module_init(usb_remote_init); -module_exit(usb_remote_exit); - -#if defined(KERNEL_2_5) -#include <linux/vermagic.h> -MODULE_INFO(vermagic, VERMAGIC_STRING); -#endif - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(usb, usb_remote_id_table); - -module_param(sample_rate, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(sample_rate, "Sampling rate in Hz (default: 100)"); - -EXPORT_NO_SYMBOLS; diff --git a/ubuntu/lirc/lirc_imon/Makefile b/ubuntu/lirc/lirc_imon/Makefile deleted file mode 100644 index f4386f7d908..00000000000 --- a/ubuntu/lirc/lirc_imon/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. - -obj-$(CONFIG_LIRC_IMON) += lirc_imon.o diff --git a/ubuntu/lirc/lirc_imon/lirc_imon.c b/ubuntu/lirc/lirc_imon/lirc_imon.c deleted file mode 100644 index 901c4388f8d..00000000000 --- a/ubuntu/lirc/lirc_imon/lirc_imon.c +++ /dev/null @@ -1,2368 +0,0 @@ -/* - * lirc_imon.c: LIRC/VFD/LCD driver for SoundGraph iMON IR/VFD/LCD - * including the iMON PAD model - * - * $Id: lirc_imon.c,v 1.111 2009/09/11 04:56:18 jarodwilson Exp $ - * - * Copyright(C) 2004 Venky Raju(dev@venky.ws) - * - * lirc_imon is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -#include <linux/version.h> - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) -#error "*** Sorry, this driver requires a 2.6 kernel" -#endif - -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) -#include <asm/uaccess.h> -#else -#include <linux/uaccess.h> -#endif -#include <linux/usb.h> -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) -#include <linux/usb/input.h> -#else -#include <linux/input.h> -#endif -#include <linux/time.h> -#include <linux/timer.h> - -#include "../kcompat.h" -#include "../lirc.h" -#include "../lirc_dev/lirc_dev.h" - - -#define MOD_AUTHOR "Venky Raju <dev@venky.ws>" -#define MOD_DESC "Driver for SoundGraph iMON MultiMedia IR/Display" -#define MOD_NAME "lirc_imon" -#define MOD_VERSION "0.6" - -#define DISPLAY_MINOR_BASE 144 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) -#define DEVFS_MODE (S_IFCHR | S_IRUSR | S_IWUSR | \ - S_IRGRP | S_IWGRP | S_IROTH) -#endif -#define DEVICE_NAME LIRC_DEVFS_PREFIX "lcd%d" - -#define BUF_CHUNK_SIZE 4 -#define BUF_SIZE 128 - -#define BIT_DURATION 250 /* each bit received is 250us */ - -#define IMON_CLOCK_ENABLE_PACKETS 2 - -#define dprintk(fmt, args...) \ - do { \ - if (debug) \ - printk(KERN_INFO MOD_NAME ": " fmt, ## args); \ - } while (0) - -/*** P R O T O T Y P E S ***/ - -/* USB Callback prototypes */ -static int imon_probe(struct usb_interface *interface, - const struct usb_device_id *id); -static void imon_disconnect(struct usb_interface *interface); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -static void usb_rx_callback_intf0(struct urb *urb, struct pt_regs *regs); -static void usb_rx_callback_intf1(struct urb *urb, struct pt_regs *regs); -static void usb_tx_callback(struct urb *urb, struct pt_regs *regs); -#else -static void usb_rx_callback_intf0(struct urb *urb); -static void usb_rx_callback_intf1(struct urb *urb); -static void usb_tx_callback(struct urb *urb); -#endif - -/* suspend/resume support */ -static int imon_resume(struct usb_interface *intf); -static int imon_suspend(struct usb_interface *intf, pm_message_t message); - -/* Display file_operations function prototypes */ -static int display_open(struct inode *inode, struct file *file); -static int display_close(struct inode *inode, struct file *file); - -/* VFD write operation */ -static ssize_t vfd_write(struct file *file, const char *buf, - size_t n_bytes, loff_t *pos); - -/* LCD file_operations override function prototypes */ -static ssize_t lcd_write(struct file *file, const char *buf, - size_t n_bytes, loff_t *pos); - -/* LIRC driver function prototypes */ -static int ir_open(void *data); -static void ir_close(void *data); - -/* Driver init/exit prototypes */ -static int __init imon_init(void); -static void __exit imon_exit(void); - -/*** G L O B A L S ***/ - -struct imon_context { - struct usb_device *usbdev_intf0; - /* Newer devices have two interfaces */ - struct usb_device *usbdev_intf1; - int display_supported; /* not all controllers do */ - int display_isopen; /* display port has been opened */ - int ir_isopen; /* IR port open */ - int ir_isassociating; /* IR port open for association */ - int dev_present_intf0; /* USB device presence, interface 0 */ - int dev_present_intf1; /* USB device presence, interface 1 */ - struct mutex lock; /* to lock this object */ - wait_queue_head_t remove_ok; /* For unexpected USB disconnects */ - - int vfd_proto_6p; /* some VFD require a 6th packet */ - int ir_onboard_decode; /* IR signals decoded onboard */ - - struct lirc_driver *driver; - struct usb_endpoint_descriptor *rx_endpoint_intf0; - struct usb_endpoint_descriptor *rx_endpoint_intf1; - struct usb_endpoint_descriptor *tx_endpoint; - struct urb *rx_urb_intf0; - struct urb *rx_urb_intf1; - struct urb *tx_urb; - int tx_control; - unsigned char usb_rx_buf[8]; - unsigned char usb_tx_buf[8]; - - struct rx_data { - int count; /* length of 0 or 1 sequence */ - int prev_bit; /* logic level of sequence */ - int initial_space; /* initial space flag */ - } rx; - - struct tx_t { - unsigned char data_buf[35]; /* user data buffer */ - struct completion finished; /* wait for write to finish */ - atomic_t busy; /* write in progress */ - int status; /* status of tx completion */ - } tx; - - int ffdc_dev; /* is this the overused ffdc ID? */ - int ir_protocol; /* iMON or MCE (RC6) IR protocol? */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) - struct input_dev *mouse; /* input device for iMON PAD remote */ - struct input_dev *touch; /* input device for touchscreen */ -#endif - int display_type; /* store the display type */ - int pad_mouse; /* toggle kbd(0)/mouse(1) mode */ - int touch_x; /* x coordinate on touchscreen */ - int touch_y; /* y coordinate on touchscreen */ - char name_mouse[128]; - char phys_mouse[64]; - char name_touch[128]; - char phys_touch[64]; - struct timer_list timer; -}; - -#define TOUCH_TIMEOUT (HZ/30) - -/* display file operations. Nb: lcd_write will be subbed in as needed later */ -static struct file_operations display_fops = { - .owner = THIS_MODULE, - .open = &display_open, - .write = &vfd_write, - .release = &display_close -}; - -enum { - IMON_DISPLAY_TYPE_AUTO = 0, - IMON_DISPLAY_TYPE_VFD = 1, - IMON_DISPLAY_TYPE_LCD = 2, - IMON_DISPLAY_TYPE_VGA = 3, - IMON_DISPLAY_TYPE_NONE = 4, -}; - -enum { - IMON_IR_PROTOCOL_IMON = 0, - IMON_IR_PROTOCOL_MCE = 1, - IMON_IR_PROTOCOL_IMON_NOPAD = 2, -}; -/* - * USB Device ID for iMON USB Control Boards - * - * The Windows drivers contain 6 different inf files, more or less one for - * each new device until the 0x0034-0x0046 devices, which all use the same - * driver. Some of the devices in the 34-46 range haven't been definitively - * identified yet. Early devices have either a TriGem Computer, Inc. or a - * Samsung vendor ID (0x0aa8 and 0x04e8 respectively), while all later - * devices use the SoundGraph vendor ID (0x15c2). - */ -static struct usb_device_id imon_usb_id_table[] = { - /* TriGem iMON (IR only) -- TG_iMON.inf */ - { USB_DEVICE(0x0aa8, 0x8001) }, - - /* SoundGraph iMON (IR only) -- sg_imon.inf */ - { USB_DEVICE(0x04e8, 0xff30) }, - - /* SoundGraph iMON VFD (IR & VFD) -- iMON_VFD.inf */ - { USB_DEVICE(0x0aa8, 0xffda) }, - - /* SoundGraph iMON SS (IR & VFD) -- iMON_SS.inf */ - { USB_DEVICE(0x15c2, 0xffda) }, - - /* - * Several devices with this same device ID, all use iMON_PAD.inf - * SoundGraph iMON PAD (IR & VFD) - * SoundGraph iMON PAD (IR & LCD) - * SoundGraph iMON Knob (IR only) - */ - /* SoundGraph iMON PAD (IR & VFD/LCD), iMON Knob */ - { USB_DEVICE(0x15c2, 0xffdc) }, - - /* - * Newer devices, all driven by the latest iMON Windows driver, full - * list of device IDs extracted via 'strings Setup/data1.hdr |grep 15c2' - * Need user input to fill in details on unknown devices. - */ - /* SoundGraph iMON OEM Touch LCD (IR & 7" VGA LCD) */ - { USB_DEVICE(0x15c2, 0x0034) }, - /* SoundGraph iMON OEM Touch LCD (IR & 4.3" VGA LCD) */ - { USB_DEVICE(0x15c2, 0x0035) }, - /* SoundGraph iMON OEM VFD (IR & VFD) */ - { USB_DEVICE(0x15c2, 0x0036) }, - /* device specifics unknown */ - { USB_DEVICE(0x15c2, 0x0037) }, - /* SoundGraph iMON OEM LCD (IR & LCD) */ - { USB_DEVICE(0x15c2, 0x0038) }, - /* device specifics unknown */ - { USB_DEVICE(0x15c2, 0x0039) }, - /* device specifics unknown */ - { USB_DEVICE(0x15c2, 0x003a) }, - /* device specifics unknown */ - { USB_DEVICE(0x15c2, 0x003b) }, - /* SoundGraph iMON OEM Inside (IR only) */ - { USB_DEVICE(0x15c2, 0x003c) }, - /* device specifics unknown */ - { USB_DEVICE(0x15c2, 0x003d) }, - /* device specifics unknown */ - { USB_DEVICE(0x15c2, 0x003e) }, - /* device specifics unknown */ - { USB_DEVICE(0x15c2, 0x003f) }, - /* device specifics unknown */ - { USB_DEVICE(0x15c2, 0x0040) }, - /* SoundGraph iMON MINI (IR only) */ - { USB_DEVICE(0x15c2, 0x0041) }, - /* Antec Veris Multimedia Station EZ External (IR only) */ - { USB_DEVICE(0x15c2, 0x0042) }, - /* Antec Veris Multimedia Station Basic Internal (IR only) */ - { USB_DEVICE(0x15c2, 0x0043) }, - /* Antec Veris Multimedia Station Elite (IR & VFD) */ - { USB_DEVICE(0x15c2, 0x0044) }, - /* Antec Veris Multimedia Station Premiere (IR & LCD) */ - { USB_DEVICE(0x15c2, 0x0045) }, - /* device specifics unknown */ - { USB_DEVICE(0x15c2, 0x0046) }, - {} -}; - -/* Some iMON VFD models requires a 6th packet for VFD writes */ -static struct usb_device_id vfd_proto_6p_list[] = { - { USB_DEVICE(0x15c2, 0xffda) }, - { USB_DEVICE(0x15c2, 0xffdc) }, - { USB_DEVICE(0x15c2, 0x0036) }, - { USB_DEVICE(0x15c2, 0x0044) }, - {} -}; - -/* newer iMON models use control endpoints */ -static struct usb_device_id ctl_ep_device_list[] = { - { USB_DEVICE(0x15c2, 0x0034) }, - { USB_DEVICE(0x15c2, 0x0035) }, - { USB_DEVICE(0x15c2, 0x0036) }, - { USB_DEVICE(0x15c2, 0x0037) }, - { USB_DEVICE(0x15c2, 0x0038) }, - { USB_DEVICE(0x15c2, 0x0039) }, - { USB_DEVICE(0x15c2, 0x003a) }, - { USB_DEVICE(0x15c2, 0x003b) }, - { USB_DEVICE(0x15c2, 0x003c) }, - { USB_DEVICE(0x15c2, 0x003d) }, - { USB_DEVICE(0x15c2, 0x003e) }, - { USB_DEVICE(0x15c2, 0x003f) }, - { USB_DEVICE(0x15c2, 0x0040) }, - { USB_DEVICE(0x15c2, 0x0041) }, - { USB_DEVICE(0x15c2, 0x0042) }, - { USB_DEVICE(0x15c2, 0x0043) }, - { USB_DEVICE(0x15c2, 0x0044) }, - { USB_DEVICE(0x15c2, 0x0045) }, - { USB_DEVICE(0x15c2, 0x0046) }, - {} -}; - -/* iMON LCD models use a different write op */ -static struct usb_device_id lcd_device_list[] = { - { USB_DEVICE(0x15c2, 0xffdc) }, - { USB_DEVICE(0x15c2, 0x0038) }, - { USB_DEVICE(0x15c2, 0x0045) }, - {} -}; - -/* iMON devices with front panel buttons or touchscreen need a larger buffer */ -static struct usb_device_id large_buffer_list[] = { - { USB_DEVICE(0x15c2, 0x0034) }, - { USB_DEVICE(0x15c2, 0x0035) }, - { USB_DEVICE(0x15c2, 0x0038) }, - { USB_DEVICE(0x15c2, 0x0045) }, -}; - -/* Newer iMON models decode the signal onboard */ -static struct usb_device_id ir_onboard_decode_list[] = { - { USB_DEVICE(0x15c2, 0xffdc) }, - { USB_DEVICE(0x15c2, 0x0034) }, - { USB_DEVICE(0x15c2, 0x0035) }, - { USB_DEVICE(0x15c2, 0x0036) }, - { USB_DEVICE(0x15c2, 0x0037) }, - { USB_DEVICE(0x15c2, 0x0038) }, - { USB_DEVICE(0x15c2, 0x0039) }, - { USB_DEVICE(0x15c2, 0x003a) }, - { USB_DEVICE(0x15c2, 0x003b) }, - { USB_DEVICE(0x15c2, 0x003c) }, - { USB_DEVICE(0x15c2, 0x003d) }, - { USB_DEVICE(0x15c2, 0x003e) }, - { USB_DEVICE(0x15c2, 0x003f) }, - { USB_DEVICE(0x15c2, 0x0040) }, - { USB_DEVICE(0x15c2, 0x0041) }, - { USB_DEVICE(0x15c2, 0x0042) }, - { USB_DEVICE(0x15c2, 0x0043) }, - { USB_DEVICE(0x15c2, 0x0044) }, - { USB_DEVICE(0x15c2, 0x0045) }, - { USB_DEVICE(0x15c2, 0x0046) }, - {} -}; - -/* Some iMON devices have no lcd/vfd, don't set one up */ -static struct usb_device_id ir_only_list[] = { - { USB_DEVICE(0x0aa8, 0x8001) }, - { USB_DEVICE(0x04e8, 0xff30) }, - /* the first imon lcd and the knob share this device id. :\ */ - /*{ USB_DEVICE(0x15c2, 0xffdc) },*/ - { USB_DEVICE(0x15c2, 0x003c) }, - { USB_DEVICE(0x15c2, 0x0041) }, - { USB_DEVICE(0x15c2, 0x0042) }, - { USB_DEVICE(0x15c2, 0x0043) }, - {} -}; - -/* iMON devices with VGA touchscreens */ -static struct usb_device_id imon_touchscreen_list[] = { - { USB_DEVICE(0x15c2, 0x0034) }, - { USB_DEVICE(0x15c2, 0x0035) }, - {} -}; - -/* USB Device data */ -static struct usb_driver imon_driver = { - LIRC_THIS_MODULE(.owner = THIS_MODULE) - .name = MOD_NAME, - .probe = imon_probe, - .disconnect = imon_disconnect, - .suspend = imon_suspend, - .resume = imon_resume, - .id_table = imon_usb_id_table, -}; - -static struct usb_class_driver imon_class = { - .name = DEVICE_NAME, - .fops = &display_fops, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) - .mode = DEVFS_MODE, -#endif - .minor_base = DISPLAY_MINOR_BASE, -}; - -/* to prevent races between open() and disconnect(), probing, etc */ -static DEFINE_MUTEX(driver_lock); - -static int debug; - -/* lcd, vfd, vga or none? should be auto-detected, but can be overridden... */ -static int display_type; - -/* IR protocol: native iMON, Windows MCE (RC-6), or iMON w/o PAD stabilize */ -static int ir_protocol; - -/* - * In certain use cases, mouse mode isn't really helpful, and could actually - * cause confusion, so allow disabling it when the IR device is open. - */ -static int nomouse; - -/* threshold at which a pad push registers as an arrow key in kbd mode */ -static int pad_thresh; - - -/*** M O D U L E C O D E ***/ - -MODULE_AUTHOR(MOD_AUTHOR); -MODULE_DESCRIPTION(MOD_DESC); -MODULE_VERSION(MOD_VERSION); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(usb, imon_usb_id_table); -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes(default: no)"); -module_param(display_type, int, S_IRUGO); -MODULE_PARM_DESC(display_type, "Type of attached display. 0=autodetect, " - "1=vfd, 2=lcd, 3=vga, 4=none (default: autodetect)"); -module_param(ir_protocol, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(ir_protocol, "Which IR protocol to use. 0=native iMON, " - "1=Windows Media Center Ed. (RC-6), 2=iMON w/o PAD stabilize " - "(default: native iMON)"); -module_param(nomouse, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(nomouse, "Disable mouse input device mode when IR device is " - "open. 0=don't disable, 1=disable. (default: don't disable)"); -module_param(pad_thresh, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(pad_thresh, "Threshold at which a pad push registers as an " - "arrow key in kbd mode (default: 28)"); - -static void free_imon_context(struct imon_context *context) -{ - usb_free_urb(context->tx_urb); - usb_free_urb(context->rx_urb_intf0); - usb_free_urb(context->rx_urb_intf1); - lirc_buffer_free(context->driver->rbuf); - kfree(context->driver->rbuf); - kfree(context->driver); - kfree(context); - - dprintk("%s: iMON context freed\n", __func__); -} - -static void deregister_from_lirc(struct imon_context *context) -{ - int retval; - int minor = context->driver->minor; - - retval = lirc_unregister_driver(minor); - if (retval) - err("%s: unable to deregister from lirc(%d)", - __func__, retval); - else - printk(KERN_INFO MOD_NAME ": Deregistered iMON driver " - "(minor:%d)\n", minor); - -} - -/** - * Called when the Display device (e.g. /dev/lcd0) - * is opened by the application. - */ -static int display_open(struct inode *inode, struct file *file) -{ - struct usb_interface *interface; - struct imon_context *context = NULL; - int subminor; - int retval = 0; - - /* prevent races with disconnect */ - mutex_lock(&driver_lock); - - subminor = iminor(inode); - interface = usb_find_interface(&imon_driver, subminor); - if (!interface) { - err("%s: could not find interface for minor %d", - __func__, subminor); - retval = -ENODEV; - goto exit; - } - context = usb_get_intfdata(interface); - - if (!context) { - err("%s: no context found for minor %d", - __func__, subminor); - retval = -ENODEV; - goto exit; - } - - mutex_lock(&context->lock); - - if (!context->display_supported) { - err("%s: display not supported by device", __func__); - retval = -ENODEV; - } else if (context->display_isopen) { - err("%s: display port is already open", __func__); - retval = -EBUSY; - } else { - MOD_INC_USE_COUNT; - context->display_isopen = 1; - file->private_data = context; - printk(KERN_INFO "display port opened\n"); - } - - mutex_unlock(&context->lock); - -exit: - mutex_unlock(&driver_lock); - return retval; -} - -/** - * Called when the display device (e.g. /dev/lcd0) - * is closed by the application. - */ -static int display_close(struct inode *inode, struct file *file) -{ - struct imon_context *context = NULL; - int retval = 0; - - context = (struct imon_context *)file->private_data; - - if (!context) { - err("%s: no context for device", __func__); - return -ENODEV; - } - - mutex_lock(&context->lock); - - if (!context->display_supported) { - err("%s: display not supported by device", __func__); - retval = -ENODEV; - } else if (!context->display_isopen) { - err("%s: display is not open", __func__); - retval = -EIO; - } else { - context->display_isopen = 0; - MOD_DEC_USE_COUNT; - printk(KERN_INFO "display port closed\n"); - if (!context->dev_present_intf0 && !context->ir_isopen) { - /* - * Device disconnected before close and IR port is not - * open. If IR port is open, context will be deleted by - * ir_close. - */ - mutex_unlock(&context->lock); - free_imon_context(context); - return retval; - } - } - - mutex_unlock(&context->lock); - return retval; -} - -/** - * Sends a packet to the device - */ -static int send_packet(struct imon_context *context) -{ - unsigned int pipe; - int interval = 0; - int retval = 0; - struct usb_ctrlrequest *control_req = NULL; - - /* Check if we need to use control or interrupt urb */ - if (!context->tx_control) { - pipe = usb_sndintpipe(context->usbdev_intf0, - context->tx_endpoint->bEndpointAddress); - interval = context->tx_endpoint->bInterval; - - usb_fill_int_urb(context->tx_urb, context->usbdev_intf0, pipe, - context->usb_tx_buf, - sizeof(context->usb_tx_buf), - usb_tx_callback, context, interval); - - context->tx_urb->actual_length = 0; - } else { - /* fill request into kmalloc'ed space: */ - control_req = kmalloc(sizeof(struct usb_ctrlrequest), - GFP_KERNEL); - if (control_req == NULL) - return -ENOMEM; - - /* setup packet is '21 09 0200 0001 0008' */ - control_req->bRequestType = 0x21; - control_req->bRequest = 0x09; - control_req->wValue = cpu_to_le16(0x0200); - control_req->wIndex = cpu_to_le16(0x0001); - control_req->wLength = cpu_to_le16(0x0008); - - /* control pipe is endpoint 0x00 */ - pipe = usb_sndctrlpipe(context->usbdev_intf0, 0); - - /* build the control urb */ - usb_fill_control_urb(context->tx_urb, context->usbdev_intf0, pipe, - (unsigned char *)control_req, - context->usb_tx_buf, - sizeof(context->usb_tx_buf), - usb_tx_callback, context); - context->tx_urb->actual_length = 0; - } - - init_completion(&context->tx.finished); - atomic_set(&(context->tx.busy), 1); - - retval = usb_submit_urb(context->tx_urb, GFP_KERNEL); - if (retval) { - atomic_set(&(context->tx.busy), 0); - err("%s: error submitting urb(%d)", __func__, retval); - } else { - /* Wait for transmission to complete (or abort) */ - mutex_unlock(&context->lock); - retval = wait_for_completion_interruptible( - &context->tx.finished); - if (retval) - err("%s: task interrupted", __func__); - mutex_lock(&context->lock); - - retval = context->tx.status; - if (retval) - err("%s: packet tx failed (%d)", __func__, retval); - } - - kfree(control_req); - - return retval; -} - -/** - * Sends an associate packet to the iMON 2.4G. - * - * This might not be such a good idea, since it has an id collision with - * some versions of the "IR & VFD" combo. The only way to determine if it - * is an RF version is to look at the product description string. (Which - * we currently do not fetch). - */ -static int send_associate_24g(struct imon_context *context) -{ - int retval; - const unsigned char packet[8] = { 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x20 }; - - if (!context) { - err("%s: no context for device", __func__); - return -ENODEV; - } - - if (!context->dev_present_intf0) { - err("%s: no iMON device present", __func__); - return -ENODEV; - } - - memcpy(context->usb_tx_buf, packet, sizeof(packet)); - retval = send_packet(context); - - return retval; -} - -/** - * Sends packets to setup and show clock on iMON display - * - * Arguments: year - last 2 digits of year, month - 1..12, - * day - 1..31, dow - day of the week (0-Sun...6-Sat), - * hour - 0..23, minute - 0..59, second - 0..59 - */ -static int send_set_imon_clock(struct imon_context *context, - unsigned int year, unsigned int month, - unsigned int day, unsigned int dow, - unsigned int hour, unsigned int minute, - unsigned int second) -{ - unsigned char clock_enable_pkt[IMON_CLOCK_ENABLE_PACKETS][8]; - int retval = 0; - int i; - - if (!context) { - err("%s: no context for device", __func__); - return -ENODEV; - } - - switch(context->display_type) { - case IMON_DISPLAY_TYPE_LCD: - clock_enable_pkt[0][0] = 0x80; - clock_enable_pkt[0][1] = year; - clock_enable_pkt[0][2] = month-1; - clock_enable_pkt[0][3] = day; - clock_enable_pkt[0][4] = hour; - clock_enable_pkt[0][5] = minute; - clock_enable_pkt[0][6] = second; - - clock_enable_pkt[1][0] = 0x80; - clock_enable_pkt[1][1] = 0; - clock_enable_pkt[1][2] = 0; - clock_enable_pkt[1][3] = 0; - clock_enable_pkt[1][4] = 0; - clock_enable_pkt[1][5] = 0; - clock_enable_pkt[1][6] = 0; - - if (context->ffdc_dev) { - clock_enable_pkt[0][7] = 0x50; - clock_enable_pkt[1][7] = 0x51; - } else { - clock_enable_pkt[0][7] = 0x88; - clock_enable_pkt[1][7] = 0x8a; - } - - break; - - case IMON_DISPLAY_TYPE_VFD: - clock_enable_pkt[0][0] = year; - clock_enable_pkt[0][1] = month-1; - clock_enable_pkt[0][2] = day; - clock_enable_pkt[0][3] = dow; - clock_enable_pkt[0][4] = hour; - clock_enable_pkt[0][5] = minute; - clock_enable_pkt[0][6] = second; - clock_enable_pkt[0][7] = 0x40; - - clock_enable_pkt[1][0] = 0; - clock_enable_pkt[1][1] = 0; - clock_enable_pkt[1][2] = 1; - clock_enable_pkt[1][3] = 0; - clock_enable_pkt[1][4] = 0; - clock_enable_pkt[1][5] = 0; - clock_enable_pkt[1][6] = 0; - clock_enable_pkt[1][7] = 0x42; - - break; - - default: - return -ENODEV; - } - - - for (i = 0; i < IMON_CLOCK_ENABLE_PACKETS; i++) { - memcpy(context->usb_tx_buf, clock_enable_pkt[i], 8); - retval = send_packet(context); - if (retval) { - err("%s: send_packet failed for packet %d", - __func__, i); - break; - } - } - - return retval; - -} - -/** - * These are the sysfs functions to handle the association on the iMON 2.4G LT. - */ -static ssize_t show_associate_remote(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct imon_context *context = dev_get_drvdata(d); - - if (!context) - return -ENODEV; - - mutex_lock(&context->lock); - if (context->ir_isassociating) { - strcpy(buf, "associating\n"); - } else if (context->ir_isopen) { - strcpy(buf, "open\n"); - } else { - strcpy(buf, "closed\n"); - } - printk(KERN_INFO "Visit http://www.lirc.org/html/imon-24g.html for " - "instructions on how to associate your iMON 2.4G DT/LT " - "remote\n"); - mutex_unlock(&context->lock); - return strlen(buf); -} - -static ssize_t store_associate_remote(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct imon_context *context; - - context = dev_get_drvdata(d); - - if (!context) - return -ENODEV; - - mutex_lock(&context->lock); - if (!context->ir_isopen) { - mutex_unlock(&context->lock); - return -EINVAL; - } - - if (context->ir_isopen) { - context->ir_isassociating = 1; - send_associate_24g(context); - } - mutex_unlock(&context->lock); - - return count; -} - -/** - * sysfs functions to control internal imon clock - */ -static ssize_t show_imon_clock(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct imon_context *context = dev_get_drvdata(d); - size_t len; - - if (!context) - return -ENODEV; - - mutex_lock(&context->lock); - - if (!context->display_supported) { - len = snprintf(buf, PAGE_SIZE, "Not supported."); - } else { - len = snprintf(buf, PAGE_SIZE, - "To set the clock on your iMON display:\n" - "# date \"+%%y %%m %%d %%w %%H %%M %%S\" > imon_clock\n" - "%s", context->display_isopen ? - "\nNOTE: imon device must be closed\n" : ""); - } - - mutex_unlock(&context->lock); - - return len; -} - -static ssize_t store_imon_clock(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct imon_context *context = dev_get_drvdata(d); - ssize_t retval; - unsigned int year, month, day, dow, hour, minute, second; - - if (!context) - return -ENODEV; - - mutex_lock(&context->lock); - - if (!context->display_supported) { - retval = -ENODEV; - goto exit; - } else if (context->display_isopen) { - retval = -EBUSY; - goto exit; - } - - if (sscanf(buf, "%u %u %u %u %u %u %u", &year, &month, &day, &dow, - &hour, &minute, &second) != 7) { - retval = -EINVAL; - goto exit; - } - - if ((month < 1 || month > 12) || - (day < 1 || day > 31) || (dow > 6) || - (hour > 23) || (minute > 59) || (second > 59)) { - retval = -EINVAL; - goto exit; - } - - retval = send_set_imon_clock(context, year, month, day, dow, - hour, minute, second); - if (retval) - goto exit; - - retval = count; -exit: - mutex_unlock(&context->lock); - - return retval; -} - - -static DEVICE_ATTR(imon_clock, S_IWUSR | S_IRUGO, show_imon_clock, - store_imon_clock); - -static DEVICE_ATTR(associate_remote, S_IWUSR | S_IRUGO, show_associate_remote, - store_associate_remote); - -static struct attribute *imon_display_sysfs_entries[] = { - &dev_attr_imon_clock.attr, - NULL -}; - -static struct attribute_group imon_display_attribute_group = { - .attrs = imon_display_sysfs_entries -}; - -static struct attribute *imon_rf_sysfs_entries[] = { - &dev_attr_associate_remote.attr, - NULL -}; - -static struct attribute_group imon_rf_attribute_group = { - .attrs = imon_rf_sysfs_entries -}; - -/** - * Writes data to the VFD. The iMON VFD is 2x16 characters - * and requires data in 5 consecutive USB interrupt packets, - * each packet but the last carrying 7 bytes. - * - * I don't know if the VFD board supports features such as - * scrolling, clearing rows, blanking, etc. so at - * the caller must provide a full screen of data. If fewer - * than 32 bytes are provided spaces will be appended to - * generate a full screen. - */ -static ssize_t vfd_write(struct file *file, const char *buf, - size_t n_bytes, loff_t *pos) -{ - int i; - int offset; - int seq; - int retval = 0; - struct imon_context *context; - const unsigned char vfd_packet6[] = { - 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF }; - - context = (struct imon_context *)file->private_data; - if (!context) { - err("%s: no context for device", __func__); - return -ENODEV; - } - - mutex_lock(&context->lock); - - if (!context->dev_present_intf0) { - err("%s: no iMON device present", __func__); - retval = -ENODEV; - goto exit; - } - - if (n_bytes <= 0 || n_bytes > 32) { - err("%s: invalid payload size", __func__); - retval = -EINVAL; - goto exit; - } - - if (copy_from_user(context->tx.data_buf, buf, n_bytes)) { - retval = -EFAULT; - goto exit; - } - - /* Pad with spaces */ - for (i = n_bytes; i < 32; ++i) - context->tx.data_buf[i] = ' '; - - for (i = 32; i < 35; ++i) - context->tx.data_buf[i] = 0xFF; - - offset = 0; - seq = 0; - - do { - memcpy(context->usb_tx_buf, context->tx.data_buf + offset, 7); - context->usb_tx_buf[7] = (unsigned char) seq; - - retval = send_packet(context); - if (retval) { - err("%s: send packet failed for packet #%d", - __func__, seq/2); - goto exit; - } else { - seq += 2; - offset += 7; - } - - } while (offset < 35); - - if (context->vfd_proto_6p) { - /* Send packet #6 */ - memcpy(context->usb_tx_buf, &vfd_packet6, sizeof(vfd_packet6)); - context->usb_tx_buf[7] = (unsigned char) seq; - retval = send_packet(context); - if (retval) - err("%s: send packet failed for packet #%d", - __func__, seq/2); - } - -exit: - mutex_unlock(&context->lock); - - return (!retval) ? n_bytes : retval; -} - -/** - * Writes data to the LCD. The iMON OEM LCD screen excepts 8-byte - * packets. We accept data as 16 hexadecimal digits, followed by a - * newline (to make it easy to drive the device from a command-line - * -- even though the actual binary data is a bit complicated). - * - * The device itself is not a "traditional" text-mode display. It's - * actually a 16x96 pixel bitmap display. That means if you want to - * display text, you've got to have your own "font" and translate the - * text into bitmaps for display. This is really flexible (you can - * display whatever diacritics you need, and so on), but it's also - * a lot more complicated than most LCDs... - */ -static ssize_t lcd_write(struct file *file, const char *buf, - size_t n_bytes, loff_t *pos) -{ - int retval = 0; - struct imon_context *context; - - context = (struct imon_context *)file->private_data; - if (!context) { - err("%s: no context for device", __func__); - return -ENODEV; - } - - mutex_lock(&context->lock); - - if (!context->display_supported) { - err("%s: no iMON display present", __func__); - retval = -ENODEV; - goto exit; - } - - if (n_bytes != 8) { - err("%s: invalid payload size: %d (expecting 8)", - __func__, (int) n_bytes); - retval = -EINVAL; - goto exit; - } - - if (copy_from_user(context->usb_tx_buf, buf, 8)) { - retval = -EFAULT; - goto exit; - } - - retval = send_packet(context); - if (retval) { - err("%s: send packet failed!", __func__); - goto exit; - } else { - dprintk("%s: write %d bytes to LCD\n", __func__, (int) n_bytes); - } -exit: - mutex_unlock(&context->lock); - return (!retval) ? n_bytes : retval; -} - -/** - * Callback function for USB core API: transmit data - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -static void usb_tx_callback(struct urb *urb, struct pt_regs *regs) -#else -static void usb_tx_callback(struct urb *urb) -#endif -{ - struct imon_context *context; - - if (!urb) - return; - context = (struct imon_context *)urb->context; - if (!context) - return; - - context->tx.status = urb->status; - - /* notify waiters that write has finished */ - atomic_set(&context->tx.busy, 0); - complete(&context->tx.finished); - - return; -} - -/** - * iMON IR receivers support two different signal sets -- those used by - * the iMON remotes, and those used by the Windows MCE remotes (which is - * really just RC-6), but only one or the other at a time, as the signals - * are decoded onboard the receiver. - */ -static void imon_set_ir_protocol(struct imon_context *context) -{ - int retval; - unsigned char ir_proto_packet[] = - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 }; - - switch (ir_protocol) { - case IMON_IR_PROTOCOL_MCE: - /* MCE proto not supported on devices without tx control */ - if (!context->tx_control) { - printk(KERN_INFO "%s: MCE IR protocol not supported on " - "this device, using iMON protocol\n", __func__); - context->ir_protocol = IMON_IR_PROTOCOL_IMON; - return; - } - dprintk("Configuring IR receiver for MCE protocol\n"); - ir_proto_packet[0] = 0x01; - context->ir_protocol = IMON_IR_PROTOCOL_MCE; - break; - case IMON_IR_PROTOCOL_IMON: - dprintk("Configuring IR receiver for iMON protocol\n"); - /* ir_proto_packet[0] = 0x00; // already the default */ - context->ir_protocol = IMON_IR_PROTOCOL_IMON; - break; - case IMON_IR_PROTOCOL_IMON_NOPAD: - dprintk("Configuring IR receiver for iMON protocol without " - "PAD stabilize function enabled\n"); - /* ir_proto_packet[0] = 0x00; // already the default */ - context->ir_protocol = IMON_IR_PROTOCOL_IMON_NOPAD; - break; - default: - printk(KERN_INFO "%s: unknown IR protocol specified, will " - "just default to iMON protocol\n", __func__); - context->ir_protocol = IMON_IR_PROTOCOL_IMON; - break; - } - memcpy(context->usb_tx_buf, &ir_proto_packet, - sizeof(ir_proto_packet)); - retval = send_packet(context); - if (retval) - printk(KERN_INFO "%s: failed to set remote type\n", __func__); -} - - -/** - * Called by lirc_dev when the application opens /dev/lirc - */ -static int ir_open(void *data) -{ - int retval = 0; - struct imon_context *context; - - /* prevent races with disconnect */ - mutex_lock(&driver_lock); - - context = (struct imon_context *)data; - - /* initial IR protocol decode variables */ - context->rx.count = 0; - context->rx.initial_space = 1; - context->rx.prev_bit = 0; - - /* set new IR protocol if it has changed since init or last open */ - if (ir_protocol != context->ir_protocol) - imon_set_ir_protocol(context); - - context->ir_isopen = 1; - printk(KERN_INFO MOD_NAME ": IR port opened\n"); - - mutex_unlock(&driver_lock); - return retval; -} - -/** - * Called by lirc_dev when the application closes /dev/lirc - */ -static void ir_close(void *data) -{ - struct imon_context *context; - - context = (struct imon_context *)data; - if (!context) { - err("%s: no context for device", __func__); - return; - } - - mutex_lock(&context->lock); - - context->ir_isopen = 0; - context->ir_isassociating = 0; - MOD_DEC_USE_COUNT; - printk(KERN_INFO MOD_NAME ": IR port closed\n"); - - if (!context->dev_present_intf0) { - /* - * Device disconnected while IR port was still open. Driver - * was not deregistered at disconnect time, so do it now. - */ - deregister_from_lirc(context); - - if (!context->display_isopen) { - mutex_unlock(&context->lock); - free_imon_context(context); - return; - } - /* - * If display port is open, context will be deleted by - * display_close - */ - } - - mutex_unlock(&context->lock); - return; -} - -/** - * Convert bit count to time duration (in us) and submit - * the value to lirc_dev. - */ -static void submit_data(struct imon_context *context) -{ - unsigned char buf[4]; - int value = context->rx.count; - int i; - - dprintk("submitting data to LIRC\n"); - - value *= BIT_DURATION; - value &= PULSE_MASK; - if (context->rx.prev_bit) - value |= PULSE_BIT; - - for (i = 0; i < 4; ++i) - buf[i] = value>>(i*8); - - lirc_buffer_write(context->driver->rbuf, buf); - wake_up(&context->driver->rbuf->wait_poll); - return; -} - -static inline int tv2int(const struct timeval *a, const struct timeval *b) -{ - int usecs = 0; - int sec = 0; - - if (b->tv_usec > a->tv_usec) { - usecs = 1000000; - sec--; - } - - usecs += a->tv_usec - b->tv_usec; - - sec += a->tv_sec - b->tv_sec; - sec *= 1000; - usecs /= 1000; - sec += usecs; - - if (sec < 0) - sec = 1000; - - return sec; -} - -/** - * The directional pad behaves a bit differently, depending on whether this is - * one of the older ffdc devices or a newer device. Newer devices appear to - * have a higher resolution matrix for more precise mouse movement, but it - * makes things overly sensitive in keyboard mode, so we do some interesting - * contortions to make it less touchy. Older devices run through the same - * routine with shorter timeout and a smaller threshold. - */ -static int stabilize(int a, int b, u16 timeout, u16 threshold) -{ - struct timeval ct; - static struct timeval prev_time = {0, 0}; - static struct timeval hit_time = {0, 0}; - static int x, y, prev_result, hits; - int result = 0; - int msec, msec_hit; - - do_gettimeofday(&ct); - msec = tv2int(&ct, &prev_time); - msec_hit = tv2int(&ct, &hit_time); - - if (msec > 100) { - x = 0; - y = 0; - hits = 0; - } - - x += a; - y += b; - - prev_time = ct; - - if (abs(x) > threshold || abs(y) > threshold) { - if (abs(y) > abs(x)) - result = (y > 0) ? 0x7F : 0x80; - else - result = (x > 0) ? 0x7F00 : 0x8000; - - x = 0; - y = 0; - - if (result == prev_result) { - hits++; - - if (hits > 3) { - switch (result) { - case 0x7F: - y = 17 * threshold / 30; - break; - case 0x80: - y -= 17 * threshold / 30; - break; - case 0x7F00: - x = 17 * threshold / 30; - break; - case 0x8000: - x -= 17 * threshold / 30; - break; - } - } - - if (hits == 2 && msec_hit < timeout) { - result = 0; - hits = 1; - } - } else { - prev_result = result; - hits = 1; - hit_time = ct; - } - } - - return result; -} - -/** - * Process the incoming packet - */ -static void imon_incoming_packet(struct imon_context *context, - struct urb *urb, int intf) -{ - int len = urb->actual_length; - unsigned char *buf = urb->transfer_buffer; - char rel_x = 0x00, rel_y = 0x00; - int octet, bit; - unsigned char mask; - int i, chunk_num; - int ts_input = 0; - int dir = 0; - u16 timeout, threshold; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) - int mouse_input; - int right_shift = 1; - struct input_dev *mouse = NULL; - struct input_dev *touch = NULL; - const unsigned char toggle_button1[] = { 0x29, 0x91, 0x15, 0xb7 }; - const unsigned char toggle_button2[] = { 0x29, 0x91, 0x35, 0xb7 }; - const unsigned char ch_up[] = { 0x28, 0x93, 0x95, 0xb7 }; - const unsigned char ch_down[] = { 0x28, 0x87, 0x95, 0xb7 }; -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) - mouse = context->mouse; - if (context->display_type == IMON_DISPLAY_TYPE_VGA) - touch = context->touch; - - /* keyboard/mouse mode toggle button */ - if (memcmp(buf, toggle_button1, 4) == 0 || - memcmp(buf, toggle_button2, 4) == 0) { - if (!nomouse) { - context->pad_mouse = ~(context->pad_mouse) & 0x1; - dprintk("toggling to %s mode\n", - context->pad_mouse ? "mouse" : "keyboard"); - } else { - context->pad_mouse = 0; - dprintk("mouse mode was disabled by modparam\n"); - } - return; - } - - /* send touchscreen events through input subsystem if touchpad data */ - if (context->display_type == IMON_DISPLAY_TYPE_VGA && len == 8 && - buf[7] == 0x86) { - if (touch == NULL) { - printk(KERN_WARNING "%s: touchscreen input device is " - "NULL!\n", __func__); - return; - } - mod_timer(&context->timer, jiffies + TOUCH_TIMEOUT); - context->touch_x = (buf[0] << 4) | (buf[1] >> 4); - context->touch_y = 0xfff - ((buf[2] << 4) | (buf[1] & 0xf)); - input_report_abs(touch, ABS_X, context->touch_x); - input_report_abs(touch, ABS_Y, context->touch_y); - input_report_key(touch, BTN_TOUCH, 0x01); - input_sync(touch); - ts_input = 1; - - /* send mouse events through input subsystem in mouse mode */ - } else if (context->pad_mouse || !context->ir_isopen) { - /* newer iMON device PAD or mouse button */ - if (!context->ffdc_dev && (buf[0] & 0x01) && len == 5) { - mouse_input = 1; - rel_x = buf[2]; - rel_y = buf[3]; - right_shift = 1; - /* 0xffdc iMON PAD or mouse button input */ - } else if (context->ffdc_dev && (buf[0] & 0x40) && - !((buf[1] & 0x01) || ((buf[1] >> 2) & 0x01))) { - mouse_input = 1; - rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 | - (buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6; - if (buf[0] & 0x02) - rel_x |= ~0x0f; - rel_x = rel_x + rel_x / 2; - rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 | - (buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6; - if (buf[0] & 0x01) - rel_y |= ~0x0f; - rel_y = rel_y + rel_y / 2; - right_shift = 2; - /* some ffdc devices decode mouse buttons differently... */ - } else if (context->ffdc_dev && (buf[0] == 0x68)) { - mouse_input = 1; - right_shift = 2; - /* ch+/- buttons, which we use for an emulated scroll wheel */ - } else if (!memcmp(buf, ch_up, 4)) { - mouse_input = 1; - dir = 1; - } else if (!memcmp(buf, ch_down, 4)) { - mouse_input = 1; - dir = -1; - } else - mouse_input = 0; - - if (mouse_input) { - if (mouse == NULL) { - printk(KERN_WARNING "%s: mouse input device " - "is NULL!\n", __func__); - return; - } - dprintk("sending mouse data via input subsystem\n"); - - if (dir) { - input_report_rel(mouse, REL_WHEEL, dir); - } else if (rel_x || rel_y) { - input_report_rel(mouse, REL_X, rel_x); - input_report_rel(mouse, REL_Y, rel_y); - } else { - input_report_key(mouse, BTN_LEFT, buf[1] & 0x1); - input_report_key(mouse, BTN_RIGHT, - buf[1] >> right_shift & 0x1); - } - input_sync(mouse); - return; - } - } -#endif - - /* - * at this point, mouse and touchscreen input has been handled, so - * anything else goes to lirc -- bail out if no listening IR client - */ - if (!context->ir_isopen) - return; - - /* - * we need to add some special handling for - * the imon's IR mouse events - */ - if ((len == 5) && (buf[0] == 0x01) && (buf[4] == 0x00)) { - /* first, pad to 8 bytes so it conforms with everything else */ - buf[5] = buf[6] = buf[7] = 0; - len = 8; - timeout = 500; /* in msecs */ - /* (2*threshold) x (2*threshold) square */ - threshold = pad_thresh ? pad_thresh : 28; - rel_x = buf[2]; - rel_y = buf[3]; - - /* - * the imon directional pad functions more like a touchpad. - * Bytes 3 & 4 contain a position coordinate (x,y), with each - * component ranging from -14 to 14. Since this doesn't - * cooperate well with the way lirc works (it would appear to - * lirc as more than 100 different buttons) we need to map it - * to 4 discrete values. Also, when you get too close to - * diagonals, it has a tendancy to jump back and forth, so lets - * try to ignore when they get too close - */ - if (context->ir_protocol == IMON_IR_PROTOCOL_IMON) { - if ((buf[1] == 0) && ((rel_x != 0) || (rel_y != 0))) { - dir = stabilize((int)rel_x, (int)rel_y, - timeout, threshold); - if (!dir) - return; - buf[2] = dir & 0xFF; - buf[3] = (dir >> 8) & 0xFF; - } - } else { - if (abs(rel_y) > abs(rel_x)) { - buf[2] = (rel_y > 0) ? 0x7F : 0x80; - buf[3] = 0; - } else { - buf[2] = 0; - buf[3] = (rel_x > 0) ? 0x7F : 0x80; - } - } - - } else if ((len == 8) && (buf[0] & 0x40) && - !(buf[1] & 0x01 || buf[1] >> 2 & 0x01)) { - /* - * Handle on-board decoded pad events for e.g. older - * VFD/iMON-Pad (15c2:ffdc). The remote generates various codes - * from 0x68nnnnB7 to 0x6AnnnnB7, the left mouse button - * generates 0x688301b7 and the right one 0x688481b7. All other - * keys generate 0x2nnnnnnn. Length has been padded to 8 - * already, position coordinate is encoded in buf[1] and buf[2] - * with reversed endianess. Extract direction from buffer, - * rotate endianess, adjust sign and feed the values into - * stabilize(). The resulting codes will be 0x01008000, - * 0x01007F00, ..., so one can use the normal imon-pad config - * from the remotes dir. - */ - timeout = 10; /* in msecs */ - /* (2*threshold) x (2*threshold) square */ - threshold = pad_thresh ? pad_thresh : 15; - - /* buf[1] is x */ - rel_x = (buf[1] & 0x08) | (buf[1] & 0x10) >> 2 | - (buf[1] & 0x20) >> 4 | (buf[1] & 0x40) >> 6; - if(buf[0] & 0x02) - rel_x |= ~0x10+1; - /* buf[2] is y */ - rel_y = (buf[2] & 0x08) | (buf[2] & 0x10) >> 2 | - (buf[2] & 0x20) >> 4 | (buf[2] & 0x40) >> 6; - if(buf[0] & 0x01) - rel_y |= ~0x10+1; - - buf[0] = 0x01; - buf[1] = buf[4] = buf[5] = buf[6] = buf[7] = 0; - - if (context->ir_protocol == IMON_IR_PROTOCOL_IMON) { - dir = stabilize((int)rel_x, (int)rel_y, - timeout, threshold); - if (!dir) - return; - buf[2] = dir & 0xFF; - buf[3] = (dir >> 8) & 0xFF; - } else { - if (abs(rel_y) > abs(rel_x)) { - buf[2] = (rel_y > 0) ? 0x7F : 0x80; - buf[3] = 0; - } else { - buf[2] = 0; - buf[3] = (rel_x > 0) ? 0x7F : 0x80; - } - } - - } else if (ts_input) { - /* - * this is touchscreen input, which we need to down-sample - * to a 64 button matrix at the moment... - */ - buf[0] = buf[0] >> 5; - buf[1] = 0x00; - buf[2] = buf[2] >> 5; - buf[3] = 0x00; - buf[4] = 0x00; - buf[5] = 0x00; - buf[6] = 0x14; - buf[7] = 0xff; - } - - if (len != 8) { - printk(KERN_WARNING "imon %s: invalid incoming packet " - "size (len = %d, intf%d)\n", __func__, len, intf); - return; - } - - /* iMON 2.4G associate frame */ - if (buf[0] == 0x00 && - buf[2] == 0xFF && /* REFID */ - buf[3] == 0xFF && - buf[4] == 0xFF && - buf[5] == 0xFF && /* iMON 2.4G */ - ((buf[6] == 0x4E && buf[7] == 0xDF) || /* LT */ - (buf[6] == 0x5E && buf[7] == 0xDF))) { /* DT */ - printk(KERN_WARNING "%s: remote associated refid=%02X\n", - __func__, buf[1]); - context->ir_isassociating = 0; - } - - chunk_num = buf[7]; - - if (chunk_num == 0xFF && !ts_input) - return; /* filler frame, no data here */ - - if (buf[0] == 0xFF && - buf[1] == 0xFF && - buf[2] == 0xFF && - buf[3] == 0xFF && - buf[4] == 0xFF && - buf[5] == 0xFF && /* iMON 2.4G */ - ((buf[6] == 0x4E && buf[7] == 0xAF) || /* LT */ - (buf[6] == 0x5E && buf[7] == 0xAF))) /* DT */ - return; /* filler frame, no data here */ - - if (debug) { - if (context->ir_onboard_decode) - printk("intf%d decoded packet: ", intf); - else - printk("raw packet: "); - for (i = 0; i < len; ++i) - printk("%02x ", buf[i]); - printk("\n"); - } - - if (context->ir_onboard_decode) { - /* The signals have been decoded onboard the iMON controller */ - lirc_buffer_write(context->driver->rbuf, buf); - wake_up(&context->driver->rbuf->wait_poll); - return; - } - - /* - * Translate received data to pulse and space lengths. - * Received data is active low, i.e. pulses are 0 and - * spaces are 1. - * - * My original algorithm was essentially similar to - * Changwoo Ryu's with the exception that he switched - * the incoming bits to active high and also fed an - * initial space to LIRC at the start of a new sequence - * if the previous bit was a pulse. - * - * I've decided to adopt his algorithm. - */ - - if (chunk_num == 1 && context->rx.initial_space) { - /* LIRC requires a leading space */ - context->rx.prev_bit = 0; - context->rx.count = 4; - submit_data(context); - context->rx.count = 0; - } - - for (octet = 0; octet < 5; ++octet) { - mask = 0x80; - for (bit = 0; bit < 8; ++bit) { - int curr_bit = !(buf[octet] & mask); - if (curr_bit != context->rx.prev_bit) { - if (context->rx.count) { - submit_data(context); - context->rx.count = 0; - } - context->rx.prev_bit = curr_bit; - } - ++context->rx.count; - mask >>= 1; - } - } - - if (chunk_num == 10) { - if (context->rx.count) { - submit_data(context); - context->rx.count = 0; - } - context->rx.initial_space = context->rx.prev_bit; - } -} - -/** - * report touchscreen input - */ -static void imon_touch_display_timeout(unsigned long data) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) - struct imon_context *context = (struct imon_context *)data; - struct input_dev *touch; - - if (!context->display_type == IMON_DISPLAY_TYPE_VGA) - return; - - touch = context->touch; - input_report_abs(touch, ABS_X, context->touch_x); - input_report_abs(touch, ABS_Y, context->touch_y); - input_report_key(touch, BTN_TOUCH, 0x00); - input_sync(touch); -#endif - - return; -} - -/** - * Callback function for USB core API: receive data - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -static void usb_rx_callback_intf0(struct urb *urb, struct pt_regs *regs) -#else -static void usb_rx_callback_intf0(struct urb *urb) -#endif -{ - struct imon_context *context; - unsigned char *buf; - int len; - int intfnum = 0; - - if (!urb) - return; - - context = (struct imon_context *)urb->context; - if (!context) - return; - - buf = urb->transfer_buffer; - len = urb->actual_length; - - switch (urb->status) { - case -ENOENT: /* usbcore unlink successful! */ - return; - - case 0: - imon_incoming_packet(context, urb, intfnum); - break; - - default: - printk(KERN_WARNING "imon %s: status(%d): ignored\n", - __func__, urb->status); - break; - } - - usb_submit_urb(context->rx_urb_intf0, GFP_ATOMIC); - - return; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -static void usb_rx_callback_intf1(struct urb *urb, struct pt_regs *regs) -#else -static void usb_rx_callback_intf1(struct urb *urb) -#endif -{ - struct imon_context *context; - unsigned char *buf; - int len; - int intfnum = 1; - - if (!urb) - return; - - context = (struct imon_context *)urb->context; - if (!context) - return; - - buf = urb->transfer_buffer; - len = urb->actual_length; - - switch (urb->status) { - case -ENOENT: /* usbcore unlink successful! */ - return; - - case 0: - imon_incoming_packet(context, urb, intfnum); - break; - - default: - printk(KERN_WARNING "imon %s: status(%d): ignored\n", - __func__, urb->status); - break; - } - - usb_submit_urb(context->rx_urb_intf1, GFP_ATOMIC); - - return; -} - -/** - * Callback function for USB core API: Probe - */ -static int imon_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct usb_device *usbdev = NULL; - struct usb_host_interface *iface_desc = NULL; - struct usb_endpoint_descriptor *rx_endpoint = NULL; - struct usb_endpoint_descriptor *tx_endpoint = NULL; - struct urb *rx_urb = NULL; - struct urb *tx_urb = NULL; - struct lirc_driver *driver = NULL; - struct lirc_buffer *rbuf = NULL; - struct usb_interface *first_if; - int ifnum; - int lirc_minor = 0; - int num_endpts; - int retval = 0; - int display_ep_found = 0; - int ir_ep_found = 0; - int alloc_status = 0; - int vfd_proto_6p = 0; - int ir_onboard_decode = 0; - int buf_chunk_size = BUF_CHUNK_SIZE; - int code_length; - int tx_control = 0; - struct imon_context *context = NULL; - struct imon_context *first_if_context = NULL; - int i, sysfs_err; - int configured_display_type = IMON_DISPLAY_TYPE_VFD; - u16 vendor, product; - const unsigned char fp_packet[] = { 0x40, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x88 }; - - /* - * Try to auto-detect the type of display if the user hasn't set - * it by hand via the display_type modparam. Default is VFD. - */ - if (display_type == IMON_DISPLAY_TYPE_AUTO) { - if (usb_match_id(interface, lcd_device_list)) - configured_display_type = IMON_DISPLAY_TYPE_LCD; - else if (usb_match_id(interface, imon_touchscreen_list)) - configured_display_type = IMON_DISPLAY_TYPE_VGA; - else if (usb_match_id(interface, ir_only_list)) - configured_display_type = IMON_DISPLAY_TYPE_NONE; - else - configured_display_type = IMON_DISPLAY_TYPE_VFD; - } else { - configured_display_type = display_type; - dprintk("%s: overriding display type to %d via modparam\n", - __func__, display_type); - } - - /* - * If it's the LCD, as opposed to the VFD, we just need to replace - * the "write" file op. - */ - if (configured_display_type == IMON_DISPLAY_TYPE_LCD) - display_fops.write = &lcd_write; - - /* - * To get front panel buttons working properly for newer LCD devices, - * we really do need a larger buffer. - */ - if (usb_match_id(interface, large_buffer_list)) - buf_chunk_size = 2 * BUF_CHUNK_SIZE; - - code_length = buf_chunk_size * 8; - - usbdev = usb_get_dev(interface_to_usbdev(interface)); - iface_desc = interface->cur_altsetting; - num_endpts = iface_desc->desc.bNumEndpoints; - ifnum = iface_desc->desc.bInterfaceNumber; - vendor = le16_to_cpu(usbdev->descriptor.idVendor); - product = le16_to_cpu(usbdev->descriptor.idProduct); - - dprintk("%s: found iMON device (%04x:%04x, intf%d)\n", - __func__, vendor, product, ifnum); - - /* prevent races probing devices w/multiple interfaces */ - mutex_lock(&driver_lock); - - first_if = usb_ifnum_to_if(usbdev, 0); - first_if_context = (struct imon_context *)usb_get_intfdata(first_if); - - /* - * Scan the endpoint list and set: - * first input endpoint = IR endpoint - * first output endpoint = display endpoint - */ - for (i = 0; i < num_endpts && !(ir_ep_found && display_ep_found); ++i) { - struct usb_endpoint_descriptor *ep; - int ep_dir; - int ep_type; - ep = &iface_desc->endpoint[i].desc; - ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK; - ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; - - if (!ir_ep_found && - ep_dir == USB_DIR_IN && - ep_type == USB_ENDPOINT_XFER_INT) { - - rx_endpoint = ep; - ir_ep_found = 1; - dprintk("%s: found IR endpoint\n", __func__); - - } else if (!display_ep_found && - ep_dir == USB_DIR_OUT && - ep_type == USB_ENDPOINT_XFER_INT) { - tx_endpoint = ep; - display_ep_found = 1; - dprintk("%s: found display endpoint\n", __func__); - } - } - - /* - * If we didn't find a display endpoint, this is probably one of the - * newer iMON devices that use control urb instead of interrupt - */ - if (!display_ep_found) { - if (usb_match_id(interface, ctl_ep_device_list)) { - tx_control = 1; - display_ep_found = 1; - dprintk("%s: device uses control endpoint, not " - "interface OUT endpoint\n", __func__); - } - } - - /* - * Some iMON receivers have no display. Unfortunately, it seems - * that SoundGraph recycles device IDs between devices both with - * and without... :\ - */ - if (configured_display_type == IMON_DISPLAY_TYPE_NONE) { - display_ep_found = 0; - dprintk("%s: device has no display\n", __func__); - } - - /* - * iMON Touch devices have a VGA touchscreen, but no "display", as - * that refers to e.g. /dev/lcd0 (a character device LCD or VFD). - */ - if (configured_display_type == IMON_DISPLAY_TYPE_VGA) { - display_ep_found = 0; - dprintk("%s: iMON Touch device found\n", __func__); - } - - /* Input endpoint is mandatory */ - if (!ir_ep_found) { - err("%s: no valid input (IR) endpoint found.", __func__); - retval = -ENODEV; - goto exit; - } else { - /* Determine if the IR signals are decoded onboard */ - if (usb_match_id(interface, ir_onboard_decode_list)) - ir_onboard_decode = 1; - - dprintk("%s: ir_onboard_decode: %d\n", - __func__, ir_onboard_decode); - } - - /* Determine if display requires 6 packets */ - if (display_ep_found) { - if (usb_match_id(interface, vfd_proto_6p_list)) - vfd_proto_6p = 1; - - dprintk("%s: vfd_proto_6p: %d\n", - __func__, vfd_proto_6p); - } - - if (ifnum == 0) { - context = kzalloc(sizeof(struct imon_context), GFP_KERNEL); - if (!context) { - err("%s: kzalloc failed for context", __func__); - alloc_status = 1; - goto alloc_status_switch; - } - driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); - if (!driver) { - err("%s: kzalloc failed for lirc_driver", __func__); - alloc_status = 2; - goto alloc_status_switch; - } - rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); - if (!rbuf) { - err("%s: kmalloc failed for lirc_buffer", __func__); - alloc_status = 3; - goto alloc_status_switch; - } - if (lirc_buffer_init(rbuf, buf_chunk_size, BUF_SIZE)) { - err("%s: lirc_buffer_init failed", __func__); - alloc_status = 4; - goto alloc_status_switch; - } - rx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!rx_urb) { - err("%s: usb_alloc_urb failed for IR urb", __func__); - alloc_status = 5; - goto alloc_status_switch; - } - tx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!tx_urb) { - err("%s: usb_alloc_urb failed for display urb", - __func__); - alloc_status = 6; - goto alloc_status_switch; - } - - mutex_init(&context->lock); - context->vfd_proto_6p = vfd_proto_6p; - context->ir_onboard_decode = ir_onboard_decode; - - strcpy(driver->name, MOD_NAME); - driver->minor = -1; - driver->code_length = ir_onboard_decode ? - code_length : sizeof(int) * 8; - driver->sample_rate = 0; - driver->features = (ir_onboard_decode) ? - LIRC_CAN_REC_LIRCCODE : LIRC_CAN_REC_MODE2; - driver->data = context; - driver->rbuf = rbuf; - driver->set_use_inc = ir_open; - driver->set_use_dec = ir_close; -#ifdef LIRC_HAVE_SYSFS - driver->dev = &interface->dev; -#endif - driver->owner = THIS_MODULE; - - mutex_lock(&context->lock); - - context->driver = driver; - /* start out in keyboard mode */ - context->pad_mouse = 0; - - init_timer(&context->timer); - context->timer.data = (unsigned long)context; - context->timer.function = imon_touch_display_timeout; - - lirc_minor = lirc_register_driver(driver); - if (lirc_minor < 0) { - err("%s: lirc_register_driver failed", __func__); - alloc_status = 7; - goto alloc_status_switch; - } else - printk(KERN_INFO MOD_NAME ": Registered iMON driver " - "(lirc minor: %d)\n", lirc_minor); - - /* Needed while unregistering! */ - driver->minor = lirc_minor; - - } else { - /* this is the secondary interface on the device */ - if (first_if_context->driver) { - rx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!rx_urb) { - err("%s: usb_alloc_urb failed for IR urb", - __func__); - alloc_status = 5; - goto alloc_status_switch; - } - - context = first_if_context; - } - mutex_lock(&context->lock); - } - - if (ifnum == 0) { - context->usbdev_intf0 = usbdev; - context->dev_present_intf0 = 1; - context->rx_endpoint_intf0 = rx_endpoint; - context->rx_urb_intf0 = rx_urb; - - /* - * tx is used to send characters to lcd/vfd, associate RF - * remotes, set IR protocol, and maybe more... - */ - context->tx_endpoint = tx_endpoint; - context->tx_urb = tx_urb; - context->tx_control = tx_control; - - if (display_ep_found) - context->display_supported = 1; - - if (product == 0xffdc) - context->ffdc_dev = 1; - - context->display_type = configured_display_type; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) - context->mouse = input_allocate_device(); - - snprintf(context->name_mouse, sizeof(context->name_mouse), - "iMON PAD IR Mouse (%04x:%04x)", - vendor, product); - context->mouse->name = context->name_mouse; - - usb_make_path(usbdev, context->phys_mouse, sizeof(context->phys_mouse)); - strlcat(context->phys_mouse, "/input0", sizeof(context->phys_mouse)); - context->mouse->phys = context->phys_mouse; - - context->mouse->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); - context->mouse->keybit[BIT_WORD(BTN_MOUSE)] = - BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT) | - BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_SIDE) | - BIT_MASK(BTN_EXTRA); - context->mouse->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y) | - BIT_MASK(REL_WHEEL); - - input_set_drvdata(context->mouse, context); - - usb_to_input_id(usbdev, &context->mouse->id); - context->mouse->dev.parent = &interface->dev; - retval = input_register_device(context->mouse); - if (retval) - printk(KERN_INFO "%s: pad mouse input device setup failed\n", - __func__); -#endif - - usb_fill_int_urb(context->rx_urb_intf0, context->usbdev_intf0, - usb_rcvintpipe(context->usbdev_intf0, - context->rx_endpoint_intf0->bEndpointAddress), - context->usb_rx_buf, sizeof(context->usb_rx_buf), - usb_rx_callback_intf0, context, - context->rx_endpoint_intf0->bInterval); - - retval = usb_submit_urb(context->rx_urb_intf0, GFP_KERNEL); - - if (retval) { - err("%s: usb_submit_urb failed for intf0 (%d)", - __func__, retval); - mutex_unlock(&context->lock); - goto exit; - } - - } else { - context->usbdev_intf1 = usbdev; - context->dev_present_intf1 = 1; - context->rx_endpoint_intf1 = rx_endpoint; - context->rx_urb_intf1 = rx_urb; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) - if (context->display_type == IMON_DISPLAY_TYPE_VGA) { - context->touch = input_allocate_device(); - - snprintf(context->name_touch, sizeof(context->name_touch), - "iMON USB Touchscreen (%04x:%04x)", - vendor, product); - context->touch->name = context->name_touch; - - usb_make_path(usbdev, context->phys_touch, - sizeof(context->phys_touch)); - strlcat(context->phys_touch, "/input1", - sizeof(context->phys_touch)); - context->touch->phys = context->phys_touch; - - context->touch->evbit[0] = - BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - context->touch->keybit[BIT_WORD(BTN_TOUCH)] = - BIT_MASK(BTN_TOUCH); - input_set_abs_params(context->touch, ABS_X, - 0x00, 0xfff, 0, 0); - input_set_abs_params(context->touch, ABS_Y, - 0x00, 0xfff, 0, 0); - - input_set_drvdata(context->touch, context); - - usb_to_input_id(usbdev, &context->touch->id); - context->touch->dev.parent = &interface->dev; - retval = input_register_device(context->touch); - if (retval) - printk(KERN_INFO "%s: touchscreen input device setup failed\n", - __func__); - } else - context->touch = NULL; -#endif - - usb_fill_int_urb(context->rx_urb_intf1, context->usbdev_intf1, - usb_rcvintpipe(context->usbdev_intf1, - context->rx_endpoint_intf1->bEndpointAddress), - context->usb_rx_buf, sizeof(context->usb_rx_buf), - usb_rx_callback_intf1, context, - context->rx_endpoint_intf1->bInterval); - - retval = usb_submit_urb(context->rx_urb_intf1, GFP_KERNEL); - - if (retval) { - err("%s: usb_submit_urb failed for intf1 (%d)", - __func__, retval); - mutex_unlock(&context->lock); - goto exit; - } - } - - usb_set_intfdata(interface, context); - - /* RF products *also* use 0xffdc... sigh... */ - if (context->ffdc_dev) { - sysfs_err = sysfs_create_group(&interface->dev.kobj, - &imon_rf_attribute_group); - if (sysfs_err) - err("%s: Could not create RF sysfs entries(%d)", - __func__, sysfs_err); - } - - if (context->display_supported && ifnum == 0) { - dprintk("%s: Registering iMON display with sysfs\n", __func__); - - /* set up sysfs entry for built-in clock */ - sysfs_err = sysfs_create_group(&interface->dev.kobj, - &imon_display_attribute_group); - if (sysfs_err) - err("%s: Could not create display sysfs entries(%d)", - __func__, sysfs_err); - - if (usb_register_dev(interface, &imon_class)) { - /* Not a fatal error, so ignore */ - printk(KERN_INFO "%s: could not get a minor number for " - "display\n", __func__); - } - - /* Enable front-panel buttons and/or knobs */ - memcpy(context->usb_tx_buf, &fp_packet, sizeof(fp_packet)); - retval = send_packet(context); - /* Not fatal, but warn about it */ - if (retval) - printk(KERN_INFO "%s: failed to enable front-panel " - "buttons and/or knobs\n", __func__); - } - - /* set IR protocol/remote type */ - imon_set_ir_protocol(context); - - printk(KERN_INFO MOD_NAME ": iMON device (%04x:%04x, intf%d) on " - "usb<%d:%d> initialized\n", vendor, product, ifnum, - usbdev->bus->busnum, usbdev->devnum); - -alloc_status_switch: - mutex_unlock(&context->lock); - - switch (alloc_status) { - case 7: - usb_free_urb(tx_urb); - case 6: - usb_free_urb(rx_urb); - case 5: - if (rbuf) - lirc_buffer_free(rbuf); - case 4: - kfree(rbuf); - case 3: - kfree(driver); - case 2: - kfree(context); - context = NULL; - case 1: - retval = -ENOMEM; - break; - case 0: - retval = 0; - } - -exit: - mutex_unlock(&driver_lock); - - return retval; -} - -/** - * Callback function for USB core API: disconnect - */ -static void imon_disconnect(struct usb_interface *interface) -{ - struct imon_context *context; - int ifnum; - - /* prevent races with ir_open()/display_open() */ - mutex_lock(&driver_lock); - - context = usb_get_intfdata(interface); - ifnum = interface->cur_altsetting->desc.bInterfaceNumber; - - mutex_lock(&context->lock); - - /* - * sysfs_remove_group is safe to call even if sysfs_create_group - * hasn't been called - */ - sysfs_remove_group(&interface->dev.kobj, - &imon_display_attribute_group); - sysfs_remove_group(&interface->dev.kobj, - &imon_rf_attribute_group); - - usb_set_intfdata(interface, NULL); - - /* Abort ongoing write */ - if (atomic_read(&context->tx.busy)) { - usb_kill_urb(context->tx_urb); - complete_all(&context->tx.finished); - } - - if (ifnum == 0) { - context->dev_present_intf0 = 0; - usb_kill_urb(context->rx_urb_intf0); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) - input_unregister_device(context->mouse); -#endif - if (context->display_supported) - usb_deregister_dev(interface, &imon_class); - } else { - context->dev_present_intf1 = 0; - usb_kill_urb(context->rx_urb_intf1); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) - if (context->display_type == IMON_DISPLAY_TYPE_VGA) - input_unregister_device(context->touch); -#endif - } - - if (!context->ir_isopen && !context->dev_present_intf0 && - !context->dev_present_intf1) { - del_timer_sync(&context->timer); - deregister_from_lirc(context); - mutex_unlock(&context->lock); - if (!context->display_isopen) - free_imon_context(context); - } else - mutex_unlock(&context->lock); - - mutex_unlock(&driver_lock); - - printk(KERN_INFO "%s: iMON device (intf%d) disconnected\n", - __func__, ifnum); -} - -static int imon_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct imon_context *context = usb_get_intfdata(intf); - int ifnum = intf->cur_altsetting->desc.bInterfaceNumber; - - if (ifnum == 0) - usb_kill_urb(context->rx_urb_intf0); - else - usb_kill_urb(context->rx_urb_intf1); - - return 0; -} - -static int imon_resume(struct usb_interface *intf) -{ - int rc = 0; - struct imon_context *context = usb_get_intfdata(intf); - int ifnum = intf->cur_altsetting->desc.bInterfaceNumber; - - if (ifnum == 0) { - usb_fill_int_urb(context->rx_urb_intf0, context->usbdev_intf0, - usb_rcvintpipe(context->usbdev_intf0, - context->rx_endpoint_intf0->bEndpointAddress), - context->usb_rx_buf, sizeof(context->usb_rx_buf), - usb_rx_callback_intf0, context, - context->rx_endpoint_intf0->bInterval); - - rc = usb_submit_urb(context->rx_urb_intf0, GFP_ATOMIC); - - } else { - usb_fill_int_urb(context->rx_urb_intf1, context->usbdev_intf1, - usb_rcvintpipe(context->usbdev_intf1, - context->rx_endpoint_intf1->bEndpointAddress), - context->usb_rx_buf, sizeof(context->usb_rx_buf), - usb_rx_callback_intf1, context, - context->rx_endpoint_intf1->bInterval); - - rc = usb_submit_urb(context->rx_urb_intf1, GFP_ATOMIC); - } - - return rc; -} - -static int __init imon_init(void) -{ - int rc; - - printk(KERN_INFO MOD_NAME ": " MOD_DESC ", v" MOD_VERSION "\n"); - - rc = usb_register(&imon_driver); - if (rc) { - err("%s: usb register failed(%d)", __func__, rc); - return -ENODEV; - } - - return 0; -} - -static void __exit imon_exit(void) -{ - usb_deregister(&imon_driver); - printk(KERN_INFO MOD_NAME ": module removed. Goodbye!\n"); -} - -module_init(imon_init); -module_exit(imon_exit); diff --git a/ubuntu/lirc/lirc_it87/Makefile b/ubuntu/lirc/lirc_it87/Makefile deleted file mode 100644 index de8556c6fbb..00000000000 --- a/ubuntu/lirc/lirc_it87/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. - -obj-$(CONFIG_LIRC_IT87) += lirc_it87.o diff --git a/ubuntu/lirc/lirc_it87/README b/ubuntu/lirc/lirc_it87/README deleted file mode 100644 index 70a5a5363f6..00000000000 --- a/ubuntu/lirc/lirc_it87/README +++ /dev/null @@ -1,46 +0,0 @@ -This is the README using the ITE IT8705 and IT8712 CIR port for LIRC. - -The IT8705 for example can be found on the ECS K7S5A. - -The driver supports receiving (MODE2) and sending (PULSE). It seems -sending 'LIRC_CAN_SEND_PULSE' isn't optimal for this type of hardware. -But because I don't know how to implement 'LIRC_CAN_SEND_CODE', I did -it this way. - -Attention: -Because of missing hardware, the following hasn't been tested: -a) receiving with demodulator enabled, -b) sending (debugging output looks good) and -c) using IT8712 - -Any help and/or additions etc. is welcome. - -lirc_it87 knows about the following module-parameters: -MODULE_DESCRIPTION("LIRC driver for ITE IT8712/IT8705 CIR port"); -MODULE_PARM(io, "i"); -MODULE_PARM_DESC(io, "I/O base address (default: 0x310)"); -MODULE_PARM(irq, "i"); -MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 7)"); -MODULE_PARM(it87_enable_demodulator, "i"); -MODULE_PARM_DESC(it87_enable_demodulator, "Receiver demodulator - enable/disable (1/0), default: 0"); - - -Usage: - -a) io and irq: - -If the driver finds the IT8705/12-CIR port initialized, io and irq of -the preinitialized hardware is used by the driver. If both values are -read 0x0 from the hardware, the default or given value is used. -Note: I experienced using irq=3. The driver initialized without any -problems, but no irqs are recognized by the system. I had to switch -back to default, irq 7. - -b) it87_enable_demodulator: - -The demodulator for the receiver can be switched off (default within -the driver). If you need the demodulator simple enable it by the -following way: it87_enable_demodulator=1. - -Hans-Günter Lütke Uphues diff --git a/ubuntu/lirc/lirc_it87/TODO b/ubuntu/lirc/lirc_it87/TODO deleted file mode 100644 index 5f04437e731..00000000000 --- a/ubuntu/lirc/lirc_it87/TODO +++ /dev/null @@ -1,5 +0,0 @@ -This is my todo-list for lirc_it87: - -1. enabling/using shared IRQ -2. init/drop IRQ-usage in lirc_open/lirc_close - diff --git a/ubuntu/lirc/lirc_it87/lirc_it87.c b/ubuntu/lirc/lirc_it87/lirc_it87.c deleted file mode 100644 index 9d74f0f29df..00000000000 --- a/ubuntu/lirc/lirc_it87/lirc_it87.c +++ /dev/null @@ -1,1011 +0,0 @@ -/* - * LIRC driver for ITE IT8712/IT8705/IT8720 CIR port - * - * Copyright (C) 2001 Hans-Günter Lütke Uphues <hg_lu@web.de> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * ITE IT8705, IT8712(not tested) and IT8720 CIR-port support for lirc based - * via cut and paste from lirc_sir.c (C) 2000 Milan Pikula - * - * Attention: Sendmode only tested with debugging logs - * - * 2001/02/27 Christoph Bartelmus <lirc@bartelmus.de> : - * reimplemented read function - * 2005/06/05 Andrew Calkin implemented support for Asus Digimatrix, - * based on work of the following member of the Outertrack Digimatrix - * Forum: Art103 <r_tay@hotmail.com> - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <linux/version.h> -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/signal.h> -#include <linux/fs.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/kernel.h> -#include <linux/serial_reg.h> -#include <linux/time.h> -#include <linux/string.h> -#include <linux/types.h> -#include <linux/wait.h> -#include <linux/mm.h> -#include <linux/delay.h> -#include <linux/poll.h> -#include <asm/system.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/fcntl.h> -#else -#include <linux/io.h> -#include <linux/irq.h> -#include <linux/fcntl.h> -#endif - -#include <linux/timer.h> - -#include "../lirc.h" -#include "../lirc_dev/lirc_dev.h" -#include "../kcompat.h" - -#include "lirc_it87.h" - -#ifdef LIRC_IT87_DIGIMATRIX -static int digimatrix = 1; -static int it87_freq = 36; /* kHz */ -static int irq = 9; -#else -static int digimatrix; -static int it87_freq = 38; /* kHz */ -static int irq = IT87_CIR_DEFAULT_IRQ; -#endif - -static unsigned long it87_bits_in_byte_out; -static unsigned long it87_send_counter; -static unsigned char it87_RXEN_mask = IT87_CIR_RCR_RXEN; - -#define RBUF_LEN 1024 -#define WBUF_LEN 1024 - -#define LIRC_DRIVER_NAME "lirc_it87" - -/* timeout for sequences in jiffies (=5/100s) */ -/* must be longer than TIME_CONST */ -#define IT87_TIMEOUT (HZ*5/100) - -/* module parameters */ -static int debug; -#define dprintk(fmt, args...) \ - do { \ - if (debug) \ - printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ - fmt, ## args); \ - } while (0) - -static int io = IT87_CIR_DEFAULT_IOBASE; -/* receiver demodulator default: off */ -static int it87_enable_demodulator; - -static int timer_enabled; -static DEFINE_SPINLOCK(timer_lock); -static struct timer_list timerlist; -/* time of last signal change detected */ -static struct timeval last_tv = {0, 0}; -/* time of last UART data ready interrupt */ -static struct timeval last_intr_tv = {0, 0}; -static int last_value; - -static DECLARE_WAIT_QUEUE_HEAD(lirc_read_queue); - -static DEFINE_SPINLOCK(hardware_lock); -static DEFINE_SPINLOCK(dev_lock); - -static lirc_t rx_buf[RBUF_LEN]; -unsigned int rx_tail, rx_head; -static lirc_t tx_buf[WBUF_LEN]; - -/* SECTION: Prototypes */ - -/* Communication with user-space */ -static int lirc_open(struct inode *inode, struct file *file); -static int lirc_close(struct inode *inode, struct file *file); -static unsigned int lirc_poll(struct file *file, poll_table *wait); -static ssize_t lirc_read(struct file *file, char *buf, - size_t count, loff_t *ppos); -static ssize_t lirc_write(struct file *file, const char *buf, - size_t n, loff_t *pos); -static int lirc_ioctl(struct inode *node, struct file *filep, - unsigned int cmd, unsigned long arg); -static void add_read_queue(int flag, unsigned long val); -static int init_chrdev(void); -static void drop_chrdev(void); - /* Hardware */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -static irqreturn_t it87_interrupt(int irq, void *dev_id, - struct pt_regs *regs); -#else -static irqreturn_t it87_interrupt(int irq, void *dev_id); -#endif -static void send_space(unsigned long len); -static void send_pulse(unsigned long len); -static void init_send(void); -static void terminate_send(unsigned long len); -static int init_hardware(void); -static void drop_hardware(void); -/* Initialisation */ -static int init_port(void); -static void drop_port(void); - - -/* SECTION: Communication with user-space */ - -static int lirc_open(struct inode *inode, struct file *file) -{ - spin_lock(&dev_lock); - if (MOD_IN_USE) { - spin_unlock(&dev_lock); - return -EBUSY; - } - MOD_INC_USE_COUNT; - spin_unlock(&dev_lock); - return 0; -} - - -static int lirc_close(struct inode *inode, struct file *file) -{ - MOD_DEC_USE_COUNT; - return 0; -} - - -static unsigned int lirc_poll(struct file *file, poll_table *wait) -{ - poll_wait(file, &lirc_read_queue, wait); - if (rx_head != rx_tail) - return POLLIN | POLLRDNORM; - return 0; -} - - -static ssize_t lirc_read(struct file *file, char *buf, - size_t count, loff_t *ppos) -{ - int n = 0; - int retval = 0; - - while (n < count) { - if (file->f_flags & O_NONBLOCK && rx_head == rx_tail) { - retval = -EAGAIN; - break; - } - retval = wait_event_interruptible(lirc_read_queue, - rx_head != rx_tail); - if (retval) - break; - - if (copy_to_user((void *) buf + n, (void *) (rx_buf + rx_head), - sizeof(lirc_t))) { - retval = -EFAULT; - break; - } - rx_head = (rx_head + 1) & (RBUF_LEN - 1); - n += sizeof(lirc_t); - } - if (n) - return n; - return retval; -} - - -static ssize_t lirc_write(struct file *file, const char *buf, - size_t n, loff_t *pos) -{ - int i = 0; - - if (n % sizeof(lirc_t) || (n / sizeof(lirc_t)) > WBUF_LEN) - return -EINVAL; - if (copy_from_user(tx_buf, buf, n)) - return -EFAULT; - n /= sizeof(lirc_t); - init_send(); - while (1) { - if (i >= n) - break; - if (tx_buf[i]) - send_pulse(tx_buf[i]); - i++; - if (i >= n) - break; - if (tx_buf[i]) - send_space(tx_buf[i]); - i++; - } - terminate_send(tx_buf[i - 1]); - return n; -} - - -static int lirc_ioctl(struct inode *node, struct file *filep, - unsigned int cmd, unsigned long arg) -{ - int retval = 0; - unsigned long value = 0; - unsigned int ivalue; - unsigned long hw_flags; - - if (cmd == LIRC_GET_FEATURES) - value = LIRC_CAN_SEND_PULSE | - LIRC_CAN_SET_SEND_CARRIER | - LIRC_CAN_REC_MODE2; - else if (cmd == LIRC_GET_SEND_MODE) - value = LIRC_MODE_PULSE; - else if (cmd == LIRC_GET_REC_MODE) - value = LIRC_MODE_MODE2; - - switch (cmd) { - case LIRC_GET_FEATURES: - case LIRC_GET_SEND_MODE: - case LIRC_GET_REC_MODE: - retval = put_user(value, (unsigned long *) arg); - break; - - case LIRC_SET_SEND_MODE: - case LIRC_SET_REC_MODE: - retval = get_user(value, (unsigned long *) arg); - break; - - case LIRC_SET_SEND_CARRIER: - retval = get_user(ivalue, (unsigned int *) arg); - if (retval) - return retval; - ivalue /= 1000; - if (ivalue > IT87_CIR_FREQ_MAX || - ivalue < IT87_CIR_FREQ_MIN) - return -EINVAL; - - it87_freq = ivalue; - - spin_lock_irqsave(&hardware_lock, hw_flags); - outb(((inb(io + IT87_CIR_TCR2) & IT87_CIR_TCR2_TXMPW) | - (it87_freq - IT87_CIR_FREQ_MIN) << 3), - io + IT87_CIR_TCR2); - spin_unlock_irqrestore(&hardware_lock, hw_flags); - dprintk("demodulation frequency: %d kHz\n", it87_freq); - - break; - - default: - retval = -EINVAL; - } - - if (retval) - return retval; - - if (cmd == LIRC_SET_REC_MODE) { - if (value != LIRC_MODE_MODE2) - retval = -ENOSYS; - } else if (cmd == LIRC_SET_SEND_MODE) { - if (value != LIRC_MODE_PULSE) - retval = -ENOSYS; - } - return retval; -} - -static void add_read_queue(int flag, unsigned long val) -{ - unsigned int new_rx_tail; - lirc_t newval; - - dprintk("add flag %d with val %lu\n", flag, val); - - newval = val & PULSE_MASK; - - /* - * statistically, pulses are ~TIME_CONST/2 too long. we could - * maybe make this more exact, but this is good enough - */ - if (flag) { - /* pulse */ - if (newval > TIME_CONST / 2) - newval -= TIME_CONST / 2; - else /* should not ever happen */ - newval = 1; - newval |= PULSE_BIT; - } else - newval += TIME_CONST / 2; - new_rx_tail = (rx_tail + 1) & (RBUF_LEN - 1); - if (new_rx_tail == rx_head) { - dprintk("Buffer overrun.\n"); - return; - } - rx_buf[rx_tail] = newval; - rx_tail = new_rx_tail; - wake_up_interruptible(&lirc_read_queue); -} - - -static struct file_operations lirc_fops = { - .owner = THIS_MODULE, - .read = lirc_read, - .write = lirc_write, - .poll = lirc_poll, - .ioctl = lirc_ioctl, - .open = lirc_open, - .release = lirc_close, -}; - -static int set_use_inc(void *data) -{ - return 0; -} - -static void set_use_dec(void *data) -{ -} - -static struct lirc_driver driver = { - .name = LIRC_DRIVER_NAME, - .minor = -1, - .code_length = 1, - .sample_rate = 0, - .data = NULL, - .add_to_buf = NULL, -#ifndef LIRC_REMOVE_DURING_EXPORT - .get_queue = NULL, -#endif - .set_use_inc = set_use_inc, - .set_use_dec = set_use_dec, - .fops = &lirc_fops, - .dev = NULL, - .owner = THIS_MODULE, -}; - - -static int init_chrdev(void) -{ - driver.minor = lirc_register_driver(&driver); - - if (driver.minor < 0) { - printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n"); - return -EIO; - } - return 0; -} - - -static void drop_chrdev(void) -{ - lirc_unregister_driver(driver.minor); -} - - -/* SECTION: Hardware */ -static long delta(struct timeval *tv1, struct timeval *tv2) -{ - unsigned long deltv; - - deltv = tv2->tv_sec - tv1->tv_sec; - if (deltv > 15) - deltv = 0xFFFFFF; - else - deltv = deltv*1000000 + tv2->tv_usec - tv1->tv_usec; - return deltv; -} - -static void it87_timeout(unsigned long data) -{ - unsigned long flags; - - /* avoid interference with interrupt */ - spin_lock_irqsave(&timer_lock, flags); - - if (digimatrix) { - /* We have timed out. Disable the RX mechanism. */ - - outb((inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN) | - IT87_CIR_RCR_RXACT, io + IT87_CIR_RCR); - if (it87_RXEN_mask) - outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN, - io + IT87_CIR_RCR); - dprintk(" TIMEOUT\n"); - timer_enabled = 0; - - /* fifo clear */ - outb(inb(io + IT87_CIR_TCR1) | IT87_CIR_TCR1_FIFOCLR, - io+IT87_CIR_TCR1); - - } else { - /* - * if last received signal was a pulse, but receiving stopped - * within the 9 bit frame, we need to finish this pulse and - * simulate a signal change to from pulse to space. Otherwise - * upper layers will receive two sequences next time. - */ - - if (last_value) { - unsigned long pulse_end; - - /* determine 'virtual' pulse end: */ - pulse_end = delta(&last_tv, &last_intr_tv); - dprintk("timeout add %d for %lu usec\n", - last_value, pulse_end); - add_read_queue(last_value, pulse_end); - last_value = 0; - last_tv = last_intr_tv; - } - } - spin_unlock_irqrestore(&timer_lock, flags); -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -static irqreturn_t it87_interrupt(int irq, void *dev_id, struct pt_regs *regs) -#else -static irqreturn_t it87_interrupt(int irq, void *dev_id) -#endif -{ - unsigned char data; - struct timeval curr_tv; - static unsigned long deltv; - unsigned long deltintrtv; - unsigned long flags, hw_flags; - int iir, lsr; - int fifo = 0; - static char lastbit; - char bit; - - /* Bit duration in microseconds */ - const unsigned long bit_duration = 1000000ul / - (115200 / IT87_CIR_BAUDRATE_DIVISOR); - - - iir = inb(io + IT87_CIR_IIR); - - switch (iir & IT87_CIR_IIR_IID) { - case 0x4: - case 0x6: - lsr = inb(io + IT87_CIR_RSR) & (IT87_CIR_RSR_RXFTO | - IT87_CIR_RSR_RXFBC); - fifo = lsr & IT87_CIR_RSR_RXFBC; - dprintk("iir: 0x%x fifo: 0x%x\n", iir, lsr); - - /* avoid interference with timer */ - spin_lock_irqsave(&timer_lock, flags); - spin_lock_irqsave(&hardware_lock, hw_flags); - if (digimatrix) { - static unsigned long acc_pulse; - static unsigned long acc_space; - - do { - data = inb(io + IT87_CIR_DR); - data = ~data; - fifo--; - if (data != 0x00) { - if (timer_enabled) - del_timer(&timerlist); - /* - * start timer for end of - * sequence detection - */ - timerlist.expires = jiffies + - IT87_TIMEOUT; - add_timer(&timerlist); - timer_enabled = 1; - } - /* Loop through */ - for (bit = 0; bit < 8; ++bit) { - if ((data >> bit) & 1) { - ++acc_pulse; - if (lastbit == 0) { - add_read_queue(0, - acc_space * - bit_duration); - acc_space = 0; - } - } else { - ++acc_space; - if (lastbit == 1) { - add_read_queue(1, - acc_pulse * - bit_duration); - acc_pulse = 0; - } - } - lastbit = (data >> bit) & 1; - } - - } while (fifo != 0); - } else { /* Normal Operation */ - do { - del_timer(&timerlist); - data = inb(io + IT87_CIR_DR); - - dprintk("data=%.2x\n", data); - do_gettimeofday(&curr_tv); - deltv = delta(&last_tv, &curr_tv); - deltintrtv = delta(&last_intr_tv, &curr_tv); - - dprintk("t %lu , d %d\n", - deltintrtv, (int)data); - - /* - * if nothing came in last 2 cycles, - * it was gap - */ - if (deltintrtv > TIME_CONST * 2) { - if (last_value) { - dprintk("GAP\n"); - - /* simulate signal change */ - add_read_queue(last_value, - deltv - - deltintrtv); - last_value = 0; - last_tv.tv_sec = - last_intr_tv.tv_sec; - last_tv.tv_usec = - last_intr_tv.tv_usec; - deltv = deltintrtv; - } - } - data = 1; - if (data ^ last_value) { - /* - * deltintrtv > 2*TIME_CONST, - * remember ? the other case is - * timeout - */ - add_read_queue(last_value, - deltv-TIME_CONST); - last_value = data; - last_tv = curr_tv; - if (last_tv.tv_usec >= TIME_CONST) - last_tv.tv_usec -= TIME_CONST; - else { - last_tv.tv_sec--; - last_tv.tv_usec += 1000000 - - TIME_CONST; - } - } - last_intr_tv = curr_tv; - if (data) { - /* - * start timer for end of - * sequence detection - */ - timerlist.expires = - jiffies + IT87_TIMEOUT; - add_timer(&timerlist); - } - outb((inb(io + IT87_CIR_RCR) & - ~IT87_CIR_RCR_RXEN) | - IT87_CIR_RCR_RXACT, - io + IT87_CIR_RCR); - if (it87_RXEN_mask) - outb(inb(io + IT87_CIR_RCR) | - IT87_CIR_RCR_RXEN, - io + IT87_CIR_RCR); - fifo--; - } while (fifo != 0); - } - spin_unlock_irqrestore(&hardware_lock, hw_flags); - spin_unlock_irqrestore(&timer_lock, flags); - - return IRQ_RETVAL(IRQ_HANDLED); - - default: - /* not our irq */ - dprintk("unknown IRQ (shouldn't happen) !!\n"); - return IRQ_RETVAL(IRQ_NONE); - } -} - - -static void send_it87(unsigned long len, unsigned long stime, - unsigned char send_byte, unsigned int count_bits) -{ - long count = len / stime; - long time_left = 0; - static unsigned char byte_out; - unsigned long hw_flags; - - dprintk("%s: len=%ld, sb=%d\n", __func__, len, send_byte); - - time_left = (long)len - (long)count * (long)stime; - count += ((2 * time_left) / stime); - while (count) { - long i = 0; - for (i = 0; i < count_bits; i++) { - byte_out = (byte_out << 1) | (send_byte & 1); - it87_bits_in_byte_out++; - } - if (it87_bits_in_byte_out == 8) { - dprintk("out=0x%x, tsr_txfbc: 0x%x\n", - byte_out, - inb(io + IT87_CIR_TSR) & - IT87_CIR_TSR_TXFBC); - - while ((inb(io + IT87_CIR_TSR) & - IT87_CIR_TSR_TXFBC) >= IT87_CIR_FIFO_SIZE) - ; - - spin_lock_irqsave(&hardware_lock, hw_flags); - outb(byte_out, io + IT87_CIR_DR); - spin_unlock_irqrestore(&hardware_lock, hw_flags); - - it87_bits_in_byte_out = 0; - it87_send_counter++; - byte_out = 0; - } - count--; - } -} - - -/*TODO: maybe exchange space and pulse because it8705 only modulates 0-bits */ - -static void send_space(unsigned long len) -{ - send_it87(len, TIME_CONST, IT87_CIR_SPACE, IT87_CIR_BAUDRATE_DIVISOR); -} - -static void send_pulse(unsigned long len) -{ - send_it87(len, TIME_CONST, IT87_CIR_PULSE, IT87_CIR_BAUDRATE_DIVISOR); -} - - -static void init_send() -{ - unsigned long flags; - - spin_lock_irqsave(&hardware_lock, flags); - /* RXEN=0: receiver disable */ - it87_RXEN_mask = 0; - outb(inb(io + IT87_CIR_RCR) & ~IT87_CIR_RCR_RXEN, - io + IT87_CIR_RCR); - spin_unlock_irqrestore(&hardware_lock, flags); - it87_bits_in_byte_out = 0; - it87_send_counter = 0; -} - - -static void terminate_send(unsigned long len) -{ - unsigned long flags; - unsigned long last = 0; - - last = it87_send_counter; - /* make sure all necessary data has been sent */ - while (last == it87_send_counter) - send_space(len); - /* wait until all data sent */ - while ((inb(io + IT87_CIR_TSR) & IT87_CIR_TSR_TXFBC) != 0) - ; - /* then re-enable receiver */ - spin_lock_irqsave(&hardware_lock, flags); - it87_RXEN_mask = IT87_CIR_RCR_RXEN; - outb(inb(io + IT87_CIR_RCR) | IT87_CIR_RCR_RXEN, - io + IT87_CIR_RCR); - spin_unlock_irqrestore(&hardware_lock, flags); -} - - -static int init_hardware(void) -{ - unsigned long flags; - unsigned char it87_rcr = 0; - - spin_lock_irqsave(&hardware_lock, flags); - /* init cir-port */ - /* enable r/w-access to Baudrate-Register */ - outb(IT87_CIR_IER_BR, io + IT87_CIR_IER); - outb(IT87_CIR_BAUDRATE_DIVISOR % 0x100, io+IT87_CIR_BDLR); - outb(IT87_CIR_BAUDRATE_DIVISOR / 0x100, io+IT87_CIR_BDHR); - /* Baudrate Register off, define IRQs: Input only */ - if (digimatrix) { - outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RFOIE, io + IT87_CIR_IER); - /* RX: HCFS=0, RXDCR = 001b (33,75..38,25 kHz), RXEN=1 */ - } else { - outb(IT87_CIR_IER_IEC | IT87_CIR_IER_RDAIE, io + IT87_CIR_IER); - /* RX: HCFS=0, RXDCR = 001b (35,6..40,3 kHz), RXEN=1 */ - } - it87_rcr = (IT87_CIR_RCR_RXEN & it87_RXEN_mask) | 0x1; - if (it87_enable_demodulator) - it87_rcr |= IT87_CIR_RCR_RXEND; - outb(it87_rcr, io + IT87_CIR_RCR); - if (digimatrix) { - /* Set FIFO depth to 1 byte, and disable TX */ - outb(inb(io + IT87_CIR_TCR1) | 0x00, - io + IT87_CIR_TCR1); - - /* - * TX: it87_freq (36kHz), 'reserved' sensitivity - * setting (0x00) - */ - outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x00, - io + IT87_CIR_TCR2); - } else { - /* TX: 38kHz, 13,3us (pulse-width) */ - outb(((it87_freq - IT87_CIR_FREQ_MIN) << 3) | 0x06, - io + IT87_CIR_TCR2); - } - spin_unlock_irqrestore(&hardware_lock, flags); - return 0; -} - - -static void drop_hardware(void) -{ - unsigned long flags; - - spin_lock_irqsave(&hardware_lock, flags); - disable_irq(irq); - /* receiver disable */ - it87_RXEN_mask = 0; - outb(0x1, io + IT87_CIR_RCR); - /* turn off irqs */ - outb(0, io + IT87_CIR_IER); - /* fifo clear */ - outb(IT87_CIR_TCR1_FIFOCLR, io+IT87_CIR_TCR1); - /* reset */ - outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER); - enable_irq(irq); - spin_unlock_irqrestore(&hardware_lock, flags); -} - - -static unsigned char it87_read(unsigned char port) -{ - outb(port, IT87_ADRPORT); - return inb(IT87_DATAPORT); -} - - -static void it87_write(unsigned char port, unsigned char data) -{ - outb(port, IT87_ADRPORT); - outb(data, IT87_DATAPORT); -} - - -/* SECTION: Initialisation */ - -static int init_port(void) -{ - unsigned long hw_flags; - int retval = 0; - - unsigned char init_bytes[4] = IT87_INIT; - unsigned char it87_chipid = 0; - unsigned char ldn = 0; - unsigned int it87_io = 0; - unsigned int it87_irq = 0; - - /* Enter MB PnP Mode */ - outb(init_bytes[0], IT87_ADRPORT); - outb(init_bytes[1], IT87_ADRPORT); - outb(init_bytes[2], IT87_ADRPORT); - outb(init_bytes[3], IT87_ADRPORT); - - /* 8712 or 8705 ? */ - it87_chipid = it87_read(IT87_CHIP_ID1); - if (it87_chipid != 0x87) { - retval = -ENXIO; - return retval; - } - it87_chipid = it87_read(IT87_CHIP_ID2); - if ((it87_chipid != 0x12) && - (it87_chipid != 0x05) && - (it87_chipid != 0x20)) { - printk(KERN_INFO LIRC_DRIVER_NAME - ": no IT8705/12/20 found, exiting..\n"); - retval = -ENXIO; - return retval; - } - printk(KERN_INFO LIRC_DRIVER_NAME - ": found IT87%.2x.\n", - it87_chipid); - - /* get I/O-Port and IRQ */ - if (it87_chipid == 0x12) - ldn = IT8712_CIR_LDN; - else - ldn = IT8705_CIR_LDN; - it87_write(IT87_LDN, ldn); - - it87_io = it87_read(IT87_CIR_BASE_MSB) * 256 + - it87_read(IT87_CIR_BASE_LSB); - if (it87_io == 0) { - if (io == 0) - io = IT87_CIR_DEFAULT_IOBASE; - printk(KERN_INFO LIRC_DRIVER_NAME - ": set default io 0x%x\n", - io); - it87_write(IT87_CIR_BASE_MSB, io / 0x100); - it87_write(IT87_CIR_BASE_LSB, io % 0x100); - } else - io = it87_io; - - it87_irq = it87_read(IT87_CIR_IRQ); - if (digimatrix || it87_irq == 0) { - if (irq == 0) - irq = IT87_CIR_DEFAULT_IRQ; - printk(KERN_INFO LIRC_DRIVER_NAME - ": set default irq 0x%x\n", - irq); - it87_write(IT87_CIR_IRQ, irq); - } else - irq = it87_irq; - - spin_lock_irqsave(&hardware_lock, hw_flags); - /* reset */ - outb(IT87_CIR_IER_RESET, io+IT87_CIR_IER); - /* fifo clear */ - outb(IT87_CIR_TCR1_FIFOCLR | - /* IT87_CIR_TCR1_ILE | */ - IT87_CIR_TCR1_TXRLE | - IT87_CIR_TCR1_TXENDF, io+IT87_CIR_TCR1); - spin_unlock_irqrestore(&hardware_lock, hw_flags); - - /* get I/O port access and IRQ line */ - if (request_region(io, 8, LIRC_DRIVER_NAME) == NULL) { - printk(KERN_ERR LIRC_DRIVER_NAME - ": i/o port 0x%.4x already in use.\n", io); - /* Leaving MB PnP Mode */ - it87_write(IT87_CFGCTRL, 0x2); - return -EBUSY; - } - - /* activate CIR-Device */ - it87_write(IT87_CIR_ACT, 0x1); - - /* Leaving MB PnP Mode */ - it87_write(IT87_CFGCTRL, 0x2); - - retval = request_irq(irq, it87_interrupt, 0 /*IRQF_DISABLED*/, - LIRC_DRIVER_NAME, NULL); - if (retval < 0) { - printk(KERN_ERR LIRC_DRIVER_NAME - ": IRQ %d already in use.\n", - irq); - release_region(io, 8); - return retval; - } - - printk(KERN_INFO LIRC_DRIVER_NAME - ": I/O port 0x%.4x, IRQ %d.\n", io, irq); - - init_timer(&timerlist); - timerlist.function = it87_timeout; - timerlist.data = 0xabadcafe; - - return 0; -} - - -static void drop_port(void) -{ -#if 0 - unsigned char init_bytes[4] = IT87_INIT; - - /* Enter MB PnP Mode */ - outb(init_bytes[0], IT87_ADRPORT); - outb(init_bytes[1], IT87_ADRPORT); - outb(init_bytes[2], IT87_ADRPORT); - outb(init_bytes[3], IT87_ADRPORT); - - /* deactivate CIR-Device */ - it87_write(IT87_CIR_ACT, 0x0); - - /* Leaving MB PnP Mode */ - it87_write(IT87_CFGCTRL, 0x2); -#endif - - del_timer_sync(&timerlist); - free_irq(irq, NULL); - release_region(io, 8); -} - - -static int init_lirc_it87(void) -{ - int retval; - - init_waitqueue_head(&lirc_read_queue); - retval = init_port(); - if (retval < 0) - return retval; - init_hardware(); - printk(KERN_INFO LIRC_DRIVER_NAME ": Installed.\n"); - return 0; -} - - -static int __init lirc_it87_init(void) -{ - int retval; - - retval = init_chrdev(); - if (retval < 0) - return retval; - retval = init_lirc_it87(); - if (retval) { - drop_chrdev(); - return retval; - } - return 0; -} - - -static void __exit lirc_it87_exit(void) -{ - drop_hardware(); - drop_chrdev(); - drop_port(); - printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n"); -} - -module_init(lirc_it87_init); -module_exit(lirc_it87_exit); - -MODULE_DESCRIPTION("LIRC driver for ITE IT8712/IT8705 CIR port"); -MODULE_AUTHOR("Hans-Günter Lütke Uphues"); -MODULE_LICENSE("GPL"); - -module_param(io, int, S_IRUGO); -MODULE_PARM_DESC(io, "I/O base address (default: 0x310)"); - -module_param(irq, int, S_IRUGO); -#ifdef LIRC_IT87_DIGIMATRIX -MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 9)"); -#else -MODULE_PARM_DESC(irq, "Interrupt (1,3-12) (default: 7)"); -#endif - -module_param(it87_enable_demodulator, bool, S_IRUGO); -MODULE_PARM_DESC(it87_enable_demodulator, - "Receiver demodulator enable/disable (1/0), default: 0"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Enable debugging messages"); - -module_param(digimatrix, bool, S_IRUGO | S_IWUSR); -#ifdef LIRC_IT87_DIGIMATRIX -MODULE_PARM_DESC(digimatrix, - "Asus Digimatrix it87 compat. enable/disable (1/0), default: 1"); -#else -MODULE_PARM_DESC(digimatrix, - "Asus Digimatrix it87 compat. enable/disable (1/0), default: 0"); -#endif - - -module_param(it87_freq, int, S_IRUGO); -#ifdef LIRC_IT87_DIGIMATRIX -MODULE_PARM_DESC(it87_freq, - "Carrier demodulator frequency (kHz), (default: 36)"); -#else -MODULE_PARM_DESC(it87_freq, - "Carrier demodulator frequency (kHz), (default: 38)"); -#endif -EXPORT_NO_SYMBOLS; diff --git a/ubuntu/lirc/lirc_it87/lirc_it87.h b/ubuntu/lirc/lirc_it87/lirc_it87.h deleted file mode 100644 index cf021c893a3..00000000000 --- a/ubuntu/lirc/lirc_it87/lirc_it87.h +++ /dev/null @@ -1,116 +0,0 @@ -/* lirc_it87.h */ -/* SECTION: Definitions */ - -/********************************* ITE IT87xx ************************/ - -/* based on the following documentation from ITE: - a) IT8712F Preliminary CIR Programming Guide V0.1 - b) IT8705F Simple LPC I/O Preliminary Specification V0.3 - c) IT8712F EC-LPC I/O Preliminary Specification V0.5 -*/ - -/* IT8712/05 Ports: */ -#define IT87_ADRPORT 0x2e -#define IT87_DATAPORT 0x2f -#define IT87_INIT {0x87, 0x01, 0x55, 0x55} - -/* alternate Ports: */ -/* -#define IT87_ADRPORT 0x4e -#define IT87_DATAPORT 0x4f -#define IT87_INIT {0x87, 0x01, 0x55, 0xaa} - */ - -/* IT8712/05 Registers */ -#define IT87_CFGCTRL 0x2 -#define IT87_LDN 0x7 -#define IT87_CHIP_ID1 0x20 -#define IT87_CHIP_ID2 0x21 -#define IT87_CFG_VERSION 0x22 -#define IT87_SWSUSPEND 0x23 - -#define IT8712_CIR_LDN 0xa -#define IT8705_CIR_LDN 0x7 - -/* CIR Configuration Registers: */ -#define IT87_CIR_ACT 0x30 -#define IT87_CIR_BASE_MSB 0x60 -#define IT87_CIR_BASE_LSB 0x61 -#define IT87_CIR_IRQ 0x70 -#define IT87_CIR_CONFIG 0xf0 - -/* List of IT87_CIR registers: offset to BaseAddr */ -#define IT87_CIR_DR 0 -#define IT87_CIR_IER 1 -#define IT87_CIR_RCR 2 -#define IT87_CIR_TCR1 3 -#define IT87_CIR_TCR2 4 -#define IT87_CIR_TSR 5 -#define IT87_CIR_RSR 6 -#define IT87_CIR_BDLR 5 -#define IT87_CIR_BDHR 6 -#define IT87_CIR_IIR 7 - -/* Bit Definition */ -/* IER: */ -#define IT87_CIR_IER_TM_EN 0x80 -#define IT87_CIR_IER_RESEVED 0x40 -#define IT87_CIR_IER_RESET 0x20 -#define IT87_CIR_IER_BR 0x10 -#define IT87_CIR_IER_IEC 0x8 -#define IT87_CIR_IER_RFOIE 0x4 -#define IT87_CIR_IER_RDAIE 0x2 -#define IT87_CIR_IER_TLDLIE 0x1 - -/* RCR: */ -#define IT87_CIR_RCR_RDWOS 0x80 -#define IT87_CIR_RCR_HCFS 0x40 -#define IT87_CIR_RCR_RXEN 0x20 -#define IT87_CIR_RCR_RXEND 0x10 -#define IT87_CIR_RCR_RXACT 0x8 -#define IT87_CIR_RCR_RXDCR 0x7 - -/* TCR1: */ -#define IT87_CIR_TCR1_FIFOCLR 0x80 -#define IT87_CIR_TCR1_ILE 0x40 -#define IT87_CIR_TCR1_FIFOTL 0x30 -#define IT87_CIR_TCR1_TXRLE 0x8 -#define IT87_CIR_TCR1_TXENDF 0x4 -#define IT87_CIR_TCR1_TXMPM 0x3 - -/* TCR2: */ -#define IT87_CIR_TCR2_CFQ 0xf8 -#define IT87_CIR_TCR2_TXMPW 0x7 - -/* TSR: */ -#define IT87_CIR_TSR_RESERVED 0xc0 -#define IT87_CIR_TSR_TXFBC 0x3f - -/* RSR: */ -#define IT87_CIR_RSR_RXFTO 0x80 -#define IT87_CIR_RSR_RESERVED 0x40 -#define IT87_CIR_RSR_RXFBC 0x3f - -/* IIR: */ -#define IT87_CIR_IIR_RESERVED 0xf8 -#define IT87_CIR_IIR_IID 0x6 -#define IT87_CIR_IIR_IIP 0x1 - -/* TM: */ -#define IT87_CIR_TM_IL_SEL 0x80 -#define IT87_CIR_TM_RESERVED 0x40 -#define IT87_CIR_TM_TM_REG 0x3f - -#define IT87_CIR_FIFO_SIZE 32 - -/* Baudratedivisor for IT87: power of 2: only 1,2,4 or 8) */ -#define IT87_CIR_BAUDRATE_DIVISOR 0x1 -#define IT87_CIR_DEFAULT_IOBASE 0x310 -#define IT87_CIR_DEFAULT_IRQ 0x7 -#define IT87_CIR_SPACE 0x00 -#define IT87_CIR_PULSE 0xff -#define IT87_CIR_FREQ_MIN 27 -#define IT87_CIR_FREQ_MAX 58 -#define TIME_CONST (IT87_CIR_BAUDRATE_DIVISOR * 8000000ul / 115200ul) - -/********************************* ITE IT87xx ************************/ diff --git a/ubuntu/lirc/lirc_ite8709/Makefile b/ubuntu/lirc/lirc_ite8709/Makefile deleted file mode 100644 index 1d8387cf092..00000000000 --- a/ubuntu/lirc/lirc_ite8709/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. - -obj-$(CONFIG_LIRC_ITE8709) += lirc_ite8709.o diff --git a/ubuntu/lirc/lirc_ite8709/lirc_ite8709.c b/ubuntu/lirc/lirc_ite8709/lirc_ite8709.c deleted file mode 100644 index bcbc2ad0b03..00000000000 --- a/ubuntu/lirc/lirc_ite8709/lirc_ite8709.c +++ /dev/null @@ -1,552 +0,0 @@ -/* - * LIRC driver for ITE8709 CIR port - * - * Copyright (C) 2008 Grégory Lardière <spmf2004-lirc@yahoo.fr> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#include <linux/version.h> -#include <linux/module.h> -#include <linux/pnp.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -#include <asm/io.h> -#else -#include <linux/io.h> -#endif - -#include "../lirc.h" -#include "../lirc_dev/lirc_dev.h" -#include "../kcompat.h" - -#define LIRC_DRIVER_NAME "lirc_ite8709" - -#define BUF_CHUNK_SIZE sizeof(lirc_t) -#define BUF_SIZE (128*BUF_CHUNK_SIZE) - -/* - * The ITE8709 device seems to be the combination of IT8512 superIO chip and - * a specific firmware running on the IT8512's embedded micro-controller. - * In addition of the embedded micro-controller, the IT8512 chip contains a - * CIR module and several other modules. A few modules are directly accessible - * by the host CPU, but most of them are only accessible by the - * micro-controller. The CIR module is only accessible by the micro-controller. - * The battery-backed SRAM module is accessible by the host CPU and the - * micro-controller. So one of the MC's firmware role is to act as a bridge - * between the host CPU and the CIR module. The firmware implements a kind of - * communication protocol using the SRAM module as a shared memory. The IT8512 - * specification is publicly available on ITE's web site, but the communication - * protocol is not, so it was reverse-engineered. - */ - -/* ITE8709 Registers addresses and values (reverse-engineered) */ -#define ITE8709_MODE 0x1a -#define ITE8709_REG_ADR 0x1b -#define ITE8709_REG_VAL 0x1c -#define ITE8709_IIR 0x1e /* Interrupt identification register */ -#define ITE8709_RFSR 0x1f /* Receiver FIFO status register */ -#define ITE8709_FIFO_START 0x20 - -#define ITE8709_MODE_READY 0X00 -#define ITE8709_MODE_WRITE 0X01 -#define ITE8709_MODE_READ 0X02 -#define ITE8709_IIR_RDAI 0x02 /* Receiver data available interrupt */ -#define ITE8709_IIR_RFOI 0x04 /* Receiver FIFO overrun interrupt */ -#define ITE8709_RFSR_MASK 0x3f /* FIFO byte count mask */ - -/* - * IT8512 CIR-module registers addresses and values - * (from IT8512 E/F specification v0.4.1) - */ -#define IT8512_REG_MSTCR 0x01 /* Master control register */ -#define IT8512_REG_IER 0x02 /* Interrupt enable register */ -#define IT8512_REG_CFR 0x04 /* Carrier frequency register */ -#define IT8512_REG_RCR 0x05 /* Receive control register */ -#define IT8512_REG_BDLR 0x08 /* Baud rate divisor low byte register */ -#define IT8512_REG_BDHR 0x09 /* Baud rate divisor high byte register */ - -#define IT8512_MSTCR_RESET 0x01 /* Reset registers to default value */ -#define IT8512_MSTCR_FIFOCLR 0x02 /* Clear FIFO */ -#define IT8512_MSTCR_FIFOTL_7 0x04 /* FIFO threshold level : 7 */ -#define IT8512_MSTCR_FIFOTL_25 0x0c /* FIFO threshold level : 25 */ -#define IT8512_IER_RDAIE 0x02 /* Enable data interrupt request */ -#define IT8512_IER_RFOIE 0x04 /* Enable FIFO overrun interrupt req */ -#define IT8512_IER_IEC 0x80 /* Enable interrupt request */ -#define IT8512_CFR_CF_36KHZ 0x09 /* Carrier freq : low speed, 36kHz */ -#define IT8512_RCR_RXDCR_1 0x01 /* Demodulation carrier range : 1 */ -#define IT8512_RCR_RXACT 0x08 /* Receiver active */ -#define IT8512_RCR_RXEN 0x80 /* Receiver enable */ -#define IT8512_BDR_6 6 /* Baud rate divisor : 6 */ - -/* Actual values used by this driver */ -#define CFG_FIFOTL IT8512_MSTCR_FIFOTL_25 -#define CFG_CR_FREQ IT8512_CFR_CF_36KHZ -#define CFG_DCR IT8512_RCR_RXDCR_1 -#define CFG_BDR IT8512_BDR_6 -#define CFG_TIMEOUT 100000 /* Rearm interrupt when a space is > 100 ms */ - -static int debug; - -struct ite8709_device { - int use_count; - int io; - int irq; - spinlock_t hardware_lock; - unsigned long long acc_pulse; - unsigned long long acc_space; - char lastbit; - struct timeval last_tv; - struct lirc_driver driver; - struct lirc_buffer buffer; - struct tasklet_struct tasklet; - char force_rearm; - char rearmed; - char device_busy; -}; - -#define dprintk(fmt, args...) \ - do { \ - if (debug) \ - printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ - fmt, ## args); \ - } while (0) - - -static unsigned char ite8709_read(struct ite8709_device *dev, - unsigned char port) -{ - outb(port, dev->io); - return inb(dev->io+1); -} - -static void ite8709_write(struct ite8709_device *dev, unsigned char port, - unsigned char data) -{ - outb(port, dev->io); - outb(data, dev->io+1); -} - -static void ite8709_wait_device(struct ite8709_device *dev) -{ - int i = 0; - /* - * loop until device tells it's ready to continue - * iterations count is usually ~750 but can sometimes achieve 13000 - */ - for (i = 0; i < 15000; i++) { - udelay(2); - if (ite8709_read(dev, ITE8709_MODE) == ITE8709_MODE_READY) - break; - } -} - -static void ite8709_write_register(struct ite8709_device *dev, - unsigned char reg_adr, unsigned char reg_value) -{ - ite8709_wait_device(dev); - - ite8709_write(dev, ITE8709_REG_VAL, reg_value); - ite8709_write(dev, ITE8709_REG_ADR, reg_adr); - ite8709_write(dev, ITE8709_MODE, ITE8709_MODE_WRITE); -} - -static void ite8709_init_hardware(struct ite8709_device *dev) -{ - spin_lock_irq(&dev->hardware_lock); - dev->device_busy = 1; - spin_unlock_irq(&dev->hardware_lock); - - ite8709_write_register(dev, IT8512_REG_BDHR, (CFG_BDR >> 8) & 0xff); - ite8709_write_register(dev, IT8512_REG_BDLR, CFG_BDR & 0xff); - ite8709_write_register(dev, IT8512_REG_CFR, CFG_CR_FREQ); - ite8709_write_register(dev, IT8512_REG_IER, - IT8512_IER_IEC | IT8512_IER_RFOIE | IT8512_IER_RDAIE); - ite8709_write_register(dev, IT8512_REG_RCR, CFG_DCR); - ite8709_write_register(dev, IT8512_REG_MSTCR, - CFG_FIFOTL | IT8512_MSTCR_FIFOCLR); - ite8709_write_register(dev, IT8512_REG_RCR, - IT8512_RCR_RXEN | IT8512_RCR_RXACT | CFG_DCR); - - spin_lock_irq(&dev->hardware_lock); - dev->device_busy = 0; - spin_unlock_irq(&dev->hardware_lock); - - tasklet_enable(&dev->tasklet); -} - -static void ite8709_drop_hardware(struct ite8709_device *dev) -{ - tasklet_disable(&dev->tasklet); - - spin_lock_irq(&dev->hardware_lock); - dev->device_busy = 1; - spin_unlock_irq(&dev->hardware_lock); - - ite8709_write_register(dev, IT8512_REG_RCR, 0); - ite8709_write_register(dev, IT8512_REG_MSTCR, - IT8512_MSTCR_RESET | IT8512_MSTCR_FIFOCLR); - - spin_lock_irq(&dev->hardware_lock); - dev->device_busy = 0; - spin_unlock_irq(&dev->hardware_lock); -} - -static int ite8709_set_use_inc(void *data) -{ - struct ite8709_device *dev; - MOD_INC_USE_COUNT; - dev = data; - if (dev->use_count == 0) - ite8709_init_hardware(dev); - dev->use_count++; - return 0; -} - -static void ite8709_set_use_dec(void *data) -{ - struct ite8709_device *dev; - MOD_DEC_USE_COUNT; - dev = data; - dev->use_count--; - if (dev->use_count == 0) - ite8709_drop_hardware(dev); -} - -static void ite8709_add_read_queue(struct ite8709_device *dev, int flag, - unsigned long long val) -{ - lirc_t value; - - dprintk("add a %llu usec %s\n", val, flag ? "pulse" : "space"); - - value = (val > PULSE_MASK) ? PULSE_MASK : val; - if (flag) - value |= PULSE_BIT; - - if (!lirc_buffer_full(&dev->buffer)) { - lirc_buffer_write(&dev->buffer, (void *) &value); - wake_up(&dev->buffer.wait_poll); - } -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -static irqreturn_t ite8709_interrupt(int irq, void *dev_id, - struct pt_regs *regs) -#else -static irqreturn_t ite8709_interrupt(int irq, void *dev_id) -#endif -{ - unsigned char data; - int iir, rfsr, i; - int fifo = 0; - char bit; - struct timeval curr_tv; - - /* Bit duration in microseconds */ - const unsigned long bit_duration = 1000000ul / (115200 / CFG_BDR); - - struct ite8709_device *dev; - dev = dev_id; - - /* - * If device is busy, we simply discard data because we are in one of - * these two cases : shutting down or rearming the device, so this - * doesn't really matter and this avoids waiting too long in IRQ ctx - */ - spin_lock(&dev->hardware_lock); - if (dev->device_busy) { - spin_unlock(&dev->hardware_lock); - return IRQ_RETVAL(IRQ_HANDLED); - } - - iir = ite8709_read(dev, ITE8709_IIR); - - switch (iir) { - case ITE8709_IIR_RFOI: - dprintk("fifo overrun, scheduling forced rearm just in case\n"); - dev->force_rearm = 1; - tasklet_schedule(&dev->tasklet); - spin_unlock(&dev->hardware_lock); - return IRQ_RETVAL(IRQ_HANDLED); - - case ITE8709_IIR_RDAI: - rfsr = ite8709_read(dev, ITE8709_RFSR); - fifo = rfsr & ITE8709_RFSR_MASK; - if (fifo > 32) - fifo = 32; - dprintk("iir: 0x%x rfsr: 0x%x fifo: %d\n", iir, rfsr, fifo); - - if (dev->rearmed) { - do_gettimeofday(&curr_tv); - dev->acc_space += 1000000ull - * (curr_tv.tv_sec - dev->last_tv.tv_sec) - + (curr_tv.tv_usec - dev->last_tv.tv_usec); - dev->rearmed = 0; - } - for (i = 0; i < fifo; i++) { - data = ite8709_read(dev, i+ITE8709_FIFO_START); - data = ~data; - /* Loop through */ - for (bit = 0; bit < 8; ++bit) { - if ((data >> bit) & 1) { - dev->acc_pulse += bit_duration; - if (dev->lastbit == 0) { - ite8709_add_read_queue(dev, 0, - dev->acc_space); - dev->acc_space = 0; - } - } else { - dev->acc_space += bit_duration; - if (dev->lastbit == 1) { - ite8709_add_read_queue(dev, 1, - dev->acc_pulse); - dev->acc_pulse = 0; - } - } - dev->lastbit = (data >> bit) & 1; - } - } - ite8709_write(dev, ITE8709_RFSR, 0); - - if (dev->acc_space > CFG_TIMEOUT) { - dprintk("scheduling rearm IRQ\n"); - do_gettimeofday(&dev->last_tv); - dev->force_rearm = 0; - tasklet_schedule(&dev->tasklet); - } - - spin_unlock(&dev->hardware_lock); - return IRQ_RETVAL(IRQ_HANDLED); - - default: - /* not our irq */ - dprintk("unknown IRQ (shouldn't happen) !!\n"); - spin_unlock(&dev->hardware_lock); - return IRQ_RETVAL(IRQ_NONE); - } -} - -static void ite8709_rearm_irq(unsigned long data) -{ - struct ite8709_device *dev; - unsigned long flags; - dev = (struct ite8709_device *) data; - - spin_lock_irqsave(&dev->hardware_lock, flags); - dev->device_busy = 1; - spin_unlock_irqrestore(&dev->hardware_lock, flags); - - if (dev->force_rearm || dev->acc_space > CFG_TIMEOUT) { - dprintk("rearming IRQ\n"); - ite8709_write_register(dev, IT8512_REG_RCR, - IT8512_RCR_RXACT | CFG_DCR); - ite8709_write_register(dev, IT8512_REG_MSTCR, - CFG_FIFOTL | IT8512_MSTCR_FIFOCLR); - ite8709_write_register(dev, IT8512_REG_RCR, - IT8512_RCR_RXEN | IT8512_RCR_RXACT | CFG_DCR); - if (!dev->force_rearm) - dev->rearmed = 1; - dev->force_rearm = 0; - } - - spin_lock_irqsave(&dev->hardware_lock, flags); - dev->device_busy = 0; - spin_unlock_irqrestore(&dev->hardware_lock, flags); -} - -static int ite8709_cleanup(struct ite8709_device *dev, int stage, int errno, - char *msg) -{ - if (msg != NULL) - printk(KERN_ERR LIRC_DRIVER_NAME ": %s\n", msg); - - switch (stage) { - case 6: - if (dev->use_count > 0) - ite8709_drop_hardware(dev); - case 5: - free_irq(dev->irq, dev); - case 4: - release_region(dev->io, 2); - case 3: - lirc_unregister_driver(dev->driver.minor); - case 2: - lirc_buffer_free(dev->driver.rbuf); - case 1: - kfree(dev); - case 0: - ; - } - - return errno; -} - -static int __devinit ite8709_pnp_probe(struct pnp_dev *dev, - const struct pnp_device_id *dev_id) -{ - struct lirc_driver *driver; - struct ite8709_device *ite8709_dev; - int ret; - - /* Check resources validity */ - if (!pnp_irq_valid(dev, 0)) - return ite8709_cleanup(NULL, 0, -ENODEV, "invalid IRQ"); - if (!pnp_port_valid(dev, 2)) - return ite8709_cleanup(NULL, 0, -ENODEV, "invalid IO port"); - - /* Allocate memory for device struct */ - ite8709_dev = kzalloc(sizeof(struct ite8709_device), GFP_KERNEL); - if (ite8709_dev == NULL) - return ite8709_cleanup(NULL, 0, -ENOMEM, "kzalloc failed"); - pnp_set_drvdata(dev, ite8709_dev); - - /* Initialize device struct */ - ite8709_dev->use_count = 0; - ite8709_dev->irq = pnp_irq(dev, 0); - ite8709_dev->io = pnp_port_start(dev, 2); - ite8709_dev->hardware_lock = __SPIN_LOCK_UNLOCKED( - ite8709_dev->hardware_lock); - ite8709_dev->acc_pulse = 0; - ite8709_dev->acc_space = 0; - ite8709_dev->lastbit = 0; - do_gettimeofday(&ite8709_dev->last_tv); - tasklet_init(&ite8709_dev->tasklet, ite8709_rearm_irq, - (long) ite8709_dev); - ite8709_dev->force_rearm = 0; - ite8709_dev->rearmed = 0; - ite8709_dev->device_busy = 0; - - /* Initialize driver struct */ - driver = &ite8709_dev->driver; - strcpy(driver->name, LIRC_DRIVER_NAME); - driver->minor = -1; - driver->code_length = sizeof(lirc_t) * 8; - driver->sample_rate = 0; - driver->features = LIRC_CAN_REC_MODE2; - driver->data = ite8709_dev; - driver->add_to_buf = NULL; -#ifndef LIRC_REMOVE_DURING_EXPORT - driver->get_queue = NULL; -#endif - driver->rbuf = &ite8709_dev->buffer; - driver->set_use_inc = ite8709_set_use_inc; - driver->set_use_dec = ite8709_set_use_dec; - driver->fops = NULL; - driver->dev = &dev->dev; - driver->owner = THIS_MODULE; - - /* Initialize LIRC buffer */ - if (lirc_buffer_init(driver->rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) - return ite8709_cleanup(ite8709_dev, 1, -ENOMEM, - "lirc_buffer_init() failed"); - - /* Register LIRC driver */ - ret = lirc_register_driver(driver); - if (ret < 0) - return ite8709_cleanup(ite8709_dev, 2, ret, - "lirc_register_driver() failed"); - - /* Reserve I/O port access */ - if (!request_region(ite8709_dev->io, 2, LIRC_DRIVER_NAME)) - return ite8709_cleanup(ite8709_dev, 3, -EBUSY, - "i/o port already in use"); - - /* Reserve IRQ line */ - ret = request_irq(ite8709_dev->irq, ite8709_interrupt, 0, - LIRC_DRIVER_NAME, ite8709_dev); - if (ret < 0) - return ite8709_cleanup(ite8709_dev, 4, ret, - "IRQ already in use"); - - /* Initialize hardware */ - ite8709_drop_hardware(ite8709_dev); /* Shutdown hw until first use */ - - printk(KERN_INFO LIRC_DRIVER_NAME ": device found : irq=%d io=0x%x\n", - ite8709_dev->irq, ite8709_dev->io); - - return 0; -} - -static void __devexit ite8709_pnp_remove(struct pnp_dev *dev) -{ - struct ite8709_device *ite8709_dev; - ite8709_dev = pnp_get_drvdata(dev); - - ite8709_cleanup(ite8709_dev, 6, 0, NULL); - - printk(KERN_INFO LIRC_DRIVER_NAME ": device removed\n"); -} - -#ifdef CONFIG_PM -static int ite8709_pnp_suspend(struct pnp_dev *dev, pm_message_t state) -{ - struct ite8709_device *ite8709_dev; - ite8709_dev = pnp_get_drvdata(dev); - - if (ite8709_dev->use_count > 0) - ite8709_drop_hardware(ite8709_dev); - - return 0; -} - -static int ite8709_pnp_resume(struct pnp_dev *dev) -{ - struct ite8709_device *ite8709_dev; - ite8709_dev = pnp_get_drvdata(dev); - - if (ite8709_dev->use_count > 0) - ite8709_init_hardware(ite8709_dev); - - return 0; -} -#else -#define ite8709_pnp_suspend NULL -#define ite8709_pnp_resume NULL -#endif - -static const struct pnp_device_id pnp_dev_table[] = { - {"ITE8709", 0}, - {} -}; - -MODULE_DEVICE_TABLE(pnp, pnp_dev_table); - -static struct pnp_driver ite8709_pnp_driver = { - .name = LIRC_DRIVER_NAME, - .probe = ite8709_pnp_probe, - .remove = __devexit_p(ite8709_pnp_remove), - .suspend = ite8709_pnp_suspend, - .resume = ite8709_pnp_resume, - .id_table = pnp_dev_table, -}; - -int init_module(void) -{ - return pnp_register_driver(&ite8709_pnp_driver); -} - -void cleanup_module(void) -{ - pnp_unregister_driver(&ite8709_pnp_driver); -} - -MODULE_DESCRIPTION("LIRC driver for ITE8709 CIR port"); -MODULE_AUTHOR("Grégory Lardière"); -MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Enable debugging messages"); -EXPORT_NO_SYMBOLS; diff --git a/ubuntu/lirc/lirc_mceusb/Makefile b/ubuntu/lirc/lirc_mceusb/Makefile deleted file mode 100644 index 4ea43b471fb..00000000000 --- a/ubuntu/lirc/lirc_mceusb/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. - -obj-$(CONFIG_LIRC_MCEUSB) += lirc_mceusb.o diff --git a/ubuntu/lirc/lirc_mceusb/lirc_mceusb.c b/ubuntu/lirc/lirc_mceusb/lirc_mceusb.c deleted file mode 100644 index 4813b31fb30..00000000000 --- a/ubuntu/lirc/lirc_mceusb/lirc_mceusb.c +++ /dev/null @@ -1,1288 +0,0 @@ -/* - * LIRC driver for Windows Media Center Edition USB Infrared Transceivers - * - * (C) by Martin A. Blatter <martin_a_blatter@yahoo.com> - * - * Transmitter support and reception code cleanup. - * (C) by Daniel Melander <lirc@rajidae.se> - * - * Original lirc_mceusb driver for 1st-gen device: - * Copyright (c) 2003-2004 Dan Conti <dconti@acm.wwu.edu> - * - * Original lirc_mceusb driver deprecated in favor of this driver, which - * supports the 1st-gen device now too. Transmitting on the 1st-gen device - * only functions on port #2 at the moment. - * - * Support for 1st-gen device added June 2009, - * by Jarod Wilson <jarod@wilsonet.com> - * - * Initial transmission support for 1st-gen device added August 2009, - * by Patrick Calhoun <phineas@ou.edu> - * - * Derived from ATI USB driver by Paul Miller and the original - * MCE USB driver by Dan Conti ((and now including chunks of the latter - * relevant to the 1st-gen device initialization) - * - * This driver will only work reliably with kernel version 2.6.10 - * or higher, probably because of differences in USB device enumeration - * in the kernel code. Device initialization fails most of the time - * with earlier kernel versions. - * - ********************************************************************** - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/version.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 5) -#error "*******************************************************" -#error "Sorry, this driver needs kernel version 2.6.5 or higher" -#error "*******************************************************" -#endif -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/kmod.h> -#include <linux/smp_lock.h> -#include <linux/completion.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) -#include <asm/uaccess.h> -#else -#include <linux/uaccess.h> -#endif -#include <linux/usb.h> -#include <linux/wait.h> -#include <linux/time.h> - -#include "../lirc.h" -#include "../kcompat.h" -#include "../lirc_dev/lirc_dev.h" - -#define DRIVER_VERSION "1.90" -#define DRIVER_AUTHOR "Daniel Melander <lirc@rajidae.se>, " \ - "Martin Blatter <martin_a_blatter@yahoo.com>, " \ - "Dan Conti <dconti@acm.wwu.edu>" -#define DRIVER_DESC "Windows Media Center Edition USB IR Transceiver " \ - "driver for LIRC" -#define DRIVER_NAME "lirc_mceusb" - -#define USB_BUFLEN 32 /* USB reception buffer length */ -#define LIRCBUF_SIZE 256 /* LIRC work buffer length */ - -/* MCE constants */ -#define MCE_CMDBUF_SIZE 384 /* MCE Command buffer length */ -#define MCE_TIME_UNIT 50 /* Approx 50us resolution */ -#define MCE_CODE_LENGTH 5 /* Normal length of packet (with header) */ -#define MCE_PACKET_SIZE 4 /* Normal length of packet (without header) */ -#define MCE_PACKET_HEADER 0x84 /* Actual header format is 0x80 + num_bytes */ -#define MCE_CONTROL_HEADER 0x9F /* MCE status header */ -#define MCE_TX_HEADER_LENGTH 3 /* # of bytes in the initializing tx header */ -#define MCE_MAX_CHANNELS 2 /* Two transmitters, hardware dependent? */ -#define MCE_DEFAULT_TX_MASK 0x03 /* Val opts: TX1=0x01, TX2=0x02, ALL=0x03 */ -#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 */ - - -/* module parameters */ -#ifdef CONFIG_USB_DEBUG -static int debug = 1; -#else -static int debug; -#endif -#define dprintk(fmt, args...) \ - do { \ - if (debug) \ - printk(KERN_DEBUG fmt, ## args); \ - } while (0) - -/* general constants */ -#define SEND_FLAG_IN_PROGRESS 1 -#define SEND_FLAG_COMPLETE 2 -#define RECV_FLAG_IN_PROGRESS 3 -#define RECV_FLAG_COMPLETE 4 - -#define MCEUSB_INBOUND 1 -#define MCEUSB_OUTBOUND 2 - -#define VENDOR_PHILIPS 0x0471 -#define VENDOR_SMK 0x0609 -#define VENDOR_TATUNG 0x1460 -#define VENDOR_GATEWAY 0x107b -#define VENDOR_SHUTTLE 0x1308 -#define VENDOR_SHUTTLE2 0x051c -#define VENDOR_MITSUMI 0x03ee -#define VENDOR_TOPSEED 0x1784 -#define VENDOR_RICAVISION 0x179d -#define VENDOR_ITRON 0x195d -#define VENDOR_FIC 0x1509 -#define VENDOR_LG 0x043e -#define VENDOR_MICROSOFT 0x045e -#define VENDOR_FORMOSA 0x147a -#define VENDOR_FINTEK 0x1934 -#define VENDOR_PINNACLE 0x2304 -#define VENDOR_ECS 0x1019 -#define VENDOR_WISTRON 0x0fb8 -#define VENDOR_COMPRO 0x185b -#define VENDOR_NORTHSTAR 0x04eb - -static struct usb_device_id mceusb_dev_table[] = { - /* Original Microsoft MCE IR Transceiver (often HP-branded) */ - { USB_DEVICE(VENDOR_MICROSOFT, 0x006d) }, - /* Philips Infrared Transceiver - Sahara branded */ - { USB_DEVICE(VENDOR_PHILIPS, 0x0608) }, - /* Philips Infrared Transceiver - HP branded */ - { USB_DEVICE(VENDOR_PHILIPS, 0x060c) }, - /* Philips SRM5100 */ - { USB_DEVICE(VENDOR_PHILIPS, 0x060d) }, - /* Philips Infrared Transceiver - Omaura */ - { USB_DEVICE(VENDOR_PHILIPS, 0x060f) }, - /* Philips Infrared Transceiver - Spinel plus */ - { USB_DEVICE(VENDOR_PHILIPS, 0x0613) }, - /* Philips eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_PHILIPS, 0x0815) }, - /* SMK/Toshiba G83C0004D410 */ - { USB_DEVICE(VENDOR_SMK, 0x031d) }, - /* SMK eHome Infrared Transceiver (Sony VAIO) */ - { USB_DEVICE(VENDOR_SMK, 0x0322) }, - /* bundled with Hauppauge PVR-150 */ - { USB_DEVICE(VENDOR_SMK, 0x0334) }, - /* Tatung eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_TATUNG, 0x9150) }, - /* Shuttle eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_SHUTTLE, 0xc001) }, - /* Shuttle eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_SHUTTLE2, 0xc001) }, - /* Gateway eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_GATEWAY, 0x3009) }, - /* Mitsumi */ - { USB_DEVICE(VENDOR_MITSUMI, 0x2501) }, - /* Topseed eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_TOPSEED, 0x0001) }, - /* Topseed HP eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_TOPSEED, 0x0006) }, - /* Topseed eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_TOPSEED, 0x0007) }, - /* Topseed eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_TOPSEED, 0x0008) }, - /* Topseed eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_TOPSEED, 0x000a) }, - /* Ricavision internal Infrared Transceiver */ - { USB_DEVICE(VENDOR_RICAVISION, 0x0010) }, - /* Itron ione Libra Q-11 */ - { USB_DEVICE(VENDOR_ITRON, 0x7002) }, - /* FIC eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_FIC, 0x9242) }, - /* LG eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_LG, 0x9803) }, - /* Microsoft MCE Infrared Transceiver */ - { USB_DEVICE(VENDOR_MICROSOFT, 0x00a0) }, - /* Formosa eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_FORMOSA, 0xe015) }, - /* Formosa21 / eHome Infrared Receiver */ - { USB_DEVICE(VENDOR_FORMOSA, 0xe016) }, - /* Formosa aim / Trust MCE Infrared Receiver */ - { USB_DEVICE(VENDOR_FORMOSA, 0xe017) }, - /* Formosa Industrial Computing / Beanbag Emulation Device */ - { USB_DEVICE(VENDOR_FORMOSA, 0xe018) }, - /* Formosa21 / eHome Infrared Receiver */ - { USB_DEVICE(VENDOR_FORMOSA, 0xe03a) }, - /* Formosa Industrial Computing AIM IR605/A */ - { USB_DEVICE(VENDOR_FORMOSA, 0xe03c) }, - /* Fintek eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_FINTEK, 0x0602) }, - /* Fintek eHome Infrared Transceiver (in the AOpen MP45) */ - { USB_DEVICE(VENDOR_FINTEK, 0x0702) }, - /* Pinnacle Remote Kit */ - { USB_DEVICE(VENDOR_PINNACLE, 0x0225) }, - /* Elitegroup Computer Systems IR */ - { USB_DEVICE(VENDOR_ECS, 0x0f38) }, - /* Wistron Corp. eHome Infrared Receiver */ - { USB_DEVICE(VENDOR_WISTRON, 0x0002) }, - /* Compro K100 */ - { USB_DEVICE(VENDOR_COMPRO, 0x3020) }, - /* Compro K100 v2 */ - { USB_DEVICE(VENDOR_COMPRO, 0x3082) }, - /* Northstar Systems eHome Infrared Transceiver */ - { USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) }, - /* Terminating entry */ - { } -}; - -static struct usb_device_id pinnacle_list[] = { - { USB_DEVICE(VENDOR_PINNACLE, 0x0225) }, - {} -}; - -static struct usb_device_id microsoft_gen1_list[] = { - { USB_DEVICE(VENDOR_MICROSOFT, 0x006d) }, - {} -}; - -static struct usb_device_id transmitter_mask_list[] = { - { USB_DEVICE(VENDOR_SMK, 0x031d) }, - { USB_DEVICE(VENDOR_SMK, 0x0322) }, - { USB_DEVICE(VENDOR_SMK, 0x0334) }, - { USB_DEVICE(VENDOR_TOPSEED, 0x0001) }, - { USB_DEVICE(VENDOR_TOPSEED, 0x0006) }, - { USB_DEVICE(VENDOR_TOPSEED, 0x0007) }, - { USB_DEVICE(VENDOR_TOPSEED, 0x0008) }, - { USB_DEVICE(VENDOR_TOPSEED, 0x000a) }, - { USB_DEVICE(VENDOR_PINNACLE, 0x0225) }, - {} -}; - -/* data structure for each usb transceiver */ -struct mceusb_dev { - - /* usb */ - struct usb_device *usbdev; - struct urb *urb_in; - int devnum; - struct usb_endpoint_descriptor *usb_ep_in; - struct usb_endpoint_descriptor *usb_ep_out; - - /* buffers and dma */ - unsigned char *buf_in; - unsigned int len_in; - dma_addr_t dma_in; - dma_addr_t dma_out; - unsigned int overflow_len; - - /* lirc */ - struct lirc_driver *d; - lirc_t lircdata; - unsigned char is_pulse; - struct { - u32 connected:1; - u32 pinnacle:1; - u32 transmitter_mask_inverted:1; - u32 microsoft_gen1:1; - u32 reserved:28; - } flags; - - unsigned char transmitter_mask; - unsigned int carrier_freq; - - /* handle sending (init strings) */ - int send_flags; - wait_queue_head_t wait_out; - - struct mutex 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}; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) -static unsigned long usecs_to_jiffies(const unsigned int u) -{ - if (u > jiffies_to_usecs(MAX_JIFFY_OFFSET)) - return MAX_JIFFY_OFFSET; -#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ) - return (u + (USEC_PER_SEC / HZ) - 1) / (USEC_PER_SEC / HZ); -#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC) - return u * (HZ / USEC_PER_SEC); -#else - return (u * HZ + USEC_PER_SEC - 1) / USEC_PER_SEC; -#endif -} -#endif -static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, int len) -{ - char codes[USB_BUFLEN * 3 + 1]; - int i; - - if (len <= 0) - return; - - if (ir->flags.microsoft_gen1 && len <= 2) - 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); -} - -static void usb_async_callback(struct urb *urb, struct pt_regs *regs) -{ - struct mceusb_dev *ir; - int len; - - if (!urb) - return; - - ir = urb->context; - if (ir) { - len = urb->actual_length; - - dprintk(DRIVER_NAME - "[%d]: callback called (status=%d len=%d)\n", - ir->devnum, urb->status, len); - - if (debug) - mceusb_dev_printdata(ir, urb->transfer_buffer, len); - } - -} - -/* 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) -{ - int res; - struct urb *async_urb; - unsigned char *async_buf; - - if (urb_type) { - async_urb = usb_alloc_urb(0, GFP_KERNEL); - if (unlikely(!async_urb)) - return; - - async_buf = kmalloc(size, GFP_KERNEL); - if (!async_buf) { - 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 { - /* standard request */ - async_urb = ir->urb_in; - ir->send_flags = RECV_FLAG_IN_PROGRESS; - } - - dprintk(DRIVER_NAME "[%d]: receive request called (size=%#x)\n", - ir->devnum, size); - - async_urb->transfer_buffer_length = size; - async_urb->dev = ir->usbdev; - - res = usb_submit_urb(async_urb, GFP_ATOMIC); - if (res) { - dprintk(DRIVER_NAME "[%d]: receive request FAILED! (res=%d)\n", - ir->devnum, res); - return; - } - dprintk(DRIVER_NAME "[%d]: receive request complete (res=%d)\n", - ir->devnum, res); -} - -static int unregister_from_lirc(struct mceusb_dev *ir) -{ - struct lirc_driver *d = ir->d; - int devnum; - int rtn; - - devnum = ir->devnum; - dprintk(DRIVER_NAME "[%d]: unregister from lirc called\n", devnum); - - rtn = lirc_unregister_driver(d->minor); - if (rtn > 0) { - printk(DRIVER_NAME "[%d]: error in lirc_unregister minor: %d\n" - "Trying again...\n", devnum, d->minor); - if (rtn == -EBUSY) { - printk(DRIVER_NAME - "[%d]: device is opened, will unregister" - " on close\n", devnum); - return -EAGAIN; - } - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); - - rtn = lirc_unregister_driver(d->minor); - if (rtn > 0) - printk(DRIVER_NAME "[%d]: lirc_unregister failed\n", - devnum); - } - - if (rtn) { - printk(DRIVER_NAME "[%d]: didn't free resources\n", devnum); - return -EAGAIN; - } - - printk(DRIVER_NAME "[%d]: usb remote disconnected\n", devnum); - - lirc_buffer_free(d->rbuf); - kfree(d->rbuf); - kfree(d); - kfree(ir); - return 0; -} - -static int mceusb_ir_open(void *data) -{ - struct mceusb_dev *ir = data; - - if (!ir) { - printk(DRIVER_NAME "[?]: %s called with no context\n", - __func__); - return -EIO; - } - dprintk(DRIVER_NAME "[%d]: mceusb IR device opened\n", ir->devnum); - - MOD_INC_USE_COUNT; - if (!ir->flags.connected) { - if (!ir->usbdev) - return -ENOENT; - ir->flags.connected = 1; - } - - return 0; -} - -static void mceusb_ir_close(void *data) -{ - struct mceusb_dev *ir = data; - - if (!ir) { - printk(DRIVER_NAME "[?]: %s called with no context\n", - __func__); - return; - } - dprintk(DRIVER_NAME "[%d]: mceusb IR device closed\n", ir->devnum); - - if (ir->flags.connected) { - mutex_lock(&ir->lock); - ir->flags.connected = 0; - mutex_unlock(&ir->lock); - } - MOD_DEC_USE_COUNT; -} - -static void send_packet_to_lirc(struct mceusb_dev *ir) -{ - if (ir->lircdata) { - lirc_buffer_write(ir->d->rbuf, - (unsigned char *) &ir->lircdata); - wake_up(&ir->d->rbuf->wait_poll); - ir->lircdata = 0; - } -} - -static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len) -{ - int i, j; - int packet_len = 0; - int start_index = 0; - - /* skip meaningless 0xb1 0x60 header bytes on orig receiver */ - if (ir->flags.microsoft_gen1) - start_index = 2; - - /* this should only trigger w/the 1st-gen mce receiver */ - for (i = start_index; i < (start_index + ir->overflow_len) && - i < buf_len; i++) { - /* rising/falling flank */ - if (ir->is_pulse != (ir->buf_in[i] & MCE_PULSE_BIT)) { - send_packet_to_lirc(ir); - ir->is_pulse = ir->buf_in[i] & MCE_PULSE_BIT; - } - - /* accumulate mce pulse/space values */ - ir->lircdata += (ir->buf_in[i] & MCE_PULSE_MASK) * - MCE_TIME_UNIT; - ir->lircdata |= (ir->is_pulse ? PULSE_BIT : 0); - } - start_index += ir->overflow_len; - ir->overflow_len = 0; - - for (i = start_index; i < buf_len; i++) { - /* decode mce packets of the form (84),AA,BB,CC,DD */ - if (ir->buf_in[i] >= 0x80 && ir->buf_in[i] <= 0x9e) { - /* data headers */ - /* decode packet data */ - packet_len = ir->buf_in[i] & MCE_PACKET_LENGTH_MASK; - ir->overflow_len = i + 1 + packet_len - buf_len; - for (j = 1; j <= packet_len && (i + j < buf_len); j++) { - /* rising/falling flank */ - if (ir->is_pulse != - (ir->buf_in[i + j] & MCE_PULSE_BIT)) { - send_packet_to_lirc(ir); - ir->is_pulse = - ir->buf_in[i + j] & - MCE_PULSE_BIT; - } - - /* accumulate mce pulse/space values */ - ir->lircdata += - (ir->buf_in[i + j] & MCE_PULSE_MASK) * - MCE_TIME_UNIT; - ir->lircdata |= (ir->is_pulse ? PULSE_BIT : 0); - } - - i += packet_len; - } else if (ir->buf_in[i] == MCE_CONTROL_HEADER) { - /* status header (0x9F) */ - /* - * A transmission containing one or more consecutive ir - * commands always ends with a GAP of 100ms followed by - * the sequence 0x9F 0x01 0x01 0x9F 0x15 0x00 0x00 0x80 - */ - -#if 0 - Uncomment this if the last 100ms "infinity"-space should be transmitted - to lirc directly instead of at the beginning of the next transmission. - Changes pulse/space order. - - if (++i < buf_len && ir->buf_in[i]==0x01) - send_packet_to_lirc(ir); - -#endif - - /* end decode loop */ - dprintk(DRIVER_NAME "[%d] %s: found control header\n", - ir->devnum, __func__); - ir->overflow_len = 0; - break; - } else { - dprintk(DRIVER_NAME "[%d] %s: stray packet?\n", - ir->devnum, __func__); - ir->overflow_len = 0; - } - } - - return; -} - -static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs) -{ - struct mceusb_dev *ir; - int buf_len; - - if (!urb) - return; - - ir = urb->context; - if (!ir) { - urb->transfer_flags |= URB_ASYNC_UNLINK; - usb_unlink_urb(urb); - return; - } - - buf_len = urb->actual_length; - - if (debug) - mceusb_dev_printdata(ir, urb->transfer_buffer, buf_len); - - if (ir->send_flags == RECV_FLAG_IN_PROGRESS) { - ir->send_flags = SEND_FLAG_COMPLETE; - dprintk(DRIVER_NAME "[%d]: setup answer received %d bytes\n", - ir->devnum, buf_len); - } - - switch (urb->status) { - /* success */ - case 0: - mceusb_process_ir_data(ir, buf_len); - break; - - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - urb->transfer_flags |= URB_ASYNC_UNLINK; - usb_unlink_urb(urb); - return; - - case -EPIPE: - default: - break; - } - - usb_submit_urb(urb, GFP_ATOMIC); -} - - -static ssize_t mceusb_transmit_ir(struct file *file, const char *buf, - size_t n, loff_t *ppos) -{ - int i, count = 0, cmdcount = 0; - struct mceusb_dev *ir = NULL; - lirc_t wbuf[LIRCBUF_SIZE]; /* Workbuffer with values from lirc */ - unsigned char cmdbuf[MCE_CMDBUF_SIZE]; /* MCE command buffer */ - unsigned long signal_duration = 0; /* Singnal length in us */ - struct timeval start_time, end_time; - - do_gettimeofday(&start_time); - - /* Retrieve lirc_driver data for the device */ - ir = lirc_get_pdata(file); - if (!ir || !ir->usb_ep_out) - return -EFAULT; - - if (n % sizeof(lirc_t)) - return -EINVAL; - count = n / sizeof(lirc_t); - - /* Check if command is within limits */ - if (count > LIRCBUF_SIZE || count%2 == 0) - return -EINVAL; - if (copy_from_user(wbuf, buf, n)) - return -EFAULT; - - /* MCE tx init header */ - cmdbuf[cmdcount++] = MCE_CONTROL_HEADER; - cmdbuf[cmdcount++] = 0x08; - cmdbuf[cmdcount++] = ir->transmitter_mask; - - /* Generate mce packet data */ - for (i = 0; (i < count) && (cmdcount < MCE_CMDBUF_SIZE); i++) { - signal_duration += wbuf[i]; - wbuf[i] = wbuf[i] / MCE_TIME_UNIT; - - do { /* loop to support long pulses/spaces > 127*50us=6.35ms */ - - /* Insert mce packet header every 4th entry */ - if ((cmdcount < MCE_CMDBUF_SIZE) && - (cmdcount - MCE_TX_HEADER_LENGTH) % - MCE_CODE_LENGTH == 0) - cmdbuf[cmdcount++] = MCE_PACKET_HEADER; - - /* Insert mce packet data */ - if (cmdcount < MCE_CMDBUF_SIZE) - cmdbuf[cmdcount++] = - (wbuf[i] < MCE_PULSE_BIT ? - wbuf[i] : MCE_MAX_PULSE_LENGTH) | - (i & 1 ? 0x00 : MCE_PULSE_BIT); - else - return -EINVAL; - } while ((wbuf[i] > MCE_MAX_PULSE_LENGTH) && - (wbuf[i] -= MCE_MAX_PULSE_LENGTH)); - } - - /* Fix packet length in last header */ - cmdbuf[cmdcount - (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH] = - 0x80 + (cmdcount - MCE_TX_HEADER_LENGTH) % MCE_CODE_LENGTH - 1; - - /* Check if we have room for the empty packet at the end */ - if (cmdcount >= MCE_CMDBUF_SIZE) - return -EINVAL; - - /* All mce commands end with an empty packet (0x80) */ - cmdbuf[cmdcount++] = 0x80; - - /* Transmit the command to the mce device */ - request_packet_async(ir, ir->usb_ep_out, cmdbuf, - cmdcount, MCEUSB_OUTBOUND); - - /* - * The lircd gap calculation expects the write function to - * wait the time it takes for the ircommand to be sent before - * it returns. - */ - do_gettimeofday(&end_time); - signal_duration -= (end_time.tv_usec - start_time.tv_usec) + - (end_time.tv_sec - start_time.tv_sec) * 1000000; - - /* delay with the closest number of ticks */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(usecs_to_jiffies(signal_duration)); - - return n; -} - -static void set_transmitter_mask(struct mceusb_dev *ir, unsigned int mask) -{ - if (ir->flags.transmitter_mask_inverted) - /* - * The mask begins at 0x02 and has an inverted - * numbering scheme - */ - ir->transmitter_mask = - (mask != 0x03 ? mask ^ 0x03 : mask) << 1; - else - ir->transmitter_mask = mask; -} - - -/* Sets the send carrier frequency */ -static int set_send_carrier(struct mceusb_dev *ir, int carrier) -{ - int clk = 10000000; - int prescaler = 0, divisor = 0; - unsigned char cmdbuf[] = { 0x9F, 0x06, 0x01, 0x80 }; - - /* Carrier is changed */ - if (ir->carrier_freq != carrier) { - - if (carrier <= 0) { - 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); - return carrier; - } - - for (prescaler = 0; prescaler < 4; ++prescaler) { - divisor = (clk >> (2 * prescaler)) / carrier; - if (divisor <= 0xFF) { - ir->carrier_freq = carrier; - cmdbuf[2] = prescaler; - cmdbuf[3] = divisor; - dprintk(DRIVER_NAME "[%d]: SET_CARRIER " - "requesting %d Hz\n", - ir->devnum, carrier); - - /* Transmit new carrier to mce device */ - request_packet_async(ir, ir->usb_ep_out, - cmdbuf, sizeof(cmdbuf), - MCEUSB_OUTBOUND); - return carrier; - } - } - - return -EINVAL; - - } - - return carrier; -} - - -static int mceusb_lirc_ioctl(struct inode *node, struct file *filep, - unsigned int cmd, unsigned long arg) -{ - int result; - unsigned int ivalue; - unsigned long lvalue; - struct mceusb_dev *ir = NULL; - - /* Retrieve lirc_driver data for the device */ - ir = lirc_get_pdata(filep); - if (!ir || !ir->usb_ep_out) - return -EFAULT; - - - switch (cmd) { - case LIRC_SET_TRANSMITTER_MASK: - - result = get_user(ivalue, (unsigned int *) arg); - if (result) - return result; - switch (ivalue) { - case 0x01: /* Transmitter 1 => 0x04 */ - case 0x02: /* Transmitter 2 => 0x02 */ - case 0x03: /* Transmitter 1 & 2 => 0x06 */ - set_transmitter_mask(ir, ivalue); - break; - - default: /* Unsupported transmitter mask */ - return MCE_MAX_CHANNELS; - } - - 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); - if (result) - return result; - - set_send_carrier(ir, ivalue); - break; - - default: - return -ENOIOCTLCMD; - } - - return 0; -} - -static struct file_operations lirc_fops = { - .owner = THIS_MODULE, - .write = mceusb_transmit_ir, - .ioctl = mceusb_lirc_ioctl, -}; - -static int 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]); - - /* - * 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); - dprintk("%s - ret = %d, devnum = %d\n", - __func__, ret, ir->usbdev->devnum); - dprintk("%s - data[0] = %d, data[1] = %d\n", - __func__, data[0], data[1]); - - /* set feature */ - ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), - USB_REQ_SET_FEATURE, USB_TYPE_VENDOR, - 0xc04e, 0x0000, NULL, 0, HZ * 3); - - dprintk("%s - ret = %d\n", __func__, ret); - - /* strange: bRequest == 4 */ - ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), - 4, USB_TYPE_VENDOR, - 0x0808, 0x0000, NULL, 0, HZ * 3); - dprintk("%s - retB = %d\n", __func__, ret); - - /* strange: bRequest == 2 */ - ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), - 2, USB_TYPE_VENDOR, - 0x0000, 0x0100, NULL, 0, HZ * 3); - dprintk("%s - retC = %d\n", __func__, ret); - - return ret; - -}; - -static int 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; - struct usb_endpoint_descriptor *ep = NULL; - struct usb_endpoint_descriptor *ep_in = NULL; - struct usb_endpoint_descriptor *ep_out = NULL; - struct usb_host_config *config; - struct mceusb_dev *ir = NULL; - struct lirc_driver *driver = NULL; - struct lirc_buffer *rbuf = NULL; - int devnum, pipe, maxp; - int minor = 0; - int i; - char buf[63], name[128] = ""; - int mem_failure = 0; - int is_pinnacle; - int 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_microsoft_gen1 = usb_match_id(intf, microsoft_gen1_list) ? 1 : 0; - - /* step through the endpoints to find first bulk in and out endpoint */ - for (i = 0; i < idesc->desc.bNumEndpoints; ++i) { - ep = &idesc->endpoint[i].desc; - - if ((ep_in == NULL) - && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) - == USB_DIR_IN) - && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_BULK) - || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_INT))) { - - dprintk(DRIVER_NAME ": acceptable inbound endpoint " - "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; - } - - if ((ep_out == NULL) - && ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) - == USB_DIR_OUT) - && (((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_BULK) - || ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_INT))) { - - dprintk(DRIVER_NAME ": acceptable outbound endpoint " - "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; - } - } - if (ep_in == NULL || ep_out == NULL) { - dprintk(DRIVER_NAME ": inbound and/or " - "outbound endpoint not found\n"); - return -ENODEV; - } - - devnum = dev->devnum; - pipe = usb_rcvintpipe(dev, ep_in->bEndpointAddress); - maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - - mem_failure = 0; - ir = kzalloc(sizeof(struct mceusb_dev), GFP_KERNEL); - if (!ir) { - mem_failure = 1; - goto mem_failure_switch; - } - - driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); - if (!driver) { - mem_failure = 2; - goto mem_failure_switch; - } - - 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_alloc_coherent(dev, maxp, GFP_ATOMIC, &ir->dma_in); - if (!ir->buf_in) { - mem_failure = 5; - goto mem_failure_switch; - } - - ir->urb_in = usb_alloc_urb(0, GFP_KERNEL); - if (!ir->urb_in) { - mem_failure = 7; - goto mem_failure_switch; - } - - strcpy(driver->name, DRIVER_NAME " "); - driver->minor = -1; - driver->features = LIRC_CAN_SEND_PULSE | - LIRC_CAN_SET_TRANSMITTER_MASK | - LIRC_CAN_REC_MODE2 | - LIRC_CAN_SET_SEND_CARRIER; - driver->data = ir; - driver->rbuf = rbuf; - driver->set_use_inc = &mceusb_ir_open; - driver->set_use_dec = &mceusb_ir_close; - driver->code_length = sizeof(lirc_t) * 8; - driver->fops = &lirc_fops; - driver->dev = &intf->dev; - driver->owner = THIS_MODULE; - - mutex_init(&ir->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_free_coherent(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; - } - - driver->minor = minor; - ir->d = driver; - ir->devnum = devnum; - ir->usbdev = dev; - 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; - - 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; - - if (dev->descriptor.iManufacturer - && usb_string(dev, dev->descriptor.iManufacturer, - buf, sizeof(buf)) > 0) - strlcpy(name, buf, sizeof(name)); - if (dev->descriptor.iProduct - && usb_string(dev, dev->descriptor.iProduct, - buf, sizeof(buf)) > 0) - snprintf(name + strlen(name), sizeof(name) - strlen(name), - " %s", buf); - printk(DRIVER_NAME "[%d]: %s on usb%d:%d\n", devnum, name, - dev->bus->busnum, devnum); - - /* inbound data */ - 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 */ - mceusb_gen1_init(ir); - } else { - - 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); - } - - /* - * 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); - - usb_set_intfdata(intf, ir); - - return 0; -} - - -static void mceusb_dev_disconnect(struct usb_interface *intf) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct mceusb_dev *ir = usb_get_intfdata(intf); - - usb_set_intfdata(intf, NULL); - - if (!ir || !ir->d) - return; - - ir->usbdev = NULL; - wake_up_all(&ir->wait_out); - - mutex_lock(&ir->lock); - usb_kill_urb(ir->urb_in); - usb_free_urb(ir->urb_in); - usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in); - mutex_unlock(&ir->lock); - - unregister_from_lirc(ir); -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) -static int mceusb_dev_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct mceusb_dev *ir = usb_get_intfdata(intf); - printk(DRIVER_NAME "[%d]: suspend\n", ir->devnum); - usb_kill_urb(ir->urb_in); - return 0; -} - -static int mceusb_dev_resume(struct usb_interface *intf) -{ - struct mceusb_dev *ir = usb_get_intfdata(intf); - printk(DRIVER_NAME "[%d]: resume\n", ir->devnum); - if (usb_submit_urb(ir->urb_in, GFP_ATOMIC)) - return -EIO; - return 0; -} -#endif - -static struct usb_driver mceusb_dev_driver = { - LIRC_THIS_MODULE(.owner = THIS_MODULE) - .name = DRIVER_NAME, - .probe = mceusb_dev_probe, - .disconnect = mceusb_dev_disconnect, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) - .suspend = mceusb_dev_suspend, - .resume = mceusb_dev_resume, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) - .reset_resume = mceusb_dev_resume, -#endif -#endif - .id_table = mceusb_dev_table -}; - -static int __init mceusb_dev_init(void) -{ - int i; - - printk(KERN_INFO DRIVER_NAME ": " DRIVER_DESC " " DRIVER_VERSION "\n"); - printk(KERN_INFO DRIVER_NAME ": " DRIVER_AUTHOR "\n"); - dprintk(DRIVER_NAME ": debug mode enabled\n"); - - i = usb_register(&mceusb_dev_driver); - if (i < 0) { - printk(DRIVER_NAME ": usb register failed, result = %d\n", i); - return -ENODEV; - } - - return 0; -} - -static void __exit mceusb_dev_exit(void) -{ - usb_deregister(&mceusb_dev_driver); -} - -module_init(mceusb_dev_init); -module_exit(mceusb_dev_exit); - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(usb, mceusb_dev_table); -/* this was originally lirc_mceusb2, lirc_mceusb and lirc_mceusb2 merged now */ -MODULE_ALIAS("lirc_mceusb2"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); - -EXPORT_NO_SYMBOLS; diff --git a/ubuntu/lirc/lirc_parallel/Makefile b/ubuntu/lirc/lirc_parallel/Makefile deleted file mode 100644 index 6304d6f44b9..00000000000 --- a/ubuntu/lirc/lirc_parallel/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. - -obj-$(CONFIG_LIRC_PARALLEL) += lirc_parallel.o diff --git a/ubuntu/lirc/lirc_parallel/lirc_parallel.c b/ubuntu/lirc/lirc_parallel/lirc_parallel.c deleted file mode 100644 index 59d0a591386..00000000000 --- a/ubuntu/lirc/lirc_parallel/lirc_parallel.c +++ /dev/null @@ -1,762 +0,0 @@ -/* $Id: lirc_parallel.c,v 5.53 2009/03/08 19:22:28 lirc Exp $ */ -/* - * lirc_parallel.c - * - * lirc_parallel - device driver for infra-red signal receiving and - * transmitting unit built by the author - * - * Copyright (C) 1998 Christoph Bartelmus <lirc@bartelmus.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/*** Includes ***/ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#include <linux/version.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18) -#error "**********************************************************" -#error " Sorry, this driver needs kernel version 2.2.18 or higher " -#error "**********************************************************" -#endif - -#ifdef CONFIG_SMP -#error "--- Sorry, this driver is not SMP safe. ---" -#endif - -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/signal.h> -#include <linux/fs.h> -#include <linux/kernel.h> -#include <linux/ioport.h> -#include <linux/time.h> -#include <linux/mm.h> -#include <linux/delay.h> - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) -#include <asm/io.h> -#include <asm/signal.h> -#include <asm/irq.h> -#include <asm/uaccess.h> -#else -#include <linux/io.h> -#include <linux/signal.h> -#include <linux/irq.h> -#include <linux/uaccess.h> -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) -#include <asm/div64.h> -#endif - -#include <linux/poll.h> -#include <linux/parport.h> - -#include "../lirc.h" -#include "../kcompat.h" -#include "../lirc_dev/lirc_dev.h" - -#include "lirc_parallel.h" - -#define LIRC_DRIVER_NAME "lirc_parallel" - -#ifndef LIRC_IRQ -#define LIRC_IRQ 7 -#endif -#ifndef LIRC_PORT -#define LIRC_PORT 0x378 -#endif -#ifndef LIRC_TIMER -#define LIRC_TIMER 65536 -#endif - -/*** Global Variables ***/ - -static int debug; -static int check_pselecd; - -unsigned int irq = LIRC_IRQ; -unsigned int io = LIRC_PORT; -#ifdef LIRC_TIMER -unsigned int timer; -unsigned int default_timer = LIRC_TIMER; -#endif - -#define WBUF_SIZE (256) -#define RBUF_SIZE (256) /* this must be a power of 2 larger than 1 */ - -static lirc_t wbuf[WBUF_SIZE]; -static lirc_t rbuf[RBUF_SIZE]; - -DECLARE_WAIT_QUEUE_HEAD(lirc_wait); - -unsigned int rptr; -unsigned int wptr; -unsigned int lost_irqs; -int is_open; - -struct parport *pport; -struct pardevice *ppdevice; -int is_claimed; - -unsigned int tx_mask = 1; - -/*** Internal Functions ***/ - -static unsigned int in(int offset) -{ - switch (offset) { - case LIRC_LP_BASE: - return parport_read_data(pport); - case LIRC_LP_STATUS: - return parport_read_status(pport); - case LIRC_LP_CONTROL: - return parport_read_control(pport); - } - return 0; /* make compiler happy */ -} - -static void out(int offset, int value) -{ - switch (offset) { - case LIRC_LP_BASE: - parport_write_data(pport, value); - break; - case LIRC_LP_CONTROL: - parport_write_control(pport, value); - break; - case LIRC_LP_STATUS: - printk(KERN_INFO "%s: attempt to write to status register\n", - LIRC_DRIVER_NAME); - break; - } -} - -static unsigned int lirc_get_timer(void) -{ - return in(LIRC_PORT_TIMER) & LIRC_PORT_TIMER_BIT; -} - -static unsigned int lirc_get_signal(void) -{ - return in(LIRC_PORT_SIGNAL) & LIRC_PORT_SIGNAL_BIT; -} - -static void lirc_on(void) -{ - out(LIRC_PORT_DATA, tx_mask); -} - -static void lirc_off(void) -{ - out(LIRC_PORT_DATA, 0); -} - -static unsigned int init_lirc_timer(void) -{ - struct timeval tv, now; - unsigned int level, newlevel, timeelapsed, newtimer; - int count = 0; - - do_gettimeofday(&tv); - tv.tv_sec++; /* wait max. 1 sec. */ - level = lirc_get_timer(); - do { - newlevel = lirc_get_timer(); - if (level == 0 && newlevel != 0) - count++; - level = newlevel; - do_gettimeofday(&now); - } while (count < 1000 && (now.tv_sec < tv.tv_sec - || (now.tv_sec == tv.tv_sec - && now.tv_usec < tv.tv_usec))); - - timeelapsed = ((now.tv_sec + 1 - tv.tv_sec)*1000000 - + (now.tv_usec - tv.tv_usec)); - if (count >= 1000 && timeelapsed > 0) { - if (default_timer == 0) { - /* autodetect timer */ - newtimer = (1000000*count)/timeelapsed; - printk(KERN_INFO "%s: %u Hz timer detected\n", - LIRC_DRIVER_NAME, newtimer); - return newtimer; - } else { - newtimer = (1000000*count)/timeelapsed; - if (abs(newtimer - default_timer) > default_timer/10) { - /* bad timer */ - printk(KERN_NOTICE "%s: bad timer: %u Hz\n", - LIRC_DRIVER_NAME, newtimer); - printk(KERN_NOTICE "%s: using default timer: " - "%u Hz\n", - LIRC_DRIVER_NAME, default_timer); - return default_timer; - } else { - printk(KERN_INFO "%s: %u Hz timer detected\n", - LIRC_DRIVER_NAME, newtimer); - return newtimer; /* use detected value */ - } - } - } else { - printk(KERN_NOTICE "%s: no timer detected\n", LIRC_DRIVER_NAME); - return 0; - } -} - -static int lirc_claim(void) -{ - if (parport_claim(ppdevice) != 0) { - printk(KERN_WARNING "%s: could not claim port\n", - LIRC_DRIVER_NAME); - printk(KERN_WARNING "%s: waiting for port becoming available" - "\n", LIRC_DRIVER_NAME); - if (parport_claim_or_block(ppdevice) < 0) { - printk(KERN_NOTICE "%s: could not claim port, giving" - " up\n", LIRC_DRIVER_NAME); - return 0; - } - } - out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP); - is_claimed = 1; - return 1; -} - -/*** interrupt handler ***/ - -static void rbuf_write(lirc_t signal) -{ - unsigned int nwptr; - - nwptr = (wptr + 1) & (RBUF_SIZE - 1); - if (nwptr == rptr) { - /* no new signals will be accepted */ - lost_irqs++; - printk(KERN_NOTICE "%s: buffer overrun\n", LIRC_DRIVER_NAME); - return; - } - rbuf[wptr] = signal; - wptr = nwptr; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -static void irq_handler(int i, void *blah, struct pt_regs *regs) -#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) -static void irq_handler(int i, void *blah) -#else -static void irq_handler(void *blah) -#endif -{ - struct timeval tv; - static struct timeval lasttv; - static int init; - long signal; - lirc_t data; - unsigned int level, newlevel; - unsigned int timeout; - - if (!MOD_IN_USE) - return; - - if (!is_claimed) - return; - -#if 0 - /* disable interrupt */ - disable_irq(irq); - out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ) & (~LP_PINTEN)); -#endif - if (check_pselecd && (in(1) & LP_PSELECD)) - return; - -#ifdef LIRC_TIMER - if (init) { - do_gettimeofday(&tv); - - signal = tv.tv_sec - lasttv.tv_sec; - if (signal > 15) - /* really long time */ - data = PULSE_MASK; - else - data = (lirc_t) (signal*1000000 + - tv.tv_usec - lasttv.tv_usec + - LIRC_SFH506_DELAY); - - rbuf_write(data); /* space */ - } else { - if (timer == 0) { - /* - * wake up; we'll lose this signal, but it will be - * garbage if the device is turned on anyway - */ - timer = init_lirc_timer(); - /* enable_irq(irq); */ - return; - } - init = 1; - } - - timeout = timer/10; /* timeout after 1/10 sec. */ - signal = 1; - level = lirc_get_timer(); - do { - newlevel = lirc_get_timer(); - if (level == 0 && newlevel != 0) - signal++; - level = newlevel; - - /* giving up */ - if (signal > timeout - || (check_pselecd && (in(1) & LP_PSELECD))) { - signal = 0; - printk(KERN_NOTICE "%s: timeout\n", LIRC_DRIVER_NAME); - break; - } - } while (lirc_get_signal()); - - if (signal != 0) { - /* adjust value to usecs */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) - unsigned long long helper; - - helper = ((unsigned long long) signal)*1000000; - do_div(helper, timer); - signal = (long) helper; -#else - signal = (long) ((((double) signal)*1000000)/timer); -#endif - - if (signal > LIRC_SFH506_DELAY) - data = signal - LIRC_SFH506_DELAY; - else - data = 1; - rbuf_write(PULSE_BIT|data); /* pulse */ - } - do_gettimeofday(&lasttv); -#else - /* add your code here */ -#endif - - wake_up_interruptible(&lirc_wait); - - /* enable interrupt */ - /* - enable_irq(irq); - out(LIRC_PORT_IRQ, in(LIRC_PORT_IRQ)|LP_PINTEN); - */ -} - -/*** file operations ***/ - -static loff_t lirc_lseek(struct file *filep, loff_t offset, int orig) -{ - return -ESPIPE; -} - -static ssize_t lirc_read(struct file *filep, char *buf, size_t n, loff_t *ppos) -{ - int result = 0; - int count = 0; - DECLARE_WAITQUEUE(wait, current); - - if (n % sizeof(lirc_t)) - return -EINVAL; - - add_wait_queue(&lirc_wait, &wait); - set_current_state(TASK_INTERRUPTIBLE); - while (count < n) { - if (rptr != wptr) { - if (copy_to_user(buf+count, (char *) &rbuf[rptr], - sizeof(lirc_t))) { - result = -EFAULT; - break; - } - rptr = (rptr + 1) & (RBUF_SIZE - 1); - count += sizeof(lirc_t); - } else { - if (filep->f_flags & O_NONBLOCK) { - result = -EAGAIN; - break; - } - if (signal_pending(current)) { - result = -ERESTARTSYS; - break; - } - schedule(); - set_current_state(TASK_INTERRUPTIBLE); - } - } - remove_wait_queue(&lirc_wait, &wait); - set_current_state(TASK_RUNNING); - return count ? count : result; -} - -static ssize_t lirc_write(struct file *filep, const char *buf, size_t n, - loff_t *ppos) -{ - int count; - unsigned int i; - unsigned int level, newlevel; - unsigned long flags; - lirc_t counttimer; - - if (!is_claimed) - return -EBUSY; - - if (n % sizeof(lirc_t)) - return -EINVAL; - - count = n / sizeof(lirc_t); - - if (count > WBUF_SIZE || count % 2 == 0) - return -EINVAL; - - if (copy_from_user(wbuf, buf, n)) - return -EFAULT; - -#ifdef LIRC_TIMER - if (timer == 0) { - /* try again if device is ready */ - timer = init_lirc_timer(); - if (timer == 0) - return -EIO; - } - - /* adjust values from usecs */ - for (i = 0; i < count; i++) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) - unsigned long long helper; - - helper = ((unsigned long long) wbuf[i])*timer; - do_div(helper, 1000000); - wbuf[i] = (lirc_t) helper; -#else - wbuf[i] = (lirc_t) (((double) wbuf[i])*timer/1000000); -#endif - } - - local_irq_save(flags); - i = 0; - while (i < count) { - level = lirc_get_timer(); - counttimer = 0; - lirc_on(); - do { - newlevel = lirc_get_timer(); - if (level == 0 && newlevel != 0) - counttimer++; - level = newlevel; - if (check_pselecd && (in(1) & LP_PSELECD)) { - lirc_off(); - local_irq_restore(flags); - return -EIO; - } - } while (counttimer < wbuf[i]); - i++; - - lirc_off(); - if (i == count) - break; - counttimer = 0; - do { - newlevel = lirc_get_timer(); - if (level == 0 && newlevel != 0) - counttimer++; - level = newlevel; - if (check_pselecd && (in(1) & LP_PSELECD)) { - local_irq_restore(flags); - return -EIO; - } - } while (counttimer < wbuf[i]); - i++; - } - local_irq_restore(flags); -#else - /* place code that handles write without external timer here */ -#endif - return n; -} - -static unsigned int lirc_poll(struct file *file, poll_table *wait) -{ - poll_wait(file, &lirc_wait, wait); - if (rptr != wptr) - return POLLIN | POLLRDNORM; - return 0; -} - -static int lirc_ioctl(struct inode *node, struct file *filep, unsigned int cmd, - unsigned long arg) -{ - int result; - unsigned long features = LIRC_CAN_SET_TRANSMITTER_MASK | - LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2; - unsigned long mode; - unsigned int ivalue; - - switch (cmd) { - case LIRC_GET_FEATURES: - result = put_user(features, (unsigned long *) arg); - if (result) - return result; - break; - case LIRC_GET_SEND_MODE: - result = put_user(LIRC_MODE_PULSE, (unsigned long *) arg); - if (result) - return result; - break; - case LIRC_GET_REC_MODE: - result = put_user(LIRC_MODE_MODE2, (unsigned long *) arg); - if (result) - return result; - break; - case LIRC_SET_SEND_MODE: - result = get_user(mode, (unsigned long *) arg); - if (result) - return result; - if (mode != LIRC_MODE_PULSE) - return -EINVAL; - break; - case LIRC_SET_REC_MODE: - result = get_user(mode, (unsigned long *) arg); - if (result) - return result; - if (mode != LIRC_MODE_MODE2) - return -ENOSYS; - break; - case LIRC_SET_TRANSMITTER_MASK: - result = get_user(ivalue, (unsigned int *) arg); - if (result) - return result; - if ((ivalue & LIRC_PARALLEL_TRANSMITTER_MASK) != ivalue) - return LIRC_PARALLEL_MAX_TRANSMITTERS; - tx_mask = ivalue; - break; - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static int lirc_open(struct inode *node, struct file *filep) -{ - if (MOD_IN_USE || !lirc_claim()) - return -EBUSY; - - parport_enable_irq(pport); - - /* init read ptr */ - rptr = 0; - wptr = 0; - lost_irqs = 0; - - MOD_INC_USE_COUNT; - is_open = 1; - return 0; -} - -static int lirc_close(struct inode *node, struct file *filep) -{ - if (is_claimed) { - is_claimed = 0; - parport_release(ppdevice); - } - is_open = 0; - MOD_DEC_USE_COUNT; - return 0; -} - -static struct file_operations lirc_fops = { - .owner = THIS_MODULE, - .llseek = lirc_lseek, - .read = lirc_read, - .write = lirc_write, - .poll = lirc_poll, - .ioctl = lirc_ioctl, - .open = lirc_open, - .release = lirc_close -}; - -static int set_use_inc(void *data) -{ - return 0; -} - -static void set_use_dec(void *data) -{ -} - -static struct lirc_driver driver = { - .name = LIRC_DRIVER_NAME, - .minor = -1, - .code_length = 1, - .sample_rate = 0, - .data = NULL, - .add_to_buf = NULL, -#ifndef LIRC_REMOVE_DURING_EXPORT - .get_queue = NULL, -#endif - .set_use_inc = set_use_inc, - .set_use_dec = set_use_dec, - .fops = &lirc_fops, - .dev = NULL, - .owner = THIS_MODULE, -}; - -#ifdef MODULE -static int pf(void *handle); -static void kf(void *handle); - -static struct timer_list poll_timer; -static void poll_state(unsigned long ignored); - -static void poll_state(unsigned long ignored) -{ - printk(KERN_NOTICE "%s: time\n", - LIRC_DRIVER_NAME); - del_timer(&poll_timer); - if (is_claimed) - return; - kf(NULL); - if (!is_claimed) { - printk(KERN_NOTICE "%s: could not claim port, giving up\n", - LIRC_DRIVER_NAME); - init_timer(&poll_timer); - poll_timer.expires = jiffies + HZ; - poll_timer.data = (unsigned long)current; - poll_timer.function = poll_state; - add_timer(&poll_timer); - } -} - -static int pf(void *handle) -{ - parport_disable_irq(pport); - is_claimed = 0; - return 0; -} - -static void kf(void *handle) -{ - if (!is_open) - return; - if (!lirc_claim()) - return; - parport_enable_irq(pport); - lirc_off(); - /* this is a bit annoying when you actually print...*/ - /* - printk(KERN_INFO "%s: reclaimed port\n", LIRC_DRIVER_NAME); - */ -} - -/*** module initialization and cleanup ***/ - -static int __init lirc_parallel_init(void) -{ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 3) - pport = parport_find_base(io); -#else - pport = parport_enumerate(); - while (pport != NULL) { - if (pport->base == io) - break; - pport = pport->next; - } -#endif - if (pport == NULL) { - printk(KERN_NOTICE "%s: no port at %x found\n", - LIRC_DRIVER_NAME, io); - return -ENXIO; - } - ppdevice = parport_register_device(pport, LIRC_DRIVER_NAME, - pf, kf, irq_handler, 0, NULL); -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 3) - parport_put_port(pport); -#endif - if (ppdevice == NULL) { - printk(KERN_NOTICE "%s: parport_register_device() failed\n", - LIRC_DRIVER_NAME); - return -ENXIO; - } - if (parport_claim(ppdevice) != 0) - goto skip_init; - is_claimed = 1; - out(LIRC_LP_CONTROL, LP_PSELECP|LP_PINITP); - -#ifdef LIRC_TIMER - if (debug) - out(LIRC_PORT_DATA, tx_mask); - - timer = init_lirc_timer(); - -#if 0 /* continue even if device is offline */ - if (timer == 0) { - is_claimed = 0; - parport_release(pport); - parport_unregister_device(ppdevice); - return -EIO; - } - -#endif - if (debug) - out(LIRC_PORT_DATA, 0); -#endif - - is_claimed = 0; - parport_release(ppdevice); - skip_init: - driver.minor = lirc_register_driver(&driver); - if (driver.minor < 0) { - printk(KERN_NOTICE "%s: register_chrdev() failed\n", - LIRC_DRIVER_NAME); - parport_unregister_device(ppdevice); - return -EIO; - } - printk(KERN_INFO "%s: installed using port 0x%04x irq %d\n", - LIRC_DRIVER_NAME, io, irq); - return 0; -} - -static void __exit lirc_parallel_exit(void) -{ - parport_unregister_device(ppdevice); - lirc_unregister_driver(driver.minor); -} - -module_init(lirc_parallel_init); -module_exit(lirc_parallel_exit); - -MODULE_DESCRIPTION("Infrared receiver driver for parallel ports."); -MODULE_AUTHOR("Christoph Bartelmus"); -MODULE_LICENSE("GPL"); - -module_param(io, int, S_IRUGO); -MODULE_PARM_DESC(io, "I/O address base (0x3bc, 0x378 or 0x278)"); - -module_param(irq, int, S_IRUGO); -MODULE_PARM_DESC(irq, "Interrupt (7 or 5)"); - -module_param(tx_mask, int, S_IRUGO); -MODULE_PARM_DESC(tx_maxk, "Transmitter mask (default: 0x01)"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Enable debugging messages"); - -module_param(check_pselecd, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Check for printer (default: 0)"); -EXPORT_NO_SYMBOLS; -#endif /* MODULE */ diff --git a/ubuntu/lirc/lirc_parallel/lirc_parallel.h b/ubuntu/lirc/lirc_parallel/lirc_parallel.h deleted file mode 100644 index 59679c6ac60..00000000000 --- a/ubuntu/lirc/lirc_parallel/lirc_parallel.h +++ /dev/null @@ -1,26 +0,0 @@ -/* $Id: lirc_parallel.h,v 5.2 2007/01/25 04:32:05 lirc Exp $ */ - -#ifndef _LIRC_PARALLEL_H -#define _LIRC_PARALLEL_H - -#include <linux/lp.h> - -#define LIRC_PORT_LEN 3 - -#define LIRC_LP_BASE 0 -#define LIRC_LP_STATUS 1 -#define LIRC_LP_CONTROL 2 - -#define LIRC_PORT_DATA LIRC_LP_BASE /* base */ -#define LIRC_PORT_TIMER LIRC_LP_STATUS /* status port */ -#define LIRC_PORT_TIMER_BIT LP_PBUSY /* busy signal */ -#define LIRC_PORT_SIGNAL LIRC_LP_STATUS /* status port */ -#define LIRC_PORT_SIGNAL_BIT LP_PACK /* ack signal */ -#define LIRC_PORT_IRQ LIRC_LP_CONTROL /* control port */ - -#define LIRC_SFH506_DELAY 0 /* delay t_phl in usecs */ - -#define LIRC_PARALLEL_MAX_TRANSMITTERS 8 -#define LIRC_PARALLEL_TRANSMITTER_MASK ((1<<LIRC_PARALLEL_MAX_TRANSMITTERS) - 1) - -#endif diff --git a/ubuntu/lirc/lirc_sasem/Makefile b/ubuntu/lirc/lirc_sasem/Makefile deleted file mode 100644 index 18e23f8c9de..00000000000 --- a/ubuntu/lirc/lirc_sasem/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. -obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o diff --git a/ubuntu/lirc/lirc_sasem/lirc_sasem.c b/ubuntu/lirc/lirc_sasem/lirc_sasem.c deleted file mode 100644 index f5a39b12da5..00000000000 --- a/ubuntu/lirc/lirc_sasem/lirc_sasem.c +++ /dev/null @@ -1,1106 +0,0 @@ -/* $Id: lirc_sasem.c,v 1.40 2009/02/28 10:27:10 lirc Exp $ */ -/* - * lirc_sasem.c - USB remote support for LIRC - * Version 0.5 - * - * Copyright (C) 2004-2005 Oliver Stabel <oliver.stabel@gmx.de> - * Tim Davies <tim@opensystems.net.au> - * - * This driver was derived from: - * Venky Raju <dev@venky.ws> - * "lirc_imon - "LIRC/VFD driver for Ahanix/Soundgraph IMON IR/VFD" - * Paul Miller <pmiller9@users.sourceforge.net>'s 2003-2004 - * "lirc_atiusb - USB remote support for LIRC" - * Culver Consulting Services <henry@culcon.com>'s 2003 - * "Sasem OnAir VFD/IR USB driver" - * - * - * NOTE - The LCDproc iMon driver should work with this module. More info at - * http://www.frogstorm.info/sasem - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/version.h> - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 22) -#error "*** Sorry, this driver requires kernel version 2.4.22 or higher" -#endif - -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) -#include <asm/uaccess.h> -#else -#include <linux/uaccess.h> -#endif -#include <linux/usb.h> - -#include "../kcompat.h" -#include "../lirc.h" -#include "../lirc_dev/lirc_dev.h" - - -#define MOD_AUTHOR "Oliver Stabel <oliver.stabel@gmx.de>, " \ - "Tim Davies <tim@opensystems.net.au>" -#define MOD_DESC "USB Driver for Sasem Remote Controller V1.1" -#define MOD_NAME "lirc_sasem" -#define MOD_VERSION "0.5" - -#define VFD_MINOR_BASE 144 /* Same as LCD */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) -#define DEVFS_MODE S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH -#endif -#define DEVFS_NAME LIRC_DEVFS_PREFIX "lcd%d" - -#define BUF_CHUNK_SIZE 8 -#define BUF_SIZE 128 - -#define IOCTL_LCD_CONTRAST 1 - -/*** P R O T O T Y P E S ***/ - -/* USB Callback prototypes */ -#ifdef KERNEL_2_5 -static int sasem_probe(struct usb_interface *interface, - const struct usb_device_id *id); -static void sasem_disconnect(struct usb_interface *interface); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -static void usb_rx_callback(struct urb *urb, struct pt_regs *regs); -static void usb_tx_callback(struct urb *urb, struct pt_regs *regs); -#else -static void usb_rx_callback(struct urb *urb); -static void usb_tx_callback(struct urb *urb); -#endif -#else -static void *sasem_probe(struct usb_device *dev, unsigned int intf, - const struct usb_device_id *id); -static void sasem_disconnect(struct usb_device *dev, void *data); -static void usb_rx_callback(struct urb *urb); -static void usb_tx_callback(struct urb *urb); -#endif - -/* VFD file_operations function prototypes */ -static int vfd_open(struct inode *inode, struct file *file); -static int vfd_ioctl(struct inode *inode, struct file *file, - unsigned cmd, unsigned long arg); -static int vfd_close(struct inode *inode, struct file *file); -static ssize_t vfd_write(struct file *file, const char *buf, - size_t n_bytes, loff_t *pos); - -/* LIRC driver function prototypes */ -static int ir_open(void *data); -static void ir_close(void *data); - -/* Driver init/exit prototypes */ -static int __init sasem_init(void); -static void __exit sasem_exit(void); - -/*** G L O B A L S ***/ - -struct sasem_context { - - struct usb_device *dev; - int vfd_isopen; /* VFD port has been opened */ - unsigned int vfd_contrast; /* VFD contrast */ -#if !defined(KERNEL_2_5) - int subminor; /* index into minor_table */ - devfs_handle_t devfs; -#endif - int ir_isopen; /* IR port has been opened */ - int dev_present; /* USB device presence */ - struct mutex lock; /* to lock this object */ - wait_queue_head_t remove_ok; /* For unexpected USB disconnects */ - - struct lirc_driver *driver; - struct usb_endpoint_descriptor *rx_endpoint; - struct usb_endpoint_descriptor *tx_endpoint; - struct urb *rx_urb; - struct urb *tx_urb; - unsigned char usb_rx_buf[8]; - unsigned char usb_tx_buf[8]; - - struct tx_t { - unsigned char data_buf[32]; /* user data buffer */ - struct completion finished; /* wait for write to finish */ - atomic_t busy; /* write in progress */ - int status; /* status of tx completion */ - } tx; - - /* for dealing with repeat codes (wish there was a toggle bit!) */ - struct timeval presstime; - char lastcode[8]; - int codesaved; -}; - -/* VFD file operations */ -static struct file_operations vfd_fops = { - - .owner = THIS_MODULE, - .open = &vfd_open, - .write = &vfd_write, - .ioctl = &vfd_ioctl, - .release = &vfd_close -}; - -/* USB Device ID for Sasem USB Control Board */ -static struct usb_device_id sasem_usb_id_table [] = { - /* Sasem USB Control Board */ - { USB_DEVICE(0x11ba, 0x0101) }, - /* Terminating entry */ - {} -}; - -/* USB Device data */ -static struct usb_driver sasem_driver = { - LIRC_THIS_MODULE(.owner = THIS_MODULE) - .name = MOD_NAME, - .probe = sasem_probe, - .disconnect = sasem_disconnect, - .id_table = sasem_usb_id_table, -#if !defined(KERNEL_2_5) - .fops = &vfd_fops, - .minor = VFD_MINOR_BASE, -#endif -}; - -#ifdef KERNEL_2_5 -static struct usb_class_driver sasem_class = { - .name = DEVFS_NAME, - .fops = &vfd_fops, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 15) - .mode = DEVFS_MODE, -#endif - .minor_base = VFD_MINOR_BASE, -}; -#endif - -/* to prevent races between open() and disconnect() */ -static DEFINE_MUTEX(disconnect_lock); - -static int debug; - -#if !defined(KERNEL_2_5) - -#define MAX_DEVICES 4 /* In case there's more than one Sasem device */ -static struct sasem_context *minor_table [MAX_DEVICES]; - -/* the global usb devfs handle */ -extern devfs_handle_t usb_devfs_handle; - -#endif - -/*** M O D U L E C O D E ***/ - -MODULE_AUTHOR(MOD_AUTHOR); -MODULE_DESCRIPTION(MOD_DESC); -MODULE_LICENSE("GPL"); -module_param(debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug messages: 0=no, 1=yes (default: no)"); - -static void delete_context(struct sasem_context *context) -{ - usb_free_urb(context->tx_urb); /* VFD */ - usb_free_urb(context->rx_urb); /* IR */ - lirc_buffer_free(context->driver->rbuf); - kfree(context->driver->rbuf); - kfree(context->driver); - kfree(context); - - if (debug) - printk(KERN_INFO "%s: context deleted\n", __func__); -} - -static void deregister_from_lirc(struct sasem_context *context) -{ - int retval; - int minor = context->driver->minor; - - retval = lirc_unregister_driver(minor); - if (retval) - err("%s: unable to deregister from lirc (%d)", - __func__, retval); - else - printk(KERN_INFO "Deregistered Sasem driver (minor:%d)\n", - minor); - -} - -/** - * Called when the VFD device (e.g. /dev/usb/lcd) - * is opened by the application. - */ -static int vfd_open(struct inode *inode, struct file *file) -{ -#ifdef KERNEL_2_5 - struct usb_interface *interface; -#endif - struct sasem_context *context = NULL; - int subminor; - int retval = 0; - - /* prevent races with disconnect */ - mutex_lock(&disconnect_lock); - -#ifdef KERNEL_2_5 - subminor = iminor(inode); - interface = usb_find_interface(&sasem_driver, subminor); - if (!interface) { - err("%s: could not find interface for minor %d", - __func__, subminor); - retval = -ENODEV; - goto exit; - } - context = usb_get_intfdata(interface); -#else - subminor = MINOR(inode->i_rdev) - VFD_MINOR_BASE; - if (subminor < 0 || subminor >= MAX_DEVICES) { - err("%s: no record of minor %d", __func__, subminor); - retval = -ENODEV; - goto exit; - } - context = minor_table [subminor]; -#endif - - if (!context) { - err("%s: no context found for minor %d", - __func__, subminor); - retval = -ENODEV; - goto exit; - } - - mutex_lock(&context->lock); - - if (context->vfd_isopen) { - err("%s: VFD port is already open", __func__); - retval = -EBUSY; - } else { - MOD_INC_USE_COUNT; - context->vfd_isopen = 1; - file->private_data = context; - printk(KERN_INFO "VFD port opened\n"); - } - - mutex_unlock(&context->lock); - -exit: - mutex_unlock(&disconnect_lock); - return retval; -} - -/** - * Called when the VFD device (e.g. /dev/usb/lcd) - * is closed by the application. - */ -static int vfd_ioctl(struct inode *inode, struct file *file, - unsigned cmd, unsigned long arg) -{ - struct sasem_context *context = NULL; - - context = (struct sasem_context *) file->private_data; - - if (!context) { - err("%s: no context for device", __func__); - return -ENODEV; - } - - mutex_lock(&context->lock); - - switch (cmd) { - case IOCTL_LCD_CONTRAST: - if (arg > 1000) - arg = 1000; - context->vfd_contrast = (unsigned int)arg; - break; - default: - printk(KERN_INFO "Unknown IOCTL command\n"); - mutex_unlock(&context->lock); - return -ENOIOCTLCMD; /* not supported */ - } - - mutex_unlock(&context->lock); - return 0; -} - -/** - * Called when the VFD device (e.g. /dev/usb/lcd) - * is closed by the application. - */ -static int vfd_close(struct inode *inode, struct file *file) -{ - struct sasem_context *context = NULL; - int retval = 0; - - context = (struct sasem_context *) file->private_data; - - if (!context) { - err("%s: no context for device", __func__); - return -ENODEV; - } - - mutex_lock(&context->lock); - - if (!context->vfd_isopen) { - err("%s: VFD is not open", __func__); - retval = -EIO; - } else { - context->vfd_isopen = 0; - MOD_DEC_USE_COUNT; - printk(KERN_INFO "VFD port closed\n"); - if (!context->dev_present && !context->ir_isopen) { - - /* Device disconnected before close and IR port is - * not open. If IR port is open, context will be - * deleted by ir_close. */ - mutex_unlock(&context->lock); - delete_context(context); - return retval; - } - } - - mutex_unlock(&context->lock); - return retval; -} - -/** - * Sends a packet to the VFD. - */ -static int send_packet(struct sasem_context *context) -{ - unsigned int pipe; - int interval = 0; - int retval = 0; - - pipe = usb_sndintpipe(context->dev, - context->tx_endpoint->bEndpointAddress); -#ifdef KERNEL_2_5 - interval = context->tx_endpoint->bInterval; -#endif /* Use 0 for 2.4 kernels */ - - usb_fill_int_urb(context->tx_urb, context->dev, pipe, - context->usb_tx_buf, sizeof(context->usb_tx_buf), - usb_tx_callback, context, interval); - - context->tx_urb->actual_length = 0; - - init_completion(&context->tx.finished); - atomic_set(&(context->tx.busy), 1); - -#ifdef KERNEL_2_5 - retval = usb_submit_urb(context->tx_urb, GFP_KERNEL); -#else - retval = usb_submit_urb(context->tx_urb); -#endif - if (retval) { - atomic_set(&(context->tx.busy), 0); - err("%s: error submitting urb (%d)", __func__, retval); - } else { - /* Wait for transmission to complete (or abort) */ - mutex_unlock(&context->lock); - wait_for_completion(&context->tx.finished); - mutex_lock(&context->lock); - - retval = context->tx.status; - if (retval) - err("%s: packet tx failed (%d)", __func__, retval); - } - - return retval; -} - -/** - * Writes data to the VFD. The Sasem VFD is 2x16 characters - * and requires data in 9 consecutive USB interrupt packets, - * each packet carrying 8 bytes. - */ -static ssize_t vfd_write(struct file *file, const char *buf, - size_t n_bytes, loff_t *pos) -{ - int i; - int retval = 0; - struct sasem_context *context; - - context = (struct sasem_context *) file->private_data; - if (!context) { - err("%s: no context for device", __func__); - return -ENODEV; - } - - mutex_lock(&context->lock); - - if (!context->dev_present) { - err("%s: no Sasem device present", __func__); - retval = -ENODEV; - goto exit; - } - - if (n_bytes <= 0 || n_bytes > 32) { - err("%s: invalid payload size", __func__); - retval = -EINVAL; - goto exit; - } - - retval = copy_from_user(context->tx.data_buf, buf, n_bytes); - if (retval < 0) - goto exit; - - /* Pad with spaces */ - for (i = n_bytes; i < 32; ++i) - context->tx.data_buf[i] = ' '; - - /* Nine 8 byte packets to be sent */ - /* NOTE: "\x07\x01\0\0\0\0\0\0" or "\x0c\0\0\0\0\0\0\0" - * will clear the VFD */ - for (i = 0; i < 9; i++) { - switch (i) { - case 0: - memcpy(context->usb_tx_buf, "\x07\0\0\0\0\0\0\0", 8); - context->usb_tx_buf[1] = (context->vfd_contrast) ? - (0x2B - (context->vfd_contrast - 1) / 250) - : 0x2B; - break; - case 1: - memcpy(context->usb_tx_buf, "\x09\x01\0\0\0\0\0\0", 8); - break; - case 2: - memcpy(context->usb_tx_buf, "\x0b\x01\0\0\0\0\0\0", 8); - break; - case 3: - memcpy(context->usb_tx_buf, context->tx.data_buf, 8); - break; - case 4: - memcpy(context->usb_tx_buf, - context->tx.data_buf + 8, 8); - break; - case 5: - memcpy(context->usb_tx_buf, "\x09\x01\0\0\0\0\0\0", 8); - break; - case 6: - memcpy(context->usb_tx_buf, "\x0b\x02\0\0\0\0\0\0", 8); - break; - case 7: - memcpy(context->usb_tx_buf, - context->tx.data_buf + 16, 8); - break; - case 8: - memcpy(context->usb_tx_buf, - context->tx.data_buf + 24, 8); - break; - } - retval = send_packet(context); - if (retval) { - - err("%s: send packet failed for packet #%d", - __func__, i); - goto exit; - } - } -exit: - - mutex_unlock(&context->lock); - - return (!retval) ? n_bytes : retval; -} - -/** - * Callback function for USB core API: transmit data - */ -#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -static void usb_tx_callback(struct urb *urb, struct pt_regs *regs) -#else -static void usb_tx_callback(struct urb *urb) -#endif -{ - struct sasem_context *context; - - if (!urb) - return; - context = (struct sasem_context *) urb->context; - if (!context) - return; - - context->tx.status = urb->status; - - /* notify waiters that write has finished */ - atomic_set(&context->tx.busy, 0); - complete(&context->tx.finished); - - return; -} - -/** - * Called by lirc_dev when the application opens /dev/lirc - */ -static int ir_open(void *data) -{ - int retval = 0; - struct sasem_context *context; - - /* prevent races with disconnect */ - mutex_lock(&disconnect_lock); - - context = (struct sasem_context *) data; - - mutex_lock(&context->lock); - - if (context->ir_isopen) { - err("%s: IR port is already open", __func__); - retval = -EBUSY; - goto exit; - } - - usb_fill_int_urb(context->rx_urb, context->dev, - usb_rcvintpipe(context->dev, - context->rx_endpoint->bEndpointAddress), - context->usb_rx_buf, sizeof(context->usb_rx_buf), - usb_rx_callback, context, context->rx_endpoint->bInterval); - -#ifdef KERNEL_2_5 - retval = usb_submit_urb(context->rx_urb, GFP_KERNEL); -#else - retval = usb_submit_urb(context->rx_urb); -#endif - - if (retval) - err("%s: usb_submit_urb failed for ir_open (%d)", - __func__, retval); - else { - MOD_INC_USE_COUNT; - context->ir_isopen = 1; - printk(KERN_INFO "IR port opened\n"); - } - -exit: - mutex_unlock(&context->lock); - - mutex_unlock(&disconnect_lock); - return 0; -} - -/** - * Called by lirc_dev when the application closes /dev/lirc - */ -static void ir_close(void *data) -{ - struct sasem_context *context; - - context = (struct sasem_context *)data; - if (!context) { - err("%s: no context for device", __func__); - return; - } - - mutex_lock(&context->lock); - - usb_kill_urb(context->rx_urb); - context->ir_isopen = 0; - MOD_DEC_USE_COUNT; - printk(KERN_INFO "IR port closed\n"); - - if (!context->dev_present) { - - /* - * Device disconnected while IR port was - * still open. Driver was not deregistered - * at disconnect time, so do it now. - */ - deregister_from_lirc(context); - - if (!context->vfd_isopen) { - - mutex_unlock(&context->lock); - delete_context(context); - return; - } - /* If VFD port is open, context will be deleted by vfd_close */ - } - - mutex_unlock(&context->lock); - return; -} - -/** - * Process the incoming packet - */ -static void incoming_packet(struct sasem_context *context, - struct urb *urb) -{ - int len = urb->actual_length; - unsigned char *buf = urb->transfer_buffer; - long ms; - struct timeval tv; - - if (len != 8) { - printk(KERN_WARNING "%s: invalid incoming packet size (%d)\n", - __func__, len); - return; - } - -#ifdef DEBUG - int i; - for (i = 0; i < 8; ++i) - printk(KERN_INFO "%02x ", buf [i]); - printk(KERN_INFO "\n"); -#endif - - /* - * Lirc could deal with the repeat code, but we really need to block it - * if it arrives too late. Otherwise we could repeat the wrong code. - */ - - /* get the time since the last button press */ - do_gettimeofday(&tv); - ms = (tv.tv_sec - context->presstime.tv_sec) * 1000 + - (tv.tv_usec - context->presstime.tv_usec) / 1000; - - if (memcmp(buf, "\x08\0\0\0\0\0\0\0", 8) == 0) { - /* - * the repeat code is being sent, so we copy - * the old code to LIRC - */ - - /* - * NOTE: Only if the last code was less than 250ms ago - * - no one should be able to push another (undetected) button - * in that time and then get a false repeat of the previous - * press but it is long enough for a genuine repeat - */ - if ((ms < 250) && (context->codesaved != 0)) { - memcpy(buf, &context->lastcode, 8); - context->presstime.tv_sec = tv.tv_sec; - context->presstime.tv_usec = tv.tv_usec; - } - } else { - /* save the current valid code for repeats */ - memcpy(&context->lastcode, buf, 8); - /* - * set flag to signal a valid code was save; - * just for safety reasons - */ - context->codesaved = 1; - context->presstime.tv_sec = tv.tv_sec; - context->presstime.tv_usec = tv.tv_usec; - } - - lirc_buffer_write(context->driver->rbuf, buf); - wake_up(&context->driver->rbuf->wait_poll); -} - -/** - * Callback function for USB core API: receive data - */ -#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -static void usb_rx_callback(struct urb *urb, struct pt_regs *regs) -#else -static void usb_rx_callback(struct urb *urb) -#endif -{ - struct sasem_context *context; - - if (!urb) - return; - context = (struct sasem_context *) urb->context; - if (!context) - return; - - switch (urb->status) { - - case -ENOENT: /* usbcore unlink successful! */ - return; - - case 0: - if (context->ir_isopen) - incoming_packet(context, urb); - break; - - default: - printk(KERN_WARNING "%s: status (%d): ignored\n", - __func__, urb->status); - break; - } - -#ifdef KERNEL_2_5 - usb_submit_urb(context->rx_urb, GFP_ATOMIC); -#endif - return; -} - - - -/** - * Callback function for USB core API: Probe - */ -#ifdef KERNEL_2_5 -static int sasem_probe(struct usb_interface *interface, - const struct usb_device_id *id) -#else -static void *sasem_probe(struct usb_device *dev, unsigned int intf, - const struct usb_device_id *id) -#endif -{ -#ifdef KERNEL_2_5 - struct usb_device *dev = NULL; - struct usb_host_interface *iface_desc = NULL; -#else - struct usb_interface *interface = NULL; - struct usb_interface_descriptor *iface_desc = NULL; - char name [10]; - int subminor = 0; -#endif - struct usb_endpoint_descriptor *rx_endpoint = NULL; - struct usb_endpoint_descriptor *tx_endpoint = NULL; - struct urb *rx_urb = NULL; - struct urb *tx_urb = NULL; - struct lirc_driver *driver = NULL; - struct lirc_buffer *rbuf = NULL; - int lirc_minor = 0; - int num_endpoints; - int retval = 0; - int vfd_ep_found; - int ir_ep_found; - int alloc_status; - struct sasem_context *context = NULL; - int i; - - printk(KERN_INFO "%s: found Sasem device\n", __func__); - -#if !defined(KERNEL_2_5) - for (subminor = 0; subminor < MAX_DEVICES; ++subminor) { - if (minor_table [subminor] == NULL) - break; - } - if (subminor == MAX_DEVICES) { - err("%s: allowed number of devices already present", - __func__); - retval = -ENOMEM; - goto exit; - } -#endif - -#ifdef KERNEL_2_5 - dev = usb_get_dev(interface_to_usbdev(interface)); - iface_desc = interface->cur_altsetting; - num_endpoints = iface_desc->desc.bNumEndpoints; -#else - interface = &dev->actconfig->interface [intf]; - iface_desc = &interface->altsetting [interface->act_altsetting]; - num_endpoints = iface_desc->bNumEndpoints; -#endif - - /* - * Scan the endpoint list and set: - * first input endpoint = IR endpoint - * first output endpoint = VFD endpoint - */ - - ir_ep_found = 0; - vfd_ep_found = 0; - - for (i = 0; i < num_endpoints && !(ir_ep_found && vfd_ep_found); ++i) { - - struct usb_endpoint_descriptor *ep; - int ep_dir; - int ep_type; -#ifdef KERNEL_2_5 - ep = &iface_desc->endpoint [i].desc; -#else - ep = &iface_desc->endpoint [i]; -#endif - ep_dir = ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK; - ep_type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; - - if (!ir_ep_found && - ep_dir == USB_DIR_IN && - ep_type == USB_ENDPOINT_XFER_INT) { - - rx_endpoint = ep; - ir_ep_found = 1; - if (debug) - printk(KERN_INFO "%s: found IR endpoint\n", - __func__); - - } else if (!vfd_ep_found && - ep_dir == USB_DIR_OUT && - ep_type == USB_ENDPOINT_XFER_INT) { - - tx_endpoint = ep; - vfd_ep_found = 1; - if (debug) - printk(KERN_INFO "%s: found VFD endpoint\n", - __func__); - } - } - - /* Input endpoint is mandatory */ - if (!ir_ep_found) { - - err("%s: no valid input (IR) endpoint found.", __func__); - retval = -ENODEV; - goto exit; - } - - if (!vfd_ep_found) - printk(KERN_INFO "%s: no valid output (VFD) endpoint found.\n", - __func__); - - - /* Allocate memory */ - alloc_status = 0; - - context = kzalloc(sizeof(struct sasem_context), GFP_KERNEL); - if (!context) { - err("%s: kzalloc failed for context", __func__); - alloc_status = 1; - goto alloc_status_switch; - } - driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL); - if (!driver) { - err("%s: kzalloc failed for lirc_driver", __func__); - alloc_status = 2; - goto alloc_status_switch; - } - rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); - if (!rbuf) { - err("%s: kmalloc failed for lirc_buffer", __func__); - alloc_status = 3; - goto alloc_status_switch; - } - if (lirc_buffer_init(rbuf, BUF_CHUNK_SIZE, BUF_SIZE)) { - err("%s: lirc_buffer_init failed", __func__); - alloc_status = 4; - goto alloc_status_switch; - } -#ifdef KERNEL_2_5 - rx_urb = usb_alloc_urb(0, GFP_KERNEL); -#else - rx_urb = usb_alloc_urb(0); -#endif - if (!rx_urb) { - err("%s: usb_alloc_urb failed for IR urb", __func__); - alloc_status = 5; - goto alloc_status_switch; - } - if (vfd_ep_found) { -#ifdef KERNEL_2_5 - tx_urb = usb_alloc_urb(0, GFP_KERNEL); -#else - tx_urb = usb_alloc_urb(0); -#endif - if (!tx_urb) { - err("%s: usb_alloc_urb failed for VFD urb", __func__); - alloc_status = 6; - goto alloc_status_switch; - } - } - - mutex_init(&context->lock); - - strcpy(driver->name, MOD_NAME); - driver->minor = -1; - driver->code_length = 64; - driver->sample_rate = 0; - driver->features = LIRC_CAN_REC_LIRCCODE; - driver->data = context; - driver->rbuf = rbuf; - driver->set_use_inc = ir_open; - driver->set_use_dec = ir_close; -#ifdef LIRC_HAVE_SYSFS - driver->dev = &interface->dev; -#endif - driver->owner = THIS_MODULE; - - mutex_lock(&context->lock); - - lirc_minor = lirc_register_driver(driver); - if (lirc_minor < 0) { - err("%s: lirc_register_driver failed", __func__); - alloc_status = 7; - mutex_unlock(&context->lock); - } else - printk(KERN_INFO "%s: Registered Sasem driver (minor:%d)\n", - __func__, lirc_minor); - -alloc_status_switch: - - switch (alloc_status) { - - case 7: - if (vfd_ep_found) - usb_free_urb(tx_urb); - case 6: - usb_free_urb(rx_urb); - case 5: - lirc_buffer_free(rbuf); - case 4: - kfree(rbuf); - case 3: - kfree(driver); - case 2: - kfree(context); - context = NULL; - case 1: - retval = -ENOMEM; - goto exit; - } - - /* Needed while unregistering! */ - driver->minor = lirc_minor; - - context->dev = dev; - context->dev_present = 1; - context->rx_endpoint = rx_endpoint; - context->rx_urb = rx_urb; - if (vfd_ep_found) { - context->tx_endpoint = tx_endpoint; - context->tx_urb = tx_urb; - context->vfd_contrast = 1000; /* range 0 - 1000 */ - } - context->driver = driver; - -#ifdef KERNEL_2_5 - usb_set_intfdata(interface, context); -#else - minor_table [subminor] = context; - context->subminor = subminor; -#endif - - if (vfd_ep_found) { - -#ifdef KERNEL_2_5 - if (debug) - printk(KERN_INFO "Registering VFD with sysfs\n"); - if (usb_register_dev(interface, &sasem_class)) - /* Not a fatal error, so ignore */ - printk(KERN_INFO "%s: could not get a minor number " - "for VFD\n", __func__); -#else - if (debug) - printk(KERN_INFO "Registering VFD with devfs\n"); - sprintf(name, DEVFS_NAME, subminor); - context->devfs = devfs_register(usb_devfs_handle, name, - DEVFS_FL_DEFAULT, - USB_MAJOR, VFD_MINOR_BASE + subminor, - DEVFS_MODE, &vfd_fops, NULL); - if (!context->devfs) - /* not a fatal error so ignore */ - printk(KERN_INFO "%s: devfs register failed for VFD\n", - __func__); -#endif - } - - printk(KERN_INFO "%s: Sasem device on usb<%d:%d> initialized\n", - __func__, dev->bus->busnum, dev->devnum); - - mutex_unlock(&context->lock); -exit: -#ifdef KERNEL_2_5 - return retval; -#else - return (!retval) ? context : NULL; -#endif -} - -/** - * Callback function for USB core API: disonnect - */ -#ifdef KERNEL_2_5 -static void sasem_disconnect(struct usb_interface *interface) -#else -static void sasem_disconnect(struct usb_device *dev, void *data) -#endif -{ - struct sasem_context *context; - - /* prevent races with ir_open()/vfd_open() */ - mutex_lock(&disconnect_lock); - -#ifdef KERNEL_2_5 - context = usb_get_intfdata(interface); -#else - context = (struct sasem_context *)data; -#endif - mutex_lock(&context->lock); - - printk(KERN_INFO "%s: Sasem device disconnected\n", __func__); - -#ifdef KERNEL_2_5 - usb_set_intfdata(interface, NULL); -#else - minor_table [context->subminor] = NULL; -#endif - context->dev_present = 0; - - /* Stop reception */ - usb_kill_urb(context->rx_urb); - - /* Abort ongoing write */ - if (atomic_read(&context->tx.busy)) { - - usb_kill_urb(context->tx_urb); - wait_for_completion(&context->tx.finished); - } - - /* De-register from lirc_dev if IR port is not open */ - if (!context->ir_isopen) - deregister_from_lirc(context); - -#ifdef KERNEL_2_5 - usb_deregister_dev(interface, &sasem_class); -#else - if (context->devfs) - devfs_unregister(context->devfs); -#endif - - mutex_unlock(&context->lock); - - if (!context->ir_isopen && !context->vfd_isopen) - delete_context(context); - - mutex_unlock(&disconnect_lock); -} - -static int __init sasem_init(void) -{ - int rc; - - printk(KERN_INFO MOD_DESC ", v" MOD_VERSION "\n"); - printk(KERN_INFO MOD_AUTHOR "\n"); - - rc = usb_register(&sasem_driver); - if (rc < 0) { - err("%s: usb register failed (%d)", __func__, rc); - return -ENODEV; - } - return 0; -} - -static void __exit sasem_exit(void) -{ - usb_deregister(&sasem_driver); - printk(KERN_INFO "module removed. Goodbye!\n"); -} - - -module_init(sasem_init); -module_exit(sasem_exit); - -#if !defined(KERNEL_2_5) -EXPORT_NO_SYMBOLS; -#endif diff --git a/ubuntu/lirc/lirc_serial/Makefile b/ubuntu/lirc/lirc_serial/Makefile deleted file mode 100644 index 54adadbec3f..00000000000 --- a/ubuntu/lirc/lirc_serial/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. - -obj-$(CONFIG_LIRC_SERIAL) += lirc_serial.o diff --git a/ubuntu/lirc/lirc_serial/lirc_serial.c b/ubuntu/lirc/lirc_serial/lirc_serial.c deleted file mode 100644 index 2bc798039c9..00000000000 --- a/ubuntu/lirc/lirc_serial/lirc_serial.c +++ /dev/null @@ -1,1420 +0,0 @@ -/* $Id: lirc_serial.c,v 5.104 2009/03/15 09:34:00 lirc Exp $ */ -/* - * lirc_serial.c - * - * lirc_serial - Device driver that records pulse- and pause-lengths - * (space-lengths) between DDCD event on a serial port. - * - * Copyright (C) 1996,97 Ralph Metzler <rjkm@thp.uni-koeln.de> - * Copyright (C) 1998 Trent Piepho <xyzzy@u.washington.edu> - * Copyright (C) 1998 Ben Pfaff <blp@gnu.org> - * Copyright (C) 1999 Christoph Bartelmus <lirc@bartelmus.de> - * Copyright (C) 2007 Andrei Tanas <andrei@tanas.ca> (suspend/resume support) - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -/* - * Steve's changes to improve transmission fidelity: - * - for systems with the rdtsc instruction and the clock counter, a - * send_pule that times the pulses directly using the counter. - * This means that the LIRC_SERIAL_TRANSMITTER_LATENCY fudge is - * not needed. Measurement shows very stable waveform, even where - * PCI activity slows the access to the UART, which trips up other - * versions. - * - For other system, non-integer-microsecond pulse/space lengths, - * done using fixed point binary. So, much more accurate carrier - * frequency. - * - fine tuned transmitter latency, taking advantage of fractional - * microseconds in previous change - * - Fixed bug in the way transmitter latency was accounted for by - * tuning the pulse lengths down - the send_pulse routine ignored - * this overhead as it timed the overall pulse length - so the - * pulse frequency was right but overall pulse length was too - * long. Fixed by accounting for latency on each pulse/space - * iteration. - * - * Steve Davies <steve@daviesfam.org> July 2001 - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#include <linux/version.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18) -#error "**********************************************************" -#error " Sorry, this driver needs kernel version 2.2.18 or higher " -#error "**********************************************************" -#endif - -#include <linux/module.h> -#include <linux/errno.h> -#include <linux/signal.h> -#include <linux/sched.h> -#include <linux/fs.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/kernel.h> -#include <linux/major.h> -#include <linux/serial_reg.h> -#include <linux/time.h> -#include <linux/string.h> -#include <linux/types.h> -#include <linux/wait.h> -#include <linux/mm.h> -#include <linux/delay.h> -#include <linux/poll.h> -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) -#include <linux/platform_device.h> -#endif - -#include <asm/system.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) -#include <asm/uaccess.h> -#else -#include <linux/uaccess.h> -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16) -#include <asm/io.h> -#else -#include <linux/io.h> -#endif -#include <linux/irq.h> -#include <linux/fcntl.h> - -#if defined(LIRC_SERIAL_NSLU2) -#include <asm/hardware.h> -/* From Intel IXP42X Developer's Manual (#252480-005): */ -/* ftp://download.intel.com/design/network/manuals/25248005.pdf */ -#define UART_IE_IXP42X_UUE 0x40 /* IXP42X UART Unit enable */ -#define UART_IE_IXP42X_RTOIE 0x10 /* IXP42X Receiver Data Timeout int.enable */ -#ifndef NSLU2_LED_GRN_GPIO -/* added in 2.6.22 */ -#define NSLU2_LED_GRN_GPIO NSLU2_LED_GRN -#endif -#endif - -#include "../lirc.h" -#include "../kcompat.h" -#include "../lirc_dev/lirc_dev.h" - -#if defined(LIRC_SERIAL_SOFTCARRIER) && !defined(LIRC_SERIAL_TRANSMITTER) -#warning "Software carrier only affects transmitting" -#endif - -#if defined(rdtscl) - -#define USE_RDTSC -#warning "Note: using rdtsc instruction" -#endif - -#ifdef LIRC_SERIAL_ANIMAX -#ifdef LIRC_SERIAL_TRANSMITTER -#warning "******************************************" -#warning " This receiver does not have a " -#warning " transmitter diode " -#warning "******************************************" -#endif -#endif - -#define LIRC_DRIVER_VERSION "$Revision: 5.104 $" -#define LIRC_DRIVER_NAME "lirc_serial" - -struct lirc_serial { - int signal_pin; - int signal_pin_change; - int on; - int off; - long (*send_pulse)(unsigned long length); - void (*send_space)(long length); - int features; -}; - -#define LIRC_HOMEBREW 0 -#define LIRC_IRDEO 1 -#define LIRC_IRDEO_REMOTE 2 -#define LIRC_ANIMAX 3 -#define LIRC_IGOR 4 -#define LIRC_NSLU2 5 - -#ifdef LIRC_SERIAL_IRDEO -static int type = LIRC_IRDEO; -#elif defined(LIRC_SERIAL_IRDEO_REMOTE) -static int type = LIRC_IRDEO_REMOTE; -#elif defined(LIRC_SERIAL_ANIMAX) -static int type = LIRC_ANIMAX; -#elif defined(LIRC_SERIAL_IGOR) -static int type = LIRC_IGOR; -#elif defined(LIRC_SERIAL_NSLU2) -static int type = LIRC_NSLU2; -#else -static int type = LIRC_HOMEBREW; -#endif - -/* Set defaults for NSLU2 */ -#if defined(LIRC_SERIAL_NSLU2) -#ifndef LIRC_IRQ -#define LIRC_IRQ IRQ_IXP4XX_UART2 -#endif -#ifndef LIRC_PORT -#define LIRC_PORT (IXP4XX_UART2_BASE_VIRT + REG_OFFSET) -#endif -#ifndef LIRC_IOMMAP -#define LIRC_IOMMAP IXP4XX_UART2_BASE_PHYS -#endif -#ifndef LIRC_IOSHIFT -#define LIRC_IOSHIFT 2 -#endif -#ifndef LIRC_ALLOW_MMAPPED_IO -#define LIRC_ALLOW_MMAPPED_IO -#endif -#endif - -#if defined(LIRC_ALLOW_MMAPPED_IO) -#ifndef LIRC_IOMMAP -#define LIRC_IOMMAP 0 -#endif -#ifndef LIRC_IOSHIFT -#define LIRC_IOSHIFT 0 -#endif -static int iommap = LIRC_IOMMAP; -static int ioshift = LIRC_IOSHIFT; -#endif - -#ifdef LIRC_SERIAL_SOFTCARRIER -static int softcarrier = 1; -#else -static int softcarrier; -#endif - -static int share_irq; -static int debug; - -#define dprintk(fmt, args...) \ - do { \ - if (debug) \ - printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ - fmt, ## args); \ - } while (0) - -/* forward declarations */ -static long send_pulse_irdeo(unsigned long length); -static long send_pulse_homebrew(unsigned long length); -static void send_space_irdeo(long length); -static void send_space_homebrew(long length); - -static struct lirc_serial hardware[] = { - [LIRC_HOMEBREW] = { - .signal_pin = UART_MSR_DCD, - .signal_pin_change = UART_MSR_DDCD, - .on = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR), - .off = (UART_MCR_RTS | UART_MCR_OUT2), - .send_pulse = send_pulse_homebrew, - .send_space = send_space_homebrew, -#ifdef LIRC_SERIAL_TRANSMITTER - .features = (LIRC_CAN_SET_SEND_DUTY_CYCLE | - LIRC_CAN_SET_SEND_CARRIER | - LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2) -#else - .features = LIRC_CAN_REC_MODE2 -#endif - }, - - [LIRC_IRDEO] = { - .signal_pin = UART_MSR_DSR, - .signal_pin_change = UART_MSR_DDSR, - .on = UART_MCR_OUT2, - .off = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2), - .send_pulse = send_pulse_irdeo, - .send_space = send_space_irdeo, - .features = (LIRC_CAN_SET_SEND_DUTY_CYCLE | - LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2) - }, - - [LIRC_IRDEO_REMOTE] = { - .signal_pin = UART_MSR_DSR, - .signal_pin_change = UART_MSR_DDSR, - .on = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2), - .off = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2), - .send_pulse = send_pulse_irdeo, - .send_space = send_space_irdeo, - .features = (LIRC_CAN_SET_SEND_DUTY_CYCLE | - LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2) - }, - - [LIRC_ANIMAX] = { - .signal_pin = UART_MSR_DCD, - .signal_pin_change = UART_MSR_DDCD, - .on = 0, - .off = (UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2), - .send_pulse = NULL, - .send_space = NULL, - .features = LIRC_CAN_REC_MODE2 - }, - - [LIRC_IGOR] = { - .signal_pin = UART_MSR_DSR, - .signal_pin_change = UART_MSR_DDSR, - .on = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR), - .off = (UART_MCR_RTS | UART_MCR_OUT2), - .send_pulse = send_pulse_homebrew, - .send_space = send_space_homebrew, -#ifdef LIRC_SERIAL_TRANSMITTER - .features = (LIRC_CAN_SET_SEND_DUTY_CYCLE | - LIRC_CAN_SET_SEND_CARRIER | - LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2) -#else - .features = LIRC_CAN_REC_MODE2 -#endif - }, - -#if defined(LIRC_SERIAL_NSLU2) - /* - * Modified Linksys Network Storage Link USB 2.0 (NSLU2): - * We receive on CTS of the 2nd serial port (R142,LHS), we - * transmit with a IR diode between GPIO[1] (green status LED), - * and ground (Matthias Goebl <matthias.goebl@goebl.net>). - * See also http://www.nslu2-linux.org for this device - */ - [LIRC_NSLU2] = { - .signal_pin = UART_MSR_CTS, - .signal_pin_change = UART_MSR_DCTS, - .on = (UART_MCR_RTS | UART_MCR_OUT2 | UART_MCR_DTR), - .off = (UART_MCR_RTS | UART_MCR_OUT2), - .send_pulse = send_pulse_homebrew, - .send_space = send_space_homebrew, -#ifdef LIRC_SERIAL_TRANSMITTER - .features = (LIRC_CAN_SET_SEND_DUTY_CYCLE | - LIRC_CAN_SET_SEND_CARRIER | - LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2) -#else - .features = LIRC_CAN_REC_MODE2 -#endif - }, -#endif - -}; - -#define RS_ISR_PASS_LIMIT 256 - -/* - * A long pulse code from a remote might take up to 300 bytes. The - * daemon should read the bytes as soon as they are generated, so take - * the number of keys you think you can push before the daemon runs - * and multiply by 300. The driver will warn you if you overrun this - * buffer. If you have a slow computer or non-busmastering IDE disks, - * maybe you will need to increase this. - */ - -/* This MUST be a power of two! It has to be larger than 1 as well. */ - -#define RBUF_LEN 256 -#define WBUF_LEN 256 - -static int sense = -1; /* -1 = auto, 0 = active high, 1 = active low */ -static int txsense; /* 0 = active high, 1 = active low */ - -#ifndef LIRC_IRQ -#define LIRC_IRQ 4 -#endif -#ifndef LIRC_PORT -#define LIRC_PORT 0x3f8 -#endif - -static int io = LIRC_PORT; -static int irq = LIRC_IRQ; - -static struct timeval lasttv = {0, 0}; - -static struct lirc_buffer rbuf; - -static lirc_t wbuf[WBUF_LEN]; - -static unsigned int freq = 38000; -static unsigned int duty_cycle = 50; - -/* Initialized in init_timing_params() */ -static unsigned long period; -static unsigned long pulse_width; -static unsigned long space_width; - -#if defined(__i386__) -/* - * From: - * Linux I/O port programming mini-HOWTO - * Author: Riku Saikkonen <Riku.Saikkonen@hut.fi> - * v, 28 December 1997 - * - * [...] - * Actually, a port I/O instruction on most ports in the 0-0x3ff range - * takes almost exactly 1 microsecond, so if you're, for example, using - * the parallel port directly, just do additional inb()s from that port - * to delay. - * [...] - */ -/* transmitter latency 1.5625us 0x1.90 - this figure arrived at from - * comment above plus trimming to match actual measured frequency. - * This will be sensitive to cpu speed, though hopefully most of the 1.5us - * is spent in the uart access. Still - for reference test machine was a - * 1.13GHz Athlon system - Steve - */ - -/* - * changed from 400 to 450 as this works better on slower machines; - * faster machines will use the rdtsc code anyway - */ -#define LIRC_SERIAL_TRANSMITTER_LATENCY 450 - -#else - -/* does anybody have information on other platforms ? */ -/* 256 = 1<<8 */ -#define LIRC_SERIAL_TRANSMITTER_LATENCY 256 - -#endif /* __i386__ */ - -static unsigned int sinp(int offset) -{ -#if defined(LIRC_ALLOW_MMAPPED_IO) - if (iommap != 0) { - /* the register is memory-mapped */ - offset <<= ioshift; - return readb(io + offset); - } -#endif - return inb(io + offset); -} - -static void soutp(int offset, int value) -{ -#if defined(LIRC_ALLOW_MMAPPED_IO) - if (iommap != 0) { - /* the register is memory-mapped */ - offset <<= ioshift; - writeb(value, io + offset); - } -#endif - outb(value, io + offset); -} - -static void on(void) -{ -#if defined(LIRC_SERIAL_NSLU2) - /* - * On NSLU2, we put the transmit diode between the output of the green - * status LED and ground - */ - if (type == LIRC_NSLU2) { - gpio_line_set(NSLU2_LED_GRN_GPIO, IXP4XX_GPIO_LOW); - return; - } -#endif - if (txsense) - soutp(UART_MCR, hardware[type].off); - else - soutp(UART_MCR, hardware[type].on); -} - -static void off(void) -{ -#if defined(LIRC_SERIAL_NSLU2) - if (type == LIRC_NSLU2) { - gpio_line_set(NSLU2_LED_GRN_GPIO, IXP4XX_GPIO_HIGH); - return; - } -#endif - if (txsense) - soutp(UART_MCR, hardware[type].on); - else - soutp(UART_MCR, hardware[type].off); -} - -#ifndef MAX_UDELAY_MS -#define MAX_UDELAY_US 5000 -#else -#define MAX_UDELAY_US (MAX_UDELAY_MS*1000) -#endif - -static void safe_udelay(unsigned long usecs) -{ - while (usecs > MAX_UDELAY_US) { - udelay(MAX_UDELAY_US); - usecs -= MAX_UDELAY_US; - } - udelay(usecs); -} - -#ifdef USE_RDTSC -/* - * This is an overflow/precision juggle, complicated in that we can't - * do long long divide in the kernel - */ - -/* - * When we use the rdtsc instruction to measure clocks, we keep the - * pulse and space widths as clock cycles. As this is CPU speed - * dependent, the widths must be calculated in init_port and ioctl - * time - */ - -/* So send_pulse can quickly convert microseconds to clocks */ -static unsigned long conv_us_to_clocks; - -static int init_timing_params(unsigned int new_duty_cycle, - unsigned int new_freq) -{ - unsigned long long loops_per_sec, work; - - duty_cycle = new_duty_cycle; - freq = new_freq; - - loops_per_sec = current_cpu_data.loops_per_jiffy; - loops_per_sec *= HZ; - - /* How many clocks in a microsecond?, avoiding long long divide */ - work = loops_per_sec; - work *= 4295; /* 4295 = 2^32 / 1e6 */ - conv_us_to_clocks = (work >> 32); - - /* - * Carrier period in clocks, approach good up to 32GHz clock, - * gets carrier frequency within 8Hz - */ - period = loops_per_sec >> 3; - period /= (freq >> 3); - - /* Derive pulse and space from the period */ - pulse_width = period * duty_cycle / 100; - space_width = period - pulse_width; - dprintk("in init_timing_params, freq=%d, duty_cycle=%d, " - "clk/jiffy=%ld, pulse=%ld, space=%ld, " - "conv_us_to_clocks=%ld\n", - freq, duty_cycle, current_cpu_data.loops_per_jiffy, - pulse_width, space_width, conv_us_to_clocks); - return 0; -} -#else /* ! USE_RDTSC */ -static int init_timing_params(unsigned int new_duty_cycle, - unsigned int new_freq) -{ -/* - * period, pulse/space width are kept with 8 binary places - - * IE multiplied by 256. - */ - if (256 * 1000000L / new_freq * new_duty_cycle / 100 <= - LIRC_SERIAL_TRANSMITTER_LATENCY) - return -EINVAL; - if (256 * 1000000L / new_freq * (100 - new_duty_cycle) / 100 <= - LIRC_SERIAL_TRANSMITTER_LATENCY) - return -EINVAL; - duty_cycle = new_duty_cycle; - freq = new_freq; - period = 256 * 1000000L / freq; - pulse_width = period * duty_cycle / 100; - space_width = period - pulse_width; - dprintk("in init_timing_params, freq=%d pulse=%ld, " - "space=%ld\n", freq, pulse_width, space_width); - return 0; -} -#endif /* USE_RDTSC */ - - -/* return value: space length delta */ - -static long send_pulse_irdeo(unsigned long length) -{ - long rawbits, ret; - int i; - unsigned char output; - unsigned char chunk, shifted; - - /* how many bits have to be sent ? */ - rawbits = length * 1152 / 10000; - if (duty_cycle > 50) - chunk = 3; - else - chunk = 1; - for (i = 0, output = 0x7f; rawbits > 0; rawbits -= 3) { - shifted = chunk << (i * 3); - shifted >>= 1; - output &= (~shifted); - i++; - if (i == 3) { - soutp(UART_TX, output); - while (!(sinp(UART_LSR) & UART_LSR_THRE)) - ; - output = 0x7f; - i = 0; - } - } - if (i != 0) { - soutp(UART_TX, output); - while (!(sinp(UART_LSR) & UART_LSR_TEMT)) - ; - } - - if (i == 0) - ret = (-rawbits) * 10000 / 1152; - else - ret = (3 - i) * 3 *10000 / 1152 + (-rawbits) * 10000 / 1152; - - return ret; -} - -#ifdef USE_RDTSC -/* Version that uses Pentium rdtsc instruction to measure clocks */ - -/* - * This version does sub-microsecond timing using rdtsc instruction, - * and does away with the fudged LIRC_SERIAL_TRANSMITTER_LATENCY - * Implicitly i586 architecture... - Steve - */ - -static long send_pulse_homebrew_softcarrier(unsigned long length) -{ - int flag; - unsigned long target, start, now; - - /* Get going quick as we can */ - rdtscl(start); - on(); - /* Convert length from microseconds to clocks */ - length *= conv_us_to_clocks; - /* And loop till time is up - flipping at right intervals */ - now = start; - target = pulse_width; - flag = 1; - while ((now - start) < length) { - /* Delay till flip time */ - do { - rdtscl(now); - } while ((now - start) < target); - - /* flip */ - if (flag) { - rdtscl(now); - off(); - target += space_width; - } else { - rdtscl(now); on(); - target += pulse_width; - } - flag = !flag; - } - rdtscl(now); - return ((now - start) - length) / conv_us_to_clocks; -} -#else /* ! USE_RDTSC */ -/* Version using udelay() */ - -/* - * here we use fixed point arithmetic, with 8 - * fractional bits. that gets us within 0.1% or so of the right average - * frequency, albeit with some jitter in pulse length - Steve - */ - -/* To match 8 fractional bits used for pulse/space length */ - -static long send_pulse_homebrew_softcarrier(unsigned long length) -{ - int flag; - unsigned long actual, target, d; - length <<= 8; - - actual = 0; target = 0; flag = 0; - while (actual < length) { - if (flag) { - off(); - target += space_width; - } else { - on(); - target += pulse_width; - } - d = (target - actual - - LIRC_SERIAL_TRANSMITTER_LATENCY + 128) >> 8; - /* - * Note - we've checked in ioctl that the pulse/space - * widths are big enough so that d is > 0 - */ - udelay(d); - actual += (d << 8) + LIRC_SERIAL_TRANSMITTER_LATENCY; - flag = !flag; - } - return (actual-length) >> 8; -} -#endif /* USE_RDTSC */ - -static long send_pulse_homebrew(unsigned long length) -{ - if (length <= 0) - return 0; - - if (softcarrier) - return send_pulse_homebrew_softcarrier(length); - else { - on(); - safe_udelay(length); - return 0; - } -} - -static void send_space_irdeo(long length) -{ - if (length <= 0) - return; - - safe_udelay(length); -} - -static void send_space_homebrew(long length) -{ - off(); - if (length <= 0) - return; - safe_udelay(length); -} - -static void rbwrite(lirc_t l) -{ - if (lirc_buffer_full(&rbuf)) { - /* no new signals will be accepted */ - dprintk("Buffer overrun\n"); - return; - } - lirc_buffer_write(&rbuf, (void *)&l); -} - -static void frbwrite(lirc_t l) -{ - /* simple noise filter */ - static lirc_t pulse = 0L, space = 0L; - static unsigned int ptr; - - if (ptr > 0 && (l & PULSE_BIT)) { - pulse += l & PULSE_MASK; - if (pulse > 250) { - rbwrite(space); - rbwrite(pulse | PULSE_BIT); - ptr = 0; - pulse = 0; - } - return; - } - if (!(l & PULSE_BIT)) { - if (ptr == 0) { - if (l > 20000) { - space = l; - ptr++; - return; - } - } else { - if (l > 20000) { - space += pulse; - if (space > PULSE_MASK) - space = PULSE_MASK; - space += l; - if (space > PULSE_MASK) - space = PULSE_MASK; - pulse = 0; - return; - } - rbwrite(space); - rbwrite(pulse | PULSE_BIT); - ptr = 0; - pulse = 0; - } - } - rbwrite(l); -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) -static irqreturn_t irq_handler(int i, void *blah) -#else -static irqreturn_t irq_handler(int i, void *blah, struct pt_regs *regs) -#endif -{ - struct timeval tv; - int status, counter, dcd; - long deltv; - lirc_t data; - static int last_dcd = -1; - - if ((sinp(UART_IIR) & UART_IIR_NO_INT)) { - /* not our interrupt */ - return IRQ_RETVAL(IRQ_NONE); - } - - counter = 0; - do { - counter++; - status = sinp(UART_MSR); - if (counter > RS_ISR_PASS_LIMIT) { - printk(KERN_WARNING LIRC_DRIVER_NAME ": AIEEEE: " - "We're caught!\n"); - break; - } - if ((status & hardware[type].signal_pin_change) - && sense != -1) { - /* get current time */ - do_gettimeofday(&tv); - - /* New mode, written by Trent Piepho - <xyzzy@u.washington.edu>. */ - - /* - * The old format was not very portable. - * We now use an int to pass pulses - * and spaces to user space. - * - * If PULSE_BIT is set a pulse has been - * received, otherwise a space has been - * received. The driver needs to know if your - * receiver is active high or active low, or - * the space/pulse sense could be - * inverted. The bits denoted by PULSE_MASK are - * the length in microseconds. Lengths greater - * than or equal to 16 seconds are clamped to - * PULSE_MASK. All other bits are unused. - * This is a much simpler interface for user - * programs, as well as eliminating "out of - * phase" errors with space/pulse - * autodetection. - */ - - /* calc time since last interrupt in microseconds */ - dcd = (status & hardware[type].signal_pin) ? 1 : 0; - - if (dcd == last_dcd) { - printk(KERN_WARNING LIRC_DRIVER_NAME - ": ignoring spike: %d %d %lx %lx %lx %lx\n", - dcd, sense, - tv.tv_sec, lasttv.tv_sec, - tv.tv_usec, lasttv.tv_usec); - continue; - } - - deltv = tv.tv_sec-lasttv.tv_sec; - if (tv.tv_sec < lasttv.tv_sec || - (tv.tv_sec == lasttv.tv_sec && - tv.tv_usec < lasttv.tv_usec)) { - printk(KERN_WARNING LIRC_DRIVER_NAME - ": AIEEEE: your clock just jumped " - "backwards\n"); - printk(KERN_WARNING LIRC_DRIVER_NAME - ": %d %d %lx %lx %lx %lx\n", - dcd, sense, - tv.tv_sec, lasttv.tv_sec, - tv.tv_usec, lasttv.tv_usec); - data = PULSE_MASK; - } else if (deltv > 15) { - data = PULSE_MASK; /* really long time */ - if (!(dcd^sense)) { - /* sanity check */ - printk(KERN_WARNING LIRC_DRIVER_NAME - ": AIEEEE: " - "%d %d %lx %lx %lx %lx\n", - dcd, sense, - tv.tv_sec, lasttv.tv_sec, - tv.tv_usec, lasttv.tv_usec); - /* - * detecting pulse while this - * MUST be a space! - */ - sense = sense ? 0 : 1; - } - } else - data = (lirc_t) (deltv*1000000 + - tv.tv_usec - - lasttv.tv_usec); - frbwrite(dcd^sense ? data : (data|PULSE_BIT)); - lasttv = tv; - last_dcd = dcd; - wake_up_interruptible(&rbuf.wait_poll); - } - } while (!(sinp(UART_IIR) & UART_IIR_NO_INT)); /* still pending ? */ - return IRQ_RETVAL(IRQ_HANDLED); -} - -static void hardware_init_port(void) -{ - unsigned long flags; - local_irq_save(flags); - - /* Set DLAB 0. */ - soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); - - /* First of all, disable all interrupts */ - soutp(UART_IER, sinp(UART_IER) & - (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); - - /* Clear registers. */ - sinp(UART_LSR); - sinp(UART_RX); - sinp(UART_IIR); - sinp(UART_MSR); - -#if defined(LIRC_SERIAL_NSLU2) - if (type == LIRC_NSLU2) { - /* Setup NSLU2 UART */ - - /* Enable UART */ - soutp(UART_IER, sinp(UART_IER) | UART_IE_IXP42X_UUE); - /* Disable Receiver data Time out interrupt */ - soutp(UART_IER, sinp(UART_IER) & ~UART_IE_IXP42X_RTOIE); - /* set out2 = interrupt unmask; off() doesn't set MCR - on NSLU2 */ - soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2); - } -#endif - - /* Set line for power source */ - off(); - - /* Clear registers again to be sure. */ - sinp(UART_LSR); - sinp(UART_RX); - sinp(UART_IIR); - sinp(UART_MSR); - - switch (type) { - case LIRC_IRDEO: - case LIRC_IRDEO_REMOTE: - /* setup port to 7N1 @ 115200 Baud */ - /* 7N1+start = 9 bits at 115200 ~ 3 bits at 38kHz */ - - /* Set DLAB 1. */ - soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB); - /* Set divisor to 1 => 115200 Baud */ - soutp(UART_DLM, 0); - soutp(UART_DLL, 1); - /* Set DLAB 0 + 7N1 */ - soutp(UART_LCR, UART_LCR_WLEN7); - /* THR interrupt already disabled at this point */ - break; - default: - break; - } - - local_irq_restore(flags); -} - -static int init_port(void) -{ - int i, nlow, nhigh; - - /* Reserve io region. */ -#if defined(LIRC_ALLOW_MMAPPED_IO) - /* - * Future MMAP-Developers: Attention! - * For memory mapped I/O you *might* need to use ioremap() first, - * for the NSLU2 it's done in boot code. - */ - if (((iommap != 0) - && (request_mem_region(iommap, 8 << ioshift, - LIRC_DRIVER_NAME) == NULL)) - || ((iommap == 0) - && (request_region(io, 8, LIRC_DRIVER_NAME) == NULL))) { -#else - if (request_region(io, 8, LIRC_DRIVER_NAME) == NULL) { -#endif - printk(KERN_ERR LIRC_DRIVER_NAME - ": port %04x already in use\n", io); - printk(KERN_WARNING LIRC_DRIVER_NAME - ": use 'setserial /dev/ttySX uart none'\n"); - printk(KERN_WARNING LIRC_DRIVER_NAME - ": or compile the serial port driver as module and\n"); - printk(KERN_WARNING LIRC_DRIVER_NAME - ": make sure this module is loaded first\n"); - return -EBUSY; - } - - hardware_init_port(); - - /* Initialize pulse/space widths */ - init_timing_params(duty_cycle, freq); - - /* If pin is high, then this must be an active low receiver. */ - if (sense == -1) { - /* wait 1/2 sec for the power supply */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11) - msleep(500); -#else - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/2); -#endif - - /* - * probe 9 times every 0.04s, collect "votes" for - * active high/low - */ - nlow = 0; - nhigh = 0; - for (i = 0; i < 9; i++) { - if (sinp(UART_MSR) & hardware[type].signal_pin) - nlow++; - else - nhigh++; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11) - msleep(40); -#else - schedule_timeout(HZ/25); -#endif - } - sense = (nlow >= nhigh ? 1 : 0); - printk(KERN_INFO LIRC_DRIVER_NAME ": auto-detected active " - "%s receiver\n", sense ? "low" : "high"); - } else - printk(KERN_INFO LIRC_DRIVER_NAME ": Manually using active " - "%s receiver\n", sense ? "low" : "high"); - - return 0; -} - -static int set_use_inc(void *data) -{ - int result; - unsigned long flags; - - /* Init read buffer. */ - if (lirc_buffer_init(&rbuf, sizeof(lirc_t), RBUF_LEN) < 0) - return -ENOMEM; - - /* initialize timestamp */ - do_gettimeofday(&lasttv); - - result = request_irq(irq, irq_handler, - IRQF_DISABLED | (share_irq ? IRQF_SHARED : 0), - LIRC_DRIVER_NAME, (void *)&hardware); - - switch (result) { - case -EBUSY: - printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n", irq); - lirc_buffer_free(&rbuf); - return -EBUSY; - case -EINVAL: - printk(KERN_ERR LIRC_DRIVER_NAME - ": Bad irq number or handler\n"); - lirc_buffer_free(&rbuf); - return -EINVAL; - default: - dprintk("Interrupt %d, port %04x obtained\n", irq, io); - break; - }; - - local_irq_save(flags); - - /* Set DLAB 0. */ - soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); - - soutp(UART_IER, sinp(UART_IER)|UART_IER_MSI); - - local_irq_restore(flags); - - MOD_INC_USE_COUNT; - return 0; -} - -static void set_use_dec(void *data) -{ unsigned long flags; - - local_irq_save(flags); - - /* Set DLAB 0. */ - soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); - - /* First of all, disable all interrupts */ - soutp(UART_IER, sinp(UART_IER) & - (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); - local_irq_restore(flags); - - free_irq(irq, (void *)&hardware); - - dprintk("freed IRQ %d\n", irq); - lirc_buffer_free(&rbuf); - - MOD_DEC_USE_COUNT; -} - -static ssize_t lirc_write(struct file *file, const char *buf, - size_t n, loff_t *ppos) -{ - int i, count; - unsigned long flags; - long delta = 0; - - if (!(hardware[type].features&LIRC_CAN_SEND_PULSE)) - return -EBADF; - - if (n % sizeof(lirc_t)) - return -EINVAL; - count = n / sizeof(lirc_t); - if (count > WBUF_LEN || count % 2 == 0) - return -EINVAL; - if (copy_from_user(wbuf, buf, n)) - return -EFAULT; - local_irq_save(flags); - if (type == LIRC_IRDEO) { - /* DTR, RTS down */ - on(); - } - for (i = 0; i < count; i++) { - if (i%2) - hardware[type].send_space(wbuf[i]-delta); - else - delta = hardware[type].send_pulse(wbuf[i]); - } - off(); - local_irq_restore(flags); - return n; -} - -static int lirc_ioctl(struct inode *node, struct file *filep, unsigned int cmd, - unsigned long arg) -{ - int result; - unsigned long value; - unsigned int ivalue; - - switch (cmd) { - case LIRC_GET_SEND_MODE: - if (!(hardware[type].features&LIRC_CAN_SEND_MASK)) - return -ENOIOCTLCMD; - - result = put_user(LIRC_SEND2MODE - (hardware[type].features&LIRC_CAN_SEND_MASK), - (unsigned long *) arg); - if (result) - return result; - break; - - case LIRC_SET_SEND_MODE: - if (!(hardware[type].features&LIRC_CAN_SEND_MASK)) - return -ENOIOCTLCMD; - - result = get_user(value, (unsigned long *) arg); - if (result) - return result; - /* only LIRC_MODE_PULSE supported */ - if (value != LIRC_MODE_PULSE) - return -ENOSYS; - break; - - case LIRC_GET_LENGTH: - return -ENOSYS; - break; - - case LIRC_SET_SEND_DUTY_CYCLE: - dprintk("SET_SEND_DUTY_CYCLE\n"); - if (!(hardware[type].features&LIRC_CAN_SET_SEND_DUTY_CYCLE)) - return -ENOIOCTLCMD; - - result = get_user(ivalue, (unsigned int *) arg); - if (result) - return result; - if (ivalue <= 0 || ivalue > 100) - return -EINVAL; - return init_timing_params(ivalue, freq); - break; - - case LIRC_SET_SEND_CARRIER: - dprintk("SET_SEND_CARRIER\n"); - if (!(hardware[type].features&LIRC_CAN_SET_SEND_CARRIER)) - return -ENOIOCTLCMD; - - result = get_user(ivalue, (unsigned int *) arg); - if (result) - return result; - if (ivalue > 500000 || ivalue < 20000) - return -EINVAL; - return init_timing_params(duty_cycle, ivalue); - break; - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static struct file_operations lirc_fops = { - .owner = THIS_MODULE, - .write = lirc_write, - .ioctl = lirc_ioctl, -}; - -static struct lirc_driver driver = { - .name = LIRC_DRIVER_NAME, - .minor = -1, - .code_length = 1, - .sample_rate = 0, - .data = NULL, - .add_to_buf = NULL, -#ifndef LIRC_REMOVE_DURING_EXPORT - .get_queue = NULL, -#endif - .rbuf = &rbuf, - .set_use_inc = set_use_inc, - .set_use_dec = set_use_dec, - .fops = &lirc_fops, - .dev = NULL, - .owner = THIS_MODULE, -}; - -#ifdef MODULE - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) -static struct platform_device *lirc_serial_dev; - -static int __devinit lirc_serial_probe(struct platform_device *dev) -{ - return 0; -} - -static int __devexit lirc_serial_remove(struct platform_device *dev) -{ - return 0; -} - -static int lirc_serial_suspend(struct platform_device *dev, - pm_message_t state) -{ - /* Set DLAB 0. */ - soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); - - /* Disable all interrupts */ - soutp(UART_IER, sinp(UART_IER) & - (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); - - /* Clear registers. */ - sinp(UART_LSR); - sinp(UART_RX); - sinp(UART_IIR); - sinp(UART_MSR); - - return 0; -} - -static int lirc_serial_resume(struct platform_device *dev) -{ - unsigned long flags; - - hardware_init_port(); - - local_irq_save(flags); - /* Enable Interrupt */ - do_gettimeofday(&lasttv); - soutp(UART_IER, sinp(UART_IER)|UART_IER_MSI); - off(); - - lirc_buffer_clear(&rbuf); - - local_irq_restore(flags); - - return 0; -} - -static struct platform_driver lirc_serial_driver = { - .probe = lirc_serial_probe, - .remove = __devexit_p(lirc_serial_remove), - .suspend = lirc_serial_suspend, - .resume = lirc_serial_resume, - .driver = { - .name = "lirc_serial", - .owner = THIS_MODULE, - }, -}; - -static int __init lirc_serial_init(void) -{ - int result; - - result = platform_driver_register(&lirc_serial_driver); - if (result) { - printk("lirc register returned %d\n", result); - return result; - } - - lirc_serial_dev = platform_device_alloc("lirc_serial", 0); - if (!lirc_serial_dev) { - result = -ENOMEM; - goto exit_driver_unregister; - } - - result = platform_device_add(lirc_serial_dev); - if (result) - goto exit_device_put; - - return 0; - -exit_device_put: - platform_device_put(lirc_serial_dev); -exit_driver_unregister: - platform_driver_unregister(&lirc_serial_driver); - return result; -} - -static void __exit lirc_serial_exit(void) -{ - platform_device_unregister(lirc_serial_dev); - platform_driver_unregister(&lirc_serial_driver); -} -#endif - -static int __init lirc_serial_init_module(void) -{ - int result; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) - result = lirc_serial_init(); - if (result) - return result; -#endif - switch (type) { - case LIRC_HOMEBREW: - case LIRC_IRDEO: - case LIRC_IRDEO_REMOTE: - case LIRC_ANIMAX: - case LIRC_IGOR: -#if defined(LIRC_SERIAL_NSLU2) - case LIRC_NSLU2: -#endif - break; - default: - result = -EINVAL; - goto exit_serial_exit; - } - if (!softcarrier) { - switch (type) { - case LIRC_HOMEBREW: - case LIRC_IGOR: - case LIRC_NSLU2: - hardware[type].features &= - ~(LIRC_CAN_SET_SEND_DUTY_CYCLE| - LIRC_CAN_SET_SEND_CARRIER); - break; - } - } - - result = init_port(); - if (result < 0) - goto exit_serial_exit; - driver.features = hardware[type].features; - driver.minor = lirc_register_driver(&driver); - if (driver.minor < 0) { - printk(KERN_ERR LIRC_DRIVER_NAME - ": register_chrdev failed!\n"); - result = -EIO; - goto exit_release; - } - - printk(KERN_INFO - LIRC_DRIVER_NAME " " LIRC_DRIVER_VERSION " registered\n"); - dprintk("type = %d\n", type); - dprintk("IRQ = %d, port = %04x\n", irq, io); - dprintk("share_irq = %d\n", share_irq); -#ifdef LIRC_SERIAL_TRANSMITTER - dprintk("txsense = %d\n", txsense); -#endif - dprintk("softcarrier = %d\n", softcarrier); - - return 0; -exit_release: - release_region(io, 8); -exit_serial_exit: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) - lirc_serial_exit(); -#endif - return result; -} - -static void __exit lirc_serial_exit_module(void) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) - lirc_serial_exit(); -#endif -#if defined(LIRC_ALLOW_MMAPPED_IO) - if (iommap != 0) - release_mem_region(iommap, 8 << ioshift); - else - release_region(io, 8); -#else - release_region(io, 8); -#endif - lirc_unregister_driver(driver.minor); - dprintk("cleaned up module\n"); -} - - -module_init(lirc_serial_init_module); -module_exit(lirc_serial_exit_module); - -MODULE_DESCRIPTION("Infra-red receiver driver for serial ports."); -MODULE_AUTHOR("Ralph Metzler, Trent Piepho, Ben Pfaff, " - "Christoph Bartelmus, Andrei Tanas"); -MODULE_LICENSE("GPL"); - -module_param(type, int, S_IRUGO); -#if defined(LIRC_SERIAL_NSLU2) -MODULE_PARM_DESC(type, "Hardware type (0 = home-brew, 1 = IRdeo," - " 2 = IRdeo Remote, 3 = AnimaX, 4 = IgorPlug," - " 5 = NSLU2 RX:CTS2/TX:GreenLED)"); -#else -MODULE_PARM_DESC(type, "Hardware type (0 = home-brew, 1 = IRdeo," - " 2 = IRdeo Remote, 3 = AnimaX, 4 = IgorPlug)"); -#endif - -module_param(io, int, S_IRUGO); -MODULE_PARM_DESC(io, "I/O address base (0x3f8 or 0x2f8)"); - -#if defined(LIRC_ALLOW_MMAPPED_IO) -/* some architectures (e.g. intel xscale) have memory mapped registers */ -module_param(iommap, bool, S_IRUGO); -MODULE_PARM_DESC(iommap, "physical base for memory mapped I/O" - " (0 = no memory mapped io)"); - -/* - * some architectures (e.g. intel xscale) align the 8bit serial registers - * on 32bit word boundaries. - * See linux-kernel/serial/8250.c serial_in()/out() - */ -module_param(ioshift, int, S_IRUGO); -MODULE_PARM_DESC(ioshift, "shift I/O register offset (0 = no shift)"); -#endif - -module_param(irq, int, S_IRUGO); -MODULE_PARM_DESC(irq, "Interrupt (4 or 3)"); - -module_param(share_irq, bool, S_IRUGO); -MODULE_PARM_DESC(share_irq, "Share interrupts (0 = off, 1 = on)"); - -module_param(sense, bool, S_IRUGO); -MODULE_PARM_DESC(sense, "Override autodetection of IR receiver circuit" - " (0 = active high, 1 = active low )"); - -#ifdef LIRC_SERIAL_TRANSMITTER -module_param(txsense, bool, S_IRUGO); -MODULE_PARM_DESC(txsense, "Sense of transmitter circuit" - " (0 = active high, 1 = active low )"); -#endif - -module_param(softcarrier, bool, S_IRUGO); -MODULE_PARM_DESC(softcarrier, "Software carrier (0 = off, 1 = on)"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Enable debugging messages"); - -EXPORT_NO_SYMBOLS; - -#endif /* MODULE */ diff --git a/ubuntu/lirc/lirc_sir/Makefile b/ubuntu/lirc/lirc_sir/Makefile deleted file mode 100644 index e9afc76e5e4..00000000000 --- a/ubuntu/lirc/lirc_sir/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. - -obj-$(CONFIG_LIRC_SIR) += lirc_sir.o diff --git a/ubuntu/lirc/lirc_sir/lirc_sir.c b/ubuntu/lirc/lirc_sir/lirc_sir.c deleted file mode 100644 index 2e4cbb8c915..00000000000 --- a/ubuntu/lirc/lirc_sir/lirc_sir.c +++ /dev/null @@ -1,1345 +0,0 @@ -/* - * LIRC SIR driver, (C) 2000 Milan Pikula <www@fornax.sk> - * - * lirc_sir - Device driver for use with SIR (serial infra red) - * mode of IrDA on many notebooks. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * 2000/09/16 Frank Przybylski <mail@frankprzybylski.de> : - * added timeout and relaxed pulse detection, removed gap bug - * - * 2000/12/15 Christoph Bartelmus <lirc@bartelmus.de> : - * added support for Tekram Irmate 210 (sending does not work yet, - * kind of disappointing that nobody was able to implement that - * before), - * major clean-up - * - * 2001/02/27 Christoph Bartelmus <lirc@bartelmus.de> : - * added support for StrongARM SA1100 embedded microprocessor - * parts cut'n'pasted from sa1100_ir.c (C) 2000 Russell King - */ - -#include <linux/version.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18) -#error "**********************************************************" -#error " Sorry, this driver needs kernel version 2.2.18 or higher " -#error "**********************************************************" -#endif -#include <linux/module.h> - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/signal.h> -#include <linux/fs.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/kernel.h> -#include <linux/serial_reg.h> -#include <linux/time.h> -#include <linux/string.h> -#include <linux/types.h> -#include <linux/wait.h> -#include <linux/mm.h> -#include <linux/delay.h> -#include <linux/poll.h> -#include <asm/system.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) -#include <asm/uaccess.h> -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16) -#include <asm/io.h> -#else -#include <linux/io.h> -#endif -#include <asm/irq.h> -#include <linux/fcntl.h> -#ifdef LIRC_ON_SA1100 -#include <asm/hardware.h> -#ifdef CONFIG_SA1100_COLLIE -#include <asm/arch/tc35143.h> -#include <asm/ucb1200.h> -#endif -#endif - -#include <linux/timer.h> - -#include "../lirc.h" -#include "../lirc_dev/lirc_dev.h" -#include "../kcompat.h" - -/* SECTION: Definitions */ - -/*** Tekram dongle ***/ -#ifdef LIRC_SIR_TEKRAM -/* stolen from kernel source */ -/* definitions for Tekram dongle */ -#define TEKRAM_115200 0x00 -#define TEKRAM_57600 0x01 -#define TEKRAM_38400 0x02 -#define TEKRAM_19200 0x03 -#define TEKRAM_9600 0x04 -#define TEKRAM_2400 0x08 - -#define TEKRAM_PW 0x10 /* Pulse select bit */ - -/* 10bit * 1s/115200bit in milliseconds = 87ms*/ -#define TIME_CONST (10000000ul/115200ul) - -#endif - -#ifdef LIRC_SIR_ACTISYS_ACT200L -static void init_act200(void); -#elif defined(LIRC_SIR_ACTISYS_ACT220L) -static void init_act220(void); -#endif - -/*** SA1100 ***/ -#ifdef LIRC_ON_SA1100 -struct sa1100_ser2_registers { - /* HSSP control register */ - unsigned char hscr0; - /* UART registers */ - unsigned char utcr0; - unsigned char utcr1; - unsigned char utcr2; - unsigned char utcr3; - unsigned char utcr4; - unsigned char utdr; - unsigned char utsr0; - unsigned char utsr1; -} sr; - -static int irq = IRQ_Ser2ICP; - -#define LIRC_ON_SA1100_TRANSMITTER_LATENCY 0 - -/* pulse/space ratio of 50/50 */ -static unsigned long pulse_width = (13-LIRC_ON_SA1100_TRANSMITTER_LATENCY); -/* 1000000/freq-pulse_width */ -static unsigned long space_width = (13-LIRC_ON_SA1100_TRANSMITTER_LATENCY); -static unsigned int freq = 38000; /* modulation frequency */ -static unsigned int duty_cycle = 50; /* duty cycle of 50% */ - -#endif - -#define RBUF_LEN 1024 -#define WBUF_LEN 1024 - -#define LIRC_DRIVER_NAME "lirc_sir" - -#define PULSE '[' - -#ifndef LIRC_SIR_TEKRAM -/* 9bit * 1s/115200bit in milli seconds = 78.125ms*/ -#define TIME_CONST (9000000ul/115200ul) -#endif - - -/* timeout for sequences in jiffies (=5/100s), must be longer than TIME_CONST */ -#define SIR_TIMEOUT (HZ*5/100) - -#ifndef LIRC_ON_SA1100 -#ifndef LIRC_IRQ -#define LIRC_IRQ 4 -#endif -#ifndef LIRC_PORT -/* for external dongles, default to com1 */ -#if defined(LIRC_SIR_ACTISYS_ACT200L) || \ - defined(LIRC_SIR_ACTISYS_ACT220L) || \ - defined(LIRC_SIR_TEKRAM) -#define LIRC_PORT 0x3f8 -#else -/* onboard sir ports are typically com3 */ -#define LIRC_PORT 0x3e8 -#endif -#endif - -static int io = LIRC_PORT; -static int irq = LIRC_IRQ; -static int threshold = 3; -#endif - -static DEFINE_SPINLOCK(timer_lock); -static struct timer_list timerlist; -/* time of last signal change detected */ -static struct timeval last_tv = {0, 0}; -/* time of last UART data ready interrupt */ -static struct timeval last_intr_tv = {0, 0}; -static int last_value; - -static DECLARE_WAIT_QUEUE_HEAD(lirc_read_queue); - -static DEFINE_SPINLOCK(hardware_lock); -static DEFINE_SPINLOCK(dev_lock); - -static lirc_t rx_buf[RBUF_LEN]; -static unsigned int rx_tail, rx_head; -static lirc_t tx_buf[WBUF_LEN]; - -static int debug; -#define dprintk(fmt, args...) \ - do { \ - if (debug) \ - printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ - fmt, ## args); \ - } while (0) - -/* SECTION: Prototypes */ - -/* Communication with user-space */ -static int lirc_open(struct inode *inode, struct file *file); -static int lirc_close(struct inode *inode, struct file *file); -static unsigned int lirc_poll(struct file *file, poll_table *wait); -static ssize_t lirc_read(struct file *file, char *buf, size_t count, - loff_t *ppos); -static ssize_t lirc_write(struct file *file, const char *buf, size_t n, - loff_t *pos); -static int lirc_ioctl(struct inode *node, struct file *filep, unsigned int cmd, - unsigned long arg); -static void add_read_queue(int flag, unsigned long val); -#ifdef MODULE -static int init_chrdev(void); -static void drop_chrdev(void); -#endif -/* Hardware */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -static irqreturn_t sir_interrupt(int irq, void *dev_id, - struct pt_regs *regs); -#else -static irqreturn_t sir_interrupt(int irq, void *dev_id); -#endif -static void send_space(unsigned long len); -static void send_pulse(unsigned long len); -static int init_hardware(void); -static void drop_hardware(void); -/* Initialisation */ -static int init_port(void); -static void drop_port(void); - -#ifdef LIRC_ON_SA1100 -static void on(void) -{ - PPSR |= PPC_TXD2; -} - -static void off(void) -{ - PPSR &= ~PPC_TXD2; -} -#else -static unsigned int sinp(int offset) -{ - return inb(io + offset); -} - -static void soutp(int offset, int value) -{ - outb(value, io + offset); -} -#endif - -#ifndef MAX_UDELAY_MS -#define MAX_UDELAY_US 5000 -#else -#define MAX_UDELAY_US (MAX_UDELAY_MS*1000) -#endif - -static void safe_udelay(unsigned long usecs) -{ - while (usecs > MAX_UDELAY_US) { - udelay(MAX_UDELAY_US); - usecs -= MAX_UDELAY_US; - } - udelay(usecs); -} - -/* SECTION: Communication with user-space */ - -static int lirc_open(struct inode *inode, struct file *file) -{ - spin_lock(&dev_lock); - if (MOD_IN_USE) { - spin_unlock(&dev_lock); - return -EBUSY; - } - MOD_INC_USE_COUNT; - spin_unlock(&dev_lock); - return 0; -} - -static int lirc_close(struct inode *inode, struct file *file) -{ - MOD_DEC_USE_COUNT; - return 0; -} - -static unsigned int lirc_poll(struct file *file, poll_table *wait) -{ - poll_wait(file, &lirc_read_queue, wait); - if (rx_head != rx_tail) - return POLLIN | POLLRDNORM; - return 0; -} - -static ssize_t lirc_read(struct file *file, char *buf, size_t count, - loff_t *ppos) -{ - int n = 0; - int retval = 0; - DECLARE_WAITQUEUE(wait, current); - - if (count % sizeof(lirc_t)) - return -EINVAL; - - add_wait_queue(&lirc_read_queue, &wait); - set_current_state(TASK_INTERRUPTIBLE); - while (n < count) { - if (rx_head != rx_tail) { - if (copy_to_user((void *) buf + n, - (void *) (rx_buf + rx_head), - sizeof(lirc_t))) { - retval = -EFAULT; - break; - } - rx_head = (rx_head + 1) & (RBUF_LEN - 1); - n += sizeof(lirc_t); - } else { - if (file->f_flags & O_NONBLOCK) { - retval = -EAGAIN; - break; - } - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - schedule(); - set_current_state(TASK_INTERRUPTIBLE); - } - } - remove_wait_queue(&lirc_read_queue, &wait); - set_current_state(TASK_RUNNING); - return n ? n : retval; -} -static ssize_t lirc_write(struct file *file, const char *buf, size_t n, - loff_t *pos) -{ - unsigned long flags; - int i; - - if (n % sizeof(lirc_t) || (n / sizeof(lirc_t)) > WBUF_LEN) - return -EINVAL; - if (copy_from_user(tx_buf, buf, n)) - return -EFAULT; - i = 0; - n /= sizeof(lirc_t); -#ifdef LIRC_ON_SA1100 - /* disable receiver */ - Ser2UTCR3 = 0; -#endif - local_irq_save(flags); - while (1) { - if (i >= n) - break; - if (tx_buf[i]) - send_pulse(tx_buf[i]); - i++; - if (i >= n) - break; - if (tx_buf[i]) - send_space(tx_buf[i]); - i++; - } - local_irq_restore(flags); -#ifdef LIRC_ON_SA1100 - off(); - udelay(1000); /* wait 1ms for IR diode to recover */ - Ser2UTCR3 = 0; - /* clear status register to prevent unwanted interrupts */ - Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB); - /* enable receiver */ - Ser2UTCR3 = UTCR3_RXE|UTCR3_RIE; -#endif - return n; -} - -static int lirc_ioctl(struct inode *node, struct file *filep, unsigned int cmd, - unsigned long arg) -{ - int retval = 0; - unsigned long value = 0; -#ifdef LIRC_ON_SA1100 - unsigned int ivalue; - - if (cmd == LIRC_GET_FEATURES) - value = LIRC_CAN_SEND_PULSE | - LIRC_CAN_SET_SEND_DUTY_CYCLE | - LIRC_CAN_SET_SEND_CARRIER | - LIRC_CAN_REC_MODE2; - else if (cmd == LIRC_GET_SEND_MODE) - value = LIRC_MODE_PULSE; - else if (cmd == LIRC_GET_REC_MODE) - value = LIRC_MODE_MODE2; -#else - if (cmd == LIRC_GET_FEATURES) - value = LIRC_CAN_SEND_PULSE | LIRC_CAN_REC_MODE2; - else if (cmd == LIRC_GET_SEND_MODE) - value = LIRC_MODE_PULSE; - else if (cmd == LIRC_GET_REC_MODE) - value = LIRC_MODE_MODE2; -#endif - - switch (cmd) { - case LIRC_GET_FEATURES: - case LIRC_GET_SEND_MODE: - case LIRC_GET_REC_MODE: - retval = put_user(value, (unsigned long *) arg); - break; - - case LIRC_SET_SEND_MODE: - case LIRC_SET_REC_MODE: - retval = get_user(value, (unsigned long *) arg); - break; -#ifdef LIRC_ON_SA1100 - case LIRC_SET_SEND_DUTY_CYCLE: - retval = get_user(ivalue, (unsigned int *) arg); - if (retval) - return reetval; - if (ivalue <= 0 || ivalue > 100) - return -EINVAL; - /* (ivalue/100)*(1000000/freq) */ - duty_cycle = ivalue; - pulse_width = (unsigned long) duty_cycle*10000/freq; - space_width = (unsigned long) 1000000L/freq-pulse_width; - if (pulse_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY) - pulse_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY; - if (space_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY) - space_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY; - break; - case LIRC_SET_SEND_CARRIER: - retval = get_user(ivalue, (unsigned int *) arg); - if (retval) - return retval; - if (ivalue > 500000 || ivalue < 20000) - return -EINVAL; - freq = ivalue; - pulse_width = (unsigned long) duty_cycle*10000/freq; - space_width = (unsigned long) 1000000L/freq-pulse_width; - if (pulse_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY) - pulse_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY; - if (space_width >= LIRC_ON_SA1100_TRANSMITTER_LATENCY) - space_width -= LIRC_ON_SA1100_TRANSMITTER_LATENCY; - break; -#endif - default: - retval = -ENOIOCTLCMD; - - } - - if (retval) - return retval; - if (cmd == LIRC_SET_REC_MODE) { - if (value != LIRC_MODE_MODE2) - retval = -ENOSYS; - } else if (cmd == LIRC_SET_SEND_MODE) { - if (value != LIRC_MODE_PULSE) - retval = -ENOSYS; - } - - return retval; -} - -static void add_read_queue(int flag, unsigned long val) -{ - unsigned int new_rx_tail; - lirc_t newval; - - dprintk("add flag %d with val %lu\n", flag, val); - - newval = val & PULSE_MASK; - - /* - * statistically, pulses are ~TIME_CONST/2 too long. we could - * maybe make this more exact, but this is good enough - */ - if (flag) { - /* pulse */ - if (newval > TIME_CONST/2) - newval -= TIME_CONST/2; - else /* should not ever happen */ - newval = 1; - newval |= PULSE_BIT; - } else { - newval += TIME_CONST/2; - } - new_rx_tail = (rx_tail + 1) & (RBUF_LEN - 1); - if (new_rx_tail == rx_head) { - dprintk("Buffer overrun.\n"); - return; - } - rx_buf[rx_tail] = newval; - rx_tail = new_rx_tail; - wake_up_interruptible(&lirc_read_queue); -} - -static struct file_operations lirc_fops = { - .owner = THIS_MODULE, - .read = lirc_read, - .write = lirc_write, - .poll = lirc_poll, - .ioctl = lirc_ioctl, - .open = lirc_open, - .release = lirc_close, -}; - -static int set_use_inc(void *data) -{ - return 0; -} - -static void set_use_dec(void *data) -{ -} - -static struct lirc_driver driver = { - .name = LIRC_DRIVER_NAME, - .minor = -1, - .code_length = 1, - .sample_rate = 0, - .data = NULL, - .add_to_buf = NULL, -#ifndef LIRC_REMOVE_DURING_EXPORT - .get_queue = NULL, -#endif - .set_use_inc = set_use_inc, - .set_use_dec = set_use_dec, - .fops = &lirc_fops, - .dev = NULL, - .owner = THIS_MODULE, -}; - - -#ifdef MODULE -static int init_chrdev(void) -{ - driver.minor = lirc_register_driver(&driver); - if (driver.minor < 0) { - printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n"); - return -EIO; - } - return 0; -} - -static void drop_chrdev(void) -{ - lirc_unregister_driver(driver.minor); -} -#endif - -/* SECTION: Hardware */ -static long delta(struct timeval *tv1, struct timeval *tv2) -{ - unsigned long deltv; - - deltv = tv2->tv_sec - tv1->tv_sec; - if (deltv > 15) - deltv = 0xFFFFFF; - else - deltv = deltv*1000000 + - tv2->tv_usec - - tv1->tv_usec; - return deltv; -} - -static void sir_timeout(unsigned long data) -{ - /* - * if last received signal was a pulse, but receiving stopped - * within the 9 bit frame, we need to finish this pulse and - * simulate a signal change to from pulse to space. Otherwise - * upper layers will receive two sequences next time. - */ - - unsigned long flags; - unsigned long pulse_end; - - /* avoid interference with interrupt */ - spin_lock_irqsave(&timer_lock, flags); - if (last_value) { -#ifndef LIRC_ON_SA1100 - /* clear unread bits in UART and restart */ - outb(UART_FCR_CLEAR_RCVR, io + UART_FCR); -#endif - /* determine 'virtual' pulse end: */ - pulse_end = delta(&last_tv, &last_intr_tv); - dprintk("timeout add %d for %lu usec\n", last_value, pulse_end); - add_read_queue(last_value, pulse_end); - last_value = 0; - last_tv = last_intr_tv; - } - spin_unlock_irqrestore(&timer_lock, flags); -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -static irqreturn_t sir_interrupt(int irq, void *dev_id, - struct pt_regs *regs) -#else -static irqreturn_t sir_interrupt(int irq, void *dev_id) -#endif -{ - unsigned char data; - struct timeval curr_tv; - static unsigned long deltv; -#ifdef LIRC_ON_SA1100 - int status; - static int n; - - status = Ser2UTSR0; - /* - * Deal with any receive errors first. The bytes in error may be - * the only bytes in the receive FIFO, so we do this first. - */ - while (status & UTSR0_EIF) { - int bstat; - - if (debug) { - dprintk("EIF\n"); - bstat = Ser2UTSR1; - - if (bstat & UTSR1_FRE) - dprintk("frame error\n"); - if (bstat & UTSR1_ROR) - dprintk("receive fifo overrun\n"); - if (bstat & UTSR1_PRE) - dprintk("parity error\n"); - } - - bstat = Ser2UTDR; - n++; - status = Ser2UTSR0; - } - - if (status & (UTSR0_RFS | UTSR0_RID)) { - do_gettimeofday(&curr_tv); - deltv = delta(&last_tv, &curr_tv); - do { - data = Ser2UTDR; - dprintk("%d data: %u\n", n, (unsigned int) data); - n++; - } while (status & UTSR0_RID && /* do not empty fifo in order to - * get UTSR0_RID in any case */ - Ser2UTSR1 & UTSR1_RNE); /* data ready */ - - if (status&UTSR0_RID) { - add_read_queue(0 , deltv - n * TIME_CONST); /*space*/ - add_read_queue(1, n * TIME_CONST); /*pulse*/ - n = 0; - last_tv = curr_tv; - } - } - - if (status & UTSR0_TFS) - printk(KERN_ERR "transmit fifo not full, shouldn't happen\n"); - - /* We must clear certain bits. */ - status &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB); - if (status) - Ser2UTSR0 = status; -#else - unsigned long deltintrtv; - unsigned long flags; - int iir, lsr; - - while ((iir = inb(io + UART_IIR) & UART_IIR_ID)) { - switch (iir&UART_IIR_ID) { /* FIXME toto treba preriedit */ - case UART_IIR_MSI: - (void) inb(io + UART_MSR); - break; - case UART_IIR_RLSI: - (void) inb(io + UART_LSR); - break; - case UART_IIR_THRI: -#if 0 - if (lsr & UART_LSR_THRE) /* FIFO is empty */ - outb(data, io + UART_TX) -#endif - break; - case UART_IIR_RDI: - /* avoid interference with timer */ - spin_lock_irqsave(&timer_lock, flags); - do { - del_timer(&timerlist); - data = inb(io + UART_RX); - do_gettimeofday(&curr_tv); - deltv = delta(&last_tv, &curr_tv); - deltintrtv = delta(&last_intr_tv, &curr_tv); - dprintk("t %lu, d %d\n", deltintrtv, (int)data); - /* - * if nothing came in last X cycles, - * it was gap - */ - if (deltintrtv > TIME_CONST * threshold) { - if (last_value) { - dprintk("GAP\n"); - /* simulate signal change */ - add_read_queue(last_value, - deltv - - deltintrtv); - last_value = 0; - last_tv.tv_sec = - last_intr_tv.tv_sec; - last_tv.tv_usec = - last_intr_tv.tv_usec; - deltv = deltintrtv; - } - } - data = 1; - if (data ^ last_value) { - /* - * deltintrtv > 2*TIME_CONST, remember? - * the other case is timeout - */ - add_read_queue(last_value, - deltv-TIME_CONST); - last_value = data; - last_tv = curr_tv; - if (last_tv.tv_usec >= TIME_CONST) { - last_tv.tv_usec -= TIME_CONST; - } else { - last_tv.tv_sec--; - last_tv.tv_usec += 1000000 - - TIME_CONST; - } - } - last_intr_tv = curr_tv; - if (data) { - /* - * start timer for end of - * sequence detection - */ - timerlist.expires = jiffies + - SIR_TIMEOUT; - add_timer(&timerlist); - } - - lsr = inb(io + UART_LSR); - } while (lsr & UART_LSR_DR); /* data ready */ - spin_unlock_irqrestore(&timer_lock, flags); - break; - default: - break; - } - } -#endif - return IRQ_RETVAL(IRQ_HANDLED); -} - -#ifdef LIRC_ON_SA1100 -static void send_pulse(unsigned long length) -{ - unsigned long k, delay; - int flag; - - if (length == 0) - return; - /* - * this won't give us the carrier frequency we really want - * due to integer arithmetic, but we can accept this inaccuracy - */ - - for (k = flag = 0; k < length; k += delay, flag = !flag) { - if (flag) { - off(); - delay = space_width; - } else { - on(); - delay = pulse_width; - } - safe_udelay(delay); - } - off(); -} - -static void send_space(unsigned long length) -{ - if (length == 0) - return; - off(); - safe_udelay(length); -} -#else -static void send_space(unsigned long len) -{ - safe_udelay(len); -} - -static void send_pulse(unsigned long len) -{ - long bytes_out = len / TIME_CONST; - long time_left; - - time_left = (long)len - (long)bytes_out * (long)TIME_CONST; - if (bytes_out == 0) { - bytes_out++; - time_left = 0; - } - while (bytes_out--) { - outb(PULSE, io + UART_TX); - /* FIXME treba seriozne cakanie z drivers/char/serial.c */ - while (!(inb(io + UART_LSR) & UART_LSR_THRE)) - ; - } -#if 0 - if (time_left > 0) - safe_udelay(time_left); -#endif -} -#endif - -#ifdef CONFIG_SA1100_COLLIE -static int sa1100_irda_set_power_collie(int state) -{ - if (state) { - /* - * 0 - off - * 1 - short range, lowest power - * 2 - medium range, medium power - * 3 - maximum range, high power - */ - ucb1200_set_io_direction(TC35143_GPIO_IR_ON, - TC35143_IODIR_OUTPUT); - ucb1200_set_io(TC35143_GPIO_IR_ON, TC35143_IODAT_LOW); - udelay(100); - } else { - /* OFF */ - ucb1200_set_io_direction(TC35143_GPIO_IR_ON, - TC35143_IODIR_OUTPUT); - ucb1200_set_io(TC35143_GPIO_IR_ON, TC35143_IODAT_HIGH); - } - return 0; -} -#endif - -static int init_hardware(void) -{ - unsigned long flags; - - spin_lock_irqsave(&hardware_lock, flags); - /* reset UART */ -#ifdef LIRC_ON_SA1100 -#ifdef CONFIG_SA1100_BITSY - if (machine_is_bitsy()) { - printk(KERN_INFO "Power on IR module\n"); - set_bitsy_egpio(EGPIO_BITSY_IR_ON); - } -#endif -#ifdef CONFIG_SA1100_COLLIE - sa1100_irda_set_power_collie(3); /* power on */ -#endif - sr.hscr0 = Ser2HSCR0; - - sr.utcr0 = Ser2UTCR0; - sr.utcr1 = Ser2UTCR1; - sr.utcr2 = Ser2UTCR2; - sr.utcr3 = Ser2UTCR3; - sr.utcr4 = Ser2UTCR4; - - sr.utdr = Ser2UTDR; - sr.utsr0 = Ser2UTSR0; - sr.utsr1 = Ser2UTSR1; - - /* configure GPIO */ - /* output */ - PPDR |= PPC_TXD2; - PSDR |= PPC_TXD2; - /* set output to 0 */ - off(); - - /* Enable HP-SIR modulation, and ensure that the port is disabled. */ - Ser2UTCR3 = 0; - Ser2HSCR0 = sr.hscr0 & (~HSCR0_HSSP); - - /* clear status register to prevent unwanted interrupts */ - Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB); - - /* 7N1 */ - Ser2UTCR0 = UTCR0_1StpBit|UTCR0_7BitData; - /* 115200 */ - Ser2UTCR1 = 0; - Ser2UTCR2 = 1; - /* use HPSIR, 1.6 usec pulses */ - Ser2UTCR4 = UTCR4_HPSIR|UTCR4_Z1_6us; - - /* enable receiver, receive fifo interrupt */ - Ser2UTCR3 = UTCR3_RXE|UTCR3_RIE; - - /* clear status register to prevent unwanted interrupts */ - Ser2UTSR0 &= (UTSR0_RID | UTSR0_RBB | UTSR0_REB); - -#elif defined(LIRC_SIR_TEKRAM) - /* disable FIFO */ - soutp(UART_FCR, - UART_FCR_CLEAR_RCVR| - UART_FCR_CLEAR_XMIT| - UART_FCR_TRIGGER_1); - - /* Set DLAB 0. */ - soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); - - /* First of all, disable all interrupts */ - soutp(UART_IER, sinp(UART_IER) & - (~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI))); - - /* Set DLAB 1. */ - soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB); - - /* Set divisor to 12 => 9600 Baud */ - soutp(UART_DLM, 0); - soutp(UART_DLL, 12); - - /* Set DLAB 0. */ - soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); - - /* power supply */ - soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); - safe_udelay(50*1000); - - /* -DTR low -> reset PIC */ - soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2); - udelay(1*1000); - - soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); - udelay(100); - - - /* -RTS low -> send control byte */ - soutp(UART_MCR, UART_MCR_DTR|UART_MCR_OUT2); - udelay(7); - soutp(UART_TX, TEKRAM_115200|TEKRAM_PW); - - /* one byte takes ~1042 usec to transmit at 9600,8N1 */ - udelay(1500); - - /* back to normal operation */ - soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); - udelay(50); - - udelay(1500); - - /* read previous control byte */ - printk(KERN_INFO LIRC_DRIVER_NAME - ": 0x%02x\n", sinp(UART_RX)); - - /* Set DLAB 1. */ - soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB); - - /* Set divisor to 1 => 115200 Baud */ - soutp(UART_DLM, 0); - soutp(UART_DLL, 1); - - /* Set DLAB 0, 8 Bit */ - soutp(UART_LCR, UART_LCR_WLEN8); - /* enable interrupts */ - soutp(UART_IER, sinp(UART_IER)|UART_IER_RDI); -#else - outb(0, io + UART_MCR); - outb(0, io + UART_IER); - /* init UART */ - /* set DLAB, speed = 115200 */ - outb(UART_LCR_DLAB | UART_LCR_WLEN7, io + UART_LCR); - outb(1, io + UART_DLL); outb(0, io + UART_DLM); - /* 7N1+start = 9 bits at 115200 ~ 3 bits at 44000 */ - outb(UART_LCR_WLEN7, io + UART_LCR); - /* FIFO operation */ - outb(UART_FCR_ENABLE_FIFO, io + UART_FCR); - /* interrupts */ - /* outb(UART_IER_RLSI|UART_IER_RDI|UART_IER_THRI, io + UART_IER); */ - outb(UART_IER_RDI, io + UART_IER); - /* turn on UART */ - outb(UART_MCR_DTR|UART_MCR_RTS|UART_MCR_OUT2, io + UART_MCR); -#ifdef LIRC_SIR_ACTISYS_ACT200L - init_act200(); -#elif defined(LIRC_SIR_ACTISYS_ACT220L) - init_act220(); -#endif -#endif - spin_unlock_irqrestore(&hardware_lock, flags); - return 0; -} - -static void drop_hardware(void) -{ - unsigned long flags; - - spin_lock_irqsave(&hardware_lock, flags); - -#ifdef LIRC_ON_SA1100 - Ser2UTCR3 = 0; - - Ser2UTCR0 = sr.utcr0; - Ser2UTCR1 = sr.utcr1; - Ser2UTCR2 = sr.utcr2; - Ser2UTCR4 = sr.utcr4; - Ser2UTCR3 = sr.utcr3; - - Ser2HSCR0 = sr.hscr0; -#ifdef CONFIG_SA1100_BITSY - if (machine_is_bitsy()) - clr_bitsy_egpio(EGPIO_BITSY_IR_ON); -#endif -#ifdef CONFIG_SA1100_COLLIE - sa1100_irda_set_power_collie(0); /* power off */ -#endif -#else - /* turn off interrupts */ - outb(0, io + UART_IER); -#endif - spin_unlock_irqrestore(&hardware_lock, flags); -} - -/* SECTION: Initialisation */ - -static int init_port(void) -{ - int retval; - - /* get I/O port access and IRQ line */ -#ifndef LIRC_ON_SA1100 - if (request_region(io, 8, LIRC_DRIVER_NAME) == NULL) { - printk(KERN_ERR LIRC_DRIVER_NAME - ": i/o port 0x%.4x already in use.\n", io); - return -EBUSY; - } -#endif - retval = request_irq(irq, sir_interrupt, IRQF_DISABLED, - LIRC_DRIVER_NAME, NULL); - if (retval < 0) { -# ifndef LIRC_ON_SA1100 - release_region(io, 8); -# endif - printk(KERN_ERR LIRC_DRIVER_NAME - ": IRQ %d already in use.\n", - irq); - return retval; - } -#ifndef LIRC_ON_SA1100 - printk(KERN_INFO LIRC_DRIVER_NAME - ": I/O port 0x%.4x, IRQ %d.\n", - io, irq); -#endif - - init_timer(&timerlist); - timerlist.function = sir_timeout; - timerlist.data = 0xabadcafe; - - return 0; -} - -static void drop_port(void) -{ - free_irq(irq, NULL); - del_timer_sync(&timerlist); -#ifndef LIRC_ON_SA1100 - release_region(io, 8); -#endif -} - -#ifdef LIRC_SIR_ACTISYS_ACT200L -/* Crystal/Cirrus CS8130 IR transceiver, used in Actisys Act200L dongle */ -/* some code borrowed from Linux IRDA driver */ - -/* Register 0: Control register #1 */ -#define ACT200L_REG0 0x00 -#define ACT200L_TXEN 0x01 /* Enable transmitter */ -#define ACT200L_RXEN 0x02 /* Enable receiver */ -#define ACT200L_ECHO 0x08 /* Echo control chars */ - -/* Register 1: Control register #2 */ -#define ACT200L_REG1 0x10 -#define ACT200L_LODB 0x01 /* Load new baud rate count value */ -#define ACT200L_WIDE 0x04 /* Expand the maximum allowable pulse */ - -/* Register 3: Transmit mode register #2 */ -#define ACT200L_REG3 0x30 -#define ACT200L_B0 0x01 /* DataBits, 0=6, 1=7, 2=8, 3=9(8P) */ -#define ACT200L_B1 0x02 /* DataBits, 0=6, 1=7, 2=8, 3=9(8P) */ -#define ACT200L_CHSY 0x04 /* StartBit Synced 0=bittime, 1=startbit */ - -/* Register 4: Output Power register */ -#define ACT200L_REG4 0x40 -#define ACT200L_OP0 0x01 /* Enable LED1C output */ -#define ACT200L_OP1 0x02 /* Enable LED2C output */ -#define ACT200L_BLKR 0x04 - -/* Register 5: Receive Mode register */ -#define ACT200L_REG5 0x50 -#define ACT200L_RWIDL 0x01 /* fixed 1.6us pulse mode */ - /*.. other various IRDA bit modes, and TV remote modes..*/ - -/* Register 6: Receive Sensitivity register #1 */ -#define ACT200L_REG6 0x60 -#define ACT200L_RS0 0x01 /* receive threshold bit 0 */ -#define ACT200L_RS1 0x02 /* receive threshold bit 1 */ - -/* Register 7: Receive Sensitivity register #2 */ -#define ACT200L_REG7 0x70 -#define ACT200L_ENPOS 0x04 /* Ignore the falling edge */ - -/* Register 8,9: Baud Rate Divider register #1,#2 */ -#define ACT200L_REG8 0x80 -#define ACT200L_REG9 0x90 - -#define ACT200L_2400 0x5f -#define ACT200L_9600 0x17 -#define ACT200L_19200 0x0b -#define ACT200L_38400 0x05 -#define ACT200L_57600 0x03 -#define ACT200L_115200 0x01 - -/* Register 13: Control register #3 */ -#define ACT200L_REG13 0xd0 -#define ACT200L_SHDW 0x01 /* Enable access to shadow registers */ - -/* Register 15: Status register */ -#define ACT200L_REG15 0xf0 - -/* Register 21: Control register #4 */ -#define ACT200L_REG21 0x50 -#define ACT200L_EXCK 0x02 /* Disable clock output driver */ -#define ACT200L_OSCL 0x04 /* oscillator in low power, medium accuracy mode */ - -static void init_act200(void) -{ - int i; - __u8 control[] = { - ACT200L_REG15, - ACT200L_REG13 | ACT200L_SHDW, - ACT200L_REG21 | ACT200L_EXCK | ACT200L_OSCL, - ACT200L_REG13, - ACT200L_REG7 | ACT200L_ENPOS, - ACT200L_REG6 | ACT200L_RS0 | ACT200L_RS1, - ACT200L_REG5 | ACT200L_RWIDL, - ACT200L_REG4 | ACT200L_OP0 | ACT200L_OP1 | ACT200L_BLKR, - ACT200L_REG3 | ACT200L_B0, - ACT200L_REG0 | ACT200L_TXEN | ACT200L_RXEN, - ACT200L_REG8 | (ACT200L_115200 & 0x0f), - ACT200L_REG9 | ((ACT200L_115200 >> 4) & 0x0f), - ACT200L_REG1 | ACT200L_LODB | ACT200L_WIDE - }; - - /* Set DLAB 1. */ - soutp(UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN8); - - /* Set divisor to 12 => 9600 Baud */ - soutp(UART_DLM, 0); - soutp(UART_DLL, 12); - - /* Set DLAB 0. */ - soutp(UART_LCR, UART_LCR_WLEN8); - /* Set divisor to 12 => 9600 Baud */ - - /* power supply */ - soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); - for (i = 0; i < 50; i++) - safe_udelay(1000); - - /* Reset the dongle : set RTS low for 25 ms */ - soutp(UART_MCR, UART_MCR_DTR|UART_MCR_OUT2); - for (i = 0; i < 25; i++) - udelay(1000); - - soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); - udelay(100); - - /* Clear DTR and set RTS to enter command mode */ - soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2); - udelay(7); - - /* send out the control register settings for 115K 7N1 SIR operation */ - for (i = 0; i < sizeof(control); i++) { - soutp(UART_TX, control[i]); - /* one byte takes ~1042 usec to transmit at 9600,8N1 */ - udelay(1500); - } - - /* back to normal operation */ - soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); - udelay(50); - - udelay(1500); - soutp(UART_LCR, sinp(UART_LCR) | UART_LCR_DLAB); - - /* Set DLAB 1. */ - soutp(UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN7); - - /* Set divisor to 1 => 115200 Baud */ - soutp(UART_DLM, 0); - soutp(UART_DLL, 1); - - /* Set DLAB 0. */ - soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB)); - - /* Set DLAB 0, 7 Bit */ - soutp(UART_LCR, UART_LCR_WLEN7); - - /* enable interrupts */ - soutp(UART_IER, sinp(UART_IER)|UART_IER_RDI); -} -#endif - -#ifdef LIRC_SIR_ACTISYS_ACT220L -/* - * Derived from linux IrDA driver (net/irda/actisys.c) - * Drop me a mail for any kind of comment: maxx@spaceboyz.net - */ - -void init_act220(void) -{ - int i; - - /* DLAB 1 */ - soutp(UART_LCR, UART_LCR_DLAB|UART_LCR_WLEN7); - - /* 9600 baud */ - soutp(UART_DLM, 0); - soutp(UART_DLL, 12); - - /* DLAB 0 */ - soutp(UART_LCR, UART_LCR_WLEN7); - - /* reset the dongle, set DTR low for 10us */ - soutp(UART_MCR, UART_MCR_RTS|UART_MCR_OUT2); - udelay(10); - - /* back to normal (still 9600) */ - soutp(UART_MCR, UART_MCR_DTR|UART_MCR_RTS|UART_MCR_OUT2); - - /* - * send RTS pulses until we reach 115200 - * i hope this is really the same for act220l/act220l+ - */ - for (i = 0; i < 3; i++) { - udelay(10); - /* set RTS low for 10 us */ - soutp(UART_MCR, UART_MCR_DTR|UART_MCR_OUT2); - udelay(10); - /* set RTS high for 10 us */ - soutp(UART_MCR, UART_MCR_RTS|UART_MCR_DTR|UART_MCR_OUT2); - } - - /* back to normal operation */ - udelay(1500); /* better safe than sorry ;) */ - - /* Set DLAB 1. */ - soutp(UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN7); - - /* Set divisor to 1 => 115200 Baud */ - soutp(UART_DLM, 0); - soutp(UART_DLL, 1); - - /* Set DLAB 0, 7 Bit */ - /* The dongle doesn't seem to have any problems with operation at 7N1 */ - soutp(UART_LCR, UART_LCR_WLEN7); - - /* enable interrupts */ - soutp(UART_IER, UART_IER_RDI); -} -#endif - -static int init_lirc_sir(void) -{ - int retval; - - init_waitqueue_head(&lirc_read_queue); - retval = init_port(); - if (retval < 0) - return retval; - init_hardware(); - printk(KERN_INFO LIRC_DRIVER_NAME - ": Installed.\n"); - return 0; -} - -#ifdef MODULE - -static int __init lirc_sir_init(void) -{ - int retval; - - retval = init_chrdev(); - if (retval < 0) - return retval; - retval = init_lirc_sir(); - if (retval) { - drop_chrdev(); - return retval; - } - return 0; -} - -static void __exit lirc_sir_exit(void) -{ - drop_hardware(); - drop_chrdev(); - drop_port(); - printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n"); -} - -module_init(lirc_sir_init); -module_exit(lirc_sir_exit); - -#ifdef LIRC_SIR_TEKRAM -MODULE_DESCRIPTION("Infrared receiver driver for Tekram Irmate 210"); -MODULE_AUTHOR("Christoph Bartelmus"); -#elif defined(LIRC_ON_SA1100) -MODULE_DESCRIPTION("LIRC driver for StrongARM SA1100 embedded microprocessor"); -MODULE_AUTHOR("Christoph Bartelmus"); -#elif defined(LIRC_SIR_ACTISYS_ACT200L) -MODULE_DESCRIPTION("LIRC driver for Actisys Act200L"); -MODULE_AUTHOR("Karl Bongers"); -#elif defined(LIRC_SIR_ACTISYS_ACT220L) -MODULE_DESCRIPTION("LIRC driver for Actisys Act220L(+)"); -MODULE_AUTHOR("Jan Roemisch"); -#else -MODULE_DESCRIPTION("Infrared receiver driver for SIR type serial ports"); -MODULE_AUTHOR("Milan Pikula"); -#endif -MODULE_LICENSE("GPL"); - -#ifdef LIRC_ON_SA1100 -module_param(irq, int, S_IRUGO); -MODULE_PARM_DESC(irq, "Interrupt (16)"); -#else -module_param(io, int, S_IRUGO); -MODULE_PARM_DESC(io, "I/O address base (0x3f8 or 0x2f8)"); - -module_param(irq, int, S_IRUGO); -MODULE_PARM_DESC(irq, "Interrupt (4 or 3)"); - -module_param(threshold, int, S_IRUGO); -MODULE_PARM_DESC(threshold, "space detection threshold (3)"); -#endif - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Enable debugging messages"); - -EXPORT_NO_SYMBOLS; - -#endif /* MODULE */ diff --git a/ubuntu/lirc/lirc_streamzap/Makefile b/ubuntu/lirc/lirc_streamzap/Makefile deleted file mode 100644 index aa332306e62..00000000000 --- a/ubuntu/lirc/lirc_streamzap/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. -obj-$(CONFIG_LIRC_STREAMZAP) += lirc_streamzap.o diff --git a/ubuntu/lirc/lirc_streamzap/lirc_streamzap.c b/ubuntu/lirc/lirc_streamzap/lirc_streamzap.c deleted file mode 100755 index d5e3ea30fcd..00000000000 --- a/ubuntu/lirc/lirc_streamzap/lirc_streamzap.c +++ /dev/null @@ -1,888 +0,0 @@ -/* $Id: lirc_streamzap.c,v 1.48 2009/03/15 09:34:00 lirc Exp $ */ -/* - * Streamzap Remote Control driver - * - * Copyright (c) 2005 Christoph Bartelmus <lirc@bartelmus.de> - * - * This driver was based on the work of Greg Wickham and Adrian - * Dewhurst. It was substantially rewritten to support correct signal - * gaps and now maintains a delay buffer, which is used to present - * consistent timing behaviour to user space applications. Without the - * delay buffer an ugly hack would be required in lircd, which can - * cause sluggish signal decoding in certain situations. - * - * This driver is based on the USB skeleton driver packaged with the - * kernel; copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/version.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) -#error "*******************************************************" -#error "Sorry, this driver needs kernel version 2.4.0 or higher" -#error "*******************************************************" -#endif -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/smp_lock.h> -#include <linux/completion.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) -#include <asm/uaccess.h> -#else -#include <linux/uaccess.h> -#endif -#include <linux/usb.h> - -#include "../lirc.h" -#include "../kcompat.h" -#include "../lirc_dev/lirc_dev.h" - -#define DRIVER_VERSION "$Revision: 1.48 $" -#define DRIVER_NAME "lirc_streamzap" -#define DRIVER_DESC "Streamzap Remote Control driver" - -static int debug; - -#define USB_STREAMZAP_VENDOR_ID 0x0e9c -#define USB_STREAMZAP_PRODUCT_ID 0x0000 - -/* Use our own dbg macro */ -#define dprintk(fmt, args...) \ - do { \ - if (debug) \ - printk(KERN_DEBUG DRIVER_NAME "[%d]: " \ - fmt "\n", ## args); \ - } while (0) - -/* table of devices that work with this driver */ -static struct usb_device_id streamzap_table[] = { - /* Streamzap Remote Control */ - { USB_DEVICE(USB_STREAMZAP_VENDOR_ID, USB_STREAMZAP_PRODUCT_ID) }, - /* Terminating entry */ - { } -}; - -MODULE_DEVICE_TABLE(usb, streamzap_table); - -#define STREAMZAP_PULSE_MASK 0xf0 -#define STREAMZAP_SPACE_MASK 0x0f -#define STREAMZAP_RESOLUTION 256 - -/* number of samples buffered */ -#define STREAMZAP_BUFFER_SIZE 128 - -enum StreamzapDecoderState { - PulseSpace, - FullPulse, - FullSpace, - IgnorePulse -}; - -/* Structure to hold all of our device specific stuff - * - * some remarks regarding locking: - * theoretically this struct can be accessed from three threads: - * - * - from lirc_dev through set_use_inc/set_use_dec - * - * - from the USB layer throuh probe/disconnect/irq - * - * Careful placement of lirc_register_driver/lirc_unregister_driver - * calls will prevent conflicts. lirc_dev makes sure that - * set_use_inc/set_use_dec are not being executed and will not be - * called after lirc_unregister_driver returns. - * - * - by the timer callback - * - * The timer is only running when the device is connected and the - * LIRC device is open. Making sure the timer is deleted by - * set_use_dec will make conflicts impossible. - */ -struct usb_streamzap { - - /* usb */ - /* save off the usb device pointer */ - struct usb_device *udev; - /* the interface for this device */ - struct usb_interface *interface; - - /* buffer & dma */ - unsigned char *buf_in; - dma_addr_t dma_in; - unsigned int buf_in_len; - - struct usb_endpoint_descriptor *endpoint; - - /* IRQ */ - struct urb *urb_in; - - /* lirc */ - struct lirc_driver driver; - struct lirc_buffer delay_buf; - struct lirc_buffer lirc_buf; - - /* timer used to support delay buffering */ - struct timer_list delay_timer; - int timer_running; - spinlock_t timer_lock; - - /* tracks whether we are currently receiving some signal */ - int idle; - /* sum of signal lengths received since signal start */ - unsigned long sum; - /* start time of signal; necessary for gap tracking */ - struct timeval signal_last; - struct timeval signal_start; - enum StreamzapDecoderState decoder_state; - struct timer_list flush_timer; - int flush; - int in_use; -}; - - -/* local function prototypes */ -#ifdef KERNEL_2_5 -static int streamzap_probe(struct usb_interface *interface, - const struct usb_device_id *id); -static void streamzap_disconnect(struct usb_interface *interface); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -static void usb_streamzap_irq(struct urb *urb, struct pt_regs *regs); -#else -static void usb_streamzap_irq(struct urb *urb); -#endif -#else -static void *streamzap_probe(struct usb_device *udev, unsigned int ifnum, - const struct usb_device_id *id); -static void streamzap_disconnect(struct usb_device *dev, void *ptr); -static void usb_streamzap_irq(struct urb *urb); -#endif -static int streamzap_use_inc(void *data); -static void streamzap_use_dec(void *data); -static int streamzap_ioctl(struct inode *node, struct file *filep, - unsigned int cmd, unsigned long arg); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) -static int streamzap_suspend(struct usb_interface *intf, pm_message_t message); -static int streamzap_resume(struct usb_interface *intf); -#endif - -/* usb specific object needed to register this driver with the usb subsystem */ - -static struct usb_driver streamzap_driver = { - LIRC_THIS_MODULE(.owner = THIS_MODULE) - .name = DRIVER_NAME, - .probe = streamzap_probe, - .disconnect = streamzap_disconnect, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) - .suspend = streamzap_suspend, - .resume = streamzap_resume, -#endif - .id_table = streamzap_table, -}; - -static void stop_timer(struct usb_streamzap *sz) -{ - unsigned long flags; - - spin_lock_irqsave(&sz->timer_lock, flags); - if (sz->timer_running) { - sz->timer_running = 0; - spin_unlock_irqrestore(&sz->timer_lock, flags); - del_timer_sync(&sz->delay_timer); - } else { - spin_unlock_irqrestore(&sz->timer_lock, flags); - } -} - -static void flush_timeout(unsigned long arg) -{ - struct usb_streamzap *sz = (struct usb_streamzap *) arg; - - /* finally start accepting data */ - sz->flush = 0; -} -static void delay_timeout(unsigned long arg) -{ - unsigned long flags; - /* deliver data every 10 ms */ - static unsigned long timer_inc = - (10000/(1000000/HZ)) == 0 ? 1 : (10000/(1000000/HZ)); - struct usb_streamzap *sz = (struct usb_streamzap *) arg; - lirc_t data; - - spin_lock_irqsave(&sz->timer_lock, flags); - - if (!lirc_buffer_empty(&sz->delay_buf) && - !lirc_buffer_full(&sz->lirc_buf)) { - lirc_buffer_read(&sz->delay_buf, (unsigned char *) &data); - lirc_buffer_write(&sz->lirc_buf, (unsigned char *) &data); - } - if (!lirc_buffer_empty(&sz->delay_buf)) { - while (lirc_buffer_available(&sz->delay_buf) < - STREAMZAP_BUFFER_SIZE/2 && - !lirc_buffer_full(&sz->lirc_buf)) { - lirc_buffer_read(&sz->delay_buf, - (unsigned char *) &data); - lirc_buffer_write(&sz->lirc_buf, - (unsigned char *) &data); - } - if (sz->timer_running) { - sz->delay_timer.expires = jiffies + timer_inc; - add_timer(&sz->delay_timer); - } - } else { - sz->timer_running = 0; - } - - if (!lirc_buffer_empty(&sz->lirc_buf)) - wake_up(&sz->lirc_buf.wait_poll); - - spin_unlock_irqrestore(&sz->timer_lock, flags); -} - -static void flush_delay_buffer(struct usb_streamzap *sz) -{ - lirc_t data; - int empty = 1; - - while (!lirc_buffer_empty(&sz->delay_buf)) { - empty = 0; - lirc_buffer_read(&sz->delay_buf, (unsigned char *) &data); - if (!lirc_buffer_full(&sz->lirc_buf)) { - lirc_buffer_write(&sz->lirc_buf, - (unsigned char *) &data); - } else { - dprintk("buffer overflow", sz->driver.minor); - } - } - if (!empty) - wake_up(&sz->lirc_buf.wait_poll); -} - -static void push(struct usb_streamzap *sz, unsigned char *data) -{ - unsigned long flags; - - spin_lock_irqsave(&sz->timer_lock, flags); - if (lirc_buffer_full(&sz->delay_buf)) { - lirc_t data; - - lirc_buffer_read(&sz->delay_buf, (unsigned char *) &data); - if (!lirc_buffer_full(&sz->lirc_buf)) { - lirc_buffer_write(&sz->lirc_buf, - (unsigned char *) &data); - } else { - dprintk("buffer overflow", sz->driver.minor); - } - } - - lirc_buffer_write(&sz->delay_buf, data); - - if (!sz->timer_running) { - sz->delay_timer.expires = jiffies + HZ/10; - add_timer(&sz->delay_timer); - sz->timer_running = 1; - } - - spin_unlock_irqrestore(&sz->timer_lock, flags); -} - -static void push_full_pulse(struct usb_streamzap *sz, - unsigned char value) -{ - lirc_t pulse; - - if (sz->idle) { - long deltv; - lirc_t tmp; - - sz->signal_last = sz->signal_start; - do_gettimeofday(&sz->signal_start); - - deltv = sz->signal_start.tv_sec-sz->signal_last.tv_sec; - if (deltv > 15) { - tmp = PULSE_MASK; /* really long time */ - } else { - tmp = (lirc_t) (deltv*1000000+ - sz->signal_start.tv_usec - - sz->signal_last.tv_usec); - tmp -= sz->sum; - } - dprintk("ls %u", sz->driver.minor, tmp); - push(sz, (char *)&tmp); - - sz->idle = 0; - sz->sum = 0; - } - - pulse = ((lirc_t) value)*STREAMZAP_RESOLUTION; - pulse += STREAMZAP_RESOLUTION/2; - sz->sum += pulse; - pulse |= PULSE_BIT; - - dprintk("p %u", sz->driver.minor, pulse&PULSE_MASK); - push(sz, (char *)&pulse); -} - -static void push_half_pulse(struct usb_streamzap *sz, - unsigned char value) -{ - push_full_pulse(sz, (value & STREAMZAP_PULSE_MASK)>>4); -} - -static void push_full_space(struct usb_streamzap *sz, - unsigned char value) -{ - lirc_t space; - - space = ((lirc_t) value)*STREAMZAP_RESOLUTION; - space += STREAMZAP_RESOLUTION/2; - sz->sum += space; - dprintk("s %u", sz->driver.minor, space); - push(sz, (char *)&space); -} - -static void push_half_space(struct usb_streamzap *sz, - unsigned char value) -{ - push_full_space(sz, value & STREAMZAP_SPACE_MASK); -} - -/** - * usb_streamzap_irq - IRQ handler - * - * This procedure is invoked on reception of data from - * the usb remote. - */ -#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -static void usb_streamzap_irq(struct urb *urb, struct pt_regs *regs) -#else -static void usb_streamzap_irq(struct urb *urb) -#endif -{ - struct usb_streamzap *sz; - int len; - unsigned int i = 0; - - if (!urb) - return; - - sz = urb->context; - len = urb->actual_length; - - switch (urb->status) { - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* - * this urb is terminated, clean up. - * sz might already be invalid at this point - */ - dprintk("urb status: %d", -1, urb->status); - return; - default: - break; - } - - dprintk("received %d", sz->driver.minor, urb->actual_length); - if (!sz->flush) { - for (i = 0; i < urb->actual_length; i++) { - dprintk("%d: %x", sz->driver.minor, - i, (unsigned char) sz->buf_in[i]); - switch (sz->decoder_state) { - case PulseSpace: - if ((sz->buf_in[i]&STREAMZAP_PULSE_MASK) == - STREAMZAP_PULSE_MASK) { - sz->decoder_state = FullPulse; - continue; - } else if ((sz->buf_in[i]&STREAMZAP_SPACE_MASK) - == STREAMZAP_SPACE_MASK) { - push_half_pulse(sz, sz->buf_in[i]); - sz->decoder_state = FullSpace; - continue; - } else { - push_half_pulse(sz, sz->buf_in[i]); - push_half_space(sz, sz->buf_in[i]); - } - break; - case FullPulse: - push_full_pulse(sz, sz->buf_in[i]); - sz->decoder_state = IgnorePulse; - break; - case FullSpace: - if (sz->buf_in[i] == 0xff) { - sz->idle = 1; - stop_timer(sz); - flush_delay_buffer(sz); - } else - push_full_space(sz, sz->buf_in[i]); - sz->decoder_state = PulseSpace; - break; - case IgnorePulse: - if ((sz->buf_in[i]&STREAMZAP_SPACE_MASK) == - STREAMZAP_SPACE_MASK) { - sz->decoder_state = FullSpace; - continue; - } - push_half_space(sz, sz->buf_in[i]); - sz->decoder_state = PulseSpace; - break; - } - } - } - -#ifdef KERNEL_2_5 - usb_submit_urb(urb, GFP_ATOMIC); -#endif - - return; -} - -static struct file_operations streamzap_fops = { - .owner = THIS_MODULE, - .ioctl = streamzap_ioctl, -}; - - -/** - * streamzap_probe - * - * Called by usb-core to associated with a candidate device - * On any failure the return value is the ERROR - * On success return 0 - */ -#ifdef KERNEL_2_5 -static int streamzap_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(interface); - struct usb_host_interface *iface_host; -#else -static void *streamzap_probe(struct usb_device *udev, unsigned int ifnum, - const struct usb_device_id *id) -{ - struct usb_interface *interface = &udev->actconfig->interface[ifnum]; - struct usb_interface_descriptor *iface_host; -#endif - int retval = -ENOMEM; - struct usb_streamzap *sz = NULL; - char buf[63], name[128] = ""; - - /* Allocate space for device driver specific data */ - sz = kzalloc(sizeof(struct usb_streamzap), GFP_KERNEL); - if (sz == NULL) - goto error; - - sz->udev = udev; - sz->interface = interface; - - /* Check to ensure endpoint information matches requirements */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 5) - iface_host = &interface->altsetting[interface->act_altsetting]; -#else - iface_host = interface->cur_altsetting; -#endif - -#ifdef KERNEL_2_5 - if (iface_host->desc.bNumEndpoints != 1) { -#else - if (iface_host->bNumEndpoints != 1) { -#endif -#ifdef KERNEL_2_5 - err("%s: Unexpected desc.bNumEndpoints (%d)", __func__, - iface_host->desc.bNumEndpoints); -#else - err("%s: Unexpected desc.bNumEndpoints (%d)", __func__, - iface_host->bNumEndpoints); -#endif - retval = -ENODEV; - goto error; - } - -#ifdef KERNEL_2_5 - sz->endpoint = &(iface_host->endpoint[0].desc); -#else - sz->endpoint = &(iface_host->endpoint[0]); -#endif - if ((sz->endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) - != USB_DIR_IN) { - err("%s: endpoint doesn't match input device 02%02x", - __func__, sz->endpoint->bEndpointAddress); - retval = -ENODEV; - goto error; - } - - if ((sz->endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - != USB_ENDPOINT_XFER_INT) { - err("%s: endpoint attributes don't match xfer 02%02x", - __func__, sz->endpoint->bmAttributes); - retval = -ENODEV; - goto error; - } - - if (sz->endpoint->wMaxPacketSize == 0) { - err("%s: endpoint message size==0? ", __func__); - retval = -ENODEV; - goto error; - } - - /* Allocate the USB buffer and IRQ URB */ - - sz->buf_in_len = sz->endpoint->wMaxPacketSize; -#ifdef KERNEL_2_5 - 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 - if (sz->buf_in == NULL) - goto error; - -#ifdef KERNEL_2_5 - sz->urb_in = usb_alloc_urb(0, GFP_KERNEL); -#else - - sz->urb_in = usb_alloc_urb(0); -#endif - if (sz->urb_in == NULL) - goto error; - - /* Connect this device to the LIRC sub-system */ - - if (lirc_buffer_init(&sz->lirc_buf, sizeof(lirc_t), - STREAMZAP_BUFFER_SIZE)) - goto error; - - if (lirc_buffer_init(&sz->delay_buf, sizeof(lirc_t), - STREAMZAP_BUFFER_SIZE)) { - lirc_buffer_free(&sz->lirc_buf); - goto error; - } - - strcpy(sz->driver.name, DRIVER_NAME); - 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.data = sz; - sz->driver.rbuf = &sz->lirc_buf; - sz->driver.set_use_inc = &streamzap_use_inc; - sz->driver.set_use_dec = &streamzap_use_dec; - sz->driver.fops = &streamzap_fops; -#ifdef LIRC_HAVE_SYSFS - sz->driver.dev = &interface->dev; -#endif - sz->driver.owner = THIS_MODULE; - - sz->idle = 1; - sz->decoder_state = PulseSpace; - init_timer(&sz->delay_timer); - sz->delay_timer.function = delay_timeout; - sz->delay_timer.data = (unsigned long) sz; - sz->timer_running = 0; - spin_lock_init(&sz->timer_lock); - - init_timer(&sz->flush_timer); - sz->flush_timer.function = flush_timeout; - sz->flush_timer.data = (unsigned long) sz; - /* Complete final initialisations */ - - usb_fill_int_urb(sz->urb_in, udev, - usb_rcvintpipe(udev, sz->endpoint->bEndpointAddress), - sz->buf_in, sz->buf_in_len, usb_streamzap_irq, sz, - sz->endpoint->bInterval); -#ifdef KERNEL_2_5 - sz->urb_in->transfer_dma = sz->dma_in; - sz->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; -#endif - - if (udev->descriptor.iManufacturer - && usb_string(udev, udev->descriptor.iManufacturer, - buf, sizeof(buf)) > 0) - strlcpy(name, buf, sizeof(name)); - - if (udev->descriptor.iProduct - && usb_string(udev, udev->descriptor.iProduct, - buf, sizeof(buf)) > 0) - snprintf(name + strlen(name), sizeof(name) - strlen(name), - " %s", buf); - - printk(KERN_INFO DRIVER_NAME "[%d]: %s on usb%d:%d attached\n", - sz->driver.minor, name, - udev->bus->busnum, sz->udev->devnum); - -#ifdef KERNEL_2_5 - usb_set_intfdata(interface, sz); -#endif - - if (lirc_register_driver(&sz->driver) < 0) { - lirc_buffer_free(&sz->delay_buf); - lirc_buffer_free(&sz->lirc_buf); - goto error; - } - -#ifdef KERNEL_2_5 - return 0; -#else - return sz; -#endif - -error: - - /* - * Premise is that a 'goto error' can be invoked from inside the - * probe function and all necessary cleanup actions will be taken - * including freeing any necessary memory blocks - */ - - if (retval == -ENOMEM) - err("Out of memory"); - - if (sz) { - usb_free_urb(sz->urb_in); -#ifdef KERNEL_2_5 - usb_free_coherent(udev, sz->buf_in_len, sz->buf_in, sz->dma_in); -#else - if (sz->buf_in) { - kfree(sz->buf_in); - } -#endif - kfree(sz); - } - -#ifdef KERNEL_2_5 - return retval; -#else - return NULL; -#endif -} - -static int streamzap_use_inc(void *data) -{ - struct usb_streamzap *sz = data; - - if (!sz) { - dprintk("%s called with no context", -1, __func__); - return -EINVAL; - } - dprintk("set use inc", sz->driver.minor); - MOD_INC_USE_COUNT; - - lirc_buffer_clear(&sz->lirc_buf); - lirc_buffer_clear(&sz->delay_buf); - - sz->flush_timer.expires = jiffies + HZ; - sz->flush = 1; - add_timer(&sz->flush_timer); - - sz->urb_in->dev = sz->udev; -#ifdef KERNEL_2_5 - if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) { -#else - if (usb_submit_urb(sz->urb_in)) { -#endif - dprintk("open result = -EIO error submitting urb", - sz->driver.minor); - MOD_DEC_USE_COUNT; - return -EIO; - } - sz->in_use++; - - return 0; -} - -static void streamzap_use_dec(void *data) -{ - struct usb_streamzap *sz = data; - - if (!sz) { - dprintk("%s called with no context", -1, __func__); - return; - } - dprintk("set use dec", sz->driver.minor); - - if (sz->flush) { - sz->flush = 0; - del_timer_sync(&sz->flush_timer); - } - - usb_kill_urb(sz->urb_in); - - stop_timer(sz); - - MOD_DEC_USE_COUNT; - sz->in_use--; -} - -static int streamzap_ioctl(struct inode *node, struct file *filep, - unsigned int cmd, unsigned long arg) -{ - int result; - - switch (cmd) { - case LIRC_GET_REC_RESOLUTION: - result = put_user(STREAMZAP_RESOLUTION, (unsigned int *) arg); - if (result) - return result; - break; - default: - return -ENOIOCTLCMD; - } - return 0; -} - -/** - * streamzap_disconnect - * - * Called by the usb core when the device is removed from the system. - * - * This routine guarantees that the driver will not submit any more urbs - * by clearing dev->udev. It is also supposed to terminate any currently - * active urbs. Unfortunately, usb_bulk_msg(), used in streamzap_read(), - * does not provide any way to do this. - */ -#ifdef KERNEL_2_5 -static void streamzap_disconnect(struct usb_interface *interface) -#else -static void streamzap_disconnect(struct usb_device *dev, void *ptr) -#endif -{ - struct usb_streamzap *sz; - int errnum; - int minor; - -#ifdef KERNEL_2_5 - sz = usb_get_intfdata(interface); -#else - sz = ptr; -#endif - - /* unregister from the LIRC sub-system */ - - errnum = lirc_unregister_driver(sz->driver.minor); - if (errnum != 0) - dprintk("error in lirc_unregister: (returned %d)", - sz->driver.minor, errnum); - - lirc_buffer_free(&sz->delay_buf); - lirc_buffer_free(&sz->lirc_buf); - - /* unregister from the USB sub-system */ - - usb_free_urb(sz->urb_in); - -#ifdef KERNEL_2_5 - usb_free_coherent(sz->udev, sz->buf_in_len, sz->buf_in, sz->dma_in); -#else - kfree(sz->buf_in); -#endif - - minor = sz->driver.minor; - kfree(sz); - - printk(KERN_INFO DRIVER_NAME "[%d]: disconnected\n", minor); -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) -static int streamzap_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct usb_streamzap *sz = usb_get_intfdata(intf); - - printk(KERN_INFO DRIVER_NAME "[%d]: suspend\n", sz->driver.minor); - if (sz->in_use) { - if (sz->flush) { - sz->flush = 0; - del_timer_sync(&sz->flush_timer); - } - - stop_timer(sz); - - usb_kill_urb(sz->urb_in); - } - return 0; -} - -static int streamzap_resume(struct usb_interface *intf) -{ - struct usb_streamzap *sz = usb_get_intfdata(intf); - - lirc_buffer_clear(&sz->lirc_buf); - lirc_buffer_clear(&sz->delay_buf); - - if (sz->in_use) { - sz->flush_timer.expires = jiffies + HZ; - sz->flush = 1; - add_timer(&sz->flush_timer); - - sz->urb_in->dev = sz->udev; -#ifdef KERNEL_2_5 - if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) { -#else - if (usb_submit_urb(sz->urb_in)) { -#endif - dprintk("open result = -EIO error submitting urb", - sz->driver.minor); - MOD_DEC_USE_COUNT; - return -EIO; - } - } - return 0; -} -#endif - -#ifdef MODULE -/** - * usb_streamzap_init - */ -static int __init usb_streamzap_init(void) -{ - int result; - - /* register this driver with the USB subsystem */ - result = usb_register(&streamzap_driver); - - if (result) { - err("usb_register failed. Error number %d", - result); - return result; - } - - printk(KERN_INFO DRIVER_NAME " " DRIVER_VERSION " registered\n"); - return 0; -} - -/** - * usb_streamzap_exit - */ -static void __exit usb_streamzap_exit(void) -{ - usb_deregister(&streamzap_driver); -} - - -module_init(usb_streamzap_init); -module_exit(usb_streamzap_exit); - -MODULE_AUTHOR("Christoph Bartelmus, Greg Wickham, Adrian Dewhurst"); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Enable debugging messages"); -EXPORT_NO_SYMBOLS; -#endif /* MODULE */ diff --git a/ubuntu/lirc/lirc_ttusbir/Makefile b/ubuntu/lirc/lirc_ttusbir/Makefile deleted file mode 100644 index aee214f4120..00000000000 --- a/ubuntu/lirc/lirc_ttusbir/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. - -obj-$(CONFIG_LIRC_TTUSBIR) += lirc_ttusbir.o diff --git a/ubuntu/lirc/lirc_ttusbir/lirc_ttusbir.c b/ubuntu/lirc/lirc_ttusbir/lirc_ttusbir.c deleted file mode 100644 index 36cf51981c7..00000000000 --- a/ubuntu/lirc/lirc_ttusbir/lirc_ttusbir.c +++ /dev/null @@ -1,410 +0,0 @@ -/* - * lirc_ttusbir.c - * - * lirc_ttusbir - LIRC device driver for the TechnoTrend USB IR Receiver - * - * Copyright (C) 2007 Stefan Macher <st_maker-lirc@yahoo.de> - * - * This LIRC driver provides access to the TechnoTrend USB IR Receiver. - * The receiver delivers the IR signal as raw sampled true/false data in - * isochronous USB packets each of size 128 byte. - * Currently the driver reduces the sampling rate by factor of 8 as this - * is still more than enough to decode RC-5 - others should be analyzed. - * But the driver does not rely on RC-5 it should be able to decode every - * IR signal that is not too fast. - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/version.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/errno.h> -#include <linux/slab.h> -#include <linux/usb.h> - -#include "../lirc.h" -#include "../kcompat.h" -#include "../lirc_dev/lirc_dev.h" - -MODULE_DESCRIPTION("TechnoTrend USB IR device driver for LIRC"); -MODULE_AUTHOR("Stefan Macher (st_maker-lirc@yahoo.de)"); -MODULE_LICENSE("GPL"); - -/* #define DEBUG */ -#ifdef DEBUG -#define DPRINTK printk -#else -#define DPRINTK(_x_, a...) -#endif - -/* function declarations */ -static int probe(struct usb_interface *intf, const struct usb_device_id *id); -static void disconnect(struct usb_interface *intf); -#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -static void urb_complete(struct urb *urb, struct pt_regs *pt_regs); -#else -static void urb_complete(struct urb *urb); -#endif -static int set_use_inc(void *data); -static void set_use_dec(void *data); - -static int num_urbs = 2; -module_param(num_urbs, int, S_IRUGO); -MODULE_PARM_DESC(num_urbs, - "Number of URBs in queue. Try to increase to 4 in case " - "of problems (default: 2; minimum: 2)"); - -/* table of devices that work with this driver */ -static struct usb_device_id device_id_table[] = { - /* TechnoTrend USB IR Receiver */ - { USB_DEVICE(0x0B48, 0x2003) }, - /* Terminating entry */ - { } -}; -MODULE_DEVICE_TABLE(usb, device_id_table); - -/* USB driver definition */ -static struct usb_driver usb_driver = { - .name = "TTUSBIR", - .id_table = &(device_id_table[0]), - .probe = probe, - .disconnect = disconnect, -}; - -/* USB device definition */ -struct ttusbir_device { - struct usb_driver *usb_driver; - struct usb_device *udev; - struct usb_interface *interf; - struct usb_class_driver class_driver; - unsigned int ifnum; /* Interface number to use */ - unsigned int alt_setting; /* alternate setting to use */ - unsigned int endpoint; /* Endpoint to use */ - struct urb **urb; /* num_urb URB pointers*/ - char **buffer; /* 128 byte buffer for each URB */ - struct lirc_buffer rbuf; /* Buffer towards LIRC */ - struct lirc_driver driver; - int minor; - int last_pulse; /* remembers if last received byte was pulse or space */ - int last_num; /* remembers how many last bytes appeared */ - int opened; -}; - -/*** LIRC specific functions ***/ -static int set_use_inc(void *data) -{ - int i, retval; - struct ttusbir_device *ttusbir = data; - - DPRINTK("Sending first URBs\n"); - /* @TODO Do I need to check if I am already opened */ - ttusbir->opened = 1; - - for (i = 0; i < num_urbs; i++) { - retval = usb_submit_urb(ttusbir->urb[i], GFP_KERNEL); - if (retval) { - err("%s: usb_submit_urb failed on urb %d", - __func__, i); - return retval; - } - } - return 0; -} - -static void set_use_dec(void *data) -{ - struct ttusbir_device *ttusbir = data; - - DPRINTK("Device closed\n"); - - ttusbir->opened = 0; -} - -/*** USB specific functions ***/ - -/* - * This mapping table is used to do a very simple filtering of the - * input signal. - * For a value with at least 4 bits set it returns 0xFF otherwise - * 0x00. For faster IR signals this can not be used. But for RC-5 we - * still have about 14 samples per pulse/space, i.e. we sample with 14 - * times higher frequency than the signal frequency - */ -const unsigned char map_table[] = -{ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, - 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, - 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, - 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, - 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -#if defined(KERNEL_2_5) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19) -static void urb_complete(struct urb *urb, struct pt_regs *pt_regs) -#else -static void urb_complete(struct urb *urb) -#endif -{ - struct ttusbir_device *ttusbir; - unsigned char *buf; - int i; - lirc_t l; - - ttusbir = urb->context; - - if (!ttusbir->opened) - return; - - buf = (unsigned char *)urb->transfer_buffer; - - for (i = 0; i < 128; i++) { - /* Here we do the filtering and some kind of down sampling */ - buf[i] = ~map_table[buf[i]]; - if (ttusbir->last_pulse == buf[i]) { - if (ttusbir->last_num < PULSE_MASK/63) - ttusbir->last_num++; - /* - * else we are in a idle period and do not need to - * increment any longer - */ - } else { - l = ttusbir->last_num * 62; /* about 62 = us/byte */ - if (ttusbir->last_pulse) /* pulse or space? */ - l |= PULSE_BIT; - if (!lirc_buffer_full(&ttusbir->rbuf)) { - lirc_buffer_write(&ttusbir->rbuf, (void *)&l); - wake_up_interruptible(&ttusbir->rbuf.wait_poll); - } - ttusbir->last_num = 0; - ttusbir->last_pulse = buf[i]; - } - } - usb_submit_urb(urb, GFP_ATOMIC); /* keep data rolling :-) */ -} - -/* - * Called whenever the USB subsystem thinks we could be the right driver - * to handle this device - */ -static int probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - int alt_set, endp; - int found = 0; - int i, j; - int struct_size; - struct usb_host_interface *host_interf; - struct usb_interface_descriptor *interf_desc; - struct usb_host_endpoint *host_endpoint; - struct ttusbir_device *ttusbir; - - DPRINTK("Module ttusbir probe\n"); - - /* To reduce memory fragmentation we use only one allocation */ - struct_size = sizeof(struct ttusbir_device) + - (sizeof(struct urb *) * num_urbs) + - (sizeof(char *) * num_urbs) + - (num_urbs * 128); - ttusbir = kzalloc(struct_size, GFP_KERNEL); - if (!ttusbir) - return -ENOMEM; - - ttusbir->urb = (struct urb **)((char *)ttusbir + - sizeof(struct ttusbir_device)); - ttusbir->buffer = (char **)((char *)ttusbir->urb + - (sizeof(struct urb *) * num_urbs)); - for (i = 0; i < num_urbs; i++) - ttusbir->buffer[i] = (char *)ttusbir->buffer + - (sizeof(char *)*num_urbs) + (i * 128); - - ttusbir->usb_driver = &usb_driver; - ttusbir->alt_setting = -1; - /* @TODO check if error can be returned */ - ttusbir->udev = usb_get_dev(interface_to_usbdev(intf)); - ttusbir->interf = intf; - ttusbir->last_pulse = 0x00; - ttusbir->last_num = 0; - - /* - * Now look for interface setting we can handle - * We are searching for the alt setting where end point - * 0x82 has max packet size 16 - */ - for (alt_set = 0; alt_set < intf->num_altsetting && !found; alt_set++) { - host_interf = &intf->altsetting[alt_set]; - interf_desc = &host_interf->desc; - for (endp = 0; endp < interf_desc->bNumEndpoints; endp++) { - host_endpoint = &host_interf->endpoint[endp]; - if ((host_endpoint->desc.bEndpointAddress == 0x82) && - (host_endpoint->desc.wMaxPacketSize == 0x10)) { - ttusbir->alt_setting = alt_set; - ttusbir->endpoint = endp; - found = 1; - break; - } - } - } - if (ttusbir->alt_setting != -1) - DPRINTK("alt setting: %d\n", ttusbir->alt_setting); - else { - err("Could not find alternate setting\n"); - kfree(ttusbir); - return -EINVAL; - } - - /* OK lets setup this interface setting */ - usb_set_interface(ttusbir->udev, 0, ttusbir->alt_setting); - - /* Store device info in interface structure */ - usb_set_intfdata(intf, ttusbir); - - /* Register as a LIRC driver */ - if (lirc_buffer_init(&ttusbir->rbuf, sizeof(lirc_t), 256) < 0) { - err("Could not get memory for LIRC data buffer\n"); - usb_set_intfdata(intf, NULL); - kfree(ttusbir); - return -ENOMEM; - } - strcpy(ttusbir->driver.name, "TTUSBIR"); - ttusbir->driver.minor = -1; - ttusbir->driver.code_length = 1; - ttusbir->driver.sample_rate = 0; - ttusbir->driver.data = ttusbir; - ttusbir->driver.add_to_buf = NULL; -#ifndef LIRC_REMOVE_DURING_EXPORT - ttusbir->driver.get_queue = NULL; -#endif - ttusbir->driver.rbuf = &ttusbir->rbuf; - ttusbir->driver.set_use_inc = set_use_inc; - ttusbir->driver.set_use_dec = set_use_dec; - ttusbir->driver.fops = NULL; - ttusbir->driver.dev = &intf->dev; - ttusbir->driver.owner = THIS_MODULE; - ttusbir->driver.features = LIRC_CAN_REC_MODE2; - ttusbir->minor = lirc_register_driver(&ttusbir->driver); - if (ttusbir->minor < 0) { - err("Error registering as LIRC driver\n"); - usb_set_intfdata(intf, NULL); - lirc_buffer_free(&ttusbir->rbuf); - kfree(ttusbir); - return -EIO; - } - - /* Allocate and setup the URB that we will use to talk to the device */ - for (i = 0; i < num_urbs; i++) { - ttusbir->urb[i] = usb_alloc_urb(8, GFP_KERNEL); - if (!ttusbir->urb[i]) { - err("Could not allocate memory for the URB\n"); - for (j = i - 1; j >= 0; j--) - kfree(ttusbir->urb[j]); - lirc_buffer_free(&ttusbir->rbuf); - lirc_unregister_driver(ttusbir->minor); - kfree(ttusbir); - usb_set_intfdata(intf, NULL); - return -ENOMEM; - } - ttusbir->urb[i]->dev = ttusbir->udev; - ttusbir->urb[i]->context = ttusbir; - ttusbir->urb[i]->pipe = usb_rcvisocpipe(ttusbir->udev, - ttusbir->endpoint); - ttusbir->urb[i]->interval = 1; - ttusbir->urb[i]->transfer_flags = URB_ISO_ASAP; - ttusbir->urb[i]->transfer_buffer = &ttusbir->buffer[i][0]; - ttusbir->urb[i]->complete = urb_complete; - ttusbir->urb[i]->number_of_packets = 8; - ttusbir->urb[i]->transfer_buffer_length = 128; - for (j = 0; j < 8; j++) { - ttusbir->urb[i]->iso_frame_desc[j].offset = j*16; - ttusbir->urb[i]->iso_frame_desc[j].length = 16; - } - } - return 0; -} - -/** - * Called when the driver is unloaded or the device is unplugged - */ -static void disconnect(struct usb_interface *intf) -{ - int i; - struct ttusbir_device *ttusbir; - - DPRINTK("Module ttusbir disconnect\n"); - - ttusbir = (struct ttusbir_device *) usb_get_intfdata(intf); - usb_set_intfdata(intf, NULL); - lirc_unregister_driver(ttusbir->minor); - DPRINTK("unregistered\n"); - - for (i = 0; i < num_urbs; i++) { - usb_kill_urb(ttusbir->urb[i]); - usb_free_urb(ttusbir->urb[i]); - } - DPRINTK("URBs killed\n"); - lirc_buffer_free(&ttusbir->rbuf); - kfree(ttusbir); -} - -static int ttusbir_init_module(void) -{ - int result; - - DPRINTK(KERN_DEBUG "Module ttusbir init\n"); - - /* register this driver with the USB subsystem */ - result = usb_register(&usb_driver); - if (result) - err("usb_register failed. Error number %d", result); - return result; -} - -static void ttusbir_exit_module(void) -{ - printk(KERN_DEBUG "Module ttusbir exit\n"); - usb_deregister(&usb_driver); -} - -module_init(ttusbir_init_module); -module_exit(ttusbir_exit_module); diff --git a/ubuntu/lirc/lirc_wpc8769l/Makefile b/ubuntu/lirc/lirc_wpc8769l/Makefile deleted file mode 100644 index 9f828e7fb7e..00000000000 --- a/ubuntu/lirc/lirc_wpc8769l/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -EXTRA_CFLAGS =-DIRCTL_DEV_MAJOR=61 -DLIRC_SERIAL_TRANSMITTER -DLIRC_SERIAL_SOFTCARRIER -I$(src)/.. - -obj-$(CONFIG_LIRC_WPC8769l) += lirc_wpc8769l.o diff --git a/ubuntu/lirc/lirc_wpc8769l/lirc_wpc8769l.c b/ubuntu/lirc/lirc_wpc8769l/lirc_wpc8769l.c deleted file mode 100644 index 99c325e0877..00000000000 --- a/ubuntu/lirc/lirc_wpc8769l/lirc_wpc8769l.c +++ /dev/null @@ -1,1177 +0,0 @@ -/* $Id: lirc_wpc8769l.c,v 1.8 2009/03/15 09:34:01 lirc Exp $ */ - -/**************************************************************************** - ** lirc_wpc8769l.c **************************************************** - **************************************************************************** - * - * lirc_wpc8769l - Device driver for the integrated CIR receiver found in - * Acer Aspire 6530G (and probably other models), based on - * the Winbond 8769L embedded controller. - * (Written using the lirc_serial driver as a guide). - * - * Copyright (C) 2008, 2009 Juan J. Garcia de Soria <skandalfo@gmail.com> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#include <linux/version.h> -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18) -#error "**********************************************************" -#error " Sorry, this driver needs kernel version 2.2.18 or higher " -#error "**********************************************************" -#endif - -#include <linux/module.h> -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/time.h> -#include <linux/timer.h> -#include <linux/types.h> -#include <linux/poll.h> - -#include <linux/bitops.h> - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16) -#include <asm/io.h> -#else -#include <linux/io.h> -#endif -#include <linux/irq.h> - -#include <linux/acpi.h> - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) -#include <linux/platform_device.h> -#endif - -#include "../lirc.h" -#include "../kcompat.h" -#include "../lirc_dev/lirc_dev.h" - -#include "lirc_wpc8769l.h" - -/* Name of the lirc device. */ -#define LIRC_DRIVER_NAME "lirc_wpc8769l" - -#define dprintk(fmt, args...) \ - do { \ - if (debug) \ - printk(KERN_DEBUG LIRC_DRIVER_NAME ": " \ - fmt, ## args); \ - } while (0) - -#define wprintk(fmt, args...) \ - do { \ - printk(KERN_WARN LIRC_DRIVER_NAME ": " \ - fmt, ## args); \ - } while (0) - -#define eprintk(fmt, args...) \ - do { \ - printk(KERN_ERR LIRC_DRIVER_NAME ": " \ - fmt, ## args); \ - } while (0) - -#define iprintk(fmt, args...) \ - do { \ - printk(KERN_INFO LIRC_DRIVER_NAME ": " \ - fmt, ## args); \ - } while (0) - -/* Number of driver->lirc-dev buffer elements. */ -#define RBUF_LEN 256 - -/* Number of 0xff bytes received in a row. */ -static unsigned int wpc8769l_ff_bytes_in_a_row; - -/* Hardware resource parameters. */ -static unsigned int baseport1; -static unsigned int baseport2; -static unsigned int irq; - -/* Debugging flag. */ -static int debug; - -/* If true, we skip ACPI autodetection and use the parameter-supplied I/O and - * IRQ. */ -static int skip_probe; - -/* Whether the device is open or not. */ -static int lirc_wpc8769l_is_open; - -/* Code disabled since it didn't seem to work with the test hardware. */ -/*#define LIRC_WPC8769L_WAKEUP*/ -#ifdef LIRC_WPC8769L_WAKEUP -/* These parameters are taken from the driver for MS Windows Vista. - * The specific values used for your hardware may be found at this registry - * key: - * - * HKEY_LOCAL_MACHINE/CurrentControlSet/Services/Winbond CIR/PowerKey - */ -static int protocol_select = 2; -static int max_info_bits = 24; -static unsigned int rc_wakeup_code = 0x7ffffbf3; -static unsigned int rc_wakeup_mask = 0xff000fff; -#endif - -/* Resource allocation pointers. */ -static struct resource *wpc8769l_portblock1_resource; -static struct resource *wpc8769l_portblock2_resource; - -/* Hardware related spinlock. */ -static DEFINE_SPINLOCK(wpc8769l_hw_spinlock); - -/* The buffer for ISR to bottom half data transfer. */ -static struct lirc_buffer rbuf; - -/* Bit-to-MODE2 coalescing helper variables. */ -static int last_was_pulse; -static lirc_t last_counter; - -/* Microseconds after a timeout-triggered pulse. */ -static s64 lastus; - -/* Microseconds when the timer was started. */ -static s64 timerstartus; - -/* Put another pulse/space to the queue, checking for overruns. */ -static void put_item(lirc_t data) -{ - if (lirc_buffer_full(&rbuf)) { - if (printk_ratelimit()) - eprintk("RX buffer overrun.\n"); - return; - } - lirc_buffer_write(&rbuf, (void *) &data); -} - -/* Put any accumulated pulse/space to userspace. */ -static void put_span(void) -{ - lirc_t data; - if (last_counter) { - /* Take the usecs length. */ - data = last_counter; - - /* Mark pulse or space. */ - if (last_was_pulse) - data |= PULSE_BIT; - - /* Put the span to the buffer. */ - put_item(data); - - /* Reset counter, in order to avoid emitting duplicate data. */ - last_counter = 0; - } -} - -/* Aggregate pulse time. */ -static void put_pulse_bit(lirc_t n) -{ - if (last_was_pulse) { - last_counter += n; - if (last_counter > PULSE_MASK) - last_counter = PULSE_MASK; - } else { - put_span(); - last_was_pulse = 1; - last_counter = n; - if (last_counter > PULSE_MASK) - last_counter = PULSE_MASK; - } -} - -/* Aggregate space time. */ -static void put_space_bit(lirc_t n) -{ - if (!last_was_pulse) { - last_counter += n; - if (last_counter > PULSE_MASK) - last_counter = PULSE_MASK; - } else { - put_span(); - last_was_pulse = 0; - last_counter = n; - if (last_counter > PULSE_MASK) - last_counter = PULSE_MASK; - } -} - -/* Timeout function for last pulse part. */ -static void wpc8769l_last_timeout(unsigned long l) -{ - struct timeval currenttv; - - unsigned long flags; - spin_lock_irqsave(&wpc8769l_hw_spinlock, flags); - - /* Mark the time at which we inserted the timeout span. */ - do_gettimeofday(¤ttv); - lastus = ((s64) currenttv.tv_sec) * 1000000ll + currenttv.tv_usec; - - /* Emit the timeout as a space. */ - put_space_bit(lastus - timerstartus); - - /* Signal the bottom half wait queue - * that there's data available. */ - wake_up_interruptible(&rbuf.wait_poll); - - spin_unlock_irqrestore(&wpc8769l_hw_spinlock, flags); -} - -/* Timer for end-of-code pulse timeout. */ -static struct timer_list last_span_timer = - TIMER_INITIALIZER(wpc8769l_last_timeout, 0, 0); - -/* Interrupt handler, doing the bit sample to mode2 conversion. - * Perhaps this work should be taken outside of the ISR... */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) -static irqreturn_t irq_handler(int irqno, void *blah) -#else -static irqreturn_t irq_handler(int irqno, void *blah, struct pt_regs *regs) -#endif -{ - unsigned int data; - int handled = 0; - int count, more; - struct timeval currenttv; - s64 currentus, span; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) - unsigned char data_buf[WPC8769L_BYTE_BUFFER_SIZE]; - unsigned char *data_ptr; - unsigned long *ldata; - unsigned int next_one, next_zero, size; -#else - unsigned int mask; -#endif - - unsigned long flags; - spin_lock_irqsave(&wpc8769l_hw_spinlock, flags); - - /* Check whether there's any data available. */ - outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG); - data = inb(baseport1 + WPC8769L_DATA_STATUS_REG); - - if (data & WPC8769L_DATA_READY_MASK) { - /* Get current timestamp. */ - do_gettimeofday(¤ttv); - currentus = ((s64) currenttv.tv_sec) * 1000000ll + - currenttv.tv_usec; - - /* If we had a timeout before we might need to fill - * in additional space time. */ - if (lastus) { - /* Calculate the difference, compensating - * the time for the data successfully - * received (estimated to be - * WPC8769L_BYTES_PER_BURST bytes). */ - span = currentus - lastus - - WPC8769L_BYTES_PER_BURST - * WPC8769L_USECS_PER_BYTE; - - /* Only insert positive spans. */ - if (span > 0) { - /* Emit the extended gap as a space. */ - put_space_bit(span); - } - - /* Mark that we had the last timeout into account. */ - lastus = 0; - } - - count = 0; - more = 1; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) - data_ptr = data_buf; -#endif - do { - /* Read the next byte of data. */ - outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG); - data = inb(baseport1 + WPC8769L_DATA_REG); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) - *data_ptr++ = data; -#else - for (mask = 0x01 ; mask < 0x100; mask <<= 1) { - if (data & mask) - put_space_bit(WPC8769L_USECS_PER_BIT); - else - put_pulse_bit(WPC8769L_USECS_PER_BIT); - } -#endif - - /* Check for 0xff in a row. */ - if (data == 0xff) - wpc8769l_ff_bytes_in_a_row++; - else - wpc8769l_ff_bytes_in_a_row = 0; - - outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG); - data = inb(baseport1 + WPC8769L_DATA_ACK_REG); - if (data & WPC8769L_DATA_ACK_REG) { - outb(WPC8769L_BANK_E0, - baseport1 + WPC8769L_SELECT_REG); - data = inb(baseport1 + - WPC8769L_REMAINING_RX_DATA_REG); - if (!data) - more = 0; - } else - more = 0; - - count++; - } while (more && count < WPC8769L_BYTES_PER_BURST); - - if (wpc8769l_ff_bytes_in_a_row - >= WPC8769L_FF_BYTES_BEFORE_RESET) { - - /* Put in another 0xff byte. */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) - *data_ptr++ = 0xff; - count++; -#else - put_space_bit(8 * WPC8769L_USECS_PER_BIT); -#endif - - /* Reset the hardware in the case of too many - * 0xff bytes in a row. */ - outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG); - outb(WPC8769L_TIMEOUT_RESET_MASK, - baseport1 + WPC8769L_TIMEOUT_RESET_REG); - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) - /* Emit the data. */ - size = count << 3; - - ldata = (unsigned long *) data_buf; - next_one = generic_find_next_le_bit(ldata, size, 0); - - if (next_one > 0) - put_pulse_bit(next_one - * WPC8769L_USECS_PER_BIT); - - while (next_one < size) { - next_zero = generic_find_next_zero_le_bit(ldata, - size, next_one + 1); - - put_space_bit( - (next_zero - next_one) - * WPC8769L_USECS_PER_BIT); - - if (next_zero < size) { - next_one = generic_find_next_le_bit(ldata, - size, next_zero + 1); - - put_pulse_bit( - (next_one - next_zero) - * WPC8769L_USECS_PER_BIT); - } else { - next_one = size; - } - } -#endif - - /* Mark the IRQ as handled. */ - handled = 1; - - /* Signal the bottom half wait queue - * that there's data available. */ - wake_up_interruptible(&rbuf.wait_poll); - - /* Set up timeout handling. */ - mod_timer(&last_span_timer, - jiffies + WPC8769L_LAST_TIMEOUT_JIFFIES); - - /* Set up last timer us mark. */ - timerstartus = currentus; - } - - spin_unlock_irqrestore(&wpc8769l_hw_spinlock, flags); - return IRQ_RETVAL(handled); -} - -/* Prepare the hardware on module load. */ -static void wpc8769l_prepare_hardware(void) -{ - unsigned long flags; - spin_lock_irqsave(&wpc8769l_hw_spinlock, flags); - - /* I don't know why this needs reading. */ - outb(WPC8769L_BANK_E4, baseport1 + WPC8769L_SELECT_REG); - inb(baseport1 + WPC8769L_READ_ON_STARTUP_REG); - - spin_unlock_irqrestore(&wpc8769l_hw_spinlock, flags); -} - - -/* Wake up device from power down and check whether it was the - * device that woke us up. - */ -static int wpc8769l_power_up_and_check_if_we_woke_us_up(void) -{ - unsigned int data; - int res; - - unsigned long flags; - spin_lock_irqsave(&wpc8769l_hw_spinlock, flags); - - if (baseport2) { - data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG); - data &= ~WPC8769L_CLOCK_OFF_MASK; - data |= WPC8769L_CLOCK_ON_MASK; - outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG); - - res = inb(baseport2 + WPC8769L_WAKEUP_STATUS_REG) - & WPC8769L_WAKEUP_WOKE_UP_MASK; - - data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG); - data &= ~WPC8769L_CLOCK_OFF_MASK; - data |= WPC8769L_CLOCK_ON_MASK; - outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG); - - outb(WPC8769L_WAKEUP_WOKE_UP_MASK, - baseport2 + WPC8769L_WAKEUP_STATUS_REG); - - outb(WPC8769L_WAKEUP_ACK_MASK, - baseport2 + WPC8769L_WAKEUP_ACK_REG); - } else { - outb(WPC8769L_BANK_F0, baseport1 + WPC8769L_SELECT_REG); - res = (inb(baseport1 + WPC8769L_WAKEUP_STATUS_LEG_REG) - & WPC8769L_WAKEUP_STATUS_LEG_MASK) ? 1 : 0; - } - - spin_unlock_irqrestore(&wpc8769l_hw_spinlock, flags); - - return res; -} - -/* Disable interrupts from device. */ -static void wpc8769l_disable_interrupts(void) -{ - unsigned long flags; - spin_lock_irqsave(&wpc8769l_hw_spinlock, flags); - - outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG); - outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG); - outb(inb(baseport1 + WPC8769L_INTERRUPT_REG) - & ~WPC8769L_INTERRUPT_1_MASK, - baseport1 + WPC8769L_INTERRUPT_REG); - outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG); - outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG); - outb(inb(baseport1 + WPC8769L_INTERRUPT_REG) - & ~WPC8769L_INTERRUPT_1_MASK, - baseport1 + WPC8769L_INTERRUPT_REG); - - spin_unlock_irqrestore(&wpc8769l_hw_spinlock, flags); -} - -#ifdef LIRC_WPC8769L_WAKEUP -/* Expand value nibble for configuration of wake up parameters. - * This seems to manchester-encode a nibble into a byte. */ -static unsigned int wpc8769l_expand_value_nibble(unsigned int nibble) -{ - int i; - unsigned int tmp, tmp2, res; - - res = 0; - - for (i = 0; i < 4; i += 2) { - tmp = (nibble >> i) & 0x3; - switch (tmp) { - case 3: - tmp2 = 5; - break; - case 2: - tmp2 = 6; - break; - case 1: - tmp2 = 9; - break; - case 0: - tmp2 = 0x0a; - break; - default: - return 0; - break; - } - res |= ((tmp2 << i) << i); - } - - return res; -} - -/* Expand mask nibble for configuration of wake up parameters. */ -static unsigned int wpc8769l_expand_mask_nibble(unsigned int nibble) -{ - int i; - unsigned int tmp, tmp2, res; - - res = 0; - - for (i = 0; i < 4; i += 2) { - tmp = (nibble >> i) & 0x3; - switch (tmp) { - case 0: - tmp2 = 0; - break; - case 1: - tmp2 = 3; - break; - case 2: - tmp2 = 0x0c; - break; - case 3: - tmp2 = 0x0f; - break; - default: - return 0; - break; - } - res |= ((tmp2 << i) << i); - } - - return res; -} - -/* Configure wake up triggers for the hardware that supports it. - * THE CALLER MUST HAVE ACQUIRED wpc8769l_hw_spinlock BEFORE CALLING. - */ -static void wpc8769l_configure_wakeup_triggers(void) -{ - unsigned int x; - unsigned int data, data2; - - int i, j; - - x = inb(baseport2 + WPC8769L_WAKEUP_ENABLE_REG) - & WPC8769L_WAKEUP_ENABLE_MASK; - outb(inb(baseport2 + WPC8769L_WAKEUP_ENABLE_REG) - & ~WPC8769L_WAKEUP_ENABLE_MASK, - baseport2 + WPC8769L_WAKEUP_ENABLE_REG); - - data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG); - data &= ~WPC8769L_CLOCK_OFF_MASK; - data |= WPC8769L_CLOCK_ON_MASK; - outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG); - - outb(WPC8769L_WAKEUP_CONFIGURING_MASK, - baseport2 + WPC8769L_WAKEUP_STATUS_REG); - outb(WPC8769L_WAKEUP_ACK_MASK, - baseport2 + WPC8769L_WAKEUP_ACK_REG); - - data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG); - data &= ~WPC8769L_CLOCK_OFF_MASK; - data |= WPC8769L_CLOCK_ON_MASK; - outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG); - - data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG); - data &= ~WPC8769L_CLOCK_OFF_MASK; - data |= WPC8769L_CLOCK_ON_MASK; - outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG); - - data = inb(baseport2 + WPC8769L_WAKEUP_CONFIG_REG); - data &= WPC8769L_WAKEUP_CONFIG_PRE_MASK; - data |= (max_info_bits + WPC8769L_MAX_INFO_BITS_BIAS) - << WPC8769L_MAX_INFO_BITS_SHIFT; - outb(data, baseport2 + WPC8769L_WAKEUP_CONFIG_REG); - - i = j = 0; - - /* Program values. */ - while (j < WPC8769L_WAKEUP_DATA_BITS) { - data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG); - data &= ~WPC8769L_CLOCK_OFF_MASK; - data |= WPC8769L_CLOCK_ON_MASK; - outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG); - - outb(i + WPC8769L_WAKEUP_DATA_BASE, - baseport2 + WPC8769L_WAKEUP_DATA_PTR_REG); - - data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG); - data &= ~WPC8769L_CLOCK_OFF_MASK; - data |= WPC8769L_CLOCK_ON_MASK; - outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG); - - data = (rc_wakeup_code >> j) & 0x0f; - data = wpc8769l_expand_value_nibble(data); - outb(data, baseport2 + WPC8769L_WAKEUP_DATA_REG); - - i++; - j += 4; - } - - /* Program masks. */ - while (j < WPC8769L_WAKEUP_DATA_BITS) { - data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG); - data &= ~WPC8769L_CLOCK_OFF_MASK; - data |= WPC8769L_CLOCK_ON_MASK; - outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG); - - outb(i + WPC8769L_WAKEUP_MASK_BASE, - baseport2 + WPC8769L_WAKEUP_DATA_PTR_REG); - - data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG); - data &= ~WPC8769L_CLOCK_OFF_MASK; - data |= WPC8769L_CLOCK_ON_MASK; - outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG); - - data = (rc_wakeup_mask >> j) & 0x0f; - data = wpc8769l_expand_mask_nibble(data); - outb(data, baseport2 + WPC8769L_WAKEUP_DATA_REG); - - i++; - j += 4; - } - - data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG); - data &= ~WPC8769L_CLOCK_OFF_MASK; - data |= WPC8769L_CLOCK_ON_MASK; - outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG); - - data2 = inb(baseport2 + WPC8769L_WAKEUP_CONFIG2_REG); - data2 &= WPC8769L_WAKEUP_CONFIG2_AND_MASK; - data2 |= WPC8769L_WAKEUP_CONFIG2_OR_MASK; - - data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG); - data &= ~WPC8769L_CLOCK_OFF_MASK; - data |= WPC8769L_CLOCK_ON_MASK; - outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG); - - outb(data2, baseport2 + WPC8769L_WAKEUP_CONFIG2_REG); - - if (x != WPC8769L_WAKEUP_ENABLE_MASK) - outb(inb(baseport2 + WPC8769L_WAKEUP_ENABLE_REG) - | WPC8769L_WAKEUP_ENABLE_MASK, - baseport2 + WPC8769L_WAKEUP_ENABLE_REG); -} -#endif - -/* Enable interrupts from device. */ -static void wpc8769l_enable_interrupts(void) -{ - unsigned int data, data2, data_save; - - unsigned int a, b; - - unsigned long flags; - spin_lock_irqsave(&wpc8769l_hw_spinlock, flags); - - outb(WPC8769L_BANK_F0, baseport1 + WPC8769L_SELECT_REG); - data_save = inb(baseport1 + WPC8769L_WAKEUP_STATUS_LEG_REG); - - outb(WPC8769L_BANK_E0, baseport1 + WPC8769L_SELECT_REG); - outb(0, baseport1 + WPC8769L_HARDWARE_ENABLE1_REG); - - outb(WPC8769L_BANK_E0, baseport1 + WPC8769L_SELECT_REG); - outb(WPC8769L_BANK_E0, baseport1 + WPC8769L_SELECT_REG); - outb(inb(baseport1 + WPC8769L_HARDWARE_ENABLE1_REG) - | WPC8769L_HARDWARE_ENABLE1_MASK, - baseport1 + WPC8769L_HARDWARE_ENABLE1_REG); - - outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG); - outb(0, baseport1 + WPC8769L_CONFIG_REG); - - outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG); - outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG); - data = inb(baseport1 + WPC8769L_CONFIG_REG); - data &= ~WPC8769L_CONFIG_OFF_MASK; - data |= WPC8769L_CONFIG_ON_MASK; - outb(data, baseport1 + WPC8769L_CONFIG_REG); - - outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG); - outb(WPC8769L_DATA_STATUS_MASK_1, baseport1 + WPC8769L_DATA_STATUS_REG); - - outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG); - outb(WPC8769L_DATA_STATUS_MASK_2, baseport1 + WPC8769L_DATA_STATUS_REG); - - outb(WPC8769L_BANK_F4, baseport1 + WPC8769L_SELECT_REG); - outb(WPC8769L_BANK_F4, baseport1 + WPC8769L_SELECT_REG); - outb(inb(baseport1 + WPC8769L_CONFIG2_REG) - & ~WPC8769L_CONFIG2_OFF_MASK, - baseport1 + WPC8769L_CONFIG2_REG); - - outb(WPC8769L_BANK_EC, baseport1 + WPC8769L_SELECT_REG); - outb(WPC8769L_BANK_EC, baseport1 + WPC8769L_SELECT_REG); - outb(inb(baseport1 + WPC8769L_CONFIG3_REG) - | WPC8769L_CONFIG3_ON_MASK, - baseport1 + WPC8769L_CONFIG3_REG); - - outb(WPC8769L_BANK_F4, baseport1 + WPC8769L_SELECT_REG); - data = inb(baseport1 + WPC8769L_CONFIG4_REG); - data &= WPC8769L_CONFIG4_AND_MASK; - data |= WPC8769L_CONFIG4_ON_MASK; - - outb(WPC8769L_BANK_F4, baseport1 + WPC8769L_SELECT_REG); - outb(data, baseport1 + WPC8769L_CONFIG4_REG); - - outb(WPC8769L_BANK_E0, baseport1 + WPC8769L_SELECT_REG); - outb(WPC8769L_BANK_E0, baseport1 + WPC8769L_SELECT_REG); - outb(inb(baseport1 + WPC8769L_CONFIG5_REG) - | WPC8769L_CONFIG5_ON_MASK, - baseport1 + WPC8769L_CONFIG5_REG); - - outb(WPC8769L_BANK_E0, baseport1 + WPC8769L_SELECT_REG); - outb(WPC8769L_CONFIG6_MASK, baseport1 + WPC8769L_CONFIG6_REG); - - outb(WPC8769L_BANK_E0, baseport1 + WPC8769L_SELECT_REG); - outb(0, baseport1 + WPC8769L_CONFIG7_REG); - - if (baseport2) { - /* - * This has to do with wake-up support, which is - * disabled when the second I/O range doesn't - * exist. - */ - /* -- internal subroutine -- */ - data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG); - data &= ~WPC8769L_CLOCK_OFF_MASK; - data |= WPC8769L_CLOCK_ON_MASK; - outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG); - - data2 = inb(baseport2 + WPC8769L_WAKEUP_CONFIG3_REG); - a = (data2 >> WPC8769L_WAKEUP_CONFIG3_A_SHIFT) - & WPC8769L_WAKEUP_CONFIG3_A_MASK; - b = (data2 >> WPC8769L_WAKEUP_CONFIG3_B_SHIFT) - & WPC8769L_WAKEUP_CONFIG3_B_MASK; - - data = inb(baseport2 + WPC8769L_BANK2_CLOCK_REG); - data &= ~WPC8769L_CLOCK_OFF_MASK; - data |= WPC8769L_CLOCK_ON_MASK; - outb(data, baseport2 + WPC8769L_BANK2_CLOCK_REG); - - data2 &= ~WPC8769L_WAKEUP_CONFIG3_OFF_MASK; - data2 |= WPC8769L_WAKEUP_CONFIG3_ON_MASK; - outb(data2, baseport2 + WPC8769L_WAKEUP_CONFIG3_REG); - /* -- end internal subroutine -- */ - -#ifdef LIRC_WPC8769L_WAKEUP - /* Call for setting wake up filters */ - wpc8769l_configure_wakeup_triggers(); -#endif - } else { - /* No second port range. Take these defaults. */ - a = (data_save & WPC8769L_WAKEUP_STATUS_LEG_MASK_A) - ? 0 : 1; - b = (data_save & WPC8769L_WAKEUP_STATUS_LEG_MASK_B) - ? 1 : 0; - } - - outb(WPC8769L_BANK_EC, baseport1 + WPC8769L_SELECT_REG); - outb(WPC8769L_BANK_EC, baseport1 + WPC8769L_SELECT_REG); - - data = inb(baseport1 + WPC8769L_CONFIG3_REG); - data = (a == 1) - ? (data & ~WPC8769L_CONFIG3_MASK_1) - : (data | WPC8769L_CONFIG3_MASK_1); - outb(data, baseport1 + WPC8769L_CONFIG3_REG); - - outb(WPC8769L_BANK_F4, baseport1 + WPC8769L_SELECT_REG); - outb(WPC8769L_BANK_F4, baseport1 + WPC8769L_SELECT_REG); - - data = inb(baseport1 + WPC8769L_CONFIG2_REG); - data = (b == 0) - ? (data & ~WPC8769L_CONFIG2_MASK_1) - : (data | WPC8769L_CONFIG2_MASK_1); - outb(data, baseport1 + WPC8769L_CONFIG2_REG); - - outb(0, baseport1 + WPC8769L_CONFIG8_REG); - - outb(0, baseport1 + WPC8769L_CONFIG9_REG); - - outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG); - outb(WPC8769L_BANK_00, baseport1 + WPC8769L_SELECT_REG); - outb(inb(baseport1 + WPC8769L_INTERRUPT_REG) - | WPC8769L_INTERRUPT_1_MASK, - baseport1 + WPC8769L_INTERRUPT_REG); - - spin_unlock_irqrestore(&wpc8769l_hw_spinlock, flags); -} - -/* Called when the device is opened. */ -static int set_use_inc(void *data) -{ - int result; - - /* Reset pulse values. */ - last_was_pulse = 0; - last_counter = 0; - - /* Reset last timeout value. */ - lastus = 0; - - /* Init the read buffer. */ - if (lirc_buffer_init(&rbuf, sizeof(lirc_t), RBUF_LEN) < 0) - return -ENOMEM; - - /* Acquire the IRQ. */ - result = request_irq(irq, irq_handler, - IRQF_DISABLED | IRQF_SHARED, - LIRC_DRIVER_NAME, THIS_MODULE); - - switch (result) { - case -EBUSY: - eprintk("IRQ %d busy\n", irq); - lirc_buffer_free(&rbuf); - return -EBUSY; - case -EINVAL: - eprintk("Bad irq number or handler\n"); - lirc_buffer_free(&rbuf); - return -EINVAL; - default: - dprintk("IRQ %d obtained.\n", irq); - break; - }; - - /* Mark the device as open. */ - lirc_wpc8769l_is_open = 1; - - /* Enable hardware interrupts. */ - wpc8769l_enable_interrupts(); - - MOD_INC_USE_COUNT; - return 0; -} - -/* Called when the device is released. */ -static void set_use_dec(void *data) -{ - /* Mark the device as closed. */ - lirc_wpc8769l_is_open = 0; - - /* Cancel the timeout if pending. */ - del_timer_sync(&last_span_timer); - - /* Disable the hardware interrupts. */ - wpc8769l_disable_interrupts(); - - /* Free the IRQ. */ - free_irq(irq, THIS_MODULE); - dprintk("Freed IRQ %d\n", irq); - - /* Free the RX buffer. */ - lirc_buffer_free(&rbuf); - - MOD_DEC_USE_COUNT; -} - -static struct lirc_driver driver = { - .name = LIRC_DRIVER_NAME, - .minor = -1, - .code_length = 1, - .sample_rate = 0, - .data = NULL, - .add_to_buf = NULL, - .get_queue = NULL, - .rbuf = &rbuf, - .set_use_inc = set_use_inc, - .set_use_dec = set_use_dec, - .fops = NULL, - .dev = NULL, - .owner = THIS_MODULE, -}; - -static acpi_status wec_parse_resources(struct acpi_resource *resource, - void *context) -{ - if (resource->type == ACPI_RESOURCE_TYPE_IO) { - /* Read the two I/O ranges. */ - if (!baseport1) - baseport1 = resource->data.io.minimum; - else if (!baseport2) - baseport2 = resource->data.io.minimum; - } else if (resource->type == ACPI_RESOURCE_TYPE_IRQ) { - /* Read the rx IRQ number. */ - if (!irq) - irq = resource->data.irq.interrupts[0]; - } - return AE_OK; -} - -static acpi_status wec_parse_device(acpi_handle handle, u32 level, - void *context, void **return_value) -{ - acpi_status status; - iprintk("Found %s device via ACPI.\n", WPC8769L_ACPI_HID); - - status = acpi_walk_resources(handle, METHOD_NAME__CRS, - wec_parse_resources, NULL); - if (ACPI_FAILURE(status)) - return status; - - return AE_OK; -} - -/* Find the device I/O ranges and IRQ number by searching for the - * CIR ACPI entry. */ -static int wpc8769l_acpi_detect(void) -{ - acpi_status status; - status = acpi_get_devices(WPC8769L_ACPI_HID, wec_parse_device, NULL, - NULL); - if (ACPI_FAILURE(status)) - return -ENOENT; - else - return 0; -} - -#ifdef MODULE -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) -static struct platform_device *lirc_wpc8769l_platform_dev; - -static int __devinit lirc_wpc8769l_probe(struct platform_device *dev) -{ - return 0; -} - -static int __devexit lirc_wpc8769l_remove(struct platform_device *dev) -{ - return 0; -} - -static int lirc_wpc8769l_suspend(struct platform_device *dev, - pm_message_t state) -{ - if (lirc_wpc8769l_is_open) - /* Disable all interrupts. */ - wpc8769l_disable_interrupts(); - return 0; -} - -static int lirc_wpc8769l_resume(struct platform_device *dev) -{ - if (lirc_wpc8769l_is_open) { - /* Check if we caused resuming; we still do nothing about it. */ - wpc8769l_power_up_and_check_if_we_woke_us_up(); - - /* Enable interrupts again. */ - wpc8769l_enable_interrupts(); - } - return 0; -} - -static struct platform_driver lirc_wpc8769l_platform_driver = { - .probe = lirc_wpc8769l_probe, - .remove = __devexit_p(lirc_wpc8769l_remove), - .suspend = lirc_wpc8769l_suspend, - .resume = lirc_wpc8769l_resume, - .driver = { - .name = LIRC_DRIVER_NAME, - .owner = THIS_MODULE, - }, -}; - -static int __init lirc_wpc8769l_platform_init(void) -{ - int result; - - result = platform_driver_register(&lirc_wpc8769l_platform_driver); - if (result) { - eprintk("Platform driver register returned %d.\n", result); - return result; - } - - lirc_wpc8769l_platform_dev = platform_device_alloc(LIRC_DRIVER_NAME, 0); - if (!lirc_wpc8769l_platform_dev) { - result = -ENOMEM; - goto exit_driver_unregister; - } - - result = platform_device_add(lirc_wpc8769l_platform_dev); - if (result) - goto exit_device_put; - - return 0; - -exit_device_put: - platform_device_put(lirc_wpc8769l_platform_dev); - -exit_driver_unregister: - platform_driver_unregister(&lirc_wpc8769l_platform_driver); - return result; -} - -static void __exit lirc_wpc8769l_platform_exit(void) -{ - platform_device_unregister(lirc_wpc8769l_platform_dev); - platform_driver_unregister(&lirc_wpc8769l_platform_driver); -} -#endif - -static int __init lirc_wpc8769l_module_init(void) -{ - int rc; - - /* If needed, read the resource information for the ACPI device - * description. */ - if (!skip_probe) { - rc = wpc8769l_acpi_detect(); - if (rc) { - eprintk("Error when looking for %s ACPI device.\n", - WPC8769L_ACPI_HID); - return rc; - } - } - - /* Check that we got some resource info to work with. */ - if (!baseport1 || !irq) { - rc = -ENODEV; - eprintk("Not all required resources found for %s device.\n", - LIRC_DRIVER_NAME); - return rc; - } - - dprintk("%s device found to use 0x%04x, 0x%04x I/O bases, IRQ #%d.\n", - LIRC_DRIVER_NAME, baseport1, baseport2, irq); - - /* Request the two I/O regions. */ - wpc8769l_portblock1_resource = request_region(baseport1, - WPC8769L_IO_REGION_1_SIZE, LIRC_DRIVER_NAME); - if (!wpc8769l_portblock1_resource) { - rc = -EBUSY; - eprintk("Could not allocate I/O range at 0x%04x", baseport1); - return rc; - } - if (baseport2) { - wpc8769l_portblock2_resource = request_region(baseport2, - WPC8769L_IO_REGION_2_SIZE, LIRC_DRIVER_NAME); - if (!wpc8769l_portblock2_resource) { - rc = -EBUSY; - printk(KERN_ERR "Could not allocate I/O range " - "at 0x%04x", - baseport2); - goto exit_release_region_1; - } - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) - /* Register the platform driver and device. */ - rc = lirc_wpc8769l_platform_init(); - if (rc) - goto exit_release_region_2; -#endif - - /* Prepare the hardware. */ - wpc8769l_prepare_hardware(); - - /* Do load-time checks. */ - wpc8769l_power_up_and_check_if_we_woke_us_up(); - - /* Configure the driver hooks. */ - driver.features = LIRC_CAN_REC_MODE2; - driver.minor = lirc_register_driver(&driver); - if (driver.minor < 0) { - eprintk("lirc_register_driver failed!\n"); - rc = -EIO; - goto exit_platform_exit; - } - - iprintk("Driver loaded.\n"); - - return 0; /* Everything OK. */ - -exit_platform_exit: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) - lirc_wpc8769l_platform_exit(); - -exit_release_region_2: -#endif - if (baseport2) - release_region(baseport2, WPC8769L_IO_REGION_2_SIZE); - -exit_release_region_1: - release_region(baseport1, WPC8769L_IO_REGION_1_SIZE); - - return rc; -} - -module_init(lirc_wpc8769l_module_init); - -static void __exit lirc_wpc8769l_module_exit(void) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) - /* Unregister the platform driver and device. */ - lirc_wpc8769l_platform_exit(); -#endif - - /* Unregister the LIRC driver. */ - lirc_unregister_driver(driver.minor); - - /* Release the second range. */ - if (baseport2) - release_region(baseport2, WPC8769L_IO_REGION_2_SIZE); - - /* Release the first range. */ - release_region(baseport1, WPC8769L_IO_REGION_1_SIZE); - - iprintk("Driver unloaded.\n"); -} - -module_exit(lirc_wpc8769l_module_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Juan J. Garcia de Soria"); -MODULE_DESCRIPTION("Driver for the integrated Winbond WPC8769L-based IR\ - receiver found in Acer laptops."); -MODULE_VERSION("0.0"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Enable debugging messages"); - -module_param(baseport1, uint, S_IRUGO); -MODULE_PARM_DESC(baseport1, - "First I/O range base address (default: ACPI autodetect)."); - -module_param(baseport2, uint, S_IRUGO); -MODULE_PARM_DESC(baseport2, - "Second I/O range base address (default: ACPI autodetect)."); - -module_param(irq, uint, S_IRUGO); -MODULE_PARM_DESC(irq, "IRQ number (default: ACPI autodetect)."); - -module_param(skip_probe, bool, S_IRUGO); -MODULE_PARM_DESC(skip_probe, - "Skip ACPI-based device detection \ -(default: false for ACPI autodetect)."); - -#ifdef LIRC_WPC8769L_WAKEUP -module_param(protocol_select, int, S_IRUGO); -MODULE_PARM_DESC(protocol_select, - "Define the protocol for wake up functions (default: 2)."); - -module_param(max_info_bits, int, S_IRUGO); -MODULE_PARM_DESC(max_info_bits, - "Define the maximum info bits for wake up functions (default: 24)."); - -module_param(rc_wakeup_code, uint, S_IRUGO); -MODULE_PARM_DESC(rc_wakeup_code, - "Define the RC code value for wake up functions\ - (default: 0x7ffffbf3)."); - -module_param(rc_wakeup_mask, uint, S_IRUGO); -MODULE_PARM_DESC(rc_wakeup_mask, - "Define the RC code mask for wake up functions (default: 0xff000fff)."); -#endif - -EXPORT_NO_SYMBOLS; - -#endif /* MODULE */ - diff --git a/ubuntu/lirc/lirc_wpc8769l/lirc_wpc8769l.h b/ubuntu/lirc/lirc_wpc8769l/lirc_wpc8769l.h deleted file mode 100644 index d250bdc7a54..00000000000 --- a/ubuntu/lirc/lirc_wpc8769l/lirc_wpc8769l.h +++ /dev/null @@ -1,186 +0,0 @@ -/* $Id: lirc_wpc8769l.h,v 1.5 2009/06/15 15:11:39 jarodwilson Exp $ */ - -/**************************************************************************** - ** lirc_wpc8769l.h **************************************************** - **************************************************************************** - * - * lirc_wpc8769l - Device driver for the integrated CIR receiver found in - * Acer Aspire 6530G (and probably other models), based on - * the Winbond 8769L embedded controller. - * (Written using the lirc_serial driver as a guide). - * - * Copyright (C) 2008, 2009 Juan J. Garcia de Soria <skandalfo@gmail.com> - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include <linux/types.h> - -/* Name of the ACPI resource used to autodetect the receiver. */ -#define WPC8769L_ACPI_HID "WEC1020" - -/* Number of microseconds for a whole byte of samples. */ -/* This is assuming 20 kHz bit sampling frequency. */ -#define WPC8769L_USECS_PER_BYTE 400 - -/* Number of microseconds for a bit sample. */ -#define WPC8769L_USECS_PER_BIT (WPC8769L_USECS_PER_BYTE >> 3) - -/* Number of bytes in each data burst. */ -#define WPC8769L_BYTES_PER_BURST 14 - -/* Number of 0xff bytes before reset. */ -#define WPC8769L_FF_BYTES_BEFORE_RESET 250 - -/* Microseconds timeout for last part of code. */ -#define WPC8769L_LAST_TIMEOUT_JIFFIES (HZ / 20) - -/* Microseconds timeout for last part of code. */ -#define WPC8769L_LAST_TIMEOUT_JIFFIES (HZ / 20) - -/* Size of I/O region 1. */ -#define WPC8769L_IO_REGION_1_SIZE 0x08 - -/* Size of I/O region 2. */ -#define WPC8769L_IO_REGION_2_SIZE 0x20 - -/* Size of a byte array for a complete burst, rounded - * up to an integral number of unsigned longs. */ -#define WPC8769L_BYTE_BUFFER_SIZE \ - (((WPC8769L_BYTES_PER_BURST + 1 + BITS_PER_LONG / 8 - 1) \ - / (BITS_PER_LONG / 8)) * (BITS_PER_LONG / 8)) - - - -/* WPC8769L register set definitions. Note that these are all wild guesses.*/ - -/* Registers for I/O range 1. */ -#define WPC8769L_SELECT_REG 0x03 - -/*------------*/ -#define WPC8769L_BANK_00 0x00 - -#define WPC8769L_DATA_REG 0x00 - -#define WPC8769L_INTERRUPT_REG 0x01 -#define WPC8769L_INTERRUPT_1_MASK 0x01 -#define WPC8769L_INTERRUPT_2_MASK 0x01 - -#define WPC8769L_DATA_STATUS_REG 0x02 -#define WPC8769L_DATA_READY_MASK 0x01 -#define WPC8769L_DATA_STATUS_MASK_1 0x02 -#define WPC8769L_DATA_STATUS_MASK_2 0xd0 - -#define WPC8769L_CONFIG_REG 0x04 -#define WPC8769L_CONFIG_OFF_MASK 0xe0 -#define WPC8769L_CONFIG_ON_MASK 0xc0 - -#define WPC8769L_DATA_ACK_REG 0x05 -#define WPC8769L_DATA_ACK_MASK 0x01 - -#define WPC8769L_TIMEOUT_RESET_REG 0x07 -#define WPC8769L_TIMEOUT_RESET_MASK 0x20 - -/*------------*/ -#define WPC8769L_BANK_E0 0xe0 - -#define WPC8769L_CONFIG6_REG 0x00 -#define WPC8769L_CONFIG6_MASK 0x4b - -#define WPC8769L_CONFIG7_REG 0x01 - -#define WPC8769L_HARDWARE_ENABLE1_REG 0x02 -#define WPC8769L_HARDWARE_ENABLE1_MASK 0x01 - -#define WPC8769L_CONFIG5_REG 0x04 -#define WPC8769L_CONFIG5_ON_MASK 0x30 - -#define WPC8769L_REMAINING_RX_DATA_REG 0x07 - -/*------------*/ -#define WPC8769L_BANK_E4 0xe4 - -#define WPC8769L_READ_ON_STARTUP_REG 0x00 - -/*------------*/ -#define WPC8769L_BANK_EC 0xec - -#define WPC8769L_CONFIG3_REG 0x04 -#define WPC8769L_CONFIG3_ON_MASK 0x01 -#define WPC8769L_CONFIG3_MASK_1 0x10 - -/*------------*/ -#define WPC8769L_BANK_F0 0xf0 - -#define WPC8769L_WAKEUP_STATUS_LEG_REG 0x02 -#define WPC8769L_WAKEUP_STATUS_LEG_MASK 0x04 -#define WPC8769L_WAKEUP_STATUS_LEG_MASK_A 0x02 -#define WPC8769L_WAKEUP_STATUS_LEG_MASK_B 0x08 - -/*------------*/ -#define WPC8769L_BANK_F4 0xf4 - -#define WPC8769L_CONFIG9_REG 0x01 - -#define WPC8769L_CONFIG4_REG 0x02 -#define WPC8769L_CONFIG4_AND_MASK 0x0f -#define WPC8769L_CONFIG4_ON_MASK 0x50 - -#define WPC8769L_CONFIG8_REG 0x04 - -#define WPC8769L_CONFIG2_REG 0x07 -#define WPC8769L_CONFIG2_OFF_MASK 0x20 -#define WPC8769L_CONFIG2_MASK_1 0x10 - - -/* Registers for I/O range 2. */ -#define WPC8769L_WAKEUP_ACK_REG 0x00 -#define WPC8769L_WAKEUP_ACK_MASK 0x10 - -#define WPC8769L_WAKEUP_ENABLE_REG 0x02 -#define WPC8769L_WAKEUP_ENABLE_MASK 0x10 - -#define WPC8769L_BANK2_CLOCK_REG 0x04 -#define WPC8769L_CLOCK_OFF_MASK 0x02 -#define WPC8769L_CLOCK_ON_MASK 0x01 - -#define WPC8769L_WAKEUP_CONFIG_REG 0x1a -#define WPC8769L_WAKEUP_CONFIG_PRE_MASK 0x80 -#define WPC8769L_MAX_INFO_BITS_BIAS 0x0e -#define WPC8769L_MAX_INFO_BITS_SHIFT 0x01 - -#define WPC8769L_WAKEUP_CONFIG3_REG 0x13 -#define WPC8769L_WAKEUP_CONFIG3_OFF_MASK 0x10 -#define WPC8769L_WAKEUP_CONFIG3_ON_MASK 0x21 -#define WPC8769L_WAKEUP_CONFIG3_A_SHIFT 0x01 -#define WPC8769L_WAKEUP_CONFIG3_A_MASK 0x03 -#define WPC8769L_WAKEUP_CONFIG3_B_SHIFT 0x03 -#define WPC8769L_WAKEUP_CONFIG3_B_MASK 0x01 - -#define WPC8769L_WAKEUP_STATUS_REG 0x14 -#define WPC8769L_WAKEUP_WOKE_UP_MASK 0x01 -#define WPC8769L_WAKEUP_CONFIGURING_MASK 0x17 - -#define WPC8769L_WAKEUP_CONFIG2_REG 0x15 -#define WPC8769L_WAKEUP_CONFIG2_AND_MASK 0xf9 -#define WPC8769L_WAKEUP_CONFIG2_OR_MASK 0x01 - -#define WPC8769L_WAKEUP_DATA_PTR_REG 0x18 -#define WPC8769L_WAKEUP_DATA_BITS 0x20 -#define WPC8769L_WAKEUP_DATA_BASE 0x10 -#define WPC8769L_WAKEUP_MASK_BASE 0x20 - -#define WPC8769L_WAKEUP_DATA_REG 0x19 - |