Buttons-poll mechanism for character Devices

Source: Internet
Author: User

Buttons. c

# Include <Linux/fs. h>
# Include <Linux/module. h>
# Include <Linux/errno. h>
# Include <Linux/kernel. h>
# Include <Linux/init. h>
# Include <Linux/cdev. h>
# Include <Linux/ioport. h>
# Include <Linux/PCI. h>
# Include <ASM/uaccess. h>
# Include <ASM/IO. h>
# Include <ASM/IRQ. h>
# Include <Linux/interrupt. h>
# Include <ASM/Mach/IRQ. h>
# Include <ASM/ARCH/regs-gpio.h>
# Include <Linux/poll. h>

Static int major = 0;
Static struct class * CLS;

/* Gpecon 0x56000040 */
/* Gpfcon 0x56000050 */
/* Gpgcon 0x56000060 */
Static volatile unsigned long * gpecon;
Static volatile unsigned long * gpedat;

Static volatile unsigned long * gpfcon;
Static volatile unsigned long * gpfdat;

Static volatile unsigned long * gpgcon;
Static volatile unsigned long * gpgdat;

Struct key_desc {
Int IRQ;
Int pin;
Char * Name;
Char key_val;
};

Struct key_desc [] = {
{Irq_eint0, s3c2410_gpf0, "K10", 1},/* release: 1, press: 0x81 */
{Irq_eint2, s3c2410_gpf2, "K7", 2},/* release: 2, press: 0x82 */
{Irq_eint11, s3c2410_gpg3, "K4", 3},/* release: 3, press: 0x83 */
{Irq_eint19, s3c2410_gpg11, "K1", 4},/* release: 4, press: 0x84 */
};
 
Volatile char key = 0;

Static wait_queue_head_t button_waitq;

# Define buf_len 10
Static char key_buf [buf_len];
Static volatile int r = 0, W = 0;

Static int isempty (void)
{
Return (r = W );
}

Static int isfull (void)
{
Return (r = (W + 1) % buf_len ));
}

Static int putdata (char Val)
{
If (isfull ())
{
Return-1;
}
Else
{
Key_buf [w] = val;
W = (W + 1) % buf_len;
Return 0;
}
}

Static int getdata (char * P)
{
If (isempty ())
{
Return-1;
}
Else
{
* P = key_buf [R];
R = (R + 1) % buf_len;
Return 0;
}
}

Static irqreturn_t buttons_irq (int irq, void * dev_id)
{
Struct key_desc * Kd = (struct key_desc *) dev_id;
Int up;
Char key;
 
/* Confirm the button: Which button, press or release */
Up = s3c2410_gpio_getpin (KD-> pin); // gpfdat, gpgdat
If (up)
{
Key = KD-> key_val;
}
Else
{
Key = KD-> key_val | 0x80;
}

// Printk ("Key = 0x % x \ n", key );
Putdata (key );

/* Wake up the application */
Wake_up_interruptible (& button_waitq );

// Printk ("buttons_irq current % s, pid = % d \ n", current-> comm, current-> PID );

 
Return irq_handled;
}

Int buttons_open (struct inode * inode, struct file * file)
{
Int I;
 
/* Registration interrupted */
For (I = 0; I <4; I ++)
{
Request_irq (key_desc [I]. IRQ, buttons_irq,
Irqf_shared | irqf_trigger_rising | irqf_trigger_falling,
Key_desc [I]. Name, & key_desc [I]);
}

/* Set gpio as the interrupt pin
* Set the trigger mode.
* Enable interruption
*/

/* Set kscan0 (gpe11) as the output pin and output 0 */
* Gpecon & = ~ (0x3 <22 );
* Gpecon | = (1 <22 );
* Gpedat & = ~ (1 <11 );
 
Return 0;
}

Ssize_t buttons_read (struct file * file, char _ User * Buf, size_t size, loff_t * offset)
{
/* If no buttons occur, sleep */
/* The Key is equal to 0 to sleep.
* The key is not 0 and does not sleep
*/
// Command
// Printk ("Current % s, pid = % d before sleep \ n", current-> comm, current-> PID );
Char key;

If (isempty () & (file-> f_flags & o_nonblock ))
Return-eagain;
 
Wait_event_interruptible (button_waitq ,! Isempty ());
 
// Printk ("Current % s, pid = % d after sleep \ n", current-> comm, current-> PID );

/* After being awakened, return the key value to the user program */
Getdata (& Key );
Copy_to_user (BUF, & Key, 1 );

/* Interrupted, key = xxx */
 
// Key = 0;
 
Return 1;
}

Int buttons_close (struct inode * inode, struct file * file)
{
Int I;
For (I = 0; I <4; I ++)
{
Free_irq (key_desc [I]. IRQ, & key_desc [I]);
}
Return 0;
}

Static unsigned intButtons_poll(Struct file * file, struct poll_table_struct * Wait)
{
Static int CNT = 0;
Printk ("buttons_poll CNT = % d \ n", CNT ++ );
 Poll_wait(File, & button_waitq, wait );
ReturnIsempty ()? 0: Pollin | pollrdnorm;
}

Static const struct file_operations buttons_fops = {
. Owner = this_module,
. Read = buttons_read,
. Open = buttons_open,/* set the pin and apply for resources */
. Release = buttons_close,
. Poll = buttons_poll,
};

Int buttons_init (void)
{
Int I;
 
Major = register_chrdev (0, "buttons", & buttons_fops );

/* Sysfs => mount to/sys */
CLS = class_create (this_module, "buttons_class ");
Class_device_create (CLS, null, mkdev (Major, 0), null, "buttons ");

// Mdev creates/dev/buttons Based on the content in/sys.

Gpecon = ioremap (0x56000040,409 6 );
Gpedat = gpecon + 1;

Gpfcon = gpecon + 4;
Gpfdat = gpfcon + 1;

Gpgcon = gpecon + 8;
Gpgdat = gpgcon + 1;

Init_waitqueue_head (& button_waitq );
 
Return 0;
}

Void buttons_exit (void)
{
Unregister_chrdev (Major, "buttons ");

Class_device_destroy (CLS, mkdev (Major, 0 ));
Class_destroy (CLS );

Iounmap (gpecon );
}

Module_init (buttons_init );
Module_exit (buttons_exit );

Module_license ("GPL ");

Buttons_test.c

# Include <stdio. h>
# Include <sys/types. h>
# Include <sys/STAT. h>
# Include <fcntl. h>
# Include <unistd. h>
# Include <poll. h>

Int main (INT argc, char ** argv)
{
Char Buf [4];
Int FD;
Int ret;
Int CNT = 0;
Int main_cnt = 0;
Struct pollfdFDS [1];/* file descriptor Set */
 
FD = open ("/dev/buttons", o_rdonly );
 
If (FD <0)
{
Printf ("can't open/dev/buttons \ n ");
Return-1;
}

FDS [0]. FD = FD;/* file to be queried */
FDS [0]. Events = Pollin;/* What to query:
* Pollin indicates that data is available for reading.
* Pollout indicates that there is space for writing.
*/

While (1)
{
Printf ("app poll CNT = % d \ n", main_cnt ++ );
Ret = poll (FDS, 1, 5000 );
If (ret = 0)
{
Printf ("time out: % d \ n", CNT ++ );
}
Else if (Ret> 0)
{
Ret = read (FD, Buf, 1 );
Printf ("Key = 0x % x \ n", Buf [0]);
}
Else
{
Printf ("error! \ N ");
}
}
 
Return 0;
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.