Add preliminary support for CyIO/BooEvent
This commit is contained in:
parent
76f20f4d40
commit
6a09ec6d7a
@ -19,3 +19,4 @@ obj-$(CONFIG_S3C2416_PM) += pm.o
|
||||
# Machine support
|
||||
|
||||
obj-$(CONFIG_MACH_SMDK2416) += mach-smdk2416.o
|
||||
obj-$(CONFIG_MACH_SMDK2416) += qisda-utils.o
|
||||
|
||||
32
arch/arm/mach-s3c2416/cyio-dev.c
Normal file
32
arch/arm/mach-s3c2416/cyio-dev.c
Normal file
@ -0,0 +1,32 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/irq.h>
|
||||
#include <asm/arch/fb.h>
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/arch/udc.h>
|
||||
#include <asm/arch/l3.h>
|
||||
#include <asm/arch/audio.h>
|
||||
|
||||
#include <asm/arch/buttons.h>
|
||||
|
||||
#include "devs.h"
|
||||
#include "cpu.h"
|
||||
|
||||
struct platform_device s3c_device_cyio = {
|
||||
.name = "cyio2",
|
||||
.id = -1,
|
||||
};
|
||||
EXPORT_SYMBOL(s3c_device_cyio);
|
||||
|
||||
166
arch/arm/mach-s3c2416/qisda-utils.c
Normal file
166
arch/arm/mach-s3c2416/qisda-utils.c
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* qisda-utils.c
|
||||
*
|
||||
* Copyright 2009 Bookeen/Qisda
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
#include <asm/arch/regs-irq.h>
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <asm/arch/regs-udc-hs.h>
|
||||
#include <asm/arch/regs-s3c2416-clock.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/irq.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include <asm/arch/regs-serial.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-gpioj.h>
|
||||
#include <asm/arch/regs-lcd.h>
|
||||
#include <asm/arch/regs-mem.h>
|
||||
|
||||
#include <asm/plat-s3c24xx/s3c2410.h>
|
||||
#include <asm/plat-s3c24xx/s3c2440.h>
|
||||
#include <asm/plat-s3c24xx/clock.h>
|
||||
#include <asm/plat-s3c24xx/devs.h>
|
||||
#include <asm/plat-s3c24xx/cpu.h>
|
||||
|
||||
#include <asm/plat-s3c24xx/common-smdk.h>
|
||||
|
||||
int charging_source = 3;
|
||||
EXPORT_SYMBOL(charging_source);
|
||||
|
||||
|
||||
/* Qisda, ShiYong Lin, 2009/09/10, Detect insertion source {*/
|
||||
/*Leo*/
|
||||
int IsWallCharger(void)
|
||||
{
|
||||
/*u32 i=0;*/
|
||||
/*u32 i=0;*/
|
||||
u32 read_pin=99;/*, test_pin = 99;*/
|
||||
udelay(1000);
|
||||
|
||||
if((readl(S3C2410_GPGDAT)&0x2)==0x2){
|
||||
s3c2410_gpio_cfgpin(S3C2443_GPH14, S3C2443_GPH14_OUTP);
|
||||
s3c2410_gpio_setpin(S3C2443_GPH14, 1); /* usb power enbale */
|
||||
s3c2410_gpio_cfgpin(S3C2410_GPD13, S3C2410_GPD13_OUTP);
|
||||
s3c2410_gpio_setpin(S3C2410_GPD13,1); /* usb power enbale */
|
||||
|
||||
/* if reset by sleep wakeup, control the retention I/O cell */
|
||||
if (__raw_readl(S3C_RSTSTAT) & 0x8)
|
||||
__raw_writel(__raw_readl(S3C_RSTCON)|(1<<16), S3C_RSTCON);
|
||||
|
||||
__raw_writel(__raw_readl(S3C2410_MISCCR)&~(1<<12), S3C2410_MISCCR);
|
||||
__raw_writel(__raw_readl(S3C_PWRCFG)|(1<<4), S3C_PWRCFG);
|
||||
__raw_writel((0<<2)|(1<<0), S3C_URSTCON);
|
||||
|
||||
udelay(1000);
|
||||
__raw_writel((1<<2)|(0<<0), S3C_URSTCON);
|
||||
__raw_writel((0<<2)|(0<<0), S3C_URSTCON);
|
||||
__raw_writel((0<<3)|(0<<2)|(0<<1)|(0<<0), S3C_PHYCTRL);
|
||||
__raw_writel((1<<31)|(0<<4)|(0<<3)|(0<<2)|(0<<1)|(0<<0), S3C_PHYPWR);
|
||||
__raw_writel((0<<31)|(1<<2)|(1<<1)|(1<<0), S3C_UCLKCON);
|
||||
__raw_writel((1<<31)|(1<<2)|(1<<1)|(1<<0), S3C_UCLKCON);
|
||||
}
|
||||
|
||||
|
||||
read_pin = __raw_readl(S3C_UDC_SYS_STATUS_REG)&0x60;
|
||||
if(read_pin !=0x60){
|
||||
|
||||
// printk("usb\n");
|
||||
#if defined(CONFIG_QISDA_E600_EVT2)|| defined(CONFIG_QISDA_QD060N00_DVT1_1)
|
||||
if((readl(S3C2410_GPGDAT) &(1<<1))==0)
|
||||
{
|
||||
if((readl(S3C2410_GPHDAT) &&(1<<11))==0)
|
||||
{
|
||||
printk("3G Module off\n");
|
||||
|
||||
s3c2410_gpio_cfgpin(S3C2443_GPH14, S3C2443_GPH14_OUTP);
|
||||
s3c2410_gpio_setpin(S3C2443_GPH14, 0);
|
||||
}
|
||||
__raw_writel((0<<31)|(0<<2)|(1<<1)|(1<<0), S3C_UCLKCON);
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_QISDA_AS090B00_EVT1)||defined(CONFIG_QISDA_AS090B00_EVT1_1)||defined(CONFIG_QISDA_QD090B00_EVT1)
|
||||
if((readl(S3C2410_GPGDAT) &(1<<1))==0)
|
||||
{
|
||||
if((readl(S3C2410_GPHDAT) &(1<<11))==0)
|
||||
{
|
||||
// printk("3G Module off\n");
|
||||
s3c2410_gpio_cfgpin(S3C2443_GPH14, S3C2443_GPH14_OUTP);
|
||||
s3c2410_gpio_setpin(S3C2443_GPH14, 0);
|
||||
}
|
||||
__raw_writel((0<<31)|(0<<2)|(1<<1)|(1<<0), S3C_UCLKCON);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// printk("wall charger\n");
|
||||
#if defined(CONFIG_QISDA_E600_EVT2)||defined(CONFIG_QISDA_QD060N00_DVT1_1)
|
||||
if((readl(S3C2410_GPGDAT) &(1<<1))==0)
|
||||
{
|
||||
|
||||
|
||||
s3c2410_gpio_cfgpin(S3C2443_GPH14, S3C2443_GPH14_OUTP);
|
||||
s3c2410_gpio_setpin(S3C2443_GPH14, 0);
|
||||
|
||||
__raw_writel((0<<31)|(0<<2)|(1<<1)|(1<<0), S3C_UCLKCON);
|
||||
}
|
||||
#endif
|
||||
#if defined(CONFIG_QISDA_AS090B00_EVT1)||defined(CONFIG_QISDA_AS090B00_EVT1_1)||defined(CONFIG_QISDA_QD090B00_EVT1)
|
||||
if((readl(S3C2410_GPGDAT) &(1<<1))==0)
|
||||
{
|
||||
|
||||
if((readl(S3C2410_GPHDAT) &(1<<11))==0)
|
||||
{
|
||||
s3c2410_gpio_cfgpin(S3C2443_GPH14, S3C2443_GPH14_OUTP);
|
||||
s3c2410_gpio_setpin(S3C2443_GPH14, 0);
|
||||
}
|
||||
__raw_writel((0<<31)|(0<<2)|(1<<1)|(1<<0), S3C_UCLKCON);
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/*Leo*/
|
||||
/* } Qisda, ShiYong Lin, 2009/09/10, Detect insertion source */
|
||||
EXPORT_SYMBOL(IsWallCharger);
|
||||
|
||||
1588
cybook.config
Normal file
1588
cybook.config
Normal file
File diff suppressed because it is too large
Load Diff
@ -324,7 +324,9 @@ static int s3c_adc_ioctl(struct inode *inode, struct file *file,
|
||||
wkup_srce = (unsigned long) arg;
|
||||
printk("Wakeup parameter = %d\n", wkup_srce);
|
||||
/* Qisda, ShiYong Lin, 2009/09/28, Add the sleep event message when sleep {*/
|
||||
#ifdef QISDA
|
||||
s3c_keypad_pm_sleep_message_to_ap(1);
|
||||
#endif
|
||||
/* } Qisda, ShiYong Lin, 2009/09/28, Add the sleep event message when sleep */
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
@ -248,4 +248,10 @@ config KEYPAD_S3C_QISDA
|
||||
tony.yc.huang@qisda.com
|
||||
#Qisda Tony 090324, add keypad ]
|
||||
|
||||
config CYBOOK_CYIO
|
||||
tristate "CYBOOK buttons"
|
||||
default y
|
||||
help
|
||||
To compile this driver as a module, choose M here.
|
||||
|
||||
endif
|
||||
|
||||
@ -23,3 +23,4 @@ obj-$(CONFIG_KEYPAD_S3C) += s3c-keypad.o
|
||||
#Qisda Tony 090324, add keypad [
|
||||
obj-$(CONFIG_KEYPAD_S3C_QISDA) += s3c-keypad-qisda.o
|
||||
#Qisda Tony 090324, add keypad ]
|
||||
obj-$(CONFIG_CYIO) += cyio.o
|
||||
|
||||
940
drivers/input/keyboard/cyio.c
Normal file
940
drivers/input/keyboard/cyio.c
Normal file
@ -0,0 +1,940 @@
|
||||
// ===========================================================================
|
||||
// cyio.c
|
||||
// Copyright (C) 2008-2009 Bookeen - All rights reserved
|
||||
// ===========================================================================
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/pm.h>
|
||||
|
||||
#include <cybook.h>
|
||||
|
||||
#include "cyio.h"
|
||||
|
||||
//#define CYIO_TIMER
|
||||
#define CYIO_REPEAT
|
||||
|
||||
#define CYIO_ALTERNATE_KEY
|
||||
|
||||
#define DEBUG_MESSAGES
|
||||
#define DBG_IRQ
|
||||
|
||||
#include <asm/hardware.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm-arm/irq.h>
|
||||
#include <asm/arch/gpio.h>
|
||||
#include <asm/arch/regs-gpio.h>
|
||||
#include <asm/arch/regs-irq.h>
|
||||
#include <asm-arm/arch-s3c2410/irqs.h>
|
||||
#include <asm-arm/arch-s3c2410/gpio.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
// ===========================================================================
|
||||
spinlock_t io_lock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
static unsigned long io_status = 0;
|
||||
struct task_struct *ptsk = 0;
|
||||
|
||||
unsigned int platform_type = CYBOOK_GEN4;
|
||||
|
||||
#ifdef CYIO_TIMER
|
||||
#define IO_TIMER_DELAY_1 ((HZ * 1) / 2) /* 500 ms */
|
||||
#define IO_TIMER_DELAY_2 ((HZ * 2) / 1) /* 2 s */
|
||||
#define IO_TIMER_DELAY_3 ((HZ * 1) / 1) /* 1 s */
|
||||
static struct timer_list io_timer;
|
||||
static int timer_inited = 0;
|
||||
static int timer_run = 0;
|
||||
#endif
|
||||
|
||||
#define TRUE (1==1)
|
||||
#define FALSE (0==1)
|
||||
|
||||
#define PFX "CyIO:"
|
||||
|
||||
typedef struct _cyIrq_
|
||||
{
|
||||
int nIrq;
|
||||
u32 nGpio;
|
||||
u8 bActive;
|
||||
u8 bKeyIrq; // IRQ generated by a key?
|
||||
u8 bIsAltKey;
|
||||
u8 nCodeActive; // All interrupts generate a code when active
|
||||
u8 nCodeInactive; // Some interrupts generate a code when inactive
|
||||
u8 nCodeAlternate;
|
||||
char* sName;
|
||||
} cyIrq;
|
||||
|
||||
typedef struct _cyEvent_
|
||||
{
|
||||
u8 nCode;
|
||||
u8 nKeyEvent;
|
||||
void* pNext;
|
||||
} cyEvent;
|
||||
|
||||
static cyEvent s_nEvents[10];
|
||||
static int s_nEventMax = sizeof(s_nEvents)/sizeof(s_nEvents[0]);
|
||||
static int s_nEventCnt = 0;
|
||||
static int s_nKeyLogMax = 1;
|
||||
static int s_nKeyLogCnt = 0;
|
||||
static cyEvent* s_pEventR = 0;
|
||||
static cyEvent* s_pEventW = 0;
|
||||
#ifdef CYIO_REPEAT
|
||||
static u8 s_nPrevKey = 0;
|
||||
static u8 s_bRepMode = 0;
|
||||
#endif
|
||||
#ifdef CYIO_ALTERNATE_KEY
|
||||
static u8 s_altKeyPress = 0;
|
||||
static u32 s_altKeyGpio = 0;
|
||||
static u8 s_altKeyPresent = FALSE; /* By default we don't have a Alt Key */
|
||||
#endif
|
||||
|
||||
#define GPIO_F0 S3C2410_GPF0
|
||||
#define GPIO_F1 S3C2410_GPF1
|
||||
#define GPIO_F2 S3C2410_GPF2
|
||||
#define GPIO_F3 S3C2410_GPF3
|
||||
#define GPIO_F4 S3C2410_GPF4
|
||||
#define GPIO_F5 S3C2410_GPF5
|
||||
#define GPIO_F6 S3C2410_GPF6
|
||||
#define GPIO_F7 S3C2410_GPF7
|
||||
#define GPIO_F8 S3C2410_GPF8
|
||||
#define GPIO_F9 S3C2410_GPF9
|
||||
#define GPIO_F10 S3C2410_GPF10
|
||||
|
||||
#define GPIO_G0 S3C2410_GPG0
|
||||
#define GPIO_G1 S3C2410_GPG1
|
||||
#define GPIO_G2 S3C2410_GPG2
|
||||
#define GPIO_G3 S3C2410_GPG3
|
||||
#define GPIO_G4 S3C2410_GPG4
|
||||
#define GPIO_G5 S3C2410_GPG5
|
||||
#define GPIO_G6 S3C2410_GPG6
|
||||
#define GPIO_G7 S3C2410_GPG7
|
||||
#define GPIO_G8 S3C2410_GPG8
|
||||
#define GPIO_G9 S3C2410_GPG9
|
||||
|
||||
static cyIrq *s_nIrq ;
|
||||
static int nCnt;
|
||||
|
||||
static cyIrq s_nIrq_GEN4[] =
|
||||
{ /* Event structure for the Cybook Gen3 (2440) */
|
||||
/* IRQ GPIO A B C Depress Event Release Event Alt Event Name Number */
|
||||
{ IRQ_EINT0, GPIO_F0, 0, 1, 0, CYEVENT_KEY_OFF, 0, 0, "PowerBtn" } //0
|
||||
//, { IRQ_EINT1, GPIO_F1, 0, 0, 0, CYEVENT_SD_IN, CYEVENT_SD_OUT, 0, "SD Card" } //1
|
||||
//, { IRQ_EINT2, GPIO_F2, 0, 0, 0, CYEVENT_TP_PRESS, CYEVENT_TP_REL, 0, "Touch Panel" } //2
|
||||
//
|
||||
/* EINT3 is not Wifi EINT */
|
||||
/* EINT4 is Headphone plug status */
|
||||
/* EINT5 is Touchpanel Enable */
|
||||
/* EINT6 is charger status */
|
||||
, { IRQ_EINT7, GPIO_F7, 0, 1, 0, CYEVENT_KEY_LEFT, 0, 0, "Left" } //3
|
||||
/* INT8 is Power Keey???? */
|
||||
//, { IRQ_EINT9, GPIO_G1, 0, 0, 0, CYEVENT_USB_IN, CYEVENT_USB_OUT, 0, "USB" } //4
|
||||
/* EINT10 is SD power enable */
|
||||
, { IRQ_EINT15, GPIO_G7, 0, 1, 0, CYEVENT_KEY_RIGHT, 0, 0, "Right" } //5
|
||||
/* IRQ GPIO A B C Depress Event Release Event Alt Event Name Number */
|
||||
/* A:Reserved (must be 0) - B: Is Keypress Event? (or Allow Repeat?) (1: Yes, 0: No) - C: Is Alt Key? (1: Yes 0: No) */
|
||||
};
|
||||
|
||||
static u8* s_pbUsbPowered = NULL;
|
||||
static u8* s_pbAcPowered = NULL;
|
||||
static u8* s_pbPowerOff = NULL;
|
||||
static u8* s_pbVolMinus = NULL;
|
||||
|
||||
static irqreturn_t io_interrupt(int irq, void *dev_id);
|
||||
|
||||
#ifdef CYIO_TIMER
|
||||
static void io_timer_handler(unsigned long nData);
|
||||
#endif
|
||||
|
||||
#undef MSG
|
||||
#undef DBG
|
||||
#ifdef DEBUG_MESSAGES
|
||||
#define MSG(str) { printk(KERN_ALERT str "\n"); }
|
||||
#define DBG(str, ...) { printk(KERN_ALERT str "\n", __VA_ARGS__); }
|
||||
#else
|
||||
#define MSG(str)
|
||||
#define DBG(str, ...)
|
||||
#endif
|
||||
|
||||
//#define DEBUG_SPINLOCK
|
||||
|
||||
#ifdef DEBUG_SPINLOCK
|
||||
|
||||
#define spinLock(spin) {\
|
||||
printk(KERN_ALERT ")))))))))))) (%s:%d) Wait for %p\n", __func__, __LINE__, spin);\
|
||||
spin_lock(spin); \
|
||||
printk(KERN_ALERT ")))))))))))) (%s:%d) Gain %p\n", __func__, __LINE__, spin);\
|
||||
}
|
||||
|
||||
#define spinUnlock(spin) {\
|
||||
printk(KERN_ALERT ")))))))))))) (%s:%d) Free %p\n", __func__, __LINE__, spin);\
|
||||
spin_unlock(spin);\
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define spinLock(spin) spin_lock(spin)
|
||||
#define spinUnlock(spin) spin_unlock(spin)
|
||||
|
||||
#endif
|
||||
|
||||
/* Allow other modules/driver to push cyio event */
|
||||
void Cyio_PushEvent(char eventId, char unique)
|
||||
{
|
||||
cyEvent *pEventC;
|
||||
|
||||
spinLock(&io_lock);
|
||||
|
||||
if (unique != 0)
|
||||
{
|
||||
pEventC = s_pEventR;
|
||||
do
|
||||
{
|
||||
if (pEventC->nCode == eventId)
|
||||
goto exit;
|
||||
pEventC = pEventC->pNext;
|
||||
} while ((pEventC != s_pEventW) && (s_pEventR != s_pEventW));
|
||||
}
|
||||
DBG("New Pushed event '%c'\n", eventId);
|
||||
if (s_pEventW)
|
||||
{
|
||||
++s_nEventCnt;
|
||||
s_pEventW->nCode = eventId;
|
||||
s_pEventW->nKeyEvent = 0;
|
||||
s_pEventW = s_pEventW->pNext;
|
||||
}
|
||||
spinUnlock(&io_lock);
|
||||
|
||||
exit:
|
||||
if (ptsk)
|
||||
wake_up_process(ptsk);
|
||||
}
|
||||
EXPORT_SYMBOL(Cyio_PushEvent);
|
||||
|
||||
#ifdef CYIO_TIMER
|
||||
/* Allow other module/driver to reset the timer event */
|
||||
void Cyio_ResetTimer(void)
|
||||
{
|
||||
if (timer_inited == 0)
|
||||
return;
|
||||
if (timer_run == 0)
|
||||
return;
|
||||
#ifndef ALTERNATE_TIMER_CHANGE
|
||||
del_timer(&io_timer);
|
||||
if (io_timer.data == CYEVENT_SUSPEND_SCREEN)
|
||||
{
|
||||
io_timer.expires = IO_TIMER_DELAY_1;
|
||||
}
|
||||
else //if (io_timer.data == CYEVENT_SUSPEND_DEVICE)
|
||||
{
|
||||
io_timer.expires = IO_TIMER_DELAY_2 - IO_TIMER_DELAY_1;
|
||||
}
|
||||
|
||||
io_timer.expires += jiffies;
|
||||
add_timer(&io_timer);
|
||||
timer_run = 1;
|
||||
#else
|
||||
//io_timer.expires += IO_TIMER_DELAY_3;
|
||||
mod_timer(&io_timer, IO_TIMER_DELAY_3 + io_timer.expires);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL(Cyio_ResetTimer);
|
||||
#endif /* CYIO_TIMER */
|
||||
|
||||
// ===========================================================================
|
||||
void io_initEventList(void)
|
||||
{
|
||||
int i;
|
||||
s_pEventR = 0;
|
||||
s_nEventCnt = 0;
|
||||
s_nKeyLogCnt = 0;
|
||||
for (i=0; i<s_nEventMax; ++i)
|
||||
{
|
||||
cyEvent* pEvent = &s_nEvents[i];
|
||||
pEvent->nCode = 0;
|
||||
pEvent->nKeyEvent = 0;
|
||||
if (s_pEventR)
|
||||
s_pEventR->pNext = pEvent;
|
||||
s_pEventR = pEvent;
|
||||
}
|
||||
s_pEventR = &s_nEvents[0];
|
||||
s_nEvents[s_nEventMax-1].pNext = s_pEventR;
|
||||
s_pEventW = s_pEventR;
|
||||
#ifdef CYIO_REPEAT
|
||||
s_nPrevKey = 0;
|
||||
s_bRepMode = 0;
|
||||
#endif
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
u8 io_factoryPowerOff(void)
|
||||
{
|
||||
return (s_pbPowerOff &&
|
||||
s_pbVolMinus &&
|
||||
(*s_pbPowerOff) &&
|
||||
(*s_pbVolMinus))
|
||||
? 1
|
||||
: 0;
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
void io_initIrq(void)
|
||||
{
|
||||
|
||||
int i;
|
||||
cyIrq *pIrq, *pIrq0;
|
||||
int ret;
|
||||
pIrq0 = &s_nIrq[0];
|
||||
|
||||
// Read state as fast as possible (important when resuming)
|
||||
for (i=0, pIrq=pIrq0; i<nCnt; ++i, ++pIrq)
|
||||
{
|
||||
#if 1
|
||||
pIrq->bActive = !gpio_get_value(pIrq->nGpio);
|
||||
#else
|
||||
int j, nUp = 0;
|
||||
for (j=0; j<4; ++j)
|
||||
if (gpio_get_value(pIrq->nGpio))
|
||||
++nUp;
|
||||
pIrq->bActive = (nUp < 2);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Preparatory pass
|
||||
for (i=0, pIrq=pIrq0; i<nCnt; ++i, ++pIrq)
|
||||
{
|
||||
switch (pIrq->nCodeActive)
|
||||
{
|
||||
case CYEVENT_USB_IN:
|
||||
s_pbUsbPowered = &pIrq->bActive;
|
||||
s_pbAcPowered = &pIrq->bActive;
|
||||
break;
|
||||
case CYEVENT_AC_IN:
|
||||
break;
|
||||
case CYEVENT_KEY_OFF:
|
||||
s_pbPowerOff = &pIrq->bActive;
|
||||
break;
|
||||
case CYEVENT_KEY_VOLN:
|
||||
s_pbVolMinus = &pIrq->bActive;
|
||||
break;
|
||||
}
|
||||
#ifdef CYIO_ALTERNATE_KEY
|
||||
if (pIrq->bIsAltKey)
|
||||
{ /* If this event is configured as the Alt key, just fill the needed variables */
|
||||
DBG("Found Alt key as '%s'\n", pIrq->sName);
|
||||
s_altKeyPresent = TRUE;
|
||||
s_altKeyGpio = pIrq->nGpio;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (io_factoryPowerOff())
|
||||
{ // Special case
|
||||
spinLock(&io_lock);
|
||||
if (s_pEventW)
|
||||
{
|
||||
++s_nEventCnt;
|
||||
++s_nKeyLogCnt;
|
||||
s_pEventW->nCode = CYEVENT_FACTORY_OFF;
|
||||
s_pEventW->nKeyEvent = 1;
|
||||
s_pEventW = s_pEventW->pNext;
|
||||
}
|
||||
spinUnlock(&io_lock);
|
||||
}
|
||||
else
|
||||
{ // Register events as if they had just occurred (esp. when resuming)
|
||||
spinLock(&io_lock);
|
||||
for (i=0, pIrq=pIrq0; i<nCnt; ++i, ++pIrq)
|
||||
{
|
||||
if (!pIrq->bActive && pIrq->bKeyIrq)
|
||||
continue;
|
||||
|
||||
if ((s_nEventMax <= s_nEventCnt) ||
|
||||
(pIrq->bKeyIrq && s_nKeyLogMax <= s_nKeyLogCnt))
|
||||
{
|
||||
//break;
|
||||
// !!! BUGBUG (we might miss system events once a key event is queued)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (s_pEventW)
|
||||
{
|
||||
++s_nEventCnt;
|
||||
if (pIrq->bKeyIrq)
|
||||
++s_nKeyLogCnt;
|
||||
s_pEventW->nCode = pIrq->bActive ? pIrq->nCodeActive : pIrq->nCodeInactive;
|
||||
s_pEventW->nKeyEvent = pIrq->bKeyIrq;
|
||||
s_pEventW = s_pEventW->pNext;
|
||||
}
|
||||
}
|
||||
spinUnlock(&io_lock);
|
||||
}
|
||||
|
||||
for (i=0, pIrq=pIrq0; i<nCnt; ++i, ++pIrq)
|
||||
{
|
||||
int nIrq = pIrq->nIrq;
|
||||
set_irq_type(nIrq, IRQT_BOTHEDGE);
|
||||
|
||||
DBG(".. io_initIrq [%s][%c] bActive[%d]", pIrq->sName, pIrq->bActive || !pIrq->nCodeInactive ? (char)pIrq->nCodeActive : (char)pIrq->nCodeInactive, pIrq->bActive);
|
||||
ret = request_irq(nIrq, io_interrupt, SA_INTERRUPT|SA_SHIRQ, "cyio", pIrq);
|
||||
if (ret != 0)
|
||||
{
|
||||
printk(KERN_ERR PFX "Error registering IRQ %d [%s]!\n", nIrq, pIrq->sName);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CYIO_TIMER
|
||||
init_timer(&io_timer);
|
||||
timer_inited = 1;
|
||||
io_timer.function = io_timer_handler;
|
||||
io_timer.data = CYEVENT_SUSPEND_SCREEN;
|
||||
#endif
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
void io_deinitIrq(void)
|
||||
{
|
||||
int i;
|
||||
cyIrq *pIrq, *pIrq0;
|
||||
|
||||
#ifdef CYIO_TIMER
|
||||
del_timer(&io_timer);
|
||||
timer_run = 0;
|
||||
#endif
|
||||
|
||||
//nCnt = sizeof(s_nIrq)/sizeof(s_nIrq[0]);
|
||||
pIrq0 = &s_nIrq[0];
|
||||
for (i=0, pIrq=pIrq0; i<nCnt; ++i, ++pIrq)
|
||||
free_irq(pIrq->nIrq, pIrq);
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
//#define DBG_IRQ
|
||||
static irqreturn_t io_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
cyIrq* pIrq = (cyIrq*)dev_id;
|
||||
u8 bActive;
|
||||
u8 blCodeActive;
|
||||
unsigned long flags;
|
||||
|
||||
spinlock_t lock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
#ifdef CYIO_ALTERNATE_KEY
|
||||
static int bAltKeyUsed = FALSE;
|
||||
#endif
|
||||
|
||||
#ifdef DBG_IRQ
|
||||
static int s_nIrq_dbg = 0;
|
||||
++s_nIrq_dbg;
|
||||
#endif
|
||||
|
||||
spin_lock_irqsave(&lock, flags);
|
||||
{ // Avoid bounces
|
||||
int i, nUp = 0;
|
||||
for (i=0; i<10000; ++i)
|
||||
if (gpio_get_value(pIrq->nGpio))
|
||||
++nUp;
|
||||
bActive = (nUp < 5000);
|
||||
}
|
||||
spin_unlock_irqrestore(&lock, flags);
|
||||
|
||||
if (pIrq->bActive == bActive)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
#ifdef DBG_IRQ
|
||||
DBG(".. io_irq #%d [%s][%c] alt[%d:%d] bActive[%d]", s_nIrq_dbg, pIrq->sName, bActive || !pIrq->nCodeInactive ? (char)pIrq->nCodeActive : (char)pIrq->nCodeInactive, (s_altKeyPress && pIrq->bKeyIrq) ? pIrq->nCodeAlternate : (bActive ? pIrq->nCodeActive : pIrq->nCodeInactive), s_altKeyPress, bActive);
|
||||
#endif
|
||||
|
||||
blCodeActive = (s_altKeyPress && pIrq->bKeyIrq) ? pIrq->nCodeAlternate : (bActive ? pIrq->nCodeActive : pIrq->nCodeInactive);
|
||||
#ifdef CYIO_ALTERNATE_KEY
|
||||
if (s_altKeyPresent)
|
||||
{
|
||||
s_altKeyPress = !gpio_get_value(s_altKeyGpio);
|
||||
DBG("alt status: %d", s_altKeyPress);
|
||||
}
|
||||
#endif
|
||||
|
||||
spinLock(&io_lock);
|
||||
pIrq->bActive = bActive;
|
||||
if (pIrq->bKeyIrq)
|
||||
{
|
||||
|
||||
#ifdef CYIO_REPEAT
|
||||
DBG("bfr: s_nPrevKey = %d", s_nPrevKey);
|
||||
if (s_nPrevKey)
|
||||
{
|
||||
DBG("s_nPrevKey is != 0 [%d]", s_nPrevKey);
|
||||
|
||||
if (!pIrq->bActive /*|| s_nPrevKey != blCodeActive*/)
|
||||
s_nPrevKey = 0;
|
||||
|
||||
DBG("s_nPrevKey == %d (s_bRepMode:%d, pIrq->bActive:%d)", s_nPrevKey, s_bRepMode, pIrq->bActive);
|
||||
|
||||
if (s_bRepMode && !s_nPrevKey)
|
||||
{
|
||||
MSG("Exit repeat mode...");
|
||||
s_bRepMode = 0;
|
||||
if (s_pEventW)
|
||||
{ // NB: This is considered as a system event
|
||||
++s_nEventCnt;
|
||||
s_pEventW->nCode = CYEVENT_KEY_REPEAT_END;
|
||||
s_pEventW->nKeyEvent = 0;
|
||||
s_pEventW = s_pEventW->pNext;
|
||||
}
|
||||
if (ptsk)
|
||||
wake_up_process(ptsk);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef CYIO_ALTERNATE_KEY
|
||||
if ((!pIrq->bActive) && (pIrq->nGpio != s_altKeyGpio))
|
||||
#else
|
||||
if (!pIrq->bActive)
|
||||
#endif
|
||||
{
|
||||
spinUnlock(&io_lock);
|
||||
MSG("Exiting IRQ Handler");
|
||||
#ifdef CYIO_KERNEL_2_4
|
||||
return;
|
||||
#else
|
||||
return IRQ_HANDLED;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
spinUnlock(&io_lock);
|
||||
|
||||
//#ifdef DBG_IRQ
|
||||
// DBG(".. io_irq #%d [%s][%c] bActive[%d]", s_nIrq_dbg, pIrq->sName, bActive || !pIrq->nCodeInactive ? (char)pIrq->nCodeActive : (char)pIrq->nCodeInactive, bActive);
|
||||
//#endif
|
||||
|
||||
if (io_factoryPowerOff())
|
||||
{ // Special case
|
||||
spinLock(&io_lock);
|
||||
MSG("Request Factory Setting...\n");
|
||||
if (s_pEventW)
|
||||
{
|
||||
++s_nEventCnt;
|
||||
++s_nKeyLogCnt;
|
||||
s_pEventW->nCode = CYEVENT_FACTORY_OFF;
|
||||
s_pEventW->nKeyEvent = 1;
|
||||
s_pEventW = s_pEventW->pNext;
|
||||
}
|
||||
spinUnlock(&io_lock);
|
||||
}
|
||||
else
|
||||
{
|
||||
spinLock(&io_lock);
|
||||
if ((s_nEventMax <= s_nEventCnt) ||
|
||||
(pIrq->bKeyIrq && s_nKeyLogMax <= s_nKeyLogCnt))
|
||||
{
|
||||
spinUnlock(&io_lock);
|
||||
DBG("s_nEventMax:%d, s_nEventCnt:%d, s_nKeyLogMax:%d, s_nKeyLogCnt:%d",s_nEventMax,s_nEventCnt,s_nKeyLogMax,s_nKeyLogCnt);
|
||||
MSG("!!! Event list full !!!");
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
#ifdef CYIO_ALTERNATE_KEY
|
||||
|
||||
if (s_altKeyPresent && bAltKeyUsed && !s_altKeyPress && (pIrq->nGpio == s_altKeyGpio))
|
||||
{ /* If the released key is the Alt Key and it was used as the Alt Key, do not send an event */
|
||||
MSG("Alt Key released... Do Nothing");
|
||||
bAltKeyUsed = FALSE;
|
||||
s_nPrevKey = 0;
|
||||
spinUnlock(&io_lock);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
if (s_altKeyPresent && (pIrq->nGpio == s_altKeyGpio))
|
||||
{ /* If the altKey is pressed, we have to do a little trick: Inverse it's active state */
|
||||
MSG("Alt key event...");
|
||||
/* To be sure */
|
||||
s_nPrevKey = 0;
|
||||
s_bRepMode = 0;
|
||||
|
||||
bActive = !bActive;
|
||||
}
|
||||
else if (s_altKeyPresent && s_altKeyPress && pIrq->bKeyIrq)
|
||||
{/* The event is a keypress and the AltKey is pressed, set our internal value to prevent Alt to send an event */
|
||||
MSG("Button press with Alt...");
|
||||
if (pIrq->nCodeAlternate != 0)
|
||||
bAltKeyUsed = TRUE;
|
||||
}
|
||||
MSG("Hum...");
|
||||
#endif
|
||||
|
||||
if (s_pEventW)
|
||||
{
|
||||
MSG("Will push another event...");
|
||||
++s_nEventCnt;
|
||||
if (pIrq->bKeyIrq)
|
||||
++s_nKeyLogCnt;
|
||||
|
||||
#ifdef CYIO_ALTERNATE_KEY
|
||||
s_pEventW->nCode = (s_altKeyPress && pIrq->bKeyIrq) ? pIrq->nCodeAlternate : (bActive ? pIrq->nCodeActive : pIrq->nCodeInactive);
|
||||
#else
|
||||
s_pEventW->nCode = bActive ? pIrq->nCodeActive : pIrq->nCodeInactive;
|
||||
#endif
|
||||
|
||||
s_pEventW->nKeyEvent = pIrq->bKeyIrq;
|
||||
|
||||
s_pEventW = s_pEventW->pNext;
|
||||
}
|
||||
spinUnlock(&io_lock);
|
||||
}
|
||||
|
||||
if (ptsk)
|
||||
wake_up_process(ptsk);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
#ifdef CYIO_TIMER
|
||||
static void io_timer_handler(unsigned long nData)
|
||||
{
|
||||
/* YEP inside */
|
||||
#if 0
|
||||
//#ifdef G_SENSOR
|
||||
if (hold_wakeup==1) {
|
||||
del_timer(&io_timer);
|
||||
goto end_timer;
|
||||
}
|
||||
#endif
|
||||
/* end YEP inside */
|
||||
DBG("Timer [%ld] tick...\n", nData);
|
||||
|
||||
spin_lock_irq(&io_lock);
|
||||
|
||||
del_timer(&io_timer);
|
||||
timer_run = 0;
|
||||
if (s_nEventCnt < s_nEventMax)
|
||||
{
|
||||
if (s_pEventW)
|
||||
{
|
||||
++s_nEventCnt;
|
||||
s_pEventW->nCode = (u8)nData;
|
||||
s_pEventW->nKeyEvent = 0;
|
||||
s_pEventW = s_pEventW->pNext;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irq(&io_lock);
|
||||
|
||||
if (ptsk)
|
||||
wake_up_process(ptsk);
|
||||
//end_timer:
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ===========================================================================
|
||||
static int io_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
//MSG(">> io_open");
|
||||
|
||||
//spin_lock_irq(&io_lock);
|
||||
spinLock(&io_lock);
|
||||
|
||||
if (io_status)
|
||||
{
|
||||
//spin_unlock_irq(&io_lock);
|
||||
spinUnlock(&io_lock);
|
||||
//MSG(".. io_open !!! Busy");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
io_status = 1;
|
||||
|
||||
//spin_unlock_irq(&io_lock);
|
||||
spinUnlock(&io_lock);
|
||||
|
||||
io_initIrq();
|
||||
|
||||
return 0;
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
static int io_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
MSG(">> io_release");
|
||||
|
||||
io_deinitIrq();
|
||||
|
||||
spin_lock_irq(&io_lock);
|
||||
|
||||
io_status = 0;
|
||||
|
||||
// The driver is likely to be closed & reopened within suspend sequences
|
||||
// Only initialize the list when registering the driver and when closing it
|
||||
// This allows for a quicker opening of the driver
|
||||
io_initEventList();
|
||||
|
||||
spin_unlock_irq(&io_lock);
|
||||
|
||||
MSG("<< io_release");
|
||||
return 0;
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
ssize_t io_read(struct file *file, char *buf, size_t count, loff_t *ppos)
|
||||
{
|
||||
int nBytes = sizeof(unsigned long);
|
||||
unsigned long nData;
|
||||
ssize_t nRes = 0;
|
||||
|
||||
if (count < sizeof(unsigned long))
|
||||
return -EINVAL;
|
||||
|
||||
while (1)
|
||||
{
|
||||
//spin_lock_irq(&io_lock);
|
||||
spinLock(&io_lock);
|
||||
nData = 0;
|
||||
if (s_nEventCnt)
|
||||
{
|
||||
nData = s_pEventR->nCode;
|
||||
s_pEventR->nCode = 0;
|
||||
--s_nEventCnt;
|
||||
if (s_pEventR->nKeyEvent)
|
||||
{
|
||||
--s_nKeyLogCnt;
|
||||
#ifdef CYIO_REPEAT
|
||||
if (nData != CYEVENT_KEY_OFF)
|
||||
{
|
||||
DBG("(line %d)Set s_nPrevKey", __LINE__);
|
||||
s_nPrevKey = nData;
|
||||
s_bRepMode = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
s_pEventR = s_pEventR->pNext;
|
||||
}
|
||||
#ifdef CYIO_REPEAT
|
||||
if (!nData && s_nPrevKey)
|
||||
{ // Check new status
|
||||
int i;
|
||||
cyIrq *pIrq, *pIrq0;
|
||||
|
||||
pIrq0 = &s_nIrq[0];
|
||||
MSG("Will test key...");
|
||||
for (i=0, pIrq=pIrq0; i<nCnt; ++i, ++pIrq)
|
||||
{
|
||||
#ifdef CYIO_ALTERNATE_KEY
|
||||
if ((pIrq->nCodeActive != s_nPrevKey) && (pIrq->nCodeAlternate != s_nPrevKey))
|
||||
#else
|
||||
if (pIrq->nCodeActive != s_nPrevKey)
|
||||
#endif
|
||||
{
|
||||
MSG("!CodeActive and Alt+!AltCode");
|
||||
continue;
|
||||
}
|
||||
|
||||
MSG("May clear prevkey");
|
||||
if (!pIrq->bActive || gpio_get_value(pIrq->nGpio))
|
||||
{
|
||||
DBG("(line %d)Set s_nPrevKey", __LINE__);
|
||||
s_nPrevKey = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (s_nPrevKey)
|
||||
{
|
||||
MSG("Will Set Repeat flag...");
|
||||
nData = s_nPrevKey | CYEVENT_KEY_REPEAT_FLAG;
|
||||
s_bRepMode = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
spinUnlock(&io_lock);
|
||||
|
||||
if (nData != 0)
|
||||
{
|
||||
#ifdef CYIO_TIMER
|
||||
del_timer(&io_timer);
|
||||
timer_run = 0;
|
||||
io_timer.data = (nData == CYEVENT_SUSPEND_SCREEN) ? CYEVENT_SUSPEND_DEVICE : CYEVENT_SUSPEND_SCREEN;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef CYIO_TIMER
|
||||
if (s_pbUsbPowered && s_pbAcPowered && !(*s_pbUsbPowered) && !(*s_pbAcPowered))
|
||||
{
|
||||
del_timer(&io_timer);
|
||||
timer_run = 0;
|
||||
if (io_timer.data == CYEVENT_SUSPEND_SCREEN)
|
||||
{
|
||||
io_timer.expires = IO_TIMER_DELAY_1;
|
||||
io_timer.expires += jiffies;
|
||||
add_timer(&io_timer);
|
||||
}
|
||||
else //if (io_timer.data == CYEVENT_SUSPEND_DEVICE)
|
||||
{
|
||||
io_timer.expires = IO_TIMER_DELAY_2 - IO_TIMER_DELAY_1;
|
||||
io_timer.expires += jiffies;
|
||||
add_timer(&io_timer);
|
||||
}
|
||||
timer_run = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
ptsk = current;
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule();
|
||||
set_current_state(TASK_RUNNING);
|
||||
ptsk = 0;
|
||||
|
||||
if (signal_pending(current))
|
||||
{
|
||||
nRes = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (nData)
|
||||
{
|
||||
nRes = copy_to_user(buf,&nData,nBytes);
|
||||
if (!nRes)
|
||||
nRes = nBytes;
|
||||
}
|
||||
|
||||
return nRes;
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
static int io_ioctl(struct inode *inode, struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
// ===========================================================================
|
||||
static struct file_operations s_io_fops =
|
||||
{
|
||||
owner: THIS_MODULE,
|
||||
read: io_read,
|
||||
ioctl: io_ioctl,
|
||||
open: io_open,
|
||||
release: io_release,
|
||||
};
|
||||
|
||||
static struct miscdevice s_io_dev =
|
||||
{
|
||||
.minor = 250,
|
||||
.name = "cyio",
|
||||
.fops = &s_io_fops,
|
||||
};
|
||||
// ===========================================================================
|
||||
// ---------------------------------------------------------------------------
|
||||
static int io_probe(struct platform_device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
static int io_remove(struct platform_device *dev)
|
||||
{
|
||||
misc_deregister(&s_io_dev);
|
||||
return 0;
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
static int io_resume(struct platform_device *dev)
|
||||
{
|
||||
//cyIrq *pIrq;
|
||||
//u8 bSdCd;
|
||||
MSG(">>Resume() .......\n");
|
||||
#if 0
|
||||
if ((platform_type == CYBOOK_GEN3) || (platform_type == CYBOOK_GEN3GOLD))
|
||||
{
|
||||
pIrq = &s_nIrq[13];
|
||||
}
|
||||
else
|
||||
{
|
||||
pIrq = &s_nIrq[11];
|
||||
}
|
||||
|
||||
bSdCd = !read_gpio_bit(pIrq->nGpio);
|
||||
|
||||
//MSG(">>Resume() .......bSdCd 0x%x\n",bSdCd);
|
||||
if (pIrq->bActive == bSdCd)
|
||||
return 0;
|
||||
|
||||
spinLock(&io_lock);
|
||||
pIrq->bActive = bSdCd;
|
||||
if (s_pEventW)
|
||||
{
|
||||
++s_nEventCnt;
|
||||
s_pEventW->nCode = pIrq->bActive ? pIrq->nCodeActive : pIrq->nCodeInactive;
|
||||
s_pEventW->nKeyEvent = pIrq->bKeyIrq;
|
||||
s_pEventW = s_pEventW->pNext;
|
||||
}
|
||||
spinUnlock(&io_lock);
|
||||
if (ptsk)
|
||||
wake_up_process(ptsk);
|
||||
#endif
|
||||
|
||||
MSG("<<Resume() .......\n");
|
||||
return 0;
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
static struct platform_driver cyio_driver =
|
||||
{
|
||||
.driver =
|
||||
{
|
||||
.name = "cyio",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = io_probe,
|
||||
.remove = io_remove,
|
||||
.suspend = NULL,
|
||||
.resume = io_resume,
|
||||
};
|
||||
// ---------------------------------------------------------------------------
|
||||
// ===========================================================================
|
||||
static int __init cyIo_init(void)
|
||||
{
|
||||
#if 0
|
||||
if(platform_type == CYBOOK_OPUS)
|
||||
{
|
||||
s_nIrq = s_nIrq_OPUS;
|
||||
nCnt = sizeof(s_nIrq_OPUS)/sizeof(s_nIrq_OPUS[0]);
|
||||
}
|
||||
else if (/* GEN3 && GEN3GOLD */
|
||||
{
|
||||
s_nIrq = s_nIrq_GEN3;
|
||||
nCnt = sizeof(s_nIrq_GEN3)/sizeof(s_nIrq_GEN3[0]);
|
||||
}
|
||||
#endif
|
||||
s_nIrq = s_nIrq_GEN4;
|
||||
nCnt = sizeof(s_nIrq_GEN4)/sizeof(s_nIrq_GEN4[0]);
|
||||
|
||||
DBG("s_nEventMax:%d, s_nEventCnt:%d, s_nKeyLogMax:%d, s_nKeyLogCnt:%d",s_nEventMax,s_nEventCnt,s_nKeyLogMax,s_nKeyLogCnt);
|
||||
|
||||
|
||||
/* end YEP inside */
|
||||
|
||||
io_initEventList();
|
||||
|
||||
if (misc_register(&s_io_dev))
|
||||
return -EBUSY;
|
||||
|
||||
platform_driver_register(&cyio_driver);
|
||||
|
||||
return 0;
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
static void __exit cyIo_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&cyio_driver);
|
||||
|
||||
misc_deregister(&s_io_dev);
|
||||
|
||||
//MSG("<< cyIo_exit");
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
module_init(cyIo_init);
|
||||
module_exit(cyIo_exit);
|
||||
// ---------------------------------------------------------------------------
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Bookeen <developers@bookeen.com>");
|
||||
MODULE_DESCRIPTION("Cybook Event Manager");
|
||||
MODULE_VERSION("3.0");
|
||||
// ===========================================================================
|
||||
65
drivers/input/keyboard/cyio.h
Normal file
65
drivers/input/keyboard/cyio.h
Normal file
@ -0,0 +1,65 @@
|
||||
// ===========================================================================
|
||||
// cyio.h
|
||||
// Copyright (C) 2008-2009 Bookeen - All rights reserved
|
||||
// ===========================================================================
|
||||
// Key events
|
||||
#define CYEVENT_KEY_ENTER 'e'
|
||||
#define CYEVENT_KEY_RIGHT 'r'
|
||||
#define CYEVENT_KEY_DOWN 'd'
|
||||
#define CYEVENT_KEY_LEFT 'l'
|
||||
#define CYEVENT_KEY_UP 'u'
|
||||
#define CYEVENT_KEY_F1 '1'
|
||||
#define CYEVENT_KEY_F2 '2'
|
||||
#define CYEVENT_KEY_F3 '3'
|
||||
#define CYEVENT_KEY_F4 '4'
|
||||
#define CYEVENT_KEY_OFF 'o'
|
||||
#define CYEVENT_KEY_VOLP '+'
|
||||
#define CYEVENT_KEY_VOLN '-'
|
||||
#define CYEVENT_KEY_REPEAT_FLAG 0x80
|
||||
#define CYEVENT_KEY_REPEAT_END '0'
|
||||
// Physical events
|
||||
#define CYEVENT_USB_IN 'p'
|
||||
#define CYEVENT_USB_OUT 'q'
|
||||
#define CYEVENT_AC_IN 'a'
|
||||
#define CYEVENT_AC_OUT 'b'
|
||||
#define CYEVENT_ACN_IN 'j'
|
||||
#define CYEVENT_ACN_OUT 'k'
|
||||
#define CYEVENT_SD_IN 's'
|
||||
#define CYEVENT_SD_OUT 't'
|
||||
#define CYEVENT_SDN_IN 'u'
|
||||
#define CYEVENT_SDN_OUT 'v'
|
||||
|
||||
// G-Sensor events
|
||||
#define CYEVENT_ORIENTATIONCHANGED 'O'
|
||||
#define CYEVENT_G_ROT000 'A'
|
||||
#define CYEVENT_G_ROT090 'B'
|
||||
#define CYEVENT_G_ROT180 'C'
|
||||
#define CYEVENT_G_ROT270 'D'
|
||||
#define CYEVENT_TOGGLE_GSENSOR 'G'
|
||||
|
||||
// Logical events
|
||||
// CYEVENT_KEY_OFF + CYEVENT_KEY_VOLN
|
||||
#define CYEVENT_FACTORY_OFF 'x'
|
||||
#define CYEVENT_SUSPEND_SCREEN 'y'
|
||||
#define CYEVENT_SUSPEND_DEVICE 'z'
|
||||
// ===========================================================================
|
||||
/* YEP inside */
|
||||
#define CYIO_KERNEL_2_6 1
|
||||
|
||||
#define G_SENSOR_ON '1'
|
||||
#define G_SENSOR_OFF '0'
|
||||
#define G_SENSOR_CAL 'C'
|
||||
|
||||
/* end YEP inside */
|
||||
enum
|
||||
{
|
||||
CYGSENSOR_STATUS_ENABLED = 0,
|
||||
CYGSENSOR_STATUS_DISABLED = 1,
|
||||
CYGSENSOR_STATUS_NOTCALIB = 2, /* Not calibrated, or invalid calibration data */
|
||||
CYGSENSOR_STATUS_CALIBRATED = 3, /* This status should never been read, but it could help to debug */
|
||||
CYGSENSOR_STATUS_UNKNOWN = 4, /* This status should not been read too, but it could help to debug */
|
||||
};
|
||||
|
||||
/* Exported function of CyIO */
|
||||
void Cyio_ResetTimer(void);
|
||||
void Cyio_PushEvent(char eventId, char unique);
|
||||
@ -48,7 +48,9 @@ static unsigned int tick_count;
|
||||
|
||||
/* Qisda, ShiYong Lin, 2009/07/22, Implement function for RTC tick service {*/
|
||||
static unsigned long uiResolution = 0;
|
||||
#ifdef QISDA
|
||||
extern void rtc_tick_keypad_message_to_ap (void);
|
||||
#endif
|
||||
/* Qisda, ShiYong Lin, 2009/07/22, Implement function for RTC tick service }*/
|
||||
|
||||
static irqreturn_t s3c_rtc_alarmirq(int irq, void *id)
|
||||
@ -67,8 +69,9 @@ static irqreturn_t s3c_rtc_tickirq(int irq, void *id)
|
||||
{
|
||||
struct rtc_device *rdev = id;
|
||||
|
||||
#ifdef QISDA
|
||||
rtc_tick_keypad_message_to_ap();
|
||||
|
||||
#endif
|
||||
rtc_update_irq(&rdev->class_dev, tick_count++, RTC_PF | RTC_IRQF);
|
||||
|
||||
#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
|
||||
|
||||
@ -128,7 +128,9 @@ static void reconfig_usbd(void);
|
||||
/*send key code F6 1 when USB plugin*/
|
||||
/*send key code F6 0 when USB unplugin*/
|
||||
/*send key code F6 0 when USB safety remove USB{*/
|
||||
void USB_SaftRemove_keypad_message_to_ap(uint uiSleep);
|
||||
#ifdef QISDA
|
||||
void USB_SaftRemove_keypad_message_to_ap(uint uiSleep)
|
||||
#endif
|
||||
/*}Qisda,Leo SJ Yang,2009/10/26*/
|
||||
static __inline__ u32 usb_read(u32 port, u8 ind)
|
||||
{
|
||||
@ -1125,8 +1127,10 @@ static irqreturn_t s3c_udc_irq(int irq, void *_dev)
|
||||
/*send key code F6 0 when USB safety remove USB{*/
|
||||
/*Qisda,Leo SJ Yang,2009/11/13*/
|
||||
/*prevent from sending saftremove event to MMI when the event to be occured is not the action of saftremove{*/
|
||||
#ifdef QISDA
|
||||
if((intr_status&S3C_UDC_INT_VBUSON)==0)
|
||||
USB_SaftRemove_keypad_message_to_ap(0);
|
||||
#endif
|
||||
/*}Qisda,Leo SJ Yang,2009/11/13*/
|
||||
#endif
|
||||
/*}Qisda,Leo SJ Yang,2009/08/26 set g_EMUSBTestIsOK=0 when uplug USB*/
|
||||
@ -1793,8 +1797,9 @@ static void s3c_ep0_setup(struct s3c_udc *dev, u32 csr)
|
||||
/*Qisda,Leo SJ Yang,2009/07/28 add /proc/driver/udc for EM mode{*/
|
||||
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
|
||||
g_EMUSBTestIsOK=1;
|
||||
#ifdef QISDA
|
||||
USB_SaftRemove_keypad_message_to_ap(1);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/*}Qisda,Leo SJ Yang,2009/07/28 add /proc/driver/udc for EM mode*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
28803
drivers/video/logo/logo_linux_customer_6_inch_clut224.ppm.old
Normal file
28803
drivers/video/logo/logo_linux_customer_6_inch_clut224.ppm.old
Normal file
File diff suppressed because it is too large
Load Diff
19
include/cybook.h
Normal file
19
include/cybook.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Disclaimer (blabla)
|
||||
*
|
||||
* Author: Manoël Trapier <manoelt@bookeen.com>
|
||||
* Copyright (c) 2009 Bookeen
|
||||
*
|
||||
*/
|
||||
#ifndef CYBOOK_H
|
||||
#define CYBOOK_H
|
||||
|
||||
enum {
|
||||
CYBOOK_GEN3 = 0,
|
||||
CYBOOK_OPUS,
|
||||
CYBOOK_GEN3GOLD,
|
||||
CYBOOK_GEN4,
|
||||
};
|
||||
|
||||
extern unsigned int platform_type;
|
||||
#endif /* CYBOOK_H */
|
||||
@ -254,7 +254,9 @@ static int enter_pm_cpu_mode(suspend_state_t state)
|
||||
Unlock:
|
||||
mutex_unlock(&pm_mutex);
|
||||
/* Qisda, ShiYong Lin, 2009/09/28, Add the sleep event message when sleep {*/
|
||||
s3c_keypad_pm_sleep_message_to_ap(0);
|
||||
#ifdef QISDA
|
||||
s3c_keypad_pm_sleep_message_to_ap(0);
|
||||
#endif
|
||||
// printk(KERN_ERR "Sleep end enter_pm_cpu_mode, %d\n", state);
|
||||
/* } Qisda, ShiYong Lin, 2009/09/28, Add the sleep event message when sleep */
|
||||
return error;
|
||||
@ -299,7 +301,9 @@ static int enter_state(suspend_state_t state)
|
||||
Unlock:
|
||||
mutex_unlock(&pm_mutex);
|
||||
/* Qisda, ShiYong Lin, 2009/09/28, Add the sleep event message when sleep {*/
|
||||
s3c_keypad_pm_sleep_message_to_ap(0);
|
||||
#ifdef QISDA
|
||||
s3c_keypad_pm_sleep_message_to_ap(0);
|
||||
#endif
|
||||
/* } Qisda, ShiYong Lin, 2009/09/28, Add the sleep event message when sleep */
|
||||
return error;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user