2e179c93d9445a7f33c05b58deac1b431ae637b4
[gnuk/gnuk.git] / emulation / usbip-server.c
1 /*
2  * usbip-server.c - USB Device Emulation by USBIP Protocol
3  *
4  * Copyright (C) 2017  Flying Stone Technology
5  * Author: NIIBE Yutaka <gniibe@fsij.org>
6  *
7  * This file is a part of Chopstx, a thread library for embedded.
8  *
9  * Chopstx is free software: you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * Chopstx is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include <unistd.h>
25
26 #include <stdint.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include <arpa/inet.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
34
35 #define USBIP_PORT 3240
36
37 #define CMD_REQ_LIST   0x01008005
38 #define CMD_REQ_ATTACH 0x01008003
39 #define CMD_URB        0x00000001
40 #define CMD_DETACH     0x00000002
41
42 struct usbip_msg_head {
43   uint32_t cmd;
44   uint32_t seq;
45 };
46
47 static char *
48 list_devices (size_t *len_p)
49 {
50   *len_p = 0;
51   return NULL;
52 }
53
54 static char *
55 attach_device (char busid[32], size_t *len_p)
56 {
57   *len_p = 0;
58   return NULL;
59 }
60
61 static int
62 handle_urb (int fd)
63 {
64   return 0;
65 }
66
67
68
69 void
70 run_server (void)
71 {
72   int sock;
73   struct sockaddr_in v4addr;
74   const int one = 1;
75
76   if ((sock = socket (PF_INET, SOCK_STREAM, 0)) < 0)
77     {
78       perror ("socket");
79       exit (1);
80     }
81
82   if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
83                   (const char*)&one, sizeof (int)) < 0)
84     perror ("WARN: setsockopt");
85
86   memset (&v4addr, 0, sizeof (v4addr));
87   v4addr.sin_family = AF_INET;
88   v4addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
89   v4addr.sin_port = htons (USBIP_PORT);
90
91   if (bind (sock, (const struct sockaddr *)&v4addr, sizeof (v4addr)) < 0)
92     {
93       perror ("bind");
94       exit (1);
95     }
96
97   /* We only accept a connection from a single client.  */
98   if (listen (sock, 1) < 0)
99     {
100       perror ("listen");
101       exit (1);
102     }
103
104   for (;;)
105     {
106       int fd;
107       int attached = 0;
108
109       /* We don't care who is connecting.  */
110       if ((fd = accept (sock, NULL, NULL)) < 0)
111         {
112           perror ("accept");
113           exit (1);
114         }
115
116       for (;;)
117         {
118           struct usbip_msg_head msg;
119
120           if (recv (fd, (char *)&msg, sizeof (msg), 0) != sizeof (msg))
121             {
122               perror ("msg recv");
123               break;
124             }
125
126           msg.cmd = ntohl (msg.cmd);
127           msg.seq = ntohl (msg.seq);
128
129           if (msg.cmd == CMD_REQ_LIST)
130             {
131               char *device_list;
132               size_t device_list_size;
133
134               if (attached)
135                 {
136                   fprintf (stderr, "REQ list while attached\n");
137                   break;
138                 }
139
140               device_list = list_devices (&device_list_size);
141
142               if (send (fd, device_list, device_list_size, 0) != device_list_size)
143                 {
144                   perror ("list send");
145                   break;
146                 }
147
148               free (device_list);
149             }
150           else if (msg.cmd == CMD_REQ_ATTACH)
151             {
152               char busid[32];
153               char *attach;
154               size_t attach_size;
155
156               if (attached)
157                 {
158                   fprintf (stderr, "REQ attach while attached\n");
159                   break;
160                 }
161               
162               if (recv (fd, busid, 32, 0) != 32)
163                 {
164                   perror ("attach recv");
165                   break;
166                 }
167
168               attach = attach_device (busid, &attach_size);
169               if (send (fd, attach, attach_size, 0) != attach_size)
170                 {
171                   perror ("list send");
172                   break;
173                 }
174
175               free (attach);
176               attached = 1;
177             }
178           else if (msg.cmd == CMD_URB)
179             {
180               if (!attached)
181                 {
182                   fprintf (stderr, "URB while attached\n");
183                   break;
184                 }
185
186               if (handle_urb (fd) < 0)
187                 {
188                   fprintf (stderr, "URB handling failed\n");
189                   break;
190                 }
191             }
192           else if(msg.cmd == CMD_DETACH)
193             {
194               if (!attached)
195                 {
196                   fprintf (stderr, "DETACH while attached\n");
197                   break;
198                 }
199
200               /* send reply??? */
201               break;
202             }
203           else
204             {
205               fprintf (stderr, "Unknown command %x, disconnecting.\n", msg.cmd);
206               break;
207             }
208         }
209
210        close (fd);
211     }
212 }