Driver Attributes/Device Attributes 及作为linux的一种读写接口的用法(timed_output实例)
2012-03-08 14:41
621 查看
(1)Driver Attributes
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.在实际调试时,用cat xxx即相当于执行show;用echo 1/0 > xxx相当于执行store了。需要注意的是,不管是show还是store,buf都可返回字符串,在store时返回的字符串可标示store操作的结果好坏。
实例:在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
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);
..............................
}
注意电池设备在probe中已经用platform_device_register(&battery_device),这里的battery_device就是device_create_file的第一个dev。之后,在路径/sys/devices/platform/mt6573-battery中可以看到属性
(3)Device Attributes配合sysfs_create_file/sysfs_create_group
同样是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命令来显示固件版本号和命令升级,其中实例中具体调用到的函数请见/article/1948700.html。在TP驱动文件中中添加DEVICE_ATTR属性
在static int __devinit tpd_probe(struct i2c_client *client, const struct i2c_device_id *id)中添加:
编译烧录,最后查看属性的路径是:
用cat melfasver即可回显固件版本号,用echo 1 > melfasupdate即可实现发命令升级。需要注意的是,要留意store的操作参数,上文仅仅是提供一个操作接口并不带参数;如果需要用到*buf这个参数,注意它是字符,比如*buf为'0'或者'1'。
类似地,用sysfs_create_group创建的属性组,最终属性在下面目录
(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,以一个马达举例。
首先是定义此类型设备的结构体:
再在马达的初始化中完成:
进入/sys/class/timed_output/vibrator/目录,按pwd即可在ADB中看到如下的属性:
用echo 0或者1> enable即可进行马达的开关控制。这个完成的是驱动层,在上层比如一个测试程序,则可以通过write来调用到timed_output_dev的store函数接口,从而调用到enable。类似,通过read可以得到show属性值。
(5)上面的sysfs_create_file/sysfs_create_group建立时都是跟client关联的,如何创建一个sysfs属性,使它不跟驱动中的client关联?答案是kobject_create_and_add。
sysfs 文件系统,是用户空间与内核空间进行交互的一个媒介,内核空间与用户空间的映射关系如下表所示:
内核空间(internel) ——->用户空间(externel)
内核对象(kernel objects) ——->目录(directories)
对象属性(object attributes) ——->普通文件(regular files)
可以先使用kobject_create_and_add() 創建目錄(该函数不需形参,可见不与任何client关联),再透過sysfs_create_group(example_kobj, &attr_group) 創建目录下的属性文件组。最终创建的属性文件直接在/sys下面找,更直接简单。一个实例:
结果
(6)安卓J***A层基本的读写属性的语句,假设值1或者0
假设sysfs设备属性值是"/sys/devices/platform/mt-i2c.1/i2c-1/1-0038/ftstpwakeupswitch",基本的读写函数
实际使用时,readFile("/sys/devices/platform/mt-i2c.1/i2c-1/1-0038/ftstpwakeupswitch");或者writeFile("/sys/devices/platform/mt-i2c.1/i2c-1/1-0038/ftstpwakeupswitch", 49);即可(49是1的ASCII码)。
参考文章:http://blog.csdn.net/wtao616/article/details/6147721
参考文章:http://blog.csdn.net/zq5848/article/details/6857453
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.在实际调试时,用cat xxx即相当于执行show;用echo 1/0 > xxx相当于执行store了。需要注意的是,不管是show还是store,buf都可返回字符串,在store时返回的字符串可标示store操作的结果好坏。
实例:在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);
..............................
}
注意电池设备在probe中已经用platform_device_register(&battery_device),这里的battery_device就是device_create_file的第一个dev。之后,在路径/sys/devices/platform/mt6573-battery中可以看到属性
(3)Device Attributes配合sysfs_create_file/sysfs_create_group
同样是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命令来显示固件版本号和命令升级,其中实例中具体调用到的函数请见/article/1948700.html。在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"); //提示读固件号错误 else num_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); } else mfs6000_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'。
类似地,用sysfs_create_group创建的属性组,最终属性在下面目录
(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); }
(5)上面的sysfs_create_file/sysfs_create_group建立时都是跟client关联的,如何创建一个sysfs属性,使它不跟驱动中的client关联?答案是kobject_create_and_add。
sysfs 文件系统,是用户空间与内核空间进行交互的一个媒介,内核空间与用户空间的映射关系如下表所示:
内核空间(internel) ——->用户空间(externel)
内核对象(kernel objects) ——->目录(directories)
对象属性(object attributes) ——->普通文件(regular files)
可以先使用kobject_create_and_add() 創建目錄(该函数不需形参,可见不与任何client关联),再透過sysfs_create_group(example_kobj, &attr_group) 創建目录下的属性文件组。最终创建的属性文件直接在/sys下面找,更直接简单。一个实例:
static int ts_firmware_file(void) { int ret; struct kobject *kobject_ts; kobject_ts = kobject_create_and_add("touch_screen", NULL); if (!kobject_ts) { printk("create kobjetct error!\n"); return -1; } ret = sysfs_create_file(kobject_ts, &update_firmware_attribute.attr); if (ret) { kobject_put(kobject_ts); printk("create file error\n"); return -1; } return 0; }
结果
(6)安卓J***A层基本的读写属性的语句,假设值1或者0
假设sysfs设备属性值是"/sys/devices/platform/mt-i2c.1/i2c-1/1-0038/ftstpwakeupswitch",基本的读写函数
//write data public void writeFile(String filePath,int i) throws IOException{ FileOutputStream out = null; try{ File f = new File(filePath); out = new FileOutputStream(f); out.write(i); }catch(IOException e){ e.printStackTrace(); }finally{ if (out != null) { out.close(); } } } //read data public String readFile(String filePath) throws IOException{ String res=""; FileInputStream input = null; File f = new File(filePath); try { input = new FileInputStream(f); byte[] buffer = new byte[1]; input.read(buffer, 0, 1); res = new String(buffer); } catch (IOException e) { e.printStackTrace(); }finally { if (input != null){ try { input.close(); } catch (IOException e) { } } } return res; }
实际使用时,readFile("/sys/devices/platform/mt-i2c.1/i2c-1/1-0038/ftstpwakeupswitch");或者writeFile("/sys/devices/platform/mt-i2c.1/i2c-1/1-0038/ftstpwakeupswitch", 49);即可(49是1的ASCII码)。
参考文章:http://blog.csdn.net/wtao616/article/details/6147721
参考文章:http://blog.csdn.net/zq5848/article/details/6857453
相关文章推荐
- Driver Attributes/Device Attributes 及作为linux的一种读写接口的用法(timed_output实例)
- Driver Attributes/Device Attributes 及作为linux的一种读写接口的用法(timed_output实例)
- linux设备模型bus,device,driver
- UIDeviceOrientation 和 UIInterfaceOrientation 设备旋转的用法 (实例)
- Linux设备模型(总线、设备、驱动程序和类)之三:device_driver && 多厂家驱动自动识别
- Linux Platform Device and Driver,platform_add_devices()->platform_driver_register()
- Linux中使用SecureCRT上传、下载文件命令sz与rz用法实例
- 读写锁接口实例-通过ReadWriteLock实现一个简单的缓存
- IIC Device(At24c02) Driver for Linux2.6.xx+ARM9
- linux平台设备驱动架构详解 Linux Platform Device and Driver
- Linux中configure/makefile的用法实例(附代码)
- 关于Linux driver中device_create()使用的注意事项
- linux wget 命令用法详解(附实例说明)
- Linux device driver 关于driver返回值和用户空间处理
- Writting Linux Frame Buffer Driver fo LCD Device
- deviceDriver.py与robot framework结合使用的简单实例
- Linux Platform Device and Driver的注册过程解析
- linux驱动开发之——device与driver关系趣谈
- Linux 系统编程--fcntl()读写锁实例
- Linux Platform Device and Driver