在sysfs中添加文件--添加设备非默认属性

 
sysfs是虚拟的文件系统,向用户空间导出内核的数据结构、数据结构的属性,以及它们直接的关系,并向用户空间提供接口。
 
手头上的一个项目需要用一个ID标识每一个usb设备,而且需要随时读取和修改它的ID。之前的方案是每次需要读取ID时使用libus库从usb芯片ft232的eeprom里读出来,当cpu负载重时,读取一批usb设备ID显得很吃力很慢。如果修改驱动,导出id到sysfs文件系统,那么该值由内核控制访问,每次读取都是读取sysfs的一个文件,写ID也只需输出到该文件即可。防止大量重复的操作,用户空间使用方便。好处是高效高速又方便。缺点是需要修改驱动。
 
 
简单来说就是:定义一个设备属性和show,store的操作(只读属性不需要store)。在探测设备时在sysfs对应目录创建设备属性文件,断开时删除文件。
 
 
 
下面是在设备的sysfs目录中在设备文件夹下添加新的属性的一个简单的例子:
 
在include/linux.h/device.h有添加非默认属性的接口
/* driverfs interface for exporting device attributes */

struct device_attribute {
	struct attribute	attr;
	ssize_t (*show)(struct device * dev, char * buf);
	ssize_t (*store)(struct device * dev, const char * buf, size_t count);
};
/* 定义新属性的宏 */
#define DEVICE_ATTR(_name,_mode,_show,_store) \
struct device_attribute dev_attr_##_name = __ATTR(_name,_mode,_show,_store)

/* 添加/删除 属性 函数*/
extern int device_create_file(struct device *device, struct device_attribute * entry);
extern void device_remove_file(struct device * dev, struct device_attribute * attr);


在驱动文件里,定义新属性

static unsigned char moteid[6] = "-1"; 
ssize_t show_moteid(struct device * dev, char * buf)
{
	strcpy(buf, moteid);
	return strlen(buf);
}

ssize_t store_moteid(struct device * dev, const char * buf, size_t count)
{
	int id;
	if(count > 4)
		count = 4;
	sscanf(buf, "%d", &id);
	printk("buf: %s; write id: %d\n", buf, id);
	strncpy(moteid, buf, 4);
	//if(id < 1024 && id > 0)
		//moteid_write(container_of(dev, struct usb_device, dev), id);

	return strlen(moteid);
}

DEVICE_ATTR(moteid,S_IRUGO | S_IWUSR,show_moteid,store_moteid);
//device_create_file(&serial->dev->dev, &dev_attr_moteid); /* 在设备探测函数里加入 */
//device_remove_file(&serial->dev->dev, &dev_attr_moteid); /* 在设备断开函数里加入 */


以下是我的usb探测函数,我在里面加入:

/* Startup for the FT232BM chip */
/* Called from usbserial:serial_probe */
static int ftdi_FT232BM_startup (struct usb_serial *serial)
{ /* ftdi_FT232BM_startup */
	struct ftdi_private *priv;
	int err;
	device_create_file(&serial->dev->dev, &dev_attr_moteid); /* 在sysfs相应目录创建文件!!!*/
	moteid_read(serial->dev);	
	printk("ftdi_FT232BM_startup: \n");
	err = ftdi_common_startup(serial);
	if (err){
		return (err);
	}

	priv = usb_get_serial_port_data(serial->port[0]);
	priv->chip_type = FT232BM;
	priv->baud_base = 48000000 / 2; /* Would be / 16, but FT232BM supports multiple of 0.125 divisor fractions! */

	printk("%s:[%s]: %s end: \n",__FILE__, __LINE__, __FUNCTION__);
	return (0);
} /* ftdi_FT232BM_startup */


 

下面的是我的断开设备的函数:

/* ftdi_shutdown is called from usbserial:usb_serial_disconnect 
 *   it is called when the usb device is disconnected
 *
 *   usbserial:usb_serial_disconnect
 *      calls __serial_close for each open of the port
 *      shutdown is called then (ie ftdi_shutdown)
 */
static void ftdi_shutdown (struct usb_serial *serial)
{ /* ftdi_shutdown */
	printk("%s:%s ftdi_shutdown begin: %s\n",__FILE__, __LINE__, __FUNCTION__);
	device_remove_file(&serial->dev->dev, &dev_attr_moteid);
	struct usb_serial_port *port = serial->port[0];
	struct ftdi_private *priv = usb_get_serial_port_data(port);

	/* all open ports are closed at this point 
         *    (by usbserial.c:__serial_close, which calls ftdi_close)  
	 */
	if (priv) {
		usb_set_serial_port_data(port, NULL);
		kfree(priv);
	}
	printk("%s:%s ftdi_shutdown end: %s\n",__FILE__, __LINE__, __FUNCTION__);
} /* ftdi_shutdown */


 

在用户空间的验证, 插入对应的usb设备后:

/sys/devices/platform/ep93xxusb0/usb1/1-3 # ls
1-3:1.0              bNumInterfaces       manufacturer
bConfigurationValue  bcdDevice            maxchild
bDeviceClass         bmAttributes         moteid(就是添加的自定义属性!!!)
bDeviceProtocol      detach_state         product
bDeviceSubClass      devnum               serial
bMaxPower            idProduct            speed
bNumConfigurations   idVendor             version


 

用户可对该文件进行读写,当然啦,我的实现不是简单的在moteid[]里面,而是写入eeprom,第一次读则从eeprom读出来!

 

 

你可能感兴趣的:(在sysfs中添加文件--添加设备非默认属性)