1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
4 * 2005-2007 Takahiro Hirofuchi
5 * Copyright (C) 2015-2016 Samsung Electronics
6 * Igor Kotrasinski <i.kotrasinsk@samsung.com>
7 * Krzysztof Opasiak <k.opasiak@samsung.com>
22 #include "vhci_driver.h"
23 #include "usbip_common.h"
24 #include "usbip_network.h"
27 static const char usbip_attach_usage_string
[] =
28 "usbip attach <args>\n"
29 " -r, --remote=<host> The machine with exported USB devices\n"
30 " -b, --busid=<busid> Busid of the device on <host>\n"
31 " -d, --device=<devid> Id of the virtual UDC on <host>\n";
33 void usbip_attach_usage(void)
35 printf("usage: %s", usbip_attach_usage_string
);
39 static int record_connection(char *host
, char *port
, char *busid
, int rhport
)
42 char path
[PATH_MAX
+1];
43 char buff
[MAX_BUFF
+1];
46 ret
= mkdir(VHCI_STATE_PATH
, 0700);
48 /* if VHCI_STATE_PATH exists, then it better be a directory */
49 if (errno
== EEXIST
) {
52 ret
= stat(VHCI_STATE_PATH
, &s
);
55 if (!(s
.st_mode
& S_IFDIR
))
61 snprintf(path
, PATH_MAX
, VHCI_STATE_PATH
"/port%d", rhport
);
63 fd
= open(path
, O_WRONLY
|O_CREAT
|O_TRUNC
, S_IRWXU
);
67 snprintf(buff
, MAX_BUFF
, "%s %s %s\n",
70 ret
= write(fd
, buff
, strlen(buff
));
71 if (ret
!= (ssize_t
) strlen(buff
)) {
81 static int import_device(int sockfd
, struct usbip_usb_device
*udev
)
85 uint32_t speed
= udev
->speed
;
87 rc
= usbip_vhci_driver_open();
89 err("open vhci_driver");
94 port
= usbip_vhci_get_free_port(speed
);
97 goto err_driver_close
;
100 dbg("got free port %d", port
);
102 rc
= usbip_vhci_attach_device(port
, sockfd
, udev
->busnum
,
103 udev
->devnum
, udev
->speed
);
104 if (rc
< 0 && errno
!= EBUSY
) {
105 err("import device");
106 goto err_driver_close
;
110 usbip_vhci_driver_close();
115 usbip_vhci_driver_close();
120 static int query_import_device(int sockfd
, char *busid
)
123 struct op_import_request request
;
124 struct op_import_reply reply
;
125 uint16_t code
= OP_REP_IMPORT
;
128 memset(&request
, 0, sizeof(request
));
129 memset(&reply
, 0, sizeof(reply
));
132 rc
= usbip_net_send_op_common(sockfd
, OP_REQ_IMPORT
, 0);
134 err("send op_common");
138 strncpy(request
.busid
, busid
, SYSFS_BUS_ID_SIZE
-1);
140 PACK_OP_IMPORT_REQUEST(0, &request
);
142 rc
= usbip_net_send(sockfd
, (void *) &request
, sizeof(request
));
144 err("send op_import_request");
148 /* receive a reply */
149 rc
= usbip_net_recv_op_common(sockfd
, &code
, &status
);
151 err("Attach Request for %s failed - %s\n",
152 busid
, usbip_op_common_status_string(status
));
156 rc
= usbip_net_recv(sockfd
, (void *) &reply
, sizeof(reply
));
158 err("recv op_import_reply");
162 PACK_OP_IMPORT_REPLY(0, &reply
);
164 /* check the reply */
165 if (strncmp(reply
.udev
.busid
, busid
, SYSFS_BUS_ID_SIZE
)) {
166 err("recv different busid %s", reply
.udev
.busid
);
170 /* import a device */
171 return import_device(sockfd
, &reply
.udev
);
174 static int attach_device(char *host
, char *busid
)
180 sockfd
= usbip_net_tcp_connect(host
, usbip_port_string
);
186 rhport
= query_import_device(sockfd
, busid
);
192 rc
= record_connection(host
, usbip_port_string
, busid
, rhport
);
194 err("record connection");
201 int usbip_attach(int argc
, char *argv
[])
203 static const struct option opts
[] = {
204 { "remote", required_argument
, NULL
, 'r' },
205 { "busid", required_argument
, NULL
, 'b' },
206 { "device", required_argument
, NULL
, 'd' },
215 opt
= getopt_long(argc
, argv
, "d:r:b:", opts
, NULL
);
236 ret
= attach_device(host
, busid
);
240 usbip_attach_usage();