一.class_create 和 xxx_classdev_register 混合使用
1.class_create标准用法
class_create(THIS_MODULE, "sensors");
class_create(THIS_MODULE, "leds");
class_create(THIS_MODULE, "backlight");
class_create(THIS_MODULE, "sound");
2. 混合使用demo
(1)framwork 代码功能 :(sensors_class.c)
《1》 在sys/class/目录下面创建xxx目录,并设置dev_attrs
sensors_class = class_create(THIS_MODULE, "sensors");
if (IS_ERR(sensors_class))
return PTR_ERR(sensors_class);
sensors_class->dev_attrs = sensors_class_attrs;
《2》定义了 /sys/class/xxx 目录下的 dev_attrs
static struct device_attribute sensors_class_attrs[] = {
__ATTR(name, 0444, sensors_name_show, NULL),
__ATTR(vendor, 0444, sensors_vendor_show, NULL),
__ATTR(version, 0444, sensors_version_show, NULL),
__ATTR(handle, 0444, sensors_handle_show, NULL),
__ATTR(type, 0444, sensors_type_show, NULL),
__ATTR(max_range, 0444, sensors_max_range_show, NULL),
__ATTR(resolution, 0444, sensors_resolution_show, NULL),
__ATTR(sensor_power, 0444, sensors_power_show, NULL),
__ATTR(min_delay, 0444, sensors_min_delay_show, NULL),
__ATTR(fifo_reserved_event_count, 0444, sensors_fifo_event_show, NULL),
__ATTR(fifo_max_event_count, 0444, sensors_fifo_max_show, NULL),
__ATTR(max_delay, 0444, sensors_max_delay_show, NULL),
__ATTR(flags, 0444, sensors_flags_show, NULL),
__ATTR(enable, 0664, sensors_enable_show, sensors_enable_store),
__ATTR(enable_wakeup, 0664, sensors_enable_wakeup_show,
sensors_enable_wakeup_store),
__ATTR(poll_delay, 0664, sensors_delay_show, sensors_delay_store),
__ATTR(self_test, 0440, sensors_test_show, NULL),
__ATTR(max_latency, 0660, sensors_max_latency_show,
sensors_max_latency_store),
__ATTR(flush, 0660, sensors_flush_show, sensors_flush_store),
__ATTR(calibrate, 0664, sensors_calibrate_show,
sensors_calibrate_store),
__ATTR_NULL,
};
(2)drv代码功能 : (bma2x2.c)
创建相关 dev_attr,并实现相关 dev_attr 对应的回调函数
static struct sensors_classdev sensors_acc_cdev = {
.name = "bma2x2",
.vendor = "bosch",
.version = 1,
.handle = SENSORS_ACCELERATION_HANDLE,
.type = SENSOR_TYPE_ACCELEROMETER,
.max_range = "156.8",
.resolution = "0.153125",
.sensor_power = "0.13",
.min_delay = 10*1000, /* us */
.fifo_reserved_event_count = 0,
.fifo_max_event_count = 0,
.enabled = 0,
.delay_msec = 200,
.sensors_enable = NULL,
.sensors_poll_delay = NULL,
};
data->bma_cdev = sensors_acc_cdev;
data-> bma_cdev .sensors_enable=bma2x2_cdev_set_enable; // 实现 framwork 回调函数,一般只需要实现 eable 和 poll_delay
data-> bma_cdev.sensors_poll_delay=bma2x2_cdev_set_poll_delay;
err = sensors_classdev_register(&client->dev, &data->bma_cdev); // 在/sys/class/sensors/目录下创建名字为 bma2x2 的一些 dev_attr 属性文件
二、 sysfs_create_group
一般用作 sys/class/sensors/ap3426xx/device目录下 dev_attr 的创建
1.在sys/class/sensors/ap3426xx/device 目录下创建 attr组
sysfs_create_group(&data->client->dev.kobj, &ap3426_attr_group);
2、定义 attr组
static const struct attribute_group ap3426_attr_group = {
.attrs = ap3426_attributes,
};
----------
static struct attribute *ap3426_attributes[] = {
&dev_attr_range.attr,
&dev_attr_mode.attr,
&dev_attr_lux.attr,
&dev_attr_object.attr,
&dev_attr_pxvalue.attr,
&dev_attr_althres.attr,
&dev_attr_ahthres.attr,
&dev_attr_plthres.attr,
&dev_attr_phthres.attr,
&dev_attr_calibration.attr,
#ifdef LSC_DBG
&dev_attr_em.attr,
#endif
NULL
};
3. 实现每一个attr
static DEVICE_ATTR(range, S_IWUSR | S_IRUGO,ap3426_show_range, ap3426_store_range);
4、实现每一个attr对应的回调函数
/* range */
static ssize_t ap3426_show_range(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct input_dev *input = to_input_dev(dev);
struct ap3426_data *data = input_get_drvdata(input);
return sprintf(buf, "%i\n", ap3426_get_range(data->client));
}
static ssize_t ap3426_store_range(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct input_dev *input = to_input_dev(dev);
struct ap3426_data *data = input_get_drvdata(input);
unsigned long val;
int ret;
if ((strict_strtoul(buf, 10, &val) < 0) || (val > 3))
return -EINVAL;
ret = ap3426_set_range(data->client, val);
return (ret < 0)? ret:count;
}
----------
----
三、device_create_file devices下面创建属性文件
1.原型
device_create_file(struct device *dev, const struct device_attribute *attr)
2.demo
// sys/class/android_usb
android_class = class_create(THIS_MODULE, "android_usb");
----------
// sys/class/android_usb/android0
dev->dev = device_create(android_class, NULL,MKDEV(0, 0), NULL, "android0");
----------
while ((attr = *android_usb_attributes++/**/)) {
err = device_create_file(dev->dev, attr);
}
----------
static struct device_attribute ***android_usb_attributes**[] = {
&dev_attr_idVendor,
&dev_attr_idProduct,
&dev_attr_bcdDevice,
&dev_attr_bDeviceClass,
&dev_attr_bDeviceSubClass,
&dev_attr_bDeviceProtocol,
&dev_attr_iManufacturer,
&dev_attr_iProduct,
&dev_attr_iSerial,
&**dev_attr_functions**,
&dev_attr_enable,
&dev_attr_state,
NULL
};
----------
DESCRIPTOR_ATTR(**idVendor**, "%04x\n")
DESCRIPTOR_ATTR(**idProduct**, "%04x\n")
DESCRIPTOR_ATTR(bcdDevice, "%04x\n")
DESCRIPTOR_ATTR(bDeviceClass, "%d\n")
DESCRIPTOR_ATTR(bDeviceSubClass, "%d\n")
DESCRIPTOR_ATTR(bDeviceProtocol, "%d\n")
DESCRIPTOR_STRING_ATTR(iManufacturer, manufacturer_string)
DESCRIPTOR_STRING_ATTR(iProduct, product_string)
DESCRIPTOR_STRING_ATTR(iSerial, serial_string)