LCH-256V2S 坏了,重新开卡修复成功

未分类 | Posted by 老沙
3月 31 2020

不多说上工具,怎么用网上找

我亲自测试,只有这个版本的开卡工具可以用

其它版本都开卡失败SM2246AB_MPO1027A_FWO1026A

SM2246AB_MPO1027A_FWO1026A

urwtest

碧霞元君 北顶娘娘庙事件 鸟巢

个人的心情空间, 心情空间, 未分类 | Posted by 老沙
10月 23 2019

简介:

碧霞元君是以中国大陆华北地区为中心的山神信仰(道教),称为“东岳泰山天仙玉女碧霞元君”。中国古代神话传说中的女神。其道场是在中国五岳之尊的东岳泰山,位于山东省的泰安市。碧霞元君的影响力由山东省泰安市传播开来,历经上千年,特别是在明清时期以后,对于中国北方地区文化产生了重大的影响。
碧霞元君全称为“东岳泰山天仙玉女碧霞元君”,道经称为“天仙玉女碧霞护世弘济真人”“天仙玉女保生真人宏德碧霞元君”。因坐镇泰山,尊称泰山圣母碧霞元君,俗称泰山娘娘、泰山老奶奶、泰山老母、万山奶奶等。道教认为,碧霞元君“庇佑众生,灵应九州”“统摄岳府神兵,照察人间善恶”,是道教中的重要女神,中国历史上影响最大的女神之一。
中国民间的“北元君 南妈祖”的说法,指得是泰山奶奶和妈祖娘娘之间,虽然有地域之差和山神、海神之别,但同样都普度众生、舍己为人,成为北方地区和南方地区闻名于世的保护女神,“碧霞”意指东方的日光之霞,“元君”则带有浓重的道教色彩,是对道教女神的尊称

 

鸟巢迁址事件:

鸟巢西南,水立下南边有一座古庙,供奉民间传说中的北顶娘娘,许多老人十分敬畏这座庙宇。但是,当时为了方便施工,准备拆掉这座庙宇。各项准备工作结束以后,拆迁工程就开始了。然而,刚刚拆掉两扇门后,鸟巢附近就刮来了一阵罕见的大风,将已经建好的地基全部摧毁,建筑现场有两名工人被砖石打死(后奇迹复活,编者注),几十名工人受伤。专家告诉大家说这是陆地上罕见的尘卷风,数百年才出现一次。大家虽然觉得十分怪异,但想到专家这么说,拆迁工作还是继续进行。但是,第二天,一个更离奇的消息从水立方传来。在水立方的施工现场,挖掘到一个巨大的洞,几名工人好奇,稍稍往里面探了探,发现里面竟然全是蛇!施工立即停止!就在停工的这一天,鸟巢和水立方晚上发生了不明原因的停电,大家在停电时眺望远方时,发现北顶娘娘庙那里灯火通明,就如同有万盏电灯那样,可是在那儿根本就没有电灯的啊。总工程师连夜召集大家开会研究,最后放弃了拆迁,并把鸟巢和水立方往北方移了一段距离,也就是说,我们今天看到的这两座体育场并不是在最初决定的地方,而是在冥冥中的指示下往北移了。虽然耗费了不少财力物力,但是后来的施工十分顺利,而且也保护下来了这座数百年历史的古建筑。

我觉得应该是真有其事,因为按照那谁谁的一般做事风格,如果不是因为有特别原因,是不可能改动这个国际性的建筑设计,也就是说这里真的是有神仙。我多次前去许愿,我觉得还是挺灵验的:)

 

再来几张图(点击看大图)

行车记录仪4PIN接口定义

硬件相关 | Posted by 老沙
3月 11 2019

【BYSSJ】开源 破解小牛电动车电池BMS(附源码) N1 N1S M1 U1 均可用

STM8 | Posted by 老沙
11月 28 2018

