EDA365电子论坛网
标题:
怎样在Linux环境下实现USB口的热插拔
[打印本页]
作者:
haidaowang
时间:
2019-11-11 11:19
标题:
怎样在Linux环境下实现USB口的热插拔
3 n* E, ?3 d6 e& ]
目前要做一个在嵌入式平台上的USB口的热插拔事件。
& K5 F- y# p" \: X' `' k
$ N: Z J9 U# a: H
经过我现在的分析总结目前有如下方法:
. U& \2 ~- `( ^2 ]: d* C2 K h
% x, u! q: f$ y. n; M( m2 z
1,定时检查/proc/scsi/scsi文件
0 L3 N1 R* z3 T7 Q3 k! ~
" H J& G/ f* R& t! B# y. H% t
此方法只能在PC上,但在嵌入式平台上不可用。
) i% \( m- F! y! V9 r
2 l, r1 ~+ ^" l$ x# E
2,netlink方式
; n* [+ H7 t% k
5 Q3 g% h- w7 V' o$ C- s4 X1 y
使用netlink.
. }' J3 m ]" M' h; @
; ?4 D% v2 K& h+ f
#include <stdio.h>
# |& S$ N& N- W7 O( N" ^
#include <stdlib.h>
0 R+ M; r0 C, ~( M/ B
#include <string.h>
# @2 e( S. D" G$ M( r
#include <ctype.h>
% }2 X, ~* h8 e. B0 ?( A
#include <sys/un.h>
/ l' C6 G5 h) q7 y* P9 N
#include <sys/ioctl.h>
3 B$ c0 H, u* w% L/ r# T+ a& d
#include <sys/socket.h>
8 U/ a" g p( @& Q( _
#include <linux/types.h>
7 N" Y& o( Z, B8 V6 n
#include <linux/netlink.h>
3 ]1 l1 X( i9 y: w) C) q) J
#include <errno.h>
2 D1 F3 r3 Y% I4 o
#include <unistd.h>
9 R% R- \& z. N# X
#include <arpa/inet.h>
0 s: [$ L% Q4 K/ S. L2 [/ _/ B) J
#include <netinet/in.h>
! ^4 ]" {- j V9 ]; `$ {6 x
- `. [4 d3 b( {8 t
#define UEVENT_BUFFER_SIZE 2048
$ ?) k0 U8 S) @* J8 K% r
/ F# Q& u, u' ?) D% G* g" Z, Q
static int init_hotplug_sock()
% Z E/ Z* V* |' s R* F
{
. I- M, z9 V( E# A' K H
const int buffersize = 1024;
7 K& d% q, F8 B, Y( U* i
int ret;
/ r/ A' b9 ~/ h, C( t
% Q3 M" C# m. M* f5 a1 j ~
struct sockaddr_nl snl;
! K3 p$ q* R: \1 c! [
bzero(&snl, sizeof(struct sockaddr_nl));
: d. Z7 o% Q7 {/ H
snl.nl_family = AF_NETLINK;
_/ U7 M/ ?3 X0 E
snl.nl_pid = getpid();
# _; V$ ?1 e- P! k9 h
snl.nl_groups = 1;
; g7 {) \' k5 Q1 j4 o; z) P
8 @/ m" X' J; D- H5 n2 R3 b- ]
int s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
& a5 V* h# g5 n2 F
if (s == -1)
0 G% [* f+ |: d7 ~6 X
{
3 Y, X2 F8 H- D0 y# |+ m/ z) J7 F
perror("socket");
& m! p' u- ?; R; V0 d
return -1;
" T% k- k& E/ i* s6 p
}
- k' [+ q t! V, N& s
setsockopt(s, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize));
7 c$ Z8 s* J5 v! e
" x( a; V- d6 v+ E
ret = bind(s, (struct sockaddr *)&snl, sizeof(struct sockaddr_nl));
5 a- T$ b- I0 y$ \! G
if (ret < 0)
( K: _, ~- t& w% l( s
{
. d/ ?% V% b& B3 g2 R
perror("bind");
) g; k/ I" ^. K
close(s);
% K6 s0 }, z$ n1 u5 x
return -1;
- }2 V- M- c, n1 A) Y: ~
}
, A* T; q* i- {+ m
3 W! V7 N4 g1 L- C- N
return s;
/ C; z, a5 }3 o6 H3 N
}
1 ^( |- Q5 m7 A+ D
; u* {; s" P& `* ~ }
int main(int argc, char* argv[])
6 B( ]3 l! X3 E" }' k7 P, e3 l- }4 G( v
{
- }6 h* l6 F, v9 v6 S
int hotplug_sock = init_hotplug_sock();
$ V4 s3 b2 q' V/ a, ~) \( P5 j" u
& C* V; Q2 x( [5 p0 p, k
while(1)
- F/ `0 w0 R: x, V
{
7 s, d! i* _0 r$ P7 Y! |+ q/ j
/* Netlink message buffer */
& e9 V1 p8 a7 C: @
char buf[UEVENT_BUFFER_SIZE * 2] = {0};
( S+ Q9 A* K) Q9 u
recv(hotplug_sock, &buf, sizeof(buf), 0);
! a+ S" O0 d: t5 y1 w& [2 y+ ]
printf("%s\n", buf);
0 V1 n. p5 b3 E @5 e! S8 k
5 ?; ~$ d) s; e+ b5 Y7 T9 D
/* USB 设备的插拔会出现字符信息,通过比较不同的信息确定特定设备的插拔,在这添加比较代码 */
8 z4 u8 r& i- A8 b( s% T
}
) L9 r n9 T# G, T5 T5 Q+ n
return 0;
6 [: q: Z$ T" r5 Z+ H6 r
, Q) L; l3 H: [7 R8 w
}
& W* _7 p; ^3 [1 Z
0 ^" V4 U5 \" t2 t6 l' h) H4 _
经过测试发现只能实现插与拔,但是无法具体到具体是什么设备。
0 f- _$ O" Y+ S8 |! p% f# o) l
6 P# O$ {" a/ r, B) K$ M/ A
3,使用mdev。
9 b0 M/ \2 s( a% @' T) u
9 b% L$ Q" a$ }& c- W% F2 B U
此方法相当麻烦,现在在研究中。
: D% {, u" G2 e( A
' W% ]) [& A1 Y9 Q. F$ _
4,使用最原始的解析文件方式
( ?; w$ e. T$ f8 s7 s: S1 |- q
. g _/ o6 K% Y0 G
此方法相当麻烦,生成很多文件。
: ]+ D& `8 I& C1 }
" I6 b. J# s% S3 ]1 _) {
就是用cat /proc/bus/usb/devices的信息生成的文件进行解析。
/ k" R8 A4 c' ~' S3 [0 ^
" `- u0 n8 S& e l
目前我已经完成此功能。虽然能用,但是效率太低。
作者:
Demyar
时间:
2019-11-21 13:38
看看楼主说的方法。
欢迎光临 EDA365电子论坛网 (https://bbs.eda365.com/)
Powered by Discuz! X3.2