(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.執行個體:在GSENSOR 8452驅動中申明的屬性,可以在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;
}
之後,在終端路徑/sys/bus/platform/drivers/gsensor,就可以看到屬性值
(2)Device Attributes配合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.執行個體,在電池驅動中添加的屬性,也可以在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);
..............................
}
之後,在路徑/sys/devices/platform/mt6573-battery中可以看到屬性
(3)Device Attributes配合sysfs_create_file
同樣是DEVICE_ATTR,建立sysfs的函數不同,得到的結果也不同。device_create_file的形參是struct device *和struct device_attribute *,而sysfs_create_file的形參是struct kobject *和struct attribute *。所以兩者的使用方法有區別:前者用在模組XXX_probe(struct platform_device *dev)中,因為需要&(dev->dev)得到要求的第一個形參;後者用在類似某I2C_probe(struct
i2c_client *client,xxx)中,因為需要&client->dev.kobj得到要求的第一個形參;兩者的第二個參數差別不大,struct device_attribute的一個成員就是struct attribute。下面舉一個使用sysfs_create_file的執行個體,實現使用ADB的cat 和echo命令來顯示韌體版本號碼和命令升級,其中執行個體中具體調用到的函數請見http://blog.csdn.net/zhandoushi1982/article/details/7704416。在TP驅動檔案中中添加DEVICE_ATTR屬性
static ssize_t melfas_version_show(struct device *dev,struct device_attribute *attr, char *buf)//顯示韌體版本號碼{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");//提示讀韌體號錯誤elsenum_read_chars = snprintf(buf, PAGE_SIZE, "%02X\n", fwver);return num_read_chars;//返回韌體版本號碼值}static DEVICE_ATTR(melfasver, S_IRUGO|S_IWUSR, melfas_version_show, melfas_version_store);static ssize_t melfas_fwupdate_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count){//函數的形參並沒有用到int UpResult;mt65xx_eint_mask(CUST_EINT_TOUCH_PANEL_NUM);UpResult = ms6000_firmware_upgrade();//可以在串口資訊看到升級過程if(UpResult== MS6000_RET_SUCCESS){printk("MFS6000 DOWNLOAD SUCCESS \r\n");msleep(100);}elsemfs6000_print_fail_result(UpResult);i2c_client->addr = MS6000_8BIT_I2CADDR;mt_set_gpio_mode(GPIO_I2C0_SCA_PIN, GPIO_I2C0_SCA_PIN_M_SCL);mt_set_gpio_mode(GPIO_I2C0_SDA_PIN, GPIO_I2C0_SDA_PIN_M_SDA);mt65xx_eint_unmask(CUST_EINT_TOUCH_PANEL_NUM);return count;}static DEVICE_ATTR(melfasupdate, S_IRUGO|S_IWUSR, melfas_fwupdate_show, melfas_fwupdate_store);
在static int __devinit tpd_probe(struct i2c_client *client, const struct i2c_device_id *id)中添加:
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"); }
編譯燒錄,最後查看屬性的路徑是:
用cat melfasver即可回顯韌體版本號碼,用echo 1 > melfasupdate即可實現發命令升級。需要注意的是,要留意store的巨集指令引數,上文僅僅是提供一個操作介面並不帶參數;如果需要用到*buf這個參數,注意它是字元,比如*buf為'0'或者'1'。
(4)timed_output_dev裝置的讀寫
綜(3)所執行個體,利用屬性操作中對檔案進行讀寫,也是除了檔案操作IOCTL之外的一種好方法,除了手動操作之外,也可以通過程式訪問show store屬性。timed_output_dev,就是時間輸出類的一個常用介面(定義在Timed_output.c (kernel\drivers\staging\android)),它的特點是要用timed_output_dev_register進行註冊,這樣就會組建目錄:/sys/class/timed_output,以一個馬達舉例。
首先是定義此類型裝置的結構體:
static struct timed_output_dev mt6573_vibrator = {.name = "vibrator",.get_time = vibrator_get_time,.enable = vibrator_enable,};
再在馬達的初始化中完成:
timed_output_dev_register(&mt6573_vibrator);
進入/sys/class/timed_output/vibrator/目錄,按pwd即可在ADB中看到如下的屬性:
用echo 0或者1> enable即可進行馬達的開關控制。這個完成的是驅動層,在上層比如一個測試程式,則可以通過write來調用到timed_output_dev的store函數介面,從而調用到enable。類似,通過read可以得到show屬性值。
#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);}
參考文章:http://blog.csdn.net/wtao616/article/details/6147721
參考文章:http://blog.csdn.net/zq5848/article/details/6857453