开篇: 之前发了一个贴子 破解小牛电动车电池BMS http://bbs.mydigit.cn/read.php?tid=2497489
这贴很水,只是简单了说一下破解的过程,但就这么一点点的贡献就得到了广大网友的支持。
这让我感到深深的惭愧。。。。让我久久不能入睡。。。。。。。。。。。。。`~~~~~~~~~~~ZZZ。。。
所以我考虑把代码发出来,造福大家,但又考虑到我自己的饭碗问题。
所以这次发一个阉割的版本。这次是干货,内容包括PCB源文件,与 IAR 源代码。
阉割的部分就是电容锁定在100%。其它的部分正常。
全系列车型可用,电路是V1.1版本的,最新的是V3.31,目前还没发布汗一个
电路部分是包括电压识别的,我只是在程序上阉割了,有能力的网友可以自己加上去这个功能

需要的工具:
STLINK 一个 刷程序用的
电路板:V1.1是之前剩下的,还有6个,有需要的可以问我(有图你都找不到我,那说明你应该是搞不定)
AD,IAR

哎,算了 TB 搜 【BYSSJ】可以找到我.
下图是正事。镇楼图

干货下载(电路图+IAR 源代码):NIU_BMS_V1.1_20180810_GNU

 

 

 

 

NIU_BMS_V1.11

STM8的ADC的五种工作模式

STM8 | Posted by 老沙
10月 19 2018

STM8的ADC的五种工作模式

STM8的ADC是10位的逐次比较型模拟数字转换器,多达16个多功能的输入通道。拥有5种转换模式,转换结束可产生中断。

STM8 ADC的初始化顺序如下:

1、AD输入通道对应的IO设置为上拉输入;

2、配置AD参数,如:预分频系数、是否使用外部触发转换、是否使用施密特触发器、是否使用缓存以及是否使用扫描模式等;

3、开启ADC;

4、开启转换;

注意!开启ADC和开启转换实际上都是置位ADON。

然后就可以通过ADC_DR寄存器读取转换后的值。

l单次模式:

在单次转换模式中,ADC仅在由ADC_CSR寄存器的CH[3:0]选定的通道上完成一次转换。该模式是在当CONT位为0时通过置位ADC_CR1寄存器的ADON位来启动的。

一旦转换完成,转换后的数据存储在ADC_DR寄存器中,EOC(转换结束)标志被置EOCIE 被置位将产生一个中断。

注意!初始化的时候只能选择一个通道。转换多个通道只能通过反复重新初始化或扫描模式!

示例程序:

void adc_init(void)

{

GPIO_Init(GPIOD,GPIO_PIN_3,GPIO_MODE_IN_PU_NO_IT);//AIN4 IO设置为上拉输入

ADC1_PrescalerConfig(ADC1_PRESSEL_FCPU_D2);//预分频2

ADC1_ExternalTriggerConfig(ADC1_EXTTRIG_TIM,DISABLE);//不使用外部触发

ADC1_SchmittTriggerConfig(ADC1_SCHMITTTRIG_CHANNEL4,DISABLE);

//禁止AIN2 AIN4的施密特触发器,降低IO静态功耗

//PD5,PD6上的通道如果施密特方式禁用会导致串口无法收发数据!

ADC1_ConversionConfig(ADC1_CONVERSIONMODE_SINGLE,//单次转换

ADC1_CHANNEL_4,//只能选择一个通道!

ADC1_ALIGN_RIGHT);//右对齐

ADC1_Cmd(ENABLE);//开启ADC

}

void main( void )

{

u16value=0;

adc_init();

while(1)

{

ADC1_StartConversion();//开启一次转换一次

while(!ADC1_GetFlagStatus(ADC1_FLAG_EOC));//等待转换完成

ADC1_ClearFlag(ADC1_FLAG_EOC);//软件清除

value=(u16)ADC1_GetConversionValue();//从ADC_DR中读取ADC值

}

}

l连续模式与带缓存的连续模式:

在连换模式中,ADC在完成一次转换后就立刻开始下一次的转换。当CONT位被置位时即将ADC设为连续模式,该模式是通过置位 ADC_CR1寄存器的 ADON 位来启动的。

如果缓冲功能没有被使能(ADC_CR3寄存器的DBUF位=0),那么转换结果数据保存在ADC_DR寄存器中同时 EOC 标志被置位。如果EOCIE 位已被置位时将产生一次中断。然后开始下一次转换。

如果缓存功能被使能(DBUF=1),那么某个选定通道上的8个或者10个连续的转换结果会填满数据缓存(此时填满的是同一个通道的数据!!扫描模式时才是不同通道的数据!),当缓存被填满时,EOC(转换结束)标志被置位,如果EOCIE位已被置位,则会产生一个中断,然后一个新的转换自动开始。如果某个数据缓存寄存器在被读走之前被覆盖,OVR标志将置1。

如果要停止连续转换,可以复位清零CONT位来停止转换或者复位清零ADON位来关闭ADC的电源。

示例程序(不带缓存):

void adc_init(void)

{

GPIO_Init(GPIOD,GPIO_PIN_3,GPIO_MODE_IN_PU_NO_IT);//AIN4 IO设置为上拉输入

ADC1_PrescalerConfig(ADC1_PRESSEL_FCPU_D2);//预分频2

ADC1_ExternalTriggerConfig(ADC1_EXTTRIG_TIM,DISABLE);//不使用外部触发

ADC1_SchmittTriggerConfig(ADC1_SCHMITTTRIG_CHANNEL4,DISABLE);

//禁止AIN2 AIN4的施密特触发器,降低IO静态功耗

//PD5,PD6上的通道如果施密特方式禁用会导致串口无法收发数据!

ADC1_ConversionConfig(ADC1_CONVERSIONMODE_CONTINUOUS, //连续转换

ADC1_CHANNEL_4,//只能选择一个通道!

ADC1_ALIGN_RIGHT);//右对齐

ADC1_Cmd(ENABLE);//开启ADC

ADC1_StartConversion();//开启连续转换

}

void main( void )

{

u16value=0;

adc_init();

while(1)

{

while(!ADC1_GetFlagStatus(ADC1_FLAG_EOC));//等待转换完成

ADC1_ClearFlag(ADC1_FLAG_EOC);//软件清除

value=(u16)ADC1_GetConversionValue();//从ADC_DR中读取ADC值

}

}

示例程序(带缓存):

void adc_init(void)

{

GPIO_Init(GPIOD,GPIO_PIN_3,GPIO_MODE_IN_PU_NO_IT);//AIN4 IO设置为上拉输入

ADC1_PrescalerConfig(ADC1_PRESSEL_FCPU_D2);//预分频2

ADC1_ExternalTriggerConfig(ADC1_EXTTRIG_TIM,DISABLE);//不使用外部触发

ADC1_SchmittTriggerConfig(ADC1_SCHMITTTRIG_CHANNEL4,DISABLE);

//禁止AIN2 AIN4的施密特触发器,降低IO静态功耗

//PD5,PD6上的通道如果施密特方式禁用会导致串口无法收发数据!

ADC1_ConversionConfig(ADC1_CONVERSIONMODE_CONTINUOUS, //连续转换

ADC1_CHANNEL_4,//只能选择一个通道!

ADC1_ALIGN_RIGHT);//右对齐

ADC1_Cmd(ENABLE);//开启ADC

ADC1_StartConversion();//开启连续转换

ADC1_DataBufferCmd(ENABLE);//开启缓存

}

void main( void )

{

u16value=0;

adc_init();

while(1)

{

while(!ADC1_GetFlagStatus(ADC1_FLAG_EOC));//等待转换完成

ADC1_ClearFlag(ADC1_FLAG_EOC);//软件清除

value=0;

for(u8 i=0;i<10;i++)//

{

value+=ADC1_GetBufferValue(i);//将10个缓存中的值求和

}

value=value/10;//求出ADC的平均值

}

}

注意,只有在连续转换模式下ADC_DB寄存器才能称之为缓存,此时存储的是同一个通道多次转换的值。在单次扫描和连续扫描模式下该寄存器被用来存放不同通道的转换值。

l单次扫描模式:

该模式是用来转换从AIN0到AINn之间的一连串模拟通道,‘n’是在 ADC_CSR寄存器的CH[3:0]位中指定的通道编号(即CH[3:0]里配置第n个通道,就从通道0顺序递增逐个通道进行转换,直到第n个通道结束。例如,CH[3:0]里配置为AIN4,则对AIN0、AIN1、AIN2、AIN3、AIN4进行转换,其他通道不转换)。在扫描转换的过程中,序号 CH[3:0]位的值是被硬件自动更新的,它总保存当前正在被转换的通道编号。

单次转换模式可以在在SCAN 位被置位且CONT 位以被清零时通过置位 ADON 位来启动。

注意:当使用扫描模式时,不可以将AIN0到AINn之间通道对应的I/O口设为输出状态,因为ADC的多路选择器已经将这些I/O口的输出模块禁用了。

对于单次扫描模式,转换是从AIN0通道开始的,而且结果数据被存储在数据缓冲寄存器ADC_DBxR 中(例如,CH[3:0]里配置为AIN4,则ADC_DB0R存放AIN0的转换结果,ADC_DB1R存放AIN1的转换结果,以此类推。 ),当最后一个通道(通道‘n’)被转换完成后,EOC(转换结束)标志被置位,当EOCIE 位已被置位时将产生一个中断。

可以从缓冲寄存器中读取各个通道的转换结果值。如果某个数据缓存寄存器在被读走之前被覆盖,OVR标志将置1。

在转换序列正在进行过程中不要清零SCAN位;单次扫描模式可通过清零ADON位来立即停止。为了开启一次新SCAN扫描转换,可以通过对ADC_CR1寄存器的EOC位清零和ADON位置位来实现。

示例程序:

void adc_init(void)

{

GPIO_Init(GPIOC,GPIO_PIN_4,GPIO_MODE_IN_PU_NO_IT);//AIN2IO设置为上拉输入

GPIO_Init(GPIOD,GPIO_PIN_3,GPIO_MODE_IN_PU_NO_IT);//AIN4 IO设置为上拉输入

ADC1_PrescalerConfig(ADC1_PRESSEL_FCPU_D2);//预分频2

ADC1_ExternalTriggerConfig(ADC1_EXTTRIG_TIM,DISABLE);//不使用外部触发

ADC1_SchmittTriggerConfig(ADC1_SCHMITTTRIG_CHANNEL4,DISABLE);

//禁止AIN2 AIN4的施密特触发器,降低IO静态功耗

//PD5,PD6上的通道如果施密特方式禁用会导致串口无法收发数据!

ADC1_ConversionConfig(ADC1_CONVERSIONMODE_SINGLE,//单次转换

ADC1_CHANNEL_4,//配置通道号最大的那个

ADC1_ALIGN_RIGHT);//右对齐

ADC1_Cmd(ENABLE);//开启ADC

ADC1_ScanModeCmd(ENABLE);//开启扫描模式

}

void main( void )

{

u16value1=0;

u16value2=0;

adc_init();

while(1)

{

ADC1_StartConversion();//开启一次转换

while(!ADC1_GetFlagStatus(ADC1_FLAG_EOC));//等待转换完成

ADC1_ClearFlag(ADC1_FLAG_EOC);//软件清除

value1=(u16)ADC1_GetBufferValue(ADC1_SCHMITTTRIG_CHANNEL2)//读取AIN2的值

value2=(u16)ADC1_GetBufferValue(ADC1_SCHMITTTRIG_CHANNEL4)//读取AIN4的值

}

}

l连续扫描模式:

该模式和单次扫描模式相近,只是每一次在最后通道转换完成时,一次新的从通道0到通道n扫

描转换会自动开始。如果某个数据缓存寄存器在被读走之前被覆盖,OVR标志将置1。连续扫描模式是在当SCAN位和CONT位已被置时,通过置位ADON位来启动的。在转换序列正在进行过程中不要清零SCAN位。

连续扫描模式可以通过清零ADON位来立即停止。另外一种选择就是当转换过程中清除CONT位那么转换会在下一次的最后一个通道转换完成时停止。

注意:在扫描模式(连续扫描模式)中,不要使用位操作指令(BRES)去清除EOC标志位,这是因为该指令是对整个ADC_CSR寄存器的一个读-修改-写操作。从CH[3:0]寄存器中读取当前的通道编号和写回该寄存器,将会改变扫描系列的最后通道编号。在连续扫描模式中正确的清除EOC标志位的方法是 个RAM变量中载入一个字节到ADC_CSR寄存器,这样来清除EOC标志位同时还重新载入扫描系列新的最后通道编号。

笔者实验发现,位操作指令只在连续扫描模式中会清除CH[3:0]寄存器中的值,但并不影响其他值。因此将ADC_CSR中的值读出,再将CH[3:0]中原来通道号加入进去,最后重新写入ADC_CSR中即可。写法如下:

ADC1->CSR = (uint8_t)(ADC1->CSR &(~ADC1_FLAG_EOC)|ADC1_CHANNEL_n);

注:ADC1_CHANNEL_n表示扫描到那个通道结束。

示例程序:

void adc_init(void)

{

GPIO_Init(GPIOC,GPIO_PIN_4,GPIO_MODE_IN_PU_NO_IT);//AIN2IO设置为上拉输入

GPIO_Init(GPIOD,GPIO_PIN_3,GPIO_MODE_IN_PU_NO_IT);//AIN4 IO设置为上拉输入

ADC1_PrescalerConfig(ADC1_PRESSEL_FCPU_D2);//预分频2

ADC1_ExternalTriggerConfig(ADC1_EXTTRIG_TIM,DISABLE);//不使用外部触发

ADC1_SchmittTriggerConfig(ADC1_SCHMITTTRIG_CHANNEL4,DISABLE);

//禁止AIN2 AIN4的施密特触发器,降低IO静态功耗

//PD5,PD6上的通道如果施密特方式禁用会导致串口无法收发数据!

ADC1_ConversionConfig(ADC1_CONVERSIONMODE_CONTINUOUS, //连续转换

ADC1_CHANNEL_4,//配置通道号最大的那个

ADC1_ALIGN_RIGHT);//右对齐

ADC1_Cmd(ENABLE);//开启ADC

ADC1_ScanModeCmd(ENABLE);//开启扫描模式

ADC1_StartConversion();//开启转换

}

void main( void )

{

u16value1=0;

u16value2=0;

adc_init();

while(1)

{

while(!ADC1_GetFlagStatus(ADC1_FLAG_EOC));//等待转换完成

ADC1->CSR = (uint8_t)(ADC1->CSR &(~ADC1_FLAG_EOC)|ADC1_CHANNEL_4);//软件清除

value1=(u16)ADC1_GetBufferValue(ADC1_SCHMITTTRIG_CHANNEL2)//读取AIN2的值

value2=(u16)ADC1_GetBufferValue(ADC1_SCHMITTTRIG_CHANNEL4)//读取AIN4的值

}

}

至此,STM8的ADC的5种工作模式全部介绍完毕。总结一下学习经验就是仔细对照芯片手册编写程序,然后进行仿真调试,观察寄存器中的值的变化,从中领悟手册中的意思。

Solidworks 开启 Realview

其它工具 | Posted by 老沙
1月 05 2018

Windows Registry Editor Version 5.00
; 开启 SolidWorks 2017 RealView 视图功能
; 其中GeForce GT 635M/PCIe/SSE2 为自己显卡的名称,在HKEY_CURRENT_USER\SOFTWARE\SolidWorks
\SOLIDWORKS 2017\Performance\Graphics\Hardware\Current当中可以看到
[HKEY_CURRENT_USER\SOFTWARE\SolidWorks\SOLIDWORKS 2017\Performance\Graphics\Hardware\Gl2Shaders\NV40\GeForce GT 635M/PCIe/SSE2]
“Workarounds”=dword:00040408
[HKEY_CURRENT_USER\SOFTWARE\SolidWorks\SOLIDWORKS 2017\Performance\Graphics\Hardware\Gl2Shaders\NV40\GeForce GT 635M/PCIe/SSE2\V001_FG_P614108426_R816119100]
“Workarounds”=dword:00060408

AIS-AIR 空气净化器官网 小杰SSJ

STM8, 个人的心情空间, 硬件相关 | Posted by 老沙
12月 29 2017

买了一个AIS-AIR 空气净化器

非常好用,低风量十分安静,可以睡觉用

高风量暴力,那个大风吹呀吹。。。。。

官网:

淘宝店:

https://kumouse.taobao.com/?spm=2013.1.1000126.d21.6b7f1849L7JcBE

https://item.taobao.com/item.htm?spm=a230r.7195193.1997079397.8.lhcQLr&id=562691358312&abbucket=17

新的SSD 镁光 CT275MX300SSD1

心情空间 | Posted by 老沙
12月 15 2017

openwrt 加载usb过程

LINUX | Posted by 老沙
8月 20 2017

opkg update

opkg install kmod-usb-core

opkg install kmod-usb-ohci #安装usb ohci控制器驱动
#opkg install kmod-usb-uhci  #UHCI USB控制器
opkg install kmod-usb2 #安装usb2.0
opkg install kmod-usb-storage #安装usb存储设备驱动
opkg install kmod-fs-ext3 #安装ext3分区格式支持组件
opkg install mount-utils #挂载卸载工具
opkg install ntfs-3g #挂载NTFS
opkg install kmod-fs-vfat #挂载FAT
opkg install block-mount
opkg install fdisk

opkg install usbutils #安装了这个后可以用 lsusb

挂载Swap分区
###在/mnt/sda1/下创建一个64M的交换文件
dd if=/dev/zero of=/mnt/sda1/swapfile bs=1024 count=62142
###将这个交换文件用作Swap分区
mkswap /mnt/sda1/swapfile
###启用活动分区
swapon /mnt/sda1/swapfile

###停止
swapoff /mnt/sda1/swapfile

 

openwrt 格盘

opkg update

opkg install e2fsprogs    #安装格盘软件

mkfs.ext4 /dev/sda1       #格etx4

mkfs.ext3 /dev/sda1       #格etx3

mkfs.ext2 /dev/sda1       #格etx2

 

 

挂载windows共享文件 cifs 

opkg install kmod-nls-utf8
opkg install kmod-fs-cifs

mkdir /mnt/share
mount -t cifs //192.168.1.2/tool /mnt/share -o username=administrator,password=123456,,nounix,noserverino,iocharset=utf8

 

利用NETLINK检测USB热插拔的C语言实现

LINUX C & ARM & C51 | Posted by 老沙
8月 20 2017

做嵌入式开发,尤其在网关、路由器或者其他支持USB设备的终端上,为了提高用户体验,我们常常需要支持自动识别并挂载USB设备功能。某些应用程序,在使用USB设备的过程中,也希望能够侦测到USB断开事件,不至于某些工作因为USB已经不存在而白做。在Linux下,我们主要有两种办法检测USB热插拔。
第一种便是定时检查/proc/scsi/scsi文件,该文件内会按照标准格式保存着当前设备内挂载的存储介质基本信息,如果在PC端,除了硬盘(ATA)、光驱(CD-ROM)外,就是USB设备(Direct-Access)了,轮询该scsi文件,检查文件内是否新增或减少数据便可实现自动侦测USB热插拔的效果。但是这种方法对于热插拔(hotplug)设备,如U盘,效果就没那么理想了,因为我们不知道设备什么时候插上,又是什么时候被拔掉了,只能验证当前是否已经插上或者已经拔除的事实。于是便有了另一种办法,我们采用一种特殊类的的文件描述符(套结字)专门用于Linux内核跟用户空间之间的异步通信,这种技术通常被成为NETLINK。
由于NETLINK是linux内置功能,所以使用起来很简单:创建一个AF_NETLINK协议族下NETLINK_KOBJECT_UEVENT类型的特殊文件描述符(套结字)CppLive,然后利用setsocketopt允许该文件描述符(套结字)复用其他端口,再利用band函数将自身进程绑定到特殊文件描述符(套结字)CppLive,最后利用select在while循环内监听CppLive是否可读,如果可读则调用recv接收Linux系统内核传递过来的数据并打印出来,这些输出便是USB热插拔信息。当然你也可以个性化地处理来自内核的热插拔信息,让程序变得更加智能以及人性化。

利用NETLINK检测USB热插拔的C语言实现代码如下:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <fcntl.h>
  5. #include <sys/socket.h>
  6. #include <linux/netlink.h>
  7. #define UEVENT_BUFFER_SIZE 2048
  8. int main(void)
  9. {
  10.     struct sockaddr_nl client;
  11.     struct timeval tv;
  12.     int CppLive, rcvlen, ret;
  13.     fd_set fds;
  14.     int buffersize = 1024;
  15.     CppLive = socket(AF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
  16.     memset(&client, 0, sizeof(client));
  17.     client.nl_family = AF_NETLINK;
  18.     client.nl_pid = getpid();
  19.     client.nl_groups = 1; /* receive broadcast message*/
  20.     setsockopt(CppLive, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize));
  21.     bind(CppLive, (struct sockaddr*)&client, sizeof(client));
  22.     while (1) {
  23.         char buf[UEVENT_BUFFER_SIZE] = { 0 };
  24.         FD_ZERO(&fds);
  25.         FD_SET(CppLive, &fds);
  26.         tv.tv_sec = 0;
  27.         tv.tv_usec = 100 * 1000;
  28.         ret = select(CppLive + 1, &fds, NULL, NULL, &tv);
  29.         if(ret < 0)
  30.             continue;
  31.         if(!(ret > 0 && FD_ISSET(CppLive, &fds)))
  32.             continue;
  33.         /* receive data */
  34.         rcvlen = recv(CppLive, &buf, sizeof(buf), 0);
  35.         if (rcvlen > 0) {
  36.             printf(“%s\n”, buf);
  37.             /*You can do something here to make the program more perfect!!!*/
  38.         }
  39.     }
  40.     close(CppLive);
  41.     return 0;
  42. }

运行程序,测试U盘插入/拔除,输出如下:

  1. add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1
  2. add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0
  3. add@/module/usb_storage
  4. add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6
  5. add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/scsi_host/host6
  6. add@/bus/usb/drivers/usb-storage
  7. add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0
  8. add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0
  9. add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/scsi_disk/6:0:0:0
  10. add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/scsi_device/6:0:0:0
  11. add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/scsi_generic/sg2
  12. add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/bsg/6:0:0:0
  13. change@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0
  14. add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/block/sdb
  15. add@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/block/sdb/sdb4
  16. add@/devices/virtual/bdi/8:16
  17. add@/module/fat
  18. add@/kernel/slab/fat_cache
  19. add@/kernel/slab/fat_inode_cache
  20. add@/module/vfat
  21. add@/module/nls_cp437
  22. add@/module/nls_iso8859_1
  23. remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/bsg/6:0:0:0
  24. remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/scsi_generic/sg2
  25. remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/scsi_device/6:0:0:0
  26. remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/scsi_disk/6:0:0:0
  27. remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/block/sdb/sdb4
  28. remove@/devices/virtual/bdi/8:16
  29. remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0/block/sdb
  30. remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/target6:0:0/6:0:0:0
  31. remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6/scsi_host/host6
  32. remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0/host6
  33. remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1/2-1:1.0
  34. remove@/devices/pci0000:00/0000:00:1d.7/usb2/2-1
  35. remove@/host6/target6:0:0