static int send_reply_devlist(int connfd) { struct usbip_exported_device *edev; struct usbip_usb_device pdu_udev; struct usbip_usb_interface pdu_uinf; struct op_devlist_reply reply; int i; int rc; reply.ndev = 0; /* number of exported devices */ dlist_for_each_data(host_driver->edev_list, edev, struct usbip_exported_device) { reply.ndev += 1; } info("exportable devices: %d", reply.ndev); rc = usbip_net_send_op_common(connfd, OP_REP_DEVLIST, ST_OK); if (rc < 0) { dbg("usbip_net_send_op_common failed: %#0x", OP_REP_DEVLIST); return -1; } PACK_OP_DEVLIST_REPLY(1, &reply); rc = usbip_net_send(connfd, &reply, sizeof(reply)); if (rc < 0) { dbg("usbip_net_send failed: %#0x", OP_REP_DEVLIST); return -1; } dlist_for_each_data(host_driver->edev_list, edev, struct usbip_exported_device) { dump_usb_device(&edev->udev); memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev)); usbip_net_pack_usb_device(1, &pdu_udev); rc = usbip_net_send(connfd, &pdu_udev, sizeof(pdu_udev)); if (rc < 0) { dbg("usbip_net_send failed: pdu_udev"); return -1; } for (i = 0; i < edev->udev.bNumInterfaces; i++) { dump_usb_interface(&edev->uinf[i]); memcpy(&pdu_uinf, &edev->uinf[i], sizeof(pdu_uinf)); usbip_net_pack_usb_interface(1, &pdu_uinf); rc = usbip_net_send(connfd, &pdu_uinf, sizeof(pdu_uinf)); if (rc < 0) { dbg("usbip_net_send failed: pdu_uinf"); return -1; } } } return 0; }
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_send_op_common(int sockfd, uint32_t code, uint32_t status) { struct op_common op_common; int rc; memset(&op_common, 0, sizeof(op_common)); op_common.version = USBIP_VERSION; op_common.code = code; op_common.status = status; PACK_OP_COMMON(1, &op_common); rc = usbip_net_send(sockfd, &op_common, sizeof(op_common)); if (rc < 0) { dbg("usbip_net_send failed: %d", rc); return -1; } 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; }