static int query_import_device(int sockfd, char *busid) { int rc; struct op_import_request request; struct op_import_reply reply; uint16_t code = OP_REP_IMPORT; memset(&request, 0, sizeof(request)); memset(&reply, 0, sizeof(reply)); /* send a request */ rc = usbip_net_send_op_common(sockfd, OP_REQ_IMPORT, 0); if (rc < 0) { err("send op_common"); return -1; } strncpy(request.busid, busid, SYSFS_BUS_ID_SIZE-1); PACK_OP_IMPORT_REQUEST(0, &request); rc = usbip_net_send(sockfd, (void *) &request, sizeof(request)); if (rc < 0) { err("send op_import_request"); return -1; } /* receive a reply */ rc = usbip_net_recv_op_common(sockfd, &code); if (rc < 0) { err("recv op_common"); return -1; } rc = usbip_net_recv(sockfd, (void *) &reply, sizeof(reply)); if (rc < 0) { err("recv op_import_reply"); return -1; } PACK_OP_IMPORT_REPLY(0, &reply); /* check the reply */ if (strncmp(reply.udev.busid, busid, SYSFS_BUS_ID_SIZE)) { err("recv different busid %s", reply.udev.busid); return -1; } /* import a device */ return import_device(sockfd, &reply.udev); }
int usbip_net_recv_op_common(int sockfd, uint16_t *code, int *status) { struct op_common op_common; int rc; memset(&op_common, 0, sizeof(op_common)); rc = usbip_net_recv(sockfd, &op_common, sizeof(op_common)); if (rc < 0) { dbg("usbip_net_recv failed: %d", rc); goto err; } PACK_OP_COMMON(0, &op_common); if (op_common.version != USBIP_VERSION) { err("USBIP Kernel and tool version mismatch: %d %d:", op_common.version, USBIP_VERSION); goto err; } switch (*code) { case OP_UNSPEC: break; default: if (op_common.code != *code) { dbg("unexpected pdu %#0x for %#0x", op_common.code, *code); /* return error status */ *status = ST_ERROR; goto err; } } *status = op_common.status; if (op_common.status != ST_OK) { dbg("request failed at peer: %d", op_common.status); goto err; } *code = op_common.code; return 0; err: return -1; }
static int recv_request_devlist(int connfd) { struct op_devlist_request req; int rc; memset(&req, 0, sizeof(req)); rc = usbip_net_recv(connfd, &req, sizeof(req)); if (rc < 0) { dbg("usbip_net_recv failed: devlist request"); return -1; } rc = send_reply_devlist(connfd); if (rc < 0) { dbg("send_reply_devlist failed"); return -1; } return 0; }
static int get_exported_devices(char *host, int sockfd) { char product_name[100]; char class_name[100]; struct op_devlist_reply reply; uint16_t code = OP_REP_DEVLIST; struct usbip_usb_device udev; struct usbip_usb_interface uintf; unsigned int i; int j, rc; rc = usbip_net_send_op_common(sockfd, OP_REQ_DEVLIST, 0); if (rc < 0) { dbg("usbip_net_send_op_common failed"); return -1; } rc = usbip_net_recv_op_common(sockfd, &code); if (rc < 0) { dbg("usbip_net_recv_op_common failed"); return -1; } memset(&reply, 0, sizeof(reply)); rc = usbip_net_recv(sockfd, &reply, sizeof(reply)); if (rc < 0) { dbg("usbip_net_recv_op_devlist failed"); return -1; } PACK_OP_DEVLIST_REPLY(0, &reply); dbg("exportable devices: %d\n", reply.ndev); if (reply.ndev == 0) { info("no exportable devices found on %s", host); return 0; } printf("Exportable USB devices\n"); printf("======================\n"); printf(" - %s\n", host); for (i = 0; i < reply.ndev; i++) { memset(&udev, 0, sizeof(udev)); rc = usbip_net_recv(sockfd, &udev, sizeof(udev)); if (rc < 0) { dbg("usbip_net_recv failed: usbip_usb_device[%d]", i); return -1; } usbip_net_pack_usb_device(0, &udev); usbip_names_get_product(product_name, sizeof(product_name), udev.idVendor, udev.idProduct); usbip_names_get_class(class_name, sizeof(class_name), udev.bDeviceClass, udev.bDeviceSubClass, udev.bDeviceProtocol); printf("%11s: %s\n", udev.busid, product_name); printf("%11s: %s\n", "", udev.path); printf("%11s: %s\n", "", class_name); for (j = 0; j < udev.bNumInterfaces; j++) { rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf)); if (rc < 0) { dbg("usbip_net_recv failed: usbip_usb_intf[%d]", j); return -1; } usbip_net_pack_usb_interface(0, &uintf); usbip_names_get_class(class_name, sizeof(class_name), uintf.bInterfaceClass, uintf.bInterfaceSubClass, uintf.bInterfaceProtocol); printf("%11s: %2d - %s\n", "", j, class_name); } printf("\n"); } return 0; }
static int recv_request_import(int sockfd) { struct op_import_request req; struct op_common reply; struct usbip_exported_device *edev; struct usbip_usb_device pdu_udev; int found = 0; int error = 0; int rc; memset(&req, 0, sizeof(req)); memset(&reply, 0, sizeof(reply)); rc = usbip_net_recv(sockfd, &req, sizeof(req)); if (rc < 0) { dbg("usbip_net_recv failed: import request"); return -1; } PACK_OP_IMPORT_REQUEST(0, &req); dlist_for_each_data(host_driver->edev_list, edev, struct usbip_exported_device) { if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) { info("found requested device: %s", req.busid); found = 1; break; } } if (found) { /* should set TCP_NODELAY for usbip */ usbip_net_set_nodelay(sockfd); /* export device needs a TCP/IP socket descriptor */ rc = usbip_host_export_device(edev, sockfd); if (rc < 0) error = 1; } else { info("requested device not found: %s", req.busid); error = 1; } rc = usbip_net_send_op_common(sockfd, OP_REP_IMPORT, (!error ? ST_OK : ST_NA)); if (rc < 0) { dbg("usbip_net_send_op_common failed: %#0x", OP_REP_IMPORT); return -1; } if (error) { dbg("import request busid %s: failed", req.busid); return -1; } memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev)); usbip_net_pack_usb_device(1, &pdu_udev); rc = usbip_net_send(sockfd, &pdu_udev, sizeof(pdu_udev)); if (rc < 0) { dbg("usbip_net_send failed: devinfo"); return -1; } dbg("import request busid %s: complete", req.busid); return 0; }