📄 嵌入式系统字符驱动程序(应用)问题(初学),请帮忙回答 linux-unix社区 - 内核及驱动程序研究区 - csdn社区 community_csdn_net.htm
字号:
protect against overrun */ <BR> unsigned
int head, tail; /* head and tail
for queued events */ <BR>
wait_queue_head_t wq; <BR> spinlock_t lock;
<BR> #ifdef USE_ASYNC <BR> struct fasync_struct
*aq; <BR> #endif <BR> #ifdef CONFIG_PM
<BR> struct pm_dev *pm_dev; <BR> #endif
<BR> } TS_DEV; <BR> <BR> static
TS_DEV tsdev; <BR> <BR> #define
BUF_HEAD (tsdev.buf[tsdev.head]) <BR> #define BUF_TAIL
(tsdev.buf[tsdev.tail]) <BR> #define INCBUF(x,mod)
((++(x)) & ((mod) - 1)) <BR>
<BR> static int tsMajor = 0; <BR>
<BR> static void (*tsEvent)(void); <BR>
<BR> #define HOOK_FOR_DRAG <BR> #ifdef
HOOK_FOR_DRAG <BR> #define TS_TIMER_DELAY
(HZ/100) /* 10 ms */ <BR> static
struct timer_list ts_timer; <BR> #endif
<BR> <BR> static int adc_state =
0; <BR> static int x, y; /* touch
screen coorinates */ <BR> <BR>
static void tsEvent_raw(void) <BR> {
<BR> if (tsdev.penStatus == PEN_DOWN) {
<BR> BUF_HEAD.x = x; <BR> BUF_HEAD.y =
y; <BR> BUF_HEAD.pressure = PEN_DOWN;
<BR> <BR> #ifdef HOOK_FOR_DRAG
<BR> ts_timer.expires = jiffies +
TS_TIMER_DELAY; <BR> add_timer(&ts_timer); <BR>
#endif <BR> } else { <BR> #ifdef
HOOK_FOR_DRAG <BR> del_timer(&ts_timer);
<BR> #endif <BR> <BR> BUF_HEAD.x =
0; <BR> BUF_HEAD.y = 0; <BR>
BUF_HEAD.pressure = PEN_UP; <BR> } <BR>
<BR> tsdev.head = INCBUF(tsdev.head,
MAX_TS_BUF); <BR> wake_up_interruptible(&(tsdev.wq));
<BR> <BR> #ifdef USE_ASYNC <BR> if
(tsdev.aq) <BR> kill_fasync(&(tsdev.aq), SIGIO,
POLL_IN); <BR> #endif <BR> <BR> #ifdef
CONFIG_PM <BR> pm_access(tsdev.pm_dev); <BR>
#endif <BR> } <BR> <BR> static int
tsRead(TS_RET * ts_ret) <BR> {
<BR> spin_lock_irq(&(tsdev.lock)); <BR> ts_ret->x
= BUF_TAIL.x; <BR> ts_ret->y =
BUF_TAIL.y; <BR> ts_ret->pressure =
BUF_TAIL.pressure; <BR> tsdev.tail =
INCBUF(tsdev.tail, MAX_TS_BUF); <BR>
spin_unlock_irq(&(tsdev.lock)); <BR> <BR> return
sizeof(TS_RET); <BR> } <BR> <BR>
<BR> static ssize_t s3c2410_ts_read(struct
file *filp, char *buffer, size_t count,
loff_t *ppos) <BR> { <BR> TS_RET
ts_ret; <BR> <BR> retry: <BR> if
(tsdev.head != tsdev.tail) { <BR> int
count; <BR> count = tsRead(&ts_ret);
<BR> if (count) copy_to_user(buffer, (char
*)&ts_ret, count); <BR> return count;
<BR> } else { <BR> if
(filp->f_flags & O_NONBLOCK) <BR> return
-EAGAIN; <BR> interruptible_sleep_on(&(tsdev.wq));
<BR> if (signal_pending(current)) <BR> return
-ERESTARTSYS; <BR> goto retry; <BR> }
<BR> <BR> return sizeof(TS_RET);
<BR> } <BR> <BR> #ifdef USE_ASYNC
<BR> static int s3c2410_ts_fasync(int fd,
struct file *filp, int mode)
<BR> { <BR> return fasync_helper(fd, filp,
mode, &(tsdev.aq)); <BR> } <BR>
#endif <BR> <BR> static unsigned int
<A name=baidusnap0></A><B
style="COLOR: black; BACKGROUND-COLOR: #ffff66">s3c2410_ts_poll</B>(struct
file *filp, struct poll_table_struct *wait)
<BR> { <BR> poll_wait(filp, &(tsdev.wq),
wait); <BR> return (tsdev.head ==
tsdev.tail) ? 0 : (POLLIN |
POLLRDNORM); <BR> } <BR> <BR>
static inline void start_ts_adc(void) <BR> {
<BR> adc_state = 0; <BR> mode_x_axis();
<BR> start_adc_x(); <BR> } <BR>
<BR> static inline void s3c2410_get_XY(void)
<BR> { <BR> if (adc_state == 0) {
<BR> adc_state = 1; <BR>
disable_ts_adc(); <BR> y = (ADCDAT0 &
0x3ff); <BR> mode_y_axis(); <BR>
start_adc_y(); <BR> } else if (adc_state
== 1) { <BR> adc_state =
0; <BR> disable_ts_adc(); <BR> x =
(ADCDAT1 & 0x3ff); <BR> tsdev.penStatus
= PEN_DOWN; <BR> DPRINTK("PEN DOWN: x:
%08d, y: %08d\n", x, y); <BR>
wait_up_int(); <BR> tsEvent(); <BR> }
<BR> } <BR> <BR> static void
s3c2410_isr_adc(int irq, void *dev_id, struct
pt_regs *reg) <BR> { <BR> #if 0
<BR> DPRINTK("Occured Touch Screen Interrupt\n");
<BR> DPRINTK("SUBSRCPND = 0x%08lx\n",
SUBSRCPND); <BR> #endif <BR>
spin_lock_irq(&(tsdev.lock)); <BR> if (tsdev.penStatus
== PEN_UP) <BR> s3c2410_get_XY();
<BR> #ifdef HOOK_FOR_DRAG <BR> else
<BR> s3c2410_get_XY(); <BR> #endif
<BR> spin_unlock_irq(&(tsdev.lock)); <BR> }
<BR> <BR> static void s3c2410_isr_tc(int
irq, void *dev_id, struct pt_regs *reg)
<BR> { <BR> #if 0 <BR>
DPRINTK("Occured Touch Screen Interrupt\n");
<BR> DPRINTK("SUBSRCPND = 0x%08lx\n", SUBSRCPND);
<BR> #endif <BR> spin_lock_irq(&(tsdev.lock));
<BR> if (tsdev.penStatus == PEN_UP) {
<BR> start_ts_adc(); <BR> } else
{ <BR> tsdev.penStatus = PEN_UP;
<BR> DPRINTK("PEN UP: x: %08d,
y: %08d\n", x, y); <BR>
wait_down_int(); <BR> tsEvent(); <BR> }
<BR> spin_unlock_irq(&(tsdev.lock)); <BR> }
<BR> <BR> #ifdef HOOK_FOR_DRAG <BR>
static void ts_timer_handler(unsigned long data)
<BR> { <BR> spin_lock_irq(&(tsdev.lock));
<BR> if (tsdev.penStatus == PEN_DOWN) {
<BR> start_ts_adc(); <BR> } <BR>
spin_unlock_irq(&(tsdev.lock)); <BR> } <BR> #endif
<BR> <BR> static int
s3c2410_ts_open(struct inode *inode, struct file
*filp) <BR> { <BR> tsdev.head =
tsdev.tail = 0; <BR> tsdev.penStatus =
PEN_UP; <BR> #ifdef HOOK_FOR_DRAG <BR>
init_timer(&ts_timer); <BR> ts_timer.function =
ts_timer_handler; <BR> #endif <BR> tsEvent =
tsEvent_raw; <BR> init_waitqueue_head(&(tsdev.wq));
<BR> <BR> MOD_INC_USE_COUNT; <BR> return
0; <BR> } <BR> <BR> static
int s3c2410_ts_release(struct inode *inode, struct
file *filp) <BR> { <BR> #ifdef
HOOK_FOR_DRAG <BR> del_timer(&ts_timer); <BR>
#endif <BR> MOD_DEC_USE_COUNT; <BR> return 0;
<BR> } <BR> <BR> static struct
file_operations s3c2410_fops = { <BR>
owner: THIS_MODULE, <BR> open: s3c2410_ts_open, <BR>
read: s3c2410_ts_read, <BR> release: s3c2410_ts_release,
<BR> #ifdef USE_ASYNC <BR> fasync: s3c2410_ts_fasync,
<BR> #endif <BR> poll: <B
style="COLOR: black; BACKGROUND-COLOR: #ffff66">s3c2410_ts_poll</B>,
<BR> }; <BR> <BR> void
tsEvent_dummy(void) {} <BR> #ifdef CONFIG_PM
<BR> static int s3c2410_ts_pm_callback(struct pm_dev
*pm_dev, pm_request_t req, <BR>
void *data) <BR> { <BR>
switch (req) { <BR> case
PM_SUSPEND: <BR> tsEvent = tsEvent_dummy;
<BR> break; <BR> case PM_RESUME:
<BR> tsEvent = tsEvent_raw; <BR>
wait_down_int(); <BR> break; <BR>
} <BR> return 0;
<BR> } <BR> #endif <BR> <BR> #ifdef
CONFIG_DEVFS_FS <BR> static devfs_handle_t
devfs_ts_dir, devfs_tsraw; <BR> #endif <BR>
static int __init s3c2410_ts_init(void) <BR> {
<BR> int ret; <BR> <BR> tsEvent
= tsEvent_dummy; <BR> <BR> ret =
register_chrdev(0, DEVICE_NAME, &s3c2410_fops);
<BR> if (ret < 0) { <BR>
printk(DEVICE_NAME " can't get major
number\n"); <BR> return ret;
<BR> } <BR> tsMajor = ret; <BR>
<BR> /* set gpio to XP, YM,
YP and YM */ <BR>
set_gpio_ctrl(GPIO_YPON); <BR> set_gpio_ctrl(GPIO_YMON);
<BR> set_gpio_ctrl(GPIO_XPON); <BR>
set_gpio_ctrl(GPIO_XMON); <BR> ret =
request_irq(IRQ_ADC_DONE, s3c2410_isr_adc, SA_INTERRUPT,
<BR> DEVICE_NAME, s3c2410_isr_adc);
<BR> if (ret) goto adc_failed; <BR> ret
= request_irq(IRQ_TC, s3c2410_isr_tc, SA_INTERRUPT,
<BR> DEVICE_NAME, s3c2410_isr_tc);
<BR> if (ret) goto tc_failed;
<BR> <BR> /* Wait for touch
screen interrupts */ <BR> wait_down_int();
<BR> <BR> tsdev.pm_dev =
pm_register(PM_DEBUG_DEV, PM_USER_INPUT, <BR>
s3c2410_ts_pm_callback); <BR> #endif <BR>
printk(DEVICE_NAME " initialized\n"); <BR>
<BR> return 0; <BR> tc_failed:
<BR> free_irq(IRQ_ADC_DONE, s3c2410_isr_adc); <BR>
adc_failed: <BR> return ret; <BR> }
<BR> <BR> static void __exit
s3c2410_ts_exit(void) <BR> { <BR> #ifdef
CONFIG_DEVFS_FS <BR> devfs_unregister(devfs_tsraw);
<BR> devfs_unregister(devfs_ts_dir); <BR> #endif
<BR> unregister_chrdev(tsMajor, DEVICE_NAME); <BR>
#ifdef CONFIG_PM <BR> pm_unregister(tsdev.pm_dev);
<BR> #endif <BR> free_irq(IRQ_ADC_DONE,
s3c2410_isr_adc); <BR> free_irq(IRQ_TC, s3c2410_isr_tc);
<BR> } <BR> <BR>
module_init(s3c2410_ts_init); <BR> module_exit(s3c2410_ts_exit);
<BR> <BR></DIV>
<DIV id=TopicButtomInfoRegion>问题点数:<SPAN id=TopicPoint>20</SPAN>、回复次数:<SPAN
id=TopicReplyNum>9</SPAN> </DIV></DIV>
<DIV class=z></DIV>
<DIV class=rightbgbottom></DIV>
<DIV id=ReplysRegion>
<DIV class=ReplysRegion id=ReplysRegion_22919178><A name=Reply_22919178>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -