1 #include "UsbIpUtils.h"
2
3 #include <arpa/inet.h>
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <log/log.h>
7 #include <netinet/in.h>
8 #include <netinet/tcp.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/socket.h>
13 #include <unistd.h>
14
15 constexpr uint16_t kIpVersion = 0x0111;
16
17 constexpr uint16_t kOpRequest = 0x8003;
18 constexpr uint16_t kOpResponse = 0x0003;
19
20 // Fields associated with all USBIP packets.
21 typedef struct op_req_common {
22 uint16_t ip_version;
23 uint16_t command_code;
24 uint32_t status;
25 } op_req_common;
26
27 typedef struct op_req_import {
28 op_req_common common;
29 uint32_t busid[8];
30 } op_req_import;
31
32 typedef struct op_rep_import {
33 op_req_common common;
34 } op_rep_import;
35
36 // Metadata fields only valid for successful status flag.
37 typedef struct op_rep_import_metadata {
38 uint32_t path[64];
39 uint32_t bus_id[8];
40 uint32_t bus_num;
41 uint32_t dev_num;
42 uint32_t speed;
43 uint16_t id_vendor;
44 uint16_t id_product;
45 uint16_t bcd_device;
46 uint8_t device_class;
47 uint8_t device_subclass;
48 uint8_t device_protocol;
49 uint8_t configuration_value;
50 uint8_t num_configurations;
51 uint8_t num_interfaces;
52 } op_rep_import_success;
53
get_usbip_connection(const char * server,const char * port,const char * dev_id,usbip_conn_info * info)54 bool get_usbip_connection(const char *server, const char *port,
55 const char *dev_id, usbip_conn_info *info) {
56 struct sockaddr_in address;
57
58 // Setup socket to the server.
59 if ((info->sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == 0) {
60 ALOGE("Opening socket failed: %s\n", strerror(errno));
61 return false;
62 }
63
64 int flags = 1;
65 if (setsockopt(info->sock_fd, SOL_SOCKET, SO_KEEPALIVE, &flags,
66 sizeof(flags)) == -1) {
67 ALOGE("Failed to enable keep alive: %s\n", strerror(errno));
68 close(info->sock_fd);
69 return false;
70 }
71 if (setsockopt(info->sock_fd, SOL_TCP, TCP_NODELAY, &flags,
72 sizeof(flags)) == -1) {
73 ALOGE("Failed to enable no delay: %s\n", strerror(errno));
74 close(info->sock_fd);
75 return false;
76 }
77
78 address.sin_family = AF_INET;
79 if (inet_aton(server, &address.sin_addr) == 0) {
80 ALOGE("Failure to convert ip address %s\n", server);
81 close(info->sock_fd);
82 return false;
83 }
84
85 errno = 0;
86 char *error;
87 address.sin_port = strtol(port, &error, 10);
88 if (address.sin_port == 0) {
89 ALOGE("Port is invalid %s\n", port);
90 close(info->sock_fd);
91 return false;
92 }
93 address.sin_port = htons(address.sin_port);
94 if (connect(info->sock_fd, (struct sockaddr *)&address, sizeof(address)) ==
95 -1) {
96 ALOGE("Connection failed: %s\n", strerror(errno));
97 close(info->sock_fd);
98 return false;
99 }
100
101 // Fill in op request
102 op_req_import op_req;
103 op_req.common.ip_version = htons(kIpVersion);
104 op_req.common.command_code = htons(kOpRequest);
105 op_req.common.status = 0x0000;
106 strncpy((char *)op_req.busid, dev_id, sizeof(op_req.busid));
107
108 if (send(info->sock_fd, &op_req, sizeof(op_req), 0) == -1) {
109 ALOGE("Error sending op_req: %s\n", strerror(errno));
110 close(info->sock_fd);
111 return false;
112 }
113
114 // Read in op response.
115 op_rep_import op_rep;
116 if (recv(info->sock_fd, &op_rep, sizeof(op_rep), MSG_WAITALL) == -1) {
117 ALOGE("Error receiving op_rep: %s\n", strerror(errno));
118 close(info->sock_fd);
119 return false;
120 }
121
122 if (op_rep.common.status != 0) {
123 ALOGE("op_rep status is invalid.\n");
124 close(info->sock_fd);
125 return false;
126 }
127
128 uint16_t command = ntohs(op_rep.common.command_code);
129 if (command != kOpResponse) {
130 ALOGE("Invalid command expected: %d received: %d", command, kOpResponse);
131 close(info->sock_fd);
132 return false;
133 }
134
135 op_rep_import_success data;
136 if (recv(info->sock_fd, &data, sizeof(data), MSG_WAITALL) == -1) {
137 ALOGE("Error receiving op_rep_data: %s\n", strerror(errno));
138 close(info->sock_fd);
139 return false;
140 }
141
142 int temp_bus_num = ntohl(data.bus_num);
143 int temp_dev_num = ntohl(data.dev_num);
144 info->speed = ntohl(data.speed);
145 info->dev_id = (temp_bus_num << 16) | temp_dev_num;
146 return true;
147 }
148
get_free_vhci_port(FILE * file,int speed)149 int get_free_vhci_port(FILE *file, int speed) {
150 // Throw away the header line.
151 char *buf = NULL;
152 size_t length = 0;
153 if (getline(&buf, &length, file) == -1) {
154 ALOGE("Couldn't get the header line: %s\n", strerror(errno));
155 free(buf);
156 return -1;
157 }
158 free(buf);
159
160 char busid[32];
161 char hub[3];
162 int port = 0;
163 int status = 0;
164 int spd = 0;
165 int dev = 0;
166 int sockfd = 0;
167 const char *expected_hub = (speed == USBIP_SPEED_SUPER) ? "ss" : "hs";
168
169 // Scan status lines for a free USB port.
170 while (fscanf(file, "%2s %d %d %d %x %u %31s\n", hub, &port, &status, &spd,
171 &dev, &sockfd, busid) != EOF) {
172 if (strcmp(expected_hub, hub) == 0 && status == USBIP_VDEV_NULL) {
173 return port;
174 }
175 }
176
177 return -1;
178 }
179