Sysfs interface function to build _device_attr
Recently in the sensor drive, saw a manufacturer of the finished product drive, the implementation of all is the Sysfs interface, HAL layer using the interface generated by SYSFS, sensor operation.
Said Sysfs interface, you have to mention the function of macro device_attr
Prototypes are # define DEVICE_ATTR (_name, _mode, _show, _store) \
struct Device_attribute dev_attr_# #_name = __attr (_name, _mode, _show, _store)
The function macro device_attr is encapsulated in the __attr (_name,_mode,_show,_stroe) method, _show represents the Read method, and _stroe represents the Write method.
Of course _attr is not an only child, he also has a series of sisters __attr_ro macro only read methods, __attr_null and so on
such as the use of the device device_attr, the use of bus_attr on the bus, to drive the use of driver_attr, the category (class) using CLASS_ATTR, these four advanced macros from the <include/linux/devi Ce.h>
The DEVICE_ATTR macro declaration has four parameters, namely, name, permission bit, read function, write function. where read and write functions are function names for read and write functions.
If you complete the fill of the DEVICE_ATTR function macro, you need to create the interface below
For example:
Static device_attr (Polling, S_irugo | S_IWUSR, show_polling, set_polling);
static struct attribute *dev_attrs[] = {
&dev_attr_polling.attr,
Null
};
When you want to implement the interface name is polling, you need to implement struct struct attribute *dev_attrs[]
The name of the member variable must be &dev_attr_polling.attr
and then encapsulate
static struct Attribute_group dev_attr_grp = {
. Attrs = Dev_attrs,
};
using Sysfs_create_group (&pdev->dev.kobj, &DEV_ATTR_GRP); Creating an interface
With the simple three steps above, you can see the interface in the ADB shell terminal. When we echo the data into the interface, we actually complete a write operation on the upper layer, which corresponds to kernel, and calls the "store" in the driver. Similarly, "show" is called when we have a cat interface. Here, simply built the android layer to the kernel bridge, the actual implementation of the hardware operation, or in the "show" and "store" completed.
######################################################################
Here's an example:
/*
* Sample Kobject implementation
*
* Copyright (C) 2004-2007 Greg kroah-hartman <[email protected]>
* Copyright (C) Novell Inc.
*
* Released under the GPL version 2 only.
*
*/
#include <linux/kobject.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/module.h>
#include <linux/init.h>
#include <asm/gpio.h>
#include <linux/delay.h>
/*
* This module shows what to create a simple subdirectory in Sysfs called
*/sys/kernel/kobject-example in this directory, 3 files are created:
* "foo", "Baz", and "bar". If An integer was written to these files, it can
* Later read out of it.
*/
static int foo;
/*
* the "foo" file where a static variable is read from and written to.
*/
static struct Msm_gpio qup_i2c_gpios_io[] = {
{gpio_cfg (0, Gpio_cfg_output, Gpio_cfg_no_pull, Gpio_cfg_8ma),
"QUP_SCL"},
{gpio_cfg (0, Gpio_cfg_input, Gpio_cfg_no_pull, Gpio_cfg_8ma),
"Qup_sda"},
{gpio_cfg (131, 0, Gpio_cfg_output, Gpio_cfg_no_pull, Gpio_cfg_8ma),
"QUP_SCL"},
{gpio_cfg (0, Gpio_cfg_input, Gpio_cfg_no_pull, Gpio_cfg_8ma),
"Qup_sda"},
};
static struct Msm_gpio qup_i2c_gpios_hw[] = {
{gpio_cfg (1, Gpio_cfg_input, Gpio_cfg_no_pull, Gpio_cfg_8ma),
"QUP_SCL"},
{gpio_cfg (1, Gpio_cfg_input, Gpio_cfg_no_pull, Gpio_cfg_8ma),
"Qup_sda"},
{gpio_cfg (131, 2, Gpio_cfg_input, Gpio_cfg_no_pull, Gpio_cfg_8ma),
"QUP_SCL"},
{gpio_cfg (2, Gpio_cfg_input, Gpio_cfg_no_pull, Gpio_cfg_8ma),
"Qup_sda"},
};
static void Gsbi_qup_i2c_gpio_config (int adap_id, int config_type)
{
int RC;
if (adap_id < 0 | | adap_id > 1)
Return
/* Each adapter gets 2 lines from the table */
if (Config_type)
rc = Msm_gpios_enable (&qup_i2c_gpios_hw[adap_id*2], 2);
Else
rc = Msm_gpios_enable (&qup_i2c_gpios_io[adap_id*2], 2);
if (RC < 0)
Pr_err ("QUP GPIO request/enable failed:%d\n", RC);
}
Static ssize_t foo_show (struct kobject *kobj, struct Kobj_attribute *attr,
Char *buf)
{
Return sprintf (buf, "%d\n", foo);
}
Static ssize_t Foo_store (struct kobject *kobj, struct Kobj_attribute *attr,
const char *BUF, size_t count)
{
int SDA,SCL;
int i;
SSCANF (buf, "%du", &foo);
PRINTK ("foo =%d.\n", foo);
foo = foo-1;
if (Foo < 0 | | foo > 1)
{
PRINTK ("Input foo error. foo=%d.\n ", foo);
return 0;
}
SDA = Gpio_pin ((&qup_i2c_gpios_hw[foo*2+1])->gpio_cfg);
SCL = Gpio_pin ((&qup_i2c_gpios_hw[foo*2])->gpio_cfg);
PRINTK ("SDA =%d.\n", SDA);
PRINTK ("SCL =%d.\n", SCL);
Gsbi_qup_i2c_gpio_config (foo,0);
for (i=0;i<9;i++)
{
if (Gpio_get_value (SDA))
{
PRINTK ("SDA of i2c%d is high when%d pulse was output on scl.\n", foo,i);
Break
}
Gpio_set_value (scl,0);
Udelay (5);
Gpio_set_value (scl,1);
Udelay (5);
}
Gsbi_qup_i2c_gpio_config (foo,1);
PRINTK ("finish.\n");
return count;
}
static struct Kobj_attribute Foo_attribute =
__attr (I2c_unlock, 0666, Foo_show, Foo_store);
/*
* Create a group of attributes so, we can Create and destroy them all
* at once.
*/
static struct attribute *attrs[] = {
&foo_attribute.attr,
null,»/* need to NULL terminate the list of attributes */
};
/*
* An unnamed attribute group would put all of the attributes directly in
* The Kobject directory. If We specify a name, a subdirectory would be
* Created for the attributes with the directory being the name of the
* Attribute group.
*/
static struct Attribute_group Attr_group = {
. Attrs = Attrs,
};
static struct Kobject *example_kobj;
static int __init example_init (void)
{
int retval;
/*
* Create a simple kobject with the name of "Kobject_example",
* Located under/sys/kernel/
*
* As this was a simple directory, no uevent would be sent to
* Userspace. That's why this function should not being used for
* Any type of dynamic kobjects, where the name and number is
* Not known ahead of time.
*/
Example_kobj = Kobject_create_and_add ("I2c_recovery", kernel_kobj);
if (!example_kobj)
Return-enomem;
/* Create The files associated with this kobject */
retval = Sysfs_create_group (Example_kobj, &attr_group);
if (retval)
Kobject_put (Example_kobj);
return retval;
}
static void __exit example_exit (void)
{
Kobject_put (Example_kobj);
}
Module_init (Example_init);
Module_exit (Example_exit);
Module_license ("GPL");
Module_author ("Wupeng");
Establishment of SYSFS interface function _device_attr (RPM)