summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--config-arm2
-rw-r--r--config-generic58
-rw-r--r--config-i686-PAE1
-rw-r--r--config-ia64-generic1
-rw-r--r--config-powerpc-generic2
-rw-r--r--config-powerpc32-generic1
-rw-r--r--config-s390x2
-rw-r--r--config-x86-generic19
-rw-r--r--config-x86_64-generic16
-rw-r--r--git-utrace.patch552
-rw-r--r--kernel.spec67
-rw-r--r--linux-2.6-build-nonintconfig.patch128
-rw-r--r--linux-2.6-ext4-fix-freeze-deadlock.patch46
-rw-r--r--linux-2.6-makefile-after_link.patch10
-rw-r--r--linux-2.6-silence-noise.patch23
-rw-r--r--linux-2.6-v4l-dvb-add-kworld-a340-support.patch165
-rw-r--r--linux-2.6-v4l-dvb-ir-core-memleak-fixes.patch142
-rw-r--r--lirc-staging-2.6.36.patch12206
-rw-r--r--only-use-alpha2-regulatory-information-from-country-IE.patch788
-rw-r--r--pci-acpi-disable-aspm-if-no-osc.patch53
-rw-r--r--pci-aspm-dont-enable-too-early.patch50
-rwxr-xr-xscripts/pull-upstreams.sh1
-rw-r--r--sources2
-rw-r--r--utrace-ptrace-fix-build.patch29
-rw-r--r--utrace-remove-use-of-kref_set.patch32
26 files changed, 261 insertions, 14137 deletions
diff --git a/.gitignore b/.gitignore
index 79727843a..85d44c736 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,4 @@ patch-*.bz2
clog
*.rpm
kernel-2.6.*/
-patch-2.6.35-git1.bz2
+patch-2.6.36-rc1.bz2
diff --git a/config-arm b/config-arm
index d0ba0f376..8d7e46a49 100644
--- a/config-arm
+++ b/config-arm
@@ -120,3 +120,5 @@ CONFIG_AUTO_ZRELADDR=y
# CONFIG_ARM_CHARLCD is not set
# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+
+# CONFIG_ARM_SP805_WATCHDOG is not set
diff --git a/config-generic b/config-generic
index 13dfa01e9..c6f5c4504 100644
--- a/config-generic
+++ b/config-generic
@@ -496,6 +496,7 @@ CONFIG_SCSI_SAS_HOST_SMP=y
CONFIG_RAID_ATTRS=m
CONFIG_ISCSI_TCP=m
+CONFIG_ISCSI_BOOT_SYSFS=m
#
# SCSI low-level drivers
@@ -719,6 +720,7 @@ CONFIG_FIREWIRE_OHCI=m
CONFIG_FIREWIRE_SBP2=m
CONFIG_FIREWIRE_NET=m
CONFIG_FIREWIRE_OHCI_DEBUG=y
+CONFIG_FIREWIRE_NOSY=m
# CONFIG_FIREWIRE_OHCI_REMOTE_DMA is not set
#
@@ -845,6 +847,7 @@ CONFIG_DECNET_ROUTER=y
# CONFIG_DECNET_NF_GRABULATOR is not set
CONFIG_BRIDGE=m
CONFIG_BRIDGE_IGMP_SNOOPING=y
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
CONFIG_NETFILTER=y
CONFIG_NETFILTER_ADVANCED=y
CONFIG_NF_CONNTRACK=y
@@ -903,6 +906,10 @@ CONFIG_NETFILTER_XT_MATCH_U32=m
CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
CONFIG_NETFILTER_XT_MATCH_HL=m
CONFIG_NETFILTER_XT_MATCH_OSF=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_MATCH_CPU=m
+CONFIG_NETFILTER_XT_MATCH_IPVS=m
# CONFIG_NETFILTER_DEBUG is not set
CONFIG_BRIDGE_NETFILTER=y
@@ -1318,6 +1325,7 @@ CONFIG_CHELSIO_T1=m
CONFIG_CHELSIO_T1_1G=y
CONFIG_CHELSIO_T3=m
CONFIG_CHELSIO_T4=m
+CONFIG_CHELSIO_T4VF=m
CONFIG_IP1000=m
CONFIG_IXGB=m
CONFIG_IXGBEVF=m
@@ -1513,6 +1521,8 @@ CONFIG_WL1251=m
CONFIG_WL1251_SPI=m
CONFIG_WL1251_SDIO=m
CONFIG_WL1271=m
+CONFIG_WL1271_SDIO=m
+CONFIG_WL1271_SPI=m
#
# Token Ring devices
@@ -1565,6 +1575,7 @@ CONFIG_CAN_SJA1000_ISA=m
CONFIG_CAN_SJA1000_PLATFORM=m
CONFIG_CAN_EMS_PCI=m
CONFIG_CAN_EMS_USB=m
+CONFIG_CAN_ESD_USB2=m
CONFIG_CAN_KVASER_PCI=m
CONFIG_CAN_PLX_PCI=m
CONFIG_NETROM=m
@@ -1644,6 +1655,7 @@ CONFIG_BT_HCIBTUSB=m
CONFIG_BT_HCIUART=m
CONFIG_BT_HCIUART_H4=y
CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_ATH3K=y
CONFIG_BT_HCIDTL1=m
CONFIG_BT_HCIBT3C=m
CONFIG_BT_HCIBLUECARD=m
@@ -1812,6 +1824,7 @@ CONFIG_INPUT_YEALINK=m
CONFIG_INPUT_CM109=m
CONFIG_INPUT_POLLDEV=m
CONFIG_INPUT_SPARSEKMAP=m
+# CONFIG_INPUT_ADXL34X is not set
#
# Input I/O drivers
@@ -1846,6 +1859,7 @@ CONFIG_KEYBOARD_ATKBD=y
# FIXME: Do we really need these keyboards enabled ?
CONFIG_KEYBOARD_ADP5588=m
CONFIG_KEYBOARD_MAX7359=m
+# CONFIG_KEYBOARD_MCS is not set
CONFIG_KEYBOARD_OPENCORES=m
CONFIG_KEYBOARD_QT2160=m
# CONFIG_KEYBOARD_TCA6416 is not set
@@ -1909,6 +1923,8 @@ CONFIG_TOUCHSCREEN_USB_E2I=y
CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
CONFIG_TOUCHSCREEN_DYNAPRO=m
# CONFIG_TOUCHSCREEN_WM97XX is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_QT602240 is not set
CONFIG_TOUCHSCREEN_EETI=m
CONFIG_TOUCHSCREEN_W90X900=m
CONFIG_TOUCHSCREEN_MCS5000=m
@@ -1985,6 +2001,7 @@ CONFIG_CYCLADES=m
# CONFIG_STALLION is not set
# CONFIG_ISTALLION is not set
CONFIG_SERIAL_JSM=m
+# CONFIG_SERIAL_MFD_HSU is not set
# CONFIG_SERIAL_ALTERA_JTAGUART is not set
# CONFIG_SERIAL_ALTERA_UART is not set
@@ -2008,6 +2025,8 @@ CONFIG_PPDEV=m
CONFIG_I2C=m
CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
+# CONFIG_I2C_MUX is not set
+# CONFIG_I2C_MUX_PCA954x is not set
#
# I2C Algorithms
@@ -2153,6 +2172,13 @@ CONFIG_SENSORS_ADT7411=m
CONFIG_SENSORS_ASC7621=m
CONFIG_SENSORS_EMC1403=m
CONFIG_SENSORS_TMP102=m
+# CONFIG_SENSORS_BH1780 is not set
+# CONFIG_SENSORS_JC42 is not set
+# CONFIG_SENSORS_SMM665 is not set
+# CONFIG_SENSORS_EMC2103 is not set
+
+# CONFIG_HMC6352 is not set
+# CONFIG_BMP085 is not set
CONFIG_W1=m
CONFIG_W1_CON=y
@@ -2308,6 +2334,7 @@ CONFIG_DRM_NOUVEAU=m
CONFIG_DRM_NOUVEAU_BACKLIGHT=y
CONFIG_DRM_NOUVEAU_DEBUG=y
CONFIG_DRM_I2C_CH7006=m
+CONFIG_DRM_I2C_SIL164=m
CONFIG_DRM_VMWGFX=m
#
@@ -2974,6 +3001,8 @@ CONFIG_HID_TOPSEED=m
CONFIG_HID_THRUSTMASTER=m
CONFIG_HID_ZEROPLUS=m
CONFIG_HID_ZYDACRON=m
+CONFIG_HID_ACRUX_FF=m
+CONFIG_HID_ELECOM=m
#
@@ -3038,6 +3067,7 @@ CONFIG_USB_KONICAWC=m
CONFIG_USB_S2255=m
CONFIG_USB_SE401=m
# CONFIG_VIDEO_SH_MOBILE_CEU is not set
+# CONFIG_VIDEO_SH_MOBILE_CSI2 is not set
# CONFIG_USB_STV680 is not set
# CONFIG_USB_SN9C102 is not set
CONFIG_USB_ZR364XX=m
@@ -3165,6 +3195,7 @@ CONFIG_USB_SERIAL_XIRCOM=m
CONFIG_USB_SERIAL_QCAUX=m
CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
CONFIG_USB_SERIAL_DEBUG=m
+CONFIG_USB_SERIAL_SSU100=m
CONFIG_USB_EZUSB=y
CONFIG_USB_EMI62=m
@@ -3248,6 +3279,8 @@ CONFIG_INPUT_PCF50633_PMU=m
CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
CONFIG_CHARGER_PCF50633=m
CONFIG_RTC_DRV_PCF50633=m
+CONFIG_RTC_DRV_DS3232=m
+CONFIG_RTC_DRV_ISL12022=m
CONFIG_MFD_SUPPORT=y
CONFIG_MFD_SM501=m
@@ -3391,7 +3424,8 @@ CONFIG_JFFS2_FS_POSIX_ACL=y
CONFIG_JFFS2_FS_SECURITY=y
CONFIG_CRAMFS=m
CONFIG_SQUASHFS=m
-CONFIG_SQUASHFS_XATTRS=y
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZO=y
# CONFIG_SQUASHFS_EMBEDDED is not set
CONFIG_VXFS_FS=m
# CONFIG_HPFS_FS is not set
@@ -3420,6 +3454,7 @@ CONFIG_NFSD_V3=y
CONFIG_NFSD_V3_ACL=y
CONFIG_NFSD_V4=y
CONFIG_NFS_FSCACHE=y
+# CONFIG_NFS_USE_LEGACY_DNS is not set
CONFIG_LOCKD=m
CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=m
@@ -3591,6 +3626,7 @@ CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
CONFIG_SECURITY_SELINUX_AVC_STATS=y
# CONFIG_SECURITY_SMACK is not set
# CONFIG_SECURITY_TOMOYO is not set
+# CONFIG_SECURITY_APPARMOR is not set
CONFIG_AUDIT=y
CONFIG_AUDITSYSCALL=y
@@ -3599,6 +3635,7 @@ CONFIG_AUDITSYSCALL=y
#
CONFIG_CRYPTO=y
CONFIG_CRYPTO_FIPS=y
+CONFIG_CRYPTO_MANAGER_TESTS=y
CONFIG_CRYPTO_HW=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_MANAGER=m
@@ -4167,6 +4204,11 @@ CONFIG_USB_ATMEL=m
# CONFIG_RAMZSWAP is not set
# CONFIG_BATMAN_ADV is not set
# CONFIG_FB_SM7XX is not set
+# CONFIG_SPECTRA is not set
+# CONFIG_ZRAM is not set
+# CONFIG_EASYCAP is not set
+# CONFIG_SOLO6X10 is not set
+# CONFIG_ACPI_QUICKSTART is not set
#
# Android
@@ -4214,6 +4256,8 @@ CONFIG_KSM=y
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
CONFIG_FSNOTIFY=y
+CONFIG_FANOTIFY=y
+CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
CONFIG_IEEE802154=m
CONFIG_IEEE802154_DRIVERS=m
@@ -4253,6 +4297,8 @@ CONFIG_DEBUG_RODATA_TEST=y
CONFIG_DEBUG_NX_TEST=m
CONFIG_DEBUG_BOOT_PARAMS=y
CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_LOCKUP_DETECTOR=y
+# CONFIG_DEBUG_INFO_REDUCED is not set
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_DETECT_HUNG_TASK=y
# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
@@ -4291,3 +4337,13 @@ CONFIG_PROFILE_KSYM_TRACER=y
CONFIG_KPROBE_EVENT=y
# CONFIG_RAMOOPS is not set
+
+CONFIG_IR_CORE=m
+CONFIG_IR_ENE=m
+CONFIG_IR_STREAMZAP=m
+
+# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_TPS6586X is not set
diff --git a/config-i686-PAE b/config-i686-PAE
index 1e58e65b2..429853e32 100644
--- a/config-i686-PAE
+++ b/config-i686-PAE
@@ -1,5 +1,6 @@
# CONFIG_HIGHMEM4G is not set
CONFIG_HIGHMEM64G=y
+# CONFIG_OLPC_OPENFIRMWARE is not set
CONFIG_XEN_DEV_EVTCHN=m
CONFIG_XEN_SYS_HYPERVISOR=y
diff --git a/config-ia64-generic b/config-ia64-generic
index f1581b40c..a178b8a17 100644
--- a/config-ia64-generic
+++ b/config-ia64-generic
@@ -138,6 +138,7 @@ CONFIG_ACPI_THERMAL=y
CONFIG_ACPI_VIDEO=m
# CONFIG_ACPI_PROC_EVENT is not set
CONFIG_ACPI_HED=m
+CONFIG_ACPI_EC_DEBUGFS=m
CONFIG_PM=y
CONFIG_HOTPLUG_PCI=y
diff --git a/config-powerpc-generic b/config-powerpc-generic
index 430396dfc..0effe3d0d 100644
--- a/config-powerpc-generic
+++ b/config-powerpc-generic
@@ -332,3 +332,5 @@ CONFIG_SERIAL_GRLIB_GAISLER_APBUART=m
# CONFIG_MFD_TC35892 is not set
# CONFIG_GPIO_SCH is not set
+
+# CONFIG_PPC_MPC512x is not set
diff --git a/config-powerpc32-generic b/config-powerpc32-generic
index 07b450ad3..d2304955f 100644
--- a/config-powerpc32-generic
+++ b/config-powerpc32-generic
@@ -149,6 +149,7 @@ CONFIG_FSL_EMB_PERFMON=y
CONFIG_MPC8272_ADS=y
CONFIG_PQ2FADS=y
CONFIG_EP8248E=y
+CONFIG_MPC830x_RDB=y
CONFIG_MPC831x_RDB=y
CONFIG_MPC832x_MDS=y
CONFIG_MPC832x_RDB=y
diff --git a/config-s390x b/config-s390x
index 0d3a14b06..d9294023d 100644
--- a/config-s390x
+++ b/config-s390x
@@ -226,3 +226,5 @@ CONFIG_SMSGIUCV_EVENT=m
# CONFIG_PREEMPT_TRACER is not set
CONFIG_VMCP=y
+
+CONFIG_ZFCP_DIF=y
diff --git a/config-x86-generic b/config-x86-generic
index 58a8cf11b..5f14f346a 100644
--- a/config-x86-generic
+++ b/config-x86-generic
@@ -393,6 +393,7 @@ CONFIG_SENSORS_I5K_AMB=m
CONFIG_HP_WATCHDOG=m
CONFIG_OLPC=y
+CONFIG_OLPC_OPENFIRMWARE=y
CONFIG_BATTERY_OLPC=y
CONFIG_MOUSE_PS2_OLPC=y
@@ -479,6 +480,20 @@ CONFIG_TOSHIBA_BT_RFKILL=m
CONFIG_VGA_SWITCHEROO=y
CONFIG_LPC_SCH=m
-CONFIG_INTEL_IDLE=m
-
CONFIG_PCI_CNB20LE_QUIRK=y
+
+CONFIG_ACPI_EC_DEBUGFS=m
+# CONFIG_ACPI_APEI_ERST_DEBUG is not set
+CONFIG_INTEL_IDLE=y
+# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
+CONFIG_SENSORS_PKGTEMP=m
+CONFIG_F71808E_WDT=m
+CONFIG_HPWDT_NMI_DECODING=y
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_INTEL_MID_DMAC is not set
+CONFIG_PCH_DMA=m
+CONFIG_XEN_PLATFORM_PCI=m
+# CONFIG_ACPI_QUICKSTART is not set
+CONFIG_IDEAPAD_ACPI=m
+CONFIG_INTEL_IPS=m
+
diff --git a/config-x86_64-generic b/config-x86_64-generic
index 204dfff62..27e242128 100644
--- a/config-x86_64-generic
+++ b/config-x86_64-generic
@@ -403,7 +403,21 @@ CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m
CONFIG_VGA_SWITCHEROO=y
CONFIG_LPC_SCH=m
-CONFIG_INTEL_IDLE=m
CONFIG_I7300_IDLE=m
CONFIG_PCI_CNB20LE_QUIRK=y
+
+CONFIG_ACPI_EC_DEBUGFS=m
+# CONFIG_ACPI_APEI_ERST_DEBUG is not set
+CONFIG_INTEL_IDLE=y
+# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
+CONFIG_SENSORS_PKGTEMP=m
+CONFIG_F71808E_WDT=m
+CONFIG_HPWDT_NMI_DECODING=y
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_INTEL_MID_DMAC is not set
+CONFIG_PCH_DMA=m
+CONFIG_XEN_PLATFORM_PCI=m
+# CONFIG_ACPI_QUICKSTART is not set
+CONFIG_IDEAPAD_ACPI=m
+CONFIG_INTEL_IPS=m
diff --git a/git-utrace.patch b/git-utrace.patch
index 77b5fa749..1be088c50 100644
--- a/git-utrace.patch
+++ b/git-utrace.patch
@@ -1,348 +1,5 @@
-From c2f1645ae87d5b7fc5e5973c3a93a4ae1684a76b Mon Sep 17 00:00:00 2001
-From: Kyle McMartin <kyle@dreadnought.i.jkkm.org>
-Date: Tue, 22 Jun 2010 11:31:13 +0100
-Subject: Merge remote branch 'utrace/utrace-ptrace' into rawhide
-
-% git log --oneline --no-merges 7e27d6e..a91f6b7
-f979955 utrace-ptrace: fix compiling ptrace_regset under CONFIG_UTRACE
-b5f196b utrace-ptrace: copy PTRACE_GETREGSET code to utrace-ptrace
-d83135e utrace: fix utrace_maybe_reap() vs find_matching_engine() race
-9a2c607 utrace: move CONFIG_UTRACE after AUDITSYSCALL in init/Kconfig
-62f4621 utrace: s/rmb/mb/ in tracehook_notify_resume()
-65f5e9d utrace: fix utrace_maybe_reap logic
-ed1f9c2 utrace: fix syntax nit for !CONFIG_UTRACE
-71e3f39 ptrace: add utrace comment
-e7afc73 utrace: use WARN with text
-a8ced33 utrace: cosmetic restructure
-4330b80 utrace: remove some inline keywords
-d4be40a utrace: remove report_clone special priority for utrace_attach_task on child
-8c56566 ptrace: updates for utrace API changes
-1900135 utrace: streamline callback API
-97662d3 utrace: more cosmetic trivia
-fd414cd utrace: more cosmetic cleanup
-f30f068 utrace: cosmetic trivia
-cfebda7 utrace: fix the comments about rmb() in task_utrace_struct()
-875858a utrace: improve the comment in tracehook_notify_resume()
-76b49a5 utrace: fix the ->cloning check in utrace_attach_delay()
-e0755bb utrace: kill mb() in tracehook_report_death()
-9fdc988 fix __must_check warnings
-3e02499 kill suppress_sigtrap()
-f872e69 utrace: don't set ->ops = utrace_detached_ops lockless
-938482e utrace: fix doc typo
-7fae049 utrace: avoid BUG_ON when engine leaves bogus si_signo
-71b7a85 utrace: trivial, move CONFIG_UTRACE into "General setup"
-9c8dbe0 utrace: reset report action for UTRACE_SYSCALL_RESUMED iteration
-4c7514e join PTRACE_EVENT_SYSCALL_XXX states
-a8f782e export __ptrace_detach() and do_notify_parent_cldstop()
-c3473e1 ptrace_signal: check PT_PTRACED before reporting a signal
-b396f5e tracehooks: check PT_PTRACED before reporting the single-step
-45667dd tracehooks: kill some PT_PTRACED checks
-e8a2f23 ptrace: cleanup ptrace_init_task()->ptrace_link() path
-611dab8 kill CONFIG_UTRACE_PTRACE
-8d3833e rm kernel/ptrace-common.h
-494deb7 export __ptrace_detach(), add "ifndef CONFIG_UTRACE" into ptrace.c
-05cb325 (upstream) reorder the code in kernel/ptrace.c
-eb10f13 restore the old kernel/ptrace.c
-ddcc525 utrace_resume: Avoid finish_resume_report() for UTRACE_RESUME
-47852f9 mv kernel/ptrace.c kernel/ptrace-utrace.c
-de5a46e utrace: fix UTRACE_SYSCALL_RESUMED nits
-3bd4be9 stepping, accommodate to utrace-cleanup changes
-679be9e Revert "utrace: synthesize SIGTRAP for single-stepping at syscall-exit"
-23ab966 utrace: barrier nits
-d3800b8 utrace: tracehook_init_task
-64daf14 utrace: task_utrace_struct() barrier
-f19442c utrace: synthesize SIGTRAP for single-stepping at syscall-exit
-2583b32 utrace: nit for utrace-ptrace
-a88b467 ptrace: x86: change syscall_trace_leave() to rely on tracehook when stepping
-e01acf4 ptrace: x86: implement user_single_step_siginfo()
-462a57b ptrace: change tracehook_report_syscall_exit() to handle stepping
-172590d ptrace: powerpc: implement user_single_step_siginfo()
-d63b43d ptrace: introduce user_single_step_siginfo() helper
-c575558 utrace: barriers for initializing struct utrace
-89df3c7 utrace: utrace_attach_task() forgets to return when ->utrace == NULL
-4d17e95 utrace: finish_report() must never set ->resume = UTRACE_STOP
-212f67e utrace: utrace_get_signal() must check ->pending_attach
-eff6ca8 change ptrace_report_signal() to use user_single_step_siginfo()
-cba1272 don't send the unnecessary SIGTRAP after SYSCALL_EXIT
-8aa71a6 revert "turn PTRACE_EVENT_SIGTRAP into PTRACE_EVENT_SIGNAL"
-90c8237 utrace-ptrace: minimally handle UTRACE_SYSCALL_RESUMED
-a7e9198 utrace: clean up resume-action handling
-962eb2f utrace: update after merge
-e2ced71 re-introduce utrace_finish_stop() to fix the race with SIGKILL
-603e19c turn PTRACE_EVENT_SIGTRAP into PTRACE_EVENT_SIGNAL
-ff87f65 introduce suppress_sigtrap() to prevent unwanted send_sigtrap()
-6505e3c move ptrace_resume()->send_sigtrap() logic into ptrace_report_signal()
-5261baa prepare ptrace_report_signal() to synthesize SIGTRAP
-ef9534b ptrace_request: turn ptrace_resume() into default case
-f50c776 s/context/ctx/
-228b2e3 ptrace_notify_stop: kill the temporary WARN_ON()
-93e866a ptrace_request(PTRACE_KILL) should not(?) return -ESRCH
-26fefca utrace: sticky resume action
-28b2774b utrace: remove ->stopped field
-9e0f357 utrace_set_events: nit clean up
-6d0bad3 nits
-48bab07 (utrace) utrace_get_signal: don't dequeue_signal() if ->group_stop_count
-d4ef551 (upstream) signals: check ->group_stop_count after tracehook_get_signal()
-6292daa ptrace_detach_task: don't use valid_signal()
-c5a6a82 cosmetic, renames
-e422a3f cosmetic, relocate some code in ptrace.c
-b96e4db (upstream) introduce kernel/ptrace.h
-7665564 (upstream) tracehook_signal_handler: check PT_PTRACED
-7d708ca tracehooks: revert utrace-ptrace changes
-4104e29 (upstream) ptrace_init_task: cleanup the usage of ptrace_link()
-d04ccb7 revert all utrace-ptrace changes in ptrace.h
-80786ce revert utrace-ptrace changes in kernel/signal.c
-0b02f9e introduce PT_UTRACED to replace PT_PTRACED inside ptrace.c
-030ce35 tracehooks: remove some PT_PTRACED checks
-4b7b15a revert the clone() related changes in tracehook.h
-769030e hack ptrace_check_attach() to make it almost correct
-7aa5c3a cosmetic, fold do_ptrace_resume() into ptrace_resume()
-d27ebc1 cosmetic, introduce ptrace_resume_action()
-35fbca4 turn context->sysemu into PTRACE_O_SYSEMU
-38a8c1f PTRACE_SYSEMU_SINGLESTEP support
-4367836 PTRACE_SYSEMU support
-16819db ptrace_report_clone: minor cleanups + comments
-ac1afd8 ptrace_resume: rewrite request processing
-6b0d4f6 do_ptrace_resume: always use ptrace_wake_up()
-fa92ce3 do_ptrace_resume: consolidate multiple switch stmts
-135d780 uglify the code again to report VFORK_DONE after VFORK
-4e3f362 fix PTRACE_SYSCALL after PTRACE_EVENT_VFORK_DONE stop
-3f95189 ptrace_report_clone: uglify even more to handle TRACEVFORKDONE without TRACEVFORK
-66ca8b6 ptrace_report_clone: uglify CLONE_PTRACE/CLONE_UNTRACED behaviour to match upstream
-fc82b2c pretend PTRACE_O_TRACEVFORKDONE doesn't exist
-28aa15a utrace_set_events: never return -EINPROGRESS unless clearing some event bits
-a7f4350 utrace_stop: do ptrace_notify_stop() unconditionally
-cb78492 ptrace_report_exit: fix WARN_ON() condition
-bb941c3 do_ptrace_notify_stop: document the usage of tracee->exit_code
-383ba85 ptrace_wake_up: don't clear tracee->exit_code + update comments
-3d5c221 ptrace_wake_up: add "bool force_wakeup" argument for implicit detach
-be6862e ptrace_wake_up: clear context->stop_code
-bfb40c8 detach: use ptrace_wake_up() instead of utrace_control()
-7de148a shift context re-initialization from detach to reuse
-464def3 cleanup/optimize reuse/attch in ptrace_attach_task()
-50f56b9 ptrace_attach_task: rely on utrace_barrier(), don't check ->ops
-03376fd use set_stop_code() in ptrace_report_signal(UTRACE_SIGNAL_HANDLER)
-85f8b3a detach should reset the context of self-detaching engine
-a27233a attach: try to re-use the self-detaching engine
-8667615 ptrace_notify_stop: fix engine leak
-3d5d053 ptrace_detach_task: don't use engine ptr before IS_ERR(engine)
-01875c7 fold detach_signal() into ptrace_detach_task()
-464c2b7 don't detach the engine with the parting signal
-97b345c implement the basic detach-with-signal logic
-a158247 rework access to context->siginfo
-20ea83b introduce set_stop_code() helper
-eb222ed cosmetic, misc renames
-f83b2ca move "event << 8" into syscall_code()
-4c99287 kill context->ev_name
-df7c8f2 encode internal stop events in ->ev_code too
-3f48297 introduce get_stop_code(context) helper
-313bad1 introduce syscall_code(context) helper
-47b5e2c don't clear context->ev_code for debugging
-4e09fe3 convert ptrace_setsiginfo() to use ptrace_rw_siginfo()
-53187be convert ptrace_getsiginfo() to use ptrace_rw_siginfo()
-e7ac055 introduce ptrace_rw_siginfo() helper
-c625793 move "resume signal" logic into the tracee's context
-0768d89 UTRACE_SIGNAL_HANDLER should never see ->siginfo != NULL
-e90cb71 don't use task_struct->ptrace_message
-842684f do_ptrace_notify_stop: fix the race with SIGKILL
-d0ed18d do_ptrace_notify_stop: backport the "sync wakeup" logic
-08f4a21 fix the stepping over syscall
-a55d174 implement the stacked SYSCALL_EXIT event
-ba73824 ptrace_resume: don't ignore "data" argument
-fbd4368 kill context->ev_array[]
-3c6f822 Revert "ptrace_resume_signal() should use context->siginfo under ->siglock"
-ee31432 Revert "UTRACE_SIGNAL_HANDLER should never see ->siginfo != NULL"
-a4e5af1 Revert "introduce context_siginfo() helper"
-9bc939a revert merge w/s change
-6752625 introduce context_siginfo() helper
-d43a453 UTRACE_SIGNAL_HANDLER should never see ->siginfo != NULL
-e4e48df ptrace_resume_signal() should use context->siginfo under ->siglock
-4492770 implement UTRACE_SIGNAL_HANDLER stepping
-5f926a5 implement PTRACE_SINGLESTEP/PTRACE_SINGLEBLOCK
-8b70ae1 ptrace_request: use ptrace_lookup_engine()
-abd580d change ptrace_resume() to have the single "return"
-85878ae introduce ptrace_lookup_engine()
-74904f1 mv task_struct->last_siginfo ptrace_context->siginfo
-2b17f4a pretens ptrace_detach(sig) works
-075db41 ptrace_report_quiesce() can't trust fatal_signal_pending()
-d583c87 remove the now unneeded code
-69a6c83 break ptrace_report_signal()
-d6a31ee do_ptrace_notify_stop: kill "->ev_message != 0" check
-e194687 convert ptrace_report_exit()
-8bf8304 PTRACE_EVENT_VFORK_DONE: set ev_options = PTRACE_O_TRACEVFORKDONE
-b8f5e2a make sure PTRACE_SYSCALL reports SYSCALL_EXIT
-258b27d make sure PTRACE_CONT "disables" SYSCALL_EXIT report
-d26b659 introduce ptrace_event->ev_options
-03a0fe3 convert ptrace_report_exec()
-bea6139 convert ptrace_report_syscall_entry()
-17dd96d cleanup/simplify stop/resume mess
-97fc962 utrace: comments
-c661ddb utrace: move struct utrace back where it belongs
-95dcdee implement stacked stop events
-8608da6 ptrace_report_syscall_exit: do not WARN() if killed
-95a6b6b ptrace_report_clone: rework the stop/resume logic
-25dd723 remove the current PTRACE_EVENT_VFORK_DONE logic
-7d8900a ptrace_wake_up: fix the "compatibility bug" logic
-9a50d27 ptrace_report_syscall_exit: return UTRACE_STOP, not UTRACE_RESUME
-c07370d simplify utrace_add_engine() vs utrace_reap() protection
-0f4d918 utrace_add_engine: cleanup
-a24e891 fix utrace_reset() vs release_task() theoretical race
-dfc0917 change attach/release to avoid unnecessary utrace_reap()
-cbed668 utrace_attach_task: do no check ->exit_state
-9d114a6 utrace_wakeup: do not check target->state
-9368f18 utrace_wakeup: lock ->siglock directly
-e9b58e9 convert ptrace_report_syscall_exit() to use ptrace_context
-1d47e4d introduce context->resume_stopped()
-c34d813 introduce context->stopped_code
-b7edb5e introduce ptrace_notify_stop()
-93b2e7e utrace_release_task: cosmetic
-ac6e19c utrace_reap: loop lockless, do not clear ->ops and ->flags early
-7852d10 utrace: slow_path -> pending_attach
-c827b15 utrace_add_engine() should set ->utrace_flags |= REAP
-2e12892 utrace_reap: fix missing callback
-04852f3 utrace: do not force report on attach
-37b68f7 kill ptrace_setoptions() and ptrace_update_utrace()
-f1b39f3 use context->options instead of "->ptrace & PT_"
-d05bf8e ptrace_set_options: use PTRACE_O_ instead of PT_
-167b56a "disable" tracehook_prepare_clone()
-5e526f3 introduce ptrace_set_options()
-4a50ac1 introduce ptrace_context->options
-0457aa8 introduce the empty struct ptrace_context
-a2bca6f utrace_reset: do not use "unsafe mode"
-eac91f4 utrace_control: don't mark_engine_detached() before engine_wants_stop()
-c2916fb utrace_control: fix utrace_reset(safe) usage when ->exit_state != 0
-c36a311 utrace_reset fix
-8d2fc04 utrace: remove unused inline
-64a8ca3 utrace_reset cleanup
-d1a14ce utrace: change UTRACE_STOP bookkeeping
-96fe3cc Revert "utrace_stop: fix UTRACE_DETACH race"
-ceaae71 utrace: check QUIESCE before reporting UTRACE_SIGNAL_REPORT/HANDLER
-fc30d20 utrace_do_stop: move "if (exit_state)" logic to the caller
-9b655f7 utrace_do_stop: don't set ->stopped when ->exit_state
-9ed6a39 utrace_set_events: never return -EINPROGRESS on a zombie
-592d977 utrace_do_stop: cleanup the usage of ->siglock
-7f51e58 utrace: fix utrace->signal_handler "leakage"
-be5e266 utrace: utrace_finish_vfork: check ->vfork_stop lockless
-c3580f1 utrace-ptrace: fix conditions in ptrace_do_detach
-00932db utrace_stop: fix UTRACE_DETACH race
-b032859 utrace: move utrace_stop down
-a62ed15 utrace: consolidate utrace_reset callers
-c8315d3 ptrace_do_detach: Fiddle code to avoid warnings.
-e3635f1 utrace-ptrace: use WARN_ON(), suppress __must_check warning
-8ba59d7 ptrace_attach_task: kill ->ptrace != 0 check
-a18378e exit_ptrace: use ptrace_do_detach()
-371c69c ptrace_detach: do ptrace_unlink() first
-096f3ed ptrace_detach: kill the unconditional wakeup
-d999521 ptrace_report_clone: rework auto-attaching
-8cefebf move ->ptrace == 0 checks to ptrace_attach_task()
-471d6f4 utrace_engine_ops: add release hook
-78ca7e7 utrace_control: return -EINVAL for missing UTRACE_EVENT(QUIESCE)
-fcb8fa0 change ptrace_traceme() to use the new helpers, kill prepare/finish attach
-e82feff rework prepare_ptrace_attach/finish_ptrace_attach
-3bea38f do not use engine->data
-57cedd0 ptrace_detach_task: always do UTRACE_DETACH
-2093f3a shift ptrace_utrace_exit() from tracehook_report_exit() to exit_ptrace()
-33fb930 ptrace_resume()->send_sig() can crash
-a7b05fd ptrace_check_attach: check child->parent
-5ed4eff remove (almost all) !CONFIG_UTRACE_PTRACE code
-fb9379c change utrace_stop() to return void
-5bbbb41 kill utrace_report->killed
-0b57f74 finish_utrace_stop: use __fatal_signal_pending(), dont take ->siglock
-113a07e utrace: rework finish_report flag logic
-8ad60bb utrace_stop: preserve report/interrupt requests across stop/resume
-af3eb44 get_utrace_lock: do not check EXIT_DEAD
-d87e8c4 finish_utrace_stop: check ->stopped lockless
-3e0a686 utrace_report_jctl/utrace_get_signal: do not play with ->stopped
-7d97118 utrace_do_stop: s/STOPPED/TRACED/ to protect against SIGCONT
-ad2497a use tracehook_finish_jctl() to clear ->stopped
-f99db9f utrace_report_jctl: do not play with the group-stop state
-fd89498 introduce tracehook_finish_jctl() helper
-ff6be89 do_signal_stop: do not call tracehook_notify_jctl() in TASK_STOPPED state
-66e0705 utrace_stop: don't forget about SIGNAL_STOP_STOPPED
-2edad7d utrace_wakeup: take ->group_stop_count into account
-d4bcb57 utrace_reap: clear engine->flags when finishing detach
-cf890ad utrace: fix utrace->reporting left set for no callback
-cbe5188 More than one user has hit the -EEXIST problem when using utrace_attach_task and UTRACE_ATTACH_EXCLUSIVE without UTRACE_ATTACH_MATCH_DATA|_OPS. Document that a bit more.
-52db080 UTRACE_SYSCALL_RESUMED repeat callback
-5e67e22 utrace docbook: s/first/last/ braino
-4bd78f8 utrace: reverse engine callback order for report_syscall_entry
-1757088 utrace: WARN instead of BUG on misuse of UTRACE_*STEP without arch_has_*_step() check
-5d4e97b utrace: restore tracehook_report_death comment misplaced in merges
-cb49dcd utrace_report_syscall_entry: remove unnecessary recalc_sigpending() check
-c0909b5 utrace_resume: fix potential TIF_SIGPENDING race
-f0a1c64 utrace: use \t separator in /proc/pid/status
-13a5838 utrace: init_task syntax nit
-715d2a1 utrace: cosmetic
-42de707 utrace_report_jctl: do splice_attaching
-622013d utrace_resume: remove racy BUG_ON
-282d685 whitespace fix
-bec92f8 signals: tracehook_notify_jctl change
-a7181aa utrace: simplify death report condition
-4d8a6fd utrace: barrier between TIF_NOTIFY_RESUME check and utrace_flags/utrace->report checks
-ae3096f utrace-ptrace: remove unsafe_exec and tracer_task hooks
-325fecc utrace: get rid of tracer_task and unsafe_exec hooks
-0084fc2 utrace: ensure UTRACE_REPORT callback return leads to callback after utrace_stop
-5bdc6f1 utrace: cosmetic: DEAD_FLAGS_MASK macro
-5c5bdbe utrace: cosmetic: _UTRACE_DEATH_EVENTS macro
-f067223 utrace: make sure utrace_flags is nonzero before set_notify_resume at attach
-e2d293e utrace: drop racy unlocked check in utrace_do_stop
-68f3899 utrace: fix ->report_jctl @notify argument
-c743327 utrace: avoid unnecessary list_for_each_safe
-acd516b utrace_stop: trivial, kill the unnecessary assignment
-81ed517 utrace_add_engine: add missing 'else' after 'if (utrace->reap)'
-215a076 utrace: tracehook.h comment
-a584c66 utrace: fix utrace_attach_delay() creator test
-827ec3b utrace: comment ->reporting implementation
-07732b4 utrace-ptrace: handle -ERESTARTNOINTR from utrace_attach_task
-2233b06 utrace: finish utrace_reap conversion after indirect->direct struct utrace
-dd30e86 utrace: fix utrace_attach_delay() to loop, remove struct utrace.cloning field
-be4f357 get_utrace_lock: kill the bogus engine->kref.refcount check
-c367207 utrace: clear struct in utrace_init_task
-94f168c utrace: define UTRACE_API_VERSION
-742f120 utrace: place struct utrace directly in task_struct
-cb25a58 utrace: comment fixes
-2b834a5 utrace-ptrace: struct utrace_attached_engine -> struct utrace_engine
-6b8306a utrace: struct utrace_attached_engine -> struct utrace_engine
-9fe3bac utrace-ptrace: Kconfig doc update
-5bb0052 utrace: cosmetic changes
-556a7e7 utrace-ptrace: fix resuming with blocked signal
-3a9f4c8 utrace: order utrace_control() after callback return value processing
-269150d Cosmetic reorganization to further simplify utrace pointer vs embedded-struct.
-ea30176 Use task_utrace_struct() helper in utrace_interrupt_pending().
-ed2098a Use task_utrace_struct() helper
-97d5cde cosmetic code reorganization
-4e8a7ca Remove UTRACE_DEBUG hacks
-25fb674 utrace: exclude PTRACE_TRACEME
-f286be7 utrace-ptrace: remove utrace_engine_put stub
-e0c36bd Disable mutual exclusion if CONFIG_UTRACE_PTRACE
-c93d704 utrace/ptrace mutual exclusion
-594f22c cond_resched() before race-restart in utrace_attach_task
-0da72f3 Clean up utrace_attach_task code.
-fd3d457 utrace: ptrace cooperation
-f357a74 utrace core
----
- Documentation/DocBook/Makefile | 2 +-
- Documentation/DocBook/utrace.tmpl | 590 +++++++++
- fs/proc/array.c | 3 +
- include/linux/ptrace.h | 3 +-
- include/linux/sched.h | 6 +
- include/linux/tracehook.h | 97 ++-
- include/linux/utrace.h | 692 +++++++++++
- init/Kconfig | 9 +
- kernel/Makefile | 2 +
- kernel/fork.c | 3 +
- kernel/ptrace-utrace.c | 1127 +++++++++++++++++
- kernel/ptrace.c | 620 +++++-----
- kernel/signal.c | 4 +-
- kernel/utrace.c | 2452 +++++++++++++++++++++++++++++++++++++
- 14 files changed, 5291 insertions(+), 319 deletions(-)
- create mode 100644 Documentation/DocBook/utrace.tmpl
- create mode 100644 include/linux/utrace.h
- create mode 100644 kernel/ptrace-utrace.c
- create mode 100644 kernel/utrace.c
-
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
-index c7e5dc7..e63f889 100644
+index 34929f2..884c36b 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -14,7 +14,7 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \
@@ -356,10 +13,10 @@ index c7e5dc7..e63f889 100644
# The build process is as follows (targets):
diff --git a/Documentation/DocBook/utrace.tmpl b/Documentation/DocBook/utrace.tmpl
new file mode 100644
-index 0000000..e149f49
+index 0000000..0c40add
--- /dev/null
+++ b/Documentation/DocBook/utrace.tmpl
-@@ -0,0 +1,590 @@
+@@ -0,0 +1,589 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
@@ -719,13 +376,12 @@ index 0000000..e149f49
+ after a successful call, no event callbacks not requested in the new
+ flags will be made. It fails with <constant>-EALREADY</constant> if
+ you try to clear <constant>UTRACE_EVENT(DEATH)</constant> when the
-+ <function>report_death</function> callback may already have begun, if
-+ you try to clear <constant>UTRACE_EVENT(REAP)</constant> when the
-+ <function>report_reap</function> callback may already have begun, or if
++ <function>report_death</function> callback may already have begun, or if
+ you try to newly set <constant>UTRACE_EVENT(DEATH)</constant> or
+ <constant>UTRACE_EVENT(QUIESCE)</constant> when the target is already
+ dead or dying. Like <function>utrace_control</function>, it returns
-+ <constant>-ESRCH</constant> when the thread has already been detached
++ <constant>-ESRCH</constant> when the <function>report_reap</function>
++ callback may already have begun, or the thread has already been detached
+ (including forcible detach on reaping). This lets the tracing engine
+ know for sure which event callbacks it will or won't see after
+ <function>utrace_set_events</function> has returned. By checking for
@@ -951,7 +607,7 @@ index 0000000..e149f49
+
+</book>
diff --git a/fs/proc/array.c b/fs/proc/array.c
-index 9b58d38..c7c7881 100644
+index fff6572..a67bd83 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -81,6 +81,7 @@
@@ -991,10 +647,10 @@ index 4272521..235c1b0 100644
extern void ptrace_disable(struct task_struct *);
extern int ptrace_check_attach(struct task_struct *task, int kill);
diff --git a/include/linux/sched.h b/include/linux/sched.h
-index f118809..d3fef7a 100644
+index ce160d6..66a1ec8 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
-@@ -1348,6 +1348,11 @@ struct task_struct {
+@@ -1339,6 +1339,11 @@ struct task_struct {
#endif
seccomp_t seccomp;
@@ -1006,7 +662,7 @@ index f118809..d3fef7a 100644
/* Thread group tracking */
u32 parent_exec_id;
u32 self_exec_id;
-@@ -2033,6 +2038,7 @@ extern int kill_pgrp(struct pid *pid, int sig, int priv);
+@@ -2030,6 +2035,7 @@ extern int kill_pgrp(struct pid *pid, int sig, int priv);
extern int kill_pid(struct pid *pid, int sig, int priv);
extern int kill_proc_info(int, struct siginfo *, pid_t);
extern int do_notify_parent(struct task_struct *, int);
@@ -1975,12 +1631,12 @@ index 0000000..f251efe
+
+#endif /* linux/utrace.h */
diff --git a/init/Kconfig b/init/Kconfig
-index 5cff9a9..c0b7f81 100644
+index 2de5b1c..a283086 100644
--- a/init/Kconfig
+++ b/init/Kconfig
-@@ -328,6 +328,15 @@ config AUDIT_TREE
+@@ -332,6 +332,15 @@ config AUDIT_TREE
depends on AUDITSYSCALL
- select INOTIFY
+ select FSNOTIFY
+config UTRACE
+ bool "Infrastructure for tracing and debugging user processes"
@@ -1995,7 +1651,7 @@ index 5cff9a9..c0b7f81 100644
choice
diff --git a/kernel/Makefile b/kernel/Makefile
-index 057472f..dfdc01c 100644
+index 0b72d1a..b09c9a5 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -70,6 +70,8 @@ obj-$(CONFIG_IKCONFIG) += configs.o
@@ -2004,11 +1660,11 @@ index 057472f..dfdc01c 100644
obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o
+obj-$(CONFIG_UTRACE) += utrace.o
+obj-$(CONFIG_UTRACE) += ptrace-utrace.o
- obj-$(CONFIG_AUDIT) += audit.o auditfilter.o audit_watch.o
+ obj-$(CONFIG_AUDIT) += audit.o auditfilter.o
obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
- obj-$(CONFIG_GCOV_KERNEL) += gcov/
+ obj-$(CONFIG_AUDIT_WATCH) += audit_watch.o
diff --git a/kernel/fork.c b/kernel/fork.c
-index b6cce14..ac4a6ec 100644
+index 98b4508..3ceff6f 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -161,6 +161,7 @@ void free_task(struct task_struct *tsk)
@@ -2019,7 +1675,7 @@ index b6cce14..ac4a6ec 100644
free_task_struct(tsk);
}
EXPORT_SYMBOL(free_task);
-@@ -1007,6 +1008,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
+@@ -1008,6 +1009,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
if (!p)
goto fork_out;
@@ -2030,10 +1686,10 @@ index b6cce14..ac4a6ec 100644
rt_mutex_init_task(p);
diff --git a/kernel/ptrace-utrace.c b/kernel/ptrace-utrace.c
new file mode 100644
-index 0000000..86234ee
+index 0000000..1a8ba5e
--- /dev/null
+++ b/kernel/ptrace-utrace.c
-@@ -0,0 +1,1127 @@
+@@ -0,0 +1,1125 @@
+/*
+ * linux/kernel/ptrace.c
+ *
@@ -2086,8 +1742,6 @@ index 0000000..86234ee
+ child->ptrace = 0;
+ child->parent = child->real_parent;
+ list_del_init(&child->ptrace_entry);
-+
-+ arch_ptrace_untrace(child);
+}
+
+struct ptrace_context {
@@ -3162,7 +2816,7 @@ index 0000000..86234ee
+}
+#endif /* CONFIG_COMPAT */
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
-index 74a3d69..c77f9bf 100644
+index f34d798..daed9e8 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -23,7 +23,317 @@
@@ -3417,7 +3071,7 @@ index 74a3d69..c77f9bf 100644
+ out:
+ return ret;
+}
-+
+
+int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data)
+{
+ unsigned long tmp;
@@ -3478,7 +3132,7 @@ index 74a3d69..c77f9bf 100644
+ return ret;
+}
+#endif /* CONFIG_COMPAT */
-
++
+#ifndef CONFIG_UTRACE
/*
* ptrace a task: make the debugger its new parent and
@@ -3537,10 +3191,47 @@ index 74a3d69..c77f9bf 100644
int ptrace_attach(struct task_struct *task)
{
int retval;
-@@ -242,57 +505,6 @@ int ptrace_traceme(void)
- return ret;
- }
+@@ -205,92 +468,41 @@ int ptrace_attach(struct task_struct *task)
+ send_sig_info(SIGSTOP, SEND_SIG_FORCED, task);
+ retval = 0;
+-unlock_tasklist:
+- write_unlock_irq(&tasklist_lock);
+-unlock_creds:
+- mutex_unlock(&task->cred_guard_mutex);
+-out:
+- return retval;
+-}
+-
+-/**
+- * ptrace_traceme -- helper for PTRACE_TRACEME
+- *
+- * Performs checks and sets PT_PTRACED.
+- * Should be used by all ptrace implementations for PTRACE_TRACEME.
+- */
+-int ptrace_traceme(void)
+-{
+- int ret = -EPERM;
+-
+- write_lock_irq(&tasklist_lock);
+- /* Are we already being traced? */
+- if (!current->ptrace) {
+- ret = security_ptrace_traceme(current->parent);
+- /*
+- * Check PF_EXITING to ensure ->real_parent has not passed
+- * exit_ptrace(). Otherwise we don't report the error but
+- * pretend ->real_parent untraces us right after return.
+- */
+- if (!ret && !(current->real_parent->flags & PF_EXITING)) {
+- current->ptrace = PT_PTRACED;
+- __ptrace_link(current, current->real_parent);
+- }
+- }
+- write_unlock_irq(&tasklist_lock);
+-
+- return ret;
+-}
+-
-/*
- * Called with irqs disabled, returns true if childs should reap themselves.
- */
@@ -3563,16 +3254,30 @@ index 74a3d69..c77f9bf 100644
- * If it's a zombie, our attachedness prevented normal parent notification
- * or self-reaping. Do notification now if it would have happened earlier.
- * If it should reap itself, return true.
-- *
++unlock_tasklist:
++ write_unlock_irq(&tasklist_lock);
++unlock_creds:
++ mutex_unlock(&task->cred_guard_mutex);
++out:
++ return retval;
++}
++
++/**
++ * ptrace_traceme -- helper for PTRACE_TRACEME
+ *
- * If it's our own child, there is no notification to do. But if our normal
- * children self-reap, then this child was prevented by ptrace and we must
- * reap it now, in that case we must also wake up sub-threads sleeping in
- * do_wait().
-- */
++ * Performs checks and sets PT_PTRACED.
++ * Should be used by all ptrace implementations for PTRACE_TRACEME.
+ */
-static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p)
--{
++int ptrace_traceme(void)
+ {
- __ptrace_unlink(p);
--
++ int ret = -EPERM;
+
- if (p->exit_state == EXIT_ZOMBIE) {
- if (!task_detached(p) && thread_group_empty(p)) {
- if (!same_thread_group(p->real_parent, tracer))
@@ -3586,17 +3291,29 @@ index 74a3d69..c77f9bf 100644
- /* Mark it as in the process of being reaped. */
- p->exit_state = EXIT_DEAD;
- return true;
-- }
-- }
--
++ write_lock_irq(&tasklist_lock);
++ /* Are we already being traced? */
++ if (!current->ptrace) {
++ ret = security_ptrace_traceme(current->parent);
++ /*
++ * Check PF_EXITING to ensure ->real_parent has not passed
++ * exit_ptrace(). Otherwise we don't report the error but
++ * pretend ->real_parent untraces us right after return.
++ */
++ if (!ret && !(current->real_parent->flags & PF_EXITING)) {
++ current->ptrace = PT_PTRACED;
++ __ptrace_link(current, current->real_parent);
+ }
+ }
++ write_unlock_irq(&tasklist_lock);
+
- return false;
--}
--
++ return ret;
+ }
+
int ptrace_detach(struct task_struct *child, unsigned int data)
- {
- bool dead = false;
-@@ -346,56 +558,6 @@ void exit_ptrace(struct task_struct *tracer)
- }
+@@ -352,56 +564,6 @@ void exit_ptrace(struct task_struct *tracer)
+ write_lock_irq(&tasklist_lock);
}
-int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len)
@@ -3652,7 +3369,7 @@ index 74a3d69..c77f9bf 100644
static int ptrace_setoptions(struct task_struct *child, long data)
{
child->ptrace &= ~PT_TRACE_MASK;
-@@ -456,7 +618,6 @@ static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info)
+@@ -462,7 +624,6 @@ static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info)
return error;
}
@@ -3660,7 +3377,7 @@ index 74a3d69..c77f9bf 100644
#ifdef PTRACE_SINGLESTEP
#define is_singlestep(request) ((request) == PTRACE_SINGLESTEP)
#else
-@@ -510,47 +671,6 @@ static int ptrace_resume(struct task_struct *child, long request, long data)
+@@ -516,47 +677,6 @@ static int ptrace_resume(struct task_struct *child, long request, long data)
return 0;
}
@@ -3708,7 +3425,7 @@ index 74a3d69..c77f9bf 100644
int ptrace_request(struct task_struct *child, long request,
long addr, long data)
{
-@@ -666,88 +786,7 @@ int ptrace_request(struct task_struct *child, long request,
+@@ -672,88 +792,7 @@ int ptrace_request(struct task_struct *child, long request,
return ret;
}
@@ -3797,7 +3514,7 @@ index 74a3d69..c77f9bf 100644
int compat_ptrace_request(struct task_struct *child, compat_long_t request,
compat_ulong_t addr, compat_ulong_t data)
{
-@@ -825,42 +864,5 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
+@@ -831,42 +870,5 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
return ret;
}
@@ -3842,10 +3559,10 @@ index 74a3d69..c77f9bf 100644
#endif /* CONFIG_COMPAT */
+#endif /* CONFIG_UTRACE */
diff --git a/kernel/signal.c b/kernel/signal.c
-index 906ae5a..8087f13 100644
+index bded651..6d13d9f 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
-@@ -1518,7 +1518,7 @@ int do_notify_parent(struct task_struct *tsk, int sig)
+@@ -1521,7 +1521,7 @@ int do_notify_parent(struct task_struct *tsk, int sig)
return ret;
}
@@ -3854,7 +3571,7 @@ index 906ae5a..8087f13 100644
{
struct siginfo info;
unsigned long flags;
-@@ -1788,7 +1788,7 @@ static int do_signal_stop(int signr)
+@@ -1791,7 +1791,7 @@ static int do_signal_stop(int signr)
static int ptrace_signal(int signr, siginfo_t *info,
struct pt_regs *regs, void *cookie)
{
@@ -3865,10 +3582,10 @@ index 906ae5a..8087f13 100644
ptrace_signal_deliver(regs, cookie);
diff --git a/kernel/utrace.c b/kernel/utrace.c
new file mode 100644
-index 0000000..f5a9e2c
+index 0000000..4d61096
--- /dev/null
+++ b/kernel/utrace.c
-@@ -0,0 +1,2452 @@
+@@ -0,0 +1,2450 @@
+/*
+ * utrace infrastructure interface for debugging user processes
+ *
@@ -4099,6 +3816,7 @@ index 0000000..f5a9e2c
+ */
+ list_add_tail(&engine->entry, &utrace->attaching);
+ utrace->pending_attach = 1;
++ utrace_engine_get(engine);
+ ret = 0;
+unlock:
+ spin_unlock(&utrace->lock);
@@ -4172,10 +3890,10 @@ index 0000000..f5a9e2c
+ return ERR_PTR(-ENOMEM);
+
+ /*
-+ * Initialize the new engine structure. It starts out with two
-+ * refs: one ref to return, and one ref for being attached.
++ * Initialize the new engine structure. It starts out with one ref
++ * to return. utrace_add_engine() adds another for being attached.
+ */
-+ kref_set(&engine->kref, 2);
++ kref_init(&engine->kref);
+ engine->flags = 0;
+ engine->ops = ops;
+ engine->data = data;
@@ -4188,6 +3906,7 @@ index 0000000..f5a9e2c
+ engine = ERR_PTR(ret);
+ }
+
++
+ return engine;
+}
+EXPORT_SYMBOL_GPL(utrace_attach_task);
@@ -4292,7 +4011,7 @@ index 0000000..f5a9e2c
+
+ utrace = task_utrace_struct(target);
+ spin_lock(&utrace->lock);
-+ if (unlikely(!engine->ops) ||
++ if (unlikely(utrace->reap) || unlikely(!engine->ops) ||
+ unlikely(engine->ops == &utrace_detached_ops)) {
+ /*
+ * By the time we got the utrace lock,
@@ -4358,13 +4077,12 @@ index 0000000..f5a9e2c
+ *
+ * This fails with -%EALREADY and does nothing if you try to clear
+ * %UTRACE_EVENT(%DEATH) when the @report_death callback may already have
-+ * begun, if you try to clear %UTRACE_EVENT(%REAP) when the @report_reap
-+ * callback may already have begun, or if you try to newly set
-+ * %UTRACE_EVENT(%DEATH) or %UTRACE_EVENT(%QUIESCE) when @target is
-+ * already dead or dying.
++ * begun, or if you try to newly set %UTRACE_EVENT(%DEATH) or
++ * %UTRACE_EVENT(%QUIESCE) when @target is already dead or dying.
+ *
-+ * This can fail with -%ESRCH when @target has already been detached,
-+ * including forcible detach on reaping.
++ * This fails with -%ESRCH if you try to clear %UTRACE_EVENT(%REAP) when
++ * the @report_reap callback may already have begun, or when @target has
++ * already been detached, including forcible detach on reaping.
+ *
+ * If @target was stopped before the call, then after a successful call,
+ * no event callbacks not requested in @events will be made; if
@@ -4395,7 +4113,7 @@ index 0000000..f5a9e2c
+{
+ struct utrace *utrace;
+ unsigned long old_flags, old_utrace_flags;
-+ int ret;
++ int ret = -EALREADY;
+
+ /*
+ * We just ignore the internal bit, so callers can use
@@ -4410,14 +4128,12 @@ index 0000000..f5a9e2c
+ old_utrace_flags = target->utrace_flags;
+ old_flags = engine->flags & ~ENGINE_STOP;
+
-+ if (target->exit_state &&
-+ (((events & ~old_flags) & _UTRACE_DEATH_EVENTS) ||
-+ (utrace->death &&
-+ ((old_flags & ~events) & _UTRACE_DEATH_EVENTS)) ||
-+ (utrace->reap && ((old_flags & ~events) & UTRACE_EVENT(REAP))))) {
-+ spin_unlock(&utrace->lock);
-+ return -EALREADY;
-+ }
++ /*
++ * If utrace_report_death() is already progress now,
++ * it's too late to clear the death event bits.
++ */
++ if (((old_flags & ~events) & _UTRACE_DEATH_EVENTS) && utrace->death)
++ goto unlock;
+
+ /*
+ * When setting these flags, it's essential that we really
@@ -4429,12 +4145,11 @@ index 0000000..f5a9e2c
+ * knows positively that utrace_report_death() will be called or
+ * that it won't.
+ */
-+ if ((events & ~old_utrace_flags) & _UTRACE_DEATH_EVENTS) {
++ if ((events & ~old_flags) & _UTRACE_DEATH_EVENTS) {
+ read_lock(&tasklist_lock);
+ if (unlikely(target->exit_state)) {
+ read_unlock(&tasklist_lock);
-+ spin_unlock(&utrace->lock);
-+ return -EALREADY;
++ goto unlock;
+ }
+ target->utrace_flags |= events;
+ read_unlock(&tasklist_lock);
@@ -4462,7 +4177,7 @@ index 0000000..f5a9e2c
+ if (utrace->reporting == engine)
+ ret = -EINPROGRESS;
+ }
-+
++unlock:
+ spin_unlock(&utrace->lock);
+
+ return ret;
@@ -6321,6 +6036,3 @@ index 0000000..f5a9e2c
+{
+ seq_printf(m, "Utrace:\t%lx\n", p->utrace_flags);
+}
---
-1.7.0.1
-
diff --git a/kernel.spec b/kernel.spec
index 2967f43f3..deb81ef3d 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -79,9 +79,9 @@ Summary: The Linux kernel
# The next upstream release sublevel (base_sublevel+1)
%define upstream_sublevel %(echo $((%{base_sublevel} + 1)))
# The rc snapshot level
-%define rcrev 0
+%define rcrev 1
# The git snapshot level
-%define gitrev 1
+%define gitrev 0
# Set rpm version accordingly
%define rpmversion 2.6.%{upstream_sublevel}
%endif
@@ -149,7 +149,6 @@ Summary: The Linux kernel
%define debugbuildsenabled 0
# Want to build a vanilla kernel build without any non-upstream patches?
-# (well, almost none, we need nonintconfig for build purposes). Default to 0 (off).
%define with_vanilla %{?_with_vanilla: 1} %{?!_with_vanilla: 0}
# pkg_release is what we'll fill in for the rpm Release: field
@@ -372,12 +371,12 @@ Summary: The Linux kernel
%define vdso_arches ppc ppc64
%endif
+# Should make listnewconfig fail if there's config options
+# printed out?
%if %{nopatches}%{using_upstream_branch}
-# Ignore unknown options in our config-* files.
-# Some options go with patches we're not applying.
-%define oldconfig_target loose_nonint_oldconfig
+%define listnewconfig_fail 0
%else
-%define oldconfig_target nonint_oldconfig
+%define listnewconfig_fail 1
%endif
# To temporarily exclude an architecture from being built, add it to
@@ -579,9 +578,6 @@ Patch00: patch-2.6.%{base_sublevel}-git%{gitrev}.bz2
Patch02: git-linus.diff
-# we always need nonintconfig, even for -vanilla kernels
-Patch03: linux-2.6-build-nonintconfig.patch
-
# we also need compile fixes for -vanilla
Patch04: linux-2.6-compile-fixes.patch
@@ -598,8 +594,6 @@ Patch09: linux-2.6-upstream-reverts.patch
Patch20: linux-2.6-hotfixes.patch
Patch30: git-utrace.patch
-Patch31: utrace-ptrace-fix-build.patch
-Patch32: utrace-remove-use-of-kref_set.patch
Patch150: linux-2.6.29-sparc-IOC_TYPECHECK.patch
@@ -614,8 +608,6 @@ Patch204: linux-2.6-debug-always-inline-kzalloc.patch
Patch380: linux-2.6-defaults-pci_no_msi.patch
Patch383: linux-2.6-defaults-aspm.patch
-Patch384: pci-acpi-disable-aspm-if-no-osc.patch
-Patch385: pci-aspm-dont-enable-too-early.patch
Patch390: linux-2.6-defaults-acpi-video.patch
Patch391: linux-2.6-acpi-video-dos.patch
@@ -671,16 +663,12 @@ Patch2901: linux-2.6-v4l-dvb-experimental.patch
Patch2902: linux-2.6-v4l-dvb-uvcvideo-update.patch
Patch2910: linux-2.6-v4l-dvb-add-lgdt3304-support.patch
-Patch2911: linux-2.6-v4l-dvb-add-kworld-a340-support.patch
Patch2912: linux-2.6-v4l-dvb-ir-core-update.patch
-Patch2913: linux-2.6-v4l-dvb-ir-core-memleak-fixes.patch
-Patch2915: lirc-staging-2.6.36.patch
#Patch2916: lirc-staging-2.6.36-fixes.patch
Patch2917: hdpvr-ir-enable.patch
# fs fixes
-Patch3000: linux-2.6-ext4-fix-freeze-deadlock.patch
# NFSv4
@@ -696,8 +684,6 @@ Patch12018: neuter_intel_microcode_load.patch
Patch12030: ssb_check_for_sprom.patch
-Patch12040: only-use-alpha2-regulatory-information-from-country-IE.patch
-
%endif
BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root
@@ -1099,11 +1085,6 @@ make -f %{SOURCE20} VERSION=%{version} configs
ApplyOptionalPatch git-linus.diff
-# This patch adds a "make nonint_oldconfig" which is non-interactive and
-# also gives a list of missing options at the end. Useful for automated
-# builds (as used in the buildsystem).
-ApplyPatch linux-2.6-build-nonintconfig.patch
-
ApplyPatch linux-2.6-makefile-after_link.patch
#
@@ -1120,8 +1101,6 @@ ApplyPatch linux-2.6-hotfixes.patch
# Roland's utrace ptrace replacement.
ApplyPatch git-utrace.patch
-ApplyPatch utrace-ptrace-fix-build.patch
-ApplyPatch utrace-remove-use-of-kref_set.patch
# Architecture patches
# x86(-64)
@@ -1150,7 +1129,6 @@ ApplyPatch linux-2.6-32bit-mmap-exec-randomization.patch
#
# ext4
-ApplyPatch linux-2.6-ext4-fix-freeze-deadlock.patch
# xfs
@@ -1175,7 +1153,7 @@ ApplyPatch linux-2.6-acpi-debug-infinite-loop.patch
ApplyPatch linux-2.6-debug-sizeof-structs.patch
ApplyPatch linux-2.6-debug-nmi-timeout.patch
ApplyPatch linux-2.6-debug-taint-vm.patch
-ApplyPatch linux-2.6-debug-vm-would-have-oomkilled.patch
+###FIX###ApplyPatch linux-2.6-debug-vm-would-have-oomkilled.patch
ApplyPatch linux-2.6-debug-always-inline-kzalloc.patch
#
@@ -1185,10 +1163,6 @@ ApplyPatch linux-2.6-debug-always-inline-kzalloc.patch
ApplyPatch linux-2.6-defaults-pci_no_msi.patch
# enable ASPM by default on hardware we expect to work
ApplyPatch linux-2.6-defaults-aspm.patch
-# disable aspm if acpi doesn't provide an _OSC method
-ApplyPatch pci-acpi-disable-aspm-if-no-osc.patch
-# allow drivers to disable aspm at load time
-ApplyPatch pci-aspm-dont-enable-too-early.patch
#
# SCSI Bits.
@@ -1242,7 +1216,7 @@ ApplyPatch fix_xen_guest_on_old_EC2.patch
#ApplyPatch revert-drm-kms-toggle-poll-around-switcheroo.patch
# Nouveau DRM + drm fixes
-ApplyPatch drm-nouveau-updates.patch
+#ApplyPatch drm-nouveau-updates.patch
ApplyPatch drm-intel-big-hammer.patch
ApplyOptionalPatch drm-intel-next.patch
ApplyPatch drm-intel-make-lvds-work.patch
@@ -1260,15 +1234,12 @@ ApplyPatch linux-2.6-silence-acpi-blacklist.patch
ApplyOptionalPatch linux-2.6-v4l-dvb-fixes.patch
ApplyOptionalPatch linux-2.6-v4l-dvb-update.patch
ApplyOptionalPatch linux-2.6-v4l-dvb-experimental.patch
-ApplyPatch linux-2.6-v4l-dvb-uvcvideo-update.patch
+#ApplyPatch linux-2.6-v4l-dvb-uvcvideo-update.patch
+#ApplyPatch linux-2.6-v4l-dvb-ir-core-update.patch
-ApplyPatch linux-2.6-v4l-dvb-ir-core-update.patch
-ApplyPatch linux-2.6-v4l-dvb-ir-core-memleak-fixes.patch
-ApplyPatch linux-2.6-v4l-dvb-add-lgdt3304-support.patch
-ApplyPatch linux-2.6-v4l-dvb-add-kworld-a340-support.patch
+###FIX###ApplyPatch linux-2.6-v4l-dvb-add-lgdt3304-support.patch
# http://www.lirc.org/
-ApplyPatch lirc-staging-2.6.36.patch
#ApplyOptionalPatch lirc-staging-2.6.36-fixes.patch
# enable IR receiver on Hauppauge HD PVR (v4l-dvb merge pending)
ApplyPatch hdpvr-ir-enable.patch
@@ -1281,8 +1252,6 @@ ApplyPatch neuter_intel_microcode_load.patch
# rhbz#533746
#ApplyPatch ssb_check_for_sprom.patch
-ApplyPatch only-use-alpha2-regulatory-information-from-country-IE.patch
-
# END OF PATCH APPLICATIONS
%endif
@@ -1314,7 +1283,14 @@ for i in *.config
do
mv $i .config
Arch=`head -1 .config | cut -b 3-`
- make ARCH=$Arch %{oldconfig_target} > /dev/null
+ make ARCH=$Arch listnewconfig | egrep '^CONFIG_' >.newoptions || true
+%if %{listnewconfig_fail}
+ if [ -s .newoptions ]; then
+ cat .newoptions
+ exit 0
+ fi
+%endif
+ rm -f .newoptions
echo "# $Arch" > configs/$i
cat .config >> configs/$i
done
@@ -1391,7 +1367,7 @@ BuildKernel() {
Arch=`head -1 .config | cut -b 3-`
echo USING ARCH=$Arch
- make -s ARCH=$Arch %{oldconfig_target} > /dev/null
+ make -s ARCH=$Arch oldnoconfig >/dev/null
make -s ARCH=$Arch V=1 %{?_smp_mflags} $MakeTarget %{?sparse_mflags}
make -s ARCH=$Arch V=1 %{?_smp_mflags} modules %{?sparse_mflags} || exit 1
@@ -1883,6 +1859,9 @@ fi
%changelog
* Tue Aug 17 2010 Kyle McMartin <kyle@redhat.com>
+- Linux 2.6.36-rc1
+
+* Tue Aug 17 2010 Kyle McMartin <kyle@redhat.com>
- Prevent scripts/setlocalversion from mucking with our version
numbers.
diff --git a/linux-2.6-build-nonintconfig.patch b/linux-2.6-build-nonintconfig.patch
deleted file mode 100644
index e88e0ea1e..000000000
--- a/linux-2.6-build-nonintconfig.patch
+++ /dev/null
@@ -1,128 +0,0 @@
-diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
-index 6d69c7c..ff84d12 100644
---- a/scripts/kconfig/Makefile
-+++ b/scripts/kconfig/Makefile
-@@ -58,6 +58,11 @@ localyesconfig: $(obj)/streamline_config.pl $(obj)/conf
- fi
- $(Q)rm -f .tmp.config
-
-+nonint_oldconfig: $(obj)/conf
-+ $< -b $(Kconfig)
-+loose_nonint_oldconfig: $(obj)/conf
-+ $< -B $(Kconfig)
-+
- # Create new linux.pot file
- # Adjust charset to UTF-8 in .po file to accept UTF-8 in Kconfig files
- # The symlink is used to repair a deficiency in arch/um
-diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
-index 9960d1c..ac8d455 100644
---- a/scripts/kconfig/conf.c
-+++ b/scripts/kconfig/conf.c
-@@ -23,6 +23,8 @@ enum {
- ask_all,
- ask_new,
- ask_silent,
-+ dont_ask,
-+ dont_ask_dont_tell,
- set_default,
- set_yes,
- set_mod,
-@@ -360,7 +362,10 @@ static void conf(struct menu *menu)
-
- switch (prop->type) {
- case P_MENU:
-- if (input_mode == ask_silent && rootEntry != menu) {
-+ if ((input_mode == ask_silent ||
-+ input_mode == dont_ask ||
-+ input_mode == dont_ask_dont_tell) &&
-+ rootEntry != menu) {
- check_conf(menu);
- return;
- }
-@@ -406,6 +411,8 @@ conf_childs:
- indent -= 2;
- }
-
-+static int return_value;
-+
- static void check_conf(struct menu *menu)
- {
- struct symbol *sym;
-@@ -418,12 +425,21 @@ static void check_conf(struct menu *menu)
- if (sym && !sym_has_value(sym)) {
- if (sym_is_changable(sym) ||
- (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
-+ if (input_mode == dont_ask ||
-+ input_mode == dont_ask_dont_tell) {
-+ if (input_mode == dont_ask &&
-+ sym->name && !sym_is_choice_value(sym)) {
-+ fprintf(stderr,"CONFIG_%s\n",sym->name);
-+ ++return_value;
-+ }
-+ } else {
- if (!conf_cnt++)
- printf(_("*\n* Restart config...\n*\n"));
- rootEntry = menu_get_parent_menu(menu);
- conf(rootEntry);
- }
- }
-+ }
-
- for (child = menu->list; child; child = child->next)
- check_conf(child);
-@@ -439,7 +455,7 @@ int main(int ac, char **av)
- bindtextdomain(PACKAGE, LOCALEDIR);
- textdomain(PACKAGE);
-
-- while ((opt = getopt(ac, av, "osdD:nmyrh")) != -1) {
-+ while ((opt = getopt(ac, av, "osbBdD:nmyrh")) != -1) {
- switch (opt) {
- case 'o':
- input_mode = ask_silent;
-@@ -448,6 +464,12 @@ int main(int ac, char **av)
- input_mode = ask_silent;
- sync_kconfig = 1;
- break;
-+ case 'b':
-+ input_mode = dont_ask;
-+ break;
-+ case 'B':
-+ input_mode = dont_ask_dont_tell;
-+ break;
- case 'd':
- input_mode = set_default;
- break;
-@@ -525,6 +547,8 @@ int main(int ac, char **av)
- case ask_silent:
- case ask_all:
- case ask_new:
-+ case dont_ask:
-+ case dont_ask_dont_tell:
- conf_read(NULL);
- break;
- case set_no:
-@@ -586,12 +610,16 @@ int main(int ac, char **av)
- conf(&rootmenu);
- input_mode = ask_silent;
- /* fall through */
-+ case dont_ask:
-+ case dont_ask_dont_tell:
- case ask_silent:
- /* Update until a loop caused no more changes */
- do {
- conf_cnt = 0;
- check_conf(&rootmenu);
-- } while (conf_cnt);
-+ } while (conf_cnt &&
-+ (input_mode != dont_ask &&
-+ input_mode != dont_ask_dont_tell));
- break;
- }
-
-@@ -613,5 +641,5 @@ int main(int ac, char **av)
- exit(1);
- }
- }
-- return 0;
-+ return return_value;
- }
diff --git a/linux-2.6-ext4-fix-freeze-deadlock.patch b/linux-2.6-ext4-fix-freeze-deadlock.patch
deleted file mode 100644
index e7eb817af..000000000
--- a/linux-2.6-ext4-fix-freeze-deadlock.patch
+++ /dev/null
@@ -1,46 +0,0 @@
-[PATCH] ext4: fix freeze deadlock under IO
-
-Commit 6b0310fbf087ad6 caused a regression resulting in deadlocks
-when freezing a filesystem which had active IO; the vfs_check_frozen
-level (SB_FREEZE_WRITE) did not let the freeze-related IO syncing
-through. Duh.
-
-Changing the test to FREEZE_TRANS should let the normal freeze
-syncing get through the fs, but still block any transactions from
-starting once the fs is completely frozen.
-
-I tested this by running fsstress in the background while periodically
-snapshotting the fs and running fsck on the result. I ran into
-occasional deadlocks, but different ones. I think this is a
-fine fix for the problem at hand, and the other deadlocky things
-will need more investigation.
-
-Reported-by: Phillip Susi <psusi@cfl.rr.com>
-Signed-off-by: Eric Sandeen <sandeen@redhat.com>
----
-
-diff --git a/fs/ext4/super.c b/fs/ext4/super.c
-index 4e8983a..a45ced9 100644
---- a/fs/ext4/super.c
-+++ b/fs/ext4/super.c
-@@ -241,7 +241,7 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)
- if (sb->s_flags & MS_RDONLY)
- return ERR_PTR(-EROFS);
-
-- vfs_check_frozen(sb, SB_FREEZE_WRITE);
-+ vfs_check_frozen(sb, SB_FREEZE_TRANS);
- /* Special case here: if the journal has aborted behind our
- * backs (eg. EIO in the commit thread), then we still need to
- * take the FS itself readonly cleanly. */
-@@ -3491,7 +3491,7 @@ int ext4_force_commit(struct super_block *sb)
-
- journal = EXT4_SB(sb)->s_journal;
- if (journal) {
-- vfs_check_frozen(sb, SB_FREEZE_WRITE);
-+ vfs_check_frozen(sb, SB_FREEZE_TRANS);
- ret = ext4_journal_force_commit(journal);
- }
-
-
-
-
diff --git a/linux-2.6-makefile-after_link.patch b/linux-2.6-makefile-after_link.patch
index 94b71f9b1..d484388cd 100644
--- a/linux-2.6-makefile-after_link.patch
+++ b/linux-2.6-makefile-after_link.patch
@@ -42,16 +42,18 @@ index 79da65d..f11c21b 100644
cmd_vdso64as = $(CC) $(a_flags) -c -o $@ $<
diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile
-index 6b4ffed..cbc3d05 100644
+index 4a2afa1..12ad9f7 100644
--- a/arch/x86/vdso/Makefile
+++ b/arch/x86/vdso/Makefile
-@@ -120,7 +120,8 @@ $(obj)/vdso32-syms.lds: $(vdso32.so-y:%=$(obj)/vdso32-%-syms.lds) FORCE
+@@ -120,8 +120,9 @@ $(obj)/vdso32-syms.lds: $(vdso32.so-y:%=$(obj)/vdso32-%-syms.lds) FORCE
quiet_cmd_vdso = VDSO $@
cmd_vdso = $(CC) -nostdlib -o $@ \
$(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \
-- -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^)
+- -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \
+- sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
+ -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) \
-+ $(if $(AFTER_LINK),; $(AFTER_LINK))
++ $(if $(AFTER_LINK),; $(AFTER_LINK)) && \
++ sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
GCOV_PROFILE := n
diff --git a/linux-2.6-silence-noise.patch b/linux-2.6-silence-noise.patch
index d5de8f439..119a97769 100644
--- a/linux-2.6-silence-noise.patch
+++ b/linux-2.6-silence-noise.patch
@@ -64,26 +64,3 @@ Signed-off-by: Dave Jones <davej@redhat.com>
}
#endif
-Some devices (like the nuforce udac) spew this quite a lot.
-This patch kinda sucks, but it'll shut things up for now.
-
-Probably not an upstream candidate. I suspect the answer would be
-"don't turn SND_DEBUG then"
-
---- linux-2.6.34.noarch/sound/usb/clock.c~ 2010-07-16 22:11:41.000000000 -0400
-+++ linux-2.6.34.noarch/sound/usb/clock.c 2010-07-16 22:15:21.000000000 -0400
-@@ -212,8 +212,13 @@ static int set_sample_rate_v1(struct snd
-
- /* if endpoint doesn't have sampling rate control, bail out */
- if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE)) {
-- snd_printk(KERN_WARNING "%d:%d:%d: endpoint lacks sample rate attribute bit, cannot set.\n",
-+ static int once;
-+
-+ if (!once) {
-+ snd_printk(KERN_WARNING "%d:%d:%d: endpoint lacks sample rate attribute bit, cannot set.\n",
- dev->devnum, iface, fmt->altsetting);
-+ once = 1;
-+ }
- return 0;
- }
-
diff --git a/linux-2.6-v4l-dvb-add-kworld-a340-support.patch b/linux-2.6-v4l-dvb-add-kworld-a340-support.patch
deleted file mode 100644
index f1ac30793..000000000
--- a/linux-2.6-v4l-dvb-add-kworld-a340-support.patch
+++ /dev/null
@@ -1,165 +0,0 @@
-commit 611225f5e7f9d11c4b119fac224f1bd6903b0150
-Author: Jarod Wilson <jarod@redhat.com>
-Date: Sun Mar 7 17:55:43 2010 -0300
-
- V4L/DVB: dvb: add support for kworld 340u and ub435-q to em28xx-dvb
-
- This adds support for the KWorld PlusTV 340U and KWorld UB345-Q ATSC
- sticks, which are really the same device. The sticks have an eMPIA
- em2870 usb bridge chipset, an LG Electronics LGDT3304 ATSC/QAM
- demodulator and an NXP TDA18271HD tuner -- early versions of the 340U
- have a a TDA18271HD/C1, later models and the UB435-Q have a C2.
-
- The stick has been tested succesfully with both VSB_8 and QAM_256 signals.
- Its using lgdt3304 support added to the lgdt3305 driver by a prior patch,
- rather than the current lgdt3304 driver, as its severely lacking in
- functionality by comparison (see said patch for details).
-
- Signed-off-by: Jarod Wilson <jarod@redhat.com>
- Signed-off-by: Michael Krufky <mkrufky@kernellabs.com>
- Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-
-diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx
-index 3a623aa..5c56875 100644
---- a/Documentation/video4linux/CARDLIST.em28xx
-+++ b/Documentation/video4linux/CARDLIST.em28xx
-@@ -72,3 +72,4 @@
- 73 -> Reddo DVB-C USB TV Box (em2870)
- 74 -> Actionmaster/LinXcel/Digitus VC211A (em2800)
- 75 -> Dikom DK300 (em2882)
-+ 76 -> KWorld PlusTV 340U or UB435-Q (ATSC) (em2870) [1b80:a340]
-diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
-index 3a4fd85..ffbe544 100644
---- a/drivers/media/video/em28xx/em28xx-cards.c
-+++ b/drivers/media/video/em28xx/em28xx-cards.c
-@@ -158,6 +158,22 @@ static struct em28xx_reg_seq evga_indtube_digital[] = {
- { -1, -1, -1, -1},
- };
-
-+/*
-+ * KWorld PlusTV 340U and UB435-Q (ATSC) GPIOs map:
-+ * EM_GPIO_0 - currently unknown
-+ * EM_GPIO_1 - LED disable/enable (1 = off, 0 = on)
-+ * EM_GPIO_2 - currently unknown
-+ * EM_GPIO_3 - currently unknown
-+ * EM_GPIO_4 - TDA18271HD/C1 tuner (1 = active, 0 = in reset)
-+ * EM_GPIO_5 - LGDT3304 ATSC/QAM demod (1 = active, 0 = in reset)
-+ * EM_GPIO_6 - currently unknown
-+ * EM_GPIO_7 - currently unknown
-+ */
-+static struct em28xx_reg_seq kworld_a340_digital[] = {
-+ {EM28XX_R08_GPIO, 0x6d, ~EM_GPIO_4, 10},
-+ { -1, -1, -1, -1},
-+};
-+
- /* Pinnacle Hybrid Pro eb1a:2881 */
- static struct em28xx_reg_seq pinnacle_hybrid_pro_analog[] = {
- {EM28XX_R08_GPIO, 0xfd, ~EM_GPIO_4, 10},
-@@ -1667,6 +1683,16 @@ struct em28xx_board em28xx_boards[] = {
- .tuner_gpio = reddo_dvb_c_usb_box,
- .has_dvb = 1,
- },
-+ /* 1b80:a340 - Empia EM2870, NXP TDA18271HD and LG DT3304, sold
-+ * initially as the KWorld PlusTV 340U, then as the UB435-Q.
-+ * Early variants have a TDA18271HD/C1, later ones a TDA18271HD/C2 */
-+ [EM2870_BOARD_KWORLD_A340] = {
-+ .name = "KWorld PlusTV 340U or UB435-Q (ATSC)",
-+ .tuner_type = TUNER_ABSENT, /* Digital-only TDA18271HD */
-+ .has_dvb = 1,
-+ .dvb_gpio = kworld_a340_digital,
-+ .tuner_gpio = default_tuner_gpio,
-+ },
- };
- const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
-
-@@ -1788,6 +1814,8 @@ struct usb_device_id em28xx_id_table[] = {
- .driver_info = EM2820_BOARD_IODATA_GVMVP_SZ },
- { USB_DEVICE(0xeb1a, 0x50a6),
- .driver_info = EM2860_BOARD_GADMEI_UTV330 },
-+ { USB_DEVICE(0x1b80, 0xa340),
-+ .driver_info = EM2870_BOARD_KWORLD_A340 },
- { },
- };
- MODULE_DEVICE_TABLE(usb, em28xx_id_table);
-diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c
-index cf1d8c3..3ac8d30 100644
---- a/drivers/media/video/em28xx/em28xx-dvb.c
-+++ b/drivers/media/video/em28xx/em28xx-dvb.c
-@@ -30,11 +30,13 @@
- #include "tuner-simple.h"
-
- #include "lgdt330x.h"
-+#include "lgdt3305.h"
- #include "zl10353.h"
- #include "s5h1409.h"
- #include "mt352.h"
- #include "mt352_priv.h" /* FIXME */
- #include "tda1002x.h"
-+#include "tda18271.h"
-
- MODULE_DESCRIPTION("driver for em28xx based DVB cards");
- MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>");
-@@ -231,6 +233,18 @@ static struct lgdt330x_config em2880_lgdt3303_dev = {
- .demod_chip = LGDT3303,
- };
-
-+static struct lgdt3305_config em2870_lgdt3304_dev = {
-+ .i2c_addr = 0x0e,
-+ .demod_chip = LGDT3304,
-+ .spectral_inversion = 1,
-+ .deny_i2c_rptr = 1,
-+ .mpeg_mode = LGDT3305_MPEG_PARALLEL,
-+ .tpclk_edge = LGDT3305_TPCLK_FALLING_EDGE,
-+ .tpvalid_polarity = LGDT3305_TP_VALID_HIGH,
-+ .vsb_if_khz = 3250,
-+ .qam_if_khz = 4000,
-+};
-+
- static struct zl10353_config em28xx_zl10353_with_xc3028 = {
- .demod_address = (0x1e >> 1),
- .no_tuner = 1,
-@@ -247,6 +261,17 @@ static struct s5h1409_config em28xx_s5h1409_with_xc3028 = {
- .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK
- };
-
-+static struct tda18271_std_map kworld_a340_std_map = {
-+ .atsc_6 = { .if_freq = 3250, .agc_mode = 3, .std = 0,
-+ .if_lvl = 1, .rfagc_top = 0x37, },
-+ .qam_6 = { .if_freq = 4000, .agc_mode = 3, .std = 1,
-+ .if_lvl = 1, .rfagc_top = 0x37, },
-+};
-+
-+static struct tda18271_config kworld_a340_config = {
-+ .std_map = &kworld_a340_std_map,
-+};
-+
- static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = {
- .demod_address = (0x1e >> 1),
- .no_tuner = 1,
-@@ -572,6 +597,14 @@ static int dvb_init(struct em28xx *dev)
- }
- }
- break;
-+ case EM2870_BOARD_KWORLD_A340:
-+ dvb->frontend = dvb_attach(lgdt3305_attach,
-+ &em2870_lgdt3304_dev,
-+ &dev->i2c_adap);
-+ if (dvb->frontend != NULL)
-+ dvb_attach(tda18271_attach, dvb->frontend, 0x60,
-+ &dev->i2c_adap, &kworld_a340_config);
-+ break;
- default:
- em28xx_errdev("/2: The frontend of your DVB/ATSC card"
- " isn't supported yet\n");
-diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
-index 6216786..1c61a6b 100644
---- a/drivers/media/video/em28xx/em28xx.h
-+++ b/drivers/media/video/em28xx/em28xx.h
-@@ -114,6 +114,7 @@
- #define EM2870_BOARD_REDDO_DVB_C_USB_BOX 73
- #define EM2800_BOARD_VC211A 74
- #define EM2882_BOARD_DIKOM_DK300 75
-+#define EM2870_BOARD_KWORLD_A340 76
-
- /* Limits minimum and default number of buffers */
- #define EM28XX_MIN_BUF 4
diff --git a/linux-2.6-v4l-dvb-ir-core-memleak-fixes.patch b/linux-2.6-v4l-dvb-ir-core-memleak-fixes.patch
deleted file mode 100644
index 59ba20a43..000000000
--- a/linux-2.6-v4l-dvb-ir-core-memleak-fixes.patch
+++ /dev/null
@@ -1,142 +0,0 @@
- drivers/media/IR/imon.c | 20 +-------------------
- drivers/media/IR/mceusb.c | 15 +--------------
- 2 files changed, 2 insertions(+), 33 deletions(-)
-
-diff --git a/drivers/media/IR/imon.c b/drivers/media/IR/imon.c
-index 65c125e..c185422 100644
---- a/drivers/media/IR/imon.c
-+++ b/drivers/media/IR/imon.c
-@@ -87,7 +87,6 @@ static ssize_t lcd_write(struct file *file, const char *buf,
- struct imon_context {
- struct device *dev;
- struct ir_dev_props *props;
-- struct ir_input_dev *ir;
- /* Newer devices have two interfaces */
- struct usb_device *usbdev_intf0;
- struct usb_device *usbdev_intf1;
-@@ -1656,7 +1655,6 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx)
- {
- struct input_dev *idev;
- struct ir_dev_props *props;
-- struct ir_input_dev *ir;
- int ret, i;
-
- idev = input_allocate_device();
-@@ -1671,12 +1669,6 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx)
- goto props_alloc_failed;
- }
-
-- ir = kzalloc(sizeof(struct ir_input_dev), GFP_KERNEL);
-- if (!ir) {
-- dev_err(ictx->dev, "remote ir input dev allocation failed\n");
-- goto ir_dev_alloc_failed;
-- }
--
- snprintf(ictx->name_idev, sizeof(ictx->name_idev),
- "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product);
- idev->name = ictx->name_idev;
-@@ -1706,14 +1698,9 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx)
- props->change_protocol = imon_ir_change_protocol;
- ictx->props = props;
-
-- ictx->ir = ir;
-- memcpy(&ir->dev, ictx->dev, sizeof(struct device));
--
- usb_to_input_id(ictx->usbdev_intf0, &idev->id);
- idev->dev.parent = ictx->dev;
-
-- input_set_drvdata(idev, ir);
--
- ret = ir_input_register(idev, RC_MAP_IMON_PAD, props, MOD_NAME);
- if (ret < 0) {
- dev_err(ictx->dev, "remote input dev register failed\n");
-@@ -1723,8 +1710,6 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx)
- return idev;
-
- idev_register_failed:
-- kfree(ir);
--ir_dev_alloc_failed:
- kfree(props);
- props_alloc_failed:
- input_free_device(idev);
-@@ -1944,7 +1929,6 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf)
-
- urb_submit_failed:
- ir_input_unregister(ictx->idev);
-- input_free_device(ictx->idev);
- idev_setup_failed:
- find_endpoint_failed:
- mutex_unlock(&ictx->lock);
-@@ -2014,10 +1998,8 @@ static struct imon_context *imon_init_intf1(struct usb_interface *intf,
- return ictx;
-
- urb_submit_failed:
-- if (ictx->touch) {
-+ if (ictx->touch)
- input_unregister_device(ictx->touch);
-- input_free_device(ictx->touch);
-- }
- touch_setup_failed:
- find_endpoint_failed:
- mutex_unlock(&ictx->lock);
-diff --git a/drivers/media/IR/mceusb.c b/drivers/media/IR/mceusb.c
-index 78bf7f7..65b0738 100644
---- a/drivers/media/IR/mceusb.c
-+++ b/drivers/media/IR/mceusb.c
-@@ -228,7 +228,6 @@ static struct usb_device_id std_tx_mask_list[] = {
- /* data structure for each usb transceiver */
- struct mceusb_dev {
- /* ir-core bits */
-- struct ir_input_dev *irdev;
- struct ir_dev_props *props;
- struct ir_raw_event rawir;
-
-@@ -739,7 +738,7 @@ static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
-
- if (ir->send_flags == RECV_FLAG_IN_PROGRESS) {
- ir->send_flags = SEND_FLAG_COMPLETE;
-- dev_dbg(&ir->irdev->dev, "setup answer received %d bytes\n",
-+ dev_dbg(ir->dev, "setup answer received %d bytes\n",
- buf_len);
- }
-
-@@ -861,7 +860,6 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
- {
- struct input_dev *idev;
- struct ir_dev_props *props;
-- struct ir_input_dev *irdev;
- struct device *dev = ir->dev;
- int ret = -ENODEV;
-
-@@ -878,12 +876,6 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
- goto props_alloc_failed;
- }
-
-- irdev = kzalloc(sizeof(struct ir_input_dev), GFP_KERNEL);
-- if (!irdev) {
-- dev_err(dev, "remote ir input dev allocation failed\n");
-- goto ir_dev_alloc_failed;
-- }
--
- snprintf(ir->name, sizeof(ir->name), "Media Center Ed. eHome "
- "Infrared Remote Transceiver (%04x:%04x)",
- le16_to_cpu(ir->usbdev->descriptor.idVendor),
-@@ -902,9 +894,6 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
- props->tx_ir = mceusb_tx_ir;
-
- ir->props = props;
-- ir->irdev = irdev;
--
-- input_set_drvdata(idev, irdev);
-
- ret = ir_input_register(idev, RC_MAP_RC6_MCE, props, DRIVER_NAME);
- if (ret < 0) {
-@@ -915,8 +904,6 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
- return idev;
-
- irdev_failed:
-- kfree(irdev);
--ir_dev_alloc_failed:
- kfree(props);
- props_alloc_failed:
- input_free_device(idev);
diff --git a/lirc-staging-2.6.36.patch b/lirc-staging-2.6.36.patch
deleted file mode 100644
index 23c80bc0e..000000000
--- a/lirc-staging-2.6.36.patch
+++ /dev/null
@@ -1,12206 +0,0 @@
- drivers/staging/Kconfig | 2 +
- drivers/staging/Makefile | 1 +
- drivers/staging/lirc/Kconfig | 111 +++
- drivers/staging/lirc/Makefile | 19 +
- drivers/staging/lirc/TODO | 8 +
- drivers/staging/lirc/TODO.lirc_i2c | 3 +
- drivers/staging/lirc/lirc_bt829.c | 383 +++++++++
- drivers/staging/lirc/lirc_ene0100.c | 646 ++++++++++++++
- drivers/staging/lirc/lirc_ene0100.h | 169 ++++
- drivers/staging/lirc/lirc_i2c.c | 536 ++++++++++++
- drivers/staging/lirc/lirc_igorplugusb.c | 555 ++++++++++++
- drivers/staging/lirc/lirc_imon.c | 1058 +++++++++++++++++++++++
- drivers/staging/lirc/lirc_it87.c | 1022 +++++++++++++++++++++++
- drivers/staging/lirc/lirc_it87.h | 116 +++
- drivers/staging/lirc/lirc_ite8709.c | 542 ++++++++++++
- drivers/staging/lirc/lirc_parallel.c | 705 ++++++++++++++++
- drivers/staging/lirc/lirc_parallel.h | 26 +
- drivers/staging/lirc/lirc_sasem.c | 933 +++++++++++++++++++++
- drivers/staging/lirc/lirc_serial.c | 1313 +++++++++++++++++++++++++++++
- drivers/staging/lirc/lirc_sir.c | 1282 ++++++++++++++++++++++++++++
- drivers/staging/lirc/lirc_streamzap.c | 821 ++++++++++++++++++
- drivers/staging/lirc/lirc_ttusbir.c | 396 +++++++++
- drivers/staging/lirc/lirc_zilog.c | 1387 +++++++++++++++++++++++++++++++
- 23 files changed, 12034 insertions(+), 0 deletions(-)
-
-diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
-index 984a754..9296517 100644
---- a/drivers/staging/Kconfig
-+++ b/drivers/staging/Kconfig
-@@ -147,5 +147,7 @@ source "drivers/staging/mrst-touchscreen/Kconfig"
-
- source "drivers/staging/msm/Kconfig"
-
-+source "drivers/staging/lirc/Kconfig"
-+
- endif # !STAGING_EXCLUDE_BUILD
- endif # STAGING
-diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
-index 9fa2513..6c5b523 100644
---- a/drivers/staging/Makefile
-+++ b/drivers/staging/Makefile
-@@ -8,6 +8,7 @@ obj-$(CONFIG_SLICOSS) += slicoss/
- obj-$(CONFIG_VIDEO_GO7007) += go7007/
- obj-$(CONFIG_VIDEO_CX25821) += cx25821/
- obj-$(CONFIG_VIDEO_TM6000) += tm6000/
-+obj-$(CONFIG_LIRC_STAGING) += lirc/
- obj-$(CONFIG_USB_IP_COMMON) += usbip/
- obj-$(CONFIG_W35UND) += winbond/
- obj-$(CONFIG_PRISM2_USB) += wlan-ng/
-diff --git a/drivers/staging/lirc/Kconfig b/drivers/staging/lirc/Kconfig
-new file mode 100644
-index 0000000..ab30a09
---- /dev/null
-+++ b/drivers/staging/lirc/Kconfig
-@@ -0,0 +1,111 @@
-+#
-+# LIRC driver(s) configuration
-+#
-+menuconfig LIRC_STAGING
-+ bool "Linux Infrared Remote Control IR receiver/transmitter drivers"
-+ depends on LIRC
-+ help
-+ Say Y here, and all supported Linux Infrared Remote Control IR and
-+ RF receiver and transmitter drivers will be displayed. When paired
-+ with a remote control and the lirc daemon, the receiver drivers
-+ allow control of your Linux system via remote control.
-+
-+if LIRC_STAGING
-+
-+config LIRC_BT829
-+ tristate "BT829 based hardware"
-+ depends on LIRC_STAGING && PCI
-+ help
-+ Driver for the IR interface on BT829-based hardware
-+
-+config LIRC_ENE0100
-+ tristate "ENE KB3924/ENE0100 CIR Port Reciever"
-+ depends on LIRC_STAGING && PNP
-+ help
-+ This is a driver for CIR port handled by ENE KB3924 embedded
-+ controller found on some notebooks.
-+ It appears on PNP list as ENE0100.
-+
-+config LIRC_I2C
-+ tristate "I2C Based IR Receivers"
-+ depends on LIRC_STAGING && I2C
-+ help
-+ Driver for I2C-based IR receivers, such as those commonly
-+ found onboard Hauppauge PVR-150/250/350 video capture cards
-+
-+config LIRC_IGORPLUGUSB
-+ tristate "Igor Cesko's USB IR Receiver"
-+ depends on LIRC_STAGING && USB
-+ help
-+ Driver for Igor Cesko's USB IR Receiver
-+
-+config LIRC_IMON
-+ tristate "Legacy SoundGraph iMON Receiver and Display"
-+ depends on LIRC_STAGING && USB
-+ help
-+ Driver for the original SoundGraph iMON IR Receiver and Display
-+
-+ Current generation iMON devices use the input layer imon driver.
-+
-+config LIRC_IT87
-+ tristate "ITE IT87XX CIR Port Receiver"
-+ depends on LIRC_STAGING && PNP
-+ help
-+ Driver for the ITE IT87xx IR Receiver
-+
-+config LIRC_ITE8709
-+ tristate "ITE8709 CIR Port Receiver"
-+ depends on LIRC_STAGING && PNP
-+ help
-+ Driver for the ITE8709 IR Receiver
-+
-+config LIRC_PARALLEL
-+ tristate "Homebrew Parallel Port Receiver"
-+ depends on LIRC_STAGING && PARPORT && !SMP
-+ help
-+ Driver for Homebrew Parallel Port Receivers
-+
-+config LIRC_SASEM
-+ tristate "Sasem USB IR Remote"
-+ depends on LIRC_STAGING && USB
-+ help
-+ Driver for the Sasem OnAir Remocon-V or Dign HV5 HTPC IR/VFD Module
-+
-+config LIRC_SERIAL
-+ tristate "Homebrew Serial Port Receiver"
-+ depends on LIRC_STAGING
-+ help
-+ Driver for Homebrew Serial Port Receivers
-+
-+config LIRC_SERIAL_TRANSMITTER
-+ bool "Serial Port Transmitter"
-+ default y
-+ depends on LIRC_SERIAL
-+ help
-+ Serial Port Transmitter support
-+
-+config LIRC_SIR
-+ tristate "Built-in SIR IrDA port"
-+ depends on LIRC_STAGING
-+ help
-+ Driver for the SIR IrDA port
-+
-+config LIRC_STREAMZAP
-+ tristate "Streamzap PC Receiver"
-+ depends on LIRC_STAGING && USB
-+ help
-+ Driver for the Streamzap PC Receiver
-+
-+config LIRC_TTUSBIR
-+ tristate "Technotrend USB IR Receiver"
-+ depends on LIRC_STAGING && USB
-+ help
-+ Driver for the Technotrend USB IR Receiver
-+
-+config LIRC_ZILOG
-+ tristate "Zilog/Hauppauge IR Transmitter"
-+ depends on LIRC_STAGING && I2C
-+ help
-+ Driver for the Zilog/Hauppauge IR Transmitter, found on
-+ PVR-150/500, HVR-1200/1250/1700/1800, HD-PVR and other cards
-+endif
-diff --git a/drivers/staging/lirc/Makefile b/drivers/staging/lirc/Makefile
-new file mode 100644
-index 0000000..a019182
---- /dev/null
-+++ b/drivers/staging/lirc/Makefile
-@@ -0,0 +1,19 @@
-+# Makefile for the lirc drivers.
-+#
-+
-+# Each configuration option enables a list of files.
-+
-+obj-$(CONFIG_LIRC_BT829) += lirc_bt829.o
-+obj-$(CONFIG_LIRC_ENE0100) += lirc_ene0100.o
-+obj-$(CONFIG_LIRC_I2C) += lirc_i2c.o
-+obj-$(CONFIG_LIRC_IGORPLUGUSB) += lirc_igorplugusb.o
-+obj-$(CONFIG_LIRC_IMON) += lirc_imon.o
-+obj-$(CONFIG_LIRC_IT87) += lirc_it87.o
-+obj-$(CONFIG_LIRC_ITE8709) += lirc_ite8709.o
-+obj-$(CONFIG_LIRC_PARALLEL) += lirc_parallel.o
-+obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o
-+obj-$(CONFIG_LIRC_SERIAL) += lirc_serial.o
-+obj-$(CONFIG_LIRC_SIR) += lirc_sir.o
-+obj-$(CONFIG_LIRC_STREAMZAP) += lirc_streamzap.o
-+obj-$(CONFIG_LIRC_TTUSBIR) += lirc_ttusbir.o
-+obj-$(CONFIG_LIRC_ZILOG) += lirc_zilog.o
-diff --git a/drivers/staging/lirc/TODO b/drivers/staging/lirc/TODO
-new file mode 100644
-index 0000000..b6cb593
---- /dev/null
-+++ b/drivers/staging/lirc/TODO
-@@ -0,0 +1,8 @@
-+- All drivers should either be ported to ir-core, or dropped entirely
-+ (see drivers/media/IR/mceusb.c vs. lirc_mceusb.c in lirc cvs for an
-+ example of a previously completed port).
-+
-+Please send patches to:
-+Jarod Wilson <jarod@wilsonet.com>
-+Greg Kroah-Hartman <greg@kroah.com>
-+
-diff --git a/drivers/staging/lirc/TODO.lirc_i2c b/drivers/staging/lirc/TODO.lirc_i2c
-new file mode 100644
-index 0000000..1f0a6ff
---- /dev/null
-+++ b/drivers/staging/lirc/TODO.lirc_i2c
-@@ -0,0 +1,3 @@
-+lirc_i2c provides support for some drivers that have already a RC
-+driver under drivers/media/video. It should be integrated into those
-+drivers, in special with drivers/media/video/ir-kbd-i2c.c.
-diff --git a/drivers/staging/lirc/lirc_bt829.c b/drivers/staging/lirc/lirc_bt829.c
-new file mode 100644
-index 0000000..3388102
---- /dev/null
-+++ b/drivers/staging/lirc/lirc_bt829.c
-@@ -0,0 +1,383 @@
-+/*
-+ * 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/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 <media/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;
-+ 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)
-+{
-+ dprintk("driver is opened\n");
-+ return 0;
-+}
-+
-+static void atir_set_use_dec(void *data)
-+{
-+ 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;
-+ atir_driver.dev = &pdev->dev;
-+ 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");
-diff --git a/drivers/staging/lirc/lirc_ene0100.c b/drivers/staging/lirc/lirc_ene0100.c
-new file mode 100644
-index 0000000..a152c52
---- /dev/null
-+++ b/drivers/staging/lirc/lirc_ene0100.c
-@@ -0,0 +1,646 @@
-+/*
-+ * 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 <linux/sched.h>
-+#include "lirc_ene0100.h"
-+
-+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 */
-+static irqreturn_t ene_hw_irq(int irq, void *data)
-+{
-+ 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);
-diff --git a/drivers/staging/lirc/lirc_ene0100.h b/drivers/staging/lirc/lirc_ene0100.h
-new file mode 100644
-index 0000000..776b693
---- /dev/null
-+++ b/drivers/staging/lirc/lirc_ene0100.h
-@@ -0,0 +1,169 @@
-+/*
-+ * 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 <media/lirc.h>
-+#include <media/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/drivers/staging/lirc/lirc_i2c.c b/drivers/staging/lirc/lirc_i2c.c
-new file mode 100644
-index 0000000..6df2c0e
---- /dev/null
-+++ b/drivers/staging/lirc/lirc_i2c.c
-@@ -0,0 +1,536 @@
-+/*
-+ * 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
-+ */
-+
-+
-+#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 <media/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;
-+
-+ dprintk("%s called\n", __func__);
-+
-+ /* lock bttv in memory while /dev/lirc is in use */
-+ i2c_use_client(&ir->c);
-+
-+ return 0;
-+}
-+
-+static void set_use_dec(void *data)
-+{
-+ struct IR *ir = data;
-+
-+ dprintk("%s called\n", __func__);
-+
-+ i2c_release_client(&ir->c);
-+}
-+
-+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,
-+};
-+
-+static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id);
-+static int ir_remove(struct i2c_client *client);
-+static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg);
-+
-+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 */
-+ { }
-+};
-+
-+static struct i2c_driver driver = {
-+ .driver = {
-+ .owner = THIS_MODULE,
-+ .name = "i2c ir driver",
-+ },
-+ .probe = ir_probe,
-+ .remove = ir_remove,
-+ .id_table = ir_receiver_id,
-+ .command = ir_command,
-+};
-+
-+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)
-+{
-+ struct IR *ir;
-+ struct i2c_adapter *adap = client->adapter;
-+ unsigned short addr = client->addr;
-+ int retval;
-+
-+ ir = kzalloc(sizeof(struct IR), GFP_KERNEL);
-+ if (!ir)
-+ return -ENOMEM;
-+ memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver));
-+ memcpy(&ir->c, client, sizeof(struct i2c_client));
-+
-+ i2c_set_clientdata(client, ir);
-+ 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:
-+ if (adap->id == I2C_HW_B_CX2388x)
-+ strlcpy(ir->c.name, "Hauppauge HVR1300", I2C_NAME_SIZE);
-+ else /* bt8xx or cx2341x */
-+ /*
-+ * 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);
-+ 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:
-+ if (adap->id == 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;
-+ } else { /* bt8xx or cx2341x */
-+ strlcpy(ir->c.name, "Hauppauge IR", I2C_NAME_SIZE);
-+ ir->l.code_length = 13;
-+ ir->l.add_to_buf = add_to_buf_haup;
-+ }
-+ 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:
-+ pcf_probe(client, ir);
-+ 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);
-+
-+ retval = lirc_register_driver(&ir->l);
-+
-+ if (retval < 0) {
-+ printk(KERN_ERR "lirc_i2c: failed to register driver!\n");
-+ 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);
-+
-+ /* free memory */
-+ kfree(ir);
-+ return 0;
-+}
-+
-+static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg)
-+{
-+ /* nothing */
-+ return 0;
-+}
-+
-+static int __init lirc_i2c_init(void)
-+{
-+ 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);
-diff --git a/drivers/staging/lirc/lirc_igorplugusb.c b/drivers/staging/lirc/lirc_igorplugusb.c
-new file mode 100644
-index 0000000..bce600e
---- /dev/null
-+++ b/drivers/staging/lirc/lirc_igorplugusb.c
-@@ -0,0 +1,555 @@
-+/*
-+ * 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/module.h>
-+#include <linux/kernel.h>
-+#include <linux/kmod.h>
-+#include <linux/sched.h>
-+#include <linux/errno.h>
-+#include <linux/fs.h>
-+#include <linux/usb.h>
-+#include <linux/time.h>
-+
-+#include <media/lirc.h>
-+#include <media/lirc_dev.h>
-+
-+
-+/* module identification */
-+#define DRIVER_VERSION "0.1"
-+#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 fmt, ## args); \
-+ } while (0)
-+
-+/* One mode2 pulse/space has 4 bytes. */
-+#define CODE_LENGTH sizeof(int)
-+
-+/* 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;
-+
-+ dma_addr_t dma_in;
-+
-+ /* lirc */
-+ struct lirc_driver *d;
-+
-+ /* handle sending (init strings) */
-+ int send_flags;
-+ wait_queue_head_t wait_out;
-+};
-+
-+static int unregister_from_lirc(struct igorplug *ir)
-+{
-+ struct lirc_driver *d = ir->d;
-+ int devnum;
-+
-+ if (!ir->d)
-+ return -EINVAL;
-+
-+ 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);
-+
-+ kfree(d);
-+ ir->d = NULL;
-+ kfree(ir);
-+ return 0;
-+}
-+
-+static int set_use_inc(void *data)
-+{
-+ struct igorplug *ir = data;
-+
-+ 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);
-+
-+ if (!ir->usbdev)
-+ return -ENODEV;
-+
-+ return 0;
-+}
-+
-+static void set_use_dec(void *data)
-+{
-+ struct igorplug *ir = data;
-+
-+ if (!ir) {
-+ printk(DRIVER_NAME "[?]: set_use_dec called with no context\n");
-+ return;
-+ }
-+ dprintk(DRIVER_NAME "[%d]: set use dec\n", ir->devnum);
-+}
-+
-+
-+/**
-+ * 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) {
-+ int i = DEVICE_HEADERLEN;
-+ int code, timediff;
-+ struct timeval now;
-+
-+ if (ret <= 1) /* ACK packet has 1 byte --> ignore */
-+ return -ENODATA;
-+
-+ dprintk(DRIVER_NAME ": Got %d bytes. Header: %02x %02x %02x\n",
-+ ret, ir->buf_in[0], ir->buf_in[1], ir->buf_in[2]);
-+
-+ if (ir->buf_in[2] != 0) {
-+ printk(DRIVER_NAME "[%d]: Device buffer overrun.\n",
-+ ir->devnum);
-+ /* start at earliest byte */
-+ i = DEVICE_HEADERLEN + ir->buf_in[2];
-+ /* where are we now? space, gap or pulse? */
-+ }
-+
-+ 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 */
-+
-+ /* MODE2: pulse/space (PULSE_BIT) in 1us units */
-+
-+ while (i < ret) {
-+ /* 1 Igor-tick = 85.333333 us */
-+ code = (unsigned int)ir->buf_in[i] * 85
-+ + (unsigned int)ir->buf_in[i] / 3;
-+ if (ir->in_space)
-+ code |= PULSE_BIT;
-+ lirc_buffer_write(buf, (unsigned char *)&code);
-+ /* 1 chunk = CODE_LENGTH bytes */
-+ ir->in_space ^= 1;
-+ ++i;
-+ }
-+
-+ 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(DRIVER_NAME "[%d]: SET_INFRABUFFER_EMPTY: "
-+ "error %d\n", ir->devnum, ret);
-+ return 0;
-+ } else if (ret < 0)
-+ printk(DRIVER_NAME "[%d]: GET_INFRACODE: error %d\n",
-+ ir->devnum, ret);
-+
-+ return -ENODATA;
-+}
-+
-+
-+
-+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;
-+ 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(DRIVER_NAME ": usb probe called.\n");
-+
-+ dev = interface_to_usbdev(intf);
-+
-+ idesc = intf->cur_altsetting;
-+
-+ 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);
-+ devnum = dev->devnum;
-+ maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
-+
-+ dprintk(DRIVER_NAME "[%d]: bytes_in_key=%lu 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;
-+ }
-+
-+ ir->buf_in = usb_alloc_coherent(dev,
-+ DEVICE_BUFLEN+DEVICE_HEADERLEN,
-+ GFP_ATOMIC, &ir->dma_in);
-+ 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->chunk_size = CODE_LENGTH;
-+ 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;
-+ driver->dev = &intf->dev;
-+ driver->owner = THIS_MODULE;
-+
-+ 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_coherent(dev, DEVICE_BUFLEN+DEVICE_HEADERLEN,
-+ ir->buf_in, ir->dma_in);
-+ 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 = 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(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(DRIVER_NAME "[%d]: SET_INFRABUFFER_EMPTY: error %d\n",
-+ devnum, ret);
-+
-+ usb_set_intfdata(intf, ir);
-+ return 0;
-+}
-+
-+
-+static void usb_remote_disconnect(struct usb_interface *intf)
-+{
-+ struct usb_device *dev = interface_to_usbdev(intf);
-+ struct igorplug *ir = usb_get_intfdata(intf);
-+ usb_set_intfdata(intf, NULL);
-+
-+ if (!ir || !ir->d)
-+ return;
-+
-+ ir->usbdev = NULL;
-+ wake_up_all(&ir->wait_out);
-+
-+ usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in);
-+
-+ unregister_from_lirc(ir);
-+}
-+
-+static struct usb_device_id usb_remote_id_table[] = {
-+ /* Igor Plug USB (Atmel's Manufact. ID) */
-+ { USB_DEVICE(0x03eb, 0x0002) },
-+
-+ /* Terminating entry */
-+ { }
-+};
-+
-+static struct usb_driver usb_remote_driver = {
-+ .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 "\n"
-+ DRIVER_NAME ": " DRIVER_DESC " v" DRIVER_VERSION "\n");
-+ printk(DRIVER_NAME ": " DRIVER_AUTHOR "\n");
-+ dprintk(DRIVER_NAME ": debug mode enabled\n");
-+
-+ i = usb_register(&usb_remote_driver);
-+ if (i < 0) {
-+ 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);
-+
-+#include <linux/vermagic.h>
-+MODULE_INFO(vermagic, VERMAGIC_STRING);
-+
-+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)");
-+
-diff --git a/drivers/staging/lirc/lirc_imon.c b/drivers/staging/lirc/lirc_imon.c
-new file mode 100644
-index 0000000..6649325
---- /dev/null
-+++ b/drivers/staging/lirc/lirc_imon.c
-@@ -0,0 +1,1058 @@
-+/*
-+ * lirc_imon.c: LIRC/VFD/LCD driver for SoundGraph iMON IR/VFD/LCD
-+ * including the iMON PAD model
-+ *
-+ * Copyright(C) 2004 Venky Raju(dev@venky.ws)
-+ * Copyright(C) 2009 Jarod Wilson <jarod@wilsonet.com>
-+ *
-+ * 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/errno.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include <linux/uaccess.h>
-+#include <linux/usb.h>
-+
-+#include <media/lirc.h>
-+#include <media/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.8"
-+
-+#define DISPLAY_MINOR_BASE 144
-+#define DEVICE_NAME "lcd%d"
-+
-+#define BUF_CHUNK_SIZE 4
-+#define BUF_SIZE 128
-+
-+#define BIT_DURATION 250 /* each bit received is 250us */
-+
-+/*** 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);
-+static void usb_rx_callback(struct urb *urb);
-+static void usb_tx_callback(struct urb *urb);
-+
-+/* 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);
-+
-+/* 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 ***/
-+#define IMON_DATA_BUF_SZ 35
-+
-+struct imon_context {
-+ struct usb_device *usbdev;
-+ /* Newer devices have two interfaces */
-+ int display; /* not all controllers do */
-+ int display_isopen; /* display port has been opened */
-+ int ir_isopen; /* IR port open */
-+ int dev_present; /* USB device presence */
-+ struct mutex ctx_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 */
-+
-+ 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 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[IMON_DATA_BUF_SZ]; /* user data buffer */
-+ struct completion finished; /* wait for write to finish */
-+ atomic_t busy; /* write in progress */
-+ int status; /* status of tx completion */
-+ } tx;
-+};
-+
-+static const struct file_operations display_fops = {
-+ .owner = THIS_MODULE,
-+ .open = &display_open,
-+ .write = &vfd_write,
-+ .release = &display_close
-+};
-+
-+/*
-+ * 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) },
-+
-+ {}
-+};
-+
-+/* Some iMON VFD models requires a 6th packet for VFD writes */
-+static struct usb_device_id vfd_proto_6p_list[] = {
-+ { USB_DEVICE(0x15c2, 0xffda) },
-+ {}
-+};
-+
-+/* 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) },
-+ {}
-+};
-+
-+/* USB Device data */
-+static struct usb_driver imon_driver = {
-+ .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,
-+ .minor_base = DISPLAY_MINOR_BASE,
-+};
-+
-+/* to prevent races between open() and disconnect(), probing, etc */
-+static DEFINE_MUTEX(driver_lock);
-+
-+static int debug;
-+
-+/*** 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)");
-+
-+static void free_imon_context(struct imon_context *context)
-+{
-+ struct device *dev = context->driver->dev;
-+ usb_free_urb(context->tx_urb);
-+ usb_free_urb(context->rx_urb);
-+ lirc_buffer_free(context->driver->rbuf);
-+ kfree(context->driver->rbuf);
-+ kfree(context->driver);
-+ kfree(context);
-+
-+ dev_dbg(dev, "%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->ctx_lock);
-+
-+ if (!context->display) {
-+ 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 {
-+ context->display_isopen = 1;
-+ file->private_data = context;
-+ dev_info(context->driver->dev, "display port opened\n");
-+ }
-+
-+ mutex_unlock(&context->ctx_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->ctx_lock);
-+
-+ if (!context->display) {
-+ 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;
-+ dev_info(context->driver->dev, "display 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->ctx_lock);
-+ free_imon_context(context);
-+ return retval;
-+ }
-+ }
-+
-+ mutex_unlock(&context->ctx_lock);
-+ return retval;
-+}
-+
-+/**
-+ * Sends a packet to the device -- this function must be called
-+ * with context->ctx_lock held.
-+ */
-+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 */
-+ pipe = usb_sndintpipe(context->usbdev,
-+ context->tx_endpoint->bEndpointAddress);
-+ interval = context->tx_endpoint->bInterval;
-+
-+ usb_fill_int_urb(context->tx_urb, context->usbdev, 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);
-+
-+ 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->ctx_lock);
-+ retval = wait_for_completion_interruptible(
-+ &context->tx.finished);
-+ if (retval)
-+ err("%s: task interrupted", __func__);
-+ mutex_lock(&context->ctx_lock);
-+
-+ retval = context->tx.status;
-+ if (retval)
-+ err("%s: packet tx failed (%d)", __func__, retval);
-+ }
-+
-+ kfree(control_req);
-+
-+ return retval;
-+}
-+
-+/**
-+ * 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 };
-+ int *data_buf;
-+
-+ context = (struct imon_context *)file->private_data;
-+ if (!context) {
-+ err("%s: no context for device", __func__);
-+ return -ENODEV;
-+ }
-+
-+ mutex_lock(&context->ctx_lock);
-+
-+ if (!context->dev_present) {
-+ err("%s: no iMON device present", __func__);
-+ retval = -ENODEV;
-+ goto exit;
-+ }
-+
-+ if (n_bytes <= 0 || n_bytes > IMON_DATA_BUF_SZ - 3) {
-+ err("%s: invalid payload size", __func__);
-+ retval = -EINVAL;
-+ goto exit;
-+ }
-+
-+ data_buf = memdup_user(buf, n_bytes);
-+ if (IS_ERR(data_buf)) {
-+ retval = PTR_ERR(data_buf);
-+ goto exit;
-+ }
-+
-+ memcpy(context->tx.data_buf, data_buf, n_bytes);
-+
-+ /* Pad with spaces */
-+ for (i = n_bytes; i < IMON_DATA_BUF_SZ - 3; ++i)
-+ context->tx.data_buf[i] = ' ';
-+
-+ for (i = IMON_DATA_BUF_SZ - 3; i < IMON_DATA_BUF_SZ; ++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 < IMON_DATA_BUF_SZ);
-+
-+ 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->ctx_lock);
-+
-+ return (!retval) ? n_bytes : retval;
-+}
-+
-+/**
-+ * Callback function for USB core API: transmit data
-+ */
-+static void usb_tx_callback(struct urb *urb)
-+{
-+ 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;
-+}
-+
-+/**
-+ * 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;
-+
-+ context->ir_isopen = 1;
-+ dev_info(context->driver->dev, "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->ctx_lock);
-+
-+ context->ir_isopen = 0;
-+ dev_info(context->driver->dev, "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->display_isopen) {
-+ mutex_unlock(&context->ctx_lock);
-+ free_imon_context(context);
-+ return;
-+ }
-+ /*
-+ * If display port is open, context will be deleted by
-+ * display_close
-+ */
-+ }
-+
-+ mutex_unlock(&context->ctx_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;
-+
-+ dev_dbg(context->driver->dev, "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;
-+}
-+
-+/**
-+ * 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;
-+ struct device *dev = context->driver->dev;
-+ int octet, bit;
-+ unsigned char mask;
-+ int i, chunk_num;
-+
-+ /*
-+ * just bail out if no listening IR client
-+ */
-+ if (!context->ir_isopen)
-+ return;
-+
-+ if (len != 8) {
-+ dev_warn(dev, "imon %s: invalid incoming packet "
-+ "size (len = %d, intf%d)\n", __func__, len, intf);
-+ return;
-+ }
-+
-+ if (debug) {
-+ printk(KERN_INFO "raw packet: ");
-+ for (i = 0; i < len; ++i)
-+ printk("%02x ", buf[i]);
-+ printk("\n");
-+ }
-+
-+ /*
-+ * 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 (buf[7] == 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;
-+ }
-+}
-+
-+/**
-+ * Callback function for USB core API: receive data
-+ */
-+static void usb_rx_callback(struct urb *urb)
-+{
-+ 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:
-+ dev_warn(context->driver->dev, "imon %s: status(%d): ignored\n",
-+ __func__, urb->status);
-+ break;
-+ }
-+
-+ usb_submit_urb(context->rx_urb, 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 device *dev = &interface->dev;
-+ 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 code_length;
-+ struct imon_context *context = NULL;
-+ int i;
-+ u16 vendor, product;
-+
-+ context = kzalloc(sizeof(struct imon_context), GFP_KERNEL);
-+ if (!context) {
-+ err("%s: kzalloc failed for context", __func__);
-+ alloc_status = 1;
-+ goto alloc_status_switch;
-+ }
-+
-+ /*
-+ * 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 (usb_match_id(interface, ir_only_list))
-+ context->display = 0;
-+ else
-+ context->display = 1;
-+
-+ 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);
-+
-+ dev_dbg(dev, "%s: found iMON device (%04x:%04x, intf%d)\n",
-+ __func__, vendor, product, ifnum);
-+
-+ /* prevent races probing devices w/multiple interfaces */
-+ mutex_lock(&driver_lock);
-+
-+ /*
-+ * 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;
-+ dev_dbg(dev, "%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;
-+ dev_dbg(dev, "%s: found display endpoint\n", __func__);
-+ }
-+ }
-+
-+ /*
-+ * Some iMON receivers have no display. Unfortunately, it seems
-+ * that SoundGraph recycles device IDs between devices both with
-+ * and without... :\
-+ */
-+ if (context->display == 0) {
-+ display_ep_found = 0;
-+ dev_dbg(dev, "%s: device has no display\n", __func__);
-+ }
-+
-+ /* Input endpoint is mandatory */
-+ if (!ir_ep_found) {
-+ err("%s: no valid input (IR) endpoint found.", __func__);
-+ retval = -ENODEV;
-+ alloc_status = 2;
-+ goto alloc_status_switch;
-+ }
-+
-+ /* Determine if display requires 6 packets */
-+ if (display_ep_found) {
-+ if (usb_match_id(interface, vfd_proto_6p_list))
-+ vfd_proto_6p = 1;
-+
-+ dev_dbg(dev, "%s: vfd_proto_6p: %d\n",
-+ __func__, vfd_proto_6p);
-+ }
-+
-+ 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->ctx_lock);
-+ context->vfd_proto_6p = vfd_proto_6p;
-+
-+ strcpy(driver->name, MOD_NAME);
-+ driver->minor = -1;
-+ driver->code_length = sizeof(int) * 8;
-+ driver->sample_rate = 0;
-+ driver->features = LIRC_CAN_REC_MODE2;
-+ driver->data = context;
-+ driver->rbuf = rbuf;
-+ driver->set_use_inc = ir_open;
-+ driver->set_use_dec = ir_close;
-+ driver->dev = &interface->dev;
-+ driver->owner = THIS_MODULE;
-+
-+ mutex_lock(&context->ctx_lock);
-+
-+ context->driver = driver;
-+ /* start out in keyboard mode */
-+
-+ 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
-+ dev_info(dev, "Registered iMON driver "
-+ "(lirc minor: %d)\n", lirc_minor);
-+
-+ /* Needed while unregistering! */
-+ driver->minor = lirc_minor;
-+
-+ context->usbdev = usbdev;
-+ context->dev_present = 1;
-+ context->rx_endpoint = rx_endpoint;
-+ context->rx_urb = 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;
-+
-+ if (display_ep_found)
-+ context->display = 1;
-+
-+ usb_fill_int_urb(context->rx_urb, context->usbdev,
-+ usb_rcvintpipe(context->usbdev,
-+ context->rx_endpoint->bEndpointAddress),
-+ context->usb_rx_buf, sizeof(context->usb_rx_buf),
-+ usb_rx_callback, context,
-+ context->rx_endpoint->bInterval);
-+
-+ retval = usb_submit_urb(context->rx_urb, GFP_KERNEL);
-+
-+ if (retval) {
-+ err("%s: usb_submit_urb failed for intf0 (%d)",
-+ __func__, retval);
-+ mutex_unlock(&context->ctx_lock);
-+ goto exit;
-+ }
-+
-+ usb_set_intfdata(interface, context);
-+
-+ if (context->display && ifnum == 0) {
-+ dev_dbg(dev, "%s: Registering iMON display with sysfs\n",
-+ __func__);
-+
-+ if (usb_register_dev(interface, &imon_class)) {
-+ /* Not a fatal error, so ignore */
-+ dev_info(dev, "%s: could not get a minor number for "
-+ "display\n", __func__);
-+ }
-+ }
-+
-+ dev_info(dev, "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->ctx_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:
-+ if (retval != -ENODEV)
-+ 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->ctx_lock);
-+
-+ 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);
-+ }
-+
-+ context->dev_present = 0;
-+ usb_kill_urb(context->rx_urb);
-+ if (context->display)
-+ usb_deregister_dev(interface, &imon_class);
-+
-+ if (!context->ir_isopen && !context->dev_present) {
-+ deregister_from_lirc(context);
-+ mutex_unlock(&context->ctx_lock);
-+ if (!context->display_isopen)
-+ free_imon_context(context);
-+ } else
-+ mutex_unlock(&context->ctx_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);
-+
-+ usb_kill_urb(context->rx_urb);
-+
-+ return 0;
-+}
-+
-+static int imon_resume(struct usb_interface *intf)
-+{
-+ int rc = 0;
-+ struct imon_context *context = usb_get_intfdata(intf);
-+
-+ usb_fill_int_urb(context->rx_urb, context->usbdev,
-+ usb_rcvintpipe(context->usbdev,
-+ context->rx_endpoint->bEndpointAddress),
-+ context->usb_rx_buf, sizeof(context->usb_rx_buf),
-+ usb_rx_callback, context,
-+ context->rx_endpoint->bInterval);
-+
-+ rc = usb_submit_urb(context->rx_urb, 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/drivers/staging/lirc/lirc_it87.c b/drivers/staging/lirc/lirc_it87.c
-new file mode 100644
-index 0000000..ec11c0e
---- /dev/null
-+++ b/drivers/staging/lirc/lirc_it87.c
-@@ -0,0 +1,1022 @@
-+/*
-+ * LIRC driver for ITE IT8712/IT8705 CIR port
-+ *
-+ * Copyright (C) 2001 Hans-Gunter Lutke 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 and 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>
-+ * 2009/12/24 James Edwards <jimbo-lirc@edwardsclan.net> implemeted support
-+ * for ITE8704/ITE8718, on my machine, the DSDT reports 8704, but the
-+ * chip identifies as 18.
-+ */
-+
-+#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/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>
-+#include <linux/io.h>
-+#include <linux/irq.h>
-+#include <linux/fcntl.h>
-+
-+#include <linux/timer.h>
-+#include <linux/pnp.h>
-+
-+#include <media/lirc.h>
-+#include <media/lirc_dev.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 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 bool device_open;
-+
-+static int rx_buf[RBUF_LEN];
-+unsigned int rx_tail, rx_head;
-+
-+static struct pnp_driver it87_pnp_driver;
-+
-+/* 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 long lirc_ioctl(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 */
-+static irqreturn_t it87_interrupt(int irq, void *dev_id);
-+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 (device_open) {
-+ spin_unlock(&dev_lock);
-+ return -EBUSY;
-+ }
-+ device_open = true;
-+ spin_unlock(&dev_lock);
-+ return 0;
-+}
-+
-+
-+static int lirc_close(struct inode *inode, struct file *file)
-+{
-+ spin_lock(&dev_lock);
-+ device_open = false;
-+ spin_unlock(&dev_lock);
-+ 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(int))) {
-+ retval = -EFAULT;
-+ break;
-+ }
-+ rx_head = (rx_head + 1) & (RBUF_LEN - 1);
-+ n += sizeof(int);
-+ }
-+ 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;
-+ int *tx_buf;
-+
-+ if (n % sizeof(int))
-+ return -EINVAL;
-+ tx_buf = memdup_user(buf, n);
-+ if (IS_ERR(tx_buf))
-+ return PTR_ERR(tx_buf);
-+ n /= sizeof(int);
-+ 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 long lirc_ioctl(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;
-+ int 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 const struct file_operations lirc_fops = {
-+ .owner = THIS_MODULE,
-+ .read = lirc_read,
-+ .write = lirc_write,
-+ .poll = lirc_poll,
-+ .unlocked_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,
-+ .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);
-+}
-+
-+static irqreturn_t it87_interrupt(int irq, void *dev_id)
-+{
-+ 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=%02x\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 != 0x05) &&
-+ (it87_chipid != 0x12) &&
-+ (it87_chipid != 0x18) &&
-+ (it87_chipid != 0x20)) {
-+ printk(KERN_INFO LIRC_DRIVER_NAME
-+ ": no IT8704/05/12/18/20 found (claimed IT87%02x), "
-+ "exiting..\n", it87_chipid);
-+ retval = -ENXIO;
-+ return retval;
-+ }
-+ printk(KERN_INFO LIRC_DRIVER_NAME
-+ ": found IT87%02x.\n",
-+ it87_chipid);
-+
-+ /* get I/O-Port and IRQ */
-+ if (it87_chipid == 0x12 || it87_chipid == 0x18)
-+ 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 it87_probe(struct pnp_dev *pnp_dev,
-+ const struct pnp_device_id *dev_id)
-+{
-+ int retval;
-+
-+ driver.dev = &pnp_dev->dev;
-+
-+ retval = init_chrdev();
-+ if (retval < 0)
-+ return retval;
-+
-+ retval = init_lirc_it87();
-+ if (retval)
-+ goto init_lirc_it87_failed;
-+
-+ return 0;
-+
-+init_lirc_it87_failed:
-+ drop_chrdev();
-+
-+ return retval;
-+}
-+
-+static int __init lirc_it87_init(void)
-+{
-+ return pnp_register_driver(&it87_pnp_driver);
-+}
-+
-+
-+static void __exit lirc_it87_exit(void)
-+{
-+ drop_hardware();
-+ drop_chrdev();
-+ drop_port();
-+ pnp_unregister_driver(&it87_pnp_driver);
-+ printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n");
-+}
-+
-+/* SECTION: PNP for ITE8704/18 */
-+
-+static const struct pnp_device_id pnp_dev_table[] = {
-+ {"ITE8704", 0},
-+ {}
-+};
-+
-+MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
-+
-+static struct pnp_driver it87_pnp_driver = {
-+ .name = LIRC_DRIVER_NAME,
-+ .id_table = pnp_dev_table,
-+ .probe = it87_probe,
-+};
-+
-+module_init(lirc_it87_init);
-+module_exit(lirc_it87_exit);
-+
-+MODULE_DESCRIPTION("LIRC driver for ITE IT8704/05/12/18/20 CIR port");
-+MODULE_AUTHOR("Hans-Gunter Lutke 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
-diff --git a/drivers/staging/lirc/lirc_it87.h b/drivers/staging/lirc/lirc_it87.h
-new file mode 100644
-index 0000000..cf021c8
---- /dev/null
-+++ b/drivers/staging/lirc/lirc_it87.h
-@@ -0,0 +1,116 @@
-+/* 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/drivers/staging/lirc/lirc_ite8709.c b/drivers/staging/lirc/lirc_ite8709.c
-new file mode 100644
-index 0000000..9352f45
---- /dev/null
-+++ b/drivers/staging/lirc/lirc_ite8709.c
-@@ -0,0 +1,542 @@
-+/*
-+ * 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/module.h>
-+#include <linux/interrupt.h>
-+#include <linux/sched.h>
-+#include <linux/delay.h>
-+#include <linux/pnp.h>
-+#include <linux/io.h>
-+
-+#include <media/lirc.h>
-+#include <media/lirc_dev.h>
-+
-+#define LIRC_DRIVER_NAME "lirc_ite8709"
-+
-+#define BUF_CHUNK_SIZE sizeof(int)
-+#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 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;
-+ 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;
-+ 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)
-+{
-+ int 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->driver.rbuf)) {
-+ lirc_buffer_write(dev->driver.rbuf, (void *) &value);
-+ wake_up(&dev->driver.rbuf->wait_poll);
-+ }
-+}
-+
-+static irqreturn_t ite8709_interrupt(int irq, void *dev_id)
-+{
-+ 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);
-+ kfree(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(int) * 8;
-+ driver->sample_rate = 0;
-+ driver->features = LIRC_CAN_REC_MODE2;
-+ driver->data = ite8709_dev;
-+ driver->add_to_buf = NULL;
-+ driver->set_use_inc = ite8709_set_use_inc;
-+ driver->set_use_dec = ite8709_set_use_dec;
-+ driver->dev = &dev->dev;
-+ driver->owner = THIS_MODULE;
-+
-+ /* Initialize LIRC buffer */
-+ driver->rbuf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
-+ if (!driver->rbuf)
-+ return ite8709_cleanup(ite8709_dev, 1, -ENOMEM,
-+ "can't allocate 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,
-+};
-+
-+static int __init ite8709_init_module(void)
-+{
-+ return pnp_register_driver(&ite8709_pnp_driver);
-+}
-+module_init(ite8709_init_module);
-+
-+static void __exit ite8709_cleanup_module(void)
-+{
-+ pnp_unregister_driver(&ite8709_pnp_driver);
-+}
-+module_exit(ite8709_cleanup_module);
-+
-+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");
-diff --git a/drivers/staging/lirc/lirc_parallel.c b/drivers/staging/lirc/lirc_parallel.c
-new file mode 100644
-index 0000000..6da4a8c
---- /dev/null
-+++ b/drivers/staging/lirc/lirc_parallel.c
-@@ -0,0 +1,705 @@
-+/*
-+ * 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 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>
-+
-+#include <linux/io.h>
-+#include <linux/signal.h>
-+#include <linux/irq.h>
-+#include <linux/uaccess.h>
-+#include <asm/div64.h>
-+
-+#include <linux/poll.h>
-+#include <linux/parport.h>
-+
-+#include <media/lirc.h>
-+#include <media/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 RBUF_SIZE (256) /* this must be a power of 2 larger than 1 */
-+
-+static int 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(int 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;
-+}
-+
-+static void irq_handler(void *blah)
-+{
-+ struct timeval tv;
-+ static struct timeval lasttv;
-+ static int init;
-+ long signal;
-+ int data;
-+ unsigned int level, newlevel;
-+ unsigned int timeout;
-+
-+ if (!is_open)
-+ 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 = (int) (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) {
-+ /* ajust value to usecs */
-+ unsigned long long helper;
-+
-+ helper = ((unsigned long long) signal)*1000000;
-+ do_div(helper, timer);
-+ signal = (long) helper;
-+
-+ 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(int))
-+ 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(int))) {
-+ result = -EFAULT;
-+ break;
-+ }
-+ rptr = (rptr + 1) & (RBUF_SIZE - 1);
-+ count += sizeof(int);
-+ } 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;
-+ int counttimer;
-+ int *wbuf;
-+
-+ if (!is_claimed)
-+ return -EBUSY;
-+
-+ count = n / sizeof(int);
-+
-+ if (n % sizeof(int) || count % 2 == 0)
-+ return -EINVAL;
-+
-+ wbuf = memdup_user(buf, n);
-+ if (IS_ERR(wbuf))
-+ return PTR_ERR(wbuf);
-+
-+#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++) {
-+ unsigned long long helper;
-+
-+ helper = ((unsigned long long) wbuf[i])*timer;
-+ do_div(helper, 1000000);
-+ wbuf[i] = (int) helper;
-+ }
-+
-+ 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 long lirc_ioctl(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 (is_open || !lirc_claim())
-+ return -EBUSY;
-+
-+ parport_enable_irq(pport);
-+
-+ /* init read ptr */
-+ rptr = 0;
-+ wptr = 0;
-+ lost_irqs = 0;
-+
-+ 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;
-+ return 0;
-+}
-+
-+static const struct file_operations lirc_fops = {
-+ .owner = THIS_MODULE,
-+ .llseek = lirc_lseek,
-+ .read = lirc_read,
-+ .write = lirc_write,
-+ .poll = lirc_poll,
-+ .unlocked_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,
-+ .set_use_inc = set_use_inc,
-+ .set_use_dec = set_use_dec,
-+ .fops = &lirc_fops,
-+ .dev = NULL,
-+ .owner = THIS_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)
-+{
-+ pport = parport_find_base(io);
-+ 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);
-+ parport_put_port(pport);
-+ 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)");
-diff --git a/drivers/staging/lirc/lirc_parallel.h b/drivers/staging/lirc/lirc_parallel.h
-new file mode 100644
-index 0000000..4bed6af
---- /dev/null
-+++ b/drivers/staging/lirc/lirc_parallel.h
-@@ -0,0 +1,26 @@
-+/* lirc_parallel.h */
-+
-+#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/drivers/staging/lirc/lirc_sasem.c b/drivers/staging/lirc/lirc_sasem.c
-new file mode 100644
-index 0000000..73166c3
---- /dev/null
-+++ b/drivers/staging/lirc/lirc_sasem.c
-@@ -0,0 +1,933 @@
-+/*
-+ * 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/errno.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include <linux/uaccess.h>
-+#include <linux/usb.h>
-+
-+#include <media/lirc.h>
-+#include <media/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 */
-+#define DEVICE_NAME "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 */
-+static int sasem_probe(struct usb_interface *interface,
-+ const struct usb_device_id *id);
-+static void sasem_disconnect(struct usb_interface *interface);
-+static void usb_rx_callback(struct urb *urb);
-+static void usb_tx_callback(struct urb *urb);
-+
-+/* VFD file_operations function prototypes */
-+static int vfd_open(struct inode *inode, struct file *file);
-+static long vfd_ioctl(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 ***/
-+#define SASEM_DATA_BUF_SZ 32
-+
-+struct sasem_context {
-+
-+ struct usb_device *dev;
-+ int vfd_isopen; /* VFD port has been opened */
-+ unsigned int vfd_contrast; /* VFD contrast */
-+ int ir_isopen; /* IR port has been opened */
-+ int dev_present; /* USB device presence */
-+ struct mutex ctx_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[SASEM_DATA_BUF_SZ]; /* 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 const struct file_operations vfd_fops = {
-+ .owner = THIS_MODULE,
-+ .open = &vfd_open,
-+ .write = &vfd_write,
-+ .unlocked_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 = {
-+ .name = MOD_NAME,
-+ .probe = sasem_probe,
-+ .disconnect = sasem_disconnect,
-+ .id_table = sasem_usb_id_table,
-+};
-+
-+static struct usb_class_driver sasem_class = {
-+ .name = DEVICE_NAME,
-+ .fops = &vfd_fops,
-+ .minor_base = VFD_MINOR_BASE,
-+};
-+
-+/* to prevent races between open() and disconnect() */
-+static DEFINE_MUTEX(disconnect_lock);
-+
-+static int debug;
-+
-+
-+/*** 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)
-+{
-+ struct usb_interface *interface;
-+ struct sasem_context *context = NULL;
-+ int subminor;
-+ int retval = 0;
-+
-+ /* prevent races with disconnect */
-+ mutex_lock(&disconnect_lock);
-+
-+ 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);
-+
-+ if (!context) {
-+ err("%s: no context found for minor %d",
-+ __func__, subminor);
-+ retval = -ENODEV;
-+ goto exit;
-+ }
-+
-+ mutex_lock(&context->ctx_lock);
-+
-+ if (context->vfd_isopen) {
-+ err("%s: VFD port is already open", __func__);
-+ retval = -EBUSY;
-+ } else {
-+ context->vfd_isopen = 1;
-+ file->private_data = context;
-+ printk(KERN_INFO "VFD port opened\n");
-+ }
-+
-+ mutex_unlock(&context->ctx_lock);
-+
-+exit:
-+ mutex_unlock(&disconnect_lock);
-+ return retval;
-+}
-+
-+/**
-+ * Called when the VFD device (e.g. /dev/usb/lcd)
-+ * is closed by the application.
-+ */
-+static long vfd_ioctl(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->ctx_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->ctx_lock);
-+ return -ENOIOCTLCMD; /* not supported */
-+ }
-+
-+ mutex_unlock(&context->ctx_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->ctx_lock);
-+
-+ if (!context->vfd_isopen) {
-+ err("%s: VFD is not open", __func__);
-+ retval = -EIO;
-+ } else {
-+ context->vfd_isopen = 0;
-+ 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->ctx_lock);
-+ delete_context(context);
-+ return retval;
-+ }
-+ }
-+
-+ mutex_unlock(&context->ctx_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);
-+ interval = context->tx_endpoint->bInterval;
-+
-+ 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);
-+
-+ 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->ctx_lock);
-+ wait_for_completion(&context->tx.finished);
-+ mutex_lock(&context->ctx_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;
-+ int *data_buf;
-+
-+ context = (struct sasem_context *) file->private_data;
-+ if (!context) {
-+ err("%s: no context for device", __func__);
-+ return -ENODEV;
-+ }
-+
-+ mutex_lock(&context->ctx_lock);
-+
-+ if (!context->dev_present) {
-+ err("%s: no Sasem device present", __func__);
-+ retval = -ENODEV;
-+ goto exit;
-+ }
-+
-+ if (n_bytes <= 0 || n_bytes > SASEM_DATA_BUF_SZ) {
-+ err("%s: invalid payload size", __func__);
-+ retval = -EINVAL;
-+ goto exit;
-+ }
-+
-+ data_buf = memdup_user(buf, n_bytes);
-+ if (PTR_ERR(data_buf))
-+ return PTR_ERR(data_buf);
-+
-+ memcpy(context->tx.data_buf, data_buf, n_bytes);
-+
-+ /* Pad with spaces */
-+ for (i = n_bytes; i < SASEM_DATA_BUF_SZ; ++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->ctx_lock);
-+
-+ return (!retval) ? n_bytes : retval;
-+}
-+
-+/**
-+ * Callback function for USB core API: transmit data
-+ */
-+static void usb_tx_callback(struct urb *urb)
-+{
-+ 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->ctx_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);
-+
-+ retval = usb_submit_urb(context->rx_urb, GFP_KERNEL);
-+
-+ if (retval)
-+ err("%s: usb_submit_urb failed for ir_open (%d)",
-+ __func__, retval);
-+ else {
-+ context->ir_isopen = 1;
-+ printk(KERN_INFO "IR port opened\n");
-+ }
-+
-+exit:
-+ mutex_unlock(&context->ctx_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->ctx_lock);
-+
-+ usb_kill_urb(context->rx_urb);
-+ context->ir_isopen = 0;
-+ 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->ctx_lock);
-+ delete_context(context);
-+ return;
-+ }
-+ /* If VFD port is open, context will be deleted by vfd_close */
-+ }
-+
-+ mutex_unlock(&context->ctx_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
-+ */
-+static void usb_rx_callback(struct urb *urb)
-+{
-+ 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",
-+ __func__, urb->status);
-+ break;
-+ }
-+
-+ usb_submit_urb(context->rx_urb, GFP_ATOMIC);
-+ return;
-+}
-+
-+
-+
-+/**
-+ * Callback function for USB core API: Probe
-+ */
-+static int sasem_probe(struct usb_interface *interface,
-+ const struct usb_device_id *id)
-+{
-+ struct usb_device *dev = 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;
-+ 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__);
-+
-+
-+ dev = usb_get_dev(interface_to_usbdev(interface));
-+ iface_desc = interface->cur_altsetting;
-+ num_endpoints = iface_desc->desc.bNumEndpoints;
-+
-+ /*
-+ * 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;
-+ 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;
-+ 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;
-+ }
-+ 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;
-+ }
-+ if (vfd_ep_found) {
-+ tx_urb = usb_alloc_urb(0, GFP_KERNEL);
-+ if (!tx_urb) {
-+ err("%s: usb_alloc_urb failed for VFD urb",
-+ __func__);
-+ alloc_status = 6;
-+ goto alloc_status_switch;
-+ }
-+ }
-+
-+ mutex_init(&context->ctx_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;
-+ driver->dev = &interface->dev;
-+ driver->owner = THIS_MODULE;
-+
-+ mutex_lock(&context->ctx_lock);
-+
-+ lirc_minor = lirc_register_driver(driver);
-+ if (lirc_minor < 0) {
-+ err("%s: lirc_register_driver failed", __func__);
-+ alloc_status = 7;
-+ mutex_unlock(&context->ctx_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;
-+
-+ usb_set_intfdata(interface, context);
-+
-+ if (vfd_ep_found) {
-+
-+ 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__);
-+ }
-+
-+ printk(KERN_INFO "%s: Sasem device on usb<%d:%d> initialized\n",
-+ __func__, dev->bus->busnum, dev->devnum);
-+
-+ mutex_unlock(&context->ctx_lock);
-+exit:
-+ return retval;
-+}
-+
-+/**
-+ * Callback function for USB core API: disonnect
-+ */
-+static void sasem_disconnect(struct usb_interface *interface)
-+{
-+ struct sasem_context *context;
-+
-+ /* prevent races with ir_open()/vfd_open() */
-+ mutex_lock(&disconnect_lock);
-+
-+ context = usb_get_intfdata(interface);
-+ mutex_lock(&context->ctx_lock);
-+
-+ printk(KERN_INFO "%s: Sasem device disconnected\n", __func__);
-+
-+ usb_set_intfdata(interface, NULL);
-+ 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);
-+
-+ usb_deregister_dev(interface, &sasem_class);
-+
-+ mutex_unlock(&context->ctx_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);
-diff --git a/drivers/staging/lirc/lirc_serial.c b/drivers/staging/lirc/lirc_serial.c
-new file mode 100644
-index 0000000..9456f8e
---- /dev/null
-+++ b/drivers/staging/lirc/lirc_serial.c
-@@ -0,0 +1,1313 @@
-+/*
-+ * 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
-+ */
-+
-+#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/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 <linux/platform_device.h>
-+
-+#include <asm/system.h>
-+#include <linux/io.h>
-+#include <linux/irq.h>
-+#include <linux/fcntl.h>
-+#include <linux/spinlock.h>
-+
-+#ifdef CONFIG_LIRC_SERIAL_NSLU2
-+#include <asm/hardware.h>
-+#endif
-+/* 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 */
-+
-+#include <media/lirc.h>
-+#include <media/lirc_dev.h>
-+
-+#define LIRC_DRIVER_NAME "lirc_serial"
-+
-+struct lirc_serial {
-+ int signal_pin;
-+ int signal_pin_change;
-+ u8 on;
-+ u8 off;
-+ long (*send_pulse)(unsigned long length);
-+ void (*send_space)(long length);
-+ int features;
-+ spinlock_t lock;
-+};
-+
-+#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
-+
-+/*** module parameters ***/
-+static int type;
-+static int io;
-+static int irq;
-+static int iommap;
-+static int ioshift;
-+static int softcarrier = 1;
-+static int share_irq;
-+static int debug;
-+static int sense = -1; /* -1 = auto, 0 = active high, 1 = active low */
-+static int txsense; /* 0 = active high, 1 = active low */
-+
-+#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 CONFIG_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 CONFIG_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
-+ },
-+
-+#ifdef CONFIG_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 CONFIG_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
-+
-+static struct timeval lasttv = {0, 0};
-+
-+static struct lirc_buffer rbuf;
-+
-+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__ */
-+/*
-+ * FIXME: should we be using hrtimers instead of this
-+ * LIRC_SERIAL_TRANSMITTER_LATENCY nonsense?
-+ */
-+
-+/* fetch serial input packet (1 byte) from register offset */
-+static u8 sinp(int offset)
-+{
-+ if (iommap != 0)
-+ /* the register is memory-mapped */
-+ offset <<= ioshift;
-+
-+ return inb(io + offset);
-+}
-+
-+/* write serial output packet (1 byte) of value to register offset */
-+static void soutp(int offset, u8 value)
-+{
-+ if (iommap != 0)
-+ /* the register is memory-mapped */
-+ offset <<= ioshift;
-+
-+ outb(value, io + offset);
-+}
-+
-+static void on(void)
-+{
-+#ifdef CONFIG_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, IXP4XX_GPIO_LOW);
-+ return;
-+ }
-+#endif
-+ if (txsense)
-+ soutp(UART_MCR, hardware[type].off);
-+ else
-+ soutp(UART_MCR, hardware[type].on);
-+}
-+
-+static void off(void)
-+{
-+#ifdef CONFIG_LIRC_SERIAL_NSLU2
-+ if (type == LIRC_NSLU2) {
-+ gpio_line_set(NSLU2_LED_GRN, 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;
-+ /*
-+ * FIXME: This looks like a hard busy wait, without even an occasional,
-+ * polite, cpu_relax() call. There's got to be a better way?
-+ *
-+ * The i2c code has the result of a lot of bit-banging work, I wonder if
-+ * there's something there which could be helpful here.
-+ */
-+ 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(int 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(int l)
-+{
-+ /* simple noise filter */
-+ static int pulse, space;
-+ 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);
-+}
-+
-+static irqreturn_t irq_handler(int i, void *blah)
-+{
-+ struct timeval tv;
-+ int counter, dcd;
-+ u8 status;
-+ long deltv;
-+ int data;
-+ static int last_dcd = -1;
-+
-+ if ((sinp(UART_IIR) & UART_IIR_NO_INT)) {
-+ /* not our interrupt */
-+ return 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 = (int) (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_HANDLED;
-+}
-+
-+
-+static int hardware_init_port(void)
-+{
-+ u8 scratch, scratch2, scratch3;
-+
-+ /*
-+ * This is a simple port existence test, borrowed from the autoconfig
-+ * function in drivers/serial/8250.c
-+ */
-+ scratch = sinp(UART_IER);
-+ soutp(UART_IER, 0);
-+#ifdef __i386__
-+ outb(0xff, 0x080);
-+#endif
-+ scratch2 = sinp(UART_IER) & 0x0f;
-+ soutp(UART_IER, 0x0f);
-+#ifdef __i386__
-+ outb(0x00, 0x080);
-+#endif
-+ scratch3 = sinp(UART_IER) & 0x0f;
-+ soutp(UART_IER, scratch);
-+ if (scratch2 != 0 || scratch3 != 0x0f) {
-+ /* we fail, there's nothing here */
-+ printk(KERN_ERR LIRC_DRIVER_NAME ": port existence test "
-+ "failed, cannot continue\n");
-+ return -EINVAL;
-+ }
-+
-+
-+
-+ /* 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);
-+
-+#ifdef CONFIG_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;
-+ }
-+
-+ return 0;
-+}
-+
-+static int init_port(void)
-+{
-+ int i, nlow, nhigh;
-+
-+ /* Reserve io region. */
-+ /*
-+ * 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))) {
-+ 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;
-+ }
-+
-+ if (hardware_init_port() < 0)
-+ return -EINVAL;
-+
-+ /* 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 */
-+ msleep(500);
-+
-+ /*
-+ * 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++;
-+ msleep(40);
-+ }
-+ 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;
-+
-+ /* 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);
-+ return -EBUSY;
-+ case -EINVAL:
-+ printk(KERN_ERR LIRC_DRIVER_NAME
-+ ": Bad irq number or handler\n");
-+ return -EINVAL;
-+ default:
-+ dprintk("Interrupt %d, port %04x obtained\n", irq, io);
-+ break;
-+ };
-+
-+ spin_lock_irqsave(&hardware[type].lock, flags);
-+
-+ /* Set DLAB 0. */
-+ soutp(UART_LCR, sinp(UART_LCR) & (~UART_LCR_DLAB));
-+
-+ soutp(UART_IER, sinp(UART_IER)|UART_IER_MSI);
-+
-+ spin_unlock_irqrestore(&hardware[type].lock, flags);
-+
-+ return 0;
-+}
-+
-+static void set_use_dec(void *data)
-+{ unsigned long flags;
-+
-+ spin_lock_irqsave(&hardware[type].lock, 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)));
-+ spin_unlock_irqrestore(&hardware[type].lock, flags);
-+
-+ free_irq(irq, (void *)&hardware);
-+
-+ dprintk("freed IRQ %d\n", irq);
-+}
-+
-+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;
-+ int *wbuf;
-+
-+ if (!(hardware[type].features & LIRC_CAN_SEND_PULSE))
-+ return -EBADF;
-+
-+ count = n / sizeof(int);
-+ if (n % sizeof(int) || count % 2 == 0)
-+ return -EINVAL;
-+ wbuf = memdup_user(buf, n);
-+ if (PTR_ERR(wbuf))
-+ return PTR_ERR(wbuf);
-+ spin_lock_irqsave(&hardware[type].lock, 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();
-+ spin_unlock_irqrestore(&hardware[type].lock, flags);
-+ return n;
-+}
-+
-+static long lirc_ioctl(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 lirc_dev_fop_ioctl(filep, cmd, arg);
-+ }
-+ return 0;
-+}
-+
-+static const struct file_operations lirc_fops = {
-+ .owner = THIS_MODULE,
-+ .write = lirc_write,
-+ .unlocked_ioctl = lirc_ioctl,
-+ .read = lirc_dev_fop_read,
-+ .poll = lirc_dev_fop_poll,
-+ .open = lirc_dev_fop_open,
-+ .release = lirc_dev_fop_close,
-+};
-+
-+static struct lirc_driver driver = {
-+ .name = LIRC_DRIVER_NAME,
-+ .minor = -1,
-+ .code_length = 1,
-+ .sample_rate = 0,
-+ .data = NULL,
-+ .add_to_buf = NULL,
-+ .rbuf = &rbuf,
-+ .set_use_inc = set_use_inc,
-+ .set_use_dec = set_use_dec,
-+ .fops = &lirc_fops,
-+ .dev = NULL,
-+ .owner = THIS_MODULE,
-+};
-+
-+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;
-+}
-+
-+/* twisty maze... need a forward-declaration here... */
-+static void lirc_serial_exit(void);
-+
-+static int lirc_serial_resume(struct platform_device *dev)
-+{
-+ unsigned long flags;
-+
-+ if (hardware_init_port() < 0) {
-+ lirc_serial_exit();
-+ return -EINVAL;
-+ }
-+
-+ spin_lock_irqsave(&hardware[type].lock, flags);
-+ /* Enable Interrupt */
-+ do_gettimeofday(&lasttv);
-+ soutp(UART_IER, sinp(UART_IER)|UART_IER_MSI);
-+ off();
-+
-+ lirc_buffer_clear(&rbuf);
-+
-+ spin_unlock_irqrestore(&hardware[type].lock, 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;
-+
-+ /* Init read buffer. */
-+ result = lirc_buffer_init(&rbuf, sizeof(int), RBUF_LEN);
-+ if (result < 0)
-+ return -ENOMEM;
-+
-+ result = platform_driver_register(&lirc_serial_driver);
-+ if (result) {
-+ printk("lirc register returned %d\n", result);
-+ goto exit_buffer_free;
-+ }
-+
-+ 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);
-+exit_buffer_free:
-+ lirc_buffer_free(&rbuf);
-+ return result;
-+}
-+
-+static void lirc_serial_exit(void)
-+{
-+ platform_device_unregister(lirc_serial_dev);
-+ platform_driver_unregister(&lirc_serial_driver);
-+ lirc_buffer_free(&rbuf);
-+}
-+
-+static int __init lirc_serial_init_module(void)
-+{
-+ int result;
-+
-+ result = lirc_serial_init();
-+ if (result)
-+ return result;
-+
-+ switch (type) {
-+ case LIRC_HOMEBREW:
-+ case LIRC_IRDEO:
-+ case LIRC_IRDEO_REMOTE:
-+ case LIRC_ANIMAX:
-+ case LIRC_IGOR:
-+ /* if nothing specified, use ttyS0/com1 and irq 4 */
-+ io = io ? io : 0x3f8;
-+ irq = irq ? irq : 4;
-+ break;
-+#ifdef CONFIG_LIRC_SERIAL_NSLU2
-+ case LIRC_NSLU2:
-+ io = io ? io : IRQ_IXP4XX_UART2;
-+ irq = irq ? irq : (IXP4XX_UART2_BASE_VIRT + REG_OFFSET);
-+ iommap = iommap ? iommap : IXP4XX_UART2_BASE_PHYS;
-+ ioshift = ioshift ? ioshift : 2;
-+ break;
-+#endif
-+ default:
-+ result = -EINVAL;
-+ goto exit_serial_exit;
-+ }
-+ if (!softcarrier) {
-+ switch (type) {
-+ case LIRC_HOMEBREW:
-+ case LIRC_IGOR:
-+#ifdef CONFIG_LIRC_SERIAL_NSLU2
-+ case LIRC_NSLU2:
-+#endif
-+ 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.dev = &lirc_serial_dev->dev;
-+ 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;
-+ }
-+ return 0;
-+exit_release:
-+ release_region(io, 8);
-+exit_serial_exit:
-+ lirc_serial_exit();
-+ return result;
-+}
-+
-+static void __exit lirc_serial_exit_module(void)
-+{
-+ lirc_serial_exit();
-+ if (iommap != 0)
-+ release_mem_region(iommap, 8 << ioshift);
-+ else
-+ release_region(io, 8);
-+ 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);
-+MODULE_PARM_DESC(type, "Hardware type (0 = home-brew, 1 = IRdeo,"
-+ " 2 = IRdeo Remote, 3 = AnimaX, 4 = IgorPlug,"
-+ " 5 = NSLU2 RX:CTS2/TX:GreenLED)");
-+
-+module_param(io, int, S_IRUGO);
-+MODULE_PARM_DESC(io, "I/O address base (0x3f8 or 0x2f8)");
-+
-+/* 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)");
-+
-+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 CONFIG_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, default on)");
-+
-+module_param(debug, bool, S_IRUGO | S_IWUSR);
-+MODULE_PARM_DESC(debug, "Enable debugging messages");
-diff --git a/drivers/staging/lirc/lirc_sir.c b/drivers/staging/lirc/lirc_sir.c
-new file mode 100644
-index 0000000..eb08fa7
---- /dev/null
-+++ b/drivers/staging/lirc/lirc_sir.c
-@@ -0,0 +1,1282 @@
-+/*
-+ * 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/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>
-+#include <linux/io.h>
-+#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 <media/lirc.h>
-+#include <media/lirc_dev.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 int rx_buf[RBUF_LEN];
-+static unsigned int rx_tail, rx_head;
-+
-+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 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 long lirc_ioctl(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 */
-+static irqreturn_t sir_interrupt(int irq, void *dev_id);
-+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 inline unsigned int sinp(int offset)
-+{
-+ return inb(io + offset);
-+}
-+
-+static inline 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 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(int))
-+ 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(int))) {
-+ retval = -EFAULT;
-+ break;
-+ }
-+ rx_head = (rx_head + 1) & (RBUF_LEN - 1);
-+ n += sizeof(int);
-+ } 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, count;
-+ int *tx_buf;
-+
-+ count = n / sizeof(int);
-+ if (n % sizeof(int) || count % 2 == 0)
-+ return -EINVAL;
-+ tx_buf = memdup_user(buf, n);
-+ if (IS_ERR(tx_buf))
-+ return PTR_ERR(tx_buf);
-+ i = 0;
-+#ifdef LIRC_ON_SA1100
-+ /* disable receiver */
-+ Ser2UTCR3 = 0;
-+#endif
-+ local_irq_save(flags);
-+ while (1) {
-+ if (i >= count)
-+ break;
-+ if (tx_buf[i])
-+ send_pulse(tx_buf[i]);
-+ i++;
-+ if (i >= count)
-+ 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 count;
-+}
-+
-+static long lirc_ioctl(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 retval;
-+ 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;
-+ int 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 const struct file_operations lirc_fops = {
-+ .owner = THIS_MODULE,
-+ .read = lirc_read,
-+ .write = lirc_write,
-+ .poll = lirc_poll,
-+ .unlocked_ioctl = lirc_ioctl,
-+ .open = lirc_dev_fop_open,
-+ .release = lirc_dev_fop_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,
-+ .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 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);
-+}
-+
-+static irqreturn_t sir_interrupt(int irq, void *dev_id)
-+{
-+ 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 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;
-+}
-+
-+
-+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");
-diff --git a/drivers/staging/lirc/lirc_streamzap.c b/drivers/staging/lirc/lirc_streamzap.c
-new file mode 100644
-index 0000000..be09c10
---- /dev/null
-+++ b/drivers/staging/lirc/lirc_streamzap.c
-@@ -0,0 +1,821 @@
-+/*
-+ * 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/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>
-+#include <linux/uaccess.h>
-+#include <linux/usb.h>
-+
-+#include <media/lirc.h>
-+#include <media/lirc_dev.h>
-+
-+#define DRIVER_VERSION "1.28"
-+#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_TIMEOUT 0xff
-+#define STREAMZAP_RESOLUTION 256
-+
-+/* number of samples buffered */
-+#define STREAMZAP_BUF_LEN 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;
-+
-+ /* 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;
-+ int timeout_enabled;
-+};
-+
-+
-+/* local function prototypes */
-+static int streamzap_probe(struct usb_interface *interface,
-+ const struct usb_device_id *id);
-+static void streamzap_disconnect(struct usb_interface *interface);
-+static void usb_streamzap_irq(struct urb *urb);
-+static int streamzap_use_inc(void *data);
-+static void streamzap_use_dec(void *data);
-+static long streamzap_ioctl(struct file *filep, unsigned int cmd,
-+ unsigned long arg);
-+static int streamzap_suspend(struct usb_interface *intf, pm_message_t message);
-+static int streamzap_resume(struct usb_interface *intf);
-+
-+/* usb specific object needed to register this driver with the usb subsystem */
-+
-+static struct usb_driver streamzap_driver = {
-+ .name = DRIVER_NAME,
-+ .probe = streamzap_probe,
-+ .disconnect = streamzap_disconnect,
-+ .suspend = streamzap_suspend,
-+ .resume = streamzap_resume,
-+ .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;
-+ int data;
-+
-+ spin_lock_irqsave(&sz->timer_lock, flags);
-+
-+ if (!lirc_buffer_empty(sz->delay_buf) &&
-+ !lirc_buffer_full(sz->driver->rbuf)) {
-+ lirc_buffer_read(sz->delay_buf, (unsigned char *) &data);
-+ lirc_buffer_write(sz->driver->rbuf, (unsigned char *) &data);
-+ }
-+ if (!lirc_buffer_empty(sz->delay_buf)) {
-+ while (lirc_buffer_available(sz->delay_buf) <
-+ STREAMZAP_BUF_LEN / 2 &&
-+ !lirc_buffer_full(sz->driver->rbuf)) {
-+ lirc_buffer_read(sz->delay_buf,
-+ (unsigned char *) &data);
-+ lirc_buffer_write(sz->driver->rbuf,
-+ (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->driver->rbuf))
-+ wake_up(&sz->driver->rbuf->wait_poll);
-+
-+ spin_unlock_irqrestore(&sz->timer_lock, flags);
-+}
-+
-+static void flush_delay_buffer(struct usb_streamzap *sz)
-+{
-+ int 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->driver->rbuf)) {
-+ lirc_buffer_write(sz->driver->rbuf,
-+ (unsigned char *) &data);
-+ } else {
-+ dprintk("buffer overflow", sz->driver->minor);
-+ }
-+ }
-+ if (!empty)
-+ wake_up(&sz->driver->rbuf->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)) {
-+ int read_data;
-+
-+ lirc_buffer_read(sz->delay_buf,
-+ (unsigned char *) &read_data);
-+ if (!lirc_buffer_full(sz->driver->rbuf)) {
-+ lirc_buffer_write(sz->driver->rbuf,
-+ (unsigned char *) &read_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)
-+{
-+ int pulse;
-+
-+ if (sz->idle) {
-+ long deltv;
-+ int 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) {
-+ /* really long time */
-+ tmp = LIRC_SPACE(LIRC_VALUE_MASK);
-+ } else {
-+ tmp = (int) (deltv*1000000+
-+ sz->signal_start.tv_usec -
-+ sz->signal_last.tv_usec);
-+ tmp -= sz->sum;
-+ tmp = LIRC_SPACE(tmp);
-+ }
-+ dprintk("ls %u", sz->driver->minor, tmp);
-+ push(sz, (char *)&tmp);
-+
-+ sz->idle = 0;
-+ sz->sum = 0;
-+ }
-+
-+ pulse = ((int) value) * STREAMZAP_RESOLUTION;
-+ pulse += STREAMZAP_RESOLUTION / 2;
-+ sz->sum += pulse;
-+ pulse = LIRC_PULSE(pulse);
-+
-+ 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)
-+{
-+ int space;
-+
-+ space = ((int) value)*STREAMZAP_RESOLUTION;
-+ space += STREAMZAP_RESOLUTION/2;
-+ sz->sum += space;
-+ space = LIRC_SPACE(space);
-+ dprintk("s %u", sz->driver->minor, space);
-+ push(sz, (char *)&space);
-+}
-+
-+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.
-+ */
-+static void usb_streamzap_irq(struct urb *urb)
-+{
-+ 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] == STREAMZAP_TIMEOUT) {
-+ sz->idle = 1;
-+ stop_timer(sz);
-+ if (sz->timeout_enabled) {
-+ int timeout =
-+ LIRC_TIMEOUT
-+ (STREAMZAP_TIMEOUT *
-+ STREAMZAP_RESOLUTION);
-+ push(sz, (char *)&timeout);
-+ }
-+ 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;
-+ }
-+ }
-+ }
-+
-+ usb_submit_urb(urb, GFP_ATOMIC);
-+
-+ return;
-+}
-+
-+static const struct file_operations streamzap_fops = {
-+ .owner = THIS_MODULE,
-+ .unlocked_ioctl = streamzap_ioctl,
-+ .read = lirc_dev_fop_read,
-+ .write = lirc_dev_fop_write,
-+ .poll = lirc_dev_fop_poll,
-+ .open = lirc_dev_fop_open,
-+ .release = lirc_dev_fop_close,
-+};
-+
-+
-+/**
-+ * 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
-+ */
-+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;
-+ struct usb_streamzap *sz;
-+ struct lirc_driver *driver;
-+ struct lirc_buffer *lirc_buf;
-+ struct lirc_buffer *delay_buf;
-+ char buf[63], name[128] = "";
-+ int retval = -ENOMEM;
-+ int minor = 0;
-+
-+ /* Allocate space for device driver specific data */
-+ sz = kzalloc(sizeof(struct usb_streamzap), GFP_KERNEL);
-+ if (sz == NULL)
-+ return -ENOMEM;
-+
-+ sz->udev = udev;
-+ sz->interface = interface;
-+
-+ /* Check to ensure endpoint information matches requirements */
-+ iface_host = interface->cur_altsetting;
-+
-+ if (iface_host->desc.bNumEndpoints != 1) {
-+ err("%s: Unexpected desc.bNumEndpoints (%d)", __func__,
-+ iface_host->desc.bNumEndpoints);
-+ retval = -ENODEV;
-+ goto free_sz;
-+ }
-+
-+ sz->endpoint = &(iface_host->endpoint[0].desc);
-+ 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 free_sz;
-+ }
-+
-+ 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 free_sz;
-+ }
-+
-+ if (sz->endpoint->wMaxPacketSize == 0) {
-+ err("%s: endpoint message size==0? ", __func__);
-+ retval = -ENODEV;
-+ goto free_sz;
-+ }
-+
-+ /* Allocate the USB buffer and IRQ URB */
-+
-+ sz->buf_in_len = sz->endpoint->wMaxPacketSize;
-+ sz->buf_in = usb_alloc_coherent(sz->udev, sz->buf_in_len,
-+ GFP_ATOMIC, &sz->dma_in);
-+ if (sz->buf_in == NULL)
-+ goto free_sz;
-+
-+ sz->urb_in = usb_alloc_urb(0, GFP_KERNEL);
-+ if (sz->urb_in == NULL)
-+ goto free_sz;
-+
-+ /* Connect this device to the LIRC sub-system */
-+ driver = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
-+ if (!driver)
-+ goto free_sz;
-+
-+ lirc_buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
-+ if (!lirc_buf)
-+ goto free_driver;
-+ if (lirc_buffer_init(lirc_buf, sizeof(int), STREAMZAP_BUF_LEN))
-+ goto kfree_lirc_buf;
-+
-+ delay_buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
-+ if (!delay_buf)
-+ goto free_lirc_buf;
-+ if (lirc_buffer_init(delay_buf, sizeof(int), STREAMZAP_BUF_LEN))
-+ goto kfree_delay_buf;
-+
-+ sz->driver = driver;
-+ strcpy(sz->driver->name, DRIVER_NAME);
-+ sz->driver->minor = -1;
-+ sz->driver->sample_rate = 0;
-+ sz->driver->code_length = sizeof(int) * 8;
-+ sz->driver->features = LIRC_CAN_REC_MODE2 |
-+ LIRC_CAN_GET_REC_RESOLUTION |
-+ LIRC_CAN_SET_REC_TIMEOUT;
-+ sz->driver->data = sz;
-+ sz->driver->min_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION;
-+ sz->driver->max_timeout = STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION;
-+ sz->driver->rbuf = lirc_buf;
-+ sz->delay_buf = delay_buf;
-+ sz->driver->set_use_inc = &streamzap_use_inc;
-+ sz->driver->set_use_dec = &streamzap_use_dec;
-+ sz->driver->fops = &streamzap_fops;
-+ sz->driver->dev = &interface->dev;
-+ 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);
-+ sz->urb_in->transfer_dma = sz->dma_in;
-+ sz->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-+
-+ 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);
-+
-+ minor = lirc_register_driver(driver);
-+
-+ if (minor < 0)
-+ goto free_delay_buf;
-+
-+ sz->driver->minor = minor;
-+
-+ usb_set_intfdata(interface, sz);
-+
-+ printk(KERN_INFO DRIVER_NAME "[%d]: %s on usb%d:%d attached\n",
-+ sz->driver->minor, name,
-+ udev->bus->busnum, sz->udev->devnum);
-+
-+ return 0;
-+
-+free_delay_buf:
-+ lirc_buffer_free(sz->delay_buf);
-+kfree_delay_buf:
-+ kfree(delay_buf);
-+free_lirc_buf:
-+ lirc_buffer_free(sz->driver->rbuf);
-+kfree_lirc_buf:
-+ kfree(lirc_buf);
-+free_driver:
-+ kfree(driver);
-+free_sz:
-+ if (retval == -ENOMEM)
-+ err("Out of memory");
-+
-+ if (sz) {
-+ usb_free_urb(sz->urb_in);
-+ usb_free_coherent(udev, sz->buf_in_len, sz->buf_in, sz->dma_in);
-+ kfree(sz);
-+ }
-+
-+ return retval;
-+}
-+
-+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);
-+
-+ lirc_buffer_clear(sz->driver->rbuf);
-+ 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;
-+ if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) {
-+ dprintk("open result = -EIO error submitting urb",
-+ sz->driver->minor);
-+ 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);
-+
-+ sz->in_use--;
-+}
-+
-+static long streamzap_ioctl(struct file *filep, unsigned int cmd,
-+ unsigned long arg)
-+{
-+ int result = 0;
-+ int val;
-+ struct usb_streamzap *sz = lirc_get_pdata(filep);
-+
-+ switch (cmd) {
-+ case LIRC_GET_REC_RESOLUTION:
-+ result = put_user(STREAMZAP_RESOLUTION, (unsigned int *) arg);
-+ break;
-+ case LIRC_SET_REC_TIMEOUT:
-+ result = get_user(val, (int *)arg);
-+ if (result == 0) {
-+ if (val == STREAMZAP_TIMEOUT * STREAMZAP_RESOLUTION)
-+ sz->timeout_enabled = 1;
-+ else if (val == 0)
-+ sz->timeout_enabled = 0;
-+ else
-+ result = -EINVAL;
-+ }
-+ break;
-+ default:
-+ return lirc_dev_fop_ioctl(filep, cmd, arg);
-+ }
-+ return result;
-+}
-+
-+/**
-+ * 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.
-+ */
-+static void streamzap_disconnect(struct usb_interface *interface)
-+{
-+ struct usb_streamzap *sz;
-+ int errnum;
-+ int minor;
-+
-+ sz = usb_get_intfdata(interface);
-+
-+ /* 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->driver->rbuf);
-+
-+ /* unregister from the USB sub-system */
-+
-+ usb_free_urb(sz->urb_in);
-+
-+ usb_free_coherent(sz->udev, sz->buf_in_len, sz->buf_in, sz->dma_in);
-+
-+ minor = sz->driver->minor;
-+ kfree(sz->driver->rbuf);
-+ kfree(sz->driver);
-+ kfree(sz->delay_buf);
-+ kfree(sz);
-+
-+ printk(KERN_INFO DRIVER_NAME "[%d]: disconnected\n", minor);
-+}
-+
-+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->driver->rbuf);
-+ 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;
-+ if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) {
-+ dprintk("open result = -EIO error submitting urb",
-+ sz->driver->minor);
-+ return -EIO;
-+ }
-+ }
-+ return 0;
-+}
-+
-+/**
-+ * 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");
-diff --git a/drivers/staging/lirc/lirc_ttusbir.c b/drivers/staging/lirc/lirc_ttusbir.c
-new file mode 100644
-index 0000000..e345ab9
---- /dev/null
-+++ b/drivers/staging/lirc/lirc_ttusbir.c
-@@ -0,0 +1,396 @@
-+/*
-+ * 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 <media/lirc.h>
-+#include <media/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);
-+static void urb_complete(struct urb *urb);
-+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
-+};
-+
-+static void urb_complete(struct urb *urb)
-+{
-+ struct ttusbir_device *ttusbir;
-+ unsigned char *buf;
-+ int i;
-+ int 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(int), 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;
-+ ttusbir->driver.rbuf = &ttusbir->rbuf;
-+ ttusbir->driver.set_use_inc = set_use_inc;
-+ ttusbir->driver.set_use_dec = set_use_dec;
-+ 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/drivers/staging/lirc/lirc_zilog.c b/drivers/staging/lirc/lirc_zilog.c
-new file mode 100644
-index 0000000..100caab
---- /dev/null
-+++ b/drivers/staging/lirc/lirc_zilog.c
-@@ -0,0 +1,1387 @@
-+/*
-+ * i2c IR lirc driver for devices with zilog IR processors
-+ *
-+ * 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 PVR-150 IR TX device by
-+ * Mark Weaver <mark@npsl.co.uk>
-+ * changed name from lirc_pvr150 to lirc_zilog, works on more than pvr-150
-+ * Jarod Wilson <jarod@redhat.com>
-+ *
-+ * parts are cut&pasted from the lirc_i2c.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
-+ *
-+ */
-+
-+
-+#include <linux/version.h>
-+#include <linux/module.h>
-+#include <linux/kmod.h>
-+#include <linux/kernel.h>
-+#include <linux/sched.h>
-+#include <linux/fs.h>
-+#include <linux/poll.h>
-+#include <linux/string.h>
-+#include <linux/timer.h>
-+#include <linux/delay.h>
-+#include <linux/completion.h>
-+#include <linux/errno.h>
-+#include <linux/slab.h>
-+#include <linux/i2c.h>
-+#include <linux/firmware.h>
-+#include <linux/vmalloc.h>
-+
-+#include <linux/mutex.h>
-+#include <linux/kthread.h>
-+
-+#include <media/lirc_dev.h>
-+#include <media/lirc.h>
-+
-+struct IR {
-+ struct lirc_driver l;
-+
-+ /* Device info */
-+ struct mutex ir_lock;
-+ int open;
-+
-+ /* RX device */
-+ struct i2c_client c_rx;
-+ int have_rx;
-+
-+ /* RX device buffer & lock */
-+ struct lirc_buffer buf;
-+ struct mutex buf_lock;
-+
-+ /* RX polling thread data */
-+ struct completion *t_notify;
-+ struct completion *t_notify2;
-+ int shutdown;
-+ struct task_struct *task;
-+
-+ /* RX read data */
-+ unsigned char b[3];
-+
-+ /* TX device */
-+ struct i2c_client c_tx;
-+ int need_boot;
-+ int have_tx;
-+};
-+
-+/* Minor -> data mapping */
-+static struct IR *ir_devices[MAX_IRCTL_DEVICES];
-+
-+/* Block size for IR transmitter */
-+#define TX_BLOCK_SIZE 99
-+
-+/* Hauppauge IR transmitter data */
-+struct tx_data_struct {
-+ /* Boot block */
-+ unsigned char *boot_data;
-+
-+ /* Start of binary data block */
-+ unsigned char *datap;
-+
-+ /* End of binary data block */
-+ unsigned char *endp;
-+
-+ /* Number of installed codesets */
-+ unsigned int num_code_sets;
-+
-+ /* Pointers to codesets */
-+ unsigned char **code_sets;
-+
-+ /* Global fixed data template */
-+ int fixed[TX_BLOCK_SIZE];
-+};
-+
-+static struct tx_data_struct *tx_data;
-+static struct mutex tx_data_lock;
-+
-+#define zilog_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, \
-+ ## args)
-+#define zilog_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args)
-+
-+#define ZILOG_HAUPPAUGE_IR_RX_NAME "Zilog/Hauppauge IR RX"
-+#define ZILOG_HAUPPAUGE_IR_TX_NAME "Zilog/Hauppauge IR TX"
-+
-+/* module parameters */
-+static int debug; /* debug output */
-+static int disable_rx; /* disable RX device */
-+static int disable_tx; /* disable TX device */
-+static int minor = -1; /* minor number */
-+
-+#define dprintk(fmt, args...) \
-+ do { \
-+ if (debug) \
-+ printk(KERN_DEBUG KBUILD_MODNAME ": " fmt, \
-+ ## args); \
-+ } while (0)
-+
-+static int add_to_buf(struct IR *ir)
-+{
-+ __u16 code;
-+ unsigned char codes[2];
-+ unsigned char keybuf[6];
-+ int got_data = 0;
-+ int ret;
-+ int failures = 0;
-+ unsigned char sendbuf[1] = { 0 };
-+
-+ if (lirc_buffer_full(&ir->buf)) {
-+ dprintk("buffer overflow\n");
-+ return -EOVERFLOW;
-+ }
-+
-+ /*
-+ * service the device as long as it is returning
-+ * data and we have space
-+ */
-+ do {
-+ /*
-+ * Lock i2c bus for the duration. RX/TX chips interfere so
-+ * this is worth it
-+ */
-+ mutex_lock(&ir->ir_lock);
-+
-+ /*
-+ * Send random "poll command" (?) Windows driver does this
-+ * and it is a good point to detect chip failure.
-+ */
-+ ret = i2c_master_send(&ir->c_rx, sendbuf, 1);
-+ if (ret != 1) {
-+ zilog_error("i2c_master_send failed with %d\n", ret);
-+ if (failures >= 3) {
-+ mutex_unlock(&ir->ir_lock);
-+ zilog_error("unable to read from the IR chip "
-+ "after 3 resets, giving up\n");
-+ return ret;
-+ }
-+
-+ /* Looks like the chip crashed, reset it */
-+ zilog_error("polling the IR receiver chip failed, "
-+ "trying reset\n");
-+
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout((100 * HZ + 999) / 1000);
-+ ir->need_boot = 1;
-+
-+ ++failures;
-+ mutex_unlock(&ir->ir_lock);
-+ continue;
-+ }
-+
-+ ret = i2c_master_recv(&ir->c_rx, keybuf, sizeof(keybuf));
-+ mutex_unlock(&ir->ir_lock);
-+ if (ret != sizeof(keybuf)) {
-+ zilog_error("i2c_master_recv failed with %d -- "
-+ "keeping last read buffer\n", ret);
-+ } else {
-+ ir->b[0] = keybuf[3];
-+ ir->b[1] = keybuf[4];
-+ ir->b[2] = keybuf[5];
-+ dprintk("key (0x%02x/0x%02x)\n", ir->b[0], ir->b[1]);
-+ }
-+
-+ /* key pressed ? */
-+#ifdef I2C_HW_B_HDPVR
-+ if (ir->c_rx.adapter->id == I2C_HW_B_HDPVR) {
-+ if (got_data && (keybuf[0] == 0x80))
-+ return 0;
-+ else if (got_data && (keybuf[0] == 0x00))
-+ return -ENODATA;
-+ } else if ((ir->b[0] & 0x80) == 0)
-+#else
-+ if ((ir->b[0] & 0x80) == 0)
-+#endif
-+ return got_data ? 0 : -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 */
-+ lirc_buffer_write(&ir->buf, codes);
-+ ++got_data;
-+ } while (!lirc_buffer_full(&ir->buf));
-+
-+ return 0;
-+}
-+
-+/*
-+ * Main function of the polling thread -- from lirc_dev.
-+ * We don't fit the LIRC model at all anymore. This is horrible, but
-+ * basically we have a single RX/TX device with a nasty failure mode
-+ * that needs to be accounted for across the pair. lirc lets us provide
-+ * fops, but prevents us from using the internal polling, etc. if we do
-+ * so. Hence the replication. Might be neater to extend the LIRC model
-+ * to account for this but I'd think it's a very special case of seriously
-+ * messed up hardware.
-+ */
-+static int lirc_thread(void *arg)
-+{
-+ struct IR *ir = arg;
-+
-+ if (ir->t_notify != NULL)
-+ complete(ir->t_notify);
-+
-+ dprintk("poll thread started\n");
-+
-+ do {
-+ if (ir->open) {
-+ set_current_state(TASK_INTERRUPTIBLE);
-+
-+ /*
-+ * This is ~113*2 + 24 + jitter (2*repeat gap +
-+ * code length). We use this interval as the chip
-+ * resets every time you poll it (bad!). This is
-+ * therefore just sufficient to catch all of the
-+ * button presses. It makes the remote much more
-+ * responsive. You can see the difference by
-+ * running irw and holding down a button. With
-+ * 100ms, the old polling interval, you'll notice
-+ * breaks in the repeat sequence corresponding to
-+ * lost keypresses.
-+ */
-+ schedule_timeout((260 * HZ) / 1000);
-+ if (ir->shutdown)
-+ break;
-+ if (!add_to_buf(ir))
-+ wake_up_interruptible(&ir->buf.wait_poll);
-+ } else {
-+ /* if device not opened so we can sleep half a second */
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ schedule_timeout(HZ/2);
-+ }
-+ } while (!ir->shutdown);
-+
-+ if (ir->t_notify2 != NULL)
-+ wait_for_completion(ir->t_notify2);
-+
-+ ir->task = NULL;
-+ if (ir->t_notify != NULL)
-+ complete(ir->t_notify);
-+
-+ dprintk("poll thread ended\n");
-+ return 0;
-+}
-+
-+static int set_use_inc(void *data)
-+{
-+ struct IR *ir = data;
-+
-+ if (ir->l.owner == NULL || try_module_get(ir->l.owner) == 0)
-+ return -ENODEV;
-+
-+ /* lock bttv in memory while /dev/lirc is in use */
-+ /*
-+ * this is completely broken code. lirc_unregister_driver()
-+ * must be possible even when the device is open
-+ */
-+ if (ir->c_rx.addr)
-+ i2c_use_client(&ir->c_rx);
-+ if (ir->c_tx.addr)
-+ i2c_use_client(&ir->c_tx);
-+
-+ return 0;
-+}
-+
-+static void set_use_dec(void *data)
-+{
-+ struct IR *ir = data;
-+
-+ if (ir->c_rx.addr)
-+ i2c_release_client(&ir->c_rx);
-+ if (ir->c_tx.addr)
-+ i2c_release_client(&ir->c_tx);
-+ if (ir->l.owner != NULL)
-+ module_put(ir->l.owner);
-+}
-+
-+/* safe read of a uint32 (always network byte order) */
-+static int read_uint32(unsigned char **data,
-+ unsigned char *endp, unsigned int *val)
-+{
-+ if (*data + 4 > endp)
-+ return 0;
-+ *val = ((*data)[0] << 24) | ((*data)[1] << 16) |
-+ ((*data)[2] << 8) | (*data)[3];
-+ *data += 4;
-+ return 1;
-+}
-+
-+/* safe read of a uint8 */
-+static int read_uint8(unsigned char **data,
-+ unsigned char *endp, unsigned char *val)
-+{
-+ if (*data + 1 > endp)
-+ return 0;
-+ *val = *((*data)++);
-+ return 1;
-+}
-+
-+/* safe skipping of N bytes */
-+static int skip(unsigned char **data,
-+ unsigned char *endp, unsigned int distance)
-+{
-+ if (*data + distance > endp)
-+ return 0;
-+ *data += distance;
-+ return 1;
-+}
-+
-+/* decompress key data into the given buffer */
-+static int get_key_data(unsigned char *buf,
-+ unsigned int codeset, unsigned int key)
-+{
-+ unsigned char *data, *endp, *diffs, *key_block;
-+ unsigned char keys, ndiffs, id;
-+ unsigned int base, lim, pos, i;
-+
-+ /* Binary search for the codeset */
-+ for (base = 0, lim = tx_data->num_code_sets; lim; lim >>= 1) {
-+ pos = base + (lim >> 1);
-+ data = tx_data->code_sets[pos];
-+
-+ if (!read_uint32(&data, tx_data->endp, &i))
-+ goto corrupt;
-+
-+ if (i == codeset)
-+ break;
-+ else if (codeset > i) {
-+ base = pos + 1;
-+ --lim;
-+ }
-+ }
-+ /* Not found? */
-+ if (!lim)
-+ return -EPROTO;
-+
-+ /* Set end of data block */
-+ endp = pos < tx_data->num_code_sets - 1 ?
-+ tx_data->code_sets[pos + 1] : tx_data->endp;
-+
-+ /* Read the block header */
-+ if (!read_uint8(&data, endp, &keys) ||
-+ !read_uint8(&data, endp, &ndiffs) ||
-+ ndiffs > TX_BLOCK_SIZE || keys == 0)
-+ goto corrupt;
-+
-+ /* Save diffs & skip */
-+ diffs = data;
-+ if (!skip(&data, endp, ndiffs))
-+ goto corrupt;
-+
-+ /* Read the id of the first key */
-+ if (!read_uint8(&data, endp, &id))
-+ goto corrupt;
-+
-+ /* Unpack the first key's data */
-+ for (i = 0; i < TX_BLOCK_SIZE; ++i) {
-+ if (tx_data->fixed[i] == -1) {
-+ if (!read_uint8(&data, endp, &buf[i]))
-+ goto corrupt;
-+ } else {
-+ buf[i] = (unsigned char)tx_data->fixed[i];
-+ }
-+ }
-+
-+ /* Early out key found/not found */
-+ if (key == id)
-+ return 0;
-+ if (keys == 1)
-+ return -EPROTO;
-+
-+ /* Sanity check */
-+ key_block = data;
-+ if (!skip(&data, endp, (keys - 1) * (ndiffs + 1)))
-+ goto corrupt;
-+
-+ /* Binary search for the key */
-+ for (base = 0, lim = keys - 1; lim; lim >>= 1) {
-+ /* Seek to block */
-+ unsigned char *key_data;
-+ pos = base + (lim >> 1);
-+ key_data = key_block + (ndiffs + 1) * pos;
-+
-+ if (*key_data == key) {
-+ /* skip key id */
-+ ++key_data;
-+
-+ /* found, so unpack the diffs */
-+ for (i = 0; i < ndiffs; ++i) {
-+ unsigned char val;
-+ if (!read_uint8(&key_data, endp, &val) ||
-+ diffs[i] >= TX_BLOCK_SIZE)
-+ goto corrupt;
-+ buf[diffs[i]] = val;
-+ }
-+
-+ return 0;
-+ } else if (key > *key_data) {
-+ base = pos + 1;
-+ --lim;
-+ }
-+ }
-+ /* Key not found */
-+ return -EPROTO;
-+
-+corrupt:
-+ zilog_error("firmware is corrupt\n");
-+ return -EFAULT;
-+}
-+
-+/* send a block of data to the IR TX device */
-+static int send_data_block(struct IR *ir, unsigned char *data_block)
-+{
-+ int i, j, ret;
-+ unsigned char buf[5];
-+
-+ for (i = 0; i < TX_BLOCK_SIZE;) {
-+ int tosend = TX_BLOCK_SIZE - i;
-+ if (tosend > 4)
-+ tosend = 4;
-+ buf[0] = (unsigned char)(i + 1);
-+ for (j = 0; j < tosend; ++j)
-+ buf[1 + j] = data_block[i + j];
-+ dprintk("%02x %02x %02x %02x %02x",
-+ buf[0], buf[1], buf[2], buf[3], buf[4]);
-+ ret = i2c_master_send(&ir->c_tx, buf, tosend + 1);
-+ if (ret != tosend + 1) {
-+ zilog_error("i2c_master_send failed with %d\n", ret);
-+ return ret < 0 ? ret : -EFAULT;
-+ }
-+ i += tosend;
-+ }
-+ return 0;
-+}
-+
-+/* send boot data to the IR TX device */
-+static int send_boot_data(struct IR *ir)
-+{
-+ int ret;
-+ unsigned char buf[4];
-+
-+ /* send the boot block */
-+ ret = send_data_block(ir, tx_data->boot_data);
-+ if (ret != 0)
-+ return ret;
-+
-+ /* kick it off? */
-+ buf[0] = 0x00;
-+ buf[1] = 0x20;
-+ ret = i2c_master_send(&ir->c_tx, buf, 2);
-+ if (ret != 2) {
-+ zilog_error("i2c_master_send failed with %d\n", ret);
-+ return ret < 0 ? ret : -EFAULT;
-+ }
-+ ret = i2c_master_send(&ir->c_tx, buf, 1);
-+ if (ret != 1) {
-+ zilog_error("i2c_master_send failed with %d\n", ret);
-+ return ret < 0 ? ret : -EFAULT;
-+ }
-+
-+ /* Here comes the firmware version... (hopefully) */
-+ ret = i2c_master_recv(&ir->c_tx, buf, 4);
-+ if (ret != 4) {
-+ zilog_error("i2c_master_recv failed with %d\n", ret);
-+ return 0;
-+ }
-+ if (buf[0] != 0x80) {
-+ zilog_error("unexpected IR TX response: %02x\n", buf[0]);
-+ return 0;
-+ }
-+ zilog_notify("Zilog/Hauppauge IR blaster firmware version "
-+ "%d.%d.%d loaded\n", buf[1], buf[2], buf[3]);
-+
-+ return 0;
-+}
-+
-+/* unload "firmware", lock held */
-+static void fw_unload_locked(void)
-+{
-+ if (tx_data) {
-+ if (tx_data->code_sets)
-+ vfree(tx_data->code_sets);
-+
-+ if (tx_data->datap)
-+ vfree(tx_data->datap);
-+
-+ vfree(tx_data);
-+ tx_data = NULL;
-+ dprintk("successfully unloaded IR blaster firmware\n");
-+ }
-+}
-+
-+/* unload "firmware" for the IR TX device */
-+static void fw_unload(void)
-+{
-+ mutex_lock(&tx_data_lock);
-+ fw_unload_locked();
-+ mutex_unlock(&tx_data_lock);
-+}
-+
-+/* load "firmware" for the IR TX device */
-+static int fw_load(struct IR *ir)
-+{
-+ int ret;
-+ unsigned int i;
-+ unsigned char *data, version, num_global_fixed;
-+ const struct firmware *fw_entry;
-+
-+ /* Already loaded? */
-+ mutex_lock(&tx_data_lock);
-+ if (tx_data) {
-+ ret = 0;
-+ goto out;
-+ }
-+
-+ /* Request codeset data file */
-+ ret = request_firmware(&fw_entry, "haup-ir-blaster.bin", &ir->c_tx.dev);
-+ if (ret != 0) {
-+ zilog_error("firmware haup-ir-blaster.bin not available "
-+ "(%d)\n", ret);
-+ ret = ret < 0 ? ret : -EFAULT;
-+ goto out;
-+ }
-+ dprintk("firmware of size %zu loaded\n", fw_entry->size);
-+
-+ /* Parse the file */
-+ tx_data = vmalloc(sizeof(*tx_data));
-+ if (tx_data == NULL) {
-+ zilog_error("out of memory\n");
-+ release_firmware(fw_entry);
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-+ tx_data->code_sets = NULL;
-+
-+ /* Copy the data so hotplug doesn't get confused and timeout */
-+ tx_data->datap = vmalloc(fw_entry->size);
-+ if (tx_data->datap == NULL) {
-+ zilog_error("out of memory\n");
-+ release_firmware(fw_entry);
-+ vfree(tx_data);
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-+ memcpy(tx_data->datap, fw_entry->data, fw_entry->size);
-+ tx_data->endp = tx_data->datap + fw_entry->size;
-+ release_firmware(fw_entry); fw_entry = NULL;
-+
-+ /* Check version */
-+ data = tx_data->datap;
-+ if (!read_uint8(&data, tx_data->endp, &version))
-+ goto corrupt;
-+ if (version != 1) {
-+ zilog_error("unsupported code set file version (%u, expected"
-+ "1) -- please upgrade to a newer driver",
-+ version);
-+ fw_unload_locked();
-+ ret = -EFAULT;
-+ goto out;
-+ }
-+
-+ /* Save boot block for later */
-+ tx_data->boot_data = data;
-+ if (!skip(&data, tx_data->endp, TX_BLOCK_SIZE))
-+ goto corrupt;
-+
-+ if (!read_uint32(&data, tx_data->endp,
-+ &tx_data->num_code_sets))
-+ goto corrupt;
-+
-+ dprintk("%u IR blaster codesets loaded\n", tx_data->num_code_sets);
-+
-+ tx_data->code_sets = vmalloc(
-+ tx_data->num_code_sets * sizeof(char *));
-+ if (tx_data->code_sets == NULL) {
-+ fw_unload_locked();
-+ ret = -ENOMEM;
-+ goto out;
-+ }
-+
-+ for (i = 0; i < TX_BLOCK_SIZE; ++i)
-+ tx_data->fixed[i] = -1;
-+
-+ /* Read global fixed data template */
-+ if (!read_uint8(&data, tx_data->endp, &num_global_fixed) ||
-+ num_global_fixed > TX_BLOCK_SIZE)
-+ goto corrupt;
-+ for (i = 0; i < num_global_fixed; ++i) {
-+ unsigned char pos, val;
-+ if (!read_uint8(&data, tx_data->endp, &pos) ||
-+ !read_uint8(&data, tx_data->endp, &val) ||
-+ pos >= TX_BLOCK_SIZE)
-+ goto corrupt;
-+ tx_data->fixed[pos] = (int)val;
-+ }
-+
-+ /* Filch out the position of each code set */
-+ for (i = 0; i < tx_data->num_code_sets; ++i) {
-+ unsigned int id;
-+ unsigned char keys;
-+ unsigned char ndiffs;
-+
-+ /* Save the codeset position */
-+ tx_data->code_sets[i] = data;
-+
-+ /* Read header */
-+ if (!read_uint32(&data, tx_data->endp, &id) ||
-+ !read_uint8(&data, tx_data->endp, &keys) ||
-+ !read_uint8(&data, tx_data->endp, &ndiffs) ||
-+ ndiffs > TX_BLOCK_SIZE || keys == 0)
-+ goto corrupt;
-+
-+ /* skip diff positions */
-+ if (!skip(&data, tx_data->endp, ndiffs))
-+ goto corrupt;
-+
-+ /*
-+ * After the diffs we have the first key id + data -
-+ * global fixed
-+ */
-+ if (!skip(&data, tx_data->endp,
-+ 1 + TX_BLOCK_SIZE - num_global_fixed))
-+ goto corrupt;
-+
-+ /* Then we have keys-1 blocks of key id+diffs */
-+ if (!skip(&data, tx_data->endp,
-+ (ndiffs + 1) * (keys - 1)))
-+ goto corrupt;
-+ }
-+ ret = 0;
-+ goto out;
-+
-+corrupt:
-+ zilog_error("firmware is corrupt\n");
-+ fw_unload_locked();
-+ ret = -EFAULT;
-+
-+out:
-+ mutex_unlock(&tx_data_lock);
-+ return ret;
-+}
-+
-+/* initialise the IR TX device */
-+static int tx_init(struct IR *ir)
-+{
-+ int ret;
-+
-+ /* Load 'firmware' */
-+ ret = fw_load(ir);
-+ if (ret != 0)
-+ return ret;
-+
-+ /* Send boot block */
-+ ret = send_boot_data(ir);
-+ if (ret != 0)
-+ return ret;
-+ ir->need_boot = 0;
-+
-+ /* Looks good */
-+ return 0;
-+}
-+
-+/* do nothing stub to make LIRC happy */
-+static loff_t lseek(struct file *filep, loff_t offset, int orig)
-+{
-+ return -ESPIPE;
-+}
-+
-+/* copied from lirc_dev */
-+static ssize_t read(struct file *filep, char *outbuf, size_t n, loff_t *ppos)
-+{
-+ struct IR *ir = (struct IR *)filep->private_data;
-+ unsigned char buf[ir->buf.chunk_size];
-+ int ret = 0, written = 0;
-+ DECLARE_WAITQUEUE(wait, current);
-+
-+ dprintk("read called\n");
-+ if (ir->c_rx.addr == 0)
-+ return -ENODEV;
-+
-+ if (mutex_lock_interruptible(&ir->buf_lock))
-+ return -ERESTARTSYS;
-+
-+ if (n % ir->buf.chunk_size) {
-+ dprintk("read result = -EINVAL\n");
-+ mutex_unlock(&ir->buf_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 < n && ret == 0) {
-+ if (lirc_buffer_empty(&ir->buf)) {
-+ /*
-+ * According to the read(2) man page, 'written' can be
-+ * returned as less than 'n', instead of blocking
-+ * again, returning -EWOULDBLOCK, or returning
-+ * -ERESTARTSYS
-+ */
-+ if (written)
-+ break;
-+ if (filep->f_flags & O_NONBLOCK) {
-+ ret = -EWOULDBLOCK;
-+ break;
-+ }
-+ if (signal_pending(current)) {
-+ ret = -ERESTARTSYS;
-+ break;
-+ }
-+ schedule();
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ } else {
-+ lirc_buffer_read(&ir->buf, buf);
-+ ret = copy_to_user((void *)outbuf+written, buf,
-+ ir->buf.chunk_size);
-+ written += ir->buf.chunk_size;
-+ }
-+ }
-+
-+ remove_wait_queue(&ir->buf.wait_poll, &wait);
-+ set_current_state(TASK_RUNNING);
-+ mutex_unlock(&ir->buf_lock);
-+
-+ dprintk("read result = %s (%d)\n",
-+ ret ? "-EFAULT" : "OK", ret);
-+
-+ return ret ? ret : written;
-+}
-+
-+/* send a keypress to the IR TX device */
-+static int send_code(struct IR *ir, unsigned int code, unsigned int key)
-+{
-+ unsigned char data_block[TX_BLOCK_SIZE];
-+ unsigned char buf[2];
-+ int i, ret;
-+
-+ /* Get data for the codeset/key */
-+ ret = get_key_data(data_block, code, key);
-+
-+ if (ret == -EPROTO) {
-+ zilog_error("failed to get data for code %u, key %u -- check "
-+ "lircd.conf entries\n", code, key);
-+ return ret;
-+ } else if (ret != 0)
-+ return ret;
-+
-+ /* Send the data block */
-+ ret = send_data_block(ir, data_block);
-+ if (ret != 0)
-+ return ret;
-+
-+ /* Send data block length? */
-+ buf[0] = 0x00;
-+ buf[1] = 0x40;
-+ ret = i2c_master_send(&ir->c_tx, buf, 2);
-+ if (ret != 2) {
-+ zilog_error("i2c_master_send failed with %d\n", ret);
-+ return ret < 0 ? ret : -EFAULT;
-+ }
-+ ret = i2c_master_send(&ir->c_tx, buf, 1);
-+ if (ret != 1) {
-+ zilog_error("i2c_master_send failed with %d\n", ret);
-+ return ret < 0 ? ret : -EFAULT;
-+ }
-+
-+ /* Send finished download? */
-+ ret = i2c_master_recv(&ir->c_tx, buf, 1);
-+ if (ret != 1) {
-+ zilog_error("i2c_master_recv failed with %d\n", ret);
-+ return ret < 0 ? ret : -EFAULT;
-+ }
-+ if (buf[0] != 0xA0) {
-+ zilog_error("unexpected IR TX response #1: %02x\n",
-+ buf[0]);
-+ return -EFAULT;
-+ }
-+
-+ /* Send prepare command? */
-+ buf[0] = 0x00;
-+ buf[1] = 0x80;
-+ ret = i2c_master_send(&ir->c_tx, buf, 2);
-+ if (ret != 2) {
-+ zilog_error("i2c_master_send failed with %d\n", ret);
-+ return ret < 0 ? ret : -EFAULT;
-+ }
-+
-+#ifdef I2C_HW_B_HDPVR
-+ /*
-+ * The sleep bits aren't necessary on the HD PVR, and in fact, the
-+ * last i2c_master_recv always fails with a -5, so for now, we're
-+ * going to skip this whole mess and say we're done on the HD PVR
-+ */
-+ if (ir->c_rx.adapter->id == I2C_HW_B_HDPVR)
-+ goto done;
-+#endif
-+
-+ /*
-+ * This bit NAKs until the device is ready, so we retry it
-+ * sleeping a bit each time. This seems to be what the windows
-+ * driver does, approximately.
-+ * Try for up to 1s.
-+ */
-+ for (i = 0; i < 20; ++i) {
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout((50 * HZ + 999) / 1000);
-+ ret = i2c_master_send(&ir->c_tx, buf, 1);
-+ if (ret == 1)
-+ break;
-+ dprintk("NAK expected: i2c_master_send "
-+ "failed with %d (try %d)\n", ret, i+1);
-+ }
-+ if (ret != 1) {
-+ zilog_error("IR TX chip never got ready: last i2c_master_send "
-+ "failed with %d\n", ret);
-+ return ret < 0 ? ret : -EFAULT;
-+ }
-+
-+ /* Seems to be an 'ok' response */
-+ i = i2c_master_recv(&ir->c_tx, buf, 1);
-+ if (i != 1) {
-+ zilog_error("i2c_master_recv failed with %d\n", ret);
-+ return -EFAULT;
-+ }
-+ if (buf[0] != 0x80) {
-+ zilog_error("unexpected IR TX response #2: %02x\n", buf[0]);
-+ return -EFAULT;
-+ }
-+
-+done:
-+ /* Oh good, it worked */
-+ dprintk("sent code %u, key %u\n", code, key);
-+ return 0;
-+}
-+
-+/*
-+ * Write a code to the device. We take in a 32-bit number (an int) and then
-+ * decode this to a codeset/key index. The key data is then decompressed and
-+ * sent to the device. We have a spin lock as per i2c documentation to prevent
-+ * multiple concurrent sends which would probably cause the device to explode.
-+ */
-+static ssize_t write(struct file *filep, const char *buf, size_t n,
-+ loff_t *ppos)
-+{
-+ struct IR *ir = (struct IR *)filep->private_data;
-+ size_t i;
-+ int failures = 0;
-+
-+ if (ir->c_tx.addr == 0)
-+ return -ENODEV;
-+
-+ /* Validate user parameters */
-+ if (n % sizeof(int))
-+ return -EINVAL;
-+
-+ /* Lock i2c bus for the duration */
-+ mutex_lock(&ir->ir_lock);
-+
-+ /* Send each keypress */
-+ for (i = 0; i < n;) {
-+ int ret = 0;
-+ int command;
-+
-+ if (copy_from_user(&command, buf + i, sizeof(command))) {
-+ mutex_unlock(&ir->ir_lock);
-+ return -EFAULT;
-+ }
-+
-+ /* Send boot data first if required */
-+ if (ir->need_boot == 1) {
-+ ret = send_boot_data(ir);
-+ if (ret == 0)
-+ ir->need_boot = 0;
-+ }
-+
-+ /* Send the code */
-+ if (ret == 0) {
-+ ret = send_code(ir, (unsigned)command >> 16,
-+ (unsigned)command & 0xFFFF);
-+ if (ret == -EPROTO) {
-+ mutex_unlock(&ir->ir_lock);
-+ return ret;
-+ }
-+ }
-+
-+ /*
-+ * Hmm, a failure. If we've had a few then give up, otherwise
-+ * try a reset
-+ */
-+ if (ret != 0) {
-+ /* Looks like the chip crashed, reset it */
-+ zilog_error("sending to the IR transmitter chip "
-+ "failed, trying reset\n");
-+
-+ if (failures >= 3) {
-+ zilog_error("unable to send to the IR chip "
-+ "after 3 resets, giving up\n");
-+ mutex_unlock(&ir->ir_lock);
-+ return ret;
-+ }
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_timeout((100 * HZ + 999) / 1000);
-+ ir->need_boot = 1;
-+ ++failures;
-+ } else
-+ i += sizeof(int);
-+ }
-+
-+ /* Release i2c bus */
-+ mutex_unlock(&ir->ir_lock);
-+
-+ /* All looks good */
-+ return n;
-+}
-+
-+/* copied from lirc_dev */
-+static unsigned int poll(struct file *filep, poll_table *wait)
-+{
-+ struct IR *ir = (struct IR *)filep->private_data;
-+ unsigned int ret;
-+
-+ dprintk("poll called\n");
-+ if (ir->c_rx.addr == 0)
-+ return -ENODEV;
-+
-+ mutex_lock(&ir->buf_lock);
-+
-+ poll_wait(filep, &ir->buf.wait_poll, wait);
-+
-+ dprintk("poll result = %s\n",
-+ lirc_buffer_empty(&ir->buf) ? "0" : "POLLIN|POLLRDNORM");
-+
-+ ret = lirc_buffer_empty(&ir->buf) ? 0 : (POLLIN|POLLRDNORM);
-+
-+ mutex_unlock(&ir->buf_lock);
-+ return ret;
-+}
-+
-+static long ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
-+{
-+ struct IR *ir = (struct IR *)filep->private_data;
-+ int result;
-+ unsigned long mode, features = 0;
-+
-+ if (ir->c_rx.addr != 0)
-+ features |= LIRC_CAN_REC_LIRCCODE;
-+ if (ir->c_tx.addr != 0)
-+ features |= LIRC_CAN_SEND_PULSE;
-+
-+ switch (cmd) {
-+ case LIRC_GET_LENGTH:
-+ result = put_user((unsigned long)13,
-+ (unsigned long *)arg);
-+ break;
-+ case LIRC_GET_FEATURES:
-+ result = put_user(features, (unsigned long *) arg);
-+ break;
-+ case LIRC_GET_REC_MODE:
-+ if (!(features&LIRC_CAN_REC_MASK))
-+ return -ENOSYS;
-+
-+ result = put_user(LIRC_REC2MODE
-+ (features&LIRC_CAN_REC_MASK),
-+ (unsigned long *)arg);
-+ break;
-+ case LIRC_SET_REC_MODE:
-+ if (!(features&LIRC_CAN_REC_MASK))
-+ return -ENOSYS;
-+
-+ result = get_user(mode, (unsigned long *)arg);
-+ if (!result && !(LIRC_MODE2REC(mode) & features))
-+ result = -EINVAL;
-+ break;
-+ case LIRC_GET_SEND_MODE:
-+ if (!(features&LIRC_CAN_SEND_MASK))
-+ return -ENOSYS;
-+
-+ result = put_user(LIRC_MODE_PULSE, (unsigned long *) arg);
-+ break;
-+ case LIRC_SET_SEND_MODE:
-+ if (!(features&LIRC_CAN_SEND_MASK))
-+ return -ENOSYS;
-+
-+ result = get_user(mode, (unsigned long *) arg);
-+ if (!result && mode != LIRC_MODE_PULSE)
-+ return -EINVAL;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+ return result;
-+}
-+
-+/*
-+ * Open the IR device. Get hold of our IR structure and
-+ * stash it in private_data for the file
-+ */
-+static int open(struct inode *node, struct file *filep)
-+{
-+ struct IR *ir;
-+ int ret;
-+
-+ /* find our IR struct */
-+ unsigned minor = MINOR(node->i_rdev);
-+ if (minor >= MAX_IRCTL_DEVICES) {
-+ dprintk("minor %d: open result = -ENODEV\n",
-+ minor);
-+ return -ENODEV;
-+ }
-+ ir = ir_devices[minor];
-+
-+ /* increment in use count */
-+ mutex_lock(&ir->ir_lock);
-+ ++ir->open;
-+ ret = set_use_inc(ir);
-+ if (ret != 0) {
-+ --ir->open;
-+ mutex_unlock(&ir->ir_lock);
-+ return ret;
-+ }
-+ mutex_unlock(&ir->ir_lock);
-+
-+ /* stash our IR struct */
-+ filep->private_data = ir;
-+
-+ return 0;
-+}
-+
-+/* Close the IR device */
-+static int close(struct inode *node, struct file *filep)
-+{
-+ /* find our IR struct */
-+ struct IR *ir = (struct IR *)filep->private_data;
-+ if (ir == NULL) {
-+ zilog_error("close: no private_data attached to the file!\n");
-+ return -ENODEV;
-+ }
-+
-+ /* decrement in use count */
-+ mutex_lock(&ir->ir_lock);
-+ --ir->open;
-+ set_use_dec(ir);
-+ mutex_unlock(&ir->ir_lock);
-+
-+ return 0;
-+}
-+
-+static struct lirc_driver lirc_template = {
-+ .name = "lirc_zilog",
-+ .set_use_inc = set_use_inc,
-+ .set_use_dec = set_use_dec,
-+ .owner = THIS_MODULE
-+};
-+
-+static int ir_remove(struct i2c_client *client);
-+static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id);
-+static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg);
-+
-+static const struct i2c_device_id ir_transceiver_id[] = {
-+ /* Generic entry for any IR transceiver */
-+ { "ir_video", 0 },
-+ /* IR device specific entries should be added here */
-+ { "ir_tx_z8f0811_haup", 0 },
-+ { "ir_rx_z8f0811_haup", 0 },
-+ { }
-+};
-+
-+static struct i2c_driver driver = {
-+ .driver = {
-+ .owner = THIS_MODULE,
-+ .name = "Zilog/Hauppauge i2c IR",
-+ },
-+ .probe = ir_probe,
-+ .remove = ir_remove,
-+ .command = ir_command,
-+ .id_table = ir_transceiver_id,
-+};
-+
-+static const struct file_operations lirc_fops = {
-+ .owner = THIS_MODULE,
-+ .llseek = lseek,
-+ .read = read,
-+ .write = write,
-+ .poll = poll,
-+ .unlocked_ioctl = ioctl,
-+ .open = open,
-+ .release = close
-+};
-+
-+static int ir_remove(struct i2c_client *client)
-+{
-+ struct IR *ir = i2c_get_clientdata(client);
-+
-+ mutex_lock(&ir->ir_lock);
-+
-+ if (ir->have_rx || ir->have_tx) {
-+ DECLARE_COMPLETION(tn);
-+ DECLARE_COMPLETION(tn2);
-+
-+ /* end up polling thread */
-+ if (ir->task && !IS_ERR(ir->task)) {
-+ ir->t_notify = &tn;
-+ ir->t_notify2 = &tn2;
-+ ir->shutdown = 1;
-+ wake_up_process(ir->task);
-+ complete(&tn2);
-+ wait_for_completion(&tn);
-+ ir->t_notify = NULL;
-+ ir->t_notify2 = NULL;
-+ }
-+
-+ } else {
-+ mutex_unlock(&ir->ir_lock);
-+ zilog_error("%s: detached from something we didn't "
-+ "attach to\n", __func__);
-+ return -ENODEV;
-+ }
-+
-+ /* unregister lirc driver */
-+ if (ir->l.minor >= 0 && ir->l.minor < MAX_IRCTL_DEVICES) {
-+ lirc_unregister_driver(ir->l.minor);
-+ ir_devices[ir->l.minor] = NULL;
-+ }
-+
-+ /* free memory */
-+ lirc_buffer_free(&ir->buf);
-+ mutex_unlock(&ir->ir_lock);
-+ kfree(ir);
-+
-+ return 0;
-+}
-+
-+static int ir_probe(struct i2c_client *client, const struct i2c_device_id *id)
-+{
-+ struct IR *ir = NULL;
-+ struct i2c_adapter *adap = client->adapter;
-+ char buf;
-+ int ret;
-+ int have_rx = 0, have_tx = 0;
-+
-+ dprintk("%s: adapter id=0x%x, client addr=0x%02x\n",
-+ __func__, adap->id, client->addr);
-+
-+ /*
-+ * The external IR receiver is at i2c address 0x71.
-+ * The IR transmitter is at 0x70.
-+ */
-+ client->addr = 0x70;
-+
-+ if (!disable_tx) {
-+ if (i2c_master_recv(client, &buf, 1) == 1)
-+ have_tx = 1;
-+ dprintk("probe 0x70 @ %s: %s\n",
-+ adap->name, have_tx ? "success" : "failed");
-+ }
-+
-+ if (!disable_rx) {
-+ client->addr = 0x71;
-+ if (i2c_master_recv(client, &buf, 1) == 1)
-+ have_rx = 1;
-+ dprintk("probe 0x71 @ %s: %s\n",
-+ adap->name, have_rx ? "success" : "failed");
-+ }
-+
-+ if (!(have_rx || have_tx)) {
-+ zilog_error("%s: no devices found\n", adap->name);
-+ goto out_nodev;
-+ }
-+
-+ printk(KERN_INFO "lirc_zilog: chip found with %s\n",
-+ have_rx && have_tx ? "RX and TX" :
-+ have_rx ? "RX only" : "TX only");
-+
-+ ir = kzalloc(sizeof(struct IR), GFP_KERNEL);
-+
-+ if (!ir)
-+ goto out_nomem;
-+
-+ ret = lirc_buffer_init(&ir->buf, 2, BUFLEN / 2);
-+ if (ret)
-+ goto out_nomem;
-+
-+ mutex_init(&ir->ir_lock);
-+ mutex_init(&ir->buf_lock);
-+ ir->need_boot = 1;
-+
-+ memcpy(&ir->l, &lirc_template, sizeof(struct lirc_driver));
-+ ir->l.minor = -1;
-+
-+ /* I2C attach to device */
-+ i2c_set_clientdata(client, ir);
-+
-+ /* initialise RX device */
-+ if (have_rx) {
-+ DECLARE_COMPLETION(tn);
-+ memcpy(&ir->c_rx, client, sizeof(struct i2c_client));
-+
-+ ir->c_rx.addr = 0x71;
-+ strlcpy(ir->c_rx.name, ZILOG_HAUPPAUGE_IR_RX_NAME,
-+ I2C_NAME_SIZE);
-+
-+ /* try to fire up polling thread */
-+ ir->t_notify = &tn;
-+ ir->task = kthread_run(lirc_thread, ir, "lirc_zilog");
-+ if (IS_ERR(ir->task)) {
-+ ret = PTR_ERR(ir->task);
-+ zilog_error("lirc_register_driver: cannot run "
-+ "poll thread %d\n", ret);
-+ goto err;
-+ }
-+ wait_for_completion(&tn);
-+ ir->t_notify = NULL;
-+ ir->have_rx = 1;
-+ }
-+
-+ /* initialise TX device */
-+ if (have_tx) {
-+ memcpy(&ir->c_tx, client, sizeof(struct i2c_client));
-+ ir->c_tx.addr = 0x70;
-+ strlcpy(ir->c_tx.name, ZILOG_HAUPPAUGE_IR_TX_NAME,
-+ I2C_NAME_SIZE);
-+ ir->have_tx = 1;
-+ }
-+
-+ /* set lirc_dev stuff */
-+ ir->l.code_length = 13;
-+ ir->l.rbuf = &ir->buf;
-+ ir->l.fops = &lirc_fops;
-+ ir->l.data = ir;
-+ ir->l.minor = minor;
-+ ir->l.dev = &adap->dev;
-+ ir->l.sample_rate = 0;
-+
-+ /* register with lirc */
-+ ir->l.minor = lirc_register_driver(&ir->l);
-+ if (ir->l.minor < 0 || ir->l.minor >= MAX_IRCTL_DEVICES) {
-+ zilog_error("ir_attach: \"minor\" must be between 0 and %d "
-+ "(%d)!\n", MAX_IRCTL_DEVICES-1, ir->l.minor);
-+ ret = -EBADRQC;
-+ goto err;
-+ }
-+
-+ /* store this for getting back in open() later on */
-+ ir_devices[ir->l.minor] = ir;
-+
-+ /*
-+ * if we have the tx device, load the 'firmware'. We do this
-+ * after registering with lirc as otherwise hotplug seems to take
-+ * 10s to create the lirc device.
-+ */
-+ if (have_tx) {
-+ /* Special TX init */
-+ ret = tx_init(ir);
-+ if (ret != 0)
-+ goto err;
-+ }
-+
-+ return 0;
-+
-+err:
-+ /* undo everything, hopefully... */
-+ if (ir->c_rx.addr)
-+ ir_remove(&ir->c_rx);
-+ if (ir->c_tx.addr)
-+ ir_remove(&ir->c_tx);
-+ return ret;
-+
-+out_nodev:
-+ zilog_error("no device found\n");
-+ return -ENODEV;
-+
-+out_nomem:
-+ zilog_error("memory allocation failure\n");
-+ kfree(ir);
-+ return -ENOMEM;
-+}
-+
-+static int ir_command(struct i2c_client *client, unsigned int cmd, void *arg)
-+{
-+ /* nothing */
-+ return 0;
-+}
-+
-+static int __init zilog_init(void)
-+{
-+ int ret;
-+
-+ zilog_notify("Zilog/Hauppauge IR driver initializing\n");
-+
-+ mutex_init(&tx_data_lock);
-+
-+ request_module("firmware_class");
-+
-+ ret = i2c_add_driver(&driver);
-+ if (ret)
-+ zilog_error("initialization failed\n");
-+ else
-+ zilog_notify("initialization complete\n");
-+
-+ return ret;
-+}
-+
-+static void __exit zilog_exit(void)
-+{
-+ i2c_del_driver(&driver);
-+ /* if loaded */
-+ fw_unload();
-+ zilog_notify("Zilog/Hauppauge IR driver unloaded\n");
-+}
-+
-+module_init(zilog_init);
-+module_exit(zilog_exit);
-+
-+MODULE_DESCRIPTION("Zilog/Hauppauge infrared transmitter driver (i2c stack)");
-+MODULE_AUTHOR("Gerd Knorr, Michal Kochanowicz, Christoph Bartelmus, "
-+ "Ulrich Mueller, Stefan Jahn, Jerome Brock, Mark Weaver");
-+MODULE_LICENSE("GPL");
-+/* for compat with old name, which isn't all that accurate anymore */
-+MODULE_ALIAS("lirc_pvr150");
-+
-+module_param(minor, int, 0444);
-+MODULE_PARM_DESC(minor, "Preferred minor device number");
-+
-+module_param(debug, bool, 0644);
-+MODULE_PARM_DESC(debug, "Enable debugging messages");
-+
-+module_param(disable_rx, bool, 0644);
-+MODULE_PARM_DESC(disable_rx, "Disable the IR receiver device");
-+
-+module_param(disable_tx, bool, 0644);
-+MODULE_PARM_DESC(disable_tx, "Disable the IR transmitter device");
diff --git a/only-use-alpha2-regulatory-information-from-country-IE.patch b/only-use-alpha2-regulatory-information-from-country-IE.patch
deleted file mode 100644
index 5e7459cf8..000000000
--- a/only-use-alpha2-regulatory-information-from-country-IE.patch
+++ /dev/null
@@ -1,788 +0,0 @@
-From linville@tuxdriver.com Thu Jul 15 15:40:22 2010
-From: "John W. Linville" <linville@tuxdriver.com>
-Subject: [RFC] wireless: only use alpha2 regulatory information from country IE
-Date: Thu, 15 Jul 2010 15:06:47 -0400
-
-The meaning and/or usage of the country IE is somewhat poorly defined.
-In practice, this means that regulatory rulesets in a country IE are
-often incomplete and might be untrustworthy. This removes the code
-associated with interpreting those rulesets while preserving respect
-for country "alpha2" codes also contained in the country IE.
-
-Signed-off-by: John W. Linville <linville@tuxdriver.com>
----
-This patch is compile-tested only! Please feel free to suggest that
-I have left something out or missed some nuance of our regulatory
-enforcement code...
-
- include/net/regulatory.h | 1 -
- net/wireless/reg.c | 625 +---------------------------------------------
- 2 files changed, 12 insertions(+), 614 deletions(-)
-
-diff --git a/include/net/regulatory.h b/include/net/regulatory.h
-index f873ee3..9e103a4 100644
---- a/include/net/regulatory.h
-+++ b/include/net/regulatory.h
-@@ -54,7 +54,6 @@ struct regulatory_request {
- enum nl80211_reg_initiator initiator;
- char alpha2[2];
- bool intersect;
-- u32 country_ie_checksum;
- enum environment_cap country_ie_env;
- struct list_head list;
- };
-diff --git a/net/wireless/reg.c b/net/wireless/reg.c
-index 1ac2bdd..678d0bd 100644
---- a/net/wireless/reg.c
-+++ b/net/wireless/reg.c
-@@ -67,17 +67,9 @@ static struct platform_device *reg_pdev;
- const struct ieee80211_regdomain *cfg80211_regdomain;
-
- /*
-- * We use this as a place for the rd structure built from the
-- * last parsed country IE to rest until CRDA gets back to us with
-- * what it thinks should apply for the same country
-- */
--static const struct ieee80211_regdomain *country_ie_regdomain;
--
--/*
- * Protects static reg.c components:
- * - cfg80211_world_regdom
- * - cfg80211_regdom
-- * - country_ie_regdomain
- * - last_request
- */
- static DEFINE_MUTEX(reg_mutex);
-@@ -275,25 +267,6 @@ static bool is_user_regdom_saved(void)
- return true;
- }
-
--/**
-- * country_ie_integrity_changes - tells us if the country IE has changed
-- * @checksum: checksum of country IE of fields we are interested in
-- *
-- * If the country IE has not changed you can ignore it safely. This is
-- * useful to determine if two devices are seeing two different country IEs
-- * even on the same alpha2. Note that this will return false if no IE has
-- * been set on the wireless core yet.
-- */
--static bool country_ie_integrity_changes(u32 checksum)
--{
-- /* If no IE has been set then the checksum doesn't change */
-- if (unlikely(!last_request->country_ie_checksum))
-- return false;
-- if (unlikely(last_request->country_ie_checksum != checksum))
-- return true;
-- return false;
--}
--
- static int reg_copy_regd(const struct ieee80211_regdomain **dst_regd,
- const struct ieee80211_regdomain *src_regd)
- {
-@@ -506,471 +479,6 @@ static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range,
- }
-
- /*
-- * This is a work around for sanity checking ieee80211_channel_to_frequency()'s
-- * work. ieee80211_channel_to_frequency() can for example currently provide a
-- * 2 GHz channel when in fact a 5 GHz channel was desired. An example would be
-- * an AP providing channel 8 on a country IE triplet when it sent this on the
-- * 5 GHz band, that channel is designed to be channel 8 on 5 GHz, not a 2 GHz
-- * channel.
-- *
-- * This can be removed once ieee80211_channel_to_frequency() takes in a band.
-- */
--static bool chan_in_band(int chan, enum ieee80211_band band)
--{
-- int center_freq = ieee80211_channel_to_frequency(chan);
--
-- switch (band) {
-- case IEEE80211_BAND_2GHZ:
-- if (center_freq <= 2484)
-- return true;
-- return false;
-- case IEEE80211_BAND_5GHZ:
-- if (center_freq >= 5005)
-- return true;
-- return false;
-- default:
-- return false;
-- }
--}
--
--/*
-- * Some APs may send a country IE triplet for each channel they
-- * support and while this is completely overkill and silly we still
-- * need to support it. We avoid making a single rule for each channel
-- * though and to help us with this we use this helper to find the
-- * actual subband end channel. These type of country IE triplet
-- * scenerios are handled then, all yielding two regulaotry rules from
-- * parsing a country IE:
-- *
-- * [1]
-- * [2]
-- * [36]
-- * [40]
-- *
-- * [1]
-- * [2-4]
-- * [5-12]
-- * [36]
-- * [40-44]
-- *
-- * [1-4]
-- * [5-7]
-- * [36-44]
-- * [48-64]
-- *
-- * [36-36]
-- * [40-40]
-- * [44-44]
-- * [48-48]
-- * [52-52]
-- * [56-56]
-- * [60-60]
-- * [64-64]
-- * [100-100]
-- * [104-104]
-- * [108-108]
-- * [112-112]
-- * [116-116]
-- * [120-120]
-- * [124-124]
-- * [128-128]
-- * [132-132]
-- * [136-136]
-- * [140-140]
-- *
-- * Returns 0 if the IE has been found to be invalid in the middle
-- * somewhere.
-- */
--static int max_subband_chan(enum ieee80211_band band,
-- int orig_cur_chan,
-- int orig_end_channel,
-- s8 orig_max_power,
-- u8 **country_ie,
-- u8 *country_ie_len)
--{
-- u8 *triplets_start = *country_ie;
-- u8 len_at_triplet = *country_ie_len;
-- int end_subband_chan = orig_end_channel;
--
-- /*
-- * We'll deal with padding for the caller unless
-- * its not immediate and we don't process any channels
-- */
-- if (*country_ie_len == 1) {
-- *country_ie += 1;
-- *country_ie_len -= 1;
-- return orig_end_channel;
-- }
--
-- /* Move to the next triplet and then start search */
-- *country_ie += 3;
-- *country_ie_len -= 3;
--
-- if (!chan_in_band(orig_cur_chan, band))
-- return 0;
--
-- while (*country_ie_len >= 3) {
-- int end_channel = 0;
-- struct ieee80211_country_ie_triplet *triplet =
-- (struct ieee80211_country_ie_triplet *) *country_ie;
-- int cur_channel = 0, next_expected_chan;
--
-- /* means last triplet is completely unrelated to this one */
-- if (triplet->ext.reg_extension_id >=
-- IEEE80211_COUNTRY_EXTENSION_ID) {
-- *country_ie -= 3;
-- *country_ie_len += 3;
-- break;
-- }
--
-- if (triplet->chans.first_channel == 0) {
-- *country_ie += 1;
-- *country_ie_len -= 1;
-- if (*country_ie_len != 0)
-- return 0;
-- break;
-- }
--
-- if (triplet->chans.num_channels == 0)
-- return 0;
--
-- /* Monitonically increasing channel order */
-- if (triplet->chans.first_channel <= end_subband_chan)
-- return 0;
--
-- if (!chan_in_band(triplet->chans.first_channel, band))
-- return 0;
--
-- /* 2 GHz */
-- if (triplet->chans.first_channel <= 14) {
-- end_channel = triplet->chans.first_channel +
-- triplet->chans.num_channels - 1;
-- }
-- else {
-- end_channel = triplet->chans.first_channel +
-- (4 * (triplet->chans.num_channels - 1));
-- }
--
-- if (!chan_in_band(end_channel, band))
-- return 0;
--
-- if (orig_max_power != triplet->chans.max_power) {
-- *country_ie -= 3;
-- *country_ie_len += 3;
-- break;
-- }
--
-- cur_channel = triplet->chans.first_channel;
--
-- /* The key is finding the right next expected channel */
-- if (band == IEEE80211_BAND_2GHZ)
-- next_expected_chan = end_subband_chan + 1;
-- else
-- next_expected_chan = end_subband_chan + 4;
--
-- if (cur_channel != next_expected_chan) {
-- *country_ie -= 3;
-- *country_ie_len += 3;
-- break;
-- }
--
-- end_subband_chan = end_channel;
--
-- /* Move to the next one */
-- *country_ie += 3;
-- *country_ie_len -= 3;
--
-- /*
-- * Padding needs to be dealt with if we processed
-- * some channels.
-- */
-- if (*country_ie_len == 1) {
-- *country_ie += 1;
-- *country_ie_len -= 1;
-- break;
-- }
--
-- /* If seen, the IE is invalid */
-- if (*country_ie_len == 2)
-- return 0;
-- }
--
-- if (end_subband_chan == orig_end_channel) {
-- *country_ie = triplets_start;
-- *country_ie_len = len_at_triplet;
-- return orig_end_channel;
-- }
--
-- return end_subband_chan;
--}
--
--/*
-- * Converts a country IE to a regulatory domain. A regulatory domain
-- * structure has a lot of information which the IE doesn't yet have,
-- * so for the other values we use upper max values as we will intersect
-- * with our userspace regulatory agent to get lower bounds.
-- */
--static struct ieee80211_regdomain *country_ie_2_rd(
-- enum ieee80211_band band,
-- u8 *country_ie,
-- u8 country_ie_len,
-- u32 *checksum)
--{
-- struct ieee80211_regdomain *rd = NULL;
-- unsigned int i = 0;
-- char alpha2[2];
-- u32 flags = 0;
-- u32 num_rules = 0, size_of_regd = 0;
-- u8 *triplets_start = NULL;
-- u8 len_at_triplet = 0;
-- /* the last channel we have registered in a subband (triplet) */
-- int last_sub_max_channel = 0;
--
-- *checksum = 0xDEADBEEF;
--
-- /* Country IE requirements */
-- BUG_ON(country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN ||
-- country_ie_len & 0x01);
--
-- alpha2[0] = country_ie[0];
-- alpha2[1] = country_ie[1];
--
-- /*
-- * Third octet can be:
-- * 'I' - Indoor
-- * 'O' - Outdoor
-- *
-- * anything else we assume is no restrictions
-- */
-- if (country_ie[2] == 'I')
-- flags = NL80211_RRF_NO_OUTDOOR;
-- else if (country_ie[2] == 'O')
-- flags = NL80211_RRF_NO_INDOOR;
--
-- country_ie += 3;
-- country_ie_len -= 3;
--
-- triplets_start = country_ie;
-- len_at_triplet = country_ie_len;
--
-- *checksum ^= ((flags ^ alpha2[0] ^ alpha2[1]) << 8);
--
-- /*
-- * We need to build a reg rule for each triplet, but first we must
-- * calculate the number of reg rules we will need. We will need one
-- * for each channel subband
-- */
-- while (country_ie_len >= 3) {
-- int end_channel = 0;
-- struct ieee80211_country_ie_triplet *triplet =
-- (struct ieee80211_country_ie_triplet *) country_ie;
-- int cur_sub_max_channel = 0, cur_channel = 0;
--
-- if (triplet->ext.reg_extension_id >=
-- IEEE80211_COUNTRY_EXTENSION_ID) {
-- country_ie += 3;
-- country_ie_len -= 3;
-- continue;
-- }
--
-- /*
-- * APs can add padding to make length divisible
-- * by two, required by the spec.
-- */
-- if (triplet->chans.first_channel == 0) {
-- country_ie++;
-- country_ie_len--;
-- /* This is expected to be at the very end only */
-- if (country_ie_len != 0)
-- return NULL;
-- break;
-- }
--
-- if (triplet->chans.num_channels == 0)
-- return NULL;
--
-- if (!chan_in_band(triplet->chans.first_channel, band))
-- return NULL;
--
-- /* 2 GHz */
-- if (band == IEEE80211_BAND_2GHZ)
-- end_channel = triplet->chans.first_channel +
-- triplet->chans.num_channels - 1;
-- else
-- /*
-- * 5 GHz -- For example in country IEs if the first
-- * channel given is 36 and the number of channels is 4
-- * then the individual channel numbers defined for the
-- * 5 GHz PHY by these parameters are: 36, 40, 44, and 48
-- * and not 36, 37, 38, 39.
-- *
-- * See: http://tinyurl.com/11d-clarification
-- */
-- end_channel = triplet->chans.first_channel +
-- (4 * (triplet->chans.num_channels - 1));
--
-- cur_channel = triplet->chans.first_channel;
--
-- /*
-- * Enhancement for APs that send a triplet for every channel
-- * or for whatever reason sends triplets with multiple channels
-- * separated when in fact they should be together.
-- */
-- end_channel = max_subband_chan(band,
-- cur_channel,
-- end_channel,
-- triplet->chans.max_power,
-- &country_ie,
-- &country_ie_len);
-- if (!end_channel)
-- return NULL;
--
-- if (!chan_in_band(end_channel, band))
-- return NULL;
--
-- cur_sub_max_channel = end_channel;
--
-- /* Basic sanity check */
-- if (cur_sub_max_channel < cur_channel)
-- return NULL;
--
-- /*
-- * Do not allow overlapping channels. Also channels
-- * passed in each subband must be monotonically
-- * increasing
-- */
-- if (last_sub_max_channel) {
-- if (cur_channel <= last_sub_max_channel)
-- return NULL;
-- if (cur_sub_max_channel <= last_sub_max_channel)
-- return NULL;
-- }
--
-- /*
-- * When dot11RegulatoryClassesRequired is supported
-- * we can throw ext triplets as part of this soup,
-- * for now we don't care when those change as we
-- * don't support them
-- */
-- *checksum ^= ((cur_channel ^ cur_sub_max_channel) << 8) |
-- ((cur_sub_max_channel ^ cur_sub_max_channel) << 16) |
-- ((triplet->chans.max_power ^ cur_sub_max_channel) << 24);
--
-- last_sub_max_channel = cur_sub_max_channel;
--
-- num_rules++;
--
-- if (country_ie_len >= 3) {
-- country_ie += 3;
-- country_ie_len -= 3;
-- }
--
-- /*
-- * Note: this is not a IEEE requirement but
-- * simply a memory requirement
-- */
-- if (num_rules > NL80211_MAX_SUPP_REG_RULES)
-- return NULL;
-- }
--
-- country_ie = triplets_start;
-- country_ie_len = len_at_triplet;
--
-- size_of_regd = sizeof(struct ieee80211_regdomain) +
-- (num_rules * sizeof(struct ieee80211_reg_rule));
--
-- rd = kzalloc(size_of_regd, GFP_KERNEL);
-- if (!rd)
-- return NULL;
--
-- rd->n_reg_rules = num_rules;
-- rd->alpha2[0] = alpha2[0];
-- rd->alpha2[1] = alpha2[1];
--
-- /* This time around we fill in the rd */
-- while (country_ie_len >= 3) {
-- int end_channel = 0;
-- struct ieee80211_country_ie_triplet *triplet =
-- (struct ieee80211_country_ie_triplet *) country_ie;
-- struct ieee80211_reg_rule *reg_rule = NULL;
-- struct ieee80211_freq_range *freq_range = NULL;
-- struct ieee80211_power_rule *power_rule = NULL;
--
-- /*
-- * Must parse if dot11RegulatoryClassesRequired is true,
-- * we don't support this yet
-- */
-- if (triplet->ext.reg_extension_id >=
-- IEEE80211_COUNTRY_EXTENSION_ID) {
-- country_ie += 3;
-- country_ie_len -= 3;
-- continue;
-- }
--
-- if (triplet->chans.first_channel == 0) {
-- country_ie++;
-- country_ie_len--;
-- break;
-- }
--
-- reg_rule = &rd->reg_rules[i];
-- freq_range = &reg_rule->freq_range;
-- power_rule = &reg_rule->power_rule;
--
-- reg_rule->flags = flags;
--
-- /* 2 GHz */
-- if (band == IEEE80211_BAND_2GHZ)
-- end_channel = triplet->chans.first_channel +
-- triplet->chans.num_channels -1;
-- else
-- end_channel = triplet->chans.first_channel +
-- (4 * (triplet->chans.num_channels - 1));
--
-- end_channel = max_subband_chan(band,
-- triplet->chans.first_channel,
-- end_channel,
-- triplet->chans.max_power,
-- &country_ie,
-- &country_ie_len);
--
-- /*
-- * The +10 is since the regulatory domain expects
-- * the actual band edge, not the center of freq for
-- * its start and end freqs, assuming 20 MHz bandwidth on
-- * the channels passed
-- */
-- freq_range->start_freq_khz =
-- MHZ_TO_KHZ(ieee80211_channel_to_frequency(
-- triplet->chans.first_channel) - 10);
-- freq_range->end_freq_khz =
-- MHZ_TO_KHZ(ieee80211_channel_to_frequency(
-- end_channel) + 10);
--
-- /*
-- * These are large arbitrary values we use to intersect later.
-- * Increment this if we ever support >= 40 MHz channels
-- * in IEEE 802.11
-- */
-- freq_range->max_bandwidth_khz = MHZ_TO_KHZ(40);
-- power_rule->max_antenna_gain = DBI_TO_MBI(100);
-- power_rule->max_eirp = DBM_TO_MBM(triplet->chans.max_power);
--
-- i++;
--
-- if (country_ie_len >= 3) {
-- country_ie += 3;
-- country_ie_len -= 3;
-- }
--
-- BUG_ON(i > NL80211_MAX_SUPP_REG_RULES);
-- }
--
-- return rd;
--}
--
--
--/*
- * Helper for regdom_intersect(), this does the real
- * mathematical intersection fun
- */
-@@ -1191,7 +699,6 @@ static int freq_reg_info_regd(struct wiphy *wiphy,
-
- return -EINVAL;
- }
--EXPORT_SYMBOL(freq_reg_info);
-
- int freq_reg_info(struct wiphy *wiphy,
- u32 center_freq,
-@@ -1205,6 +712,7 @@ int freq_reg_info(struct wiphy *wiphy,
- reg_rule,
- NULL);
- }
-+EXPORT_SYMBOL(freq_reg_info);
-
- /*
- * Note that right now we assume the desired channel bandwidth
-@@ -1243,41 +751,8 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
- desired_bw_khz,
- &reg_rule);
-
-- if (r) {
-- /*
-- * This means no regulatory rule was found in the country IE
-- * with a frequency range on the center_freq's band, since
-- * IEEE-802.11 allows for a country IE to have a subset of the
-- * regulatory information provided in a country we ignore
-- * disabling the channel unless at least one reg rule was
-- * found on the center_freq's band. For details see this
-- * clarification:
-- *
-- * http://tinyurl.com/11d-clarification
-- */
-- if (r == -ERANGE &&
-- last_request->initiator ==
-- NL80211_REGDOM_SET_BY_COUNTRY_IE) {
-- REG_DBG_PRINT("cfg80211: Leaving channel %d MHz "
-- "intact on %s - no rule found in band on "
-- "Country IE\n",
-- chan->center_freq, wiphy_name(wiphy));
-- } else {
-- /*
-- * In this case we know the country IE has at least one reg rule
-- * for the band so we respect its band definitions
-- */
-- if (last_request->initiator ==
-- NL80211_REGDOM_SET_BY_COUNTRY_IE)
-- REG_DBG_PRINT("cfg80211: Disabling "
-- "channel %d MHz on %s due to "
-- "Country IE\n",
-- chan->center_freq, wiphy_name(wiphy));
-- flags |= IEEE80211_CHAN_DISABLED;
-- chan->flags = flags;
-- }
-+ if (r)
- return;
-- }
-
- power_rule = &reg_rule->power_rule;
- freq_range = &reg_rule->freq_range;
-@@ -2010,7 +1485,7 @@ EXPORT_SYMBOL(regulatory_hint);
-
- /* Caller must hold reg_mutex */
- static bool reg_same_country_ie_hint(struct wiphy *wiphy,
-- u32 country_ie_checksum)
-+ char *alpha2, enum environment_cap env)
- {
- struct wiphy *request_wiphy;
-
-@@ -2026,13 +1501,17 @@ static bool reg_same_country_ie_hint(struct wiphy *wiphy,
- return false;
-
- if (likely(request_wiphy != wiphy))
-- return !country_ie_integrity_changes(country_ie_checksum);
-+ return (last_request->alpha2[0] == alpha2[0] &&
-+ last_request->alpha2[1] == alpha2[1] &&
-+ last_request->country_ie_env == env);
- /*
- * We should not have let these through at this point, they
- * should have been picked up earlier by the first alpha2 check
- * on the device
- */
-- if (WARN_ON(!country_ie_integrity_changes(country_ie_checksum)))
-+ if (WARN_ON((last_request->alpha2[0] == alpha2[0] &&
-+ last_request->alpha2[1] == alpha2[1] &&
-+ last_request->country_ie_env == env )))
- return true;
- return false;
- }
-@@ -2048,7 +1527,6 @@ void regulatory_hint_11d(struct wiphy *wiphy,
- {
- struct ieee80211_regdomain *rd = NULL;
- char alpha2[2];
-- u32 checksum = 0;
- enum environment_cap env = ENVIRON_ANY;
- struct regulatory_request *request;
-
-@@ -2064,14 +1542,6 @@ void regulatory_hint_11d(struct wiphy *wiphy,
- if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
- goto out;
-
-- /*
-- * Pending country IE processing, this can happen after we
-- * call CRDA and wait for a response if a beacon was received before
-- * we were able to process the last regulatory_hint_11d() call
-- */
-- if (country_ie_regdomain)
-- goto out;
--
- alpha2[0] = country_ie[0];
- alpha2[1] = country_ie[1];
-
-@@ -2090,12 +1560,6 @@ void regulatory_hint_11d(struct wiphy *wiphy,
- wiphy_idx_valid(last_request->wiphy_idx)))
- goto out;
-
-- rd = country_ie_2_rd(band, country_ie, country_ie_len, &checksum);
-- if (!rd) {
-- REG_DBG_PRINT("cfg80211: Ignoring bogus country IE\n");
-- goto out;
-- }
--
- /*
- * This will not happen right now but we leave it here for the
- * the future when we want to add suspend/resume support and having
-@@ -2105,24 +1569,17 @@ void regulatory_hint_11d(struct wiphy *wiphy,
- * If we hit this before we add this support we want to be informed of
- * it as it would indicate a mistake in the current design
- */
-- if (WARN_ON(reg_same_country_ie_hint(wiphy, checksum)))
-+ if (WARN_ON(reg_same_country_ie_hint(wiphy, alpha2, env)))
- goto free_rd_out;
-
- request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL);
- if (!request)
- goto free_rd_out;
-
-- /*
-- * We keep this around for when CRDA comes back with a response so
-- * we can intersect with that
-- */
-- country_ie_regdomain = rd;
--
- request->wiphy_idx = get_wiphy_idx(wiphy);
-- request->alpha2[0] = rd->alpha2[0];
-- request->alpha2[1] = rd->alpha2[1];
-+ request->alpha2[0] = alpha2[0];
-+ request->alpha2[1] = alpha2[1];
- request->initiator = NL80211_REGDOM_SET_BY_COUNTRY_IE;
-- request->country_ie_checksum = checksum;
- request->country_ie_env = env;
-
- mutex_unlock(&reg_mutex);
-@@ -2383,33 +1840,6 @@ static void print_regdomain_info(const struct ieee80211_regdomain *rd)
- print_rd_rules(rd);
- }
-
--#ifdef CONFIG_CFG80211_REG_DEBUG
--static void reg_country_ie_process_debug(
-- const struct ieee80211_regdomain *rd,
-- const struct ieee80211_regdomain *country_ie_regdomain,
-- const struct ieee80211_regdomain *intersected_rd)
--{
-- printk(KERN_DEBUG "cfg80211: Received country IE:\n");
-- print_regdomain_info(country_ie_regdomain);
-- printk(KERN_DEBUG "cfg80211: CRDA thinks this should applied:\n");
-- print_regdomain_info(rd);
-- if (intersected_rd) {
-- printk(KERN_DEBUG "cfg80211: We intersect both of these "
-- "and get:\n");
-- print_regdomain_info(intersected_rd);
-- return;
-- }
-- printk(KERN_DEBUG "cfg80211: Intersection between both failed\n");
--}
--#else
--static inline void reg_country_ie_process_debug(
-- const struct ieee80211_regdomain *rd,
-- const struct ieee80211_regdomain *country_ie_regdomain,
-- const struct ieee80211_regdomain *intersected_rd)
--{
--}
--#endif
--
- /* Takes ownership of rd only if it doesn't fail */
- static int __set_regdom(const struct ieee80211_regdomain *rd)
- {
-@@ -2521,34 +1951,6 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
- return 0;
- }
-
-- /*
-- * Country IE requests are handled a bit differently, we intersect
-- * the country IE rd with what CRDA believes that country should have
-- */
--
-- /*
-- * Userspace could have sent two replies with only
-- * one kernel request. By the second reply we would have
-- * already processed and consumed the country_ie_regdomain.
-- */
-- if (!country_ie_regdomain)
-- return -EALREADY;
-- BUG_ON(rd == country_ie_regdomain);
--
-- /*
-- * Intersect what CRDA returned and our what we
-- * had built from the Country IE received
-- */
--
-- intersected_rd = regdom_intersect(rd, country_ie_regdomain);
--
-- reg_country_ie_process_debug(rd,
-- country_ie_regdomain,
-- intersected_rd);
--
-- kfree(country_ie_regdomain);
-- country_ie_regdomain = NULL;
--
- if (!intersected_rd)
- return -EINVAL;
-
-@@ -2688,9 +2090,6 @@ void /* __init_or_exit */ regulatory_exit(void)
-
- reset_regdomains();
-
-- kfree(country_ie_regdomain);
-- country_ie_regdomain = NULL;
--
- kfree(last_request);
-
- platform_device_unregister(reg_pdev);
---
-1.7.1.1
-
-
diff --git a/pci-acpi-disable-aspm-if-no-osc.patch b/pci-acpi-disable-aspm-if-no-osc.patch
deleted file mode 100644
index 044f38964..000000000
--- a/pci-acpi-disable-aspm-if-no-osc.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-From: Matthew Garrett <mjg@redhat.com>
-Subject: ACPI: Disable ASPM if the platform won't provide _OSC control for PCIe
-
-ACPI: Disable ASPM if the platform won't provide _OSC control for PCIe
-
-The PCI SIG documentation for the _OSC OS/firmware handshaking interface
-states:
-
-"If the _OSC control method is absent from the scope of a host bridge
-device, then the operating system must not enable or attempt to use any
-features defined in this section for the hierarchy originated by the host
-bridge."
-
-The obvious interpretation of this is that the OS should not attempt to use
-PCIe hotplug, PME or AER - however, the specification also notes that an
-_OSC method is *required* for PCIe hierarchies, and experimental validation
-with An Alternative OS indicates that it doesn't use any PCIe functionality
-if the _OSC method is missing. That arguably means we shouldn't be using
-MSI or extended config space, but right now our problems seem to be limited
-to vendors being surprised when ASPM gets enabled on machines when other
-OSs refuse to do so. So, for now, let's just disable ASPM if the _OSC
-method doesn't exist or refuses to hand over PCIe capability control.
-
-Signed-off-by: Matthew Garrett <mjg@redhat.com>
----
-
-diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
-index 4eac593..1f67057 100644
---- a/drivers/acpi/pci_root.c
-+++ b/drivers/acpi/pci_root.c
-@@ -33,6 +33,7 @@
- #include <linux/pm_runtime.h>
- #include <linux/pci.h>
- #include <linux/pci-acpi.h>
-+#include <linux/pci-aspm.h>
- #include <linux/acpi.h>
- #include <linux/slab.h>
- #include <acpi/acpi_bus.h>
-@@ -543,6 +544,14 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
- if (flags != base_flags)
- acpi_pci_osc_support(root, flags);
-
-+ status = acpi_pci_osc_control_set(root->device->handle,
-+ 0);
-+
-+ if (status == AE_NOT_EXIST) {
-+ printk(KERN_INFO "Unable to assume PCIe control: Disabling ASPM\n");
-+ pcie_no_aspm();
-+ }
-+
- pci_acpi_add_bus_pm_notifier(device, root->bus);
- if (device->wakeup.flags.run_wake)
- device_set_run_wake(root->bus->bridge, true);
diff --git a/pci-aspm-dont-enable-too-early.patch b/pci-aspm-dont-enable-too-early.patch
deleted file mode 100644
index ea91a2554..000000000
--- a/pci-aspm-dont-enable-too-early.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From: Matthew Garrett <mjg@redhat.com>
-Date: Wed, 9 Jun 2010 20:05:07 +0000 (-0400)
-Subject: PCI: Don't enable aspm before drivers have had a chance to veto it
-X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fjbarnes%2Fpci-2.6.git;a=commitdiff_plain;h=8f0b08c29f1df91315e48adce04462eb23671099
-
-PCI: Don't enable aspm before drivers have had a chance to veto it
-
-The aspm code will currently set the configured aspm policy before drivers
-have had an opportunity to indicate that their hardware doesn't support it.
-Unfortunately, putting some hardware in L0 or L1 can result in the hardware
-no longer responding to any requests, even after aspm is disabled. It makes
-more sense to leave aspm policy at the BIOS defaults at initial setup time,
-reconfiguring it after pci_enable_device() is called. This allows the
-driver to blacklist individual devices beforehand.
-
-Reviewed-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
-Signed-off-by: Matthew Garrett <mjg@redhat.com>
-Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
----
-
-diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
-index be53d98..7122281 100644
---- a/drivers/pci/pcie/aspm.c
-+++ b/drivers/pci/pcie/aspm.c
-@@ -588,11 +588,23 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
- * update through pcie_aspm_cap_init().
- */
- pcie_aspm_cap_init(link, blacklist);
-- pcie_config_aspm_path(link);
-
- /* Setup initial Clock PM state */
- pcie_clkpm_cap_init(link, blacklist);
-- pcie_set_clkpm(link, policy_to_clkpm_state(link));
-+
-+ /*
-+ * At this stage drivers haven't had an opportunity to change the
-+ * link policy setting. Enabling ASPM on broken hardware can cripple
-+ * it even before the driver has had a chance to disable ASPM, so
-+ * default to a safe level right now. If we're enabling ASPM beyond
-+ * the BIOS's expectation, we'll do so once pci_enable_device() is
-+ * called.
-+ */
-+ if (aspm_policy != POLICY_POWERSAVE) {
-+ pcie_config_aspm_path(link);
-+ pcie_set_clkpm(link, policy_to_clkpm_state(link));
-+ }
-+
- unlock:
- mutex_unlock(&aspm_lock);
- out:
diff --git a/scripts/pull-upstreams.sh b/scripts/pull-upstreams.sh
index e94fcfd48..11df40466 100755
--- a/scripts/pull-upstreams.sh
+++ b/scripts/pull-upstreams.sh
@@ -1,7 +1,6 @@
#!/bin/bash
utrace_base=2.6-current
-utrace_base=2.6.34
url=http://people.redhat.com/roland/utrace/${1:-$utrace_base}
diff --git a/sources b/sources
index 3b9d52ac3..efaf7e0cc 100644
--- a/sources
+++ b/sources
@@ -1,2 +1,2 @@
091abeb4684ce03d1d936851618687b6 linux-2.6.35.tar.bz2
-1e730019937132cd4d0bcf2c35384e86 patch-2.6.35-git1.bz2
+4f51963b5e076fb87ab32bda229a524f patch-2.6.36-rc1.bz2
diff --git a/utrace-ptrace-fix-build.patch b/utrace-ptrace-fix-build.patch
deleted file mode 100644
index c0de8764d..000000000
--- a/utrace-ptrace-fix-build.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 9b7ec0e07ce85c377b76626cef552d27d59cc405 Mon Sep 17 00:00:00 2001
-From: Kyle McMartin <kyle@dreadnought.i.jkkm.org>
-Date: Tue, 22 Jun 2010 13:57:47 +0100
-Subject: utrace-ptrace: removed defunct arch_ptrace_untrace call
-
-commit faa4602e removed the unused BTS code which had added
-this hook.
-
-Signed-off-by: Kyle McMartin <kyle@redhat.com>
----
- kernel/ptrace-utrace.c | 2 --
- 1 files changed, 0 insertions(+), 2 deletions(-)
-
-diff --git a/kernel/ptrace-utrace.c b/kernel/ptrace-utrace.c
-index 86234ee..1a8ba5e 100644
---- a/kernel/ptrace-utrace.c
-+++ b/kernel/ptrace-utrace.c
-@@ -50,8 +50,6 @@ void __ptrace_unlink(struct task_struct *child)
- child->ptrace = 0;
- child->parent = child->real_parent;
- list_del_init(&child->ptrace_entry);
--
-- arch_ptrace_untrace(child);
- }
-
- struct ptrace_context {
---
-1.7.0.1
-
diff --git a/utrace-remove-use-of-kref_set.patch b/utrace-remove-use-of-kref_set.patch
deleted file mode 100644
index f696f81fb..000000000
--- a/utrace-remove-use-of-kref_set.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From ad778e66100e4b76bab6b939e3d0c781da82d980 Mon Sep 17 00:00:00 2001
-From: Kyle McMartin <kyle@dreadnought.i.jkkm.org>
-Date: Tue, 22 Jun 2010 14:09:30 +0100
-Subject: utrace: remove use of kref_set
-
-Unfortunatey db1afffa which removed kref_set did not anticipate
-anyone would actually like to use a kref which starts with a refcnt
-above 1. Replace kref_set in utrace with a kref_init + kref_get to
-immediately bump the reference count.
-
-Signed-off-by: Kyle McMartin <kyle@redhat.com>
----
- kernel/utrace.c | 3 ++-
- 1 files changed, 2 insertions(+), 1 deletions(-)
-
-diff --git a/kernel/utrace.c b/kernel/utrace.c
-index f5a9e2c..cc864d5 100644
---- a/kernel/utrace.c
-+++ b/kernel/utrace.c
-@@ -304,7 +304,8 @@ struct utrace_engine *utrace_attach_task(
- * Initialize the new engine structure. It starts out with two
- * refs: one ref to return, and one ref for being attached.
- */
-- kref_set(&engine->kref, 2);
-+ kref_init(&engine->kref);
-+ kref_get(&engine->kref);
- engine->flags = 0;
- engine->ops = ops;
- engine->data = data;
---
-1.7.0.1
-