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 z1,定时检查/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# E2,netlink方式
; n* [+ H7 t% k5 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, Qstatic 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- {+ m3 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/ A3,使用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