现在的位置: 首页 > 综合 > 正文

Linux remote USB device detection

2013年06月12日 ⁄ 综合 ⁄ 共 8896字 ⁄ 字号 评论关闭

Program flow:

 

Server code:

  1. /*
  2.  * usbdetect_server.c
  3.  *
  4.  * Copyright (C) 2008 Breathomn <breathomn@sohu.com>
  5.  *
  6.  */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <ctype.h>
  11. #include <sys/un.h>
  12. #include <sys/ioctl.h>
  13. #include <sys/socket.h>
  14. #include <linux/types.h>
  15. #include <linux/netlink.h>
  16. #include <errno.h>
  17. #include <unistd.h>
  18. #include <arpa/inet.h>
  19. #include <netinet/in.h>
  20. #define UEVENT_BUFFER_SIZE 2048
  21. #define PORT 9606
  22. static char adstr[41] = "add@/devices/pci0000:00/";
  23. static char rmstr[44] = "remove@/devices/pci0000:00/";
  24. /* command array */
  25. char cmd[40];
  26. /* communication package */
  27. typedef struct bus_msg
  28. {
  29.     char msgtype;
  30.     char busname[4];
  31. } BUS_MSG;
  32. static int init_hotplug_sock()
  33. {
  34.     const int buffersize = 1024;
  35.     int ret;
  36.     struct sockaddr_nl snl;
  37.     bzero(&snl, sizeof(struct sockaddr_nl));
  38.     snl.nl_family = AF_NETLINK;
  39.     snl.nl_pid = getpid();
  40.     snl.nl_groups = 1;
  41.     int s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
  42.     if (s == -1) 
  43.     {
  44.         perror("socket");
  45.         return -1;
  46.     }
  47.     setsockopt(s, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize));
  48.     ret = bind(s, (struct sockaddr *)&snl, sizeof(struct sockaddr_nl));
  49.     if (ret < 0) 
  50.     {
  51.         perror("bind");
  52.         close(s);
  53.         return -1;
  54.     }
  55.     return s;
  56. }
  57. char* get_busname(char* buf)
  58. {
  59.     int len = strlen(buf);
  60.     char *current = buf + len - 1;
  61.     while(*(current - 1) != '/') current--;
  62.     return current;
  63. }
  64. static int send_buf(struct in_addr destip, char *buf, int len)
  65. {
  66.     struct sockaddr_in si_other;
  67.     int s, ret;
  68.     if ((s = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
  69.         perror ("socket");
  70.     memset ((char *) &si_other, sizeof (si_other), 0);
  71.     si_other.sin_family = AF_INET;
  72.     si_other.sin_port = htons (PORT);
  73.     si_other.sin_addr.s_addr = destip.s_addr;
  74.     ret = sendto (s, buf, len, 0, (struct sockaddr *) &si_other, sizeof (si_other));
  75.     if (ret == -1)
  76.         perror ("sendto() error");
  77.     else if (ret != len)
  78.         perror ("sendapmsg UDP message not complete!");
  79.     else
  80.     {
  81.         printf ("send a udp message to %s/n", inet_ntoa (destip));
  82.     }
  83.     close (s);
  84.     return 1;
  85. }
  86. int main(int argc, char* argv[])
  87. {
  88.     /* Two switch specified for filtering the same adstr & rmstr */
  89.     unsigned char insertflag = 0x00;
  90.     unsigned char removeflag = 0x00;
  91.     int hotplug_sock = init_hotplug_sock();
  92.     while(1)
  93.     {
  94.         /* Netlink message buffer */
  95.         char buf[UEVENT_BUFFER_SIZE * 2] = {0};
  96.         int adeql = 0, rmeql = 0, recvlen = 0;
  97.         int buflen;
  98.         int i;
  99.         /* sendbuf specified for sending busname to the other end */
  100.         char *sendbuf;
  101.         BUS_MSG *bus_msg;
  102.         int sendbuf_len;
  103.         /* Allocate a send buffer and put it zero */
  104.         sendbuf_len = sizeof(struct bus_msg);
  105.         sendbuf = (char *)malloc(sendbuf_len);
  106.         bzero (sendbuf, sendbuf_len);
  107.         bus_msg = (BUS_MSG*)sendbuf;
  108.         recv(hotplug_sock, &buf, sizeof(buf), 0);
  109. //      printf("%s/n", buf);
  110.         buflen = strlen(buf);
  111.         /* Match plugged string */
  112.         adeql = memcmp(buf, adstr, strlen(adstr));
  113.         /* Match unplugged string */
  114.         rmeql = memcmp(buf, rmstr, strlen(rmstr));
  115.         /* Any device plugged into server, notify client */
  116.         if (adeql == 0)
  117.         {
  118.             insertflag = ~insertflag;
  119.             if (insertflag == 0xff)
  120.             {
  121.                 printf("Device plugged!/n");
  122.                 bus_msg->msgtype = '1';
  123.                 char* str = get_busname(buf);
  124.                 sprintf(cmd, "bind_usbip ");
  125.                 strcat(cmd, str);
  126.                 system(cmd);
  127.                 strncpy(bus_msg->busname, str, 3);
  128.                 struct in_addr destip;
  129.                 inet_aton ("127.0.0.1", &destip);
  130.                 send_buf (destip, sendbuf, sendbuf_len);
  131.                 printf("********************************/n");
  132.             }
  133.         }
  134.         /* Any device unplugged from server, notify client */
  135.         if (rmeql == 0)
  136.         {
  137.             removeflag = ~removeflag;
  138.             if (removeflag == 0x00)
  139.             {
  140.                 printf("Device unplugged!/n");
  141.                 bus_msg->msgtype = '0';
  142.                 char* str = get_busname(buf);
  143.                 sprintf(cmd, "unbind_usbip ");
  144.                 strcat(cmd, str);
  145.                 system(cmd);
  146.                 strncpy(bus_msg->busname, str, 3);
  147.                 struct in_addr destip;
  148.                 inet_aton ("127.0.0.1", &destip);
  149.                 send_buf (destip, sendbuf, sendbuf_len);
  150.                 printf("********************************/n");
  151.             }
  152.         }
  153.         free(sendbuf);
  154.     }
  155.     return 0;
  156. }

Client code:

  1. /*
  2.  * usbdetect_client.c
  3.  *
  4.  * Copyright (C) 2008 Breathomn <breathomn@sohu.com>
  5.  *
  6.  */
  7. #include <arpa/inet.h>
  8. #include <netinet/in.h>
  9. #include <stdlib.h>
  10. #include <stdio.h>
  11. #include <sys/types.h>
  12. #include <sys/socket.h>
  13. #include <unistd.h>
  14. #include <sys/time.h>
  15. #include <sys/select.h>
  16. #include <string.h>
  17. #include <errno.h>
  18. #define PORT 9606
  19. #define RECVBUFLEN 5
  20. typedef struct bus_msg
  21. {
  22.     char msgtype;
  23.     char busname[4];
  24. } BUS_MSG;
  25. typedef struct device_table
  26. {
  27.     u_int8_t portnum;
  28.     char busname[4];
  29. } DEVICE_TABLE;
  30. DEVICE_TABLE local_table[8];
  31. static void init_table()
  32. {
  33.     int i;
  34.     for (i = 0; i < 8; i++)
  35.         local_table[i].portnum = 9;
  36. }
  37. static int add_to_table(BUS_MSG *bus_msg)
  38. {
  39.     int i;
  40.     for (i = 0; i < 8; i++)
  41.     {
  42.         if (local_table[i].portnum == 9)
  43.         {
  44.             local_table[i].portnum = i;
  45.             strcpy(local_table[i].busname, bus_msg->busname);
  46.             return 0;
  47.         }
  48.     }
  49.     return -1;
  50.     
  51. }
  52. static int del_from_table(BUS_MSG *bus_msg)
  53. {
  54.     int i;
  55.     for (i = 0; i < 8; i++)
  56.     {
  57.         if (strcmp(local_table[i].busname, bus_msg->busname) == 0)
  58.         {
  59.             local_table[i].portnum = 9;
  60.             strcpy(local_table[i].busname, "");
  61.             return i;
  62.         }
  63.     }
  64.     return -1;
  65. }
  66. static int get_port_from_table(BUS_MSG *bus_msg)
  67. {
  68.     int i;
  69.     for (i = 0; i < 8; i++)
  70.     {
  71.         if (strcmp(local_table[i].busname, bus_msg->busname) == 0)
  72.         {
  73.             return (int)local_table[i].portnum;
  74.         }
  75.     }
  76.     return -1;
  77. }
  78. static void print_table()
  79. {
  80.     int i;
  81.     printf("******************** Local Table ***************************/n");
  82.     for (i = 0; i < 8; i++)
  83.         printf("%d/t%s/n", local_table[i].portnum, local_table[i].busname);
  84.     printf("************************************************************/n");
  85. }
  86. int main()
  87. {
  88.     struct sockaddr_in si_me, si_other;
  89.     int s;
  90.     socklen_t slen = sizeof(si_other), ret;
  91.     char buf[RECVBUFLEN];
  92.     char cmd[40];
  93.     int tableret;
  94.     fd_set readsock;
  95.     BUS_MSG *bus_msg;
  96.     init_table();
  97.     print_table();
  98.     /* Initialize the socket to recv messages */
  99.     if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
  100.         perror ("socket");
  101.     memset ((char *)&si_me, 0, sizeof(si_me));
  102.     si_me.sin_family = AF_INET;
  103.     si_me.sin_port = htons (PORT);
  104.     si_me.sin_addr.s_addr = htonl (INADDR_ANY);
  105.     if (bind (s, (struct sockaddr *)&si_me, sizeof (si_me)) == -1)
  106.         perror("bind");
  107.     while (1)
  108.     {
  109.         memset(buf, 0, sizeof(buf));
  110.         FD_ZERO(&readsock);
  111.         FD_SET(s, &readsock);
  112.         ret = select(FD_SETSIZE, &readsock, NULL, NULL, NULL);
  113.         if (ret == -1)
  114.             perror("error in select() at main loop");
  115.         if (ret > 0)
  116.         {
  117.             if (FD_ISSET(s, &readsock))
  118.             {
  119.                 if (recvfrom(s, buf, RECVBUFLEN, 0, (struct sockaddr *)&si_other, &slen) == -1)
  120.                     perror("recvfrom()");
  121.                 bus_msg = (BUS_MSG*)buf;
  122.                 /* Any device plugged into server */
  123.                 if (bus_msg->msgtype == '1')
  124.                 {
  125.                     tableret = add_to_table(bus_msg);
  126.                     if (tableret != 0)
  127.                     {
  128.                         printf("No hub any more./n");
  129.                         return -1;
  130.                     }
  131.                     print_table();
  132.                     printf("Received a bus (%s) from %s/n", bus_msg->busname, inet_ntoa(si_other.sin_addr));
  133.                     sprintf(cmd, "usbip_attach ");
  134.                     strcat(cmd, inet_ntoa(si_other.sin_addr));
  135.                     strcat(cmd, " ");
  136.                     strcat(cmd, bus_msg->busname);
  137.                     system(cmd);
  138.                 }
  139.                 /* Any device unplugged from server */
  140.                 if (bus_msg->msgtype == '0')
  141.                 {
  142.                     char str[2];
  143.                     tableret = del_from_table(bus_msg);
  144.                     if (tableret == -1)
  145.                     {
  146.                         printf("Device not found./n");
  147.                         return -1;
  148.                     }
  149.                     print_table();
  150.                     printf("Received a bus (%s) from %s/n", bus_msg->busname, inet_ntoa(si_other.sin_addr));
  151.                     sprintf(cmd, "usbip_detach ");
  152.                     sprintf(str, "%d", tableret);
  153.                     strcat(cmd, str);
  154.                     system(cmd);
  155.                 }
  156.             }
  157.         }
  158.     }
  159.     close(s);
  160. }

 

抱歉!评论已关闭.