diff --git a/packages/audio/alsa/config/asound.conf b/packages/audio/alsa/config/asound.conf new file mode 100644 index 0000000000..faac879698 --- /dev/null +++ b/packages/audio/alsa/config/asound.conf @@ -0,0 +1,69 @@ +pcm.!default { +type plug +slave { +pcm "both" +} +} + +pcm.both { +type route +slave { +pcm multi +channels 6 +} +ttable.0.0 1.0 +ttable.1.1 1.0 +ttable.0.2 1.0 +ttable.1.3 1.0 +ttable.0.4 1.0 +ttable.1.5 1.0 +} + +pcm.multi { +type multi +slaves.a { +pcm "tv" +channels 2 +} +slaves.b { +pcm "receiver" +channels 2 +} +slaves.c { +pcm "analog" +channels 2 +} +bindings.0.slave a +bindings.0.channel 0 +bindings.1.slave a +bindings.1.channel 1 +bindings.2.slave b +bindings.2.channel 0 +bindings.3.slave b +bindings.3.channel 1 +bindings.4.slave c +bindings.4.channel 0 +bindings.5.slave c +bindings.5.channel 1 +} + +pcm.tv { +type hw +card 0 +device 3 +channels 2 +} + +pcm.receiver { +type hw +card 0 +device 1 +channels 2 +} + +pcm.analog { +type hw +card 0 +device 0 +channels 2 +} diff --git a/packages/linux/patches/linux-2.6.33-02-add_lirc_driver_nct667x-0.5.diff b/packages/linux/patches/linux-2.6.33-02-add_lirc_driver_nct667x-0.5.diff new file mode 100644 index 0000000000..44fb32e0ce --- /dev/null +++ b/packages/linux/patches/linux-2.6.33-02-add_lirc_driver_nct667x-0.5.diff @@ -0,0 +1,3700 @@ +diff -Naur linux-2.6.33.2/drivers/input/lirc/Kconfig linux-2.6.33.2.patch/drivers/input/lirc/Kconfig +--- linux-2.6.33.2/drivers/input/lirc/Kconfig 2010-04-03 18:40:52.365577611 +0200 ++++ linux-2.6.33.2.patch/drivers/input/lirc/Kconfig 2010-04-03 18:42:04.203701785 +0200 +@@ -64,6 +64,12 @@ + help + Driver for Windows Media Center Ed. USB IR Transceivers + ++config LIRC_NCT667X ++ tristate "Nuvolo (Winbond) 667x IR Transeiver" ++ depends on INPUT_LIRC && PNP ++ help ++ Driver for Nuvolo (Winbond) 667x IR Transeiver IR Transceivers ++ + config LIRC_PARALLEL + tristate "Homebrew Parallel Port Receiver" + depends on INPUT_LIRC && !SMP +diff -Naur linux-2.6.33.2/drivers/input/lirc/lirc_wb677_common_extern.h linux-2.6.33.2.patch/drivers/input/lirc/lirc_wb677_common_extern.h +--- linux-2.6.33.2/drivers/input/lirc/lirc_wb677_common_extern.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.33.2.patch/drivers/input/lirc/lirc_wb677_common_extern.h 2010-04-03 18:46:59.068576829 +0200 +@@ -0,0 +1,118 @@ ++#ifndef __LIRC_WB677_COMMON_EXTERN_HEADER__ ++#define __LIRC_WB677_COMMON_EXTERN_HEADER__ ++ ++#include ++ ++#include ++#include "lirc_dev.h" ++ ++extern char *DRVNAME; ++ ++/* chip id string, at most 7 characters */ ++extern char *chip_id; ++ ++ ++ ++ ++/* allow show debug messages ++ * without additional debug setting, only show current IRQ number, I/O port and final decode output */ ++/*//#define IR_667_DEBUG*/ ++ ++/* show debug message while decode mce keyboard and mouse signals */ ++#ifdef IR_667_DEBUG ++/*//#define ALLOW_DEBUG_DECODE*/ ++#endif ++ ++/* show incoming interrupt signals ++ * may block machine, mask it if sure interrupt signal is good */ ++#ifdef IR_667_DEBUG ++/*//#define ALLOW_DEBUG_INTERRUPT*/ ++#endif ++ ++/* show received infrared pulse and cancel decode functions, mask it in stable version ++ * it will stop decode MCE controller, keyboard and mouse ++ * mask it if want to decode incoming signals ++ */ ++#ifdef IR_667_DEBUG ++/*//#define ALLOW_DEBUG_PRINT_PULSE*/ ++#endif ++ ++/* show debug message while set WAKE UP key ++ * it will print cir_wake buf message while setting wake up key ++ * mask it in stable version ++ */ ++#ifdef IR_667_DEBUG ++#define ALLOW_DEBUG_WAKE ++#endif ++ ++/* show STUDY debug messages */ ++#ifdef IR_667_DEBUG ++#define ALLOW_DEBUG_STUDY ++#endif ++ ++/* show ioctl debug messages */ ++#ifdef IR_667_DEBUG ++#define ALLOW_DEBUG_IOCTL ++#endif ++ ++/* step debug */ ++#ifdef IR_667_DEBUG ++#define ALLOW_DEBUG_STEP ++#endif ++ ++#ifdef ALLOW_DEBUG_STEP ++#define STEP_DBG \ ++ do { \ ++ printk("w83667hg_ir step debug: %s, %d\n", __FILE__, __LINE__); \ ++ } while (0); ++#else ++#define STEP_DBG ++#endif ++ ++#ifdef ALLOW_DEBUG_PRINT_PULSE ++/* print current received ir pulse ++ * it will output all data, clean CIR_IRSTS so make all following irq_handler ignore ++ */ ++void debug_print_pulse(void); ++ ++void debug_print_wake_pulse(void); ++#endif ++ ++ ++ ++ ++/* register lirc device & buffer */ ++ ++/* mininum value 76, recommend 256 */ ++#define IRCTL_BUF_LIMIT 2048 ++ ++ ++struct irctl { ++ struct input_dev *input_dev; /* allocate by input_init */ ++ struct lirc_buffer *lirc_buffer; ++ struct lirc_driver *lirc_plugin; ++ spinlock_t lock; ++ /* for controller */ ++ int lircdata; ++ u8 ctrl_fix_head; /* fix controller not sync problem*/ ++ /* for keyboard */ ++ u8 pressed_keycode; /* initialize as 0*/ ++ u8 pressed_shiftmask; /* initialize as 0*/ ++ /* for decode */ ++ u8 buf[IRCTL_BUF_LIMIT]; ++ unsigned int buf_count; /* init as 0, reset 0 after decode*/ ++ unsigned int cur_buf_num; /* init as 0, set as 0 while clean*/ ++ /* for study */ ++#define ST_STUDY_NONE 0x0 ++#define ST_STUDY_START 0x01 ++#define ST_STUDY_CARRIER 0x02 ++#define ST_STUDY_ALL_RECV 0x04 ++ u8 study_state; ++ /* carrier period = 1 / frequency */ ++ unsigned int carrier; ++ wait_queue_head_t queue; ++}; ++ ++extern unsigned int usb_kbd_keycode[256]; ++ ++#endif +diff -Naur linux-2.6.33.2/drivers/input/lirc/lirc_wb677.h linux-2.6.33.2.patch/drivers/input/lirc/lirc_wb677.h +--- linux-2.6.33.2/drivers/input/lirc/lirc_wb677.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.33.2.patch/drivers/input/lirc/lirc_wb677.h 2010-04-03 18:47:28.580576601 +0200 +@@ -0,0 +1,683 @@ ++/* ++* LIRC driver for Nuvoton w83667hg/w83677hg-i ++* ++* Copyright (C) 2009 Nuvoton PS Team ++* ++* 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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/*//#include */ ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++ ++ ++#include "lirc_wb677_common_extern.h" ++ ++ ++ ++/* CIR settings */ ++ ++/* total length of CIR and CIR WAKE */ ++#define CIR_IOREG_LENGTH 0x0f ++ ++/* RX limit length, 8 high bits for SLCH, 8 low bits for SLCL ++ * 0x7d0 = 2000 */ ++#define CIR_RX_LIMIT_COUNT 0x7d0 ++ ++/* CIR Regs */ ++#define CIR_IRCON 0x00 ++#define CIR_IRSTS 0x01 ++#define CIR_IREN 0x02 ++#define CIR_RXFCONT 0x03 ++#define CIR_CP 0x04 ++#define CIR_CC 0x05 ++#define CIR_SLCH 0x06 ++#define CIR_SLCL 0x07 ++#define CIR_FIFOCON 0x08 ++#define CIR_IRFIFOSTS 0x09 ++#define CIR_SRXFIFO 0x0A ++#define CIR_TXFCONT 0x0B ++#define CIR_STXFIFO 0x0C ++#define CIR_FCCH 0x0D ++#define CIR_FCCL 0x0E ++#define CIR_IRFSM 0x0F ++ ++/* CIR IRCON settings */ ++#define CIR_IRCON_RECV 0x80 ++#define CIR_IRCON_WIREN 0x40 ++#define CIR_IRCON_TXEN 0x20 ++#define CIR_IRCON_RXEN 0x10 ++#define CIR_IRCON_WRXINV 0x08 ++#define CIR_IRCON_RXINV 0x04 ++ ++#define CIR_IRCON_SAMPLE_PERIOD_SEL_1 0x00 ++#define CIR_IRCON_SAMPLE_PERIOD_SEL_25 0x01 ++#define CIR_IRCON_SAMPLE_PERIOD_SEL_50 0x02 ++#define CIR_IRCON_SAMPLE_PERIOD_SEL_100 0x03 ++ ++/* select sample period as 50us */ ++#define CIR_IRCON_SAMPLE_PERIOD_SEL CIR_IRCON_SAMPLE_PERIOD_SEL_50 ++ ++/* CIR IRSTS settings */ ++#define CIR_IRSTS_RDR 0x80 ++#define CIR_IRSTS_RTR 0x40 ++#define CIR_IRSTS_PE 0x20 ++#define CIR_IRSTS_RFO 0x10 ++#define CIR_IRSTS_TE 0x08 ++#define CIR_IRSTS_TTR 0x04 ++#define CIR_IRSTS_TFU 0x02 ++#define CIR_IRSTS_GH 0x01 ++ ++/* CIR IREN settings */ ++#define CIR_IREN_RDR 0x80 ++#define CIR_IREN_RTR 0x40 ++#define CIR_IREN_PE 0x20 ++#define CIR_IREN_RFO 0x10 ++#define CIR_IREN_TE 0x08 ++#define CIR_IREN_TTR 0x04 ++#define CIR_IREN_TFU 0x02 ++#define CIR_IREN_GH 0x01 ++ ++/* CIR FIFOCON settings */ ++#define CIR_FIFOCON_TXFIFOCLR 0x80 ++ ++#define CIR_FIFOCON_TX_TRIGGER_LEV_31 0x00 ++#define CIR_FIFOCON_TX_TRIGGER_LEV_24 0x10 ++#define CIR_FIFOCON_TX_TRIGGER_LEV_16 0x20 ++#define CIR_FIFOCON_TX_TRIGGER_LEV_8 0x30 ++ ++/* select TX trigger level as 16 */ ++#define CIR_FIFOCON_TX_TRIGGER_LEV CIR_FIFOCON_TX_TRIGGER_LEV_16 ++ ++#define CIR_FIFOCON_RXFIFOCLR 0x08 ++ ++#define CIR_FIFOCON_RX_TRIGGER_LEV_1 0x00 ++#define CIR_FIFOCON_RX_TRIGGER_LEV_8 0x01 ++#define CIR_FIFOCON_RX_TRIGGER_LEV_16 0x02 ++#define CIR_FIFOCON_RX_TRIGGER_LEV_24 0x03 ++ ++/* select RX trigger level as 1 */ ++#define CIR_FIFOCON_RX_TRIGGER_LEV CIR_FIFOCON_RX_TRIGGER_LEV_1 ++ ++/* CIR IRFIFOSTS settings */ ++#define CIR_IRFIFOSTS_IR_PENDING 0x80 ++#define CIR_IRFIFOSTS_RX_GS 0x40 ++#define CIR_IRFIFOSTS_RX_FTA 0x20 ++#define CIR_IRFIFOSTS_RX_EMPTY 0x10 ++#define CIR_IRFIFOSTS_RX_FULL 0x08 ++#define CIR_IRFIFOSTS_TX_FTA 0x04 ++#define CIR_IRFIFOSTS_TX_EMPTY 0x02 ++#define CIR_IRFIFOSTS_TX_FULL 0x01 ++ ++ ++/* CIR WAKE UP Regs */ ++#define CIR_WAKE_IRCON 0x00 ++#define CIR_WAKE_IRSTS 0x01 ++#define CIR_WAKE_IREN 0x02 ++#define CIR_WAKE_FIFO_CMP_DEEP 0x03 ++#define CIR_WAKE_FIFO_CMP_TOL 0x04 ++#define CIR_WAKE_FIFO_COUNT 0x05 ++#define CIR_WAKE_SLCH 0x06 ++#define CIR_WAKE_SLCL 0x07 ++#define CIR_WAKE_FIFOCON 0x08 ++#define CIR_WAKE_SRXFSTS 0x09 ++#define CIR_WAKE_SAMPLE_RX_FIFO 0x0A ++#define CIR_WAKE_WR_FIFO_DATA 0x0B ++#define CIR_WAKE_RD_FIFO_ONLY 0x0C ++#define CIR_WAKE_RD_FIFO_ONLY_IDX 0x0D ++#define CIR_WAKE_FIFO_IGNORE 0x0E ++#define CIR_WAKE_IRFSM 0x0F ++ ++/* CIR WAKE UP IRCON settings */ ++#define CIR_WAKE_IRCON_DEC_RST 0x80 ++#define CIR_WAKE_IRCON_MODE1 0x40 ++#define CIR_WAKE_IRCON_MODE0 0x20 ++#define CIR_WAKE_IRCON_RXEN 0x10 ++#define CIR_WAKE_IRCON_R 0x08 ++#define CIR_WAKE_IRCON_RXINV 0x04 ++ ++/* select a same sample period like cir register */ ++#define CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL CIR_IRCON_SAMPLE_PERIOD_SEL_50 ++ ++/* CIR WAKE UP IRSTS settings */ ++#define CIR_WAKE_IRSTS_RDR 0x80 ++#define CIR_WAKE_IRSTS_RTR 0x40 ++#define CIR_WAKE_IRSTS_PE 0x20 ++#define CIR_WAKE_IRSTS_RFO 0x10 ++#define CIR_WAKE_IRSTS_GH 0x08 ++#define CIR_WAKE_IRSTS_IR_PENDING 0x01 ++ ++/* CIR WAKE UP IREN settings */ ++#define CIR_WAKE_IREN_RDR 0x80 ++#define CIR_WAKE_IREN_RTR 0x40 ++#define CIR_WAKE_IREN_PE 0x20 ++#define CIR_WAKE_IREN_RFO 0x10 ++#define CIR_WAKE_IREN_TE 0x08 ++#define CIR_WAKE_IREN_TTR 0x04 ++#define CIR_WAKE_IREN_TFU 0x02 ++#define CIR_WAKE_IREN_GH 0x01 ++ ++/* CIR WAKE FIFOCON settings */ ++#define CIR_WAKE_FIFOCON_RXFIFOCLR 0x08 ++ ++#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67 0x00 ++#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_66 0x01 ++#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_65 0x02 ++#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_64 0x03 ++ ++/* select WAKE UP RX trigger level as 67 */ ++#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67 ++ ++/* CIR WAKE SRXFSTS settings */ ++#define CIR_WAKE_IRFIFOSTS_RX_GS 0x80 ++#define CIR_WAKE_IRFIFOSTS_RX_FTA 0x40 ++#define CIR_WAKE_IRFIFOSTS_RX_EMPTY 0x20 ++#define CIR_WAKE_IRFIFOSTS_RX_FULL 0x10 ++ ++ ++ ++ ++/* Config Regs */ ++ ++/* Chip Control Regs */ ++#define cr_cfg_idx 0x2e ++#define cr_cfg_dat 0x2f ++ ++#define cr_cfg_idx2 0x4e ++#define cr_cfg_dat2 0x4f ++ ++static u8 CFG_idx = cr_cfg_idx; ++static u8 CFG_dat = cr_cfg_dat; ++ ++#define CHIP_ID_HIGH_ADDR 0x20 ++#define CHIP_ID_LOW_ADDR 0x21 ++ ++#define CHIP_ID_HIGH 0xB4 ++#define CHIP_ID_LOW 0x73 ++ ++#define ACTIVE_LOG_DEV 0x01 ++#define DEACTIVE_LOG_DEV 0x0 ++ ++#define CIR_LOG_DEV 0x06 ++ ++#define ACPI_LOG_DEV 0x0A ++ ++#define ENABLE_CIR_WAKE 0x08 ++#define DISABLE_CIR_WAKE 0xF7 ++ ++#define ENABLE_CIR_INTR_OF_MOUSE_IRQ 0x80 ++#define DISABLE_CIR_INTR_OF_MOUSE_IRQ 0x7F ++ ++#define ENABLE_PME_INTR_OF_CIR_PASS 0x08 ++#define DISABLE_PME_INTR_OF_CIR_PASS 0xF7 ++ ++#define CIR_WAKE_LOG_DEV 0x0E ++ ++ ++/* read/update registers functions */ ++ ++/* enter extended function mode */ ++static inline void cr_enter_ext(void); ++ ++/* exit extended function mode */ ++static inline void cr_exit_ext(void); ++ ++/* select logical device */ ++static inline void cr_select_log_dev(int cr); ++ ++static inline void cr_update(int dat, int cr); ++ ++static inline u8 cr_read(int cr); ++ ++/* update cr register without change other bits */ ++static inline void cr_safe_update(u8 dat, int cr); ++ ++/* clear cr register without change other bits */ ++static inline void cr_safe_clear(u8 dat, int cr); ++ ++ ++ ++/* read/write cir registers */ ++ ++static inline void cir_update(u8 dat, int cir); ++ ++static u8 cir_read(int cir); ++ ++/* read/write cir wake registers */ ++ ++static inline void cir_wake_update(u8 dat, int cir); ++ ++static u8 cir_wake_read(int cir); ++ ++ ++/* dump current cir registers */ ++static void cir_dump_reg(void); ++ ++/* dump current cir wake up registers */ ++static void cir_wake_dump_reg(void); ++ ++ ++ ++ ++ ++/* driver module load/unload functions */ ++ ++/* Config Registers init */ ++/* ++ * initialize cr, cir, apci, cir wake logical devices ++ * open these devices and irq ++ */ ++static int w83667hg_cr_init(void); ++ ++/* Config Registers uninit */ ++/* ++ * close cir and cir wake logical devices ++ */ ++static void w83667hg_cr_uninit(void); ++ ++ ++/* register input device (keyboard and mouse) ++ * ++ */ ++ ++/* Define it for decoding keyboard and mouse in driver */ ++#define DECODE_KEYBOARD_MOUSE ++ ++/* this is the keycode table of US-EN layout keyboard ++ * modify it to support other layout keyboard ++ */ ++unsigned int usb_kbd_keycode[256] = { ++ 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, ++ 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, ++ 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, ++ 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, ++ 65, 66, 67, 68, 87, 88, 99, 70, 119, 110, 102, 104, 111, 107, 109, 106, ++ 105, 108, 103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, ++ 72, 73, 82, 83, 86, 127, 116, 117, 183, 184, 185, 186, 187, 188, 189, 190, ++ 191, 192, 193, 194, 134, 138, 130, 132, 128, 129, 131, 137, 133, 135, 136, 113, ++ 115, 114, 0, 0, 0, 121, 0, 89, 93, 124, 92, 94, 95, 0, 0, 0, ++ 122, 123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ++ 29, 42, 56, 125, 97, 54, 100, 126, 164, 166, 165, 163, 161, 115, 114, 113, ++ 150, 158, 159, 128, 136, 177, 178, 176, 142, 152, 173, 140 ++}; ++ ++/* input device name, locate in /sys/input/inputNUM/name */ ++static char *INPUTNAME = "MCE Remote Keyboard"; ++ ++static struct input_id w83667hg_input_id = { ++ .bustype = BUS_HOST, /* comunicate 667 by HOST, or I2C ? */ ++ .vendor = 0x1050, /* Winbond PCI VENDOR ID */ ++ .product = 1, /* for basic devices, like keyboard & mouse */ ++ .version = 0, /* ignore it */ ++}; ++ ++ ++static int w83667hg_input_open(struct input_dev *cur_input_dev); ++ ++static void w83667hg_input_close(struct input_dev *cur_input_dev); ++ ++static struct input_dev *w83667hg_input_init(void); ++ ++static void w83667hg_input_uninit(struct input_dev *cur_input_dev); ++ ++/* internal call for register lirc */ ++static int lirc_set_use_inc(void *data); ++ ++static void lirc_set_use_dec(void *data); ++ ++ ++ ++static struct ir_recv_t { ++ spinlock_t lock; ++ u8 buf[IRCTL_BUF_LIMIT]; ++ unsigned int buf_count; ++ wait_queue_head_t queue; ++ /* for wake */ ++#define ST_WAKE_NONE 0x0 ++#define ST_WAKE_START 0x01 ++#define ST_WAKE_FINISH 0x02 ++ u8 wake_state; ++ /* for recv */ ++#define ST_RECV_WAIT_7F 0x01 ++#define ST_RECV_WAIT_HEAD 0x02 ++#define ST_RECV_WAIT_SILENT_END 0x04 ++ u8 recv_state; ++} w83667hg_ir_recv; ++ ++static struct ir_send_t { ++ spinlock_t lock; ++ u8 buf[IRCTL_BUF_LIMIT]; ++ unsigned int buf_count; ++ unsigned int cur_buf_num; ++ wait_queue_head_t queue; ++ /* for send */ ++#define ST_SEND_NONE 0x0 ++#define ST_SEND_REQUEST 0x02 ++#define ST_SEND_REPLY 0x04 ++ u8 send_state; ++} w83667hg_ir_send; ++ ++/* We initialise it at lirc_wb667_init() becuase of lirc group does not allow to initialise static varialbe to null.*/ ++static struct input_dev *w83667hg_input_dev; ++ ++/* We initialise it at lirc_wb667_init() becuase of lirc group does not allow to initialise static varialbe to null.*/ ++static struct lirc_driver *w83667hg_lirc_plugin; ++ ++#define LIRCBUF_SIZE 256 ++ ++/* We initialise it at lirc_wb667_init() becuase of lirc group does not allow to initialise static varialbe to null.*/ ++static struct lirc_buffer *w83667hg_lirc_buffer; ++ ++static void w83667hg_ir_recv_init(struct ir_recv_t *ir_recv); ++ ++static void w83667hg_ir_send_init(struct ir_send_t *ir_send); ++ ++static int w83667hg_irctl_init(struct irctl *ir); ++ ++static void w83667hg_irctl_uninit(struct irctl *ir); ++ ++ ++ ++ ++/* MCE CIR signal length, related on sample period */ ++ ++/* MCE CIR controller signal length: about 43ms ++ * 43ms / 50us (sample period) * 0.85 (inaccuracy) ++ */ ++#define CONTROLLER_BUF_LEN_MIN 830 ++ ++/* MCE CIR keyboard signal length: about 26ms ++ * 26ms / 50us (sample period) * 0.85 (inaccuracy) ++ */ ++#define KEYBOARD_BUF_LEN_MAX 650 ++#define KEYBOARD_BUF_LEN_MIN 610 ++ ++/* MCE CIR mouse signal length: about 24ms ++ * 24ms / 50us (sample period) * 0.85 (inaccuracy) ++ */ ++#define MOUSE_BUF_LEN_MIN 565 ++ ++ ++#define CIR_SAMPLE_PERIOD 50 ++#define CIR_SAMPLE_LOW_INACCURACY 0.85 ++ ++ ++/* MAX silence time that driver will sent to lirc */ ++#define MAX_SILENCE_TIME 60000 ++ ++ ++/* fops */ ++/* set carrier frequency by ioctl IR_IOSETCARRIER ++ * ++ * that value can be get by ioctl value IR_IOGETCARRIER ++ * on 667, set carrier on 2 registers: CP & CC ++ * always set CP as 0x81 ++ * set CC by SPEC, CC = 3MHz/carrier - 1 ++ */ ++static int w83667hg_set_carrier(unsigned int *carrier); ++ ++static int lirc_ioctl(struct inode *node, struct file *filep, unsigned int cmd, ++ unsigned long arg); ++ ++/* lirc_write ++ * ++ * 1) clean TX fifo first (handled by AP) ++ * 2) copy data from user space ++ * 3) open TX interrupt: TTR & TFU ++ * 4) send 9 pulses to open TTR ++ * in interrupt_handler: ++ * 5) send all data out ++ * go back to write(): ++ * 6) close TX interrupt ++ * ++ * The key problem of this function is user space data may larger than ++ * driver's data buf length. So lirc_wirte() only copy IRCTL_BUF_LIMIT data to ++ * buf. And keep current copied data buf num in cur_buf_num. But driver's buf ++ * number may larger than TXFCONT (0xFF). So in interrupt_handler, it has to ++ * set TXFCONT as 0xff, until buf_count less than 0xff. ++ * The confustion is cur_buf_num in decode, study and send is designed on ++ * different meaning. ++ * ++ */ ++static ssize_t lirc_write(struct file *file, const char *buf, size_t n, loff_t * ppos); ++ ++ ++ ++/* 1) clean lircdata and buf_count in irctl struct ++ * 2) clean RX and TX fifo ++ */ ++static void w83667hg_clean_data(struct ir_recv_t *ir_recv, struct irctl *ir); ++ ++ ++ ++ ++/* send 1 recorded controller signal to lirc */ ++static void w83667hg_send_packet_to_lirc_1(struct irctl *ir, int *val); ++ ++/* this value copy from lirc_mod_mce */ ++#if CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_100 ++ #define MCE_TIME_UNIT 100 ++#elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_50 ++ #define MCE_TIME_UNIT 50 ++#elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_25 ++ #define MCE_TIME_UNIT 25 ++#else ++ #define MCE_TIME_UNIT 1 ++#endif ++ ++/* recode mce controller signal and send to lirc ++ * ++ * recode steps: ++ * 1) high pulse, +128 ++ * 2) low pulse, do nothing ++ * 3) keycode = pulse * 50 ++ * 4) sync head: PULSE_MASK (0xFF FFFF) ++ * 5) 1, |PULSE_BIT (0x100 0000) ++ * 0, +keycode ++ * ++ * function steps: ++ * 0) clean lircdata[] ++ * 1) jump head, put PULSE_BIT in lircdata[0] ++ * 2) normal decode, "10"=>1 |PULSE_BIT ++ * save in lircdata[] ++ * 3) send lircdata[] to lirc ++ */ ++static void w83667hg_submit_controller(struct irctl *ir); ++ ++ ++/* copy data from hardware fifo to driver buf ++ * ++ * 1. initial state is WAIT_7F ++ * 2. if data is not 0x7f, copy data from hardware fifo to struct ir_recv buf ++ * 3. if data is 0x7f, set recv_state as WAIT_HEAD, copy data from ir_recv to irctl ++ * 4. depend on received buf length to select submit_ function ++ * 5. set irctl buf len as 0 ++ * 5. receive data until data is not 0x7f, drop received 0x7f data, set recv_state as WAIT_7F again ++ * ++ * in normal, there are 3 parts in one infrared signal: ++ * 1. not silent pulse (ST_WAIT_7F) ++ * 2. 0x7f silent pulse (ST_WAIT_HEAD) ++ * 3. silent pulse shorter than 0x7f (ST_WAIT_HEAD) ++ * ++ * so this function copy signal part 1 and a 0x7f (for decode) to submit_() functions. ++ * when receive 0x7f, this function copy data from ir_recv to irctl, and wait for next high pulse. ++ */ ++static void w83667hg_recv(struct ir_recv_t *ir_recv, struct irctl *ir); ++ ++ ++/* as VISTA MCE definition, valid carrier value */ ++#define MAX_CARRIER 60000 ++#define MIN_CARRIER 30000 ++ ++/* receive function for STUDY ++ * ++ * 0. not receive 0x80, copy received data to ir_recv buf ++ * when get 0x80, it means user released controller, and only need process received data ++ * 1. get carrier ++ * 2. get pulse ++ */ ++static void w83667hg_study_recv(struct ir_recv_t *ir_recv, struct irctl *ir); ++ ++static irqreturn_t w83667hg_wake_interrupt_handler(int irq, void *dev); ++ ++static irqreturn_t w83667hg_interrupt_handler(int irq, void *dev); ++ ++ ++/* pnp device */ ++#ifdef CONFIG_PNP ++ ++ ++/* CIR and CIR WAKE */ ++static const struct pnp_device_id pnp_dev_table[] = { ++ { "WEC0530", 0 }, /* CIR */ ++ { "NTN0530", 0 }, /* CIR for new chip's pnp id*/ ++ { "", 0 }, ++}; ++ ++ ++MODULE_DEVICE_TABLE(pnp, pnp_dev_table); ++ ++static int __devinit lirc_wb667_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id); ++ ++static void __devexit lirc_wb667_pnp_remove(struct pnp_dev *dev); ++ ++/* before suspend ++ * 1. set all states as NONE ++ * 2. close CIR and WAKE interrupt ++ * 3. close CIR and WAKE cr ++ * 4. close input ++ */ ++static int lirc_wb667_pnp_suspend(struct pnp_dev *dev, pm_message_t state); ++ ++/* resume all register and input device ++ */ ++static int lirc_wb667_pnp_resume(struct pnp_dev *dev); ++ ++/* We initialise it as lirc_wb667_init because lirc group does not allow us to initialise static vaiable as 0 here. */ ++static unsigned int nopnp; ++ ++#else ++ ++/* We initialise it as lirc_lirc_wb667_init because lirc group does not allow us to initialise static vaiable as 0 here. */ ++static unsigned int nopnp; ++ ++#endif ++ ++ ++/* create io region for cir and cir wake ++ * create irq handler ++ * create dev and data struct ++ */ ++static int w83667hg_cir_probe(void); ++ ++/* uninit cir, cir wake, dev and data struct, release irq and io port */ ++static void w83667hg_cir_remove(void); ++ ++ ++static int lirc_wb667_init(void); ++ ++void lirc_wb667_uninit(void); ++ ++ ++/* ++ * 1. init cr ++ * 2. init input ++ * 3. init lirc buffer, register, irctl ++ * 4. init 667 cir dev, req_region, req_irq ++ */ ++/*int init_module(void); ++void cleanup_module(void);*/ ++int init_module_wb667(void); ++void cleanup_module_wb667(void); ++ ++MODULE_DESCRIPTION("LIRC driver for Nuvoton W83667HG-A & W83677HG CIR"); ++MODULE_AUTHOR("Nuvoton PS Team"); ++MODULE_LICENSE("GPL"); ++ ++/* device file name, locate in /dev/ directory */ ++/*//static char *DRVNAME = "w83667hg_ir";*/ ++/* FIXME, stable name*/ ++char *DRVNAME = "lirc_wb677"; ++module_param(DRVNAME, charp, S_IRUGO); ++MODULE_PARM_DESC(DRVNAME, "Device file name in /dev/ and /sys/class/."); ++ ++/* platform driver name to register */ ++#define PLATNAME "lirc_wb677_cir" ++#define PLATNAME_W "lirc_wb667_wake" ++ ++/* device file major number */ ++#define CIR_MAJOR 229 ++ ++/* cir device base address */ ++static u16 CIR_BASE = 0x240; ++module_param(CIR_BASE, ushort, S_IRUGO); ++MODULE_PARM_DESC(CIR_BASE, "Base IO port address of 667/677 CIR device."); ++ ++/* cir base i/o address */ ++static unsigned int cir_address; ++ ++/* cir irq */ ++static ushort CIR_IRQ_NUM = 5; ++module_param(CIR_IRQ_NUM, ushort, S_IRUGO); ++MODULE_PARM_DESC(CIR_IRQ_NUM, "IRQ number for 667/677 CIR device."); ++ ++/* handle cir wake up request in driver or not */ ++#define ENABLE_CIR_WAKE_IRQ ++ ++/* cir wake up device base address */ ++static u16 CIR_WAKE_BASE = 0x250; ++module_param(CIR_WAKE_BASE, ushort, S_IRUGO); ++MODULE_PARM_DESC(CIR_WAKE_BASE, "Base IO port address of 667/677 CIR WAKE device."); ++ ++/* cir wake up base i/o address */ ++static unsigned int cir_wake_address; ++ ++/* cir wake up irq */ ++static ushort CIR_WAKE_IRQ_NUM = 5; ++module_param(CIR_WAKE_IRQ_NUM, ushort, S_IRUGO); ++MODULE_PARM_DESC(CIR_WAKE_IRQ_NUM, "IRQ number for 667/677 CIR WAKE device."); ++ ++/* nopnp option */ ++#ifdef CONFIG_PNP ++module_param(nopnp, uint, S_IRUGO); ++MODULE_PARM_DESC(nopnp, "Scan for device instead of relying on PNP. (default 0)"); ++#endif ++ ++/*//EXPORT_NO_SYMBOLS;*/ ++ ++ ++ +diff -Naur linux-2.6.33.2/drivers/input/lirc/lirc_wb677_main.c linux-2.6.33.2.patch/drivers/input/lirc/lirc_wb677_main.c +--- linux-2.6.33.2/drivers/input/lirc/lirc_wb677_main.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.33.2.patch/drivers/input/lirc/lirc_wb677_main.c 2010-04-04 00:13:44.035576247 +0200 +@@ -0,0 +1,1723 @@ ++#define _GNU_SOURCE ++#include ++#include ++ ++#define MOD_INC_USE_COUNT ++#define MOD_DEC_USE_COUNT ++ ++#include "lirc_wb677.h" ++#include "lirc_wb677_mouse_kbd.h" ++#include "wb83677hg_ir.h" ++ ++struct irctl w83667hg_irctl; ++ ++/* chip id string, at most 7 characters */ ++char *chip_id = "w677hga"; ++ ++ ++ ++ ++/* enter extended function mode */ ++static inline void cr_enter_ext(void) ++{ ++ outb(0x87, CFG_idx); ++ outb(0x87, CFG_idx); ++ ++ if (0xff == cr_read(0x20)) { ++ CFG_idx = cr_cfg_idx2; ++ CFG_dat = cr_cfg_dat2; ++ outb(0x87, CFG_idx); ++ outb(0x87, CFG_idx); ++ } ++} ++ ++ ++/* exit extended function mode */ ++static inline void cr_exit_ext(void) ++{ ++ outb(0xaa, CFG_idx); ++} ++ ++/* select logical device */ ++static inline void cr_select_log_dev(int cr) ++{ ++ outb(0x07, CFG_idx); ++ outb(cr, CFG_dat); ++} ++ ++static inline void cr_update(int dat, int cr) ++{ ++ outb(cr, CFG_idx); ++ outb(dat, CFG_dat); ++} ++ ++static inline u8 cr_read(int cr) ++{ ++ outb(cr, CFG_idx); ++ return inb(CFG_dat); ++} ++ ++static inline void cr_safe_update(u8 dat, int cr) ++{ ++ cr_update(cr_read(cr) | dat, cr); ++} ++ ++static inline void cr_safe_clear(u8 dat, int cr) ++{ ++ cr_update(cr_read(cr) & dat, cr); ++} ++ ++ ++/* read/write cir registers */ ++ ++static inline void cir_update(u8 dat, int cir) ++{ ++ outb(dat, cir_address + (cir & 0xff)); ++} ++ ++static u8 cir_read(int cir) ++{ ++ u8 val; ++ ++ val = inb(cir_address + (cir & 0xff)); ++ ++ return val; ++} ++ ++static inline void cir_wake_update(u8 dat, int cir) ++{ ++ ++ outb(dat, cir_wake_address + (cir & 0xff)); ++ ++} ++ ++static u8 cir_wake_read(int cir) ++{ ++ u8 val; ++ ++ val = inb(cir_wake_address + (cir & 0xff)); ++ ++ return val; ++} ++ ++static void cir_dump_reg(void) ++{ ++ cr_enter_ext(); ++ printk("Dump CIR CR logical device:\n"); ++ cr_select_log_dev(CIR_LOG_DEV); ++ printk("CR CIR ACTIVE : 0x%x\n", cr_read(0x30)); ++ printk("CR CIR BASE ADDR: 0x%x\n", (cr_read(0x61) << 8)|cr_read(0x60)); ++ printk("CR CIR IRQ NUM: 0x%x\n", cr_read(0x70)); ++ cr_exit_ext(); ++ ++ printk("Dump CIR Registers\n"); ++ printk("CIR IRCON: 0x%x\n", cir_read(CIR_IRCON)); ++ printk("CIR IRSTS: 0x%x\n", cir_read(CIR_IRSTS)); ++ printk("CIR IREN: 0x%x\n", cir_read(CIR_IREN)); ++ printk("CIR RXFCONT: 0x%x\n", cir_read(CIR_RXFCONT)); ++ printk("CIR CP: 0x%x\n", cir_read(CIR_CP)); ++ printk("CIR CC: 0x%x\n", cir_read(CIR_CC)); ++ printk("CIR SLCH: 0x%x\n", cir_read(CIR_SLCH)); ++ printk("CIR SLCL: 0x%x\n", cir_read(CIR_SLCL)); ++ printk("CIR FIFOCON: 0x%x\n", cir_read(CIR_FIFOCON)); ++ printk("CIR IRFIFOSTS: 0x%x\n", cir_read(CIR_IRFIFOSTS)); ++ printk("CIR SRXFIFO: 0x%x\n", cir_read(CIR_SRXFIFO)); ++ printk("CIR TXFCONT: 0x%x\n", cir_read(CIR_TXFCONT)); ++ printk("CIR STXFIFO: 0x%x\n", cir_read(CIR_STXFIFO)); ++ printk("CIR FCCH: 0x%x\n", cir_read(CIR_FCCH)); ++ printk("CIR FCCL: 0x%x\n", cir_read(CIR_FCCL)); ++ printk("CIR IRFSM: 0x%x\n", cir_read(CIR_IRFSM)); ++ ++} ++ ++static void cir_wake_dump_reg(void) ++{ ++ u8 i = 0; ++ ++ cr_enter_ext(); ++ printk("Dump CIR WKAE CR logical device:\n"); ++ cr_select_log_dev(CIR_WAKE_LOG_DEV); ++ printk("CR CIR WAKE ACTIVE : 0x%x \n", cr_read(0x30)); ++ printk("CR CIR WAKE BASE ADDR: 0x%x\n", (cr_read(0x61) << 8)|cr_read(0x60)); ++ printk("CR CIR WAKE IRQ NUM: 0x%x\n", cr_read(0x70)); ++ cr_exit_ext(); ++ ++ printk("Dump CIR WAKE Registers\n"); ++ printk("CIR WAKE IRCON: 0x%x\n", cir_wake_read(CIR_WAKE_IRCON)); ++ printk("CIR IRSTS: 0x%x\n", cir_wake_read(CIR_WAKE_IRSTS)); ++ printk("CIR IREN: 0x%x\n", cir_wake_read(CIR_WAKE_IREN)); ++ printk("CIR WAKE FIFO CMP DEEP: 0x%x\n", cir_wake_read(CIR_WAKE_FIFO_CMP_DEEP)); ++ printk("CIR WAKE FIFO CMP TOL: 0x%x\n", cir_wake_read(CIR_WAKE_FIFO_CMP_TOL)); ++ printk("CIR WAKE FIFO COUNT: 0x%x\n", cir_wake_read(CIR_WAKE_FIFO_COUNT)); ++ printk("CIR WAKE SLCH: 0x%x\n", cir_wake_read(CIR_WAKE_SLCH)); ++ printk("CIR WAKE SLCL: 0x%x\n", cir_wake_read(CIR_WAKE_SLCL)); ++ printk("CIR WAKE FIFOCON: 0x%x\n", cir_wake_read(CIR_WAKE_FIFOCON)); ++ printk("CIR WAKE SRXFSTS: 0x%x\n", cir_wake_read(CIR_WAKE_SRXFSTS)); ++ printk("CIR WAKE SAMPLE RX FIFO: 0x%x\n", cir_wake_read(CIR_WAKE_SAMPLE_RX_FIFO)); ++ printk("CIR WAKE WR FIFO DATA: 0x%x\n", cir_wake_read(CIR_WAKE_WR_FIFO_DATA)); ++ printk("CIR WAKE RD FIFO ONLY: 0x%x\n", cir_wake_read(CIR_WAKE_RD_FIFO_ONLY)); ++ printk("CIR WAKE RD FIFO ONLY IDX: 0x%x\n", cir_wake_read(CIR_WAKE_RD_FIFO_ONLY_IDX)); ++ printk("CIR WAKE FIFO IGNORE: 0x%x\n", cir_wake_read(CIR_WAKE_FIFO_IGNORE)); ++ printk("CIR WAKE IRFSM: 0x%x\n", cir_wake_read(CIR_WAKE_IRFSM)); ++ ++ printk("Dump CIR WAKE keys\n"); ++ printk("%s FIFO count len = %d\n", DRVNAME, cir_wake_read(CIR_WAKE_FIFO_COUNT)); ++ i = 0; ++ for (; i < 67; i++) { ++ printk("%s FIFO = 0x%x\n", DRVNAME, cir_wake_read(CIR_WAKE_RD_FIFO_ONLY)); ++ } ++ ++} ++ ++ ++/* 1. */ ++/* 677HG Config Registers init */ ++static int w83667hg_cr_init(void) ++{ ++ int val = 0; ++ ++ cr_enter_ext(); ++ ++ /* Check 677 CHIP ID first */ ++ val = cr_read(CHIP_ID_HIGH_ADDR); ++ if (val != CHIP_ID_HIGH) { ++ printk("%s %s: chip id high: 0x%x expect:0x%x\n", DRVNAME, chip_id, val, CHIP_ID_HIGH); ++ /*// cr_exit_ext(); ++ // return -ENODEV;*/ ++ } ++ else{ ++ printk("%s %s: chip id high: 0x%x\n", DRVNAME, chip_id, val); ++ } ++ ++ /* now check chip id, LSB */ ++ val = cr_read(CHIP_ID_LOW_ADDR); ++ if (CHIP_ID_LOW == (val & CHIP_ID_LOW)) { ++ printk("%s %s: chip id low: 0x%x expect:0x%x\n", DRVNAME, chip_id, val, CHIP_ID_LOW); ++ /*// cr_exit_ext(); ++ // return -ENODEV;*/ ++ } else{ ++ printk("%s %s: chip id low: 0x%x\n", DRVNAME, chip_id, val); ++ } ++ ++ /* for multi-function pin selection */ ++ val = cr_read(0x27); ++ val = (val&0xbc) | 0x41; ++ cr_update(val, 0x27); /*For W83677, CIR TX,RX, CIRWB pin selection*/ ++ ++ ++ ++ /* FIXME*/ ++ /* set Logical Dev 1: LPT */ ++ /* not sure really need it or not, find it in 667 wake up windows driver */ ++ cr_select_log_dev(0x01); ++ cr_update(DEACTIVE_LOG_DEV, 0x30); ++ cr_update(0, 0x70); ++ ++ /* Then set Logical Dev 6: CIR */ ++ cr_select_log_dev(CIR_LOG_DEV); ++ cr_update(ACTIVE_LOG_DEV, 0x30); ++ ++ cir_address = CIR_BASE; ++ cr_update(((CIR_BASE & 0xff00) >> 8), 0x60); ++ cr_update((CIR_BASE & 0xff), 0x61); ++#ifdef IR_667_DEBUG ++ printk("%s base io port address: 0x%x\n", DRVNAME, cir_address); ++#endif ++ ++ cr_update(CIR_IRQ_NUM, 0x70); ++#ifdef IR_667_DEBUG ++ printk("%s irq number: %d\n", DRVNAME, CIR_IRQ_NUM); ++#endif ++ ++ ++ /* Then set Logical Dev A: ACPI */ ++ cr_select_log_dev(ACPI_LOG_DEV); ++ ++ cr_update(ACTIVE_LOG_DEV, 0x30); ++ ++ /* enable cir wake up via PSOUT# (pin 60) */ ++ cr_safe_update(ENABLE_CIR_WAKE, 0xe0); ++ ++ /* enable cir interrupt of mouse IRQ event */ ++ /*//cr_safe_update(ENABLE_CIR_INTR_OF_MOUSE_IRQ, 0xf6);*/ ++ ++ /* enable pme interrupt of cir password event */ ++ /*//cr_safe_update(ENABLE_PME_INTR_OF_CIR_PASS, 0xf7);*/ ++ ++ ++ /* Then set Logical Dev E: CIR WAKE */ ++ cr_select_log_dev(CIR_WAKE_LOG_DEV); ++ cr_update(ACTIVE_LOG_DEV, 0x30); ++ ++ cir_wake_address = CIR_WAKE_BASE; ++ cr_update(((CIR_WAKE_BASE & 0xff00) >> 8), 0x60); ++ cr_update((CIR_WAKE_BASE & 0xff), 0x61); ++#ifdef IR_667_DEBUG ++ printk("%s cir wake up base io port address: 0x%x\n", DRVNAME, cir_wake_address); ++#endif ++ ++#ifdef ENABLE_CIR_WAKE_IRQ ++ cr_update(CIR_WAKE_IRQ_NUM, 0x70); ++#ifdef IR_667_DEBUG ++ printk("%s cir wake up irq number: %d\n", DRVNAME, CIR_WAKE_IRQ_NUM); ++#endif ++#endif ++ ++ cr_exit_ext(); ++ ++ return 0; ++} ++ ++static void w83667hg_cr_uninit(void) ++{ ++ cr_enter_ext(); ++ ++ /* close CIR */ ++ /* Don't close CIR Wake. When wake-up at power-on, it needs the function. 20091224 ++ cr_select_log_dev(CIR_WAKE_LOG_DEV); ++ cr_update(DEACTIVE_LOG_DEV, 0x30); ++ */ ++ ++ ++ /* Close Logical Dev A: ACPI */ ++ /*//cr_select_log_dev(ACPI_LOG_DEV);*/ ++ ++ /* enable cir wake up via PSOUT# (pin 60) */ ++ /*//cr_safe_clear(DISABLE_CIR_WAKE, 0xe0);*/ ++ ++ /* enable cir interrupt of mouse IRQ event */ ++ /*//cr_safe_clear(DISABLE_CIR_INTR_OF_MOUSE_IRQ, 0xf6);*/ ++ ++ /* enable pme interrupt of cir password event */ ++ /*//cr_safe_clear(DISABLE_PME_INTR_OF_CIR_PASS, 0xf7);*/ ++ ++ ++ /* close CIR wake up XXX */ ++ /*//cr_select_log_dev(CIR_WAKE_LOG_DEV); ++ //cr_update(DEACTIVE_LOG_DEV, 0x30);*/ ++ ++ cr_exit_ext(); ++} ++ ++static int w83667hg_input_open(struct input_dev *cur_input_dev) ++{ ++ return 0; ++} ++ ++static void w83667hg_input_close(struct input_dev *cur_input_dev) ++{ ++} ++ ++/* 2. */ ++/* init linux input structure */ ++static struct input_dev *w83667hg_input_init(void) ++{ ++ int i; ++ struct input_dev *cur_input_dev = NULL; ++ ++ cur_input_dev = input_allocate_device(); ++ if (NULL == cur_input_dev) { ++ printk("alloc input device error\n"); ++ return NULL; ++ } ++ ++ cur_input_dev->name = INPUTNAME; ++ cur_input_dev->phys = DRVNAME; ++ memcpy(&cur_input_dev->id, &w83667hg_input_id, sizeof(struct input_id)); ++ ++ cur_input_dev->open = w83667hg_input_open; ++ cur_input_dev->close = w83667hg_input_close; ++ ++ /*//cur_input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); ++ //cur_input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y);*/ ++ cur_input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); ++ cur_input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); ++ for (i = 0; i < 256; i++) { ++ set_bit(usb_kbd_keycode[i], cur_input_dev->keybit); ++ } ++ clear_bit(0, cur_input_dev->keybit); ++/*// cur_input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);*/ ++ cur_input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); ++ ++ ++ if (input_register_device(cur_input_dev)) { ++ printk("register input device error\n"); ++ return NULL; ++ } ++ ++ return cur_input_dev; ++} ++ ++static void w83667hg_input_uninit(struct input_dev *cur_input_dev) ++{ ++ input_get_device(cur_input_dev); ++ input_unregister_device(cur_input_dev); ++ input_free_device(cur_input_dev); ++ cur_input_dev = NULL; ++} ++ ++ ++/* internal call for register lirc */ ++static int lirc_set_use_inc(void *data) ++{ ++ struct irctl *ir = data; ++ ++ if (!ir) { ++ printk("%s: set_use_inc called with no context\n", DRVNAME); ++ return -EIO; ++ } ++#ifdef IR_667_DEBUG ++ printk("%s : set use inc\n", DRVNAME); ++#endif ++ spin_lock(&ir->lock); ++ ir->ctrl_fix_head = 1; ++ spin_unlock(&ir->lock); ++ ++ ++ MOD_INC_USE_COUNT; ++ ++ return 0; ++} ++ ++static void lirc_set_use_dec(void *data) ++{ ++ struct irctl *ir = data; ++ ++ if (!ir) { ++ printk("%s: set_use_dec called with no context\n", DRVNAME); ++ return; ++ } ++#ifdef IR_667_DEBUG ++ printk("%s : set use dec\n", DRVNAME); ++#endif ++ ++ MOD_DEC_USE_COUNT; ++} ++ ++ ++static int lirc_ioctl(struct inode *node, struct file *filep, unsigned int cmd, unsigned long arg) ++{ ++ int ret = 0; ++ void __user *uptr = (void __user *)arg; ++ ++ int mode = 0; ++ struct irctl *ir = &w83667hg_irctl; ++ struct ir_recv_t *ir_recv = &w83667hg_ir_recv; ++ ++#ifdef ALLOW_DEBUG_IOCTL ++ printk("%s: IO Ctrl Code:%d\n", DRVNAME, cmd); ++#endif ++ ++ switch (cmd) { ++ /* lirc ioctl commands */ ++ case LIRC_GET_FEATURES: ++ ret = put_user(w83667hg_lirc_plugin->features, (unsigned long *)arg); ++ break; ++ case LIRC_GET_SEND_MODE: ++ if (!(w83667hg_lirc_plugin->features & LIRC_CAN_REC_MASK)) ++ return -ENOSYS; ++ ++ ret = put_user(LIRC_REC2MODE ++ (w83667hg_lirc_plugin->features & LIRC_CAN_REC_MASK), ++ (unsigned long *)arg); ++ if (ret) ++ return ret; ++ break; ++ case LIRC_SET_SEND_MODE: ++ ret = get_user(mode, (unsigned long *)arg); ++ if (ret) ++ return ret; ++ if (mode != (LIRC_MODE_PULSE&LIRC_CAN_SEND_MASK)) ++ return -EINVAL; ++ break; ++ case LIRC_GET_LENGTH: ++ ret = put_user((unsigned long)w83667hg_lirc_plugin->code_length, ++ (unsigned long *)arg); ++ break; ++ ++ /* ioctl commands for lirc_wb667 */ ++ case IR_DUMPCIRREG: ++ cir_dump_reg(); ++ break; ++ case IR_DUMPWAKEREG: ++ cir_wake_dump_reg(); ++ break; ++ case IR_IOLEARNWAKE: ++ spin_lock(&ir_recv->lock); ++ if (ir_recv->wake_state) { ++ spin_unlock(&ir_recv->lock); ++ ret = -EFAULT; ++ break; ++ } ++ ir_recv->wake_state = ST_WAKE_START; ++ spin_unlock(&ir_recv->lock); ++ ++ /* close cir first */ ++ cr_enter_ext(); ++ cr_select_log_dev(CIR_LOG_DEV); ++ cr_update(DEACTIVE_LOG_DEV, 0x30); ++ cr_exit_ext(); ++ /*//cir_update(0, CIR_IREN);*/ ++ cir_update(0xff, CIR_IRSTS); ++ ++ /* set cir wake */ ++ cir_wake_update(CIR_WAKE_IRCON_RXEN | CIR_WAKE_IRCON_RXINV | CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL, CIR_WAKE_IRCON); ++ cir_wake_update(0xff, CIR_WAKE_IRSTS); ++ cir_wake_update(0xff, CIR_WAKE_FIFOCON); ++ cir_wake_update(0, CIR_WAKE_FIFOCON); ++#ifdef ALLOW_DEBUG_WAKE ++ printk("%s FIFO count len = %d\n", DRVNAME, cir_wake_read(CIR_WAKE_FIFO_COUNT)); ++#endif ++ cir_wake_update(CIR_WAKE_IREN_PE, CIR_WAKE_IREN); ++ ++ wait_event(ir_recv->queue, ir_recv->wake_state == ST_WAKE_FINISH); ++ while ((cir_wake_read(CIR_WAKE_RD_FIFO_ONLY_IDX)) != 0) { ++#ifdef ALLOW_DEBUG_WAKE ++ printk("%s setting wake up key: 0x%x\n", DRVNAME, cir_wake_read(CIR_WAKE_RD_FIFO_ONLY)); ++#else ++ cir_wake_read(CIR_WAKE_RD_FIFO_ONLY); ++#endif ++ } ++ ++ /* learn wake up complete */ ++ spin_lock(&ir_recv->lock); ++ ir_recv->wake_state = ST_WAKE_NONE; ++ spin_unlock(&ir_recv->lock); ++ ++#ifdef ALLOW_DEBUG_WAKE ++ ret = 0; ++ for (; ret < 67; ret++) { ++ printk("%s FIFO count = 0x%x\n", DRVNAME, cir_wake_read(CIR_WAKE_RD_FIFO_ONLY)); ++ } ++ printk("%s FIFO count len = %d\n", DRVNAME, cir_wake_read(CIR_WAKE_FIFO_COUNT)); ++#endif ++ ++ /* cir wake interrupt stop, resume cir */ ++ cir_wake_update(CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN | CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV | CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL, CIR_WAKE_IRCON); ++ cir_wake_update(0xff, CIR_WAKE_IRSTS); ++ cir_wake_update(0, CIR_WAKE_IREN); ++ cr_enter_ext(); ++ cr_select_log_dev(CIR_LOG_DEV); ++ cr_update(ACTIVE_LOG_DEV, 0x30); ++ cr_exit_ext(); ++ ret = 0; ++ ++ break; ++ case IR_IOUNSETWAKE: ++ cir_wake_update(0, CIR_WAKE_IRCON); ++ cir_wake_update(0, CIR_WAKE_IREN); ++ cir_wake_update(0xFF, CIR_WAKE_IRSTS); ++ cir_wake_update(0, CIR_WAKE_IRSTS); ++ cr_enter_ext(); ++ cr_select_log_dev(CIR_WAKE_LOG_DEV); ++ cr_update(DEACTIVE_LOG_DEV, 0x30); ++ cr_exit_ext(); ++ /*//cir_wake_update(CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN | CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV | CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL, CIR_WAKE_IRCON);*/ ++ break; ++ case IR_IOSETWAKE: ++ cr_enter_ext(); ++ cr_select_log_dev(CIR_WAKE_LOG_DEV); ++ cr_update(ACTIVE_LOG_DEV, 0x30); ++ cr_exit_ext(); ++ cir_wake_update(CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN | CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV | CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL, CIR_WAKE_IRCON); ++ cir_wake_update(0xFF, CIR_WAKE_IRSTS); ++ cir_wake_update(0, CIR_WAKE_IRSTS); ++ cir_wake_update(0, CIR_WAKE_IREN); ++ break; ++ case IR_IOCLEANDATA: ++ w83667hg_clean_data(&w83667hg_ir_recv, &w83667hg_irctl); ++ break; ++ case IR_IOSTARTSTUDY: ++ spin_lock(&ir->lock); ++ ir->study_state = ST_STUDY_START; ++ spin_unlock(&ir->lock); ++ /*//cir_update(cir_read(CIR_IRCON) | CIR_IRCON_WIREN, CIR_IRCON);*/ ++ cir_update(CIR_IRCON_WIREN | CIR_IRCON_RXEN | CIR_IRCON_SAMPLE_PERIOD_SEL, CIR_IRCON); ++ ++/* for WRX RTR ++ cir_update(CIR_FIFOCON_RX_TRIGGER_LEV_8, CIR_FIFOCON); ++ //cir_update(CIR_IREN_RTR, CIR_IREN); ++ cir_update(0, CIR_IREN); ++*/ ++ break; ++ case IR_IOSTOPSTUDY: ++ cir_update(CIR_IRCON_TXEN | CIR_IRCON_RXEN | CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, CIR_IRCON); ++ spin_lock(&ir->lock); ++ ir->study_state = ST_STUDY_NONE; ++ ir->buf_count = 0; ++ ir->cur_buf_num = 0; ++ wake_up(&ir->queue); ++ spin_unlock(&ir->lock); ++ break; ++ case IR_IOGETCARRIER: ++ spin_lock(&ir->lock); ++ if (!(ir->study_state > ST_STUDY_NONE)) { ++ ret = -EFAULT; ++ spin_unlock(&ir->lock); ++ break; ++ } ++ /*//w83667hg_record_study_carrier(ir);*/ ++#ifdef ALLOW_DEBUG_IOCTL ++ printk("%s: current get carrier: %d\n", DRVNAME, ir->carrier); ++#endif ++ if (copy_to_user(uptr, &ir->carrier, sizeof(unsigned int))) { ++ ret = -EFAULT; ++ } ++ spin_unlock(&ir->lock); ++ break; ++ case IR_IOSETCARRIER: ++ spin_lock(&ir->lock); ++ /* you can set carrier at any time */ ++ /* ++ if (~(ir->send_state)) { ++ ret = -EFAULT; ++ up(&ir->lock); ++ break; ++ } ++ */ ++ if (copy_from_user(&ir->carrier, uptr, sizeof(unsigned int))) { ++ ret = -EFAULT; ++ spin_unlock(&ir->lock); ++ break; ++ } ++#ifdef ALLOW_DEBUG_IOCTL ++ printk("%s: current set carrier: %x\n", DRVNAME, ir->carrier); ++#endif ++ w83667hg_set_carrier(&ir->carrier); ++ spin_unlock(&ir->lock); ++ break; ++ case IR_IOSTUDYLEN: ++ spin_lock(&ir->lock); ++ if (ir->study_state == ST_STUDY_NONE) { ++ spin_unlock(&ir->lock); ++#ifdef ALLOW_DEBUG_IOCTL ++ printk("%s: open STUDY first\n", DRVNAME); ++#endif ++ ret = -EFAULT; ++ break; ++ } ++ ir->study_state = ST_STUDY_START; ++ spin_unlock(&ir->lock); ++ wait_event(ir->queue, ir->study_state == ST_STUDY_ALL_RECV); ++ spin_lock(&ir->lock); ++ ++ /* in STUDY, copy data buf len to user space for read() */ ++ ir->cur_buf_num = 0; ++ if (ir->buf_count == 0) { ++ ret = -EFAULT; ++ } else if (copy_to_user(uptr, &ir->buf_count, sizeof(unsigned int))) { ++ ret = -EFAULT; ++ } ++ /* copy data to lirc plugin buffer, ready copy to user space */ ++ spin_unlock(&ir->lock); ++ break; ++ case IR_IOSTUDYBUF: ++ spin_lock(&ir->lock); ++ if (ir->study_state != ST_STUDY_ALL_RECV) { ++ spin_unlock(&ir->lock); ++ ret = -EFAULT; ++ break; ++ } ++ if (copy_to_user(uptr, &ir->buf[ir->cur_buf_num], sizeof(unsigned char))) { ++ spin_unlock(&ir->lock); ++ ret = -EFAULT; ++ break; ++ } ++ if (ir->cur_buf_num < ir->buf_count) { ++ ir->cur_buf_num++; ++ } ++ spin_unlock(&ir->lock); ++ break; ++ case IR_IORESTUDYBUF: ++ spin_lock(&ir->lock); ++ ir->cur_buf_num = 0; ++ spin_unlock(&ir->lock); ++ break; ++ case IR_CHECKCHIP: ++ if (copy_to_user(uptr, chip_id, sizeof(unsigned long long))) { ++ ret = -EFAULT; ++ } ++ break; ++ default: ++ return -ENOIOCTLCMD; ++ } ++ ++ return ret; ++} ++ ++static int w83667hg_set_carrier(unsigned int *carrier) ++{ ++ u16 val; ++ ++ cir_update(1, CIR_CP); ++ val = 3000000 / (*carrier) - 1; ++ cir_update(val & 0xff, CIR_CC); ++ ++#ifdef ALLOW_DEBUG_STUDY ++ printk("cp: 0x%x cc: 0x%x\n", cir_read(CIR_CP), cir_read(CIR_CC)); ++#endif ++ return 0; ++} ++ ++static ssize_t lirc_write(struct file *file, const char *buf, size_t n, loff_t * ppos) ++{ ++ size_t cur_count; ++ struct ir_send_t *ir_send = &w83667hg_ir_send; ++ unsigned int i; ++ ssize_t ret; ++ ++ spin_lock(&ir_send->lock); ++ ++ if (n >= IRCTL_BUF_LIMIT) { ++ ir_send->buf_count = cur_count = IRCTL_BUF_LIMIT; ++ ret = IRCTL_BUF_LIMIT; ++ } else { ++ ir_send->buf_count = cur_count = n; ++ ret = n; ++ } ++ ++ /* the first copy from user and open interrupt for TX */ ++ if (copy_from_user(ir_send->buf, buf, ir_send->buf_count)) { ++ ir_send->buf_count = 0; ++ spin_unlock(&ir_send->lock); ++ return -EFAULT; ++ } ++ ++ ir_send->cur_buf_num = 0; ++ ++ /* for safety, close RX while TX */ ++ cir_update(CIR_IREN_TFU | CIR_IREN_TTR, CIR_IREN); ++ ++ ir_send->send_state = ST_SEND_REPLY; ++ ++ cir_update(CIR_FIFOCON_TX_TRIGGER_LEV_8 | CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON); ++ /* turn on TTR interrupt, it's ugly */ ++ i = 0; ++ for (; i < 9; i++) { ++ cir_update(0x01, CIR_STXFIFO); ++ } ++ spin_unlock(&ir_send->lock); ++ ++ wait_event(ir_send->queue, ir_send->send_state == ST_SEND_REQUEST); ++ ++ spin_lock(&ir_send->lock); ++ ir_send->send_state = ST_SEND_NONE; ++ spin_unlock(&ir_send->lock); ++ ++ cir_update(CIR_IREN_RDR | CIR_IREN_PE, CIR_IREN); ++ ++ return ret; ++} ++ ++static void w83667hg_clean_data(struct ir_recv_t *ir_recv, struct irctl *ir) ++{ ++ spin_lock(&ir_recv->lock); ++ ir_recv->buf_count = 0; ++ /*//ir_recv->wake_state = ST_WAKE_NONE;*/ ++ wake_up(&ir_recv->queue); ++ spin_unlock(&ir_recv->lock); ++ ++ spin_lock(&ir->lock); ++ ir->lircdata = 0; ++ /* ++ for (i = 0; i < IRCTL_BUF_LIMIT; i++) { ++ ir->buf = 0; ++ } ++ */ ++ ir->pressed_keycode = 0; ++ ir->pressed_shiftmask = 0; ++ ir->buf_count = 0; ++ ir->cur_buf_num = 0; ++ /* ++ ir->study_state = ST_STUDY_NONE; ++ ir->send_state = ST_SEND_NONE; ++ */ ++ wake_up(&ir->queue); ++ spin_unlock(&ir->lock); ++ ++ cir_update(cir_read(CIR_FIFOCON) | 0x88, CIR_FIFOCON); ++ cir_wake_update(cir_wake_read(CIR_WAKE_FIFOCON) | 0x8, CIR_WAKE_FIFOCON); ++ ++} ++ ++/* 3. */ ++static void w83667hg_ir_recv_init(struct ir_recv_t *ir_recv) ++{ ++ ir_recv->buf_count = 0; ++ spin_lock_init(&ir_recv->lock); ++ ir_recv->wake_state = ST_WAKE_NONE; ++ init_waitqueue_head(&ir_recv->queue); ++ ir_recv->recv_state = ST_RECV_WAIT_7F; ++} ++ ++static void w83667hg_ir_send_init(struct ir_send_t *ir_send) ++{ ++ ir_send->buf_count = 0; ++ spin_lock_init(&ir_send->lock); ++ ir_send->send_state = ST_SEND_NONE; ++ init_waitqueue_head(&ir_send->queue); ++} ++ ++ ++/* lirc_fops ++ * ++ * 1) it's LIRC's fops, so NOT allow add owner in it ++ * 2) define lirc functions at here will replace the lirc original fops functions, so lirc_write() in lirc_dev will not work ++ * 3) lirc has its own ioctl, lirc_ioctl() in current file not register in lirc_fops, so it only work for lirc_wb667 ++ * lirc_ioctl() in current file register in w83667hg_irctl_init() as lirc_plugin's ioctl while initial driver, and it does not effect on lirc_dev ++ */ ++static struct file_operations lirc_fops = { ++ write: lirc_write, ++ ioctl : lirc_ioctl, ++}; ++ ++ ++/* init lirc buffer, register, irctl */ ++static int w83667hg_irctl_init(struct irctl *ir) ++{ ++ int err = 0, minor = -1; ++ ++ w83667hg_lirc_buffer = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL); ++ if (!w83667hg_lirc_buffer) { ++ err = -ENOMEM; ++ goto out_lirc_buffer; ++ } ++ memset(w83667hg_lirc_buffer, 0, sizeof(struct lirc_buffer)); ++ ++ if (lirc_buffer_init(w83667hg_lirc_buffer, sizeof(int), LIRCBUF_SIZE)) { ++ err = -ENOMEM; ++ goto out_lirc_buffer; ++ } ++ ++ w83667hg_lirc_plugin = kmalloc(sizeof(struct lirc_driver), GFP_KERNEL); ++ if (!w83667hg_lirc_plugin) { ++ err = -ENOMEM; ++ goto out_lirc_plugin; ++ } ++ memset(w83667hg_lirc_plugin, 0, sizeof(struct lirc_driver)); ++ ++ ir->lirc_plugin = w83667hg_lirc_plugin; ++ ++ strcpy(w83667hg_lirc_plugin->name, DRVNAME); ++ w83667hg_lirc_plugin->minor = -1; ++ w83667hg_lirc_plugin->features = LIRC_CAN_SEND_PULSE | ++ LIRC_CAN_SET_TRANSMITTER_MASK | ++ LIRC_CAN_REC_MODE2; ++ /*// LIRC_CAN_SET_SEND_DUTY_CYCLE | ++ // LIRC_CAN_SET_SEND_CARRIER;*/ ++ w83667hg_lirc_plugin->data = &w83667hg_irctl; ++ w83667hg_lirc_plugin->rbuf = w83667hg_lirc_buffer; ++ w83667hg_lirc_plugin->set_use_inc = &lirc_set_use_inc; ++ w83667hg_lirc_plugin->set_use_dec = &lirc_set_use_dec; ++ w83667hg_lirc_plugin->code_length = sizeof(int) * 8; ++/*// w83667hg_lirc_plugin->ioctl = lirc_ioctl;*/ ++ w83667hg_lirc_plugin->fops = &lirc_fops; ++ w83667hg_lirc_plugin->dev = NULL; ++ w83667hg_lirc_plugin->owner = THIS_MODULE; ++ ++ minor = lirc_register_driver(w83667hg_lirc_plugin); ++ if (minor < 0) { ++ err = -ENOMEM; ++ goto out_lirc_plugin_register; ++ } ++#ifdef IR_667_DEBUG ++ printk("%s register lirc minor: %d\n", DRVNAME, minor); ++#endif ++ ++ w83667hg_lirc_plugin->minor = minor; ++ ir->lirc_plugin = w83667hg_lirc_plugin; ++ ++ /* init irctl */ ++ ir->pressed_keycode = 0; ++ ir->pressed_shiftmask = 0; ++ ir->buf_count = 0; ++ ir->ctrl_fix_head = 1; ++ spin_lock_init(&ir->lock); ++ ir->study_state = ST_STUDY_NONE; ++ init_waitqueue_head(&ir->queue); ++ ++ goto out; ++ ++ out_lirc_plugin_register: ++ kfree(w83667hg_lirc_plugin); ++ out_lirc_plugin: ++ lirc_buffer_free(w83667hg_lirc_buffer); ++ out_lirc_buffer: ++ kfree(w83667hg_lirc_buffer); ++ out: ++ return err; ++} ++ ++static void w83667hg_irctl_uninit(struct irctl *ir) ++{ ++ /*//lirc_unregister_plugin(w83667hg_lirc_plugin->minor);*/ ++ lirc_unregister_driver(w83667hg_lirc_plugin->minor); ++ kfree(w83667hg_lirc_plugin); ++ ir->lirc_plugin = NULL; ++ lirc_buffer_free(w83667hg_lirc_buffer); ++ kfree(w83667hg_lirc_buffer); ++ ir->lirc_buffer = NULL; ++} ++ ++#ifdef ALLOW_DEBUG_PRINT_PULSE ++void debug_print_pulse(void) ++{ ++ u8 count, i; ++ ++ count = cir_read(CIR_RXFCONT); ++ for (i = 0; i < count; i++) { ++ printk("%s current cir pluse: 0x%x\n", DRVNAME, cir_read(CIR_SRXFIFO)); ++ } ++} ++ ++void debug_print_wake_pulse(void) ++{ ++ u8 count, i; ++ ++ count = cir_wake_read(CIR_WAKE_FIFO_COUNT); ++ for (i = 0; i < count; i++) { ++ printk("%s current cir wake pluse: 0x%x\n", DRVNAME, cir_wake_read(CIR_WAKE_SRXFSTS)); ++ } ++} ++#endif ++ ++static void w83667hg_study_recv(struct ir_recv_t *ir_recv, struct irctl *ir) ++{ ++ unsigned int i = 0; ++ unsigned int packet_on_dur = 0; ++ ++ spin_lock(&ir_recv->lock); ++ ir_recv->buf[ir_recv->buf_count] = cir_read(CIR_SRXFIFO); ++ if (ir_recv->buf[ir_recv->buf_count] == 0x80) { ++ /* close interrupt now */ ++ /*//cir_wake_update(0, CIR_WAKE_IREN);*/ ++ ++ spin_lock(&ir->lock); ++ ++ /* 1. get carrier */ ++ ir->carrier = cir_read(CIR_FCCL); ++ ir->carrier |= cir_read(CIR_FCCH) << 8; ++ ++ if (ir->carrier == 0) { ++ printk("%s: get carrier error!\n", DRVNAME); ++ } ++ ++ i = 0; ++ for (; i < ir_recv->buf_count; i++) { ++ if (ir_recv->buf[i] & BIT_PULSE_MASK) { ++ packet_on_dur += ir_recv->buf[i] & BIT_LEN; ++ } ++ } ++ packet_on_dur *= MCE_TIME_UNIT; ++ ++#ifdef ALLOW_DEBUG_STUDY ++ printk("%s: carrier count: 0x%x\n", DRVNAME, ir->carrier); ++ printk("%s: packet on duration: %u\n", DRVNAME, packet_on_dur); ++#endif ++ ir->carrier *= 1000000; ++ ir->carrier /= packet_on_dur; ++#ifdef ALLOW_DEBUG_STUDY ++ printk("%s: final carrier frequency: %u\n", DRVNAME, ir->carrier); ++#endif ++ if ((ir->carrier > MAX_CARRIER) || (ir->carrier < MIN_CARRIER)) { ++ /* carrier is too large or too small */ ++#ifdef ALLOW_DEBUG_STUDY ++ printk("%s: current received carrier is too large or too small\n", DRVNAME); ++#endif ++ ir_recv->buf_count = 0; ++ spin_unlock(&ir_recv->lock); ++ ++ ir->buf_count = 0; ++ ir->study_state = ST_STUDY_ALL_RECV; ++ wake_up(&ir->queue); ++ spin_unlock(&ir->lock); ++ return; ++ } ++ ++ /* 2. get pulse */ ++ i = 0; ++ /* 1) find sync head */ ++ while (!((ir_recv->buf[i] & BIT_PULSE_MASK) & 0x80)) { ++ i++; ++ } ++ /* 2) find 0x7f */ ++ /* FIXME, the silent part of infrared signal may change by protocol or sample period. but current value fits MCE RC-6*/ ++ while ((ir_recv->buf[i] != 0x7f) || ++ (ir_recv->buf[i + 1] != 0x7f) || ++ (ir_recv->buf[i + 2] != 0x7f)) { ++ i++; ++ } ++ /* 3) find next head */ ++ while (!((ir_recv->buf[i] & BIT_PULSE_MASK) & 0x80)) { ++ i++; ++ } ++ /*//ir->buf_count = --i;*/ ++ /* now buf_count direct to next pulse sync head */ ++ ir->buf_count = i; ++ /* 4) copy pluse from recv to ir */ ++ i = 0; ++ for (; i <= ir->buf_count; i++) { ++ ir->buf[i] = ir_recv->buf[i]; ++ } ++ ++ ++ ir_recv->buf_count = 0; ++ spin_unlock(&ir_recv->lock); ++ ++ ir->study_state = ST_STUDY_ALL_RECV; ++ wake_up(&ir->queue); ++ spin_unlock(&ir->lock); ++ } else { ++ ir_recv->buf_count++; ++ spin_unlock(&ir_recv->lock); ++ } ++} ++ ++ ++static void w83667hg_recv(struct ir_recv_t *ir_recv, struct irctl *ir) ++{ ++ u8 buf; ++ unsigned int i = 0, rlc = 0; ++ ++ spin_lock(&ir_recv->lock); ++ ++ ir_recv->buf[ir_recv->buf_count] = cir_read(CIR_SRXFIFO); ++ if (ir_recv->buf[ir_recv->buf_count] == 0x7f) { ++ if (ir_recv->recv_state & ST_RECV_WAIT_7F) { ++ ir_recv->recv_state = ST_RECV_WAIT_HEAD; ++ ir_recv->buf_count++; ++ { /* decode begin*/ ++ spin_lock(&ir->lock); ++ ++ ir->buf_count = ir_recv->buf_count; ++ for (; i < ir->buf_count; i++) { ++ ir->buf[i] = ir_recv->buf[i]; ++ } ++ ir->cur_buf_num = 0; ++ ++ /*//ir_recv->buf_count++;*/ ++ spin_unlock(&ir_recv->lock); ++ ++ i = 0; ++ while (i < ir->buf_count) { ++ rlc += ir->buf[i] & BIT_LEN; ++ i++; ++ } ++#ifdef ALLOW_DEBUG_DECODE ++ printk("\n%s cur rlc len: %d\n", DRVNAME, rlc); ++#endif ++ ++#ifdef DECODE_KEYBOARD_MOUSE ++ if (rlc >= CONTROLLER_BUF_LEN_MIN) { ++#endif ++ /* lirc controller*/ ++ w83667hg_submit_controller(ir); ++ ++#ifdef DECODE_KEYBOARD_MOUSE ++ } else if ((rlc >= KEYBOARD_BUF_LEN_MIN) && ++ (rlc < KEYBOARD_BUF_LEN_MAX)) { ++ w83667hg_submit_key(ir); ++ input_sync(ir->input_dev); ++ } else if ((rlc >= MOUSE_BUF_LEN_MIN) && ++ (rlc < KEYBOARD_BUF_LEN_MIN)) { ++ w83667hg_submit_mouse(ir); ++ input_sync(ir->input_dev); ++ } ++#endif ++ ++ ir->buf_count = 0; ++ spin_unlock(&ir->lock); ++ } /* decode end*/ ++ } else { ++ ir_recv->buf_count++; ++ spin_unlock(&ir_recv->lock); ++ } ++ } else { /* normal recv*/ ++ if (ir_recv->recv_state & ST_RECV_WAIT_HEAD) { ++ if (ir_recv->buf[ir_recv->buf_count] & BIT_PULSE_MASK) { ++ ir_recv->recv_state = ST_RECV_WAIT_7F; ++ buf = ir_recv->buf[ir_recv->buf_count]; ++ ir_recv->buf_count = 0; ++ ir_recv->buf[0] = buf; ++ } ++ } ++ ir_recv->buf_count++; ++ spin_unlock(&ir_recv->lock); ++ } ++} ++ ++ ++ ++static void w83667hg_send_packet_to_lirc_1(struct irctl *ir, int *val) ++{ ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s: send data to lirc : 0x%x\n", DRVNAME, (*val)); ++#endif ++/*// lirc_buffer_write_1(ir->lirc_plugin->rbuf, (char *)val);*/ ++ lirc_buffer_write(ir->lirc_plugin->rbuf, (char *)val); ++ wake_up(&ir->lirc_plugin->rbuf->wait_poll); ++} ++ ++ ++static void w83667hg_submit_controller(struct irctl *ir) ++{ ++ unsigned int buf_num; ++ u8 bit; ++ ++ static struct timeval last_time; ++ static bool is_not_initialed_yet = true; /* lirc group does not allow to initialize static variable to false(0) */ ++ struct timeval curr_time; ++ long duration; ++ ++ /* silence time */ ++ ++ ir->lircdata = 0; ++ ++ if (is_not_initialed_yet == true) { ++ duration = MAX_SILENCE_TIME; ++ is_not_initialed_yet = false; ++ } else{ ++ do_gettimeofday(&curr_time); ++ duration = (curr_time.tv_usec - last_time.tv_usec) + ++ (curr_time.tv_sec - last_time.tv_sec) * 1000000; ++ } ++ ++ if (duration >= MAX_SILENCE_TIME) { ++ ir->lircdata = MAX_SILENCE_TIME; ++ } else{ ++ ir->lircdata = duration; ++ } ++ w83667hg_send_packet_to_lirc_1(ir, &ir->lircdata); ++ ++ ++ /* fix controller head not sync problem */ ++ /* lirc doesn't response DK MCE controller signal until press several times, not find same problem on M$ MCE controller keyboard */ ++ /* for lirc group's suggestion, we need not add these code to prevent from this problem. ++ Just make it as comment. If we do not get any problem report from our customer, we will remove it at next some version. ++ if (ir->ctrl_fix_head) { ++ ir->lircdata = 50000; ++ w83667hg_send_packet_to_lirc_1(ir, &ir->lircdata); ++ ir->ctrl_fix_head = 0; ++ } ++ */ ++ ++ ++ buf_num = 0; ++ bit = BIT_PULSE_MASK; ++ ir->lircdata = 0; ++ for (; buf_num < ir->buf_count; buf_num++) { ++ if (bit == (ir->buf[buf_num] & BIT_PULSE_MASK)) { ++ ir->lircdata += (ir->buf[buf_num] & BIT_LEN) * MCE_TIME_UNIT; ++ } else { ++ if (bit) { ++ ir->lircdata |= PULSE_BIT; ++ } ++ w83667hg_send_packet_to_lirc_1(ir, &ir->lircdata); ++ bit = ir->buf[buf_num] & BIT_PULSE_MASK; ++ ir->lircdata = (ir->buf[buf_num] & BIT_LEN) * MCE_TIME_UNIT; ++ } ++ } ++ ++ /* update last_time for measure silence time*/ ++ do_gettimeofday(&last_time); ++ ++ /* for final silent pulse */ ++ /*ir->lircdata = 50000; ++ w83667hg_send_packet_to_lirc_1(ir, &ir->lircdata);*/ ++ ++#ifdef ALLOW_DEBUG_DECODE ++ printk("\n"); ++#endif ++} ++ ++static irqreturn_t w83667hg_interrupt_handler(int irq, void *dev) ++{ ++ u8 tmp = 0; ++ struct irctl *ir = (struct irctl *)dev; ++ struct ir_send_t *ir_send = &w83667hg_ir_send; ++ ++ ++ /*Because interrupt is shared, check IREN first. */ ++ tmp = cir_read(CIR_IREN); ++ if (!tmp) { ++ return IRQ_RETVAL(IRQ_NONE); ++ } ++ tmp = cir_read(CIR_IRSTS); ++ cir_update(0xff, CIR_IRSTS); ++ if (!tmp) { ++ return IRQ_NONE; ++ } ++ if (tmp & CIR_IRSTS_RDR) { ++ ++ ++#ifdef ALLOW_DEBUG_INTERRUPT ++ printk("get CIR_IRSTS_RDR\n"); ++#endif ++#ifdef ALLOW_DEBUG_PRINT_PULSE ++ debug_print_pulse(); ++#else ++ spin_lock(&ir_send->lock); ++ if (ir_send->send_state == ST_SEND_NONE) { ++ spin_unlock(&ir_send->lock); ++ if (ir->study_state & ST_STUDY_START) { ++ w83667hg_study_recv(&w83667hg_ir_recv, &w83667hg_irctl); ++ } else { ++ w83667hg_recv(&w83667hg_ir_recv, &w83667hg_irctl); ++ } ++ } else { ++ spin_unlock(&ir_send->lock); ++ } ++#endif ++ } ++ if (tmp & CIR_IRSTS_RTR) { ++#ifdef ALLOW_DEBUG_INTERRUPT ++ printk("get CIR_IRSTS_RTR\n"); ++#endif ++ } ++ if (tmp & CIR_IRSTS_PE) { ++#ifdef ALLOW_DEBUG_INTERRUPT ++ printk("get CIR_IRSTS_PE\n"); ++#endif ++#ifdef ALLOW_DEBUG_PRINT_PULSE ++ printk("\n now get interrupt PE\n\n"); ++ debug_print_pulse(); ++#else ++ if (ir->study_state == ST_STUDY_NONE) { ++ w83667hg_clean_data(&w83667hg_ir_recv, &w83667hg_irctl); ++ } ++#endif ++ } ++ if (tmp & CIR_IRSTS_RFO) { ++#ifdef ALLOW_DEBUG_INTERRUPT ++ printk("get CIR_IRSTS_RFO\n"); ++#endif ++ } ++ if (tmp & CIR_IRSTS_TE) { ++#ifdef ALLOW_DEBUG_INTERRUPT ++ printk("get CIR_IRSTS_TE\n"); ++#endif ++ } ++ if (tmp & CIR_IRSTS_TTR) { ++#ifdef ALLOW_DEBUG_INTERRUPT ++ printk("get CIR_IRSTS_TTR\n"); ++#endif ++ ++ spin_lock(&ir_send->lock); ++ if (ir_send->cur_buf_num < ir_send->buf_count) { ++ cir_update(ir_send->buf[ir_send->cur_buf_num++], CIR_STXFIFO); ++ } else { ++ cir_update(cir_read(CIR_IREN) & (~CIR_IREN_TTR), CIR_IREN); ++ } ++ spin_unlock(&ir_send->lock); ++ ++ } ++ if (tmp & CIR_IRSTS_TFU) { ++#ifdef ALLOW_DEBUG_INTERRUPT ++ printk("get CIR_IRSTS_TFU\n"); ++#endif ++ spin_lock(&ir_send->lock); ++ if (ST_SEND_REPLY == ir_send->send_state) { ++ ir_send->send_state = ST_SEND_REQUEST; ++ wake_up(&ir_send->queue); ++ } ++ spin_unlock(&ir_send->lock); ++ } ++ if (tmp & CIR_IRSTS_GH) { ++#ifdef ALLOW_DEBUG_INTERRUPT ++ printk("get CIR_IRSTS_GH\n"); ++#endif ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static irqreturn_t w83667hg_wake_interrupt_handler(int irq, void *dev) ++{ ++ u8 tmp; ++ struct ir_recv_t *ir_recv = (struct ir_recv_t *)dev; ++ ++ ++ /*Because interrupt is shared, check IREN first. */ ++ tmp = cir_wake_read(CIR_WAKE_IREN); ++ if (!tmp) { ++ return IRQ_RETVAL(IRQ_NONE); ++ } ++ ++ tmp = cir_wake_read(CIR_WAKE_IRSTS); ++ if (!tmp) { ++ return IRQ_NONE; ++ } ++ cir_wake_update(0xff, CIR_WAKE_IRSTS); ++ ++ if (tmp & CIR_WAKE_IRSTS_RDR) { ++#ifdef ALLOW_DEBUG_INTERRUPT ++ printk("get CIR_WAKE_IRSTS_RDR\n"); ++#endif ++#ifdef ALLOW_DEBUG_PRINT_PULSE ++ debug_print_wake_pulse(); ++#endif ++ } ++ if (tmp & CIR_WAKE_IRSTS_RTR) { ++#ifdef ALLOW_DEBUG_INTERRUPT ++ printk("get CIR_WAKE_IRSTS_RTR\n"); ++#endif ++ } ++ if ((tmp & CIR_WAKE_IRSTS_PE) && ++ (ST_WAKE_START == ir_recv->wake_state)) { ++#ifdef ALLOW_DEBUG_INTERRUPT ++ printk("get CIR_WAKE_IRSTS_PE\n"); ++#endif ++#ifdef ALLOW_DEBUG_PRINT_PULSE ++ printk("\n now get interrupt PE\n\n"); ++ debug_print_wake_pulse(); ++#else ++ while ((cir_wake_read(CIR_WAKE_RD_FIFO_ONLY_IDX)) != 0) { ++#ifdef ALLOW_DEBUG_WAKE ++ printk("%s setting wake up key: 0x%x\n", DRVNAME, cir_wake_read(CIR_WAKE_RD_FIFO_ONLY)); ++#else ++ cir_wake_read(CIR_WAKE_RD_FIFO_ONLY); ++#endif ++ } ++ ++ cir_wake_update(0, CIR_WAKE_IREN); ++ spin_lock(&ir_recv->lock); ++ ir_recv->wake_state = ST_WAKE_FINISH; ++ wake_up(&ir_recv->queue); ++ spin_unlock(&ir_recv->lock); ++#endif ++ } ++ if (tmp & CIR_WAKE_IRSTS_RFO) { ++#ifdef ALLOW_DEBUG_INTERRUPT ++ printk("get CIR_WAKE_IRSTS_RFO\n"); ++#endif ++ } ++ if (tmp & CIR_WAKE_IRSTS_GH) { ++#ifdef ALLOW_DEBUG_INTERRUPT ++ printk("get CIR_WAKE_IRSTS_GH\n"); ++#endif ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++/* 4. */ ++/* init 667 cir dev, req_region, req_irq */ ++static int w83667hg_cir_probe(void) ++{ ++ int err = 0; ++ ++ if (!request_region(cir_address, CIR_IOREG_LENGTH, DRVNAME)) { ++ err = -EBUSY; ++#ifdef IR_667_DEBUG ++ printk("%s request 667 cir io port error! \n", DRVNAME); ++#endif ++ goto exit; ++ } ++ ++ cir_update(CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, CIR_IRCON); ++ cir_update(0xFF, CIR_IRSTS); ++ cir_update(CIR_RX_LIMIT_COUNT >> 8, CIR_SLCH); ++ cir_update(CIR_RX_LIMIT_COUNT & 0xff, CIR_SLCL); ++ cir_update(CIR_FIFOCON_TXFIFOCLR | CIR_FIFOCON_TX_TRIGGER_LEV_24 | CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON); ++ cir_update(CIR_IRCON_RECV | CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, CIR_IRCON); ++ cir_update(CIR_IRCON_TXEN | CIR_IRCON_RXEN | CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, CIR_IRCON); ++ ++ if (0 != request_irq(CIR_IRQ_NUM, w83667hg_interrupt_handler, IRQF_SHARED, ++ DRVNAME, &w83667hg_irctl)) { ++ err = -EINTR; ++#ifdef IR_667_DEBUG ++ printk("%s : request cir irq error\n", DRVNAME); ++#endif ++ goto rel_irq_exit; ++ } ++ /* open interrupt */ ++ cir_update(CIR_IREN_RDR | CIR_IREN_PE, CIR_IREN); ++ ++ if (!request_region(cir_wake_address, CIR_IOREG_LENGTH, DRVNAME)) { ++ err = -EBUSY; ++#ifdef IR_667_DEBUG ++ printk("%s request 667 cir wake io port error! \n", DRVNAME); ++#endif ++ goto rel_wake_exit; ++ } ++ ++ cir_wake_update(0xff, CIR_WAKE_IRSTS); ++ /* Modify it as more safe values: CIR_WAKE_FIFO_CMP_DEEP reg:0x41, ++ CIR_WAKE_FIFO_CMP_TOL reg: 0x05. 20091224 ++ */ ++ cir_wake_update(0x41, CIR_WAKE_FIFO_CMP_DEEP); /* 0x41 = 65 */ ++ cir_wake_update(0x05, CIR_WAKE_FIFO_CMP_TOL); ++ cir_wake_update(CIR_RX_LIMIT_COUNT >> 8, CIR_WAKE_SLCH); ++ cir_wake_update(CIR_RX_LIMIT_COUNT & 0xff, CIR_WAKE_SLCL); ++ cir_wake_update(0xff, CIR_WAKE_FIFOCON); ++ cir_wake_update(0, CIR_WAKE_FIFOCON); ++ cir_wake_update(CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN | CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV | CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL, CIR_WAKE_IRCON); ++ ++ /* cir wake has irq_handler, open interrupt after received ioctl IR_IOLEARNWAKE */ ++ if (0 != request_irq(CIR_WAKE_IRQ_NUM, w83667hg_wake_interrupt_handler, IRQF_SHARED, ++ DRVNAME, &w83667hg_ir_recv)) { ++ err = -EINTR; ++#ifdef IR_667_DEBUG ++ printk("%s : request cir wake irq error\n", DRVNAME); ++#endif ++ goto rel_wake_irq_exit; ++ } ++ ++#ifdef IR_667_DEBUG ++ printk("%s : init cir success\n", DRVNAME); ++#endif ++ goto exit; ++ ++ /* error exit */ ++ rel_wake_irq_exit: ++ release_region(cir_wake_address, CIR_IOREG_LENGTH); ++ rel_wake_exit: ++ cir_update(0, CIR_IREN); ++ free_irq(CIR_IRQ_NUM, &w83667hg_irctl); ++ rel_irq_exit: ++ release_region(cir_address, CIR_IOREG_LENGTH); ++ ++ /* final exit */ ++ exit: ++ return err; ++} ++ ++static void w83667hg_cir_remove(void) ++{ ++ /* Don't clean CIR_WAKE_IRCON. When wake-up at power-on, it needs the function. 20091224 ++ cir_wake_update(0, CIR_WAKE_IRCON); ++ */ ++ free_irq(CIR_WAKE_IRQ_NUM, &w83667hg_ir_recv); ++ release_region(cir_wake_address, CIR_IOREG_LENGTH); ++ cir_update(0, CIR_IRCON); ++ free_irq(CIR_IRQ_NUM, &w83667hg_irctl); ++ release_region(cir_address, CIR_IOREG_LENGTH); ++} ++ ++static int lirc_wb667_init(void) ++{ ++ int err = 0; ++ ++ /* Initialise global static variables here instead of at declaration becuase of ++ lirc group does not allow it.*/ ++#ifdef CONFIG_PNP ++ nopnp = 0; ++#else ++ nopnp = 1; ++#endif ++ w83667hg_input_dev = NULL; ++ w83667hg_lirc_plugin = NULL; ++ w83667hg_lirc_buffer = NULL; ++ ++ /* 1. init cr */ ++ if (w83667hg_cr_init()) { ++ printk("%s: Unable to init device.\n", DRVNAME); ++ err = -ENODEV; ++ goto out; ++ } ++ ++ /* 2. init input */ ++ w83667hg_input_dev = w83667hg_input_init(); ++ if (!w83667hg_input_dev) { ++ printk("%s: Unable to register input device.\n", DRVNAME); ++ err = -ENODEV; ++ goto out_input; ++ } ++ w83667hg_irctl.input_dev = w83667hg_input_dev; ++ ++ /* 3. init lirc buffer, register, irctl */ ++ w83667hg_ir_recv_init(&w83667hg_ir_recv); ++ w83667hg_ir_send_init(&w83667hg_ir_send); ++ err = w83667hg_irctl_init(&w83667hg_irctl); ++ if (err) { ++ printk("%s: Unable to register lirc.\n", DRVNAME); ++ goto out_irctl; ++ } ++ ++ ++ /* 4. init 667 cir dev, req_region, req_irq */ ++ err = w83667hg_cir_probe(); ++ if (err) { ++ printk("%s: Unable to probe cir device.\n", DRVNAME); ++ goto out_cir_probe; ++ } ++ ++ goto out; ++ ++ /* error exit */ ++ out_cir_probe: ++ w83667hg_irctl_uninit(&w83667hg_irctl); ++ w83667hg_irctl.input_dev = NULL; ++ out_irctl: ++ w83667hg_input_uninit(w83667hg_input_dev); ++ out_input: ++ w83667hg_cr_uninit(); ++ ++ /* final exit */ ++ out: ++ return err; ++} ++ ++void lirc_wb667_uninit(void) ++{ ++ w83667hg_cir_remove(); ++ w83667hg_irctl_uninit(&w83667hg_irctl); ++ w83667hg_irctl.input_dev = NULL; ++ w83667hg_input_uninit(w83667hg_input_dev); ++ w83667hg_cr_uninit(); ++ ++} ++ ++ ++ ++/* For resume function use only. 20100119*/ ++static void w83667hg_irctl_resume_reset(struct irctl *ir) ++{ ++ /* init irctl */ ++ ir->pressed_keycode = 0; ++ ir->pressed_shiftmask = 0; ++ ir->buf_count = 0; ++ ir->ctrl_fix_head = 1; ++ spin_lock_init(&ir->lock); ++ ir->study_state = ST_STUDY_NONE; ++ init_waitqueue_head(&ir->queue); ++} ++ ++ ++/* For resume function use only. 20100119*/ ++static int w83667hg_cir_resume_reset(void) ++{ ++ int err = 0; ++ ++ cir_update(CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, CIR_IRCON); ++ cir_update(0xFF, CIR_IRSTS); ++ cir_update(CIR_RX_LIMIT_COUNT >> 8, CIR_SLCH); ++ cir_update(CIR_RX_LIMIT_COUNT & 0xff, CIR_SLCL); ++ cir_update(CIR_FIFOCON_TXFIFOCLR | CIR_FIFOCON_TX_TRIGGER_LEV_24 | CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON); ++ cir_update(CIR_IRCON_RECV | CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, CIR_IRCON); ++ cir_update(CIR_IRCON_TXEN | CIR_IRCON_RXEN | CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, CIR_IRCON); ++ ++ /* open interrupt */ ++ cir_update(CIR_IREN_RDR | CIR_IREN_PE, CIR_IREN); ++ ++ ++ cir_wake_update(0xff, CIR_WAKE_IRSTS); ++ ++ cir_wake_update(0x41, CIR_WAKE_FIFO_CMP_DEEP); /* 0x41 = 65 */ ++ cir_wake_update(0x05, CIR_WAKE_FIFO_CMP_TOL); ++ cir_wake_update(CIR_RX_LIMIT_COUNT >> 8, CIR_WAKE_SLCH); ++ cir_wake_update(CIR_RX_LIMIT_COUNT & 0xff, CIR_WAKE_SLCL); ++ cir_wake_update(0xff, CIR_WAKE_FIFOCON); ++ cir_wake_update(0, CIR_WAKE_FIFOCON); ++ cir_wake_update(CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN | CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV | CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL, CIR_WAKE_IRCON); ++ ++ ++#ifdef IR_667_DEBUG ++ printk("%s : cir_resume_reset finish\n", DRVNAME); ++#endif ++ ++ return err; ++} ++ ++ ++/* For resume function use only. 20100119*/ ++static int lirc_wb667_resume_init(void) ++{ ++ int err = 0; ++ ++ /* init lirc buffer */ ++ w83667hg_ir_recv_init(&w83667hg_ir_recv); ++ w83667hg_ir_send_init(&w83667hg_ir_send); ++ ++ /* reset variables in irctl, but no re-locate and no re-register 20100119*/ ++ w83667hg_irctl_resume_reset(&w83667hg_irctl); ++ ++ ++ /* init 667 cir dev */ ++ ++ w83667hg_cir_resume_reset(); ++ ++ ++ return err; ++} ++ ++ ++ ++#ifdef CONFIG_PNP ++ ++/* CIR and CIR WAKE */ ++ ++static struct pnp_driver lirc_wb667_pnp_driver = { ++ .name = PLATNAME, ++ .id_table = pnp_dev_table, ++ .probe = lirc_wb667_pnp_probe, ++ .remove = __devexit_p(lirc_wb667_pnp_remove), ++ .suspend = lirc_wb667_pnp_suspend, ++ .resume = lirc_wb667_pnp_resume, ++}; ++ ++static int __devinit lirc_wb667_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) ++{ ++ /* CIR */ ++ ++ #ifdef IR_667_DEBUG ++ printk("%s receive probe\n", DRVNAME); ++ #endif ++ ++ if (!pnp_port_valid(dev, 0)) ++ return -ENODEV; ++ ++ ++ CIR_BASE = (unsigned int)pnp_port_start(dev, 0); ++ CIR_IRQ_NUM = (unsigned short)pnp_irq(dev, 0); ++ ++ ++ /* CIR WAKE*/ ++ if (!pnp_port_valid(dev, 1)) ++ return -ENODEV; ++ CIR_WAKE_BASE = (unsigned int)pnp_port_start(dev, 1); ++ CIR_WAKE_IRQ_NUM = (unsigned short)pnp_irq(dev, 0); /* share the same irq with CIR device.*/ ++ ++ return 0; ++} ++ ++static void __devexit lirc_wb667_pnp_remove(struct pnp_dev *dev) ++{ ++} ++ ++ ++ ++static int lirc_wb667_pnp_suspend(struct pnp_dev *dev, pm_message_t state) ++{ ++ struct irctl *ir = &w83667hg_irctl; ++ struct ir_recv_t *ir_recv = &w83667hg_ir_recv; ++ struct ir_send_t *ir_send = &w83667hg_ir_send; ++ ++#ifdef IR_667_DEBUG ++ printk("%s receive suspend\n", DRVNAME); ++#endif ++ ++ /* 1. */ ++ spin_lock(&ir->lock); ++ ir->study_state = ST_STUDY_NONE; ++ spin_unlock(&ir->lock); ++ ++ spin_lock(&ir_recv->lock); ++ ir_recv->wake_state = ST_WAKE_NONE; ++ spin_unlock(&ir_recv->lock); ++ ++ spin_lock(&ir_send->lock); ++ ir_send->send_state = ST_SEND_NONE; ++ spin_unlock(&ir_send->lock); ++ ++ /* 2. */ ++ cir_update(0, CIR_IREN); ++ cir_wake_update(0, CIR_WAKE_IREN); ++ ++ ++ /* 3. */ ++ cr_enter_ext(); ++ cr_select_log_dev(CIR_LOG_DEV); ++ cr_update(DEACTIVE_LOG_DEV, 0x30); ++ ++ /*Don't close CIR Wake. When wake-up at power-on, it needs the function. 20091224 ++ cr_select_log_dev(CIR_WAKE_LOG_DEV); ++ cr_update(DEACTIVE_LOG_DEV, 0x30); ++ */ ++ ++ cr_exit_ext(); ++ ++ ++ return 0; ++} ++ ++static int lirc_wb667_pnp_resume(struct pnp_dev *dev) ++{ ++ int ret = 0; ++ ++#ifdef IR_667_DEBUG ++ printk("%s receive resume\n", DRVNAME); ++#endif ++ ++ ++ /* open interrupt */ ++ cir_update(CIR_IREN_RDR | CIR_IREN_PE, CIR_IREN); ++ ++ ++ /* Enable CIR logical device */ ++ cr_enter_ext(); ++ cr_select_log_dev(CIR_LOG_DEV); ++ cr_update(ACTIVE_LOG_DEV, 0x30); ++ ++ ++ /*Don't close CIR Wake. When wake-up at power-on, it needs the function. 20091224 ++ cr_select_log_dev(CIR_WAKE_LOG_DEV); ++ cr_update(ACTIVE_LOG_DEV, 0x30); ++ */ ++ cr_exit_ext(); ++ ++ /* special uninit function for resume only. 20100119 */ ++ lirc_wb667_resume_init(); ++ ++ return ret; ++} ++ ++ ++ ++ ++ ++ ++#endif ++ ++ ++/*//int init_module(void)*/ ++int init_module_wb667(void) ++{ ++ int ret; ++ ++ if (nopnp) { ++ printk("%s does not support Non-PNP kernel now.\n", DRVNAME); ++ } ++ ++#ifdef CONFIG_PNP ++ if (!nopnp) { ++ ++ ret = pnp_register_driver(&lirc_wb667_pnp_driver); ++ if (ret < 0) ++ return ret; ++ ++ ++ ++ } ++#endif /* CONFIG_PNP */ ++ ++ ++ ++ ++ ret = lirc_wb667_init(); ++ if (ret) { ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/*//void cleanup_module(void)*/ ++void cleanup_module_wb667(void) ++{ ++ ++#ifdef CONFIG_PNP ++ if (!nopnp) { ++ pnp_unregister_driver(&lirc_wb667_pnp_driver); ++ ++ } ++#endif /* CONFIG_PNP */ ++ ++ ++ lirc_wb667_uninit(); ++} ++ ++module_init(init_module_wb667); ++module_exit(cleanup_module_wb667); ++ ++ +diff -Naur linux-2.6.33.2/drivers/input/lirc/lirc_wb677_mouse_kbd.c linux-2.6.33.2.patch/drivers/input/lirc/lirc_wb677_mouse_kbd.c +--- linux-2.6.33.2/drivers/input/lirc/lirc_wb677_mouse_kbd.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.33.2.patch/drivers/input/lirc/lirc_wb677_mouse_kbd.c 2010-04-03 18:42:04.214701792 +0200 +@@ -0,0 +1,881 @@ ++/* Notice: ++ Do NOT merge this file with other file. ++ According to lirc group's suggestion, they hope that ++ we should put keyboard/mouse decoding into a separate file if we want to preserve it. ++*/ ++ ++#include ++#include "lirc_wb677_common_extern.h" ++#include "lirc_wb677_mouse_kbd.h" ++ ++ ++void w83667hg_set_key(u8 *set_frame, u8 val, u8 *keycode, u8 *shiftmask) ++{ ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s set key: %d\n", DRVNAME, val); ++#endif ++ ++ if (*set_frame <= KEY_SUBMIT_KEYCODE_FRAME_NUM + 1) { ++ *keycode <<= 1; ++ *keycode |= val; ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s set key keycode:0x%x\n", DRVNAME, *keycode); ++ printk("set frame: %d\n", *set_frame); ++#endif ++ } else { ++ *shiftmask <<= 1; ++ *shiftmask |= val; ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s set key mask:0x%x\n", DRVNAME, *shiftmask); ++ printk("set frame: %d\n", *set_frame); ++#endif ++ } ++ (*set_frame)++; ++} ++ ++ ++int w83667hg_jump_frame(struct irctl *ir, u8 frame_num, unsigned int *buf_num, u8 *out_bit, u8 *decode_status) ++{ ++ unsigned int rlc = 0, cur_buf_num = *buf_num; ++ u8 bit = *out_bit, buf; ++ u8 cur_decode_status = *decode_status; ++ u8 cur_frame_num; ++ ++ cur_frame_num = 1; ++ for (; cur_frame_num <= frame_num; cur_buf_num++) { ++ buf = ir->buf[cur_buf_num]; ++ if (cur_buf_num > ir->buf_count) { ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s: jump frame error\n", DRVNAME); ++ printk("current buf num: %d\n", cur_buf_num); ++ printk("current jumped frame: %d\n", cur_frame_num); ++ printk("current frame length: %d\n", rlc); ++ printk("total cir signal:\n"); ++ for (cur_buf_num = 0; cur_buf_num < ir->buf_count; cur_buf_num++) { ++ printk("0x%x ", ir->buf[cur_buf_num]); ++ if (cur_buf_num % 6 == 5) { ++ printk("\n"); ++ } ++ } ++#endif ++ return -1; ++ } ++ if (bit == (buf & BIT_PULSE_MASK)) { ++ rlc += buf & BIT_LEN; ++ } else { ++ ++ /* decode*/ ++ switch (cur_decode_status) { ++ case ST_DECODE_NEW: ++ if ((rlc > ONE_PULSE_LEN_LOW) && ++ (rlc < ONE_PULSE_LEN_HIGH)) { ++ if (bit & BIT_PULSE_MASK) { ++ cur_decode_status = ST_DECODE_ONE; ++ } else { ++ cur_decode_status = ST_DECODE_ZERO; ++ } ++ } else if ((rlc > TWO_PULSE_LEN_LOW) && ++ (rlc < TWO_PULSE_LEN_HIGH)) { ++ /* error occur, just ignore */ ++ cur_decode_status = ST_DECODE_NEW; ++ cur_frame_num++; ++ } ++ break; ++ case ST_DECODE_ZERO: ++ if ((rlc > ONE_PULSE_LEN_LOW) && ++ (rlc < ONE_PULSE_LEN_HIGH)) { ++ if (bit & BIT_PULSE_MASK) { ++ /* "01" => 0 */ ++ cur_decode_status = ST_DECODE_NEW; ++ cur_frame_num++; ++ } else { ++ /* error */ ++ cur_decode_status = ST_DECODE_NEW; ++ cur_frame_num++; ++ } ++ } else if ((rlc > TWO_PULSE_LEN_LOW) && ++ (rlc < TWO_PULSE_LEN_HIGH)) { ++ if (bit & BIT_PULSE_MASK) { ++ /* "01" => 0 */ ++ cur_decode_status = ST_DECODE_ONE; ++ cur_frame_num++; ++ } else { ++ /* error */ ++ cur_decode_status = ST_DECODE_ZERO; ++ cur_frame_num++; ++ } ++ } ++ break; ++ case ST_DECODE_ONE: ++ if ((rlc > ONE_PULSE_LEN_LOW) && ++ (rlc < ONE_PULSE_LEN_HIGH)) { ++ if (bit & BIT_PULSE_MASK) { ++ /* "11" => error */ ++ cur_decode_status = ST_DECODE_NEW; ++ cur_frame_num++; ++ } else { ++ /* "10" => 1 */ ++ cur_decode_status = ST_DECODE_NEW; ++ cur_frame_num++; ++ } ++ } else if (rlc > TWO_PULSE_LEN_LOW) { ++ if (bit & BIT_PULSE_MASK) { ++ /* "11" => error */ ++ cur_decode_status = ST_DECODE_ONE; ++ cur_frame_num++; ++ } else { ++ /* "10" => 1 */ ++ cur_decode_status = ST_DECODE_ZERO; ++ cur_frame_num++; ++ } ++ } ++ break; ++ } /* switch*/ ++ ++ bit = buf & BIT_PULSE_MASK; ++ rlc = buf & BIT_LEN; ++ } ++ } /* for decode*/ ++ ++/* ++ bit = ir->buf[cur_buf_num] & BIT_PULSE_MASK; ++ if (cur_decode_status & ST_DECODE_NEW) { ++ if (bit) { ++ *decode_status = ST_DECODE_ONE; ++ } else { ++ *decode_status = ST_DECODE_ZERO; ++ } ++ } else { ++ *decode_status = ST_DECODE_NEW; ++ } ++ *out_bit = bit; ++*/ ++ ++ /* Fix problem 1 */ ++ if ((ir->buf[cur_buf_num] & BIT_LEN) > TWO_PULSE_LEN_LOW) { ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s: fix problem 1 in jump_frame()\n", DRVNAME); ++#endif ++#ifdef ALLOW_DEBUG_DECODE ++ if (cur_frame_num > frame_num + 1) { ++ printk("%s error: jump_frame() get a too long frame\n", DRVNAME); ++ } ++#endif ++ cur_buf_num--; ++ } ++ ++ /* copy from jump_iden */ ++ if (cur_decode_status & ST_DECODE_NEW) { ++#ifdef ALLOW_DEBUG_DECODE ++ printk("hey man, it's NEW in jump_frame\n"); ++printk("cur buf: 0x%x\n", ir->buf[cur_buf_num]); ++printk("cur state: 0x%x\n", cur_decode_status); ++#endif ++ *buf_num = --cur_buf_num; ++ /*//cur_buf_num--;*/ ++ *out_bit = ir->buf[cur_buf_num] & BIT_PULSE_MASK; ++ if (*out_bit) { ++ *decode_status = ST_DECODE_ONE; ++ } else { ++ *decode_status = ST_DECODE_ZERO; ++ } ++ } else { ++#ifdef ALLOW_DEBUG_DECODE ++printk("cur buf: 0x%x\n", ir->buf[cur_buf_num]); ++printk("cur state: 0x%x\n", cur_decode_status); ++#endif ++ *buf_num = cur_buf_num; ++ *out_bit = ir->buf[cur_buf_num] & BIT_PULSE_MASK; ++ *decode_status = ST_DECODE_NEW; ++/* ++ if (*out_bit) { ++ *decode_status = ST_DECODE_ONE; ++ } else { ++ *decode_status = ST_DECODE_ZERO; ++ } ++*/ ++ } ++ ++ return 0; ++} ++ ++int w83667hg_jump_head(struct irctl *ir, unsigned int *buf_num) ++{ ++ unsigned int i, rlc = 0, max_buf_count = ir->buf_count; ++ u8 bit = BIT_PULSE_MASK, buf; ++ ++ for (i = 0; i < max_buf_count; i++) { ++ buf = ir->buf[i]; ++ if (bit == (buf & BIT_PULSE_MASK)) { ++ rlc += buf & BIT_LEN; ++ } else { ++ if ((rlc > HEAD_SYNC_LEN_LOW) && ++ (rlc < HEAD_SYNC_LEN_HIGH) && ++ (bit & BIT_PULSE_MASK)) { ++ break; ++ } ++ bit = buf & BIT_PULSE_MASK; ++ rlc = buf & BIT_LEN; ++ } ++ } /* for decode*/ ++ ++ if (i >= max_buf_count) { ++/*//#ifdef ALLOW_DEBUG_DECODE*/ ++#if 0 ++ printk("%s jump pulse error\n", DRVNAME); ++ printk("current buf num: %d\n", *buf_num); ++ printk("current jumped pulse: %d\n", i); ++ printk("current pulse length: %d\n", rlc); ++ printk("total cir signal:\n"); ++ for (i = 0; i < max_buf_count; i++) { ++ printk("0x%x ", ir->buf[i]); ++ if (i % 6 == 5) { ++ printk("\n"); ++ } ++ } ++#endif ++ return -1; ++ } ++ ++ *buf_num = i; ++ ++ return 0; ++} ++ ++ ++int w83667hg_check_identification(u8 val, u8 identification, u8 *cur_iden) ++{ ++ *cur_iden <<= 1; ++ *cur_iden |= val ; ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s current check iden recv: %d\n", DRVNAME, val); ++ printk("%s current iden value: 0x%x\n", DRVNAME, *cur_iden); ++#endif ++ ++ if (identification == (*cur_iden & IDENTIFICATION_CHECK_BIT)) { ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s find identification\n\n", DRVNAME); ++#endif ++ return 0; ++ } else { ++ return -1; ++ } ++} ++ ++int w83667hg_jump_identification(struct irctl *ir, u8 identification, unsigned int *buf_num, u8 *out_bit, u8 *decode_status) ++{ ++ unsigned int rlc = 0, i = 1; ++ u8 bit = *out_bit, buf; ++ u8 cur_iden = 0; ++ u8 cur_decode_status = *decode_status; ++ ++ bit = BIT_PULSE_MASK; ++ cur_decode_status = ST_DECODE_NEW; ++ ++ for (; i < ir->buf_count; i++) { ++ buf = ir->buf[i]; ++#ifdef ALLOW_DEBUG_DECODE ++printk("buf: 0x%x\n", buf); ++#endif ++ if (bit == (buf & BIT_PULSE_MASK)) { ++ rlc += buf & BIT_LEN; ++ } else { ++ /* decode*/ ++ switch (cur_decode_status) { ++ case ST_DECODE_NEW: ++ if ((rlc > ONE_PULSE_LEN_LOW) && ++ (rlc < ONE_PULSE_LEN_HIGH)) { ++ if (bit & BIT_PULSE_MASK) { ++ cur_decode_status = ST_DECODE_ONE; ++ } else { ++ cur_decode_status = ST_DECODE_ZERO; ++ } ++ } else if ((rlc > TWO_PULSE_LEN_LOW) && ++ (rlc < TWO_PULSE_LEN_HIGH)) { ++ /* error occur, just ignore */ ++ cur_decode_status = ST_DECODE_NEW; ++ if (!w83667hg_check_identification(0, identification, &cur_iden)) { ++ goto find_iden; ++ } ++ } ++ break; ++ case ST_DECODE_ZERO: ++ if ((rlc > ONE_PULSE_LEN_LOW) && ++ (rlc < ONE_PULSE_LEN_HIGH)) { ++ if (bit & BIT_PULSE_MASK) { ++ /* "01" => 0 */ ++ cur_decode_status = ST_DECODE_NEW; ++ if (!w83667hg_check_identification(0, identification, &cur_iden)) { ++ goto find_iden; ++ } ++ } else { ++ /* error */ ++ cur_decode_status = ST_DECODE_NEW; ++ if (!w83667hg_check_identification(0, identification, &cur_iden)) { ++ goto find_iden; ++ } ++ } ++ } else if ((rlc > TWO_PULSE_LEN_LOW) && ++ (rlc < TWO_PULSE_LEN_HIGH)) { ++ if (bit & BIT_PULSE_MASK) { ++ /* "01" => 0 */ ++ cur_decode_status = ST_DECODE_ONE; ++ if (!w83667hg_check_identification(0, identification, &cur_iden)) { ++ goto find_iden; ++ } ++ } else { ++ /* error */ ++ cur_decode_status = ST_DECODE_ZERO; ++ if (!w83667hg_check_identification(0, identification, &cur_iden)) { ++ goto find_iden; ++ } ++ } ++ } ++ break; ++ case ST_DECODE_ONE: ++ if ((rlc > ONE_PULSE_LEN_LOW) && ++ (rlc < ONE_PULSE_LEN_HIGH)) { ++ if (bit & BIT_PULSE_MASK) { ++ /* "11" => error */ ++ cur_decode_status = ST_DECODE_NEW; ++ if (!w83667hg_check_identification(0, identification, &cur_iden)) { ++ goto find_iden; ++ } ++ } else { ++ /* "10" => 1 */ ++ cur_decode_status = ST_DECODE_NEW; ++ if (!w83667hg_check_identification(1, identification, &cur_iden)) { ++ goto find_iden; ++ } ++ } ++ } else if (rlc > TWO_PULSE_LEN_LOW) { ++ if (bit & BIT_PULSE_MASK) { ++ /* "11" => error */ ++ cur_decode_status = ST_DECODE_ONE; ++ if (!w83667hg_check_identification(0, identification, &cur_iden)) { ++ goto find_iden; ++ } ++ } else { ++ /* "10" => 1 */ ++ cur_decode_status = ST_DECODE_ZERO; ++ if (!w83667hg_check_identification(1, identification, &cur_iden)) { ++ goto find_iden; ++ } ++ } ++ } ++ break; ++ } /* switch*/ ++ bit = buf & BIT_PULSE_MASK; ++ rlc = buf & BIT_LEN; ++ } ++ } ++ ++ if (i >= ir->buf_count) { ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s jump iden error\n", DRVNAME); ++ printk("current buf num: %d\n", i); ++ printk("current pulse length: %d\n", rlc); ++ printk("total cir signal:\n"); ++ for (i = 0; i < ir->buf_count; i++) { ++ printk("0x%x ", ir->buf[i]); ++ if (i % 6 == 5) { ++ printk("\n"); ++ } ++ } ++#endif ++ return -1; ++ } ++ ++ find_iden: ++#ifdef ALLOW_DEBUG_DECODE ++ printk("current buf num after iden: %d\n", i); ++ printk("current pulse length: %d\n", rlc); ++#endif ++ /* try fix problem 1 */ ++ if ((rlc & BIT_LEN) >= TWO_PULSE_LEN_LOW) { ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s fix problem 1 in jump iden\n", DRVNAME); ++ printk("cur pulse len: %d\n", ir->buf[i] & BIT_LEN); ++#endif ++ *buf_num = i + 1; ++ *out_bit = ir->buf[i] & BIT_PULSE_MASK; ++ if (*out_bit) { ++ *decode_status = ST_DECODE_ZERO; ++ } else { ++ *decode_status = ST_DECODE_ONE; ++ } ++ ++ return 0; ++ } ++ ++ /* now find identification successful! */ ++ { ++ *buf_num = i; ++ i--; ++ *out_bit = ir->buf[i] & BIT_PULSE_MASK; ++ if (bit) { ++ *decode_status = ST_DECODE_ONE; ++ } else { ++ *decode_status = ST_DECODE_ZERO; ++ } ++ } ++#ifdef ALLOW_DEBUG_DECODE ++ printk("total cir signal:\n"); ++ for (i = 0; i < ir->buf_count; i++) { ++ printk("0x%x ", ir->buf[i]); ++ if (i % 7 == 6) { ++ printk("\n"); ++ } ++ } ++ printk("\n"); ++#endif ++ ++ return 0; ++} ++ ++void w83667hg_submit_key(struct irctl *ir) ++{ ++ unsigned int rlc = 0, buf_num = 0, i; ++ /* current usb keyboard key code setting, usb_kbd_keycode[keycode] */ ++ unsigned int input_code; ++ u8 bit, buf; ++ /* keycode and shiftmask parts in mce keyboard protocol*/ ++ u8 keycode = 0, shiftmask = 0; ++ u8 decode_status; ++ u8 frame_num, set_frame; ++ ++ /* 1) jump head */ ++ if (w83667hg_jump_head(ir, &buf_num)) { ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s: decode key jump head error\n", DRVNAME); ++#endif ++ return; ++ } ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s buf_num after jump head: %d\n", DRVNAME, buf_num); ++#endif ++ ++ /* 2) jump identification */ ++ if (w83667hg_jump_identification(ir, KEY_IDENTIFICATION, &buf_num, &bit, &decode_status)) { ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s: decode key jump identification error\n", DRVNAME); ++#endif ++ return; ++ } ++ ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s jump iden success\n\n", DRVNAME); ++ printk("%s buf_num after jump iden: %d\n", DRVNAME, buf_num); ++ printk("decode status: 0x%x, bit: 0x%x\n", decode_status, bit); ++#endif ++ ++ /* 3) jump "unknown", "C" and "CodeSet" parts in mce keyboard signal */ ++ if (w83667hg_jump_frame(ir, KEY_KEYCODE_FRAME_AFTER_I_START, &buf_num, &bit, &decode_status)) { ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s: decode key jump pulse error\n", DRVNAME); ++#endif ++ return; ++ } ++ ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s buf_num after jump pulse: %d\n", DRVNAME, buf_num); ++ printk("decode status: 0x%x, bit: 0x%x\n", decode_status, bit); ++ frame_num = buf_num; ++ for (; frame_num < ir->buf_count; frame_num++) { ++ printk("0x%x\t", ir->buf[frame_num]); ++ if (frame_num % 7 == 6) { ++ printk("\n"); ++ } ++ } ++ printk("\n"); ++#endif ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s: decode status before check key: %x\n", DRVNAME, decode_status); ++#endif ++ ++ ++ /* 4) deocde "KeyCode" and "ShiftMask" parts in mce key signal */ ++ frame_num = 1, set_frame = 1; ++ for (; frame_num < KEY_FRAME_AFTER_JUMP + 2; buf_num++) { ++ if (bit != (ir->buf[buf_num] & BIT_PULSE_MASK)) { ++ /* decode*/ ++ if (rlc > PULSE_SILENT_LEN_LOW) { ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s error: cir signal end before received all key pulses\n", DRVNAME); ++ printk("bit: %d ", bit); ++ printk("rlc: %d\n", rlc); ++ printk("current pulse number: %d\n", frame_num); ++#endif ++ if (decode_status == ST_DECODE_ONE) { ++ /* must set the last one */ ++ w83667hg_set_key(&set_frame, 1, &keycode, &shiftmask); ++ } ++ break; ++ } ++ switch (decode_status) { ++ case ST_DECODE_NEW: ++ if ((rlc > ONE_PULSE_LEN_LOW) && ++ (rlc < ONE_PULSE_LEN_HIGH)) { ++ if (bit & BIT_PULSE_MASK) { ++ decode_status = ST_DECODE_ONE; ++ } else { ++ decode_status = ST_DECODE_ZERO; ++ } ++ } else if ((rlc > TWO_PULSE_LEN_LOW) && ++ (rlc < TWO_PULSE_LEN_HIGH)) { ++ /* error occur, just ignore */ ++ decode_status = ST_DECODE_NEW; ++ w83667hg_set_key(&set_frame, 0, &keycode, &shiftmask); ++ frame_num += 1; ++ } ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s cur state: %x\n", DRVNAME, decode_status); ++#endif ++ break; ++ case ST_DECODE_ZERO: ++ if ((rlc > ONE_PULSE_LEN_LOW) && ++ (rlc < ONE_PULSE_LEN_HIGH)) { ++ if (bit & BIT_PULSE_MASK) { ++ /* "01" => 0 */ ++ decode_status = ST_DECODE_NEW; ++ w83667hg_set_key(&set_frame, 0, &keycode, &shiftmask); ++ frame_num += 1; ++ } else { ++ /* error */ ++ decode_status = ST_DECODE_NEW; ++ w83667hg_set_key(&set_frame, 0, &keycode, &shiftmask); ++ } ++ } else if ((rlc > TWO_PULSE_LEN_LOW) && ++ (rlc < TWO_PULSE_LEN_HIGH)) { ++ if (bit & BIT_PULSE_MASK) { ++ /* "01" => 0 */ ++ decode_status = ST_DECODE_ONE; ++ w83667hg_set_key(&set_frame, 0, &keycode, &shiftmask); ++ frame_num += 1; ++ } else { ++ /* error */ ++ decode_status = ST_DECODE_ZERO; ++ w83667hg_set_key(&set_frame, 0, &keycode, &shiftmask); ++ } ++ } ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s cur state: %x\n", DRVNAME, decode_status); ++#endif ++ break; ++ case ST_DECODE_ONE: ++ if ((rlc > ONE_PULSE_LEN_LOW) && ++ (rlc < ONE_PULSE_LEN_HIGH)) { ++ if (bit & BIT_PULSE_MASK) { ++ /* "11" => error */ ++ decode_status = ST_DECODE_NEW; ++ w83667hg_set_key(&set_frame, 0, &keycode, &shiftmask); ++ } else { ++ /* "10" => 1 */ ++ decode_status = ST_DECODE_NEW; ++ w83667hg_set_key(&set_frame, 1, &keycode, &shiftmask); ++ frame_num += 1; ++ } ++ } else if (rlc > TWO_PULSE_LEN_LOW) { ++ if (bit & BIT_PULSE_MASK) { ++ /* "11" => error */ ++ decode_status = ST_DECODE_ONE; ++ w83667hg_set_key(&set_frame, 0, &keycode, &shiftmask); ++ } else { ++ /* "10" => 1 */ ++ decode_status = ST_DECODE_ZERO; ++ w83667hg_set_key(&set_frame, 1, &keycode, &shiftmask); ++ frame_num += 1; ++ } ++ } ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s cur state %x\n", DRVNAME, decode_status); ++#endif ++ break; ++ } /* switch*/ ++ bit = ir->buf[buf_num] & BIT_PULSE_MASK; ++ rlc = ir->buf[buf_num] & BIT_LEN; ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s: decode keyboard buf: 0x%x\n", DRVNAME, ir->buf[buf_num]); ++#endif ++ ++ } else { ++ /* continue last pulse*/ ++ rlc += ir->buf[buf_num] & BIT_LEN; ++ } ++ ++ } /* for*/ ++ ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s: after decode keyboard:\n", DRVNAME); ++ printk("keycode: 0x%x ", keycode); ++ printk("shiftmask: 0x%x\n\n", shiftmask); ++#endif ++ ++ /* 5) submit keycode to input */ ++ if (keycode != ir->pressed_keycode) { ++ if (ir->pressed_keycode) { ++ input_code = (unsigned int)usb_kbd_keycode[ir->pressed_keycode]; ++ input_report_key(ir->input_dev, input_code, 0); ++ } ++ ir->pressed_keycode = keycode; ++ if (keycode) { ++ input_code = (unsigned int)usb_kbd_keycode[keycode]; ++ input_report_key(ir->input_dev, input_code, 1); ++ } ++ } ++ ++ /* 6) submit shiftmask to input */ ++ ++ if (shiftmask != ir->pressed_shiftmask) { ++ for (i = 0; i < 7; i++) { ++ buf = 1<pressed_shiftmask) && (!(buf & shiftmask))) { ++ input_code = (unsigned int)usb_kbd_keycode[0xE0 + i]; ++ input_report_key(ir->input_dev, input_code, 0); ++ } else if (!(buf & ir->pressed_shiftmask) && (buf & shiftmask)) { ++ input_code = (unsigned int)usb_kbd_keycode[0xE0 + i]; ++ input_report_key(ir->input_dev, input_code, 1); ++ } ++ } /* for*/ ++ ir->pressed_shiftmask = shiftmask; ++ } ++} ++ ++void w83667hg_set_mouse(u8 *set_frame, u8 val, u8 *deltay, u8 *deltax, u8 *clickrl) ++{ ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s set mouse val:%d\n", DRVNAME, val); ++#endif ++ if (*set_frame <= MOUSE_SUBMIT_DELTAY_FRAME_NUM + 1) { ++ *deltay <<= 1; ++ *deltay |= val; ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s set mouse delta y:0x%x\n", DRVNAME, *deltay); ++#endif ++ } else if (*set_frame <= MOUSE_SUBMIT_DELTAX_FRAME_NUM) { ++ *deltax <<= 1; ++ *deltax |= val; ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s set mouse delta x:0x%x\n", DRVNAME, *deltax); ++#endif ++ } else if (*set_frame <= MOUSE_SUBMIT_L_FRAME_NUM) { ++ /* move right key, then set left key */ ++ *clickrl <<= 1; ++ *clickrl |= val; ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s set mouse l:0x%x\n", DRVNAME, *clickrl); ++ printk("set pulse: %d\n", *set_frame); ++#endif ++ } ++ (*set_frame)++; ++} ++ ++void w83667hg_submit_mouse(struct irctl *ir) ++{ ++ unsigned int rlc = 0, buf_num = 0; ++ u8 bit; ++ /* deltax, deltay and clickrl parts in mce mouse protocol*/ ++ u8 deltax = 0, deltay = 0, clickrl = 0; ++ signed char x, y; ++ u8 decode_status; ++ u8 frame_num, set_frame; ++ ++ /* 1) jump head */ ++ if (w83667hg_jump_head(ir, &buf_num)) { ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s: decode mouse jump head error\n", DRVNAME); ++#endif ++ return; ++ } ++ ++ /* 2) jump identification */ ++ if (w83667hg_jump_identification(ir, MOUSE_IDENTIFICATION, &buf_num, &bit, &decode_status)) { ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s: decode mouse jump identification error\n", DRVNAME); ++#endif ++ return; ++ } ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s: after iden mouse:\n", DRVNAME); ++ printk("decode status: 0x%x, bit: 0x%x\n", decode_status, bit); ++ frame_num = buf_num; ++ for (; frame_num < ir->buf_count; frame_num++) { ++ printk("0x%x ", ir->buf[frame_num]); ++ if (frame_num % 7 == 6) { ++ printk("\n"); ++ } ++ } ++ printk("\n"); ++#endif ++ ++ /* 3) jump "unknown" part in mce mouse signal */ ++ if (w83667hg_jump_frame(ir, MOUSE_DELTAY_PULSE_AFTER_I_START, &buf_num, &bit, &decode_status)) { ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s: decode mouse jump pulse error\n", DRVNAME); ++#endif ++ return; ++ } ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s: after jump pulse buf num: %d\n", DRVNAME, buf_num); ++ printk("decode status: 0x%x, bit: 0x%x\n", decode_status, bit); ++ frame_num = buf_num; ++ for (; frame_num < ir->buf_count; frame_num++) { ++ printk("0x%x ", ir->buf[frame_num]); ++ if (frame_num % 7 == 6) { ++ printk("\n"); ++ } ++ } ++ printk("\n"); ++#endif ++ ++ /* 4) deocde "deltay", "deltax", "r" and "l" parts in mce mouse signal */ ++ frame_num = 1, set_frame = 1; ++ for (; frame_num < MOUSE_CHECKSUM_FRAME_AFTER_JUMP + 1; buf_num++) { ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s: cur buf: 0x%x, pulse num: %d\n", DRVNAME, ir->buf[buf_num], frame_num); ++ printk("decode status: 0x%x\n", decode_status); ++#endif ++ if (bit != (ir->buf[buf_num] & BIT_PULSE_MASK)) { ++ /* decode*/ ++ if (rlc > PULSE_SILENT_LEN_LOW) { ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s error: cir signal end before received all mouse pulses\n", DRVNAME); ++ printk("bit: %d ", bit); ++ printk("rlc: %d\n", rlc); ++#endif ++ break; ++ } ++ switch (decode_status) { ++ case ST_DECODE_NEW: ++ if ((rlc > ONE_PULSE_LEN_LOW) && ++ (rlc < ONE_PULSE_LEN_HIGH)) { ++ if (bit & BIT_PULSE_MASK) { ++ decode_status = ST_DECODE_ONE; ++ } else { ++ decode_status = ST_DECODE_ZERO; ++ } ++ } else ++ if ((rlc > TWO_PULSE_LEN_LOW) && ++ (rlc < TWO_PULSE_LEN_HIGH)) { ++ /* error occur, just ignore */ ++ decode_status = ST_DECODE_NEW; ++ w83667hg_set_mouse(&set_frame, 0, &deltay, &deltax, &clickrl); ++ frame_num += 1; ++ } ++ break; ++ case ST_DECODE_ZERO: ++ if ((rlc > ONE_PULSE_LEN_LOW) && ++ (rlc < ONE_PULSE_LEN_HIGH)) { ++ if (bit & BIT_PULSE_MASK) { ++ /* "01" => 0 */ ++ decode_status = ST_DECODE_NEW; ++ w83667hg_set_mouse(&set_frame, 0, &deltay, &deltax, &clickrl); ++ frame_num += 1; ++ } else { ++ /* error */ ++ decode_status = ST_DECODE_NEW; ++ w83667hg_set_mouse(&set_frame, 0, &deltay, &deltax, &clickrl); ++ } ++ } else if ((rlc > TWO_PULSE_LEN_LOW) && ++ (rlc < TWO_PULSE_LEN_HIGH)) { ++ if (bit & BIT_PULSE_MASK) { ++ /* "01" => 0 */ ++ decode_status = ST_DECODE_ONE; ++ w83667hg_set_mouse(&set_frame, 0, &deltay, &deltax, &clickrl); ++ frame_num += 1; ++ } else { ++ /* error */ ++ decode_status = ST_DECODE_ZERO; ++ w83667hg_set_mouse(&set_frame, 0, &deltay, &deltax, &clickrl); ++ } ++ } ++ break; ++ case ST_DECODE_ONE: ++ if ((rlc > ONE_PULSE_LEN_LOW) && ++ (rlc < ONE_PULSE_LEN_HIGH)) { ++ if (bit & BIT_PULSE_MASK) { ++ /* "11" => error */ ++ decode_status = ST_DECODE_NEW; ++ w83667hg_set_mouse(&set_frame, 0, &deltay, &deltax, &clickrl); ++ } else { ++ /* "10" => 1 */ ++ decode_status = ST_DECODE_NEW; ++ w83667hg_set_mouse(&set_frame, 1, &deltay, &deltax, &clickrl); ++ frame_num += 1; ++ } ++ } else if (rlc > TWO_PULSE_LEN_LOW) { ++ if (bit & BIT_PULSE_MASK) { ++ /* "11" => error */ ++ decode_status = ST_DECODE_ONE; ++ w83667hg_set_mouse(&set_frame, 0, &deltay, &deltax, &clickrl); ++ frame_num += 1; ++ } else { ++ /* "10" => 1 */ ++ decode_status = ST_DECODE_ZERO; ++ w83667hg_set_mouse(&set_frame, 1, &deltay, &deltax, &clickrl); ++ frame_num += 1; ++ } ++ } ++ break; ++ } /* switch*/ ++ bit = ir->buf[buf_num] & BIT_PULSE_MASK; ++ rlc = ir->buf[buf_num] & BIT_LEN; ++ } else { ++ /* continue last pulse*/ ++ rlc += ir->buf[buf_num] & BIT_LEN; ++ } ++ ++ } /* for*/ ++ ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s: after decode mouse:\n", DRVNAME); ++ frame_num = buf_num; ++ for (; frame_num < ir->buf_count; frame_num++) { ++ printk("0x%x ", ir->buf[frame_num]); ++ if (frame_num % 7 == 6) { ++ printk("\n"); ++ } ++ } ++ printk("\n"); ++#endif ++ ++ /* fix deltax lost problem */ ++ if (deltax) { ++ deltax <<= 1; ++ deltax |= 1; ++ } ++ ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s: after decode mouse:\n", DRVNAME); ++ printk("deltay: 0x%x ", deltay); ++ printk("deltax: 0x%x ", deltax); ++ printk("click rl: 0x%x \n\n", clickrl); ++#endif ++ if (deltay & 0x40) { ++ y = -((~deltay & 0x7f) + 1); ++ } else { ++ y = deltay; ++ } ++ if (deltax & 0x40) { ++ x = -((~deltax & 0x7f) + 1); ++ } else { ++ x = deltax; ++ } ++ ++ /* 5) send to input */ ++ ++#ifdef ALLOW_DEBUG_DECODE ++ printk("%s: after decode mouse and rebuild:\n", DRVNAME); ++ printk("y: %d ", y); ++ printk("x: %d ", x); ++ printk("click rl: 0x%x \n\n", clickrl); ++#endif ++ ++ input_report_rel(ir->input_dev, REL_X, x); ++ input_report_rel(ir->input_dev, REL_Y, y); ++ ++ input_report_key(ir->input_dev, BTN_LEFT, clickrl & 1); ++ input_report_key(ir->input_dev, BTN_RIGHT, (clickrl >> 1) & 1); ++} ++ ++ +diff -Naur linux-2.6.33.2/drivers/input/lirc/lirc_wb677_mouse_kbd.h linux-2.6.33.2.patch/drivers/input/lirc/lirc_wb677_mouse_kbd.h +--- linux-2.6.33.2/drivers/input/lirc/lirc_wb677_mouse_kbd.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.33.2.patch/drivers/input/lirc/lirc_wb677_mouse_kbd.h 2010-04-03 18:42:04.216701266 +0200 +@@ -0,0 +1,190 @@ ++#ifndef __LIRC_WB677_MOUSE_KBD_HEADER__ ++#define __LIRC_WB677_MOUSE_KBD_HEADER__ ++ ++ ++ ++ ++/* jump asked frame number, can use on key, mouse and controller signals ++ * ++ * after jump frame_num, current frame number = frame_num + 1 ++ * record current buf number of irctl buf ++ * record current pulse's bit and decode_status ++ * ++ * problem 1: ++ * When jump_frame() stops on a two_width_len pulse, the buf_num will be the ++ * second pulse of the double_width_len pulse. ++ * So jump_frame() must increase buf_num 1 on problem 1. ++ * For sample period is 50us, a 444us piulse's minimal sample value is 7, and ++ * two piulses' minimal sample value is 15. So just increase buf_num 1 works ++ * fine. If sample period changes, this solution also need change. ++ * ++ * one_width_len pulse: ++ * _ _ ++ * .| |_| |_. (1010) ++ * ^ ++ * | ++ * stop: jumped frame_num ++ * ++ * ++ * problem 1: double_width_len pulse: ++ * __ _ ++ * .| |__| |. (11001) ++ * ^ ++ * | ++ * stop: jumped frame_num + 1, buf_num + 1 ++ * ++ * so if cur buf len > TWO_PULSE_LEN_LOW, buf_num -- ++ * and recheck polar bit and decode_status ++ * decode_status go back 1 buf, ++ * NEW -> ONE/ZERO; ONE/ZERO -> NEW ++ * ++ * jump out of buf limit, return < 0 ++ */ ++int w83667hg_jump_frame(struct irctl *ir, u8 frame_num, unsigned int *buf_num, u8 *out_bit, u8 *decode_status); ++ ++/* jump MCE head sync signal (1111 11) ++ * ++ * after jump signal head, current pulse number = 7 ++ * record current buf number of irctl buf ++ * record current pulse's bit and decode_status ++ * ++ * jump out of buf limit, return < 0 ++ */ ++int w83667hg_jump_head(struct irctl *ir, unsigned int *buf_num); ++ ++#define KEY_IDENTIFICATION 0x04 ++#define MOUSE_IDENTIFICATION 0x01 ++#define IDENTIFICATION_CHECK_BIT 0xF ++ ++/* check mce identification ++ * ++ * compare identification and cur_iden ++ * same return 0 ++ * else return < 0, need continue check ++ */ ++int w83667hg_check_identification(u8 val, u8 identification, u8 *cur_iden); ++ ++/* jump mce identification ++ * can use on key, mouse and controller signals ++ * ++ * jump and search identification parts ++ * record current buf number of irctl buf ++ * ++ * jump all pulse until find identification ++ * ++ * ++ * ++ * problem 1: ++ * When jump_identification() stops on a double_width_len pulse, the buf_num will be the ++ * second pulse of the doule_width_len frame. ++ * ++ * one_width_len pulse: ++ * _ _ ++ * .| |_| |_. (1010) ++ * ^ ++ * | ++ * stop: jumped frame_num ++ * ++ * ++ * problem 1: double_width_len pulse: ++ * __ _ ++ * .| |__| |. (11001) ++ * ^ ++ * | ++ * stop: jumped frame_num + 1, buf_num + 2 ++ * ++ * solution: ++ * Now buf_num is the next double-pulse-width buf. ++ * Just decrease buf_num by one can fix this problem. ++ * ++ * ++ * After jump iden, output may diff by decode status: ++ * 1) ++ * For status ONE and ZERO, all decode work is done. ++ * Set status as NEW and inverse out_bit ++ * in fact, bit is not important, for a buf can indicate one frame, whether its ++ * length is one or two, the bit can be ignored ++ * ++ * after jump frame, all status is NEW! reset them as inverse polar bit ++ * ++ * ++ * ++ * ++ * can not find identification, return < 0 ++ */ ++int w83667hg_jump_identification(struct irctl *ir, u8 identification, unsigned int *buf_num, u8 *out_bit, u8 *decode_status); ++ ++ ++/* the frame number between identification and code */ ++#define KEY_KEYCODE_FRAME_AFTER_I_START 16 /*//32*/ ++#define KEY_FRAME_AFTER_JUMP 16 /*//64*/ ++#define KEY_SUBMIT_KEYCODE_FRAME_NUM 8 ++ ++ ++#define MOUSE_DELTAY_PULSE_AFTER_I_START 8 ++#define MOUSE_CHECKSUM_FRAME_AFTER_JUMP 16 ++#define MOUSE_SUBMIT_DELTAY_FRAME_NUM 7 ++#define MOUSE_SUBMIT_DELTAX_FRAME_NUM 14 ++#define MOUSE_SUBMIT_R_FRAME_NUM 15 ++#define MOUSE_SUBMIT_L_FRAME_NUM 16 ++ ++ ++/* FIXME, not sure this value, select a large number*/ ++#define PULSE_SILENT_LEN_LOW 90 ++ ++ ++/* set keycode and shiftmask for keyboard */ ++void w83667hg_set_key(u8 *set_frame, u8 val, u8 *keycode, u8 *shiftmask); ++ ++/* decode mce keyboard signal and send data to input ++ * ++ * 1) jump mce keyboard signal sync head (1111 11) ++ * 2) jump identification (0100) ++ * pulse number before identification is not sure ++ * 3) jump "unknown", "C" and "CodeSet" parts in mce keyboard signal ++ * 4) deocde "KeyCode" and "ShiftMask" parts in mce key signal ++ * 5) send keycode to input by array usb_kbd_keycode ++ * 6) send shiftmask to input by array usb_kbd_keycode ++ */ ++void w83667hg_submit_key(struct irctl *ir); ++ ++/* set deltax, deltay, x, y for mce mouse */ ++void w83667hg_set_mouse(u8 *set_frame, u8 val, u8 *deltay, u8 *deltax, u8 *clickrl); ++ ++/* decode mce mouse signal and send data to input ++ * ++ * 1) jump mce mouse signal sync head (1111 11) ++ * 2) jump identification (0001) ++ * pulse number before identification is not sure ++ * 3) jump "unknown" part in mce mouse signal ++ * 4) deocde "deltay", "deltax", "r" and "l" parts in mce mouse signal ++ * 5) send these parts to input ++ */ ++void w83667hg_submit_mouse(struct irctl *ir); ++ ++ ++ ++#define BIT_PULSE_MASK 0x80 ++#define BIT_LEN 0x7f ++ ++ ++ ++/* "10"=>1 (+2), "01"=>0 (+2) */ ++#define ST_DECODE_NEW 0x01 ++#define ST_DECODE_ZERO 0x02 ++#define ST_DECODE_ONE 0x04 ++ ++/* RC6 sync head: 1111 11 ++ * 6 * 444us / 50us (sample period) * 0.85 (inaccuracy) ++ */ ++#define HEAD_SYNC_LEN_LOW 45 ++/* 7 pulses long, for inaccuracy */ ++#define HEAD_SYNC_LEN_HIGH 71 ++ ++#define ONE_PULSE_LEN_LOW 2 ++#define ONE_PULSE_LEN_HIGH 10 ++#define TWO_PULSE_LEN_LOW 10 ++#define TWO_PULSE_LEN_HIGH 15 ++ ++ ++#endif +diff -Naur linux-2.6.33.2/drivers/input/lirc/Makefile linux-2.6.33.2.patch/drivers/input/lirc/Makefile +--- linux-2.6.33.2/drivers/input/lirc/Makefile 2010-04-03 18:40:52.422576074 +0200 ++++ linux-2.6.33.2.patch/drivers/input/lirc/Makefile 2010-04-03 18:42:04.217701457 +0200 +@@ -1,6 +1,9 @@ + # Makefile for the lirc drivers. + # + ++# Multipart objects. ++lirc_wb677-objs := lirc_wb677_main.o lirc_wb677_mouse_kbd.o ++ + # Each configuration option enables a list of files. + + obj-$(CONFIG_INPUT_LIRC) += lirc_dev.o +@@ -12,6 +15,7 @@ + obj-$(CONFIG_LIRC_IT87) += lirc_it87.o + obj-$(CONFIG_LIRC_ITE8709) += lirc_ite8709.o + obj-$(CONFIG_LIRC_MCEUSB) += lirc_mceusb.o ++obj-$(CONFIG_LIRC_NCT667X) += lirc_wb677.o + obj-$(CONFIG_LIRC_PARALLEL) += lirc_parallel.o + obj-$(CONFIG_LIRC_SASEM) += lirc_sasem.o + obj-$(CONFIG_LIRC_SERIAL) += lirc_serial.o +diff -Naur linux-2.6.33.2/drivers/input/lirc/wb83677hg_ir.h linux-2.6.33.2.patch/drivers/input/lirc/wb83677hg_ir.h +--- linux-2.6.33.2/drivers/input/lirc/wb83677hg_ir.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.33.2.patch/drivers/input/lirc/wb83677hg_ir.h 2010-04-03 18:42:04.218701439 +0200 +@@ -0,0 +1,44 @@ ++#define IR_IOC_MAGIC 'i' ++ ++/* output chip registers for debug */ ++#define IR_DUMPCIRREG _IO(IR_IOC_MAGIC, 0x80) ++#define IR_DUMPWAKEREG _IO(IR_IOC_MAGIC, 0x81) ++ ++ ++/* study wake key on MCE CIR controller */ ++#define IR_IOLEARNWAKE _IO(IR_IOC_MAGIC, 0x82) ++ ++/* disable cir wake */ ++#define IR_IOUNSETWAKE _IO(IR_IOC_MAGIC, 0x83) ++ ++/* enable cir wake */ ++#define IR_IOSETWAKE _IO(IR_IOC_MAGIC, 0x84) ++ ++ ++/* get carrier for study ir signal */ ++#define IR_IOGETCARRIER _IOR(IR_IOC_MAGIC, 0x85, unsigned int) ++ ++/* set carrier for send ir signal */ ++#define IR_IOSETCARRIER _IOW(IR_IOC_MAGIC, 0x86, unsigned int) ++ ++/* start/stop study key */ ++#define IR_IOSTARTSTUDY _IO(IR_IOC_MAGIC, 0x88) ++#define IR_IOSTOPSTUDY _IO(IR_IOC_MAGIC, 0x89) ++ ++/* study key buf len */ ++#define IR_IOSTUDYLEN _IOR(IR_IOC_MAGIC, 0x8A, unsigned int) ++ ++/* study key buf data */ ++#define IR_IOSTUDYBUF _IOR(IR_IOC_MAGIC, 0x8B, unsigned char) ++ ++/* restudy key buf data */ ++#define IR_IORESTUDYBUF _IO(IR_IOC_MAGIC, 0x8C) ++ ++ ++/* clean data */ ++#define IR_IOCLEANDATA _IO(IR_IOC_MAGIC, 0x8E) ++ ++ ++/* check chip identification for the applications which are related to hardware */ ++#define IR_CHECKCHIP _IOR(IR_IOC_MAGIC, 0x8F, unsigned long long) ++ diff --git a/packages/mediacenter/xbmc-theme-Confluence/url b/packages/mediacenter/xbmc-theme-Confluence/url index bb8258f751..fade2f3c6f 100644 --- a/packages/mediacenter/xbmc-theme-Confluence/url +++ b/packages/mediacenter/xbmc-theme-Confluence/url @@ -1 +1 @@ -http://sources.openelec.tv/svn/xbmc-theme-Confluence-29914.tar.bz2 +http://sources.openelec.tv/svn/xbmc-theme-Confluence-29890.tar.bz2 diff --git a/packages/mediacenter/xbmc-theme-PM3-HD/url b/packages/mediacenter/xbmc-theme-PM3-HD/url index 75ccaeea51..d9c23c30c2 100644 --- a/packages/mediacenter/xbmc-theme-PM3-HD/url +++ b/packages/mediacenter/xbmc-theme-PM3-HD/url @@ -1 +1 @@ -http://sources.openelec.tv/svn/xbmc-theme-PM3-HD-29914.tar.bz2 +http://sources.openelec.tv/svn/xbmc-theme-PM3-HD-29890.tar.bz2 diff --git a/packages/mediacenter/xbmc/url b/packages/mediacenter/xbmc/url index e4d83fad7a..2051c6e482 100644 --- a/packages/mediacenter/xbmc/url +++ b/packages/mediacenter/xbmc/url @@ -1 +1 @@ -http://sources.openelec.tv/svn/xbmc-29914.tar.bz2 +http://sources.openelec.tv/svn/xbmc-29890.tar.bz2