Linux下达成USB口的热插拔

2019-10-23 22:10 来源:未知

当下要做八个在嵌入式平台上的USB口的热插拔事件。

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <linux/netlink.h>

经过自家明天的分析总括近期有如下方法:

// netlink.h 中定义
//struct sockaddr_nl
//{
// sa_family_t     nl_family;   // AF_NETLINK
// unsigned short nl_pad;      // zero
// __u32       nl_pid;       // 进程ID
//    __u32       nl_groups; // 多播组掩码
//};
//

1,准时检查/proc/scsi/scsi文件

static int
monitoring_usb_device( void )
{
    // 本函数重临值
    int iResult = 0;
    // 接纳内核发来的音讯字符串
    char caKernelMsgBuff[1024];
    // 选用内核发来的新闻缓冲区大小
    const unsigned int uiRecvBuffSize = sizeof( caKernelMsgBuff );
    // 套接字地址
    struct sockaddr_nl snl;
    // 套接字文件呈报符
    int sfd = -1;

此办法只可以在PC上,但在嵌入式平台上不可用。

    do // 非循环,只是为了减少分支嵌套
    {
        // 1.添写套接字地址
        snl.nl_family = AF_NETLINK;
        snl.nl_pad = 0;
        // 假使希望内核管理新闻或多播信息,就把该字段设置为 0,
        // 不然设置为管理音讯的长河ID。
        snl.nl_pid = getpid();
        snl.nl_groups = 1;

2,netlink方式

        // 2.创办套接字
        // NETLINK_KOBJECT_UEVENT - 内核新闻到顾客空间,出未来 Linux 2.6.10
        sfd = socket( PF_NETLINK, // 使用 netlink
                      SOCK_DGRAM, // 使用不总是离谱赖的数量包连接
                      NETLINK_KOBJECT_UEVENT );
        // 若是 制造套接字失利 的话,则
        if ( -1 == sfd )
        {
            iResult = -1;
            break;
        }

使用netlink.

        // 3.设置套接字选拔缓冲区大小
        setsockopt( sfd,
                    SOL_SOCKET, // 存取 socket 层
                    SO_RCVBUF,  // 设置选取缓冲区大小
                    &uiRecvBuffSize,
                    sizeof( uiRecvBuffSize ) );

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/un.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/types.h>
#include <linux/netlink.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>

        // 4.将套接字到场钦赐的多播组
        iResult = bind( sfd,
                        (struct sockaddr*)&snl,
                        sizeof( snl ) );
        // 假使 将套接字到场钦赐的多播组战败 的话,则
        if ( -1 == iResult )
        {
            return -2;
            break;
        }

#define UEVENT_BUFFER_SIZE 2048

        while( 1 )
        {
            // 选用内核新闻
            recv( sfd,
                  &caKernelMsgBuff,
                  sizeof( caKernelMsgBuff ),
                  0 );

static int init_hotplug_sock()
{
  const int buffersize = 1024;
  int ret;

            printf( "Kernel Message:n%sn", caKernelMsgBuff );

  struct sockaddr_nl snl;
  bzero(&snl, sizeof(struct sockaddr_nl));
  snl.nl_family = AF_NETLINK;
  snl.nl_pid = getpid();
  snl.nl_groups = 1;

            // USB 设备的插入时,会冷俊不禁以 add@/devices/ 开始,含 usb 的字符串
            if( 0 == memcmp( caKernelMsgBuff,
                             "add@",
                             4 )
                &&
                NULL != strstr( caKernelMsgBuff,
                                "usb" ) )
            {
                printf( "Add USB Devicen" );
                break;
            }

  int s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
  if (s == -1)
  {
        perror("socket");
        return -1;
  }
  setsockopt(s, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize));

            // USB 设备的消亡时,会产出以 remove@/devices/ 开端,含 usb 的字符串
            if( 0 == memcmp( caKernelMsgBuff,
                             "remove@",
                             7 )
                &&
                NULL != strstr( caKernelMsgBuff,
                                "usb" ) )
            {
                printf( "Remove USB Devicen" );
                break;
            }
        }

  ret = bind(s, (struct sockaddr *)&snl, sizeof(struct sockaddr_nl));
  if (ret < 0)
  {
        perror("bind");
        close(s);
        return -1;
  }

        // 等豆蔻梢头秒钟,让设备加载完成
        sleep(1);

  return s;
}

    }while( 0 );

int main(int argc, char* argv[])
{
  int hotplug_sock = init_hotplug_sock();

    // 要是 创立套接字成功 的话,则
    if ( -1 != sfd )
    {
        // 关闭套接字
        close( sfd );
        sfd = -1;
    }

  while(1)
  {
      /* Netlink message buffer */
      char buf[UEVENT_BUFFER_SIZE * 2] = {0};
      recv(hotplug_sock, &buf, sizeof(buf), 0);
      printf("%sn", buf);

    return iResult;
}

     /* USB 设备的插拔会冒出字符消息,通过相比不相同的音讯鲜明特定设备的插拔,在此增多相比代码 */
  }
  return 0;

int main(int argc, char* argv[])
{
    printf( "monitoring_usb_device return %dn",
            monitoring_usb_device() );

}

    return 0;
 
}

通过测验发掘只好促成插与拔,不过爱莫能助实际到现实是哪些设备。

图片 1

3,使用mdev。

此办法极其费劲,现在在研究中。

4,使用最原始的分析文件格局

此格局相当费劲,生成相当多文本。

尽管用cat /proc/bus/usb/devices的音信更动的公文进行分析。

脚下本人早就成功此功用。即便能用,不过作用太低。

图片 2

TAG标签:
版权声明:本文由990888藏宝阁发布于网络应用,转载请注明出处:Linux下达成USB口的热插拔