(1) driver attributes
struct driver_attribute { struct attribute attr; ssize_t (*show)(struct device_driver *driver, char *buf); ssize_t (*store)(struct device_driver *, const char * buf, size_t count);};
Device drivers can export attributes via their sysfs directories. drivers can declare attributes using a driver_attr macro that works identically to the device_attr macro. instance: Attributes stated in the gsensor 8452 driver can be viewed in ADB.
Static driver_attr (chipinfo, s_irugo, show_chipinfo_value, null );
Static struct driver_attribute * mma8452q_attr_list [] = {
& Driver_attr_chipinfo,/* chip information */
........................................
};
Static int mma8452q_create_attr (struct device_driver * driver)
{
For (idx = 0; idx <num; idx ++)
{
If (ERR = driver_create_file (driver, mma8452q_attr_list [idx])
{
Gse_err ("driver_create_file (% S) = % d \ n", mma8452q_attr_list [idx]-> ATTR. Name, err );
Break;
}
}
Return err;
}
Then, you can see the attribute value in the terminal path/sys/bus/platform/Drivers/gsensor.
(2) combination of device attributes and device_create_file
struct device_attribute { struct attribute attr; ssize_t (*show)(struct device *dev, struct device_attribute *attr,char *buf); ssize_t (*store)(struct device *dev, struct device_attribute *attr,const char *buf, size_t count);};
Attributes of devices can be exported via drivers using a simple procfs-like interface, attributes are declared using a macro called device_attr. instance, you can also find the properties added in the battery drive in ADB.
Static ssize_t show_power_on_voltage (struct device * Dev, struct device_attribute * ATTR, char * BUF)
{
Int ret_value = 1;
Ret_value = batt_volttopercent_table [0]. battvolt;
Printk ("[Em] power_on_voltage: % d \ n", ret_value );
Return sprintf (BUF, "% u \ n", ret_value );
}
Static device_attr (power_on_voltage, 0664, show_power_on_voltage, store_power_on_voltage );
Static int mt6573_battery_probe (struct platform_device * Dev)
{
...............................
Device_create_file (& (Dev-> Dev), & dev_attr_power_on_voltage );
..............................
}
Then you can see the properties in the path/sys/devices/platform/mt6573-battery
(3) combination of device attributes and sysfs_create_file
The same is device_attr. The function used to create sysfs is different and the result is different. The parameters of device_create_file are struct device * and struct device_attribute *, while the parameters of sysfs_create_file are struct kobject * and struct attribute *. Therefore, there is a difference between the two methods: the former is used in the module xxx_probe (struct platform_device * Dev), because the required first parameter needs to be obtained from & (Dev-> Dev; the latter is used in an i2c_probe (struct
I2c_client * client, XXX), because & client-> Dev. kobj gets the first required parameter. The second parameter does not have much difference between the two. One member of struct device_attribute is struct attribute. The following is an instance that uses sysfs_create_file. The cat and echo commands of ADB are used to display the firmware version number and command upgrade. For more information about the called functions in the instance, see refer to functions. Add the device_attr attribute to the TP driver file.
Static ssize_t melfas_version_show (struct device * Dev, struct device_attribute * ATTR, char * BUF) // display the firmware version {ssize_t num_read_chars = 0; u8 fwver = 0; if (mfs_i2c_read_single_reg (0x21, & fwver) = false) num_read_chars = snprintf (BUF, page_size, "Get tp fw version fail! \ N "); // The system prompts elsenum_read_chars = snprintf (BUF, page_size," % 02x \ n ", fwver); Return num_read_chars; // return the firmware version number} static device_attr (melfasver, s_irugo | s_iwusr, region, melfas_version_store); static ssize_t evaluate (struct device * Dev, struct device_attribute * ATTR, const char * Buf, size_t count) {// the parameter of the function does not use int upresult; mt65xx_eint_mask (cust_eint_touch_panel_num); upresult = ms6000_firmware_upgrade (); // you can see the upgrade process in the serial port information if (upresult = ms6000_ret_success) {printk ("mfs6000 download success \ r \ n"); msleep (100 );} merge (upresult); i2c_client-> ADDR = merge; mt_set_gpio_mode (inflow, inflow); mt_set_gpio_mode (inflow, inflow); merge (inflow); Return count;} static device_attr (melfasupdate, s_irugo | s_iwusr, melfas_fwupdate_show, melfas_fwupdate_store );
In static int _ devinit tpd_probe (struct i2c_client * client, const struct i2c_device_id * ID), add:
int err = 0; err = sysfs_create_file(&client->dev.kobj, &dev_attr_melfasver.attr); if (0 != err) {printk("sysfs_create_file dev_attr_melfasver failed \r\n");sysfs_remove_file(&client->dev.kobj, &dev_attr_melfasver.attr);} else { printk("melfas:dev_attr_melfasver- sysfs_create_file() succeeded.\n"); }err = sysfs_create_file(&client->dev.kobj, &dev_attr_melfasupdate.attr); if (0 != err) {printk("sysfs_create_file dev_attr_melfasupdate failed \r\n");sysfs_remove_file(&client->dev.kobj, &dev_attr_melfasupdate.attr);} else { printk("melfas:dev_attr_melfasupdate - sysfs_create_file() succeeded.\n"); }
Compile the script and check the attribute path as follows:
You can use Cat melfasver to display the firmware version. You can use Echo 1> melfasupdate to update the firmware. Note that you should pay attention to the operation parameters of the store. The preceding section only provides an operation interface without parameters. If you need to use the * Buf parameter, note that it is a character, for example, * the Buf is '0' or '1 '.
(4) read/write of the timed_output_dev Device
In summary (3), using attribute operations to read and write files is also a good method in addition to IOCTL for file operations. In addition to manual operations, you can also access the show store attribute through a program. Timed_output_dev is a common interface of the time output class (defined in timed_output.c (kernel \ drivers \ staging \ Android). It is characterized by registration with timed_output_dev_register to generate a directory: /sys/class/timed_output, for example, a motor.
First, define the struct of this type of device:
static struct timed_output_dev mt6573_vibrator = {.name = "vibrator",.get_time = vibrator_get_time,.enable = vibrator_enable,};
Complete the following in the initialization of the motor:
timed_output_dev_register(&mt6573_vibrator);
Go to the/sys/class/timed_output/vibrator/directory and press PWD to see the following attributes in ADB:
Use Echo 0 or 1> enable to switch and control the motor. This completes the driver layer. In the upper layer, for example, a test program, you can use write to call the store function interface of timed_output_dev to call enable. Similarly, you can get the show property value through read.
#define THE_DEVICE "/sys/class/timed_output/vibrator/enable"static int sendit(int timeout_ms){ int nwr, ret, fd; char value[20]; fd = open(THE_DEVICE, O_RDWR); if(fd < 0) return errno; nwr = sprintf(value, "%d\n", timeout_ms); ret = write(fd, value, nwr); close(fd); return (ret == nwr) ? 0 : -1;}int vibrator_on(int timeout_ms){ return sendit(timeout_ms);}int vibrator_off(){ return sendit(0);}
Reference: http://blog.csdn.net/wtao616/article/details/6147721
Reference: http://blog.csdn.net/zq5848/article/details/6857453