Program flow:
Server code:
- /*
- * usbdetect_server.c
- *
- * Copyright (C) 2008 Breathomn <breathomn@sohu.com>
- *
- */
- #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>
- #define UEVENT_BUFFER_SIZE 2048
- #define PORT 9606
- static char adstr[41] = "add@/devices/pci0000:00/";
- static char rmstr[44] = "remove@/devices/pci0000:00/";
- /* command array */
- char cmd[40];
- /* communication package */
- typedef struct bus_msg
- {
- char msgtype;
- char busname[4];
- } BUS_MSG;
- static int init_hotplug_sock()
- {
- const int buffersize = 1024;
- int ret;
- struct sockaddr_nl snl;
- bzero(&snl, sizeof(struct sockaddr_nl));
- snl.nl_family = AF_NETLINK;
- snl.nl_pid = getpid();
- snl.nl_groups = 1;
- 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));
- ret = bind(s, (struct sockaddr *)&snl, sizeof(struct sockaddr_nl));
- if (ret < 0)
- {
- perror("bind");
- close(s);
- return -1;
- }
- return s;
- }
- char* get_busname(char* buf)
- {
- int len = strlen(buf);
- char *current = buf + len - 1;
- while(*(current - 1) != '/') current--;
- return current;
- }
- static int send_buf(struct in_addr destip, char *buf, int len)
- {
- struct sockaddr_in si_other;
- int s, ret;
- if ((s = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
- perror ("socket");
- memset ((char *) &si_other, sizeof (si_other), 0);
- si_other.sin_family = AF_INET;
- si_other.sin_port = htons (PORT);
- si_other.sin_addr.s_addr = destip.s_addr;
- ret = sendto (s, buf, len, 0, (struct sockaddr *) &si_other, sizeof (si_other));
- if (ret == -1)
- perror ("sendto() error");
- else if (ret != len)
- perror ("sendapmsg UDP message not complete!");
- else
- {
- printf ("send a udp message to %s/n", inet_ntoa (destip));
- }
- close (s);
- return 1;
- }
- int main(int argc, char* argv[])
- {
- /* Two switch specified for filtering the same adstr & rmstr */
- unsigned char insertflag = 0x00;
- unsigned char removeflag = 0x00;
- int hotplug_sock = init_hotplug_sock();
- while(1)
- {
- /* Netlink message buffer */
- char buf[UEVENT_BUFFER_SIZE * 2] = {0};
- int adeql = 0, rmeql = 0, recvlen = 0;
- int buflen;
- int i;
- /* sendbuf specified for sending busname to the other end */
- char *sendbuf;
- BUS_MSG *bus_msg;
- int sendbuf_len;
- /* Allocate a send buffer and put it zero */
- sendbuf_len = sizeof(struct bus_msg);
- sendbuf = (char *)malloc(sendbuf_len);
- bzero (sendbuf, sendbuf_len);
- bus_msg = (BUS_MSG*)sendbuf;
- recv(hotplug_sock, &buf, sizeof(buf), 0);
- // printf("%s/n", buf);
- buflen = strlen(buf);
- /* Match plugged string */
- adeql = memcmp(buf, adstr, strlen(adstr));
- /* Match unplugged string */
- rmeql = memcmp(buf, rmstr, strlen(rmstr));
- /* Any device plugged into server, notify client */
- if (adeql == 0)
- {
- insertflag = ~insertflag;
- if (insertflag == 0xff)
- {
- printf("Device plugged!/n");
- bus_msg->msgtype = '1';
- char* str = get_busname(buf);
- sprintf(cmd, "bind_usbip ");
- strcat(cmd, str);
- system(cmd);
- strncpy(bus_msg->busname, str, 3);
- struct in_addr destip;
- inet_aton ("127.0.0.1", &destip);
- send_buf (destip, sendbuf, sendbuf_len);
- printf("********************************/n");
- }
- }
- /* Any device unplugged from server, notify client */
- if (rmeql == 0)
- {
- removeflag = ~removeflag;
- if (removeflag == 0x00)
- {
- printf("Device unplugged!/n");
- bus_msg->msgtype = '0';
- char* str = get_busname(buf);
- sprintf(cmd, "unbind_usbip ");
- strcat(cmd, str);
- system(cmd);
- strncpy(bus_msg->busname, str, 3);
- struct in_addr destip;
- inet_aton ("127.0.0.1", &destip);
- send_buf (destip, sendbuf, sendbuf_len);
- printf("********************************/n");
- }
- }
- free(sendbuf);
- }
- return 0;
- }
Client code:
- /*
- * usbdetect_client.c
- *
- * Copyright (C) 2008 Breathomn <breathomn@sohu.com>
- *
- */
- #include <arpa/inet.h>
- #include <netinet/in.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <unistd.h>
- #include <sys/time.h>
- #include <sys/select.h>
- #include <string.h>
- #include <errno.h>
- #define PORT 9606
- #define RECVBUFLEN 5
- typedef struct bus_msg
- {
- char msgtype;
- char busname[4];
- } BUS_MSG;
- typedef struct device_table
- {
- u_int8_t portnum;
- char busname[4];
- } DEVICE_TABLE;
- DEVICE_TABLE local_table[8];
- static void init_table()
- {
- int i;
- for (i = 0; i < 8; i++)
- local_table[i].portnum = 9;
- }
- static int add_to_table(BUS_MSG *bus_msg)
- {
- int i;
- for (i = 0; i < 8; i++)
- {
- if (local_table[i].portnum == 9)
- {
- local_table[i].portnum = i;
- strcpy(local_table[i].busname, bus_msg->busname);
- return 0;
- }
- }
- return -1;
- }
- static int del_from_table(BUS_MSG *bus_msg)
- {
- int i;
- for (i = 0; i < 8; i++)
- {
- if (strcmp(local_table[i].busname, bus_msg->busname) == 0)
- {
- local_table[i].portnum = 9;
- strcpy(local_table[i].busname, "");
- return i;
- }
- }
- return -1;
- }
- static int get_port_from_table(BUS_MSG *bus_msg)
- {
- int i;
- for (i = 0; i < 8; i++)
- {
- if (strcmp(local_table[i].busname, bus_msg->busname) == 0)
- {
- return (int)local_table[i].portnum;
- }
- }
- return -1;
- }
- static void print_table()
- {
- int i;
- printf("******************** Local Table ***************************/n");
- for (i = 0; i < 8; i++)
- printf("%d/t%s/n", local_table[i].portnum, local_table[i].busname);
- printf("************************************************************/n");
- }
- int main()
- {
- struct sockaddr_in si_me, si_other;
- int s;
- socklen_t slen = sizeof(si_other), ret;
- char buf[RECVBUFLEN];
- char cmd[40];
- int tableret;
- fd_set readsock;
- BUS_MSG *bus_msg;
- init_table();
- print_table();
- /* Initialize the socket to recv messages */
- if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
- perror ("socket");
- memset ((char *)&si_me, 0, sizeof(si_me));
- si_me.sin_family = AF_INET;
- si_me.sin_port = htons (PORT);
- si_me.sin_addr.s_addr = htonl (INADDR_ANY);
- if (bind (s, (struct sockaddr *)&si_me, sizeof (si_me)) == -1)
- perror("bind");
- while (1)
- {
- memset(buf, 0, sizeof(buf));
- FD_ZERO(&readsock);
- FD_SET(s, &readsock);
- ret = select(FD_SETSIZE, &readsock, NULL, NULL, NULL);
- if (ret == -1)
- perror("error in select() at main loop");
- if (ret > 0)
- {
- if (FD_ISSET(s, &readsock))
- {
- if (recvfrom(s, buf, RECVBUFLEN, 0, (struct sockaddr *)&si_other, &slen) == -1)
- perror("recvfrom()");
- bus_msg = (BUS_MSG*)buf;
- /* Any device plugged into server */
- if (bus_msg->msgtype == '1')
- {
- tableret = add_to_table(bus_msg);
- if (tableret != 0)
- {
- printf("No hub any more./n");
- return -1;
- }
- print_table();
- printf("Received a bus (%s) from %s/n", bus_msg->busname, inet_ntoa(si_other.sin_addr));
- sprintf(cmd, "usbip_attach ");
- strcat(cmd, inet_ntoa(si_other.sin_addr));
- strcat(cmd, " ");
- strcat(cmd, bus_msg->busname);
- system(cmd);
- }
- /* Any device unplugged from server */
- if (bus_msg->msgtype == '0')
- {
- char str[2];
- tableret = del_from_table(bus_msg);
- if (tableret == -1)
- {
- printf("Device not found./n");
- return -1;
- }
- print_table();
- printf("Received a bus (%s) from %s/n", bus_msg->busname, inet_ntoa(si_other.sin_addr));
- sprintf(cmd, "usbip_detach ");
- sprintf(str, "%d", tableret);
- strcat(cmd, str);
- system(cmd);
- }
- }
- }
- }
- close(s);
- }